Annotation of Net2/arch/i386/isa/as.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Adaptech 1542 SCSI driver for 386bsd
                      3:  *
                      4:  * Pace Willisson     [email protected]    March 28, 1992
                      5:  *
                      6:  * Placed in the public domain with NO WARRANTIES, not even the
                      7:  * implied warranties for MERCHANTABILITY or FITNESS FOR A 
                      8:  * PARTICULAR PURPOSE.
                      9:  *
                     10:  *
                     11:  * This is a very early version - use with care.
                     12:  *
                     13:  * Here is the config info:
                     14:  *
                     15:  * controller  as0     at isa? port 0x330 bio irq 11 drq 5 vector asintr
                     16:  * disk                dk6     at as0 drive 0 
                     17:  *
                     18:  * Also, don't forget to update sys/i386/conf/files.i386.
                     19:  *
                     20:  * So far, used with:
                     21:  *
                     22:  *   CDC WREN 5 600 Megabyte magnetic disk
                     23:  *   EXABYTE EXB-8200 8mm tape drive
                     24:  *   SONY CDU-541 cdrom
                     25:  *
                     26:  * The the tape stuff still needs a lot of working concerning
                     27:  * file marks, end of tape handling and rewinding, but I have
                     28:  * extracted tar tapes to a file system mounted on the CDC disk.
                     29:  *
                     30:  * minor number bits:
                     31:  *
                     32:  *      7  6  5  4  3  2  1  0
                     33:  *                     +-----+  partition number
                     34:  *            +-----+           scsi target number
                     35:  *      +--+                    unused (should be 0)
                     36:  *
                     37:  * For tape drives, set the partition number to 0 for regular,
                     38:  * 1 for no rewind.
                     39:  *
                     40:  * Only supports LUN 0.
                     41:  *
                     42:  * To use with a read-write disk, first use diskpart to create
                     43:  * a disktab entry, then use disklabel.  Since I don't have
                     44:  * the boot programs done yet, I faked it with:
                     45:  *
                     46:  *             # cd /usr/mdec
                     47:  *             # cp wdboot asboot
                     48:  *             # cp bootwd bootas
                     49:  *
                     50:  * Now you can run disklabel, newfs, etc.
                     51:  *
                     52:  * Please send patches and names other perpherials that work to
                     53:  * [email protected].  If you have trouble that you can't fix, please
                     54:  * wait for the next release before contacting me.
1.1.1.2 ! root       55:  *
        !            56:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            57:  * --------------------         -----   ----------------------
        !            58:  * CURRENT PATCH LEVEL:         1       00088
        !            59:  * --------------------         -----   ----------------------
        !            60:  *
        !            61:  * 23 Oct 92   Joerg Lohse             changed ccb opcode for compatibility
        !            62:  *                                     with Adaptec AHA-1542A
        !            63:  * 27 Feb 93   James da Silva          Tapedrive fixes. 
1.1       root       64:  */
                     65: 
                     66: #include "as.h"
                     67: #if NAS > 0
                     68: 
                     69: #include "param.h"
                     70: #include "dkbad.h"
                     71: #include "systm.h"
                     72: #include "conf.h"
                     73: #include "file.h"
                     74: #include "stat.h"
                     75: #include "ioctl.h"
                     76: #include "disklabel.h"
                     77: #include "buf.h"
                     78: #include "uio.h"
                     79: #include "i386/isa/isa_device.h"
                     80: #include "i386/isa/icu.h"
                     81: #include "syslog.h"
                     82: #include "vm/vm.h"
                     83: #include "kernel.h"
                     84: 
                     85: #include "asreg.h"
                     86: 
                     87: int asstrategy ();
                     88: int asabort ();
                     89: extern int hz;
                     90: 
                     91: int asverbose = 0;
                     92: 
                     93: 
                     94: /* target id 7 is the controller itself */
                     95: #define NTARGETS 7
                     96: 
                     97: struct mailbox_entry mailboxes[NTARGETS * 2] = {0};
                     98: 
                     99: #define b_cylin        b_resid /* fake cylinder number for disksort */
                    100: 
                    101: /* maximum scatter list size for Adaptech controller */
                    102: #define NSCATTER 17
                    103: 
                    104: /* this array must reside in contiguous physical memory */
                    105: struct asinfo {
                    106:        dev_t dev;
                    107:        struct buf requests;
                    108:        struct mailbox_entry *mailbox;
                    109:        int active;
                    110:        struct ccb ccb;
                    111:        unsigned int ccb_phys;
                    112:        char scatter_list[NSCATTER * 6];
                    113: 
                    114:        struct disklabel label;
                    115:        struct dos_partition dospart[NDOSPART];
                    116:        int have_label;
                    117: 
                    118:        int scsi_lock;
                    119:        struct buf *scsi_bp;
                    120:        int scsi_cdb_len;
                    121:        unsigned char scsi_cdb[MAXCDB];
                    122: 
                    123:        int tape;               /* sequential */
                    124:        int disk;               /* nonsequential */
                    125:        int read_only;          /* CDROM */
                    126:        int removable;          /* unsupported and tested */
                    127:        char vendor[9];
                    128:        char model[17];
                    129:        char revision[5];
                    130:        int bs;                 /* device block size */
                    131: 
                    132:        int open_lock;
                    133:        int open;
                    134:        int units_open;
                    135: 
                    136:        int wlabel;
                    137: 
                    138:        int retry_count;
                    139:        int start_time;
                    140:        int restart_pending;
                    141: 
                    142: } asinfo[NTARGETS] = {0};
                    143: 
                    144: #define dev_part(dev) (minor (dev) & 7)
                    145: #define dev_target(dev) ((minor (dev) >> 3) & 7)
                    146: #define dev_rewind(dev) ((minor (dev) & 1) == 0)
                    147: 
                    148: #define makeasdev(major, target, part) \
                    149:        makedev ((major), ((target) << 3) | (part))
                    150: 
                    151: int as_port;
                    152: 
                    153: int    asprobe(struct isa_device *), asattach(struct isa_device *),
                    154:        asintr(dev_t);
                    155: 
                    156: struct isa_driver asdriver = {
                    157:        asprobe, asattach, "as",
                    158: };
                    159: 
                    160: int
                    161: asprobe (struct isa_device *dvp)
                    162: {
                    163:        int val;
                    164: 
                    165:        as_port = dvp->id_iobase;
                    166: 
                    167:        outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
                    168:        DELAY (30000);
                    169:        val = inb (as_port + AS_STATUS);
                    170: 
                    171:        if (val == (AS_STATUS_INIT | AS_STATUS_IDLE))
                    172:                return (1);
                    173:        as_port = 0;
                    174:        return (0);
                    175: }
                    176: 
                    177: asattach (struct isa_device *dvp)
                    178: {
                    179:        int i;
                    180:        unsigned int physaddr;
                    181:        int val;
                    182:        int s;
                    183: 
                    184:        for (i = 0; i < NTARGETS; i++) {
                    185:                asinfo[i].mailbox = &mailboxes[i];
                    186:                asinfo[i].ccb_phys = vtophys (&asinfo[i].ccb);
                    187:        }
                    188: 
                    189:        isa_dmacascade(dvp->id_drq);
                    190:        
                    191:        physaddr = vtophys (mailboxes);
                    192:        
                    193:        s = splbio ();
                    194:        if (as_put_byte (AS_CMD_MAILBOX_INIT) < 0
                    195:            || as_put_byte (NTARGETS) < 0
                    196:            || as_put_byte (physaddr >> 16) < 0
                    197:            || as_put_byte (physaddr >> 8) < 0
                    198:            || as_put_byte (physaddr) < 0) {
                    199:                splx (s);
                    200:                return (EIO);
                    201:        }
                    202:        splx (s);
                    203:        DELAY (300);
                    204:        val = inb (as_port + AS_STATUS);
                    205: 
                    206:        if (val & AS_STATUS_INIT)
                    207:                printf ("as: mailbox init error: 0x%x\n", val);
                    208: }
                    209: 
                    210: int
                    211: ascmd (as, bp, direction, count, retrycount)
                    212: struct asinfo *as;
                    213: struct buf *bp;
                    214: int direction;
                    215: int count;
                    216: int retrycount;
                    217: {
                    218:        int err;
                    219: 
                    220:        do {
                    221:                if (asverbose)
                    222:                        printf ("ascmd ");
                    223:                bp->b_bcount = count;
                    224:                bp->b_error = 0;
                    225:                bp->b_flags &= ~(B_READ | B_ERROR | B_DONE);
                    226:                if (direction == B_READ)
                    227:                        bp->b_flags |= B_READ;
                    228: 
                    229:                bp->b_dev = as->dev;
                    230:                bp->b_blkno = 0;
                    231: 
                    232:                as->scsi_bp = bp;
                    233:                /* scsi_cdb, scsi_cdb_len set up by caller */
                    234: 
                    235:                asstrategy (bp);
                    236:                err = biowait (bp);
                    237:                as->scsi_bp = NULL;
                    238:                
                    239:        } while (err && --retrycount);
                    240: 
                    241:        return (err);
                    242: }
                    243: 
                    244: asstring (dest, src, size)
                    245: char *dest;
                    246: char *src;
                    247: int size;
                    248: {
                    249:        size--;
                    250:        bcopy (src, dest, size);
                    251:        while (size > 0 && dest[size - 1] == ' ')
                    252:                size--;
                    253:        dest[size] = 0;
                    254: }
                    255: 
                    256: asopen (dev, flag)
                    257: dev_t dev;
                    258: int flag;
                    259: {
                    260:        struct asinfo *as;
                    261:        unsigned int physaddr;
                    262:        struct buf *bp = NULL;
                    263:        int retry;
                    264:        unsigned char *cdb;
                    265:        char *p, *q;
                    266:        int n;
                    267:        int error;
                    268:        char vendor[9];
                    269:        char model[17];
                    270:        int disksize;
                    271: 
                    272:        if (as_port == 0 || dev_target (dev) >= NTARGETS)
                    273:                return (ENXIO);
                    274: 
                    275:        as = &asinfo[dev_target (dev)];
                    276:        as->dev = dev;
                    277: 
                    278:        while (as->open_lock)
                    279:                if (error = tsleep ((caddr_t)as, PZERO|PCATCH, "scsiopen", 0))
                    280:                        return (error);
                    281: 
                    282:        if (as->open) {
                    283:                if (as->tape)
                    284:                        return (EBUSY);
                    285: 
                    286:                if (as->have_label == 0 && dev_part (dev) != 3)
                    287:                        return (ENXIO);
                    288:                
                    289:                as->units_open |= 1 << dev_part (dev);
                    290:                return (0);
                    291:        }
                    292: 
                    293:        as->open_lock = 1;
                    294: 
                    295:        /* it seems like we might have to block here in case someone
                    296:         * opens the device just after someone else closes
                    297:         */
                    298:        while (as->scsi_lock)
                    299:                if (error = tsleep ((caddr_t)as, PZERO|PCATCH, "scsicmd", 0))
                    300:                        return (error);
                    301: 
                    302:        as->scsi_lock = 1;
                    303: 
                    304:        error = EIO;
                    305: 
                    306:        as->have_label = 0;
                    307:        as->tape = 0;
                    308:        as->disk = 0;
                    309:        as->read_only = 0;
                    310:        as->removable = 0;
                    311:        bcopy(as->vendor, vendor, sizeof(vendor));
                    312:        bcopy(as->model, model, sizeof(model));
                    313:        as->vendor[0] = 0;
                    314:        as->model[0] = 0;
                    315:        as->revision[0] = 0;
                    316: 
                    317:        bp = geteblk (DEV_BSIZE);
                    318: 
                    319:        if (asverbose) {
                    320:                printf ("openbuf = 0x%x phys 0x%x\n",
                    321:                        bp->b_un.b_addr, vtophys (bp->b_un.b_addr));
                    322:                printf ("mailboxes = 0x%x\n", mailboxes);
                    323:        }
                    324: 
                    325:        /* first, find out if a device is present, and just what it is */
                    326:        as->scsi_cdb_len = 6;
                    327:        cdb = as->scsi_cdb;
                    328:        bzero (cdb, 6);
                    329:        cdb[0] = 0x12; /* INQUIRY */
                    330:        cdb[4] = 255; /* allocation length */
                    331:        if (error = ascmd (as, bp, B_READ, DEV_BSIZE, 2))
                    332:                /* does not respond to inquiry, obviously not CCS, give up */
                    333:                goto done;
                    334: 
                    335:        
                    336:        /* blather on console about it */
                    337:        p = bp->b_un.b_addr;
                    338:        if (asverbose) {
                    339:                printf ("inquiry: ");
                    340:                for (n = 0; n < 20; n++)
                    341:                        printf ("%x ", p[n] & 0xff);
                    342:                printf ("\n");
                    343:                for (n = 0; n < 40; n++) {
                    344:                        if (p[n] >= ' ' && p[n] < 0177)
                    345:                                printf ("%c", p[n]);
                    346:                        else
                    347:                                printf (".");
                    348:                }
                    349:                printf ("\n");
                    350:        }
                    351: 
                    352:        switch (p[0]) {
                    353:        case 0: /* normal disk */
                    354:        case 4: /* write once disk */
                    355:                as->disk = 1;
                    356:                break;
                    357:        case 5: /* read only disk */
                    358:                as->read_only = 1;
                    359:                as->disk = 1;
                    360:                break;
                    361:        case 1: /* tape */
                    362:                as->tape = 1;
                    363:                break;
                    364:        case 0x7f:
                    365:                printf ("logical unit not present\n");
                    366:                goto done;
                    367:        default:
                    368:                printf ("unknown peripheral device type: 0x%x\n", p[0]);
                    369:                goto done;
                    370:        }
                    371: 
                    372:        as->removable = (p[1] & 0x80) ? 1 : 0;
                    373: 
                    374:        n = p[4] & 0xff;
                    375:        if (n >= 31) {
                    376:                asstring (as->vendor, p + 8, sizeof as->vendor);
                    377:                asstring (as->model, p + 16, sizeof as->model);
                    378:                asstring (as->revision, p + 32, sizeof as->revision);
                    379:        }
                    380: 
                    381:        if(bcmp(as->vendor,vendor, sizeof(vendor)) != 0 ||
                    382:                bcmp(as->model,model, sizeof(model)) != 0) {
                    383:                printf("as%d: attached tgt %d <%s %s %s> ",  0, dev_target(dev),
                    384:                        as->vendor, as->model, as->revision);
                    385:                if (as->read_only) printf("readonly ");
                    386:                if (!as->removable) printf("winchester ");
                    387:                if (as->tape) printf("tape ");
                    388:                if (as->disk) printf("disk ");
                    389:                printf("\n");
                    390:        }
                    391: 
                    392:        /* probe for desired block size */
                    393: 
                    394:        /* assume default of 512, except if CDROM (2048) */
                    395:        if (as->read_only)
                    396:                as->bs = 2048;
                    397:        else
                    398:                as->bs = 512;
                    399: 
                    400:        bzero(cdb, 6);
                    401:        cdb[0] = 0x1A;  /* SCSI_MDSENSE */
                    402:        cdb[4] = 255;
                    403:        if (as->tape && ascmd (as, bp, B_READ, 12, 2) == 0)  {
                    404:                int minblk, maxblk;
                    405: 
                    406: #ifdef notdef
                    407:                /* blather about device more */
                    408:                if(bcmp(as->vendor,vendor, sizeof(vendor)) != 0 ||
                    409:                        bcmp(as->model,model, sizeof(model)) != 0) {
                    410:                        p = bp->b_un.b_addr;
                    411:                        printf("as%d: data len %d medium %d speed/bufmode 0x%x desc len %d\n",
                    412:                                dev_target(dev), p[0], p[1], p[2], p[3]);
                    413:                        printf("as%d: density %d nblocks %d block len %d\n",
                    414:                                dev_target(dev), p[4],
                    415:                                (long)p[5]*65536+p[6]*256+p[7],
                    416:                                (long)p[9]*65536+p[10]*256+p[11]);
                    417:                }
                    418: #endif
                    419:                
                    420:                /* obtain possible block sizes */
                    421:                bzero(cdb, 6);
                    422:                cdb[0] = 0x05; /* SCSI_RDLIMITS; */
                    423:                if (ascmd (as, bp, B_READ, 12, 2) == 0) {
                    424:                        p = bp->b_un.b_addr;
                    425:                        minblk = p[4]*256+p[5];
                    426:                        maxblk = p[1]*65536+p[2]*256+p[3];
                    427: #ifdef notdef
                    428:                        if(bcmp(as->vendor,vendor, sizeof(vendor)) != 0 ||
                    429:                                bcmp(as->model,model, sizeof(model)) != 0) {
                    430:                                printf("as%d: limits: min block len %ld  max block len %ld\n",
                    431:                                        dev_target(dev), minblk, maxblk);
                    432:                        }
                    433: #endif
                    434:                        if ( minblk == maxblk )
                    435:                                as->bs = minblk;
                    436:                        else if (as->tape)
                    437:                                as->bs = 1;
                    438:                }
                    439:        }
                    440:        
                    441:        as->scsi_cdb_len = 10;
                    442:        bzero(cdb, 10);
                    443:        cdb[0] = 0x25;  /* SCSI_READCAPACITY */
                    444:        disksize = 0;
                    445:        if (as->disk && ascmd (as, bp, B_READ, 12, 2) == 0)  {
                    446:                p = bp->b_un.b_addr;
                    447:                disksize = ntohl(*(long *)p);
                    448:                as->bs = ntohl(*(long *)(p+4));
                    449:                
                    450:        }
                    451: 
                    452: if(asverbose)
                    453:        printf("block size %d disksize %d ", as->bs, disksize);
                    454: 
                    455: 
                    456:        /* for standard disk, negotiate block size */
                    457:        if (as->read_only == 0 && as->disk) {
                    458:                /* do mode select to set the logical block size */
                    459:                as->scsi_cdb_len = 6;
                    460:                cdb = as->scsi_cdb;
                    461:                bzero (cdb, 6);
                    462:                cdb[0] = 0x15; /* MODE SELECT */
                    463:                cdb[4] = 12; /* parameter list length */
                    464:        
                    465:                p = bp->b_un.b_addr;
                    466:                bzero (p, 12);
                    467:                p[3] = 8; /* block descriptor length */
                    468:                n = as->bs == 1 ? 0 : as->bs;
                    469:                p[9] = n >> 16;
                    470:                p[10] = n >> 8;
                    471:                p[11] = n;
                    472:        
                    473:                (void) ascmd (as, bp, B_WRITE, 12, 2);
                    474:        }
                    475: 
                    476:        /* device online and ready? */
                    477:        as->scsi_cdb_len = 6;
                    478:        bzero(cdb, 6);
                    479:        cdb[0] = 0x00;  /* SCSI_UNITRDY */
                    480:        if (error = ascmd (as, bp, B_READ, 12, 2)) {
                    481:                printf("as%d: drive not online\n", dev_target(dev));
                    482:                goto done;
                    483:        }
                    484: 
                    485:        if (as->disk && as->read_only == 0) {
                    486:                /* read disk label */
                    487:                bzero ((caddr_t)&as->label, sizeof as->label);
                    488:                as->label.d_secsize = as->bs;
                    489:                as->label.d_secpercyl = 64*32;
                    490:                as->label.d_type = DTYPE_SCSI;
                    491: 
                    492:                
                    493:                /* read label using "d" partition */
                    494:                if ((p = readdisklabel (
                    495:                        makeasdev (major (dev), dev_target (dev), 3),
                    496:                        asstrategy, &as->label, as->dospart, 0, 0)) == NULL){
                    497:                        as->have_label = 1;
                    498:                } else {
                    499:                        if (disksize) {
                    500:                                as->label.d_subtype = DSTYPE_GEOMETRY;
                    501:                                as->label.d_npartitions = 3;
                    502:                                /* partition 0  holds bios, partition 1 ESDI */
                    503:                                as->label.d_partitions[2].p_size = disksize;
                    504:                                as->label.d_partitions[2].p_offset = 0;
                    505:                        }
                    506:                        if (asverbose || dev_part (dev) != 3)
                    507:                                printf ("error reading label: %s\n", p);
                    508:                        if (dev_part (dev) != 3) {
                    509:                                error = EINVAL;
                    510:                                goto done;
                    511:                        }
                    512:                }
                    513:        }
                    514: 
                    515:        /* may want to set logical block size here ? */
                    516:        error = 0;
                    517: 
                    518:  done:
                    519:        if (bp) {
                    520:                bp->b_flags |= B_INVAL | B_AGE;
                    521:                brelse (bp);
                    522:        }
                    523: 
                    524:        if (error == 0)
                    525:                as->open = 1;
                    526: 
                    527:        as->open_lock = 0;
                    528:        as->scsi_lock = 0;
                    529:        wakeup (as);
                    530: 
                    531:        return (error);
                    532: }
                    533: 
                    534: asclose (dev, flag)
                    535: dev_t dev;
                    536: {
                    537:        struct asinfo *as;
                    538:        int error = 0;
                    539:        unsigned char *cdb;
                    540:        struct buf *bp;
                    541:        int n;
                    542: 
                    543:        as = &asinfo[dev_target (dev)];
                    544: 
                    545:        while (as->open_lock)
                    546:                if (error = tsleep ((caddr_t)as, PZERO|PCATCH, "scsiclose", 0))
                    547:                        return (error);
                    548: 
                    549:        as->open_lock = 1;
                    550: 
                    551:        if (as->tape) {
                    552:                while (as->scsi_lock)
                    553:                        if (error = tsleep ((caddr_t)as, PZERO|PCATCH,
                    554:                                            "scsicmd", 0))
                    555:                                return (error);
                    556: 
                    557:                as->scsi_lock = 1;
                    558:                
                    559:                bp = geteblk (DEV_BSIZE);
                    560: 
1.1.1.2 ! root      561:              if ((flag & FWRITE) != 0) {
1.1       root      562:                              /* presume user will use tape again */
                    563:                      as->scsi_cdb_len = 6;
                    564:                      cdb = as->scsi_cdb;
                    565:                      bzero (cdb, 6);
                    566:                      cdb[0] = 0x10; /* write filemarks */
                    567:                      cdb[4] = 1; /* one of them */
                    568:                      error = ascmd (as, bp, B_READ, 0, 1);
                    569:              }
                    570:              if (dev_rewind (dev) || error) {
                    571:                      if ( error == 0 && (flag & FWRITE) != 0) {
                    572:                                      /* presumption error correction */
                    573:                              as->scsi_cdb_len = 6;
                    574:                              cdb = as->scsi_cdb;
                    575:                              bzero (cdb, 6);
                    576:                              cdb[0] = 0x10; /* write filemarks */
                    577:                              cdb[4] = 1; /* one of them */
                    578:                              error |= ascmd (as, bp, B_READ, 0, 1);
                    579:                      }
                    580:                      as->scsi_cdb_len = 6;
                    581:                      cdb = as->scsi_cdb;
                    582:                      bzero (cdb, 6);
                    583:                      cdb[0] = 0x1; /* rewind */
                    584:                      cdb[1] = 1; /* don't wait until done */
                    585:                      error |= ascmd (as, bp, B_READ, 0, 1);
                    586:              }
                    587: #ifdef notdef
                    588:                } else {
                    589:                        cdb[0] = 0x11; /* backspace */
                    590:                        cdb[1] = 1; /* look at filemarks (instead of blocks) */
                    591:                        n = -1;
                    592:                        cdb[2] = n >> 16;
                    593:                        cdb[3] = n >> 8;
                    594:                        cdb[4] = n;
                    595:                        error = ascmd (as, bp, B_READ, 0, 1);
                    596:                } 
                    597: #endif
                    598: 
                    599:                bp->b_flags |= B_INVAL | B_AGE;
                    600:                brelse (bp);
                    601: 
                    602:                as->scsi_lock = 0;
                    603:        }
                    604: 
                    605:        as->units_open &= ~(1 << dev_part (dev));
                    606: 
                    607:        if (as->units_open == 0)
                    608:                as->open = 0;
                    609: 
                    610:        as->open_lock = 0;
                    611: 
                    612:        wakeup (as);
                    613: 
                    614:        return (error);
                    615: }
                    616: 
                    617: int
                    618: asioctl (dev, cmd, addr, flag)
                    619: dev_t dev;
                    620: int cmd;
                    621: caddr_t addr;
                    622: int flag;
                    623: {
                    624:        struct scsicmd *cmdp;
                    625:        struct asinfo *as;
                    626:        int ccblen;
                    627:        struct buf *bp;
                    628:        int error = 0;
                    629:        int direction;
                    630:        struct disklabel *dl;
                    631:        int old_wlabel;
                    632: 
                    633:        as = &asinfo[dev_target (dev)];
                    634: 
                    635:        switch (cmd) {
                    636:        case DIOCGDINFO:
                    637:                *(struct disklabel *)addr = as->label;
                    638:                break;
                    639: 
                    640:         case DIOCSDINFO:
                    641:                 if ((flag & FWRITE) == 0) {
                    642:                         error = EBADF;
                    643:                        break;
                    644:                }
                    645:                dl = (struct disklabel *)addr;
                    646:                if (error = setdisklabel(&as->label, dl, 0, as->dospart))
                    647:                        break;
                    648:                as->have_label = 1;
                    649:                 break;
                    650: 
                    651:         case DIOCWLABEL:
                    652:                 if ((flag & FWRITE) == 0) {
                    653:                         error = EBADF;
                    654:                        break;
                    655:                }
                    656:                as->wlabel = *(int *)addr;
                    657:                 break;
                    658: 
                    659:         case DIOCWDINFO:
                    660:                 if ((flag & FWRITE) == 0) {
                    661:                         error = EBADF;
                    662:                        break;
                    663:                }
                    664: 
                    665:                dl = (struct disklabel *)addr;
                    666: 
                    667:                if (error = setdisklabel (&as->label, dl, 0, as->dospart))
                    668:                        break;
                    669: 
                    670:                as->have_label = 1;
                    671: 
                    672:                old_wlabel = as->wlabel;
                    673:                as->wlabel = 1;
                    674:                error = writedisklabel(dev, asstrategy, &as->label,
                    675:                                as->dospart);
                    676:                as->wlabel = old_wlabel;
                    677:                 break;
                    678: 
                    679:        case SCSICMD:
                    680:                cmdp = (struct scsicmd *)addr;
                    681: 
                    682:                /* limited by max sizeof of geteblk */
                    683:                if (cmdp->datalen >= 8192 
                    684:                    || cmdp->cdblen >= MAXCDB) {
                    685:                        error = EINVAL;
                    686:                        break;
                    687:                }
                    688: 
                    689:                ccblen = cmdp->ccblen;
                    690:                if (ccblen > sizeof (struct ccb))
                    691:                        ccblen = sizeof (struct ccb);
                    692: 
                    693:                while (as->scsi_lock)
                    694:                        if (error = tsleep ((caddr_t)as, PZERO|PCATCH,
                    695:                                            "scsicmd", 0))
                    696:                                break;
                    697: 
                    698:                as->scsi_lock = 1;
                    699:                        
                    700:                bp = geteblk (cmdp->datalen);
                    701: 
                    702:                as->scsi_cdb_len = cmdp->cdblen;
                    703:                if (error = copyin (cmdp->cdb, as->scsi_cdb, cmdp->cdblen))
                    704:                        goto done;
                    705:                
                    706:                direction = cmdp->readflag ? B_READ : B_WRITE;
                    707: 
                    708:                if (direction == B_WRITE)
                    709:                        if (error = copyin (cmdp->data,
                    710:                                            bp->b_un.b_addr, cmdp->datalen))
                    711:                                goto done;
                    712:                
                    713:                ascmd (as, bp, direction, cmdp->datalen, 1);
                    714: 
                    715:                copyout (&as->ccb, cmdp->ccb, ccblen);
                    716:                if (direction == B_READ)
                    717:                        copyout (bp->b_un.b_addr, cmdp->data, cmdp->datalen);
                    718:        done:
                    719:                bp->b_flags |= B_INVAL | B_AGE;
                    720:                brelse (bp);
                    721:                as->scsi_lock = 0;
                    722:                wakeup (as);
                    723:                break;
                    724:        default:
                    725:                error = ENOTTY;
                    726:                break;
                    727:        }
                    728:        return (error);
                    729: }
                    730: 
                    731: int
                    732: asstrategy (bp)
                    733: struct buf *bp;
                    734: {
                    735:        struct asinfo *as;
                    736:        int s;
                    737: 
                    738:        if (asverbose)
                    739:                printf ("asstrategy %d %d ", bp->b_blkno, bp->b_bcount);
                    740:        s = splbio ();
                    741: 
                    742:        as = &asinfo[dev_target (bp->b_dev)];
                    743:        
                    744:        if (as->tape) {
                    745:                bp->av_forw = NULL;
                    746:                if (as->requests.b_actf)
                    747:                        as->requests.b_actl->av_forw = bp;
                    748:                else
                    749:                        as->requests.b_actf = bp;
                    750:                as->requests.b_actl = bp;
                    751:        } else {
                    752:                if (bp != as->scsi_bp
                    753:                    && as->have_label == 0
                    754:                    && dev_part (bp->b_dev) != 3)
                    755:                        goto bad;
                    756: 
                    757:                bp->b_cylin = bp->b_blkno;
                    758:                disksort (&as->requests, bp);
                    759:        }
                    760:        
                    761:        if (as->active == 0)
                    762:                asstart (as);
                    763: 
                    764:        splx (s);
                    765:        return;
                    766: 
                    767:  bad:
                    768:        bp->b_flags |= B_ERROR;
                    769:        biodone (bp);
                    770: }
                    771: 
                    772: asrestart (as)
                    773: struct asinfo *as;
                    774: {
                    775:        int s;
                    776:        s = splbio ();
                    777:        as->restart_pending = 0;
                    778:        as->retry_count++;
                    779:        asstart (as);
                    780:        splx (s);
                    781: }
                    782: 
                    783: asstart (as)
                    784: struct asinfo *as;
                    785: {
                    786:        struct buf *bp;
                    787:        int blknum;
                    788:        unsigned int physaddr;
                    789:        struct ccb *ccb;
                    790:        unsigned char *cdb;
                    791:        int target;
                    792:        char *p;
                    793:        int n;
                    794:        char *sp;
                    795:        int nscatter;
                    796:        int thistime;
                    797:        int nbytes;
                    798:        struct partition *part;
                    799:        int blkno;
                    800:        int nblocks;
                    801:        int total;
                    802:        int bs = as->bs;
                    803: 
                    804: 
                    805:        if (as->restart_pending) {
                    806:                as->restart_pending = 0;
                    807:                untimeout (asrestart, as);
                    808:        }
                    809: 
                    810:  again:
                    811:        if ((bp = as->requests.b_actf) == NULL)
                    812:                return;
                    813: 
                    814:        bp->b_error = 0;
                    815: 
                    816:        if (asverbose)
                    817:                printf ("asstart %x ", bp);
                    818: 
                    819:        if (as->mailbox->cmd != 0) {
                    820:                /* this can't happen, unless the card flakes */
                    821:                printf ("asstart: mailbox not available\n");
                    822:                bp->b_error = EIO;
                    823:                goto bad;
                    824:        }
                    825: 
                    826:        if (as->retry_count == 0) {
                    827:                as->start_time = time.tv_sec;
                    828:        } else {
                    829:                if (time.tv_sec - as->start_time > 60) {
                    830:                        printf ("as: command timed out\n");
                    831:                        bp->b_error = EIO;
                    832:                        goto done;
                    833:                }
                    834:        }
                    835: 
                    836:        if (bp != as->scsi_bp) {
                    837:                if (bp->b_bcount == 0)
                    838:                        goto done;
                    839: 
                    840:                if ((bp->b_bcount % bs) != 0) {
                    841:                        printf("as: partial block read\n");
                    842:                        bp->b_error = EIO;
                    843:                        goto bad;
                    844:                }
                    845:        }
                    846: 
                    847:        if (bp != as->scsi_bp) {
                    848: 
                    849:                blkno = bp->b_blkno;
                    850:                nblocks = bp->b_bcount / bs;
                    851: 
                    852:                if (as->have_label && dev_part(bp->b_dev) != 3) {
                    853:                        part = &as->label.d_partitions[dev_part (bp->b_dev)];
                    854:                        
                    855:                        if (blkno > part->p_size) {
                    856:                                bp->b_error = EINVAL;
                    857:                                goto bad;
                    858:                        }
                    859:                        if (blkno == part->p_size) {
                    860:                                bp->b_resid = bp->b_bcount;
                    861:                                goto done;
                    862:                        }
                    863:                        
                    864:                        if (blkno + nblocks >= part->p_size)
                    865:                                nblocks = part->p_size - blkno;
                    866:                        
                    867:                        blkno += part->p_offset;
                    868:                } else
                    869:                        blkno = (blkno * DEV_BSIZE)/bs;
                    870: if(asverbose)
                    871:        printf("trans %d ", blkno);
                    872:                if (nblocks > 255)
                    873:                        nblocks = 255;
                    874:                total = nblocks * bs;
                    875: if(asverbose)
                    876: printf("total %d nblocks %d ", total, nblocks);
                    877:                /*bp->b_bcount = total; /* XXX partial tape block read - wrong */
                    878:        } else {
                    879: #ifdef nomore
                    880:                if (as->fixed == 0) {
                    881:                        total = bp->b_bcount;
                    882:                } else {
                    883:                        total = bp->b_bcount;
                    884:                        blkno = bp->b_blkno;
                    885:                        nblocks = bp->b_bcount / as->fixed;
                    886:                }
                    887: #else
                    888:                total = bp->b_bcount;
                    889: #endif
                    890:        }
                    891: 
                    892:        p = bp->b_un.b_addr;
                    893:        n = 0;
                    894:        sp = as->scatter_list;
                    895:        nscatter = 0;
1.1.1.2 ! root      896:        if (as->tape && as->bs == 1)
        !           897:                total = bp->b_bcount;
1.1       root      898:        while (n < total && nscatter < NSCATTER) {
                    899:                thistime = page_size - ((vm_offset_t)p - trunc_page (p));
                    900: 
                    901:                if (n + thistime > total)
                    902:                        thistime = total - n;
                    903: 
                    904:                physaddr = vtophys (p);
                    905:                
                    906:                if (asverbose)
                    907:                        printf ("%d bytes to %x (%x)\n",
                    908:                                thistime, p, physaddr);
                    909:                sp[0] = thistime >> 16;
                    910:                sp[1] = thistime >> 8;
                    911:                sp[2] = thistime;
                    912:                sp[3] = physaddr >> 16;
                    913:                sp[4] = physaddr >> 8;
                    914:                sp[5] = physaddr;
                    915:                
                    916:                p += thistime;
                    917:                n += thistime;
                    918:                sp += 6;
                    919:                nscatter++;
                    920:        }
                    921:        
                    922:        if (nscatter == NSCATTER) {
                    923:                printf("out of range, cannot happen?");
                    924:                bp->b_error = ENXIO;
                    925:                goto bad;
                    926:        }
                    927: 
                    928:        ccb = &as->ccb;
                    929: 
                    930:        /* this only needed to make debugging easier */
                    931:        bzero ((caddr_t)ccb, sizeof *ccb); 
                    932: 
                    933:        if (nscatter)
1.1.1.2 ! root      934:                ccb->ccb_opcode = 2; /* scatter cmd, return resid */
1.1       root      935:        else
1.1.1.2 ! root      936:                ccb->ccb_opcode = 0;
1.1       root      937:        target = dev_target (bp->b_dev);
                    938:        ccb->ccb_addr_and_control = target << 5;
                    939:        if (bp->b_bcount != 0)
                    940:                ccb->ccb_addr_and_control |= (bp->b_flags & B_READ) ? 8 : 0x10;
                    941:        else
                    942:                ccb->ccb_addr_and_control |= 0x18;
                    943: 
                    944:        nbytes = nscatter * 6;
                    945:        ccb->ccb_data_len_msb = nbytes >> 16;
                    946:        ccb->ccb_data_len_mid = nbytes >> 8;
                    947:        ccb->ccb_data_len_lsb = nbytes;
                    948: 
                    949:        ccb->ccb_requst_sense_allocation_len = MAXSENSE;
                    950: 
                    951:        physaddr = vtophys (as->scatter_list);
                    952:        ccb->ccb_data_ptr_msb = physaddr >> 16;
                    953:        ccb->ccb_data_ptr_mid = physaddr >> 8;
                    954:        ccb->ccb_data_ptr_lsb = physaddr;
                    955: 
                    956:        ccb->ccb_link_msb = 0;
                    957:        ccb->ccb_link_mid = 0;
                    958:        ccb->ccb_link_lsb = 0;
                    959:        ccb->ccb_link_id = 0;
                    960:        ccb->ccb_host_status = 0;
                    961:        ccb->ccb_target_status = 0;
                    962:        ccb->ccb_zero1 = 0;
                    963:        ccb->ccb_zero2 = 0;
                    964: 
                    965:        cdb = ccb->ccb_cdb;
                    966:        if (bp == as->scsi_bp) {
                    967:                ccb->ccb_scsi_command_len = as->scsi_cdb_len;
                    968:                bcopy (as->scsi_cdb, cdb, as->scsi_cdb_len);
                    969:        } else if (as->tape) {
                    970:                ccb->ccb_scsi_command_len = 6;
                    971:                cdb[0] = (bp->b_flags & B_READ) ? 8 : 0xa;
                    972:                if (as->bs == 1) {
                    973:                        cdb[1] = 0; /* logical unit 0, variable block size */
                    974:                        cdb[2] = bp->b_bcount >> 16;
                    975:                        cdb[3] = bp->b_bcount >> 8;
                    976:                        cdb[4] = bp->b_bcount;
                    977:                } else {
                    978:                        cdb[1] = 1;     /* fixed block size */
                    979:                        cdb[2] = nblocks >> 16;
                    980:                        cdb[3] = nblocks >> 8;
                    981:                        cdb[4] = nblocks;
                    982:                }
                    983:                cdb[5] = 0; /* control byte (used in linking) */
                    984:        } else {
                    985:                ccb->ccb_scsi_command_len = 10;
                    986:                cdb[0] = (bp->b_flags & B_READ) ? 0x28 : 0x2a;
                    987:                cdb[1] = 0;
                    988:                *(long *) (cdb+2) = htonl(blkno);
                    989:                *(short *) (cdb+7) = htons(nblocks);
                    990:                cdb[9] = 0; /* control byte (used in linking) */
                    991:        }
                    992: 
                    993: #ifdef notdef
                    994:        if (asverbose) {
                    995:                printf ("ccb: ");
                    996:                for (n = 0; n < 48; n++)
                    997:                        printf ("%02x ", ((unsigned char *)ccb)[n]);
                    998:                printf ("\n");
                    999:        }
                   1000: #endif
                   1001: 
                   1002:        physaddr = vtophys (ccb);
                   1003:        as->mailbox->msb = physaddr >> 16;
                   1004:        as->mailbox->mid = physaddr >> 8;
                   1005:        as->mailbox->lsb = physaddr;
                   1006:        as->mailbox->cmd = 1;
                   1007:        
                   1008:        /* tell controller to look in its mailbox */
                   1009:        as_put_byte (AS_CMD_START_SCSI_COMMAND);
                   1010:        as->active = 1;
                   1011:        timeout (asabort, as, hz * 60 * 2);
                   1012:        return;
                   1013: 
                   1014:  bad:
                   1015:        bp->b_flags |= B_ERROR;
                   1016:  done:
                   1017:        asdone (as, 0);
                   1018:        goto again;
                   1019: }
                   1020: 
                   1021: asabort (as)
                   1022: struct asinfo *as;
                   1023: {
                   1024:        int s;
                   1025:        int physaddr;
                   1026:        struct buf *bp;
                   1027: 
                   1028:        s = splbio ();
                   1029:        if (as->active) {
                   1030:                printf ("asabort %d\n", as - asinfo);
                   1031:                physaddr = vtophys (&as->ccb);
                   1032:                as->mailbox->msb = physaddr >> 16;
                   1033:                as->mailbox->mid = physaddr >> 8;
                   1034:                as->mailbox->lsb = physaddr;
                   1035:                as->mailbox->cmd = 2;
                   1036:                as_put_byte (AS_CMD_START_SCSI_COMMAND);
                   1037: 
                   1038:                as->active = 0;
                   1039:                bp = as->requests.b_actf;
                   1040:                if (bp) {
                   1041:                        bp->b_flags |= B_ERROR;
                   1042:                        asdone (as, 1);
                   1043:                }
                   1044:        }
                   1045:        splx (s);
                   1046: }
                   1047: 
                   1048: asintr (dev_t dev)
                   1049: {
                   1050:        int didwork;
                   1051:        int i, j;
                   1052:        struct mailbox_entry *mp;
                   1053:        unsigned int physaddr;
                   1054:        int val;
                   1055: 
                   1056:        outb (as_port + AS_CONTROL, AS_CONTROL_IRST);
                   1057: #ifdef notdef
                   1058:        if (asverbose)
                   1059:                printf ("asintr %x ", cpl);
                   1060: #endif
                   1061:  again:
                   1062:        didwork = 0;
                   1063:        for (i = NTARGETS; i < NTARGETS * 2; i++) {
                   1064:                mp = &mailboxes[i];
                   1065:                
                   1066:                if ((val = mp->cmd) == 0)
                   1067:                        continue;
                   1068:                
                   1069:                didwork = 1;
                   1070: 
                   1071:                physaddr = (mp->msb << 16)
                   1072:                        | (mp->mid << 8)
                   1073:                                | mp->lsb;
                   1074:                
                   1075:                for (j = 0; j < NTARGETS; j++) {
                   1076:                        if (asinfo[j].ccb_phys == physaddr) {
                   1077:                                mp->cmd = 0;
                   1078:                                asintr1 (&asinfo[j], val);
                   1079:                                break;
                   1080:                        }
                   1081:                }
                   1082:                if (j == NTARGETS) {
                   1083:                        printf ("as: unknown mailbox paddr 0x%x\n", physaddr);
                   1084:                        mp->cmd = 0;
                   1085:                }
                   1086:        }
                   1087: 
                   1088:        if (didwork)
                   1089:                goto again;
                   1090: }
                   1091: 
                   1092: asintr1 (as, val)
                   1093: struct asinfo *as;
                   1094: int val;
                   1095: {
                   1096:        struct buf *bp;
                   1097:        struct ccb *ccb;
                   1098:        int n;
                   1099:        int bad;
                   1100:        char *msg;
                   1101:        char msgbuf[100];
                   1102:        unsigned char *sp;
                   1103:        int i,key;
                   1104: 
                   1105:        if (asverbose)
                   1106:                printf ("asintr1 %x ", val);
                   1107:        if (as->active == 0) {
                   1108:                printf ("as: stray intr 0x%x\n", as->dev);
                   1109:                return;
                   1110:        }
                   1111: 
                   1112:        as->active = 0;
                   1113:        untimeout (asabort, as);
                   1114:        
                   1115:        bp = as->requests.b_actf;
                   1116:        ccb = &as->ccb;
                   1117: 
                   1118:        if (bp == as->scsi_bp) {
                   1119:                /* no fancy error recovery in this case */
                   1120:                if (asverbose)
                   1121:                        printf ("asintr1:scsicmd ");
                   1122: #if 0
                   1123:                if (val != 1)
                   1124:                        bp->b_flags |= B_ERROR;
                   1125:                goto next;
                   1126: #endif
                   1127:        }
                   1128: 
                   1129:        bad = 0;
                   1130:        msg = NULL;
                   1131: 
                   1132:        if (val != 1 && val != 4) {
                   1133:                bad = 1;
                   1134:                sprintf (msgbuf, "funny mailbox message 0x%x\n", val);
                   1135:                msg = msgbuf;
                   1136:                goto wrapup;
                   1137:        }
                   1138: 
                   1139:        if (ccb->ccb_host_status != 0) {
                   1140:                bad = 1;
                   1141:                sprintf (msgbuf, "controller error 0x%x",
                   1142:                         ccb->ccb_host_status);
                   1143:                msg = msgbuf;
                   1144:                goto wrapup;
                   1145:        }
                   1146: 
                   1147:        if (ccb->ccb_target_status == 0)
                   1148:                /* good transfer */
                   1149:                goto wrapup;
                   1150: 
                   1151:        if (ccb->ccb_target_status == 8) {
                   1152:                /* target rejected command because it is busy
                   1153:                 * and wants us to try again later.  We'll wait 1 second
                   1154:                 */
                   1155:                as->restart_pending = 1;
                   1156:                timeout (asrestart, as, hz);
                   1157:                return;
                   1158:        }
                   1159: 
                   1160:        if (ccb->ccb_target_status != 2) {
                   1161:                bad = 1;
                   1162:                sprintf (msgbuf, "target error 0x%x",
                   1163:                         ccb->ccb_target_status);
                   1164:                msg = msgbuf;
                   1165:                goto wrapup;
                   1166:        }
                   1167: 
                   1168:        /* normal path for errors */
                   1169: 
                   1170:        sp = ccb_sense (ccb);
                   1171:        /* check for extended sense information */
                   1172:        if ((sp[0] & 0x7f) != 0x70) {
                   1173:                /* none */
                   1174:                bad = 1;
                   1175:                sprintf (msgbuf, "scsi error 0x%x", sp[0] & 0x7f);
                   1176:                msg = msgbuf;
                   1177:                goto wrapup;
                   1178:        }
                   1179:        
                   1180:        if (as->tape && (sp[2] & 0xf) == 0) {
                   1181:                if (sp[2] & 0xe0) {
                   1182:                        /* either we read a file mark, the early warning EOT,
                   1183:                         * or the block size did not match.  In any case, the
                   1184:                         * normal residue handling will work (I think)
                   1185:                         */
                   1186:                        goto wrapup;
                   1187:                }
                   1188:        }
                   1189: 
                   1190:        bad = 1;
                   1191: 
                   1192:        switch (key = sp[2] & 0xf) {
                   1193:        case 1: 
                   1194:                msg = "soft error";
                   1195:                bad = 0;
                   1196:                break;
                   1197:        case 2:
                   1198:                msg = "not ready";
                   1199:                break;
                   1200:        case 3:
                   1201:                msg = "hard error";
                   1202:                break;
                   1203:        case 4:
                   1204:                msg = "target hardware error";
                   1205:                break;
                   1206:        case 5:
                   1207:                msg = "illegal request";
                   1208:                break;
                   1209:        case 6:
                   1210:                msg = "unit attention error";
                   1211:                break;
                   1212:        case 7: 
                   1213:                msg = "write protect error";
                   1214:                break;
                   1215:        case 0xd:
                   1216:                msg = "volume overflow";
                   1217:                break;
                   1218:        default:
                   1219:                sprintf (msgbuf, "scsi extended error 0x%x", sp[2] & 0xf);
                   1220:                msg = msgbuf;
                   1221:                break;
                   1222:        }
                   1223: 
                   1224:  wrapup:
                   1225: 
                   1226:        if (bad && msg == NULL)
                   1227:                msg = "unknown error";
                   1228: 
                   1229:        if (msg && key != 6) {
                   1230:                diskerr (bp, "as", msg,
                   1231:                         LOG_PRINTF,
                   1232:                         -1, /* number of successful blks */
                   1233:                         as->have_label ? &as->label : NULL);
                   1234:                printf ("\n");
                   1235:        }
                   1236: 
                   1237:        if (bad && key != 6) {
                   1238:                bp->b_flags |= B_ERROR;
                   1239:                printf ("scsi sense: ");
                   1240:                sp = ccb_sense (ccb);
                   1241:                for (i = 0; i < 30; i++)
                   1242:                        printf ("%x ", sp[i] & 0xff);
                   1243:                printf ("\n");
                   1244:        }
                   1245: 
1.1.1.2 ! root     1246:        /* this assignment mixed sizes of controller commands
        !          1247:            and data to read/write.
        !          1248:        bp->b_resid = (ccb->ccb_data_len_msb << 16)
        !          1249:                | (ccb->ccb_data_len_mid << 8)
        !          1250:                        | ccb->ccb_data_len_lsb;
        !          1251:         */
        !          1252:        bp->b_resid = 0;
1.1       root     1253: 
                   1254:  next:
                   1255:        asdone (as, 1);
                   1256: }
                   1257: 
                   1258: asdone (as, restart)
                   1259: struct asinfo *as;
                   1260: int restart;
                   1261: {
                   1262:        struct buf *bp;
                   1263: 
                   1264:        bp = as->requests.b_actf;
                   1265:        as->requests.b_actf = bp->av_forw;
                   1266:        biodone (bp);
                   1267:        as->retry_count = 0;
                   1268:        if (restart && as->requests.b_actf)
                   1269:                asstart (as);
                   1270: }
                   1271: 
                   1272: int
                   1273: assize (dev)
                   1274: dev_t dev;
                   1275: {
                   1276:        struct asinfo *as;
                   1277:        struct disklabel *lp;
                   1278:        int val;
                   1279: 
                   1280:        if (as_port == 0 || dev_target (dev) >= NTARGETS)
                   1281:                return (ENXIO);
                   1282: 
                   1283:        as = &asinfo[dev_target (dev)];
                   1284: 
                   1285:        if (as->open == 0
                   1286:            && asopen (dev, FREAD, S_IFBLK, NULL) != 0)
                   1287:                return (0);
                   1288: 
                   1289:        if (as->have_label == 0)
                   1290:                return (0);
                   1291: 
                   1292:        lp = &as->label;
                   1293:        val = lp->d_partitions[dev_part (dev)].p_size
                   1294:                * lp->d_secsize / DEV_BSIZE;
                   1295:        (void) asclose(dev, FREAD, S_IFBLK, NULL);
                   1296:        return (val);
                   1297: }
                   1298: 
                   1299: int
                   1300: as_put_byte (val)
                   1301: int val;
                   1302: {
                   1303:        int i;
                   1304: 
                   1305:        for (i = 100; i > 0; i--) {
                   1306:                if ((inb (as_port + AS_STATUS) & AS_STATUS_CDF) == 0)
                   1307:                        break;
                   1308:                DELAY (100);
                   1309:        }
                   1310:        if (i == 0) {
                   1311:                printf ("as: put byte timed out\n");
                   1312:                return (-1);
                   1313:        }
                   1314:        outb (as_port + AS_DATA_OUT, val);
                   1315:        return (0);
                   1316: }
                   1317:                
                   1318: int
                   1319: as_get_byte (as)
                   1320: {
                   1321:        int i;
                   1322: 
                   1323:        for (i = 100; i > 0; i--) {
                   1324:                if ((inb (as_port + AS_STATUS) & AS_STATUS_DF) != 0)
                   1325:                        break;
                   1326:                DELAY (100);
                   1327:        }
                   1328:        if (i == 0) {
                   1329:                printf ("as_get_byte timed out\n");
                   1330:                return (-1);
                   1331:        }
                   1332:        return (inb (as_port + AS_DATA_OUT) & 0xff);
                   1333: }
                   1334: #endif /* NAS */

unix.superglobalmegacorp.com

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