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*53083Sralph * @(#)rz.c 7.2 (Berkeley) 03/29/92 1152130Smckusick */ 1252130Smckusick 1352130Smckusick /* 1452130Smckusick * SCSI CCS (Command Command Set) disk driver. 1552130Smckusick * NOTE: The name was changed from "sd" to "rz" for DEC compatibility. 1652130Smckusick * I guess I can't avoid confusion someplace. 1752130Smckusick */ 1852130Smckusick #include "rz.h" 1952130Smckusick #if NRZ > 0 2052130Smckusick 2152130Smckusick #include "param.h" 2252130Smckusick #include "systm.h" 2352130Smckusick #include "buf.h" 2452130Smckusick #include "errno.h" 2552130Smckusick #include "dkstat.h" 2652130Smckusick #include "disklabel.h" 2752130Smckusick #include "malloc.h" 2852130Smckusick 2952130Smckusick #include "device.h" 3052130Smckusick #include "scsi.h" 3152130Smckusick #include "devDiskLabel.h" 3252130Smckusick 3352130Smckusick #include "proc.h" 3452130Smckusick #include "uio.h" 3552130Smckusick 3652130Smckusick extern void printf(); 3752130Smckusick extern void bcopy(); 3852130Smckusick extern void disksort(); 3952130Smckusick extern int splbio(); 4052130Smckusick extern void splx(); 4152130Smckusick extern int physio(); 4252130Smckusick 4352130Smckusick int rzprobe(); 4452130Smckusick void rzstrategy(), rzstart(), rzdone(); 4552130Smckusick 4652130Smckusick struct driver rzdriver = { 4752130Smckusick "rz", rzprobe, rzstart, rzdone, 4852130Smckusick }; 4952130Smckusick 5052130Smckusick struct size { 5152130Smckusick u_long strtblk; 5252130Smckusick u_long endblk; 5352130Smckusick int nblocks; 5452130Smckusick }; 5552130Smckusick 5652130Smckusick struct rzinfo { 5752130Smckusick struct size part[8]; 5852130Smckusick }; 5952130Smckusick 6052130Smckusick /* 6152130Smckusick * Since the SCSI standard tends to hide the disk structure, we define 6252130Smckusick * partitions in terms of DEV_BSIZE blocks. The default partition table 6352130Smckusick * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg 6452130Smckusick * root and 32 meg of swap. The rest of the space on the drive goes in 6552130Smckusick * the G partition. As usual, the C partition covers the entire disk 6652130Smckusick * (including the boot area). 6752130Smckusick */ 6852130Smckusick struct rzinfo rzdefaultpart = { 6952130Smckusick 1024, 17408, 16384 , /* A */ 7052130Smckusick 17408, 82944, 65536 , /* B */ 7152130Smckusick 0, 0, 0 , /* C */ 7252130Smckusick 17408, 115712, 98304 , /* D */ 7352130Smckusick 115712, 218112, 102400 , /* E */ 7452130Smckusick 218112, 0, 0 , /* F */ 7552130Smckusick 82944, 0, 0 , /* G */ 7652130Smckusick 115712, 0, 0 , /* H */ 7752130Smckusick }; 7852130Smckusick 7952130Smckusick struct rzstats { 8052130Smckusick long rzresets; 8152130Smckusick long rztransfers; 8252130Smckusick long rzpartials; 8352130Smckusick }; 8452130Smckusick 8552130Smckusick struct rz_softc { 8652130Smckusick struct scsi_device *sc_sd; /* physical unit info */ 8752130Smckusick int sc_format_pid; /* process using "format" mode */ 8852130Smckusick short sc_flags; /* see below */ 8952130Smckusick short sc_type; /* drive type from INQUIRY cmd */ 9052130Smckusick u_int sc_blks; /* number of blocks on device */ 9152130Smckusick int sc_blksize; /* device block size in bytes */ 9252130Smckusick int sc_bshift; /* convert device blocks to DEV_BSIZE */ 9352130Smckusick u_int sc_wpms; /* average xfer rate in 16bit wds/sec */ 9452130Smckusick struct rzinfo sc_info; /* drive partition table & label info */ 9552130Smckusick struct rzstats sc_stats; /* statisic counts */ 9652130Smckusick struct buf sc_tab; /* queue of pending operations */ 9752130Smckusick struct buf sc_buf; /* buf for doing I/O */ 9852130Smckusick struct buf sc_errbuf; /* buf for doing REQUEST_SENSE */ 9952130Smckusick struct ScsiCmd sc_cmd; /* command for controller */ 10052130Smckusick ScsiGroup1Cmd sc_rwcmd; /* SCSI cmd if not in "format" mode */ 10152130Smckusick struct scsi_fmt_cdb sc_cdb; /* SCSI cmd if in "format" mode */ 10252130Smckusick struct scsi_fmt_sense sc_sense; /* sense data from last cmd */ 10352130Smckusick } rz_softc[NRZ]; 10452130Smckusick 10552130Smckusick /* sc_flags values */ 10652130Smckusick #define RZF_ALIVE 0x1 /* drive found and ready */ 10752130Smckusick #define RZF_SENSEINPROGRESS 0x2 /* REQUEST_SENSE command in progress */ 10852130Smckusick 10952130Smckusick #ifdef DEBUG 11052130Smckusick int rzdebug = 3; 11152130Smckusick #define RZB_ERROR 0x01 11252130Smckusick #define RZB_PARTIAL 0x02 11352130Smckusick #define RZB_PRLABEL 0x04 11452130Smckusick #endif 11552130Smckusick 11652130Smckusick #define rzunit(x) ((minor(x) >> 3) & 0x7) 11752130Smckusick #define rzpart(x) (minor(x) & 0x7) 11852130Smckusick #define b_cylin b_resid 11952130Smckusick 12052130Smckusick /* 12152130Smckusick * Table of scsi commands users are allowed to access via "format" mode. 12252130Smckusick * 0 means not legal. 12352130Smckusick * 1 means legal. 12452130Smckusick */ 12552130Smckusick static char legal_cmds[256] = { 12652130Smckusick /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 12752130Smckusick /*00*/ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12852130Smckusick /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 12952130Smckusick /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13052130Smckusick /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13152130Smckusick /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13252130Smckusick /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13352130Smckusick /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13452130Smckusick /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13552130Smckusick /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13652130Smckusick /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13752130Smckusick /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13852130Smckusick /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13952130Smckusick /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14052130Smckusick /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14152130Smckusick /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14252130Smckusick /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14352130Smckusick }; 14452130Smckusick 14552130Smckusick /* 14652130Smckusick * Test to see if device is present. 14752130Smckusick * Return true if found and initialized ok. 14852130Smckusick */ 14952130Smckusick rzprobe(sd) 15052130Smckusick register struct scsi_device *sd; 15152130Smckusick { 15252130Smckusick register struct rz_softc *sc = &rz_softc[sd->sd_unit]; 15352130Smckusick register int tries, i; 15452130Smckusick ScsiInquiryData inqbuf; 15552130Smckusick u_char capbuf[8]; 15652130Smckusick ScsiClass7Sense *sp; 15752130Smckusick 15852130Smckusick /* init some parameters that don't change */ 15952130Smckusick sc->sc_sd = sd; 16052130Smckusick sc->sc_cmd.sd = sd; 16152130Smckusick sc->sc_cmd.unit = sd->sd_unit; 16252130Smckusick sc->sc_rwcmd.unitNumber = sd->sd_slave; 16352130Smckusick 16452130Smckusick /* try to find out what type of device this is */ 16552130Smckusick sc->sc_format_pid = 1; /* force use of sc_cdb */ 16652130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 16752130Smckusick scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), 16852130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 16952130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 17052130Smckusick sc->sc_buf.b_bcount = sizeof(inqbuf); 17152130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf; 17252130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 17352130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 17452130Smckusick rzstart(sd->sd_unit); 17552130Smckusick if (biowait(&sc->sc_buf) || 17652130Smckusick (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5) 17752130Smckusick goto bad; 17852130Smckusick switch (inqbuf.type) { 17952130Smckusick case SCSI_DISK_TYPE: /* disk */ 18052130Smckusick case SCSI_WORM_TYPE: /* WORM */ 18152130Smckusick case SCSI_ROM_TYPE: /* CD-ROM */ 18252130Smckusick case SCSI_OPTICAL_MEM_TYPE: /* Magneto-optical */ 18352130Smckusick break; 18452130Smckusick 18552130Smckusick default: /* not a disk */ 18652130Smckusick goto bad; 18752130Smckusick } 18852130Smckusick sc->sc_type = inqbuf.type; 18952130Smckusick 19052130Smckusick /* see if device is ready */ 19152130Smckusick for (tries = 10; ; ) { 19252130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 19352130Smckusick scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0, 19452130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 19552130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 19652130Smckusick sc->sc_buf.b_bcount = 0; 19752130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 19852130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 19952130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 20052130Smckusick 20152130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 20252130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 20352130Smckusick sc->sc_cmd.buf = (caddr_t)0; 20452130Smckusick sc->sc_cmd.buflen = 0; 20552130Smckusick /* setup synchronous data transfers if the device supports it */ 20652130Smckusick if (tries == 10 && (inqbuf.flags & SCSI_SYNC)) 20752130Smckusick sc->sc_cmd.flags = SCSICMD_USE_SYNC; 20852130Smckusick else 20952130Smckusick sc->sc_cmd.flags = 0; 21052130Smckusick 21152130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 21252130Smckusick if (!biowait(&sc->sc_buf)) 21352130Smckusick break; 21452130Smckusick if (--tries < 0) 21552130Smckusick goto bad; 21652130Smckusick if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) 21752130Smckusick goto again; 21852130Smckusick sp = (ScsiClass7Sense *)sc->sc_sense.sense; 21952130Smckusick if (sp->error7 != 0x70) 22052130Smckusick goto again; 22152130Smckusick if (sp->key == SCSI_CLASS7_UNIT_ATTN && tries != 9) { 22252130Smckusick /* drive recalibrating, give it a while */ 22352130Smckusick DELAY(1000000); 22452130Smckusick continue; 22552130Smckusick } 22652130Smckusick if (sp->key == SCSI_CLASS7_NOT_READY) { 22752130Smckusick ScsiStartStopCmd *cp; 22852130Smckusick 22952130Smckusick /* try to spin-up disk with start/stop command */ 23052130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 23152130Smckusick cp = (ScsiStartStopCmd *)sc->sc_cdb.cdb; 23252130Smckusick cp->command = SCSI_START_STOP; 23352130Smckusick cp->unitNumber = sd->sd_slave; 23452130Smckusick cp->immed = 0; 23552130Smckusick cp->loadEject = 0; 23652130Smckusick cp->start = 1; 23752130Smckusick cp->pad1 = 0; 23852130Smckusick cp->pad2 = 0; 23952130Smckusick cp->pad3 = 0; 24052130Smckusick cp->pad4 = 0; 24152130Smckusick cp->control = 0; 24252130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 24352130Smckusick sc->sc_buf.b_bcount = 0; 24452130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 24552130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 24652130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 24752130Smckusick rzstart(sd->sd_unit); 24852130Smckusick if (biowait(&sc->sc_buf)) 24952130Smckusick goto bad; 25052130Smckusick continue; 25152130Smckusick } 25252130Smckusick again: 25352130Smckusick DELAY(1000); 25452130Smckusick } 25552130Smckusick 25652130Smckusick /* find out how big a disk this is */ 25752130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup1Cmd); 25852130Smckusick scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, 25952130Smckusick (ScsiGroup1Cmd *)sc->sc_cdb.cdb); 26052130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 26152130Smckusick sc->sc_buf.b_bcount = sizeof(capbuf); 26252130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)capbuf; 26352130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 26452130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 26552130Smckusick rzstart(sd->sd_unit); 26652130Smckusick if (biowait(&sc->sc_buf) || sc->sc_buf.b_resid != 0) 26752130Smckusick goto bad; 26852130Smckusick sc->sc_blks = (capbuf[0] << 24) | (capbuf[1] << 16) | 26952130Smckusick (capbuf[2] << 8) | capbuf[3]; 27052130Smckusick sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) | 27152130Smckusick (capbuf[6] << 8) | capbuf[7]; 27252130Smckusick 27352130Smckusick printf("rz%d at %s%d drive %d slave %d", sd->sd_unit, 27452130Smckusick sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive, 27552130Smckusick sd->sd_slave); 27652130Smckusick if (inqbuf.version > 1 || i < 36) 27752130Smckusick printf(" type 0x%x, qual 0x%x, ver %d", 27852130Smckusick inqbuf.type, inqbuf.qualifier, inqbuf.version); 27952130Smckusick else { 28052130Smckusick char vid[9], pid[17], revl[5]; 28152130Smckusick 28252130Smckusick bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8); 28352130Smckusick bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16); 28452130Smckusick bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4); 28552130Smckusick for (i = 8; --i > 0; ) 28652130Smckusick if (vid[i] != ' ') 28752130Smckusick break; 28852130Smckusick vid[i+1] = 0; 28952130Smckusick for (i = 16; --i > 0; ) 29052130Smckusick if (pid[i] != ' ') 29152130Smckusick break; 29252130Smckusick pid[i+1] = 0; 29352130Smckusick for (i = 4; --i > 0; ) 29452130Smckusick if (revl[i] != ' ') 29552130Smckusick break; 29652130Smckusick revl[i+1] = 0; 29752130Smckusick printf(" %s %s rev %s", vid, pid, revl); 29852130Smckusick } 29952130Smckusick printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 30052130Smckusick if (sc->sc_blksize != DEV_BSIZE) { 30152130Smckusick if (sc->sc_blksize < DEV_BSIZE) { 30252130Smckusick printf("rz%d: need %d byte blocks - drive ignored\n", 30352130Smckusick sd->sd_unit, DEV_BSIZE); 30452130Smckusick goto bad; 30552130Smckusick } 30652130Smckusick for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 30752130Smckusick ++sc->sc_bshift; 30852130Smckusick sc->sc_blks <<= sc->sc_bshift; 30952130Smckusick } 31052130Smckusick sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 31152130Smckusick sc->sc_format_pid = 0; 31252130Smckusick sc->sc_flags = RZF_ALIVE; 31352130Smckusick 31452130Smckusick /* try to read disk label or partition table information */ 31552130Smckusick if (rzreadlabel(sc, sd) == 0) 31652130Smckusick goto ok; 31752130Smckusick 31852130Smckusick /* 31952130Smckusick * We don't have a disk label, build a default partition 32052130Smckusick * table with 'standard' size root & swap and everything else 32152130Smckusick * in the G partition. 32252130Smckusick */ 32352130Smckusick sc->sc_info = rzdefaultpart; 32452130Smckusick /* C gets everything */ 32552130Smckusick sc->sc_info.part[2].nblocks = sc->sc_blks; 32652130Smckusick sc->sc_info.part[2].endblk = sc->sc_blks; 32752130Smckusick /* G gets from end of B to end of disk */ 32852130Smckusick sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk; 32952130Smckusick sc->sc_info.part[6].endblk = sc->sc_blks; 33052130Smckusick /* 33152130Smckusick * We also define the D, E and F paritions as an alternative to 33252130Smckusick * B and G. D is 48Mb, starts after A and is intended for swapping. 33352130Smckusick * E is 50Mb, starts after D and is intended for /usr. F starts 33452130Smckusick * after E and is what ever is left. 33552130Smckusick */ 33652130Smckusick if (sc->sc_blks >= sc->sc_info.part[4].endblk) { 33752130Smckusick sc->sc_info.part[5].nblocks = 33852130Smckusick sc->sc_blks - sc->sc_info.part[4].endblk; 33952130Smckusick sc->sc_info.part[5].endblk = sc->sc_blks; 34052130Smckusick } else { 34152130Smckusick sc->sc_info.part[5].strtblk = 0; 34252130Smckusick sc->sc_info.part[3] = sc->sc_info.part[5]; 34352130Smckusick sc->sc_info.part[4] = sc->sc_info.part[5]; 34452130Smckusick } 34552130Smckusick /* 34652130Smckusick * H is a single partition alternative to E and F. 34752130Smckusick */ 34852130Smckusick if (sc->sc_blks >= sc->sc_info.part[3].endblk) { 34952130Smckusick sc->sc_info.part[7].nblocks = 35052130Smckusick sc->sc_blks - sc->sc_info.part[3].endblk; 35152130Smckusick sc->sc_info.part[7].endblk = sc->sc_blks; 35252130Smckusick } else 35352130Smckusick sc->sc_info.part[7].strtblk = 0; 35452130Smckusick 35552130Smckusick ok: 35652130Smckusick sc->sc_buf.b_flags = 0; 35752130Smckusick return (1); 35852130Smckusick 35952130Smckusick bad: 36052130Smckusick /* doesn't exist or not a CCS device */ 36152130Smckusick sc->sc_format_pid = 0; 36252130Smckusick sc->sc_buf.b_flags = 0; 36352130Smckusick return (0); 36452130Smckusick } 36552130Smckusick 36652130Smckusick /* 36752130Smckusick * Try to read the disk label and fill in the partition table info. 36852130Smckusick */ 36952130Smckusick static int 37052130Smckusick rzreadlabel(sc, sd) 37152130Smckusick register struct rz_softc *sc; 37252130Smckusick register struct scsi_device *sd; 37352130Smckusick { 37452130Smckusick register struct size *sp; 37552130Smckusick Sun_DiskLabel *sunLabelPtr; 37652130Smckusick Dec_DiskLabel *decLabelPtr; 37752130Smckusick char labelBuffer[DEV_BSIZE]; 37852130Smckusick int part, error; 37952130Smckusick 38052130Smckusick /* 38152130Smckusick * The label of a SCSI disk normally resides in the first sector. 38252130Smckusick * Format and send a SCSI READ command to fetch the sector. 38352130Smckusick */ 38452130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 38552130Smckusick sc->sc_buf.b_bcount = sizeof(labelBuffer); 38652130Smckusick sc->sc_buf.b_un.b_addr = labelBuffer; 38752130Smckusick sc->sc_buf.b_cylin = SUN_LABEL_SECTOR; 38852130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 38952130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 39052130Smckusick rzstart(sd->sd_unit); 39152130Smckusick if (error = biowait(&sc->sc_buf)) 39252130Smckusick return (error); 39352130Smckusick sunLabelPtr = (Sun_DiskLabel *)labelBuffer; 39452130Smckusick if (sunLabelPtr->magic == SUN_DISK_MAGIC) { 39552130Smckusick /* 39652130Smckusick * XXX - Should really check if label is valid. 39752130Smckusick */ 39852130Smckusick #ifdef DEBUG 39952130Smckusick if (rzdebug & RZB_PRLABEL) { 40052130Smckusick printf("rz%d: SUN label %s\n", sd->sd_unit, 40152130Smckusick sunLabelPtr->asciiLabel); 40252130Smckusick printf(" Partitions"); 40352130Smckusick } 40452130Smckusick #endif 40552130Smckusick sp = sc->sc_info.part; 40652130Smckusick for (part = 0; part < DEV_NUM_DISK_PARTS; part++, sp++) { 40752130Smckusick sp->strtblk = 40852130Smckusick sunLabelPtr->map[part].cylinder * 40952130Smckusick sunLabelPtr->numHeads * 41052130Smckusick sunLabelPtr->numSectors; 41152130Smckusick sp->nblocks = 41252130Smckusick sunLabelPtr->map[part].numBlocks; 41352130Smckusick sp->endblk = sp->strtblk + sp->nblocks; 41452130Smckusick #ifdef DEBUG 41552130Smckusick if (rzdebug & RZB_PRLABEL) 41652130Smckusick printf(" (%d,%d)", sp->strtblk, sp->nblocks); 41752130Smckusick #endif 41852130Smckusick } 41952130Smckusick #ifdef DEBUG 42052130Smckusick if (rzdebug & RZB_PRLABEL) 42152130Smckusick printf("\n"); 42252130Smckusick #endif 42352130Smckusick return (0); 42452130Smckusick } 42552130Smckusick 42652130Smckusick /* 42752130Smckusick * The disk isn't in SUN or UNIX format so try Dec format. 42852130Smckusick * We have to read the right sector first. 42952130Smckusick */ 43052130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 43152130Smckusick sc->sc_buf.b_bcount = sizeof(labelBuffer); 43252130Smckusick sc->sc_buf.b_un.b_addr = labelBuffer; 43352130Smckusick sc->sc_buf.b_cylin = DEC_LABEL_SECTOR; 43452130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 43552130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 43652130Smckusick rzstart(sd->sd_unit); 43752130Smckusick if (error = biowait(&sc->sc_buf)) 43852130Smckusick return (error); 43952130Smckusick decLabelPtr = (Dec_DiskLabel *)labelBuffer; 44052130Smckusick if (decLabelPtr->magic == DEC_LABEL_MAGIC && 44152130Smckusick decLabelPtr->isPartitioned) { 44252130Smckusick /* 44352130Smckusick * XXX - Should really check if label is valid. 44452130Smckusick */ 44552130Smckusick #ifdef DEBUG 44652130Smckusick if (rzdebug & RZB_PRLABEL) { 44752130Smckusick printf("rz%d: DEC label\n", sd->sd_unit); 44852130Smckusick printf(" Partitions"); 44952130Smckusick } 45052130Smckusick #endif 45152130Smckusick sp = sc->sc_info.part; 45252130Smckusick for (part = 0; part < DEV_NUM_DISK_PARTS; part++, sp++) { 45352130Smckusick sp->strtblk = decLabelPtr->map[part].startBlock; 45452130Smckusick sp->nblocks = decLabelPtr->map[part].numBlocks; 45552130Smckusick sp->endblk = sp->strtblk + sp->nblocks; 45652130Smckusick #ifdef DEBUG 45752130Smckusick if (rzdebug & RZB_PRLABEL) 45852130Smckusick printf(" (%d,%d)", sp->strtblk, sp->nblocks); 45952130Smckusick #endif 46052130Smckusick } 46152130Smckusick #ifdef DEBUG 46252130Smckusick if (rzdebug & RZB_PRLABEL) 46352130Smckusick printf("\n"); 46452130Smckusick #endif 46552130Smckusick return (0); 46652130Smckusick } 46752130Smckusick return (EIO); 46852130Smckusick } 46952130Smckusick 47052130Smckusick /* 47152130Smckusick * This routine is called for partial block transfers and non-aligned 47252130Smckusick * transfers (the latter only being possible on devices with a block size 47352130Smckusick * larger than DEV_BSIZE). The operation is performed in three steps 47452130Smckusick * using a locally allocated buffer: 47552130Smckusick * 1. transfer any initial partial block 47652130Smckusick * 2. transfer full blocks 47752130Smckusick * 3. transfer any final partial block 47852130Smckusick */ 47952130Smckusick static void 48052130Smckusick rzlblkstrat(bp, bsize) 48152130Smckusick register struct buf *bp; 48252130Smckusick register int bsize; 48352130Smckusick { 48452130Smckusick register struct buf *cbp; 48552130Smckusick caddr_t cbuf; 48652130Smckusick register int bn, resid; 48752130Smckusick register caddr_t addr; 48852130Smckusick 48952130Smckusick cbp = (struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK); 49052130Smckusick cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); 49152130Smckusick bzero((caddr_t)cbp, sizeof(*cbp)); 49252130Smckusick cbp->b_proc = curproc; 49352130Smckusick cbp->b_dev = bp->b_dev; 49452130Smckusick bn = bp->b_blkno; 49552130Smckusick resid = bp->b_bcount; 49652130Smckusick addr = bp->b_un.b_addr; 49752130Smckusick #ifdef DEBUG 49852130Smckusick if (rzdebug & RZB_PARTIAL) 49952130Smckusick printf("rzlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", 50052130Smckusick bp, bp->b_flags, bn, resid, addr); 50152130Smckusick #endif 50252130Smckusick 50352130Smckusick while (resid > 0) { 50452130Smckusick register int boff = dbtob(bn) & (bsize - 1); 50552130Smckusick register int count; 50652130Smckusick 50752130Smckusick if (boff || resid < bsize) { 50852130Smckusick rz_softc[rzunit(bp->b_dev)].sc_stats.rzpartials++; 50952130Smckusick count = MIN(resid, bsize - boff); 51052130Smckusick cbp->b_flags = B_BUSY | B_PHYS | B_READ; 51152130Smckusick cbp->b_blkno = bn - btodb(boff); 51252130Smckusick cbp->b_un.b_addr = cbuf; 51352130Smckusick cbp->b_bcount = bsize; 51452130Smckusick #ifdef DEBUG 51552130Smckusick if (rzdebug & RZB_PARTIAL) 51652130Smckusick printf(" readahead: bn %x cnt %x off %x addr %x\n", 51752130Smckusick cbp->b_blkno, count, boff, addr); 51852130Smckusick #endif 51952130Smckusick rzstrategy(cbp); 52052130Smckusick biowait(cbp); 52152130Smckusick if (cbp->b_flags & B_ERROR) { 52252130Smckusick bp->b_flags |= B_ERROR; 52352130Smckusick bp->b_error = cbp->b_error; 52452130Smckusick break; 52552130Smckusick } 52652130Smckusick if (bp->b_flags & B_READ) { 52752130Smckusick bcopy(&cbuf[boff], addr, count); 52852130Smckusick goto done; 52952130Smckusick } 53052130Smckusick bcopy(addr, &cbuf[boff], count); 53152130Smckusick #ifdef DEBUG 53252130Smckusick if (rzdebug & RZB_PARTIAL) 53352130Smckusick printf(" writeback: bn %x cnt %x off %x addr %x\n", 53452130Smckusick cbp->b_blkno, count, boff, addr); 53552130Smckusick #endif 53652130Smckusick } else { 53752130Smckusick count = resid & ~(bsize - 1); 53852130Smckusick cbp->b_blkno = bn; 53952130Smckusick cbp->b_un.b_addr = addr; 54052130Smckusick cbp->b_bcount = count; 54152130Smckusick #ifdef DEBUG 54252130Smckusick if (rzdebug & RZB_PARTIAL) 54352130Smckusick printf(" fulltrans: bn %x cnt %x addr %x\n", 54452130Smckusick cbp->b_blkno, count, addr); 54552130Smckusick #endif 54652130Smckusick } 54752130Smckusick cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ); 54852130Smckusick rzstrategy(cbp); 54952130Smckusick biowait(cbp); 55052130Smckusick if (cbp->b_flags & B_ERROR) { 55152130Smckusick bp->b_flags |= B_ERROR; 55252130Smckusick bp->b_error = cbp->b_error; 55352130Smckusick break; 55452130Smckusick } 55552130Smckusick done: 55652130Smckusick bn += btodb(count); 55752130Smckusick resid -= count; 55852130Smckusick addr += count; 55952130Smckusick #ifdef DEBUG 56052130Smckusick if (rzdebug & RZB_PARTIAL) 56152130Smckusick printf(" done: bn %x resid %x addr %x\n", 56252130Smckusick bn, resid, addr); 56352130Smckusick #endif 56452130Smckusick } 56552130Smckusick free(cbuf, M_DEVBUF); 56652130Smckusick free(cbp, M_DEVBUF); 56752130Smckusick } 56852130Smckusick 56952130Smckusick void 57052130Smckusick rzstrategy(bp) 57152130Smckusick register struct buf *bp; 57252130Smckusick { 57352130Smckusick register int unit = rzunit(bp->b_dev); 57452130Smckusick register int part = rzpart(bp->b_dev); 57552130Smckusick register int bn, sz; 57652130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 57752130Smckusick register int s; 57852130Smckusick 57952130Smckusick if (sc->sc_format_pid) { 58052130Smckusick if (sc->sc_format_pid != curproc->p_pid) { 58152130Smckusick bp->b_error = EPERM; 58252130Smckusick goto bad; 58352130Smckusick } 58452130Smckusick bp->b_cylin = 0; 58552130Smckusick } else { 58652130Smckusick bn = bp->b_blkno; 58752130Smckusick sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT; 58852130Smckusick if (bn < 0 || bn + sz > sc->sc_info.part[part].nblocks) { 58952130Smckusick if (bn == sc->sc_info.part[part].nblocks) { 59052130Smckusick bp->b_resid = bp->b_bcount; 59152130Smckusick goto done; 59252130Smckusick } 59352130Smckusick bp->b_error = EINVAL; 59452130Smckusick goto bad; 59552130Smckusick } 59652130Smckusick /* 59752130Smckusick * Non-aligned or partial-block transfers handled specially. 59852130Smckusick */ 59952130Smckusick s = sc->sc_blksize - 1; 60052130Smckusick if ((dbtob(bn) & s) || (bp->b_bcount & s)) { 60152130Smckusick rzlblkstrat(bp, sc->sc_blksize); 60252130Smckusick goto done; 60352130Smckusick } 60452130Smckusick bp->b_cylin = (bn + sc->sc_info.part[part].strtblk) >> 60552130Smckusick sc->sc_bshift; 60652130Smckusick } 60752130Smckusick /* don't let disksort() see sc_errbuf */ 60852130Smckusick while (sc->sc_flags & RZF_SENSEINPROGRESS) 60952130Smckusick printf("SENSE\n"); /* XXX */ 61052130Smckusick s = splbio(); 61152130Smckusick disksort(&sc->sc_tab, bp); 61252130Smckusick if (sc->sc_tab.b_active == 0) { 61352130Smckusick sc->sc_tab.b_active = 1; 61452130Smckusick rzstart(unit); 61552130Smckusick } 61652130Smckusick splx(s); 61752130Smckusick return; 61852130Smckusick bad: 61952130Smckusick bp->b_flags |= B_ERROR; 62052130Smckusick done: 62152130Smckusick biodone(bp); 62252130Smckusick } 62352130Smckusick 62452130Smckusick void 62552130Smckusick rzstart(unit) 62652130Smckusick int unit; 62752130Smckusick { 62852130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 62952130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 63052130Smckusick register int n; 63152130Smckusick 63252130Smckusick sc->sc_cmd.buf = bp->b_un.b_addr; 63352130Smckusick sc->sc_cmd.buflen = bp->b_bcount; 63452130Smckusick 63552130Smckusick if (sc->sc_format_pid || (sc->sc_flags & RZF_SENSEINPROGRESS)) { 63652130Smckusick sc->sc_cmd.flags = !(bp->b_flags & B_READ) ? 63752130Smckusick SCSICMD_DATA_TO_DEVICE : 0; 63852130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 63952130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 64052130Smckusick } else { 64152130Smckusick if (bp->b_flags & B_READ) { 64252130Smckusick sc->sc_cmd.flags = 0; 64352130Smckusick sc->sc_rwcmd.command = SCSI_READ_EXT; 64452130Smckusick } else { 64552130Smckusick sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE; 64652130Smckusick sc->sc_rwcmd.command = SCSI_WRITE_EXT; 64752130Smckusick } 64852130Smckusick sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 64952130Smckusick sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd); 65052130Smckusick n = bp->b_cylin; 65152130Smckusick sc->sc_rwcmd.highAddr = n >> 24; 65252130Smckusick sc->sc_rwcmd.midHighAddr = n >> 16; 65352130Smckusick sc->sc_rwcmd.midLowAddr = n >> 8; 65452130Smckusick sc->sc_rwcmd.lowAddr = n; 65552130Smckusick n = howmany(bp->b_bcount, sc->sc_blksize); 65652130Smckusick sc->sc_rwcmd.highBlockCount = n >> 8; 65752130Smckusick sc->sc_rwcmd.lowBlockCount = n; 65852130Smckusick #ifdef DEBUG 65952130Smckusick if ((bp->b_bcount & (sc->sc_blksize - 1)) != 0) 66052130Smckusick printf("rz%d: partial block xfer -- %x bytes\n", 66152130Smckusick unit, bp->b_bcount); 66252130Smckusick #endif 66352130Smckusick sc->sc_stats.rztransfers++; 66452130Smckusick if ((n = sc->sc_sd->sd_dk) >= 0) { 66552130Smckusick dk_busy |= 1 << n; 66652130Smckusick ++dk_seek[n]; 66752130Smckusick ++dk_xfer[n]; 66852130Smckusick dk_wds[n] += bp->b_bcount >> 6; 66952130Smckusick } 67052130Smckusick } 67152130Smckusick 67252130Smckusick /* tell controller to start this command */ 67352130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 67452130Smckusick } 67552130Smckusick 67652130Smckusick /* 67752130Smckusick * This is called by the controller driver when the command is done. 67852130Smckusick */ 67952130Smckusick void 68052130Smckusick rzdone(unit, error, resid, status) 68152130Smckusick register int unit; 68252130Smckusick int error; /* error number from errno.h */ 68352130Smckusick int resid; /* amount not transfered */ 68452130Smckusick int status; /* SCSI status byte */ 68552130Smckusick { 68652130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 68752130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 68852130Smckusick register struct scsi_device *sd = sc->sc_sd; 68952130Smckusick extern int cold; 69052130Smckusick 69152130Smckusick if (bp == NULL) { 69252130Smckusick printf("rz%d: bp == NULL\n", unit); 69352130Smckusick return; 69452130Smckusick } 69552130Smckusick if (sd->sd_dk >= 0) 69652130Smckusick dk_busy &= ~(1 << sd->sd_dk); 69752130Smckusick if (sc->sc_flags & RZF_SENSEINPROGRESS) { 69852130Smckusick sc->sc_flags &= ~RZF_SENSEINPROGRESS; 69952130Smckusick sc->sc_tab.b_actf = bp = bp->av_forw; /* remove sc_errbuf */ 70052130Smckusick 70152130Smckusick if (error || (status & SCSI_STATUS_CHECKCOND)) { 70252130Smckusick #ifdef DEBUG 70352130Smckusick if (rzdebug & RZB_ERROR) 70452130Smckusick printf("rz%d: error reading sense data: error %d scsi status 0x%x\n", 70552130Smckusick unit, error, status); 70652130Smckusick #endif 70752130Smckusick /* 70852130Smckusick * We got an error during the REQUEST_SENSE, 70952130Smckusick * fill in no sense for data. 71052130Smckusick */ 71152130Smckusick sc->sc_sense.sense[0] = 0x70; 71252130Smckusick sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE; 713*53083Sralph } else if (!cold) { 71452130Smckusick printf("rz%d: ", unit); 71552130Smckusick scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense, 71652130Smckusick sizeof(sc->sc_sense.sense) - resid); 71752130Smckusick } 71852130Smckusick } else if (error || (status & SCSI_STATUS_CHECKCOND)) { 71952130Smckusick #ifdef DEBUG 720*53083Sralph if (!cold && (rzdebug & RZB_ERROR)) 72152130Smckusick printf("rz%d: error %d scsi status 0x%x\n", 72252130Smckusick unit, error, status); 72352130Smckusick #endif 72452130Smckusick /* save error info */ 72552130Smckusick sc->sc_sense.status = status; 72652130Smckusick bp->b_flags |= B_ERROR; 72752130Smckusick bp->b_error = error; 72852130Smckusick bp->b_resid = resid; 72952130Smckusick 73052130Smckusick if (status & SCSI_STATUS_CHECKCOND) { 73152130Smckusick /* 73252130Smckusick * Start a REQUEST_SENSE command. 73352130Smckusick * Since we are called at interrupt time, we can't 73452130Smckusick * wait for the command to finish; that's why we use 73552130Smckusick * the sc_flags field. 73652130Smckusick */ 73752130Smckusick sc->sc_flags |= RZF_SENSEINPROGRESS; 73852130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 73952130Smckusick scsiGroup0Cmd(SCSI_REQUEST_SENSE, sd->sd_slave, 0, 74052130Smckusick sizeof(sc->sc_sense.sense), 74152130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 74252130Smckusick sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ; 74352130Smckusick sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense); 74452130Smckusick sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense; 74552130Smckusick sc->sc_errbuf.av_forw = bp; 74652130Smckusick sc->sc_tab.b_actf = &sc->sc_errbuf; 74752130Smckusick rzstart(unit); 74852130Smckusick return; 74952130Smckusick } 75052130Smckusick } else { 75152130Smckusick sc->sc_sense.status = status; 75252130Smckusick bp->b_resid = resid; 75352130Smckusick } 75452130Smckusick 75552130Smckusick sc->sc_tab.b_actf = bp->av_forw; 75652130Smckusick biodone(bp); 75752130Smckusick if (sc->sc_tab.b_actf) 75852130Smckusick rzstart(unit); 75952130Smckusick else 76052130Smckusick sc->sc_tab.b_active = 0; 76152130Smckusick } 76252130Smckusick 76352130Smckusick int 76452130Smckusick rzopen(dev, flags, mode, p) 76552130Smckusick dev_t dev; 76652130Smckusick int flags, mode; 76752130Smckusick struct proc *p; 76852130Smckusick { 76952130Smckusick register int unit = rzunit(dev); 77052130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 77152130Smckusick 77252130Smckusick if (unit >= NRZ) 77352130Smckusick return (ENXIO); 77452130Smckusick if (!(sc->sc_flags & RZF_ALIVE) || suser(p->p_ucred, &p->p_acflag)) 77552130Smckusick return (ENXIO); 77652130Smckusick 77752130Smckusick if (sc->sc_sd->sd_dk >= 0) 77852130Smckusick dk_wpms[sc->sc_sd->sd_dk] = sc->sc_wpms; 77952130Smckusick return (0); 78052130Smckusick } 78152130Smckusick 78252130Smckusick rzclose(dev, flags) 78352130Smckusick dev_t dev; 78452130Smckusick int flags; 78552130Smckusick { 78652130Smckusick return (0); 78752130Smckusick } 78852130Smckusick 78952130Smckusick int 79052130Smckusick rzread(dev, uio) 79152130Smckusick dev_t dev; 79252130Smckusick struct uio *uio; 79352130Smckusick { 79452130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 79552130Smckusick 79652130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 79752130Smckusick return (EPERM); 79852130Smckusick 79952130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 80052130Smckusick B_READ, minphys, uio)); 80152130Smckusick } 80252130Smckusick 80352130Smckusick int 80452130Smckusick rzwrite(dev, uio) 80552130Smckusick dev_t dev; 80652130Smckusick struct uio *uio; 80752130Smckusick { 80852130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 80952130Smckusick 81052130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 81152130Smckusick return (EPERM); 81252130Smckusick 81352130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 81452130Smckusick B_WRITE, minphys, uio)); 81552130Smckusick } 81652130Smckusick 81752130Smckusick int 81852130Smckusick rzioctl(dev, cmd, data, flag, p) 81952130Smckusick dev_t dev; 82052130Smckusick int cmd; 82152130Smckusick caddr_t data; 82252130Smckusick int flag; 82352130Smckusick struct proc *p; 82452130Smckusick { 82552130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 82652130Smckusick 82752130Smckusick switch (cmd) { 82852130Smckusick default: 82952130Smckusick return (EINVAL); 83052130Smckusick 83152130Smckusick case SDIOCSFORMAT: 83252130Smckusick /* take this device into or out of "format" mode */ 83352130Smckusick if (suser(p->p_ucred, &p->p_acflag)) 83452130Smckusick return (EPERM); 83552130Smckusick 83652130Smckusick if (*(int *)data) { 83752130Smckusick if (sc->sc_format_pid) 83852130Smckusick return (EPERM); 83952130Smckusick sc->sc_format_pid = p->p_pid; 84052130Smckusick } else 84152130Smckusick sc->sc_format_pid = 0; 84252130Smckusick return (0); 84352130Smckusick 84452130Smckusick case SDIOCGFORMAT: 84552130Smckusick /* find out who has the device in format mode */ 84652130Smckusick *(int *)data = sc->sc_format_pid; 84752130Smckusick return (0); 84852130Smckusick 84952130Smckusick case SDIOCSCSICOMMAND: 85052130Smckusick /* 85152130Smckusick * Save what user gave us as SCSI cdb to use with next 85252130Smckusick * read or write to the char device. 85352130Smckusick */ 85452130Smckusick if (sc->sc_format_pid != p->p_pid) 85552130Smckusick return (EPERM); 85652130Smckusick if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0) 85752130Smckusick return (EINVAL); 85852130Smckusick bcopy(data, (caddr_t)&sc->sc_cdb, sizeof(sc->sc_cdb)); 85952130Smckusick return (0); 86052130Smckusick 86152130Smckusick case SDIOCSENSE: 86252130Smckusick /* 86352130Smckusick * return the SCSI sense data saved after the last 86452130Smckusick * operation that completed with "check condition" status. 86552130Smckusick */ 86652130Smckusick bcopy((caddr_t)&sc->sc_sense, data, sizeof(sc->sc_sense)); 86752130Smckusick return (0); 86852130Smckusick 86952130Smckusick } 87052130Smckusick /*NOTREACHED*/ 87152130Smckusick } 87252130Smckusick 87352130Smckusick int 87452130Smckusick rzsize(dev) 87552130Smckusick dev_t dev; 87652130Smckusick { 87752130Smckusick register int unit = rzunit(dev); 87852130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 87952130Smckusick 88052130Smckusick if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE)) 88152130Smckusick return (-1); 88252130Smckusick 88352130Smckusick return (sc->sc_info.part[rzpart(dev)].nblocks); 88452130Smckusick } 88552130Smckusick 88652130Smckusick /* 88752130Smckusick * Non-interrupt driven, non-dma dump routine. 88852130Smckusick */ 88952130Smckusick int 89052130Smckusick rzdump(dev) 89152130Smckusick dev_t dev; 89252130Smckusick { 89352130Smckusick #ifdef notdef 89452130Smckusick int part = rzpart(dev); 89552130Smckusick int unit = rzunit(dev); 89652130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 89752130Smckusick register struct scsi_device *sd = sc->sc_hd; 89852130Smckusick register daddr_t baddr; 89952130Smckusick register int maddr; 90052130Smckusick register int pages, i; 90152130Smckusick int stat; 90252130Smckusick extern int lowram; 90352130Smckusick 90452130Smckusick /* 90552130Smckusick * Hmm... all vax drivers dump maxfree pages which is physmem minus 90652130Smckusick * the message buffer. Is there a reason for not dumping the 90752130Smckusick * message buffer? Savecore expects to read 'dumpsize' pages of 90852130Smckusick * dump, where dumpsys() sets dumpsize to physmem! 90952130Smckusick */ 91052130Smckusick pages = physmem; 91152130Smckusick 91252130Smckusick /* is drive ok? */ 91352130Smckusick if (unit >= NRZ || (sc->sc_flags & RZF_ALIVE) == 0) 91452130Smckusick return (ENXIO); 91552130Smckusick /* dump parameters in range? */ 91652130Smckusick if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks) 91752130Smckusick return (EINVAL); 91852130Smckusick if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks) 91952130Smckusick pages = dtoc(sc->sc_info.part[part].nblocks - dumplo); 92052130Smckusick maddr = lowram; 92152130Smckusick baddr = dumplo + sc->sc_info.part[part].strtblk; 92252130Smckusick /* scsi bus idle? */ 92352130Smckusick if (!scsireq(&sc->sc_dq)) { 92452130Smckusick scsireset(sd->sd_ctlr); 92552130Smckusick sc->sc_stats.rzresets++; 92652130Smckusick printf("[ drive %d reset ] ", unit); 92752130Smckusick } 92852130Smckusick for (i = 0; i < pages; i++) { 92952130Smckusick #define NPGMB (1024*1024/NBPG) 93052130Smckusick /* print out how many Mbs we have dumped */ 93152130Smckusick if (i && (i % NPGMB) == 0) 93252130Smckusick printf("%d ", i / NPGMB); 93352130Smckusick #undef NPBMG 93452130Smckusick mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); 93552130Smckusick stat = scsi_tt_write(sd->sd_ctlr, sd->sd_drive, sd->sd_slave, 93652130Smckusick vmmap, NBPG, baddr, sc->sc_bshift); 93752130Smckusick if (stat) { 93852130Smckusick printf("rzdump: scsi write error 0x%x\n", stat); 93952130Smckusick return (EIO); 94052130Smckusick } 94152130Smckusick maddr += NBPG; 94252130Smckusick baddr += ctod(1); 94352130Smckusick } 94452130Smckusick return (0); 94552130Smckusick #else notdef 94652130Smckusick return (ENXIO); 94752130Smckusick #endif notdef 94852130Smckusick } 94952130Smckusick #endif 950