1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1990 The Regents of the University of California. 3*41480Smckusick * All rights reserved. 4*41480Smckusick * 5*41480Smckusick * This code is derived from software contributed to Berkeley by 6*41480Smckusick * Van Jacobson of Lawrence Berkeley Laboratory. 7*41480Smckusick * 8*41480Smckusick * %sccs.include.redist.c% 9*41480Smckusick * 10*41480Smckusick * @(#)sd.c 7.1 (Berkeley) 05/08/90 11*41480Smckusick */ 12*41480Smckusick 13*41480Smckusick /* 14*41480Smckusick * SCSI CCS (Command Command Set) disk driver. 15*41480Smckusick */ 16*41480Smckusick #include "sd.h" 17*41480Smckusick #if NSD > 0 18*41480Smckusick 19*41480Smckusick #ifndef lint 20*41480Smckusick static char rcsid[] = "$Header: sd.c,v 1.5 90/01/10 16:06:12 mike Locked $"; 21*41480Smckusick #endif 22*41480Smckusick 23*41480Smckusick #include "param.h" 24*41480Smckusick #include "systm.h" 25*41480Smckusick #include "buf.h" 26*41480Smckusick #include "errno.h" 27*41480Smckusick #include "dkstat.h" 28*41480Smckusick #include "disklabel.h" 29*41480Smckusick #include "device.h" 30*41480Smckusick #include "malloc.h" 31*41480Smckusick #include "scsireg.h" 32*41480Smckusick 33*41480Smckusick #include "user.h" 34*41480Smckusick #include "proc.h" 35*41480Smckusick #include "uio.h" 36*41480Smckusick 37*41480Smckusick extern int scsi_test_unit_rdy(); 38*41480Smckusick extern int scsi_request_sense(); 39*41480Smckusick extern int scsi_inquiry(); 40*41480Smckusick extern int scsi_read_capacity(); 41*41480Smckusick extern int scsi_tt_write(); 42*41480Smckusick extern int scsireq(); 43*41480Smckusick extern int scsiustart(); 44*41480Smckusick extern int scsigo(); 45*41480Smckusick extern void scsifree(); 46*41480Smckusick extern void scsireset(); 47*41480Smckusick 48*41480Smckusick extern void printf(); 49*41480Smckusick extern void bcopy(); 50*41480Smckusick extern void disksort(); 51*41480Smckusick extern int splbio(); 52*41480Smckusick extern void splx(); 53*41480Smckusick extern void biodone(); 54*41480Smckusick extern int physio(); 55*41480Smckusick extern void TBIS(); 56*41480Smckusick 57*41480Smckusick int sdinit(); 58*41480Smckusick void sdstrategy(), sdstart(), sdustart(), sdgo(), sdintr(); 59*41480Smckusick 60*41480Smckusick struct driver sddriver = { 61*41480Smckusick sdinit, "sd", (int (*)())sdstart, (int (*)())sdgo, (int (*)())sdintr, 62*41480Smckusick }; 63*41480Smckusick 64*41480Smckusick struct size { 65*41480Smckusick u_long strtblk; 66*41480Smckusick u_long endblk; 67*41480Smckusick int nblocks; 68*41480Smckusick }; 69*41480Smckusick 70*41480Smckusick struct sdinfo { 71*41480Smckusick struct size part[8]; 72*41480Smckusick }; 73*41480Smckusick 74*41480Smckusick /* 75*41480Smckusick * since the SCSI standard tends to hide the disk structure, we define 76*41480Smckusick * partitions in terms of DEV_BSIZE blocks. The default partition table 77*41480Smckusick * (for an unlabeled disk) reserves 512K for a boot area, has an 8 meg 78*41480Smckusick * root and 32 meg of swap. The rest of the space on the drive goes in 79*41480Smckusick * the G partition. As usual, the C partition covers the entire disk 80*41480Smckusick * (including the boot area). 81*41480Smckusick */ 82*41480Smckusick struct sdinfo sddefaultpart = { 83*41480Smckusick 1024, 17408, 16384 , /* A */ 84*41480Smckusick 17408, 82944, 65536 , /* B */ 85*41480Smckusick 0, 0, 0 , /* C */ 86*41480Smckusick 17408, 115712, 98304 , /* D */ 87*41480Smckusick 115712, 218112, 102400 , /* E */ 88*41480Smckusick 218112, 0, 0 , /* F */ 89*41480Smckusick 82944, 0, 0 , /* G */ 90*41480Smckusick 115712, 0, 0 , /* H */ 91*41480Smckusick }; 92*41480Smckusick 93*41480Smckusick struct sd_softc { 94*41480Smckusick struct hp_device *sc_hd; 95*41480Smckusick struct devqueue sc_dq; 96*41480Smckusick int sc_format_pid; /* process using "format" mode */ 97*41480Smckusick short sc_flags; 98*41480Smckusick short sc_type; /* drive type */ 99*41480Smckusick short sc_punit; /* physical unit (scsi lun) */ 100*41480Smckusick u_short sc_bshift; /* convert device blocks to DEV_BSIZE blks */ 101*41480Smckusick u_int sc_blks; /* number of blocks on device */ 102*41480Smckusick int sc_blksize; /* device block size in bytes */ 103*41480Smckusick u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ 104*41480Smckusick struct sdinfo sc_info; /* drive partition table & label info */ 105*41480Smckusick } sd_softc[NSD]; 106*41480Smckusick 107*41480Smckusick /* sc_flags values */ 108*41480Smckusick #define SDF_ALIVE 0x1 109*41480Smckusick 110*41480Smckusick #ifdef DEBUG 111*41480Smckusick int sddebug = 1; 112*41480Smckusick #define SDB_ERROR 0x01 113*41480Smckusick #define SDB_PARTIAL 0x02 114*41480Smckusick #endif 115*41480Smckusick 116*41480Smckusick struct sdstats { 117*41480Smckusick long sdresets; 118*41480Smckusick long sdtransfers; 119*41480Smckusick long sdpartials; 120*41480Smckusick } sdstats[NSD]; 121*41480Smckusick 122*41480Smckusick struct buf sdtab[NSD]; 123*41480Smckusick struct buf sdbuf[NSD]; 124*41480Smckusick struct scsi_fmt_cdb sdcmd[NSD]; 125*41480Smckusick struct scsi_fmt_sense sdsense[NSD]; 126*41480Smckusick 127*41480Smckusick static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT }; 128*41480Smckusick static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT }; 129*41480Smckusick 130*41480Smckusick #define sdunit(x) ((minor(x) >> 3) & 0x7) 131*41480Smckusick #define sdpart(x) (minor(x) & 0x7) 132*41480Smckusick #define sdpunit(x) ((x) & 7) 133*41480Smckusick #define b_cylin b_resid 134*41480Smckusick #define SDRETRY 2 135*41480Smckusick 136*41480Smckusick /* 137*41480Smckusick * Table of scsi commands users are allowed to access via "format" 138*41480Smckusick * mode. 0 means not legal. 1 means "immediate" (doesn't need dma). 139*41480Smckusick * -1 means needs dma and/or wait for intr. 140*41480Smckusick */ 141*41480Smckusick static char legal_cmds[256] = { 142*41480Smckusick /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 143*41480Smckusick /*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144*41480Smckusick /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 145*41480Smckusick /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146*41480Smckusick /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147*41480Smckusick /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148*41480Smckusick /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149*41480Smckusick /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150*41480Smckusick /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151*41480Smckusick /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152*41480Smckusick /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153*41480Smckusick /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154*41480Smckusick /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155*41480Smckusick /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156*41480Smckusick /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157*41480Smckusick /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158*41480Smckusick /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159*41480Smckusick }; 160*41480Smckusick 161*41480Smckusick static struct scsi_inquiry inqbuf; 162*41480Smckusick static struct scsi_fmt_cdb inq = { 163*41480Smckusick 6, 164*41480Smckusick CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 165*41480Smckusick }; 166*41480Smckusick 167*41480Smckusick static u_char capbuf[8]; 168*41480Smckusick struct scsi_fmt_cdb cap = { 169*41480Smckusick 10, 170*41480Smckusick CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 171*41480Smckusick }; 172*41480Smckusick 173*41480Smckusick static int 174*41480Smckusick sdident(sc, hd) 175*41480Smckusick struct sd_softc *sc; 176*41480Smckusick struct hp_device *hd; 177*41480Smckusick { 178*41480Smckusick int unit; 179*41480Smckusick register int ctlr, slave; 180*41480Smckusick register int i; 181*41480Smckusick register int tries = 10; 182*41480Smckusick 183*41480Smckusick ctlr = hd->hp_ctlr; 184*41480Smckusick slave = hd->hp_slave; 185*41480Smckusick unit = sc->sc_punit; 186*41480Smckusick 187*41480Smckusick /* 188*41480Smckusick * See if unit exists and is a disk then read block size & nblocks. 189*41480Smckusick */ 190*41480Smckusick while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 191*41480Smckusick if (i == -1 || --tries < 0) 192*41480Smckusick /* doesn't exist or not a CCS device */ 193*41480Smckusick return (-1); 194*41480Smckusick if (i == STS_CHECKCOND) { 195*41480Smckusick u_char sensebuf[128]; 196*41480Smckusick struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 197*41480Smckusick 198*41480Smckusick scsi_request_sense(ctlr, slave, unit, sensebuf, 199*41480Smckusick sizeof(sensebuf)); 200*41480Smckusick if (sp->class == 7 && sp->key == 6) 201*41480Smckusick /* drive doing an RTZ -- give it a while */ 202*41480Smckusick DELAY(1000000); 203*41480Smckusick } 204*41480Smckusick DELAY(1000); 205*41480Smckusick } 206*41480Smckusick if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, 207*41480Smckusick sizeof(inqbuf), B_READ) || 208*41480Smckusick scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, 209*41480Smckusick sizeof(capbuf), B_READ)) 210*41480Smckusick /* doesn't exist or not a CCS device */ 211*41480Smckusick return (-1); 212*41480Smckusick 213*41480Smckusick switch (inqbuf.type) { 214*41480Smckusick case 0: /* disk */ 215*41480Smckusick case 4: /* WORM */ 216*41480Smckusick case 5: /* CD-ROM */ 217*41480Smckusick case 7: /* Magneto-optical */ 218*41480Smckusick break; 219*41480Smckusick default: /* not a disk */ 220*41480Smckusick return (-1); 221*41480Smckusick } 222*41480Smckusick sc->sc_blks = *(u_int *)&capbuf[0]; 223*41480Smckusick sc->sc_blksize = *(int *)&capbuf[4]; 224*41480Smckusick 225*41480Smckusick if (inqbuf.version != 1) 226*41480Smckusick printf("sd%d: type 0x%x, qual 0x%x, ver %d", hd->hp_unit, 227*41480Smckusick inqbuf.type, inqbuf.qual, inqbuf.version); 228*41480Smckusick else { 229*41480Smckusick char idstr[32]; 230*41480Smckusick 231*41480Smckusick bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 232*41480Smckusick for (i = 27; i > 23; --i) 233*41480Smckusick if (idstr[i] != ' ') 234*41480Smckusick break; 235*41480Smckusick idstr[i+1] = 0; 236*41480Smckusick for (i = 23; i > 7; --i) 237*41480Smckusick if (idstr[i] != ' ') 238*41480Smckusick break; 239*41480Smckusick idstr[i+1] = 0; 240*41480Smckusick for (i = 7; i >= 0; --i) 241*41480Smckusick if (idstr[i] != ' ') 242*41480Smckusick break; 243*41480Smckusick idstr[i+1] = 0; 244*41480Smckusick printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], 245*41480Smckusick &idstr[24]); 246*41480Smckusick } 247*41480Smckusick printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 248*41480Smckusick if (sc->sc_blksize != DEV_BSIZE) { 249*41480Smckusick if (sc->sc_blksize < DEV_BSIZE) { 250*41480Smckusick printf("sd%d: need %d byte blocks - drive ignored\n", 251*41480Smckusick unit, DEV_BSIZE); 252*41480Smckusick return (-1); 253*41480Smckusick } 254*41480Smckusick for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 255*41480Smckusick ++sc->sc_bshift; 256*41480Smckusick sc->sc_blks <<= sc->sc_bshift; 257*41480Smckusick } 258*41480Smckusick sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 259*41480Smckusick return(inqbuf.type); 260*41480Smckusick } 261*41480Smckusick 262*41480Smckusick int 263*41480Smckusick sdinit(hd) 264*41480Smckusick register struct hp_device *hd; 265*41480Smckusick { 266*41480Smckusick register struct sd_softc *sc = &sd_softc[hd->hp_unit]; 267*41480Smckusick 268*41480Smckusick sc->sc_hd = hd; 269*41480Smckusick sc->sc_punit = sdpunit(hd->hp_flags); 270*41480Smckusick sc->sc_type = sdident(sc, hd); 271*41480Smckusick if (sc->sc_type < 0) 272*41480Smckusick return(0); 273*41480Smckusick sc->sc_dq.dq_ctlr = hd->hp_ctlr; 274*41480Smckusick sc->sc_dq.dq_unit = hd->hp_unit; 275*41480Smckusick sc->sc_dq.dq_slave = hd->hp_slave; 276*41480Smckusick sc->sc_dq.dq_driver = &sddriver; 277*41480Smckusick 278*41480Smckusick /* 279*41480Smckusick * If we don't have a disk label, build a default partition 280*41480Smckusick * table with 'standard' size root & swap and everything else 281*41480Smckusick * in the G partition. 282*41480Smckusick */ 283*41480Smckusick sc->sc_info = sddefaultpart; 284*41480Smckusick /* C gets everything */ 285*41480Smckusick sc->sc_info.part[2].nblocks = sc->sc_blks; 286*41480Smckusick sc->sc_info.part[2].endblk = sc->sc_blks; 287*41480Smckusick /* G gets from end of B to end of disk */ 288*41480Smckusick sc->sc_info.part[6].nblocks = sc->sc_blks - sc->sc_info.part[1].endblk; 289*41480Smckusick sc->sc_info.part[6].endblk = sc->sc_blks; 290*41480Smckusick /* 291*41480Smckusick * We also define the D, E and F paritions as an alternative to 292*41480Smckusick * B and G. D is 48Mb, starts after A and is intended for swapping. 293*41480Smckusick * E is 50Mb, starts after D and is intended for /usr. F starts 294*41480Smckusick * after E and is what ever is left. 295*41480Smckusick */ 296*41480Smckusick if (sc->sc_blks >= sc->sc_info.part[4].endblk) { 297*41480Smckusick sc->sc_info.part[5].nblocks = 298*41480Smckusick sc->sc_blks - sc->sc_info.part[4].endblk; 299*41480Smckusick sc->sc_info.part[5].endblk = sc->sc_blks; 300*41480Smckusick } else { 301*41480Smckusick sc->sc_info.part[5].strtblk = 0; 302*41480Smckusick sc->sc_info.part[3] = sc->sc_info.part[5]; 303*41480Smckusick sc->sc_info.part[4] = sc->sc_info.part[5]; 304*41480Smckusick } 305*41480Smckusick /* 306*41480Smckusick * H is a single partition alternative to E and F. 307*41480Smckusick */ 308*41480Smckusick if (sc->sc_blks >= sc->sc_info.part[3].endblk) { 309*41480Smckusick sc->sc_info.part[7].nblocks = 310*41480Smckusick sc->sc_blks - sc->sc_info.part[3].endblk; 311*41480Smckusick sc->sc_info.part[7].endblk = sc->sc_blks; 312*41480Smckusick } else { 313*41480Smckusick sc->sc_info.part[7].strtblk = 0; 314*41480Smckusick } 315*41480Smckusick 316*41480Smckusick sc->sc_flags = SDF_ALIVE; 317*41480Smckusick return(1); 318*41480Smckusick } 319*41480Smckusick 320*41480Smckusick void 321*41480Smckusick sdreset(sc, hd) 322*41480Smckusick register struct sd_softc *sc; 323*41480Smckusick register struct hp_device *hd; 324*41480Smckusick { 325*41480Smckusick sdstats[hd->hp_unit].sdresets++; 326*41480Smckusick } 327*41480Smckusick 328*41480Smckusick int 329*41480Smckusick sdopen(dev, flags) 330*41480Smckusick dev_t dev; 331*41480Smckusick int flags; 332*41480Smckusick { 333*41480Smckusick register int unit = sdunit(dev); 334*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 335*41480Smckusick 336*41480Smckusick if (unit >= NSD) 337*41480Smckusick return(ENXIO); 338*41480Smckusick if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(u.u_cred, &u.u_acflag)) 339*41480Smckusick return(ENXIO); 340*41480Smckusick 341*41480Smckusick if (sc->sc_hd->hp_dk >= 0) 342*41480Smckusick dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; 343*41480Smckusick return(0); 344*41480Smckusick } 345*41480Smckusick 346*41480Smckusick /* 347*41480Smckusick * This routine is called for partial block transfers and non-aligned 348*41480Smckusick * transfers (the latter only being possible on devices with a block size 349*41480Smckusick * larger than DEV_BSIZE). The operation is performed in three steps 350*41480Smckusick * using a locally allocated buffer: 351*41480Smckusick * 1. transfer any initial partial block 352*41480Smckusick * 2. transfer full blocks 353*41480Smckusick * 3. transfer any final partial block 354*41480Smckusick */ 355*41480Smckusick static void 356*41480Smckusick sdlblkstrat(bp, bsize) 357*41480Smckusick register struct buf *bp; 358*41480Smckusick register int bsize; 359*41480Smckusick { 360*41480Smckusick register struct buf *cbp = (struct buf *)malloc(sizeof(struct buf), 361*41480Smckusick M_DEVBUF, M_WAITOK); 362*41480Smckusick caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); 363*41480Smckusick register int bn, resid; 364*41480Smckusick register caddr_t addr; 365*41480Smckusick 366*41480Smckusick bzero((caddr_t)cbp, sizeof(*cbp)); 367*41480Smckusick cbp->b_proc = u.u_procp; 368*41480Smckusick cbp->b_dev = bp->b_dev; 369*41480Smckusick bn = bp->b_blkno; 370*41480Smckusick resid = bp->b_bcount; 371*41480Smckusick addr = bp->b_un.b_addr; 372*41480Smckusick #ifdef DEBUG 373*41480Smckusick if (sddebug & SDB_PARTIAL) 374*41480Smckusick printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", 375*41480Smckusick bp, bp->b_flags, bn, resid, addr); 376*41480Smckusick #endif 377*41480Smckusick 378*41480Smckusick while (resid > 0) { 379*41480Smckusick register int boff = dbtob(bn) & (bsize - 1); 380*41480Smckusick register int count; 381*41480Smckusick 382*41480Smckusick if (boff || resid < bsize) { 383*41480Smckusick sdstats[sdunit(bp->b_dev)].sdpartials++; 384*41480Smckusick count = MIN(resid, bsize - boff); 385*41480Smckusick cbp->b_flags = B_BUSY | B_PHYS | B_READ; 386*41480Smckusick cbp->b_blkno = bn - btodb(boff); 387*41480Smckusick cbp->b_un.b_addr = cbuf; 388*41480Smckusick cbp->b_bcount = bsize; 389*41480Smckusick #ifdef DEBUG 390*41480Smckusick if (sddebug & SDB_PARTIAL) 391*41480Smckusick printf(" readahead: bn %x cnt %x off %x addr %x\n", 392*41480Smckusick cbp->b_blkno, count, boff, addr); 393*41480Smckusick #endif 394*41480Smckusick sdstrategy(cbp); 395*41480Smckusick biowait(cbp); 396*41480Smckusick if (cbp->b_flags & B_ERROR) { 397*41480Smckusick bp->b_flags |= B_ERROR; 398*41480Smckusick bp->b_error = cbp->b_error; 399*41480Smckusick break; 400*41480Smckusick } 401*41480Smckusick if (bp->b_flags & B_READ) { 402*41480Smckusick bcopy(&cbuf[boff], addr, count); 403*41480Smckusick goto done; 404*41480Smckusick } 405*41480Smckusick bcopy(addr, &cbuf[boff], count); 406*41480Smckusick #ifdef DEBUG 407*41480Smckusick if (sddebug & SDB_PARTIAL) 408*41480Smckusick printf(" writeback: bn %x cnt %x off %x addr %x\n", 409*41480Smckusick cbp->b_blkno, count, boff, addr); 410*41480Smckusick #endif 411*41480Smckusick } else { 412*41480Smckusick count = resid & ~(bsize - 1); 413*41480Smckusick cbp->b_blkno = bn; 414*41480Smckusick cbp->b_un.b_addr = addr; 415*41480Smckusick cbp->b_bcount = count; 416*41480Smckusick #ifdef DEBUG 417*41480Smckusick if (sddebug & SDB_PARTIAL) 418*41480Smckusick printf(" fulltrans: bn %x cnt %x addr %x\n", 419*41480Smckusick cbp->b_blkno, count, addr); 420*41480Smckusick #endif 421*41480Smckusick } 422*41480Smckusick cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ); 423*41480Smckusick sdstrategy(cbp); 424*41480Smckusick biowait(cbp); 425*41480Smckusick if (cbp->b_flags & B_ERROR) { 426*41480Smckusick bp->b_flags |= B_ERROR; 427*41480Smckusick bp->b_error = cbp->b_error; 428*41480Smckusick break; 429*41480Smckusick } 430*41480Smckusick done: 431*41480Smckusick bn += btodb(count); 432*41480Smckusick resid -= count; 433*41480Smckusick addr += count; 434*41480Smckusick #ifdef DEBUG 435*41480Smckusick if (sddebug & SDB_PARTIAL) 436*41480Smckusick printf(" done: bn %x resid %x addr %x\n", 437*41480Smckusick bn, resid, addr); 438*41480Smckusick #endif 439*41480Smckusick } 440*41480Smckusick free(cbuf, M_DEVBUF); 441*41480Smckusick free(cbp, M_DEVBUF); 442*41480Smckusick } 443*41480Smckusick 444*41480Smckusick void 445*41480Smckusick sdstrategy(bp) 446*41480Smckusick register struct buf *bp; 447*41480Smckusick { 448*41480Smckusick register int part = sdpart(bp->b_dev); 449*41480Smckusick register int unit = sdunit(bp->b_dev); 450*41480Smckusick register int bn, sz; 451*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 452*41480Smckusick register struct buf *dp = &sdtab[unit]; 453*41480Smckusick register int s; 454*41480Smckusick 455*41480Smckusick if (sc->sc_format_pid) { 456*41480Smckusick if (sc->sc_format_pid != u.u_procp->p_pid) { 457*41480Smckusick bp->b_error = EPERM; 458*41480Smckusick goto bad; 459*41480Smckusick } 460*41480Smckusick bp->b_cylin = 0; 461*41480Smckusick } else { 462*41480Smckusick bn = bp->b_blkno; 463*41480Smckusick sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT; 464*41480Smckusick if (bn < 0 || bn + sz > sc->sc_info.part[part].nblocks) { 465*41480Smckusick if (bn == sc->sc_info.part[part].nblocks) { 466*41480Smckusick bp->b_resid = bp->b_bcount; 467*41480Smckusick goto done; 468*41480Smckusick } 469*41480Smckusick bp->b_error = EINVAL; 470*41480Smckusick goto bad; 471*41480Smckusick } 472*41480Smckusick /* 473*41480Smckusick * Non-aligned or partial-block transfers handled specially. 474*41480Smckusick */ 475*41480Smckusick s = sc->sc_blksize - 1; 476*41480Smckusick if ((dbtob(bn) & s) || (bp->b_bcount & s)) { 477*41480Smckusick sdlblkstrat(bp, sc->sc_blksize); 478*41480Smckusick goto done; 479*41480Smckusick } 480*41480Smckusick bp->b_cylin = (bn + sc->sc_info.part[part].strtblk) >> 481*41480Smckusick sc->sc_bshift; 482*41480Smckusick } 483*41480Smckusick s = splbio(); 484*41480Smckusick disksort(dp, bp); 485*41480Smckusick if (dp->b_active == 0) { 486*41480Smckusick dp->b_active = 1; 487*41480Smckusick sdustart(unit); 488*41480Smckusick } 489*41480Smckusick splx(s); 490*41480Smckusick return; 491*41480Smckusick bad: 492*41480Smckusick bp->b_flags |= B_ERROR; 493*41480Smckusick done: 494*41480Smckusick iodone(bp); 495*41480Smckusick } 496*41480Smckusick 497*41480Smckusick void 498*41480Smckusick sdustart(unit) 499*41480Smckusick register int unit; 500*41480Smckusick { 501*41480Smckusick if (scsireq(&sd_softc[unit].sc_dq)) 502*41480Smckusick sdstart(unit); 503*41480Smckusick } 504*41480Smckusick 505*41480Smckusick static void 506*41480Smckusick sderror(unit, sc, hp, stat) 507*41480Smckusick int unit, stat; 508*41480Smckusick register struct sd_softc *sc; 509*41480Smckusick register struct hp_device *hp; 510*41480Smckusick { 511*41480Smckusick sdsense[unit].status = stat; 512*41480Smckusick if (stat & STS_CHECKCOND) { 513*41480Smckusick struct scsi_xsense *sp; 514*41480Smckusick 515*41480Smckusick scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 516*41480Smckusick sc->sc_punit, sdsense[unit].sense, 517*41480Smckusick sizeof(sdsense[unit].sense)); 518*41480Smckusick sp = (struct scsi_xsense *)sdsense[unit].sense; 519*41480Smckusick printf("sd%d: scsi sense class %d, code %d", unit, 520*41480Smckusick sp->class, sp->code); 521*41480Smckusick if (sp->class == 7) { 522*41480Smckusick printf(", key %d", sp->key); 523*41480Smckusick if (sp->valid) 524*41480Smckusick printf(", blk %d", *(int *)&sp->info1); 525*41480Smckusick } 526*41480Smckusick printf("\n"); 527*41480Smckusick } 528*41480Smckusick } 529*41480Smckusick 530*41480Smckusick static void 531*41480Smckusick sdfinish(unit, sc, bp) 532*41480Smckusick int unit; 533*41480Smckusick register struct sd_softc *sc; 534*41480Smckusick register struct buf *bp; 535*41480Smckusick { 536*41480Smckusick sdtab[unit].b_errcnt = 0; 537*41480Smckusick sdtab[unit].b_actf = bp->b_actf; 538*41480Smckusick bp->b_resid = 0; 539*41480Smckusick iodone(bp); 540*41480Smckusick scsifree(&sc->sc_dq); 541*41480Smckusick if (sdtab[unit].b_actf) 542*41480Smckusick sdustart(unit); 543*41480Smckusick else 544*41480Smckusick sdtab[unit].b_active = 0; 545*41480Smckusick } 546*41480Smckusick 547*41480Smckusick void 548*41480Smckusick sdstart(unit) 549*41480Smckusick register int unit; 550*41480Smckusick { 551*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 552*41480Smckusick register struct hp_device *hp = sc->sc_hd; 553*41480Smckusick 554*41480Smckusick /* 555*41480Smckusick * we have the SCSI bus -- in format mode, we may or may not need dma 556*41480Smckusick * so check now. 557*41480Smckusick */ 558*41480Smckusick if (sc->sc_format_pid && legal_cmds[sdcmd[unit].cdb[0]] > 0) { 559*41480Smckusick register struct buf *bp = sdtab[unit].b_actf; 560*41480Smckusick register int sts; 561*41480Smckusick 562*41480Smckusick sts = scsi_immed_command(hp->hp_ctlr, hp->hp_slave, 563*41480Smckusick sc->sc_punit, &sdcmd[unit], 564*41480Smckusick bp->b_un.b_addr, bp->b_bcount, 565*41480Smckusick bp->b_flags & B_READ); 566*41480Smckusick sdsense[unit].status = sts; 567*41480Smckusick if (sts & 0xfe) { 568*41480Smckusick sderror(unit, sc, hp, sts); 569*41480Smckusick bp->b_flags |= B_ERROR; 570*41480Smckusick bp->b_error = EIO; 571*41480Smckusick } 572*41480Smckusick sdfinish(unit, sc, bp); 573*41480Smckusick 574*41480Smckusick } else if (scsiustart(hp->hp_ctlr)) 575*41480Smckusick sdgo(unit); 576*41480Smckusick } 577*41480Smckusick 578*41480Smckusick void 579*41480Smckusick sdgo(unit) 580*41480Smckusick register int unit; 581*41480Smckusick { 582*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 583*41480Smckusick register struct hp_device *hp = sc->sc_hd; 584*41480Smckusick register struct buf *bp = sdtab[unit].b_actf; 585*41480Smckusick register int pad; 586*41480Smckusick register struct scsi_fmt_cdb *cmd; 587*41480Smckusick 588*41480Smckusick if (sc->sc_format_pid) { 589*41480Smckusick cmd = &sdcmd[unit]; 590*41480Smckusick pad = 0; 591*41480Smckusick } else { 592*41480Smckusick cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 593*41480Smckusick *(int *)(&cmd->cdb[2]) = bp->b_cylin; 594*41480Smckusick pad = howmany(bp->b_bcount, sc->sc_blksize); 595*41480Smckusick *(u_short *)(&cmd->cdb[7]) = pad; 596*41480Smckusick pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0; 597*41480Smckusick #ifdef DEBUG 598*41480Smckusick if (pad) 599*41480Smckusick printf("sd%d: partial block xfer -- %x bytes\n", 600*41480Smckusick unit, bp->b_bcount); 601*41480Smckusick #endif 602*41480Smckusick sdstats[unit].sdtransfers++; 603*41480Smckusick } 604*41480Smckusick if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) { 605*41480Smckusick if (hp->hp_dk >= 0) { 606*41480Smckusick dk_busy |= 1 << hp->hp_dk; 607*41480Smckusick ++dk_seek[hp->hp_dk]; 608*41480Smckusick ++dk_xfer[hp->hp_dk]; 609*41480Smckusick dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 610*41480Smckusick } 611*41480Smckusick return; 612*41480Smckusick } 613*41480Smckusick #ifdef DEBUG 614*41480Smckusick if (sddebug & SDB_ERROR) 615*41480Smckusick printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n", 616*41480Smckusick unit, bp->b_flags & B_READ? "read" : "write", 617*41480Smckusick bp->b_un.b_addr, bp->b_cylin, bp->b_bcount, 618*41480Smckusick sdtab[unit].b_errcnt); 619*41480Smckusick #endif 620*41480Smckusick bp->b_flags |= B_ERROR; 621*41480Smckusick bp->b_error = EIO; 622*41480Smckusick sdfinish(unit, sc, bp); 623*41480Smckusick } 624*41480Smckusick 625*41480Smckusick void 626*41480Smckusick sdintr(unit, stat) 627*41480Smckusick register int unit; 628*41480Smckusick int stat; 629*41480Smckusick { 630*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 631*41480Smckusick register struct buf *bp = sdtab[unit].b_actf; 632*41480Smckusick register struct hp_device *hp = sc->sc_hd; 633*41480Smckusick 634*41480Smckusick if (bp == NULL) { 635*41480Smckusick printf("sd%d: bp == NULL\n", unit); 636*41480Smckusick return; 637*41480Smckusick } 638*41480Smckusick if (hp->hp_dk >= 0) 639*41480Smckusick dk_busy &=~ (1 << hp->hp_dk); 640*41480Smckusick if (stat) { 641*41480Smckusick #ifdef DEBUG 642*41480Smckusick if (sddebug & SDB_ERROR) 643*41480Smckusick printf("sd%d: sdintr: bad scsi status 0x%x\n", 644*41480Smckusick unit, stat); 645*41480Smckusick #endif 646*41480Smckusick sderror(unit, sc, hp, stat); 647*41480Smckusick bp->b_flags |= B_ERROR; 648*41480Smckusick bp->b_error = EIO; 649*41480Smckusick } 650*41480Smckusick sdfinish(unit, sc, bp); 651*41480Smckusick } 652*41480Smckusick 653*41480Smckusick int 654*41480Smckusick sdread(dev, uio) 655*41480Smckusick dev_t dev; 656*41480Smckusick struct uio *uio; 657*41480Smckusick { 658*41480Smckusick register int unit = sdunit(dev); 659*41480Smckusick register int pid; 660*41480Smckusick 661*41480Smckusick if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid) 662*41480Smckusick return (EPERM); 663*41480Smckusick 664*41480Smckusick return(physio(sdstrategy, &sdbuf[unit], dev, B_READ, minphys, uio)); 665*41480Smckusick } 666*41480Smckusick 667*41480Smckusick int 668*41480Smckusick sdwrite(dev, uio) 669*41480Smckusick dev_t dev; 670*41480Smckusick struct uio *uio; 671*41480Smckusick { 672*41480Smckusick register int unit = sdunit(dev); 673*41480Smckusick register int pid; 674*41480Smckusick 675*41480Smckusick if ((pid = sd_softc[unit].sc_format_pid) && pid != u.u_procp->p_pid) 676*41480Smckusick return (EPERM); 677*41480Smckusick 678*41480Smckusick return(physio(sdstrategy, &sdbuf[unit], dev, B_WRITE, minphys, uio)); 679*41480Smckusick } 680*41480Smckusick 681*41480Smckusick int 682*41480Smckusick sdioctl(dev, cmd, data, flag) 683*41480Smckusick dev_t dev; 684*41480Smckusick int cmd; 685*41480Smckusick caddr_t data; 686*41480Smckusick int flag; 687*41480Smckusick { 688*41480Smckusick register int unit = sdunit(dev); 689*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 690*41480Smckusick 691*41480Smckusick switch (cmd) { 692*41480Smckusick default: 693*41480Smckusick return (EINVAL); 694*41480Smckusick 695*41480Smckusick case SDIOCSFORMAT: 696*41480Smckusick /* take this device into or out of "format" mode */ 697*41480Smckusick if (suser(u.u_cred, &u.u_acflag)) 698*41480Smckusick return(EPERM); 699*41480Smckusick 700*41480Smckusick if (*(int *)data) { 701*41480Smckusick if (sc->sc_format_pid) 702*41480Smckusick return (EPERM); 703*41480Smckusick sc->sc_format_pid = u.u_procp->p_pid; 704*41480Smckusick } else 705*41480Smckusick sc->sc_format_pid = 0; 706*41480Smckusick return (0); 707*41480Smckusick 708*41480Smckusick case SDIOCGFORMAT: 709*41480Smckusick /* find out who has the device in format mode */ 710*41480Smckusick *(int *)data = sc->sc_format_pid; 711*41480Smckusick return (0); 712*41480Smckusick 713*41480Smckusick case SDIOCSCSICOMMAND: 714*41480Smckusick /* 715*41480Smckusick * Save what user gave us as SCSI cdb to use with next 716*41480Smckusick * read or write to the char device. 717*41480Smckusick */ 718*41480Smckusick if (sc->sc_format_pid != u.u_procp->p_pid) 719*41480Smckusick return (EPERM); 720*41480Smckusick if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0) 721*41480Smckusick return (EINVAL); 722*41480Smckusick bcopy(data, (caddr_t)&sdcmd[unit], sizeof(sdcmd[0])); 723*41480Smckusick return (0); 724*41480Smckusick 725*41480Smckusick case SDIOCSENSE: 726*41480Smckusick /* 727*41480Smckusick * return the SCSI sense data saved after the last 728*41480Smckusick * operation that completed with "check condition" status. 729*41480Smckusick */ 730*41480Smckusick bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0])); 731*41480Smckusick return (0); 732*41480Smckusick 733*41480Smckusick } 734*41480Smckusick /*NOTREACHED*/ 735*41480Smckusick } 736*41480Smckusick 737*41480Smckusick int 738*41480Smckusick sdsize(dev) 739*41480Smckusick dev_t dev; 740*41480Smckusick { 741*41480Smckusick register int unit = sdunit(dev); 742*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 743*41480Smckusick 744*41480Smckusick if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 745*41480Smckusick return(-1); 746*41480Smckusick 747*41480Smckusick return(sc->sc_info.part[sdpart(dev)].nblocks); 748*41480Smckusick } 749*41480Smckusick 750*41480Smckusick #include "machine/pte.h" 751*41480Smckusick #include "machine/vmparam.h" 752*41480Smckusick #include "../h/vmmac.h" 753*41480Smckusick 754*41480Smckusick /* 755*41480Smckusick * Non-interrupt driven, non-dma dump routine. 756*41480Smckusick */ 757*41480Smckusick int 758*41480Smckusick sddump(dev) 759*41480Smckusick dev_t dev; 760*41480Smckusick { 761*41480Smckusick int part = sdpart(dev); 762*41480Smckusick int unit = sdunit(dev); 763*41480Smckusick register struct sd_softc *sc = &sd_softc[unit]; 764*41480Smckusick register struct hp_device *hp = sc->sc_hd; 765*41480Smckusick register daddr_t baddr; 766*41480Smckusick register int maddr; 767*41480Smckusick register int pages, i; 768*41480Smckusick int stat; 769*41480Smckusick extern int lowram; 770*41480Smckusick 771*41480Smckusick /* 772*41480Smckusick * Hmm... all vax drivers dump maxfree pages which is physmem minus 773*41480Smckusick * the message buffer. Is there a reason for not dumping the 774*41480Smckusick * message buffer? Savecore expects to read 'dumpsize' pages of 775*41480Smckusick * dump, where dumpsys() sets dumpsize to physmem! 776*41480Smckusick */ 777*41480Smckusick pages = physmem; 778*41480Smckusick 779*41480Smckusick /* is drive ok? */ 780*41480Smckusick if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 781*41480Smckusick return (ENXIO); 782*41480Smckusick /* dump parameters in range? */ 783*41480Smckusick if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks) 784*41480Smckusick return (EINVAL); 785*41480Smckusick if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks) 786*41480Smckusick pages = dtoc(sc->sc_info.part[part].nblocks - dumplo); 787*41480Smckusick maddr = lowram; 788*41480Smckusick baddr = dumplo + sc->sc_info.part[part].strtblk; 789*41480Smckusick /* scsi bus idle? */ 790*41480Smckusick if (!scsireq(&sc->sc_dq)) { 791*41480Smckusick scsireset(hp->hp_ctlr); 792*41480Smckusick sdreset(sc, sc->sc_hd); 793*41480Smckusick printf("[ drive %d reset ] ", unit); 794*41480Smckusick } 795*41480Smckusick for (i = 0; i < pages; i++) { 796*41480Smckusick #define NPGMB (1024*1024/NBPG) 797*41480Smckusick /* print out how many Mbs we have dumped */ 798*41480Smckusick if (i && (i % NPGMB) == 0) 799*41480Smckusick printf("%d ", i / NPGMB); 800*41480Smckusick #undef NPBMG 801*41480Smckusick mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V); 802*41480Smckusick stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, 803*41480Smckusick vmmap, NBPG, baddr, sc->sc_bshift); 804*41480Smckusick if (stat) { 805*41480Smckusick printf("sddump: scsi write error 0x%x\n", stat); 806*41480Smckusick return (EIO); 807*41480Smckusick } 808*41480Smckusick maddr += NBPG; 809*41480Smckusick baddr += ctod(1); 810*41480Smckusick } 811*41480Smckusick return (0); 812*41480Smckusick } 813*41480Smckusick #endif 814