|
|
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.