ide-atapi.c revision 7bf7420a318978cd6042e5a5da34b7cfa18ae559
1/* 2 * ATAPI support. 3 */ 4 5#include <linux/kernel.h> 6#include <linux/delay.h> 7#include <linux/ide.h> 8#include <scsi/scsi.h> 9 10#ifdef DEBUG 11#define debug_log(fmt, args...) \ 12 printk(KERN_INFO "ide: " fmt, ## args) 13#else 14#define debug_log(fmt, args...) do {} while (0) 15#endif 16 17/* 18 * Check whether we can support a device, 19 * based on the ATAPI IDENTIFY command results. 20 */ 21int ide_check_atapi_device(ide_drive_t *drive, const char *s) 22{ 23 u16 *id = drive->id; 24 u8 gcw[2], protocol, device_type, removable, drq_type, packet_size; 25 26 *((u16 *)&gcw) = id[ATA_ID_CONFIG]; 27 28 protocol = (gcw[1] & 0xC0) >> 6; 29 device_type = gcw[1] & 0x1F; 30 removable = (gcw[0] & 0x80) >> 7; 31 drq_type = (gcw[0] & 0x60) >> 5; 32 packet_size = gcw[0] & 0x03; 33 34#ifdef CONFIG_PPC 35 /* kludge for Apple PowerBook internal zip */ 36 if (drive->media == ide_floppy && device_type == 5 && 37 !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") && 38 strstr((char *)&id[ATA_ID_PROD], "ZIP")) 39 device_type = 0; 40#endif 41 42 if (protocol != 2) 43 printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI\n", 44 s, drive->name, protocol); 45 else if ((drive->media == ide_floppy && device_type != 0) || 46 (drive->media == ide_tape && device_type != 1)) 47 printk(KERN_ERR "%s: %s: invalid device type (0x%02x)\n", 48 s, drive->name, device_type); 49 else if (removable == 0) 50 printk(KERN_ERR "%s: %s: the removable flag is not set\n", 51 s, drive->name); 52 else if (drive->media == ide_floppy && drq_type == 3) 53 printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not " 54 "supported\n", s, drive->name, drq_type); 55 else if (packet_size != 0) 56 printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 " 57 "bytes\n", s, drive->name, packet_size); 58 else 59 return 1; 60 return 0; 61} 62EXPORT_SYMBOL_GPL(ide_check_atapi_device); 63 64/* PIO data transfer routine using the scatter gather table. */ 65int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, 66 unsigned int bcount, int write) 67{ 68 ide_hwif_t *hwif = drive->hwif; 69 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 70 xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; 71 struct scatterlist *sg = pc->sg; 72 char *buf; 73 int count, done = 0; 74 75 while (bcount) { 76 count = min(sg->length - pc->b_count, bcount); 77 78 if (PageHighMem(sg_page(sg))) { 79 unsigned long flags; 80 81 local_irq_save(flags); 82 buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; 83 xf(drive, NULL, buf + pc->b_count, count); 84 kunmap_atomic(buf - sg->offset, KM_IRQ0); 85 local_irq_restore(flags); 86 } else { 87 buf = sg_virt(sg); 88 xf(drive, NULL, buf + pc->b_count, count); 89 } 90 91 bcount -= count; 92 pc->b_count += count; 93 done += count; 94 95 if (pc->b_count == sg->length) { 96 if (!--pc->sg_cnt) 97 break; 98 pc->sg = sg = sg_next(sg); 99 pc->b_count = 0; 100 } 101 } 102 103 if (bcount) { 104 printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, 105 bcount, write ? "padding with zeros" 106 : "discarding data"); 107 ide_pad_transfer(drive, write, bcount); 108 } 109 110 return done; 111} 112EXPORT_SYMBOL_GPL(ide_io_buffers); 113 114void ide_init_pc(struct ide_atapi_pc *pc) 115{ 116 memset(pc, 0, sizeof(*pc)); 117 pc->buf = pc->pc_buf; 118 pc->buf_size = IDE_PC_BUFFER_SIZE; 119} 120EXPORT_SYMBOL_GPL(ide_init_pc); 121 122/* TODO: unify the code thus making some arguments go away */ 123ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, 124 ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, 125 void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), 126 void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), 127 int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) 128{ 129 ide_hwif_t *hwif = drive->hwif; 130 struct request *rq = hwif->hwgroup->rq; 131 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 132 xfer_func_t *xferfunc; 133 unsigned int temp; 134 u16 bcount; 135 u8 stat, ireason, scsi = drive->scsi; 136 137 debug_log("Enter %s - interrupt handler\n", __func__); 138 139 if (pc->flags & PC_FLAG_TIMEDOUT) { 140 drive->pc_callback(drive); 141 return ide_stopped; 142 } 143 144 /* Clear the interrupt */ 145 stat = tp_ops->read_status(hwif); 146 147 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 148 if (hwif->dma_ops->dma_end(drive) || 149 (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) { 150 if (drive->media == ide_floppy && !scsi) 151 printk(KERN_ERR "%s: DMA %s error\n", 152 drive->name, rq_data_dir(pc->rq) 153 ? "write" : "read"); 154 pc->flags |= PC_FLAG_DMA_ERROR; 155 } else { 156 pc->xferred = pc->req_xfer; 157 if (update_buffers) 158 update_buffers(drive, pc); 159 } 160 debug_log("%s: DMA finished\n", drive->name); 161 } 162 163 /* No more interrupts */ 164 if ((stat & ATA_DRQ) == 0) { 165 debug_log("Packet command completed, %d bytes transferred\n", 166 pc->xferred); 167 168 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; 169 170 local_irq_enable_in_hardirq(); 171 172 if (drive->media == ide_tape && !scsi && 173 (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) 174 stat &= ~ATA_ERR; 175 176 if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) { 177 /* Error detected */ 178 debug_log("%s: I/O error\n", drive->name); 179 180 if (drive->media != ide_tape || scsi) { 181 pc->rq->errors++; 182 if (scsi) 183 goto cmd_finished; 184 } 185 186 if (rq->cmd[0] == REQUEST_SENSE) { 187 printk(KERN_ERR "%s: I/O error in request sense" 188 " command\n", drive->name); 189 return ide_do_reset(drive); 190 } 191 192 debug_log("[cmd %x]: check condition\n", rq->cmd[0]); 193 194 /* Retry operation */ 195 retry_pc(drive); 196 197 /* queued, but not started */ 198 return ide_stopped; 199 } 200cmd_finished: 201 pc->error = 0; 202 if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && 203 (stat & ATA_DSC) == 0) { 204 dsc_handle(drive); 205 return ide_stopped; 206 } 207 208 /* Command finished - Call the callback function */ 209 drive->pc_callback(drive); 210 211 return ide_stopped; 212 } 213 214 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 215 pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; 216 printk(KERN_ERR "%s: The device wants to issue more interrupts " 217 "in DMA mode\n", drive->name); 218 ide_dma_off(drive); 219 return ide_do_reset(drive); 220 } 221 222 /* Get the number of bytes to transfer on this interrupt. */ 223 ide_read_bcount_and_ireason(drive, &bcount, &ireason); 224 225 if (ireason & ATAPI_COD) { 226 printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); 227 return ide_do_reset(drive); 228 } 229 230 if (((ireason & ATAPI_IO) == ATAPI_IO) == 231 !!(pc->flags & PC_FLAG_WRITING)) { 232 /* Hopefully, we will never get here */ 233 printk(KERN_ERR "%s: We wanted to %s, but the device wants us " 234 "to %s!\n", drive->name, 235 (ireason & ATAPI_IO) ? "Write" : "Read", 236 (ireason & ATAPI_IO) ? "Read" : "Write"); 237 return ide_do_reset(drive); 238 } 239 240 if (!(pc->flags & PC_FLAG_WRITING)) { 241 /* Reading - Check that we have enough space */ 242 temp = pc->xferred + bcount; 243 if (temp > pc->req_xfer) { 244 if (temp > pc->buf_size) { 245 printk(KERN_ERR "%s: The device wants to send " 246 "us more data than expected - " 247 "discarding data\n", 248 drive->name); 249 if (scsi) 250 temp = pc->buf_size - pc->xferred; 251 else 252 temp = 0; 253 if (temp) { 254 if (pc->sg) 255 io_buffers(drive, pc, temp, 0); 256 else 257 tp_ops->input_data(drive, NULL, 258 pc->cur_pos, temp); 259 printk(KERN_ERR "%s: transferred %d of " 260 "%d bytes\n", 261 drive->name, 262 temp, bcount); 263 } 264 pc->xferred += temp; 265 pc->cur_pos += temp; 266 ide_pad_transfer(drive, 0, bcount - temp); 267 ide_set_handler(drive, handler, timeout, 268 expiry); 269 return ide_started; 270 } 271 debug_log("The device wants to send us more data than " 272 "expected - allowing transfer\n"); 273 } 274 xferfunc = tp_ops->input_data; 275 } else 276 xferfunc = tp_ops->output_data; 277 278 if ((drive->media == ide_floppy && !scsi && !pc->buf) || 279 (drive->media == ide_tape && !scsi && pc->bh) || 280 (scsi && pc->sg)) { 281 int done = io_buffers(drive, pc, bcount, 282 !!(pc->flags & PC_FLAG_WRITING)); 283 284 /* FIXME: don't do partial completions */ 285 if (drive->media == ide_floppy && !scsi) 286 ide_end_request(drive, 1, done >> 9); 287 } else 288 xferfunc(drive, NULL, pc->cur_pos, bcount); 289 290 /* Update the current position */ 291 pc->xferred += bcount; 292 pc->cur_pos += bcount; 293 294 debug_log("[cmd %x] transferred %d bytes on that intr.\n", 295 rq->cmd[0], bcount); 296 297 /* And set the interrupt handler again */ 298 ide_set_handler(drive, handler, timeout, expiry); 299 return ide_started; 300} 301EXPORT_SYMBOL_GPL(ide_pc_intr); 302 303static u8 ide_read_ireason(ide_drive_t *drive) 304{ 305 ide_task_t task; 306 307 memset(&task, 0, sizeof(task)); 308 task.tf_flags = IDE_TFLAG_IN_NSECT; 309 310 drive->hwif->tp_ops->tf_read(drive, &task); 311 312 return task.tf.nsect & 3; 313} 314 315static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) 316{ 317 int retries = 100; 318 319 while (retries-- && ((ireason & ATAPI_COD) == 0 || 320 (ireason & ATAPI_IO))) { 321 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 322 "a packet command, retrying\n", drive->name); 323 udelay(100); 324 ireason = ide_read_ireason(drive); 325 if (retries == 0) { 326 printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing " 327 "a packet command, ignoring\n", 328 drive->name); 329 ireason |= ATAPI_COD; 330 ireason &= ~ATAPI_IO; 331 } 332 } 333 334 return ireason; 335} 336 337ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, 338 ide_handler_t *handler, unsigned int timeout, 339 ide_expiry_t *expiry) 340{ 341 ide_hwif_t *hwif = drive->hwif; 342 struct request *rq = hwif->hwgroup->rq; 343 ide_startstop_t startstop; 344 u8 ireason; 345 346 if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { 347 printk(KERN_ERR "%s: Strange, packet command initiated yet " 348 "DRQ isn't asserted\n", drive->name); 349 return startstop; 350 } 351 352 ireason = ide_read_ireason(drive); 353 if (drive->media == ide_tape && !drive->scsi) 354 ireason = ide_wait_ireason(drive, ireason); 355 356 if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { 357 printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " 358 "a packet command\n", drive->name); 359 return ide_do_reset(drive); 360 } 361 362 /* Set the interrupt routine */ 363 ide_set_handler(drive, handler, timeout, expiry); 364 365 /* Begin DMA, if necessary */ 366 if (pc->flags & PC_FLAG_DMA_OK) { 367 pc->flags |= PC_FLAG_DMA_IN_PROGRESS; 368 hwif->dma_ops->dma_start(drive); 369 } 370 371 /* Send the actual packet */ 372 if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) 373 hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12); 374 375 return ide_started; 376} 377EXPORT_SYMBOL_GPL(ide_transfer_pc); 378 379ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc, 380 ide_handler_t *handler, unsigned int timeout, 381 ide_expiry_t *expiry) 382{ 383 ide_hwif_t *hwif = drive->hwif; 384 u16 bcount; 385 u8 dma = 0; 386 387 /* We haven't transferred any data yet */ 388 pc->xferred = 0; 389 pc->cur_pos = pc->buf; 390 391 /* Request to transfer the entire buffer at once */ 392 if (drive->media == ide_tape && !drive->scsi) 393 bcount = pc->req_xfer; 394 else 395 bcount = min(pc->req_xfer, 63 * 1024); 396 397 if (pc->flags & PC_FLAG_DMA_ERROR) { 398 pc->flags &= ~PC_FLAG_DMA_ERROR; 399 ide_dma_off(drive); 400 } 401 402 if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) { 403 if (drive->scsi) 404 hwif->sg_mapped = 1; 405 dma = !hwif->dma_ops->dma_setup(drive); 406 if (drive->scsi) 407 hwif->sg_mapped = 0; 408 } 409 410 if (!dma) 411 pc->flags &= ~PC_FLAG_DMA_OK; 412 413 ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE, 414 bcount, dma); 415 416 /* Issue the packet command */ 417 if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { 418 ide_execute_command(drive, ATA_CMD_PACKET, handler, 419 timeout, NULL); 420 return ide_started; 421 } else { 422 ide_execute_pkt_cmd(drive); 423 return (*handler)(drive); 424 } 425} 426EXPORT_SYMBOL_GPL(ide_issue_pc); 427