?? ide-cd.c
字號:
/* End of retry loop. */ } while (pc->stat != 0 && retries >= 0); /* Return an error if the command failed. */ return pc->stat ? -EIO : 0;}/* * Write handling */static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason){ /* Two notes about IDE interrupt reason here - 0 means that * the drive wants to receive data from us, 2 means that * the drive is expecting data from us. */ ireason &= 3; if (ireason == 2) { /* Whoops... The drive wants to send data. */ printk("%s: cdrom_write_intr: wrong transfer direction!\n", drive->name); /* Throw some data at the drive so it doesn't hang and quit this request. */ while (len > 0) { int dum = 0; HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum)); len -= sizeof(dum); } } else { /* Drive wants a command packet, or invalid ireason... */ printk("%s: cdrom_write_intr: bad interrupt reason %d\n", drive->name, ireason); } cdrom_end_request(drive, 0); return 1;}static ide_startstop_t cdrom_write_intr(ide_drive_t *drive){ int stat, ireason, len, sectors_to_transfer, uptodate; struct cdrom_info *info = drive->driver_data; int i, dma_error = 0, dma = info->dma; u8 lowcyl = 0, highcyl = 0; ide_startstop_t startstop; struct request *rq = HWGROUP(drive)->rq; /* Check for errors. */ if (dma) { info->dma = 0; if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { printk("ide-cd: write dma error\n"); HWIF(drive)->ide_dma_off(drive); } } if (cdrom_decode_status(&startstop, drive, 0, &stat)) { printk("ide-cd: write_intr decode_status bad\n"); return startstop; } /* * using dma, transfer is complete now */ if (dma) { if (dma_error) return DRIVER(drive)->error(drive, "dma error", stat); rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; ide_cdrom_end_request(drive, 1); } return ide_stopped; } /* Read the interrupt reason and the transfer length. */ ireason = HWIF(drive)->INB(IDE_IREASON_REG); lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); len = lowcyl + (256 * highcyl); /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { /* If we're not done writing, complain. * Otherwise, complete the command normally. */ uptodate = 1; if (rq->current_nr_sectors > 0) { printk("%s: write_intr: data underrun (%ld blocks)\n", drive->name, rq->current_nr_sectors); uptodate = 0; } cdrom_end_request(drive, uptodate); return ide_stopped; } /* Check that the drive is expecting to do the same thing we are. */ if (ireason & 3) if (cdrom_write_check_ireason(drive, len, ireason)) return ide_stopped; sectors_to_transfer = len / SECTOR_SIZE; /* * now loop and write out the data */ while (sectors_to_transfer > 0) { int this_transfer; if (!rq->current_nr_sectors) { printk("ide-cd: write_intr: oops\n"); break; } /* * Figure out how many sectors we can transfer */ this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors); while (this_transfer > 0) { HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; --rq->nr_sectors; --rq->current_nr_sectors; ++rq->sector; --this_transfer; --sectors_to_transfer; } /* * current buffer complete, move on */ if (rq->current_nr_sectors == 0 && rq->nr_sectors) cdrom_end_request(drive, 1); } /* re-arm handler */ ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); return ide_started;}static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive){ struct packet_command pc; /* packet_command_t pc; */ struct request *rq = HWGROUP(drive)->rq; unsigned nframes, frame; nframes = rq->nr_sectors >> 2; frame = rq->sector >> 2; memset(&pc.c, 0, sizeof(pc.c)); /* * we might as well use WRITE_12, but none of the device I have * support the streaming feature anyway, so who cares. */ pc.c[0] = GPCMD_WRITE_10;#if 0 /* the immediate bit */ pc.c[1] = 1 << 3;#endif pc.c[7] = (nframes >> 8) & 0xff; pc.c[8] = nframes & 0xff; put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]); pc.timeout = 2 * WAIT_CMD; return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);}static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq){ struct cdrom_info *info = drive->driver_data; /* * writes *must* be 2kB frame aligned */ if ((rq->nr_sectors & 3) || (rq->sector & 3)) { cdrom_end_request(drive, 0); return ide_stopped; } /* * for dvd-ram and such media, it's a really big deal to get * big writes all the time. so scour the queue and attempt to * remerge requests, often the plugging will not have had time * to do this properly */ cdrom_attempt_remerge(drive, rq); info->nsectors_buffered = 0; /* use dma, if possible. we don't need to check more, since we * know that the transfer is always (at least!) 2KB aligned */ info->dma = drive->using_dma ? 1 : 0; info->cmd = WRITE; /* Start sending the read request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);}/**************************************************************************** * cdrom driver request routine. */static ide_startstop_tide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block){ ide_startstop_t action; struct cdrom_info *info = drive->driver_data; switch (rq->cmd) { case WRITE: case READ: { if (CDROM_CONFIG_FLAGS(drive)->seeking) { int stat = HWIF(drive)->INB(IDE_STATUS_REG); if ((stat & SEEK_STAT) != SEEK_STAT) { if (time_before(jiffies, info->start_seek + IDECD_SEEK_TIMEOUT)) { ide_stall_queue(drive, IDECD_SEEK_TIMER); return ide_stopped; } printk ("%s: DSC timeout\n", drive->name); } CDROM_CONFIG_FLAGS(drive)->seeking = 0; } if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) action = cdrom_start_seek(drive, block); else { if (rq_data_dir(rq) == READ) action = cdrom_start_read(drive, block); else action = cdrom_start_write(drive, rq); } info->last_block = block; return action; } case PACKET_COMMAND: case REQUEST_SENSE_COMMAND: { return cdrom_do_packet_command(drive); } case RESET_DRIVE_COMMAND: { cdrom_end_request(drive, 1); return ide_do_reset(drive); } default: { printk("ide-cd: bad cmd %d\n", rq->cmd); cdrom_end_request(drive, 0); return ide_stopped; } }}/**************************************************************************** * Ioctl handling. * * Routines which queue packet commands take as a final argument a pointer * to a request_sense struct. If execution of the command results * in an error with a CHECK CONDITION status, this structure will be filled * with the results of the subsequent request sense command. The pointer * can also be NULL, in which case no sense information is returned. */#if ! STANDARD_ATAPIstatic inlineint bin2bcd (int x){ return (x%10) | ((x/10) << 4);}static inlineint bcd2bin (int x){ return (x >> 4) * 10 + (x & 0x0f);}staticvoid msf_from_bcd (struct atapi_msf *msf){ msf->minute = bcd2bin (msf->minute); msf->second = bcd2bin (msf->second); msf->frame = bcd2bin (msf->frame);}#endif /* not STANDARD_ATAPI */static inlinevoid lba_to_msf (int lba, byte *m, byte *s, byte *f){ lba += CD_MSF_OFFSET; lba &= 0xffffff; /* negative lbas use only 24 bits */ *m = lba / (CD_SECS * CD_FRAMES); lba %= (CD_SECS * CD_FRAMES); *s = lba / CD_FRAMES; *f = lba % CD_FRAMES;}static inlineint msf_to_lba (byte m, byte s, byte f){ return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;}static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense){ struct packet_command pc; struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; memset(&pc, 0, sizeof(pc)); pc.sense = sense; pc.c[0] = GPCMD_TEST_UNIT_READY;#if ! STANDARD_ATAPI /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs instead of supporting the LOAD_UNLOAD opcode */ pc.c[7] = cdi->sanyo_slot % 3;#endif /* not STANDARD_ATAPI */ return cdrom_queue_packet_command(drive, &pc);}/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */static intcdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense){ struct request_sense my_sense; struct packet_command pc; int stat; if (sense == NULL) sense = &my_sense; /* If the drive cannot lock the door, just pretend. */ if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { stat = 0; } else { memset(&pc, 0, sizeof(pc)); pc.sense = sense; pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; pc.c[4] = lockflag ? 1 : 0; stat = cdrom_queue_packet_command(drive, &pc); } /* If we got an illegal field error, the drive probably cannot lock the door. */ if (stat != 0 && sense->sense_key == ILLEGAL_REQUEST && (sense->asc == 0x24 || sense->asc == 0x20)) { printk ("%s: door locking not supported\n", drive->name); CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; stat = 0; } /* no medium, that's alright. */ if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) stat = 0; if (stat == 0) CDROM_STATE_FLAGS(drive)->door_locked = lockflag; return stat;}/* Eject the disk if EJECTFLAG is 0. If EJECTFLAG is 1, try to reload the disk. */static int cdrom_eject(ide_drive_t *drive, int ejectflag, struct request_sense *sense){ struct packet_command pc; if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) return -EDRIVE_CANT_DO_THIS; /* reload fails on some drives, if the tray is locked */ if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) return 0; memset(&pc, 0, sizeof (pc)); pc.sense = sense; pc.c[0] = GPCMD_START_STOP_UNIT; pc.c[4] = 0x02 + (ejectflag != 0); return cdrom_queue_packet_command(drive, &pc);}static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, struct request_sense *sense){ struct { __u32 lba; __u32 blocklen; } capbuf; int stat; str
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -