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