|
|
1.1 ! root 1: ! 2: /* ! 3: * Base of share memory for VDDC is at : 0x2000 (0x2X00) ! 4: * X is switch selectable. ! 5: */ ! 6: ! 7: #define SBR 0 ! 8: #define PGSHIFT 10 ! 9: #include "pte.h" ! 10: #include "vddc.h" ! 11: ! 12: /* ************************** ! 13: parameters for FSD,SMD,XFD ! 14: ************************** ! 15: */ ! 16: #define NOUNIT 15 ! 17: ! 18: struct DEVPAR devpar[NOUNIT] = { ! 19: 823,10,10,32,512,0,"FSD", /* FSD */ ! 20: 823,10,10,32,512,0,"FSD", /* FSD */ ! 21: 823,10,10,32,512,0,"FSD", /* FSD */ ! 22: 823,10,10,32,512,0,"FSD", /* FSD */ ! 23: 0,0,0,0,0,0," ", ! 24: 823,19,19,32,512,0,"SMD", /* SMD */ ! 25: 823,19,19,32,512,0,"SMD", /* SMD */ ! 26: 823,19,19,32,512,0,"SMD", /* SMD */ ! 27: 823,19,19,32,512,0,"SMD", /* SMD */ ! 28: 0,0,0,0,0,0," ", ! 29: 711,24,24,32,512,0,"XFD", /* XFD */ ! 30: 711,24,24,32,512,0,"XFD", /* XFD */ ! 31: 711,24,24,32,512,0,"XFD", /* XFD */ ! 32: 711,24,24,32,512,0,"XFD", /* XFD */ ! 33: 0,0,0,0,0,0," " ! 34: }; ! 35: /* ***************************************** ! 36: Controller parameters for controllers 0-3 ! 37: ***************************************** ! 38: */ ! 39: struct DA VDDCBASE[4] = { ! 40: 0xff2000,0xe0,0, /* device address, int vect, online flg */ ! 41: 0xff2100,0xe1,0, /* device address, int vect, online flg */ ! 42: 0xff2200,0xe2,0, /* device address, int vect, online flg */ ! 43: 0xff2300,0xe3,0 /* device address, int vect, online flg */ ! 44: }; ! 45: /* VDDC Master DCB packet */ ! 46: ! 47: struct MDCB mdcb; ! 48: ! 49: /* VDDC DCB */ ! 50: ! 51: struct DCB dcb; ! 52: ! 53: long VDDCbase; /* Virtual address of VDDC */ ! 54: long Vdone; /* Flag polled for status packet */ ! 55: long Format = 0; /* If set, VDDC is formatting, wait longer ! */ ! 56: long Probe = 0; /* If set do not print error message */ ! 57: extern long unused, iob0, Multi, Berr, IOinit; ! 58: int cont, type; ! 59: ! 60: vddc() ! 61: { register long r12; ! 62: long oldvec; ! 63: Probe = 0; ! 64: ! 65: /* output test header */ ! 66: ! 67: writes("\n\n\t** VDDC Test **"); ! 68: ! 69: cont = getcont(); /* Get controller number */ ! 70: type = gettype(); /* Get type of disk drives */ ! 71: ! 72: /* Check if selected controller is installed */ ! 73: ! 74: if(VDDCBASE[cont].online == 0) { ! 75: writes("\n\nVDDC controller no. "); writed(cont); ! 76: writes(" is not installed\n"); ! 77: return(0); } ! 78: m_vddc(); /* Map VDDC */ ! 79: ! 80: /* Set handler for VDDC interrupt */ ! 81: ! 82: asm("movab vddchdlr,r12"); ! 83: set_handler(VDDCBASE[cont].intvect,&oldvec,r12); ! 84: ! 85: /* Reset UDC controller */ ! 86: /*if (vddc_reset() == 0) { ! 87: writes("\n...Cannot reset VDDC controller no. "); ! 88: writed(cont); writes("\n"); ! 89: return(0); } ! 90: */ ! 91: whonline(); ! 92: return(1); ! 93: } ! 94: chk_vdadr() ! 95: { long curaddr, nvddc, vddcno; ! 96: short len; ! 97: len = 4; ! 98: writes("\nProbing for VDDC controllers..."); ! 99: for(nvddc=vddcno=0; vddcno<4; vddcno++) { ! 100: curaddr = VDDCBASE[vddcno].devaddr + IOBASE; ! 101: if(badaddr(curaddr,len) == 0) { ! 102: writes("\nVDDC controller no. "); writed(vddcno); ! 103: writes(" at address "); ! 104: curaddr -= IOBASE; ! 105: writeh(curaddr); ! 106: VDDCBASE[vddcno].online = 1; ! 107: nvddc++; } ! 108: } ! 109: writes("\n"); writed(nvddc); writes(" VDDC controller(s) found"); ! 110: return(nvddc); ! 111: } ! 112: /* Routine to map VDDC ! 113: */ ! 114: m_vddc() ! 115: { long r12, phys_pg, pte, old_pte, which1; ! 116: ! 117: phys_pg = ((VDDCBASE[cont].devaddr + IOBASE) >> PGSHIFT) & 0x3fffff; ! 118: ! 119: /* 1st physical page of VDDC in IO space */ ! 120: pte = phys_pg | PG_KW | PG_V | PG_NC; ! 121: fix_pte(SBR,unused,&old_pte,pte); ! 122: ! 123: /* Base Virtual addr of VDDC */ ! 124: VDDCbase = (unused << PGSHIFT) | (VDDCBASE[cont].devaddr & 0x3ff); ! 125: ! 126: asm("mfpr $SLR,r12"); ! 127: r12++; ! 128: asm("mtpr r12,$SLR"); ! 129: unused++; /* Next unused PTE in system map */ ! 130: } ! 131: whonline() ! 132: { register struct DEVPAR *dp; ! 133: register long unit; ! 134: for(unit=0;devpar[unit+type*5].nocyl != 0;unit++) { ! 135: Probe = 1; ! 136: devpar[unit+type*5].alive = 1; ! 137: if (!vddc_op(RD_DATA,unit,0,1,&iob0)){ ! 138: devpar[unit+type*5].alive = 0; } ! 139: else { /* Unit is on line */ ! 140: vddc_ctlr(CONFIG,unit); ! 141: vddc_ctlr(INITIALIZE,unit); ! 142: Probe = 0; ! 143: } ! 144: } ! 145: Probe = 0; ! 146: } ! 147: ! 148: /* ! 149: ****************************************************** ! 150: Routine to sent one of the following control ! 151: command to VDDC : Format, start drives, stop drives, ! 152: initialize controller, diagnose, Configure drive, ! 153: status. ! 154: op : one of the above opcode ! 155: dev : device selected ! 156: Returns 1 if command successfully completed. ! 157: ****************************************************** ! 158: */ ! 159: vddc_ctlr(op,dev) ! 160: unsigned short op; ! 161: char dev; ! 162: { long trailer[5]; ! 163: register long notrailer, noword; ! 164: register struct DEVPAR *dp; ! 165: unsigned short format_data[512]; ! 166: ! 167: dp = &devpar[dev+type*5]; ! 168: notrailer = 0; ! 169: switch (op) { ! 170: case FORMAT : ! 171: for (noword=0;noword<512;noword++) ! 172: format_data[noword] = (char)0; ! 173: trailer[0] = (long)format_data; ! 174: trailer[1] = dp->nocyl*dp->nohead*dp->secs_trak; ! 175: trailer[2] = (short)0; /* Start from log. sector 0 */ ! 176: trailer[3] = (char)0; ! 177: notrailer = (char)4; ! 178: Format = 1; ! 179: setup_dcb(&dcb,op,dev,notrailer,trailer); ! 180: noword=sento_vddc(&dcb); /* Return 1 if O.K */ ! 181: Format = 0; ! 182: return(noword); ! 183: break; ! 184: case START_DR : ! 185: break; ! 186: case STOP_DR : ! 187: break; ! 188: case CONFIG: ! 189: trailer[0] = dp->nocyl; ! 190: trailer[1] = dp->nohead; ! 191: notrailer = 2; ! 192: break; ! 193: case STATUS: ! 194: setup_dcb(&dcb,op,dev,notrailer,trailer); ! 195: sento_vddc(&dcb); ! 196: return(mdcb.ctlr_stat); ! 197: case INITIALIZE: ! 198: break; ! 199: case DIAGNOSE: ! 200: break; ! 201: } ! 202: setup_dcb(&dcb,op,dev,notrailer,trailer); ! 203: return(sento_vddc(&dcb)); /* Return 1 if O.K */ ! 204: } ! 205: ! 206: ! 207: /* ! 208: ****************************************************** ! 209: Routine to read/write N block from/to disk ! 210: op : opcode, READ or WRITE ! 211: dev : device selected ! 212: blkno : Logical block no. (1024bytes/blk) to access ! 213: no_blks : no. of blocks to access ! 214: buf_adr : Memory address ! 215: Returns 1 if command successfully completed. ! 216: ****************************************************** ! 217: */ ! 218: vddc_op(op,dev,blkno,no_blks,buf_adr) ! 219: unsigned short op; ! 220: char *buf_adr; ! 221: long no_blks, blkno; ! 222: { long trailer[3], nosec_cyl, secno; ! 223: long cyl_no, trak_no, sector_no; ! 224: register struct DEVPAR *dp; ! 225: if (!devpar[dev+type*5].alive) { ! 226: writes("\n...Unit "); writed(dev); ! 227: writes(" is not online\n"); ! 228: return(0); } ! 229: dp = &devpar[dev+type*5]; ! 230: /* Setup trailer words */ ! 231: nosec_cyl = dp->notraks * dp->secs_trak; /* No of sectors/cyl */ ! 232: secno = blkno*(BLKSIZ/dp->sector_siz); /* Abs. sector no. to access */ ! 233: ! 234: if ( (cyl_no=secno/nosec_cyl)>dp->nocyl ) { ! 235: if (!Probe) { writes("...Cylinder no "); writed(cyl_no); ! 236: writes(", too large\n"); return(0); } ! 237: } ! 238: secno = secno%nosec_cyl; ! 239: trak_no = secno/dp->secs_trak; ! 240: sector_no = secno%dp->secs_trak; ! 241: ! 242: trailer[0] = (long)buf_adr; ! 243: trailer[1] = no_blks * (BLKSIZ/2); /* Unit is in word size */ ! 244: trailer[2] = (cyl_no&0xfff)|(sector_no<<16)|(trak_no<<24); ! 245: if (!IOinit) { ! 246: /* if (op==(unsigned short)RD_DATA) writec('R'); ! 247: else writec('W'); ! 248: writeh(blkno); writec('/'); writeh(no_blks); writec('/'); ! 249: writeh(trailer[2]); */ ! 250: } ! 251: setup_dcb(&dcb,op,dev,3,trailer); ! 252: return(sento_vddc(&dcb)); /* Return 1 if O.K */ ! 253: } ! 254: /* ********************* ! 255: Reset VDDC controller ! 256: ********************* ! 257: */ ! 258: vddc_reset() ! 259: { ! 260: *((char *)(VDDCbase + 4)) = 1; /* reset VDDC */ ! 261: DELAY(0x1f0000); /* wait for 3 seconds */ ! 262: return(1); ! 263: } ! 264: vddc_init() ! 265: { ! 266: } ! 267: /* Routine to fill DCB ! 268: */ ! 269: setup_dcb(dcb,opcode,devno,notrailer,trailer) ! 270: struct DCB *dcb; ! 271: unsigned short opcode; ! 272: char devno, notrailer; ! 273: long *trailer; ! 274: { register long ix, *r12; ! 275: dcb->nxt_dcb = NO_CHAIN; ! 276: dcb->int_flags = (unsigned short)INT_SUCCESS; ! 277: dcb->opcode = opcode; ! 278: dcb->dcb_stat = 0; /* Clear DCB status */ ! 279: dcb->dev_sel = (char)devno & 0x3; /* Device selected */ ! 280: dcb->trail_wcnt = notrailer; /* No. of trailer words */ ! 281: r12 = (long *)dcb->trailer; ! 282: for (ix=0;ix<notrailer;ix++) r12[ix] = trailer[ix]; ! 283: } ! 284: ! 285: ! 286: /* ! 287: Routine to initiate a command to VDDC after DCB is set up ! 288: Input : vdcb = pointer to DCB structure ! 289: */ ! 290: TO_VDDC(vdcb) ! 291: struct DCB *vdcb; ! 292: { ! 293: mdcb.fdcb_adr = (long)vdcb; /* Set 1st DCB address */ ! 294: mdcb.dcb_active = mdcb.dcb_int = mdcb.ctlr_stat = 0; ! 295: INT_VDDC(); ! 296: } ! 297: INT_VDDC() ! 298: { ! 299: register long r12, r11, r10; ! 300: r12 = (((long)&mdcb) >> 16) & 0xffff; ! 301: r11 = ((long)&mdcb) & 0xffff; ! 302: r10 = VDDCbase; ! 303: asm("movow r12,(r10)"); ! 304: asm("movow r11,2(r10)"); ! 305: } ! 306: /* ! 307: ********************************************************** ! 308: Routine to set up, sent command packet to UDC and check ! 309: status packet received from UDC. Return 0 if error occured ! 310: ********************************************************** ! 311: */ ! 312: sento_vddc(vdcb) ! 313: struct DCB *vdcb; ! 314: { ! 315: Vdone = 0; ! 316: TO_VDDC(vdcb); /* Sent command to vddc */ ! 317: if (Multi) return(1); ! 318: if (!vddc_wait()) return(0); ! 319: return(chk_vddcstat(vdcb)); ! 320: } ! 321: ! 322: ! 323: /* ************************************************** ! 324: Routine to poll for completion interrupt from VDDC ! 325: ************************************************** ! 326: */ ! 327: vddc_wait() ! 328: { register long cnt; ! 329: if (Format) { cnt = 0xfffffff0; ! 330: writes("\nVDDC formatting..."); } ! 331: else cnt = 0xfff00; ! 332: while (!Vdone) { /* Wait for completion interrupt */ ! 333: if (Format) writec('f'); ! 334: if (--cnt <= 0) { ! 335: if (!Probe) ! 336: writes("\n...time out, lost completion interrupt..\n"); ! 337: return(0); } ! 338: } ! 339: return(1); ! 340: } ! 341: ! 342: ! 343: /* ***************************************************** ! 344: Routine to check completion status returned from VDDC ! 345: return 1 : status OK; command completed ! 346: 0 : Command did not completed ! 347: ***************************************************** ! 348: */ ! 349: chk_vddcstat(vdcb) ! 350: struct DCB *vdcb; ! 351: { ! 352: if (mdcb.dcb_int != (long)vdcb) { ! 353: writes("\n...Unsolicited DCB address, expected "); ! 354: writeh((long)vdcb); writes(", actual "); ! 355: writeh(mdcb.dcb_int); writes("\n"); ! 356: return(0); } ! 357: if (((vdcb->dcb_stat&0xf0000000) != DCB_DONE) || ! 358: (vdcb->dcb_stat&ANY_ERROR)) { ! 359: prt_vddcstat(vdcb->dcb_stat); ! 360: return(0); ! 361: } ! 362: return(1); ! 363: } ! 364: ! 365: /* *********************** ! 366: Routine to print status ! 367: *********************** ! 368: */ ! 369: prt_vddcstat(stat) ! 370: long stat; ! 371: { ! 372: if (Probe) return; ! 373: if (stat&SOFT_ERROR) { ! 374: writes("\n...soft error "); ! 375: writeh(stat&SOFTERR_MASK); ! 376: } ! 377: else { ! 378: if (stat&HARD_ERROR) { ! 379: writes("\n...hard error "); ! 380: writeh(stat&HARDERR_MASK); } ! 381: else ! 382: if (stat&DATA_CORRECT) { ! 383: writes("\n...Controller performed data correction"); ! 384: writeh(stat&HARDERR_MASK); } ! 385: } ! 386: writec('\n'); ! 387: } ! 388: /* VDDC interrupt handler ! 389: */ ! 390: vddc_hdlr() ! 391: { ! 392: Vdone = 1; /* Command done, received interrupt */ ! 393: } ! 394: Vddchdlr() ! 395: { asm(".align 2"); ! 396: asm(".globl vddchdlr"); ! 397: asm("vddchdlr:"); ! 398: asm("svpctx"); ! 399: vddc_hdlr(); /* VDDC handler */ ! 400: asm("ldpctx"); ! 401: asm("rei"); ! 402: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.