|
|
1.1 ! root 1: /* ! 2: * @(#)uda.c 7.1 (Berkeley) 6/5/86 ! 3: */ ! 4: ! 5: /************************************************************************ ! 6: * * ! 7: * Copyright (c) 1983 by * ! 8: * Digital Equipment Corporation, Maynard, MA * ! 9: * All rights reserved. * ! 10: * * ! 11: ************************************************************************/ ! 12: /* ! 13: * uda.c - UDA50A Driver ! 14: * ! 15: * decvax!rich ! 16: */ ! 17: ! 18: #define DEBUG ! 19: #define UDADEVNUM (9) /* entry in bdevsw */ ! 20: #include "ra.h" ! 21: #if NUDA > 0 ! 22: /* ! 23: * UDA50/RAxx disk device driver ! 24: * ! 25: * Restrictions: ! 26: * Unit numbers must be less than 8. ! 27: */ ! 28: #include "../machine/pte.h" ! 29: ! 30: #include "param.h" ! 31: #include "systm.h" ! 32: #include "buf.h" ! 33: #include "conf.h" ! 34: #include "dir.h" ! 35: #include "user.h" ! 36: #include "map.h" ! 37: #include "vm.h" ! 38: #include "dk.h" ! 39: #include "cmap.h" ! 40: #include "uio.h" ! 41: ! 42: #include "../vax/cpu.h" ! 43: #include "ubareg.h" ! 44: #include "ubavar.h" ! 45: #include "../vax/mtpr.h" ! 46: ! 47: #define TENSEC (1000) ! 48: ! 49: #define NRSPL2 3 /* log2 number of response packets */ ! 50: #define NCMDL2 3 /* log2 number of command packets */ ! 51: #define NRSP (1<<NRSPL2) ! 52: #define NCMD (1<<NCMDL2) ! 53: #define UDABURST 4 /* default for DMA burst size */ ! 54: ! 55: #include "../vaxuba/udareg.h" ! 56: #include "../vax/mscp.h" ! 57: ! 58: ! 59: struct uda_softc { ! 60: short sc_state; /* state of controller */ ! 61: short sc_mapped; /* Unibus map allocated for uda struct? */ ! 62: int sc_ubainfo; /* Unibus mapping info */ ! 63: struct uda *sc_uda; /* Unibus address of uda struct */ ! 64: int sc_ivec; /* interrupt vector address */ ! 65: short sc_credits; /* transfer credits */ ! 66: short sc_lastcmd; /* pointer into command ring */ ! 67: short sc_lastrsp; /* pointer into response ring */ ! 68: } uda_softc[NUDA]; ! 69: struct uda { ! 70: struct udaca uda_ca; /* communications area */ ! 71: struct mscp uda_rsp[NRSP]; /* response packets */ ! 72: struct mscp uda_cmd[NCMD]; /* command packets */ ! 73: } uda[NUDA]; ! 74: ! 75: #define udunit(dev) (minor(dev) >> 3) ! 76: ! 77: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 78: struct size { ! 79: daddr_t nblocks; ! 80: daddr_t blkoff; ! 81: } ra25_sizes[8] = { ! 82: 15884, 0, /* A=blk 0 thru 15883 */ ! 83: 10032, 15884, /* B=blk 15884 thru 49323 */ ! 84: -1, 0, /* C=blk 0 thru end */ ! 85: 0, 0, /* D=blk 340670 thru 356553 */ ! 86: 0, 0, /* E=blk 356554 thru 412489 */ ! 87: 0, 0, /* F=blk 412490 thru end */ ! 88: -1, 25916, /* G=blk 49324 thru 131403 */ ! 89: 0, 0, /* H=blk 131404 thru end */ ! 90: }, rd52_sizes[8] = { ! 91: 15884, 0, /* A=blk 0 thru 15883 */ ! 92: 9766, 15884, /* B=blk 15884 thru 25649 */ ! 93: -1, 0, /* C=blk 0 thru end */ ! 94: 0, 0, /* D=unused */ ! 95: 0, 0, /* E=unused */ ! 96: 0, 0, /* F=unused */ ! 97: -1, 25650, /* G=blk 25650 thru end */ ! 98: 0, 0, /* H=unused */ ! 99: }, rd53_sizes[8] = { ! 100: 15884, 0, /* A=blk 0 thru 15883 */ ! 101: 33440, 15884, /* B=blk 15884 thru 49323 */ ! 102: -1, 0, /* C=blk 0 thru end */ ! 103: 0, 0, /* D=unused */ ! 104: 33440, 0, /* E=blk 0 thru 33439 */ ! 105: -1, 33440, /* F=blk 33440 thru end */ ! 106: -1, 49324, /* G=blk 49324 thru end */ ! 107: -1, 15884, /* H=blk 15884 thru end */ ! 108: }, ra60_sizes[8] = { ! 109: 15884, 0, /* A=sectors 0 thru 15883 */ ! 110: 33440, 15884, /* B=sectors 15884 thru 49323 */ ! 111: 400176, 0, /* C=sectors 0 thru 400175 */ ! 112: 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ ! 113: 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ ! 114: 350852, 49324, /* F=sectors 49324 thru 400175 */ ! 115: 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ ! 116: 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */ ! 117: }, ra80_sizes[8] = { ! 118: 15884, 0, /* A=sectors 0 thru 15883 */ ! 119: 33440, 15884, /* B=sectors 15884 thru 49323 */ ! 120: 242606, 0, /* C=sectors 0 thru 242605 */ ! 121: 0, 0, /* D=unused */ ! 122: 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ ! 123: 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ ! 124: 192696, 49910, /* G=sectors 49910 thru 242605 */ ! 125: 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */ ! 126: }, ra81_sizes[8] ={ ! 127: /* ! 128: * These are the new standard partition sizes for ra81's. ! 129: * An RA_COMPAT system is compiled with D, E, and F corresponding ! 130: * to the 4.2 partitions for G, H, and F respectively. ! 131: */ ! 132: #ifndef UCBRA ! 133: 15884, 0, /* A=sectors 0 thru 15883 */ ! 134: 66880, 16422, /* B=sectors 16422 thru 83301 */ ! 135: 891072, 0, /* C=sectors 0 thru 891071 */ ! 136: #ifdef RA_COMPAT ! 137: 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ ! 138: 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ ! 139: 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */ ! 140: #else ! 141: 15884, 375564, /* D=sectors 375564 thru 391447 */ ! 142: 307200, 391986, /* E=sectors 391986 thru 699185 */ ! 143: 191352, 699720, /* F=sectors 699720 thru 891071 */ ! 144: #endif RA_COMPAT ! 145: 515508, 375564, /* G=sectors 375564 thru 891071 */ ! 146: 291346, 83538, /* H=sectors 83538 thru 374883 */ ! 147: ! 148: /* ! 149: * These partitions correspond to the sizes used by sites at Berkeley, ! 150: * and by those sites that have received copies of the Berkeley driver ! 151: * with deltas 6.2 or greater (11/15/83). ! 152: */ ! 153: #else UCBRA ! 154: ! 155: 15884, 0, /* A=sectors 0 thru 15883 */ ! 156: 33440, 15884, /* B=sectors 15884 thru 49323 */ ! 157: 891072, 0, /* C=sectors 0 thru 891071 */ ! 158: 15884, 242606, /* D=sectors 242606 thru 258489 */ ! 159: 307200, 258490, /* E=sectors 258490 thru 565689 */ ! 160: 325382, 565690, /* F=sectors 565690 thru 891071 */ ! 161: 648466, 242606, /* G=sectors 242606 thru 891071 */ ! 162: 193282, 49324, /* H=sectors 49324 thru 242605 */ ! 163: ! 164: #endif UCBRA ! 165: }; ! 166: ! 167: struct ra_info { ! 168: struct size *ra_sizes; /* Partion tables for drive */ ! 169: daddr_t radsize; /* Max user size form online pkt */ ! 170: unsigned ratype; /* Drive type int field */ ! 171: unsigned rastatus; /* Command status from */ ! 172: /* last onlin or GTUNT */ ! 173: } ra_info[NRA]; ! 174: ! 175: ! 176: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 177: struct uba_ctlr *udminfo[NUDA]; ! 178: struct uba_device *uddinfo[NRA]; ! 179: struct uba_device *udip[NUDA][8]; /* 8 == max number of drives */ ! 180: struct buf rudbuf[NRA]; ! 181: struct buf udutab[NRA]; ! 182: struct buf udwtab[NUDA]; /* I/O wait queue, per controller */ ! 183: ! 184: ! 185: int udamicro[NUDA]; /* to store microcode level */ ! 186: int udaburst[NUDA] = { 0 }; /* DMA burst size, 0 is default */ ! 187: ! 188: ! 189: /* ! 190: * Controller states ! 191: */ ! 192: #define S_IDLE 0 /* hasn't been initialized */ ! 193: #define S_STEP1 1 /* doing step 1 init */ ! 194: #define S_STEP2 2 /* doing step 2 init */ ! 195: #define S_STEP3 3 /* doing step 3 init */ ! 196: #define S_SCHAR 4 /* doing "set controller characteristics" */ ! 197: #define S_RUN 5 /* running */ ! 198: ! 199: ! 200: int udaerror = 0; /* causes hex dump of packets */ ! 201: int udadebug = 0; ! 202: int uda_cp_wait = 0; /* Something to wait on for command */ ! 203: /* packets and or credits. */ ! 204: int wakeup(); ! 205: extern int hz; /* Should find the right include */ ! 206: #ifdef DEBUG ! 207: #define printd if (udadebug) printf ! 208: #define printd10 if(udadebug >= 10) printf ! 209: #endif ! 210: #define mprintf printf /* temporary JG hack until Rich fixes*/ ! 211: ! 212: int udprobe(), udslave(), udattach(), udintr(); ! 213: struct mscp *udgetcp(); ! 214: ! 215: u_short udstd[] = { 0772150, 0772550, 0777550, 0 }; ! 216: struct uba_driver udadriver = ! 217: { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 }; ! 218: ! 219: #define b_qsize b_resid /* queue size per drive, in udutab */ ! 220: #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ ! 221: ! 222: udprobe(reg, ctlr) ! 223: caddr_t reg; ! 224: int ctlr; ! 225: { ! 226: register int br, cvec; ! 227: register struct uda_softc *sc = &uda_softc[ctlr]; ! 228: struct udadevice *udaddr; ! 229: ! 230: int cur_time; ! 231: ! 232: #ifdef lint ! 233: br = 0; cvec = br; br = cvec; ! 234: udreset(0); udintr(0); ! 235: #endif ! 236: udaddr = (struct udadevice *) reg; ! 237: ! 238: sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); ! 239: #if VAX630 ! 240: if (cpu == VAX_630) { ! 241: br = 0x15; ! 242: cvec = sc->sc_ivec; ! 243: return(sizeof (struct udadevice)); ! 244: } ! 245: #endif ! 246: udaddr->udaip = 0; /* start initialization */ ! 247: ! 248: cur_time = mfpr(TODR); /* Time of day */ ! 249: while(cur_time + TENSEC > mfpr(TODR)){ /* wait for at most 10 secs */ ! 250: if((udaddr->udasa & UDA_STEP1) != 0) ! 251: break; ! 252: } ! 253: if(cur_time + TENSEC <= mfpr(TODR)) ! 254: return(0); /* Not a uda or it won't init as it */ ! 255: /* should within ten seconds. */ ! 256: udaddr->udasa=UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); ! 257: while((udaddr->udasa&UDA_STEP2)==0) ! 258: DELAY(1000); /* intr should have */ ! 259: /* have happened by now */ ! 260: ! 261: return(sizeof (struct udadevice)); ! 262: } ! 263: ! 264: /* ARGSUSED */ ! 265: udslave(ui, reg) ! 266: struct uba_device *ui; ! 267: caddr_t reg; ! 268: { ! 269: register struct uba_ctlr *um = udminfo[ui->ui_ctlr]; ! 270: register struct uda_softc *sc = &uda_softc[ui->ui_ctlr]; ! 271: struct udadevice *udaddr; ! 272: struct mscp *mp; ! 273: int i; /* Something to write into to start */ ! 274: /* the uda polling */ ! 275: ! 276: ! 277: udaddr = (struct udadevice *)um->um_addr; ! 278: if(sc->sc_state != S_RUN){ ! 279: if(!udinit(ui->ui_ctlr)) ! 280: return(0); ! 281: } ! 282: /* Here we will wait for the controller */ ! 283: /* to come into the run state or go idle. If we go idle we are in */ ! 284: /* touble and I don't yet know what to do so I will punt */ ! 285: while(sc->sc_state != S_RUN && sc->sc_state != S_IDLE); /* spin */ ! 286: if(sc->sc_state == S_IDLE){ /* The Uda failed to initialize */ ! 287: printf("UDA failed to init\n"); ! 288: return(0); ! 289: } ! 290: /* The controller is up so let see if the drive is there! */ ! 291: if(0 == (mp = udgetcp(um))){ /* ditto */ ! 292: printf("UDA can't get command packet\n"); ! 293: return(0); ! 294: } ! 295: mp->mscp_opcode = M_OP_GTUNT; /* This should give us the drive type*/ ! 296: mp->mscp_unit = ui->ui_slave; ! 297: mp->mscp_cmdref = (long) ui->ui_slave; ! 298: #ifdef DEBUG ! 299: printd("uda%d Get unit status slave %d\n",ui->ui_ctlr,ui->ui_slave); ! 300: #endif ! 301: ra_info[ui->ui_unit].rastatus = 0; /* set to zero */ ! 302: udip[ui->ui_ctlr][ui->ui_slave] = ui; ! 303: *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT;/* maybe we should poll*/ ! 304: i = udaddr->udaip; ! 305: #ifdef lint ! 306: i = i; ! 307: #endif ! 308: while(!ra_info[ui->ui_unit].rastatus); /* Wait for some status */ ! 309: udip[ui->ui_ctlr][ui->ui_slave] = 0; ! 310: if(!ra_info[ui->ui_unit].ratype) /* packet from a GTUNT */ ! 311: return(0); /* Failed No such drive */ ! 312: else ! 313: return(1); /* Got it and it is there */ ! 314: } ! 315: ! 316: udattach(ui) ! 317: register struct uba_device *ui; ! 318: { ! 319: register struct uba_ctlr *um = ui->ui_mi ; ! 320: struct udadevice *udaddr = (struct udadevice *) um->um_addr; ! 321: struct mscp *mp; ! 322: int i; /* Something to write into to start */ ! 323: /* the uda polling */ ! 324: if (ui->ui_dk >= 0) ! 325: dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ ! 326: ui->ui_flags = 0; ! 327: udip[ui->ui_ctlr][ui->ui_slave] = ui; ! 328: /* check to see if the drive is a available if it is bring it online */ ! 329: /* if not then just return. open will try an online later */ ! 330: if(ra_info[ui->ui_unit].rastatus != M_ST_AVLBL) ! 331: return; /* status was set by a GTUNT */ ! 332: if(0 == (mp = udgetcp(um))){ /* ditto */ ! 333: printf("UDA can't get command packet\n"); ! 334: return; ! 335: } ! 336: mp->mscp_opcode = M_OP_ONLIN; ! 337: mp->mscp_unit = ui->ui_slave; ! 338: mp->mscp_cmdref = (long) ui->ui_slave; ! 339: #ifdef DEBUG ! 340: printd("uda%d ONLIN slave %d\n",ui->ui_ctlr,ui->ui_slave); ! 341: #endif ! 342: *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT; ! 343: i = udaddr->udaip; ! 344: #ifdef lint ! 345: i = i; ! 346: #endif ! 347: while(ui->ui_flags == 0 && ra_info[ui->ui_unit].ratype != 0); ! 348: } ! 349: ! 350: /* ! 351: * Open a UDA. Initialize the device and ! 352: * set the unit online. ! 353: */ ! 354: /* ARGSUSED */ ! 355: udopen(dev, flag) ! 356: dev_t dev; ! 357: int flag; ! 358: { ! 359: register int unit; ! 360: register struct uba_device *ui; ! 361: register struct uda_softc *sc; ! 362: register struct mscp *mp; ! 363: register struct uba_ctlr *um; ! 364: struct udadevice *udaddr; ! 365: int s,i; ! 366: ! 367: unit = udunit(dev); ! 368: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) ! 369: return (ENXIO); ! 370: sc = &uda_softc[ui->ui_ctlr]; ! 371: s = spl5(); ! 372: if (sc->sc_state != S_RUN) { ! 373: if (sc->sc_state == S_IDLE) ! 374: if(!udinit(ui->ui_ctlr)){ ! 375: printf("uda: Controller failed to init\n"); ! 376: (void) splx(s); ! 377: return(ENXIO); ! 378: } ! 379: /* wait for initialization to complete */ ! 380: timeout(wakeup,(caddr_t)ui->ui_mi,11*hz); /* to be sure*/ ! 381: sleep((caddr_t)ui->ui_mi, 0); ! 382: if (sc->sc_state != S_RUN) ! 383: { ! 384: (void) splx(s); /* added by Rich */ ! 385: return (EIO); ! 386: } ! 387: } ! 388: /* check to see if the device is really there. */ ! 389: /* this code was taken from Fred Canters 11 driver */ ! 390: um = ui->ui_mi; ! 391: udaddr = (struct udadevice *) um->um_addr; ! 392: (void) splx(s); ! 393: if(ui->ui_flags == 0){ ! 394: s = spl5(); ! 395: while(0 ==(mp = udgetcp(um))){ ! 396: uda_cp_wait++; ! 397: sleep((caddr_t)&uda_cp_wait,PSWP+1); ! 398: uda_cp_wait--; ! 399: } ! 400: mp->mscp_opcode = M_OP_ONLIN; ! 401: mp->mscp_unit = ui->ui_slave; ! 402: mp->mscp_cmdref = (long) & ra_info[ui->ui_unit].ratype; ! 403: /* need to sleep on something */ ! 404: #ifdef DEBUG ! 405: printd("uda: bring unit %d online\n",ui->ui_unit); ! 406: #endif ! 407: *((long *) mp->mscp_dscptr ) |= UDA_OWN | UDA_INT ; ! 408: i = udaddr->udaip; ! 409: #ifdef lint ! 410: i = i; ! 411: #endif ! 412: timeout(wakeup,(caddr_t) mp->mscp_cmdref,10 * hz); ! 413: /* make sure we wake up */ ! 414: sleep((caddr_t) mp->mscp_cmdref,PSWP+1); /*wakeup in udrsp() */ ! 415: (void) splx(s); ! 416: } ! 417: if(ui->ui_flags == 0){ ! 418: return(ENXIO); /* Didn't go online */ ! 419: } ! 420: return (0); ! 421: } ! 422: ! 423: /* ! 424: * Initialize a UDA. Set up UBA mapping registers, ! 425: * initialize data structures, and start hardware ! 426: * initialization sequence. ! 427: */ ! 428: udinit(d) ! 429: int d; ! 430: { ! 431: register struct uda_softc *sc; ! 432: register struct uda *ud; ! 433: struct udadevice *udaddr; ! 434: struct uba_ctlr *um; ! 435: ! 436: sc = &uda_softc[d]; ! 437: um = udminfo[d]; ! 438: um->um_tab.b_active++; ! 439: ud = &uda[d]; ! 440: udaddr = (struct udadevice *)um->um_addr; ! 441: if (sc->sc_mapped == 0) { ! 442: /* ! 443: * Map the communications area and command ! 444: * and response packets into Unibus address ! 445: * space. ! 446: */ ! 447: sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud, ! 448: sizeof (struct uda), 0); ! 449: sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff); ! 450: sc->sc_mapped = 1; ! 451: } ! 452: ! 453: /* ! 454: * Start the hardware initialization sequence. ! 455: */ ! 456: ! 457: if (udaburst[d] == 0) ! 458: udaburst[d] = UDABURST; ! 459: udaddr->udaip = 0; /* start initialization */ ! 460: ! 461: while((udaddr->udasa & UDA_STEP1) == 0){ ! 462: if(udaddr->udasa & UDA_ERR) ! 463: return(0); /* CHECK */ ! 464: } ! 465: udaddr->udasa=UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); ! 466: /* ! 467: * Initialization continues in interrupt routine. ! 468: */ ! 469: sc->sc_state = S_STEP1; ! 470: sc->sc_credits = 0; ! 471: return(1); ! 472: } ! 473: ! 474: udstrategy(bp) ! 475: register struct buf *bp; ! 476: { ! 477: register struct uba_device *ui; ! 478: register struct uba_ctlr *um; ! 479: register struct buf *dp; ! 480: register int unit; ! 481: register struct size *rasizes; ! 482: int xunit = minor(bp->b_dev) & 07; ! 483: daddr_t sz, maxsz; ! 484: int s; ! 485: ! 486: sz = (bp->b_bcount+511) >> 9; ! 487: unit = udunit(bp->b_dev); ! 488: if (unit >= NRA) { ! 489: bp->b_error = ENXIO; ! 490: goto bad; ! 491: } ! 492: rasizes = ra_info[unit].ra_sizes; ! 493: ui = uddinfo[unit]; ! 494: um = ui->ui_mi; ! 495: if (ui == 0 || ui->ui_alive == 0) { ! 496: bp->b_error = ENXIO; ! 497: goto bad; ! 498: } ! 499: if ((maxsz = rasizes[xunit].nblocks) < 0) ! 500: maxsz = ra_info[unit].radsize - rasizes[xunit].blkoff; ! 501: if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz || ! 502: rasizes[xunit].blkoff >= ra_info[unit].radsize) { ! 503: if (bp->b_blkno == maxsz) { ! 504: bp->b_resid = bp->b_bcount; ! 505: goto done; ! 506: } ! 507: bp->b_error = EINVAL; ! 508: goto bad; ! 509: } ! 510: s = spl5(); ! 511: /* ! 512: * Link the buffer onto the drive queue ! 513: */ ! 514: dp = &udutab[ui->ui_unit]; ! 515: if (dp->b_actf == 0) ! 516: dp->b_actf = bp; ! 517: else ! 518: dp->b_actl->av_forw = bp; ! 519: dp->b_actl = bp; ! 520: bp->av_forw = 0; ! 521: /* ! 522: * Link the drive onto the controller queue ! 523: */ ! 524: if (dp->b_active == 0) { ! 525: dp->b_forw = NULL; ! 526: if (um->um_tab.b_actf == NULL) ! 527: um->um_tab.b_actf = dp; ! 528: else ! 529: um->um_tab.b_actl->b_forw = dp; ! 530: um->um_tab.b_actl = dp; ! 531: dp->b_active = 1; ! 532: } ! 533: if (um->um_tab.b_active == 0) { ! 534: #if defined(VAX750) ! 535: if (cpu == VAX_750 ! 536: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { ! 537: if (um->um_ubinfo != 0) { ! 538: printd("udastrat: ubinfo 0x%x\n",um->um_ubinfo); ! 539: } else ! 540: um->um_ubinfo = ! 541: uballoc(um->um_ubanum, (caddr_t)0, 0, ! 542: UBA_NEEDBDP); ! 543: } ! 544: #endif ! 545: (void) udstart(um); ! 546: } ! 547: splx(s); ! 548: return; ! 549: ! 550: bad: ! 551: bp->b_flags |= B_ERROR; ! 552: done: ! 553: iodone(bp); ! 554: return; ! 555: } ! 556: ! 557: udstart(um) ! 558: register struct uba_ctlr *um; ! 559: { ! 560: register struct buf *bp, *dp; ! 561: register struct mscp *mp; ! 562: register struct uda_softc *sc; ! 563: register struct uba_device *ui; ! 564: struct size *rasizes; ! 565: struct udadevice *udaddr; ! 566: struct uda *ud = &uda[um->um_ctlr]; ! 567: int i; ! 568: ! 569: sc = &uda_softc[um->um_ctlr]; ! 570: ! 571: loop: ! 572: if ((dp = um->um_tab.b_actf) == NULL) { ! 573: /* ! 574: * Release uneeded UBA resources and return ! 575: */ ! 576: um->um_tab.b_active = 0; ! 577: /* Check for response ring transitions lost in the ! 578: * Race condition ! 579: */ ! 580: for (i = sc->sc_lastrsp;; i++) { ! 581: i %= NRSP; ! 582: if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) ! 583: break; ! 584: udrsp(um, ud, sc, i); ! 585: ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; ! 586: } ! 587: sc->sc_lastrsp = i; ! 588: return (0); ! 589: } ! 590: if ((bp = dp->b_actf) == NULL) { ! 591: /* ! 592: * No more requests for this drive, remove ! 593: * from controller queue and look at next drive. ! 594: * We know we're at the head of the controller queue. ! 595: */ ! 596: dp->b_active = 0; ! 597: um->um_tab.b_actf = dp->b_forw; ! 598: goto loop; /* Need to check for loop */ ! 599: } ! 600: um->um_tab.b_active++; ! 601: udaddr = (struct udadevice *)um->um_addr; ! 602: if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) { ! 603: harderr(bp, "ra"); ! 604: mprintf("Uda%d udasa %o, state %d\n",um->um_ctlr , udaddr->udasa&0xffff, sc->sc_state); ! 605: (void)udinit(um->um_ctlr); ! 606: /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */ ! 607: return (0); ! 608: } ! 609: ui = uddinfo[udunit(bp->b_dev)]; ! 610: rasizes = ra_info[ui->ui_unit].ra_sizes; ! 611: if (ui->ui_flags == 0) { /* not online */ ! 612: if ((mp = udgetcp(um)) == NULL){ ! 613: return (0); ! 614: } ! 615: mp->mscp_opcode = M_OP_ONLIN; ! 616: mp->mscp_unit = ui->ui_slave; ! 617: dp->b_active = 2; ! 618: um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ ! 619: #ifdef DEBUG ! 620: printd("uda: bring unit %d online\n", ui->ui_slave); ! 621: #endif ! 622: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 623: if (udaddr->udasa&UDA_ERR) ! 624: printf("Uda (%d) Error (%x)\n",um->um_ctlr , udaddr->udasa&0xffff); ! 625: i = udaddr->udaip; ! 626: goto loop; ! 627: } ! 628: switch (cpu) { ! 629: case VAX_8600: ! 630: case VAX_780: ! 631: i = UBA_NEEDBDP|UBA_CANTWAIT; ! 632: break; ! 633: ! 634: case VAX_750: ! 635: i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; ! 636: break; ! 637: ! 638: case VAX_730: ! 639: case VAX_630: ! 640: i = UBA_CANTWAIT; ! 641: break; ! 642: } ! 643: if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) ! 644: return(1); ! 645: if ((mp = udgetcp(um)) == NULL) { ! 646: #if defined(VAX750) ! 647: if (cpu == VAX_750) ! 648: i &= 0xfffffff; /* mask off bdp */ ! 649: #endif ! 650: ubarelse(um->um_ubanum,&i); ! 651: return(0); ! 652: } ! 653: mp->mscp_cmdref = (long)bp; /* pointer to get back */ ! 654: mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; ! 655: mp->mscp_unit = ui->ui_slave; ! 656: mp->mscp_lbn = bp->b_blkno + rasizes[minor(bp->b_dev)&7].blkoff; ! 657: mp->mscp_bytecnt = bp->b_bcount; ! 658: mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); ! 659: #if defined(VAX750) ! 660: if (cpu == VAX_750) ! 661: i &= 0xfffffff; /* mask off bdp */ ! 662: #endif ! 663: bp->b_ubinfo = i; /* save mapping info */ ! 664: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 665: if (udaddr->udasa&UDA_ERR) ! 666: printf("Uda(%d) udasa (%x)\n",um->um_ctlr , udaddr->udasa&0xffff); ! 667: i = udaddr->udaip; /* initiate polling */ ! 668: dp->b_qsize++; ! 669: if (ui->ui_dk >= 0) { ! 670: dk_busy |= 1<<ui->ui_dk; ! 671: dk_xfer[ui->ui_dk]++; ! 672: dk_wds[ui->ui_dk] += bp->b_bcount>>6; ! 673: } ! 674: ! 675: /* ! 676: * Move drive to the end of the controller queue ! 677: */ ! 678: if (dp->b_forw != NULL) { ! 679: um->um_tab.b_actf = dp->b_forw; ! 680: um->um_tab.b_actl->b_forw = dp; ! 681: um->um_tab.b_actl = dp; ! 682: dp->b_forw = NULL; ! 683: } ! 684: /* ! 685: * Move buffer to I/O wait queue ! 686: */ ! 687: dp->b_actf = bp->av_forw; ! 688: dp = &udwtab[um->um_ctlr]; ! 689: bp->av_forw = dp; ! 690: bp->av_back = dp->av_back; ! 691: dp->av_back->av_forw = bp; ! 692: dp->av_back = bp; ! 693: goto loop; ! 694: } ! 695: ! 696: /* ! 697: * UDA interrupt routine. ! 698: */ ! 699: udintr(d) ! 700: int d; ! 701: { ! 702: register struct uba_ctlr *um = udminfo[d]; ! 703: register struct udadevice *udaddr = (struct udadevice *)um->um_addr; ! 704: struct buf *bp; ! 705: register int i; ! 706: register struct uda_softc *sc = &uda_softc[d]; ! 707: register struct uda *ud = &uda[d]; ! 708: struct uda *uud; ! 709: struct mscp *mp; ! 710: ! 711: #ifdef DEBUG ! 712: printd10("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa); ! 713: #endif ! 714: #ifdef VAX630 ! 715: (void) spl5(); ! 716: #endif ! 717: switch (sc->sc_state) { ! 718: case S_IDLE: ! 719: printf("uda%d: random interrupt ignored\n", d); ! 720: return; ! 721: ! 722: case S_STEP1: ! 723: #define STEP1MASK 0174377 ! 724: #define STEP1GOOD (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2) ! 725: if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) { ! 726: sc->sc_state = S_IDLE; ! 727: wakeup((caddr_t)um); ! 728: return; ! 729: } ! 730: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)| ! 731: ((cpu == VAX_780) || (cpu == VAX_8600) ? UDA_PI : 0); ! 732: sc->sc_state = S_STEP2; ! 733: return; ! 734: ! 735: case S_STEP2: ! 736: #define STEP2MASK 0174377 ! 737: #define STEP2GOOD (UDA_STEP3|UDA_IE|(sc->sc_ivec/4)) ! 738: if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) { ! 739: sc->sc_state = S_IDLE; ! 740: wakeup((caddr_t)um); ! 741: return; ! 742: } ! 743: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16; ! 744: sc->sc_state = S_STEP3; ! 745: return; ! 746: ! 747: case S_STEP3: ! 748: #define STEP3MASK 0174000 ! 749: #define STEP3GOOD UDA_STEP4 ! 750: if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) { ! 751: sc->sc_state = S_IDLE; ! 752: wakeup((caddr_t)um); ! 753: return; ! 754: } ! 755: udamicro[d] = udaddr->udasa; ! 756: #ifdef DEBUG ! 757: printd("Uda%d Version %d model %d\n",d,udamicro[d]&0xF, ! 758: (udamicro[d]>>4) & 0xF); ! 759: #endif ! 760: /* ! 761: * Requesting the error status (|= 2) ! 762: * may hang older controllers. ! 763: */ ! 764: i = UDA_GO | (udaerror? 2 : 0); ! 765: if (udaburst[d]) ! 766: i |= (udaburst[d] - 1) << 2; ! 767: udaddr->udasa = i; ! 768: udaddr->udasa = UDA_GO; ! 769: sc->sc_state = S_SCHAR; ! 770: ! 771: /* ! 772: * Initialize the data structures. ! 773: */ ! 774: uud = sc->sc_uda; ! 775: for (i = 0; i < NRSP; i++) { ! 776: ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT| ! 777: (long)&uud->uda_rsp[i].mscp_cmdref; ! 778: ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i]; ! 779: ud->uda_rsp[i].mscp_header.uda_msglen = mscp_msglen; ! 780: } ! 781: for (i = 0; i < NCMD; i++) { ! 782: ud->uda_ca.ca_cmddsc[i] = UDA_INT| ! 783: (long)&uud->uda_cmd[i].mscp_cmdref; ! 784: ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i]; ! 785: ud->uda_cmd[i].mscp_header.uda_msglen = mscp_msglen; ! 786: } ! 787: bp = &udwtab[d]; ! 788: bp->av_forw = bp->av_back = bp; ! 789: sc->sc_lastcmd = 1; ! 790: sc->sc_lastrsp = 0; ! 791: mp = &uda[um->um_ctlr].uda_cmd[0]; ! 792: mp->mscp_unit = mp->mscp_modifier = 0; ! 793: mp->mscp_flags = 0; ! 794: mp->mscp_bytecnt = mp->mscp_buffer = 0; ! 795: mp->mscp_errlgfl = mp->mscp_copyspd = 0; ! 796: mp->mscp_opcode = M_OP_STCON; ! 797: mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; ! 798: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; ! 799: i = udaddr->udaip; /* initiate polling */ ! 800: return; ! 801: ! 802: case S_SCHAR: ! 803: case S_RUN: ! 804: break; ! 805: ! 806: default: ! 807: printf("uda%d: interrupt in unknown state %d ignored\n", ! 808: d, sc->sc_state); ! 809: return; ! 810: } ! 811: ! 812: if (udaddr->udasa&UDA_ERR) { ! 813: printf("uda(%d): fatal error (%o)\n", d, udaddr->udasa&0xffff); ! 814: udaddr->udaip = 0; ! 815: wakeup((caddr_t)um); ! 816: } ! 817: ! 818: /* ! 819: * Check for a buffer purge request. ! 820: */ ! 821: if (ud->uda_ca.ca_bdp) { ! 822: #ifdef DEBUG ! 823: printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp); ! 824: #endif ! 825: UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp); ! 826: ud->uda_ca.ca_bdp = 0; ! 827: udaddr->udasa = 0; /* signal purge complete */ ! 828: } ! 829: ! 830: /* ! 831: * Check for response ring transition. ! 832: */ ! 833: if (ud->uda_ca.ca_rspint) { ! 834: ud->uda_ca.ca_rspint = 0; ! 835: for (i = sc->sc_lastrsp;; i++) { ! 836: i %= NRSP; ! 837: if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) ! 838: break; ! 839: udrsp(um, ud, sc, i); ! 840: ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; ! 841: } ! 842: sc->sc_lastrsp = i; ! 843: } ! 844: ! 845: /* ! 846: * Check for command ring transition. ! 847: */ ! 848: if (ud->uda_ca.ca_cmdint) { ! 849: #ifdef DEBUG ! 850: printd("uda: command ring transition\n"); ! 851: #endif ! 852: ud->uda_ca.ca_cmdint = 0; ! 853: } ! 854: if(uda_cp_wait) ! 855: wakeup((caddr_t)&uda_cp_wait); ! 856: (void) udstart(um); ! 857: } ! 858: ! 859: /* ! 860: * Process a response packet ! 861: */ ! 862: udrsp(um, ud, sc, i) ! 863: register struct uba_ctlr *um; ! 864: register struct uda *ud; ! 865: register struct uda_softc *sc; ! 866: int i; ! 867: { ! 868: register struct mscp *mp; ! 869: struct uba_device *ui; ! 870: struct buf *dp, *bp,nullbp; ! 871: int st; ! 872: ! 873: mp = &ud->uda_rsp[i]; ! 874: mp->mscp_header.uda_msglen = mscp_msglen; ! 875: sc->sc_credits += mp->mscp_header.uda_credits & 0xf; /* just 4 bits?*/ ! 876: if ((mp->mscp_header.uda_credits & 0xf0) > 0x10) /* Check */ ! 877: return; ! 878: #ifdef DEBUG ! 879: printd10("udarsp, opcode 0x%x status 0x%x\n",mp->mscp_opcode,mp->mscp_status); ! 880: #endif ! 881: /* ! 882: * If it's an error log message (datagram), ! 883: * pass it on for more extensive processing. ! 884: */ ! 885: if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) { /* check */ ! 886: uderror(um, (struct mslg *)mp); ! 887: return; ! 888: } ! 889: st = mp->mscp_status&M_ST_MASK; ! 890: /* The controller interrupts as drive 0 */ ! 891: /* this means that you must check for controller interrupts */ ! 892: /* before you check to see if there is a drive 0 */ ! 893: if((M_OP_STCON|M_OP_END) == mp->mscp_opcode){ ! 894: if (st == M_ST_SUCC) ! 895: sc->sc_state = S_RUN; ! 896: else ! 897: sc->sc_state = S_IDLE; ! 898: um->um_tab.b_active = 0; ! 899: wakeup((caddr_t)um); ! 900: return; ! 901: } ! 902: if (mp->mscp_unit >= 8) ! 903: return; ! 904: if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0) ! 905: return; ! 906: switch (mp->mscp_opcode) { ! 907: ! 908: case M_OP_ONLIN|M_OP_END: ! 909: ra_info[ui->ui_unit].rastatus = st; ! 910: ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; ! 911: dp = &udutab[ui->ui_unit]; ! 912: if (st == M_ST_SUCC) { ! 913: /* ! 914: * Link the drive onto the controller queue ! 915: */ ! 916: dp->b_forw = NULL; ! 917: if (um->um_tab.b_actf == NULL) ! 918: um->um_tab.b_actf = dp; ! 919: else ! 920: um->um_tab.b_actl->b_forw = dp; ! 921: um->um_tab.b_actl = dp; ! 922: ui->ui_flags = 1; /* mark it online */ ! 923: ra_info[ui->ui_unit].radsize=(daddr_t)mp->mscp_untsize; ! 924: #ifdef DEBUG ! 925: printd("uda: unit %d online\n", mp->mscp_unit); ! 926: #endif ! 927: #define F_to_C(x,i) ( ((x)->mscp_mediaid) >> (i*5+7) & 0x1f ? ( ( (((x)->mscp_mediaid) >>( i*5 + 7)) & 0x1f) + 'A' - 1): ' ') ! 928: /* this mess decodes the Media type identifier */ ! 929: #ifdef DEBUG ! 930: printd("uda: unit %d online %x %c%c %c%c%c%d\n" ! 931: ,mp->mscp_unit, mp->mscp_mediaid ! 932: ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) ! 933: ,F_to_C(mp,1),F_to_C(mp,0) ! 934: ,mp->mscp_mediaid & 0x7f); ! 935: #endif ! 936: switch((int)(mp->mscp_mediaid & 0x7f)){ ! 937: case 25: ! 938: ra_info[ui->ui_unit].ra_sizes = ra25_sizes; ! 939: break; ! 940: case 52: ! 941: ra_info[ui->ui_unit].ra_sizes = rd52_sizes; ! 942: break; ! 943: case 53: ! 944: ra_info[ui->ui_unit].ra_sizes = rd53_sizes; ! 945: break; ! 946: case 60: ! 947: ra_info[ui->ui_unit].ra_sizes = ra60_sizes; ! 948: break; ! 949: case 80: ! 950: ra_info[ui->ui_unit].ra_sizes = ra80_sizes; ! 951: break; ! 952: case 81: ! 953: ra_info[ui->ui_unit].ra_sizes = ra81_sizes; ! 954: break; ! 955: default: ! 956: ui->ui_flags = 0; /* mark it offline */ ! 957: ra_info[ui->ui_unit].ratype = 0; ! 958: printf("Don't have a parition table for "); ! 959: printf("a %c%c %c%c%c%d\n" ! 960: ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) ! 961: ,F_to_C(mp,1),F_to_C(mp,0) ! 962: ,mp->mscp_mediaid & 0x7f); ! 963: while (bp = dp->b_actf) { ! 964: dp->b_actf = bp->av_forw; ! 965: bp->b_flags |= B_ERROR; ! 966: iodone(bp); ! 967: } ! 968: } ! 969: dp->b_active = 1; ! 970: } else { ! 971: if(dp->b_actf){ ! 972: harderr(dp->b_actf,"ra"); ! 973: } else { ! 974: nullbp.b_blkno = 0; ! 975: nullbp.b_dev = makedev(UDADEVNUM,ui->ui_unit); ! 976: harderr(&nullbp, "ra"); ! 977: } ! 978: printf("OFFLINE\n"); ! 979: while (bp = dp->b_actf) { ! 980: dp->b_actf = bp->av_forw; ! 981: bp->b_flags |= B_ERROR; ! 982: iodone(bp); ! 983: } ! 984: } ! 985: if(mp->mscp_cmdref!=NULL){/* Seems to get lost sometimes */ ! 986: wakeup((caddr_t)mp->mscp_cmdref); ! 987: } ! 988: break; ! 989: ! 990: /* ! 991: * The AVAILABLE ATTENTION messages occurs when the ! 992: * unit becomes available after spinup, ! 993: * marking the unit offline will force an online command ! 994: * prior to using the unit. ! 995: */ ! 996: case M_OP_AVATN: ! 997: #ifdef DEBUG ! 998: printd("uda: unit %d attention\n", mp->mscp_unit); ! 999: #endif ! 1000: ui->ui_flags = 0; /* it went offline and we didn't notice */ ! 1001: ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; ! 1002: break; ! 1003: ! 1004: case M_OP_END: ! 1005: /* ! 1006: * An endcode without an opcode (0200) is an invalid command. ! 1007: * The mscp specification states that this would be a protocol ! 1008: * type error, such as illegal opcodes. The mscp spec. also ! 1009: * states that parameter error type of invalid commands should ! 1010: * return the normal end message for the command. This does not appear ! 1011: * to be the case. An invalid logical block number returned an endcode ! 1012: * of 0200 instead of the 0241 (read) that was expected. ! 1013: */ ! 1014: ! 1015: printf("endcd=%o, stat=%o\n", mp->mscp_opcode, mp->mscp_status); ! 1016: break; ! 1017: case M_OP_READ|M_OP_END: ! 1018: case M_OP_WRITE|M_OP_END: ! 1019: bp = (struct buf *)mp->mscp_cmdref; ! 1020: ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); ! 1021: /* ! 1022: * Unlink buffer from I/O wait queue. ! 1023: */ ! 1024: bp->av_back->av_forw = bp->av_forw; ! 1025: bp->av_forw->av_back = bp->av_back; ! 1026: #if defined(VAX750) ! 1027: if (cpu == VAX_750 && um->um_tab.b_active == 0 ! 1028: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { ! 1029: if (um->um_ubinfo == 0) ! 1030: printf("udintr: um_ubinfo == 0\n"); ! 1031: else ! 1032: ubarelse(um->um_ubanum, &um->um_ubinfo); ! 1033: } ! 1034: #endif ! 1035: dp = &udutab[ui->ui_unit]; ! 1036: dp->b_qsize--; ! 1037: if (ui->ui_dk >= 0) ! 1038: if (dp->b_qsize == 0) ! 1039: dk_busy &= ~(1<<ui->ui_dk); ! 1040: if (st == M_ST_OFFLN || st == M_ST_AVLBL) { ! 1041: ui->ui_flags = 0; /* mark unit offline */ ! 1042: /* ! 1043: * Link the buffer onto the front of the drive queue ! 1044: */ ! 1045: if ((bp->av_forw = dp->b_actf) == 0) ! 1046: dp->b_actl = bp; ! 1047: dp->b_actf = bp; ! 1048: /* ! 1049: * Link the drive onto the controller queue ! 1050: */ ! 1051: if (dp->b_active == 0) { ! 1052: dp->b_forw = NULL; ! 1053: if (um->um_tab.b_actf == NULL) ! 1054: um->um_tab.b_actf = dp; ! 1055: else ! 1056: um->um_tab.b_actl->b_forw = dp; ! 1057: um->um_tab.b_actl = dp; ! 1058: dp->b_active = 1; ! 1059: } ! 1060: #if defined(VAX750) ! 1061: if (cpu == VAX750 && um->um_ubinfo == 0) ! 1062: um->um_ubinfo = ! 1063: uballoc(um->um_ubanum, (caddr_t)0, 0, ! 1064: UBA_NEEDBDP); ! 1065: #endif ! 1066: return; ! 1067: } ! 1068: if (st != M_ST_SUCC) { ! 1069: harderr(bp, "ra"); ! 1070: #ifdef DEBUG ! 1071: printd("status %o\n", mp->mscp_status); ! 1072: #endif ! 1073: bp->b_flags |= B_ERROR; ! 1074: } ! 1075: bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; ! 1076: iodone(bp); ! 1077: break; ! 1078: ! 1079: case M_OP_GTUNT|M_OP_END: ! 1080: #ifdef DEBUG ! 1081: printd("GTUNT end packet status = 0x%x media id 0x%x\n" ! 1082: ,st,mp->mscp_mediaid); ! 1083: #endif ! 1084: ra_info[ui->ui_unit].rastatus = st; ! 1085: ra_info[ui->ui_unit].ratype = mp->mscp_mediaid; ! 1086: break; ! 1087: ! 1088: default: ! 1089: printf("uda: unknown packet\n"); ! 1090: uderror(um, (struct mslg *)mp); ! 1091: } ! 1092: } ! 1093: ! 1094: ! 1095: /* ! 1096: * Process an error log message ! 1097: * ! 1098: * For now, just log the error on the console. ! 1099: * Only minimal decoding is done, only "useful" ! 1100: * information is printed. Eventually should ! 1101: * send message to an error logger. ! 1102: */ ! 1103: uderror(um, mp) ! 1104: register struct uba_ctlr *um; ! 1105: register struct mslg *mp; ! 1106: { ! 1107: register i; ! 1108: ! 1109: ! 1110: if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) ! 1111: printf("uda%d: hard error\n"); ! 1112: ! 1113: mprintf("uda%d: %s error, ", um->um_ctlr, ! 1114: mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); ! 1115: switch (mp->mslg_format) { ! 1116: case M_FM_CNTERR: ! 1117: mprintf("controller error, event 0%o\n", mp->mslg_event); ! 1118: break; ! 1119: ! 1120: case M_FM_BUSADDR: ! 1121: mprintf("host memory access error, event 0%o, addr 0%o\n", ! 1122: mp->mslg_event, mp->mslg_busaddr); ! 1123: break; ! 1124: ! 1125: case M_FM_DISKTRN: ! 1126: mprintf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x, event 0%o\n", ! 1127: mp->mslg_unit, mp->mslg_group, mp->mslg_hdr, ! 1128: mp->mslg_event); ! 1129: break; ! 1130: ! 1131: case M_FM_SDI: ! 1132: mprintf("SDI error, unit %d, event 0%o, hdr 0x%x\n", ! 1133: mp->mslg_unit, mp->mslg_event, mp->mslg_hdr); ! 1134: for(i = 0; i < 12;i++) ! 1135: mprintf("\t0x%x",mp->mslg_sdistat[i] & 0xff); ! 1136: mprintf("\n"); ! 1137: break; ! 1138: ! 1139: case M_FM_SMLDSK: ! 1140: mprintf("small disk error, unit %d, event 0%o, cyl %d\n", ! 1141: mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl); ! 1142: break; ! 1143: ! 1144: default: ! 1145: mprintf("unknown error, unit %d, format 0%o, event 0%o\n", ! 1146: mp->mslg_unit, mp->mslg_format, mp->mslg_event); ! 1147: } ! 1148: ! 1149: if (udaerror) { ! 1150: register long *p = (long *)mp; ! 1151: ! 1152: for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p)) ! 1153: printf("%x ", *p++); ! 1154: printf("\n"); ! 1155: } ! 1156: } ! 1157: ! 1158: ! 1159: /* ! 1160: * Find an unused command packet ! 1161: */ ! 1162: struct mscp * ! 1163: udgetcp(um) ! 1164: struct uba_ctlr *um; ! 1165: { ! 1166: register struct mscp *mp; ! 1167: register struct udaca *cp; ! 1168: register struct uda_softc *sc; ! 1169: register int i; ! 1170: int s; ! 1171: ! 1172: s = spl5(); ! 1173: cp = &uda[um->um_ctlr].uda_ca; ! 1174: sc = &uda_softc[um->um_ctlr]; ! 1175: /* ! 1176: * If no credits, can't issue any commands ! 1177: * until some outstanding commands complete. ! 1178: */ ! 1179: i = sc->sc_lastcmd; ! 1180: if(((cp->ca_cmddsc[i]&(UDA_OWN|UDA_INT))==UDA_INT)&& ! 1181: (sc->sc_credits >= 2)) { ! 1182: sc->sc_credits--; /* committed to issuing a command */ ! 1183: cp->ca_cmddsc[i] &= ~UDA_INT; ! 1184: mp = &uda[um->um_ctlr].uda_cmd[i]; ! 1185: mp->mscp_unit = mp->mscp_modifier = 0; ! 1186: mp->mscp_opcode = mp->mscp_flags = 0; ! 1187: mp->mscp_bytecnt = mp->mscp_buffer = 0; ! 1188: mp->mscp_errlgfl = mp->mscp_copyspd = 0; ! 1189: sc->sc_lastcmd = (i + 1) % NCMD; ! 1190: (void) splx(s); ! 1191: return(mp); ! 1192: } ! 1193: (void) splx(s); ! 1194: return(NULL); ! 1195: } ! 1196: ! 1197: udread(dev, uio) ! 1198: dev_t dev; ! 1199: struct uio *uio; ! 1200: { ! 1201: register int unit = udunit(dev); ! 1202: ! 1203: if (unit >= NRA) ! 1204: return (ENXIO); ! 1205: return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio)); ! 1206: } ! 1207: ! 1208: udwrite(dev, uio) ! 1209: dev_t dev; ! 1210: struct uio *uio; ! 1211: { ! 1212: register int unit = udunit(dev); ! 1213: ! 1214: if (unit >= NRA) ! 1215: return (ENXIO); ! 1216: return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio)); ! 1217: } ! 1218: ! 1219: udreset(uban) ! 1220: int uban; ! 1221: { ! 1222: register struct uba_ctlr *um; ! 1223: register struct uba_device *ui; ! 1224: register struct buf *bp, *dp; ! 1225: register int unit; ! 1226: struct buf *nbp; ! 1227: int d; ! 1228: ! 1229: for (d = 0; d < NUDA; d++) { ! 1230: if ((um = udminfo[d]) == 0 || um->um_ubanum != uban || ! 1231: um->um_alive == 0) ! 1232: continue; ! 1233: printf(" uda%d", d); ! 1234: um->um_tab.b_active = 0; ! 1235: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 1236: uda_softc[d].sc_state = S_IDLE; ! 1237: uda_softc[d].sc_mapped = 0; /* Rich */ ! 1238: for (unit = 0; unit < NRA; unit++) { ! 1239: if ((ui = uddinfo[unit]) == 0) ! 1240: continue; ! 1241: if (ui->ui_alive == 0 || ui->ui_mi != um) ! 1242: continue; ! 1243: udutab[unit].b_active = 0; ! 1244: udutab[unit].b_qsize = 0; ! 1245: } ! 1246: for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) { ! 1247: nbp = bp->av_forw; ! 1248: bp->b_ubinfo = 0; ! 1249: /* ! 1250: * Link the buffer onto the drive queue ! 1251: */ ! 1252: dp = &udutab[udunit(bp->b_dev)]; ! 1253: if (dp->b_actf == 0) ! 1254: dp->b_actf = bp; ! 1255: else ! 1256: dp->b_actl->av_forw = bp; ! 1257: dp->b_actl = bp; ! 1258: bp->av_forw = 0; ! 1259: /* ! 1260: * Link the drive onto the controller queue ! 1261: */ ! 1262: if (dp->b_active == 0) { ! 1263: dp->b_forw = NULL; ! 1264: if (um->um_tab.b_actf == NULL) ! 1265: um->um_tab.b_actf = dp; ! 1266: else ! 1267: um->um_tab.b_actl->b_forw = dp; ! 1268: um->um_tab.b_actl = dp; ! 1269: dp->b_active = 1; ! 1270: } ! 1271: } ! 1272: (void)udinit(d); ! 1273: } ! 1274: } ! 1275: ! 1276: #define DBSIZE 32 ! 1277: ! 1278: #define ca_Rspdsc ca_rspdsc[0] ! 1279: #define ca_Cmddsc ca_rspdsc[1] ! 1280: #define uda_Rsp uda_rsp[0] ! 1281: #define uda_Cmd uda_cmd[0] ! 1282: ! 1283: struct uda udad[NUDA]; ! 1284: ! 1285: uddump(dev) ! 1286: dev_t dev; ! 1287: { ! 1288: struct udadevice *udaddr; ! 1289: struct uda *ud_ubaddr; ! 1290: char *start; ! 1291: int num, blk, unit; ! 1292: int maxsz; ! 1293: int blkoff; ! 1294: register struct uba_regs *uba; ! 1295: register struct uba_device *ui; ! 1296: register struct uda *udp; ! 1297: register struct pte *io; ! 1298: register int i; ! 1299: struct size *rasizes; ! 1300: unit = udunit(dev); ! 1301: if (unit >= NRA) ! 1302: return (ENXIO); ! 1303: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ! 1304: ui = phys(struct uba_device *, uddinfo[unit]); ! 1305: if (ui->ui_alive == 0) ! 1306: return (ENXIO); ! 1307: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ! 1308: ubainit(uba); ! 1309: udaddr = (struct udadevice *)ui->ui_physaddr; ! 1310: DELAY(2000000); ! 1311: udp = phys(struct uda *, &udad[ui->ui_ctlr]); ! 1312: ! 1313: num = btoc(sizeof(struct uda)) + 1; ! 1314: io = &uba->uba_map[NUBMREG-num]; ! 1315: for(i = 0; i<num; i++) ! 1316: *(int *)io++ = UBAMR_MRV|(btop(udp)+i); ! 1317: ud_ubaddr = (struct uda *)(((int)udp & PGOFSET)|((NUBMREG-num)<<9)); ! 1318: ! 1319: udaddr->udaip = 0; ! 1320: while ((udaddr->udasa & UDA_STEP1) == 0) ! 1321: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1322: udaddr->udasa = UDA_ERR; ! 1323: while ((udaddr->udasa & UDA_STEP2) == 0) ! 1324: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1325: udaddr->udasa = (short)&ud_ubaddr->uda_ca.ca_ringbase; ! 1326: while ((udaddr->udasa & UDA_STEP3) == 0) ! 1327: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1328: udaddr->udasa = (short)(((int)&ud_ubaddr->uda_ca.ca_ringbase) >> 16); ! 1329: while ((udaddr->udasa & UDA_STEP4) == 0) ! 1330: if(udaddr->udasa & UDA_ERR) return(EFAULT); ! 1331: udaddr->udasa = UDA_GO; ! 1332: udp->uda_ca.ca_Rspdsc = (long)&ud_ubaddr->uda_Rsp.mscp_cmdref; ! 1333: udp->uda_ca.ca_Cmddsc = (long)&ud_ubaddr->uda_Cmd.mscp_cmdref; ! 1334: udp->uda_Cmd.mscp_cntflgs = 0; ! 1335: udp->uda_Cmd.mscp_version = 0; ! 1336: if (udcmd(M_OP_STCON, udp, udaddr) == 0) { ! 1337: return(EFAULT); ! 1338: } ! 1339: udp->uda_Cmd.mscp_unit = ui->ui_slave; ! 1340: if (udcmd(M_OP_ONLIN, udp, udaddr) == 0) { ! 1341: return(EFAULT); ! 1342: } ! 1343: ! 1344: num = maxfree; ! 1345: start = 0; ! 1346: rasizes = ra_info[ui->ui_unit].ra_sizes; ! 1347: maxsz = rasizes[minor(dev)&07].nblocks; ! 1348: blkoff = rasizes[minor(dev)&07].blkoff; ! 1349: if(maxsz < 0) ! 1350: maxsz = ra_info[unit].radsize-blkoff; ! 1351: if (dumplo < 0) ! 1352: return (EINVAL); ! 1353: if (dumplo + num >= maxsz) ! 1354: num = maxsz - dumplo; ! 1355: blkoff += dumplo; ! 1356: while (num > 0) { ! 1357: blk = num > DBSIZE ? DBSIZE : num; ! 1358: io = uba->uba_map; ! 1359: for (i = 0; i < blk; i++) ! 1360: *(int *)io++ = (btop(start)+i) | UBAMR_MRV; ! 1361: *(int *)io = 0; ! 1362: udp->uda_Cmd.mscp_lbn = btop(start) + blkoff; ! 1363: udp->uda_Cmd.mscp_unit = ui->ui_slave; ! 1364: udp->uda_Cmd.mscp_bytecnt = blk*NBPG; ! 1365: udp->uda_Cmd.mscp_buffer = 0; ! 1366: if (udcmd(M_OP_WRITE, udp, udaddr) == 0) { ! 1367: return(EIO); ! 1368: } ! 1369: start += blk*NBPG; ! 1370: num -= blk; ! 1371: } ! 1372: return (0); ! 1373: } ! 1374: ! 1375: ! 1376: udcmd(op, udp, udaddr) ! 1377: int op; ! 1378: register struct uda *udp; ! 1379: struct udadevice *udaddr; ! 1380: { ! 1381: int i; ! 1382: ! 1383: udp->uda_Cmd.mscp_opcode = op; ! 1384: udp->uda_Rsp.mscp_header.uda_msglen = mscp_msglen; ! 1385: udp->uda_Cmd.mscp_header.uda_msglen = mscp_msglen; ! 1386: udp->uda_ca.ca_Rspdsc |= UDA_OWN|UDA_INT; ! 1387: udp->uda_ca.ca_Cmddsc |= UDA_OWN|UDA_INT; ! 1388: if (udaddr->udasa&UDA_ERR) ! 1389: printf("Udaerror udasa (%x)\n", udaddr->udasa&0xffff); ! 1390: i = udaddr->udaip; ! 1391: #ifdef lint ! 1392: i = i; ! 1393: #endif ! 1394: for (;;) { ! 1395: if (udp->uda_ca.ca_cmdint) ! 1396: udp->uda_ca.ca_cmdint = 0; ! 1397: if (udp->uda_ca.ca_rspint) ! 1398: break; ! 1399: } ! 1400: udp->uda_ca.ca_rspint = 0; ! 1401: if (udp->uda_Rsp.mscp_opcode != (op|M_OP_END) || ! 1402: (udp->uda_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) { ! 1403: printf("error: com %d opc 0x%x stat 0x%x\ndump ", ! 1404: op, ! 1405: udp->uda_Rsp.mscp_opcode, ! 1406: udp->uda_Rsp.mscp_status); ! 1407: return(0); ! 1408: } ! 1409: return(1); ! 1410: } ! 1411: ! 1412: udsize(dev) ! 1413: dev_t dev; ! 1414: { ! 1415: int unit = udunit(dev); ! 1416: struct uba_device *ui; ! 1417: struct size *rasizes; ! 1418: ! 1419: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0 ! 1420: || ui->ui_flags == 0) ! 1421: return (-1); ! 1422: rasizes = ra_info[ui->ui_unit].ra_sizes; ! 1423: return (rasizes[minor(dev) & 07].nblocks); ! 1424: } ! 1425: ! 1426: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.