Annotation of uae/src/scg-linux-sg/scsi.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.