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

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

unix.superglobalmegacorp.com

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