13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier /*
43e12c5d1SDavid du Colombier * BUGS:
53e12c5d1SDavid du Colombier * no luns
63e12c5d1SDavid du Colombier * and incomplete in many other ways
73e12c5d1SDavid du Colombier */
8*fd362a73SDavid du Colombier #include <disk.h>
93e12c5d1SDavid du Colombier #include "scsireq.h"
103e12c5d1SDavid du Colombier
11968130a0SDavid du Colombier enum {
12968130a0SDavid du Colombier Debug = 0,
13968130a0SDavid du Colombier };
14968130a0SDavid du Colombier
15968130a0SDavid du Colombier /*
16968130a0SDavid du Colombier * exabyte tape drives, at least old ones like the 8200 and 8505,
17968130a0SDavid du Colombier * are dumb: you have to read the exact block size on the tape,
18968130a0SDavid du Colombier * they don't take 10-byte SCSI commands, and various other fine points.
19968130a0SDavid du Colombier */
20968130a0SDavid du Colombier extern int exabyte, force6bytecmds;
21968130a0SDavid du Colombier
22968130a0SDavid du Colombier static int debug = Debug;
23968130a0SDavid du Colombier
243e12c5d1SDavid du Colombier long
SRready(ScsiReq * rp)253e12c5d1SDavid du Colombier SRready(ScsiReq *rp)
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier uchar cmd[6];
283e12c5d1SDavid du Colombier
29e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
303e12c5d1SDavid du Colombier rp->cmd.p = cmd;
31e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
323e12c5d1SDavid du Colombier rp->data.p = cmd;
333e12c5d1SDavid du Colombier rp->data.count = 0;
343e12c5d1SDavid du Colombier rp->data.write = 1;
353e12c5d1SDavid du Colombier return SRrequest(rp);
363e12c5d1SDavid du Colombier }
373e12c5d1SDavid du Colombier
383e12c5d1SDavid du Colombier long
SRrewind(ScsiReq * rp)393e12c5d1SDavid du Colombier SRrewind(ScsiReq *rp)
403e12c5d1SDavid du Colombier {
413e12c5d1SDavid du Colombier uchar cmd[6];
423e12c5d1SDavid du Colombier
43e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
443e12c5d1SDavid du Colombier cmd[0] = ScmdRewind;
453e12c5d1SDavid du Colombier rp->cmd.p = cmd;
46e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
473e12c5d1SDavid du Colombier rp->data.p = cmd;
483e12c5d1SDavid du Colombier rp->data.count = 0;
493e12c5d1SDavid du Colombier rp->data.write = 1;
503e12c5d1SDavid du Colombier if(SRrequest(rp) >= 0){
513e12c5d1SDavid du Colombier rp->offset = 0;
523e12c5d1SDavid du Colombier return 0;
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier return -1;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier
573e12c5d1SDavid du Colombier long
SRreqsense(ScsiReq * rp)583e12c5d1SDavid du Colombier SRreqsense(ScsiReq *rp)
593e12c5d1SDavid du Colombier {
603e12c5d1SDavid du Colombier uchar cmd[6];
613e12c5d1SDavid du Colombier ScsiReq req;
623e12c5d1SDavid du Colombier long status;
633e12c5d1SDavid du Colombier
643e12c5d1SDavid du Colombier if(rp->status == Status_SD){
657dd7cddfSDavid du Colombier rp->status = STok;
663e12c5d1SDavid du Colombier return 0;
673e12c5d1SDavid du Colombier }
68e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
693e12c5d1SDavid du Colombier cmd[0] = ScmdRsense;
703e12c5d1SDavid du Colombier cmd[4] = sizeof(req.sense);
713e12c5d1SDavid du Colombier memset(&req, 0, sizeof(req));
72e6dcbf51SDavid du Colombier if(rp->flags&Fusb)
73e6dcbf51SDavid du Colombier req.flags |= Fusb;
747dd7cddfSDavid du Colombier req.fd = rp->fd;
75e6dcbf51SDavid du Colombier req.umsc = rp->umsc;
763e12c5d1SDavid du Colombier req.cmd.p = cmd;
77e29d4813SDavid du Colombier req.cmd.count = sizeof cmd;
783e12c5d1SDavid du Colombier req.data.p = rp->sense;
793e12c5d1SDavid du Colombier req.data.count = sizeof(rp->sense);
803e12c5d1SDavid du Colombier req.data.write = 0;
813e12c5d1SDavid du Colombier status = SRrequest(&req);
823e12c5d1SDavid du Colombier rp->status = req.status;
833e12c5d1SDavid du Colombier return status;
843e12c5d1SDavid du Colombier }
853e12c5d1SDavid du Colombier
863e12c5d1SDavid du Colombier long
SRformat(ScsiReq * rp)873e12c5d1SDavid du Colombier SRformat(ScsiReq *rp)
883e12c5d1SDavid du Colombier {
893e12c5d1SDavid du Colombier uchar cmd[6];
903e12c5d1SDavid du Colombier
91e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
923e12c5d1SDavid du Colombier cmd[0] = ScmdFormat;
933e12c5d1SDavid du Colombier rp->cmd.p = cmd;
94e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
953e12c5d1SDavid du Colombier rp->data.p = cmd;
963e12c5d1SDavid du Colombier rp->data.count = 6;
973e12c5d1SDavid du Colombier rp->data.write = 0;
983e12c5d1SDavid du Colombier return SRrequest(rp);
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier
1013e12c5d1SDavid du Colombier long
SRrblimits(ScsiReq * rp,uchar * list)1023e12c5d1SDavid du Colombier SRrblimits(ScsiReq *rp, uchar *list)
1033e12c5d1SDavid du Colombier {
1043e12c5d1SDavid du Colombier uchar cmd[6];
1053e12c5d1SDavid du Colombier
106e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
1073e12c5d1SDavid du Colombier cmd[0] = ScmdRblimits;
1083e12c5d1SDavid du Colombier rp->cmd.p = cmd;
109e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
1103e12c5d1SDavid du Colombier rp->data.p = list;
1113e12c5d1SDavid du Colombier rp->data.count = 6;
1123e12c5d1SDavid du Colombier rp->data.write = 0;
1133e12c5d1SDavid du Colombier return SRrequest(rp);
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier
1167dd7cddfSDavid du Colombier static int
dirdevrw(ScsiReq * rp,uchar * cmd,long nbytes)1173e12c5d1SDavid du Colombier dirdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
1183e12c5d1SDavid du Colombier {
1193e12c5d1SDavid du Colombier long n;
1203e12c5d1SDavid du Colombier
1217dd7cddfSDavid du Colombier n = nbytes / rp->lbsize;
122e29d4813SDavid du Colombier if(rp->offset <= Max24off && n <= 256 && (rp->flags & Frw10) == 0){
123e29d4813SDavid du Colombier PUTBE24(cmd+1, rp->offset);
1247dd7cddfSDavid du Colombier cmd[4] = n;
1253e12c5d1SDavid du Colombier cmd[5] = 0;
1267dd7cddfSDavid du Colombier return 6;
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier cmd[0] |= ScmdExtread;
1297dd7cddfSDavid du Colombier cmd[1] = 0;
130e29d4813SDavid du Colombier PUTBELONG(cmd+2, rp->offset);
1317dd7cddfSDavid du Colombier cmd[6] = 0;
1327dd7cddfSDavid du Colombier cmd[7] = n>>8;
1337dd7cddfSDavid du Colombier cmd[8] = n;
1347dd7cddfSDavid du Colombier cmd[9] = 0;
1357dd7cddfSDavid du Colombier return 10;
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier
1387dd7cddfSDavid du Colombier static int
seqdevrw(ScsiReq * rp,uchar * cmd,long nbytes)1393e12c5d1SDavid du Colombier seqdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
1403e12c5d1SDavid du Colombier {
1413e12c5d1SDavid du Colombier long n;
1423e12c5d1SDavid du Colombier
143e29d4813SDavid du Colombier /* don't set Cmd1sili; we want the ILI bit instead of a fatal error */
144e29d4813SDavid du Colombier cmd[1] = rp->flags&Fbfixed? Cmd1fixed: 0;
1453e12c5d1SDavid du Colombier n = nbytes / rp->lbsize;
146e29d4813SDavid du Colombier PUTBE24(cmd+2, n);
1473e12c5d1SDavid du Colombier cmd[5] = 0;
1487dd7cddfSDavid du Colombier return 6;
1493e12c5d1SDavid du Colombier }
1503e12c5d1SDavid du Colombier
1513e12c5d1SDavid du Colombier long
SRread(ScsiReq * rp,void * buf,long nbytes)1523e12c5d1SDavid du Colombier SRread(ScsiReq *rp, void *buf, long nbytes)
1533e12c5d1SDavid du Colombier {
1547dd7cddfSDavid du Colombier uchar cmd[10];
1553e12c5d1SDavid du Colombier long n;
1563e12c5d1SDavid du Colombier
157968130a0SDavid du Colombier if((nbytes % rp->lbsize) || nbytes > maxiosize){
1587d7728c9SDavid du Colombier if(debug)
1597d7728c9SDavid du Colombier if (nbytes % rp->lbsize)
1607d7728c9SDavid du Colombier fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
1617d7728c9SDavid du Colombier nbytes, rp->lbsize);
1627d7728c9SDavid du Colombier else
1637d7728c9SDavid du Colombier fprint(2, "scuzz: i/o size %ld > %ld\n",
1647d7728c9SDavid du Colombier nbytes, maxiosize);
1653e12c5d1SDavid du Colombier rp->status = Status_BADARG;
1663e12c5d1SDavid du Colombier return -1;
1673e12c5d1SDavid du Colombier }
168e29d4813SDavid du Colombier
169e29d4813SDavid du Colombier /* set up scsi read cmd */
1703e12c5d1SDavid du Colombier cmd[0] = ScmdRead;
1713e12c5d1SDavid du Colombier if(rp->flags & Fseqdev)
1727dd7cddfSDavid du Colombier rp->cmd.count = seqdevrw(rp, cmd, nbytes);
1733e12c5d1SDavid du Colombier else
1747dd7cddfSDavid du Colombier rp->cmd.count = dirdevrw(rp, cmd, nbytes);
1753e12c5d1SDavid du Colombier rp->cmd.p = cmd;
1763e12c5d1SDavid du Colombier rp->data.p = buf;
1773e12c5d1SDavid du Colombier rp->data.count = nbytes;
1783e12c5d1SDavid du Colombier rp->data.write = 0;
179e29d4813SDavid du Colombier
180e29d4813SDavid du Colombier /* issue it */
181e29d4813SDavid du Colombier n = SRrequest(rp);
182e29d4813SDavid du Colombier if(n != -1){ /* it worked? */
183e29d4813SDavid du Colombier rp->offset += n / rp->lbsize;
184e29d4813SDavid du Colombier return n;
185e29d4813SDavid du Colombier }
186e29d4813SDavid du Colombier
187e29d4813SDavid du Colombier /* request failed; maybe we just read a short record? */
188968130a0SDavid du Colombier if (exabyte) {
189968130a0SDavid du Colombier fprint(2, "read error\n");
190968130a0SDavid du Colombier rp->status = STcheck;
191968130a0SDavid du Colombier return n;
192968130a0SDavid du Colombier }
193e29d4813SDavid du Colombier if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid))
1943e12c5d1SDavid du Colombier return -1;
195e29d4813SDavid du Colombier /* compute # of bytes not read */
196e29d4813SDavid du Colombier n = GETBELONG(rp->sense+3) * rp->lbsize;
197968130a0SDavid du Colombier if (debug)
198e29d4813SDavid du Colombier fprint(2,
199e29d4813SDavid du Colombier "SRread: request failed with sense data; sense byte count %ld\n",
200e29d4813SDavid du Colombier n);
20114414594SDavid du Colombier if(!(rp->flags & Fseqdev))
20214414594SDavid du Colombier return -1;
203e29d4813SDavid du Colombier
204e29d4813SDavid du Colombier /* device is a tape or something similar */
205e29d4813SDavid du Colombier if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 ||
206e29d4813SDavid du Colombier rp->sense[2] & Sd2ili && n > 0)
2073e12c5d1SDavid du Colombier rp->data.count = nbytes - n;
2083e12c5d1SDavid du Colombier else
2093e12c5d1SDavid du Colombier return -1;
2103e12c5d1SDavid du Colombier n = rp->data.count;
211e29d4813SDavid du Colombier if (!rp->readblock++ || debug)
212e29d4813SDavid du Colombier fprint(2, "SRread: tape data count %ld%s\n", n,
213e29d4813SDavid du Colombier (rp->sense[2] & Sd2ili? " with ILI": ""));
2147dd7cddfSDavid du Colombier rp->status = STok;
2153e12c5d1SDavid du Colombier rp->offset += n / rp->lbsize;
2163e12c5d1SDavid du Colombier return n;
2173e12c5d1SDavid du Colombier }
2183e12c5d1SDavid du Colombier
2193e12c5d1SDavid du Colombier long
SRwrite(ScsiReq * rp,void * buf,long nbytes)2203e12c5d1SDavid du Colombier SRwrite(ScsiReq *rp, void *buf, long nbytes)
2213e12c5d1SDavid du Colombier {
2227dd7cddfSDavid du Colombier uchar cmd[10];
2233e12c5d1SDavid du Colombier long n;
2243e12c5d1SDavid du Colombier
225968130a0SDavid du Colombier if((nbytes % rp->lbsize) || nbytes > maxiosize){
2267d7728c9SDavid du Colombier if(debug)
2277d7728c9SDavid du Colombier if (nbytes % rp->lbsize)
2287d7728c9SDavid du Colombier fprint(2, "scuzz: i/o size %ld %% %ld != 0\n",
2297d7728c9SDavid du Colombier nbytes, rp->lbsize);
2307d7728c9SDavid du Colombier else
2317d7728c9SDavid du Colombier fprint(2, "scuzz: i/o size %ld > %ld\n",
2327d7728c9SDavid du Colombier nbytes, maxiosize);
2333e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2343e12c5d1SDavid du Colombier return -1;
2353e12c5d1SDavid du Colombier }
236e29d4813SDavid du Colombier
237e29d4813SDavid du Colombier /* set up scsi write cmd */
2383e12c5d1SDavid du Colombier cmd[0] = ScmdWrite;
2393e12c5d1SDavid du Colombier if(rp->flags & Fseqdev)
2407dd7cddfSDavid du Colombier rp->cmd.count = seqdevrw(rp, cmd, nbytes);
2413e12c5d1SDavid du Colombier else
2427dd7cddfSDavid du Colombier rp->cmd.count = dirdevrw(rp, cmd, nbytes);
2433e12c5d1SDavid du Colombier rp->cmd.p = cmd;
2443e12c5d1SDavid du Colombier rp->data.p = buf;
2453e12c5d1SDavid du Colombier rp->data.count = nbytes;
2463e12c5d1SDavid du Colombier rp->data.write = 1;
247e29d4813SDavid du Colombier
248e29d4813SDavid du Colombier /* issue it */
2493e12c5d1SDavid du Colombier if((n = SRrequest(rp)) == -1){
250968130a0SDavid du Colombier if (exabyte) {
251968130a0SDavid du Colombier fprint(2, "write error\n");
252968130a0SDavid du Colombier rp->status = STcheck;
253968130a0SDavid du Colombier return n;
254968130a0SDavid du Colombier }
255e29d4813SDavid du Colombier if(rp->status != Status_SD || rp->sense[2] != Sd2eom)
2563e12c5d1SDavid du Colombier return -1;
257e29d4813SDavid du Colombier if(rp->sense[0] & Sd0valid){
258e29d4813SDavid du Colombier n -= GETBELONG(rp->sense+3) * rp->lbsize;
2593e12c5d1SDavid du Colombier rp->data.count = nbytes - n;
2603e12c5d1SDavid du Colombier }
2613e12c5d1SDavid du Colombier else
2623e12c5d1SDavid du Colombier rp->data.count = nbytes;
2633e12c5d1SDavid du Colombier n = rp->data.count;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier rp->offset += n / rp->lbsize;
2663e12c5d1SDavid du Colombier return n;
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier
2693e12c5d1SDavid du Colombier long
SRseek(ScsiReq * rp,long offset,int type)2703e12c5d1SDavid du Colombier SRseek(ScsiReq *rp, long offset, int type)
2713e12c5d1SDavid du Colombier {
2727dd7cddfSDavid du Colombier uchar cmd[10];
2733e12c5d1SDavid du Colombier
2743e12c5d1SDavid du Colombier switch(type){
275e6dcbf51SDavid du Colombier
2763e12c5d1SDavid du Colombier case 0:
2773e12c5d1SDavid du Colombier break;
2783e12c5d1SDavid du Colombier
2793e12c5d1SDavid du Colombier case 1:
2803e12c5d1SDavid du Colombier offset += rp->offset;
2813e12c5d1SDavid du Colombier if(offset >= 0)
2823e12c5d1SDavid du Colombier break;
2833e12c5d1SDavid du Colombier /*FALLTHROUGH*/
284e6dcbf51SDavid du Colombier
2853e12c5d1SDavid du Colombier default:
2867d7728c9SDavid du Colombier if(debug)
2877d7728c9SDavid du Colombier fprint(2, "scuzz: seek failed\n");
2883e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2893e12c5d1SDavid du Colombier return -1;
2903e12c5d1SDavid du Colombier }
291e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
292e29d4813SDavid du Colombier if(offset <= Max24off && (rp->flags & Frw10) == 0){
2933e12c5d1SDavid du Colombier cmd[0] = ScmdSeek;
294e29d4813SDavid du Colombier PUTBE24(cmd+1, offset & Max24off);
2957dd7cddfSDavid du Colombier rp->cmd.count = 6;
2967dd7cddfSDavid du Colombier }else{
2977dd7cddfSDavid du Colombier cmd[0] = ScmdExtseek;
298e29d4813SDavid du Colombier PUTBELONG(cmd+2, offset);
2997dd7cddfSDavid du Colombier rp->cmd.count = 10;
3007dd7cddfSDavid du Colombier }
3013e12c5d1SDavid du Colombier rp->cmd.p = cmd;
3023e12c5d1SDavid du Colombier rp->data.p = cmd;
3033e12c5d1SDavid du Colombier rp->data.count = 0;
3043e12c5d1SDavid du Colombier rp->data.write = 1;
3053e12c5d1SDavid du Colombier SRrequest(rp);
3067dd7cddfSDavid du Colombier if(rp->status == STok)
3073e12c5d1SDavid du Colombier return rp->offset = offset;
3083e12c5d1SDavid du Colombier return -1;
3093e12c5d1SDavid du Colombier }
3103e12c5d1SDavid du Colombier
3113e12c5d1SDavid du Colombier long
SRfilemark(ScsiReq * rp,ulong howmany)3123e12c5d1SDavid du Colombier SRfilemark(ScsiReq *rp, ulong howmany)
3133e12c5d1SDavid du Colombier {
3143e12c5d1SDavid du Colombier uchar cmd[6];
3153e12c5d1SDavid du Colombier
316e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
3173e12c5d1SDavid du Colombier cmd[0] = ScmdFmark;
318e29d4813SDavid du Colombier PUTBE24(cmd+2, howmany);
3193e12c5d1SDavid du Colombier rp->cmd.p = cmd;
320e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
3213e12c5d1SDavid du Colombier rp->data.p = cmd;
3223e12c5d1SDavid du Colombier rp->data.count = 0;
3233e12c5d1SDavid du Colombier rp->data.write = 1;
3243e12c5d1SDavid du Colombier return SRrequest(rp);
3253e12c5d1SDavid du Colombier }
3263e12c5d1SDavid du Colombier
3273e12c5d1SDavid du Colombier long
SRspace(ScsiReq * rp,uchar code,long howmany)3283e12c5d1SDavid du Colombier SRspace(ScsiReq *rp, uchar code, long howmany)
3293e12c5d1SDavid du Colombier {
3303e12c5d1SDavid du Colombier uchar cmd[6];
3313e12c5d1SDavid du Colombier
332e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
3333e12c5d1SDavid du Colombier cmd[0] = ScmdSpace;
3343e12c5d1SDavid du Colombier cmd[1] = code;
335e29d4813SDavid du Colombier PUTBE24(cmd+2, howmany);
3363e12c5d1SDavid du Colombier rp->cmd.p = cmd;
337e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
3383e12c5d1SDavid du Colombier rp->data.p = cmd;
3393e12c5d1SDavid du Colombier rp->data.count = 0;
3403e12c5d1SDavid du Colombier rp->data.write = 1;
3413e12c5d1SDavid du Colombier /*
3423e12c5d1SDavid du Colombier * what about rp->offset?
3433e12c5d1SDavid du Colombier */
3443e12c5d1SDavid du Colombier return SRrequest(rp);
3453e12c5d1SDavid du Colombier }
3463e12c5d1SDavid du Colombier
3473e12c5d1SDavid du Colombier long
SRinquiry(ScsiReq * rp)3483e12c5d1SDavid du Colombier SRinquiry(ScsiReq *rp)
3493e12c5d1SDavid du Colombier {
3503e12c5d1SDavid du Colombier uchar cmd[6];
3513e12c5d1SDavid du Colombier
352e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
3533e12c5d1SDavid du Colombier cmd[0] = ScmdInq;
354e29d4813SDavid du Colombier cmd[4] = sizeof rp->inquiry;
3553e12c5d1SDavid du Colombier rp->cmd.p = cmd;
356e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
357e6dcbf51SDavid du Colombier memset(rp->inquiry, 0, sizeof rp->inquiry);
3583e12c5d1SDavid du Colombier rp->data.p = rp->inquiry;
359e29d4813SDavid du Colombier rp->data.count = sizeof rp->inquiry;
3603e12c5d1SDavid du Colombier rp->data.write = 0;
3617dd7cddfSDavid du Colombier if(SRrequest(rp) >= 0){
3627dd7cddfSDavid du Colombier rp->flags |= Finqok;
3637dd7cddfSDavid du Colombier return 0;
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier rp->flags &= ~Finqok;
3667dd7cddfSDavid du Colombier return -1;
3673e12c5d1SDavid du Colombier }
3683e12c5d1SDavid du Colombier
3693e12c5d1SDavid du Colombier long
SRmodeselect6(ScsiReq * rp,uchar * list,long nbytes)3707dd7cddfSDavid du Colombier SRmodeselect6(ScsiReq *rp, uchar *list, long nbytes)
3713e12c5d1SDavid du Colombier {
3723e12c5d1SDavid du Colombier uchar cmd[6];
3733e12c5d1SDavid du Colombier
374e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
3757dd7cddfSDavid du Colombier cmd[0] = ScmdMselect6;
3767dd7cddfSDavid du Colombier if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
3777dd7cddfSDavid du Colombier cmd[1] = 0x10;
3783e12c5d1SDavid du Colombier cmd[4] = nbytes;
3793e12c5d1SDavid du Colombier rp->cmd.p = cmd;
380e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
3813e12c5d1SDavid du Colombier rp->data.p = list;
3823e12c5d1SDavid du Colombier rp->data.count = nbytes;
3833e12c5d1SDavid du Colombier rp->data.write = 1;
3843e12c5d1SDavid du Colombier return SRrequest(rp);
3853e12c5d1SDavid du Colombier }
3863e12c5d1SDavid du Colombier
3873e12c5d1SDavid du Colombier long
SRmodeselect10(ScsiReq * rp,uchar * list,long nbytes)3887dd7cddfSDavid du Colombier SRmodeselect10(ScsiReq *rp, uchar *list, long nbytes)
3897dd7cddfSDavid du Colombier {
3907dd7cddfSDavid du Colombier uchar cmd[10];
3917dd7cddfSDavid du Colombier
392e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
3937dd7cddfSDavid du Colombier if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
3947dd7cddfSDavid du Colombier cmd[1] = 0x10;
3957dd7cddfSDavid du Colombier cmd[0] = ScmdMselect10;
3967dd7cddfSDavid du Colombier cmd[7] = nbytes>>8;
3977dd7cddfSDavid du Colombier cmd[8] = nbytes;
3987dd7cddfSDavid du Colombier rp->cmd.p = cmd;
399e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
4007dd7cddfSDavid du Colombier rp->data.p = list;
4017dd7cddfSDavid du Colombier rp->data.count = nbytes;
4027dd7cddfSDavid du Colombier rp->data.write = 1;
4037dd7cddfSDavid du Colombier return SRrequest(rp);
4047dd7cddfSDavid du Colombier }
4057dd7cddfSDavid du Colombier
4067dd7cddfSDavid du Colombier long
SRmodesense6(ScsiReq * rp,uchar page,uchar * list,long nbytes)4077dd7cddfSDavid du Colombier SRmodesense6(ScsiReq *rp, uchar page, uchar *list, long nbytes)
4083e12c5d1SDavid du Colombier {
4093e12c5d1SDavid du Colombier uchar cmd[6];
4103e12c5d1SDavid du Colombier
411e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
4127dd7cddfSDavid du Colombier cmd[0] = ScmdMsense6;
4133e12c5d1SDavid du Colombier cmd[2] = page;
4143e12c5d1SDavid du Colombier cmd[4] = nbytes;
4153e12c5d1SDavid du Colombier rp->cmd.p = cmd;
416e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
4173e12c5d1SDavid du Colombier rp->data.p = list;
4183e12c5d1SDavid du Colombier rp->data.count = nbytes;
4193e12c5d1SDavid du Colombier rp->data.write = 0;
4203e12c5d1SDavid du Colombier return SRrequest(rp);
4213e12c5d1SDavid du Colombier }
4223e12c5d1SDavid du Colombier
4233e12c5d1SDavid du Colombier long
SRmodesense10(ScsiReq * rp,uchar page,uchar * list,long nbytes)4247dd7cddfSDavid du Colombier SRmodesense10(ScsiReq *rp, uchar page, uchar *list, long nbytes)
4257dd7cddfSDavid du Colombier {
4267dd7cddfSDavid du Colombier uchar cmd[10];
4277dd7cddfSDavid du Colombier
428e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
4297dd7cddfSDavid du Colombier cmd[0] = ScmdMsense10;
4307dd7cddfSDavid du Colombier cmd[2] = page;
4317dd7cddfSDavid du Colombier cmd[7] = nbytes>>8;
4327dd7cddfSDavid du Colombier cmd[8] = nbytes;
4337dd7cddfSDavid du Colombier rp->cmd.p = cmd;
434e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
4357dd7cddfSDavid du Colombier rp->data.p = list;
4367dd7cddfSDavid du Colombier rp->data.count = nbytes;
4377dd7cddfSDavid du Colombier rp->data.write = 0;
4387dd7cddfSDavid du Colombier return SRrequest(rp);
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier long
SRstart(ScsiReq * rp,uchar code)4423e12c5d1SDavid du Colombier SRstart(ScsiReq *rp, uchar code)
4433e12c5d1SDavid du Colombier {
4443e12c5d1SDavid du Colombier uchar cmd[6];
4453e12c5d1SDavid du Colombier
446e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
4473e12c5d1SDavid du Colombier cmd[0] = ScmdStart;
4483e12c5d1SDavid du Colombier cmd[4] = code;
4493e12c5d1SDavid du Colombier rp->cmd.p = cmd;
450e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
4513e12c5d1SDavid du Colombier rp->data.p = cmd;
4523e12c5d1SDavid du Colombier rp->data.count = 0;
4533e12c5d1SDavid du Colombier rp->data.write = 1;
4543e12c5d1SDavid du Colombier return SRrequest(rp);
4553e12c5d1SDavid du Colombier }
4563e12c5d1SDavid du Colombier
4573e12c5d1SDavid du Colombier long
SRrcapacity(ScsiReq * rp,uchar * data)4583e12c5d1SDavid du Colombier SRrcapacity(ScsiReq *rp, uchar *data)
4593e12c5d1SDavid du Colombier {
460219b2ee8SDavid du Colombier uchar cmd[10];
4613e12c5d1SDavid du Colombier
462e29d4813SDavid du Colombier memset(cmd, 0, sizeof cmd);
4633e12c5d1SDavid du Colombier cmd[0] = ScmdRcapacity;
4643e12c5d1SDavid du Colombier rp->cmd.p = cmd;
465e29d4813SDavid du Colombier rp->cmd.count = sizeof cmd;
4663e12c5d1SDavid du Colombier rp->data.p = data;
4673e12c5d1SDavid du Colombier rp->data.count = 8;
4683e12c5d1SDavid du Colombier rp->data.write = 0;
4693e12c5d1SDavid du Colombier return SRrequest(rp);
4703e12c5d1SDavid du Colombier }
4713e12c5d1SDavid du Colombier
4723e12c5d1SDavid du Colombier static long
request(int fd,ScsiPtr * cmd,ScsiPtr * data,int * status)4737dd7cddfSDavid du Colombier request(int fd, ScsiPtr *cmd, ScsiPtr *data, int *status)
4743e12c5d1SDavid du Colombier {
475968130a0SDavid du Colombier long n, r;
4767dd7cddfSDavid du Colombier char buf[16];
4773e12c5d1SDavid du Colombier
478968130a0SDavid du Colombier /* this was an experiment but it seems to be a good idea */
479968130a0SDavid du Colombier *status = STok;
480968130a0SDavid du Colombier
481968130a0SDavid du Colombier /* send SCSI command */
4827dd7cddfSDavid du Colombier if(write(fd, cmd->p, cmd->count) != cmd->count){
4833e12c5d1SDavid du Colombier fprint(2, "scsireq: write cmd: %r\n");
4847dd7cddfSDavid du Colombier *status = Status_SW;
4853e12c5d1SDavid du Colombier return -1;
4863e12c5d1SDavid du Colombier }
487968130a0SDavid du Colombier
488968130a0SDavid du Colombier /* read or write actual data */
489e29d4813SDavid du Colombier werrstr("");
4903e12c5d1SDavid du Colombier if(data->write)
4917dd7cddfSDavid du Colombier n = write(fd, data->p, data->count);
492968130a0SDavid du Colombier else {
4937dd7cddfSDavid du Colombier n = read(fd, data->p, data->count);
494968130a0SDavid du Colombier if (n < 0)
495968130a0SDavid du Colombier memset(data->p, 0, data->count);
496968130a0SDavid du Colombier else if (n < data->count)
497968130a0SDavid du Colombier memset(data->p + n, 0, data->count - n);
498968130a0SDavid du Colombier }
499e29d4813SDavid du Colombier if (n != data->count && n <= 0) {
500e29d4813SDavid du Colombier if (debug)
501968130a0SDavid du Colombier fprint(2,
502968130a0SDavid du Colombier "request: tried to %s %ld bytes of data for cmd 0x%x but got %r\n",
503e29d4813SDavid du Colombier (data->write? "write": "read"),
504e29d4813SDavid du Colombier data->count, cmd->p[0]);
505e29d4813SDavid du Colombier } else if (n != data->count && (data->write || debug))
506968130a0SDavid du Colombier fprint(2, "request: %s %ld of %ld bytes of actual data\n",
507968130a0SDavid du Colombier (data->write? "wrote": "read"), n, data->count);
508968130a0SDavid du Colombier
509968130a0SDavid du Colombier /* read status */
510968130a0SDavid du Colombier buf[0] = '\0';
511968130a0SDavid du Colombier r = read(fd, buf, sizeof buf-1);
512968130a0SDavid du Colombier if(exabyte && r <= 0 || !exabyte && r < 0){
5133e12c5d1SDavid du Colombier fprint(2, "scsireq: read status: %r\n");
5147dd7cddfSDavid du Colombier *status = Status_SW;
5153e12c5d1SDavid du Colombier return -1;
5163e12c5d1SDavid du Colombier }
517968130a0SDavid du Colombier if (r >= 0)
518968130a0SDavid du Colombier buf[r] = '\0';
5197dd7cddfSDavid du Colombier *status = atoi(buf);
520968130a0SDavid du Colombier if(n < 0 && (exabyte || *status != STcheck))
521e29d4813SDavid du Colombier fprint(2, "scsireq: status 0x%2.2uX: data transfer: %r\n",
522e29d4813SDavid du Colombier *status);
5233e12c5d1SDavid du Colombier return n;
5243e12c5d1SDavid du Colombier }
5253e12c5d1SDavid du Colombier
5263e12c5d1SDavid du Colombier long
SRrequest(ScsiReq * rp)5273e12c5d1SDavid du Colombier SRrequest(ScsiReq *rp)
5283e12c5d1SDavid du Colombier {
5293e12c5d1SDavid du Colombier long n;
5307dd7cddfSDavid du Colombier int status;
5313e12c5d1SDavid du Colombier
5323e12c5d1SDavid du Colombier retry:
533e6dcbf51SDavid du Colombier if(rp->flags&Fusb)
534e6dcbf51SDavid du Colombier n = umsrequest(rp->umsc, &rp->cmd, &rp->data, &status);
535e6dcbf51SDavid du Colombier else
5367dd7cddfSDavid du Colombier n = request(rp->fd, &rp->cmd, &rp->data, &status);
5377dd7cddfSDavid du Colombier switch(rp->status = status){
5383e12c5d1SDavid du Colombier
5397dd7cddfSDavid du Colombier case STok:
5403e12c5d1SDavid du Colombier rp->data.count = n;
5413e12c5d1SDavid du Colombier break;
5423e12c5d1SDavid du Colombier
5437dd7cddfSDavid du Colombier case STcheck:
5443e12c5d1SDavid du Colombier if(rp->cmd.p[0] != ScmdRsense && SRreqsense(rp) != -1)
5453e12c5d1SDavid du Colombier rp->status = Status_SD;
546968130a0SDavid du Colombier if (exabyte)
547968130a0SDavid du Colombier fprint(2, "SRrequest: STcheck, returning -1\n");
5483e12c5d1SDavid du Colombier return -1;
5493e12c5d1SDavid du Colombier
5507dd7cddfSDavid du Colombier case STbusy:
5513e12c5d1SDavid du Colombier sleep(1000);
5523e12c5d1SDavid du Colombier goto retry;
5537dd7cddfSDavid du Colombier
5547dd7cddfSDavid du Colombier default:
5557dd7cddfSDavid du Colombier fprint(2, "status 0x%2.2uX\n", status);
5567dd7cddfSDavid du Colombier return -1;
5573e12c5d1SDavid du Colombier }
5583e12c5d1SDavid du Colombier return n;
5593e12c5d1SDavid du Colombier }
5603e12c5d1SDavid du Colombier
5613e12c5d1SDavid du Colombier int
SRclose(ScsiReq * rp)5623e12c5d1SDavid du Colombier SRclose(ScsiReq *rp)
5633e12c5d1SDavid du Colombier {
5643e12c5d1SDavid du Colombier if((rp->flags & Fopen) == 0){
5657d7728c9SDavid du Colombier if(debug)
5667d7728c9SDavid du Colombier fprint(2, "scuzz: closing closed file\n");
5673e12c5d1SDavid du Colombier rp->status = Status_BADARG;
5683e12c5d1SDavid du Colombier return -1;
5693e12c5d1SDavid du Colombier }
5707dd7cddfSDavid du Colombier close(rp->fd);
5713e12c5d1SDavid du Colombier rp->flags = 0;
5723e12c5d1SDavid du Colombier return 0;
5733e12c5d1SDavid du Colombier }
5743e12c5d1SDavid du Colombier
57543aadf5eSDavid du Colombier uint
mkascq(ScsiReq * r)57643aadf5eSDavid du Colombier mkascq(ScsiReq *r)
57743aadf5eSDavid du Colombier {
57843aadf5eSDavid du Colombier uchar *u;
57943aadf5eSDavid du Colombier
58043aadf5eSDavid du Colombier u = r->sense;
58143aadf5eSDavid du Colombier return u[2]<<16 | u[12]<<8 | u[13];
58243aadf5eSDavid du Colombier }
58343aadf5eSDavid du Colombier
5843e12c5d1SDavid du Colombier static int
dirdevopen(ScsiReq * rp)5853e12c5d1SDavid du Colombier dirdevopen(ScsiReq *rp)
5863e12c5d1SDavid du Colombier {
5873ff48bf5SDavid du Colombier ulong blocks;
5883e12c5d1SDavid du Colombier uchar data[8];
5893e12c5d1SDavid du Colombier
59043aadf5eSDavid du Colombier if(SRstart(rp, 1) == -1)
59143aadf5eSDavid du Colombier /*
59243aadf5eSDavid du Colombier * it's okay for removable media to say
59343aadf5eSDavid du Colombier * "check condition: medium not present".
59443aadf5eSDavid du Colombier * 3a is "medium not present".
59543aadf5eSDavid du Colombier */
59643aadf5eSDavid du Colombier return rp->inquiry[1] & 0x80 && (mkascq(rp) >> 8) == 0x023a?
59743aadf5eSDavid du Colombier 0: -1;
5987d7728c9SDavid du Colombier memset(data, 0, sizeof data);
5997d7728c9SDavid du Colombier if(SRrcapacity(rp, data) == -1)
6007d7728c9SDavid du Colombier return -1;
601e29d4813SDavid du Colombier rp->lbsize = GETBELONG(data+4);
602e29d4813SDavid du Colombier blocks = GETBELONG(data);
6037d7728c9SDavid du Colombier if(debug)
6047d7728c9SDavid du Colombier fprint(2, "scuzz: dirdevopen: logical block size %lud, "
6057d7728c9SDavid du Colombier "# blocks %lud\n", rp->lbsize, blocks);
606968130a0SDavid du Colombier /* some newer dev's don't support 6-byte commands */
607e29d4813SDavid du Colombier if(blocks > Max24off && !force6bytecmds)
608968130a0SDavid du Colombier rp->flags |= Frw10;
6093e12c5d1SDavid du Colombier return 0;
6103e12c5d1SDavid du Colombier }
6113e12c5d1SDavid du Colombier
6123e12c5d1SDavid du Colombier static int
seqdevopen(ScsiReq * rp)6133e12c5d1SDavid du Colombier seqdevopen(ScsiReq *rp)
6143e12c5d1SDavid du Colombier {
6157dd7cddfSDavid du Colombier uchar mode[16], limits[6];
6163e12c5d1SDavid du Colombier
6173e12c5d1SDavid du Colombier if(SRrblimits(rp, limits) == -1)
6183e12c5d1SDavid du Colombier return -1;
619e29d4813SDavid du Colombier if(limits[1] == 0 && limits[2] == limits[4] && limits[3] == limits[5]){
620e29d4813SDavid du Colombier rp->flags |= Fbfixed;
621e29d4813SDavid du Colombier rp->lbsize = limits[4]<<8 | limits[5];
6227d7728c9SDavid du Colombier if(debug)
6237d7728c9SDavid du Colombier fprint(2, "scuzz: seqdevopen: logical block size %lud\n",
6247d7728c9SDavid du Colombier rp->lbsize);
625e29d4813SDavid du Colombier return 0;
626e29d4813SDavid du Colombier }
62780ee5cbfSDavid du Colombier /*
62880ee5cbfSDavid du Colombier * On some older hardware the optional 10-byte
62980ee5cbfSDavid du Colombier * modeselect command isn't implemented.
63080ee5cbfSDavid du Colombier */
631968130a0SDavid du Colombier if (force6bytecmds)
632968130a0SDavid du Colombier rp->flags |= Fmode6;
63380ee5cbfSDavid du Colombier if(!(rp->flags & Fmode6)){
634968130a0SDavid du Colombier /* try 10-byte command first */
635e29d4813SDavid du Colombier memset(mode, 0, sizeof mode);
636968130a0SDavid du Colombier mode[3] = 0x10; /* device-specific param. */
637968130a0SDavid du Colombier mode[7] = 8; /* block descriptor length */
638968130a0SDavid du Colombier /*
639968130a0SDavid du Colombier * exabytes can't handle this, and
640968130a0SDavid du Colombier * modeselect(10) is optional.
641968130a0SDavid du Colombier */
642e29d4813SDavid du Colombier if(SRmodeselect10(rp, mode, sizeof mode) != -1){
64380ee5cbfSDavid du Colombier rp->lbsize = 1;
644968130a0SDavid du Colombier return 0; /* success */
64580ee5cbfSDavid du Colombier }
646968130a0SDavid du Colombier /* can't do 10-byte commands, back off to 6-byte ones */
64780ee5cbfSDavid du Colombier rp->flags |= Fmode6;
64880ee5cbfSDavid du Colombier }
64980ee5cbfSDavid du Colombier
650968130a0SDavid du Colombier /* 6-byte command */
651e29d4813SDavid du Colombier memset(mode, 0, sizeof mode);
652968130a0SDavid du Colombier mode[2] = 0x10; /* device-specific param. */
653968130a0SDavid du Colombier mode[3] = 8; /* block descriptor length */
654968130a0SDavid du Colombier /*
655e29d4813SDavid du Colombier * bsd sez exabytes need this bit (NBE: no busy enable) in
656e29d4813SDavid du Colombier * vendor-specific page (0), but so far we haven't needed it.
657968130a0SDavid du Colombier mode[12] |= 8;
658e29d4813SDavid du Colombier */
65980ee5cbfSDavid du Colombier if(SRmodeselect6(rp, mode, 4+8) == -1)
6603e12c5d1SDavid du Colombier return -1;
6613e12c5d1SDavid du Colombier rp->lbsize = 1;
6623e12c5d1SDavid du Colombier return 0;
6633e12c5d1SDavid du Colombier }
6643e12c5d1SDavid du Colombier
6653e12c5d1SDavid du Colombier static int
wormdevopen(ScsiReq * rp)6663e12c5d1SDavid du Colombier wormdevopen(ScsiReq *rp)
6673e12c5d1SDavid du Colombier {
668e6dcbf51SDavid du Colombier long status;
6693e12c5d1SDavid du Colombier uchar list[MaxDirData];
6703e12c5d1SDavid du Colombier
671e29d4813SDavid du Colombier if (SRstart(rp, 1) == -1 ||
672e29d4813SDavid du Colombier (status = SRmodesense10(rp, Allmodepages, list, sizeof list)) == -1)
6733e12c5d1SDavid du Colombier return -1;
674e29d4813SDavid du Colombier /* nbytes = list[0]<<8 | list[1]; */
675e29d4813SDavid du Colombier
676e6dcbf51SDavid du Colombier /* # of bytes of block descriptors of 8 bytes each; not even 1? */
677e6dcbf51SDavid du Colombier if((list[6]<<8 | list[7]) < 8)
6783e12c5d1SDavid du Colombier rp->lbsize = 2048;
6793e12c5d1SDavid du Colombier else
680e29d4813SDavid du Colombier /* last 3 bytes of block 0 descriptor */
681e29d4813SDavid du Colombier rp->lbsize = GETBE24(list+13);
6827d7728c9SDavid du Colombier if(debug)
6837d7728c9SDavid du Colombier fprint(2, "scuzz: wormdevopen: logical block size %lud\n",
6847d7728c9SDavid du Colombier rp->lbsize);
6853e12c5d1SDavid du Colombier return status;
6863e12c5d1SDavid du Colombier }
6873e12c5d1SDavid du Colombier
6883e12c5d1SDavid du Colombier int
SRopenraw(ScsiReq * rp,char * unit)6897dd7cddfSDavid du Colombier SRopenraw(ScsiReq *rp, char *unit)
6903e12c5d1SDavid du Colombier {
6917dd7cddfSDavid du Colombier char name[128];
6923e12c5d1SDavid du Colombier
6937dd7cddfSDavid du Colombier if(rp->flags & Fopen){
6947d7728c9SDavid du Colombier if(debug)
6957d7728c9SDavid du Colombier fprint(2, "scuzz: opening open file\n");
6963e12c5d1SDavid du Colombier rp->status = Status_BADARG;
6973e12c5d1SDavid du Colombier return -1;
6983e12c5d1SDavid du Colombier }
699e29d4813SDavid du Colombier memset(rp, 0, sizeof *rp);
7007dd7cddfSDavid du Colombier rp->unit = unit;
7017dd7cddfSDavid du Colombier
7027dd7cddfSDavid du Colombier sprint(name, "%s/raw", unit);
7037dd7cddfSDavid du Colombier
7047dd7cddfSDavid du Colombier if((rp->fd = open(name, ORDWR)) == -1){
7057dd7cddfSDavid du Colombier rp->status = STtimeout;
7063e12c5d1SDavid du Colombier return -1;
7073e12c5d1SDavid du Colombier }
7083e12c5d1SDavid du Colombier rp->flags = Fopen;
7093e12c5d1SDavid du Colombier return 0;
7103e12c5d1SDavid du Colombier }
7113e12c5d1SDavid du Colombier
7123e12c5d1SDavid du Colombier int
SRopen(ScsiReq * rp,char * unit)7137dd7cddfSDavid du Colombier SRopen(ScsiReq *rp, char *unit)
7143e12c5d1SDavid du Colombier {
7157dd7cddfSDavid du Colombier if(SRopenraw(rp, unit) == -1)
7163e12c5d1SDavid du Colombier return -1;
7173e12c5d1SDavid du Colombier SRready(rp);
7183e12c5d1SDavid du Colombier if(SRinquiry(rp) >= 0){
7193e12c5d1SDavid du Colombier switch(rp->inquiry[0]){
7203e12c5d1SDavid du Colombier
7213e12c5d1SDavid du Colombier default:
722219b2ee8SDavid du Colombier fprint(2, "unknown device type 0x%.2x\n", rp->inquiry[0]);
7237dd7cddfSDavid du Colombier rp->status = Status_SW;
7243e12c5d1SDavid du Colombier break;
7253e12c5d1SDavid du Colombier
7263e12c5d1SDavid du Colombier case 0x00: /* Direct access (disk) */
7277dd7cddfSDavid du Colombier case 0x05: /* CD-ROM */
728219b2ee8SDavid du Colombier case 0x07: /* rewriteable MO */
7293e12c5d1SDavid du Colombier if(dirdevopen(rp) == -1)
7303e12c5d1SDavid du Colombier break;
7313e12c5d1SDavid du Colombier return 0;
7323e12c5d1SDavid du Colombier
7333e12c5d1SDavid du Colombier case 0x01: /* Sequential eg: tape */
7343e12c5d1SDavid du Colombier rp->flags |= Fseqdev;
7353e12c5d1SDavid du Colombier if(seqdevopen(rp) == -1)
7363e12c5d1SDavid du Colombier break;
7373e12c5d1SDavid du Colombier return 0;
7383e12c5d1SDavid du Colombier
739219b2ee8SDavid du Colombier case 0x02: /* Printer */
740219b2ee8SDavid du Colombier rp->flags |= Fprintdev;
741219b2ee8SDavid du Colombier return 0;
742219b2ee8SDavid du Colombier
7433e12c5d1SDavid du Colombier case 0x04: /* Worm */
7443e12c5d1SDavid du Colombier rp->flags |= Fwormdev;
7453e12c5d1SDavid du Colombier if(wormdevopen(rp) == -1)
7463e12c5d1SDavid du Colombier break;
7473e12c5d1SDavid du Colombier return 0;
7487dd7cddfSDavid du Colombier
7497dd7cddfSDavid du Colombier case 0x08: /* medium-changer */
7507dd7cddfSDavid du Colombier rp->flags |= Fchanger;
7517dd7cddfSDavid du Colombier return 0;
7523e12c5d1SDavid du Colombier }
7533e12c5d1SDavid du Colombier }
7543e12c5d1SDavid du Colombier SRclose(rp);
7553e12c5d1SDavid du Colombier return -1;
7563e12c5d1SDavid du Colombier }
757