1*53931Shibler /* 2*53931Shibler * Copyright (c) 1991 University of Utah. 3*53931Shibler * Copyright (c) 1990 The Regents of the University of California. 4*53931Shibler * All rights reserved. 5*53931Shibler * 6*53931Shibler * This code is derived from software contributed to Berkeley by 7*53931Shibler * the Systems Programming Group of the University of Utah Computer 8*53931Shibler * Science Department. 9*53931Shibler * 10*53931Shibler * %sccs.include.redist.c% 11*53931Shibler * 12*53931Shibler * from: Utah $Hdr: ac.c 1.5 92/01/21$ 13*53931Shibler * 14*53931Shibler * @(#)ac.c 7.1 (Berkeley) 06/05/92 15*53931Shibler */ 16*53931Shibler 17*53931Shibler /* 18*53931Shibler * SCSI driver for MO autochanger. 19*53931Shibler * 20*53931Shibler * Very crude. Because of the lack of connect/disconnect support in the 21*53931Shibler * scsi driver, this driver can tie up the SCSI bus for a long time. It 22*53931Shibler * also grabs a DMA channel and holds it for the duration even though it 23*53931Shibler * never uses it. 24*53931Shibler */ 25*53931Shibler 26*53931Shibler #include "ac.h" 27*53931Shibler #if NAC > 0 28*53931Shibler 29*53931Shibler #include "param.h" 30*53931Shibler #include "buf.h" 31*53931Shibler #include "errno.h" 32*53931Shibler #include "user.h" 33*53931Shibler #include "ioctl.h" 34*53931Shibler #include "kernel.h" 35*53931Shibler #include "malloc.h" 36*53931Shibler 37*53931Shibler #include "hp/dev/device.h" 38*53931Shibler #include "scsireg.h" 39*53931Shibler #include "acioctl.h" 40*53931Shibler #include "acvar.h" 41*53931Shibler 42*53931Shibler extern int scsi_test_unit_rdy(); 43*53931Shibler extern int scsi_request_sense(); 44*53931Shibler extern int scsiustart(); 45*53931Shibler extern int scsigo(); 46*53931Shibler extern void scsifree(); 47*53931Shibler extern void scsireset(); 48*53931Shibler extern void scsi_delay(); 49*53931Shibler 50*53931Shibler extern int scsi_immed_command(); 51*53931Shibler 52*53931Shibler int acinit(), acstart(), acgo(), acintr(); 53*53931Shibler 54*53931Shibler struct driver acdriver = { 55*53931Shibler acinit, "ac", acstart, acgo, acintr, 56*53931Shibler }; 57*53931Shibler 58*53931Shibler struct ac_softc ac_softc[NAC]; 59*53931Shibler static struct buf acbuf[NAC]; 60*53931Shibler static struct scsi_fmt_cdb accmd[NAC]; 61*53931Shibler 62*53931Shibler #ifdef DEBUG 63*53931Shibler int ac_debug = 0x0000; 64*53931Shibler #define ACD_FOLLOW 0x0001 65*53931Shibler #define ACD_OPEN 0x0002 66*53931Shibler #endif 67*53931Shibler 68*53931Shibler acinit(hd) 69*53931Shibler register struct hp_device *hd; 70*53931Shibler { 71*53931Shibler int unit = hd->hp_unit; 72*53931Shibler register struct ac_softc *sc = &ac_softc[unit]; 73*53931Shibler 74*53931Shibler sc->sc_hd = hd; 75*53931Shibler sc->sc_punit = hd->hp_flags & 7; 76*53931Shibler if (acident(sc, hd) < 0) 77*53931Shibler return(0); 78*53931Shibler sc->sc_dq.dq_unit = unit; 79*53931Shibler sc->sc_dq.dq_ctlr = hd->hp_ctlr; 80*53931Shibler sc->sc_dq.dq_slave = hd->hp_slave; 81*53931Shibler sc->sc_dq.dq_driver = &acdriver; 82*53931Shibler sc->sc_bp = &acbuf[unit]; 83*53931Shibler sc->sc_cmd = &accmd[unit]; 84*53931Shibler sc->sc_flags = ACF_ALIVE; 85*53931Shibler return(1); 86*53931Shibler } 87*53931Shibler 88*53931Shibler acident(sc, hd) 89*53931Shibler register struct ac_softc *sc; 90*53931Shibler register struct hp_device *hd; 91*53931Shibler { 92*53931Shibler int unit; 93*53931Shibler register int ctlr, slave; 94*53931Shibler int i, stat; 95*53931Shibler int tries = 5; 96*53931Shibler char idstr[32]; 97*53931Shibler struct scsi_inquiry inqbuf; 98*53931Shibler static struct scsi_fmt_cdb inq = { 99*53931Shibler 6, 100*53931Shibler CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 101*53931Shibler }; 102*53931Shibler 103*53931Shibler ctlr = hd->hp_ctlr; 104*53931Shibler slave = hd->hp_slave; 105*53931Shibler unit = sc->sc_punit; 106*53931Shibler scsi_delay(-1); 107*53931Shibler 108*53931Shibler /* 109*53931Shibler * See if device is ready 110*53931Shibler */ 111*53931Shibler while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 112*53931Shibler if (i == -1 || --tries < 0) 113*53931Shibler /* doesn't exist or not a CCS device */ 114*53931Shibler goto failed; 115*53931Shibler if (i == STS_CHECKCOND) { 116*53931Shibler u_char sensebuf[128]; 117*53931Shibler struct scsi_xsense *sp; 118*53931Shibler 119*53931Shibler scsi_request_sense(ctlr, slave, unit, 120*53931Shibler sensebuf, sizeof(sensebuf)); 121*53931Shibler sp = (struct scsi_xsense *) sensebuf; 122*53931Shibler if (sp->class == 7 && sp->key == 6) 123*53931Shibler /* drive doing an RTZ -- give it a while */ 124*53931Shibler DELAY(1000000); 125*53931Shibler } 126*53931Shibler DELAY(1000); 127*53931Shibler } 128*53931Shibler /* 129*53931Shibler * Find out if it is an autochanger 130*53931Shibler */ 131*53931Shibler if (scsi_immed_command(ctlr, slave, unit, &inq, 132*53931Shibler (u_char *)&inqbuf, sizeof(inqbuf), B_READ)) 133*53931Shibler goto failed; 134*53931Shibler 135*53931Shibler if (inqbuf.type != 8 || inqbuf.qual != 0x80 || inqbuf.version != 2) 136*53931Shibler goto failed; 137*53931Shibler 138*53931Shibler bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 139*53931Shibler for (i = 27; i > 23; --i) 140*53931Shibler if (idstr[i] != ' ') 141*53931Shibler break; 142*53931Shibler idstr[i+1] = 0; 143*53931Shibler for (i = 23; i > 7; --i) 144*53931Shibler if (idstr[i] != ' ') 145*53931Shibler break; 146*53931Shibler idstr[i+1] = 0; 147*53931Shibler for (i = 7; i >= 0; --i) 148*53931Shibler if (idstr[i] != ' ') 149*53931Shibler break; 150*53931Shibler idstr[i+1] = 0; 151*53931Shibler printf("ac%d: %s %s rev %s\n", hd->hp_unit, 152*53931Shibler &idstr[0], &idstr[8], &idstr[24]); 153*53931Shibler 154*53931Shibler scsi_delay(0); 155*53931Shibler return(inqbuf.type); 156*53931Shibler failed: 157*53931Shibler scsi_delay(0); 158*53931Shibler return(-1); 159*53931Shibler } 160*53931Shibler 161*53931Shibler /*ARGSUSED*/ 162*53931Shibler acopen(dev, flag, mode, p) 163*53931Shibler dev_t dev; 164*53931Shibler int flag, mode; 165*53931Shibler struct proc *p; 166*53931Shibler { 167*53931Shibler register int unit = minor(dev); 168*53931Shibler register struct ac_softc *sc = &ac_softc[unit]; 169*53931Shibler int error = 0; 170*53931Shibler 171*53931Shibler if (unit >= NAC || (sc->sc_flags & ACF_ALIVE) == 0) 172*53931Shibler error = ENXIO; 173*53931Shibler else if (sc->sc_flags & ACF_OPEN) 174*53931Shibler error = EBUSY; 175*53931Shibler else if (acgeteinfo(dev)) 176*53931Shibler error = EIO; 177*53931Shibler else 178*53931Shibler sc->sc_flags |= ACF_OPEN; 179*53931Shibler return(error); 180*53931Shibler } 181*53931Shibler 182*53931Shibler /*ARGSUSED*/ 183*53931Shibler acclose(dev, flag, mode, p) 184*53931Shibler dev_t dev; 185*53931Shibler int flag, mode; 186*53931Shibler struct proc *p; 187*53931Shibler { 188*53931Shibler struct ac_softc *sc = &ac_softc[minor(dev)]; 189*53931Shibler 190*53931Shibler sc->sc_flags &= ~ACF_OPEN; 191*53931Shibler } 192*53931Shibler 193*53931Shibler #define ACRESLEN(ep) \ 194*53931Shibler (8 + (ep)->nmte*12 + (ep)->nse*12 + (ep)->niee*12 + (ep)->ndte*20) 195*53931Shibler 196*53931Shibler /*ARGSUSED*/ 197*53931Shibler acioctl(dev, cmd, data, flag, p) 198*53931Shibler dev_t dev; 199*53931Shibler int cmd; 200*53931Shibler caddr_t data; 201*53931Shibler int flag; 202*53931Shibler struct proc *p; 203*53931Shibler { 204*53931Shibler register struct ac_softc *sc = &ac_softc[minor(dev)]; 205*53931Shibler char *dp; 206*53931Shibler int dlen, error = 0; 207*53931Shibler 208*53931Shibler switch (cmd) { 209*53931Shibler 210*53931Shibler default: 211*53931Shibler return (EINVAL); 212*53931Shibler 213*53931Shibler /* perform an init element status and mode sense to reset state */ 214*53931Shibler case ACIOCINIT: 215*53931Shibler error = accommand(dev, ACCMD_INITES, (caddr_t)0, 0); 216*53931Shibler if (!error) 217*53931Shibler error = acgeteinfo(dev); 218*53931Shibler break; 219*53931Shibler 220*53931Shibler /* copy internal element information */ 221*53931Shibler case ACIOCGINFO: 222*53931Shibler *(struct acinfo *)data = sc->sc_einfo; 223*53931Shibler break; 224*53931Shibler 225*53931Shibler case ACIOCRAWES: 226*53931Shibler { 227*53931Shibler struct acbuffer *acbp = (struct acbuffer *)data; 228*53931Shibler 229*53931Shibler dlen = ACRESLEN(&sc->sc_einfo); 230*53931Shibler dp = (char *) malloc(dlen, M_DEVBUF, M_WAITOK); 231*53931Shibler error = accommand(dev, ACCMD_READES, dp, dlen); 232*53931Shibler if (!error) { 233*53931Shibler dlen = *(int *)&dp[4] + 8; 234*53931Shibler if (dlen > acbp->buflen) 235*53931Shibler dlen = acbp->buflen; 236*53931Shibler error = copyout(dp, acbp->bufptr, dlen); 237*53931Shibler } 238*53931Shibler break; 239*53931Shibler } 240*53931Shibler 241*53931Shibler case ACIOCGSTAT: 242*53931Shibler { 243*53931Shibler struct acbuffer *acbp = (struct acbuffer *)data; 244*53931Shibler 245*53931Shibler dlen = ACRESLEN(&sc->sc_einfo); 246*53931Shibler dp = (char *) malloc(dlen, M_DEVBUF, M_WAITOK); 247*53931Shibler error = accommand(dev, ACCMD_READES, dp, dlen); 248*53931Shibler if (!error) { 249*53931Shibler int ne; 250*53931Shibler char *tbuf; 251*53931Shibler 252*53931Shibler ne = sc->sc_einfo.nmte + sc->sc_einfo.nse + 253*53931Shibler sc->sc_einfo.niee + sc->sc_einfo.ndte; 254*53931Shibler dlen = ne * sizeof(struct aceltstat); 255*53931Shibler tbuf = (char *) malloc(dlen, M_DEVBUF, M_WAITOK); 256*53931Shibler acconvert(dp, tbuf, ne); 257*53931Shibler if (dlen > acbp->buflen) 258*53931Shibler dlen = acbp->buflen; 259*53931Shibler error = copyout(tbuf, acbp->bufptr, dlen); 260*53931Shibler free(tbuf, M_DEVBUF); 261*53931Shibler } 262*53931Shibler free(dp, M_DEVBUF); 263*53931Shibler break; 264*53931Shibler } 265*53931Shibler 266*53931Shibler case ACIOCMOVE: 267*53931Shibler error = accommand(dev, ACCMD_MOVEM, data, 268*53931Shibler sizeof(struct acmove)); 269*53931Shibler break; 270*53931Shibler } 271*53931Shibler return(error); 272*53931Shibler } 273*53931Shibler 274*53931Shibler accommand(dev, command, bufp, buflen) 275*53931Shibler dev_t dev; 276*53931Shibler int command; 277*53931Shibler char *bufp; 278*53931Shibler int buflen; 279*53931Shibler { 280*53931Shibler int unit = minor(dev); 281*53931Shibler register struct ac_softc *sc = &ac_softc[unit]; 282*53931Shibler register struct buf *bp = sc->sc_bp; 283*53931Shibler register struct scsi_fmt_cdb *cmd = sc->sc_cmd; 284*53931Shibler int error; 285*53931Shibler 286*53931Shibler #ifdef DEBUG 287*53931Shibler if (ac_debug & ACD_FOLLOW) 288*53931Shibler printf("accommand(dev=%x, cmd=%x, buf=%x, buflen=%x)\n", 289*53931Shibler dev, command, bufp, buflen); 290*53931Shibler #endif 291*53931Shibler if (sc->sc_flags & ACF_ACTIVE) 292*53931Shibler panic("accommand: active!"); 293*53931Shibler 294*53931Shibler sc->sc_flags |= ACF_ACTIVE; 295*53931Shibler bzero((caddr_t)cmd->cdb, sizeof(cmd->cdb)); 296*53931Shibler cmd->cdb[0] = command; 297*53931Shibler 298*53931Shibler switch (command) { 299*53931Shibler case ACCMD_INITES: 300*53931Shibler cmd->len = 6; 301*53931Shibler break; 302*53931Shibler case ACCMD_READES: 303*53931Shibler cmd->len = 12; 304*53931Shibler *(short *)&cmd->cdb[2] = 0; 305*53931Shibler *(short *)&cmd->cdb[4] = 306*53931Shibler sc->sc_einfo.nmte + sc->sc_einfo.nse + 307*53931Shibler sc->sc_einfo.niee + sc->sc_einfo.ndte; 308*53931Shibler cmd->cdb[7] = buflen >> 16; 309*53931Shibler cmd->cdb[8] = buflen >> 8; 310*53931Shibler cmd->cdb[9] = buflen; 311*53931Shibler break; 312*53931Shibler case ACCMD_MODESENSE: 313*53931Shibler cmd->len = 6; 314*53931Shibler cmd->cdb[2] = 0x3F; /* all pages */ 315*53931Shibler cmd->cdb[4] = buflen; 316*53931Shibler break; 317*53931Shibler case ACCMD_MOVEM: 318*53931Shibler cmd->len = 12; 319*53931Shibler *(short *)&cmd->cdb[2] = sc->sc_picker; 320*53931Shibler *(short *)&cmd->cdb[4] = *(short *)&bufp[0]; 321*53931Shibler *(short *)&cmd->cdb[6] = *(short *)&bufp[2]; 322*53931Shibler if (*(short *)&bufp[4] & AC_INVERT) 323*53931Shibler cmd->cdb[10] = 1; 324*53931Shibler bufp = 0; 325*53931Shibler buflen = 0; 326*53931Shibler break; 327*53931Shibler default: 328*53931Shibler panic("accommand: bad command"); 329*53931Shibler } 330*53931Shibler bp->b_flags = B_BUSY|B_READ; 331*53931Shibler bp->b_dev = dev; 332*53931Shibler bp->b_un.b_addr = bufp; 333*53931Shibler bp->b_bcount = buflen; 334*53931Shibler bp->b_resid = 0; 335*53931Shibler bp->b_blkno = 0; 336*53931Shibler bp->b_error = 0; 337*53931Shibler if (scsireq(&sc->sc_dq)) 338*53931Shibler acstart(unit); 339*53931Shibler error = biowait(bp); 340*53931Shibler sc->sc_flags &= ~ACF_ACTIVE; 341*53931Shibler return (error); 342*53931Shibler } 343*53931Shibler 344*53931Shibler acstart(unit) 345*53931Shibler int unit; 346*53931Shibler { 347*53931Shibler #ifdef DEBUG 348*53931Shibler if (ac_debug & ACD_FOLLOW) 349*53931Shibler printf("acstart(unit=%x)\n", unit); 350*53931Shibler #endif 351*53931Shibler if (scsiustart(ac_softc[unit].sc_hd->hp_ctlr)) 352*53931Shibler acgo(unit); 353*53931Shibler } 354*53931Shibler 355*53931Shibler acgo(unit) 356*53931Shibler int unit; 357*53931Shibler { 358*53931Shibler register struct ac_softc *sc = &ac_softc[unit]; 359*53931Shibler register struct buf *bp = sc->sc_bp; 360*53931Shibler struct hp_device *hp = sc->sc_hd; 361*53931Shibler int stat; 362*53931Shibler 363*53931Shibler #ifdef DEBUG 364*53931Shibler if (ac_debug & ACD_FOLLOW) 365*53931Shibler printf("acgo(unit=%x): ", unit); 366*53931Shibler #endif 367*53931Shibler stat = scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, 368*53931Shibler bp, sc->sc_cmd, 0); 369*53931Shibler #ifdef DEBUG 370*53931Shibler if (ac_debug & ACD_FOLLOW) 371*53931Shibler printf("scsigo returns %x\n", stat); 372*53931Shibler #endif 373*53931Shibler if (stat) { 374*53931Shibler bp->b_error = EIO; 375*53931Shibler bp->b_flags |= B_ERROR; 376*53931Shibler (void) biodone(bp); 377*53931Shibler scsifree(&sc->sc_dq); 378*53931Shibler } 379*53931Shibler } 380*53931Shibler 381*53931Shibler acintr(unit, stat) 382*53931Shibler int unit, stat; 383*53931Shibler { 384*53931Shibler register struct ac_softc *sc = &ac_softc[unit]; 385*53931Shibler register struct buf *bp = sc->sc_bp; 386*53931Shibler u_char sensebuf[78]; 387*53931Shibler struct scsi_xsense *sp; 388*53931Shibler 389*53931Shibler #ifdef DEBUG 390*53931Shibler if (ac_debug & ACD_FOLLOW) 391*53931Shibler printf("acintr(unit=%x, stat=%x)\n", unit, stat); 392*53931Shibler #endif 393*53931Shibler switch (stat) { 394*53931Shibler case 0: 395*53931Shibler bp->b_resid = 0; 396*53931Shibler break; 397*53931Shibler case STS_CHECKCOND: 398*53931Shibler scsi_request_sense(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 399*53931Shibler sc->sc_punit, sensebuf, sizeof sensebuf); 400*53931Shibler sp = (struct scsi_xsense *)sensebuf; 401*53931Shibler printf("ac%d: acintr sense key=%x, ac=%x, acq=%x\n", 402*53931Shibler unit, sp->key, sp->info4, sp->len); 403*53931Shibler bp->b_flags |= B_ERROR; 404*53931Shibler bp->b_error = EIO; 405*53931Shibler break; 406*53931Shibler default: 407*53931Shibler printf("ac%d: acintr unknown status 0x%x\n", unit, stat); 408*53931Shibler break; 409*53931Shibler } 410*53931Shibler (void) biodone(sc->sc_bp); 411*53931Shibler scsifree(&sc->sc_dq); 412*53931Shibler } 413*53931Shibler 414*53931Shibler acgeteinfo(dev) 415*53931Shibler dev_t dev; 416*53931Shibler { 417*53931Shibler register struct ac_softc *sc = &ac_softc[minor(dev)]; 418*53931Shibler register char *bp; 419*53931Shibler char msbuf[48]; 420*53931Shibler int error; 421*53931Shibler 422*53931Shibler bzero(msbuf, sizeof msbuf); 423*53931Shibler error = accommand(dev, ACCMD_MODESENSE, msbuf, sizeof msbuf); 424*53931Shibler if (error) 425*53931Shibler return(error); 426*53931Shibler bp = &msbuf[4]; 427*53931Shibler while (bp < &msbuf[48]) { 428*53931Shibler switch (bp[0] & 0x3F) { 429*53931Shibler case 0x1D: 430*53931Shibler sc->sc_einfo = *(struct acinfo *)&bp[2]; 431*53931Shibler sc->sc_picker = sc->sc_einfo.fmte; /* XXX */ 432*53931Shibler return(0); 433*53931Shibler case 0x1E: 434*53931Shibler bp += 4; 435*53931Shibler break; 436*53931Shibler case 0x1F: 437*53931Shibler bp += 20; 438*53931Shibler break; 439*53931Shibler default: 440*53931Shibler printf("acgeteinfo: bad page type %x\n", bp[0]); 441*53931Shibler return(EIO); 442*53931Shibler } 443*53931Shibler } 444*53931Shibler return(EIO); 445*53931Shibler } 446*53931Shibler 447*53931Shibler acconvert(sbuf, dbuf, ne) 448*53931Shibler char *sbuf, *dbuf; 449*53931Shibler int ne; 450*53931Shibler { 451*53931Shibler register struct aceltstat *ep = (struct aceltstat *)dbuf; 452*53931Shibler register struct ac_restatphdr *phdr; 453*53931Shibler register struct ac_restatdb *dbp; 454*53931Shibler struct ac_restathdr *hdr; 455*53931Shibler #ifdef DEBUG 456*53931Shibler register int bcount; 457*53931Shibler #endif 458*53931Shibler 459*53931Shibler hdr = (struct ac_restathdr *)&sbuf[0]; 460*53931Shibler sbuf += sizeof *hdr; 461*53931Shibler #ifdef DEBUG 462*53931Shibler if (ac_debug & ACD_FOLLOW) 463*53931Shibler printf("element status: first=%d, num=%d, len=%d\n", 464*53931Shibler hdr->ac_felt, hdr->ac_nelt, hdr->ac_bcount); 465*53931Shibler if (hdr->ac_nelt != ne) { 466*53931Shibler printf("acconvert: # of elements, %d != %d\n", 467*53931Shibler hdr->ac_nelt, ne); 468*53931Shibler if (hdr->ac_nelt < ne) 469*53931Shibler ne = hdr->ac_nelt; 470*53931Shibler } 471*53931Shibler bcount = hdr->ac_bcount; 472*53931Shibler #endif 473*53931Shibler while (ne) { 474*53931Shibler phdr = (struct ac_restatphdr *)sbuf; 475*53931Shibler sbuf += sizeof *phdr; 476*53931Shibler #ifdef DEBUG 477*53931Shibler bcount -= sizeof *phdr; 478*53931Shibler #endif 479*53931Shibler dbp = (struct ac_restatdb *)sbuf; 480*53931Shibler sbuf += phdr->ac_bcount; 481*53931Shibler #ifdef DEBUG 482*53931Shibler bcount -= phdr->ac_bcount; 483*53931Shibler #endif 484*53931Shibler while (dbp < (struct ac_restatdb *)sbuf) { 485*53931Shibler ep->type = phdr->ac_type; 486*53931Shibler ep->eaddr = dbp->ac_eaddr; 487*53931Shibler ep->flags = 0; 488*53931Shibler if (dbp->ac_full) 489*53931Shibler ep->flags |= AC_FULL; 490*53931Shibler if (dbp->ac_exc) 491*53931Shibler ep->flags |= AC_ERROR; 492*53931Shibler if (dbp->ac_acc) 493*53931Shibler ep->flags |= AC_ACCESS; 494*53931Shibler dbp = (struct ac_restatdb *) 495*53931Shibler ((char *)dbp + phdr->ac_dlen); 496*53931Shibler ep++; 497*53931Shibler ne--; 498*53931Shibler } 499*53931Shibler #ifdef DEBUG 500*53931Shibler if (ne < 0 || bcount < 0) 501*53931Shibler panic("acconvert: inconsistant"); 502*53931Shibler #endif 503*53931Shibler } 504*53931Shibler } 505*53931Shibler #endif 506