1*56830Sralph /* 2*56830Sralph * Copyright (c) 1992 Regents of the University of California. 3*56830Sralph * All rights reserved. 4*56830Sralph * 5*56830Sralph * This code is derived from software contributed to Berkeley by 6*56830Sralph * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell. 7*56830Sralph * 8*56830Sralph * %sccs.include.redist.c% 9*56830Sralph * 10*56830Sralph * @(#)rz.c 7.1 (Berkeley) 11/15/92 11*56830Sralph */ 12*56830Sralph 13*56830Sralph /* 14*56830Sralph * SCSI CCS (Command Command Set) disk driver. 15*56830Sralph * NOTE: The name was changed from "sd" to "rz" for DEC naming compatibility. 16*56830Sralph * I guess I can't avoid confusion someplace. 17*56830Sralph */ 18*56830Sralph #include <pmax/stand/samachdep.h> 19*56830Sralph #if NRZ > 0 20*56830Sralph 21*56830Sralph #include <stand/stand.h> 22*56830Sralph #include <sys/param.h> 23*56830Sralph #include <sys/disklabel.h> 24*56830Sralph #include <pmax/dev/device.h> 25*56830Sralph #include <pmax/dev/scsi.h> 26*56830Sralph 27*56830Sralph void rzstart(), rzdone(); 28*56830Sralph 29*56830Sralph struct driver rzdriver = { 30*56830Sralph "rz", (int (*)())0, rzstart, rzdone, 31*56830Sralph }; 32*56830Sralph 33*56830Sralph struct rz_softc { 34*56830Sralph struct scsi_device sc_sd; /* physical unit info */ 35*56830Sralph u_short sc_part; /* disk partition number */ 36*56830Sralph u_short sc_type; /* drive type from INQUIRY cmd */ 37*56830Sralph u_int sc_blks; /* number of blocks on device */ 38*56830Sralph int sc_blksize; /* device block size in bytes */ 39*56830Sralph int sc_bshift; /* convert device blocks to DEV_BSIZE */ 40*56830Sralph struct disklabel sc_label; /* disk label for this disk */ 41*56830Sralph struct ScsiCmd sc_cmd; /* command for controller */ 42*56830Sralph ScsiGroup1Cmd sc_rwcmd; /* group 1 SCSI commands */ 43*56830Sralph struct scsi_fmt_sense sc_sense; /* sense data from last cmd */ 44*56830Sralph int sc_error; /* error code */ 45*56830Sralph int sc_resid; /* amount of data not transfered */ 46*56830Sralph }; 47*56830Sralph 48*56830Sralph volatile int done; 49*56830Sralph 50*56830Sralph int 51*56830Sralph rzstrategy(devdata, rw, bn, reqcnt, addr, cnt) 52*56830Sralph void *devdata; 53*56830Sralph int rw; 54*56830Sralph daddr_t bn; 55*56830Sralph u_int reqcnt; 56*56830Sralph char *addr; 57*56830Sralph u_int *cnt; /* out: number of bytes transfered */ 58*56830Sralph { 59*56830Sralph register struct rz_softc *sc = (struct rz_softc *)devdata; 60*56830Sralph register int part = sc->sc_part; 61*56830Sralph register struct partition *pp = &sc->sc_label.d_partitions[part]; 62*56830Sralph register int s; 63*56830Sralph long cylin; 64*56830Sralph 65*56830Sralph sc->sc_error = 0; 66*56830Sralph s = howmany(reqcnt, DEV_BSIZE); 67*56830Sralph if ((unsigned)bn + s > pp->p_size) { 68*56830Sralph s = pp->p_size - bn; 69*56830Sralph /* if exactly at end of disk, return an EOF */ 70*56830Sralph if (s == 0) { 71*56830Sralph *cnt = 0; 72*56830Sralph return (0); 73*56830Sralph } 74*56830Sralph /* if none of it fits, error */ 75*56830Sralph if (s < 0) { 76*56830Sralph *cnt = 0; 77*56830Sralph return (EINVAL); 78*56830Sralph } 79*56830Sralph /* otherwise, truncate */ 80*56830Sralph reqcnt = dbtob(s); 81*56830Sralph } 82*56830Sralph /* 83*56830Sralph * Non-aligned or partial-block transfers not handled. 84*56830Sralph */ 85*56830Sralph s = sc->sc_blksize - 1; 86*56830Sralph if ((dbtob(bn) & s) || (reqcnt & s)) { 87*56830Sralph *cnt = 0; 88*56830Sralph return (EINVAL); 89*56830Sralph } 90*56830Sralph cylin = (bn + pp->p_offset) >> sc->sc_bshift; 91*56830Sralph 92*56830Sralph sc->sc_cmd.buf = addr; 93*56830Sralph sc->sc_cmd.buflen = reqcnt; 94*56830Sralph sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 95*56830Sralph sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd); 96*56830Sralph 97*56830Sralph if (rw & F_READ) { 98*56830Sralph sc->sc_cmd.flags = 0; 99*56830Sralph sc->sc_rwcmd.command = SCSI_READ_EXT; 100*56830Sralph } else { 101*56830Sralph sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE; 102*56830Sralph sc->sc_rwcmd.command = SCSI_WRITE_EXT; 103*56830Sralph } 104*56830Sralph sc->sc_rwcmd.highAddr = cylin >> 24; 105*56830Sralph sc->sc_rwcmd.midHighAddr = cylin >> 16; 106*56830Sralph sc->sc_rwcmd.midLowAddr = cylin >> 8; 107*56830Sralph sc->sc_rwcmd.lowAddr = cylin; 108*56830Sralph s = howmany(reqcnt, sc->sc_blksize); 109*56830Sralph sc->sc_rwcmd.highBlockCount = s >> 8; 110*56830Sralph sc->sc_rwcmd.lowBlockCount = s; 111*56830Sralph 112*56830Sralph rzstart(sc); 113*56830Sralph 114*56830Sralph *cnt = reqcnt - sc->sc_resid; 115*56830Sralph return (sc->sc_error); 116*56830Sralph } 117*56830Sralph 118*56830Sralph void 119*56830Sralph rzstart(sc) 120*56830Sralph register struct rz_softc *sc; 121*56830Sralph { 122*56830Sralph ScsiGroup0Cmd reqcmd; 123*56830Sralph 124*56830Sralph /* tell controller to start this command */ 125*56830Sralph done = 0; 126*56830Sralph (*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd); 127*56830Sralph while (!done) 128*56830Sralph ; 129*56830Sralph 130*56830Sralph /* check for errors that need to be processed */ 131*56830Sralph if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) 132*56830Sralph return; 133*56830Sralph 134*56830Sralph /* start a REQUEST_SENSE command */ 135*56830Sralph scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd.sd_slave, 0, 136*56830Sralph sizeof(sc->sc_sense.sense), &reqcmd); 137*56830Sralph sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd); 138*56830Sralph sc->sc_cmd.cmd = (u_char *)&reqcmd; 139*56830Sralph sc->sc_cmd.buf = (char *)sc->sc_sense.sense; 140*56830Sralph sc->sc_cmd.buflen = sizeof(sc->sc_sense.sense); 141*56830Sralph sc->sc_cmd.flags = 0; 142*56830Sralph 143*56830Sralph /* tell controller to start this command */ 144*56830Sralph done = 0; 145*56830Sralph (*sc->sc_sd.sd_cdriver->d_start)(&sc->sc_cmd); 146*56830Sralph while (!done) 147*56830Sralph ; 148*56830Sralph 149*56830Sralph if (sc->sc_error || (sc->sc_sense.status & SCSI_STATUS_CHECKCOND)) { 150*56830Sralph printf("rz%d: error reading sense data: error %d scsi status 0x%x\n", 151*56830Sralph sc->sc_sd.sd_unit, sc->sc_error, sc->sc_sense.status); 152*56830Sralph /* 153*56830Sralph * We got an error during the REQUEST_SENSE, 154*56830Sralph * fill in no sense for data. 155*56830Sralph */ 156*56830Sralph sc->sc_sense.sense[0] = 0x70; 157*56830Sralph sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE; 158*56830Sralph } else { 159*56830Sralph printf("rz%d: ", sc->sc_sd.sd_unit); 160*56830Sralph scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense, 161*56830Sralph sizeof(sc->sc_sense.sense) - sc->sc_resid); 162*56830Sralph } 163*56830Sralph if (sc->sc_error == 0) 164*56830Sralph sc->sc_error = EIO; 165*56830Sralph } 166*56830Sralph 167*56830Sralph /* 168*56830Sralph * This is called by the controller driver when the command is done. 169*56830Sralph */ 170*56830Sralph void 171*56830Sralph rzdone(data, error, resid, status) 172*56830Sralph void *data; 173*56830Sralph int error; /* error number from errno.h */ 174*56830Sralph int resid; /* amount not transfered */ 175*56830Sralph int status; /* SCSI status byte */ 176*56830Sralph { 177*56830Sralph register struct rz_softc *sc = (struct rz_softc *)data; 178*56830Sralph 179*56830Sralph sc->sc_error = error; 180*56830Sralph sc->sc_resid = resid; 181*56830Sralph sc->sc_sense.status = status; 182*56830Sralph done = 1; 183*56830Sralph } 184*56830Sralph 185*56830Sralph int 186*56830Sralph rzopen(f, ctlr, unit, part) 187*56830Sralph struct open_file *f; 188*56830Sralph int ctlr, unit, part; 189*56830Sralph { 190*56830Sralph register struct rz_softc *sc; 191*56830Sralph register struct disklabel *lp; 192*56830Sralph register struct scsi_device *sd; 193*56830Sralph register int i; 194*56830Sralph char *msg; 195*56830Sralph ScsiGroup0Cmd inqcmd; 196*56830Sralph ScsiInquiryData inqbuf; 197*56830Sralph u_char capbuf[8]; 198*56830Sralph char buf[DEV_BSIZE]; 199*56830Sralph int cnt; 200*56830Sralph struct driver *scsi_driver; 201*56830Sralph 202*56830Sralph if (unit >= NRZ || part >= MAXPARTITIONS) 203*56830Sralph return (ENXIO); 204*56830Sralph #ifdef DS3100 205*56830Sralph if (ctlr >= NSII) 206*56830Sralph return (ENXIO); 207*56830Sralph else { 208*56830Sralph extern struct driver siidriver; 209*56830Sralph 210*56830Sralph scsi_driver = &siidriver; 211*56830Sralph } 212*56830Sralph #endif 213*56830Sralph #ifdef DS5000 214*56830Sralph { 215*56830Sralph struct pmax_ctlr *cp, *tc_ctlr __P((int, int)); 216*56830Sralph 217*56830Sralph cp = tc_ctlr(ctlr, TC_SCSI); 218*56830Sralph if (!cp) 219*56830Sralph return (ENXIO); 220*56830Sralph ctlr = cp->pmax_unit; /* convert from slot # to controller unit */ 221*56830Sralph scsi_driver = cp->pmax_driver; 222*56830Sralph } 223*56830Sralph #endif 224*56830Sralph 225*56830Sralph sc = alloc(sizeof(struct rz_softc)); 226*56830Sralph bzero(sc, sizeof(struct rz_softc)); 227*56830Sralph f->f_devdata = (void *)sc; 228*56830Sralph 229*56830Sralph sc->sc_sd.sd_driver = &rzdriver; 230*56830Sralph sc->sc_sd.sd_cdriver = scsi_driver; 231*56830Sralph sc->sc_sd.sd_unit = unit; 232*56830Sralph sc->sc_sd.sd_ctlr = ctlr; 233*56830Sralph sc->sc_sd.sd_drive = unit; 234*56830Sralph sc->sc_sd.sd_slave = 0; 235*56830Sralph sc->sc_sd.sd_flags = 0; 236*56830Sralph sc->sc_sd.sd_alive = 1; 237*56830Sralph sc->sc_part = part; 238*56830Sralph 239*56830Sralph /* init fields that don't change */ 240*56830Sralph sc->sc_cmd.sd = sd = &sc->sc_sd; 241*56830Sralph sc->sc_cmd.unit = (int)sc; 242*56830Sralph 243*56830Sralph /* 244*56830Sralph * Try to find out what type of device this is. 245*56830Sralph */ 246*56830Sralph scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), &inqcmd); 247*56830Sralph sc->sc_cmd.cmdlen = sizeof(ScsiGroup0Cmd); 248*56830Sralph sc->sc_cmd.cmd = (u_char *)&inqcmd; 249*56830Sralph sc->sc_cmd.buflen = sizeof(inqbuf); 250*56830Sralph sc->sc_cmd.buf = (char *)&inqbuf; 251*56830Sralph sc->sc_cmd.flags = 0; 252*56830Sralph 253*56830Sralph /* tell controller to start this command */ 254*56830Sralph rzstart(sc); 255*56830Sralph 256*56830Sralph if (sc->sc_error || (i = sizeof(inqbuf) - sc->sc_resid) < 5) 257*56830Sralph goto bad; 258*56830Sralph switch (inqbuf.type) { 259*56830Sralph case SCSI_DISK_TYPE: /* disk */ 260*56830Sralph case SCSI_WORM_TYPE: /* WORM */ 261*56830Sralph case SCSI_ROM_TYPE: /* CD-ROM */ 262*56830Sralph case SCSI_OPTICAL_MEM_TYPE: /* Magneto-optical */ 263*56830Sralph break; 264*56830Sralph 265*56830Sralph default: /* not a disk */ 266*56830Sralph goto bad; 267*56830Sralph } 268*56830Sralph sc->sc_type = inqbuf.type; 269*56830Sralph 270*56830Sralph /* find out how big a disk this is */ 271*56830Sralph scsiGroup1Cmd(SCSI_READ_CAPACITY, sd->sd_slave, 0, 0, &sc->sc_rwcmd); 272*56830Sralph sc->sc_cmd.cmdlen = sizeof(ScsiGroup1Cmd); 273*56830Sralph sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 274*56830Sralph sc->sc_cmd.buflen = sizeof(capbuf); 275*56830Sralph sc->sc_cmd.buf = (char *)capbuf; 276*56830Sralph sc->sc_cmd.flags = 0; 277*56830Sralph 278*56830Sralph rzstart(sc); 279*56830Sralph 280*56830Sralph if (sc->sc_error || sc->sc_resid != 0) 281*56830Sralph goto bad; 282*56830Sralph sc->sc_blks = ((capbuf[0] << 24) | (capbuf[1] << 16) | 283*56830Sralph (capbuf[2] << 8) | capbuf[3]) + 1; 284*56830Sralph sc->sc_blksize = (capbuf[4] << 24) | (capbuf[5] << 16) | 285*56830Sralph (capbuf[6] << 8) | capbuf[7]; 286*56830Sralph 287*56830Sralph #if 0 288*56830Sralph printf("rz%d at %s%d drive %d slave %d", sd->sd_unit, 289*56830Sralph sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive, 290*56830Sralph sd->sd_slave); 291*56830Sralph if (inqbuf.version > 1 || i < 36) 292*56830Sralph printf(" type 0x%x, qual 0x%x, ver %d", 293*56830Sralph inqbuf.type, inqbuf.qualifier, inqbuf.version); 294*56830Sralph else { 295*56830Sralph char vid[9], pid[17], revl[5]; 296*56830Sralph 297*56830Sralph bcopy((caddr_t)inqbuf.vendorID, (caddr_t)vid, 8); 298*56830Sralph bcopy((caddr_t)inqbuf.productID, (caddr_t)pid, 16); 299*56830Sralph bcopy((caddr_t)inqbuf.revLevel, (caddr_t)revl, 4); 300*56830Sralph for (i = 8; --i > 0; ) 301*56830Sralph if (vid[i] != ' ') 302*56830Sralph break; 303*56830Sralph vid[i+1] = 0; 304*56830Sralph for (i = 16; --i > 0; ) 305*56830Sralph if (pid[i] != ' ') 306*56830Sralph break; 307*56830Sralph pid[i+1] = 0; 308*56830Sralph for (i = 4; --i > 0; ) 309*56830Sralph if (revl[i] != ' ') 310*56830Sralph break; 311*56830Sralph revl[i+1] = 0; 312*56830Sralph printf(" %s %s rev %s", vid, pid, revl); 313*56830Sralph } 314*56830Sralph printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 315*56830Sralph #endif 316*56830Sralph 317*56830Sralph if (sc->sc_blksize != DEV_BSIZE) { 318*56830Sralph if (sc->sc_blksize < DEV_BSIZE) { 319*56830Sralph printf("rz%d: need %d byte blocks - drive ignored\n", 320*56830Sralph unit, DEV_BSIZE); 321*56830Sralph goto bad; 322*56830Sralph } 323*56830Sralph for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 324*56830Sralph ++sc->sc_bshift; 325*56830Sralph sc->sc_blks <<= sc->sc_bshift; 326*56830Sralph } 327*56830Sralph 328*56830Sralph /* try to read disk label and partition table information */ 329*56830Sralph lp = &sc->sc_label; 330*56830Sralph lp->d_secsize = DEV_BSIZE; 331*56830Sralph lp->d_secpercyl = 1 << sc->sc_bshift; 332*56830Sralph lp->d_npartitions = MAXPARTITIONS; 333*56830Sralph lp->d_partitions[part].p_offset = 0; 334*56830Sralph lp->d_partitions[part].p_size = sc->sc_blks; 335*56830Sralph i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt); 336*56830Sralph if (i || cnt != DEV_BSIZE) { 337*56830Sralph printf("rz%d: error reading disk label\n", unit); 338*56830Sralph goto bad; 339*56830Sralph } else { 340*56830Sralph msg = getdisklabel(buf, lp); 341*56830Sralph if (msg) { 342*56830Sralph printf("rz%d: %s\n", unit, msg); 343*56830Sralph goto bad; 344*56830Sralph } 345*56830Sralph } 346*56830Sralph 347*56830Sralph if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) { 348*56830Sralph bad: 349*56830Sralph free(sc, sizeof(struct rz_softc)); 350*56830Sralph return (ENXIO); 351*56830Sralph } 352*56830Sralph return (0); 353*56830Sralph } 354*56830Sralph 355*56830Sralph rzclose(f) 356*56830Sralph struct open_file *f; 357*56830Sralph { 358*56830Sralph free(f->f_devdata, sizeof(struct rz_softc)); 359*56830Sralph f->f_devdata = (void *)0; 360*56830Sralph return (0); 361*56830Sralph } 362*56830Sralph #endif 363