1c285aa13SDavid du Colombier #include "u.h"
2c285aa13SDavid du Colombier #include "../port/lib.h"
3c285aa13SDavid du Colombier #include "mem.h"
4c285aa13SDavid du Colombier #include "dat.h"
5c285aa13SDavid du Colombier #include "fns.h"
6c285aa13SDavid du Colombier #include "io.h"
7c285aa13SDavid du Colombier #include "ureg.h"
8c285aa13SDavid du Colombier #include "../port/error.h"
9c285aa13SDavid du Colombier
10c285aa13SDavid du Colombier #include "../port/sd.h"
11c285aa13SDavid du Colombier
12c285aa13SDavid du Colombier static int
scsitest(SDreq * r)13c285aa13SDavid du Colombier scsitest(SDreq* r)
14c285aa13SDavid du Colombier {
15c285aa13SDavid du Colombier r->write = 0;
16c285aa13SDavid du Colombier memset(r->cmd, 0, sizeof(r->cmd));
17c285aa13SDavid du Colombier r->cmd[1] = r->lun<<5;
18c285aa13SDavid du Colombier r->clen = 6;
19c285aa13SDavid du Colombier r->data = nil;
20c285aa13SDavid du Colombier r->dlen = 0;
21c285aa13SDavid du Colombier r->flags = 0;
22c285aa13SDavid du Colombier
23c285aa13SDavid du Colombier r->status = ~0;
24c285aa13SDavid du Colombier
25c285aa13SDavid du Colombier return r->unit->dev->ifc->rio(r);
26c285aa13SDavid du Colombier }
27c285aa13SDavid du Colombier
28c285aa13SDavid du Colombier int
scsiverify(SDunit * unit)29c285aa13SDavid du Colombier scsiverify(SDunit* unit)
30c285aa13SDavid du Colombier {
31c285aa13SDavid du Colombier SDreq *r;
32c285aa13SDavid du Colombier int i, status;
33c285aa13SDavid du Colombier uchar *inquiry;
34c285aa13SDavid du Colombier
35c285aa13SDavid du Colombier if((r = malloc(sizeof(SDreq))) == nil)
36c285aa13SDavid du Colombier return 0;
37c285aa13SDavid du Colombier if((inquiry = sdmalloc(sizeof(unit->inquiry))) == nil){
38c285aa13SDavid du Colombier free(r);
39c285aa13SDavid du Colombier return 0;
40c285aa13SDavid du Colombier }
41c285aa13SDavid du Colombier r->unit = unit;
42c285aa13SDavid du Colombier r->lun = 0; /* ??? */
43c285aa13SDavid du Colombier
44c285aa13SDavid du Colombier memset(unit->inquiry, 0, sizeof(unit->inquiry));
45c285aa13SDavid du Colombier r->write = 0;
46c285aa13SDavid du Colombier r->cmd[0] = 0x12;
47c285aa13SDavid du Colombier r->cmd[1] = r->lun<<5;
48c285aa13SDavid du Colombier r->cmd[4] = sizeof(unit->inquiry)-1;
49c285aa13SDavid du Colombier r->clen = 6;
50c285aa13SDavid du Colombier r->data = inquiry;
51c285aa13SDavid du Colombier r->dlen = sizeof(unit->inquiry)-1;
52c285aa13SDavid du Colombier r->flags = 0;
53c285aa13SDavid du Colombier
54c285aa13SDavid du Colombier r->status = ~0;
55c285aa13SDavid du Colombier if(unit->dev->ifc->rio(r) != SDok){
56c285aa13SDavid du Colombier free(r);
57c285aa13SDavid du Colombier return 0;
58c285aa13SDavid du Colombier }
59c285aa13SDavid du Colombier memmove(unit->inquiry, inquiry, r->dlen);
60c285aa13SDavid du Colombier free(inquiry);
61c285aa13SDavid du Colombier
62c285aa13SDavid du Colombier SET(status);
63c285aa13SDavid du Colombier for(i = 0; i < 3; i++){
64c285aa13SDavid du Colombier while((status = scsitest(r)) == SDbusy)
65c285aa13SDavid du Colombier ;
66c285aa13SDavid du Colombier if(status == SDok || status != SDcheck)
67c285aa13SDavid du Colombier break;
68c285aa13SDavid du Colombier if(!(r->flags & SDvalidsense))
69c285aa13SDavid du Colombier break;
70c285aa13SDavid du Colombier if((r->sense[2] & 0x0F) != 0x02)
71c285aa13SDavid du Colombier continue;
72c285aa13SDavid du Colombier
73c285aa13SDavid du Colombier /*
74c285aa13SDavid du Colombier * Unit is 'not ready'.
75c285aa13SDavid du Colombier * If it is in the process of becoming ready or needs
76c285aa13SDavid du Colombier * an initialising command, set status so it will be spun-up
77c285aa13SDavid du Colombier * below.
78c285aa13SDavid du Colombier * If there's no medium, that's OK too, but don't
79c285aa13SDavid du Colombier * try to spin it up.
80c285aa13SDavid du Colombier */
81c285aa13SDavid du Colombier if(r->sense[12] == 0x04){
82c285aa13SDavid du Colombier if(r->sense[13] == 0x02 || r->sense[13] == 0x01){
83c285aa13SDavid du Colombier status = SDok;
84c285aa13SDavid du Colombier break;
85c285aa13SDavid du Colombier }
86c285aa13SDavid du Colombier }
87c285aa13SDavid du Colombier if(r->sense[12] == 0x3A)
88c285aa13SDavid du Colombier break;
89c285aa13SDavid du Colombier }
90c285aa13SDavid du Colombier
91c285aa13SDavid du Colombier if(status == SDok){
92c285aa13SDavid du Colombier /*
93c285aa13SDavid du Colombier * Try to ensure a direct-access device is spinning.
94c285aa13SDavid du Colombier * Don't wait for completion, ignore the result.
95c285aa13SDavid du Colombier */
9627522402SDavid du Colombier if((unit->inquiry[0] & SDinq0periphtype) == SDperdisk){
97c285aa13SDavid du Colombier memset(r->cmd, 0, sizeof(r->cmd));
98c285aa13SDavid du Colombier r->write = 0;
99c285aa13SDavid du Colombier r->cmd[0] = 0x1B;
100c285aa13SDavid du Colombier r->cmd[1] = (r->lun<<5)|0x01;
101c285aa13SDavid du Colombier r->cmd[4] = 1;
102c285aa13SDavid du Colombier r->clen = 6;
103c285aa13SDavid du Colombier r->data = nil;
104c285aa13SDavid du Colombier r->dlen = 0;
105c285aa13SDavid du Colombier r->flags = 0;
106c285aa13SDavid du Colombier
107c285aa13SDavid du Colombier r->status = ~0;
108c285aa13SDavid du Colombier unit->dev->ifc->rio(r);
109c285aa13SDavid du Colombier }
110c285aa13SDavid du Colombier }
111c285aa13SDavid du Colombier free(r);
112c285aa13SDavid du Colombier
113c285aa13SDavid du Colombier if(status == SDok || status == SDcheck)
114c285aa13SDavid du Colombier return 1;
115c285aa13SDavid du Colombier return 0;
116c285aa13SDavid du Colombier }
117c285aa13SDavid du Colombier
118c285aa13SDavid du Colombier static int
scsirio(SDreq * r)119c285aa13SDavid du Colombier scsirio(SDreq* r)
120c285aa13SDavid du Colombier {
121c285aa13SDavid du Colombier /*
122c285aa13SDavid du Colombier * Perform an I/O request, returning
123c285aa13SDavid du Colombier * -1 failure
124c285aa13SDavid du Colombier * 0 ok
125c285aa13SDavid du Colombier * 1 no medium present
126c285aa13SDavid du Colombier * 2 retry
127c285aa13SDavid du Colombier * The contents of r may be altered so the
128c285aa13SDavid du Colombier * caller should re-initialise if necesary.
129c285aa13SDavid du Colombier */
130c285aa13SDavid du Colombier r->status = ~0;
131c285aa13SDavid du Colombier switch(r->unit->dev->ifc->rio(r)){
132c285aa13SDavid du Colombier default:
133c285aa13SDavid du Colombier break;
134c285aa13SDavid du Colombier case SDcheck:
135c285aa13SDavid du Colombier if(!(r->flags & SDvalidsense))
136c285aa13SDavid du Colombier break;
137c285aa13SDavid du Colombier switch(r->sense[2] & 0x0F){
138c285aa13SDavid du Colombier case 0x00: /* no sense */
139c285aa13SDavid du Colombier case 0x01: /* recovered error */
140c285aa13SDavid du Colombier return 2;
141c285aa13SDavid du Colombier case 0x06: /* check condition */
142c285aa13SDavid du Colombier /*
143c285aa13SDavid du Colombier * 0x28 - not ready to ready transition,
144c285aa13SDavid du Colombier * medium may have changed.
145c285aa13SDavid du Colombier * 0x29 - power on or some type of reset.
146c285aa13SDavid du Colombier */
147c285aa13SDavid du Colombier if(r->sense[12] == 0x28 && r->sense[13] == 0)
148c285aa13SDavid du Colombier return 2;
149c285aa13SDavid du Colombier if(r->sense[12] == 0x29)
150c285aa13SDavid du Colombier return 2;
151c285aa13SDavid du Colombier break;
152c285aa13SDavid du Colombier case 0x02: /* not ready */
153c285aa13SDavid du Colombier /*
154c285aa13SDavid du Colombier * If no medium present, bail out.
155c285aa13SDavid du Colombier * If unit is becoming ready, rather than not
156c285aa13SDavid du Colombier * not ready, wait a little then poke it again. */
157c285aa13SDavid du Colombier if(r->sense[12] == 0x3A)
158c285aa13SDavid du Colombier break;
159c285aa13SDavid du Colombier if(r->sense[12] != 0x04 || r->sense[13] != 0x01)
160c285aa13SDavid du Colombier break;
161c285aa13SDavid du Colombier
162c285aa13SDavid du Colombier while(waserror())
163c285aa13SDavid du Colombier ;
164c285aa13SDavid du Colombier tsleep(&up->sleep, return0, 0, 500);
165c285aa13SDavid du Colombier poperror();
166c285aa13SDavid du Colombier scsitest(r);
167c285aa13SDavid du Colombier return 2;
168c285aa13SDavid du Colombier default:
169c285aa13SDavid du Colombier break;
170c285aa13SDavid du Colombier }
171c285aa13SDavid du Colombier break;
172c285aa13SDavid du Colombier case SDok:
173c285aa13SDavid du Colombier return 0;
174c285aa13SDavid du Colombier }
175c285aa13SDavid du Colombier return -1;
176c285aa13SDavid du Colombier }
177c285aa13SDavid du Colombier
178c285aa13SDavid du Colombier int
scsionline(SDunit * unit)179c285aa13SDavid du Colombier scsionline(SDunit* unit)
180c285aa13SDavid du Colombier {
181c285aa13SDavid du Colombier SDreq *r;
182c285aa13SDavid du Colombier uchar *p;
183c285aa13SDavid du Colombier int ok, retries;
184c285aa13SDavid du Colombier
185c285aa13SDavid du Colombier if((r = malloc(sizeof(SDreq))) == nil)
186c285aa13SDavid du Colombier return 0;
187c285aa13SDavid du Colombier if((p = sdmalloc(8)) == nil){
188c285aa13SDavid du Colombier free(r);
189c285aa13SDavid du Colombier return 0;
190c285aa13SDavid du Colombier }
191c285aa13SDavid du Colombier
192c285aa13SDavid du Colombier ok = 0;
193c285aa13SDavid du Colombier
194c285aa13SDavid du Colombier r->unit = unit;
195c285aa13SDavid du Colombier r->lun = 0; /* ??? */
196c285aa13SDavid du Colombier for(retries = 0; retries < 10; retries++){
197c285aa13SDavid du Colombier /*
198c285aa13SDavid du Colombier * Read-capacity is mandatory for DA, WORM, CD-ROM and
199c285aa13SDavid du Colombier * MO. It may return 'not ready' if type DA is not
200c285aa13SDavid du Colombier * spun up, type MO or type CD-ROM are not loaded or just
201c285aa13SDavid du Colombier * plain slow getting their act together after a reset.
202c285aa13SDavid du Colombier */
203c285aa13SDavid du Colombier r->write = 0;
204c285aa13SDavid du Colombier memset(r->cmd, 0, sizeof(r->cmd));
205fef25afaSDavid du Colombier r->cmd[0] = ScmdRcapacity;
206c285aa13SDavid du Colombier r->cmd[1] = r->lun<<5;
207c285aa13SDavid du Colombier r->clen = 10;
208c285aa13SDavid du Colombier r->data = p;
209c285aa13SDavid du Colombier r->dlen = 8;
210c285aa13SDavid du Colombier r->flags = 0;
211c285aa13SDavid du Colombier
212c285aa13SDavid du Colombier r->status = ~0;
213c285aa13SDavid du Colombier switch(scsirio(r)){
214c285aa13SDavid du Colombier default:
215c285aa13SDavid du Colombier break;
216c285aa13SDavid du Colombier case 0:
217c285aa13SDavid du Colombier unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
218c285aa13SDavid du Colombier unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7];
219c285aa13SDavid du Colombier
220c285aa13SDavid du Colombier /*
221c285aa13SDavid du Colombier * Some ATAPI CD readers lie about the block size.
222c285aa13SDavid du Colombier * Since we don't read audio via this interface
223c285aa13SDavid du Colombier * it's okay to always fudge this.
224c285aa13SDavid du Colombier */
225c285aa13SDavid du Colombier if(unit->secsize == 2352)
226c285aa13SDavid du Colombier unit->secsize = 2048;
227c285aa13SDavid du Colombier /*
228c285aa13SDavid du Colombier * Devices with removable media may return 0 sectors
229c285aa13SDavid du Colombier * when they have empty media (e.g. sata dvd writers);
230c285aa13SDavid du Colombier * if so, keep the count zero.
231c285aa13SDavid du Colombier *
232c285aa13SDavid du Colombier * Read-capacity returns the LBA of the last sector,
233c285aa13SDavid du Colombier * therefore the number of sectors must be incremented.
234c285aa13SDavid du Colombier */
235c285aa13SDavid du Colombier if(unit->sectors != 0)
236c285aa13SDavid du Colombier unit->sectors++;
237c285aa13SDavid du Colombier ok = 1;
238c285aa13SDavid du Colombier break;
239c285aa13SDavid du Colombier case 1:
240c285aa13SDavid du Colombier ok = 1;
241c285aa13SDavid du Colombier break;
242c285aa13SDavid du Colombier case 2:
243c285aa13SDavid du Colombier continue;
244c285aa13SDavid du Colombier }
245c285aa13SDavid du Colombier break;
246c285aa13SDavid du Colombier }
247c285aa13SDavid du Colombier free(p);
248c285aa13SDavid du Colombier free(r);
249c285aa13SDavid du Colombier
250c285aa13SDavid du Colombier if(ok)
251c285aa13SDavid du Colombier return ok+retries;
252c285aa13SDavid du Colombier else
253c285aa13SDavid du Colombier return 0;
254c285aa13SDavid du Colombier }
255c285aa13SDavid du Colombier
256c285aa13SDavid du Colombier int
scsiexec(SDunit * unit,int write,uchar * cmd,int clen,void * data,int * dlen)257c285aa13SDavid du Colombier scsiexec(SDunit* unit, int write, uchar* cmd, int clen, void* data, int* dlen)
258c285aa13SDavid du Colombier {
259c285aa13SDavid du Colombier SDreq *r;
260c285aa13SDavid du Colombier int status;
261c285aa13SDavid du Colombier
262c285aa13SDavid du Colombier if((r = malloc(sizeof(SDreq))) == nil)
263c285aa13SDavid du Colombier return SDmalloc;
264c285aa13SDavid du Colombier r->unit = unit;
265c285aa13SDavid du Colombier r->lun = cmd[1]>>5; /* ??? */
266c285aa13SDavid du Colombier r->write = write;
267c285aa13SDavid du Colombier memmove(r->cmd, cmd, clen);
268c285aa13SDavid du Colombier r->clen = clen;
269c285aa13SDavid du Colombier r->data = data;
270c285aa13SDavid du Colombier if(dlen)
271c285aa13SDavid du Colombier r->dlen = *dlen;
272c285aa13SDavid du Colombier r->flags = 0;
273c285aa13SDavid du Colombier
274c285aa13SDavid du Colombier r->status = ~0;
275c285aa13SDavid du Colombier
276c285aa13SDavid du Colombier /*
277c285aa13SDavid du Colombier * Call the device-specific I/O routine.
278c285aa13SDavid du Colombier * There should be no calls to 'error()' below this
279c285aa13SDavid du Colombier * which percolate back up.
280c285aa13SDavid du Colombier */
281c285aa13SDavid du Colombier switch(status = unit->dev->ifc->rio(r)){
282c285aa13SDavid du Colombier case SDok:
283c285aa13SDavid du Colombier if(dlen)
284c285aa13SDavid du Colombier *dlen = r->rlen;
285c285aa13SDavid du Colombier /*FALLTHROUGH*/
286c285aa13SDavid du Colombier case SDcheck:
287c285aa13SDavid du Colombier /*FALLTHROUGH*/
288c285aa13SDavid du Colombier default:
289c285aa13SDavid du Colombier /*
290c285aa13SDavid du Colombier * It's more complicated than this. There are conditions
291c285aa13SDavid du Colombier * which are 'ok' but for which the returned status code
292c285aa13SDavid du Colombier * is not 'SDok'.
293c285aa13SDavid du Colombier * Also, not all conditions require a reqsense, might
294c285aa13SDavid du Colombier * need to do a reqsense here and make it available to the
295c285aa13SDavid du Colombier * caller somehow.
296c285aa13SDavid du Colombier *
297c285aa13SDavid du Colombier * Mañana.
298c285aa13SDavid du Colombier */
299c285aa13SDavid du Colombier break;
300c285aa13SDavid du Colombier }
301c285aa13SDavid du Colombier sdfree(r);
302c285aa13SDavid du Colombier
303c285aa13SDavid du Colombier return status;
304c285aa13SDavid du Colombier }
305c285aa13SDavid du Colombier
306*2a044a09SDavid du Colombier /* extract lba and count from scsi command block cmd of clen bytes */
307*2a044a09SDavid du Colombier void
scsilbacount(uchar * cmd,int clen,uvlong * lbap,ulong * countp)308*2a044a09SDavid du Colombier scsilbacount(uchar *cmd, int clen, uvlong *lbap, ulong *countp)
309*2a044a09SDavid du Colombier {
310*2a044a09SDavid du Colombier if (clen == 16) {
311*2a044a09SDavid du Colombier *lbap = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32 |
312*2a044a09SDavid du Colombier cmd[6]<<24 | cmd[7]<<16 | cmd[8]<<8 | cmd[9];
313*2a044a09SDavid du Colombier *countp = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13];
314*2a044a09SDavid du Colombier } else if (clen == 10) {
315*2a044a09SDavid du Colombier *lbap = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
316*2a044a09SDavid du Colombier *countp = cmd[7]<<8 | cmd[8];
317*2a044a09SDavid du Colombier } else
318*2a044a09SDavid du Colombier panic("scsilbacount: command len %d unexpected", clen);
319*2a044a09SDavid du Colombier }
320*2a044a09SDavid du Colombier
321c285aa13SDavid du Colombier static void
scsifmt10(SDreq * r,int write,int lun,ulong nb,uvlong bno)322c285aa13SDavid du Colombier scsifmt10(SDreq *r, int write, int lun, ulong nb, uvlong bno)
323c285aa13SDavid du Colombier {
324c285aa13SDavid du Colombier uchar *c;
325c285aa13SDavid du Colombier
326c285aa13SDavid du Colombier c = r->cmd;
327c285aa13SDavid du Colombier if(write == 0)
328fef25afaSDavid du Colombier c[0] = ScmdExtread;
329c285aa13SDavid du Colombier else
330fef25afaSDavid du Colombier c[0] = ScmdExtwrite;
331c285aa13SDavid du Colombier c[1] = lun<<5;
332c285aa13SDavid du Colombier c[2] = bno>>24;
333c285aa13SDavid du Colombier c[3] = bno>>16;
334c285aa13SDavid du Colombier c[4] = bno>>8;
335c285aa13SDavid du Colombier c[5] = bno;
336c285aa13SDavid du Colombier c[6] = 0;
337c285aa13SDavid du Colombier c[7] = nb>>8;
338c285aa13SDavid du Colombier c[8] = nb;
339c285aa13SDavid du Colombier c[9] = 0;
340c285aa13SDavid du Colombier
341c285aa13SDavid du Colombier r->clen = 10;
342c285aa13SDavid du Colombier }
343c285aa13SDavid du Colombier
344c285aa13SDavid du Colombier static void
scsifmt16(SDreq * r,int write,int lun,ulong nb,uvlong bno)345c285aa13SDavid du Colombier scsifmt16(SDreq *r, int write, int lun, ulong nb, uvlong bno)
346c285aa13SDavid du Colombier {
347c285aa13SDavid du Colombier uchar *c;
348c285aa13SDavid du Colombier
349c285aa13SDavid du Colombier c = r->cmd;
350c285aa13SDavid du Colombier if(write == 0)
351fef25afaSDavid du Colombier c[0] = ScmdRead16;
352c285aa13SDavid du Colombier else
353fef25afaSDavid du Colombier c[0] = ScmdWrite16;
354c285aa13SDavid du Colombier c[1] = lun<<5; /* so wrong */
355c285aa13SDavid du Colombier c[2] = bno>>56;
356c285aa13SDavid du Colombier c[3] = bno>>48;
357c285aa13SDavid du Colombier c[4] = bno>>40;
358c285aa13SDavid du Colombier c[5] = bno>>32;
359c285aa13SDavid du Colombier c[6] = bno>>24;
360c285aa13SDavid du Colombier c[7] = bno>>16;
361c285aa13SDavid du Colombier c[8] = bno>>8;
362c285aa13SDavid du Colombier c[9] = bno;
363c285aa13SDavid du Colombier c[10] = nb>>24;
364c285aa13SDavid du Colombier c[11] = nb>>16;
365c285aa13SDavid du Colombier c[12] = nb>>8;
366c285aa13SDavid du Colombier c[13] = nb;
367c285aa13SDavid du Colombier c[14] = 0;
368c285aa13SDavid du Colombier c[15] = 0;
369c285aa13SDavid du Colombier
370c285aa13SDavid du Colombier r->clen = 16;
371c285aa13SDavid du Colombier }
372c285aa13SDavid du Colombier
373c285aa13SDavid du Colombier long
scsibio(SDunit * unit,int lun,int write,void * data,long nb,uvlong bno)374c285aa13SDavid du Colombier scsibio(SDunit* unit, int lun, int write, void* data, long nb, uvlong bno)
375c285aa13SDavid du Colombier {
376c285aa13SDavid du Colombier SDreq *r;
377c285aa13SDavid du Colombier long rlen;
378c285aa13SDavid du Colombier
379c285aa13SDavid du Colombier if((r = malloc(sizeof(SDreq))) == nil)
380c285aa13SDavid du Colombier error(Enomem);
381c285aa13SDavid du Colombier r->unit = unit;
382c285aa13SDavid du Colombier r->lun = lun;
383c285aa13SDavid du Colombier again:
384c285aa13SDavid du Colombier r->write = write;
385c285aa13SDavid du Colombier if(bno >= (1ULL<<32))
386c285aa13SDavid du Colombier scsifmt16(r, write, lun, nb, bno);
387c285aa13SDavid du Colombier else
388c285aa13SDavid du Colombier scsifmt10(r, write, lun, nb, bno);
389c285aa13SDavid du Colombier r->data = data;
390c285aa13SDavid du Colombier r->dlen = nb*unit->secsize;
391c285aa13SDavid du Colombier r->flags = 0;
392c285aa13SDavid du Colombier
393c285aa13SDavid du Colombier r->status = ~0;
394c285aa13SDavid du Colombier switch(scsirio(r)){
395c285aa13SDavid du Colombier default:
396c285aa13SDavid du Colombier rlen = -1;
397c285aa13SDavid du Colombier break;
398c285aa13SDavid du Colombier case 0:
399c285aa13SDavid du Colombier rlen = r->rlen;
400c285aa13SDavid du Colombier break;
401c285aa13SDavid du Colombier case 2:
402c285aa13SDavid du Colombier rlen = -1;
403c285aa13SDavid du Colombier if(!(r->flags & SDvalidsense))
404c285aa13SDavid du Colombier break;
405c285aa13SDavid du Colombier switch(r->sense[2] & 0x0F){
406c285aa13SDavid du Colombier default:
407c285aa13SDavid du Colombier break;
408c285aa13SDavid du Colombier case 0x01: /* recovered error */
409c285aa13SDavid du Colombier print("%s: recovered error at sector %llud\n",
410c285aa13SDavid du Colombier unit->name, bno);
411c285aa13SDavid du Colombier rlen = r->rlen;
412c285aa13SDavid du Colombier break;
413c285aa13SDavid du Colombier case 0x06: /* check condition */
414c285aa13SDavid du Colombier /*
415c285aa13SDavid du Colombier * Check for a removeable media change.
416c285aa13SDavid du Colombier * If so, mark it by zapping the geometry info
417c285aa13SDavid du Colombier * to force an online request.
418c285aa13SDavid du Colombier */
419c285aa13SDavid du Colombier if(r->sense[12] != 0x28 || r->sense[13] != 0)
420c285aa13SDavid du Colombier break;
42127522402SDavid du Colombier if(unit->inquiry[1] & SDinq1removable)
422c285aa13SDavid du Colombier unit->sectors = 0;
423c285aa13SDavid du Colombier break;
424c285aa13SDavid du Colombier case 0x02: /* not ready */
425c285aa13SDavid du Colombier /*
426c285aa13SDavid du Colombier * If unit is becoming ready,
427c285aa13SDavid du Colombier * rather than not not ready, try again.
428c285aa13SDavid du Colombier */
429c285aa13SDavid du Colombier if(r->sense[12] == 0x04 && r->sense[13] == 0x01)
430c285aa13SDavid du Colombier goto again;
431c285aa13SDavid du Colombier break;
432c285aa13SDavid du Colombier }
433c285aa13SDavid du Colombier break;
434c285aa13SDavid du Colombier }
435c285aa13SDavid du Colombier free(r);
436c285aa13SDavid du Colombier
437c285aa13SDavid du Colombier return rlen;
438c285aa13SDavid du Colombier }
439c285aa13SDavid du Colombier
440