123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- #include "acd.h"
- int
- msfconv(Fmt *fp)
- {
- Msf m;
- m = va_arg(fp->args, Msf);
- fmtprint(fp, "%d.%d.%d", m.m, m.s, m.f);
- return 0;
- }
- static int
- status(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0xBD;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- static int
- playmsf(Drive *d, Msf start, Msf end)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x47;
- cmd[3] = start.m;
- cmd[4] = start.s;
- cmd[5] = start.f;
- cmd[6] = end.m;
- cmd[7] = end.s;
- cmd[8] = end.f;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- int
- playtrack(Drive *d, int start, int end)
- {
- Toc *t;
- t = &d->toc;
- if(t->ntrack == 0)
- return -1;
- if(start < 0)
- start = 0;
- if(end >= t->ntrack)
- end = t->ntrack-1;
- if(end < start)
- end = start;
- return playmsf(d, t->track[start].start, t->track[end].end);
- }
- int
- resume(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x4B;
- cmd[8] = 0x01;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- int
- pause(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x4B;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- int
- stop(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x4E;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- int
- eject(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x1B;
- cmd[1] = 1;
- cmd[4] = 2;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- int
- ingest(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x1B;
- cmd[1] = 1;
- cmd[4] = 3;
- return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
- }
- static Msf
- rdmsf(uchar *p)
- {
- Msf msf;
- msf.m = p[0];
- msf.s = p[1];
- msf.f = p[2];
- return msf;
- }
- static ulong
- rdlba(uchar *p)
- {
- return (p[0]<<16) | (p[1]<<8) | p[2];
- }
- /* not a Drive, so that we don't accidentally touch Drive.toc */
- int
- gettoc(Scsi *s, Toc *t)
- {
- int i, n;
- uchar cmd[12];
- uchar resp[1024];
- Again:
- memset(t, 0, sizeof(*t));
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x43;
- cmd[1] = 0x02;
- cmd[7] = sizeof(resp)>>8;
- cmd[8] = sizeof(resp);
- s->changetime = 1;
- /* scsi sets nchange, changetime */
- if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
- return -1;
- if(s->changetime == 0) {
- t->ntrack = 0;
- werrstr("no media");
- return -1;
- }
- if(t->nchange == s->nchange && t->changetime != 0)
- return 0;
- t->nchange = s->nchange;
- t->changetime = s->changetime;
- if(t->ntrack > MTRACK)
- t->ntrack = MTRACK;
- DPRINT(2, "%d %d\n", resp[3], resp[2]);
- t->ntrack = resp[3]-resp[2]+1;
- t->track0 = resp[2];
- n = ((resp[0]<<8) | resp[1])+2;
- if(n < 4+8*(t->ntrack+1)) {
- werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1));
- return -1;
- }
- for(i=0; i<=t->ntrack; i++) /* <=: track[ntrack] = end */
- t->track[i].start = rdmsf(resp+4+i*8+5);
- for(i=0; i<t->ntrack; i++)
- t->track[i].end = t->track[i+1].start;
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x43;
- cmd[7] = sizeof(resp)>>8;
- cmd[8] = sizeof(resp);
- if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
- return -1;
- if(s->changetime != t->changetime || s->nchange != t->nchange) {
- fprint(2, "disk changed underfoot; repeating\n");
- goto Again;
- }
- n = ((resp[0]<<8) | resp[1])+2;
- if(n < 4+8*(t->ntrack+1)) {
- werrstr("bad read");
- return -1;
- }
- for(i=0; i<=t->ntrack; i++)
- t->track[i].bstart = rdlba(resp+4+i*8+5);
- for(i=0; i<t->ntrack; i++)
- t->track[i].bend = t->track[i+1].bstart;
- return 0;
- }
- static void
- dumptoc(Toc *t)
- {
- int i;
- fprint(1, "%d tracks\n", t->ntrack);
- for(i=0; i<t->ntrack; i++)
- print("%d. %M-%M (%lud-%lud)\n", i+1,
- t->track[i].start, t->track[i].end,
- t->track[i].bstart, t->track[i].bend);
- }
- static void
- ping(Drive *d)
- {
- uchar cmd[12];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x43;
- scsi(d->scsi, cmd, sizeof(cmd), nil, 0, Snone);
- }
- static int
- playstatus(Drive *d, Cdstatus *stat)
- {
- uchar cmd[12], resp[16];
- memset(cmd, 0, sizeof cmd);
- cmd[0] = 0x42;
- cmd[1] = 0x02;
- cmd[2] = 0x40;
- cmd[3] = 0x01;
- cmd[7] = sizeof(resp)>>8;
- cmd[8] = sizeof(resp);
- if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0)
- return -1;
- switch(resp[1]){
- case 0x11:
- stat->state = Splaying;
- break;
- case 0x12:
- stat->state = Spaused;
- break;
- case 0x13:
- stat->state = Scompleted;
- break;
- case 0x14:
- stat->state = Serror;
- break;
- case 0x00: /* not supported */
- case 0x15: /* no current status to return */
- default:
- stat->state = Sunknown;
- break;
- }
- stat->track = resp[6];
- stat->index = resp[7];
- stat->abs = rdmsf(resp+9);
- stat->rel = rdmsf(resp+13);
- return 0;
- }
- void
- cdstatusproc(void *v)
- {
- Drive *d;
- Toc t;
- Cdstatus s;
- t.changetime = ~0;
- t.nchange = ~0;
- threadsetname("cdstatusproc");
- d = v;
- DPRINT(2, "cdstatus %d\n", getpid());
- for(;;) {
- ping(d);
- //DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange);
- if(playstatus(d, &s) == 0)
- send(d->cstatus, &s);
- if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) {
- if(gettoc(d->scsi, &t) == 0) {
- DPRINT(2, "sendtoc...\n");
- if(debug) dumptoc(&t);
- send(d->ctocdisp, &t);
- } else
- DPRINT(2, "error: %r\n");
- }
- sleep(1000);
- }
- }
|