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

unix.superglobalmegacorp.com

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