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