Annotation of Net2/arch/amiga/dev/sd.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1990 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Van Jacobson of Lawrence Berkeley Laboratory.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)sd.c        7.8 (Berkeley) 6/9/91
        !            37:  */
        !            38: 
        !            39: /*
        !            40:  * SCSI CCS (Command Command Set) disk driver.
        !            41:  */
        !            42: #include "sd.h"
        !            43: #if NSD > 0
        !            44: 
        !            45: #ifndef lint
        !            46: static char rcsid[] = "/b/source/CVS/src/sys/arch/amiga/dev/sd.c,v 1.1.1.1 1993/07/05 19:19:47 mw Exp";
        !            47: #endif
        !            48: 
        !            49: #include "sys/param.h"
        !            50: #include "sys/systm.h"
        !            51: #include "sys/buf.h"
        !            52: #include "sys/dkstat.h"
        !            53: #include "sys/disklabel.h"
        !            54: #include "sys/malloc.h"
        !            55: #include "sys/proc.h"
        !            56: #include "sys/reboot.h"
        !            57: #include "sys/file.h"
        !            58: 
        !            59: #include "device.h"
        !            60: #include "scsireg.h"
        !            61: #include "vm/vm_param.h"
        !            62: #include "vm/lock.h"
        !            63: #include "vm/vm_statistics.h"
        !            64: #include "vm/pmap.h"
        !            65: #include "vm/vm_prot.h"
        !            66: 
        !            67: #include "rdb.h"
        !            68: 
        !            69: struct sd_softc;
        !            70: 
        !            71: extern int sdinit (register struct amiga_device *ad);
        !            72: extern void sdreset (register struct sd_softc *sc, register struct amiga_device *ad);
        !            73: extern int sdopen (dev_t dev, int flags, int mode, struct proc *p);
        !            74: extern void sdstrategy (register struct buf *bp);
        !            75: extern void sdustart (register int unit);
        !            76: extern void sdstart (register int unit);
        !            77: extern void sdgo (register int unit);
        !            78: extern void sdintr (register int unit, int stat);
        !            79: extern int sdioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
        !            80: extern int sdsize (dev_t dev);
        !            81: extern int sddump (dev_t dev);
        !            82: static int sdident (struct sd_softc *sc, struct amiga_device *ad);
        !            83: static void sdlblkstrat (register struct buf *bp, register int bsize);
        !            84: static int sderror (int unit, register struct sd_softc *sc, register struct amiga_device *am, int stat);
        !            85: static void sdfinish (int unit, register struct sd_softc *sc, register struct buf *bp);
        !            86: 
        !            87: extern void disksort();
        !            88: extern int physio();
        !            89: extern void TBIS();
        !            90: 
        !            91: int    sdinit();
        !            92: void   sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr();
        !            93: 
        !            94: struct driver sddriver = {
        !            95:        sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr, 0,
        !            96: };
        !            97: 
        !            98: #if 0
        !            99: struct size {
        !           100:        u_long  strtblk;
        !           101:        u_long  endblk;
        !           102:        int     nblocks;
        !           103: };
        !           104: 
        !           105: struct sdinfo {
        !           106:        u_int   cylinders;      /* number of driver cylinders         RDB value */
        !           107:        u_int   sectors;        /* sectors per track                  RDB value */
        !           108:        u_int   heads;          /* number of drive heads              RDB value */
        !           109:        u_int   cylblocks;      /* available number of blocks per cyl RDB value */
        !           110:        struct  size part[8];
        !           111: };
        !           112: 
        !           113: /*
        !           114:  * since the SCSI standard tends to hide the disk structure, we define
        !           115:  * partitions in terms of DEV_BSIZE blocks.  The default partition table
        !           116:  * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg
        !           117:  * root and 32 meg of swap.  The rest of the space on the drive goes in
        !           118:  * the G partition.  As usual, the C partition covers the entire disk
        !           119:  * (including the boot area).
        !           120:  */
        !           121: struct sdinfo sddefaultpart = {
        !           122:             1024,   17408,   16384   , /* A */
        !           123:            17408,   82944,   65536   , /* B */
        !           124:                0,       0,       0   , /* C */
        !           125:            17408,  115712,   98304   , /* D */
        !           126:           115712,  218112,  102400   , /* E */
        !           127:           218112,       0,       0   , /* F */
        !           128:            82944,       0,       0   , /* G */
        !           129:           115712,       0,       0   , /* H */
        !           130: };
        !           131: #endif
        !           132: 
        !           133: struct sd_softc {
        !           134:        struct  amiga_device *sc_ad;
        !           135:        struct  devqueue sc_dq;
        !           136:        int     sc_format_pid;  /* process using "format" mode */
        !           137:        short   sc_flags;
        !           138:        short   sc_type;        /* drive type */
        !           139:        short   sc_punit;       /* physical unit (scsi lun) */
        !           140:        u_short sc_bshift;      /* convert device blocks to DEV_BSIZE blks */
        !           141:        u_int   sc_blks;        /* number of blocks on device */
        !           142:        int     sc_blksize;     /* device block size in bytes */
        !           143:        u_int   sc_wpms;        /* average xfer rate in 16 bit wds/sec. */
        !           144:        char    sc_idstr[32];   /* XXX */
        !           145:        struct  disklabel sc_label;  /* drive partition table & label info */
        !           146:        int     sc_have_label;
        !           147:        int     sc_write_label;
        !           148: } sd_softc[NSD];
        !           149: 
        !           150: /* sc_flags values */
        !           151: #define        SDF_ALIVE       0x1
        !           152: 
        !           153: #ifdef DEBUG
        !           154: int sddebug = 0;
        !           155: #define SDB_ERROR      0x01
        !           156: #define SDB_PARTIAL    0x02
        !           157: /*#define QUASEL*/
        !           158: #endif
        !           159: 
        !           160: #ifdef QUASEL
        !           161: #define QPRINTF(a) printf a
        !           162: #else
        !           163: #define QPRINTF(a)
        !           164: #endif
        !           165: 
        !           166: struct sdstats {
        !           167:        long    sdresets;
        !           168:        long    sdtransfers;
        !           169:        long    sdpartials;
        !           170: } sdstats[NSD];
        !           171: 
        !           172: struct buf sdtab[NSD];
        !           173: struct scsi_fmt_cdb sdcmd[NSD];
        !           174: struct scsi_fmt_sense sdsense[NSD];
        !           175: 
        !           176: static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
        !           177: static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
        !           178: 
        !           179: #define        sdunit(x)       (minor(x) >> 3)
        !           180: #define sdpart(x)      (minor(x) & 0x7)
        !           181: #define        sdpunit(x)      ((x) & 7)
        !           182: #define        b_cylin         b_resid
        !           183: 
        !           184: #define        SDRETRY         2
        !           185: 
        !           186: /*
        !           187:  * Table of scsi commands users are allowed to access via "format"
        !           188:  * mode.  0 means not legal.  1 means "immediate" (doesn't need dma).
        !           189:  * -1 means needs dma and/or wait for intr.
        !           190:  */
        !           191: static char legal_cmds[256] = {
        !           192: /*****  0   1   2   3   4   5   6   7     8   9   A   B   C   D   E   F */
        !           193: /*00*/ 0,  0,  0,  0, -1,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           194: /*10*/ 0,  0,  1,  0,  0,  1,  0,  0,    0,  0,  1,  0,  0,  0,  0,  0,
        !           195: /*20*/ 0,  0,  0,  0,  0,  1,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           196: /*30*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           197: /*40*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           198: /*50*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           199: /*60*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           200: /*70*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           201: /*80*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           202: /*90*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           203: /*a0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           204: /*b0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           205: /*c0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           206: /*d0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           207: /*e0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           208: /*f0*/ 0,  0,  0,  0,  0,  0,  0,  0,    0,  0,  0,  0,  0,  0,  0,  0,
        !           209: };
        !           210: 
        !           211: static struct scsi_inquiry inqbuf;
        !           212: static struct scsi_fmt_cdb inq = {
        !           213:        6,
        !           214:        CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
        !           215: };
        !           216: 
        !           217: static u_char capbuf[8];
        !           218: struct scsi_fmt_cdb cap = {
        !           219:        10,
        !           220:        CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
        !           221: };
        !           222: 
        !           223: static int
        !           224: sdident(sc, ad)
        !           225:        struct sd_softc *sc;
        !           226:        struct amiga_device *ad;
        !           227: {
        !           228:        int unit;
        !           229:        register int ctlr, slave;
        !           230:        register int i;
        !           231:        register int tries = 10;
        !           232:        int ismo = 0;
        !           233: 
        !           234:        ctlr = ad->amiga_ctlr;
        !           235:        slave = ad->amiga_slave;
        !           236:        unit = sc->sc_punit;
        !           237:        scsi_delay(-1);
        !           238: 
        !           239:        /*
        !           240:         * See if unit exists and is a disk then read block size & nblocks.
        !           241:         */
        !           242:        while ((i = scsi_test_unit_rdy(slave)) != 0) {
        !           243: retry_TUR:
        !           244:                if (i == -1 || --tries < 0) {
        !           245:                        if (ismo)
        !           246:                                break;
        !           247:                        /* doesn't exist or not a CCS device */
        !           248:                        goto failed;
        !           249:                }
        !           250:                if (i == STS_CHECKCOND) {
        !           251:                        u_char sensebuf[128];
        !           252:                        struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
        !           253: 
        !           254:                        i = scsi_request_sense(slave, sensebuf, sizeof(sensebuf));
        !           255:                        if (sp->class == 7)
        !           256:                                switch (sp->key) {
        !           257:                                /* not ready -- might be MO with no media */
        !           258:                                case 2:
        !           259:                                        if (sp->len == 12 &&
        !           260:                                            sensebuf[12] == 10) /* XXX */
        !           261:                                                ismo = 1;
        !           262:                                        break;
        !           263:                                /* drive doing an RTZ -- give it a while */
        !           264:                                case 6:
        !           265:                                        DELAY(1000000);
        !           266:                                        break;
        !           267:                                default:
        !           268:                                        break;
        !           269:                                }
        !           270:                }
        !           271:                DELAY(1000);
        !           272:        }
        !           273:        /*
        !           274:         * Find out about device
        !           275:         */
        !           276:        if (i = scsi_immed_command(slave, &inq, (u_char *)&inqbuf, sizeof(inqbuf), B_READ))
        !           277:          {
        !           278:            if (i == STS_CHECKCOND)
        !           279:              goto retry_TUR;
        !           280:            goto failed;
        !           281:          }
        !           282:        switch (inqbuf.type) {
        !           283:        case 0:         /* disk */
        !           284:        case 4:         /* WORM */
        !           285:        case 5:         /* CD-ROM */
        !           286:        case 7:         /* Magneto-optical */
        !           287:                break;
        !           288:        default:        /* not a disk */
        !           289:                if (sddebug)
        !           290:                  printf ("Unit %d unknown scsi-type: %d\n", slave, inqbuf.type);
        !           291:                goto failed;
        !           292:        }
        !           293:        /*
        !           294:         * Get a usable id string
        !           295:         */
        !           296:        if (inqbuf.version < 1) {
        !           297:                bcopy("UNKNOWN", &sc->sc_idstr[0], 8);
        !           298:                bcopy("DRIVE TYPE", &sc->sc_idstr[8], 11);
        !           299:        } else {
        !           300:                bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)sc->sc_idstr, 28);
        !           301:                for (i = 27; i > 23; --i)
        !           302:                        if (sc->sc_idstr[i] != ' ')
        !           303:                                break;
        !           304:                sc->sc_idstr[i+1] = 0;
        !           305:                for (i = 23; i > 7; --i)
        !           306:                        if (sc->sc_idstr[i] != ' ')
        !           307:                                break;
        !           308:                sc->sc_idstr[i+1] = 0;
        !           309:                for (i = 7; i >= 0; --i)
        !           310:                        if (sc->sc_idstr[i] != ' ')
        !           311:                                break;
        !           312:                sc->sc_idstr[i+1] = 0;
        !           313:        }
        !           314:        i = scsi_immed_command(slave, &cap, (u_char *)&capbuf, sizeof(capbuf), B_READ);
        !           315:        if (i) {
        !           316:                if (i != STS_CHECKCOND ||
        !           317:                    bcmp(&sc->sc_idstr[0], "HP", 3) ||
        !           318:                    bcmp(&sc->sc_idstr[8], "S6300.650A", 11))
        !           319:                        goto failed;
        !           320:                /* XXX unformatted or non-existant MO media; fake it */
        !           321:                sc->sc_blks = 318664;
        !           322:                sc->sc_blksize = 1024;
        !           323:        } else {
        !           324:                sc->sc_blks = *(u_int *)&capbuf[0];
        !           325:                sc->sc_blksize = *(int *)&capbuf[4];
        !           326:        }
        !           327:        /* return value of read capacity is last valid block number */
        !           328:        sc->sc_blks++;
        !           329: 
        !           330:        if (inqbuf.version < 1)
        !           331:                printf("sd%d: type 0x%x, qual 0x%x, ver %d", ad->amiga_unit,
        !           332:                        inqbuf.type, inqbuf.qual, inqbuf.version);
        !           333:        else
        !           334:                printf("sd%d: %s %s rev %s", ad->amiga_unit, sc->sc_idstr, &sc->sc_idstr[8],
        !           335:                        &sc->sc_idstr[24]);
        !           336:        printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
        !           337:        if (sc->sc_blksize != DEV_BSIZE) {
        !           338:                if (sc->sc_blksize < DEV_BSIZE) {
        !           339:                        printf("sd%d: need %d byte blocks - drive ignored\n",
        !           340:                                unit, DEV_BSIZE);
        !           341:                        goto failed;
        !           342:                }
        !           343:                for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
        !           344:                        ++sc->sc_bshift;
        !           345:                sc->sc_blks <<= sc->sc_bshift;
        !           346:        }
        !           347:        sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);        /* XXX */
        !           348:        scsi_delay(0);
        !           349:        return(inqbuf.type);
        !           350: failed:
        !           351:        scsi_delay(0);
        !           352:        return(-1);
        !           353: }
        !           354: 
        !           355: int
        !           356: sdinit(ad)
        !           357:        register struct amiga_device *ad;
        !           358: {
        !           359:        register struct sd_softc *sc = &sd_softc[ad->amiga_unit];
        !           360:        static u_int block [DEV_BSIZE / 4];
        !           361:        struct RigidDiskBlock *rdb = (struct RigidDiskBlock *) block;
        !           362:        struct PartitionBlock *pb  = (struct PartitionBlock *) block;
        !           363:        int bnum, npbnum, num_bsd_part = 0;
        !           364:        struct disklabel *dl;
        !           365: 
        !           366:        sc->sc_ad = ad;
        !           367:        sc->sc_punit = sdpunit(ad->amiga_flags);
        !           368:        sc->sc_type = sdident(sc, ad);
        !           369:        if (sc->sc_type < 0)
        !           370:                return(0);
        !           371:        sc->sc_dq.dq_ctlr = ad->amiga_ctlr;
        !           372:        sc->sc_dq.dq_unit = ad->amiga_unit;
        !           373:        sc->sc_dq.dq_slave = ad->amiga_slave;
        !           374:        sc->sc_dq.dq_driver = &sddriver;
        !           375: 
        !           376:        /* read RDB and partition blocks to find out about which partitions
        !           377:           are ok to be scribbled upon by BSD. This is quite Amiga specific. */
        !           378: 
        !           379:        for (bnum = 0; bnum < RDB_LOCATION_LIMIT; bnum++)
        !           380:          {
        !           381:            if (scsi_tt_read (ad->amiga_slave, block, DEV_BSIZE, bnum, sc->sc_bshift))
        !           382:              /* read error on block */
        !           383:              return 0;
        !           384: 
        !           385:            if (rdb->rdb_ID == IDNAME_RIGIDDISK)
        !           386:              break;
        !           387:          }
        !           388:        if (bnum == RDB_LOCATION_LIMIT)
        !           389:          /* no RDB on this disk */
        !           390:          return 0;
        !           391: 
        !           392:        /* fill in as much as we can of the disklabel */
        !           393:        dl = &sc->sc_label;
        !           394:        bzero (dl, sizeof (*dl));
        !           395:        dl->d_magic = DISKMAGIC;
        !           396:        dl->d_type  = DTYPE_SCSI;
        !           397: 
        !           398:        strncpy (dl->d_typename, sc->sc_idstr, sizeof (dl->d_typename) - 1);
        !           399:        strcpy (dl->d_packname, "some pack");
        !           400:        
        !           401:        /* now for more serious information.. */
        !           402:        dl->d_secsize    = rdb->rdb_BlockBytes;
        !           403:        dl->d_nsectors   = rdb->rdb_Sectors;
        !           404:        dl->d_ntracks    = rdb->rdb_Heads;
        !           405:        dl->d_ncylinders = rdb->rdb_Cylinders;
        !           406:        dl->d_secpercyl  = rdb->rdb_CylBlocks;
        !           407:        dl->d_secperunit = (rdb->rdb_CylBlocks 
        !           408:                            * (rdb->rdb_HiCylinder - rdb->rdb_LoCylinder));
        !           409: 
        !           410:        /* makes sense? */
        !           411:        dl->d_acylinders = rdb->rdb_Cylinders - (rdb->rdb_HiCylinder - rdb->rdb_LoCylinder);
        !           412: 
        !           413:        dl->d_magic2 = DISKMAGIC;
        !           414: 
        !           415:        /* ok, go thru the partition blocks, and check for BSD ID's */
        !           416:        
        !           417:        for (npbnum = rdb->rdb_PartitionList; npbnum; )
        !           418:          {
        !           419:            u_int start_block, end_block, nblocks;
        !           420:            u_int reserved;
        !           421:            int part;
        !           422: 
        !           423:            if (scsi_tt_read (ad->amiga_slave, block, DEV_BSIZE, npbnum, sc->sc_bshift))
        !           424:              break;
        !           425:          
        !           426:            if (pb->pb_ID != IDNAME_PARTITION)
        !           427:              break;
        !           428: 
        !           429:            /* remember those values, they're destroyed when reading the first
        !           430:               partition block */
        !           431:            npbnum      = pb->pb_Next;
        !           432:            start_block = pb->pb_Environment[DE_LOWCYL] * dl->d_secpercyl;
        !           433:            reserved    = pb->pb_Environment[DE_RESERVEDBLKS];
        !           434:            end_block   = pb->pb_Environment[DE_UPPERCYL] * dl->d_secpercyl;
        !           435: 
        !           436:            part = -1;
        !           437:            switch (pb->pb_Environment[DE_DOSTYPE])
        !           438:              {
        !           439:              case DOSTYPE_BSD_ROOT:
        !           440:                if (! dl->d_partitions[0].p_size)
        !           441:                  {
        !           442:                    extern u_long bootdev;
        !           443: 
        !           444:                    part = 0;
        !           445: 
        !           446:                    /* Since we don't boot BSD with a standalone-kernel, but
        !           447:                       with a simple boot-loader from AmigaDOS, we fake a
        !           448:                       bootdev by assigning the just computed values of the
        !           449:                       root partition. */
        !           450: 
        !           451:                    /* 4:               sd major
        !           452:                       0:               adaptor number
        !           453:                       0:               controller number
        !           454:                       ad->amiga_unit:  scsi-unit
        !           455:                       part:            partition (A) */
        !           456: 
        !           457:                    bootdev = MAKEBOOTDEV (4, 0, 0, ad->amiga_unit, part);
        !           458:                  }
        !           459:                break;
        !           460: 
        !           461:              case DOSTYPE_BSD_SWAP:            
        !           462:                if (! dl->d_partitions[1].p_size)
        !           463:                  part = 1;
        !           464:                break;
        !           465:                
        !           466:              case DOSTYPE_BSD_D:
        !           467:                if (! dl->d_partitions[3].p_size)
        !           468:                  part = 3;
        !           469:                break;
        !           470:                
        !           471:              case DOSTYPE_BSD_E:
        !           472:                if (! dl->d_partitions[4].p_size)
        !           473:                  part = 4;
        !           474:                break;
        !           475:                
        !           476:              case DOSTYPE_BSD_F:
        !           477:                if (! dl->d_partitions[5].p_size)
        !           478:                  part = 5;
        !           479:                break;
        !           480:                
        !           481:              case DOSTYPE_BSD_G:
        !           482:                if (! dl->d_partitions[6].p_size)
        !           483:                  part = 6;
        !           484:                break;
        !           485:                
        !           486:              case DOSTYPE_BSD_H:
        !           487:                if (! dl->d_partitions[7].p_size)
        !           488:                  part = 7;
        !           489:                break;
        !           490:              }
        !           491: 
        !           492:            if (part >= 0)
        !           493:              {
        !           494:                num_bsd_part++;
        !           495: 
        !           496:                dl->d_partitions[part].p_offset = start_block + reserved;
        !           497:                dl->d_partitions[part].p_size = end_block - start_block - reserved;
        !           498: 
        !           499:                /* for now, have this static.. XXX */
        !           500:                dl->d_partitions[part].p_fsize  = 1024;
        !           501:                dl->d_partitions[part].p_fstype = part == 1 ? FS_SWAP : FS_BSDFFS;
        !           502:                dl->d_partitions[part].p_frag   = 8;
        !           503:                dl->d_partitions[part].p_cpg    = 0;    /* XXX */
        !           504:            
        !           505:                if (sddebug)
        !           506:                  printf ("%c @%d - %d = %d\n", part + 'A',
        !           507:                          start_block, end_block, end_block - start_block - reserved);
        !           508:              }
        !           509:          }
        !           510: 
        !           511:        dl->d_npartitions = num_bsd_part;
        !           512:        if (sddebug)
        !           513:          printf ("total %d BSD-partitions.\n", num_bsd_part);
        !           514: 
        !           515:        /* C gets everything */
        !           516:        dl->d_partitions[2].p_size = sc->sc_blks;
        !           517: 
        !           518:        dl->d_checksum = 0;
        !           519:        dl->d_checksum = dkcksum (dl);
        !           520: 
        !           521:        sc->sc_have_label = 1;
        !           522:        sc->sc_write_label = 0;
        !           523: 
        !           524:        sc->sc_flags = SDF_ALIVE;
        !           525:        return(1);
        !           526: }
        !           527: 
        !           528: void
        !           529: sdreset(sc, ad)
        !           530:        register struct sd_softc *sc;
        !           531:        register struct amiga_device *ad;
        !           532: {
        !           533:        sdstats[ad->amiga_unit].sdresets++;
        !           534: }
        !           535: 
        !           536: int
        !           537: sdopen(dev, flags, mode, p)
        !           538:        dev_t dev;
        !           539:        int flags, mode;
        !           540:        struct proc *p;
        !           541: {
        !           542:        register int unit = sdunit(dev);
        !           543:        register struct sd_softc *sc = &sd_softc[unit];
        !           544: 
        !           545:        if (unit >= NSD)
        !           546:                return(ENXIO);
        !           547:        if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
        !           548:                return(ENXIO);
        !           549: 
        !           550:        if (sc->sc_ad->amiga_dk >= 0)
        !           551:                dk_wpms[sc->sc_ad->amiga_dk] = sc->sc_wpms;
        !           552:        return(0);
        !           553: }
        !           554: 
        !           555: /*
        !           556:  * This routine is called for partial block transfers and non-aligned
        !           557:  * transfers (the latter only being possible on devices with a block size
        !           558:  * larger than DEV_BSIZE).  The operation is performed in three steps
        !           559:  * using a locally allocated buffer:
        !           560:  *     1. transfer any initial partial block
        !           561:  *     2. transfer full blocks
        !           562:  *     3. transfer any final partial block
        !           563:  */
        !           564: static void
        !           565: sdlblkstrat(bp, bsize)
        !           566:        register struct buf *bp;
        !           567:        register int bsize;
        !           568: {
        !           569:        register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf),
        !           570:                                                        M_DEVBUF, M_WAITOK);
        !           571:        caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
        !           572:        register int bn, resid;
        !           573:        register caddr_t addr;
        !           574: 
        !           575:        bzero((caddr_t)cbp, sizeof(*cbp));
        !           576:        cbp->b_proc = curproc;          /* XXX */
        !           577:        cbp->b_dev = bp->b_dev;
        !           578:        bn = bp->b_blkno;
        !           579:        resid = bp->b_bcount;
        !           580:        addr = bp->b_un.b_addr;
        !           581: #ifdef DEBUG
        !           582:        if (sddebug & SDB_PARTIAL)
        !           583:                printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
        !           584:                       bp, bp->b_flags, bn, resid, addr);
        !           585: #endif
        !           586: 
        !           587:        while (resid > 0) {
        !           588:                register int boff = dbtob(bn) & (bsize - 1);
        !           589:                register int count;
        !           590: 
        !           591:                if (boff || resid < bsize) {
        !           592:                        sdstats[sdunit(bp->b_dev)].sdpartials++;
        !           593:                        count = MIN(resid, bsize - boff);
        !           594:                        cbp->b_flags = B_BUSY | B_PHYS | B_READ;
        !           595:                        cbp->b_blkno = bn - btodb(boff);
        !           596:                        cbp->b_un.b_addr = cbuf;
        !           597:                        cbp->b_bcount = bsize;
        !           598: #ifdef DEBUG
        !           599:                        if (sddebug & SDB_PARTIAL)
        !           600:                                printf(" readahead: bn %x cnt %x off %x addr %x\n",
        !           601:                                       cbp->b_blkno, count, boff, addr);
        !           602: #endif
        !           603:                        sdstrategy(cbp);
        !           604:                        biowait(cbp);
        !           605:                        if (cbp->b_flags & B_ERROR) {
        !           606:                                bp->b_flags |= B_ERROR;
        !           607:                                bp->b_error = cbp->b_error;
        !           608:                                break;
        !           609:                        }
        !           610:                        if (bp->b_flags & B_READ) {
        !           611:                                bcopy(&cbuf[boff], addr, count);
        !           612:                                goto done;
        !           613:                        }
        !           614:                        bcopy(addr, &cbuf[boff], count);
        !           615: #ifdef DEBUG
        !           616:                        if (sddebug & SDB_PARTIAL)
        !           617:                                printf(" writeback: bn %x cnt %x off %x addr %x\n",
        !           618:                                       cbp->b_blkno, count, boff, addr);
        !           619: #endif
        !           620:                } else {
        !           621:                        count = resid & ~(bsize - 1);
        !           622:                        cbp->b_blkno = bn;
        !           623:                        cbp->b_un.b_addr = addr;
        !           624:                        cbp->b_bcount = count;
        !           625: #ifdef DEBUG
        !           626:                        if (sddebug & SDB_PARTIAL)
        !           627:                                printf(" fulltrans: bn %x cnt %x addr %x\n",
        !           628:                                       cbp->b_blkno, count, addr);
        !           629: #endif
        !           630:                }
        !           631:                cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);
        !           632:                sdstrategy(cbp);
        !           633:                biowait(cbp);
        !           634:                if (cbp->b_flags & B_ERROR) {
        !           635:                        bp->b_flags |= B_ERROR;
        !           636:                        bp->b_error = cbp->b_error;
        !           637:                        break;
        !           638:                }
        !           639: done:
        !           640:                bn += btodb(count);
        !           641:                resid -= count;
        !           642:                addr += count;
        !           643: #ifdef DEBUG
        !           644:                if (sddebug & SDB_PARTIAL)
        !           645:                        printf(" done: bn %x resid %x addr %x\n",
        !           646:                               bn, resid, addr);
        !           647: #endif
        !           648:        }
        !           649:        free(cbuf, M_DEVBUF);
        !           650:        free(cbp, M_DEVBUF);
        !           651: }
        !           652: 
        !           653: void
        !           654: sdstrategy(bp)
        !           655:        register struct buf *bp;
        !           656: {
        !           657:        register int unit = sdunit(bp->b_dev);
        !           658:        register struct sd_softc *sc = &sd_softc[unit];
        !           659:        register struct partition *pinfo = &sc->sc_label.d_partitions[sdpart(bp->b_dev)];
        !           660:        register struct buf *dp = &sdtab[unit];
        !           661:        register daddr_t bn;
        !           662:        register int sz, s;
        !           663: 
        !           664:        QPRINTF (("sdstrat: unit=%d [s=%d,l=%d], [b=%d,l=%d]\n", unit, 
        !           665:                  pinfo->p_offset, pinfo->p_size, bp->b_blkno, bp->b_bcount));
        !           666: 
        !           667:        if (sc->sc_format_pid) {
        !           668:                if (sc->sc_format_pid != curproc->p_pid) {      /* XXX */
        !           669:                        bp->b_error = EPERM;
        !           670:                        bp->b_flags |= B_ERROR;
        !           671:                        goto done;
        !           672:                }
        !           673:                bp->b_cylin = 0;
        !           674:        } else {
        !           675:                bn = bp->b_blkno;
        !           676:                sz = howmany(bp->b_bcount, DEV_BSIZE);
        !           677:                if (bn < 0 || bn + sz > pinfo->p_size) {
        !           678:                        sz = pinfo->p_size - bn;
        !           679:                        if (sz == 0) {
        !           680:                                bp->b_resid = bp->b_bcount;
        !           681:                                goto done;
        !           682:                        }
        !           683:                        if (sz < 0) {
        !           684:                                bp->b_error = EINVAL;
        !           685:                                bp->b_flags |= B_ERROR;
        !           686:                                goto done;
        !           687:                        }
        !           688:                        bp->b_bcount = dbtob(sz);
        !           689:                }
        !           690:                /*
        !           691:                 * Non-aligned or partial-block transfers handled specially.
        !           692:                 */
        !           693:                s = sc->sc_blksize - 1;
        !           694:                if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
        !           695:                        sdlblkstrat(bp, sc->sc_blksize);
        !           696:                        goto done;
        !           697:                }
        !           698:                bp->b_cylin = (bn + pinfo->p_offset) >> sc->sc_bshift;
        !           699:        }
        !           700:        s = splbio();
        !           701:        disksort(dp, bp);
        !           702:        if (dp->b_active == 0) {
        !           703:                dp->b_active = 1;
        !           704:                sdustart(unit);
        !           705:        }
        !           706:        splx(s);
        !           707:        return;
        !           708: done:
        !           709:        biodone(bp);
        !           710: }
        !           711: 
        !           712: void
        !           713: sdustart(unit)
        !           714:        register int unit;
        !           715: {
        !           716:        if (scsireq(&sd_softc[unit].sc_dq))
        !           717:                sdstart(unit);
        !           718: }
        !           719: 
        !           720: /*
        !           721:  * Return:
        !           722:  *     0       if not really an error
        !           723:  *     <0      if we should do a retry
        !           724:  *     >0      if a fatal error
        !           725:  */
        !           726: static int
        !           727: sderror(unit, sc, am, stat)
        !           728:        int unit, stat;
        !           729:        register struct sd_softc *sc;
        !           730:        register struct amiga_device *am;
        !           731: {
        !           732:        int cond = 1;
        !           733: 
        !           734:        sdsense[unit].status = stat;
        !           735:        if (stat & STS_CHECKCOND) {
        !           736:                struct scsi_xsense *sp;
        !           737: 
        !           738:                scsi_request_sense(am->amiga_slave,
        !           739:                                   sdsense[unit].sense,
        !           740:                                   sizeof(sdsense[unit].sense));
        !           741:                sp = (struct scsi_xsense *)sdsense[unit].sense;
        !           742:                printf("sd%d: scsi sense class %d, code %d", unit,
        !           743:                        sp->class, sp->code);
        !           744:                if (sp->class == 7) {
        !           745:                        printf(", key %d", sp->key);
        !           746:                        if (sp->valid)
        !           747:                                printf(", blk %d", *(int *)&sp->info1);
        !           748:                        switch (sp->key) {
        !           749:                        /* no sense, try again */
        !           750:                        case 0:
        !           751:                                cond = -1;
        !           752:                                break;
        !           753:                        /* recovered error, not a problem */
        !           754:                        case 1:
        !           755:                                cond = 0;
        !           756:                                break;
        !           757:                        }
        !           758:                }
        !           759:                printf("\n");
        !           760:        }
        !           761:        return(cond);
        !           762: }
        !           763: 
        !           764: static void
        !           765: sdfinish(unit, sc, bp)
        !           766:        int unit;
        !           767:        register struct sd_softc *sc;
        !           768:        register struct buf *bp;
        !           769: {
        !           770:        sdtab[unit].b_errcnt = 0;
        !           771:        sdtab[unit].b_actf = bp->b_actf;
        !           772:        bp->b_resid = 0;
        !           773:        biodone(bp);
        !           774:        scsifree(&sc->sc_dq);
        !           775:        if (sdtab[unit].b_actf)
        !           776:                sdustart(unit);
        !           777:        else
        !           778:                sdtab[unit].b_active = 0;
        !           779: }
        !           780: 
        !           781: void
        !           782: sdstart(unit)
        !           783:        register int unit;
        !           784: {
        !           785:        register struct sd_softc *sc = &sd_softc[unit];
        !           786:        register struct amiga_device *am = sc->sc_ad;
        !           787: 
        !           788:        /*
        !           789:         * we have the SCSI bus -- in format mode, we may or may not need dma
        !           790:         * so check now.
        !           791:         */
        !           792:        if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) {
        !           793:                register struct buf *bp = sdtab[unit].b_actf;
        !           794:                register int sts;
        !           795: 
        !           796:                sts = scsi_immed_command(am->amiga_slave,
        !           797:                                         &sdcmd[unit],
        !           798:                                         bp->b_un.b_addr, bp->b_bcount,
        !           799:                                         bp->b_flags & B_READ);
        !           800:                sdsense[unit].status = sts;
        !           801:                if (sts & 0xfe) {
        !           802:                        (void) sderror(unit, sc, am, sts);
        !           803:                        bp->b_flags |= B_ERROR;
        !           804:                        bp->b_error = EIO;
        !           805:                }
        !           806:                sdfinish(unit, sc, bp);
        !           807: 
        !           808:        } else if (scsiustart(am->amiga_ctlr))
        !           809:                sdgo(unit);
        !           810: }
        !           811: 
        !           812: void
        !           813: sdgo(unit)
        !           814:        register int unit;
        !           815: {
        !           816:        register struct sd_softc *sc = &sd_softc[unit];
        !           817:        register struct amiga_device *am = sc->sc_ad;
        !           818:        register struct buf *bp = sdtab[unit].b_actf;
        !           819:        register int pad;
        !           820:        register struct scsi_fmt_cdb *cmd;
        !           821: 
        !           822:        /* XXX ? */
        !           823:        if (! bp)
        !           824:          return;
        !           825: 
        !           826:        if (sc->sc_format_pid) {
        !           827:                cmd = &sdcmd[unit];
        !           828:                pad = 0;
        !           829:        } else {
        !           830:                cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
        !           831:                *(int *)(&cmd->cdb[2]) = bp->b_cylin;
        !           832:                pad = howmany(bp->b_bcount, sc->sc_blksize);
        !           833:                *(u_short *)(&cmd->cdb[7]) = pad;
        !           834:                QPRINTF(("sdgo[%d, %d]: %s @%d >%d\n",
        !           835:                         am->amiga_ctlr, am->amiga_slave,
        !           836:                         bp->b_flags & B_READ ? "R" : "W",
        !           837:                         bp->b_cylin, pad));
        !           838:                pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;
        !           839: #ifdef DEBUG
        !           840:                if (pad)
        !           841:                        printf("sd%d: partial block xfer -- %x bytes\n",
        !           842:                               unit, bp->b_bcount);
        !           843: #endif
        !           844:                sdstats[unit].sdtransfers++;
        !           845:        }
        !           846:        if (scsigo(am->amiga_ctlr, am->amiga_slave, bp, cmd, pad) == 0) {
        !           847:                if (am->amiga_dk >= 0) {
        !           848:                        dk_busy |= 1 << am->amiga_dk;
        !           849:                        ++dk_seek[am->amiga_dk];
        !           850:                        ++dk_xfer[am->amiga_dk];
        !           851:                        dk_wds[am->amiga_dk] += bp->b_bcount >> 6;
        !           852:                }
        !           853:                return;
        !           854:        }
        !           855: #ifdef DEBUG
        !           856:        if (sddebug & SDB_ERROR)
        !           857:                printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",
        !           858:                       unit, bp->b_flags & B_READ? "read" : "write",
        !           859:                       bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
        !           860:                       sdtab[unit].b_errcnt);
        !           861: #endif
        !           862:        bp->b_flags |= B_ERROR;
        !           863:        bp->b_error = EIO;
        !           864:        sdfinish(unit, sc, bp);
        !           865: }
        !           866: 
        !           867: void
        !           868: sdintr(unit, stat)
        !           869:        register int unit;
        !           870:        int stat;
        !           871: {
        !           872:        register struct sd_softc *sc = &sd_softc[unit];
        !           873:        register struct buf *bp = sdtab[unit].b_actf;
        !           874:        register struct amiga_device *am = sc->sc_ad;
        !           875:        int cond;
        !           876:        
        !           877:        if (bp == NULL) {
        !           878:                printf("sd%d: bp == NULL\n", unit);
        !           879:                return;
        !           880:        }
        !           881:        if (am->amiga_dk >= 0)
        !           882:                dk_busy &=~ (1 << am->amiga_dk);
        !           883:        if (stat) {
        !           884: #ifdef DEBUG
        !           885:                if (sddebug & SDB_ERROR)
        !           886:                        printf("sd%d: sdintr: bad scsi status 0x%x\n",
        !           887:                                unit, stat);
        !           888: #endif
        !           889:                cond = sderror(unit, sc, am, stat);
        !           890:                if (cond) {
        !           891:                        if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
        !           892: #ifdef DEBUG
        !           893:                                if (sddebug & SDB_ERROR)
        !           894:                                        printf("sd%d: retry #%d\n",
        !           895:                                               unit, sdtab[unit].b_errcnt);
        !           896: #endif
        !           897:                                sdstart(unit);
        !           898:                                return;
        !           899:                        }
        !           900:                        bp->b_flags |= B_ERROR;
        !           901:                        bp->b_error = EIO;
        !           902:                }
        !           903:        }
        !           904:        sdfinish(unit, sc, bp);
        !           905: }
        !           906: 
        !           907: #if 1
        !           908: u_int
        !           909: sdminphys (bp)
        !           910:        struct buf *bp;
        !           911: {
        !           912:        register int unit = sdunit(bp->b_dev);
        !           913:        register struct sd_softc *sc = &sd_softc[unit];
        !           914:        register struct partition *pinfo = &sc->sc_label.d_partitions[sdpart(bp->b_dev)];
        !           915:        register daddr_t bn;
        !           916:        register int sz, s;
        !           917: 
        !           918:        /* first restrict by max amount of physio possible */
        !           919:        bp->b_bcount = min(MAXPHYS, bp->b_bcount);
        !           920: 
        !           921:        /* then restrict by partition size (code replicated from sdstrategy).
        !           922:           Should minphys() really fiddle around with b_resid and b_flags ??? XXXX */
        !           923: 
        !           924:        bn = bp->b_blkno;
        !           925:        sz = howmany(bp->b_bcount, DEV_BSIZE);
        !           926:        if (bn < 0 || bn + sz > pinfo->p_size) 
        !           927:          {
        !           928:            sz = pinfo->p_size - bn;
        !           929:            if (sz == 0) 
        !           930:              {
        !           931:                bp->b_resid = bp->b_bcount;
        !           932:                goto done;
        !           933:              }
        !           934:            if (sz < 0) 
        !           935:              {
        !           936:                bp->b_error = EINVAL;
        !           937:                bp->b_flags |= B_ERROR;
        !           938:                goto done;
        !           939:              }
        !           940:            bp->b_bcount = dbtob(sz);
        !           941:          }
        !           942: 
        !           943:        return bp->b_bcount;
        !           944: done:
        !           945:        return 0;
        !           946: }
        !           947: 
        !           948: 
        !           949: int
        !           950: sdread(dev, uio, flags)
        !           951:        dev_t dev;
        !           952:        struct uio *uio;
        !           953:        int flags;
        !           954: {
        !           955:        register int unit = sdunit(dev);
        !           956:        register int pid;
        !           957: 
        !           958:        if ((pid = sd_softc[unit].sc_format_pid) &&
        !           959:            pid != uio->uio_procp->p_pid)
        !           960:                return (EPERM);
        !           961:                
        !           962:        return (physio(sdstrategy, NULL, dev, B_READ, sdminphys, uio));
        !           963: }
        !           964: 
        !           965: int
        !           966: sdwrite(dev, uio, flags)
        !           967:        dev_t dev;
        !           968:        struct uio *uio;
        !           969:        int flags;
        !           970: {
        !           971:        register int unit = sdunit(dev);
        !           972:        register int pid;
        !           973: 
        !           974:        if ((pid = sd_softc[unit].sc_format_pid) &&
        !           975:            pid != uio->uio_procp->p_pid)
        !           976:                return (EPERM);
        !           977:                
        !           978:        return (physio(sdstrategy, NULL, dev, B_WRITE, sdminphys, uio));
        !           979: }
        !           980: #endif
        !           981: 
        !           982: int
        !           983: sdioctl(dev, cmd, data, flag, p)
        !           984:        dev_t dev;
        !           985:        int cmd;
        !           986:        caddr_t data;
        !           987:        int flag;
        !           988:        struct proc *p;
        !           989: {
        !           990:        register int unit = sdunit(dev);
        !           991:        register struct sd_softc *sc = &sd_softc[unit];
        !           992:        struct disklabel *dl;
        !           993:        int error;
        !           994: 
        !           995:        switch (cmd) {
        !           996:        default:
        !           997:                return (EINVAL);
        !           998: 
        !           999:        case DIOCGDINFO:
        !          1000:                *(struct disklabel *)data = sc->sc_label;
        !          1001:                return 0;
        !          1002: 
        !          1003:         case DIOCSDINFO:
        !          1004:                 if ((flag & FWRITE) == 0)
        !          1005:                  return EBADF;
        !          1006: 
        !          1007:                dl = (struct disklabel *)data;
        !          1008:                if (error = setdisklabel(&sc->sc_label, dl, 0, 0));
        !          1009:                        return error;
        !          1010:                sc->sc_have_label = 1;
        !          1011:                 return 0;
        !          1012: 
        !          1013:         case DIOCWLABEL:
        !          1014:                 if ((flag & FWRITE) == 0)
        !          1015:                  return EBADF;
        !          1016: 
        !          1017:                sc->sc_write_label = *(int *)data;
        !          1018:                 return 0;
        !          1019: 
        !          1020:         case DIOCWDINFO:
        !          1021:                 if ((flag & FWRITE) == 0)
        !          1022:                  return EBADF;
        !          1023: 
        !          1024:                dl = (struct disklabel *)data;
        !          1025: 
        !          1026:                if (error = setdisklabel (&sc->sc_label, dl, 0, 0))
        !          1027:                  return error;
        !          1028: 
        !          1029:                sc->sc_have_label = 1;
        !          1030: 
        !          1031: #if 0
        !          1032:                old_wlabel = as->wlabel;
        !          1033:                as->wlabel = 1;
        !          1034:                error = writedisklabel(dev, asstrategy, &as->label,
        !          1035:                                as->dospart);
        !          1036:                as->wlabel = old_wlabel;
        !          1037: #endif
        !          1038:                return EINVAL;
        !          1039: 
        !          1040:        case SDIOCSFORMAT:
        !          1041:                /* take this device into or out of "format" mode */
        !          1042:                if (suser(p->p_ucred, &p->p_acflag))
        !          1043:                        return(EPERM);
        !          1044: 
        !          1045:                if (*(int *)data) {
        !          1046:                        if (sc->sc_format_pid)
        !          1047:                                return (EPERM);
        !          1048:                        sc->sc_format_pid = p->p_pid;
        !          1049:                } else
        !          1050:                        sc->sc_format_pid = 0;
        !          1051:                return (0);
        !          1052: 
        !          1053:        case SDIOCGFORMAT:
        !          1054:                /* find out who has the device in format mode */
        !          1055:                *(int *)data = sc->sc_format_pid;
        !          1056:                return (0);
        !          1057: 
        !          1058:        case SDIOCSCSICOMMAND:
        !          1059:                /*
        !          1060:                 * Save what user gave us as SCSI cdb to use with next
        !          1061:                 * read or write to the char device.
        !          1062:                 */
        !          1063:                if (sc->sc_format_pid != p->p_pid)
        !          1064:                        return (EPERM);
        !          1065:                if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)
        !          1066:                        return (EINVAL);
        !          1067:                bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0]));
        !          1068:                return (0);
        !          1069: 
        !          1070:        case SDIOCSENSE:
        !          1071:                /*
        !          1072:                 * return the SCSI sense data saved after the last
        !          1073:                 * operation that completed with "check condition" status.
        !          1074:                 */
        !          1075:                bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0]));
        !          1076:                return (0);
        !          1077:                
        !          1078:        }
        !          1079:        /*NOTREACHED*/
        !          1080: }
        !          1081: 
        !          1082: int
        !          1083: sdsize(dev)
        !          1084:        dev_t dev;
        !          1085: {
        !          1086:        register int unit = sdunit(dev);
        !          1087:        register struct sd_softc *sc = &sd_softc[unit];
        !          1088: 
        !          1089:        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
        !          1090:                return(-1);
        !          1091:        return(sc->sc_label.d_partitions[sdpart(dev)].p_size);
        !          1092: }
        !          1093: 
        !          1094: /*
        !          1095:  * Non-interrupt driven, non-dma dump routine.
        !          1096:  */
        !          1097: int
        !          1098: sddump(dev)
        !          1099:        dev_t dev;
        !          1100: {
        !          1101:        int part = sdpart(dev);
        !          1102:        int unit = sdunit(dev);
        !          1103:        register struct sd_softc *sc = &sd_softc[unit];
        !          1104:        register struct amiga_device *am = sc->sc_ad;
        !          1105:        register daddr_t baddr;
        !          1106:        register int maddr;
        !          1107:        register int pages, i;
        !          1108:        int stat;
        !          1109:        extern int lowram;
        !          1110: 
        !          1111:        /*
        !          1112:         * Hmm... all vax drivers dump maxfree pages which is physmem minus
        !          1113:         * the message buffer.  Is there a reason for not dumping the
        !          1114:         * message buffer?  Savecore expects to read 'dumpsize' pages of
        !          1115:         * dump, where dumpsys() sets dumpsize to physmem!
        !          1116:         */
        !          1117:        pages = physmem;
        !          1118: 
        !          1119:        /* is drive ok? */
        !          1120:        if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
        !          1121:                return (ENXIO);
        !          1122:        /* dump parameters in range? */
        !          1123:        if (dumplo < 0 || dumplo >= sc->sc_label.d_partitions[part].p_size)
        !          1124:                return (EINVAL);
        !          1125:        if (dumplo + ctod(pages) > sc->sc_label.d_partitions[part].p_size)
        !          1126:                pages = dtoc(sc->sc_label.d_partitions[part].p_size - dumplo);
        !          1127:        maddr = lowram;
        !          1128:        baddr = dumplo + sc->sc_label.d_partitions[part].p_offset;
        !          1129:        /* scsi bus idle? */
        !          1130:        if (!scsireq(&sc->sc_dq)) {
        !          1131:                scsireset(/*am->amiga_ctlr*/);
        !          1132:                sdreset(sc, sc->sc_ad);
        !          1133:                printf("[ drive %d reset ] ", unit);
        !          1134:        }
        !          1135:        for (i = 0; i < pages; i++) {
        !          1136: #define NPGMB  (1024*1024/NBPG)
        !          1137:                /* print out how many Mbs we have dumped */
        !          1138:                if (i && (i % NPGMB) == 0)
        !          1139:                        printf("%d ", i / NPGMB);
        !          1140: #undef NPBMG
        !          1141:                pmap_enter(pmap_kernel(), vmmap, maddr, VM_PROT_READ, TRUE);
        !          1142:                stat = scsi_tt_write(am->amiga_slave,
        !          1143:                                     vmmap, NBPG, baddr, sc->sc_bshift);
        !          1144:                if (stat) {
        !          1145:                        printf("sddump: scsi write error 0x%x\n", stat);
        !          1146:                        return (EIO);
        !          1147:                }
        !          1148:                maddr += NBPG;
        !          1149:                baddr += ctod(1);
        !          1150:        }
        !          1151:        return (0);
        !          1152: }
        !          1153: #endif

unix.superglobalmegacorp.com

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