1*52130Smckusick /* 2*52130Smckusick * Copyright (c) 1992 Regents of the University of California. 3*52130Smckusick * All rights reserved. 4*52130Smckusick * 5*52130Smckusick * This code is derived from software contributed to Berkeley by 6*52130Smckusick * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell. 7*52130Smckusick * 8*52130Smckusick * %sccs.include.redist.c% 9*52130Smckusick * 10*52130Smckusick * @(#)rz.c 7.1 (Berkeley) 01/07/92 11*52130Smckusick */ 12*52130Smckusick 13*52130Smckusick /* 14*52130Smckusick * SCSI CCS (Command Command Set) disk driver. 15*52130Smckusick * NOTE: The name was changed from "sd" to "rz" for DEC compatibility. 16*52130Smckusick * I guess I can't avoid confusion someplace. 17*52130Smckusick */ 18*52130Smckusick #include "rz.h" 19*52130Smckusick #if NRZ > 0 20*52130Smckusick 21*52130Smckusick #include "param.h" 22*52130Smckusick #include "systm.h" 23*52130Smckusick #include "buf.h" 24*52130Smckusick #include "errno.h" 25*52130Smckusick #include "dkstat.h" 26*52130Smckusick #include "disklabel.h" 27*52130Smckusick #include "malloc.h" 28*52130Smckusick 29*52130Smckusick #include "device.h" 30*52130Smckusick #include "scsi.h" 31*52130Smckusick #include "devDiskLabel.h" 32*52130Smckusick 33*52130Smckusick #include "proc.h" 34*52130Smckusick #include "uio.h" 35*52130Smckusick 36*52130Smckusick extern void printf(); 37*52130Smckusick extern void bcopy(); 38*52130Smckusick extern void disksort(); 39*52130Smckusick extern int splbio(); 40*52130Smckusick extern void splx(); 41*52130Smckusick extern int physio(); 42*52130Smckusick 43*52130Smckusick int rzprobe(); 44*52130Smckusick void rzstrategy(), rzstart(), rzdone(); 45*52130Smckusick 46*52130Smckusick struct driver rzdriver = { 47*52130Smckusick "rz", rzprobe, rzstart, rzdone, 48*52130Smckusick }; 49*52130Smckusick 50*52130Smckusick struct size { 51*52130Smckusick u_long strtblk; 52*52130Smckusick u_long endblk; 53*52130Smckusick int nblocks; 54*52130Smckusick }; 55*52130Smckusick 56*52130Smckusick struct rzinfo { 57*52130Smckusick struct size part[8]; 58*52130Smckusick }; 59*52130Smckusick 60*52130Smckusick /* 61*52130Smckusick * Since the SCSI standard tends to hide the disk structure, we define 62*52130Smckusick * partitions in terms of DEV_BSIZE blocks. The default partition table 63*52130Smckusick * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg 64*52130Smckusick * root and 32 meg of swap. The rest of the space on the drive goes in 65*52130Smckusick * the G partition. As usual, the C partition covers the entire disk 66*52130Smckusick * (including the boot area). 67*52130Smckusick */ 68*52130Smckusick struct rzinfo rzdefaultpart = { 69*52130Smckusick 1024, 17408, 16384 , /* A */ 70*52130Smckusick 17408, 82944, 65536 , /* B */ 71*52130Smckusick 0, 0, 0 , /* C */ 72*52130Smckusick 17408, 115712, 98304 , /* D */ 73*52130Smckusick 115712, 218112, 102400 , /* E */ 74*52130Smckusick 218112, 0, 0 , /* F */ 75*52130Smckusick 82944, 0, 0 , /* G */ 76*52130Smckusick 115712, 0, 0 , /* H */ 77*52130Smckusick }; 78*52130Smckusick 79*52130Smckusick struct rzstats { 80*52130Smckusick long rzresets; 81*52130Smckusick long rztransfers; 82*52130Smckusick long rzpartials; 83*52130Smckusick }; 84*52130Smckusick 85*52130Smckusick struct rz_softc { 86*52130Smckusick struct scsi_device *sc_sd; /* physical unit info */ 87*52130Smckusick int sc_format_pid; /* process using "format" mode */ 88*52130Smckusick short sc_flags; /* see below */ 89*52130Smckusick short sc_type; /* drive type from INQUIRY cmd */ 90*52130Smckusick u_int sc_blks; /* number of blocks on device */ 91*52130Smckusick int sc_blksize; /* device block size in bytes */ 92*52130Smckusick int sc_bshift; /* convert device blocks to DEV_BSIZE */ 93*52130Smckusick u_int sc_wpms; /* average xfer rate in 16bit wds/sec */ 94*52130Smckusick struct rzinfo sc_info; /* drive partition table & label info */ 95*52130Smckusick struct rzstats sc_stats; /* statisic counts */ 96*52130Smckusick struct buf sc_tab; /* queue of pending operations */ 97*52130Smckusick struct buf sc_buf; /* buf for doing I/O */ 98*52130Smckusick struct buf sc_errbuf; /* buf for doing REQUEST_SENSE */ 99*52130Smckusick struct ScsiCmd sc_cmd; /* command for controller */ 100*52130Smckusick ScsiGroup1Cmd sc_rwcmd; /* SCSI cmd if not in "format" mode */ 101*52130Smckusick struct scsi_fmt_cdb sc_cdb; /* SCSI cmd if in "format" mode */ 102*52130Smckusick struct scsi_fmt_sense sc_sense; /* sense data from last cmd */ 103*52130Smckusick } rz_softc[NRZ]; 104*52130Smckusick 105*52130Smckusick /* sc_flags values */ 106*52130Smckusick #define RZF_ALIVE 0x1 /* drive found and ready */ 107*52130Smckusick #define RZF_SENSEINPROGRESS 0x2 /* REQUEST_SENSE command in progress */ 108*52130Smckusick 109*52130Smckusick #ifdef DEBUG 110*52130Smckusick int rzdebug = 3; 111*52130Smckusick #define RZB_ERROR 0x01 112*52130Smckusick #define RZB_PARTIAL 0x02 113*52130Smckusick #define RZB_PRLABEL 0x04 114*52130Smckusick #endif 115*52130Smckusick 116*52130Smckusick #define rzunit(x) ((minor(x) >> 3) & 0x7) 117*52130Smckusick #define rzpart(x) (minor(x) & 0x7) 118*52130Smckusick #define b_cylin b_resid 119*52130Smckusick 120*52130Smckusick /* 121*52130Smckusick * Table of scsi commands users are allowed to access via "format" mode. 122*52130Smckusick * 0 means not legal. 123*52130Smckusick * 1 means legal. 124*52130Smckusick */ 125*52130Smckusick static char legal_cmds[256] = { 126*52130Smckusick /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 127*52130Smckusick /*00*/ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128*52130Smckusick /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 129*52130Smckusick /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130*52130Smckusick /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131*52130Smckusick /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132*52130Smckusick /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133*52130Smckusick /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134*52130Smckusick /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135*52130Smckusick /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136*52130Smckusick /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137*52130Smckusick /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138*52130Smckusick /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139*52130Smckusick /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140*52130Smckusick /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141*52130Smckusick /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142*52130Smckusick /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143*52130Smckusick }; 144*52130Smckusick 145*52130Smckusick /* 146*52130Smckusick * Test to see if device is present. 147*52130Smckusick * Return true if found and initialized ok. 148*52130Smckusick */ 149*52130Smckusick rzprobe(sd) 150*52130Smckusick register struct scsi_device *sd; 151*52130Smckusick { 152*52130Smckusick register struct rz_softc *sc = &rz_softc[sd->sd_unit]; 153*52130Smckusick register int tries, i; 154*52130Smckusick ScsiInquiryData inqbuf; 155*52130Smckusick u_char capbuf[8]; 156*52130Smckusick ScsiClass7Sense *sp; 157*52130Smckusick 158*52130Smckusick /* init some parameters that don't change */ 159*52130Smckusick sc->sc_sd = sd; 160*52130Smckusick sc->sc_cmd.sd = sd; 161*52130Smckusick sc->sc_cmd.unit = sd->sd_unit; 162*52130Smckusick sc->sc_rwcmd.unitNumber = sd->sd_slave; 163*52130Smckusick 164*52130Smckusick /* try to find out what type of device this is */ 165*52130Smckusick sc->sc_format_pid = 1; /* force use of sc_cdb */ 166*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 167*52130Smckusick scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), 168*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 169*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 170*52130Smckusick sc->sc_buf.b_bcount = sizeof(inqbuf); 171*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf; 172*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 173*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 174*52130Smckusick rzstart(sd->sd_unit); 175*52130Smckusick if (biowait(&sc->sc_buf) || 176*52130Smckusick (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5) 177*52130Smckusick goto bad; 178*52130Smckusick switch (inqbuf.type) { 179*52130Smckusick case SCSI_DISK_TYPE: /* disk */ 180*52130Smckusick case SCSI_WORM_TYPE: /* WORM */ 181*52130Smckusick case SCSI_ROM_TYPE: /* CD-ROM */ 182*52130Smckusick case SCSI_OPTICAL_MEM_TYPE: /* Magneto-optical */ 183*52130Smckusick break; 184*52130Smckusick 185*52130Smckusick default: /* not a disk */ 186*52130Smckusick goto bad; 187*52130Smckusick } 188*52130Smckusick sc->sc_type = inqbuf.type; 189*52130Smckusick 190*52130Smckusick /* see if device is ready */ 191*52130Smckusick for (tries = 10; ; ) { 192*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 193*52130Smckusick scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0, 194*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 195*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 196*52130Smckusick sc->sc_buf.b_bcount = 0; 197*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 198*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 199*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 200*52130Smckusick 201*52130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 202*52130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 203*52130Smckusick sc->sc_cmd.buf = (caddr_t)0; 204*52130Smckusick sc->sc_cmd.buflen = 0; 205*52130Smckusick /* setup synchronous data transfers if the device supports it */ 206*52130Smckusick if (tries == 10 && (inqbuf.flags & SCSI_SYNC)) 207*52130Smckusick sc->sc_cmd.flags = SCSICMD_USE_SYNC; 208*52130Smckusick else 209*52130Smckusick sc->sc_cmd.flags = 0; 210*52130Smckusick 211*52130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 212*52130Smckusick if (!biowait(&sc->sc_buf)) 213*52130Smckusick break; 214*52130Smckusick if (--tries < 0) 215*52130Smckusick goto bad; 216*52130Smckusick if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) 217*52130Smckusick goto again; 218*52130Smckusick sp = (ScsiClass7Sense *)sc->sc_sense.sense; 219*52130Smckusick if (sp->error7 != 0x70) 220*52130Smckusick goto again; 221*52130Smckusick if (sp->key == SCSI_CLASS7_UNIT_ATTN && tries != 9) { 222*52130Smckusick /* drive recalibrating, give it a while */ 223*52130Smckusick DELAY(1000000); 224*52130Smckusick continue; 225*52130Smckusick } 226*52130Smckusick if (sp->key == SCSI_CLASS7_NOT_READY) { 227*52130Smckusick ScsiStartStopCmd *cp; 228*52130Smckusick 229*52130Smckusick /* try to spin-up disk with start/stop command */ 230*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 231*52130Smckusick cp = (ScsiStartStopCmd *)sc->sc_cdb.cdb; 232*52130Smckusick cp->command = SCSI_START_STOP; 233*52130Smckusick cp->unitNumber = sd->sd_slave; 234*52130Smckusick cp->immed = 0; 235*52130Smckusick cp->loadEject = 0; 236*52130Smckusick cp->start = 1; 237*52130Smckusick cp->pad1 = 0; 238*52130Smckusick cp->pad2 = 0; 239*52130Smckusick cp->pad3 = 0; 240*52130Smckusick cp->pad4 = 0; 241*52130Smckusick cp->control = 0; 242*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 243*52130Smckusick sc->sc_buf.b_bcount = 0; 244*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 245*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 246*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 247*52130Smckusick rzstart(sd->sd_unit); 248*52130Smckusick if (biowait(&sc->sc_buf)) 249*52130Smckusick goto bad; 250*52130Smckusick continue; 251*52130Smckusick } 252*52130Smckusick again: 253*52130Smckusick DELAY(1000); 254*52130Smckusick } 255*52130Smckusick 256*52130Smckusick /* find out how big a disk this is */ 257*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup1Cmd); 258*52130Smckusick scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, 259*52130Smckusick (ScsiGroup1Cmd *)sc->sc_cdb.cdb); 260*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 261*52130Smckusick sc->sc_buf.b_bcount = sizeof(capbuf); 262*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)capbuf; 263*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 264*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 265*52130Smckusick rzstart(sd->sd_unit); 266*52130Smckusick if (biowait(&sc->sc_buf) || sc->sc_buf.b_resid != 0) 267*52130Smckusick goto bad; 268*52130Smckusick sc->sc_blks = (capbuf[0] << 24) | (capbuf[1] << 16) | 269*52130Smckusick (capbuf[2] << 8) | capbuf[3]; 270*52130Smckusick sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) | 271*52130Smckusick (capbuf[6] << 8) | capbuf[7]; 272*52130Smckusick 273*52130Smckusick printf("rz%d at %s%d drive %d slave %d", sd->sd_unit, 274*52130Smckusick sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive, 275*52130Smckusick sd->sd_slave); 276*52130Smckusick if (inqbuf.version > 1 || i < 36) 277*52130Smckusick printf(" type 0x%x, qual 0x%x, ver %d", 278*52130Smckusick inqbuf.type, inqbuf.qualifier, inqbuf.version); 279*52130Smckusick else { 280*52130Smckusick char vid[9], pid[17], revl[5]; 281*52130Smckusick 282*52130Smckusick bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8); 283*52130Smckusick bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16); 284*52130Smckusick bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4); 285*52130Smckusick for (i = 8; --i > 0; ) 286*52130Smckusick if (vid[i] != ' ') 287*52130Smckusick break; 288*52130Smckusick vid[i+1] = 0; 289*52130Smckusick for (i = 16; --i > 0; ) 290*52130Smckusick if (pid[i] != ' ') 291*52130Smckusick break; 292*52130Smckusick pid[i+1] = 0; 293*52130Smckusick for (i = 4; --i > 0; ) 294*52130Smckusick if (revl[i] != ' ') 295*52130Smckusick break; 296*52130Smckusick revl[i+1] = 0; 297*52130Smckusick printf(" %s %s rev %s", vid, pid, revl); 298*52130Smckusick } 299*52130Smckusick printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 300*52130Smckusick if (sc->sc_blksize != DEV_BSIZE) { 301*52130Smckusick if (sc->sc_blksize < DEV_BSIZE) { 302*52130Smckusick printf("rz%d: need %d byte blocks - drive ignored\n", 303*52130Smckusick sd->sd_unit, DEV_BSIZE); 304*52130Smckusick goto bad; 305*52130Smckusick } 306*52130Smckusick for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 307*52130Smckusick ++sc->sc_bshift; 308*52130Smckusick sc->sc_blks <<= sc->sc_bshift; 309*52130Smckusick } 310*52130Smckusick sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 311*52130Smckusick sc->sc_format_pid = 0; 312*52130Smckusick sc->sc_flags = RZF_ALIVE; 313*52130Smckusick 314*52130Smckusick /* try to read disk label or partition table information */ 315*52130Smckusick if (rzreadlabel(sc, sd) == 0) 316*52130Smckusick goto ok; 317*52130Smckusick 318*52130Smckusick /* 319*52130Smckusick * We don't have a disk label, build a default partition 320*52130Smckusick * table with 'standard' size root & swap and everything else 321*52130Smckusick * in the G partition. 322*52130Smckusick */ 323*52130Smckusick sc->sc_info = rzdefaultpart; 324*52130Smckusick /* C gets everything */ 325*52130Smckusick sc->sc_info.part[2].nblocks = sc->sc_blks; 326*52130Smckusick sc->sc_info.part[2].endblk = sc->sc_blks; 327*52130Smckusick /* G gets from end of B to end of disk */ 328*52130Smckusick sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk; 329*52130Smckusick sc->sc_info.part[6].endblk = sc->sc_blks; 330*52130Smckusick /* 331*52130Smckusick * We also define the D, E and F paritions as an alternative to 332*52130Smckusick * B and G. D is 48Mb, starts after A and is intended for swapping. 333*52130Smckusick * E is 50Mb, starts after D and is intended for /usr. F starts 334*52130Smckusick * after E and is what ever is left. 335*52130Smckusick */ 336*52130Smckusick if (sc->sc_blks >= sc->sc_info.part[4].endblk) { 337*52130Smckusick sc->sc_info.part[5].nblocks = 338*52130Smckusick sc->sc_blks - sc->sc_info.part[4].endblk; 339*52130Smckusick sc->sc_info.part[5].endblk = sc->sc_blks; 340*52130Smckusick } else { 341*52130Smckusick sc->sc_info.part[5].strtblk = 0; 342*52130Smckusick sc->sc_info.part[3] = sc->sc_info.part[5]; 343*52130Smckusick sc->sc_info.part[4] = sc->sc_info.part[5]; 344*52130Smckusick } 345*52130Smckusick /* 346*52130Smckusick * H is a single partition alternative to E and F. 347*52130Smckusick */ 348*52130Smckusick if (sc->sc_blks >= sc->sc_info.part[3].endblk) { 349*52130Smckusick sc->sc_info.part[7].nblocks = 350*52130Smckusick sc->sc_blks - sc->sc_info.part[3].endblk; 351*52130Smckusick sc->sc_info.part[7].endblk = sc->sc_blks; 352*52130Smckusick } else 353*52130Smckusick sc->sc_info.part[7].strtblk = 0; 354*52130Smckusick 355*52130Smckusick ok: 356*52130Smckusick sc->sc_buf.b_flags = 0; 357*52130Smckusick return (1); 358*52130Smckusick 359*52130Smckusick bad: 360*52130Smckusick /* doesn't exist or not a CCS device */ 361*52130Smckusick sc->sc_format_pid = 0; 362*52130Smckusick sc->sc_buf.b_flags = 0; 363*52130Smckusick return (0); 364*52130Smckusick } 365*52130Smckusick 366*52130Smckusick /* 367*52130Smckusick * Try to read the disk label and fill in the partition table info. 368*52130Smckusick */ 369*52130Smckusick static int 370*52130Smckusick rzreadlabel(sc, sd) 371*52130Smckusick register struct rz_softc *sc; 372*52130Smckusick register struct scsi_device *sd; 373*52130Smckusick { 374*52130Smckusick register struct size *sp; 375*52130Smckusick Sun_DiskLabel *sunLabelPtr; 376*52130Smckusick Dec_DiskLabel *decLabelPtr; 377*52130Smckusick char labelBuffer[DEV_BSIZE]; 378*52130Smckusick int part, error; 379*52130Smckusick 380*52130Smckusick /* 381*52130Smckusick * The label of a SCSI disk normally resides in the first sector. 382*52130Smckusick * Format and send a SCSI READ command to fetch the sector. 383*52130Smckusick */ 384*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 385*52130Smckusick sc->sc_buf.b_bcount = sizeof(labelBuffer); 386*52130Smckusick sc->sc_buf.b_un.b_addr = labelBuffer; 387*52130Smckusick sc->sc_buf.b_cylin = SUN_LABEL_SECTOR; 388*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 389*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 390*52130Smckusick rzstart(sd->sd_unit); 391*52130Smckusick if (error = biowait(&sc->sc_buf)) 392*52130Smckusick return (error); 393*52130Smckusick sunLabelPtr = (Sun_DiskLabel *)labelBuffer; 394*52130Smckusick if (sunLabelPtr->magic == SUN_DISK_MAGIC) { 395*52130Smckusick /* 396*52130Smckusick * XXX - Should really check if label is valid. 397*52130Smckusick */ 398*52130Smckusick #ifdef DEBUG 399*52130Smckusick if (rzdebug & RZB_PRLABEL) { 400*52130Smckusick printf("rz%d: SUN label %s\n", sd->sd_unit, 401*52130Smckusick sunLabelPtr->asciiLabel); 402*52130Smckusick printf(" Partitions"); 403*52130Smckusick } 404*52130Smckusick #endif 405*52130Smckusick sp = sc->sc_info.part; 406*52130Smckusick for (part = 0; part < DEV_NUM_DISK_PARTS; part++, sp++) { 407*52130Smckusick sp->strtblk = 408*52130Smckusick sunLabelPtr->map[part].cylinder * 409*52130Smckusick sunLabelPtr->numHeads * 410*52130Smckusick sunLabelPtr->numSectors; 411*52130Smckusick sp->nblocks = 412*52130Smckusick sunLabelPtr->map[part].numBlocks; 413*52130Smckusick sp->endblk = sp->strtblk + sp->nblocks; 414*52130Smckusick #ifdef DEBUG 415*52130Smckusick if (rzdebug & RZB_PRLABEL) 416*52130Smckusick printf(" (%d,%d)", sp->strtblk, sp->nblocks); 417*52130Smckusick #endif 418*52130Smckusick } 419*52130Smckusick #ifdef DEBUG 420*52130Smckusick if (rzdebug & RZB_PRLABEL) 421*52130Smckusick printf("\n"); 422*52130Smckusick #endif 423*52130Smckusick return (0); 424*52130Smckusick } 425*52130Smckusick 426*52130Smckusick /* 427*52130Smckusick * The disk isn't in SUN or UNIX format so try Dec format. 428*52130Smckusick * We have to read the right sector first. 429*52130Smckusick */ 430*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_PHYS | B_READ; 431*52130Smckusick sc->sc_buf.b_bcount = sizeof(labelBuffer); 432*52130Smckusick sc->sc_buf.b_un.b_addr = labelBuffer; 433*52130Smckusick sc->sc_buf.b_cylin = DEC_LABEL_SECTOR; 434*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 435*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 436*52130Smckusick rzstart(sd->sd_unit); 437*52130Smckusick if (error = biowait(&sc->sc_buf)) 438*52130Smckusick return (error); 439*52130Smckusick decLabelPtr = (Dec_DiskLabel *)labelBuffer; 440*52130Smckusick if (decLabelPtr->magic == DEC_LABEL_MAGIC && 441*52130Smckusick decLabelPtr->isPartitioned) { 442*52130Smckusick /* 443*52130Smckusick * XXX - Should really check if label is valid. 444*52130Smckusick */ 445*52130Smckusick #ifdef DEBUG 446*52130Smckusick if (rzdebug & RZB_PRLABEL) { 447*52130Smckusick printf("rz%d: DEC label\n", sd->sd_unit); 448*52130Smckusick printf(" Partitions"); 449*52130Smckusick } 450*52130Smckusick #endif 451*52130Smckusick sp = sc->sc_info.part; 452*52130Smckusick for (part = 0; part < DEV_NUM_DISK_PARTS; part++, sp++) { 453*52130Smckusick sp->strtblk = decLabelPtr->map[part].startBlock; 454*52130Smckusick sp->nblocks = decLabelPtr->map[part].numBlocks; 455*52130Smckusick sp->endblk = sp->strtblk + sp->nblocks; 456*52130Smckusick #ifdef DEBUG 457*52130Smckusick if (rzdebug & RZB_PRLABEL) 458*52130Smckusick printf(" (%d,%d)", sp->strtblk, sp->nblocks); 459*52130Smckusick #endif 460*52130Smckusick } 461*52130Smckusick #ifdef DEBUG 462*52130Smckusick if (rzdebug & RZB_PRLABEL) 463*52130Smckusick printf("\n"); 464*52130Smckusick #endif 465*52130Smckusick return (0); 466*52130Smckusick } 467*52130Smckusick return (EIO); 468*52130Smckusick } 469*52130Smckusick 470*52130Smckusick /* 471*52130Smckusick * This routine is called for partial block transfers and non-aligned 472*52130Smckusick * transfers (the latter only being possible on devices with a block size 473*52130Smckusick * larger than DEV_BSIZE). The operation is performed in three steps 474*52130Smckusick * using a locally allocated buffer: 475*52130Smckusick * 1. transfer any initial partial block 476*52130Smckusick * 2. transfer full blocks 477*52130Smckusick * 3. transfer any final partial block 478*52130Smckusick */ 479*52130Smckusick static void 480*52130Smckusick rzlblkstrat(bp, bsize) 481*52130Smckusick register struct buf *bp; 482*52130Smckusick register int bsize; 483*52130Smckusick { 484*52130Smckusick register struct buf *cbp; 485*52130Smckusick caddr_t cbuf; 486*52130Smckusick register int bn, resid; 487*52130Smckusick register caddr_t addr; 488*52130Smckusick 489*52130Smckusick cbp = (struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK); 490*52130Smckusick cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); 491*52130Smckusick bzero((caddr_t)cbp, sizeof(*cbp)); 492*52130Smckusick cbp->b_proc = curproc; 493*52130Smckusick cbp->b_dev = bp->b_dev; 494*52130Smckusick bn = bp->b_blkno; 495*52130Smckusick resid = bp->b_bcount; 496*52130Smckusick addr = bp->b_un.b_addr; 497*52130Smckusick #ifdef DEBUG 498*52130Smckusick if (rzdebug & RZB_PARTIAL) 499*52130Smckusick printf("rzlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", 500*52130Smckusick bp, bp->b_flags, bn, resid, addr); 501*52130Smckusick #endif 502*52130Smckusick 503*52130Smckusick while (resid > 0) { 504*52130Smckusick register int boff = dbtob(bn) & (bsize - 1); 505*52130Smckusick register int count; 506*52130Smckusick 507*52130Smckusick if (boff || resid < bsize) { 508*52130Smckusick rz_softc[rzunit(bp->b_dev)].sc_stats.rzpartials++; 509*52130Smckusick count = MIN(resid, bsize - boff); 510*52130Smckusick cbp->b_flags = B_BUSY | B_PHYS | B_READ; 511*52130Smckusick cbp->b_blkno = bn - btodb(boff); 512*52130Smckusick cbp->b_un.b_addr = cbuf; 513*52130Smckusick cbp->b_bcount = bsize; 514*52130Smckusick #ifdef DEBUG 515*52130Smckusick if (rzdebug & RZB_PARTIAL) 516*52130Smckusick printf(" readahead: bn %x cnt %x off %x addr %x\n", 517*52130Smckusick cbp->b_blkno, count, boff, addr); 518*52130Smckusick #endif 519*52130Smckusick rzstrategy(cbp); 520*52130Smckusick biowait(cbp); 521*52130Smckusick if (cbp->b_flags & B_ERROR) { 522*52130Smckusick bp->b_flags |= B_ERROR; 523*52130Smckusick bp->b_error = cbp->b_error; 524*52130Smckusick break; 525*52130Smckusick } 526*52130Smckusick if (bp->b_flags & B_READ) { 527*52130Smckusick bcopy(&cbuf[boff], addr, count); 528*52130Smckusick goto done; 529*52130Smckusick } 530*52130Smckusick bcopy(addr, &cbuf[boff], count); 531*52130Smckusick #ifdef DEBUG 532*52130Smckusick if (rzdebug & RZB_PARTIAL) 533*52130Smckusick printf(" writeback: bn %x cnt %x off %x addr %x\n", 534*52130Smckusick cbp->b_blkno, count, boff, addr); 535*52130Smckusick #endif 536*52130Smckusick } else { 537*52130Smckusick count = resid & ~(bsize - 1); 538*52130Smckusick cbp->b_blkno = bn; 539*52130Smckusick cbp->b_un.b_addr = addr; 540*52130Smckusick cbp->b_bcount = count; 541*52130Smckusick #ifdef DEBUG 542*52130Smckusick if (rzdebug & RZB_PARTIAL) 543*52130Smckusick printf(" fulltrans: bn %x cnt %x addr %x\n", 544*52130Smckusick cbp->b_blkno, count, addr); 545*52130Smckusick #endif 546*52130Smckusick } 547*52130Smckusick cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ); 548*52130Smckusick rzstrategy(cbp); 549*52130Smckusick biowait(cbp); 550*52130Smckusick if (cbp->b_flags & B_ERROR) { 551*52130Smckusick bp->b_flags |= B_ERROR; 552*52130Smckusick bp->b_error = cbp->b_error; 553*52130Smckusick break; 554*52130Smckusick } 555*52130Smckusick done: 556*52130Smckusick bn += btodb(count); 557*52130Smckusick resid -= count; 558*52130Smckusick addr += count; 559*52130Smckusick #ifdef DEBUG 560*52130Smckusick if (rzdebug & RZB_PARTIAL) 561*52130Smckusick printf(" done: bn %x resid %x addr %x\n", 562*52130Smckusick bn, resid, addr); 563*52130Smckusick #endif 564*52130Smckusick } 565*52130Smckusick free(cbuf, M_DEVBUF); 566*52130Smckusick free(cbp, M_DEVBUF); 567*52130Smckusick } 568*52130Smckusick 569*52130Smckusick void 570*52130Smckusick rzstrategy(bp) 571*52130Smckusick register struct buf *bp; 572*52130Smckusick { 573*52130Smckusick register int unit = rzunit(bp->b_dev); 574*52130Smckusick register int part = rzpart(bp->b_dev); 575*52130Smckusick register int bn, sz; 576*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 577*52130Smckusick register int s; 578*52130Smckusick 579*52130Smckusick if (sc->sc_format_pid) { 580*52130Smckusick if (sc->sc_format_pid != curproc->p_pid) { 581*52130Smckusick bp->b_error = EPERM; 582*52130Smckusick goto bad; 583*52130Smckusick } 584*52130Smckusick bp->b_cylin = 0; 585*52130Smckusick } else { 586*52130Smckusick bn = bp->b_blkno; 587*52130Smckusick sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT; 588*52130Smckusick if (bn < 0 || bn + sz > sc->sc_info.part[part].nblocks) { 589*52130Smckusick if (bn == sc->sc_info.part[part].nblocks) { 590*52130Smckusick bp->b_resid = bp->b_bcount; 591*52130Smckusick goto done; 592*52130Smckusick } 593*52130Smckusick bp->b_error = EINVAL; 594*52130Smckusick goto bad; 595*52130Smckusick } 596*52130Smckusick /* 597*52130Smckusick * Non-aligned or partial-block transfers handled specially. 598*52130Smckusick */ 599*52130Smckusick s = sc->sc_blksize - 1; 600*52130Smckusick if ((dbtob(bn) & s) || (bp->b_bcount & s)) { 601*52130Smckusick rzlblkstrat(bp, sc->sc_blksize); 602*52130Smckusick goto done; 603*52130Smckusick } 604*52130Smckusick bp->b_cylin = (bn + sc->sc_info.part[part].strtblk) >> 605*52130Smckusick sc->sc_bshift; 606*52130Smckusick } 607*52130Smckusick /* don't let disksort() see sc_errbuf */ 608*52130Smckusick while (sc->sc_flags & RZF_SENSEINPROGRESS) 609*52130Smckusick printf("SENSE\n"); /* XXX */ 610*52130Smckusick s = splbio(); 611*52130Smckusick disksort(&sc->sc_tab, bp); 612*52130Smckusick if (sc->sc_tab.b_active == 0) { 613*52130Smckusick sc->sc_tab.b_active = 1; 614*52130Smckusick rzstart(unit); 615*52130Smckusick } 616*52130Smckusick splx(s); 617*52130Smckusick return; 618*52130Smckusick bad: 619*52130Smckusick bp->b_flags |= B_ERROR; 620*52130Smckusick done: 621*52130Smckusick biodone(bp); 622*52130Smckusick } 623*52130Smckusick 624*52130Smckusick void 625*52130Smckusick rzstart(unit) 626*52130Smckusick int unit; 627*52130Smckusick { 628*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 629*52130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 630*52130Smckusick register int n; 631*52130Smckusick 632*52130Smckusick sc->sc_cmd.buf = bp->b_un.b_addr; 633*52130Smckusick sc->sc_cmd.buflen = bp->b_bcount; 634*52130Smckusick 635*52130Smckusick if (sc->sc_format_pid || (sc->sc_flags & RZF_SENSEINPROGRESS)) { 636*52130Smckusick sc->sc_cmd.flags = !(bp->b_flags & B_READ) ? 637*52130Smckusick SCSICMD_DATA_TO_DEVICE : 0; 638*52130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 639*52130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 640*52130Smckusick } else { 641*52130Smckusick if (bp->b_flags & B_READ) { 642*52130Smckusick sc->sc_cmd.flags = 0; 643*52130Smckusick sc->sc_rwcmd.command = SCSI_READ_EXT; 644*52130Smckusick } else { 645*52130Smckusick sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE; 646*52130Smckusick sc->sc_rwcmd.command = SCSI_WRITE_EXT; 647*52130Smckusick } 648*52130Smckusick sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 649*52130Smckusick sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd); 650*52130Smckusick n = bp->b_cylin; 651*52130Smckusick sc->sc_rwcmd.highAddr = n >> 24; 652*52130Smckusick sc->sc_rwcmd.midHighAddr = n >> 16; 653*52130Smckusick sc->sc_rwcmd.midLowAddr = n >> 8; 654*52130Smckusick sc->sc_rwcmd.lowAddr = n; 655*52130Smckusick n = howmany(bp->b_bcount, sc->sc_blksize); 656*52130Smckusick sc->sc_rwcmd.highBlockCount = n >> 8; 657*52130Smckusick sc->sc_rwcmd.lowBlockCount = n; 658*52130Smckusick #ifdef DEBUG 659*52130Smckusick if ((bp->b_bcount & (sc->sc_blksize - 1)) != 0) 660*52130Smckusick printf("rz%d: partial block xfer -- %x bytes\n", 661*52130Smckusick unit, bp->b_bcount); 662*52130Smckusick #endif 663*52130Smckusick sc->sc_stats.rztransfers++; 664*52130Smckusick if ((n = sc->sc_sd->sd_dk) >= 0) { 665*52130Smckusick dk_busy |= 1 << n; 666*52130Smckusick ++dk_seek[n]; 667*52130Smckusick ++dk_xfer[n]; 668*52130Smckusick dk_wds[n] += bp->b_bcount >> 6; 669*52130Smckusick } 670*52130Smckusick } 671*52130Smckusick 672*52130Smckusick /* tell controller to start this command */ 673*52130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 674*52130Smckusick } 675*52130Smckusick 676*52130Smckusick /* 677*52130Smckusick * This is called by the controller driver when the command is done. 678*52130Smckusick */ 679*52130Smckusick void 680*52130Smckusick rzdone(unit, error, resid, status) 681*52130Smckusick register int unit; 682*52130Smckusick int error; /* error number from errno.h */ 683*52130Smckusick int resid; /* amount not transfered */ 684*52130Smckusick int status; /* SCSI status byte */ 685*52130Smckusick { 686*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 687*52130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 688*52130Smckusick register struct scsi_device *sd = sc->sc_sd; 689*52130Smckusick extern int cold; 690*52130Smckusick 691*52130Smckusick if (bp == NULL) { 692*52130Smckusick printf("rz%d: bp == NULL\n", unit); 693*52130Smckusick return; 694*52130Smckusick } 695*52130Smckusick if (sd->sd_dk >= 0) 696*52130Smckusick dk_busy &= ~(1 << sd->sd_dk); 697*52130Smckusick if (sc->sc_flags & RZF_SENSEINPROGRESS) { 698*52130Smckusick sc->sc_flags &= ~RZF_SENSEINPROGRESS; 699*52130Smckusick sc->sc_tab.b_actf = bp = bp->av_forw; /* remove sc_errbuf */ 700*52130Smckusick 701*52130Smckusick if (error || (status & SCSI_STATUS_CHECKCOND)) { 702*52130Smckusick #ifdef DEBUG 703*52130Smckusick if (rzdebug & RZB_ERROR) 704*52130Smckusick printf("rz%d: error reading sense data: error %d scsi status 0x%x\n", 705*52130Smckusick unit, error, status); 706*52130Smckusick #endif 707*52130Smckusick /* 708*52130Smckusick * We got an error during the REQUEST_SENSE, 709*52130Smckusick * fill in no sense for data. 710*52130Smckusick */ 711*52130Smckusick sc->sc_sense.sense[0] = 0x70; 712*52130Smckusick sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE; 713*52130Smckusick } else if (!cold 714*52130Smckusick #ifdef DEBUG 715*52130Smckusick || (rzdebug & RZB_ERROR) 716*52130Smckusick #endif 717*52130Smckusick ) { 718*52130Smckusick printf("rz%d: ", unit); 719*52130Smckusick scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense, 720*52130Smckusick sizeof(sc->sc_sense.sense) - resid); 721*52130Smckusick } 722*52130Smckusick } else if (error || (status & SCSI_STATUS_CHECKCOND)) { 723*52130Smckusick #ifdef DEBUG 724*52130Smckusick if (rzdebug & RZB_ERROR) 725*52130Smckusick printf("rz%d: error %d scsi status 0x%x\n", 726*52130Smckusick unit, error, status); 727*52130Smckusick #endif 728*52130Smckusick /* save error info */ 729*52130Smckusick sc->sc_sense.status = status; 730*52130Smckusick bp->b_flags |= B_ERROR; 731*52130Smckusick bp->b_error = error; 732*52130Smckusick bp->b_resid = resid; 733*52130Smckusick 734*52130Smckusick if (status & SCSI_STATUS_CHECKCOND) { 735*52130Smckusick /* 736*52130Smckusick * Start a REQUEST_SENSE command. 737*52130Smckusick * Since we are called at interrupt time, we can't 738*52130Smckusick * wait for the command to finish; that's why we use 739*52130Smckusick * the sc_flags field. 740*52130Smckusick */ 741*52130Smckusick sc->sc_flags |= RZF_SENSEINPROGRESS; 742*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 743*52130Smckusick scsiGroup0Cmd(SCSI_REQUEST_SENSE, sd->sd_slave, 0, 744*52130Smckusick sizeof(sc->sc_sense.sense), 745*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 746*52130Smckusick sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ; 747*52130Smckusick sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense); 748*52130Smckusick sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense; 749*52130Smckusick sc->sc_errbuf.av_forw = bp; 750*52130Smckusick sc->sc_tab.b_actf = &sc->sc_errbuf; 751*52130Smckusick rzstart(unit); 752*52130Smckusick return; 753*52130Smckusick } 754*52130Smckusick } else { 755*52130Smckusick sc->sc_sense.status = status; 756*52130Smckusick bp->b_resid = resid; 757*52130Smckusick } 758*52130Smckusick 759*52130Smckusick sc->sc_tab.b_actf = bp->av_forw; 760*52130Smckusick biodone(bp); 761*52130Smckusick if (sc->sc_tab.b_actf) 762*52130Smckusick rzstart(unit); 763*52130Smckusick else 764*52130Smckusick sc->sc_tab.b_active = 0; 765*52130Smckusick } 766*52130Smckusick 767*52130Smckusick int 768*52130Smckusick rzopen(dev, flags, mode, p) 769*52130Smckusick dev_t dev; 770*52130Smckusick int flags, mode; 771*52130Smckusick struct proc *p; 772*52130Smckusick { 773*52130Smckusick register int unit = rzunit(dev); 774*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 775*52130Smckusick 776*52130Smckusick if (unit >= NRZ) 777*52130Smckusick return (ENXIO); 778*52130Smckusick if (!(sc->sc_flags & RZF_ALIVE) || suser(p->p_ucred, &p->p_acflag)) 779*52130Smckusick return (ENXIO); 780*52130Smckusick 781*52130Smckusick if (sc->sc_sd->sd_dk >= 0) 782*52130Smckusick dk_wpms[sc->sc_sd->sd_dk] = sc->sc_wpms; 783*52130Smckusick return (0); 784*52130Smckusick } 785*52130Smckusick 786*52130Smckusick rzclose(dev, flags) 787*52130Smckusick dev_t dev; 788*52130Smckusick int flags; 789*52130Smckusick { 790*52130Smckusick return (0); 791*52130Smckusick } 792*52130Smckusick 793*52130Smckusick int 794*52130Smckusick rzread(dev, uio) 795*52130Smckusick dev_t dev; 796*52130Smckusick struct uio *uio; 797*52130Smckusick { 798*52130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 799*52130Smckusick 800*52130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 801*52130Smckusick return (EPERM); 802*52130Smckusick 803*52130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 804*52130Smckusick B_READ, minphys, uio)); 805*52130Smckusick } 806*52130Smckusick 807*52130Smckusick int 808*52130Smckusick rzwrite(dev, uio) 809*52130Smckusick dev_t dev; 810*52130Smckusick struct uio *uio; 811*52130Smckusick { 812*52130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 813*52130Smckusick 814*52130Smckusick if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid) 815*52130Smckusick return (EPERM); 816*52130Smckusick 817*52130Smckusick return (physio(rzstrategy, (struct buf *)0, dev, 818*52130Smckusick B_WRITE, minphys, uio)); 819*52130Smckusick } 820*52130Smckusick 821*52130Smckusick int 822*52130Smckusick rzioctl(dev, cmd, data, flag, p) 823*52130Smckusick dev_t dev; 824*52130Smckusick int cmd; 825*52130Smckusick caddr_t data; 826*52130Smckusick int flag; 827*52130Smckusick struct proc *p; 828*52130Smckusick { 829*52130Smckusick register struct rz_softc *sc = &rz_softc[rzunit(dev)]; 830*52130Smckusick 831*52130Smckusick switch (cmd) { 832*52130Smckusick default: 833*52130Smckusick return (EINVAL); 834*52130Smckusick 835*52130Smckusick case SDIOCSFORMAT: 836*52130Smckusick /* take this device into or out of "format" mode */ 837*52130Smckusick if (suser(p->p_ucred, &p->p_acflag)) 838*52130Smckusick return (EPERM); 839*52130Smckusick 840*52130Smckusick if (*(int *)data) { 841*52130Smckusick if (sc->sc_format_pid) 842*52130Smckusick return (EPERM); 843*52130Smckusick sc->sc_format_pid = p->p_pid; 844*52130Smckusick } else 845*52130Smckusick sc->sc_format_pid = 0; 846*52130Smckusick return (0); 847*52130Smckusick 848*52130Smckusick case SDIOCGFORMAT: 849*52130Smckusick /* find out who has the device in format mode */ 850*52130Smckusick *(int *)data = sc->sc_format_pid; 851*52130Smckusick return (0); 852*52130Smckusick 853*52130Smckusick case SDIOCSCSICOMMAND: 854*52130Smckusick /* 855*52130Smckusick * Save what user gave us as SCSI cdb to use with next 856*52130Smckusick * read or write to the char device. 857*52130Smckusick */ 858*52130Smckusick if (sc->sc_format_pid != p->p_pid) 859*52130Smckusick return (EPERM); 860*52130Smckusick if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0) 861*52130Smckusick return (EINVAL); 862*52130Smckusick bcopy(data, (caddr_t)&sc->sc_cdb, sizeof(sc->sc_cdb)); 863*52130Smckusick return (0); 864*52130Smckusick 865*52130Smckusick case SDIOCSENSE: 866*52130Smckusick /* 867*52130Smckusick * return the SCSI sense data saved after the last 868*52130Smckusick * operation that completed with "check condition" status. 869*52130Smckusick */ 870*52130Smckusick bcopy((caddr_t)&sc->sc_sense, data, sizeof(sc->sc_sense)); 871*52130Smckusick return (0); 872*52130Smckusick 873*52130Smckusick } 874*52130Smckusick /*NOTREACHED*/ 875*52130Smckusick } 876*52130Smckusick 877*52130Smckusick int 878*52130Smckusick rzsize(dev) 879*52130Smckusick dev_t dev; 880*52130Smckusick { 881*52130Smckusick register int unit = rzunit(dev); 882*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 883*52130Smckusick 884*52130Smckusick if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE)) 885*52130Smckusick return (-1); 886*52130Smckusick 887*52130Smckusick return (sc->sc_info.part[rzpart(dev)].nblocks); 888*52130Smckusick } 889*52130Smckusick 890*52130Smckusick /* 891*52130Smckusick * Non-interrupt driven, non-dma dump routine. 892*52130Smckusick */ 893*52130Smckusick int 894*52130Smckusick rzdump(dev) 895*52130Smckusick dev_t dev; 896*52130Smckusick { 897*52130Smckusick #ifdef notdef 898*52130Smckusick int part = rzpart(dev); 899*52130Smckusick int unit = rzunit(dev); 900*52130Smckusick register struct rz_softc *sc = &rz_softc[unit]; 901*52130Smckusick register struct scsi_device *sd = sc->sc_hd; 902*52130Smckusick register daddr_t baddr; 903*52130Smckusick register int maddr; 904*52130Smckusick register int pages, i; 905*52130Smckusick int stat; 906*52130Smckusick extern int lowram; 907*52130Smckusick 908*52130Smckusick /* 909*52130Smckusick * Hmm... all vax drivers dump maxfree pages which is physmem minus 910*52130Smckusick * the message buffer. Is there a reason for not dumping the 911*52130Smckusick * message buffer? Savecore expects to read 'dumpsize' pages of 912*52130Smckusick * dump, where dumpsys() sets dumpsize to physmem! 913*52130Smckusick */ 914*52130Smckusick pages = physmem; 915*52130Smckusick 916*52130Smckusick /* is drive ok? */ 917*52130Smckusick if (unit >= NRZ || (sc->sc_flags & RZF_ALIVE) == 0) 918*52130Smckusick return (ENXIO); 919*52130Smckusick /* dump parameters in range? */ 920*52130Smckusick if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks) 921*52130Smckusick return (EINVAL); 922*52130Smckusick if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks) 923*52130Smckusick pages = dtoc(sc->sc_info.part[part].nblocks - dumplo); 924*52130Smckusick maddr = lowram; 925*52130Smckusick baddr = dumplo + sc->sc_info.part[part].strtblk; 926*52130Smckusick /* scsi bus idle? */ 927*52130Smckusick if (!scsireq(&sc->sc_dq)) { 928*52130Smckusick scsireset(sd->sd_ctlr); 929*52130Smckusick sc->sc_stats.rzresets++; 930*52130Smckusick printf("[ drive %d reset ] ", unit); 931*52130Smckusick } 932*52130Smckusick for (i = 0; i < pages; i++) { 933*52130Smckusick #define NPGMB (1024*1024/NBPG) 934*52130Smckusick /* print out how many Mbs we have dumped */ 935*52130Smckusick if (i && (i % NPGMB) == 0) 936*52130Smckusick printf("%d ", i / NPGMB); 937*52130Smckusick #undef NPBMG 938*52130Smckusick mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); 939*52130Smckusick stat = scsi_tt_write(sd->sd_ctlr, sd->sd_drive, sd->sd_slave, 940*52130Smckusick vmmap, NBPG, baddr, sc->sc_bshift); 941*52130Smckusick if (stat) { 942*52130Smckusick printf("rzdump: scsi write error 0x%x\n", stat); 943*52130Smckusick return (EIO); 944*52130Smckusick } 945*52130Smckusick maddr += NBPG; 946*52130Smckusick baddr += ctod(1); 947*52130Smckusick } 948*52130Smckusick return (0); 949*52130Smckusick #else notdef 950*52130Smckusick return (ENXIO); 951*52130Smckusick #endif notdef 952*52130Smckusick } 953*52130Smckusick #endif 954