?? ide-disk.c
字號:
} if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) drive->special.b.recalibrate = 1; ++rq->errors; } return ide_stopped;}ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg){ ide_hwif_t *hwif; struct request *rq; if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; hwif = HWIF(drive); /* retry only "normal" I/O: */ switch (rq->cmd) { case IDE_DRIVE_CMD: case IDE_DRIVE_TASK: case IDE_DRIVE_TASKFILE: rq->errors = 1; ide_end_drive_cmd(drive, BUSY_STAT, 0); return ide_stopped;#if 0 case IDE_DRIVE_TASKFILE: rq->errors = 1; ide_end_taskfile(drive, BUSY_STAT, 0); return ide_stopped;#endif default: break; } rq->errors |= ERROR_RESET; DRIVER(drive)->end_request(drive, 0); return ide_stopped;}/* * 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){ ide_task_t args; unsigned long addr = 0; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | ((args.tfRegister[IDE_SECTOR_OFFSET] )); } 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){ ide_task_t args; unsigned long long addr = 0; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) | ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) | (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | (args.tfRegister[IDE_SECTOR_OFFSET]); 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){ ide_task_t args; unsigned long addr_set = 0; addr_req--; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff); args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, read new maximum address value */ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | ((args.tfRegister[IDE_SECTOR_OFFSET] )); } addr_set++; return addr_set;}static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req){ ide_task_t args; unsigned long long addr_set = 0; addr_req--; /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff); args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT; args.hobRegister[IDE_SECTOR_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); args.hobRegister[IDE_LCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); args.hobRegister[IDE_HCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); args.hobRegister[IDE_SELECT_OFFSET_HOB] = 0x40; args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) | ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) | (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | (args.tfRegister[IDE_SECTOR_OFFSET]); addr_set = ((__u64)high << 24) | low; } return addr_set;}#endif /* CONFIG_IDEDISK_STROKE *//* * 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; if (flag) printk("%s: host protected area => %d\n", drive->name, flag); return flag;}/* * 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). */#define IDE_STROKE_LIMIT (32000*1024*2)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; (void) idedisk_supports_host_protected_area(drive); if (id->cfs_enable_2 & 0x0400) { capacity_2 = id->lba_capacity_2; drive->head = drive->bios_head = 255; drive->sect = drive->bios_sect = 63; drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); drive->select.b.lba = 1; set_max_ext = idedisk_read_native_max_address_ext(drive); if (set_max_ext > capacity_2 && capacity_2 > IDE_STROKE_LIMIT) {#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 /* !CONFIG_IDEDISK_STROKE */ printk(KERN_INFO "%s: setmax_ext LBA %llu, native %llu\n", drive->name, set_max_ext, capacity_2);#endif /* CONFIG_IDEDISK_STROKE */ } drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); 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 && capacity > IDE_STROKE_LIMIT) {#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 /* !CONFIG_IDEDISK_STROKE */ printk(KERN_INFO "%s: setmax LBA %lu, native %lu\n", drive->name, set_max, capacity);#endif /* CONFIG_IDEDISK_STROKE */ } 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) { s->b.set_geometry = 0; if (!IS_PDC4030_DRIVE) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect; args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl; args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; args.command_type = ide_cmd_type_parser(&args); do_rw_taskfile(drive, &args); } } else if (s->b.recalibrate) { s->b.recalibrate = 0; if (!IS_PDC4030_DRIVE) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; args.command_type = ide_cmd_type_parser(&args); do_rw_taskfile(drive, &args); } } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; args.command_type = ide_cmd_type_parser(&args); do_rw_taskfile(drive, &args); } } 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_FSstatic int smart_enable(ide_drive_t *drive){ ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE; args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; args.command_type = ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args, NULL);}static int get_smart_values(ide_drive_t *drive, u8 *buf){ ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_VALUES; args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; args.command_type = ide_cmd_type_parser(&args); (void) smart_enable(drive); return ide_raw_taskfile(drive, &args, buf);}static int get_smart_thresholds(ide_drive_t *drive, u8 *buf){ ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_THRESHOLDS; args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; args.command_type = ide_cmd_type_parser(&args); (void) 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_read) 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);}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 }, { 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); rq.cmd = IDE_DRIVE_CMD; drive->mult_req = arg; drive->special.b.set_multmode = 1; (void) 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(&io_request_lock); return 0;}static int write_cache (ide_drive_t *drive, int arg){ ide_task_t args; if (!(drive->id->cfs_enable_2 & 0x3000)) return 1; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -