/* * Copyright (C) 1994-1998 Linus Torvalds and authors: * * Mark Lord <mlord@pobox.com> * Gadi Oxman <gadio@netvision.net.il> * Andre Hedrick <andre@linux-ide.org> * Jens Axboe <axboe@suse.de> * Marcin Dalecki <dalecki@evision.ag> * * This is the ATA disk device driver, as evolved from hd.c and ide.c. */ #define IDEDISK_VERSION "1.14" #include <linux/config.h> #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/ide.h> #include <asm/byteorder.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/io.h> #ifdef CONFIG_BLK_DEV_PDC4030 #define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030) #else #define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ #endif /* * Perform 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; if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { printk("48-bit Drive: %llu \n", id->lba_capacity_2); 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 */ } /* * Determine the apriopriate hardware command correspnding to the action in * question, depending upon the device capabilities and setup. */ static u8 get_command(ide_drive_t *drive, int cmd) { int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; /* Well, calculating the command in this variable may be an * overoptimization. */ u8 command = WIN_NOP; #if 1 lba48bit = drive->addressing; #endif /* * 48-bit commands are pretty sanely laid out */ if (lba48bit) { command = cmd == READ ? WIN_READ_EXT : WIN_WRITE_EXT; if (drive->using_dma) { command++; /* WIN_*DMA_EXT */ if (drive->using_tcq) command++; /* WIN_*DMA_QUEUED_EXT */ } else if (drive->mult_count) command += 5; /* WIN_MULT*_EXT */ return command; } /* * 28-bit commands seem not to be, though... */ if (cmd == READ) { if (drive->using_dma) { if (drive->using_tcq) command = WIN_READDMA_QUEUED; else command = WIN_READDMA; } else if (drive->mult_count) command = WIN_MULTREAD; else command = WIN_READ; } else { if (drive->using_dma) { if (drive->using_tcq) command = WIN_WRITEDMA_QUEUED; else command = WIN_WRITEDMA; } else if (drive->mult_count) command = WIN_MULTWRITE; else command = WIN_WRITE; } return command; } static ide_startstop_t chs_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block) { struct ata_taskfile *args = &ar->ar_task; struct request *rq = ar->ar_rq; int sectors = rq->nr_sectors; unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); unsigned int cyl = (track / drive->head); memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr)); memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr)); if (sectors == 256) sectors = 0; if (ar->ar_flags & ATA_AR_QUEUED) { unsigned long flags; args->taskfile.feature = sectors; args->taskfile.sector_count = ar->ar_tag << 3; spin_lock_irqsave(DRIVE_LOCK(drive), flags); blkdev_dequeue_request(rq); spin_unlock_irqrestore(DRIVE_LOCK(drive), flags); } else args->taskfile.sector_count = sectors; args->taskfile.sector_number = sect; args->taskfile.low_cylinder = cyl; args->taskfile.high_cylinder = (cyl>>8); args->taskfile.device_head = head; args->taskfile.device_head |= drive->select.all; args->taskfile.command = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("sectors=%ld, ", rq->nr_sectors); printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif ide_cmd_type_parser(args); args->ar = ar; rq->special = ar; return ata_taskfile(drive, args, rq); } static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block) { struct ata_taskfile *args = &ar->ar_task; struct request *rq = ar->ar_rq; int sectors = rq->nr_sectors; if (sectors == 256) sectors = 0; memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr)); memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr)); if (ar->ar_flags & ATA_AR_QUEUED) { unsigned long flags; args->taskfile.feature = sectors; args->taskfile.sector_count = ar->ar_tag << 3; spin_lock_irqsave(DRIVE_LOCK(drive), flags); blkdev_dequeue_request(rq); spin_unlock_irqrestore(DRIVE_LOCK(drive), flags); } else args->taskfile.sector_count = sectors; args->taskfile.sector_number = block; args->taskfile.low_cylinder = (block >>= 8); args->taskfile.high_cylinder = (block >>= 8); args->taskfile.device_head = ((block >> 8) & 0x0f); args->taskfile.device_head |= drive->select.all; args->taskfile.command = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif ide_cmd_type_parser(args); args->ar = ar; rq->special = ar; return ata_taskfile(drive, args, rq); } /* * 268435455 == 137439 MB or 28bit limit * 320173056 == 163929 MB or 48bit addressing * 1073741822 == 549756 MB or 48bit addressing fake drive */ static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block) { struct ata_taskfile *args = &ar->ar_task; struct request *rq = ar->ar_rq; int sectors = rq->nr_sectors; memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr)); memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr)); if (sectors == 65536) sectors = 0; if (ar->ar_flags & ATA_AR_QUEUED) { unsigned long flags; args->taskfile.feature = sectors; args->hobfile.feature = sectors >> 8; args->taskfile.sector_count = ar->ar_tag << 3; spin_lock_irqsave(DRIVE_LOCK(drive), flags); blkdev_dequeue_request(rq); spin_unlock_irqrestore(DRIVE_LOCK(drive), flags); } else { args->taskfile.sector_count = sectors; args->hobfile.sector_count = sectors >> 8; } args->taskfile.sector_number = block; args->taskfile.low_cylinder = (block >>= 8); args->taskfile.high_cylinder = (block >>= 8); args->hobfile.sector_number = (block >>= 8); args->hobfile.low_cylinder = (block >>= 8); args->hobfile.high_cylinder = (block >>= 8); args->taskfile.device_head = drive->select.all; args->hobfile.device_head = args->taskfile.device_head; args->hobfile.control = (drive->ctl|0x80); args->taskfile.command = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif ide_cmd_type_parser(args); args->ar = ar; rq->special = ar; return ata_taskfile(drive, args, rq); } /* * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS * otherwise, to address sectors. It also takes care of issuing special * DRIVE_CMDs. */ static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { unsigned long flags; struct ata_request *ar; /* * Wait until all request have bin finished. */ while (drive->blocked) { yield(); printk("ide: Request while drive blocked?"); } if (!(rq->flags & REQ_CMD)) { blk_dump_rq_flags(rq, "idedisk_do_request - bad command"); ide_end_request(drive, 0); return ide_stopped; } if (IS_PDC4030_DRIVE) { extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long); return promise_rw_disk(drive, rq, block); } /* * get a new command (push ar further down to avoid grabbing lock here */ spin_lock_irqsave(DRIVE_LOCK(drive), flags); ar = ata_ar_get(drive); /* * we've reached maximum queue depth, bail */ if (!ar) { spin_unlock_irqrestore(DRIVE_LOCK(drive), flags); return ide_started; } ar->ar_rq = rq; if (drive->using_tcq) { int tag = ide_get_tag(drive); BUG_ON(drive->tcq->active_tag != -1); /* Set the tag: */ ar->ar_flags |= ATA_AR_QUEUED; ar->ar_tag = tag; drive->tcq->ar[tag] = ar; drive->tcq->active_tag = tag; ar->ar_time = jiffies; drive->tcq->queued++; } spin_unlock_irqrestore(DRIVE_LOCK(drive), flags); /* 48-bit LBA */ if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) return lba48_do_request(drive, ar, block); /* 28-bit LBA */ if (drive->select.b.lba) return lba28_do_request(drive, ar, block); /* 28-bit CHS */ return chs_do_request(drive, ar, block); } static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) { MOD_INC_USE_COUNT; if (drive->removable && drive->usage == 1) { struct ata_taskfile args; check_disk_change(inode->i_rdev); memset(&args, 0, sizeof(args)); args.taskfile.command = WIN_DOORLOCK; ide_cmd_type_parser(&args); /* * 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 && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } return 0; } static int idedisk_flushcache(ide_drive_t *drive) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); if (drive->id->cfs_enable_2 & 0x2400) args.taskfile.command = WIN_FLUSH_CACHE_EXT; else args.taskfile.command = WIN_FLUSH_CACHE; ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args, NULL); } static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { if (drive->removable && !drive->usage) { struct ata_taskfile args; invalidate_bdev(inode->i_bdev, 0); memset(&args, 0, sizeof(args)); args.taskfile.command = WIN_DOORUNLOCK; ide_cmd_type_parser(&args); if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", drive->name); MOD_DEC_USE_COUNT; } static int idedisk_check_media_change (ide_drive_t *drive) { /* if removable, always assume it was changed */ return drive->removable; } /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. */ static unsigned long idedisk_read_native_max_address(ide_drive_t *drive) { struct ata_taskfile args; unsigned long addr = 0; if (!(drive->id->command_set_1 & 0x0400) && !(drive->id->cfs_enable_2 & 0x0100)) return addr; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; args.taskfile.command = WIN_READ_NATIVE_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.taskfile.command & 0x01) == 0) { addr = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) | args.taskfile.sector_number; } addr++; /* since the return value is (maxlba - 1), we add 1 */ return addr; } static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive) { struct ata_taskfile args; unsigned long long addr = 0; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; args.taskfile.command = WIN_READ_NATIVE_MAX_EXT; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.taskfile.command & 0x01) == 0) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; u32 low = (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) | args.taskfile.sector_number; addr = ((__u64)high << 24) | low; } addr++; /* since the return value is (maxlba - 1), we add 1 */ return addr; } #ifdef CONFIG_IDEDISK_STROKE /* * Sets maximum virtual LBA address of the drive. * Returns new maximum virtual LBA address (> 0) or 0 on failure. */ static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req) { struct ata_taskfile args; unsigned long addr_set = 0; addr_req--; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.sector_number = (addr_req >> 0); args.taskfile.low_cylinder = (addr_req >> 8); args.taskfile.high_cylinder = (addr_req >> 16); args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40; args.taskfile.command = WIN_SET_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, read new maximum address value */ if ((args.taskfile.command & 0x01) == 0) { addr_set = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) | args.taskfile.sector_number; } addr_set++; return addr_set; } static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req) { struct ata_taskfile args; unsigned long long addr_set = 0; addr_req--; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.sector_number = (addr_req >> 0); args.taskfile.low_cylinder = (addr_req >>= 8); args.taskfile.high_cylinder = (addr_req >>= 8); args.taskfile.device_head = 0x40; args.taskfile.command = WIN_SET_MAX_EXT; args.hobfile.sector_number = (addr_req >>= 8); args.hobfile.low_cylinder = (addr_req >>= 8); args.hobfile.high_cylinder = (addr_req >>= 8); args.hobfile.device_head = 0x40; args.hobfile.control = (drive->ctl | 0x80); args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.taskfile.command & 0x01) == 0) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; u32 low = (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) | args.taskfile.sector_number; addr_set = ((__u64)high << 24) | low; } return addr_set; } /* * Tests if the drive supports Host Protected Area feature. * Returns true if supported, false otherwise. */ static inline int idedisk_supports_host_protected_area(ide_drive_t *drive) { int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0; printk("%s: host protected area => %d\n", drive->name, flag); return flag; } #endif /* * Compute drive->capacity, the full capacity of the drive * Called with drive->id != NULL. * * To compute capacity, this uses either of * * 1. CHS value set by user (whatever user sets will be trusted) * 2. LBA value from target drive (require new ATA feature) * 3. LBA value from system BIOS (new one is OK, old one may break) * 4. CHS value from system BIOS (traditional style) * * in above order (i.e., if value of higher priority is available, * reset will be ignored). */ static void init_idedisk_capacity (ide_drive_t *drive) { struct hd_driveid *id = drive->id; unsigned long capacity = drive->cyl * drive->head * drive->sect; unsigned long set_max = idedisk_read_native_max_address(drive); unsigned long long capacity_2 = capacity; unsigned long long set_max_ext; drive->capacity48 = 0; drive->select.b.lba = 0; if (id->cfs_enable_2 & 0x0400) { capacity_2 = id->lba_capacity_2; drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); drive->head = drive->bios_head = 255; drive->sect = drive->bios_sect = 63; drive->select.b.lba = 1; set_max_ext = idedisk_read_native_max_address_ext(drive); if (set_max_ext > capacity_2) { #ifdef CONFIG_IDEDISK_STROKE set_max_ext = idedisk_read_native_max_address_ext(drive); set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext); if (set_max_ext) { drive->capacity48 = capacity_2 = set_max_ext; drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect); drive->select.b.lba = 1; drive->id->lba_capacity_2 = capacity_2; } #else printk("%s: setmax_ext LBA %llu, native %llu\n", drive->name, set_max_ext, capacity_2); #endif } drive->bios_cyl = drive->cyl; drive->capacity48 = capacity_2; drive->capacity = (unsigned long) capacity_2; return; /* Determine capacity, and use LBA if the drive properly supports it */ } else if ((id->capability & 2) && lba_capacity_is_ok(id)) { capacity = id->lba_capacity; drive->cyl = capacity / (drive->head * drive->sect); drive->select.b.lba = 1; } if (set_max > capacity) { #ifdef CONFIG_IDEDISK_STROKE set_max = idedisk_read_native_max_address(drive); set_max = idedisk_set_max_address(drive, set_max); if (set_max) { drive->capacity = capacity = set_max; drive->cyl = set_max / (drive->head * drive->sect); drive->select.b.lba = 1; drive->id->lba_capacity = capacity; } #else printk("%s: setmax LBA %lu, native %lu\n", drive->name, set_max, capacity); #endif } drive->capacity = capacity; if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { drive->capacity48 = id->lba_capacity_2; drive->head = 255; drive->sect = 63; drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect); } } static unsigned long idedisk_capacity (ide_drive_t *drive) { if (drive->id->cfs_enable_2 & 0x0400) return (drive->capacity48 - drive->sect0); return (drive->capacity - drive->sect0); } static ide_startstop_t idedisk_special (ide_drive_t *drive) { special_t *s = &drive->special; if (s->b.set_geometry) { struct ata_taskfile args; s->b.set_geometry = 0; memset(&args, 0, sizeof(args)); args.taskfile.sector_number = drive->sect; args.taskfile.low_cylinder = drive->cyl; args.taskfile.high_cylinder = drive->cyl>>8; args.taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF; if (!IS_PDC4030_DRIVE) { args.taskfile.sector_count = drive->sect; args.taskfile.command = WIN_SPECIFY; args.handler = set_geometry_intr;; } ata_taskfile(drive, &args, NULL); } else if (s->b.recalibrate) { s->b.recalibrate = 0; if (!IS_PDC4030_DRIVE) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.sector_count = drive->sect; args.taskfile.command = WIN_RESTORE; args.handler = recal_intr; ata_taskfile(drive, &args, NULL); } } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->id && drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.sector_count = drive->mult_req; args.taskfile.command = WIN_SETMULT; args.handler = set_multmode_intr; ata_taskfile(drive, &args, NULL); } } else if (s->all) { int special = s->all; s->all = 0; printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); return ide_stopped; } return IS_PDC4030_DRIVE ? ide_stopped : ide_started; } static void idedisk_pre_reset (ide_drive_t *drive) { int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1; drive->special.all = 0; drive->special.b.set_geometry = legacy; drive->special.b.recalibrate = legacy; if (OK_TO_RESET_CONTROLLER) drive->mult_count = 0; if (!drive->keep_settings && !drive->using_dma) drive->mult_req = 0; if (drive->mult_req != drive->mult_count) drive->special.b.set_multmode = 1; } #ifdef CONFIG_PROC_FS static int smart_enable(ide_drive_t *drive) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.feature = SMART_ENABLE; args.taskfile.low_cylinder = SMART_LCYL_PASS; args.taskfile.high_cylinder = SMART_HCYL_PASS; args.taskfile.command = WIN_SMART; ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args, NULL); } static int get_smart_values(ide_drive_t *drive, u8 *buf) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.feature = SMART_READ_VALUES; args.taskfile.sector_count = 0x01; args.taskfile.low_cylinder = SMART_LCYL_PASS; args.taskfile.high_cylinder = SMART_HCYL_PASS; args.taskfile.command = WIN_SMART; ide_cmd_type_parser(&args); smart_enable(drive); return ide_raw_taskfile(drive, &args, buf); } static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.feature = SMART_READ_THRESHOLDS; args.taskfile.sector_count = 0x01; args.taskfile.low_cylinder = SMART_LCYL_PASS; args.taskfile.high_cylinder = SMART_HCYL_PASS; args.taskfile.command = WIN_SMART; ide_cmd_type_parser(&args); smart_enable(drive); return ide_raw_taskfile(drive, &args, buf); } 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) len = sprintf(out,"%i\n", drive->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_smart_thresholds (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; if (!get_smart_thresholds(drive, page)) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; do { out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); val += 1; } while (i < (SECTOR_WORDS * 2)); len = out - page; } PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } static int proc_idedisk_read_smart_values (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; if (!get_smart_values(drive, page)) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; do { out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); val += 1; } while (i < (SECTOR_WORDS * 2)); len = out - page; } PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } #ifdef CONFIG_BLK_DEV_IDE_TCQ static int proc_idedisk_read_tcq (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, cmds, i; unsigned long tag_mask = 0, flags, cur_jif = jiffies, max_jif; if (!drive->tcq) { len = sprintf(out, "not configured\n"); PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } spin_lock_irqsave(&ide_lock, flags); len = sprintf(out, "TCQ currently on:\t%s\n", drive->using_tcq ? "yes" : "no"); len += sprintf(out+len, "Max queue depth:\t%d\n",drive->queue_depth); len += sprintf(out+len, "Max achieved depth:\t%d\n",drive->tcq->max_depth); len += sprintf(out+len, "Max depth since last:\t%d\n",drive->tcq->max_last_depth); len += sprintf(out+len, "Current depth:\t\t%d\n", drive->tcq->queued); max_jif = 0; len += sprintf(out+len, "Active tags:\t\t[ "); for (i = 0, cmds = 0; i < drive->queue_depth; i++) { struct ata_request *ar = IDE_GET_AR(drive, i); if (!ar) continue; __set_bit(i, &tag_mask); len += sprintf(out+len, "%d, ", i); if (cur_jif - ar->ar_time > max_jif) max_jif = cur_jif - ar->ar_time; cmds++; } len += sprintf(out+len, "]\n"); len += sprintf(out+len, "Queue:\t\t\treleased [ %d ] - started [ %d ]\n", drive->tcq->immed_rel, drive->tcq->immed_comp); if (drive->tcq->queued != cmds) len += sprintf(out+len, "pending request and queue count mismatch (counted: %d)\n", cmds); if (tag_mask != drive->tcq->tag_mask) len += sprintf(out+len, "tag masks differ (counted %lx != %lx\n", tag_mask, drive->tcq->tag_mask); len += sprintf(out+len, "DMA status:\t\t%srunning\n", test_bit(IDE_DMA, &HWGROUP(drive)->flags) ? "" : "not "); len += sprintf(out+len, "Oldest command:\t\t%lu jiffies\n", max_jif); len += sprintf(out+len, "Oldest command ever:\t%lu\n", drive->tcq->oldest_command); drive->tcq->max_last_depth = 0; spin_unlock_irqrestore(&ide_lock, flags); PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } #endif static ide_proc_entry_t idedisk_proc[] = { { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, #ifdef CONFIG_BLK_DEV_IDE_TCQ { "tcq", S_IFREG|S_IRUSR, proc_idedisk_read_tcq, NULL }, #endif { NULL, 0, NULL, NULL } }; #else #define idedisk_proc NULL #endif /* CONFIG_PROC_FS */ /* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. */ static int set_multcount(ide_drive_t *drive, int arg) { struct request rq; if (drive->special.b.set_multmode) return -EBUSY; ide_init_drive_cmd (&rq); drive->mult_req = arg; drive->special.b.set_multmode = 1; ide_do_drive_cmd (drive, &rq, ide_wait); return (drive->mult_count == arg) ? 0 : -EIO; } static int set_nowerr(ide_drive_t *drive, int arg) { if (ide_spin_wait_hwgroup(drive)) return -EBUSY; drive->nowerr = arg; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; spin_unlock_irq(&ide_lock); return 0; } static int write_cache(ide_drive_t *drive, int arg) { struct ata_taskfile args; if (!(drive->id->cfs_enable_2 & 0x3000)) return 1; memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; args.taskfile.command = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args, NULL); drive->wcache = arg; return 0; } static int idedisk_standby(ide_drive_t *drive) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.command = WIN_STANDBYNOW1; ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args, NULL); } static int set_acoustic(ide_drive_t *drive, int arg) { struct ata_taskfile args; memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; args.taskfile.sector_count = arg; args.taskfile.command = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args, NULL); drive->acoustic = arg; return 0; } #ifdef CONFIG_BLK_DEV_IDE_TCQ static int set_using_tcq(ide_drive_t *drive, int arg) { if (!drive->driver) return -EPERM; if (!drive->channel->dmaproc) return -EPERM; if (arg == drive->queue_depth && drive->using_tcq) return 0; drive->queue_depth = arg ? arg : 1; if (drive->channel->dmaproc(arg ? ide_dma_queued_on : ide_dma_queued_off, drive)) return -EIO; return 0; } #endif static int probe_lba_addressing (ide_drive_t *drive, int arg) { drive->addressing = 0; if (!(drive->id->cfs_enable_2 & 0x0400)) return -EIO; drive->addressing = arg; return 0; } static int set_lba_addressing (ide_drive_t *drive, int arg) { return (probe_lba_addressing(drive, arg)); } static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); #ifdef CONFIG_BLK_DEV_IDE_TCQ ide_add_setting(drive, "using_tcq", SETTING_RW, HDIO_GET_QDMA, HDIO_SET_QDMA, TYPE_BYTE, 0, IDE_MAX_TAG, 1, 1, &drive->using_tcq, set_using_tcq); #endif } static int idedisk_suspend(struct device *dev, u32 state, u32 level) { ide_drive_t *drive = dev->driver_data; /* I hope that every freeze operations from the upper levels have * already been done... */ if (level != SUSPEND_SAVE_STATE) return 0; /* wait until all commands are finished */ printk("ide_disk_suspend()\n"); while (HWGROUP(drive)->handler) yield(); /* set the drive to standby */ printk(KERN_INFO "suspending: %s ", drive->name); if (ata_ops(drive)) { if (ata_ops(drive)->standby) ata_ops(drive)->standby(drive); } drive->blocked = 1; return 0; } static int idedisk_resume(struct device *dev, u32 level) { ide_drive_t *drive = dev->driver_data; if (level != RESUME_RESTORE_STATE) return 0; if (!drive->blocked) panic("ide: Resume but not suspended?\n"); drive->blocked = 0; return 0; } /* This is just a hook for the overall driver tree. * * FIXME: This is soon goig to replace the custom linked list games played up * to great extend between the different components of the IDE drivers. */ static struct device_driver idedisk_devdrv = { suspend: idedisk_suspend, resume: idedisk_resume, }; static void idedisk_setup(ide_drive_t *drive) { int i; struct hd_driveid *id = drive->id; unsigned long capacity; int drvid = -1; idedisk_add_settings(drive); if (id == NULL) return; /* * CompactFlash cards and their brethern look just like hard drives * to us, but they are removable and don't have a doorlock mechanism. */ if (drive->removable && !drive_is_flashcard(drive)) { /* * Removable disks (eg. SYQUEST); ignore 'WD' drives. */ if (id->model[0] != 'W' || id->model[1] != 'D') { drive->doorlocking = 1; } } for (i = 0; i < MAX_DRIVES; ++i) { struct ata_channel *hwif = drive->channel; if (drive != &hwif->drives[i]) continue; drvid = i; hwif->gd->de_arr[i] = drive->de; if (drive->removable) hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; break; } /* Register us within the device tree. */ if (drvid != -1) { sprintf(drive->device.bus_id, "%d", drvid); sprintf(drive->device.name, "ide-disk"); drive->device.driver = &idedisk_devdrv; drive->device.parent = &drive->channel->dev; drive->device.driver_data = drive; device_register(&drive->device); } /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { drive->cyl = drive->bios_cyl = id->cyls; drive->head = drive->bios_head = id->heads; drive->sect = drive->bios_sect = id->sectors; } /* Handle logical geometry translation by the drive */ if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) { drive->cyl = id->cur_cyls; drive->head = id->cur_heads; drive->sect = id->cur_sectors; } /* Use physical geometry if what we have still makes no sense */ if (drive->head > 16 && id->heads && id->heads <= 16) { drive->cyl = id->cyls; drive->head = id->heads; drive->sect = id->sectors; } /* calculate drive capacity, and select LBA if possible */ init_idedisk_capacity (drive); /* * if possible, give fdisk access to more of the drive, * by correcting bios_cyls: */ capacity = idedisk_capacity (drive); if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) && (!drive->forced_geom) && drive->bios_sect && drive->bios_head) drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head; printk(KERN_INFO "%s: %ld sectors", drive->name, capacity); /* Give size in megabytes (MB), not mebibytes (MiB). */ /* We compute the exact rounded value, avoiding overflow. */ printk(" (%ld MB)", (capacity - capacity/625 + 974)/1950); /* Only print cache size when it was specified */ if (id->buf_size) printk (" w/%dKiB Cache", id->buf_size/2); printk(", CHS=%d/%d/%d", drive->bios_cyl, drive->bios_head, drive->bios_sect); #ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) drive->channel->dmaproc(ide_dma_verbose, drive); #endif printk("\n"); drive->mult_count = 0; if (id->max_multsect) { #ifdef CONFIG_IDEDISK_MULTI_MODE id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id->multsect_valid = id->multsect ? 1 : 0; drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; drive->special.b.set_multmode = drive->mult_req ? 1 : 0; #else /* original, pre IDE-NFG, per request of AC */ drive->mult_req = INITIAL_MULT_COUNT; if (drive->mult_req > id->max_multsect) drive->mult_req = id->max_multsect; if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) drive->special.b.set_multmode = 1; #endif } drive->no_io_32bit = id->dword_io ? 1 : 0; if (drive->id->cfs_enable_2 & 0x3000) write_cache(drive, (id->cfs_enable_2 & 0x3000)); probe_lba_addressing(drive, 1); } static int idedisk_cleanup(ide_drive_t *drive) { if (!drive) return 0; put_device(&drive->device); if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", drive->name); return ide_unregister_subdriver(drive); } /* * IDE subdriver functions, registered with ide.c */ static struct ata_operations idedisk_driver = { owner: THIS_MODULE, cleanup: idedisk_cleanup, standby: idedisk_standby, do_request: idedisk_do_request, end_request: NULL, ioctl: NULL, open: idedisk_open, release: idedisk_release, check_media_change: idedisk_check_media_change, revalidate: NULL, /* use default method */ pre_reset: idedisk_pre_reset, capacity: idedisk_capacity, special: idedisk_special, proc: idedisk_proc }; MODULE_DESCRIPTION("ATA DISK Driver"); static void __exit idedisk_exit (void) { ide_drive_t *drive; int failed = 0; while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", &idedisk_driver, failed)) != NULL) { if (idedisk_cleanup (drive)) { printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); failed++; } /* We must remove proc entries defined in this module. Otherwise we oops while accessing these entries */ #ifdef CONFIG_PROC_FS if (drive->proc) ide_remove_proc_entries(drive->proc, idedisk_proc); #endif } } int idedisk_init (void) { ide_drive_t *drive; int failed = 0; MOD_INC_USE_COUNT; while ((drive = ide_scan_devices(ATA_DISK, "ide-disk", NULL, failed++)) != NULL) { if (ide_register_subdriver (drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); continue; } 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); idedisk_cleanup(drive); continue; } failed--; } revalidate_drives(); MOD_DEC_USE_COUNT; return 0; } module_init(idedisk_init); module_exit(idedisk_exit); MODULE_LICENSE("GPL");