19a747e4fSDavid du Colombier #include "acd.h"
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier int
msfconv(Fmt * fp)4*3ff48bf5SDavid du Colombier msfconv(Fmt *fp)
59a747e4fSDavid du Colombier {
69a747e4fSDavid du Colombier Msf m;
79a747e4fSDavid du Colombier
8*3ff48bf5SDavid du Colombier m = va_arg(fp->args, Msf);
9*3ff48bf5SDavid du Colombier fmtprint(fp, "%d.%d.%d", m.m, m.s, m.f);
109a747e4fSDavid du Colombier return 0;
119a747e4fSDavid du Colombier }
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier static int
status(Drive * d)149a747e4fSDavid du Colombier status(Drive *d)
159a747e4fSDavid du Colombier {
169a747e4fSDavid du Colombier uchar cmd[12];
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
199a747e4fSDavid du Colombier cmd[0] = 0xBD;
209a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
219a747e4fSDavid du Colombier }
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier static int
playmsf(Drive * d,Msf start,Msf end)249a747e4fSDavid du Colombier playmsf(Drive *d, Msf start, Msf end)
259a747e4fSDavid du Colombier {
269a747e4fSDavid du Colombier uchar cmd[12];
279a747e4fSDavid du Colombier
289a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
299a747e4fSDavid du Colombier cmd[0] = 0x47;
309a747e4fSDavid du Colombier cmd[3] = start.m;
319a747e4fSDavid du Colombier cmd[4] = start.s;
329a747e4fSDavid du Colombier cmd[5] = start.f;
339a747e4fSDavid du Colombier cmd[6] = end.m;
349a747e4fSDavid du Colombier cmd[7] = end.s;
359a747e4fSDavid du Colombier cmd[8] = end.f;
369a747e4fSDavid du Colombier
379a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier int
playtrack(Drive * d,int start,int end)419a747e4fSDavid du Colombier playtrack(Drive *d, int start, int end)
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier Toc *t;
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier t = &d->toc;
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier if(t->ntrack == 0)
489a747e4fSDavid du Colombier return -1;
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier if(start < 0)
519a747e4fSDavid du Colombier start = 0;
529a747e4fSDavid du Colombier if(end >= t->ntrack)
539a747e4fSDavid du Colombier end = t->ntrack-1;
549a747e4fSDavid du Colombier if(end < start)
559a747e4fSDavid du Colombier end = start;
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier return playmsf(d, t->track[start].start, t->track[end].end);
589a747e4fSDavid du Colombier }
599a747e4fSDavid du Colombier
609a747e4fSDavid du Colombier int
resume(Drive * d)619a747e4fSDavid du Colombier resume(Drive *d)
629a747e4fSDavid du Colombier {
639a747e4fSDavid du Colombier uchar cmd[12];
649a747e4fSDavid du Colombier
659a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
669a747e4fSDavid du Colombier cmd[0] = 0x4B;
679a747e4fSDavid du Colombier cmd[8] = 0x01;
689a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
699a747e4fSDavid du Colombier }
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier int
pause(Drive * d)729a747e4fSDavid du Colombier pause(Drive *d)
739a747e4fSDavid du Colombier {
749a747e4fSDavid du Colombier uchar cmd[12];
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
779a747e4fSDavid du Colombier cmd[0] = 0x4B;
789a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier
819a747e4fSDavid du Colombier int
stop(Drive * d)829a747e4fSDavid du Colombier stop(Drive *d)
839a747e4fSDavid du Colombier {
849a747e4fSDavid du Colombier uchar cmd[12];
859a747e4fSDavid du Colombier
869a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
879a747e4fSDavid du Colombier cmd[0] = 0x4E;
889a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
899a747e4fSDavid du Colombier }
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier int
eject(Drive * d)929a747e4fSDavid du Colombier eject(Drive *d)
939a747e4fSDavid du Colombier {
949a747e4fSDavid du Colombier uchar cmd[12];
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
979a747e4fSDavid du Colombier cmd[0] = 0x1B;
989a747e4fSDavid du Colombier cmd[1] = 1;
999a747e4fSDavid du Colombier cmd[4] = 2;
1009a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
1019a747e4fSDavid du Colombier }
1029a747e4fSDavid du Colombier
1039a747e4fSDavid du Colombier int
ingest(Drive * d)1049a747e4fSDavid du Colombier ingest(Drive *d)
1059a747e4fSDavid du Colombier {
1069a747e4fSDavid du Colombier uchar cmd[12];
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
1099a747e4fSDavid du Colombier cmd[0] = 0x1B;
1109a747e4fSDavid du Colombier cmd[1] = 1;
1119a747e4fSDavid du Colombier cmd[4] = 3;
1129a747e4fSDavid du Colombier return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
1139a747e4fSDavid du Colombier }
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier static Msf
rdmsf(uchar * p)1169a747e4fSDavid du Colombier rdmsf(uchar *p)
1179a747e4fSDavid du Colombier {
1189a747e4fSDavid du Colombier Msf msf;
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier msf.m = p[0];
1219a747e4fSDavid du Colombier msf.s = p[1];
1229a747e4fSDavid du Colombier msf.f = p[2];
1239a747e4fSDavid du Colombier return msf;
1249a747e4fSDavid du Colombier }
1259a747e4fSDavid du Colombier
1269a747e4fSDavid du Colombier static ulong
rdlba(uchar * p)1279a747e4fSDavid du Colombier rdlba(uchar *p)
1289a747e4fSDavid du Colombier {
1299a747e4fSDavid du Colombier return (p[0]<<16) | (p[1]<<8) | p[2];
1309a747e4fSDavid du Colombier }
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier /* not a Drive, so that we don't accidentally touch Drive.toc */
1339a747e4fSDavid du Colombier int
gettoc(Scsi * s,Toc * t)1349a747e4fSDavid du Colombier gettoc(Scsi *s, Toc *t)
1359a747e4fSDavid du Colombier {
1369a747e4fSDavid du Colombier int i, n;
1379a747e4fSDavid du Colombier uchar cmd[12];
1389a747e4fSDavid du Colombier uchar resp[1024];
1399a747e4fSDavid du Colombier
1409a747e4fSDavid du Colombier Again:
1419a747e4fSDavid du Colombier memset(t, 0, sizeof(*t));
1429a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
1439a747e4fSDavid du Colombier cmd[0] = 0x43;
1449a747e4fSDavid du Colombier cmd[1] = 0x02;
1459a747e4fSDavid du Colombier cmd[7] = sizeof(resp)>>8;
1469a747e4fSDavid du Colombier cmd[8] = sizeof(resp);
1479a747e4fSDavid du Colombier
1489a747e4fSDavid du Colombier s->changetime = 1;
1499a747e4fSDavid du Colombier /* scsi sets nchange, changetime */
1509a747e4fSDavid du Colombier if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
1519a747e4fSDavid du Colombier return -1;
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier if(s->changetime == 0) {
1549a747e4fSDavid du Colombier t->ntrack = 0;
1559a747e4fSDavid du Colombier werrstr("no media");
1569a747e4fSDavid du Colombier return -1;
1579a747e4fSDavid du Colombier }
1589a747e4fSDavid du Colombier
1599a747e4fSDavid du Colombier if(t->nchange == s->nchange && t->changetime != 0)
1609a747e4fSDavid du Colombier return 0;
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier t->nchange = s->nchange;
1639a747e4fSDavid du Colombier t->changetime = s->changetime;
1649a747e4fSDavid du Colombier
1659a747e4fSDavid du Colombier if(t->ntrack > MTRACK)
1669a747e4fSDavid du Colombier t->ntrack = MTRACK;
1679a747e4fSDavid du Colombier
1689a747e4fSDavid du Colombier DPRINT(2, "%d %d\n", resp[3], resp[2]);
1699a747e4fSDavid du Colombier t->ntrack = resp[3]-resp[2]+1;
1709a747e4fSDavid du Colombier t->track0 = resp[2];
1719a747e4fSDavid du Colombier
1729a747e4fSDavid du Colombier n = ((resp[0]<<8) | resp[1])+2;
1739a747e4fSDavid du Colombier if(n < 4+8*(t->ntrack+1)) {
1749a747e4fSDavid du Colombier werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1));
1759a747e4fSDavid du Colombier return -1;
1769a747e4fSDavid du Colombier }
1779a747e4fSDavid du Colombier
1789a747e4fSDavid du Colombier for(i=0; i<=t->ntrack; i++) /* <=: track[ntrack] = end */
1799a747e4fSDavid du Colombier t->track[i].start = rdmsf(resp+4+i*8+5);
1809a747e4fSDavid du Colombier
1819a747e4fSDavid du Colombier for(i=0; i<t->ntrack; i++)
1829a747e4fSDavid du Colombier t->track[i].end = t->track[i+1].start;
1839a747e4fSDavid du Colombier
1849a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
1859a747e4fSDavid du Colombier cmd[0] = 0x43;
1869a747e4fSDavid du Colombier cmd[7] = sizeof(resp)>>8;
1879a747e4fSDavid du Colombier cmd[8] = sizeof(resp);
1889a747e4fSDavid du Colombier if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
1899a747e4fSDavid du Colombier return -1;
1909a747e4fSDavid du Colombier
1919a747e4fSDavid du Colombier if(s->changetime != t->changetime || s->nchange != t->nchange) {
192*3ff48bf5SDavid du Colombier fprint(2, "disk changed underfoot; repeating\n");
1939a747e4fSDavid du Colombier goto Again;
1949a747e4fSDavid du Colombier }
1959a747e4fSDavid du Colombier
1969a747e4fSDavid du Colombier n = ((resp[0]<<8) | resp[1])+2;
1979a747e4fSDavid du Colombier if(n < 4+8*(t->ntrack+1)) {
1989a747e4fSDavid du Colombier werrstr("bad read");
1999a747e4fSDavid du Colombier return -1;
2009a747e4fSDavid du Colombier }
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier for(i=0; i<=t->ntrack; i++)
2039a747e4fSDavid du Colombier t->track[i].bstart = rdlba(resp+4+i*8+5);
2049a747e4fSDavid du Colombier
2059a747e4fSDavid du Colombier for(i=0; i<t->ntrack; i++)
2069a747e4fSDavid du Colombier t->track[i].bend = t->track[i+1].bstart;
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier return 0;
2099a747e4fSDavid du Colombier }
2109a747e4fSDavid du Colombier
2119a747e4fSDavid du Colombier static void
dumptoc(Toc * t)2129a747e4fSDavid du Colombier dumptoc(Toc *t)
2139a747e4fSDavid du Colombier {
2149a747e4fSDavid du Colombier int i;
2159a747e4fSDavid du Colombier
216*3ff48bf5SDavid du Colombier fprint(1, "%d tracks\n", t->ntrack);
2179a747e4fSDavid du Colombier for(i=0; i<t->ntrack; i++)
2189a747e4fSDavid du Colombier print("%d. %M-%M (%lud-%lud)\n", i+1,
2199a747e4fSDavid du Colombier t->track[i].start, t->track[i].end,
2209a747e4fSDavid du Colombier t->track[i].bstart, t->track[i].bend);
2219a747e4fSDavid du Colombier }
2229a747e4fSDavid du Colombier
2239a747e4fSDavid du Colombier static void
ping(Drive * d)2249a747e4fSDavid du Colombier ping(Drive *d)
2259a747e4fSDavid du Colombier {
2269a747e4fSDavid du Colombier uchar cmd[12];
2279a747e4fSDavid du Colombier
2289a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
2299a747e4fSDavid du Colombier cmd[0] = 0x43;
2309a747e4fSDavid du Colombier scsi(d->scsi, cmd, sizeof(cmd), nil, 0, Snone);
2319a747e4fSDavid du Colombier }
2329a747e4fSDavid du Colombier
2339a747e4fSDavid du Colombier static int
playstatus(Drive * d,Cdstatus * stat)2349a747e4fSDavid du Colombier playstatus(Drive *d, Cdstatus *stat)
2359a747e4fSDavid du Colombier {
2369a747e4fSDavid du Colombier uchar cmd[12], resp[16];
2379a747e4fSDavid du Colombier
2389a747e4fSDavid du Colombier memset(cmd, 0, sizeof cmd);
2399a747e4fSDavid du Colombier cmd[0] = 0x42;
2409a747e4fSDavid du Colombier cmd[1] = 0x02;
2419a747e4fSDavid du Colombier cmd[2] = 0x40;
2429a747e4fSDavid du Colombier cmd[3] = 0x01;
2439a747e4fSDavid du Colombier cmd[7] = sizeof(resp)>>8;
2449a747e4fSDavid du Colombier cmd[8] = sizeof(resp);
2459a747e4fSDavid du Colombier if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0)
2469a747e4fSDavid du Colombier return -1;
2479a747e4fSDavid du Colombier
2489a747e4fSDavid du Colombier switch(resp[1]){
2499a747e4fSDavid du Colombier case 0x11:
2509a747e4fSDavid du Colombier stat->state = Splaying;
2519a747e4fSDavid du Colombier break;
2529a747e4fSDavid du Colombier case 0x12:
2539a747e4fSDavid du Colombier stat->state = Spaused;
2549a747e4fSDavid du Colombier break;
2559a747e4fSDavid du Colombier case 0x13:
2569a747e4fSDavid du Colombier stat->state = Scompleted;
2579a747e4fSDavid du Colombier break;
2589a747e4fSDavid du Colombier case 0x14:
2599a747e4fSDavid du Colombier stat->state = Serror;
2609a747e4fSDavid du Colombier break;
2619a747e4fSDavid du Colombier case 0x00: /* not supported */
2629a747e4fSDavid du Colombier case 0x15: /* no current status to return */
2639a747e4fSDavid du Colombier default:
2649a747e4fSDavid du Colombier stat->state = Sunknown;
2659a747e4fSDavid du Colombier break;
2669a747e4fSDavid du Colombier }
2679a747e4fSDavid du Colombier
2689a747e4fSDavid du Colombier stat->track = resp[6];
2699a747e4fSDavid du Colombier stat->index = resp[7];
2709a747e4fSDavid du Colombier stat->abs = rdmsf(resp+9);
2719a747e4fSDavid du Colombier stat->rel = rdmsf(resp+13);
2729a747e4fSDavid du Colombier return 0;
2739a747e4fSDavid du Colombier }
2749a747e4fSDavid du Colombier
2759a747e4fSDavid du Colombier void
cdstatusproc(void * v)2769a747e4fSDavid du Colombier cdstatusproc(void *v)
2779a747e4fSDavid du Colombier {
2789a747e4fSDavid du Colombier Drive *d;
2799a747e4fSDavid du Colombier Toc t;
2809a747e4fSDavid du Colombier Cdstatus s;
2819a747e4fSDavid du Colombier
2829a747e4fSDavid du Colombier t.changetime = ~0;
2839a747e4fSDavid du Colombier t.nchange = ~0;
2849a747e4fSDavid du Colombier
2859a747e4fSDavid du Colombier threadsetname("cdstatusproc");
2869a747e4fSDavid du Colombier d = v;
2879a747e4fSDavid du Colombier DPRINT(2, "cdstatus %d\n", getpid());
2889a747e4fSDavid du Colombier for(;;) {
2899a747e4fSDavid du Colombier ping(d);
2909a747e4fSDavid du Colombier //DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange);
2919a747e4fSDavid du Colombier if(playstatus(d, &s) == 0)
2929a747e4fSDavid du Colombier send(d->cstatus, &s);
2939a747e4fSDavid du Colombier if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) {
2949a747e4fSDavid du Colombier if(gettoc(d->scsi, &t) == 0) {
2959a747e4fSDavid du Colombier DPRINT(2, "sendtoc...\n");
2969a747e4fSDavid du Colombier if(debug) dumptoc(&t);
2979a747e4fSDavid du Colombier send(d->ctocdisp, &t);
2989a747e4fSDavid du Colombier } else
2999a747e4fSDavid du Colombier DPRINT(2, "error: %r\n");
3009a747e4fSDavid du Colombier }
3019a747e4fSDavid du Colombier sleep(1000);
3029a747e4fSDavid du Colombier }
3039a747e4fSDavid du Colombier }
304