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