/*
* linux/drivers/ide/ide-disk.c Version 1.18 Mar 05, 2003
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
* Copyright (C) 1998-2002 Linux ATA Development
* Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
*/
/*
* Mostly written by Mark Lord <mlord@pobox.com>
* and Gadi Oxman <gadio@netvision.net.il>
* and Andre Hedrick <andre@linux-ide.org>
*
* This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
*
* Version 1.00 move disk only code from ide.c to ide-disk.c
* support optional byte-swapping of all data
* Version 1.01 fix previous byte-swapping code
* Version 1.02 remove ", LBA" from drive identification msgs
* Version 1.03 fix display of id->buf_size for big-endian
* Version 1.04 add /proc configurable settings and S.M.A.R.T support
* Version 1.05 add capacity support for ATA3 >= 8GB
* Version 1.06 get boot-up messages to show full cyl count
* Version 1.07 disable door-locking if it fails
* Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB,
* process of adding new ATA4 compliance.
* fixed problems in allowing fdisk to see
* the entire disk.
* Version 1.09 added increment of rq->sector in ide_multwrite
* added UDMA 3/4 reporting
* Version 1.10 request queue changes, Ultra DMA 100
* Version 1.11 added 48-bit lba
* Version 1.12 adding taskfile io access method
* Version 1.13 added standby and flush-cache for notifier
* Version 1.14 added acoustic-wcache
* Version 1.15 convert all calls to ide_raw_taskfile
* since args will return register content.
* Version 1.16 added suspend-resume-checkpower
* Version 1.17 do flush on standby, do flush on ATA < ATA6
* fix wcache setup.
*/
#define IDEDISK_VERSION "1.18"
//#define DEBUG
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/leds.h>
#define _IDE_DISK
#include <linux/ide.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/div64.h>
struct ide_disk_obj {
ide_drive_t *drive;
ide_driver_t *driver;
struct gendisk *disk;
struct kref kref;
unsigned int openers; /* protected by BKL for now */
};
static DEFINE_MUTEX(idedisk_ref_mutex);
#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
#define ide_disk_g(disk) \
container_of((disk)->private_data, struct ide_disk_obj, driver)
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
{
struct ide_disk_obj *idkp = NULL;
mutex_lock(&idedisk_ref_mutex);
idkp = ide_disk_g(disk);
if (idkp)
kref_get(&idkp->kref);
mutex_unlock(&idedisk_ref_mutex);
return idkp;
}
static void ide_disk_release(struct kref *);
static void ide_disk_put(struct ide_disk_obj *idkp)
{
mutex_lock(&idedisk_ref_mutex);
kref_put(&idkp->kref, ide_disk_release);
mutex_unlock(&idedisk_ref_mutex);
}
/*
* lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
* value for this drive (from its reported identification information).
*
* Returns: 1 if lba_capacity looks sensible
* 0 otherwise
*
* It is called only once for each drive.
*/
static int lba_capacity_is_ok (struct hd_driveid *id)
{
unsigned long lba_sects, chs_sects, head, tail;
/* No non-LBA info .. so valid! */
if (id->cyls == 0)
return 1;
/*
* The ATA spec tells large drives to return
* C/H/S = 16383/16/63 independent of their size.
* Some drives can be jumpered to use 15 heads instead of 16.
* Some drives can be jumpered to use 4092 cyls instead of 16383.
*/
if ((id->cyls == 16383
|| (id->cyls == 4092 && id->cur_cyls == 16383)) &&
id->sectors == 63 &&
(id->heads == 15 || id->heads == 16) &&
(id->lba_capacity >= 16383*63*id->heads))
return 1;
lba_sects = id->lba_capacity;
chs_sects = id->cyls * id->heads * id->sectors;
/* perform a rough sanity check on lba_sects: within 10% is OK */
if ((lba_sects - chs_sects) < chs_sects/10)
return 1;
/* some drives have the word order reversed */
head = ((lba_sects >> 16) & 0xffff);
tail = (lba_sects & 0xffff);
lba_sects = (head | (tail << 16));
if ((lba_sects - chs_sects) < chs_sects/10) {
id->lba_capacity = lba_sects;
return 1; /* lba_capacity is (now) good */
}
return 0; /* lba_capacity value may be bad */
}
/*
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
* using LBA if supported, or CHS otherwise, to address sectors.
*/
static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int dma = drive->using_dma;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;
ata_nsector_t nsectors;
nsectors.all = (u16) rq->nr_sectors;
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
if (block + rq->nr_sectors > 1ULL << 28)
dma = 0;
else
lba48 = 0;
}
if (!dma) {
ide_init_sg_cmd(drive, rq);
ide_map_sg(drive, rq);
}
if (IDE_CONTROL_REG)
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
/* FIXME: SELECT_MASK(drive, 0) ? */
if (drive->select.b.lba) {
if (lba48) {
task_ioreg_t tasklets[10];
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
tasklets[
|