|
|
1.1 root 1:
2: #include "vioc.h"
3: #include "conf.h"
4: #include "const.h"
5: #include "pte.h"
6:
7: #define ON 0x80
8: #define OFF 0
9: #define LOOPBK 0
10: #define ECHO 1
11:
12: #define MAXPORT 16
13: #define MAXRLEN 50
14: #define MAXSLEN 256
15: #define HEAD "\n\r\t** VIOC test **\n"
16: #define PORT "\rlogical port no "
17: #define NL writec('\n')
18:
19: /* Pointers to VIOC structures in I/O space */
20: struct vblok *VP; /* Pointer to commom buffer */
21: struct cmd_inp cblok; /* VIOC command block (from HOST) */
22: struct cmd_res *rblok; /* PTR to CMD respond blk (from VIOC) */
23:
24: short *s_entry;
25: short cmdrsp[MAXRLEN];
26:
27: long msg_on = 1; /* Global flag to enable messages */
28: long cmd_id = 0;
29: long IObase; /* Virtual Address of VIOC base */
30: long vioc_ack, vioc_rsp;
31: long log_p0 = 1; /* Logical port no. of 1st terminal */
32: long log_pn = 0; /* Logical port no. of last terminal */
33:
34: char port_on[MAXPORT];
35:
36: extern long savvec3, unused, clk_cnt, proc_no;
37:
38: vioc()
39: { register long ix;
40: long v_reset(), v_init();
41:
42: m_vioc(); /* Set up map for IO space */
43: init_vec(); /* Set up int. handlers */
44: if (!v_reset()) return(0); /* Reset VIOC */
45: writes("\nVIOC controller is at "); writeh(VBASE);
46: if (!v_init()) return(0); /* Initialize VIOC */
47: return(1);
48: }
49:
50: /* Routine to map VIOC :
51: VIOC space is map from 1st unused virtual page on
52: */
53: m_vioc()
54: { long phys_pg, pte, old_pte, which1;
55:
56: phys_pg = ((VBASE+IOBASE) >> PGSHIFT) & 0x3fffff;
57: /* 1st physical page of VIOC in IO space */
58: pte = phys_pg | PG_KW | PG_V | PG_NC;
59: for (which1=unused; which1<(unused+VIOC_LEN); which1++) {
60: fix_pte(SBR,which1,&old_pte,pte);
61: pte++; }
62: VP = (struct vblok *)(unused << PGSHIFT);
63: IObase = (long)VP; /* Base addr of common buffer */
64: asm("mfpr $SLR,_savvec3");
65: savvec3 += VIOC_LEN;
66: asm("mtpr _savvec3,$SLR");
67: unused = which1; /* Next unused PTE in system map */
68: }
69:
70:
71: /* Initialize Tahoe SCB vectors to handle VIOC interrupts
72: */
73: init_vec()
74: { long old_vec1, old_vec2, old_vec3;
75:
76: asm("movab ack_hdlr,_savvec3");
77: set_handler(ACK_VIOC,&old_vec1,savvec3); /* Set handler for VIOC ACK */
78: asm("movab rsp_hdlr,_savvec3");
79: set_handler(CMD_RESP,&old_vec2,savvec3); /* Set handler for VIOC RSP */
80: asm("movab unsol_hdlr,_savvec3");
81: set_handler(UNS_VEC,&old_vec3,savvec3); /* Set hdler for VIOC UNSOL */
82: }
83:
84: /* Routine to Reset VIOC
85: Poll for 10 sec. then check
86: if (VIOC busy flag is clear) and (VIOC is ready)
87: */
88: v_reset()
89: { register long cnt, stat, r10;
90:
91: VP->v_vioc = V_BSY; /* Set VIOC busy flag */
92: VP->v_ident = (short)0;
93: VP->v_hdwre = V_RESET; /* Reset VIOC */
94: cnt = 200; /* Might need to be tuned ! */
95: while (VP->v_ident==(short)0) /* WATCH OUT WHEN DATA CACHE IS ON */
96: { DELAY(0x50000);
97: if (--cnt == 0) { writes("\nVIOC error, Time out on Reset !");
98: return(0); }
99: }
100:
101: cnt = 0x1ffffff; /* Need to be TUNED */
102: for (;cnt != 0;--cnt); /* VIOC is executing its diagnostic */
103:
104: if ((VP->v_ident != (short)V_ALLOK) &&
105: (VP->v_ident != (unsigned short)0x5555) ) {
106: writes("\nVIOC error after Reset !");
107: stat = ((long)VP->v_ident) & 0xffff;
108: writes("\nFault code : ");
109: writeh(stat); writec('\n');
110: return(0);
111: }
112: VP->v_ustat = VP->v_uqual = 0; /* Clear UNSOL. BUFF */
113: return(1);
114: }
115:
116: /* VIOC initialization routines : Sent LIDENT cmd
117: (1) Define interrupt vectors
118: (2) Set 1st, Last logical port no.
119: */
120: v_init()
121: { short *flycmd(), *rsp_blk, stat_wd;
122:
123: cblok.opcode = LIDENT; /* Set opcode */
124: cblok.byte[0] = ACK_VIOC; /* Set interrupt vectors */
125: cblok.byte[1] = CMD_RESP;
126: cblok.byte[3] = UNS_VEC;
127: cblok.byte[4] = 16; /* Max no port to turn on */
128: cblok.byte[5] = log_p0 = 1; /* 1st port is logical no. 1 */
129: /* Sent command to VIOC */
130: log_pn = 0;
131: rsp_blk = flycmd(&stat_wd);
132: if ((stat_wd & 0x7f00) != 0x300) {
133: writes("LIDENT error ");
134: stat_wd = (stat_wd >> 8) & 0xff;
135: writeh((long)stat_wd); NL;
136: return(0);
137: asm("halt");
138: }
139: log_pn = (long)(rsp_blk[6] & 0xff); /* Last log. port no */
140: rsp2v(rsp_blk); /* Sent a cmd respond int. to VIOC */
141: if (log_pn < log_p0) writes("0 port available.\n");
142: else {
143: set_port();
144: writes("\nLast port no. ");
145: writed(log_pn); writec('\n');
146: }
147: return(1);
148: }
149:
150: /* check out how many ports are on line
151: */
152: set_port()
153: { long ix;
154:
155: /* Initialze ports */
156: for(ix=1; ix<=log_pn; ix++) {
157: msg_on = 0;
158: port_on[ix-1] = (char)1; /* This port is on */
159: if ( !v_initp(ix,NDBT,NSBT,BAUD,PARY)) {
160: port_on[ix-1] = (char)0; /* This port is off */
161: writes("Port "); writeh(ix);
162: writes(" is not on line\n");
163: }
164: else {
165: init_buf(ix); /* Init. input buffer */
166: }
167: msg_on = 1;
168: }
169: }
170:
171:
172: /* routine to inittialize input buffer for port X
173: input : pno - logical port no. on VIOC
174: */
175: init_buf(pno)
176: long pno;
177: { struct vbuf *vb;
178: register long ix;
179:
180: vb = &vi_buf[pno-1];
181: vb->cnt = vb->nxt_c = vb->nxt_fill = 0;
182: for(ix=0; ix<BUFLEN; ix++) vb->buf[ix] = 0;
183: }
184:
185: /* Routine to sent LPRARAX command to VIOC
186: Also used to probe if a port is on line
187: return 1 if port is on line else return 0
188: */
189: v_initp(pno, ndbits, nsbits, baud, parity)
190: long pno, ndbits, nsbits, baud, parity;
191: {
192: short *flycmd(), stat_wd, *rsp_blk;
193:
194: cblok.opcode = LPARAX; /* Set opcode */
195: cblok.byte[0] = 0; /* not used */
196: cblok.byte[1] = (char)pno; /* Port no. */
197: cblok.byte[2] = 0; /* Enable port's transmitter */
198: cblok.byte[3] = 0;
199: cblok.byte[4] = (char)ndbits; /* no. data bit */
200: cblok.byte[5] = (char)nsbits; /* no. stop bit */
201: cblok.byte[6] = (char)baud; /* Baud rate */
202: cblok.byte[7] = (char)parity; /* Parity */
203:
204: /* Sent command to VIOC */
205: rsp_blk = flycmd(&stat_wd);
206: rsp2v(rsp_blk); /* Sent a cmd respond int. to VIOC */
207: if (stat_wd) { /* CMD Respond error */
208: if (msg_on) {
209: writes("LPARAX error ");
210: stat_wd = (stat_wd >> 8) & 0xff;
211: writeh((long)stat_wd); NL; }
212: return(0);
213: }
214: return(1);
215: }
216:
217: /* Routine to sent AUTO loop back/local echo
218: command to VIOC;
219: return 1 if port is on line else return 0
220: */
221: v_autol(pno,on,op)
222: long pno,on, op;
223: {
224: short *flycmd(), stat_wd, *rsp_blk;
225:
226: cblok.opcode = AUTOLP; /* Set opcode */
227: cblok.byte[0] = on | op; /* enable/disable auto loopback/echo */
228: cblok.byte[1] = pno; /* port no */
229:
230: /* Sent command to VIOC */
231: rsp_blk = flycmd(&stat_wd);
232: rsp2v(rsp_blk); /* Sent a cmd respond int. to VIOC */
233:
234: if (stat_wd) { /* CMD Respond error */
235: if (msg_on) {
236: writes("AUTOLP error ");
237: stat_wd = (stat_wd >> 8) & 0xff;
238: writeh((long)stat_wd); NL; }
239: return(0);
240: }
241: return(1);
242: }
243:
244: /* Sent a command to VIOC. wait for respond and
245: (1) return pointer to respond buffer
246: (2) output paramter :
247: stat = 1st word of respond buffer if error;
248: 0 if command sucessfully executed by VIOC
249:
250: */
251: short *flycmd(stat)
252: short *stat;
253: { register long *r12;
254: short *sent_cmd(), *rsp_blk, stat_wd;
255:
256: rsp_blk = sent_cmd(&cblok); /* issue command to VIOC */
257: if ( !rsp_blk ) { /* HOST issued invalid interrupt */
258: stop();
259: }
260: stat_wd = (*rsp_blk) & 0xffff;
261: if ( stat_wd & (V_ERR << 8) ) *stat = stat_wd;
262: else *stat = 0;
263: return(rsp_blk);
264: }
265:
266:
267:
268:
269: /* Routine to sent a command to VIOC, Command buffer should be
270: filled by HOST before calling this routine :
271: Issue CMD INP INT to VIOC, Wait for VIOC to sent ACK INT
272: If VIOC ACK with INT ERR bit set print INT ERR code and return 0
273: else wait for CMD RESP INT from VIOC
274: Return pointer to Command Respond block.
275: */
276: short *sent_cmd(cmdblk)
277: struct cmd_inp *cmdblk;
278: {
279: register long cnt, *r11;
280: register short *rsp_stat;
281: short *sptr, *gt_rspadr(), ix;
282:
283: cnt = 0x100;
284: while (v_busy()) /* Test VIOC Busy flag */
285: { DELAY(0x50000);
286: if (--cnt == 0) panic("\nSent_cmd time out\n");
287: }
288: if (!v_rdy4cmd()) /* VIOC not ready for new command */
289: { DELAY(0x50000);
290: if (--cnt == 0) panic("\nSent_cmd not ready\n");
291: }
292: set_cadr((long)cmdblk); /* Set cmd address in commom buffer */
293: VP->v_vcbsy = V_BSY; /* Set CMD BUSY FLAG */
294: v_int((char)V_CMDI); /* Sent CMD INPUT INTERRUPT */
295:
296: for(vioc_ack=1;vioc_ack != 0;); /* Wait for ACK */
297: if (VP->v_vcid & V_ERR)
298: { /* Interrupt error */
299: writes("\nCmd input Int. error ");
300: writeh((long)(VP->v_vcid & 0x3)); NL;
301: return(0);
302: }
303: cmd_id = (long)VP->v_vcid & 0xf; /* Get command ID from VIOC */
304:
305: for(vioc_rsp=1;vioc_rsp != 0;); /* Wait for CMD respond int. */
306: rsp_stat = gt_rspadr(); /* Get addr of Respond buffer */
307:
308: /* For debugging only : Read command respond buffer from VIOC */
309: sptr = rsp_stat;
310: for (ix=0; ix <MAXRLEN; ix++) cmdrsp[ix] = *sptr++;
311:
312: return(rsp_stat);
313: }
314:
315: /* This routine sent a command respond interrupt to VIOC
316: */
317: rsp2v(rsp_blk)
318: short *rsp_blk;
319: { register long cnt;
320:
321: cnt = 0x100;
322: while (v_busy()) /* Test VIOC Busy flag */
323: { DELAY(0x50000);
324: if (--cnt == 0) panic("\nRsp2v time out\n");
325: }
326: *rsp_blk = 0; /* Clear RESP. BUSY Flag */
327: v_int((char)V_CMDRI); /* Sent a cmd respond int. to VIOC */
328: }
329:
330: /* Routine to sent a string to port #pno
331: Return a 1 if command executed else return 0
332: */
333: pstr(pno,c)
334: long pno;
335: char *c;
336: { register long *lptr, slen, phys_adr;
337: char *cptr;
338: short *rsp_blk, stat_wd , *flycnd();
339:
340: /* Count length of string */
341: slen = 0;
342: for (cptr=c; *cptr++ != NULL; slen++);
343:
344: /* Fill command buffer */
345: cblok.opcode = (short)XMITDTA; /* XMIT opcode */
346: cblok.byte[0] = (char)pno; /* Port no. */
347: cblok.byte[1] = (char)slen; /* Byte count */
348: lptr = (long *)&cblok.byte[2];
349: phys_adr = va2pa((long)c); /* Convert VA of string to phys. addr */
350: *lptr = (long)phys_adr; /* Set address of buffer */
351:
352: rsp_blk = flycmd(&stat_wd); /* Sent command to VIOC */
353: rsp2v(rsp_blk); /* sent respond int. to VIOC */
354: if (stat_wd) {
355: writes("XMITDTA error ");
356: stat_wd = (stat_wd >> 8) & 0xff;
357: writeh((long)stat_wd); NL;
358: return(0);
359: }
360: return(1);
361: }
362:
363:
364: /* Routine to put a char to port #pno
365: */
366: pchar(pno,c)
367: long pno;
368: char c;
369: {
370: char str[3];
371:
372: str[0] = c;
373: if (c=='\n') {
374: str[1] = '\r';
375: str[2] = NULL; }
376: else str[1] = NULL;
377: return(pstr(pno,str));
378: }
379:
380:
381: /* Routine return the address of CMD RESP. Buffer in
382: shared area
383: */
384: short *gt_rspadr()
385: {
386: return((short *)((long)VP + VP->v_rsp));
387: }
388:
389:
390: /* Routine to sent an interrupt to VIOC
391: Input : Bit 0,1 of 'qual' indicate type of interrupt
392: */
393: v_int(qual)
394: char qual;
395: {
396: char vint;
397:
398: vint = (char)((V_BSY | qual) & 0xff);
399: VP->v_vioc = vint; /* Set busy flag, int. qualifier */
400: VP->v_hdwre = V_INTR; /* Interrupt VIOC */
401: }
402:
403:
404: /* Routine to test if VIOC is ready to accept new command
405: Return 1 if ready Else return 0
406: */
407: v_rdy4cmd()
408: { register long *r12;
409:
410: if (VP->v_vcbsy & V_BSY) {
411: return(0);
412: }
413: else return(1);
414: }
415:
416:
417: /* Routine to test if VIOC busy, Return 1
418: if not busy Else return 0
419: */
420: v_busy()
421: { register long *r12;
422:
423: if (VP->v_vioc & V_BSY) return(1);
424: else {
425: return(0);
426: }
427: }
428:
429:
430: /* Routine to set cmd address in commom buffer.
431: Command address has to be translated to physical
432: address.
433: input : blkadr (virtual address)
434: */
435: set_cadr(blkadr)
436: long blkadr;
437: { register long word1, cmdadr;
438:
439: cmdadr = va2pa(blkadr); /* VA to physical address */
440: VP->v_vcp1 = (short)(cmdadr & 0xffff);
441: word1 = (cmdadr >> 16) & 0xffff;
442: VP->v_vcp0 = (short)word1;
443: }
444:
445:
446: /* Routine translate virtual address to physical address
447: */
448: va2pa(va)
449: long va;
450: { register long *base, pte, pte_no, page_no, cmdadr;
451:
452: /* Translate virtual to physical address */
453: asm("mfpr $SBR,r12");
454: pte_no = (va >> PGSHIFT) & 0x3fffff; /* Virtual pgno of cmd addr */
455: pte = base[pte_no]; /* PTE for this page no */
456: page_no = pte & 0x3fffff;
457: cmdadr = (page_no << PGSHIFT) | (va & 0x3ff);
458: return(cmdadr);
459: }
460:
461: panic(msg)
462: char *msg;
463: {
464: writes(msg);
465: stop();
466: }
467:
468: stop()
469: {
470: asm("halt");
471: }
472:
473:
474:
475: /* Handler of VIOC CMD RESP. INT */
476: rsp_handlr()
477: {
478: asm(".align 2");
479: asm(".globl rsp_hdlr");
480: asm("rsp_hdlr:");
481: vioc_rsp = 0; /* Clear Vioc_rsp flag */
482: asm("rei");
483: }
484:
485:
486:
487: /* Handler of VIOC ACK INT */
488: ack_handlr()
489: {
490: asm(".align 2");
491: asm(".globl ack_hdlr");
492: asm("ack_hdlr:");
493: vioc_ack = 0; /* Clear Vioc ack flag */
494: asm("rei");
495: }
496:
497: /* Global variables used in Unsolicited int. handler */
498: long silo_no, no_char, cin, count;
499: char ascii;
500:
501: /* Handler of VIOC UNSOLICITED interrupt : service on ISP
502: (1) Dump silo contents
503: */
504: unsol_handlr()
505: {
506: asm(".align 2");
507: asm(".globl unsol_hdlr");
508: asm("unsol_hdlr:");
509: asm("svpctx"); /* Save context, also switch to ISP */
510: dmp_silo();
511: asm("ldpctx"); /* Restore context, switch to KSP */
512: asm("rei");
513: }
514:
515:
516: dmp_silo()
517: { register long rsp_qual, pno, error, rec_err;
518:
519: rec_err = 0;
520: rsp_qual = VP->v_uqual & 0x7;
521: switch (rsp_qual) {
522: case 1 : {
523: writes("received data error\n");
524: rec_err = 1;
525: goto nomore; }
526: case 2 : {
527: writes("VIOC process error\n");
528: goto nomore; }
529: case 3 : {
530: writes("data set change ");
531: writeh(VP->v_uqual & 0x3f); NL;
532: goto nomore; }
533: case 4 : {
534: writes("secondary receive change");
535: goto nomore; }
536: case 5 : {
537: writes("undefined respond error code ");
538: writeh(rsp_qual); NL;
539: goto nomore; }
540: }
541: /* Data available */
542: silo_no = (long)VP->v_usdata[0];
543: for(;;) {
544: s_entry = (short *)(IObase+SILO_BASE + (silo_no * SILO_DEPTH));
545: cin = (long)((*s_entry) & 0xff); /* Get char. count */
546: if (cin==0) goto nomore;
547:
548: /* Print contents of 1 SILO */
549: for(no_char=1; no_char<=cin; no_char++)
550: {
551: ascii = (char)((s_entry[no_char] & 0xff00) >> 8);
552: if ( !(s_entry[no_char] & 0x00c0) ) {
553: pno = s_entry[no_char] & 0x3f;
554:
555: /* Check for port no out of bound */
556: if (!((pno>log_pn) || (pno<log_p0))) {
557: fillc(pno,ascii); }
558: }
559: else {
560: /* Data receive error : parity,frame,overrun */
561: /*
562: writes("data receive error ");
563: error = (long)(s_entry[no_char] & 0xc0) >> 6;
564: writeh(error & 0x3); NL;
565: */
566: }
567: }
568: *s_entry = 0; /* Clear char. count */
569: silo_no++; /* Proceed to next silo */
570: }
571: nomore:
572: count = 200;
573: while (v_busy()) /* Test VIOC Busy flag */
574: { DELAY(0x50000);
575: if (--count == 0)
576: panic("\nUNSOL hdlr : Time out on VIOC busy flag..\n");
577: }
578: VP->v_uqual = 0; /* Reset UNSOL BUSY FLAG */
579: v_int((char)V_URESP); /* Sent ACK UNSOL interrupt to VIOC */
580: return(0);
581: }
582:
583:
584: fillc(pno,c)
585: long pno;
586: char c;
587: { struct vbuf *vb;
588:
589: vb = &vi_buf[pno-1];
590: if (vb->cnt >= BUFLEN) {
591: writes("\ninput overflow port ");
592: writed(pno); NL;
593: return(0); }
594: vb->buf[vb->nxt_fill++] = c;
595: vb->cnt++;
596: if (vb->nxt_fill > BUFLEN) vb->nxt_fill = 0;
597: }
598:
599:
600: char get1c(pno)
601: long pno;
602: { struct vbuf *vb;
603: char c;
604:
605: vb = &vi_buf[pno-1];
606: if (vb->cnt == 0) return((char)0xff);
607: c = vb->buf[vb->nxt_c++];
608: vb->cnt--;
609: if (vb->nxt_c > BUFLEN) vb->nxt_c = 0;
610: return(c);
611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.