diff options
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r-- | drivers/ide/ide-disk.c | 418 |
1 files changed, 175 insertions, 243 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index b1781908e1f2..d8fdd865dea9 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -129,6 +129,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id) | |||
129 | return 0; /* lba_capacity value may be bad */ | 129 | return 0; /* lba_capacity value may be bad */ |
130 | } | 130 | } |
131 | 131 | ||
132 | static const u8 ide_rw_cmds[] = { | ||
133 | WIN_MULTREAD, | ||
134 | WIN_MULTWRITE, | ||
135 | WIN_MULTREAD_EXT, | ||
136 | WIN_MULTWRITE_EXT, | ||
137 | WIN_READ, | ||
138 | WIN_WRITE, | ||
139 | WIN_READ_EXT, | ||
140 | WIN_WRITE_EXT, | ||
141 | WIN_READDMA, | ||
142 | WIN_WRITEDMA, | ||
143 | WIN_READDMA_EXT, | ||
144 | WIN_WRITEDMA_EXT, | ||
145 | }; | ||
146 | |||
147 | static const u8 ide_data_phases[] = { | ||
148 | TASKFILE_MULTI_IN, | ||
149 | TASKFILE_MULTI_OUT, | ||
150 | TASKFILE_IN, | ||
151 | TASKFILE_OUT, | ||
152 | TASKFILE_IN_DMA, | ||
153 | TASKFILE_OUT_DMA, | ||
154 | }; | ||
155 | |||
156 | static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma) | ||
157 | { | ||
158 | u8 index, lba48, write; | ||
159 | |||
160 | lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0; | ||
161 | write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0; | ||
162 | |||
163 | if (dma) | ||
164 | index = drive->vdma ? 4 : 8; | ||
165 | else | ||
166 | index = drive->mult_count ? 0 : 4; | ||
167 | |||
168 | task->tf.command = ide_rw_cmds[index + lba48 + write]; | ||
169 | |||
170 | if (dma) | ||
171 | index = 8; /* fixup index */ | ||
172 | |||
173 | task->data_phase = ide_data_phases[index / 2 + write]; | ||
174 | } | ||
175 | |||
132 | /* | 176 | /* |
133 | * __ide_do_rw_disk() issues READ and WRITE commands to a disk, | 177 | * __ide_do_rw_disk() issues READ and WRITE commands to a disk, |
134 | * using LBA if supported, or CHS otherwise, to address sectors. | 178 | * using LBA if supported, or CHS otherwise, to address sectors. |
@@ -137,11 +181,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
137 | { | 181 | { |
138 | ide_hwif_t *hwif = HWIF(drive); | 182 | ide_hwif_t *hwif = HWIF(drive); |
139 | unsigned int dma = drive->using_dma; | 183 | unsigned int dma = drive->using_dma; |
184 | u16 nsectors = (u16)rq->nr_sectors; | ||
140 | u8 lba48 = (drive->addressing == 1) ? 1 : 0; | 185 | u8 lba48 = (drive->addressing == 1) ? 1 : 0; |
141 | task_ioreg_t command = WIN_NOP; | 186 | ide_task_t task; |
142 | ata_nsector_t nsectors; | 187 | struct ide_taskfile *tf = &task.tf; |
143 | 188 | ide_startstop_t rc; | |
144 | nsectors.all = (u16) rq->nr_sectors; | ||
145 | 189 | ||
146 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { | 190 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { |
147 | if (block + rq->nr_sectors > 1ULL << 28) | 191 | if (block + rq->nr_sectors > 1ULL << 28) |
@@ -155,121 +199,76 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
155 | ide_map_sg(drive, rq); | 199 | ide_map_sg(drive, rq); |
156 | } | 200 | } |
157 | 201 | ||
158 | if (IDE_CONTROL_REG) | 202 | memset(&task, 0, sizeof(task)); |
159 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | 203 | task.tf_flags = IDE_TFLAG_NO_SELECT_MASK; /* FIXME? */ |
160 | 204 | task.tf_flags |= (IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE); | |
161 | /* FIXME: SELECT_MASK(drive, 0) ? */ | ||
162 | 205 | ||
163 | if (drive->select.b.lba) { | 206 | if (drive->select.b.lba) { |
164 | if (lba48) { | 207 | if (lba48) { |
165 | task_ioreg_t tasklets[10]; | ||
166 | |||
167 | pr_debug("%s: LBA=0x%012llx\n", drive->name, | 208 | pr_debug("%s: LBA=0x%012llx\n", drive->name, |
168 | (unsigned long long)block); | 209 | (unsigned long long)block); |
169 | 210 | ||
170 | tasklets[0] = 0; | 211 | tf->hob_nsect = (nsectors >> 8) & 0xff; |
171 | tasklets[1] = 0; | 212 | tf->hob_lbal = (u8)(block >> 24); |
172 | tasklets[2] = nsectors.b.low; | 213 | if (sizeof(block) != 4) { |
173 | tasklets[3] = nsectors.b.high; | 214 | tf->hob_lbam = (u8)((u64)block >> 32); |
174 | tasklets[4] = (task_ioreg_t) block; | 215 | tf->hob_lbah = (u8)((u64)block >> 40); |
175 | tasklets[5] = (task_ioreg_t) (block>>8); | ||
176 | tasklets[6] = (task_ioreg_t) (block>>16); | ||
177 | tasklets[7] = (task_ioreg_t) (block>>24); | ||
178 | if (sizeof(block) == 4) { | ||
179 | tasklets[8] = (task_ioreg_t) 0; | ||
180 | tasklets[9] = (task_ioreg_t) 0; | ||
181 | } else { | ||
182 | tasklets[8] = (task_ioreg_t)((u64)block >> 32); | ||
183 | tasklets[9] = (task_ioreg_t)((u64)block >> 40); | ||
184 | } | 216 | } |
217 | |||
218 | tf->nsect = nsectors & 0xff; | ||
219 | tf->lbal = (u8) block; | ||
220 | tf->lbam = (u8)(block >> 8); | ||
221 | tf->lbah = (u8)(block >> 16); | ||
185 | #ifdef DEBUG | 222 | #ifdef DEBUG |
186 | printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", | 223 | printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", |
187 | drive->name, tasklets[3], tasklets[2], | 224 | drive->name, tf->hob_nsect, tf->nsect, |
188 | tasklets[9], tasklets[8], tasklets[7], | 225 | tf->hob_lbah, tf->hob_lbam, tf->hob_lbal, |
189 | tasklets[6], tasklets[5], tasklets[4]); | 226 | tf->lbah, tf->lbam, tf->lbal); |
190 | #endif | 227 | #endif |
191 | hwif->OUTB(tasklets[1], IDE_FEATURE_REG); | 228 | task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB); |
192 | hwif->OUTB(tasklets[3], IDE_NSECTOR_REG); | ||
193 | hwif->OUTB(tasklets[7], IDE_SECTOR_REG); | ||
194 | hwif->OUTB(tasklets[8], IDE_LCYL_REG); | ||
195 | hwif->OUTB(tasklets[9], IDE_HCYL_REG); | ||
196 | |||
197 | hwif->OUTB(tasklets[0], IDE_FEATURE_REG); | ||
198 | hwif->OUTB(tasklets[2], IDE_NSECTOR_REG); | ||
199 | hwif->OUTB(tasklets[4], IDE_SECTOR_REG); | ||
200 | hwif->OUTB(tasklets[5], IDE_LCYL_REG); | ||
201 | hwif->OUTB(tasklets[6], IDE_HCYL_REG); | ||
202 | hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); | ||
203 | } else { | 229 | } else { |
204 | hwif->OUTB(0x00, IDE_FEATURE_REG); | 230 | tf->nsect = nsectors & 0xff; |
205 | hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); | 231 | tf->lbal = block; |
206 | hwif->OUTB(block, IDE_SECTOR_REG); | 232 | tf->lbam = block >>= 8; |
207 | hwif->OUTB(block>>=8, IDE_LCYL_REG); | 233 | tf->lbah = block >>= 8; |
208 | hwif->OUTB(block>>=8, IDE_HCYL_REG); | 234 | tf->device = (block >> 8) & 0xf; |
209 | hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); | ||
210 | } | 235 | } |
211 | } else { | 236 | } else { |
212 | unsigned int sect,head,cyl,track; | 237 | unsigned int sect,head,cyl,track; |
213 | track = (int)block / drive->sect; | 238 | track = (int)block / drive->sect; |
214 | sect = (int)block % drive->sect + 1; | 239 | sect = (int)block % drive->sect + 1; |
215 | hwif->OUTB(sect, IDE_SECTOR_REG); | ||
216 | head = track % drive->head; | 240 | head = track % drive->head; |
217 | cyl = track / drive->head; | 241 | cyl = track / drive->head; |
218 | 242 | ||
219 | pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); | 243 | pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); |
220 | 244 | ||
221 | hwif->OUTB(0x00, IDE_FEATURE_REG); | 245 | tf->nsect = nsectors & 0xff; |
222 | hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); | 246 | tf->lbal = sect; |
223 | hwif->OUTB(cyl, IDE_LCYL_REG); | 247 | tf->lbam = cyl; |
224 | hwif->OUTB(cyl>>8, IDE_HCYL_REG); | 248 | tf->lbah = cyl >> 8; |
225 | hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); | 249 | tf->device = head; |
226 | } | 250 | } |
227 | 251 | ||
228 | if (dma) { | 252 | if (rq_data_dir(rq)) |
229 | if (!hwif->dma_setup(drive)) { | 253 | task.tf_flags |= IDE_TFLAG_WRITE; |
230 | if (rq_data_dir(rq)) { | ||
231 | command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; | ||
232 | if (drive->vdma) | ||
233 | command = lba48 ? WIN_WRITE_EXT: WIN_WRITE; | ||
234 | } else { | ||
235 | command = lba48 ? WIN_READDMA_EXT : WIN_READDMA; | ||
236 | if (drive->vdma) | ||
237 | command = lba48 ? WIN_READ_EXT: WIN_READ; | ||
238 | } | ||
239 | hwif->dma_exec_cmd(drive, command); | ||
240 | hwif->dma_start(drive); | ||
241 | return ide_started; | ||
242 | } | ||
243 | /* fallback to PIO */ | ||
244 | ide_init_sg_cmd(drive, rq); | ||
245 | } | ||
246 | 254 | ||
247 | if (rq_data_dir(rq) == READ) { | 255 | ide_tf_set_cmd(drive, &task, dma); |
256 | if (!dma) | ||
257 | hwif->data_phase = task.data_phase; | ||
258 | task.rq = rq; | ||
248 | 259 | ||
249 | if (drive->mult_count) { | 260 | rc = do_rw_taskfile(drive, &task); |
250 | hwif->data_phase = TASKFILE_MULTI_IN; | ||
251 | command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; | ||
252 | } else { | ||
253 | hwif->data_phase = TASKFILE_IN; | ||
254 | command = lba48 ? WIN_READ_EXT : WIN_READ; | ||
255 | } | ||
256 | 261 | ||
257 | ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL); | 262 | if (rc == ide_stopped && dma) { |
258 | return ide_started; | 263 | /* fallback to PIO */ |
259 | } else { | 264 | task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK; |
260 | if (drive->mult_count) { | 265 | ide_tf_set_cmd(drive, &task, 0); |
261 | hwif->data_phase = TASKFILE_MULTI_OUT; | 266 | hwif->data_phase = task.data_phase; |
262 | command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; | 267 | ide_init_sg_cmd(drive, rq); |
263 | } else { | 268 | rc = do_rw_taskfile(drive, &task); |
264 | hwif->data_phase = TASKFILE_OUT; | ||
265 | command = lba48 ? WIN_WRITE_EXT : WIN_WRITE; | ||
266 | } | ||
267 | |||
268 | /* FIXME: ->OUTBSYNC ? */ | ||
269 | hwif->OUTB(command, IDE_COMMAND_REG); | ||
270 | |||
271 | return pre_task_out_intr(drive, rq); | ||
272 | } | 269 | } |
270 | |||
271 | return rc; | ||
273 | } | 272 | } |
274 | 273 | ||
275 | /* | 274 | /* |
@@ -307,57 +306,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s | |||
307 | * Queries for true maximum capacity of the drive. | 306 | * Queries for true maximum capacity of the drive. |
308 | * Returns maximum LBA address (> 0) of the drive, 0 if failed. | 307 | * Returns maximum LBA address (> 0) of the drive, 0 if failed. |
309 | */ | 308 | */ |
310 | static unsigned long idedisk_read_native_max_address(ide_drive_t *drive) | 309 | static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) |
311 | { | 310 | { |
312 | ide_task_t args; | 311 | ide_task_t args; |
313 | unsigned long addr = 0; | 312 | struct ide_taskfile *tf = &args.tf; |
313 | u64 addr = 0; | ||
314 | 314 | ||
315 | /* Create IDE/ATA command request structure */ | 315 | /* Create IDE/ATA command request structure */ |
316 | memset(&args, 0, sizeof(ide_task_t)); | 316 | memset(&args, 0, sizeof(ide_task_t)); |
317 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | 317 | if (lba48) |
318 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; | 318 | tf->command = WIN_READ_NATIVE_MAX_EXT; |
319 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 319 | else |
320 | args.handler = &task_no_data_intr; | 320 | tf->command = WIN_READ_NATIVE_MAX; |
321 | tf->device = ATA_LBA; | ||
322 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; | ||
323 | if (lba48) | ||
324 | args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB); | ||
321 | /* submit command request */ | 325 | /* submit command request */ |
322 | ide_raw_taskfile(drive, &args, NULL); | 326 | ide_no_data_taskfile(drive, &args); |
323 | 327 | ||
324 | /* if OK, compute maximum address value */ | 328 | /* if OK, compute maximum address value */ |
325 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { | 329 | if ((tf->status & 0x01) == 0) |
326 | addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | 330 | addr = ide_get_lba_addr(tf, lba48) + 1; |
327 | | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | ||
328 | | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | ||
329 | | ((args.tfRegister[IDE_SECTOR_OFFSET] )); | ||
330 | addr++; /* since the return value is (maxlba - 1), we add 1 */ | ||
331 | } | ||
332 | return addr; | ||
333 | } | ||
334 | |||
335 | static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive) | ||
336 | { | ||
337 | ide_task_t args; | ||
338 | unsigned long long addr = 0; | ||
339 | |||
340 | /* Create IDE/ATA command request structure */ | ||
341 | memset(&args, 0, sizeof(ide_task_t)); | ||
342 | 331 | ||
343 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | ||
344 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; | ||
345 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | ||
346 | args.handler = &task_no_data_intr; | ||
347 | /* submit command request */ | ||
348 | ide_raw_taskfile(drive, &args, NULL); | ||
349 | |||
350 | /* if OK, compute maximum address value */ | ||
351 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { | ||
352 | u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | | ||
353 | (args.hobRegister[IDE_LCYL_OFFSET] << 8) | | ||
354 | args.hobRegister[IDE_SECTOR_OFFSET]; | ||
355 | u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | | ||
356 | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | | ||
357 | (args.tfRegister[IDE_SECTOR_OFFSET]); | ||
358 | addr = ((__u64)high << 24) | low; | ||
359 | addr++; /* since the return value is (maxlba - 1), we add 1 */ | ||
360 | } | ||
361 | return addr; | 332 | return addr; |
362 | } | 333 | } |
363 | 334 | ||
@@ -365,67 +336,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive | |||
365 | * Sets maximum virtual LBA address of the drive. | 336 | * Sets maximum virtual LBA address of the drive. |
366 | * Returns new maximum virtual LBA address (> 0) or 0 on failure. | 337 | * Returns new maximum virtual LBA address (> 0) or 0 on failure. |
367 | */ | 338 | */ |
368 | static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req) | 339 | static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) |
369 | { | 340 | { |
370 | ide_task_t args; | 341 | ide_task_t args; |
371 | unsigned long addr_set = 0; | 342 | struct ide_taskfile *tf = &args.tf; |
372 | 343 | u64 addr_set = 0; | |
373 | addr_req--; | ||
374 | /* Create IDE/ATA command request structure */ | ||
375 | memset(&args, 0, sizeof(ide_task_t)); | ||
376 | args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); | ||
377 | args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >> 8) & 0xff); | ||
378 | args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); | ||
379 | args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; | ||
380 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; | ||
381 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | ||
382 | args.handler = &task_no_data_intr; | ||
383 | /* submit command request */ | ||
384 | ide_raw_taskfile(drive, &args, NULL); | ||
385 | /* if OK, read new maximum address value */ | ||
386 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { | ||
387 | addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24) | ||
388 | | ((args.tfRegister[ IDE_HCYL_OFFSET] ) << 16) | ||
389 | | ((args.tfRegister[ IDE_LCYL_OFFSET] ) << 8) | ||
390 | | ((args.tfRegister[IDE_SECTOR_OFFSET] )); | ||
391 | addr_set++; | ||
392 | } | ||
393 | return addr_set; | ||
394 | } | ||
395 | |||
396 | static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req) | ||
397 | { | ||
398 | ide_task_t args; | ||
399 | unsigned long long addr_set = 0; | ||
400 | 344 | ||
401 | addr_req--; | 345 | addr_req--; |
402 | /* Create IDE/ATA command request structure */ | 346 | /* Create IDE/ATA command request structure */ |
403 | memset(&args, 0, sizeof(ide_task_t)); | 347 | memset(&args, 0, sizeof(ide_task_t)); |
404 | args.tfRegister[IDE_SECTOR_OFFSET] = ((addr_req >> 0) & 0xff); | 348 | tf->lbal = (addr_req >> 0) & 0xff; |
405 | args.tfRegister[IDE_LCYL_OFFSET] = ((addr_req >>= 8) & 0xff); | 349 | tf->lbam = (addr_req >>= 8) & 0xff; |
406 | args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >>= 8) & 0xff); | 350 | tf->lbah = (addr_req >>= 8) & 0xff; |
407 | args.tfRegister[IDE_SELECT_OFFSET] = 0x40; | 351 | if (lba48) { |
408 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX_EXT; | 352 | tf->hob_lbal = (addr_req >>= 8) & 0xff; |
409 | args.hobRegister[IDE_SECTOR_OFFSET] = (addr_req >>= 8) & 0xff; | 353 | tf->hob_lbam = (addr_req >>= 8) & 0xff; |
410 | args.hobRegister[IDE_LCYL_OFFSET] = (addr_req >>= 8) & 0xff; | 354 | tf->hob_lbah = (addr_req >>= 8) & 0xff; |
411 | args.hobRegister[IDE_HCYL_OFFSET] = (addr_req >>= 8) & 0xff; | 355 | tf->command = WIN_SET_MAX_EXT; |
412 | args.hobRegister[IDE_SELECT_OFFSET] = 0x40; | 356 | } else { |
413 | args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); | 357 | tf->device = (addr_req >>= 8) & 0x0f; |
414 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 358 | tf->command = WIN_SET_MAX; |
415 | args.handler = &task_no_data_intr; | 359 | } |
360 | tf->device |= ATA_LBA; | ||
361 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; | ||
362 | if (lba48) | ||
363 | args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_OUT_HOB); | ||
416 | /* submit command request */ | 364 | /* submit command request */ |
417 | ide_raw_taskfile(drive, &args, NULL); | 365 | ide_no_data_taskfile(drive, &args); |
418 | /* if OK, compute maximum address value */ | 366 | /* if OK, compute maximum address value */ |
419 | if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) { | 367 | if ((tf->status & 0x01) == 0) |
420 | u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) | | 368 | addr_set = ide_get_lba_addr(tf, lba48) + 1; |
421 | (args.hobRegister[IDE_LCYL_OFFSET] << 8) | | 369 | |
422 | args.hobRegister[IDE_SECTOR_OFFSET]; | ||
423 | u32 low = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) | | ||
424 | ((args.tfRegister[IDE_LCYL_OFFSET])<<8) | | ||
425 | (args.tfRegister[IDE_SECTOR_OFFSET]); | ||
426 | addr_set = ((__u64)high << 24) | low; | ||
427 | addr_set++; | ||
428 | } | ||
429 | return addr_set; | 370 | return addr_set; |
430 | } | 371 | } |
431 | 372 | ||
@@ -471,10 +412,8 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
471 | int lba48 = idedisk_supports_lba48(drive->id); | 412 | int lba48 = idedisk_supports_lba48(drive->id); |
472 | 413 | ||
473 | capacity = drive->capacity64; | 414 | capacity = drive->capacity64; |
474 | if (lba48) | 415 | |
475 | set_max = idedisk_read_native_max_address_ext(drive); | 416 | set_max = idedisk_read_native_max_address(drive, lba48); |
476 | else | ||
477 | set_max = idedisk_read_native_max_address(drive); | ||
478 | 417 | ||
479 | if (ide_in_drive_list(drive->id, hpa_list)) { | 418 | if (ide_in_drive_list(drive->id, hpa_list)) { |
480 | /* | 419 | /* |
@@ -495,10 +434,8 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
495 | capacity, sectors_to_MB(capacity), | 434 | capacity, sectors_to_MB(capacity), |
496 | set_max, sectors_to_MB(set_max)); | 435 | set_max, sectors_to_MB(set_max)); |
497 | 436 | ||
498 | if (lba48) | 437 | set_max = idedisk_set_max_address(drive, set_max, lba48); |
499 | set_max = idedisk_set_max_address_ext(drive, set_max); | 438 | |
500 | else | ||
501 | set_max = idedisk_set_max_address(drive, set_max); | ||
502 | if (set_max) { | 439 | if (set_max) { |
503 | drive->capacity64 = set_max; | 440 | drive->capacity64 = set_max; |
504 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", | 441 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", |
@@ -556,32 +493,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive) | |||
556 | static int smart_enable(ide_drive_t *drive) | 493 | static int smart_enable(ide_drive_t *drive) |
557 | { | 494 | { |
558 | ide_task_t args; | 495 | ide_task_t args; |
496 | struct ide_taskfile *tf = &args.tf; | ||
559 | 497 | ||
560 | memset(&args, 0, sizeof(ide_task_t)); | 498 | memset(&args, 0, sizeof(ide_task_t)); |
561 | args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE; | 499 | tf->feature = SMART_ENABLE; |
562 | args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; | 500 | tf->lbam = SMART_LCYL_PASS; |
563 | args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; | 501 | tf->lbah = SMART_HCYL_PASS; |
564 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; | 502 | tf->command = WIN_SMART; |
565 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 503 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
566 | args.handler = &task_no_data_intr; | 504 | return ide_no_data_taskfile(drive, &args); |
567 | return ide_raw_taskfile(drive, &args, NULL); | ||
568 | } | 505 | } |
569 | 506 | ||
570 | static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) | 507 | static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) |
571 | { | 508 | { |
572 | ide_task_t args; | 509 | ide_task_t args; |
510 | struct ide_taskfile *tf = &args.tf; | ||
573 | 511 | ||
574 | memset(&args, 0, sizeof(ide_task_t)); | 512 | memset(&args, 0, sizeof(ide_task_t)); |
575 | args.tfRegister[IDE_FEATURE_OFFSET] = sub_cmd; | 513 | tf->feature = sub_cmd; |
576 | args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; | 514 | tf->nsect = 0x01; |
577 | args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; | 515 | tf->lbam = SMART_LCYL_PASS; |
578 | args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; | 516 | tf->lbah = SMART_HCYL_PASS; |
579 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; | 517 | tf->command = WIN_SMART; |
580 | args.command_type = IDE_DRIVE_TASK_IN; | 518 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
581 | args.data_phase = TASKFILE_IN; | 519 | args.data_phase = TASKFILE_IN; |
582 | args.handler = &task_in_intr; | ||
583 | (void) smart_enable(drive); | 520 | (void) smart_enable(drive); |
584 | return ide_raw_taskfile(drive, &args, buf); | 521 | return ide_raw_taskfile(drive, &args, buf, 1); |
585 | } | 522 | } |
586 | 523 | ||
587 | static int proc_idedisk_read_cache | 524 | static int proc_idedisk_read_cache |
@@ -659,19 +596,20 @@ static ide_proc_entry_t idedisk_proc[] = { | |||
659 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 596 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) |
660 | { | 597 | { |
661 | ide_drive_t *drive = q->queuedata; | 598 | ide_drive_t *drive = q->queuedata; |
599 | ide_task_t task; | ||
662 | 600 | ||
663 | memset(rq->cmd, 0, sizeof(rq->cmd)); | 601 | memset(&task, 0, sizeof(task)); |
664 | |||
665 | if (ide_id_has_flush_cache_ext(drive->id) && | 602 | if (ide_id_has_flush_cache_ext(drive->id) && |
666 | (drive->capacity64 >= (1UL << 28))) | 603 | (drive->capacity64 >= (1UL << 28))) |
667 | rq->cmd[0] = WIN_FLUSH_CACHE_EXT; | 604 | task.tf.command = WIN_FLUSH_CACHE_EXT; |
668 | else | 605 | else |
669 | rq->cmd[0] = WIN_FLUSH_CACHE; | 606 | task.tf.command = WIN_FLUSH_CACHE; |
670 | 607 | task.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; | |
608 | task.data_phase = TASKFILE_NO_DATA; | ||
671 | 609 | ||
672 | rq->cmd_type = REQ_TYPE_ATA_TASK; | 610 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
673 | rq->cmd_flags |= REQ_SOFTBARRIER; | 611 | rq->cmd_flags |= REQ_SOFTBARRIER; |
674 | rq->buffer = rq->cmd; | 612 | rq->special = &task; |
675 | } | 613 | } |
676 | 614 | ||
677 | /* | 615 | /* |
@@ -753,12 +691,11 @@ static int write_cache(ide_drive_t *drive, int arg) | |||
753 | 691 | ||
754 | if (ide_id_has_flush_cache(drive->id)) { | 692 | if (ide_id_has_flush_cache(drive->id)) { |
755 | memset(&args, 0, sizeof(ide_task_t)); | 693 | memset(&args, 0, sizeof(ide_task_t)); |
756 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? | 694 | args.tf.feature = arg ? |
757 | SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; | 695 | SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; |
758 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; | 696 | args.tf.command = WIN_SETFEATURES; |
759 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 697 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
760 | args.handler = &task_no_data_intr; | 698 | err = ide_no_data_taskfile(drive, &args); |
761 | err = ide_raw_taskfile(drive, &args, NULL); | ||
762 | if (err == 0) | 699 | if (err == 0) |
763 | drive->wcache = arg; | 700 | drive->wcache = arg; |
764 | } | 701 | } |
@@ -774,12 +711,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive) | |||
774 | 711 | ||
775 | memset(&args, 0, sizeof(ide_task_t)); | 712 | memset(&args, 0, sizeof(ide_task_t)); |
776 | if (ide_id_has_flush_cache_ext(drive->id)) | 713 | if (ide_id_has_flush_cache_ext(drive->id)) |
777 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; | 714 | args.tf.command = WIN_FLUSH_CACHE_EXT; |
778 | else | 715 | else |
779 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; | 716 | args.tf.command = WIN_FLUSH_CACHE; |
780 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 717 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
781 | args.handler = &task_no_data_intr; | 718 | return ide_no_data_taskfile(drive, &args); |
782 | return ide_raw_taskfile(drive, &args, NULL); | ||
783 | } | 719 | } |
784 | 720 | ||
785 | static int set_acoustic (ide_drive_t *drive, int arg) | 721 | static int set_acoustic (ide_drive_t *drive, int arg) |
@@ -790,13 +726,11 @@ static int set_acoustic (ide_drive_t *drive, int arg) | |||
790 | return -EINVAL; | 726 | return -EINVAL; |
791 | 727 | ||
792 | memset(&args, 0, sizeof(ide_task_t)); | 728 | memset(&args, 0, sizeof(ide_task_t)); |
793 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : | 729 | args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; |
794 | SETFEATURES_DIS_AAM; | 730 | args.tf.nsect = arg; |
795 | args.tfRegister[IDE_NSECTOR_OFFSET] = arg; | 731 | args.tf.command = WIN_SETFEATURES; |
796 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; | 732 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
797 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 733 | ide_no_data_taskfile(drive, &args); |
798 | args.handler = &task_no_data_intr; | ||
799 | ide_raw_taskfile(drive, &args, NULL); | ||
800 | drive->acoustic = arg; | 734 | drive->acoustic = arg; |
801 | return 0; | 735 | return 0; |
802 | } | 736 | } |
@@ -1057,16 +991,15 @@ static int idedisk_open(struct inode *inode, struct file *filp) | |||
1057 | if (drive->removable && idkp->openers == 1) { | 991 | if (drive->removable && idkp->openers == 1) { |
1058 | ide_task_t args; | 992 | ide_task_t args; |
1059 | memset(&args, 0, sizeof(ide_task_t)); | 993 | memset(&args, 0, sizeof(ide_task_t)); |
1060 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; | 994 | args.tf.command = WIN_DOORLOCK; |
1061 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 995 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
1062 | args.handler = &task_no_data_intr; | ||
1063 | check_disk_change(inode->i_bdev); | 996 | check_disk_change(inode->i_bdev); |
1064 | /* | 997 | /* |
1065 | * Ignore the return code from door_lock, | 998 | * Ignore the return code from door_lock, |
1066 | * since the open() has already succeeded, | 999 | * since the open() has already succeeded, |
1067 | * and the door_lock is irrelevant at this point. | 1000 | * and the door_lock is irrelevant at this point. |
1068 | */ | 1001 | */ |
1069 | if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) | 1002 | if (drive->doorlocking && ide_no_data_taskfile(drive, &args)) |
1070 | drive->doorlocking = 0; | 1003 | drive->doorlocking = 0; |
1071 | } | 1004 | } |
1072 | return 0; | 1005 | return 0; |
@@ -1084,10 +1017,9 @@ static int idedisk_release(struct inode *inode, struct file *filp) | |||
1084 | if (drive->removable && idkp->openers == 1) { | 1017 | if (drive->removable && idkp->openers == 1) { |
1085 | ide_task_t args; | 1018 | ide_task_t args; |
1086 | memset(&args, 0, sizeof(ide_task_t)); | 1019 | memset(&args, 0, sizeof(ide_task_t)); |
1087 | args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK; | 1020 | args.tf.command = WIN_DOORUNLOCK; |
1088 | args.command_type = IDE_DRIVE_TASK_NO_DATA; | 1021 | args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE; |
1089 | args.handler = &task_no_data_intr; | 1022 | if (drive->doorlocking && ide_no_data_taskfile(drive, &args)) |
1090 | if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) | ||
1091 | drive->doorlocking = 0; | 1023 | drive->doorlocking = 0; |
1092 | } | 1024 | } |
1093 | 1025 | ||