📄 sr.c
字号:
*/static intsr_start_stop(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[6]; bzero((caddr_t)cdb, 6); cdb[0] = SCMD_START_STOP; cdb[1] = 0; /* immediate bit is set to 0 for now */ cdb[4] = (u_char)data; com->uscsi_cdb = cdb; com->uscsi_cdblen = 6; com->uscsi_bufaddr = 0; com->uscsi_buflen = 0; com->uscsi_flags = DK_DIAGNOSE|DK_SILENT; return (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL));}/* * This routine ejects the CDROM disc */static intsr_eject(dev)dev_t dev;{ int err; register struct scsi_device *devp; devp = srunits[SRUNIT(dev)]; /* first, unlocks the eject */ if ((err = sr_medium_removal(dev, SR_REMOVAL_ALLOW)) != 0) { return (err); } /* then ejects the disc */ if ((err = (sr_start_stop(dev, (caddr_t)2))) == 0) { DPRINTF("%s%d: Caddy ejected\n", DNAME, DUNIT); sr_ejected(devp); } return (err);}#ifdef FIXEDFIRMWARE/* * This routine control the audio output volume */static intsr_volume_ctrl(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[6]; struct cdrom_volctrl *vol; caddr_t buffer; int rtn; DPRINTF("in sr_volume_ctrl\n"); if ((buffer = IOPBALLOC(20)) == (caddr_t)0) { return (ENOMEM); } vol = (struct cdrom_volctrl *)data; bzero((caddr_t)cdb, 6); cdb[0] = SCMD_MODE_SELECT; cdb[4] = 20; /* * fill in the input data. Set the output channel 0, 1 to * output port 0, 1 respestively. Set output channel 2, 3 to * mute. The function only adjust the output volume for channel * 0 and 1. */ bzero(buffer, 20); buffer[4] = 0xe; buffer[5] = 0xe; buffer[6] = 0x4; /* set the immediate bit to 1 */ buffer[12] = 0x01; buffer[13] = vol->channel0; buffer[14] = 0x02; buffer[15] = vol->channel1; com->uscsi_cdb = cdb; com->uscsi_cdblen = 6; com->uscsi_bufaddr = buffer; com->uscsi_buflen = 20; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); IOPBFREE (buffer, 20); return (rtn);}#else/* * This routine control the audio output volume */static intsr_volume_ctrl(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[10]; struct cdrom_volctrl *vol; caddr_t buffer; int rtn; DPRINTF("in sr_volume_ctrl\n"); if ((buffer = IOPBALLOC(18)) == (caddr_t)0) { return (ENOMEM); } vol = (struct cdrom_volctrl *)data; bzero(cdb, 10); cdb[0] = 0xc9; /* vendor unique command */ cdb[7] = 0; cdb[8] = 0x12; /* * fill in the input data. Set the output channel 0, 1 to * output port 0, 1 respestively. Set output channel 2, 3 to * mute. The function only adjust the output volume for channel * 0 and 1. */ bzero(buffer, 18); buffer[10] = 0x01; buffer[11] = vol->channel0; buffer[12] = 0x02; buffer[13] = vol->channel1; com->uscsi_cdb = cdb; com->uscsi_cdblen = 10; com->uscsi_bufaddr = buffer; com->uscsi_buflen = 0x12; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); IOPBFREE (buffer, 18); return (rtn);}#endif FIXEDFIRMWARE#ifdef OLDCODE/* * read the drive's capacity and sector size * This routine is not used by srioctl(). Used when a new media is * inserted or when the device is first opened. */static intsr_read_capacity(dev)dev_t dev;{ register struct scsi_disk *un; register struct scsi_device *devp; struct uscsi_cmd cblk, *com=&cblk; char cdb[10]; struct scsi_capacity *cap; int rtn; DPRINTF("in sr_read_capacity\n"); devp = srunits[SRUNIT(dev)]; un = UPTR; if ((cap = (struct scsi_capacity *)IOPBALLOC(sizeof (struct scsi_capacity))) == (struct scsi_capacity *)0) { return (ENOMEM); } bzero(cdb, 10); cdb[0] = SCMD_READ_CAPACITY; com->uscsi_cdb = cdb; com->uscsi_cdblen = 10; com->uscsi_bufaddr = (caddr_t)cap; com->uscsi_buflen = sizeof (struct scsi_capacity); com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); un->un_capacity = cap->capacity+1; un->un_lbasize = cap->lbasize; un->un_g.dkg_nsect = un->un_capacity; DPRINTF("%s%d: capacity is %d\n", DNAME, DUNIT, un->un_capacity); IOPBFREE (cap, sizeof (struct scsi_capacity)); return (rtn);}#endif OLDCODEstatic intsr_read_subchannel(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[10]; caddr_t buffer; int rtn; struct cdrom_subchnl *subchnl; DPRINTF("in sr_read_subchannel\n"); if ((buffer = IOPBALLOC(16)) == (caddr_t)0) { return (ENOMEM); } subchnl = (struct cdrom_subchnl *)data; bzero((caddr_t)cdb, 10); cdb[0] = SCMD_READ_SUBCHANNEL; cdb[1] = (subchnl->cdsc_format & CDROM_LBA) ? 0 : 0x02; /* * set the Q bit in byte 2 to 1. */ cdb[2] = 0x40; /* * This byte (byte 3) specifies the return data format. Proposed * by Sony. To be added to SCSI-2 Rev 10b * Setting it to one tells it to return time-data format */ cdb[3] = 0x01; cdb[8] = 0x10; com->uscsi_cdb = cdb; com->uscsi_cdblen = 10; com->uscsi_bufaddr = buffer; com->uscsi_buflen = 0x10; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); subchnl->cdsc_audiostatus = buffer[1]; subchnl->cdsc_trk = buffer[6]; subchnl->cdsc_ind = buffer[7]; subchnl->cdsc_adr = buffer[5] & 0xF0; subchnl->cdsc_ctrl = buffer[5] & 0x0F; if (subchnl->cdsc_format & CDROM_LBA) { subchnl->cdsc_absaddr.lba = ((u_char)buffer[8] << 24) + ((u_char)buffer[9] << 16) + ((u_char)buffer[10] << 8) + ((u_char)buffer[11]); subchnl->cdsc_reladdr.lba = ((u_char)buffer[12] << 24) + ((u_char)buffer[13] << 16) + ((u_char)buffer[14] << 8) + ((u_char)buffer[15]); } else { subchnl->cdsc_absaddr.msf.minute = buffer[9]; subchnl->cdsc_absaddr.msf.second = buffer[10]; subchnl->cdsc_absaddr.msf.frame = buffer[11]; subchnl->cdsc_reladdr.msf.minute = buffer[13]; subchnl->cdsc_reladdr.msf.second = buffer[14]; subchnl->cdsc_reladdr.msf.frame = buffer[15]; } IOPBFREE (buffer, 16); return (rtn);}static intsr_read_mode2(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; u_char cdb[6]; int rtn; struct cdrom_read *mode2; DPRINTF("in sr_read_mode2\n"); mode2 = (struct cdrom_read *)data;#ifdef FIVETWELVE mode2->cdread_lba >>= 2;#endif FIVETWELVE bzero((caddr_t)cdb, 6); cdb[0] = SCMD_READ; cdb[1] = (u_char)((mode2->cdread_lba >> 16) & 0XFF); cdb[2] = (u_char)((mode2->cdread_lba >> 8) & 0xFF); cdb[3] = (u_char)(mode2->cdread_lba & 0xFF); cdb[4] = mode2->cdread_buflen / 2336; com->uscsi_cdb = (caddr_t)cdb; com->uscsi_cdblen = 6; com->uscsi_bufaddr = mode2->cdread_bufaddr; com->uscsi_buflen = mode2->cdread_buflen; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_MODE2)); return (rtn);}static intsr_read_mode1(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; u_char cdb[6]; int rtn; struct cdrom_read *mode1; DPRINTF("in sr_read_mode1\n"); mode1 = (struct cdrom_read *)data; bzero((caddr_t)cdb, 6); cdb[0] = SCMD_READ; cdb[1] = (u_char)((mode1->cdread_lba >> 16) & 0XFF); cdb[2] = (u_char)((mode1->cdread_lba >> 8) & 0xFF); cdb[3] = (u_char)(mode1->cdread_lba & 0xFF); cdb[4] = mode1->cdread_buflen >> 11; com->uscsi_cdb = (caddr_t)cdb; com->uscsi_cdblen = 6; com->uscsi_bufaddr = mode1->cdread_bufaddr; com->uscsi_buflen = mode1->cdread_buflen; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL)); return (rtn);}static intsr_read_tochdr(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[10]; caddr_t buffer; int rtn; struct cdrom_tochdr *hdr; DPRINTF("in sr_read_tochdr.\n"); if ((buffer = IOPBALLOC(4)) == (caddr_t)0) { return (ENOMEM); } hdr = (struct cdrom_tochdr *)data; bzero((caddr_t)cdb, 10); cdb[0] = SCMD_READ_TOC; cdb[6] = 0x00; /* * byte 7, 8 are the allocation length. In this case, it is 4 * bytes. */ cdb[8] = 0x04; com->uscsi_cdb = cdb; com->uscsi_cdblen = 10; com->uscsi_bufaddr = buffer; com->uscsi_buflen = 0x04; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); hdr->cdth_trk0 = buffer[2]; hdr->cdth_trk1 = buffer[3]; IOPBFREE (buffer, 4); return (rtn);}/* * This routine read the toc of the disc and returns the information * of a particular track. The track number is specified by the ioctl * caller. */static intsr_read_tocentry(dev, data)dev_t dev;caddr_t data;{ struct uscsi_cmd cblk, *com=&cblk; char cdb[10]; struct cdrom_tocentry *entry; caddr_t buffer; int rtn, rtn1; int lba; DPRINTF("in sr_read_tocentry.\n"); if ((buffer = IOPBALLOC(12)) == (caddr_t)0) { return (ENOMEM); } entry = (struct cdrom_tocentry *)data; if (!(entry->cdte_format & (CDROM_LBA | CDROM_MSF))) { return (EINVAL); } bzero((caddr_t)cdb, 10); cdb[0] = SCMD_READ_TOC; /* set the MSF bit of byte one */ cdb[1] = (entry->cdte_format & CDROM_LBA) ? 0 : 2; cdb[6] = entry->cdte_track; /* * byte 7, 8 are the allocation length. In this case, it is 4 + 8 * = 12 bytes, since we only need one entry. */ cdb[8] = 0x0C; com->uscsi_cdb = cdb; com->uscsi_cdblen = 10; com->uscsi_bufaddr = buffer; com->uscsi_buflen = 0x0C; com->uscsi_flags = USCSI_DIAGNOSE|USCSI_SILENT|USCSI_READ; rtn = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); entry->cdte_adr = (buffer[5] & 0xF0) >> 4; entry->cdte_ctrl = (buffer[5] & 0x0F); if (entry->cdte_format & CDROM_LBA) { entry->cdte_addr.lba = ((u_char)buffer[8] << 24) + ((u_char)buffer[9] << 16) + ((u_char)buffer[10] << 8) + ((u_char)buffer[11]); } else { entry->cdte_addr.msf.minute = buffer[9]; entry->cdte_addr.msf.second = buffer[10]; entry->cdte_addr.msf.frame = buffer[11]; } if (rtn) { IOPBFREE (buffer, 12); return (rtn); } /* * Now do a readheader to determine which data mode it is in. * ...If the track is a data track */ if ((entry->cdte_ctrl & CDROM_DATA_TRACK) && (entry->cdte_track != CDROM_LEADOUT)) { if (entry->cdte_format & CDROM_LBA) { lba = entry->cdte_addr.lba; } else { lba = (((entry->cdte_addr.msf.minute * 60) + (entry->cdte_addr.msf.second)) * 75) + entry->cdte_addr.msf.frame; } bzero((caddr_t)cdb, 10); cdb[0] = SCMD_READ_HEADER; cdb[2] = (u_char)((lba >> 24) & 0xFF); cdb[3] = (u_char)((lba >> 16) & 0xFF); cdb[4] = (u_char)((lba >> 8) & 0xFF); cdb[5] = (u_char)(lba & 0xFF); cdb[7] = 0x00; cdb[8] = 0x08; com->uscsi_buflen = 0x08; rtn1 = (srioctl_cmd(dev, (caddr_t)com, SR_USCSI_CDB_KERNEL|SR_USCSI_BUF_KERNEL)); if (rtn1) { IOPBFREE (buffer, 12); return (rtn1); } entry->cdte_datamode = buffer[0]; } else { entry->cdte_datamode = -1; } IOPBFREE (buffer, 12); return (rtn);}/* * This routine sets the drive to reading mode-2 data tracks */static intsr_mode_2(devp)struct scsi_device *devp;{ struct scsi_pkt *pkt1; struct scsi_pkt *pkt2; caddr_t buffer1; caddr_t buffer2; char cdb[6]; DPRINTF("%s%d: switching to reading mode-2.\n", DNAME, DUNIT); /* * first, do a mode sense of page 1 code */ bzero((caddr_t)cdb, 6); cdb[0] = SCMD_MODE_SENSE; cdb[2] = 1; cdb[4] = 20; pkt1 = get_pktiopb(ROUTE, (caddr_t *)&buffer1, 6, 1, 20, B_READ, NULL_FUNC); if (!pkt1) { return (ENOMEM); } makecom_all(pkt1, devp, FLAG_NOINTR, 0, cdb); if (scsi_poll(pkt1) || SCBP_C(pkt1) != STATUS_GOOD || (pkt1->pkt_state & STATE_XFERRED_DATA) == 0 || (pkt1->pkt_resid != 0)) { DPRINTF("%s%d: MODE SENSE command failed.\n", DNAME, DUNIT); free_pktiopb(pkt1, (caddr_t)buffer1, 20); return (EIO); } DPRINTF("%s%d: Parameter from Mode Sense:\n", DNAME, DUNIT); if (DEBUGGING) { int i; for (i=0; i!=20; i++) { printf("0x%x ", buffer1[i]); } } /* * then, do a mode select to set to mode-2 read */ bzero((caddr_t)cdb, 6); cdb[0] = SCMD_MODE_SELECT; cdb[4] = 20; pkt2 = get_pktiopb(ROUTE, (caddr_t *)&buffer2, 6, 1, 20, B_WRITE, NULL_FUNC); if (!pkt2) { return (ENOMEM); } /* * fill in the parameter list for mode select command */ bzero(buffer2, 20); buffer2[3] = 0x08; buffer2[10] = 0x09; buffer2[11] = 0x20; buffer2[12] = 0x01; buffer2[13] = 0x06; buffer2[14] = buffer1[14] | 0x01; buffer2[15] = buffer1[15]; /* * fire the command */ makecom_all(pkt2, devp, FLAG_NOINTR, 0, cdb); if (scsi_poll(pkt2) || SCBP_C(pkt2) != STATUS_GOOD || (pkt2->pkt_state & STATE_XFERRED_DATA) == 0 || (pkt2->pkt_resid != 0)) { DPRINTF("%s%d: MODE SELECT command failed.\n", DNAME, DUNIT); free_pktiopb(pkt2, (caddr_t)buffer2, 20); return (EIO); } free_pktiopb(pkt1, (caddr_t)buffer1, 20); free_pktiopb(pkt2, (caddr_t)buffer2, 20); return (0);}/* * This routine sets the drive to reading mode-1 data tracks */static intsr_mode_1(devp)struct scsi_device *devp;{ struct scsi_pkt *pkt1; struct scsi_pkt *pkt2; caddr_t buffer1; caddr_t buffer2; char cdb[6]; DPRINTF("%s%d: switching to reading mode-1.\n", DNAME, DUNIT); /* * first, do a mode sense of page 1 code */ bzero(cdb, 6); cdb[0] = SCMD_MODE_SENSE; /* get default page 1 values */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -