/* * infer endings from the beginnings of other tracks. */ static int mmcinfertracks(Drive *drive, int first, int last) { int i; uint8_t resp[1024]; uint32_t tot; Track *t; if (vflag) fprint(2, "inferring tracks from toc\n"); for(i = first; i <= last; i++) { memset(resp, 0, sizeof(resp)); if(mmcreadtoc(drive, 0, i, resp, sizeof(resp)) < 0) { last = i - 1; if (last < 1) last = 1; break; } t = &drive->track[i-first]; t->mtime = drive->changetime; t->type = TypeData; t->bs = BScdrom; t->beg = bige(resp+8); if(!(resp[5] & 4)) { t->type = TypeAudio; t->bs = BScdda; } } if((int32_t)drive->track[0].beg < 0) /* i've seen negative track 0's */ drive->track[0].beg = 0; tot = 0; memset(resp, 0, sizeof(resp)); /* 0xAA is lead-out */ if(mmcreadtoc(drive, 0, 0xAA, resp, sizeof(resp)) < 0) print("bad mmcreadtoc\n"); if(resp[6]) tot = bige(resp+8); t = nil; for(i=last; i>=first; i--) { t = &drive->track[i-first]; t->end = tot; tot = t->beg; if(t->end <= t->beg) t->beg = t->end = 0; /* -2: skip lead out */ t->size = (t->end - t->beg - 2) * (int64_t)t->bs; } fprint(2, "infertracks: nwa should be %,lld; tot = %,ld\n", t->size, tot); return last; }
/* t is a track number on disc, i is an index into drive->track[] for result */ static int mmctrackinfo(Drive *drive, int t, int i) { int n, type, bs; uint32_t beg, size; uint8_t tmode; uint8_t cmd[10], resp[255]; Track *track; initcdb(cmd, sizeof cmd, ScmdRtrackinfo); cmd[1] = 1; /* address below is logical track # */ cmd[2] = t>>24; cmd[3] = t>>16; cmd[4] = t>>8; cmd[5] = t; cmd[7] = sizeof(resp)>>8; cmd[8] = sizeof(resp); n = scsi(&drive->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread); if(n < 28) { if(vflag) print("trackinfo %d fails n=%d: %r\n", t, n); return -1; } tmode = resp[5] & 0x0D; // dmode = resp[6] & 0x0F; gettypebs(tmode, t, i, &type, &bs); beg = bige(&resp[8]); size = bige(&resp[24]); track = &drive->track[i]; track->mtime = drive->changetime; track->beg = beg; track->end = beg + size; track->type = type; track->bs = bs; track->size = (int64_t)(size-2) * bs; /* -2: skip lead out */ if(resp[6] & (1<<6)) { /* blank? */ track->type = TypeBlank; drive->writeok = Yes; } if(vflag) print(" start %lu end %lu", beg, beg + size - 1); gettracknwa(drive, t, beg, resp); if (vflag) print("\n"); return 0; }
/* * figure out the first writable block, if we can, into drive->aux->mmcnwa. * resp must be from ScmdRtrackinfo. */ static int32_t gettracknwa(Drive *drive, int t, uint32_t beg, uint8_t *resp) { int32_t newnwa; Mmcaux *aux; aux = drive->aux; if(resp[7] & 1) { /* nwa valid? */ newnwa = bige(&resp[12]); if (newnwa >= 0) if (aux->mmcnwa < 0) aux->mmcnwa = newnwa; else if (aux->mmcnwa != newnwa) fprint(2, "nwa is %ld but invis track starts blk %ld\n", newnwa, aux->mmcnwa); } /* resp[6] & (1<<7) of zero: invisible track */ if(t == Invistrack || t == drive->invistrack) if (aux->mmcnwa < 0) aux->mmcnwa = beg; else if (aux->mmcnwa != beg) fprint(2, "invis track starts blk %ld but nwa is %ld\n", beg, aux->mmcnwa); if (vflag && aux->mmcnwa >= 0) print(" nwa %lu", aux->mmcnwa); return 0; }
/* * infer endings from the beginnings of other tracks. */ static void mmcinfertracks(Drive *drive, int first, int last) { int i; uchar resp[1024]; ulong tot; Track *t; if (vflag) fprint(2, "inferring tracks\n"); for(i = first; i <= last; i++) { memset(resp, 0, sizeof(resp)); if(mmcreadtoc(drive, 0, i, resp, sizeof(resp)) < 0) break; t = &drive->track[i-first]; t->mtime = drive->changetime; t->type = TypeData; t->bs = BScdrom; t->beg = bige(resp+8); if(!(resp[5] & 4)) { t->type = TypeAudio; t->bs = BScdda; } } if((long)drive->track[0].beg < 0) /* i've seen negative track 0's */ drive->track[0].beg = 0; tot = 0; memset(resp, 0, sizeof(resp)); /* 0xAA is lead-out */ if(mmcreadtoc(drive, 0, 0xAA, resp, sizeof(resp)) < 0) print("bad\n"); if(resp[6]) tot = bige(resp+8); for(i=last; i>=first; i--) { t = &drive->track[i-first]; t->end = tot; tot = t->beg; if(t->end <= t->beg) t->beg = t->end = 0; /* -2: skip lead out */ t->size = (t->end - t->beg - 2) * (vlong)t->bs; } }
/* t is a track number on disc, i is an index into drive->track[] for result */ static int mmctrackinfo(Drive *drive, int t, int i) { int n, type, bs; ulong beg, size; uchar tmode; uchar cmd[10], resp[255]; Mmcaux *aux; aux = drive->aux; memset(cmd, 0, sizeof(cmd)); cmd[0] = ScmdRtrackinfo; cmd[1] = 1; /* address below is logical track # */ cmd[2] = t>>24; cmd[3] = t>>16; cmd[4] = t>>8; cmd[5] = t; cmd[7] = sizeof(resp)>>8; cmd[8] = sizeof(resp); n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread); if(n < 28) { if(vflag) print("trackinfo %d fails n=%d: %r\n", t, n); return -1; } beg = bige(&resp[8]); size = bige(&resp[24]); tmode = resp[5] & 0x0D; // dmode = resp[6] & 0x0F; if(vflag) print("track %d type %d (%s)", t, tmode, (tmode < nelem(tracktype)? tracktype[tmode]: "**GOK**")); type = TypeNone; bs = BScdda; switch(tmode){ case Tmcdda: type = TypeAudio; bs = BScdda; break; case Tm2audio: /* 2 audio channels, with pre-emphasis 50/15 μs */ if(vflag) print("audio channels with preemphasis on track %d " "(u%.3d)\n", t, i); type = TypeNone; break; case Tmunintr: /* data track, recorded uninterrupted */ case Tmintr: /* data track, recorded interrupted */ /* treat Tmintr (5) as cdrom; it's probably dvd or bd */ type = TypeData; bs = BScdrom; break; default: if(vflag) print("unknown track type %d\n", tmode); break; } drive->track[i].mtime = drive->changetime; drive->track[i].beg = beg; drive->track[i].end = beg+size; drive->track[i].type = type; drive->track[i].bs = bs; drive->track[i].size = (vlong)(size-2) * bs; /* -2: skip lead out */ if(resp[6] & (1<<6)) { /* blank? */ drive->track[i].type = TypeBlank; drive->writeok = 1; } if(vflag) print(" start %lud end %lud", beg, beg + size - 1); /* resp[6] & (1<<7) of zero: invisible track */ /* t == getinvistrack(): invisible track */ if(t == Invistrack || resp[7] & 1) { /* invis or nwa valid? */ aux->mmcnwa = bige(&resp[12]); if ((long)aux->mmcnwa < 0) /* implausible? */ aux->mmcnwa = 0; if (vflag) print(" nwa %lud", aux->mmcnwa); } if (vflag) print("\n"); return 0; }