152130Smckusick /* 252130Smckusick * Copyright (c) 1992 Regents of the University of California. 352130Smckusick * All rights reserved. 452130Smckusick * 552130Smckusick * This code is derived from software contributed to Berkeley by 652130Smckusick * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell. 752130Smckusick * 852130Smckusick * %sccs.include.redist.c% 952130Smckusick * 10*56629Sralph * @(#)rz.c 7.8 (Berkeley) 10/24/92 1152130Smckusick */ 1252130Smckusick 1352130Smckusick /* 1452130Smckusick * SCSI CCS (Command Command Set) disk driver. 1553202Sralph * NOTE: The name was changed from "sd" to "rz" for DEC naming compatibility. 1652130Smckusick * I guess I can't avoid confusion someplace. 1752130Smckusick */ 1852130Smckusick #include "rz.h" 1952130Smckusick #if NRZ > 0 2052130Smckusick 2156522Sbostic #include <sys/param.h> 2256522Sbostic #include <sys/systm.h> 2356522Sbostic #include <sys/buf.h> 2456522Sbostic #include <sys/errno.h> 2556522Sbostic #include <sys/fcntl.h> 2656522Sbostic #include <sys/ioctl.h> 2756522Sbostic #include <sys/dkstat.h> 2856522Sbostic #include <sys/disklabel.h> 2956522Sbostic #include <sys/malloc.h> 3056522Sbostic #include <sys/proc.h> 3156522Sbostic #include <sys/uio.h> 3256522Sbostic #include <sys/stat.h> 3356522Sbostic #include <sys/syslog.h> 3452130Smckusick 3556522Sbostic #include <ufs/ffs/fs.h> 3652130Smckusick 3756525Sbostic #include <pmax/dev/device.h> 3856525Sbostic #include <pmax/dev/scsi.h> 3956522Sbostic 4052130Smckusick extern int splbio(); 4152130Smckusick extern void splx(); 4252130Smckusick extern int physio(); 4354147Sralph extern char *readdisklabel(); 4452130Smckusick 4552130Smckusick int rzprobe(); 4652130Smckusick void rzstrategy(), rzstart(), rzdone(); 4752130Smckusick 4852130Smckusick struct driver rzdriver = { 4952130Smckusick "rz", rzprobe, rzstart, rzdone, 5052130Smckusick }; 5152130Smckusick 5252130Smckusick struct size { 5352130Smckusick u_long strtblk; 5453202Sralph u_long nblocks; 5552130Smckusick }; 5652130Smckusick 5752130Smckusick /* 5852130Smckusick * Since the SCSI standard tends to hide the disk structure, we define 5952130Smckusick * partitions in terms of DEV_BSIZE blocks. The default partition table 6053202Sralph * (for an unlabeled disk) reserves 8K for a boot area, has an 8 meg 6152130Smckusick * root and 32 meg of swap. The rest of the space on the drive goes in 6252130Smckusick * the G partition. As usual, the C partition covers the entire disk 6352130Smckusick * (including the boot area). 6452130Smckusick */ 65*56629Sralph static struct size rzdefaultpart[MAXPARTITIONS] = { 6653202Sralph 0, 16384, /* A */ 6753202Sralph 16384, 65536, /* B */ 6853202Sralph 0, 0, /* C */ 6953202Sralph 17408, 0, /* D */ 7053202Sralph 115712, 0, /* E */ 7153202Sralph 218112, 0, /* F */ 7253202Sralph 81920, 0, /* G */ 7353202Sralph 115712, 0, /* H */ 7452130Smckusick }; 7552130Smckusick 7653202Sralph #define RAWPART 2 /* 'c' partition */ /* XXX */ 7753202Sralph 7852130Smckusick struct rzstats { 7952130Smckusick long rzresets; 8052130Smckusick long rztransfers; 8152130Smckusick long rzpartials; 8252130Smckusick }; 8352130Smckusick 8452130Smckusick struct rz_softc { 8552130Smckusick struct scsi_device *sc_sd; /* physical unit info */ 8653202Sralph pid_t sc_format_pid; /* process using "format" mode */ 8753202Sralph u_long sc_openpart; /* partitions open */ 8853202Sralph u_long sc_bopenpart; /* block partitions open */ 8953202Sralph u_long sc_copenpart; /* character partitions open */ 9052130Smckusick short sc_flags; /* see below */ 9152130Smckusick short sc_type; /* drive type from INQUIRY cmd */ 9252130Smckusick u_int sc_blks; /* number of blocks on device */ 9352130Smckusick int sc_blksize; /* device block size in bytes */ 9452130Smckusick int sc_bshift; /* convert device blocks to DEV_BSIZE */ 9552130Smckusick u_int sc_wpms; /* average xfer rate in 16bit wds/sec */ 9653202Sralph struct disklabel sc_label; /* disk label for this disk */ 9752130Smckusick struct rzstats sc_stats; /* statisic counts */ 9852130Smckusick struct buf sc_tab; /* queue of pending operations */ 9952130Smckusick struct buf sc_buf; /* buf for doing I/O */ 10052130Smckusick struct buf sc_errbuf; /* buf for doing REQUEST_SENSE */ 10152130Smckusick struct ScsiCmd sc_cmd; /* command for controller */ 10252130Smckusick ScsiGroup1Cmd sc_rwcmd; /* SCSI cmd if not in "format" mode */ 10352130Smckusick struct scsi_fmt_cdb sc_cdb; /* SCSI cmd if in "format" mode */ 10452130Smckusick struct scsi_fmt_sense sc_sense; /* sense data from last cmd */ 10552130Smckusick } rz_softc[NRZ]; 10652130Smckusick 10752130Smckusick /* sc_flags values */ 10853202Sralph #define RZF_ALIVE 0x01 /* drive found and ready */ 10953202Sralph #define RZF_SENSEINPROGRESS 0x02 /* REQUEST_SENSE command in progress */ 11053202Sralph #define RZF_HAVELABEL 0x04 /* valid label found on disk */ 11153202Sralph #define RZF_WLABEL 0x08 /* label is writeable */ 11252130Smckusick 11352130Smckusick #ifdef DEBUG 11452130Smckusick int rzdebug = 3; 11552130Smckusick #define RZB_ERROR 0x01 11652130Smckusick #define RZB_PARTIAL 0x02 11752130Smckusick #define RZB_PRLABEL 0x04 11852130Smckusick #endif 11952130Smckusick 12053202Sralph #define rzunit(x) (minor(x) >> 3) 12152130Smckusick #define rzpart(x) (minor(x) & 0x7) 12252130Smckusick #define b_cylin b_resid 12352130Smckusick 12452130Smckusick /* 12552130Smckusick * Table of scsi commands users are allowed to access via "format" mode. 12652130Smckusick * 0 means not legal. 12752130Smckusick * 1 means legal. 12852130Smckusick */ 12952130Smckusick static char legal_cmds[256] = { 13052130Smckusick /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 13152130Smckusick /*00*/ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13252130Smckusick /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 13352130Smckusick /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13452130Smckusick /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13552130Smckusick /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13652130Smckusick /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13752130Smckusick /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13852130Smckusick /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13952130Smckusick /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14052130Smckusick /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14152130Smckusick /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14252130Smckusick /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14352130Smckusick /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14452130Smckusick /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14552130Smckusick /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14652130Smckusick /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14752130Smckusick }; 14852130Smckusick 14952130Smckusick /* 15052130Smckusick * Test to see if device is present. 15152130Smckusick * Return true if found and initialized ok. 15252130Smckusick */ 15352130Smckusick rzprobe(sd) 15452130Smckusick register struct scsi_device *sd; 15552130Smckusick { 15652130Smckusick register struct rz_softc *sc = &rz_softc[sd->sd_unit]; 15752130Smckusick register int tries, i; 15852130Smckusick ScsiInquiryData inqbuf; 15952130Smckusick u_char capbuf[8]; 16052130Smckusick ScsiClass7Sense *sp; 16152130Smckusick 16252130Smckusick /* init some parameters that don't change */ 16352130Smckusick sc->sc_sd = sd; 16452130Smckusick sc->sc_cmd.sd = sd; 16552130Smckusick sc->sc_cmd.unit = sd->sd_unit; 16652130Smckusick sc->sc_rwcmd.unitNumber = sd->sd_slave; 16752130Smckusick 16852130Smckusick /* try to find out what type of device this is */ 16952130Smckusick sc->sc_format_pid = 1; /* force use of sc_cdb */ 17052130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 17152130Smckusick scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), 17252130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 17352130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 17452130Smckusick sc->sc_buf.b_bcount = sizeof(inqbuf); 17552130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf; 176*56629Sralph sc->sc_buf.b_actf = (struct buf *)0; 177*56629Sralph sc->sc_tab.b_actf = &sc->sc_buf; 17852130Smckusick rzstart(sd->sd_unit); 17952130Smckusick if (biowait(&sc->sc_buf) || 18052130Smckusick (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5) 18152130Smckusick goto bad; 18252130Smckusick switch (inqbuf.type) { 18352130Smckusick case SCSI_DISK_TYPE: /* disk */ 18452130Smckusick case SCSI_WORM_TYPE: /* WORM */ 18552130Smckusick case SCSI_ROM_TYPE: /* CD-ROM */ 18652130Smckusick case SCSI_OPTICAL_MEM_TYPE: /* Magneto-optical */ 18752130Smckusick break; 18852130Smckusick 18952130Smckusick default: /* not a disk */ 19052130Smckusick goto bad; 19152130Smckusick } 19252130Smckusick sc->sc_type = inqbuf.type; 19352130Smckusick 19452130Smckusick /* see if device is ready */ 19552130Smckusick for (tries = 10; ; ) { 19652130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 19752130Smckusick scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0, 19852130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 19952130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 20052130Smckusick sc->sc_buf.b_bcount = 0; 20152130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 202*56629Sralph sc->sc_buf.b_actf = (struct buf *)0; 203*56629Sralph sc->sc_tab.b_actf = &sc->sc_buf; 20452130Smckusick 20552130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 20652130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 20752130Smckusick sc->sc_cmd.buf = (caddr_t)0; 20852130Smckusick sc->sc_cmd.buflen = 0; 20952130Smckusick /* setup synchronous data transfers if the device supports it */ 21052130Smckusick if (tries == 10 && (inqbuf.flags & SCSI_SYNC)) 21152130Smckusick sc->sc_cmd.flags = SCSICMD_USE_SYNC; 21252130Smckusick else 21352130Smckusick sc->sc_cmd.flags = 0; 21452130Smckusick 21552130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 21652130Smckusick if (!biowait(&sc->sc_buf)) 21752130Smckusick break; 21852130Smckusick if (--tries < 0) 21952130Smckusick goto bad; 22052130Smckusick if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) 22152130Smckusick goto again; 22252130Smckusick sp = (ScsiClass7Sense *)sc->sc_sense.sense; 22352130Smckusick if (sp->error7 != 0x70) 22452130Smckusick goto again; 22552130Smckusick if (sp->key == SCSI_CLASS7_UNIT_ATTN && tries != 9) { 22652130Smckusick /* drive recalibrating, give it a while */ 22752130Smckusick DELAY(1000000); 22852130Smckusick continue; 22952130Smckusick } 23052130Smckusick if (sp->key == SCSI_CLASS7_NOT_READY) { 23152130Smckusick ScsiStartStopCmd *cp; 23252130Smckusick 23352130Smckusick /* try to spin-up disk with start/stop command */ 23452130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 23552130Smckusick cp = (ScsiStartStopCmd *)sc->sc_cdb.cdb; 23652130Smckusick cp->command = SCSI_START_STOP; 23752130Smckusick cp->unitNumber = sd->sd_slave; 23852130Smckusick cp->immed = 0; 23952130Smckusick cp->loadEject = 0; 24052130Smckusick cp->start = 1; 24152130Smckusick cp->pad1 = 0; 24252130Smckusick cp->pad2 = 0; 24352130Smckusick cp->pad3 = 0; 24452130Smckusick cp->pad4 = 0; 24552130Smckusick cp->control = 0; 24652130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 24752130Smckusick sc->sc_buf.b_bcount = 0; 24852130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 249*56629Sralph sc->sc_buf.b_actf = (struct buf *)0; 250*56629Sralph sc->sc_tab.b_actf = &sc->sc_buf; 25152130Smckusick rzstart(sd->sd_unit); 25252130Smckusick if (biowait(&sc->sc_buf)) 25352130Smckusick goto bad; 25452130Smckusick continue; 25552130Smckusick } 25652130Smckusick again: 25752130Smckusick DELAY(1000); 25852130Smckusick } 25952130Smckusick 26052130Smckusick /* find out how big a disk this is */ 26152130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup1Cmd); 26252130Smckusick scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, 26352130Smckusick (ScsiGroup1Cmd *)sc->sc_cdb.cdb); 26452130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 26552130Smckusick sc->sc_buf.b_bcount = sizeof(capbuf); 26652130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)capbuf; 267*56629Sralph sc->sc_buf.b_actf = (struct buf *)0; 268*56629Sralph sc->sc_tab.b_actf = &sc->sc_buf; 26952130Smckusick rzstart(sd->sd_unit); 27052130Smckusick if (biowait(&sc->sc_buf) || sc->sc_buf.b_resid != 0) 27152130Smckusick goto bad; 27253202Sralph sc->sc_blks = ((capbuf[0] << 24) | (capbuf[1] << 16) | 27353202Sralph (capbuf[2] << 8) | capbuf[3]) + 1; 27452130Smckusick sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) | 27552130Smckusick (capbuf[6] << 8) | capbuf[7]; 27652130Smckusick 27752130Smckusick printf("rz%d at %s%d drive %d slave %d", sd->sd_unit, 27852130Smckusick sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive, 27952130Smckusick sd->sd_slave); 28052130Smckusick if (inqbuf.version > 1 || i < 36) 28152130Smckusick printf(" type 0x%x, qual 0x%x, ver %d", 28252130Smckusick inqbuf.type, inqbuf.qualifier, inqbuf.version); 28352130Smckusick else { 28452130Smckusick char vid[9], pid[17], revl[5]; 28552130Smckusick 28652130Smckusick bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8); 28752130Smckusick bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16); 28852130Smckusick bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4); 28952130Smckusick for (i = 8; --i > 0; ) 29052130Smckusick if (vid[i] != ' ') 29152130Smckusick break; 29252130Smckusick vid[i+1] = 0; 29352130Smckusick for (i = 16; --i > 0; ) 29452130Smckusick if (pid[i] != ' ') 29552130Smckusick break; 29652130Smckusick pid[i+1] = 0; 29752130Smckusick for (i = 4; --i > 0; ) 29852130Smckusick if (revl[i] != ' ') 29952130Smckusick break; 30052130Smckusick revl[i+1] = 0; 30152130Smckusick printf(" %s %s rev %s", vid, pid, revl); 30252130Smckusick } 30352130Smckusick printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 30452130Smckusick if (sc->sc_blksize != DEV_BSIZE) { 30552130Smckusick if (sc->sc_blksize < DEV_BSIZE) { 30652130Smckusick printf("rz%d: need %d byte blocks - drive ignored\n", 30752130Smckusick sd->sd_unit, DEV_BSIZE); 30852130Smckusick goto bad; 30952130Smckusick } 31052130Smckusick for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 31152130Smckusick ++sc->sc_bshift; 31252130Smckusick sc->sc_blks <<= sc->sc_bshift; 31352130Smckusick } 31452130Smckusick sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 31552130Smckusick sc->sc_format_pid = 0; 31652130Smckusick sc->sc_flags = RZF_ALIVE; 31752130Smckusick sc->sc_buf.b_flags = 0; 31852130Smckusick return (1); 31952130Smckusick 32052130Smckusick bad: 32152130Smckusick /* doesn't exist or not a CCS device */ 32252130Smckusick sc->sc_format_pid = 0; 32352130Smckusick sc->sc_buf.b_flags = 0; 32452130Smckusick return (0); 32552130Smckusick } 32652130Smckusick 32752130Smckusick /* 32852130Smckusick * This routine is called for partial block transfers and non-aligned 32952130Smckusick * transfers (the latter only being possible on devices with a block size 33052130Smckusick * larger than DEV_BSIZE). The operation is performed in three steps 33152130Smckusick * using a locally allocated buffer: 33252130Smckusick * 1. transfer any initial partial block 33352130Smckusick * 2. transfer full blocks 33452130Smckusick * 3. transfer any final partial block 33552130Smckusick */ 33652130Smckusick static void 33752130Smckusick rzlblkstrat(bp, bsize) 33852130Smckusick register struct buf *bp; 33952130Smckusick register int bsize; 34052130Smckusick { 34152130Smckusick register struct buf *cbp; 34252130Smckusick caddr_t cbuf; 34352130Smckusick register int bn, resid; 34452130Smckusick register caddr_t addr; 34552130Smckusick 34652130Smckusick cbp = (struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK); 34752130Smckusick cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); 34852130Smckusick bzero((caddr_t)cbp, sizeof(*cbp)); 34952130Smckusick cbp->b_proc = curproc; 35052130Smckusick cbp->b_dev = bp->b_dev; 35152130Smckusick bn = bp->b_blkno; 35252130Smckusick resid = bp->b_bcount; 35352130Smckusick addr = bp->b_un.b_addr; 35452130Smckusick #ifdef DEBUG 35552130Smckusick if (rzdebug & RZB_PARTIAL) 35652130Smckusick printf("rzlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", 35752130Smckusick bp, bp->b_flags, bn, resid, addr); 35852130Smckusick #endif 35952130Smckusick 36052130Smckusick while (resid > 0) { 36152130Smckusick register int boff = dbtob(bn) & (bsize - 1); 36252130Smckusick register int count; 36352130Smckusick 36452130Smckusick if (boff || resid < bsize) { 36552130Smckusick rz_softc[rzunit(bp->b_dev)].sc_stats.rzpartials++; 36655746Sralph count = min(resid, bsize - boff); 36752130Smckusick cbp->b_flags = B_BUSY | B_PHYS | B_READ; 36852130Smckusick cbp->b_blkno = bn - btodb(boff); 36952130Smckusick cbp->b_un.b_addr = cbuf; 37052130Smckusick cbp->b_bcount = bsize; 37152130Smckusick #ifdef DEBUG 37252130Smckusick if (rzdebug & RZB_PARTIAL) 37352130Smckusick printf(" readahead: bn %x cnt %x off %x addr %x\n", 37452130Smckusick cbp->b_blkno, count, boff, addr); 37552130Smckusick #endif 37652130Smckusick rzstrategy(cbp); 37752130Smckusick biowait(cbp); 37852130Smckusick if (cbp->b_flags & B_ERROR) { 37952130Smckusick bp->b_flags |= B_ERROR; 38052130Smckusick bp->b_error = cbp->b_error; 38152130Smckusick break; 38252130Smckusick } 38352130Smckusick if (bp->b_flags & B_READ) { 38452130Smckusick bcopy(&cbuf[boff], addr, count); 38552130Smckusick goto done; 38652130Smckusick } 38752130Smckusick bcopy(addr, &cbuf[boff], count); 38852130Smckusick #ifdef DEBUG 38952130Smckusick if (rzdebug & RZB_PARTIAL) 39052130Smckusick printf(" writeback: bn %x cnt %x off %x addr %x\n", 39152130Smckusick cbp->b_blkno, count, boff, addr); 39252130Smckusick #endif 39352130Smckusick } else { 39452130Smckusick count = resid & ~(bsize - 1); 39552130Smckusick cbp->b_blkno = bn; 39652130Smckusick cbp->b_un.b_addr = addr; 39752130Smckusick cbp->b_bcount = count; 39852130Smckusick #ifdef DEBUG 39952130Smckusick if (rzdebug & RZB_PARTIAL) 40052130Smckusick printf(" fulltrans: bn %x cnt %x addr %x\n", 40152130Smckusick cbp->b_blkno, count, addr); 40252130Smckusick #endif 40352130Smckusick } 40452130Smckusick cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ); 40552130Smckusick rzstrategy(cbp); 40652130Smckusick biowait(cbp); 40752130Smckusick if (cbp->b_flags & B_ERROR) { 40852130Smckusick bp->b_flags |= B_ERROR; 40952130Smckusick bp->b_error = cbp->b_error; 41052130Smckusick break; 41152130Smckusick } 41252130Smckusick done: 41352130Smckusick bn += btodb(count); 41452130Smckusick resid -= count; 41552130Smckusick addr += count; 41652130Smckusick #ifdef DEBUG 41752130Smckusick if (rzdebug & RZB_PARTIAL) 41852130Smckusick printf(" done: bn %x resid %x addr %x\n", 41952130Smckusick bn, resid, addr); 42052130Smckusick #endif 42152130Smckusick } 42252130Smckusick free(cbuf, M_DEVBUF); 42352130Smckusick free(cbp, M_DEVBUF); 42452130Smckusick } 42552130Smckusick 42652130Smckusick void 42752130Smckusick rzstrategy(bp) 42852130Smckusick register struct buf *bp; 42952130Smckusick { 43052130Smckusick register int unit = rzunit(bp->b_dev); 43152130Smckusick register int part = rzpart(bp->b_dev); 43252130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 43353202Sralph register struct partition *pp = &sc->sc_label.d_partitions[part]; 434*56629Sralph register daddr_t bn; 435*56629Sralph register long sz, s; 43652130Smckusick 43752130Smckusick if (sc->sc_format_pid) { 43852130Smckusick if (sc->sc_format_pid != curproc->p_pid) { 43952130Smckusick bp->b_error = EPERM; 44052130Smckusick goto bad; 44152130Smckusick } 44252130Smckusick bp->b_cylin = 0; 44352130Smckusick } else { 44452130Smckusick bn = bp->b_blkno; 445*56629Sralph sz = howmany(bp->b_bcount, DEV_BSIZE); 446*56629Sralph if ((unsigned)bn + sz > pp->p_size) { 447*56629Sralph sz = pp->p_size - bn; 44853202Sralph /* if exactly at end of disk, return an EOF */ 449*56629Sralph if (sz == 0) { 45052130Smckusick bp->b_resid = bp->b_bcount; 45152130Smckusick goto done; 45252130Smckusick } 45353202Sralph /* if none of it fits, error */ 454*56629Sralph if (sz < 0) { 45553202Sralph bp->b_error = EINVAL; 45653202Sralph goto bad; 45753202Sralph } 45853202Sralph /* otherwise, truncate */ 459*56629Sralph bp->b_bcount = dbtob(sz); 46053202Sralph } 46153202Sralph /* check for write to write protected label */ 46253202Sralph if (bn + pp->p_offset <= LABELSECTOR && 46353202Sralph #if LABELSECTOR != 0 46453202Sralph bn + pp->p_offset + sz > LABELSECTOR && 46553202Sralph #endif 46653202Sralph !(bp->b_flags & B_READ) && !(sc->sc_flags & RZF_WLABEL)) { 46753202Sralph bp->b_error = EROFS; 46852130Smckusick goto bad; 46952130Smckusick } 47052130Smckusick /* 47152130Smckusick * Non-aligned or partial-block transfers handled specially. 47252130Smckusick */ 47352130Smckusick s = sc->sc_blksize - 1; 47452130Smckusick if ((dbtob(bn) & s) || (bp->b_bcount & s)) { 47552130Smckusick rzlblkstrat(bp, sc->sc_blksize); 47652130Smckusick goto done; 47752130Smckusick } 47853202Sralph bp->b_cylin = (bn + pp->p_offset) >> sc->sc_bshift; 47952130Smckusick } 48052130Smckusick /* don't let disksort() see sc_errbuf */ 48152130Smckusick while (sc->sc_flags & RZF_SENSEINPROGRESS) 48252130Smckusick printf("SENSE\n"); /* XXX */ 48352130Smckusick s = splbio(); 48452130Smckusick disksort(&sc->sc_tab, bp); 48552130Smckusick if (sc->sc_tab.b_active == 0) { 48652130Smckusick sc->sc_tab.b_active = 1; 48752130Smckusick rzstart(unit); 48852130Smckusick } 48952130Smckusick splx(s); 49052130Smckusick return; 49152130Smckusick bad: 49252130Smckusick bp->b_flags |= B_ERROR; 49352130Smckusick done: 49452130Smckusick biodone(bp); 49552130Smckusick } 49652130Smckusick 49752130Smckusick void 49852130Smckusick rzstart(unit) 49952130Smckusick int unit; 50052130Smckusick { 50152130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 50252130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 50352130Smckusick register int n; 50452130Smckusick 50552130Smckusick sc->sc_cmd.buf = bp->b_un.b_addr; 50652130Smckusick sc->sc_cmd.buflen = bp->b_bcount; 50752130Smckusick 50852130Smckusick if (sc->sc_format_pid || (sc->sc_flags & RZF_SENSEINPROGRESS)) { 50952130Smckusick sc->sc_cmd.flags = !(bp->b_flags & B_READ) ? 51052130Smckusick SCSICMD_DATA_TO_DEVICE : 0; 51152130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 51252130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 51352130Smckusick } else { 51452130Smckusick if (bp->b_flags & B_READ) { 51552130Smckusick sc->sc_cmd.flags = 0; 51652130Smckusick sc->sc_rwcmd.command = SCSI_READ_EXT; 51752130Smckusick } else { 51852130Smckusick sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE; 51952130Smckusick sc->sc_rwcmd.command = SCSI_WRITE_EXT; 52052130Smckusick } 52152130Smckusick sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 52252130Smckusick sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd); 52352130Smckusick n = bp->b_cylin; 52452130Smckusick sc->sc_rwcmd.highAddr = n >> 24; 52552130Smckusick sc->sc_rwcmd.midHighAddr = n >> 16; 52652130Smckusick sc->sc_rwcmd.midLowAddr = n >> 8; 52752130Smckusick sc->sc_rwcmd.lowAddr = n; 52852130Smckusick n = howmany(bp->b_bcount, sc->sc_blksize); 52952130Smckusick sc->sc_rwcmd.highBlockCount = n >> 8; 53052130Smckusick sc->sc_rwcmd.lowBlockCount = n; 53152130Smckusick #ifdef DEBUG 53252130Smckusick if ((bp->b_bcount & (sc->sc_blksize - 1)) != 0) 53352130Smckusick printf("rz%d: partial block xfer -- %x bytes\n", 53452130Smckusick unit, bp->b_bcount); 53552130Smckusick #endif 53652130Smckusick sc->sc_stats.rztransfers++; 53752130Smckusick if ((n = sc->sc_sd->sd_dk) >= 0) { 53852130Smckusick dk_busy |= 1 << n; 53952130Smckusick ++dk_seek[n]; 54052130Smckusick ++dk_xfer[n]; 54152130Smckusick dk_wds[n] += bp->b_bcount >> 6; 54252130Smckusick } 54352130Smckusick } 54452130Smckusick 54552130Smckusick /* tell controller to start this command */ 54652130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 54752130Smckusick } 54852130Smckusick 54952130Smckusick /* 55052130Smckusick * This is called by the controller driver when the command is done. 55152130Smckusick */ 55252130Smckusick void 55352130Smckusick rzdone(unit, error, resid, status) 55452130Smckusick register int unit; 55552130Smckusick int error; /* error number from errno.h */ 55652130Smckusick int resid; /* amount not transfered */ 55752130Smckusick int status; /* SCSI status byte */ 55852130Smckusick { 55952130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 56052130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 56152130Smckusick register struct scsi_device *sd = sc->sc_sd; 56252130Smckusick extern int cold; 56352130Smckusick 56452130Smckusick if (bp == NULL) { 56552130Smckusick printf("rz%d: bp == NULL\n", unit); 56652130Smckusick return; 56752130Smckusick } 56852130Smckusick if (sd->sd_dk >= 0) 56952130Smckusick dk_busy &= ~(1 << sd->sd_dk); 57052130Smckusick if (sc->sc_flags & RZF_SENSEINPROGRESS) { 57152130Smckusick sc->sc_flags &= ~RZF_SENSEINPROGRESS; 572*56629Sralph sc->sc_tab.b_actf = bp = bp->b_actf; /* remove sc_errbuf */ 57352130Smckusick 57452130Smckusick if (error || (status & SCSI_STATUS_CHECKCOND)) { 57552130Smckusick #ifdef DEBUG 57652130Smckusick if (rzdebug & RZB_ERROR) 57752130Smckusick printf("rz%d: error reading sense data: error %d scsi status 0x%x\n", 57852130Smckusick unit, error, status); 57952130Smckusick #endif 58052130Smckusick /* 58152130Smckusick * We got an error during the REQUEST_SENSE, 58252130Smckusick * fill in no sense for data. 58352130Smckusick */ 58452130Smckusick sc->sc_sense.sense[0] = 0x70; 58552130Smckusick sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE; 58653083Sralph } else if (!cold) { 58752130Smckusick printf("rz%d: ", unit); 58852130Smckusick scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense, 58952130Smckusick sizeof(sc->sc_sense.sense) - resid); 59052130Smckusick } 59152130Smckusick } else if (error || (status & SCSI_STATUS_CHECKCOND)) { 59252130Smckusick #ifdef DEBUG 59353083Sralph if (!cold && (rzdebug & RZB_ERROR)) 59452130Smckusick printf("rz%d: error %d scsi status 0x%x\n", 59552130Smckusick unit, error, status); 59652130Smckusick #endif 59752130Smckusick /* save error info */ 59852130Smckusick sc->sc_sense.status = status; 59952130Smckusick bp->b_flags |= B_ERROR; 60052130Smckusick bp->b_error = error; 60152130Smckusick bp->b_resid = resid; 60252130Smckusick 60352130Smckusick if (status & SCSI_STATUS_CHECKCOND) { 60452130Smckusick /* 60552130Smckusick * Start a REQUEST_SENSE command. 60652130Smckusick * Since we are called at interrupt time, we can't 60752130Smckusick * wait for the command to finish; that's why we use 60852130Smckusick * the sc_flags field. 60952130Smckusick */ 61052130Smckusick sc->sc_flags |= RZF_SENSEINPROGRESS; 61152130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 61252130Smckusick scsiGroup0Cmd(SCSI_REQUEST_SENSE, sd->sd_slave, 0, 61352130Smckusick sizeof(sc->sc_sense.sense), 61452130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 61552130Smckusick sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ; 61652130Smckusick sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense); 61752130Smckusick sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense; 618*56629Sralph sc->sc_errbuf.b_actf = bp; 61952130Smckusick sc->sc_tab.b_actf = &sc->sc_errbuf; 62052130Smckusick rzstart(unit); 62152130Smckusick return; 62252130Smckusick } 62352130Smckusick } else { 62452130Smckusick sc->sc_sense.status = status; 62552130Smckusick bp->b_resid = resid; 62652130Smckusick } 62752130Smckusick 628*56629Sralph sc->sc_tab.b_actf = bp->b_actf; 62952130Smckusick biodone(bp); 63052130Smckusick if (sc->sc_tab.b_actf) 63152130Smckusick rzstart(unit); 63253202Sralph else { 63352130Smckusick sc->sc_tab.b_active = 0; 63453202Sralph /* finish close protocol */ 63553202Sralph if (sc->sc_openpart == 0) 63653202Sralph wakeup((caddr_t)&sc->sc_tab); 63753202Sralph } 63852130Smckusick } 63952130Smckusick 64052130Smckusick int 64152130Smckusick rzopen(dev, flags, mode, p) 64252130Smckusick dev_t dev; 64352130Smckusick int flags, mode; 64452130Smckusick struct proc *p; 64552130Smckusick { 64652130Smckusick register int unit = rzunit(dev); 64752130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 64853202Sralph register struct disklabel *lp; 64953202Sralph register int i; 65053202Sralph char *err_msg; 65153202Sralph int part; 65253202Sralph u_long mask; 65352130Smckusick 65453202Sralph if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE)) 65552130Smckusick return (ENXIO); 65653202Sralph 65753202Sralph /* try to read disk label and partition table information */ 65853202Sralph part = rzpart(dev); 65953202Sralph lp = &sc->sc_label; 66053202Sralph if (!(sc->sc_flags & RZF_HAVELABEL)) { 66153202Sralph sc->sc_flags |= RZF_HAVELABEL; 66253202Sralph lp->d_secsize = DEV_BSIZE; 66353202Sralph lp->d_secpercyl = 1 << sc->sc_bshift; 66453202Sralph lp->d_npartitions = MAXPARTITIONS; 66553202Sralph lp->d_partitions[part].p_offset = 0; 66653202Sralph lp->d_partitions[part].p_size = sc->sc_blks; 66753202Sralph if (err_msg = readdisklabel(dev, rzstrategy, lp)) { 66853202Sralph printf("rz%d: %s\n", unit, err_msg); 66953202Sralph sc->sc_label.d_magic = DISKMAGIC; 67053202Sralph sc->sc_label.d_magic2 = DISKMAGIC; 67153202Sralph sc->sc_label.d_type = DTYPE_SCSI; 67253202Sralph sc->sc_label.d_subtype = 0; 67353202Sralph sc->sc_label.d_typename[0] = '\0'; 67453202Sralph sc->sc_label.d_secsize = DEV_BSIZE; 67553202Sralph sc->sc_label.d_secperunit = sc->sc_blks; 67653202Sralph sc->sc_label.d_npartitions = MAXPARTITIONS; 67753202Sralph sc->sc_label.d_bbsize = BBSIZE; 67853202Sralph sc->sc_label.d_sbsize = SBSIZE; 67953202Sralph for (i = 0; i < MAXPARTITIONS; i++) { 68053202Sralph sc->sc_label.d_partitions[i].p_size = 68153202Sralph rzdefaultpart[i].nblocks; 68253202Sralph sc->sc_label.d_partitions[i].p_offset = 68353202Sralph rzdefaultpart[i].strtblk; 68453202Sralph } 68553202Sralph sc->sc_label.d_partitions[RAWPART].p_size = 68653202Sralph sc->sc_blks; 68753202Sralph } 68853202Sralph } 68953202Sralph 69053202Sralph if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) 69152130Smckusick return (ENXIO); 69253202Sralph /* 69353202Sralph * Warn if a partition is opened that overlaps another 69453202Sralph * already open, unless either is the `raw' partition 69553202Sralph * (whole disk). 69653202Sralph */ 69753202Sralph mask = 1 << part; 69853202Sralph if ((sc->sc_openpart & mask) == 0 && part != RAWPART) { 69953202Sralph register struct partition *pp; 70053202Sralph u_long start, end; 70152130Smckusick 70253202Sralph pp = &lp->d_partitions[part]; 70353202Sralph start = pp->p_offset; 70453202Sralph end = pp->p_offset + pp->p_size; 70553202Sralph for (pp = lp->d_partitions, i = 0; 70653202Sralph i < lp->d_npartitions; pp++, i++) { 70753202Sralph if (pp->p_offset + pp->p_size <= start || 70853202Sralph pp->p_offset >= end || i == RAWPART) 70953202Sralph continue; 71053202Sralph if (sc->sc_openpart & (1 << i)) 71153202Sralph log(LOG_WARNING, 71253202Sralph "rz%d%c: overlaps open partition (%c)\n", 71353202Sralph unit, part + 'a', i + 'a'); 71453202Sralph } 71553202Sralph } 71653202Sralph switch (mode) { 71753202Sralph case S_IFCHR: 71853202Sralph sc->sc_copenpart |= mask; 71953202Sralph break; 72053202Sralph case S_IFBLK: 72153202Sralph sc->sc_bopenpart |= mask; 72253202Sralph break; 72353202Sralph } 72453202Sralph sc->sc_openpart |= mask; 72552130Smckusick if (sc->sc_sd->sd_dk >= 0) 72652130Smckusick dk_wpms[sc->sc_sd->sd_dk] = sc->sc_wpms; 72752130Smckusick return (0); 72852130Smckusick } 72952130Smckusick 73053202Sralph rzclose(dev, flags, mode) 73152130Smckusick dev_t dev; 73253202Sralph int flags, mode; 73352130Smckusick { 73453202Sralph register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 73553202Sralph u_long mask = (1 << rzpart(dev)); 73653202Sralph int s; 73753202Sralph 73853202Sralph switch (mode) { 73953202Sralph case S_IFCHR: 74053202Sralph sc->sc_copenpart &= ~mask; 74153202Sralph break; 74253202Sralph case S_IFBLK: 74353202Sralph sc->sc_bopenpart &= ~mask; 74453202Sralph break; 74553202Sralph } 74653202Sralph sc->sc_openpart = sc->sc_copenpart | sc->sc_bopenpart; 74753202Sralph 74853202Sralph /* 74953202Sralph * Should wait for I/O to complete on this partition even if 75053202Sralph * others are open, but wait for work on blkflush(). 75153202Sralph */ 75253202Sralph if (sc->sc_openpart == 0) { 75353202Sralph s = splbio(); 75453202Sralph while (sc->sc_tab.b_actf) 75553202Sralph sleep((caddr_t)&sc->sc_tab, PZERO - 1); 75653202Sralph splx(s); 75753202Sralph sc->sc_flags &= ~RZF_WLABEL; 75853202Sralph } 75952130Smckusick return (0); 76052130Smckusick } 76152130Smckusick 76252130Smckusick int 76352130Smckusick rzread(dev, uio) 76452130Smckusick dev_t dev; 76552130Smckusick struct uio *uio; 76652130Smckusick { 76752130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 76852130Smckusick 76952130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 77052130Smckusick return (EPERM); 77152130Smckusick 77252130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 77352130Smckusick B_READ, minphys, uio)); 77452130Smckusick } 77552130Smckusick 77652130Smckusick int 77752130Smckusick rzwrite(dev, uio) 77852130Smckusick dev_t dev; 77952130Smckusick struct uio *uio; 78052130Smckusick { 78152130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 78252130Smckusick 78352130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 78452130Smckusick return (EPERM); 78552130Smckusick 78652130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 78752130Smckusick B_WRITE, minphys, uio)); 78852130Smckusick } 78952130Smckusick 79052130Smckusick int 79152130Smckusick rzioctl(dev, cmd, data, flag, p) 79252130Smckusick dev_t dev; 79352130Smckusick int cmd; 79452130Smckusick caddr_t data; 79552130Smckusick int flag; 79652130Smckusick struct proc *p; 79752130Smckusick { 79852130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 79953202Sralph int error; 80053202Sralph int flags; 80152130Smckusick 80252130Smckusick switch (cmd) { 80352130Smckusick default: 80452130Smckusick return (EINVAL); 80552130Smckusick 80652130Smckusick case SDIOCSFORMAT: 80752130Smckusick /* take this device into or out of "format" mode */ 80852130Smckusick if (suser(p->p_ucred, &p->p_acflag)) 80952130Smckusick return (EPERM); 81052130Smckusick 81152130Smckusick if (*(int *)data) { 81252130Smckusick if (sc->sc_format_pid) 81352130Smckusick return (EPERM); 81452130Smckusick sc->sc_format_pid = p->p_pid; 81552130Smckusick } else 81652130Smckusick sc->sc_format_pid = 0; 81752130Smckusick return (0); 81852130Smckusick 81952130Smckusick case SDIOCGFORMAT: 82052130Smckusick /* find out who has the device in format mode */ 82152130Smckusick *(int *)data = sc->sc_format_pid; 82252130Smckusick return (0); 82352130Smckusick 82452130Smckusick case SDIOCSCSICOMMAND: 82552130Smckusick /* 82652130Smckusick * Save what user gave us as SCSI cdb to use with next 82752130Smckusick * read or write to the char device. 82852130Smckusick */ 82952130Smckusick if (sc->sc_format_pid != p->p_pid) 83052130Smckusick return (EPERM); 83152130Smckusick if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0) 83252130Smckusick return (EINVAL); 83352130Smckusick bcopy(data, (caddr_t)&sc->sc_cdb, sizeof(sc->sc_cdb)); 83452130Smckusick return (0); 83552130Smckusick 83652130Smckusick case SDIOCSENSE: 83752130Smckusick /* 83852130Smckusick * return the SCSI sense data saved after the last 83952130Smckusick * operation that completed with "check condition" status. 84052130Smckusick */ 84152130Smckusick bcopy((caddr_t)&sc->sc_sense, data, sizeof(sc->sc_sense)); 84252130Smckusick return (0); 84352130Smckusick 84453202Sralph case DIOCGDINFO: 84553202Sralph /* get the current disk label */ 84653202Sralph *(struct disklabel *)data = sc->sc_label; 84753202Sralph return (0); 84853202Sralph 84953202Sralph case DIOCSDINFO: 85053202Sralph /* set the current disk label */ 85153202Sralph if (!(flag & FWRITE)) 85253202Sralph return (EBADF); 853*56629Sralph error = setdisklabel(&sc->sc_label, 85453202Sralph (struct disklabel *)data, 855*56629Sralph (sc->sc_flags & RZF_WLABEL) ? 0 : sc->sc_openpart); 856*56629Sralph return (error); 85753202Sralph 85853202Sralph case DIOCGPART: 85953202Sralph /* return the disk partition data */ 86053202Sralph ((struct partinfo *)data)->disklab = &sc->sc_label; 86153202Sralph ((struct partinfo *)data)->part = 86253202Sralph &sc->sc_label.d_partitions[rzpart(dev)]; 86353202Sralph return (0); 86453202Sralph 86553202Sralph case DIOCWLABEL: 86653202Sralph if (!(flag & FWRITE)) 86753202Sralph return (EBADF); 86853202Sralph if (*(int *)data) 86953202Sralph sc->sc_flags |= RZF_WLABEL; 87053202Sralph else 87153202Sralph sc->sc_flags &= ~RZF_WLABEL; 87253202Sralph return (0); 87353202Sralph 87453202Sralph case DIOCWDINFO: 87553202Sralph /* write the disk label to disk */ 87653202Sralph if (!(flag & FWRITE)) 87753202Sralph return (EBADF); 87853202Sralph error = setdisklabel(&sc->sc_label, 87953202Sralph (struct disklabel *)data, 88053202Sralph (sc->sc_flags & RZF_WLABEL) ? 0 : sc->sc_openpart); 88153202Sralph if (error) 88253202Sralph return (error); 88353202Sralph 88453202Sralph /* simulate opening partition 0 so write succeeds */ 88553202Sralph flags = sc->sc_flags; 88653202Sralph sc->sc_flags = RZF_ALIVE | RZF_WLABEL; 88753202Sralph error = writedisklabel(dev, rzstrategy, &sc->sc_label); 88853202Sralph sc->sc_flags = flags; 88953202Sralph return (error); 89052130Smckusick } 89152130Smckusick /*NOTREACHED*/ 89252130Smckusick } 89352130Smckusick 89452130Smckusick int 89552130Smckusick rzsize(dev) 89652130Smckusick dev_t dev; 89752130Smckusick { 89852130Smckusick register int unit = rzunit(dev); 89953202Sralph register int part = rzpart(dev); 90052130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 90152130Smckusick 90253202Sralph if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE) || 90353202Sralph part >= sc->sc_label.d_npartitions) 90452130Smckusick return (-1); 90552130Smckusick 90653202Sralph return (sc->sc_label.d_partitions[part].p_size); 90752130Smckusick } 90852130Smckusick 90952130Smckusick /* 91052130Smckusick * Non-interrupt driven, non-dma dump routine. 91152130Smckusick */ 91252130Smckusick int 91352130Smckusick rzdump(dev) 91452130Smckusick dev_t dev; 91552130Smckusick { 91652130Smckusick #ifdef notdef 91752130Smckusick int part = rzpart(dev); 91852130Smckusick int unit = rzunit(dev); 91952130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 92052130Smckusick register struct scsi_device *sd = sc->sc_hd; 92152130Smckusick register daddr_t baddr; 92252130Smckusick register int maddr; 92352130Smckusick register int pages, i; 92452130Smckusick int stat; 92552130Smckusick extern int lowram; 92652130Smckusick 92752130Smckusick /* 92852130Smckusick * Hmm... all vax drivers dump maxfree pages which is physmem minus 92952130Smckusick * the message buffer. Is there a reason for not dumping the 93052130Smckusick * message buffer? Savecore expects to read 'dumpsize' pages of 93152130Smckusick * dump, where dumpsys() sets dumpsize to physmem! 93252130Smckusick */ 93352130Smckusick pages = physmem; 93452130Smckusick 93552130Smckusick /* is drive ok? */ 93652130Smckusick if (unit >= NRZ || (sc->sc_flags & RZF_ALIVE) == 0) 93752130Smckusick return (ENXIO); 93852130Smckusick /* dump parameters in range? */ 93952130Smckusick if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks) 94052130Smckusick return (EINVAL); 94152130Smckusick if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks) 94252130Smckusick pages = dtoc(sc->sc_info.part[part].nblocks - dumplo); 94352130Smckusick maddr = lowram; 94452130Smckusick baddr = dumplo + sc->sc_info.part[part].strtblk; 94552130Smckusick /* scsi bus idle? */ 94652130Smckusick if (!scsireq(&sc->sc_dq)) { 94752130Smckusick scsireset(sd->sd_ctlr); 94852130Smckusick sc->sc_stats.rzresets++; 94952130Smckusick printf("[ drive %d reset ] ", unit); 95052130Smckusick } 95152130Smckusick for (i = 0; i < pages; i++) { 95252130Smckusick #define NPGMB (1024*1024/NBPG) 95352130Smckusick /* print out how many Mbs we have dumped */ 95452130Smckusick if (i && (i % NPGMB) == 0) 95552130Smckusick printf("%d ", i / NPGMB); 95652130Smckusick #undef NPBMG 95752130Smckusick mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); 95852130Smckusick stat = scsi_tt_write(sd->sd_ctlr, sd->sd_drive, sd->sd_slave, 95952130Smckusick vmmap, NBPG, baddr, sc->sc_bshift); 96052130Smckusick if (stat) { 96152130Smckusick printf("rzdump: scsi write error 0x%x\n", stat); 96252130Smckusick return (EIO); 96352130Smckusick } 96452130Smckusick maddr += NBPG; 96552130Smckusick baddr += ctod(1); 96652130Smckusick } 96752130Smckusick return (0); 96852130Smckusick #else notdef 96952130Smckusick return (ENXIO); 97052130Smckusick #endif notdef 97152130Smckusick } 97252130Smckusick #endif 973