drv_mmc.c
来自「刻录光盘的程序」· C语言 代码 · 共 1,299 行 · 第 1/3 页
C
1,299 行
#ifdef DEBUG scsiprbytes("CD write parameter:", (u_char *)mode, len);#endif if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, trackp->secsize)) return (-1); return (0);}LOCAL intclose_track_mmc(scgp, track, trackp) SCSI *scgp; int track; track_t *trackp;{ int ret; if (!is_tao(trackp)) return (0); if (scsi_flush_cache(scgp) < 0) { printf("Trouble flushing the cache\n"); return -1; } wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */ if (is_packet(trackp) && !is_noclose(trackp)) { /* close the incomplete track */ ret = scsi_close_tr_session(scgp, 1, 0xFF); wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */ return (ret); } return (0);}int toc2sess[] = { SES_DA_ROM, /* CD-DA */ SES_DA_ROM, /* CD-ROM */ SES_XA, /* CD-ROM XA mode 1 */ SES_XA, /* CD-ROM XA MODE 2 */ SES_CDI, /* CDI */ SES_DA_ROM, /* Invalid - use default */ SES_DA_ROM, /* Invalid - use default */};LOCAL intopen_session_mmc(scgp, tracks, trackp, toctype, multi) SCSI *scgp; int tracks; track_t *trackp; int toctype; int multi;{ u_char mode[0x100]; int len; struct cd_mode_page_05 *mp; fillbytes((caddr_t)mode, sizeof(mode), '\0'); if (!get_mode_params(scgp, 0x05, "CD write parameter", mode, (u_char *)0, (u_char *)0, (u_char *)0, &len)) return (-1); if (len == 0) return (-1); mp = (struct cd_mode_page_05 *) (mode + sizeof(struct scsi_mode_header) + ((struct scsi_mode_header *)mode)->blockdesc_len); mp->write_type = WT_TAO; /* fix to allow DAO later */ if (!is_tao(trackp)) { mp->write_type = WT_SAO; mp->track_mode = 0; mp->dbtype = DB_RAW; } mp->multi_session = (multi != 0) ? MS_MULTI : MS_NONE; mp->session_format = toc2sess[toctype & TOC_MASK]; if (trackp->isrc) { mp->media_cat_number[0] = 0x80; /* Set MCN valid */ strncpy((char *)&mp->media_cat_number[1], trackp->isrc, 13); } else { fillbytes(&mp->media_cat_number[0], sizeof(mp->media_cat_number), '\0'); }#ifdef DEBUG scsiprbytes("CD write parameter:", (u_char *)mode, len);#endif if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, -1)) return (-1); return (0);}LOCAL intwaitfix_mmc(scgp, secs) SCSI *scgp; int secs;{ char dibuf[16]; int i; int key;#define W_SLEEP 2 scgp->silent++; for (i = 0; i < secs/W_SLEEP; i++) { if (read_disk_info(scgp, dibuf, sizeof(dibuf)) >= 0) { scgp->silent--; return (0); } key = scsi_sense_key(scgp); if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY) break; sleep(W_SLEEP); } scgp->silent--; return (-1);#undef W_SLEEP}LOCAL intfixate_mmc(scgp, onp, dummy, toctype, tracks, trackp) SCSI *scgp; int onp; int dummy; int toctype; int tracks; track_t *trackp;{ int ret = 0; int key = 0; int code = 0; struct timeval starttime; struct timeval stoptime; starttime.tv_sec = 0; starttime.tv_usec = 0; stoptime = starttime; gettimeofday(&starttime, (struct timezone *)0); if (dummy && lverbose) printf("WARNING: Some drives don't like fixation in dummy mode.\n"); if (is_tao(trackp)) { scgp->silent++; ret = scsi_close_tr_session(scgp, 2, 0); scgp->silent--; key = scsi_sense_key(scgp); code = scsi_sense_code(scgp); } else { if (scsi_flush_cache(scgp) < 0) printf("Trouble flushing the cache\n"); } if (ret >= 0) { wait_unit_ready(scgp, 420/curspeed); /* XXX Wait for ATAPI */ waitfix_mmc(scgp, 420/curspeed); /* XXX Wait for ATAPI */ return (ret); } if ((dummy != 0 && (key != SC_ILLEGAL_REQUEST)) || /* * Try to suppress messages from drives that don't like fixation * in -dummy mode. */ ((dummy == 0) && ( ((key != SC_UNIT_ATTENTION) && (key != SC_NOT_READY)) || ((code != 0x2E) && (code != 0x04)) || (strncmp(scgp->inq->vendor_info, "MITSUMI", 7) != 0)))) { /* * UNIT ATTENTION/2E seems to be a magic for old Mitsumi ATAPI drives * NOT READY/ code 4 qual 7 (logical unit not ready, operation in progress) * seems to be a magic for newer Mitsumi ATAPI drives * when returning early from fixating. * Try to supress the error message in this case to make * simple minded users less confused. */ scsiprinterr(scgp); scsiprintresult(scgp); /* XXX restore key/code in future */ } wait_unit_ready(scgp, 420); /* XXX Wait for ATAPI */ waitfix_mmc(scgp, 420/curspeed);/* XXX Wait for ATAPI */ if (!dummy && (ret >= 0 || (key == SC_UNIT_ATTENTION && code == 0x2E))) { /* * Some ATAPI drives (e.g. Mitsumi) imply the * IMMED bit in the SCSI cdb. As there seems to be no * way to properly check for the real end of the * fixating process we wait for the expected time. */ gettimeofday(&stoptime, (struct timezone *)0); timevaldiff(&starttime, &stoptime); if (stoptime.tv_sec < (220 / curspeed)) { unsigned secs; if (lverbose) { printf("Actual fixating time: %ld seconds\n", (long)stoptime.tv_sec); } secs = (280 / curspeed) - stoptime.tv_sec; if (lverbose) { printf("ATAPI early return: sleeping %d seconds.\n", secs); } sleep(secs); } } return (ret);}char *blank_types[] = { "entire disk", "PMA, TOC, pregap", "incomplete track", "reserved track", "tail of track", "closing of last session", "last session", "reserved blanking type",};LOCAL intblank_mmc(scgp, addr, blanktype) SCSI *scgp; long addr; int blanktype;{ BOOL cdrr = FALSE; /* Read CD-R */ BOOL cdwr = FALSE; /* Write CD-R */ BOOL cdrrw = FALSE; /* Read CD-RW */ BOOL cdwrw = FALSE; /* Write CD-RW */ mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL); if (!cdwrw) return (blank_dummy(scgp, addr, blanktype)); if (lverbose) { printf("Blanking %s\n", blank_types[blanktype & 0x07]); flush(); } return (scsi_blank(scgp, addr, blanktype));}LOCAL intscsi_sony_write(scgp, bp, sectaddr, size, blocks, islast) SCSI *scgp; caddr_t bp; /* address of buffer */ long sectaddr; /* disk address (sector) to put */ long size; /* number of bytes to transfer */ int blocks; /* sector count */ BOOL islast; /* last write for track */{ return (write_xg5(scgp, bp, sectaddr, size, blocks));}Uchar db2df[] = { 0x00, /* 0 2352 bytes of raw data */ 0xFF, /* 1 2368 bytes (raw data + P/Q Subchannel) */ 0xFF, /* 2 2448 bytes (raw data + P-W Subchannel) */ 0xFF, /* 3 2448 bytes (raw data + P-W raw Subchannel)*/ 0xFF, /* 4 - Reserved */ 0xFF, /* 5 - Reserved */ 0xFF, /* 6 - Reserved */ 0xFF, /* 7 - Vendor specific */ 0x10, /* 8 2048 bytes Mode 1 (ISO/IEC 10149) */ 0xFF, /* 9 2336 bytes Mode 2 (ISO/IEC 10149) */ 0xFF, /* 10 2048 bytes Mode 2! (CD-ROM XA form 1) */ 0xFF, /* 11 2056 bytes Mode 2 (CD-ROM XA form 1) */ 0xFF, /* 12 2324 bytes Mode 2 (CD-ROM XA form 2) */ 0xFF, /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr) */ 0xFF, /* 14 - Reserved */ 0xFF, /* 15 - Vendor specific */};#include <stdxlib.h>LOCAL void fillcue __PR((struct mmc_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp));EXPORT int do_cue __PR((int tracks, track_t *trackp, struct mmc_cue **cuep));EXPORT int send_cue __PR((SCSI *scgp, int tracks, track_t *trackp));EXPORT intdo_cue(tracks, trackp, cuep) int tracks; track_t *trackp; struct mmc_cue **cuep;{ int i; struct mmc_cue *cue; struct mmc_cue *cp; int ncue = 0; int icue = 0; int pgsize; msf_t m; int ctl; int df; int scms; cue = (struct mmc_cue *)malloc(1); for (i = 0; i <= tracks; i++) { ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4; if (is_copy(&trackp[i])) ctl |= TM_ALLOW_COPY << 4; df = db2df[trackp[i].dbtype & 0x0F]; if (trackp[i].isrc) { /* MCN or ISRC */ ncue += 2; cue = (struct mmc_cue *)realloc(cue, ncue * sizeof(*cue)); cp = &cue[icue++]; if (i == 0) { cp->cs_ctladr = 0x02; movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7); cp = &cue[icue++]; cp->cs_ctladr = 0x02; movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7); } else { cp->cs_ctladr = 0x03; cp->cs_tno = i; movebytes(&trackp[i].isrc[0], &cp->cs_index, 6); cp = &cue[icue++]; cp->cs_ctladr = 0x03; cp->cs_tno = i; movebytes(&trackp[i].isrc[6], &cp->cs_index, 6); } } if (i == 0) { /* Lead in */ if (df < 0x10) df |= 1; else df |= 4; lba_to_msf(-150, &m); cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue)); cp = &cue[icue++]; fillcue(cp, ctl|0x01, i, 0, df, 0, &m); } else { scms = 0; if (is_scms(&trackp[i])) scms = 0x80; pgsize = trackp[i].pregapsize;/* if (pgsize == 0)*//* pgsize = 150;*/ lba_to_msf(trackp[i].trackstart-pgsize, &m); cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue)); cp = &cue[icue++]; fillcue(cp, ctl|0x01, i, 0, df, scms, &m); if (trackp[i].nindex == 1) { lba_to_msf(trackp[i].trackstart, &m); cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue)); cp = &cue[icue++]; fillcue(cp, ctl|0x01, i, 1, df, scms, &m); } else { int idx; long *idxlist; ncue += trackp[i].nindex; idxlist = trackp[i].tindex; cue = (struct mmc_cue *)realloc(cue, ncue * sizeof(*cue)); for(idx = 1; idx <=trackp[i].nindex; idx++) { lba_to_msf(trackp[i].trackstart + idxlist[idx], &m); cp = &cue[icue++]; fillcue(cp, ctl|0x01, i, idx, df, scms, &m); } } } } /* Lead out */ ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4; df = db2df[trackp[tracks+1].dbtype & 0x0F]; if (df < 0x10) df |= 1; else df |= 4; lba_to_msf(trackp[tracks+1].trackstart, &m); cue = (struct mmc_cue *)realloc(cue, ++ncue * sizeof(*cue)); cp = &cue[icue++]; fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m); if (lverbose > 1) for (i = 0; i < ncue; i++) { scsiprbytes("", (Uchar *)&cue[i], 8); } if (cuep) *cuep = cue; return (ncue);}LOCAL voidfillcue(cp, ca, tno, idx, dataform, scms, mp) struct mmc_cue *cp; /* The target cue entry */ int ca; /* Control/adr for this entry */ int tno; /* Track number for this entry */ int idx; /* Index for this entry */ int dataform; /* Data format for this entry */ int scms; /* Serial copy management */ msf_t *mp; /* MSF value for this entry */{ cp->cs_ctladr = ca; /* XXX wie lead in */ cp->cs_tno = tno; cp->cs_index = idx; cp->cs_dataform = dataform;/* XXX wie lead in */ cp->cs_scms = scms; cp->cs_min = mp->msf_min; cp->cs_sec = mp->msf_sec; cp->cs_frame = mp->msf_frame;}EXPORT intsend_cue(scgp, tracks, trackp) SCSI *scgp; int tracks; track_t *trackp;{ struct mmc_cue *cp; int ncue; int ret; int i; ncue = do_cue(tracks, trackp, &cp); for (i = 1; i <= tracks; i++) { if (trackp[i].tracksize < 0) { errmsgno(EX_BAD, "Track %d has unknown length.\n", i); return (-1); } } ret = send_cue_sheet(scgp, (caddr_t)cp, ncue*8); free(cp); return (ret);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?