1*17553Skarels #ifndef lint 2*17553Skarels static char *sccsid = "@(#)uda.c 6.3 (Berkeley) 12/20/84"; 3*17553Skarels #endif lint 44743Swnj 5*17553Skarels /************************************************************************ 6*17553Skarels * * 7*17553Skarels * Copyright (c) 1983 by * 8*17553Skarels * Digital Equipment Corporation, Maynard, MA * 9*17553Skarels * All rights reserved. * 10*17553Skarels * * 11*17553Skarels ************************************************************************/ 12*17553Skarels /* 13*17553Skarels * uda.c - UDA50A Driver 14*17553Skarels * 15*17553Skarels * Date: Jan 30 1984 16*17553Skarels * 17*17553Skarels * This thing has been beaten beyound belief. It still has two main features. 18*17553Skarels * 1) When this device is on the same unibus as another DMA device 19*17553Skarels * like a versatec or a rk07. the Udstrat routine complains that it still 20*17553Skarels * has a buffered data path that it shouldn't. I don't know why. 21*17553Skarels * 22*17553Skarels * decvax!rich. 23*17553Skarels * 24*17553Skarels */ 25*17553Skarels 26*17553Skarels #define DEBUG 27*17553Skarels #define UDADEVNUM (9) /* entry in bdevsw */ 284743Swnj #include "ra.h" 29*17553Skarels #if NUDA > 0 || defined(BINARY) 304743Swnj /* 314743Swnj * UDA50/RAxx disk device driver 324743Swnj * 334743Swnj * Restrictions: 34*17553Skarels * Unit numbers must be less than 8. 35*17553Skarels * Partitions A and B must be the same size on all RA drives. 364743Swnj */ 379781Ssam #include "../machine/pte.h" 384743Swnj 39*17553Skarels #include "param.h" 40*17553Skarels #include "systm.h" 41*17553Skarels #include "buf.h" 42*17553Skarels #include "conf.h" 43*17553Skarels #include "dir.h" 44*17553Skarels #include "user.h" 45*17553Skarels #include "map.h" 46*17553Skarels #include "vm.h" 47*17553Skarels #include "dk.h" 48*17553Skarels #include "cmap.h" 49*17553Skarels #include "uio.h" 504743Swnj 518482Sroot #include "../vax/cpu.h" 52*17553Skarels #include "ubareg.h" 53*17553Skarels #include "ubavar.h" 54*17553Skarels #include "../vax/mtpr.h" 558613Sroot 56*17553Skarels #define TENSEC (1000) 57*17553Skarels 58*17553Skarels #define NRSPL2 3 /* log2 number of response packets */ 59*17553Skarels #define NCMDL2 3 /* log2 number of command packets */ 60*17553Skarels #define NRSP (1<<NRSPL2) 61*17553Skarels #define NCMD (1<<NCMDL2) 628613Sroot 638482Sroot #include "../vaxuba/udareg.h" 648482Sroot #include "../vax/mscp.h" 654743Swnj 66*17553Skarels #ifdef BINARY 67*17553Skarels 68*17553Skarels extern struct uda_softc { 69*17553Skarels short sc_state; /* state of controller */ 70*17553Skarels short sc_mapped; /* Unibus map allocated for uda struct? */ 71*17553Skarels int sc_ubainfo; /* Unibus mapping info */ 72*17553Skarels struct uda *sc_uda; /* Unibus address of uda struct */ 73*17553Skarels int sc_ivec; /* interrupt vector address */ 74*17553Skarels short sc_credits; /* transfer credits */ 75*17553Skarels short sc_lastcmd; /* pointer into command ring */ 76*17553Skarels short sc_lastrsp; /* pointer into response ring */ 77*17553Skarels } uda_softc[]; 78*17553Skarels struct uda { 79*17553Skarels struct udaca uda_ca; /* communications area */ 80*17553Skarels struct mscp uda_rsp[NRSP]; /* response packets */ 81*17553Skarels struct mscp uda_cmd[NCMD]; /* command packets */ 82*17553Skarels } uda[]; 83*17553Skarels 84*17553Skarels /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 85*17553Skarels extern struct size { 86*17553Skarels daddr_t nblocks; 87*17553Skarels daddr_t blkoff; 88*17553Skarels } ra25_sizes[], ra60_sizes[], ra80_sizes[], ra81_sizes[]; 89*17553Skarels 90*17553Skarels 91*17553Skarels /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 92*17553Skarels 93*17553Skarels struct ra_info { 94*17553Skarels struct size *ra_sizes; /* Partion tables for drive */ 95*17553Skarels daddr_t radsize; /* Max user size form online pkt */ 96*17553Skarels unsigned ratype; /* Drive type int field */ 97*17553Skarels unsigned rastatus; /* Command status from */ 98*17553Skarels /* last onlin or GTUNT */ 99*17553Skarels } ra_info[]; 100*17553Skarels 101*17553Skarels extern struct uba_ctlr *udminfo[]; 102*17553Skarels extern struct uba_device *uddinfo[]; 103*17553Skarels extern struct uba_device *udip[][8]; /* 8 == max number of drives */ 104*17553Skarels extern struct buf rudbuf[]; 105*17553Skarels extern struct buf udutab[]; /* Drive queue */ 106*17553Skarels extern struct buf udwtab[]; /* I/O wait queue, per controller */ 107*17553Skarels extern int udamicro[]; /* to store microcode level */ 108*17553Skarels 109*17553Skarels extern int nNRA; 110*17553Skarels extern int nNUDA; 111*17553Skarels 112*17553Skarels #else 113*17553Skarels 1144743Swnj struct uda_softc { 115*17553Skarels short sc_state; /* state of controller */ 116*17553Skarels short sc_mapped; /* Unibus map allocated for uda struct? */ 117*17553Skarels int sc_ubainfo; /* Unibus mapping info */ 118*17553Skarels struct uda *sc_uda; /* Unibus address of uda struct */ 119*17553Skarels int sc_ivec; /* interrupt vector address */ 120*17553Skarels short sc_credits; /* transfer credits */ 121*17553Skarels short sc_lastcmd; /* pointer into command ring */ 122*17553Skarels short sc_lastrsp; /* pointer into response ring */ 1234743Swnj } uda_softc[NUDA]; 1244743Swnj struct uda { 125*17553Skarels struct udaca uda_ca; /* communications area */ 126*17553Skarels struct mscp uda_rsp[NRSP]; /* response packets */ 127*17553Skarels struct mscp uda_cmd[NCMD]; /* command packets */ 1284743Swnj } uda[NUDA]; 1294743Swnj 1304743Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 1314743Swnj struct size { 132*17553Skarels daddr_t nblocks; 133*17553Skarels daddr_t blkoff; 134*17553Skarels } ra25_sizes[8] = { 1354743Swnj 15884, 0, /* A=blk 0 thru 15883 */ 136*17553Skarels 10032, 15884, /* B=blk 15884 thru 49323 */ 137*17553Skarels -1, 0, /* C=blk 0 thru end */ 138*17553Skarels 0, 0, /* D=blk 340670 thru 356553 */ 139*17553Skarels 0, 0, /* E=blk 356554 thru 412489 */ 140*17553Skarels 0, 0, /* F=blk 412490 thru end */ 141*17553Skarels -1, 25916, /* G=blk 49324 thru 131403 */ 142*17553Skarels 0, 0, /* H=blk 131404 thru end */ 143*17553Skarels }, ra60_sizes[8] = { 144*17553Skarels 15884, 0, /* A=blk 0 thru 15883 */ 1454743Swnj 33440, 15884, /* B=blk 15884 thru 49323 */ 1464743Swnj -1, 0, /* C=blk 0 thru end */ 14715545Skarels 15884, 242606, /* D=blk 242606 thru 258489 */ 14815545Skarels 307200, 258490, /* E=blk 258490 thru 565689 */ 14915545Skarels -1, 565690, /* F=blk 565690 thru end */ 15015545Skarels -1, 242606, /* G=blk 242606 thru end */ 15115545Skarels 193282, 49324, /* H=blk 49324 thru 242605 */ 152*17553Skarels }, ra80_sizes[8] = { 153*17553Skarels 15884, 0, /* A=blk 0 thru 15883 */ 154*17553Skarels 33440, 15884, /* B=blk 15884 thru 49323 */ 155*17553Skarels -1, 0, /* C=blk 0 thru end */ 156*17553Skarels 15884, 242606, /* D=blk 242606 thru 258489 */ 157*17553Skarels 307200, 258490, /* E=blk 258490 thru 565689 */ 158*17553Skarels -1, 565690, /* F=blk 565690 thru end */ 159*17553Skarels -1, 242606, /* G=blk 242606 thru end */ 160*17553Skarels 193282, 49324, /* H=blk 49324 thru 242605 */ 161*17553Skarels }, ra81_sizes[8] ={ 162*17553Skarels 15884, 0, /* A=blk 0 thru 15883 */ 163*17553Skarels 33440, 15884, /* B=blk 15884 thru 49323 */ 164*17553Skarels -1, 0, /* C=blk 0 thru end */ 165*17553Skarels 15884, 242606, /* D=blk 242606 thru 258489 */ 166*17553Skarels 307200, 258490, /* E=blk 258490 thru 565689 */ 167*17553Skarels -1, 565690, /* F=blk 565690 thru end */ 168*17553Skarels -1, 242606, /* G=blk 242606 thru end */ 169*17553Skarels 193282, 49324, /* H=blk 49324 thru 242605 */ 1704743Swnj }; 171*17553Skarels 172*17553Skarels struct ra_info { 173*17553Skarels struct size *ra_sizes; /* Partion tables for drive */ 174*17553Skarels daddr_t radsize; /* Max user size form online pkt */ 175*17553Skarels unsigned ratype; /* Drive type int field */ 176*17553Skarels unsigned rastatus; /* Command status from */ 177*17553Skarels /* last onlin or GTUNT */ 178*17553Skarels } ra_info[NRA]; 179*17553Skarels 180*17553Skarels 1814743Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 182*17553Skarels struct uba_ctlr *udminfo[NUDA]; 183*17553Skarels struct uba_device *uddinfo[NRA]; 184*17553Skarels struct uba_device *udip[NUDA][8]; /* 8 == max number of drives */ 185*17553Skarels struct buf rudbuf[NRA]; 186*17553Skarels struct buf udutab[NRA]; 187*17553Skarels struct buf udwtab[NUDA]; /* I/O wait queue, per controller */ 1884743Swnj 18912421Ssam 190*17553Skarels int nNRA = NRA; 191*17553Skarels int nNUDA = NUDA; 192*17553Skarels int udamicro[NUDA]; /* to store microcode level */ 1934743Swnj 1944743Swnj 195*17553Skarels #endif 196*17553Skarels 197*17553Skarels /* 198*17553Skarels * Controller states 199*17553Skarels */ 200*17553Skarels #define S_IDLE 0 /* hasn't been initialized */ 201*17553Skarels #define S_STEP1 1 /* doing step 1 init */ 202*17553Skarels #define S_STEP2 2 /* doing step 2 init */ 203*17553Skarels #define S_STEP3 3 /* doing step 3 init */ 204*17553Skarels #define S_SCHAR 4 /* doing "set controller characteristics" */ 205*17553Skarels #define S_RUN 5 /* running */ 206*17553Skarels 207*17553Skarels 208*17553Skarels int udaerror = 0; /* causes hex dump of packets */ 209*17553Skarels int udadebug = 0; 210*17553Skarels int uda_cp_wait = 0; /* Something to wait on for command */ 211*17553Skarels /* packets and or credits. */ 212*17553Skarels int wakeup(); 213*17553Skarels extern int hz; /* Should find the right include */ 214*17553Skarels #ifdef DEBUG 215*17553Skarels #define printd if (udadebug) printf 216*17553Skarels #define printd10 if(udadebug >= 10) printf 217*17553Skarels #endif 218*17553Skarels #define mprintf printf /* temporary JG hack until Rich fixes*/ 219*17553Skarels 220*17553Skarels int udprobe(), udslave(), udattach(), udintr(); 221*17553Skarels struct mscp *udgetcp(); 222*17553Skarels 223*17553Skarels u_short udstd[] = { 0772150, 0772550, 0777550, 0 }; 224*17553Skarels struct uba_driver udadriver = 2254743Swnj { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 }; 2264743Swnj 227*17553Skarels #define b_qsize b_resid /* queue size per drive, in udutab */ 228*17553Skarels #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ 2294743Swnj 2304743Swnj udprobe(reg, ctlr) 2314743Swnj caddr_t reg; 2324743Swnj int ctlr; 2334743Swnj { 2344743Swnj register int br, cvec; 2354743Swnj register struct uda_softc *sc = &uda_softc[ctlr]; 236*17553Skarels struct udadevice *udaddr; 2374743Swnj 238*17553Skarels int cur_time; 239*17553Skarels 2404743Swnj #ifdef lint 241*17553Skarels br = 0; cvec = br; br = cvec; 24212778Ssam udreset(0); udintr(0); 2434743Swnj #endif 244*17553Skarels udaddr = (struct udadevice *) reg; 245*17553Skarels 246*17553Skarels sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); 247*17553Skarels udaddr->udaip = 0; /* start initialization */ 248*17553Skarels 249*17553Skarels cur_time = mfpr(TODR); /* Time of day */ 250*17553Skarels while(cur_time + TENSEC > mfpr(TODR)){ /* wait for at most 10 secs */ 251*17553Skarels if((udaddr->udasa & UDA_STEP1) != 0) 252*17553Skarels break; 253*17553Skarels } 254*17553Skarels if(cur_time + TENSEC <= mfpr(TODR)) 255*17553Skarels return(0); /* Not a uda or it won't init as it */ 256*17553Skarels /* should within ten seconds. */ 257*17553Skarels udaddr->udasa=UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); 258*17553Skarels while((udaddr->udasa&UDA_STEP2)==0) 259*17553Skarels DELAY(1000); /* intr should have */ 260*17553Skarels /* have happened by now */ 261*17553Skarels 2627410Skre return(sizeof (struct udadevice)); 2634743Swnj } 2644743Swnj 2654743Swnj udslave(ui, reg) 2664743Swnj struct uba_device *ui; 2674743Swnj caddr_t reg; 2684743Swnj { 269*17553Skarels register struct uba_ctlr *um = udminfo[ui->ui_ctlr]; 270*17553Skarels register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; 271*17553Skarels struct udadevice *udaddr; 272*17553Skarels struct mscp *mp; 273*17553Skarels int i; /* Something to write into to start */ 274*17553Skarels /* the uda polling */ 275*17553Skarels 276*17553Skarels 2776187Ssam #ifdef lint 278*17553Skarels ui = ui; reg = reg; i = i; 2796187Ssam #endif 280*17553Skarels udaddr = (struct udadevice *)um->um_addr; 281*17553Skarels if(sc->sc_state != S_RUN){ 282*17553Skarels if(!udinit(ui->ui_ctlr)) 283*17553Skarels return(0); 284*17553Skarels } 285*17553Skarels /* Here we will wait for the controller */ 286*17553Skarels /* to come into the run state or go idle. If we go idle we are in */ 287*17553Skarels /* touble and I don't yet know what to do so I will punt */ 288*17553Skarels while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE); /* spin */ 289*17553Skarels if(sc->sc_state == S_IDLE){ /* The Uda failed to initialize */ 290*17553Skarels printf("UDA failed to init\n"); 291*17553Skarels return(0); 292*17553Skarels } 293*17553Skarels /* The controller is up so let see if the drive is there! */ 294*17553Skarels if(0 == (mp = udgetcp(um))){ /* ditto */ 295*17553Skarels printf("UDA can't get command packet\n"); 296*17553Skarels return(0); 297*17553Skarels } 298*17553Skarels mp->mscp_opcode = M_OP_GTUNT; /* This should give us the drive type*/ 299*17553Skarels mp->mscp_unit = ui->ui_slave; 300*17553Skarels mp->mscp_cmdref = (long) ui->ui_slave; 301*17553Skarels #ifdef DEBUG 302*17553Skarels printd("uda%d Get unit status slave %d\n",ui->ui_ctlr,ui->ui_slave); 303*17553Skarels #endif 304*17553Skarels ra_info[ui->ui_unit].rastatus = 0; /* set to zero */ 305*17553Skarels udip[ui->ui_ctlr][ui->ui_slave] = ui; 306*17553Skarels *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT;/* maybe we should poll*/ 307*17553Skarels i = udaddr->udaip; 308*17553Skarels while(!ra_info[ui->ui_unit].rastatus); /* Wait for some status */ 309*17553Skarels udip[ui->ui_ctlr][ui->ui_slave] = 0; 310*17553Skarels if(!ra_info[ui->ui_unit].ratype) /* packet from a GTUNT */ 311*17553Skarels return(0); /* Failed No such drive */ 312*17553Skarels else 313*17553Skarels return(1); /* Got it and it is there */ 3144743Swnj } 3154743Swnj 3164743Swnj udattach(ui) 3174743Swnj register struct uba_device *ui; 3184743Swnj { 319*17553Skarels register struct uba_ctlr *um = ui->ui_mi ; 320*17553Skarels struct udadevice *udaddr = (struct udadevice *) um->um_addr; 321*17553Skarels struct mscp *mp; 322*17553Skarels int i; /* Something to write into to start */ 323*17553Skarels /* the uda polling */ 324*17553Skarels #ifdef lint 325*17553Skarels i = i; 326*17553Skarels #endif 32712443Ssam if (ui->ui_dk >= 0) 328*17553Skarels dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ 3294743Swnj ui->ui_flags = 0; 3304743Swnj udip[ui->ui_ctlr][ui->ui_slave] = ui; 331*17553Skarels /* check to see if the drive is a available if it is bring it online */ 332*17553Skarels /* if not then just return. open will try an online later */ 333*17553Skarels if(ra_info[ui->ui_unit].rastatus != M_ST_AVLBL) 334*17553Skarels return; /* status was set by a GTUNT */ 335*17553Skarels if(0 == (mp = udgetcp(um))){ /* ditto */ 336*17553Skarels printf("UDA can't get command packet\n"); 337*17553Skarels return; 338*17553Skarels } 339*17553Skarels mp->mscp_opcode = M_OP_ONLIN; 340*17553Skarels mp->mscp_unit = ui->ui_slave; 341*17553Skarels mp->mscp_cmdref = (long) ui->ui_slave; 342*17553Skarels #ifdef DEBUG 343*17553Skarels printd("uda%d ONLIN slave %d\n",ui->ui_ctlr,ui->ui_slave); 344*17553Skarels #endif 345*17553Skarels *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT; 346*17553Skarels i = udaddr->udaip; 347*17553Skarels while(ui->ui_flags == 0 && ra_info[ui->ui_unit].ratype != 0); 3484743Swnj } 3494743Swnj 3504743Swnj /* 3514743Swnj * Open a UDA. Initialize the device and 3524743Swnj * set the unit online. 3534743Swnj */ 3544743Swnj udopen(dev, flag) 3554743Swnj dev_t dev; 3564743Swnj int flag; 3574743Swnj { 3584743Swnj register int unit; 3594743Swnj register struct uba_device *ui; 3604743Swnj register struct uda_softc *sc; 361*17553Skarels register struct mscp *mp; 362*17553Skarels register struct uba_ctlr *um; 363*17553Skarels struct udadevice *udaddr; 364*17553Skarels int s,i; 365*17553Skarels extern quota; 366*17553Skarels 3676187Ssam #ifdef lint 368*17553Skarels flag = flag; i = i; 3696187Ssam #endif 3704743Swnj unit = minor(dev) >> 3; 371*17553Skarels if (unit >= nNRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) 3728576Sroot return (ENXIO); 3734743Swnj sc = &uda_softc[ui->ui_ctlr]; 3745434Sroot s = spl5(); 3754743Swnj if (sc->sc_state != S_RUN) { 3764743Swnj if (sc->sc_state == S_IDLE) 377*17553Skarels if(!udinit(ui->ui_ctlr)){ 378*17553Skarels printf("uda: Controller failed to init\n"); 379*17553Skarels return(ENXIO); 380*17553Skarels } 3816187Ssam /* wait for initialization to complete */ 382*17553Skarels timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ 3836187Ssam sleep((caddr_t)ui->ui_mi, 0); 3848576Sroot if (sc->sc_state != S_RUN) 385*17553Skarels { 386*17553Skarels (void) splx(s); /* added by Rich */ 3878576Sroot return (EIO); 388*17553Skarels } 3894743Swnj } 390*17553Skarels /* check to see if the device is really there. */ 391*17553Skarels /* this code was taken from Fred Canters 11 driver */ 392*17553Skarels um = ui->ui_mi; 393*17553Skarels udaddr = (struct udadevice *) um->um_addr; 394*17553Skarels (void) splx(s); 395*17553Skarels if(ui->ui_flags == 0){ 396*17553Skarels s = spl5(); 397*17553Skarels while(0 ==(mp = udgetcp(um))){ 398*17553Skarels uda_cp_wait++; 399*17553Skarels sleep(&uda_cp_wait,PSWP+1); 400*17553Skarels uda_cp_wait--; 401*17553Skarels } 402*17553Skarels (void) splx(s); 403*17553Skarels mp->mscp_opcode = M_OP_ONLIN; 404*17553Skarels mp->mscp_unit = ui->ui_slave; 405*17553Skarels mp->mscp_cmdref = (long) & ra_info[ui->ui_unit].ratype; 406*17553Skarels /* need to sleep on something */ 407*17553Skarels #ifdef DEBUG 408*17553Skarels printd("uda: bring unit %d online\n",ui->ui_unit); 409*17553Skarels #endif 410*17553Skarels *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT ; 411*17553Skarels i = udaddr->udaip; 412*17553Skarels timeout(wakeup,(caddr_t) mp->mscp_cmdref,10 * hz); 413*17553Skarels /* make sure we wake up */ 414*17553Skarels sleep((caddr_t) mp->mscp_cmdref,PSWP+1); /*wakeup in udrsp() */ 415*17553Skarels } 416*17553Skarels if(ui->ui_flags == 0){ 417*17553Skarels return(ENXIO); /* Didn't go online */ 418*17553Skarels } 4198576Sroot return (0); 4204743Swnj } 4214743Swnj 4224743Swnj /* 4234743Swnj * Initialize a UDA. Set up UBA mapping registers, 4244743Swnj * initialize data structures, and start hardware 4254743Swnj * initialization sequence. 4264743Swnj */ 4274743Swnj udinit(d) 4284743Swnj int d; 4294743Swnj { 4304743Swnj register struct uda_softc *sc; 4314743Swnj register struct uda *ud; 4324743Swnj struct udadevice *udaddr; 4334743Swnj struct uba_ctlr *um; 4344743Swnj 4354743Swnj sc = &uda_softc[d]; 4364743Swnj um = udminfo[d]; 4374743Swnj um->um_tab.b_active++; 4384743Swnj ud = &uda[d]; 4394743Swnj udaddr = (struct udadevice *)um->um_addr; 4404743Swnj if (sc->sc_mapped == 0) { 4414743Swnj /* 4424743Swnj * Map the communications area and command 4434743Swnj * and response packets into Unibus address 4444743Swnj * space. 4454743Swnj */ 4464743Swnj sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud, 4474743Swnj sizeof (struct uda), 0); 4484743Swnj sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff); 4494743Swnj sc->sc_mapped = 1; 4504743Swnj } 4514743Swnj 4524743Swnj /* 4534743Swnj * Start the hardware initialization sequence. 4544743Swnj */ 455*17553Skarels 456*17553Skarels udaddr->udaip = 0; /* start initialization */ 457*17553Skarels 458*17553Skarels while((udaddr->udasa & UDA_STEP1) == 0){ 459*17553Skarels if(udaddr->udasa & UDA_ERR) 460*17553Skarels return(0); /* CHECK */ 461*17553Skarels } 462*17553Skarels udaddr->udasa=UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); 4634743Swnj /* 4644743Swnj * Initialization continues in interrupt routine. 4654743Swnj */ 4664743Swnj sc->sc_state = S_STEP1; 4674743Swnj sc->sc_credits = 0; 468*17553Skarels return(1); 4694743Swnj } 4704743Swnj 4714743Swnj udstrategy(bp) 4724743Swnj register struct buf *bp; 4734743Swnj { 4744743Swnj register struct uba_device *ui; 4754743Swnj register struct uba_ctlr *um; 4764743Swnj register struct buf *dp; 4774743Swnj register int unit; 478*17553Skarels register struct size *rasizes; 4794743Swnj int xunit = minor(bp->b_dev) & 07; 4804743Swnj daddr_t sz, maxsz; 4815434Sroot int s; 4824743Swnj 4834743Swnj sz = (bp->b_bcount+511) >> 9; 4844743Swnj unit = dkunit(bp); 485*17553Skarels if (unit >= nNRA) 4864743Swnj goto bad; 487*17553Skarels rasizes = ra_info[unit].ra_sizes; 4884743Swnj ui = uddinfo[unit]; 4894743Swnj um = ui->ui_mi; 4904743Swnj if (ui == 0 || ui->ui_alive == 0) 4914743Swnj goto bad; 492*17553Skarels if ((maxsz = rasizes[xunit].nblocks) < 0) 493*17553Skarels maxsz = ra_info[unit].radsize - rasizes[xunit].blkoff; 4944743Swnj if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz || 495*17553Skarels rasizes[xunit].blkoff >= ra_info[unit].radsize) 4964743Swnj goto bad; 4975434Sroot s = spl5(); 4984743Swnj /* 4994743Swnj * Link the buffer onto the drive queue 5004743Swnj */ 5014743Swnj dp = &udutab[ui->ui_unit]; 5024743Swnj if (dp->b_actf == 0) 5034743Swnj dp->b_actf = bp; 5044743Swnj else 5054743Swnj dp->b_actl->av_forw = bp; 5064743Swnj dp->b_actl = bp; 5074743Swnj bp->av_forw = 0; 5084743Swnj /* 5094743Swnj * Link the drive onto the controller queue 5104743Swnj */ 5114743Swnj if (dp->b_active == 0) { 5124743Swnj dp->b_forw = NULL; 5134743Swnj if (um->um_tab.b_actf == NULL) 5144743Swnj um->um_tab.b_actf = dp; 5154743Swnj else 5164743Swnj um->um_tab.b_actl->b_forw = dp; 5174743Swnj um->um_tab.b_actl = dp; 5184743Swnj dp->b_active = 1; 5194743Swnj } 5204743Swnj if (um->um_tab.b_active == 0) { 5214743Swnj #if defined(VAX750) 52212421Ssam if (cpu == VAX_750 52312421Ssam && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { 524*17553Skarels if (um->um_ubinfo != 0) { 525*17553Skarels printd("udastrat: ubinfo 0x%x\n",um->um_ubinfo); 526*17553Skarels } else 5274743Swnj um->um_ubinfo = 52812421Ssam uballoc(um->um_ubanum, (caddr_t)0, 0, 5296187Ssam UBA_NEEDBDP); 5304743Swnj } 5314743Swnj #endif 5324743Swnj (void) udstart(um); 5334743Swnj } 5345434Sroot splx(s); 5354743Swnj return; 5364743Swnj 5374743Swnj bad: 5384743Swnj bp->b_flags |= B_ERROR; 5394743Swnj iodone(bp); 5404743Swnj return; 5414743Swnj } 5424743Swnj 5434743Swnj udstart(um) 5444743Swnj register struct uba_ctlr *um; 5454743Swnj { 5464743Swnj register struct buf *bp, *dp; 5474743Swnj register struct mscp *mp; 5484743Swnj register struct uda_softc *sc; 5494743Swnj register struct uba_device *ui; 550*17553Skarels struct size *rasizes; 5514743Swnj struct udadevice *udaddr; 552*17553Skarels struct uda *ud = &uda[um->um_ctlr]; 5534743Swnj int i; 5544743Swnj 5554743Swnj sc = &uda_softc[um->um_ctlr]; 5564743Swnj 5574743Swnj loop: 5584743Swnj if ((dp = um->um_tab.b_actf) == NULL) { 5594743Swnj /* 5604743Swnj * Release uneeded UBA resources and return 5614743Swnj */ 5624743Swnj um->um_tab.b_active = 0; 563*17553Skarels /* Check for response ring transitions lost in the 564*17553Skarels * Race condition 565*17553Skarels */ 566*17553Skarels for (i = sc->sc_lastrsp;; i++) { 567*17553Skarels i %= NRSP; 568*17553Skarels if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) 569*17553Skarels break; 570*17553Skarels udrsp(um, ud, sc, i); 571*17553Skarels ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; 572*17553Skarels } 573*17553Skarels sc->sc_lastrsp = i; 5746187Ssam return (0); 5754743Swnj } 5764743Swnj if ((bp = dp->b_actf) == NULL) { 5774743Swnj /* 5784743Swnj * No more requests for this drive, remove 5794743Swnj * from controller queue and look at next drive. 5804743Swnj * We know we're at the head of the controller queue. 5814743Swnj */ 5824743Swnj dp->b_active = 0; 5834743Swnj um->um_tab.b_actf = dp->b_forw; 584*17553Skarels goto loop; /* Need to check for loop */ 5854743Swnj } 5864743Swnj um->um_tab.b_active++; 5874743Swnj udaddr = (struct udadevice *)um->um_addr; 5884743Swnj if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) { 5894743Swnj harderr(bp, "ra"); 590*17553Skarels mprintf("Uda%d udasa %o, state %d\n",um->um_ctlr , udaddr->udasa&0xffff, sc->sc_state); 5914743Swnj udinit(um->um_ctlr); 5924743Swnj /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */ 5936187Ssam return (0); 5944743Swnj } 5954743Swnj ui = uddinfo[dkunit(bp)]; 596*17553Skarels rasizes = ra_info[ui->ui_unit].ra_sizes; 597*17553Skarels if (ui->ui_flags == 0) { /* not online */ 598*17553Skarels if ((mp = udgetcp(um)) == NULL){ 599*17553Skarels return (0); 600*17553Skarels } 6014743Swnj mp->mscp_opcode = M_OP_ONLIN; 6024743Swnj mp->mscp_unit = ui->ui_slave; 6034743Swnj dp->b_active = 2; 604*17553Skarels um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ 605*17553Skarels #ifdef DEBUG 6064743Swnj printd("uda: bring unit %d online\n", ui->ui_slave); 607*17553Skarels #endif 6084743Swnj *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; 609*17553Skarels if (udaddr->udasa&UDA_ERR) 610*17553Skarels printf("Uda (%d) Error (%x)\n",um->um_ctlr , udaddr->udasa&0xffff); 6114743Swnj i = udaddr->udaip; 6124743Swnj goto loop; 6134743Swnj } 6144743Swnj switch (cpu) { 6154743Swnj case VAX_780: 6164743Swnj i = UBA_NEEDBDP|UBA_CANTWAIT; 6174743Swnj break; 6184743Swnj 6194743Swnj case VAX_750: 6204743Swnj i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; 6214743Swnj break; 6224743Swnj 6236949Ssam case VAX_730: 6244743Swnj i = UBA_CANTWAIT; 6254743Swnj break; 6264743Swnj } 6274743Swnj if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) { 628*17553Skarels if(dp->b_qsize != 0){ 629*17553Skarels return(0); /* When a command completes and */ 630*17553Skarels /* frees a bdp udstart will be called */ 631*17553Skarels } 632*17553Skarels if ((mp = udgetcp(um)) == NULL){ 633*17553Skarels return (0); 634*17553Skarels } 6354743Swnj mp->mscp_opcode = M_OP_GTUNT; 6364743Swnj mp->mscp_unit = ui->ui_slave; 6374743Swnj *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; 638*17553Skarels if (udaddr->udasa&UDA_ERR) 639*17553Skarels printf("Uda(%d) udasa (%x)\n",um->um_ctlr, udaddr->udasa&0xffff); 640*17553Skarels i = udaddr->udaip; /* initiate polling */ 641*17553Skarels return(1); /* wait for interrupt */ 6424743Swnj } 643*17553Skarels if ((mp = udgetcp(um)) == NULL) { 644*17553Skarels ubarelse(um->um_ubanum,&i); 645*17553Skarels return(0); 646*17553Skarels } 647*17553Skarels mp->mscp_cmdref = (long)bp; /* pointer to get back */ 6484743Swnj mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; 6494743Swnj mp->mscp_unit = ui->ui_slave; 650*17553Skarels mp->mscp_lbn = bp->b_blkno + rasizes[minor(bp->b_dev)&7].blkoff; 6514743Swnj mp->mscp_bytecnt = bp->b_bcount; 6524743Swnj mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); 6534743Swnj #if defined(VAX750) 6544743Swnj if (cpu == VAX_750) 655*17553Skarels i &= 0xfffffff; /* mask off bdp */ 6564743Swnj #endif 657*17553Skarels bp->b_ubinfo = i; /* save mapping info */ 6584743Swnj *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; 659*17553Skarels if (udaddr->udasa&UDA_ERR) 660*17553Skarels printf("Uda(%d) udasa (%x)\n",um->um_ctlr , udaddr->udasa&0xffff); 661*17553Skarels i = udaddr->udaip; /* initiate polling */ 662*17553Skarels dp->b_qsize++; 6634743Swnj if (ui->ui_dk >= 0) { 6644743Swnj dk_busy |= 1<<ui->ui_dk; 6654743Swnj dk_xfer[ui->ui_dk]++; 6664743Swnj dk_wds[ui->ui_dk] += bp->b_bcount>>6; 6674743Swnj } 6684743Swnj 6694743Swnj /* 6704743Swnj * Move drive to the end of the controller queue 6714743Swnj */ 6724743Swnj if (dp->b_forw != NULL) { 6734743Swnj um->um_tab.b_actf = dp->b_forw; 6744743Swnj um->um_tab.b_actl->b_forw = dp; 6754743Swnj um->um_tab.b_actl = dp; 6764743Swnj dp->b_forw = NULL; 6774743Swnj } 6784743Swnj /* 6794743Swnj * Move buffer to I/O wait queue 6804743Swnj */ 6814743Swnj dp->b_actf = bp->av_forw; 6824743Swnj dp = &udwtab[um->um_ctlr]; 6834743Swnj bp->av_forw = dp; 6844743Swnj bp->av_back = dp->av_back; 6854743Swnj dp->av_back->av_forw = bp; 6864743Swnj dp->av_back = bp; 6874743Swnj goto loop; 6884743Swnj } 6894743Swnj 6904743Swnj /* 6914743Swnj * UDA interrupt routine. 6924743Swnj */ 6934743Swnj udintr(d) 6944743Swnj int d; 6954743Swnj { 6964743Swnj register struct uba_ctlr *um = udminfo[d]; 6974743Swnj register struct udadevice *udaddr = (struct udadevice *)um->um_addr; 6984743Swnj struct buf *bp; 6994743Swnj register int i; 7004743Swnj register struct uda_softc *sc = &uda_softc[d]; 7014743Swnj register struct uda *ud = &uda[d]; 7024743Swnj struct uda *uud; 7034743Swnj struct mscp *mp; 7044743Swnj 705*17553Skarels #ifdef DEBUG 706*17553Skarels printd10("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa); 707*17553Skarels #endif 7084743Swnj switch (sc->sc_state) { 7094743Swnj case S_IDLE: 7104743Swnj printf("uda%d: random interrupt ignored\n", d); 7114743Swnj return; 7124743Swnj 7134743Swnj case S_STEP1: 714*17553Skarels #define STEP1MASK 0174377 715*17553Skarels #define STEP1GOOD (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2) 7166964Ssam if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) { 7174743Swnj sc->sc_state = S_IDLE; 7186187Ssam wakeup((caddr_t)um); 7194743Swnj return; 7204743Swnj } 7214743Swnj udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)| 7224743Swnj (cpu == VAX_780 ? UDA_PI : 0); 7234743Swnj sc->sc_state = S_STEP2; 7244743Swnj return; 7254743Swnj 7264743Swnj case S_STEP2: 727*17553Skarels #define STEP2MASK 0174377 728*17553Skarels #define STEP2GOOD (UDA_STEP3|UDA_IE|(sc->sc_ivec/4)) 7296964Ssam if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) { 7304743Swnj sc->sc_state = S_IDLE; 7316187Ssam wakeup((caddr_t)um); 7324743Swnj return; 7334743Swnj } 7344743Swnj udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16; 7354743Swnj sc->sc_state = S_STEP3; 7364743Swnj return; 7374743Swnj 7384743Swnj case S_STEP3: 739*17553Skarels #define STEP3MASK 0174000 740*17553Skarels #define STEP3GOOD UDA_STEP4 7416964Ssam if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) { 7424743Swnj sc->sc_state = S_IDLE; 7436187Ssam wakeup((caddr_t)um); 7444743Swnj return; 7454743Swnj } 746*17553Skarels udamicro[d] = udaddr->udasa; 747*17553Skarels #ifdef DEBUG 748*17553Skarels printd("Uda%d Version %d model %d\n",d,udamicro[d]&0xF, 749*17553Skarels (udamicro[d]>>4) & 0xF); 750*17553Skarels /* 751*17553Skarels * Requesting the error status (|= 2) 752*17553Skarels * may hang older controllers. 753*17553Skarels */ 754*17553Skarels udaddr->udasa = UDA_GO | (udaerror? 2 : 0); 755*17553Skarels #endif 7564743Swnj udaddr->udasa = UDA_GO; 7574743Swnj sc->sc_state = S_SCHAR; 7584743Swnj 7594743Swnj /* 7604743Swnj * Initialize the data structures. 7614743Swnj */ 7624743Swnj uud = sc->sc_uda; 7634743Swnj for (i = 0; i < NRSP; i++) { 7644743Swnj ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT| 7654743Swnj (long)&uud->uda_rsp[i].mscp_cmdref; 7664743Swnj ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i]; 767*17553Skarels ud->uda_rsp[i].mscp_header.uda_msglen = mscp_msglen; 7684743Swnj } 7694743Swnj for (i = 0; i < NCMD; i++) { 7704743Swnj ud->uda_ca.ca_cmddsc[i] = UDA_INT| 7714743Swnj (long)&uud->uda_cmd[i].mscp_cmdref; 7724743Swnj ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i]; 773*17553Skarels ud->uda_cmd[i].mscp_header.uda_msglen = mscp_msglen; 7744743Swnj } 7754743Swnj bp = &udwtab[d]; 7764743Swnj bp->av_forw = bp->av_back = bp; 777*17553Skarels sc->sc_lastcmd = 1; 7784743Swnj sc->sc_lastrsp = 0; 779*17553Skarels mp = &uda[um->um_ctlr].uda_cmd[0]; 780*17553Skarels mp->mscp_unit = mp->mscp_modifier = 0; 781*17553Skarels mp->mscp_flags = 0; 782*17553Skarels mp->mscp_bytecnt = mp->mscp_buffer = 0; 783*17553Skarels mp->mscp_errlgfl = mp->mscp_copyspd = 0; 7844743Swnj mp->mscp_opcode = M_OP_STCON; 7854743Swnj mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; 7864743Swnj *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; 787*17553Skarels i = udaddr->udaip; /* initiate polling */ 7884743Swnj return; 7894743Swnj 7904743Swnj case S_SCHAR: 7914743Swnj case S_RUN: 7924743Swnj break; 7934743Swnj 7944743Swnj default: 7954743Swnj printf("uda%d: interrupt in unknown state %d ignored\n", 7964743Swnj d, sc->sc_state); 7974743Swnj return; 7984743Swnj } 7994743Swnj 8004743Swnj if (udaddr->udasa&UDA_ERR) { 801*17553Skarels printf("uda(%d): fatal error (%o)\n", d, udaddr->udasa&0xffff); 8024743Swnj udaddr->udaip = 0; 8036187Ssam wakeup((caddr_t)um); 8044743Swnj } 8054743Swnj 8064743Swnj /* 8074743Swnj * Check for a buffer purge request. 8084743Swnj */ 8094743Swnj if (ud->uda_ca.ca_bdp) { 8104743Swnj /* 8114743Swnj * THIS IS A KLUDGE. 8124743Swnj * Maybe we should change the entire 8134743Swnj * UBA interface structure. 8144743Swnj */ 815*17553Skarels int s = spl6(); /* was spl7 but I don't like turning */ 816*17553Skarels /* off machine checks */ 8174743Swnj i = um->um_ubinfo; 818*17553Skarels #ifdef DEBUG 8194743Swnj printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp); 820*17553Skarels #endif 8214743Swnj um->um_ubinfo = ud->uda_ca.ca_bdp<<28; 8224743Swnj ubapurge(um); 8234743Swnj um->um_ubinfo = i; 8244743Swnj (void) splx(s); 8254743Swnj ud->uda_ca.ca_bdp = 0; 826*17553Skarels udaddr->udasa = 0; /* signal purge complete */ 8274743Swnj } 8284743Swnj 8294743Swnj /* 8304743Swnj * Check for response ring transition. 8314743Swnj */ 8324743Swnj if (ud->uda_ca.ca_rspint) { 8334743Swnj ud->uda_ca.ca_rspint = 0; 8344743Swnj for (i = sc->sc_lastrsp;; i++) { 8354743Swnj i %= NRSP; 8364743Swnj if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) 8374743Swnj break; 8384743Swnj udrsp(um, ud, sc, i); 8394743Swnj ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; 8404743Swnj } 8414743Swnj sc->sc_lastrsp = i; 8424743Swnj } 8434743Swnj 8444743Swnj /* 8454743Swnj * Check for command ring transition. 8464743Swnj */ 8474743Swnj if (ud->uda_ca.ca_cmdint) { 848*17553Skarels #ifdef DEBUG 8494743Swnj printd("uda: command ring transition\n"); 850*17553Skarels #endif 8514743Swnj ud->uda_ca.ca_cmdint = 0; 8524743Swnj } 853*17553Skarels if(uda_cp_wait) 854*17553Skarels wakeup(&uda_cp_wait); 8556187Ssam (void) udstart(um); 8564743Swnj } 8574743Swnj 8584743Swnj /* 8594743Swnj * Process a response packet 8604743Swnj */ 8614743Swnj udrsp(um, ud, sc, i) 8624743Swnj register struct uba_ctlr *um; 8634743Swnj register struct uda *ud; 8644743Swnj register struct uda_softc *sc; 8654743Swnj int i; 8664743Swnj { 8674743Swnj register struct mscp *mp; 8684743Swnj struct uba_device *ui; 869*17553Skarels struct buf *dp, *bp,nullbp; 8704743Swnj int st; 8714743Swnj 8724743Swnj mp = &ud->uda_rsp[i]; 873*17553Skarels mp->mscp_header.uda_msglen = mscp_msglen; 874*17553Skarels sc->sc_credits += mp->mscp_header.uda_credits & 0xf; /* just 4 bits?*/ 875*17553Skarels if ((mp->mscp_header.uda_credits & 0xf0) > 0x10) /* Check */ 8764743Swnj return; 877*17553Skarels #ifdef DEBUG 878*17553Skarels printd10("udarsp, opcode 0x%x status 0x%x\n",mp->mscp_opcode,mp->mscp_status); 879*17553Skarels #endif 8804743Swnj /* 8814743Swnj * If it's an error log message (datagram), 8824743Swnj * pass it on for more extensive processing. 8834743Swnj */ 884*17553Skarels if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) { /* check */ 8854743Swnj uderror(um, (struct mslg *)mp); 8864743Swnj return; 8874743Swnj } 8884743Swnj st = mp->mscp_status&M_ST_MASK; 889*17553Skarels /* The controller interrupts as drive 0 */ 890*17553Skarels /* this means that you must check for controller interrupts */ 891*17553Skarels /* before you check to see if there is a drive 0 */ 892*17553Skarels if((M_OP_STCON|M_OP_END) == mp->mscp_opcode){ 8934743Swnj if (st == M_ST_SUCC) 8944743Swnj sc->sc_state = S_RUN; 8954743Swnj else 8964743Swnj sc->sc_state = S_IDLE; 8974743Swnj um->um_tab.b_active = 0; 8986187Ssam wakeup((caddr_t)um); 899*17553Skarels return; 900*17553Skarels } 901*17553Skarels if (mp->mscp_unit >= 8) 902*17553Skarels return; 903*17553Skarels if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0) 904*17553Skarels return; 905*17553Skarels switch (mp->mscp_opcode) { 9064743Swnj 9074743Swnj case M_OP_ONLIN|M_OP_END: 908*17553Skarels ra_info[ui->ui_unit].rastatus = st; 909*17553Skarels ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; 9104743Swnj dp = &udutab[ui->ui_unit]; 9114743Swnj if (st == M_ST_SUCC) { 912*17553Skarels /* 913*17553Skarels * Link the drive onto the controller queue 914*17553Skarels */ 915*17553Skarels dp->b_forw = NULL; 916*17553Skarels if (um->um_tab.b_actf == NULL) 917*17553Skarels um->um_tab.b_actf = dp; 918*17553Skarels else 919*17553Skarels um->um_tab.b_actl->b_forw = dp; 920*17553Skarels um->um_tab.b_actl = dp; 921*17553Skarels ui->ui_flags = 1; /* mark it online */ 922*17553Skarels ra_info[ui->ui_unit].radsize=(daddr_t)mp->mscp_untsize; 923*17553Skarels #ifdef DEBUG 9244743Swnj printd("uda: unit %d online\n", mp->mscp_unit); 925*17553Skarels #endif 926*17553Skarels #define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') 927*17553Skarels /* this mess decodes the Media type identifier */ 928*17553Skarels #ifdef DEBUG 929*17553Skarels printd("uda: unit %d online %x %c%c %c%c%c%d\n" 930*17553Skarels ,mp->mscp_unit, mp->mscp_mediaid 931*17553Skarels ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) 932*17553Skarels ,F_to_C(mp,1),F_to_C(mp,0) 933*17553Skarels ,mp->mscp_mediaid & 0x7f); 934*17553Skarels #endif 935*17553Skarels switch(mp->mscp_mediaid & 0x7f){ 936*17553Skarels case 25: 937*17553Skarels ra_info[ui->ui_unit].ra_sizes = ra25_sizes; 938*17553Skarels break; 939*17553Skarels case 60: 940*17553Skarels ra_info[ui->ui_unit].ra_sizes = ra60_sizes; 941*17553Skarels break; 942*17553Skarels case 80: 943*17553Skarels ra_info[ui->ui_unit].ra_sizes = ra80_sizes; 944*17553Skarels break; 945*17553Skarels case 81: 946*17553Skarels ra_info[ui->ui_unit].ra_sizes = ra81_sizes; 947*17553Skarels break; 948*17553Skarels default: 949*17553Skarels ui->ui_flags = 0; /* mark it offline */ 950*17553Skarels ra_info[ui->ui_unit].ratype = 0; 951*17553Skarels printf("Don't have a parition table for "); 952*17553Skarels printf("a %c%c %c%c%c%d\n" 953*17553Skarels ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) 954*17553Skarels ,F_to_C(mp,1),F_to_C(mp,0) 955*17553Skarels ,mp->mscp_mediaid & 0x7f); 956*17553Skarels while (bp = dp->b_actf) { 957*17553Skarels dp->b_actf = bp->av_forw; 958*17553Skarels bp->b_flags |= B_ERROR; 959*17553Skarels iodone(bp); 960*17553Skarels } 961*17553Skarels } 962*17553Skarels dp->b_active = 1; 9634743Swnj } else { 964*17553Skarels if(dp->b_actf){ 965*17553Skarels harderr(dp->b_actf,"ra"); 966*17553Skarels } else { 967*17553Skarels nullbp.b_blkno = 0; 968*17553Skarels nullbp.b_dev = makedev(UDADEVNUM,ui->ui_unit); 969*17553Skarels harderr(&nullbp, "ra"); 970*17553Skarels } 9714743Swnj printf("OFFLINE\n"); 9724743Swnj while (bp = dp->b_actf) { 9734743Swnj dp->b_actf = bp->av_forw; 9744743Swnj bp->b_flags |= B_ERROR; 9754743Swnj iodone(bp); 9764743Swnj } 9774743Swnj } 978*17553Skarels if(mp->mscp_cmdref!=NULL){/* Seems to get lost sometimes */ 979*17553Skarels wakeup((caddr_t *) mp->mscp_cmdref); 980*17553Skarels } 9814743Swnj break; 9824743Swnj 983*17553Skarels /* 984*17553Skarels * The AVAILABLE ATTENTION messages occurs when the 985*17553Skarels * unit becomes available after spinup, 986*17553Skarels * marking the unit offline will force an online command 987*17553Skarels * prior to using the unit. 988*17553Skarels */ 9894743Swnj case M_OP_AVATN: 990*17553Skarels #ifdef DEBUG 9914743Swnj printd("uda: unit %d attention\n", mp->mscp_unit); 992*17553Skarels #endif 993*17553Skarels ui->ui_flags = 0; /* it went offline and we didn't notice */ 994*17553Skarels ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; 9954743Swnj break; 9964743Swnj 997*17553Skarels case M_OP_END: 998*17553Skarels /* 999*17553Skarels * An endcode without an opcode (0200) is an invalid command. 1000*17553Skarels * The mscp specification states that this would be a protocol 1001*17553Skarels * type error, such as illegal opcodes. The mscp spec. also 1002*17553Skarels * states that parameter error type of invalid commands should 1003*17553Skarels * return the normal end message for the command. This does not appear 1004*17553Skarels * to be the case. An invalid logical block number returned an endcode 1005*17553Skarels * of 0200 instead of the 0241 (read) that was expected. 1006*17553Skarels */ 1007*17553Skarels 1008*17553Skarels printf("endcd=%o, stat=%o\n", mp->mscp_opcode, mp->mscp_status); 1009*17553Skarels break; 10104743Swnj case M_OP_READ|M_OP_END: 10114743Swnj case M_OP_WRITE|M_OP_END: 10124743Swnj bp = (struct buf *)mp->mscp_cmdref; 10136964Ssam ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); 10144743Swnj /* 10154743Swnj * Unlink buffer from I/O wait queue. 10164743Swnj */ 10174743Swnj bp->av_back->av_forw = bp->av_forw; 10184743Swnj bp->av_forw->av_back = bp->av_back; 101912421Ssam #if defined(VAX750) 102012421Ssam if (cpu == VAX_750 102112421Ssam && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { 102212421Ssam if (um->um_ubinfo == 0) 102312421Ssam printf("udintr: um_ubinfo == 0\n"); 102412421Ssam else 102512421Ssam ubarelse(um->um_ubanum, &um->um_ubinfo); 102612421Ssam } 102712421Ssam #endif 10284743Swnj dp = &udutab[ui->ui_unit]; 1029*17553Skarels dp->b_qsize--; 10304743Swnj if (ui->ui_dk >= 0) 1031*17553Skarels if (dp->b_qsize == 0) 10324743Swnj dk_busy &= ~(1<<ui->ui_dk); 10334743Swnj if (st == M_ST_OFFLN || st == M_ST_AVLBL) { 1034*17553Skarels ui->ui_flags = 0; /* mark unit offline */ 10354743Swnj /* 10364743Swnj * Link the buffer onto the front of the drive queue 10374743Swnj */ 10384743Swnj if ((bp->av_forw = dp->b_actf) == 0) 10394743Swnj dp->b_actl = bp; 10404743Swnj dp->b_actf = bp; 10414743Swnj /* 10424743Swnj * Link the drive onto the controller queue 10434743Swnj */ 10444743Swnj if (dp->b_active == 0) { 10454743Swnj dp->b_forw = NULL; 10464743Swnj if (um->um_tab.b_actf == NULL) 10474743Swnj um->um_tab.b_actf = dp; 10484743Swnj else 10494743Swnj um->um_tab.b_actl->b_forw = dp; 10504743Swnj um->um_tab.b_actl = dp; 10514743Swnj dp->b_active = 1; 10524743Swnj } 105312421Ssam #if defined(VAX750) 105412421Ssam if (cpu == VAX750 && um->um_ubinfo == 0) 105512421Ssam um->um_ubinfo = 105612421Ssam uballoc(um->um_ubanum, (caddr_t)0, 0, 105712421Ssam UBA_NEEDBDP); 105812421Ssam #endif 10594743Swnj return; 10604743Swnj } 10614743Swnj if (st != M_ST_SUCC) { 10624743Swnj harderr(bp, "ra"); 1063*17553Skarels #ifdef DEBUG 1064*17553Skarels printd("status %o\n", mp->mscp_status); 1065*17553Skarels #endif 10664743Swnj bp->b_flags |= B_ERROR; 10674743Swnj } 10684743Swnj bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; 10694743Swnj iodone(bp); 10704743Swnj break; 10714743Swnj 10724743Swnj case M_OP_GTUNT|M_OP_END: 1073*17553Skarels #ifdef DEBUG 1074*17553Skarels printd("GTUNT end packet status = 0x%x media id 0x%x\n" 1075*17553Skarels ,st,mp->mscp_mediaid); 1076*17553Skarels #endif 1077*17553Skarels ra_info[ui->ui_unit].rastatus = st; 1078*17553Skarels ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; 10794743Swnj break; 10804743Swnj 10814743Swnj default: 10824743Swnj printf("uda: unknown packet\n"); 1083*17553Skarels uderror(um, (struct mslg *)mp); 10844743Swnj } 10854743Swnj } 10864743Swnj 10874743Swnj 10884743Swnj /* 10894743Swnj * Process an error log message 10904743Swnj * 10914743Swnj * For now, just log the error on the console. 10924743Swnj * Only minimal decoding is done, only "useful" 10934743Swnj * information is printed. Eventually should 10944743Swnj * send message to an error logger. 10954743Swnj */ 10964743Swnj uderror(um, mp) 10974743Swnj register struct uba_ctlr *um; 10984743Swnj register struct mslg *mp; 10994743Swnj { 1100*17553Skarels register i; 1101*17553Skarels 1102*17553Skarels 1103*17553Skarels if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) 1104*17553Skarels printf("uda%d: hard error\n"); 1105*17553Skarels 1106*17553Skarels mprintf("uda%d: %s error, ", um->um_ctlr, 1107*17553Skarels mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); 11084743Swnj switch (mp->mslg_format) { 11094743Swnj case M_FM_CNTERR: 1110*17553Skarels mprintf("controller error, event 0%o\n", mp->mslg_event); 11114743Swnj break; 11124743Swnj 11134743Swnj case M_FM_BUSADDR: 1114*17553Skarels mprintf("host memory access error, event 0%o, addr 0%o\n", 11159174Ssam mp->mslg_event, mp->mslg_busaddr); 11164743Swnj break; 11174743Swnj 11184743Swnj case M_FM_DISKTRN: 1119*17553Skarels mprintf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x, event 0%o\n", 1120*17553Skarels mp->mslg_unit, mp->mslg_group, mp->mslg_hdr, 1121*17553Skarels mp->mslg_event); 11224743Swnj break; 11234743Swnj 11244743Swnj case M_FM_SDI: 1125*17553Skarels mprintf("SDI error, unit %d, event 0%o, hdr 0x%x\n", 112612421Ssam mp->mslg_unit, mp->mslg_event, mp->mslg_hdr); 1127*17553Skarels for(i = 0; i < 12;i++) 1128*17553Skarels mprintf("\t0x%x",mp->mslg_sdistat[i] & 0xff); 1129*17553Skarels mprintf("\n"); 11304743Swnj break; 11314743Swnj 11324743Swnj case M_FM_SMLDSK: 1133*17553Skarels mprintf("small disk error, unit %d, event 0%o, cyl %d\n", 11344743Swnj mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl); 11354743Swnj break; 11364743Swnj 11374743Swnj default: 1138*17553Skarels mprintf("unknown error, unit %d, format 0%o, event 0%o\n", 11394743Swnj mp->mslg_unit, mp->mslg_format, mp->mslg_event); 11404743Swnj } 11416964Ssam 11426964Ssam if (udaerror) { 11436964Ssam register long *p = (long *)mp; 11446964Ssam 11456964Ssam for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p)) 11466964Ssam printf("%x ", *p++); 11476964Ssam printf("\n"); 11486964Ssam } 11494743Swnj } 11504743Swnj 11514743Swnj 11524743Swnj /* 11534743Swnj * Find an unused command packet 11544743Swnj */ 11554743Swnj struct mscp * 11564743Swnj udgetcp(um) 11574743Swnj struct uba_ctlr *um; 11584743Swnj { 11594743Swnj register struct mscp *mp; 11604743Swnj register struct udaca *cp; 11614743Swnj register struct uda_softc *sc; 11624743Swnj register int i; 1163*17553Skarels int s; 11644743Swnj 1165*17553Skarels s = spl5(); 11664743Swnj cp = &uda[um->um_ctlr].uda_ca; 11674743Swnj sc = &uda_softc[um->um_ctlr]; 1168*17553Skarels /* 1169*17553Skarels * If no credits, can't issue any commands 1170*17553Skarels * until some outstanding commands complete. 1171*17553Skarels */ 11724743Swnj i = sc->sc_lastcmd; 1173*17553Skarels if(((cp->ca_cmddsc[i]&(UDA_OWN|UDA_INT))==UDA_INT)&& 1174*17553Skarels (sc->sc_credits >= 2)) { 1175*17553Skarels sc->sc_credits--; /* committed to issuing a command */ 11764743Swnj cp->ca_cmddsc[i] &= ~UDA_INT; 11774743Swnj mp = &uda[um->um_ctlr].uda_cmd[i]; 11784743Swnj mp->mscp_unit = mp->mscp_modifier = 0; 11794743Swnj mp->mscp_opcode = mp->mscp_flags = 0; 11804743Swnj mp->mscp_bytecnt = mp->mscp_buffer = 0; 11814743Swnj mp->mscp_errlgfl = mp->mscp_copyspd = 0; 11824743Swnj sc->sc_lastcmd = (i + 1) % NCMD; 1183*17553Skarels (void) splx(s); 11844743Swnj return(mp); 11854743Swnj } 1186*17553Skarels (void) splx(s); 11874743Swnj return(NULL); 11884743Swnj } 11894743Swnj 11907734Sroot udread(dev, uio) 11914743Swnj dev_t dev; 11927734Sroot struct uio *uio; 11934743Swnj { 11944743Swnj register int unit = minor(dev) >> 3; 11954743Swnj 1196*17553Skarels if (unit >= nNRA) 11978165Sroot return (ENXIO); 11988165Sroot return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio)); 11994743Swnj } 12004743Swnj 12017845Sroot udwrite(dev, uio) 12024743Swnj dev_t dev; 12037845Sroot struct uio *uio; 12044743Swnj { 12054743Swnj register int unit = minor(dev) >> 3; 12064743Swnj 1207*17553Skarels if (unit >= nNRA) 12088165Sroot return (ENXIO); 12098165Sroot return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio)); 12104743Swnj } 12114743Swnj 12124743Swnj udreset(uban) 12134743Swnj int uban; 12144743Swnj { 12154743Swnj register struct uba_ctlr *um; 12164743Swnj register struct uba_device *ui; 12174743Swnj register struct buf *bp, *dp; 12184743Swnj register int unit; 12194743Swnj struct buf *nbp; 12204743Swnj int d; 12214743Swnj 12224743Swnj for (d = 0; d < NUDA; d++) { 12234743Swnj if ((um = udminfo[d]) == 0 || um->um_ubanum != uban || 12244743Swnj um->um_alive == 0) 12254743Swnj continue; 12264743Swnj printf(" uda%d", d); 12274743Swnj um->um_tab.b_active = 0; 12284743Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 12294743Swnj uda_softc[d].sc_state = S_IDLE; 1230*17553Skarels uda_softc[d].sc_mapped = 0; /* Rich */ 1231*17553Skarels for (unit = 0; unit < nNRA; unit++) { 12324743Swnj if ((ui = uddinfo[unit]) == 0) 12334743Swnj continue; 12344743Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 12354743Swnj continue; 12364743Swnj udutab[unit].b_active = 0; 12374743Swnj udutab[unit].b_qsize = 0; 12384743Swnj } 12394743Swnj for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) { 12404743Swnj nbp = bp->av_forw; 12418576Sroot bp->b_ubinfo = 0; 12424743Swnj /* 12434743Swnj * Link the buffer onto the drive queue 12444743Swnj */ 12454743Swnj dp = &udutab[dkunit(bp)]; 12464743Swnj if (dp->b_actf == 0) 12474743Swnj dp->b_actf = bp; 12484743Swnj else 12494743Swnj dp->b_actl->av_forw = bp; 12504743Swnj dp->b_actl = bp; 12514743Swnj bp->av_forw = 0; 12524743Swnj /* 12534743Swnj * Link the drive onto the controller queue 12544743Swnj */ 12554743Swnj if (dp->b_active == 0) { 12564743Swnj dp->b_forw = NULL; 12574743Swnj if (um->um_tab.b_actf == NULL) 12584743Swnj um->um_tab.b_actf = dp; 12594743Swnj else 12604743Swnj um->um_tab.b_actl->b_forw = dp; 12614743Swnj um->um_tab.b_actl = dp; 12624743Swnj dp->b_active = 1; 12634743Swnj } 12644743Swnj } 12654743Swnj udinit(d); 12664743Swnj } 12674743Swnj } 12684743Swnj 1269*17553Skarels #define DBSIZE 32 1270*17553Skarels 1271*17553Skarels #define ca_Rspdsc ca_rspdsc[0] 1272*17553Skarels #define ca_Cmddsc ca_rspdsc[1] 1273*17553Skarels #define uda_Rsp uda_rsp[0] 1274*17553Skarels #define uda_Cmd uda_cmd[0] 1275*17553Skarels 1276*17553Skarels struct uda udad[NUDA]; 1277*17553Skarels 1278*17553Skarels uddump(dev) 1279*17553Skarels dev_t dev; 12804743Swnj { 1281*17553Skarels struct udadevice *udaddr; 1282*17553Skarels struct uda *ud_ubaddr; 1283*17553Skarels char *start; 1284*17553Skarels int num, blk, unit; 1285*17553Skarels int maxsz; 1286*17553Skarels int blkoff; 1287*17553Skarels register struct uba_regs *uba; 1288*17553Skarels register struct uba_device *ui; 1289*17553Skarels register struct uda *udp; 1290*17553Skarels register struct pte *io; 1291*17553Skarels register int i; 1292*17553Skarels struct size *rasizes; 1293*17553Skarels unit = minor(dev) >> 3; 1294*17553Skarels if (unit >= nNRA) 1295*17553Skarels return (ENXIO); 1296*17553Skarels #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 1297*17553Skarels ui = phys(struct uba_device *, uddinfo[unit]); 1298*17553Skarels if (ui->ui_alive == 0) 1299*17553Skarels return (ENXIO); 1300*17553Skarels uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 1301*17553Skarels ubainit(uba); 1302*17553Skarels udaddr = (struct udadevice *)ui->ui_physaddr; 1303*17553Skarels DELAY(2000000); 1304*17553Skarels udp = phys(struct uda *, &udad[ui->ui_ctlr]); 1305*17553Skarels 1306*17553Skarels num = btoc(sizeof(struct uda)) + 1; 1307*17553Skarels io = &uba->uba_map[NUBMREG-num]; 1308*17553Skarels for(i = 0; i<num; i++) 1309*17553Skarels *(int *)io++ = UBAMR_MRV|(btop(udp)+i); 1310*17553Skarels ud_ubaddr = (struct uda *)(((int)udp & PGOFSET)|((NUBMREG-num)<<9)); 1311*17553Skarels 1312*17553Skarels udaddr->udaip = 0; 1313*17553Skarels while ((udaddr->udasa & UDA_STEP1) == 0) 1314*17553Skarels if(udaddr->udasa & UDA_ERR) return(EFAULT); 1315*17553Skarels udaddr->udasa = UDA_ERR; 1316*17553Skarels while ((udaddr->udasa & UDA_STEP2) == 0) 1317*17553Skarels if(udaddr->udasa & UDA_ERR) return(EFAULT); 1318*17553Skarels udaddr->udasa = (short)&ud_ubaddr->uda_ca.ca_ringbase; 1319*17553Skarels while ((udaddr->udasa & UDA_STEP3) == 0) 1320*17553Skarels if(udaddr->udasa & UDA_ERR) return(EFAULT); 1321*17553Skarels udaddr->udasa = (short)(((int)&ud_ubaddr->uda_ca.ca_ringbase) >> 16); 1322*17553Skarels while ((udaddr->udasa & UDA_STEP4) == 0) 1323*17553Skarels if(udaddr->udasa & UDA_ERR) return(EFAULT); 1324*17553Skarels udaddr->udasa = UDA_GO; 1325*17553Skarels udp->uda_ca.ca_Rspdsc = (long)&ud_ubaddr->uda_Rsp.mscp_cmdref; 1326*17553Skarels udp->uda_ca.ca_Cmddsc = (long)&ud_ubaddr->uda_Cmd.mscp_cmdref; 1327*17553Skarels udp->uda_Cmd.mscp_cntflgs = 0; 1328*17553Skarels udp->uda_Cmd.mscp_version = 0; 1329*17553Skarels if (udcmd(M_OP_STCON, udp, udaddr) == 0) { 1330*17553Skarels return(EFAULT); 1331*17553Skarels } 1332*17553Skarels udp->uda_Cmd.mscp_unit = ui->ui_slave; 1333*17553Skarels if (udcmd(M_OP_ONLIN, udp, udaddr) == 0) { 1334*17553Skarels return(EFAULT); 1335*17553Skarels } 1336*17553Skarels 1337*17553Skarels num = maxfree; 1338*17553Skarels start = 0; 1339*17553Skarels rasizes = ra_info[ui->ui_unit].ra_sizes; 1340*17553Skarels maxsz = rasizes[minor(dev)&07].nblocks; 1341*17553Skarels blkoff = rasizes[minor(dev)&07].blkoff; 1342*17553Skarels if(maxsz < 0) 1343*17553Skarels maxsz = ra_info[unit].radsize-blkoff; 1344*17553Skarels if (dumplo < 0 || dumplo + num >= maxsz) 1345*17553Skarels return (EINVAL); 1346*17553Skarels blkoff += dumplo; 1347*17553Skarels while (num > 0) { 1348*17553Skarels blk = num > DBSIZE ? DBSIZE : num; 1349*17553Skarels io = uba->uba_map; 1350*17553Skarels for (i = 0; i < blk; i++) 1351*17553Skarels *(int *)io++ = (btop(start)+i) | UBAMR_MRV; 1352*17553Skarels *(int *)io = 0; 1353*17553Skarels udp->uda_Cmd.mscp_lbn = btop(start) + blkoff; 1354*17553Skarels udp->uda_Cmd.mscp_unit = ui->ui_slave; 1355*17553Skarels udp->uda_Cmd.mscp_bytecnt = blk*NBPG; 1356*17553Skarels udp->uda_Cmd.mscp_buffer = 0; 1357*17553Skarels if (udcmd(M_OP_WRITE, udp, udaddr) == 0) { 1358*17553Skarels return(EIO); 1359*17553Skarels } 1360*17553Skarels start += blk*NBPG; 1361*17553Skarels num -= blk; 1362*17553Skarels } 1363*17553Skarels return (0); 13644743Swnj } 1365*17553Skarels 1366*17553Skarels 1367*17553Skarels udcmd(op, udp, udaddr) 1368*17553Skarels int op; 1369*17553Skarels register struct uda *udp; 1370*17553Skarels struct udadevice *udaddr; 1371*17553Skarels { 1372*17553Skarels int i; 1373*17553Skarels 1374*17553Skarels #ifdef lint 1375*17553Skarels i = i; 1376*17553Skarels #endif 1377*17553Skarels 1378*17553Skarels udp->uda_Cmd.mscp_opcode = op; 1379*17553Skarels udp->uda_Rsp.mscp_header.uda_msglen = mscp_msglen; 1380*17553Skarels udp->uda_Cmd.mscp_header.uda_msglen = mscp_msglen; 1381*17553Skarels udp->uda_ca.ca_Rspdsc |= UDA_OWN|UDA_INT; 1382*17553Skarels udp->uda_ca.ca_Cmddsc |= UDA_OWN|UDA_INT; 1383*17553Skarels if (udaddr->udasa&UDA_ERR) 1384*17553Skarels printf("Udaerror udasa (%x)\n", udaddr->udasa&0xffff); 1385*17553Skarels i = udaddr->udaip; 1386*17553Skarels for (;;) { 1387*17553Skarels if (udp->uda_ca.ca_cmdint) 1388*17553Skarels udp->uda_ca.ca_cmdint = 0; 1389*17553Skarels if (udp->uda_ca.ca_rspint) 1390*17553Skarels break; 1391*17553Skarels } 1392*17553Skarels udp->uda_ca.ca_rspint = 0; 1393*17553Skarels if (udp->uda_Rsp.mscp_opcode != (op|M_OP_END) || 1394*17553Skarels (udp->uda_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) { 1395*17553Skarels printf("error: com %d opc 0x%x stat 0x%x\ndump ", 1396*17553Skarels op, 1397*17553Skarels udp->uda_Rsp.mscp_opcode, 1398*17553Skarels udp->uda_Rsp.mscp_status); 1399*17553Skarels return(0); 1400*17553Skarels } 1401*17553Skarels return(1); 1402*17553Skarels } 1403*17553Skarels 140412511Ssam udsize(dev) 140512511Ssam dev_t dev; 140612511Ssam { 140712511Ssam int unit = minor(dev) >> 3; 140812511Ssam struct uba_device *ui; 1409*17553Skarels struct size *rasizes; 141012511Ssam 1411*17553Skarels if (unit >= nNRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0 1412*17553Skarels || ui->ui_flags == 0) 141312511Ssam return (-1); 1414*17553Skarels rasizes = ra_info[ui->ui_unit].ra_sizes; 1415*17553Skarels return (rasizes[minor(dev) & 07].nblocks); 141612511Ssam } 1417*17553Skarels 141812511Ssam #endif 1419