📄 scsi_cdr.c
字号:
return (-1); } if (scgp->verbose) { scsiprbytes("TOC data: ", (Uchar *)xb, len > (int)sizeof(xb) - scsigetresid(scgp) ? sizeof(xb) - scsigetresid(scgp) : len); tp = &dp->desc[0]; pe = &xb[len]; while ((char *)tp < pe) { scsiprbytes("ENT: ", (Uchar *)tp, 11); tp++; } } tp = &dp->desc[0]; pe = &xb[len]; for (; (char *)tp < pe; tp++) { if (tp->sess_number != dp->hd.last) continue; if (tp->point != 0xB0) continue; if (scgp->verbose) scsiprbytes("B0: ", (Uchar *)tp, 11); if (isbcd) { l = msf_to_lba(from_bcd(tp->amin), from_bcd(tp->asec), from_bcd(tp->aframe), TRUE); } else { l = msf_to_lba(tp->amin, tp->asec, tp->aframe, TRUE); } if (b0p) *b0p = l; if (scgp->verbose) printf("B0 start: %ld\n", l); if (isbcd) { l = msf_to_lba(from_bcd(tp->pmin), from_bcd(tp->psec), from_bcd(tp->pframe), TRUE); } else { l = msf_to_lba(tp->pmin, tp->psec, tp->pframe, TRUE); } if (scgp->verbose) printf("B0 lout: %ld\n", l); if (lop) *lop = l; return (0); } return (-1);}/* * Return address of first track in last session (SCSI-3/mmc version). */EXPORT intread_session_offset(scgp, offp) SCSI *scgp; long *offp;{ struct diskinfo *dp; char xb[256]; int len; dp = (struct diskinfo *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc(scgp, (caddr_t)xb, 0, sizeof(struct tocheader), 0, FMT_SINFO) < 0) return (-1); if (scgp->verbose) scsiprbytes("tocheader: ", (Uchar *)xb, sizeof(struct tocheader) - scsigetresid(scgp)); len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2; if (len > (int)sizeof(xb)) { errmsgno(EX_BAD, "Session info too big.\n"); return (-1); } if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0) return (-1); if (scgp->verbose) scsiprbytes("tocheader: ", (Uchar *)xb, len - scsigetresid(scgp)); dp = (struct diskinfo *)xb; if (offp) *offp = a_to_u_4_byte(dp->desc[0].addr); return (0);}/* * Return address of first track in last session (pre SCSI-3 version). */EXPORT intread_session_offset_philips(scgp, offp) SCSI *scgp; long *offp;{ struct sinfo *sp; char xb[256]; int len; sp = (struct sinfo *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof(struct siheader), 0, FMT_SINFO) < 0) return (-1); len = a_to_u_2_byte(sp->hd.len) + sizeof(struct siheader)-2; if (len > (int)sizeof(xb)) { errmsgno(EX_BAD, "Session info too big.\n"); return (-1); } if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0) return (-1); /* * Old drives return the number of finished sessions in first/finished * a descriptor is returned for each session. * New drives return the number of the first and last session * one descriptor for the last finished session is returned * as in SCSI-3 * In all cases the lowest session number is set to 1. */ sp = (struct sinfo *)xb; if (offp) *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr); return (0);}EXPORT intsense_secsize(scgp, current) SCSI *scgp; int current;{ Uchar mode[0x100]; Uchar *p; Uchar *ep; int secsize = -1; scgp->silent++; (void)unit_ready(scgp); scgp->silent--; /* XXX Quick and dirty, musz verallgemeinert werden !!! */ fillbytes(mode, sizeof(mode), '\0'); scgp->silent++; if (mode_sense(scgp, mode, 0xFF, 0x3F, current?0:2) < 0) { /* All Pages */ fillbytes(mode, sizeof(mode), '\0'); if (mode_sense(scgp, mode, 0xFF, 0, current?0:2) < 0) {/* VU (block desc) */ scgp->silent--; return (-1); } } scgp->silent--; ep = mode+mode[0]; /* Points to last byte of data */ p = &mode[4]; p += mode[3]; if (scgp->debug) { printf("Pages: "); while (p < ep) { printf("0x%x ", *p&0x3F); p += p[1]+2; } printf("\n"); } if (mode[3] == 8) { if (scgp->debug) { printf("Density: 0x%x\n", mode[4]); printf("Blocks: %ld\n", a_to_u_3_byte(&mode[5])); printf("Blocklen:%ld\n", a_to_u_3_byte(&mode[9])); } secsize = a_to_u_3_byte(&mode[9]); } return (secsize);}EXPORT intselect_secsize(scgp, secsize) SCSI *scgp; int secsize;{ struct scsi_mode_data md; int count = sizeof(struct scsi_mode_header) + sizeof(struct scsi_mode_blockdesc); (void)test_unit_ready(scgp); /* clear any error situation */ fillbytes((caddr_t)&md, sizeof(md), '\0'); md.header.blockdesc_len = 8; i_to_3_byte(md.blockdesc.lblen, secsize); return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));}EXPORT BOOLis_cddrive(scgp) SCSI *scgp;{ return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);}EXPORT BOOLis_unknown_dev(scgp) SCSI *scgp;{ return (scgp->dev == DEV_UNKNOWN);}#define DEBUG#ifdef DEBUG#define G0_MAXADDR 0x1FFFFFLEXPORT intread_scsi(scgp, bp, addr, cnt) SCSI *scgp; caddr_t bp; long addr; int cnt;{ if(addr <= G0_MAXADDR && cnt < 256 && !is_atapi) return (read_g0(scgp, bp, addr, cnt)); else return (read_g1(scgp, bp, addr, cnt));}EXPORT intread_g0(scgp, bp, addr, cnt) SCSI *scgp; caddr_t bp; long addr; int cnt;{ register struct scg_cmd *scmd = scgp->scmd; if (scgp->cap->c_bsize <= 0) raisecond("capacity_not_set", 0L); fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = bp; scmd->size = cnt*scgp->cap->c_bsize; scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; scmd->cdb_len = SC_G0_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g0_cdb.cmd = SC_READ; scmd->cdb.g0_cdb.lun = scgp->lun; g0_cdbaddr(&scmd->cdb.g0_cdb, addr); scmd->cdb.g0_cdb.count = cnt;/* scmd->cdb.g0_cdb.vu_56 = 1;*/ scgp->cmdname = "read_g0"; return (scsicmd(scgp));}EXPORT intread_g1(scgp, bp, addr, cnt) SCSI *scgp; caddr_t bp; long addr; int cnt;{ register struct scg_cmd *scmd = scgp->scmd; if (scgp->cap->c_bsize <= 0) raisecond("capacity_not_set", 0L); fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = bp; scmd->size = cnt*scgp->cap->c_bsize; scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; scmd->cdb_len = SC_G1_CDBLEN; scmd->sense_len = CCS_SENSE_LEN; scmd->target = scgp->target; scmd->cdb.g1_cdb.cmd = SC_EREAD; scmd->cdb.g1_cdb.lun = scgp->lun; g1_cdbaddr(&scmd->cdb.g1_cdb, addr); g1_cdblen(&scmd->cdb.g1_cdb, cnt); scgp->cmdname = "read_g1"; return (scsicmd(scgp));}#endif /* DEBUG */EXPORT BOOLgetdev(scgp, print) SCSI *scgp; BOOL print;{ BOOL got_inquiry = TRUE; char vendor_info[8+1]; char prod_ident[16+1]; char prod_revision[4+1]; int inq_len = 0; register struct scg_cmd *scmd = scgp->scmd; register struct scsi_inquiry *inq = scgp->inq; fillbytes((caddr_t)inq, sizeof(*inq), '\0'); scgp->dev = DEV_UNKNOWN; scgp->silent++; (void)unit_ready(scgp); if (scmd->error >= SCG_FATAL && !(scmd->scb.chk && scmd->sense_count > 0)) { scgp->silent--; return (FALSE); }/* if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/ if (inquiry(scgp, (caddr_t)inq, sizeof(*inq)) < 0) { got_inquiry = FALSE; } else { inq_len = sizeof(*inq) - scsigetresid(scgp); } if (!got_inquiry) { if (scgp->verbose) { printf( "error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n", scmd->error, scmd->scb.chk, scmd->sense_count, scmd->sense.code); } /* * Folgende Kontroller kennen das Kommando * INQUIRY nicht: * * ADAPTEC ACB-4000, ACB-4010, ACB 4070 * SYSGEN SC4000 * * Leider reagieren ACB40X0 und ACB5500 identisch * wenn drive not ready (code == not ready), * sie sind dann nicht zu unterscheiden. */ if (scmd->scb.chk && scmd->sense_count == 4) { /* Test auf SYSGEN */ (void)qic02(scgp, 0x12); /* soft lock on */ if (qic02(scgp, 1) < 0) { /* soft lock off */ scgp->dev = DEV_ACB40X0;/* scgp->dev = acbdev();*/ } else { scgp->dev = DEV_SC4000; inq->type = INQ_SEQD; inq->removable = 1; } } } else if (scgp->verbose) { int i; int len = inq->add_len + 5; Uchar ibuf[256+5]; Uchar *ip = (Uchar *)inq; Uchar c; if (len > (int)sizeof (*inq) && inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) { len = inq->add_len+5 - scsigetresid(scgp); ip = ibuf; } else { len = sizeof (*inq); } printf("Inquiry Data : "); for (i = 0; i < len; i++) { c = ip[i]; if (c >= ' ' && c < 0177) printf("%c", c); else printf("."); } printf("\n"); } strncpy(vendor_info, inq->vendor_info, sizeof(inq->vendor_info)); strncpy(prod_ident, inq->prod_ident, sizeof(inq->prod_ident)); strncpy(prod_revision, inq->prod_revision, sizeof(inq->prod_revision)); vendor_info[sizeof(inq->vendor_info)] = '\0'; prod_ident[sizeof(inq->prod_ident)] = '\0'; prod_revision[sizeof(inq->prod_revision)] = '\0'; switch (inq->type) { case INQ_DASD: if (inq->add_len == 0 && inq->vendor_info[0] != '\0') { Uchar *p; /* * NT-4.0 creates fake inquiry data for IDE disks. * Unfortunately, it does not set add_len wo we * check if vendor_info, prod_ident and prod_revision * contains valid chars for a CCS inquiry. */ if (inq_len >= 36) inq->add_len = 31; for (p = (Uchar *)&inq->vendor_info[0]; p < (Uchar *)&inq->prod_revision[4]; p++) { if (*p < 0x20 || *p > 0x7E) { inq->add_len = 0; break; } } } if (inq->add_len == 0) { if (scgp->dev == DEV_UNKNOWN && got_inquiry) { scgp->dev = DEV_ACB5500; strcpy(inq->vendor_info, "ADAPTEC ACB-5500 FAKE"); } else switch (scgp->dev) { case DEV_ACB40X0: strcpy(inq->vendor_info, "ADAPTEC ACB-40X0 FAKE"); break; case DEV_ACB4000: strcpy(inq->vendor_info, "ADAPTEC ACB-4000 FAKE"); break; case DEV_ACB4010: strcpy(inq->vendor_info, "ADAPTEC ACB-4010 FAKE"); break; case DEV_ACB4070: strcpy(inq->vendor_info, "ADAPTEC ACB-4070 FAKE"); break; } } else if (inq->add_len < 31) { scgp->dev = DEV_NON_CCS_DSK; } else if (strbeg("EMULEX", vendor_info)) { if (strbeg("MD21", prod_ident)) scgp->dev = DEV_MD21; if (strbeg("MD23", prod_ident)) scgp->dev = DEV_MD23; else scgp->dev = DEV_CCS_GENDISK; } else if (strbeg("ADAPTEC", vendor_info)) { if (strbeg("ACB-4520", prod_ident)) scgp->dev = DEV_ACB4520A; if (strbeg("ACB-4525", prod_ident)) scgp->dev = DEV_ACB4525; else scgp->dev = DEV_CCS_GENDISK; } else if (strbeg("SONY", vendor_info) && strbeg("SMO-C501", prod_ident)) { scgp->dev = DEV_SONY_SMO; } else { scgp->dev = DEV_CCS_GENDISK; } break; case INQ_SEQD: if (scgp->dev == DEV_SC4000) { strcpy(inq->vendor_info, "SYSGEN SC4000 FAKE"); } else if (inq->add_len == 0 && inq->removable && inq->ansi_version == 1) { scgp->dev = DEV_MT02; strcpy(inq->vendor_info, "EMULEX MT02 FAKE"); } break;/* case INQ_OPTD:*/ case INQ_ROMD: case INQ_WORM: if (strbeg("RXT-800S", prod_ident)) scgp->dev = DEV_RXT800S; /* * Start of CD-Recorders: */ if (strbeg("ACER", vendor_info)) { if (strbeg("CR-4020C", prod_ident)) scgp->dev = DEV_RICOH_RO_1420C; } else if (strbeg("CREATIVE", vendor_info)) { if (strbeg("CDR2000", prod_ident)) scgp->dev = DEV_RICOH_RO_1060C; } else if (strbeg("GRUNDIG", vendor_info)) { if (strbeg("CDR100IPW", prod_ident)) scgp->dev = DEV_CDD_2000; } else if (strbeg("JVC", vendor_info)) { if (strbeg("XR-W2001", prod_ident)) scgp->dev = DEV_TEAC_CD_R50S; else if (strbeg("XR-W2010", prod_ident)) scgp->dev = DEV_TEAC_CD_R50S; else if (strbeg("R2626", prod_ident)) scgp->dev = DEV_TEAC_CD_R50S; } else if (strbeg("MITSBISH", vendor_info)) {#ifdef XXXX_REALLY /* It's MMC compliant */ if (strbeg("CDRW226", prod_ident)) scgp->dev = DEV_MMC_CDRW;#endif } else if (strbeg("MITSUMI", vendor_info)) { /* Don't know any product string */ scgp->dev = DEV_CDD_522; } else if (strbeg("OPTIMA", vendor_info)) { if (strbeg("CD-R 650", prod_ident)) scgp->dev = DEV_SONY_CDU_924; } else if (strbeg("PHILIPS", vendor_info) || strbeg("IMS", vendor_info) || strbeg("KODAK", vendor_info) || strbeg("HP", vendor_info)) { if (strbeg("CDD521/00", prod_ident)) scgp->dev = DEV_CDD_521_OLD; else if (strbeg("CDD521/02", prod_ident)) scgp->dev = DEV_CDD_521_OLD; /* PCD 200R? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -