Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/acme/bin/source/acd/mmc.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "acd.h"
2
 
3
int
4
msfconv(Fmt *fp)
5
{
6
	Msf m;
7
 
8
	m = va_arg(fp->args, Msf);
9
	fmtprint(fp, "%d.%d.%d", m.m, m.s, m.f);
10
	return 0;
11
}
12
 
13
static int
14
status(Drive *d)
15
{
16
	uchar cmd[12];
17
 
18
	memset(cmd, 0, sizeof cmd);
19
	cmd[0] = 0xBD;
20
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
21
}
22
 
23
static int
24
playmsf(Drive *d, Msf start, Msf end)
25
{
26
	uchar cmd[12];
27
 
28
	memset(cmd, 0, sizeof cmd);
29
	cmd[0] = 0x47;
30
	cmd[3] = start.m;
31
	cmd[4] = start.s;
32
	cmd[5] = start.f;
33
	cmd[6] = end.m;
34
	cmd[7] = end.s;
35
	cmd[8] = end.f;
36
 
37
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
38
}
39
 
40
int
41
playtrack(Drive *d, int start, int end)
42
{
43
	Toc *t;
44
 
45
	t = &d->toc;
46
 
47
	if(t->ntrack == 0)
48
		return -1;
49
 
50
	if(start < 0)
51
		start = 0;
52
	if(end >= t->ntrack)
53
		end = t->ntrack-1;
54
	if(end < start)
55
		end = start;
56
 
57
	return playmsf(d, t->track[start].start, t->track[end].end);
58
}
59
 
60
int
61
resume(Drive *d)
62
{
63
	uchar cmd[12];
64
 
65
	memset(cmd, 0, sizeof cmd);
66
	cmd[0] = 0x4B;
67
	cmd[8] = 0x01;
68
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
69
}
70
 
71
int
72
pause(Drive *d)
73
{
74
	uchar cmd[12];
75
 
76
	memset(cmd, 0, sizeof cmd);
77
	cmd[0] = 0x4B;
78
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
79
}
80
 
81
int
82
stop(Drive *d)
83
{
84
	uchar cmd[12];
85
 
86
	memset(cmd, 0, sizeof cmd);
87
	cmd[0] = 0x4E;
88
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
89
}
90
 
91
int
92
eject(Drive *d)
93
{
94
	uchar cmd[12];
95
 
96
	memset(cmd, 0, sizeof cmd);
97
	cmd[0] = 0x1B;
98
	cmd[1] = 1;
99
	cmd[4] = 2;
100
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
101
}
102
 
103
int
104
ingest(Drive *d)
105
{
106
	uchar cmd[12];
107
 
108
	memset(cmd, 0, sizeof cmd);
109
	cmd[0] = 0x1B;
110
	cmd[1] = 1;
111
	cmd[4] = 3;
112
	return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
113
}
114
 
115
static Msf
116
rdmsf(uchar *p)
117
{
118
	Msf msf;
119
 
120
	msf.m = p[0];
121
	msf.s = p[1];
122
	msf.f = p[2];
123
	return msf;
124
}
125
 
126
static ulong
127
rdlba(uchar *p)
128
{
129
	return (p[0]<<16) | (p[1]<<8) | p[2];
130
}
131
 
132
/* not a Drive, so that we don't accidentally touch Drive.toc */
133
int
134
gettoc(Scsi *s, Toc *t)
135
{
136
	int i, n;
137
	uchar cmd[12];
138
	uchar resp[1024];
139
 
140
Again:
141
	memset(t, 0, sizeof(*t));
142
	memset(cmd, 0, sizeof cmd);
143
	cmd[0] = 0x43;
144
	cmd[1] = 0x02;
145
	cmd[7] = sizeof(resp)>>8;
146
	cmd[8] = sizeof(resp);
147
 
148
	s->changetime = 1;
149
	/* scsi sets nchange, changetime */
150
	if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
151
		return -1;
152
 
153
	if(s->changetime == 0) {
154
		t->ntrack = 0;
155
		werrstr("no media");
156
		return -1;
157
	}
158
 
159
	if(t->nchange == s->nchange && t->changetime != 0)
160
		return 0;
161
 
162
	t->nchange = s->nchange;
163
	t->changetime = s->changetime;
164
 
165
	if(t->ntrack > MTRACK)
166
		t->ntrack = MTRACK;
167
 
168
DPRINT(2, "%d %d\n", resp[3], resp[2]);
169
	t->ntrack = resp[3]-resp[2]+1;
170
	t->track0 = resp[2];
171
 
172
	n = ((resp[0]<<8) | resp[1])+2;
173
	if(n < 4+8*(t->ntrack+1)) {
174
		werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1));
175
		return -1;
176
	}
177
 
178
	for(i=0; i<=t->ntrack; i++)		/* <=: track[ntrack] = end */
179
		t->track[i].start = rdmsf(resp+4+i*8+5);
180
 
181
	for(i=0; i<t->ntrack; i++)
182
		t->track[i].end = t->track[i+1].start;
183
 
184
	memset(cmd, 0, sizeof cmd);
185
	cmd[0] = 0x43;
186
	cmd[7] = sizeof(resp)>>8;
187
	cmd[8] = sizeof(resp);
188
	if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
189
		return -1;
190
 
191
	if(s->changetime != t->changetime || s->nchange != t->nchange) {
192
		fprint(2, "disk changed underfoot; repeating\n");
193
		goto Again;
194
	}
195
 
196
	n = ((resp[0]<<8) | resp[1])+2;
197
	if(n < 4+8*(t->ntrack+1)) {
198
		werrstr("bad read");
199
		return -1;
200
	}
201
 
202
	for(i=0; i<=t->ntrack; i++)
203
		t->track[i].bstart = rdlba(resp+4+i*8+5);
204
 
205
	for(i=0; i<t->ntrack; i++)
206
		t->track[i].bend = t->track[i+1].bstart;
207
 
208
	return 0;
209
}
210
 
211
static void
212
dumptoc(Toc *t)
213
{
214
	int i;
215
 
216
	fprint(1, "%d tracks\n", t->ntrack);
217
	for(i=0; i<t->ntrack; i++)
218
		print("%d. %M-%M (%lud-%lud)\n", i+1,
219
			t->track[i].start, t->track[i].end,
220
			t->track[i].bstart, t->track[i].bend);
221
}
222
 
223
static void
224
ping(Drive *d)
225
{
226
	uchar cmd[12];
227
 
228
	memset(cmd, 0, sizeof cmd);
229
	cmd[0] = 0x43;
230
	scsi(d->scsi, cmd, sizeof(cmd), nil, 0, Snone);
231
}
232
 
233
static int
234
playstatus(Drive *d, Cdstatus *stat)
235
{
236
	uchar cmd[12], resp[16];
237
 
238
	memset(cmd, 0, sizeof cmd);
239
	cmd[0] = 0x42;
240
	cmd[1] = 0x02;
241
	cmd[2] = 0x40;
242
	cmd[3] = 0x01;
243
	cmd[7] = sizeof(resp)>>8;
244
	cmd[8] = sizeof(resp);
245
	if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0)
246
		return -1;
247
 
248
	switch(resp[1]){
249
	case 0x11:
250
		stat->state = Splaying;
251
		break;
252
	case 0x12:
253
		stat->state = Spaused;
254
		break;
255
	case 0x13:
256
		stat->state = Scompleted;
257
		break;
258
	case 0x14:
259
		stat->state = Serror;
260
		break;
261
	case 0x00:	/* not supported */
262
	case 0x15:	/* no current status to return */
263
	default:
264
		stat->state = Sunknown;
265
		break;
266
	}
267
 
268
	stat->track = resp[6];
269
	stat->index = resp[7];
270
	stat->abs = rdmsf(resp+9);
271
	stat->rel = rdmsf(resp+13);
272
	return 0;
273
}
274
 
275
void
276
cdstatusproc(void *v)
277
{
278
	Drive *d;
279
	Toc t;
280
	Cdstatus s;
281
 
282
	t.changetime = ~0;
283
	t.nchange = ~0;
284
 
285
	threadsetname("cdstatusproc");
286
	d = v;
287
	DPRINT(2, "cdstatus %d\n", getpid());
288
	for(;;) {
289
		ping(d);
290
	//DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange);
291
		if(playstatus(d, &s) == 0)
292
			send(d->cstatus, &s);
293
		if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) {
294
			if(gettoc(d->scsi, &t) == 0) {
295
				DPRINT(2, "sendtoc...\n");
296
				if(debug) dumptoc(&t);
297
				send(d->ctocdisp, &t);
298
			} else
299
				DPRINT(2, "error: %r\n");
300
		}
301
		sleep(1000);
302
	}
303
}