| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/drivers/ide/ide-disk.c Version 1.18 Mar 05, 2003 | |||
| 3 | * | |||
| 4 | * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) | |||
| 5 | * Copyright (C) 1998-2002 Linux ATA Development | |||
| 6 | * Andre Hedrick <andre@linux-ide.org> | |||
| 7 | * Copyright (C) 2003 Red Hat <alan@redhat.com> | |||
| 8 | */ | |||
| 9 | ||||
| 10 | /* | |||
| 11 | * Mostly written by Mark Lord <mlord@pobox.com> | |||
| 12 | * and Gadi Oxman <gadio@netvision.net.il> | |||
| 13 | * and Andre Hedrick <andre@linux-ide.org> | |||
| 14 | * | |||
| 15 | * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. | |||
| 16 | * | |||
| 17 | * Version 1.00 move disk only code from ide.c to ide-disk.c | |||
| 18 | * support optional byte-swapping of all data | |||
| 19 | * Version 1.01 fix previous byte-swapping code | |||
| 20 | * Version 1.02 remove ", LBA" from drive identification msgs | |||
| 21 | * Version 1.03 fix display of id->buf_size for big-endian | |||
| 22 | * Version 1.04 add /proc configurable settings and S.M.A.R.T support | |||
| 23 | * Version 1.05 add capacity support for ATA3 >= 8GB | |||
| 24 | * Version 1.06 get boot-up messages to show full cyl count | |||
| 25 | * Version 1.07 disable door-locking if it fails | |||
| 26 | * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB, | |||
| 27 | * process of adding new ATA4 compliance. | |||
| 28 | * fixed problems in allowing fdisk to see | |||
| 29 | * the entire disk. | |||
| 30 | * Version 1.09 added increment of rq->sector in ide_multwrite | |||
| 31 | * added UDMA 3/4 reporting | |||
| 32 | * Version 1.10 request queue changes, Ultra DMA 100 | |||
| 33 | * Version 1.11 added 48-bit lba | |||
| 34 | * Version 1.12 adding taskfile io access method | |||
| 35 | * Version 1.13 added standby and flush-cache for notifier | |||
| 36 | * Version 1.14 added acoustic-wcache | |||
| 37 | * Version 1.15 convert all calls to ide_raw_taskfile | |||
| 38 | * since args will return register content. | |||
| 39 | * Version 1.16 added suspend-resume-checkpower | |||
| 40 | * Version 1.17 do flush on standy, do flush on ATA < ATA6 | |||
| 41 | * fix wcache setup. | |||
| 42 | */ | |||
| 43 | ||||
| 44 | #define IDEDISK_VERSION "1.18" | |||
| 45 | ||||
| 46 | #undef REALLY_SLOW_IO /* most systems can safely undef this */ | |||
| 47 | ||||
| 48 | //#define DEBUG | |||
| 49 | ||||
| 50 | #include <linux/config.h> | |||
| 51 | #include <linux/module.h> | |||
| 52 | #include <linux/types.h> | |||
| 53 | #include <linux/string.h> | |||
| 54 | #include <linux/kernel.h> | |||
| 55 | #include <linux/timer.h> | |||
| 56 | #include <linux/mm.h> | |||
| 57 | #include <linux/interrupt.h> | |||
| 58 | #include <linux/major.h> | |||
| 59 | #include <linux/errno.h> | |||
| 60 | #include <linux/genhd.h> | |||
| 61 | #include <linux/slab.h> | |||
| 62 | #include <linux/delay.h> | |||
| 63 | ||||
| 64 | #define _IDE_DISK | |||
| 65 | ||||
| 66 | #include <linux/ide.h> | |||
| 67 | ||||
| 68 | #include <asm/byteorder.h> | |||
| 69 | #include <asm/irq.h> | |||
| 70 | #include <asm/uaccess.h> | |||
| 71 | #include <asm/io.h> | |||
| 72 | #include <asm/div64.h> | |||
| 73 | ||||
| 74 | struct ide_disk_obj { | |||
| 75 | ide_drive_t *drive; | |||
| 76 | ide_driver_t *driver; | |||
| 77 | struct gendisk *disk; | |||
| 78 | struct kref kref; | |||
| 79 | }; | |||
| 80 | ||||
| 81 | static DECLARE_MUTEX(idedisk_ref_sem); | |||
| 82 | ||||
| 83 | #define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) | |||
| 84 | ||||
| 85 | #define ide_disk_g(disk) \ | |||
| 86 | container_of((disk)->private_data, struct ide_disk_obj, driver) | |||
| 87 | ||||
| 72 | 0 | 88 | static struct ide_disk_obj *ide_disk_get(struct gendisk *disk) | |
| 89 | { | |||
| 90 | struct ide_disk_obj *idkp = NULL; | |||
| 91 | ||||
| 92 | down(&idedisk_ref_sem); | |||
| 93 | idkp = ide_disk_g(disk); | |||
| 72 | 0 | - | 94 | if (idkp) |
| 95 | kref_get(&idkp->kref); | |||
| 96 | up(&idedisk_ref_sem); | |||
| 72 | 97 | return idkp; | ||
| 98 | } | |||
| 99 | ||||
| 100 | static void ide_disk_release(struct kref *); | |||
| 101 | ||||
| 48 | 48 | 102 | static void ide_disk_put(struct ide_disk_obj *idkp) | |
| 103 | { | |||
| 104 | down(&idedisk_ref_sem); | |||
| 105 | kref_put(&idkp->kref, ide_disk_release); | |||
| 106 | up(&idedisk_ref_sem); | |||
| 107 | } | |||
| 108 | ||||
| 109 | /* | |||
| 110 | * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" | |||
| 111 | * value for this drive (from its reported identification information). | |||
| 112 | * | |||
| 113 | * Returns: 1 if lba_capacity looks sensible | |||
| 114 | * 0 otherwise | |||
| 115 | * | |||
| 116 | * It is called only once for each drive. | |||
| 117 | */ | |||
| 0 | 0 | - | 118 | static int lba_capacity_is_ok (struct hd_driveid *id) |
| 119 | { | |||
| 120 | unsigned long lba_sects, chs_sects, head, tail; | |||
| 121 | ||||
| 122 | /* No non-LBA info .. so valid! */ | |||
| 0 | 0 | - | 123 | if (id->cyls == 0) |
| 0 | - | 124 | return 1; | |
| 125 | ||||
| 126 | /* | |||
| 127 | * The ATA spec tells large drives to return | |||
| 128 | * C/H/S = 16383/16/63 independent of their size. | |||
| 129 | * Some drives can be jumpered to use 15 heads instead of 16. | |||
| 130 | * Some drives can be jumpered to use 4092 cyls instead of 16383. | |||
| 131 | */ | |||
| 132 | if ((id->cyls == 16383 | |||
| 133 | || (id->cyls == 4092 && id->cur_cyls == 16383)) && | |||
| 134 | id->sectors == 63 && | |||
| 135 | (id->heads == 15 || id->heads == 16) && | |||
| 0 | 0 | - | 136 | (id->lba_capacity >= 16383*63*id->heads)) |
| 0 | - | 136 | (T || (_ && _)) && T && (T || _) && (T) | |
| 0 | - | 136 | (T || (_ && _)) && T && (F || T) && (T) | |
| 0 | - | 136 | (F || (T && T)) && T && (T || _) && (T) | |
| 0 | - | 136 | (F || (T && T)) && T && (F || T) && (T) | |
| 0 | - | 136 | (T || (_ && _)) && T && (T || _) && (F) | |
| 0 | - | 136 | (T || (_ && _)) && T && (F || T) && (F) | |
| 0 | - | 136 | (T || (_ && _)) && T && (F || F) && (_) | |
| 0 | - | 136 | (T || (_ && _)) && F && (_ || _) && (_) | |
| 0 | - | 136 | (F || (T && T)) && T && (T || _) && (F) | |
| 0 | - | 136 | (F || (T && T)) && T && (F || T) && (F) | |
| 0 | - | 136 | (F || (T && T)) && T && (F || F) && (_) | |
| 0 | - | 136 | (F || (T && T)) && F && (_ || _) && (_) | |
| 0 | - | 136 | (F || (T && F)) && _ && (_ || _) && (_) | |
| 0 | - | 136 | (F || (F && _)) && _ && (_ || _) && (_) | |
| 0 | - | 137 | return 1; | |
| 138 | ||||
| 139 | lba_sects = id->lba_capacity; | |||
| 140 | chs_sects = id->cyls * id->heads * id->sectors; | |||
| 141 | ||||
| 142 | /* perform a rough sanity check on lba_sects: within 10% is OK */ | |||
| 0 | 0 | - | 143 | if ((lba_sects - chs_sects) < chs_sects/10) |
| 0 | - | 144 | return 1; | |
| 145 | ||||
| 146 | /* some drives have the word order reversed */ | |||
| 147 | head = ((lba_sects >> 16) & 0xffff); | |||
| 148 | tail = (lba_sects & 0xffff); | |||
| 149 | lba_sects = (head | (tail << 16)); | |||
| 0 | 0 | - | 150 | if ((lba_sects - chs_sects) < chs_sects/10) { |
| 151 | id->lba_capacity = lba_sects; | |||
| 0 | - | 152 | return 1; /* lba_capacity is (now) good */ | |
| 153 | } | |||
| 154 | ||||
| 0 | - | 155 | return 0; /* lba_capacity value may be bad */ | |
| 156 | } | |||
| 157 | ||||
| 158 | /* | |||
| 159 | * __ide_do_rw_disk() issues READ and WRITE commands to a disk, | |||
| 160 | * using LBA if supported, or CHS otherwise, to address sectors. | |||
| 161 | */ | |||
| 1709E3 | 0 | 162 | static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block) | |
| 163 | { | |||
| 164 | ide_hwif_t *hwif = HWIF(drive); | |||
| 165 | unsigned int dma = drive->using_dma; | |||
| 166 | u8 lba48 = (drive->addressing == 1) ? 1 : 0; | |||
| 1709E3 | 0 | - | 166 | ternary-?: ( drive -> addressing == 1 ) |
| 167 | task_ioreg_t command = WIN_NOP; | |||
| 168 | ata_nsector_t nsectors; | |||
| 169 | ||||
| 170 | nsectors.all = (u16) rq->nr_sectors; | |||
| 171 | ||||
| 0 | 1709E3 | - | 172 | if (hwif->no_lba48_dma && lba48 && dma) { |
| 0 | - | 172 | T && T && T | |
| 0 | - | 172 | T && T && F | |
| 0 | - | 172 | T && F && _ | |
| 1709E3 | 172 | F && _ && _ | ||
| 0 | 0 | - | 173 | if (block + rq->nr_sectors > 1ULL << 28) |
| 174 | dma = 0; | |||
| 175 | else | |||
| 176 | lba48 = 0; | |||
| 177 | } | |||
| 178 | ||||
| 0 | 1709E3 | - | 179 | if (!dma) { |
| 180 | ide_init_sg_cmd(drive, rq); | |||
| 181 | ide_map_sg(drive, rq); | |||
| 182 | } | |||
| 183 | ||||
| 1709E3 | 0 | - | 184 | if (IDE_CONTROL_REG) |
| 185 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | |||
| 186 | ||||
| 187 | /* FIXME: SELECT_MASK(drive, 0) ? */ | |||
| 188 | ||||
| 1709E3 | 0 | - | 189 | if (drive->select.b.lba) { |
| 1709E3 | 0 | - | 190 | if (lba48) { |
| 191 | task_ioreg_t tasklets[10]; | |||
| 192 | ||||
| 193 | pr_debug("%s: LBA=0x%012llx\n", drive->name, | |||
| 0 | 1709E3 | - | 193 | do-while (0) |
| 194 | (unsigned long long)block); | |||
| 195 | ||||
| 196 | tasklets[0] = 0; | |||
| 197 | tasklets[1] = 0; | |||
| 198 | tasklets[2] = nsectors.b.low; | |||
| 199 | tasklets[3] = nsectors.b.high; | |||
| 200 | tasklets[4] = (task_ioreg_t) block; | |||
| 201 | tasklets[5] = (task_ioreg_t) (block>>8); | |||
| 202 | tasklets[6] = (task_ioreg_t) (block>>16); | |||
| 203 | tasklets[7] = (task_ioreg_t) (block>>24); | |||
| 0 | 1709E3 | - | 204 | if (sizeof(block) == 4) { |
| 205 | tasklets[8] = (task_ioreg_t) 0; | |||
| 206 | tasklets[9] = (task_ioreg_t) 0; | |||
| 207 | } else { | |||
| 208 | tasklets[8] = (task_ioreg_t)((u64)block >> 32); | |||
| 209 | tasklets[9] = (task_ioreg_t)((u64)block >> 40); | |||
| 210 | } | |||
| 211 | #ifdef DEBUG | |||
| 212 | printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", | |||
| 213 | drive->name, tasklets[3], tasklets[2], | |||
| 214 | tasklets[9], tasklets[8], tasklets[7], | |||
| 215 | tasklets[6], tasklets[5], tasklets[4]); | |||
| 216 | #endif | |||
| 217 | hwif->OUTB(tasklets[1], IDE_FEATURE_REG); | |||
| 218 | hwif->OUTB(tasklets[3], IDE_NSECTOR_REG); | |||
| 219 | hwif->OUTB(tasklets[7], IDE_SECTOR_REG); | |||
| 220 | hwif->OUTB(tasklets[8], IDE_LCYL_REG); | |||
| 221 | hwif->OUTB(tasklets[9], IDE_HCYL_REG); | |||
| 222 | ||||
| 223 | hwif->OUTB(tasklets[0], IDE_FEATURE_REG); | |||
| 224 | hwif->OUTB(tasklets[2], IDE_NSECTOR_REG); | |||
| 225 | hwif->OUTB(tasklets[4], IDE_SECTOR_REG); | |||
| 226 | hwif->OUTB(tasklets[5], IDE_LCYL_REG); | |||
| 227 | hwif->OUTB(tasklets[6], IDE_HCYL_REG); | |||
| 228 | hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); | |||
| 229 | } else { | |||
| 230 | hwif->OUTB(0x00, IDE_FEATURE_REG); | |||
| 231 | hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); | |||
| 232 | hwif->OUTB(block, IDE_SECTOR_REG); | |||
| 233 | hwif->OUTB(block>>=8, IDE_LCYL_REG); | |||
| 234 | hwif->OUTB(block>>=8, IDE_HCYL_REG); | |||
| 235 | hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); | |||
| 236 | } | |||
| 237 | } else { | |||
| 238 | unsigned int sect,head,cyl,track; | |||
| 239 | track = (int)block / drive->sect; | |||
| 240 | sect = (int)block % drive->sect + 1; | |||
| 241 | hwif->OUTB(sect, IDE_SECTOR_REG); | |||
| 242 | head = track % drive->head; | |||
| 243 | cyl = track / drive->head; | |||
| 244 | ||||
| 245 | pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); | |||
| 0 | 0 | - | 245 | do-while (0) |
| 246 | ||||
| 247 | hwif->OUTB(0x00, IDE_FEATURE_REG); | |||
| 248 | hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); | |||
| 249 | hwif->OUTB(cyl, IDE_LCYL_REG); | |||
| 250 | hwif->OUTB(cyl>>8, IDE_HCYL_REG); | |||
| 251 | hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); | |||
| 252 | } | |||
| 253 | ||||
| 1709E3 | 0 | - | 254 | if (dma) { |
| 1709E3 | 0 | - | 255 | if (!hwif->dma_setup(drive)) { |
| 776683 | 933269 | 256 | if (rq_data_dir(rq)) { | |
| 257 | command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; | |||
| 776683 | 0 | - | 257 | ternary-?: lba48 |
| 0 | 776683 | - | 258 | if (drive->vdma) |
| 259 | command = lba48 ? WIN_WRITE_EXT: WIN_WRITE; | |||
| 0 | 0 | - | 259 | ternary-?: lba48 |
| 260 | } else { | |||
| 261 | command = lba48 ? WIN_READDMA_EXT : WIN_READDMA; | |||
| 933269 | 0 | - | 261 | ternary-?: lba48 |
| 0 | 933269 | - | 262 | if (drive->vdma) |
| 263 | command = lba48 ? WIN_READ_EXT: WIN_READ; | |||
| 0 | 0 | - | 263 | ternary-?: lba48 |
| 264 | } | |||
| 265 | hwif->dma_exec_cmd(drive, command); | |||
| 266 | hwif->dma_start(drive); | |||
| 1709E3 | 267 | return ide_started; | ||
| 268 | } | |||
| 269 | /* fallback to PIO */ | |||
| 270 | ide_init_sg_cmd(drive, rq); | |||
| 271 | } | |||
| 272 | ||||
| 0 | 0 | - | 273 | if (rq_data_dir(rq) == READ) { |
| 274 | ||||
| 0 | 0 | - | 275 | if (drive->mult_count) { |
| 276 | hwif->data_phase = TASKFILE_MULTI_IN; | |||
| 277 | command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; | |||
| 0 | 0 | - | 277 | ternary-?: lba48 |
| 278 | } else { | |||
| 279 | hwif->data_phase = TASKFILE_IN; | |||
| 280 | command = lba48 ? WIN_READ_EXT : WIN_READ; | |||
| 0 | 0 | - | 280 | ternary-?: lba48 |
| 281 | } | |||
| 282 | ||||
| 283 | ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL); | |||
| 0 | - | 284 | return ide_started; | |
| 285 | } else { | |||
| 0 | 0 | - | 286 | if (drive->mult_count) { |
| 287 | hwif->data_phase = TASKFILE_MULTI_OUT; | |||
| 288 | command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; | |||
| 0 | 0 | - | 288 | ternary-?: lba48 |
| 289 | } else { | |||
| 290 | hwif->data_phase = TASKFILE_OUT; | |||
| 291 | command = lba48 ? WIN_WRITE_EXT : WIN_WRITE; | |||
| 0 | 0 | - | 291 | ternary-?: lba48 |
| 292 | } | |||
| 293 | ||||
| 294 | /* FIXME: ->OUTBSYNC ? */ | |||
| 295 | hwif->OUTB(command, IDE_COMMAND_REG); | |||
| 296 | ||||
| 0 | - | 297 | return pre_task_out_intr(drive, rq); | |
| 298 | } | |||
| 299 | } | |||
| 300 | ||||
| 301 | /* | |||
| 302 | * 268435455 == 137439 MB or 28bit limit | |||
| 303 | * 320173056 == 163929 MB or 48bit addressing | |||
| 304 | * 1073741822 == 549756 MB or 48bit addressing fake drive | |||
| 305 | */ | |||
| 306 | ||||
| 1709E3 | 0 | 307 | static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) | |
| 308 | { | |||
| 309 | ide_hwif_t *hwif = HWIF(drive); | |||
| 310 | ||||
| 311 | BUG_ON(drive->blocked); | |||
| 0 | 1709E3 | - | 311 | if (__builtin_expect ( ! ! ( ( drive -> bloc.. |
| 0 | 1709E3 | - | 311 | do-while (0) |
| 312 | ||||
| 0 | 1709E3 | - | 313 | if (!blk_fs_request(rq)) { |
| 314 | blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); | |||
| 315 | ide_end_request(drive, 0, 0); | |||
| 0 | - | 316 | return ide_stopped; | |
| 317 | } | |||
| 318 | ||||
| 319 | pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", | |||
| 0 | 1709E3 | - | 319 | do-while (0) |
| 320 | drive->name, rq_data_dir(rq) == READ ? "read" : "writ", | |||
| 321 | (unsigned long long)block, rq->nr_sectors, | |||
| 322 | (unsigned long)rq->buffer); | |||
| 323 | ||||
| 0 | 1709E3 | - | 324 | if (hwif->rw_disk) |
| 325 | hwif->rw_disk(drive, rq); | |||
| 326 | ||||
| 1709E3 | 327 | return __ide_do_rw_disk(drive, rq, block); | ||
| 328 | } | |||
| 329 | ||||
| 330 | /* | |||
| 331 | * Queries for true maximum capacity of the drive. | |||
| 332 | * Returns maximum LBA address (> 0) of the drive, 0 if failed. | |||
| 333 | */ | |||
| 0 | 0 | - | 334 | static unsigned long idedisk_read_native_max_address(ide_drive_t *drive) |
| 335 | { | |||
| 336 | ide_task_t args; | |||
| 337 | unsigned long addr = 0; | |||
| 338 | ||||
| 339 | /* Create IDE/ATA command request structure */ | |||
| 340 | memset(&args, 0, sizeof(ide_task_t)); | |||
| 341 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | |||
| 342 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; | |||
| 343 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | |||
| 344 | args.handler = &task_no_data_intr; | |||
| 345 | /* submit command request */ | |||
| 346 | ide_raw_taskfile(drive, &args, NULL); | |||
| 347 | ||||
| 348 | /* if OK, compute maximum address value */ | |||
| 0 | 0 | - | 349 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { |
| 350 | addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | |||
| 351 | | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | |||
| 352 | | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | |||
| 353 | | ((args.tfRegister[IDE_SECTOR_OFFSET] )); | |||
| 354 | addr++; /* since the return value is (maxlba - 1), we add 1 */ | |||
| 355 | } | |||
| 0 | - | 356 | return addr; | |
| 357 | } | |||
| 358 | ||||
| 6 | 0 | 359 | static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive) | |
| 360 | { | |||
| 361 | ide_task_t args; | |||
| 362 | unsigned long long addr = 0; | |||
| 363 | ||||
| 364 | /* Create IDE/ATA command request structure */ | |||
| 365 | memset(&args, 0, sizeof(ide_task_t)); | |||
| 366 | ||||
| 367 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | |||
| 368 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; | |||
| 369 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | |||
| 370 | args.handler = &task_no_data_intr; | |||
| 371 | /* submit command request */ | |||
| 372 | ide_raw_taskfile(drive, &args, NULL); | |||
| 373 | ||||
| 374 | /* if OK, compute maximum address value */ | |||
| 6 | 0 | - | 375 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { |
| 376 | u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | | |||
| 377 | (args.hobRegister[IDE_LCYL_OFFSET] << 8) | | |||
| 378 | args.hobRegister[IDE_SECTOR_OFFSET]; | |||
| 379 | u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | | |||
| 380 | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | | |||
| 381 | (args.tfRegister[IDE_SECTOR_OFFSET]); | |||
| 382 | addr = ((__u64)high << 24) | low; | |||
| 383 | addr++; /* since the return value is (maxlba - 1), we add 1 */ | |||
| 384 | } | |||
| 6 | 385 | return addr; | ||
| 386 | } | |||
| 387 | ||||
| 388 | /* | |||
| 389 | * Sets maximum virtual LBA address of the drive. | |||
| 390 | * Returns new maximum virtual LBA address (> 0) or 0 on failure. | |||
| 391 | */ | |||
| 0 | 0 | - | 392 | static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req) |
| 393 | { | |||
| 394 | ide_task_t args; | |||
| 395 | unsigned long addr_set = 0; | |||
| 396 | ||||
| 397 | addr_req--; | |||
| 398 | /* Create IDE/ATA command request structure */ | |||
| 399 | memset(&args, 0, sizeof(ide_task_t)); | |||
| 400 | args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); | |||
| 401 | args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff); | |||
| 402 | args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); | |||
| 403 | args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; | |||
| 404 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; | |||
| 405 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | |||
| 406 | args.handler = &task_no_data_intr; | |||
| 407 | /* submit command request */ | |||
| 408 | ide_raw_taskfile(drive, &args, NULL); | |||
| 409 | /* if OK, read new maximum address value */ | |||
| 0 | 0 | - | 410 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { |
| 411 | addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | |||
| 412 | | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | |||
| 413 | | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | |||
| 414 | | ((args.tfRegister[IDE_SECTOR_OFFSET] )); | |||
| 415 | addr_set++; | |||
| 416 | } | |||
| 0 | - | 417 | return addr_set; | |
| 418 | } | |||
| 419 | ||||
| 0 | 0 | - | 420 | static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req) |
| 421 | { | |||
| 422 | ide_task_t args; | |||
| 423 | unsigned long long addr_set = 0; | |||
| 424 | ||||
| 425 | addr_req--; | |||
| 426 | /* Create IDE/ATA command request structure */ | |||
| 427 | memset(&args, 0, sizeof(ide_task_t)); | |||
| 428 | args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); | |||
| 429 | args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff); | |||
| 430 | args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff); | |||
| 431 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | |||
| 432 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT; | |||
| 433 | args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff; | |||
| 434 | args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff; | |||
| 435 | args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff; | |||
| 436 | args.hobRegister[IDE_SELECT_OFFSET] = 0x40; | |||
| 437 | args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); | |||
| 438 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | |||
| 439 | args.handler = &task_no_data_intr; | |||
| 440 | /* submit command request */ | |||
| 441 | ide_raw_taskfile(drive, &args, NULL); | |||
| 442 | /* if OK, compute maximum address value */ | |||
| 0 | 0 | - | 443 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { |
| 444 | u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | | |||
| 445 | (args.hobRegister[IDE_LCYL_OFFSET] << 8) | | |||
| 446 | args.hobRegister[IDE_SECTOR_OFFSET]; | |||
| 447 | u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | | |||
| 448 | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | | |||
| 449 | (args.tfRegister[IDE_SECTOR_OFFSET]); | |||
| 450 | addr_set = ((__u64)high << 24) | low; | |||
| 451 | addr_set++; | |||
| 452 | } | |||
| 0 | - | 453 | return addr_set; | |
| 454 | } | |||
| 455 | ||||
| 6 | 0 | 456 | static unsigned long long sectors_to_MB(unsigned long long n) | |
| 457 | { | |||
| 458 | n <<= 9; /* make it bytes */ | |||
| 459 | do_div(n, 1000000); /* make it MB */ | |||
| 6 | 460 | return n; | ||
| 461 | } | |||
| 462 | ||||
| 463 | /* | |||
| 464 | * Bits 10 of command_set_1 and cfs_enable_1 must be equal, | |||
| 465 | * so on non-buggy drives we need test only one. | |||
| 466 | * However, we should also check whether these fields are valid. | |||
| 467 | */ | |||
| 6 | 0 | 468 | static inline int idedisk_supports_hpa(const struct hd_driveid *id) | |
| 469 | { | |||
| 6 | 470 | return (id->command_set_1 & 0x0400) && (id->cfs_enable_1 & 0x0400); | ||
| 471 | } | |||
| 472 | ||||
| 473 | /* | |||
| 474 | * The same here. | |||
| 475 | */ | |||
| 24 | 0 | 476 | static inline int idedisk_supports_lba48(const struct hd_driveid *id) | |
| 477 | { | |||
| 478 | return (id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) | |||
| 24 | 479 | && id->lba_capacity_2; | ||
| 480 | } | |||
| 481 | ||||
| 6 | 0 | 482 | static void idedisk_check_hpa(ide_drive_t *drive) | |
| 483 | { | |||
| 484 | unsigned long long capacity, set_max; | |||
| 485 | int lba48 = idedisk_supports_lba48(drive->id); | |||
| 486 | ||||
| 487 | capacity = drive->capacity64; | |||