|
|
1.1 root 1: /* @(#)scsi-linux-sg.c 1.30 98/11/06 Copyright 1997 J. Schilling */
2: #ifndef lint
3: static char __sccsid[] =
4: "@(#)scsi-linux-sg.c 1.30 98/11/06 Copyright 1997 J. Schilling";
5: #endif
6: /*
7: * Interface for Linux generic SCSI implementation (sg).
8: *
9: * This is the interface for the broken Linux SCSI generic driver.
10: * This is a hack, that tries to emulate the functionality
11: * of the scg driver.
12: *
13: * Design flaws of the sg driver:
14: * - cannot see if SCSI command could not be send
15: * - cannot get SCSI status byte
16: * - cannot get real dma count of tranfer
17: * - cannot get number of bytes valid in auto sense data
18: * - to few data in auto sense (CCS/SCSI-2/SCSI-3 needs >= 18)
19: *
20: * This code contains support for the sg driver version 2
21: *
22: * Copyright (c) 1997 J. Schilling
23: */
24: /*
25: * This program is free software; you can redistribute it and/or modify
26: * it under the terms of the GNU General Public License as published by
27: * the Free Software Foundation; either version 2, or (at your option)
28: * any later version.
29: *
30: * This program is distributed in the hope that it will be useful,
31: * but WITHOUT ANY WARRANTY; without even the implied warranty of
32: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33: * GNU General Public License for more details.
34: *
35: * You should have received a copy of the GNU General Public License
36: * along with this program; see the file COPYING. If not, write to
37: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
38: */
39:
40: #include <linux/version.h>
41:
42: #define DEBUG
43:
44: #ifndef LINUX_VERSION_CODE /* Very old kernel? */
45: # define LINUX_VERSION_CODE 0
46: #endif
47:
48: #if LINUX_VERSION_CODE >= 0x01031a /* <linux/scsi.h> introduced in 1.3.26 */
49: #if LINUX_VERSION_CODE >= 0x020000 /* <scsi/scsi.h> introduced somewhere. */
50: /* Need to fine tune the ifdef so we get the transition point right. */
51: #include <scsi/scsi.h>
52: #else
53: #include <linux/scsi.h>
54: #endif
55: #else
56: #define __KERNEL__
57: #include <linux/fs.h>
58: #undef __KERNEL__
59: #include "block/blk.h"
60: #include "scsi/scsi.h"
61: #endif
62:
63: #include <stdlib.h>
64: #include <stdio.h>
65: #include <errno.h>
66: #include <unistd.h>
67: #include <sys/types.h>
68: #include <sys/stat.h>
69: #include <sys/ioctl.h>
70: #include <sys/time.h>
71: #include <fcntl.h>
72: #include <scsi/sg.h>
73: #include <asm/param.h>
74:
75: #include "scg/defs.h"
76: #include "scg/scsitransp.h"
77: #include "scg/scgcmd.h"
78:
79: #ifndef SCSI_IOCTL_GET_BUS_NUMBER
80: #define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
81: #endif
82:
83: /*
84: * XXX There must be a better way than duplicating things from system include
85: * XXX files. This is stolen from /usr/src/linux/drivers/scsi/scsi.h
86: */
87: #ifndef DID_OK
88: #define DID_OK 0x00 /* NO error */
89: #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */
90: #define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */
91: #define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */
92: #define DID_BAD_TARGET 0x04 /* BAD target. */
93: #define DID_ABORT 0x05 /* Told to abort for some other reason */
94: #define DID_PARITY 0x06 /* Parity error */
95: #define DID_ERROR 0x07 /* Internal error */
96: #define DID_RESET 0x08 /* Reset by somebody. */
97: #define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */
98: #endif
99:
100: #define MAX_SCG 4 /* Max # of SCSI controllers */
101: #define MAX_TGT 16
102: #define MAX_LUN 8
103:
104: typedef struct SCSIPrivate {
105: int scgfile; /* Used for SG_GET_BUFSIZE ioctl() */
106: short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
107: short buscookies[MAX_SCG];
108: int pack_id; /* Should be a random number */
109: char *SCSIbuf;
110: long scg_maxdma;
111: } SCSIPrivate;
112:
113: #ifdef SG_BIG_BUFF
114: #define MAX_DMA_LINUX SG_BIG_BUFF /* Defined in include/scsi/sg.h */
115: #else
116: #define MAX_DMA_LINUX (4*1024) /* Old Linux versions */
117: #endif
118:
119: #ifndef SG_MAX_SENSE
120: # define SG_MAX_SENSE 16 /* Too small for CCS / SCSI-2 */
121: #endif /* But cannot be changed */
122:
123:
124: #if !defined(__i386) && !defined(i386) && !defined(mc68000)
125: #define MISALIGN
126: #endif
127: /*#define MISALIGN*/
128: /*#undef SG_GET_BUFSIZE*/
129:
130: #if defined(USE_PG) && !defined(USE_PG_ONLY)
131: #include "scsi-linux-pg.c"
132: #endif
133:
134: #ifdef MISALIGN
135: LOCAL int scsi_getint __PR((int *ip));
136: #endif
137: LOCAL int scsi_send __PR((SCSI *scgp, int f, struct scg_cmd *sp));
138: LOCAL BOOL sg_setup __PR((SCSI *scgp, int f, int busno, int tgt, int tlun));
139: LOCAL void sg_initdev __PR((SCSI *scgp, int f));
140: LOCAL int sg_mapbus __PR((SCSI *scgp, int ino));
141: LOCAL BOOL sg_mapdev __PR((SCSI *scgp, int f, int *busp, int *tgtp, int *lunp,
142: int *chanp, int *inop));
143: LOCAL void sg_settimeout __PR((int f, int timeout));
144: LOCAL long scsi_maxdma __PR((SCSI *scgp));
145: LOCAL void scsitimes __PR((SCSI *scgp));
146:
147: EXPORT
148: int scsi_open(scgp, device, busno, tgt, tlun)
149: SCSI *scgp;
150: char *device;
151: int busno;
152: int tgt;
153: int tlun;
154: {
155: register int f;
156: register int i;
157: register int b;
158: register int t;
159: register int l;
160: register int nopen = 0;
161: char devname[64];
162:
163: if (!(scgp->private = calloc(1, sizeof(*scgp->private)))) {
164: return -1;
165: }
166: scgp->private->pack_id = rand(); /* now is a random number */
167: scgp->private->scgfile = -1;
168: scgp->private->SCSIbuf = (void *)-1;
169:
170: for (b=0; b < MAX_SCG; b++) {
171: scgp->private->buscookies[b] = (short)-1;
172: for (t=0; t < MAX_TGT; t++) {
173: for (l=0; l < MAX_LUN ; l++)
174: scgp->private->scgfiles[b][t][l] = (short)-1;
175: }
176: }
177: if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
178: goto openbydev;
179:
180: if (busno >= 0 && tgt >= 0 && tlun >= 0) {
181: if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
182: return (-1);
183: }
184:
185: for (i=0; i < 32; i++) {
186: sprintf(devname, "/dev/sg%d", i);
187: f = open(devname, 2);
188: if (f < 0) {
189: if (errno != ENOENT && errno != ENXIO && errno != ENODEV)
190: fprintf(stderr, "Cannot open '%s'.\n", devname);
191: } else {
192: if (sg_setup(scgp, f, busno, tgt, tlun))
193: return (++nopen);
194: if (busno < 0 && tgt < 0 && tlun < 0)
195: nopen++;
196: }
197: }
198: if (nopen == 0) for (i=0; i <= 25; i++) {
199: sprintf(devname, "/dev/sg%c", i+'a');
200: f = open(devname, 2);
201: if (f < 0) {
202: if (errno != ENOENT && errno != ENXIO && errno != ENODEV)
203: fprintf(stderr, "Cannot open '%s'.\n", devname);
204: } else {
205: if (sg_setup(scgp, f, busno, tgt, tlun))
206: return (++nopen);
207: if (busno < 0 && tgt < 0 && tlun < 0)
208: nopen++;
209: }
210: }
211: openbydev:
212: if (device != NULL && *device != '\0') {
213: f = open(device, 2);
214: if (f < 0 && errno == ENOENT)
215: goto openpg;
216:
217: if (!sg_mapdev(scgp, f, &busno, &tgt, &tlun, 0, 0)) {
218: close(f);
219: goto openpg;
220: }
221:
222: if (scgp->scsibus < 0)
223: scgp->scsibus = busno;
224: if (scgp->target < 0)
225: scgp->target = tgt;
226: if (scgp->lun < 0)
227: scgp->lun = tlun;
228:
229: if (sg_setup(scgp, f, busno, tgt, tlun))
230: return (++nopen);
231: }
232: openpg:
233: #ifdef USE_PG
234: nopen += pg_open(scgp, device, busno, tgt, tlun);
235: #endif
236: return (nopen);
237: }
238:
239: LOCAL BOOL
240: sg_setup(scgp, f, busno, tgt, tlun)
241: SCSI *scgp;
242: int f;
243: int busno;
244: int tgt;
245: int tlun;
246: {
247: int n;
248: int Chan;
249: int Ino;
250: int Bus;
251: int Target;
252: int Lun;
253: BOOL onetarget = FALSE;
254:
255:
256: if (scgp->scsibus >= 0 && scgp->target >= 0 && scgp->lun >= 0)
257: onetarget = TRUE;
258:
259: sg_mapdev(scgp, f, &Bus, &Target, &Lun, &Chan, &Ino);
260:
261: /*
262: * For old kernels try to make the best guess.
263: */
264: Ino |= Chan << 8;
265: n = sg_mapbus(scgp, Ino);
266: if (Bus == -1) {
267: Bus = n;
268: if (scgp->debug)
269: printf("SCSI Bus: %d (mapped from %d)\n", Bus, Ino);
270: }
271:
272: /* if (scgp->private->scgfiles[Bus][Target][Lun] == (short)-1) */
273: scgp->private->scgfiles[Bus][Target][Lun] = (short)f;
274:
275: if (onetarget) {
276: if (Bus == busno && Target == tgt && Lun == tlun) {
277: sg_initdev(scgp, f);
278: scgp->private->scgfile = f; /* remember file for ioctl's */
279: return (TRUE);
280: } else {
281: scgp->private->scgfiles[Bus][Target][Lun] = (short)-1;
282: close(f);
283: }
284: } else {
285: sg_initdev(scgp, f);
286: if (scgp->private->scgfile < 0)
287: scgp->private->scgfile = f; /* remember file for ioctl's */
288: }
289: return (FALSE);
290: }
291:
292: LOCAL void
293: sg_initdev(scgp, f)
294: SCSI *scgp;
295: int f;
296: {
297: struct sg_rep {
298: struct sg_header hd;
299: unsigned char rbuf[100];
300: } sg_rep;
301: int n;
302:
303: /* Eat any unwanted garbage from prior use of this device */
304:
305: n = fcntl(f, F_GETFL); /* Be very proper about this */
306: fcntl(f, F_SETFL, n|O_NONBLOCK);
307:
308: fillbytes((caddr_t)&sg_rep, sizeof(struct sg_header), '\0');
309: sg_rep.hd.reply_len = sizeof(struct sg_header);
310:
311: while (read(f, &sg_rep, sizeof(sg_rep)) >= 0 || errno != EAGAIN)
312: ;
313:
314: fcntl(f, F_SETFL, n);
315:
316: sg_settimeout(f, scgp->deftimeout);
317: }
318:
319: LOCAL int
320: sg_mapbus(scgp, ino)
321: SCSI *scgp;
322: int ino;
323: {
324: register int i;
325:
326: for (i=0; i < MAX_SCG; i++) {
327: if (scgp->private->buscookies[i] == (short)-1) {
328: scgp->private->buscookies[i] = ino;
329: return (i);
330: }
331:
332: if (scgp->private->buscookies[i] == ino)
333: return (i);
334: }
335: return (0);
336: }
337:
338: LOCAL BOOL
339: sg_mapdev(scgp, f, busp, tgtp, lunp, chanp, inop)
340: SCSI *scgp;
341: int f;
342: int *busp;
343: int *tgtp;
344: int *lunp;
345: int *chanp;
346: int *inop;
347: {
348: struct sg_id {
349: long l1; /* target | lun << 8 | channel << 16 | low_ino << 24 */
350: long l2; /* Unique id */
351: } sg_id;
352: int Chan;
353: int Ino;
354: int Bus;
355: int Target;
356: int Lun;
357:
358: if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))
359: return (FALSE);
360: if (scgp->debug)
361: printf("l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);
362: if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {
363: Bus = -1;
364: }
365:
366: Target = sg_id.l1 & 0xFF;
367: Lun = (sg_id.l1 >> 8) & 0xFF;
368: Chan = (sg_id.l1 >> 16) & 0xFF;
369: Ino = (sg_id.l1 >> 24) & 0xFF;
370: if (scgp->debug) {
371: printf("Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",
372: Bus, Target, Lun, Chan, Ino);
373: }
374: *busp = Bus;
375: *tgtp = Target;
376: *lunp = Lun;
377: if (chanp)
378: *chanp = Chan;
379: if (inop)
380: *inop = Ino;
381: return (TRUE);
382: }
383:
384: LOCAL long
385: scsi_maxdma(scgp)
386: SCSI *scgp;
387: {
388: long maxdma = MAX_DMA_LINUX;
389:
390: #ifdef SG_GET_BUFSIZE
391: /*
392: * We assume that all /dev/sg instances use the same
393: * maximum buffer size.
394: */
395: if ((maxdma = ioctl(scgp->private->scgfile, SG_GET_BUFSIZE, 0)) < 0) {
396: if (scgp->private->scgfile >= 0) {
397: maxdma = MAX_DMA_LINUX;
398: }
399: }
400: #endif
401: #ifdef USE_PG
402: if (scgp->scsibus == pgbus)
403: return (pg_maxdma(scgp));
404: if ((scgp->scsibus < 0) && (pg_maxdma(scgp) < maxdma))
405: return (pg_maxdma(scgp));
406: #endif
407: return (maxdma);
408: }
409:
410: EXPORT void *
411: scsi_getbuf(scgp, amt)
412: SCSI *scgp;
413: long amt;
414: {
415: char *ret;
416:
417: if (scgp->private->scg_maxdma == 0)
418: scgp->private->scg_maxdma = scsi_maxdma(scgp);
419:
420: if (amt <= 0 || amt > scgp->private->scg_maxdma)
421: return ((void *)0);
422: if (scgp->debug)
423: printf("scsi_getbuf: %ld bytes\n", amt);
424: /*
425: * For performance reason, we allocate pagesize()
426: * bytes before the SCSI buffer to avoid
427: * copying the whole buffer contents when
428: * setting up the /dev/sg data structures.
429: */
430: ret = valloc((size_t)(amt+getpagesize()));
431: if (ret == NULL)
432: return (ret);
433: ret += getpagesize();
434: scgp->private->SCSIbuf = ret;
435: return ((void *)ret);
436: }
437:
438: EXPORT
439: BOOL scsi_havebus(scgp, busno)
440: SCSI *scgp;
441: int busno;
442: {
443: register int t;
444: register int l;
445:
446: if (busno < 0 || busno >= MAX_SCG)
447: return (FALSE);
448:
449: for (t=0; t < MAX_TGT; t++) {
450: for (l=0; l < MAX_LUN ; l++)
451: if (scgp->private->scgfiles[busno][t][l] >= 0)
452: return (TRUE);
453: }
454: return (FALSE);
455: }
456:
457: EXPORT
458: int scsi_fileno(scgp, busno, tgt, tlun)
459: SCSI *scgp;
460: int busno;
461: int tgt;
462: int tlun;
463: {
464: if (busno < 0 || busno >= MAX_SCG ||
465: tgt < 0 || tgt >= MAX_TGT ||
466: tlun < 0 || tlun >= MAX_LUN)
467: return (-1);
468:
469: return ((int)scgp->private->scgfiles[busno][tgt][tlun]);
470: }
471:
472: EXPORT
473: int scsi_isatapi(scgp)
474: SCSI *scgp;
475: {
476: #ifdef USE_PG
477: if (scgp->scsibus == pgbus)
478: return (pg_isatapi(scgp));
479: #endif
480:
481: #ifdef SG_EMULATED_HOST
482: {
483: int emulated = FALSE;
484: int f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun);
485:
486: if (ioctl(f, SG_EMULATED_HOST, &emulated) >= 0)
487: return (emulated != 0);
488: }
489: #endif
490: return (-1);
491: }
492:
493: EXPORT
494: int scsireset(scgp)
495: SCSI *scgp;
496: {
497: #ifdef USE_PG
498: if (scgp->scsibus == pgbus)
499: return (pg_reset(scgp));
500: #endif
501: /*
502: * Do we have a SCSI reset in the Linux sg driver?
503: */
504: return (-1);
505: }
506:
507: LOCAL void
508: sg_settimeout(f, tmo)
509: int f;
510: int tmo;
511: {
512: tmo *= HZ;
513: if (tmo)
514: tmo += HZ/2;
515:
516: if (ioctl(f, SG_SET_TIMEOUT, &tmo) < 0)
517: fprintf(stderr, "Cannot set SG_SET_TIMEOUT.\n");
518: }
519:
520: /*
521: * Get misaligned int.
522: * Needed for all recent processors (sparc/ppc/alpha)
523: * because the /dev/sg design forces us to do misaligned
524: * reads of integers.
525: */
526: #ifdef MISALIGN
527: LOCAL int
528: scsi_getint(ip)
529: int *ip;
530: {
531: int ret;
532: register char *cp = (char *)ip;
533: register char *tp = (char *)&ret;
534: register int i;
535:
536: for (i = sizeof(int); --i >= 0; )
537: *tp++ = *cp++;
538:
539: return (ret);
540: }
541: #define GETINT(a) scsi_getint(&(a))
542: #else
543: #define GETINT(a) (a)
544: #endif
545:
546: LOCAL int
547: scsi_send(scgp, f, sp)
548: SCSI *scgp;
549: int f;
550: struct scg_cmd *sp;
551: {
552: struct sg_rq *sgp;
553: struct sg_rq *sgp2;
554: int i;
555: int pack_len;
556: int reply_len;
557: int amt = sp->cdb_len;
558: struct sg_rq {
559: struct sg_header hd;
560: unsigned char buf[MAX_DMA_LINUX+SCG_MAX_CMD];
561: } sg_rq;
562: #ifdef SG_GET_BUFSIZE /* We may use a 'sg' version 2 driver */
563: char driver_byte;
564: char host_byte;
565: char msg_byte;
566: char status_byte;
567: #endif
568:
569: if (f < 0) {
570: sp->error = SCG_FATAL;
571: return (0);
572: }
573: #ifdef USE_PG
574: if (scgp->scsibus == pgbus)
575: return (pg_send(scgp, f, sp));
576: #endif
577: if (sp->timeout != scgp->deftimeout)
578: sg_settimeout(f, sp->timeout);
579:
580:
581: sgp2 = sgp = &sg_rq;
582: if (sp->addr == scgp->private->SCSIbuf) {
583: sgp = (struct sg_rq *)
584: (scgp->private->SCSIbuf - (sizeof(struct sg_header) + amt));
585: sgp2 = (struct sg_rq *)
586: (scgp->private->SCSIbuf - (sizeof(struct sg_header)));
587: } else {
588: if (scgp->debug) {
589: printf("DMA addr: 0x%8.8lX size: %d - using copy buffer\n",
590: (long)sp->addr, sp->size);
591: }
592: if (sp->size > (int)(sizeof(sg_rq.buf) - SCG_MAX_CMD)) {
593: errno = ENOMEM;
594: return (-1);
595: }
596: }
597:
598: /*
599: * This is done to avoid misaligned access of sgp->some_int
600: */
601: pack_len = sizeof(struct sg_header) + amt;
602: reply_len = sizeof(struct sg_header);
603: if (sp->flags & SCG_RECV_DATA) {
604: reply_len += sp->size;
605: } else {
606: pack_len += sp->size;
607: }
608:
609: #ifdef MISALIGN
610: /*
611: * sgp->some_int may be misaligned if (sp->addr == SCSIbuf)
612: * This is no problem on Intel porocessors, however
613: * all other processors don't like it.
614: * sizeof(struct sg_header) + amt is usually not a multiple of
615: * sizeof(int). For this reason, we fill in the values into sg_rq
616: * which is always corectly aligned and then copy it to the real
617: * location if this location differs from sg_rq.
618: * Never read/write directly to sgp->some_int !!!!!
619: */
620: fillbytes((caddr_t)&sg_rq, sizeof(struct sg_header), '\0');
621:
622: sg_rq.hd.pack_len = pack_len;
623: sg_rq.hd.reply_len = reply_len;
624: sg_rq.hd.pack_id = scgp->private->pack_id++;
625: /* sg_rq.hd.result = 0; not needed because of fillbytes() */
626:
627: if ((caddr_t)&sg_rq != (caddr_t)sgp)
628: movebytes((caddr_t)&sg_rq, (caddr_t)sgp, sizeof(struct sg_header));
629: #else
630: fillbytes((caddr_t)sgp, sizeof(struct sg_header), '\0');
631:
632: sgp->hd.pack_len = pack_len;
633: sgp->hd.reply_len = reply_len;
634: sgp->hd.pack_id = scgp->private->pack_id++;
635: /* sgp->hd.result = 0; not needed because of fillbytes() */
636: #endif
637: if (amt == 12)
638: sgp->hd.twelve_byte = 1;
639:
640:
641: for (i = 0; i < amt; i++ ) {
642: sgp->buf[i] = sp->cdb.cmd_cdb[i];;
643: }
644: if (!(sp->flags & SCG_RECV_DATA)) {
645: if ((void *)sp->addr != (void *)&sgp->buf[amt])
646: movebytes(sp->addr, &sgp->buf[amt], sp->size);
647: amt += sp->size;
648: }
649: #ifdef SG_GET_BUFSIZE
650: sgp->hd.want_new = 1; /* Order new behaviour */
651: sgp->hd.cdb_len = sp->cdb_len; /* Set CDB length */
652: if (sp->sense_len > SG_MAX_SENSE)
653: sgp->hd.sense_len = SG_MAX_SENSE;
654: else
655: sgp->hd.sense_len = sp->sense_len;
656: #endif
657: i = sizeof(struct sg_header) + amt;
658: if ((amt = write(f, sgp, i)) < 0) { /* write */
659: sg_settimeout(f, scgp->deftimeout);
660: return (-1);
661: } else if (amt != i) {
662: /* errmsg("scsi_send(%s) wrote %d bytes (expected %d).\n",
663: scsi_command, amt, i);*/
664: }
665:
666: if (sp->addr == scgp->private->SCSIbuf) {
667: movebytes(sgp, sgp2, sizeof(struct sg_header));
668: sgp = sgp2;
669: }
670: sgp->hd.sense_buffer[0] = 0;
671: if ((amt = read(f, sgp, reply_len)) < 0) { /* read */
672: sg_settimeout(f, scgp->deftimeout);
673: return (-1);
674: }
675:
676: if (sp->flags & SCG_RECV_DATA && ((void *)sgp->buf != (void *)sp->addr)) {
677: movebytes(sgp->buf, sp->addr, sp->size);
678: }
679: sp->ux_errno = GETINT(sgp->hd.result); /* Unaligned read */
680: sp->error = SCG_NO_ERROR;
681:
682: #ifdef SG_GET_BUFSIZE
683: if (sgp->hd.grant_new) {
684: sp->sense_count = sgp->hd.sense_len;
685: pack_len = GETINT(sgp->hd.sg_cmd_status); /* Unaligned read */
686: driver_byte = (pack_len >> 24) & 0xFF;
687: host_byte = (pack_len >> 16) & 0xFF;
688: msg_byte = (pack_len >> 8) & 0xFF;
689: status_byte = pack_len & 0xFF;
690:
691: switch (host_byte) {
692:
693: case DID_OK:
694: if (sgp->hd.sense_buffer[0] != 0) {
695: /*
696: * The Linux SCSI system up to 2.1.xx
697: * trashes the status byte in the
698: * kernel. Until this gets fixed, we
699: * need this hack.
700: */
701: sp->error = SCG_RETRYABLE;
702: status_byte = 2;
703: sgp->hd.sense_len = SG_MAX_SENSE;
704: }
705: break;
706:
707: case DID_NO_CONNECT: /* Arbitration won, retry NO_CONNECT? */
708: case DID_BAD_TARGET:
709: sp->error = SCG_FATAL;
710: break;
711:
712: case DID_TIME_OUT:
713: sp->error = SCG_TIMEOUT;
714: break;
715:
716: default:
717: sp->error = SCG_RETRYABLE;
718: break;
719:
720: }
721: if ((host_byte != DID_OK || status_byte != 0) && sp->ux_errno == 0)
722: sp->ux_errno = EIO;
723: sp->u_scb.cmd_scb[0] = status_byte;
724: if (status_byte & 2) {
725: sp->sense_count = sgp->hd.sense_len;
726: movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);
727: }
728: } else
729: #endif
730: {
731: if (GETINT(sgp->hd.result) == EBUSY) { /* Unaligned read */
732: struct timeval to;
733:
734: to.tv_sec = sp->timeout;
735: to.tv_usec = 500000;
736: scsitimes(scgp);
737:
738: if (scgp->cmdstop->tv_sec < to.tv_sec ||
739: (scgp->cmdstop->tv_sec == to.tv_sec &&
740: scgp->cmdstop->tv_usec < to.tv_usec)) {
741:
742: sp->ux_errno = 0;
743: sp->error = SCG_TIMEOUT; /* a timeout */
744: } else {
745: sp->error = SCG_RETRYABLE; /* may be BUS_BUSY */
746: }
747: }
748:
749: if (sp->flags & SCG_RECV_DATA)
750: sp->resid = (sp->size + sizeof(struct sg_header)) - amt;
751: else
752: sp->resid = 0; /* sg version1 cannot return DMA resid count */
753:
754: if (sgp->hd.sense_buffer[0] != 0) {
755: sp->error = SCG_RETRYABLE;
756: sp->scb.chk = 1;
757: sp->sense_count = SG_MAX_SENSE;
758: movebytes(sgp->hd.sense_buffer, sp->u_sense.cmd_sense, sp->sense_count);
759: if (sp->ux_errno == 0)
760: sp->ux_errno = EIO;
761: }
762: }
763:
764: if (scgp->verbose > 0 && scgp->debug) {
765: #ifdef SG_GET_BUFSIZE
766: printf("status: %X pack_len: %d, reply_len: %d pack_id: %d result: %d wn: %d gn: %d cdb_len: %d sense_len: %d sense[0]: %02X\n",
767: GETINT(sgp->hd.sg_cmd_status),
768: GETINT(sgp->hd.pack_len),
769: GETINT(sgp->hd.reply_len),
770: GETINT(sgp->hd.pack_id),
771: GETINT(sgp->hd.result),
772: sgp->hd.want_new,
773: sgp->hd.grant_new,
774: sgp->hd.cdb_len,
775: sgp->hd.sense_len,
776: sgp->hd.sense_buffer[0]);
777: #else
778: printf("pack_len: %d, reply_len: %d pack_id: %d result: %d sense[0]: %02X\n",
779: GETINT(sgp->hd.pack_len),
780: GETINT(sgp->hd.reply_len),
781: GETINT(sgp->hd.pack_id),
782: GETINT(sgp->hd.result),
783: sgp->hd.sense_buffer[0]);
784: #endif
785: #ifdef DEBUG
786: printf("sense: ");
787: for (i=0; i < 16; i++)
788: printf("%02X ", sgp->hd.sense_buffer[i]);
789: printf("\n");
790: #endif
791: }
792:
793: if (sp->timeout != scgp->deftimeout)
794: sg_settimeout(f, scgp->deftimeout);
795: return 0;
796: }
797:
798: LOCAL
799: void scsitimes(scgp)
800: SCSI *scgp;
801: {
802: struct timeval *stp = scgp->cmdstop;
803:
804: gettimeofday(stp, (struct timezone *)0);
805: stp->tv_sec -= scgp->cmdstart->tv_sec;
806: stp->tv_usec -= scgp->cmdstart->tv_usec;
807: while (stp->tv_usec < 0) {
808: stp->tv_sec -= 1;
809: stp->tv_usec += 1000000;
810: }
811: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.