xref: /plan9/sys/src/cmd/scuzz/scsireq.c (revision fd362a73ff89ae80075dd82c9aad2a3468f0f3c9)
1 #include <u.h>
2 #include <libc.h>
3 /*
4  * BUGS:
5  *	no luns
6  *	and incomplete in many other ways
7  */
8 #include <disk.h>
9 #include "scsireq.h"
10 
11 enum {
12 	Debug = 0,
13 };
14 
15 /*
16  * exabyte tape drives, at least old ones like the 8200 and 8505,
17  * are dumb: you have to read the exact block size on the tape,
18  * they don't take 10-byte SCSI commands, and various other fine points.
19  */
20 extern int exabyte, force6bytecmds;
21 
22 static int debug = Debug;
23 
24 long
SRready(ScsiReq * rp)25 SRready(ScsiReq *rp)
26 {
27 	uchar cmd[6];
28 
29 	memset(cmd, 0, sizeof cmd);
30 	rp->cmd.p = cmd;
31 	rp->cmd.count = sizeof cmd;
32 	rp->data.p = cmd;
33 	rp->data.count = 0;
34 	rp->data.write = 1;
35 	return SRrequest(rp);
36 }
37 
38 long
SRrewind(ScsiReq * rp)39 SRrewind(ScsiReq *rp)
40 {
41 	uchar cmd[6];
42 
43 	memset(cmd, 0, sizeof cmd);
44 	cmd[0] = ScmdRewind;
45 	rp->cmd.p = cmd;
46 	rp->cmd.count = sizeof cmd;
47 	rp->data.p = cmd;
48 	rp->data.count = 0;
49 	rp->data.write = 1;
50 	if(SRrequest(rp) >= 0){
51 		rp->offset = 0;
52 		return 0;
53 	}
54 	return -1;
55 }
56 
57 long
SRreqsense(ScsiReq * rp)58 SRreqsense(ScsiReq *rp)
59 {
60 	uchar cmd[6];
61 	ScsiReq req;
62 	long status;
63 
64 	if(rp->status == Status_SD){
65 		rp->status = STok;
66 		return 0;
67 	}
68 	memset(cmd, 0, sizeof cmd);
69 	cmd[0] = ScmdRsense;
70 	cmd[4] = sizeof(req.sense);
71 	memset(&req, 0, sizeof(req));
72 	if(rp->flags&Fusb)
73 		req.flags |= Fusb;
74 	req.fd = rp->fd;
75 	req.umsc = rp->umsc;
76 	req.cmd.p = cmd;
77 	req.cmd.count = sizeof cmd;
78 	req.data.p = rp->sense;
79 	req.data.count = sizeof(rp->sense);
80 	req.data.write = 0;
81 	status = SRrequest(&req);
82 	rp->status = req.status;
83 	return status;
84 }
85 
86 long
SRformat(ScsiReq * rp)87 SRformat(ScsiReq *rp)
88 {
89 	uchar cmd[6];
90 
91 	memset(cmd, 0, sizeof cmd);
92 	cmd[0] = ScmdFormat;
93 	rp->cmd.p = cmd;
94 	rp->cmd.count = sizeof cmd;
95 	rp->data.p = cmd;
96 	rp->data.count = 6;
97 	rp->data.write = 0;
98 	return SRrequest(rp);
99 }
100 
101 long
SRrblimits(ScsiReq * rp,uchar * list)102 SRrblimits(ScsiReq *rp, uchar *list)
103 {
104 	uchar cmd[6];
105 
106 	memset(cmd, 0, sizeof cmd);
107 	cmd[0] = ScmdRblimits;
108 	rp->cmd.p = cmd;
109 	rp->cmd.count = sizeof cmd;
110 	rp->data.p = list;
111 	rp->data.count = 6;
112 	rp->data.write = 0;
113 	return SRrequest(rp);
114 }
115 
116 static int
dirdevrw(ScsiReq * rp,uchar * cmd,long nbytes)117 dirdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
118 {
119 	long n;
120 
121 	n = nbytes / rp->lbsize;
122 	if(rp->offset <= Max24off && n <= 256 && (rp->flags & Frw10) == 0){
123 		PUTBE24(cmd+1, rp->offset);
124 		cmd[4] = n;
125 		cmd[5] = 0;
126 		return 6;
127 	}
128 	cmd[0] |= ScmdExtread;
129 	cmd[1] = 0;
130 	PUTBELONG(cmd+2, rp->offset);
131 	cmd[6] = 0;
132 	cmd[7] = n>>8;
133 	cmd[8] = n;
134 	cmd[9] = 0;
135 	return 10;
136 }
137 
138 static int
seqdevrw(ScsiReq * rp,uchar * cmd,long nbytes)139 seqdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
140 {
141 	long n;
142 
143 	/* don't set Cmd1sili; we want the ILI bit instead of a fatal error */
144 	cmd[1] = rp->flags&Fbfixed? Cmd1fixed: 0;
145 	n = nbytes / rp->lbsize;
146 	PUTBE24(cmd+2, n);
147 	cmd[5] = 0;
148 	return 6;
149 }
150 
151 long
SRread(ScsiReq * rp,void * buf,long nbytes)152 SRread(ScsiReq *rp, void *buf, long nbytes)
153 {
154 	uchar cmd[10];
155 	long n;
156 
157 	if((nbytes % rp->lbsize) || nbytes > maxiosize){
158 		if(debug)
159 			if (nbytes % rp->lbsize)
160 				fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
161 					nbytes, rp->lbsize);
162 			else
163 				fprint(2, "scuzz: i/o size %ld > %ld\n",
164 					nbytes, maxiosize);
165 		rp->status = Status_BADARG;
166 		return -1;
167 	}
168 
169 	/* set up scsi read cmd */
170 	cmd[0] = ScmdRead;
171 	if(rp->flags & Fseqdev)
172 		rp->cmd.count = seqdevrw(rp, cmd, nbytes);
173 	else
174 		rp->cmd.count = dirdevrw(rp, cmd, nbytes);
175 	rp->cmd.p = cmd;
176 	rp->data.p = buf;
177 	rp->data.count = nbytes;
178 	rp->data.write = 0;
179 
180 	/* issue it */
181 	n = SRrequest(rp);
182 	if(n != -1){			/* it worked? */
183 		rp->offset += n / rp->lbsize;
184 		return n;
185 	}
186 
187 	/* request failed; maybe we just read a short record? */
188 	if (exabyte) {
189 		fprint(2, "read error\n");
190 		rp->status = STcheck;
191 		return n;
192 	}
193 	if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid))
194 		return -1;
195 	/* compute # of bytes not read */
196 	n = GETBELONG(rp->sense+3) * rp->lbsize;
197 	if (debug)
198 		fprint(2,
199 	"SRread: request failed with sense data; sense byte count %ld\n",
200 			n);
201 	if(!(rp->flags & Fseqdev))
202 		return -1;
203 
204 	/* device is a tape or something similar */
205 	if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 ||
206 	    rp->sense[2] & Sd2ili && n > 0)
207 		rp->data.count = nbytes - n;
208 	else
209 		return -1;
210 	n = rp->data.count;
211 	if (!rp->readblock++ || debug)
212 		fprint(2, "SRread: tape data count %ld%s\n", n,
213 			(rp->sense[2] & Sd2ili? " with ILI": ""));
214 	rp->status = STok;
215 	rp->offset += n / rp->lbsize;
216 	return n;
217 }
218 
219 long
SRwrite(ScsiReq * rp,void * buf,long nbytes)220 SRwrite(ScsiReq *rp, void *buf, long nbytes)
221 {
222 	uchar cmd[10];
223 	long n;
224 
225 	if((nbytes % rp->lbsize) || nbytes > maxiosize){
226 		if(debug)
227 			if (nbytes % rp->lbsize)
228 				fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
229 					nbytes, rp->lbsize);
230 			else
231 				fprint(2, "scuzz: i/o size %ld > %ld\n",
232 					nbytes, maxiosize);
233 		rp->status = Status_BADARG;
234 		return -1;
235 	}
236 
237 	/* set up scsi write cmd */
238 	cmd[0] = ScmdWrite;
239 	if(rp->flags & Fseqdev)
240 		rp->cmd.count = seqdevrw(rp, cmd, nbytes);
241 	else
242 		rp->cmd.count = dirdevrw(rp, cmd, nbytes);
243 	rp->cmd.p = cmd;
244 	rp->data.p = buf;
245 	rp->data.count = nbytes;
246 	rp->data.write = 1;
247 
248 	/* issue it */
249 	if((n = SRrequest(rp)) == -1){
250 		if (exabyte) {
251 			fprint(2, "write error\n");
252 			rp->status = STcheck;
253 			return n;
254 		}
255 		if(rp->status != Status_SD || rp->sense[2] != Sd2eom)
256 			return -1;
257 		if(rp->sense[0] & Sd0valid){
258 			n -= GETBELONG(rp->sense+3) * rp->lbsize;
259 			rp->data.count = nbytes - n;
260 		}
261 		else
262 			rp->data.count = nbytes;
263 		n = rp->data.count;
264 	}
265 	rp->offset += n / rp->lbsize;
266 	return n;
267 }
268 
269 long
SRseek(ScsiReq * rp,long offset,int type)270 SRseek(ScsiReq *rp, long offset, int type)
271 {
272 	uchar cmd[10];
273 
274 	switch(type){
275 
276 	case 0:
277 		break;
278 
279 	case 1:
280 		offset += rp->offset;
281 		if(offset >= 0)
282 			break;
283 		/*FALLTHROUGH*/
284 
285 	default:
286 		if(debug)
287 			fprint(2, "scuzz: seek failed\n");
288 		rp->status = Status_BADARG;
289 		return -1;
290 	}
291 	memset(cmd, 0, sizeof cmd);
292 	if(offset <= Max24off && (rp->flags & Frw10) == 0){
293 		cmd[0] = ScmdSeek;
294 		PUTBE24(cmd+1, offset & Max24off);
295 		rp->cmd.count = 6;
296 	}else{
297 		cmd[0] = ScmdExtseek;
298 		PUTBELONG(cmd+2, offset);
299 		rp->cmd.count = 10;
300 	}
301 	rp->cmd.p = cmd;
302 	rp->data.p = cmd;
303 	rp->data.count = 0;
304 	rp->data.write = 1;
305 	SRrequest(rp);
306 	if(rp->status == STok)
307 		return rp->offset = offset;
308 	return -1;
309 }
310 
311 long
SRfilemark(ScsiReq * rp,ulong howmany)312 SRfilemark(ScsiReq *rp, ulong howmany)
313 {
314 	uchar cmd[6];
315 
316 	memset(cmd, 0, sizeof cmd);
317 	cmd[0] = ScmdFmark;
318 	PUTBE24(cmd+2, howmany);
319 	rp->cmd.p = cmd;
320 	rp->cmd.count = sizeof cmd;
321 	rp->data.p = cmd;
322 	rp->data.count = 0;
323 	rp->data.write = 1;
324 	return SRrequest(rp);
325 }
326 
327 long
SRspace(ScsiReq * rp,uchar code,long howmany)328 SRspace(ScsiReq *rp, uchar code, long howmany)
329 {
330 	uchar cmd[6];
331 
332 	memset(cmd, 0, sizeof cmd);
333 	cmd[0] = ScmdSpace;
334 	cmd[1] = code;
335 	PUTBE24(cmd+2, howmany);
336 	rp->cmd.p = cmd;
337 	rp->cmd.count = sizeof cmd;
338 	rp->data.p = cmd;
339 	rp->data.count = 0;
340 	rp->data.write = 1;
341 	/*
342 	 * what about rp->offset?
343 	 */
344 	return SRrequest(rp);
345 }
346 
347 long
SRinquiry(ScsiReq * rp)348 SRinquiry(ScsiReq *rp)
349 {
350 	uchar cmd[6];
351 
352 	memset(cmd, 0, sizeof cmd);
353 	cmd[0] = ScmdInq;
354 	cmd[4] = sizeof rp->inquiry;
355 	rp->cmd.p = cmd;
356 	rp->cmd.count = sizeof cmd;
357 	memset(rp->inquiry, 0, sizeof rp->inquiry);
358 	rp->data.p = rp->inquiry;
359 	rp->data.count = sizeof rp->inquiry;
360 	rp->data.write = 0;
361 	if(SRrequest(rp) >= 0){
362 		rp->flags |= Finqok;
363 		return 0;
364 	}
365 	rp->flags &= ~Finqok;
366 	return -1;
367 }
368 
369 long
SRmodeselect6(ScsiReq * rp,uchar * list,long nbytes)370 SRmodeselect6(ScsiReq *rp, uchar *list, long nbytes)
371 {
372 	uchar cmd[6];
373 
374 	memset(cmd, 0, sizeof cmd);
375 	cmd[0] = ScmdMselect6;
376 	if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
377 		cmd[1] = 0x10;
378 	cmd[4] = nbytes;
379 	rp->cmd.p = cmd;
380 	rp->cmd.count = sizeof cmd;
381 	rp->data.p = list;
382 	rp->data.count = nbytes;
383 	rp->data.write = 1;
384 	return SRrequest(rp);
385 }
386 
387 long
SRmodeselect10(ScsiReq * rp,uchar * list,long nbytes)388 SRmodeselect10(ScsiReq *rp, uchar *list, long nbytes)
389 {
390 	uchar cmd[10];
391 
392 	memset(cmd, 0, sizeof cmd);
393 	if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
394 		cmd[1] = 0x10;
395 	cmd[0] = ScmdMselect10;
396 	cmd[7] = nbytes>>8;
397 	cmd[8] = nbytes;
398 	rp->cmd.p = cmd;
399 	rp->cmd.count = sizeof cmd;
400 	rp->data.p = list;
401 	rp->data.count = nbytes;
402 	rp->data.write = 1;
403 	return SRrequest(rp);
404 }
405 
406 long
SRmodesense6(ScsiReq * rp,uchar page,uchar * list,long nbytes)407 SRmodesense6(ScsiReq *rp, uchar page, uchar *list, long nbytes)
408 {
409 	uchar cmd[6];
410 
411 	memset(cmd, 0, sizeof cmd);
412 	cmd[0] = ScmdMsense6;
413 	cmd[2] = page;
414 	cmd[4] = nbytes;
415 	rp->cmd.p = cmd;
416 	rp->cmd.count = sizeof cmd;
417 	rp->data.p = list;
418 	rp->data.count = nbytes;
419 	rp->data.write = 0;
420 	return SRrequest(rp);
421 }
422 
423 long
SRmodesense10(ScsiReq * rp,uchar page,uchar * list,long nbytes)424 SRmodesense10(ScsiReq *rp, uchar page, uchar *list, long nbytes)
425 {
426 	uchar cmd[10];
427 
428 	memset(cmd, 0, sizeof cmd);
429 	cmd[0] = ScmdMsense10;
430 	cmd[2] = page;
431 	cmd[7] = nbytes>>8;
432 	cmd[8] = nbytes;
433 	rp->cmd.p = cmd;
434 	rp->cmd.count = sizeof cmd;
435 	rp->data.p = list;
436 	rp->data.count = nbytes;
437 	rp->data.write = 0;
438 	return SRrequest(rp);
439 }
440 
441 long
SRstart(ScsiReq * rp,uchar code)442 SRstart(ScsiReq *rp, uchar code)
443 {
444 	uchar cmd[6];
445 
446 	memset(cmd, 0, sizeof cmd);
447 	cmd[0] = ScmdStart;
448 	cmd[4] = code;
449 	rp->cmd.p = cmd;
450 	rp->cmd.count = sizeof cmd;
451 	rp->data.p = cmd;
452 	rp->data.count = 0;
453 	rp->data.write = 1;
454 	return SRrequest(rp);
455 }
456 
457 long
SRrcapacity(ScsiReq * rp,uchar * data)458 SRrcapacity(ScsiReq *rp, uchar *data)
459 {
460 	uchar cmd[10];
461 
462 	memset(cmd, 0, sizeof cmd);
463 	cmd[0] = ScmdRcapacity;
464 	rp->cmd.p = cmd;
465 	rp->cmd.count = sizeof cmd;
466 	rp->data.p = data;
467 	rp->data.count = 8;
468 	rp->data.write = 0;
469 	return SRrequest(rp);
470 }
471 
472 static long
request(int fd,ScsiPtr * cmd,ScsiPtr * data,int * status)473 request(int fd, ScsiPtr *cmd, ScsiPtr *data, int *status)
474 {
475 	long n, r;
476 	char buf[16];
477 
478 	/* this was an experiment but it seems to be a good idea */
479 	*status = STok;
480 
481 	/* send SCSI command */
482 	if(write(fd, cmd->p, cmd->count) != cmd->count){
483 		fprint(2, "scsireq: write cmd: %r\n");
484 		*status = Status_SW;
485 		return -1;
486 	}
487 
488 	/* read or write actual data */
489 	werrstr("");
490 	if(data->write)
491 		n = write(fd, data->p, data->count);
492 	else {
493 		n = read(fd, data->p, data->count);
494 		if (n < 0)
495 			memset(data->p, 0, data->count);
496 		else if (n < data->count)
497 			memset(data->p + n, 0, data->count - n);
498 	}
499 	if (n != data->count && n <= 0) {
500 		if (debug)
501 			fprint(2,
502 	"request: tried to %s %ld bytes of data for cmd 0x%x but got %r\n",
503 				(data->write? "write": "read"),
504 				data->count, cmd->p[0]);
505 	} else if (n != data->count && (data->write || debug))
506 		fprint(2, "request: %s %ld of %ld bytes of actual data\n",
507 			(data->write? "wrote": "read"), n, data->count);
508 
509 	/* read status */
510 	buf[0] = '\0';
511 	r = read(fd, buf, sizeof buf-1);
512 	if(exabyte && r <= 0 || !exabyte && r < 0){
513 		fprint(2, "scsireq: read status: %r\n");
514 		*status = Status_SW;
515 		return -1;
516 	}
517 	if (r >= 0)
518 		buf[r] = '\0';
519 	*status = atoi(buf);
520 	if(n < 0 && (exabyte || *status != STcheck))
521 		fprint(2, "scsireq: status 0x%2.2uX: data transfer: %r\n",
522 			*status);
523 	return n;
524 }
525 
526 long
SRrequest(ScsiReq * rp)527 SRrequest(ScsiReq *rp)
528 {
529 	long n;
530 	int status;
531 
532 retry:
533 	if(rp->flags&Fusb)
534 		n = umsrequest(rp->umsc, &rp->cmd, &rp->data, &status);
535 	else
536 		n = request(rp->fd, &rp->cmd, &rp->data, &status);
537 	switch(rp->status = status){
538 
539 	case STok:
540 		rp->data.count = n;
541 		break;
542 
543 	case STcheck:
544 		if(rp->cmd.p[0] != ScmdRsense && SRreqsense(rp) != -1)
545 			rp->status = Status_SD;
546 		if (exabyte)
547 			fprint(2, "SRrequest: STcheck, returning -1\n");
548 		return -1;
549 
550 	case STbusy:
551 		sleep(1000);
552 		goto retry;
553 
554 	default:
555 		fprint(2, "status 0x%2.2uX\n", status);
556 		return -1;
557 	}
558 	return n;
559 }
560 
561 int
SRclose(ScsiReq * rp)562 SRclose(ScsiReq *rp)
563 {
564 	if((rp->flags & Fopen) == 0){
565 		if(debug)
566 			fprint(2, "scuzz: closing closed file\n");
567 		rp->status = Status_BADARG;
568 		return -1;
569 	}
570 	close(rp->fd);
571 	rp->flags = 0;
572 	return 0;
573 }
574 
575 uint
mkascq(ScsiReq * r)576 mkascq(ScsiReq *r)
577 {
578 	uchar *u;
579 
580 	u = r->sense;
581 	return u[2]<<16 | u[12]<<8 | u[13];
582 }
583 
584 static int
dirdevopen(ScsiReq * rp)585 dirdevopen(ScsiReq *rp)
586 {
587 	ulong blocks;
588 	uchar data[8];
589 
590 	if(SRstart(rp, 1) == -1)
591 		/*
592 		 * it's okay for removable media to say
593 		 * "check condition: medium not present".
594 		 * 3a is "medium not present".
595 		 */
596 		return rp->inquiry[1] & 0x80 && (mkascq(rp) >> 8) == 0x023a?
597 			0: -1;
598 	memset(data, 0, sizeof data);
599 	if(SRrcapacity(rp, data) == -1)
600 		return -1;
601 	rp->lbsize = GETBELONG(data+4);
602 	blocks =     GETBELONG(data);
603 	if(debug)
604 		fprint(2, "scuzz: dirdevopen: logical block size %lud, "
605 			"# blocks %lud\n", rp->lbsize, blocks);
606 	/* some newer dev's don't support 6-byte commands */
607 	if(blocks > Max24off && !force6bytecmds)
608 		rp->flags |= Frw10;
609 	return 0;
610 }
611 
612 static int
seqdevopen(ScsiReq * rp)613 seqdevopen(ScsiReq *rp)
614 {
615 	uchar mode[16], limits[6];
616 
617 	if(SRrblimits(rp, limits) == -1)
618 		return -1;
619 	if(limits[1] == 0 && limits[2] == limits[4] && limits[3] == limits[5]){
620 		rp->flags |= Fbfixed;
621 		rp->lbsize = limits[4]<<8 | limits[5];
622 		if(debug)
623 			fprint(2, "scuzz: seqdevopen: logical block size %lud\n",
624 				rp->lbsize);
625 		return 0;
626 	}
627 	/*
628 	 * On some older hardware the optional 10-byte
629 	 * modeselect command isn't implemented.
630 	 */
631 	if (force6bytecmds)
632 		rp->flags |= Fmode6;
633 	if(!(rp->flags & Fmode6)){
634 		/* try 10-byte command first */
635 		memset(mode, 0, sizeof mode);
636 		mode[3] = 0x10;		/* device-specific param. */
637 		mode[7] = 8;		/* block descriptor length */
638 		/*
639 		 * exabytes can't handle this, and
640 		 * modeselect(10) is optional.
641 		 */
642 		if(SRmodeselect10(rp, mode, sizeof mode) != -1){
643 			rp->lbsize = 1;
644 			return 0;	/* success */
645 		}
646 		/* can't do 10-byte commands, back off to 6-byte ones */
647 		rp->flags |= Fmode6;
648 	}
649 
650 	/* 6-byte command */
651 	memset(mode, 0, sizeof mode);
652 	mode[2] = 0x10;		/* device-specific param. */
653 	mode[3] = 8;		/* block descriptor length */
654 	/*
655 	 * bsd sez exabytes need this bit (NBE: no busy enable) in
656 	 * vendor-specific page (0), but so far we haven't needed it.
657 	mode[12] |= 8;
658 	 */
659 	if(SRmodeselect6(rp, mode, 4+8) == -1)
660 		return -1;
661 	rp->lbsize = 1;
662 	return 0;
663 }
664 
665 static int
wormdevopen(ScsiReq * rp)666 wormdevopen(ScsiReq *rp)
667 {
668 	long status;
669 	uchar list[MaxDirData];
670 
671 	if (SRstart(rp, 1) == -1 ||
672 	    (status = SRmodesense10(rp, Allmodepages, list, sizeof list)) == -1)
673 		return -1;
674 	/* nbytes = list[0]<<8 | list[1]; */
675 
676 	/* # of bytes of block descriptors of 8 bytes each; not even 1? */
677 	if((list[6]<<8 | list[7]) < 8)
678 		rp->lbsize = 2048;
679 	else
680 		/* last 3 bytes of block 0 descriptor */
681 		rp->lbsize = GETBE24(list+13);
682 	if(debug)
683 		fprint(2, "scuzz: wormdevopen: logical block size %lud\n",
684 			rp->lbsize);
685 	return status;
686 }
687 
688 int
SRopenraw(ScsiReq * rp,char * unit)689 SRopenraw(ScsiReq *rp, char *unit)
690 {
691 	char name[128];
692 
693 	if(rp->flags & Fopen){
694 		if(debug)
695 			fprint(2, "scuzz: opening open file\n");
696 		rp->status = Status_BADARG;
697 		return -1;
698 	}
699 	memset(rp, 0, sizeof *rp);
700 	rp->unit = unit;
701 
702 	sprint(name, "%s/raw", unit);
703 
704 	if((rp->fd = open(name, ORDWR)) == -1){
705 		rp->status = STtimeout;
706 		return -1;
707 	}
708 	rp->flags = Fopen;
709 	return 0;
710 }
711 
712 int
SRopen(ScsiReq * rp,char * unit)713 SRopen(ScsiReq *rp, char *unit)
714 {
715 	if(SRopenraw(rp, unit) == -1)
716 		return -1;
717 	SRready(rp);
718 	if(SRinquiry(rp) >= 0){
719 		switch(rp->inquiry[0]){
720 
721 		default:
722 			fprint(2, "unknown device type 0x%.2x\n", rp->inquiry[0]);
723 			rp->status = Status_SW;
724 			break;
725 
726 		case 0x00:	/* Direct access (disk) */
727 		case 0x05:	/* CD-ROM */
728 		case 0x07:	/* rewriteable MO */
729 			if(dirdevopen(rp) == -1)
730 				break;
731 			return 0;
732 
733 		case 0x01:	/* Sequential eg: tape */
734 			rp->flags |= Fseqdev;
735 			if(seqdevopen(rp) == -1)
736 				break;
737 			return 0;
738 
739 		case 0x02:	/* Printer */
740 			rp->flags |= Fprintdev;
741 			return 0;
742 
743 		case 0x04:	/* Worm */
744 			rp->flags |= Fwormdev;
745 			if(wormdevopen(rp) == -1)
746 				break;
747 			return 0;
748 
749 		case 0x08:	/* medium-changer */
750 			rp->flags |= Fchanger;
751 			return 0;
752 		}
753 	}
754 	SRclose(rp);
755 	return -1;
756 }
757