Annotation of coherent/d/286_KERNEL/USRSRC/io/scsi.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * This is the generic SCSI part of the
                      3:  * Adaptec AHA154x host adapter driver for the AT.
                      4:  *
                      5:  * $Log:       scsi.c,v $
                      6:  * Revision 1.10  92/01/17  11:38:37  bin
                      7:  * update by hal... looks like final 321 version
                      8:  * 
                      9:  * Revision 1.10  92/01/17  03:51:13  hal
                     10:  * Cleanup for 3.2.1.
                     11:  * 
                     12:  * Revision 1.9  91/11/11  12:32:58  hal
                     13:  * Get SD_HDS and SD_SPT from tboot.
                     14:  * 
                     15:  * Revision 1.8  91/10/25  14:50:39  hal
                     16:  * Make DMA channel patchable.
                     17:  *
                     18:  * Revision 1.7  91/10/22  13:40:36  hal
                     19:  * Use sys on kernel header includes.
                     20:  *
                     21:  * Revision 1.6  91/06/10  13:28:11  hal
                     22:  * Refix startup problem with HDGETA.  Text cleanup.
                     23:  *
                     24:  * Revision 1.5  91/06/10  12:58:04  hal
                     25:  * Partial fix for HDGETA failing if partition table absent.
                     26:  *
                     27:  * Revision 1.4  91/06/03  13:50:06  hal
                     28:  * Add HDSETA.
                     29:  *
                     30:  * Revision 1.3        91/05/08  11:00:30      root
                     31:  * Make number of heads - SD_HDS - patchable for Tandy.
                     32:  *
                     33:  * Revision 1.2        91/05/01  04:50:11      root
                     34:  * Debug code and d_time/sw_active imbalance fixed.
                     35:  *
                     36:  * Revision 1.1        91/04/30  11:02:22      root
                     37:  * Shipped with COH 3.1.0
                     38:  *
                     39:  */
                     40: 
                     41: #include       <sys/coherent.h>
                     42: #include       <sys/fdisk.h>
                     43: #include       <sys/hdioctl.h>
                     44: #include       <sys/sdioctl.h>
                     45: #include       <sys/buf.h>
                     46: #include       <sys/con.h>
                     47: #include       <sys/stat.h>
                     48: #include       <sys/uproc.h>
                     49: #include       <errno.h>
                     50: #include       <sys/scsiwork.h>
                     51: #include       <sys/typed.h>
                     52: 
                     53: extern saddr_t sds;
                     54: extern short   n_atdr;
                     55: 
                     56: /*
                     57:  * Configurable parameters
                     58:  *
                     59:  * Adaptec ROM translates at 64 heads, except the Tandy version, which
                     60:  * uses 16 heads.  Kernel variable SD_HDS is patchable for this reason.
                     61:  */
                     62: #define DEF_AHA_HDS    64
                     63: #define DEF_AHA_SPT    32
                     64: 
                     65: int SD_HDS = 0;
                     66: int SD_SPT = 0;
                     67: 
                     68: #define NDRIVE (8 * 4)                 /* 8 SCSI ids and 4 LUNs */
                     69: #define        SDMAJOR 13                      /* Major Device Number */
                     70: 
                     71: /*
                     72:  * user configurable parameters
                     73:  */
                     74: int    SDIRQ   = 11;                   /* Interrupt */
                     75: int    SDBASE  = 0x0330;               /* Port base */
                     76: int    SDDMA   = 5;                    /* Used for first party DMA */
                     77: 
                     78: /*
                     79:  *                                     LUN --------++
                     80:  * device macros                       Special-+   ||
                     81:  * minor device bits are of the form:          76543210
                     82:  *                                              |||  ||
                     83:  *                                     SCSI ID--+++  ||
                     84:  *                                     Partition ----++
                     85:  * Partition mapping:
                     86:  *
                     87:  * Description    Special Bit     Partition #          Device          Type
                     88:  * -----------    -----------     -----------          ------          ----
                     89:  * partition a         0               00              /dev/sd??a      disk
                     90:  * partition b         0               01              /dev/sd??b      disk
                     91:  * partition c         0               10              /dev/sd??c      disk
                     92:  * partition d         0               11              /dev/sd??d      disk
                     93:  * partition table     1               00              /dev/sd??x      disk
                     94:  * no rewind tape      1               01              /dev/sd??n      tape
                     95:  * UNALLOCATED         1               10                ---           ????
                     96:  * rewind tape device  1               11              /dev/sd??       tape
                     97:  */
                     98: #define        DRIVENO(minor)  (((minor) >> 2) & 0x1F) /* SCSI ID + LUN */
                     99: #define        SCSIID(minor)   (((minor) >> 4) & 0x7)  /* SCSI ID */
                    100: #define        LUN(minor)      (((minor) >> 2) & 0x3)  /* Logical Unit Number */
                    101: #define        PARTITION(minor) ((minor) & 0x3)        /* Partition */
                    102: #define        sdmkdev(maj, s, drv)    makedev((maj), ((s)|((drv)<<2)))
                    103: 
                    104: /*
                    105:  * Driver configuration.
                    106:  */
                    107: void   sdload();
                    108: void   sdunload();
                    109: void   sdopen();
                    110: void   sdclose();
                    111: void   sdread();
                    112: void   sdwrite();
                    113: int    sdioctl();
                    114: void   sdblock();
                    115: int    sdwatch();
                    116: int    nulldev();
                    117: int    nonedev();
                    118: 
                    119: CON    sdcon   = {
                    120:        DFBLK|DFCHR,                    /* Flags */
                    121:        SDMAJOR,                        /* Major index */
                    122:        sdopen,                         /* Open */
                    123:        sdclose,                        /* Close */
                    124:        sdblock,                        /* Block */
                    125:        sdread,                         /* Read */
                    126:        sdwrite,                        /* Write */
                    127:        sdioctl,                        /* Ioctl */
                    128:        nulldev,                        /* Powerfail */
                    129:        sdwatch,                        /* Timeout */
                    130:        sdload,                         /* Load */
                    131:        sdunload                        /* Unload */
                    132: };
                    133: 
                    134: /*
                    135:  *     host adapter routines
                    136:  */
                    137: int    aha_load();             /* initialize host adapter, DMA */
                    138: void   aha_unload();           /* shutdown the host adapter */
                    139: int    aha_start();            /* see if there's work */
                    140: int    aha_command();
                    141: 
                    142: /*
                    143:  * Partition Parameters - copied from disk.
                    144:  *
                    145:  *     There are NPARTN positions for the user partitions in array PPARM,
                    146:  *     plus 1 additional position to span the entire drive.
                    147:  *     Array pparmp[] contains a pointer to a kalloc()'ed PPARM
                    148:  *     entry if the drive actually exists, is a disk drive and if someone
                    149:  *     has attmpted to read a partition table from the drive.
                    150:  */
                    151: typedef        struct  fdisk_s PPARM[NPARTN + 1];      /* 4 partitions + whole drive */
                    152: static PPARM *pparmp[NDRIVE];                  /* one per possible drive */
                    153: #define        WHOLE_DRIVE     NPARTN                  /* index for whole drive */
                    154: #define        PNULL   ((PPARM *)0)
                    155: 
                    156: /*
                    157:  * Per disk controller data.
                    158:  * Only one host adapter; no more, no less.
                    159:  */
                    160: static
                    161: scsi_work_t    sd;
                    162: 
                    163: static BUF     dbuf;                   /* For raw I/O */
                    164: static int     sw_active;
                    165: 
                    166: /**
                    167:  *
                    168:  * void
                    169:  * sdload()    - load routine.
                    170:  *
                    171:  *     Action: The controller is reset and the interrupt vector is grabbed.
                    172:  *             The drive characteristics are set up at this time.
                    173:  */
                    174: static void
                    175: sdload()
                    176: {
                    177:        FIFO *ffp;
                    178:        typed_space *tp;
                    179:        extern typed_space boot_gift;
                    180: 
                    181:        /*
                    182:         * Initialize Drive Controller.
                    183:         */
                    184:        sw_active = 0;
                    185:        if (aha_load(SDDMA, SDIRQ, SDBASE, &sd) < 0) {
                    186:                u.u_error = ENXIO;
                    187:                return;
                    188:        }
                    189: 
                    190:        /*
                    191:         * Set values for # of heads and # of sectors per track.
                    192:         *
                    193:         * AHA translation mode uses the same # of heads
                    194:         * and the same # of sectors per track for all drives.
                    195:         *
                    196:         * If these values are already patched, leave them alone.
                    197:         * Otherwise, look in the data area written by tboot.
                    198:         * If nothing from tboot, use default values.
                    199:         */
                    200:        if (SD_HDS == 0 || SD_SPT == 0) {
                    201:                /* heads & spt not both patched */
                    202:                SD_HDS = DEF_AHA_HDS;
                    203:                SD_SPT = DEF_AHA_SPT;
                    204:                if (F_NULL != (ffp = fifo_open(&boot_gift, 0))) {
                    205:                        if (T_NULL != (tp = fifo_read(ffp))) {
                    206:                                BIOS_DISK *bdp = (BIOS_DISK *)tp->ts_data;
                    207:                                if ((T_BIOS_DISK == tp->ts_type) &&
                    208:                                    (n_atdr == bdp->dp_drive) ) {
                    209:                                /* got values from tboot */
                    210:                                        SD_HDS = bdp->dp_heads;
                    211:                                        SD_SPT = bdp->dp_sectors;
                    212:                                }
                    213:                        }
                    214:                        fifo_close(ffp);
                    215:                }
                    216:        }
                    217: printf(" SD_HDS=%d SD_SPT=%d\n", SD_HDS, SD_SPT);
                    218: 
                    219: /*     aha_device_info(); */           /* enable after this gets fixed */
                    220: }
                    221: 
                    222: /**
                    223:  *
                    224:  * void
                    225:  * sdunload()  - unload routine.
                    226:  */
                    227: static void
                    228: sdunload()
                    229: {
                    230:        register int i;
                    231: 
                    232:        if (sw_active > 0)
                    233:                printf("aha154x: sdunload() athough %d active\n", sw_active);
                    234:        aha_unload(SDIRQ);
                    235:        for (i = 0; i < NDRIVE; ++i)
                    236:                if (pparmp[i] != PNULL)
                    237:                        kfree(pparmp[i]);       /* free any partition tables */
                    238: }
                    239: 
                    240: /*
                    241:  * int
                    242:  * sdgetpartitions(dev)        - load partition table for specified drive
                    243:  *
                    244:  *                     - return 1 on success and 0 on failure
                    245:  */
                    246: int sdgetpartitions(dev)
                    247: dev_t  dev;
                    248: {
                    249:        register int    i;
                    250:        scsi_cmd_t      sc;
                    251:        unsigned char   *buffer;
                    252:        struct fdisk_s  *fdp;
                    253:        int     d = DRIVENO(minor(dev));
                    254: 
                    255:        pparmp[d] = kalloc(sizeof *pparmp[0]);
                    256:        fdp = (struct fdisk_s *) pparmp[d];     /* point to first entry */
                    257:        buffer = kalloc(36+1);
                    258:        if (buffer == NULL || pparmp[d] == PNULL) {
                    259:                printf("aha154x: out of kernel memory\n");
                    260:                u.u_error = EKSPACE;
                    261:                return 0;
                    262:        }
                    263:        kclear(pparmp[d], sizeof *pparmp[0]);
                    264:        sc.unit = d;
                    265:        sc.block = 0L;
                    266:        sc.blklen = 0;
                    267: 
                    268:        sc.buffer = VTOP2(buffer, sds);
                    269:        ++drvl[SDMAJOR].d_time;
                    270: #if    0
                    271:        sc.cmd = ScmdINQUIRY;
                    272:        sc.buflen = 36;
                    273:        aha_command(&sc);
                    274:        aha_command(&sc);
                    275:        buffer[36] = 0;
                    276:        printf("SCSI Disk %s", &buffer[8]);
                    277: #endif
                    278:        sc.cmd = ScmdREADCAPACITY;
                    279:        sc.buflen = 8;
                    280: 
                    281:        for(i = 0; i < sc.buflen; ++i)
                    282:                buffer[i] = 0;
                    283:        aha_command(&sc);
                    284:        aha_command(&sc);
                    285: #if    VERBOSE
                    286:        printf("buffer =");
                    287:        for(i = 0; i < sc.buflen; ++i)
                    288:                printf(" %x", buffer[i]);
                    289:        printf("\n");
                    290: #endif
                    291:        sc.block = (buffer[0]<<8) | buffer[1];
                    292:        sc.block <<= 16;
                    293:        sc.block |= (buffer[2]<<8) | buffer[3];
                    294: 
                    295:        sc.blklen = (buffer[6]<<8) | buffer[7];
                    296: #if    VERBOSE
                    297:        printf("SCSI %D. blocks of size %d\n", sc.block, sc.blklen);
                    298: #endif
                    299:        kfree(buffer);
                    300:        fdp[WHOLE_DRIVE].p_size = sc.block;
                    301:        --drvl[SDMAJOR].d_time;
                    302:        return fdisk(sdmkdev(major(dev), SDEV, d), pparmp[d]);
                    303: }
                    304: 
                    305: /**
                    306:  *
                    307:  * void
                    308:  * sdopen(dev, mode)
                    309:  * dev_t dev;
                    310:  * int mode;
                    311:  *
                    312:  *     Input:  dev = disk device to be opened.
                    313:  *             mode = access mode [IPR,IPW, IPR+IPW].
                    314:  *
                    315:  *     Action: Validate the minor device.
                    316:  *             Update the paritition table if necessary.
                    317:  */
                    318: static void
                    319: sdopen(dev, mode)
                    320: register dev_t dev;
                    321: {
                    322:        register int p;                 /* partition */
                    323:        register int d;                 /* drive (SCSI ID + LUN) */
                    324:        struct fdisk_s  *fdp;           /* one partition entry */
                    325: 
                    326:        if (minor(dev) & SDEV) {
                    327:                if (PARTITION(minor(dev)) != 0) {       /* tape device ? */
                    328:                        u.u_error = ENXIO;              /* not yet! */
                    329: devmsg(dev, "No tape yet");
                    330:                } else {
                    331:                        ++drvl[SDMAJOR].d_time;
                    332:                        ++sw_active;
                    333:                }
                    334:                return;
                    335:        }
                    336: 
                    337:        d = DRIVENO(minor(dev));
                    338:        p = PARTITION(minor(dev));
                    339: 
                    340:        /*
                    341:         * If partition not defined read partition characteristics.
                    342:         */
                    343:        if (pparmp[d] == PNULL)   /* no entry yet for this drive ? */
                    344:                if (!sdgetpartitions(dev)) {
                    345:                        u.u_error = ENXIO;
                    346:                        return;
                    347:                }
                    348:        /*
                    349:         * Ensure partition lies within drive boundaries and is non-zero size.
                    350:         */
                    351:        fdp = (struct fdisk_s *) pparmp[d];
                    352:        if ((fdp[p].p_base+fdp[p].p_size) > fdp[WHOLE_DRIVE].p_size) {
                    353:                u.u_error = EBADFMT;
                    354:        } else if (fdp[p].p_size == 0) {
                    355:                u.u_error = ENODEV;
                    356:        } else {
                    357:                ++drvl[SDMAJOR].d_time;
                    358:                ++sw_active;
                    359:        }
                    360: }
                    361: 
                    362: void sdclose(dev)
                    363: {
                    364:        --drvl[SDMAJOR].d_time;
                    365:        --sw_active;
                    366: }
                    367: 
                    368: /**
                    369:  *
                    370:  * void
                    371:  * sdread(dev, iop)    - write a block to the raw disk
                    372:  * dev_t dev;
                    373:  * IO * iop;
                    374:  *
                    375:  *     Input:  dev = disk device to be written to.
                    376:  *             iop = pointer to source I/O structure.
                    377:  *
                    378:  *     Action: Invoke the common raw I/O processing code.
                    379:  */
                    380: static void
                    381: sdread(dev, iop)
                    382: dev_t  dev;
                    383: IO     *iop;
                    384: {
                    385:        ioreq(&dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC);
                    386: }
                    387: 
                    388: /**
                    389:  *
                    390:  * void
                    391:  * sdwrite(dev, iop)   - write a block to the raw disk
                    392:  * dev_t dev;
                    393:  * IO * iop;
                    394:  *
                    395:  *     Input:  dev = disk device to be written to.
                    396:  *             iop = pointer to source I/O structure.
                    397:  *
                    398:  *     Action: Invoke the common raw I/O processing code.
                    399:  */
                    400: static void
                    401: sdwrite(dev, iop)
                    402: dev_t  dev;
                    403: IO     *iop;
                    404: {
                    405:        ioreq(&dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC);
                    406: }
                    407: 
                    408: /**
                    409:  *
                    410:  * int
                    411:  * sdioctl(dev, cmd, arg)
                    412:  * dev_t dev;
                    413:  * int cmd;
                    414:  * char * vec;
                    415:  *
                    416:  *     Input:  dev = disk device to be operated on.
                    417:  *             cmd = input/output request to be performed.
                    418:  *             vec = (pointer to) optional argument.
                    419:  *
                    420:  *     Action: Validate the minor device.
                    421:  *             Update the paritition table if necessary.
                    422:  */
                    423: static int
                    424: sdioctl(dev, cmd, vec)
                    425: register dev_t dev;
                    426: int cmd;
                    427: char * vec;
                    428: {
                    429:        int d;
                    430:        hdparm_t hdparm;
                    431:        struct fdisk_s  *fdp;
                    432:        int do_getpt = 0;       /* 1 if need to call sdgetpartitions() */
                    433: 
                    434:        d = DRIVENO(minor(dev));
                    435: 
                    436:        /*
                    437:         * Identify input/output request.
                    438:         */
                    439:        switch (cmd) {
                    440: 
                    441:        case HDGETA:
                    442:                /*
                    443:                 * If haven't loaded partition table yet for this drive,
                    444:                 * try to do it now.  Note sdgetpartitions() will fail
                    445:                 * if there is a new drive (e.g. no signature).  But all
                    446:                 * we need is allocation of pparmp[d] and capacity read
                    447:                 * properly from the drive.
                    448:                 */
                    449:                if (pparmp[d] == PNULL) {
                    450:                        do_getpt = 1;   /* REALLY just want Read Capacity */
                    451:                        sdgetpartitions(dev);
                    452:                        if (pparmp[d] == NULL) {
                    453:                                u.u_error = ENXIO;
                    454:                                return -1;
                    455:                        }
                    456:                }
                    457:                fdp = (struct fdisk_s *) pparmp[d];
                    458:                *(short *)&hdparm.landc[0] =
                    459:                *(short *)&hdparm.ncyl[0] = fdp[WHOLE_DRIVE].p_size
                    460:                                                / (SD_HDS * SD_SPT);
                    461:                hdparm.nhead = SD_HDS;
                    462:                hdparm.nspt = SD_SPT;
                    463:                kucopy(&hdparm, vec, sizeof hdparm);
                    464:                /*
                    465:                 * I know it's ugly.  But it gets around startup Catch-22.
                    466:                 *
                    467:                 * The fdisk command needs HDGETA.  HDGETA invokes
                    468:                 * sdgetpartitions(), but we want to call it again
                    469:                 * after the partition table has been created by the fdisk
                    470:                 * command.
                    471:                 */
                    472:                if (do_getpt) {
                    473:                        kfree(pparmp[d]);
                    474:                        pparmp[d] = PNULL;      /* force re-read of p. table */
                    475:                }
                    476:                return 0;
                    477:        case HDSETA:
                    478:                /*
                    479:                 * Set hard disk attributes.
                    480:                 */
                    481:                fdp = (struct fdisk_s *) pparmp[d];
                    482:                ukcopy(vec, &hdparm, sizeof hdparm);
                    483:                SD_HDS = hdparm.nhead;
                    484:                SD_SPT = hdparm.nspt;
                    485:                fdp[WHOLE_DRIVE].p_size =
                    486:                        (long)(*(short *)&hdparm.ncyl[0])
                    487:                        * (long)SD_HDS * (long)SD_SPT;
                    488: 
                    489:                return 0;
                    490:        case SCSI_HA_CMD:
                    491:                return aha_ioctl(cmd, vec);
                    492:        case SCSI_CMD:
                    493:                return 0;
                    494:        case SCSI_CMD_IN:
                    495:                return 0;
                    496:        case SCSI_CMD_OUT:
                    497:                return 0;
                    498: 
                    499:        default:
                    500:                u.u_error = EINVAL;
                    501:                return -1;
                    502:        }
                    503: }
                    504: 
                    505: /**
                    506:  *
                    507:  * void
                    508:  * sdblock(bp) - queue a block to the disk
                    509:  *
                    510:  *     Input:  bp = pointer to block to be queued.
                    511:  *
                    512:  *     Action: Queue a block to the disk.
                    513:  *             Make sure that the transfer is within the disk partition.
                    514:  */
                    515: static void
                    516: sdblock(bp)
                    517: register BUF   *bp;
                    518: {
                    519:        register scsi_work_t *sw;
                    520:        register int s;
                    521:        struct  fdisk_s *fdp;
                    522: 
                    523:        int p = PARTITION(minor(bp->b_dev));
                    524:        int drv = DRIVENO(minor(bp->b_dev));
                    525: 
                    526:        if (minor(bp->b_dev) & SDEV)
                    527:                p = WHOLE_DRIVE;
                    528:        bp->b_resid = bp->b_count;
                    529: 
                    530:        fdp = (struct fdisk_s *) pparmp[drv];
                    531: 
                    532:        /*
                    533:         * Range check disk region.
                    534:         */
                    535:        if (pparmp[drv] == PNULL) {
                    536:                if (p == WHOLE_DRIVE) {
                    537: #if 0
                    538: /* Why did we only allow people to access the first block of WHOLE_DRIVE?
                    539:    in cases where there was not a valid partition table? */
                    540:                        if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
                    541:                                bp->b_flag |= BFERR;
                    542:                                bdone(bp);
                    543:                                return;
                    544:                        }
                    545: #endif
                    546:                } else {
                    547:                        printf("aha154x: no partition table\n");
                    548:                        bp->b_flag |= BFERR;
                    549:                        bdone(bp);
                    550:                        return;
                    551:                }
                    552:        } else if ((bp->b_bno + (bp->b_count/BSIZE)) > fdp[p].p_size) {
                    553:                bp->b_flag |= BFERR;
                    554:                bdone(bp);
                    555:                return;
                    556:        }
                    557: 
                    558:        bp->b_actf = NULL;
                    559:        sw = (scsi_work_t *)kalloc(sizeof(*sw));
                    560:        if (sw == (scsi_work_t *)0) {
                    561:                printf("aha154x: out of kernel memory\n");
                    562:                bp->b_flag |= BFERR;
                    563:                bdone(bp);
                    564:                return;
                    565:        }
                    566:        sw->sw_bp = bp;
                    567:        sw->sw_drv = drv;
                    568:        sw->sw_type = 0;
                    569:        if (p != WHOLE_DRIVE)
                    570:                sw->sw_bno   = fdp[p].p_base + bp->b_bno;
                    571:        else
                    572:                sw->sw_bno   = bp->b_bno;
                    573:        sw->sw_retry = 1;
                    574: 
                    575: #if    VERBOSE
                    576:        printf("sdblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
                    577:                drv, (long)sw->sw_bno, bp, bp->b_flag);
                    578: #endif
                    579: 
                    580:        s = sphi();
                    581:        if (sd.sw_actf == NULL)
                    582:                sd.sw_actf = sw;
                    583:        else
                    584:                sd.sw_actl->sw_actf = sw;
                    585:        sd.sw_actl = sw;
                    586:        spl(s);
                    587: 
                    588:        aha_start();
                    589: }
                    590: 
                    591: sdwatch()
                    592: {
                    593:        register i;
                    594: 
                    595:        if (i = aha_start())
                    596: #if    VERBOSE
                    597:                printf("sdwatch: started %d actions\n", i);
                    598: #else
                    599:                ;
                    600: #endif
                    601:        if (i = aha_completed())
                    602: #if    VERBOSE
                    603:                printf("sdwatch: completed %d actions\n", i);
                    604: #else
                    605:                ;
                    606: #endif
                    607: }

unix.superglobalmegacorp.com

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