📄 scsi_cdr.c
字号:
u_char res[2];};struct cdd_52x_mode_page_23 { /* speed selection */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x06 = 6 Bytes */ u_char speed; u_char dummy; u_char res[4];};#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */struct yamaha_mode_page_31 { /* drive configuration */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x02 = 2 Bytes */ u_char res; Ucbit dummy : 4; Ucbit speed : 4;};#else /* Motorola byteorder */struct yamaha_mode_page_31 { /* drive configuration */ MP_P_CODE; /* parsave & pagecode */ u_char p_len; /* 0x02 = 2 Bytes */ u_char res; Ucbit speed : 4; Ucbit dummy : 4;};#endifstruct cdd_52x_mode_data { struct scsi_mode_header header; union cdd_pagex { struct cdd_52x_mode_page_21 page21; struct cdd_52x_mode_page_23 page23; struct yamaha_mode_page_31 page31; } pagex;};EXPORT intspeed_select_yamaha(speed, dummy) int speed; int dummy;{ struct cdd_52x_mode_data md; int count; fillbytes((caddr_t)&md, sizeof(md), '\0'); count = sizeof(struct scsi_mode_header) + sizeof(struct yamaha_mode_page_31); speed >>= 1; md.pagex.page31.p_code = 0x31; md.pagex.page31.p_len = 0x02; md.pagex.page31.speed = speed; md.pagex.page31.dummy = dummy?1:0; return (mode_select((u_char *)&md, count, 0, inq.data_format >= 2));}EXPORT intspeed_select_philips(speed, dummy) int speed; int dummy;{ struct cdd_52x_mode_data md; int count; fillbytes((caddr_t)&md, sizeof(md), '\0'); count = sizeof(struct scsi_mode_header) + sizeof(struct cdd_52x_mode_page_23); md.pagex.page23.p_code = 0x23; md.pagex.page23.p_len = 0x06; md.pagex.page23.speed = speed; md.pagex.page23.dummy = dummy?1:0; return (mode_select((u_char *)&md, count, 0, inq.data_format >= 2));}EXPORT intwrite_track_info(sectype) int sectype;{ struct cdd_52x_mode_data md; int count = sizeof(struct scsi_mode_header) + sizeof(struct cdd_52x_mode_page_21); fillbytes((caddr_t)&md, sizeof(md), '\0'); md.pagex.page21.p_code = 0x21; md.pagex.page21.p_len = 0x0E; /* is sectype ok ??? */ md.pagex.page21.sectype = sectype; md.pagex.page21.track = 0; /* 0 : create new track */ return (mode_select((u_char *)&md, count, 0, inq.data_format >= 2));}struct tocheader { Uchar len[2]; Uchar first; Uchar last;};struct trackdesc { Uchar res0;#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ Ucbit control : 4; Ucbit adr : 4;#else /* Motorola byteorder */ Ucbit adr : 4; Ucbit control : 4;#endif Uchar track; Uchar res3; Uchar addr[4];};struct diskinfo { struct tocheader hd; struct trackdesc desc[1];};struct siheader { Uchar len[2]; Uchar finished; Uchar unfinished;};struct sidesc { Uchar sess_number; Uchar res1; Uchar track; Uchar res3; Uchar addr[4];};struct sinfo { struct siheader hd; struct sidesc desc[1];};struct trackheader { Uchar mode; Uchar res[3]; Uchar addr[4];};#define TRM_ZERO 0#define TRM_USER_ECC 1 /* 2048 bytes user data + 288 Bytes ECC/EDC */#define TRM_USER 2 /* All user data (2336 bytes) */struct ftrackdesc { Uchar sess_number;#if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */ Ucbit control : 4; Ucbit adr : 4;#else /* Motorola byteorder */ Ucbit adr : 4; Ucbit control : 4;#endif Uchar track; Uchar point; Uchar amin; Uchar asec; Uchar aframe; Uchar res7; Uchar pmin; Uchar psec; Uchar pframe;};struct fdiskinfo { struct tocheader hd; struct ftrackdesc desc[1];};EXPORT intread_tochdr(dp, fp, lp) cdr_t *dp; int *fp; int *lp;{ struct tocheader *tp; char xb[256]; int len; tp = (struct tocheader *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc(xb, 0, sizeof(struct tocheader), 0, FMT_TOC) < 0) { if (silent == 0) errmsgno(EX_BAD, "Cannot read TOC header\n"); return (-1); } len = a_to_u_short(tp->len) + sizeof(struct tocheader)-2; if (len >= 4) { if (fp) *fp = tp->first; if (lp) *lp = tp->last; return (0); } return (-1);} EXPORT intread_trackinfo(track, offp, msfp, adrp, controlp, modep) int track; long *offp; struct msf *msfp; int *adrp; int *controlp; int *modep;{ struct diskinfo *dp; char xb[256]; int len; dp = (struct diskinfo *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc(xb, track, sizeof(struct diskinfo), 0, FMT_TOC) < 0) { if (silent <= 0) errmsgno(EX_BAD, "Cannot read TOC\n"); return (-1); } len = a_to_u_short(dp->hd.len) + sizeof(struct tocheader)-2; if (len < sizeof(struct diskinfo)) return (-1); if (offp) *offp = a_to_u_long(dp->desc[0].addr); if (adrp) *adrp = dp->desc[0].adr; if (controlp) *controlp = dp->desc[0].control; if (msfp) { silent++; if (read_toc(xb, track, sizeof(struct diskinfo), 1, FMT_TOC) >= 0) { msfp->msf_min = dp->desc[0].addr[1]; msfp->msf_sec = dp->desc[0].addr[2]; msfp->msf_frame = dp->desc[0].addr[3]; } else { msfp->msf_min = 0; msfp->msf_sec = 0; msfp->msf_frame = 0; } silent--; } if (modep == NULL) return (0); if (track == 0xAA) { *modep = -1; return (0); } fillbytes((caddr_t)xb, sizeof(xb), '\0'); silent++; if (read_header(xb, *offp, 8, 0) >= 0) { *modep = xb[0]; } else if (read_track_info_philips(xb, track, 14) >= 0) { *modep = xb[0xb] & 0xF; } else { *modep = -1; } silent--; return (0);}EXPORT intread_B0(isbcd, b0p, lop) BOOL isbcd; long *b0p; long *lop;{ struct fdiskinfo *dp; struct ftrackdesc *tp; char xb[8192]; char *pe; int len; long l; dp = (struct fdiskinfo *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc_philips(xb, 1, sizeof(struct tocheader), 0, FMT_FULLTOC) < 0) { return (-1); } len = a_to_u_short(dp->hd.len) + sizeof(struct tocheader)-2; if (len < sizeof(struct fdiskinfo)) return (-1); if (read_toc_philips(xb, 1, len, 0, FMT_FULLTOC) < 0) { return (-1); } if (verbose) { scsiprbytes("TOC data: ", (Uchar *)xb, len > sizeof(xb) - scsigetresid() ? sizeof(xb) - scsigetresid() : 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 (verbose) scsiprbytes("B0: ", (Uchar *)tp, 11); if (isbcd) { l = msf_to_lba(from_bcd(tp->amin), from_bcd(tp->asec), from_bcd(tp->aframe)); } else { l = msf_to_lba(tp->amin, tp->asec, tp->aframe); } if (b0p) *b0p = l; if (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)); } else { l = msf_to_lba(tp->pmin, tp->psec, tp->pframe); } if (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(offp) long *offp;{ struct diskinfo *dp; char xb[256]; int len; dp = (struct diskinfo *)xb; fillbytes((caddr_t)xb, sizeof(xb), '\0'); if (read_toc((caddr_t)xb, 0, sizeof(struct tocheader), 0, FMT_SINFO) < 0) return (-1); if (verbose) scsiprbytes("tocheader: ", (u_char *)xb, sizeof(struct tocheader) - scsigetresid()); len = a_to_u_short(dp->hd.len) + sizeof(struct tocheader)-2; if (len > sizeof(xb)) { errmsgno(EX_BAD, "Session info too big.\n"); return (-1); } if (read_toc((caddr_t)xb, 0, len, 0, FMT_SINFO) < 0) return (-1); if (verbose) scsiprbytes("tocheader: ", (u_char *)xb, len - scsigetresid()); dp = (struct diskinfo *)xb; if (offp) *offp = a_to_u_long(dp->desc[0].addr); return (0);}/* * Return address of first track in last session (pre SCSI-3 version). */EXPORT intread_session_offset_philips(offp) 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((caddr_t)xb, 0, sizeof(struct siheader), 0, FMT_SINFO) < 0) return (-1); len = a_to_u_short(sp->hd.len) + sizeof(struct siheader)-2; if (len > sizeof(xb)) { errmsgno(EX_BAD, "Session info too big.\n"); return (-1); } if (read_toc_philips((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_long(sp->desc[sp->hd.finished-1].addr); return (0);}EXPORT intsense_secsize(current) int current;{ u_char mode[0x100]; u_char *p; u_char *ep; int secsize = -1; silent++; (void)unit_ready(); silent--; /* XXX Quick and dirty, musz verallgemeinert werden !!! */ fillbytes(mode, sizeof(mode), '\0'); silent++; if (mode_sense(mode, 0xFF, 0x3F, current?0:2) < 0) { /* All Pages */ fillbytes(mode, sizeof(mode), '\0'); if (mode_sense(mode, 0xFF, 0, current?0:2) < 0) {/* VU (block desc) */ silent--; return (-1); } } silent--; ep = mode+mode[0]; /* Points to last byte of data */ p = &mode[4]; p += mode[3]; if (debug) { printf("Pages: "); while (p < ep) { printf("0x%x ", *p&0x3F); p += p[1]+2; } printf("\n"); } if (mode[3] == 8) { if (debug) { printf("Density: 0x%x\n", mode[4]); printf("Blocks: %ld\n", a_to_3_byte(&mode[5])); printf("Blocklen:%ld\n", a_to_3_byte(&mode[9])); } secsize = a_to_3_byte(&mode[9]); } return (secsize);}EXPORT intselect_secsize(secsize) int secsize;{ struct scsi_mode_data md; int count = sizeof(struct scsi_mode_header) + sizeof(struct scsi_mode_blockdesc); (void)test_unit_ready(); /* 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((u_char *)&md, count, 0, inq.data_format >= 2));}int dev = DEV_CDD_521;EXPORT BOOLis_cddrive(){ return (inq.type == INQ_ROMD || inq.type == INQ_WORM);}EXPORT BOOLis_unknown_dev(){ return (dev == DEV_UNKNOWN);}#define DEBUG#ifdef DEBUG#define G0_MAXADDR 0x1FFFFFLEXPORT intread_scsi(bp, addr, cnt) caddr_t bp; long addr; int cnt;{ if(addr <= G0_MAXADDR && cnt < 256) return (read_g0(bp, addr, cnt)); else return (read_g1(bp, addr, cnt));}EXPORT intread_g0(bp, addr, cnt) caddr_t bp; long addr; int cnt;{ if (cap.c_bsize <= 0) raisecond("capacity_not_set", 0L); fillbytes((caddr_t)&scmd, sizeof(scmd), '\0'); scmd.addr = bp; scmd.size = cnt*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 = target; scmd.cdb.g0_cdb.cmd = SC_READ; scmd.cdb.g0_cdb.lun = lun; g0_cdbaddr(&scmd.cdb.g0_cdb, addr); scmd.cdb.g0_cdb.count = cnt;/* scmd.cdb.g0_cdb.vu_56 = 1;*/ return (scsicmd("read_g0"));}EXPORT intread_g1(bp, addr, cnt) caddr_t bp; long addr; int cnt;{ if (cap.c_bsize <= 0) raisecond("capacity_not_set", 0L); fillbytes((caddr_t)&scmd, sizeof(scmd), '\0'); scmd.addr = bp; scmd.size = cnt*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 = target; scmd.cdb.g1_cdb.cmd = SC_EREAD; scmd.cdb.g1_cdb.lun = lun; g1_cdbaddr(&scmd.cdb.g1_cdb, addr); g1_cdblen(&scmd.cdb.g1_cdb, cnt); return (scsicmd("read_g1"));}#endif /* DEBUG */EXPORT BOOLgetdev(print) BOOL print;{ BOOL got_inquiry = TRUE; char vendor_info[8+1]; char prod_ident[16+1]; char prod_revision[4+1]; fillbytes((caddr_t)&inq, sizeof(inq), '\0'); dev = DEV_UNKNOWN; silent++; (void)unit_ready(); if (scmd.error >= SCG_FATAL && !(scmd.scb.chk && scmd.sense_count > 0)) { silent--; return (FALSE); }/* if (scmd.error < SCG_FATAL || scmd.scb.chk && scmd.sense_count > 0){*/ if (inquiry((caddr_t)&inq, sizeof(inq)) < 0) { got_inquiry = FALSE; if (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(0x12); /* soft lock on */ if (qic02(1) < 0) { /* soft lock off */ dev = DEV_ACB40X0;/* dev = acbdev();*/ } else { dev = DEV_SC4000; inq.type = INQ_SEQD; inq.removable = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -