X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fide%2Fide-disk.c;h=e5adebe8ac2c88501ff9d0e11a049a7eb530655c;hb=c77380d4534c65cc9865a6b4efea44be4d039207;hp=01846f244b40156b3822bcb504f05f7c18b12bd5;hpb=20272c8994cf1e1f8ed745a2ea161dd9ad3889f2;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 01846f244b4..e5adebe8ac2 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -14,9 +14,6 @@ * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. */ -#define IDEDISK_VERSION "1.18" - -#include #include #include #include @@ -39,54 +36,7 @@ #include #include -#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) -#define IDE_DISK_MINORS (1 << PARTN_BITS) -#else -#define IDE_DISK_MINORS 0 -#endif - -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 void ide_disk_release(struct kref *); - -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) { - if (ide_device_get(idkp->drive)) - idkp = NULL; - else - kref_get(&idkp->kref); - } - mutex_unlock(&idedisk_ref_mutex); - return idkp; -} - -static void ide_disk_put(struct ide_disk_obj *idkp) -{ - ide_drive_t *drive = idkp->drive; - - mutex_lock(&idedisk_ref_mutex); - kref_put(&idkp->kref, ide_disk_release); - ide_device_put(drive); - mutex_unlock(&idedisk_ref_mutex); -} +#include "ide-disk.h" static const u8 ide_rw_cmds[] = { ATA_CMD_READ_MULTI, @@ -140,9 +90,9 @@ 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; u16 nsectors = (u16)rq->nr_sectors; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; + u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); + u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); ide_task_t task; struct ide_taskfile *tf = &task.tf; ide_startstop_t rc; @@ -162,7 +112,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, memset(&task, 0, sizeof(task)); task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (drive->select.b.lba) { + if (drive->dev_flags & IDE_DFLAG_LBA) { if (lba48) { pr_debug("%s: LBA=0x%012llx\n", drive->name, (unsigned long long)block); @@ -187,6 +137,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, tf->lbah = block >>= 8; tf->device = (block >> 8) & 0xf; } + + tf->device |= ATA_LBA; } else { unsigned int sect, head, cyl, track; @@ -237,7 +189,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, { ide_hwif_t *hwif = HWIF(drive); - BUG_ON(drive->blocked); + BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); if (!blk_fs_request(rq)) { blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); @@ -381,142 +333,59 @@ static void idedisk_check_hpa(ide_drive_t *drive) } } -static void init_idedisk_capacity(ide_drive_t *drive) +static int ide_disk_get_capacity(ide_drive_t *drive) { u16 *id = drive->id; - /* - * If this drive supports the Host Protected Area feature set, - * then we may need to change our opinion about the drive's capacity. - */ - int hpa = ata_id_hpa_enabled(id); + int lba; if (ata_id_lba48_enabled(id)) { /* drive speaks 48-bit LBA */ - drive->select.b.lba = 1; + lba = 1; drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); - if (hpa) - idedisk_check_hpa(drive); } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) { /* drive speaks 28-bit LBA */ - drive->select.b.lba = 1; + lba = 1; drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY); - if (hpa) - idedisk_check_hpa(drive); } else { /* drive speaks boring old 28-bit CHS */ + lba = 0; drive->capacity64 = drive->cyl * drive->head * drive->sect; } -} - -static sector_t idedisk_capacity(ide_drive_t *drive) -{ - return drive->capacity64; -} -#ifdef CONFIG_IDE_PROC_FS -static int smart_enable(ide_drive_t *drive) -{ - ide_task_t args; - struct ide_taskfile *tf = &args.tf; + if (lba) { + drive->dev_flags |= IDE_DFLAG_LBA; - memset(&args, 0, sizeof(ide_task_t)); - tf->feature = ATA_SMART_ENABLE; - tf->lbam = ATA_SMART_LBAM_PASS; - tf->lbah = ATA_SMART_LBAH_PASS; - tf->command = ATA_CMD_SMART; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - return ide_no_data_taskfile(drive, &args); -} - -static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) -{ - ide_task_t args; - struct ide_taskfile *tf = &args.tf; - - memset(&args, 0, sizeof(ide_task_t)); - tf->feature = sub_cmd; - tf->nsect = 0x01; - tf->lbam = ATA_SMART_LBAM_PASS; - tf->lbah = ATA_SMART_LBAH_PASS; - tf->command = ATA_CMD_SMART; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - args.data_phase = TASKFILE_IN; - (void) smart_enable(drive); - return ide_raw_taskfile(drive, &args, buf, 1); -} - -static int proc_idedisk_read_cache - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = (ide_drive_t *) data; - char *out = page; - int len; - - if (drive->id_read) - len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2); - else - len = sprintf(out, "(none)\n"); - - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_idedisk_read_capacity - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t*drive = (ide_drive_t *)data; - int len; - - len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive)); - - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} - -static int proc_idedisk_read_smart(char *page, char **start, off_t off, - int count, int *eof, void *data, u8 sub_cmd) -{ - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; - - if (get_smart_data(drive, page, sub_cmd) == 0) { - unsigned short *val = (unsigned short *) page; - char *out = (char *)val + SECTOR_SIZE; - - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), - (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < SECTOR_SIZE / 2); - len = out - page; + /* + * If this device supports the Host Protected Area feature set, + * then we may need to change our opinion about its capacity. + */ + if (ata_id_hpa_enabled(id)) + idedisk_check_hpa(drive); } - PROC_IDE_READ_RETURN(page, start, off, count, eof, len); -} + /* limit drive capacity to 137GB if LBA48 cannot be used */ + if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 && + drive->capacity64 > 1ULL << 28) { + printk(KERN_WARNING "%s: cannot use LBA48 - full capacity " + "%llu sectors (%llu MB)\n", + drive->name, (unsigned long long)drive->capacity64, + sectors_to_MB(drive->capacity64)); + drive->capacity64 = 1ULL << 28; + } -static int proc_idedisk_read_sv - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - return proc_idedisk_read_smart(page, start, off, count, eof, data, - ATA_SMART_READ_VALUES); -} + if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && + (drive->dev_flags & IDE_DFLAG_LBA48)) { + if (drive->capacity64 > 1ULL << 28) { + printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode" + " will be used for accessing sectors " + "> %u\n", drive->name, 1 << 28); + } else + drive->dev_flags &= ~IDE_DFLAG_LBA48; + } -static int proc_idedisk_read_st - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - return proc_idedisk_read_smart(page, start, off, count, eof, data, - ATA_SMART_READ_THRESHOLDS); + return 0; } -static ide_proc_entry_t idedisk_proc[] = { - { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, - { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, - { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL }, - { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif /* CONFIG_IDE_PROC_FS */ - static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) { ide_drive_t *drive = q->queuedata; @@ -568,25 +437,43 @@ static int set_multcount(ide_drive_t *drive, int arg) return (drive->mult_count == arg) ? 0 : -EIO; } -ide_devset_get(nowerr, nowerr); +ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR); static int set_nowerr(ide_drive_t *drive, int arg) { if (arg < 0 || arg > 1) return -EINVAL; - drive->nowerr = arg; + if (arg) + drive->dev_flags |= IDE_DFLAG_NOWERR; + else + drive->dev_flags &= ~IDE_DFLAG_NOWERR; + drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; + return 0; } +static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) +{ + ide_task_t task; + + memset(&task, 0, sizeof(task)); + task.tf.feature = feature; + task.tf.nsect = nsect; + task.tf.command = ATA_CMD_SET_FEATURES; + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + + return ide_no_data_taskfile(drive, &task); +} + static void update_ordered(ide_drive_t *drive) { u16 *id = drive->id; unsigned ordered = QUEUE_ORDERED_NONE; prepare_flush_fn *prep_fn = NULL; - if (drive->wcache) { + if (drive->dev_flags & IDE_DFLAG_WCACHE) { unsigned long long capacity; int barrier; /* @@ -597,9 +484,11 @@ static void update_ordered(ide_drive_t *drive) * time we have trimmed the drive capacity if LBA48 is * not available so we don't need to recheck that. */ - capacity = idedisk_capacity(drive); - barrier = ata_id_flush_enabled(id) && !drive->noflush && - (drive->addressing == 0 || capacity <= (1ULL << 28) || + capacity = ide_gd_capacity(drive); + barrier = ata_id_flush_enabled(id) && + (drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 && + ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 || + capacity <= (1ULL << 28) || ata_id_flush_ext_enabled(id)); printk(KERN_INFO "%s: cache flushes %ssupported\n", @@ -615,25 +504,24 @@ static void update_ordered(ide_drive_t *drive) blk_queue_ordered(drive->queue, ordered, prep_fn); } -ide_devset_get(wcache, wcache); +ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE); static int set_wcache(ide_drive_t *drive, int arg) { - ide_task_t args; int err = 1; if (arg < 0 || arg > 1) return -EINVAL; if (ata_id_flush_enabled(drive->id)) { - memset(&args, 0, sizeof(ide_task_t)); - args.tf.feature = arg ? - SETFEATURES_WC_ON : SETFEATURES_WC_OFF; - args.tf.command = ATA_CMD_SET_FEATURES; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - err = ide_no_data_taskfile(drive, &args); - if (err == 0) - drive->wcache = arg; + err = ide_do_setfeature(drive, + arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0); + if (err == 0) { + if (arg) + drive->dev_flags |= IDE_DFLAG_WCACHE; + else + drive->dev_flags &= ~IDE_DFLAG_WCACHE; + } } update_ordered(drive); @@ -658,22 +546,18 @@ ide_devset_get(acoustic, acoustic); static int set_acoustic(ide_drive_t *drive, int arg) { - ide_task_t args; - if (arg < 0 || arg > 254) return -EINVAL; - memset(&args, 0, sizeof(ide_task_t)); - args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF; - args.tf.nsect = arg; - args.tf.command = ATA_CMD_SET_FEATURES; - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - ide_no_data_taskfile(drive, &args); + ide_do_setfeature(drive, + arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg); + drive->acoustic = arg; + return 0; } -ide_devset_get(addressing, addressing); +ide_devset_get_flag(addressing, IDE_DFLAG_LBA48); /* * drive->addressing: @@ -686,53 +570,37 @@ static int set_addressing(ide_drive_t *drive, int arg) if (arg < 0 || arg > 2) return -EINVAL; - drive->addressing = 0; - - if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) - return 0; - - if (ata_id_lba48_enabled(drive->id) == 0) + if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) || + ata_id_lba48_enabled(drive->id) == 0)) return -EIO; - drive->addressing = arg; + if (arg == 2) + arg = 0; + + if (arg) + drive->dev_flags |= IDE_DFLAG_LBA48; + else + drive->dev_flags &= ~IDE_DFLAG_LBA48; return 0; } -ide_devset_rw(acoustic, acoustic); -ide_devset_rw(address, addressing); -ide_devset_rw(multcount, multcount); -ide_devset_rw(wcache, wcache); - -ide_devset_rw_sync(nowerr, nowerr); - -#ifdef CONFIG_IDE_PROC_FS -ide_devset_rw_field(bios_cyl, bios_cyl); -ide_devset_rw_field(bios_head, bios_head); -ide_devset_rw_field(bios_sect, bios_sect); -ide_devset_rw_field(failures, failures); -ide_devset_rw_field(lun, lun); -ide_devset_rw_field(max_failures, max_failures); - -static const struct ide_proc_devset idedisk_settings[] = { - IDE_PROC_DEVSET(acoustic, 0, 254), - IDE_PROC_DEVSET(address, 0, 2), - IDE_PROC_DEVSET(bios_cyl, 0, 65535), - IDE_PROC_DEVSET(bios_head, 0, 255), - IDE_PROC_DEVSET(bios_sect, 0, 63), - IDE_PROC_DEVSET(failures, 0, 65535), - IDE_PROC_DEVSET(lun, 0, 7), - IDE_PROC_DEVSET(max_failures, 0, 65535), - IDE_PROC_DEVSET(multcount, 0, 16), - IDE_PROC_DEVSET(nowerr, 0, 1), - IDE_PROC_DEVSET(wcache, 0, 1), - { 0 }, -}; -#endif +ide_ext_devset_rw(acoustic, acoustic); +ide_ext_devset_rw(address, addressing); +ide_ext_devset_rw(multcount, multcount); +ide_ext_devset_rw(wcache, wcache); + +ide_ext_devset_rw_sync(nowerr, nowerr); -static void idedisk_setup(ide_drive_t *drive) +static int ide_disk_check(ide_drive_t *drive, const char *s) +{ + return 1; +} + +static void ide_disk_setup(ide_drive_t *drive) { struct ide_disk_obj *idkp = drive->driver_data; + struct request_queue *q = drive->queue; ide_hwif_t *hwif = drive->hwif; u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; @@ -740,59 +608,44 @@ static void idedisk_setup(ide_drive_t *drive) ide_proc_register_driver(drive, idkp->driver); - if (drive->id_read == 0) + if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) return; - if (drive->removable) { + if (drive->dev_flags & IDE_DFLAG_REMOVABLE) { /* * Removable disks (eg. SYQUEST); ignore 'WD' drives */ if (m[0] != 'W' || m[1] != 'D') - drive->doorlocking = 1; + drive->dev_flags |= IDE_DFLAG_DOORLOCKING; } (void)set_addressing(drive, 1); - if (drive->addressing == 1) { + if (drive->dev_flags & IDE_DFLAG_LBA48) { int max_s = 2048; if (max_s > hwif->rqsize) max_s = hwif->rqsize; - blk_queue_max_sectors(drive->queue, max_s); + blk_queue_max_sectors(q, max_s); } printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, - drive->queue->max_sectors / 2); + q->max_sectors / 2); - /* calculate drive capacity, and select LBA if possible */ - init_idedisk_capacity(drive); + if (ata_id_is_ssd(id) || ata_id_is_cfa(id)) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); - /* limit drive capacity to 137GB if LBA48 cannot be used */ - if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) { - printk(KERN_WARNING "%s: cannot use LBA48 - full capacity " - "%llu sectors (%llu MB)\n", - drive->name, (unsigned long long)drive->capacity64, - sectors_to_MB(drive->capacity64)); - drive->capacity64 = 1ULL << 28; - } - - if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) { - if (drive->capacity64 > 1ULL << 28) { - printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode" - " will be used for accessing sectors " - "> %u\n", drive->name, 1 << 28); - } else - drive->addressing = 0; - } + /* calculate drive capacity, and select LBA if possible */ + ide_disk_get_capacity(drive); /* * if possible, give fdisk access to more of the drive, * by correcting bios_cyls: */ - capacity = idedisk_capacity(drive); + capacity = ide_gd_capacity(drive); - if (!drive->forced_geom) { + if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) { if (ata_id_lba48_enabled(drive->id)) { /* compatibility */ drive->bios_sect = 63; @@ -827,301 +680,63 @@ static void idedisk_setup(ide_drive_t *drive) /* write cache enabled? */ if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) - drive->wcache = 1; + drive->dev_flags |= IDE_DFLAG_WCACHE; set_wcache(drive, 1); + + if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 && + (drive->head == 0 || drive->head > 16)) { + printk(KERN_ERR "%s: invalid geometry: %d physical heads?\n", + drive->name, drive->head); + drive->dev_flags &= ~IDE_DFLAG_ATTACH; + } else + drive->dev_flags |= IDE_DFLAG_ATTACH; } -static void ide_cacheflush_p(ide_drive_t *drive) +static void ide_disk_flush(ide_drive_t *drive) { - if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0) + if (ata_id_flush_enabled(drive->id) == 0 || + (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) return; if (do_idedisk_flushcache(drive)) printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); } -static void ide_disk_remove(ide_drive_t *drive) -{ - struct ide_disk_obj *idkp = drive->driver_data; - struct gendisk *g = idkp->disk; - - ide_proc_unregister_driver(drive, idkp->driver); - - del_gendisk(g); - - ide_cacheflush_p(drive); - - ide_disk_put(idkp); -} - -static void ide_disk_release(struct kref *kref) -{ - struct ide_disk_obj *idkp = to_ide_disk(kref); - ide_drive_t *drive = idkp->drive; - struct gendisk *g = idkp->disk; - - drive->driver_data = NULL; - g->private_data = NULL; - put_disk(g); - kfree(idkp); -} - -static int ide_disk_probe(ide_drive_t *drive); - -/* - * On HPA drives the capacity needs to be - * reinitilized on resume otherwise the disk - * can not be used and a hard reset is required - */ -static void ide_disk_resume(ide_drive_t *drive) -{ - if (ata_id_hpa_enabled(drive->id)) - init_idedisk_capacity(drive); -} - -static void ide_device_shutdown(ide_drive_t *drive) +static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk) { -#ifdef CONFIG_ALPHA - /* On Alpha, halt(8) doesn't actually turn the machine off, - it puts you into the sort of firmware monitor. Typically, - it's used to boot another kernel image, so it's not much - different from reboot(8). Therefore, we don't need to - spin down the disk in this case, especially since Alpha - firmware doesn't handle disks in standby mode properly. - On the other hand, it's reasonably safe to turn the power - off when the shutdown process reaches the firmware prompt, - as the firmware initialization takes rather long time - - at least 10 seconds, which should be sufficient for - the disk to expire its write cache. */ - if (system_state != SYSTEM_POWER_OFF) { -#else - if (system_state == SYSTEM_RESTART) { -#endif - ide_cacheflush_p(drive); - return; - } - - printk(KERN_INFO "Shutdown: %s\n", drive->name); - - drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); + return 0; } -static ide_driver_t idedisk_driver = { - .gen_driver = { - .owner = THIS_MODULE, - .name = "ide-disk", - .bus = &ide_bus_type, - }, - .probe = ide_disk_probe, - .remove = ide_disk_remove, - .resume = ide_disk_resume, - .shutdown = ide_device_shutdown, - .version = IDEDISK_VERSION, - .media = ide_disk, - .do_request = ide_do_rw_disk, - .end_request = ide_end_request, - .error = __ide_error, -#ifdef CONFIG_IDE_PROC_FS - .proc = idedisk_proc, - .settings = idedisk_settings, -#endif -}; - -static int idedisk_set_doorlock(ide_drive_t *drive, int on) +static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, + int on) { ide_task_t task; + int ret; + + if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) + return 0; memset(&task, 0, sizeof(task)); task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - return ide_no_data_taskfile(drive, &task); -} - -static int idedisk_open(struct inode *inode, struct file *filp) -{ - struct gendisk *disk = inode->i_bdev->bd_disk; - struct ide_disk_obj *idkp; - ide_drive_t *drive; - - idkp = ide_disk_get(disk); - if (idkp == NULL) - return -ENXIO; - - drive = idkp->drive; - - idkp->openers++; - - if (drive->removable && idkp->openers == 1) { - check_disk_change(inode->i_bdev); - /* - * Ignore the return code from door_lock, - * since the open() has already succeeded, - * and the door_lock is irrelevant at this point. - */ - if (drive->doorlocking && idedisk_set_doorlock(drive, 1)) - drive->doorlocking = 0; - } - return 0; -} - -static int idedisk_release(struct inode *inode, struct file *filp) -{ - struct gendisk *disk = inode->i_bdev->bd_disk; - struct ide_disk_obj *idkp = ide_disk_g(disk); - ide_drive_t *drive = idkp->drive; - - if (idkp->openers == 1) - ide_cacheflush_p(drive); - - if (drive->removable && idkp->openers == 1) { - if (drive->doorlocking && idedisk_set_doorlock(drive, 0)) - drive->doorlocking = 0; - } - - idkp->openers--; - - ide_disk_put(idkp); + ret = ide_no_data_taskfile(drive, &task); - return 0; -} - -static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - ide_drive_t *drive = idkp->drive; - - geo->heads = drive->bios_head; - geo->sectors = drive->bios_sect; - geo->cylinders = (u16)drive->bios_cyl; /* truncate */ - return 0; -} - -static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { -{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address }, -{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount }, -{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr }, -{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache }, -{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic }, -{ 0 } -}; - -static int idedisk_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct block_device *bdev = inode->i_bdev; - struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - ide_drive_t *drive = idkp->drive; - int err; - - err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); - if (err != -EOPNOTSUPP) - return err; - - return generic_ide_ioctl(drive, file, bdev, cmd, arg); -} - -static int idedisk_media_changed(struct gendisk *disk) -{ - struct ide_disk_obj *idkp = ide_disk_g(disk); - ide_drive_t *drive = idkp->drive; - - /* do not scan partitions twice if this is a removable device */ - if (drive->attach) { - drive->attach = 0; - return 0; - } - /* if removable, always assume it was changed */ - return drive->removable; -} + if (ret) + drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING; -static int idedisk_revalidate_disk(struct gendisk *disk) -{ - struct ide_disk_obj *idkp = ide_disk_g(disk); - set_capacity(disk, idedisk_capacity(idkp->drive)); - return 0; + return ret; } -static struct block_device_operations idedisk_ops = { - .owner = THIS_MODULE, - .open = idedisk_open, - .release = idedisk_release, - .ioctl = idedisk_ioctl, - .getgeo = idedisk_getgeo, - .media_changed = idedisk_media_changed, - .revalidate_disk = idedisk_revalidate_disk +const struct ide_disk_ops ide_ata_disk_ops = { + .check = ide_disk_check, + .get_capacity = ide_disk_get_capacity, + .setup = ide_disk_setup, + .flush = ide_disk_flush, + .init_media = ide_disk_init_media, + .set_doorlock = ide_disk_set_doorlock, + .do_request = ide_do_rw_disk, + .end_request = ide_end_request, + .ioctl = ide_disk_ioctl, }; - -MODULE_DESCRIPTION("ATA DISK Driver"); - -static int ide_disk_probe(ide_drive_t *drive) -{ - struct ide_disk_obj *idkp; - struct gendisk *g; - - /* strstr("foo", "") is non-NULL */ - if (!strstr("ide-disk", drive->driver_req)) - goto failed; - - if (drive->media != ide_disk) - goto failed; - - idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); - if (!idkp) - goto failed; - - g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif)); - if (!g) - goto out_free_idkp; - - ide_init_disk(g, drive); - - kref_init(&idkp->kref); - - idkp->drive = drive; - idkp->driver = &idedisk_driver; - idkp->disk = g; - - g->private_data = &idkp->driver; - - drive->driver_data = idkp; - - idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", - drive->name, drive->head); - drive->attach = 0; - } else - drive->attach = 1; - - g->minors = IDE_DISK_MINORS; - g->driverfs_dev = &drive->gendev; - g->flags |= GENHD_FL_EXT_DEVT; - if (drive->removable) - g->flags |= GENHD_FL_REMOVABLE; - set_capacity(g, idedisk_capacity(drive)); - g->fops = &idedisk_ops; - add_disk(g); - return 0; - -out_free_idkp: - kfree(idkp); -failed: - return -ENODEV; -} - -static void __exit idedisk_exit(void) -{ - driver_unregister(&idedisk_driver.gen_driver); -} - -static int __init idedisk_init(void) -{ - return driver_register(&idedisk_driver.gen_driver); -} - -MODULE_ALIAS("ide:*m-disk*"); -module_init(idedisk_init); -module_exit(idedisk_exit); -MODULE_LICENSE("GPL");