|
|
1.1 root 1: #include "vioc.h"
2: #include "conf.h"
3: #include "const.h"
4: #include "pte.h"
5:
6: #define MAXPORT 16
7: #define MAXRLEN 50
8: #define MAXSLEN 256
9: #define NL writec('\n')
10: #define STAR writes(" ***");
11:
12: /* Pointers to VIOC structures in I/O space */
13: struct vblok *VP; /* Pointer to common buffer */
14: struct cmd_inp cblok; /* VIOC command block (from HOST) */
15: struct cmd_res *rblok; /* PTR to CMD respond blk (from VIOC) */
16:
17: short *s_entry;
18: short cmdrsp[MAXRLEN];
19:
20: long viocb[NVIOC]; /* vioc buffer's address */
21: long vioctype[NVIOC]; /* viocs type */
22: long msg_on = 1; /* Global flag to enable messages */
23: long cmd_id = 0;
24: long IObase; /* Virtual Address of VIOC base */
25: long vioc_ack, vioc_rsp;
26: long log_first = 1; /* Logical port no. of 1st terminal */
27: long log_last = 0; /* Logical port no. of last terminal */
28: init_flg = 0;
29: char port_on[MAXPORT];
30: extern long savvec3, unused, clk_cnt, proc_no;
31:
32: vioc()
33: { register long ix;
34: long vnum;
35:
36: for (ix=vnum=0; ix < NVIOC ; ix++) {
37: if (viocb[ix])
38: if (vioc_diag(ix,vnum)) {
39: v_ex(ix); /* Test this VIOC */
40: }
41: vnum++;
42: }
43: }
44: /*
45: VIOC test routine
46: Return code: 0-----------------Error
47: 1-----------------Good
48: */
49: vioc_diag(unit,vdnum)
50: long unit,vdnum; /* current vioc no */
51: { register long ix, vbase;
52: long v_reset(), v_init();
53:
54: NL; writes("\nBEGIN TESTING VIOC NO. "); writed(vdnum); NL;
55: vbase = viocb[unit];
56: cmd_id = 0;
57: writes("\nInitialize VIOC at "); writeh(vbase); NL;
58: m_vioc(vbase); /* Set up map for IO space */
59: writes("\n1. Internal VIOC Reset Diagnostic"); NL;
60: if (v_reset(unit,vbase)) { /* Reset VIOC */
61: if (vioctype[ix]==VIOC_B) {
62: writes("\n VIOC-B currently not supported\n");
63: return(0);
64: }
65: else writes("\n Reset Passed");
66: }
67: else {
68: writes("\n Reset Failed"); NL;
69: return(0);
70: }
71: NL; writes("\n2. Initialize VIOC");
72: init_flg = 1;
73: if (v_init()) { /* Initialize VIOC */
74: writes(" - initialization passed"); NL;
75: DELAY(0x400000);
76: init_flg = 0;
77: }
78: else {
79: writes(" - initialization failed"); NL;
80: return(0);
81: }
82: writes("\n3. Initialize ports' parameters");NL;
83: if (log_last < log_first) writes("\n\n No ports are available\n");
84: else {
85: set_port(); /* Check how many ports on line */
86: }
87: return(1); /* good return */
88: }
89: /*
90: Check vioc controllers' buffer address
91: */
92: chk_vadr()
93: { register long curadr; /* current examine vioc address */
94: short len, viocno, nviocs,ix; /* address length */
95: ix = len = 1;
96: writes("\n\nProbing for VIOC controller(s)...");
97: curadr = 0xfe0000 + IOBASE;
98: for (nviocs=viocno= 0; viocno < NVIOC; viocno++)
99: {
100: if (!badaddr(curadr,len))
101: {
102: viocb[viocno] = curadr-IOBASE;
103: writes("\nVIOC controller no. "); writed(nviocs);
104: writes(" at address ");
105: writeh((long)curadr-IOBASE);
106: nviocs++;
107: }
108: else /* bad address return */
109: {
110: viocb[viocno] = 0; /* bad address indicator */
111: /* writed(viocno); writes(" ");
112: writes("At bad address"); NL;
113: */
114: }
115: if (ix >= 4){
116: curadr -= 0x1c000;
117: ix = 1;
118: }
119: else {
120: curadr += 0x4000; /* get to next buffer's address */
121: ix++;
122: }
123: }
124: NL; writed(nviocs); writes(" VIOC controller(s) found"); NL;
125: return(nviocs);
126: }
127: /*
128: Routine to Reset VIOC
129: Poll for 10 sec. then check
130: if (VIOC busy flag is clear) and (VIOC is ready)
131: Return code: 0---------------Fault
132: 1---------------Good
133: */
134: v_reset(unit,vbase)
135: long unit,vbase;
136: {
137: VP->v_fault = (char)0; /* Clear fault flag */
138: VP->v_vioc = V_BSY; /* Set VIOC busy flag */
139: VP->v_hdwre = V_RESET; /* Reset VIOC */
140: DELAY(0x700000); /* Wait for reset to complete */
141: if (VP->v_fault != V_ALLOK) {
142: writes("\n\tVIOC error after Reset !");
143: writes("\n\tVIOC I.D : ");
144: writeh(((long)VP->v_ident)&0xff);
145: writes(", Fault code : ");
146: writeh(((long)VP->v_fault)&0xff);
147: return(0);
148: }
149: vioctype[unit] = 0x0; /* Initialize vioc type */
150: switch (VP->v_ident) { /* Determine VIOC type */
151: case 0x1B: /* VIOC-X */
152: {
153: vioctype[unit] = VIOC_X;
154: writes("\n VIOC-X controller is at "); writeh(vbase);
155: break;
156: }
157: case 0x1C: /* VIOC-B */
158: {
159: vioctype[unit] = VIOC_B;
160: writes("\n VIOC-B controller is at "); writeh(vbase);
161: break;
162: }
163: default:
164: {
165: writes("\n Unrecognized VIOC ID"); writeh(VP->v_ident);
166: }
167: } /* end switch */
168: writes(", virtual address : "); writeh((long)VP);
169: writes("\n Max transmit block size "); writeh(VP->xmtsiz);
170: writes("\n Max receive silo char number "); writeh(VP->rcvsilo);
171: VP->v_fault = (char)0x0; /* Clear fault flag */
172: VP->v_ustat = 0x0; /* Clear unsol status */
173: VP->v_uqual = 0x0; /* Clear unsol qual and bsy flag */
174: return(1);
175: }
176: /*
177: For DEBUG. size in bytes.
178: */
179: dump(addr,size)
180: register char *addr;
181: long size;
182: { register long ix = 0;
183: for (;size;ix++) {
184: if (!(ix%4)) {
185: NL; writeh(addr); writes(": ");
186: }
187: writeh((*addr++)&0xff); writes(" ");
188: writeh((*addr++)&0xff); writes(" ");
189: writeh((*addr++)&0xff); writes(" ");
190: writeh((*addr++)&0xff); writes(" ");
191: size -= 4;
192: }
193: }
194:
195: /*
196: dump characters version
197: */
198:
199: dumpc(addr,size)
200: register char *addr;
201: long size;
202: {
203: register long ix;
204:
205: for (;size;size-=25) {
206:
207: for (ix=25;ix;--ix) {
208: writec((*addr++)&0xff); writes(" ");
209: }
210: }
211: }
212: /*
213: VIOC initialization routines : Send LIDENT cmd
214: (1) Define interrupt vectors
215: (2) Set 1st, Last logical port no.
216: */
217: v_init()
218: { short *flycmd(), *rsp_blk, stat_wd;
219:
220: cblok.opcode = LIDENT; /* Set opcode */
221: cblok.byte[0] = ACK_VIOC; /* Set ack interrupt vector */
222: cblok.byte[1] = CMD_RESP; /* Set cmd interrupt vector */
223: cblok.byte[2] = 0x0; /* Not used */
224: cblok.byte[3] = UNS_VEC; /* Set unsol interrupt vector */
225: cblok.byte[5] = log_first = 1; /* 1st port is logical no. 1 */
226: log_last = 0; /* Clear last port variable */
227: if (! (rsp_blk=flycmd()) ) return(0); /* Send command to VIOC */
228: log_last = (long)(rsp_blk[6] & 0xff); /* Last logical port no */
229: return(chk_stat(rsp_blk,"\nLIDENT")); /* Check status and return */
230: }
231: /*
232: Set ports to manual mode with (DTR) and (RTS) disabled
233: */
234: man_init(pno)
235: long pno;
236: {
237: short *rsp_blk;
238: cblok.opcode = MDMCTL; /* Set opcode */
239: cblok.byte[0] = 0x80; /* DTR/RTS disabled */
240: cblok.byte[1] = (char)pno; /* Port no. */
241: if (! (rsp_blk=flycmd()) ) return(0); /* Send to VIOC */
242: return(chk_stat(rsp_blk,"\nMDMCTL")); /* Check status and rtn */
243: }
244: /*
245: check out how many ports are on line
246: */
247: set_port()
248: { long ix;
249: short *v_reqpar();
250: char *rsp;
251:
252: for(ix=1; ix<=log_last; ix++) { /* Initialize ports */
253: msg_on = 0; /* Turn off msgs */
254: port_on[ix-1] = (char)1; /* This port is on */
255: writes("\n Port number "); writeh(ix-1);
256: man_init(ix); /* Set manual mode */
257: if ( !v_initp(ix,NDBT,NSBT,BAUD,PARY)) {
258: port_on[ix-1] = (char)0; /* This port is off */
259: writes(" is not on line");
260: }
261: else {
262: if (rsp=(char *)v_reqpar(ix)) { /* Get port parameter */
263: if ((rsp[10] == (char)NDBT)
264: && (rsp[11] == (char)NSBT)
265: && (rsp[12] == (char)BAUD)
266: && (rsp[13] == (char)PARY)) {
267: writes(" has successfully initialized");
268: init_buf(ix); /* Init. input buffer */
269: }
270: else {
271: writes(" cannot be initialized");
272: port_on[ix-1] = (char)2; /* Turn it off */
273: }
274: }
275: }
276: msg_on = 1;
277: }
278: return(0); /* don't care return code */
279: }
280: /*
281: Routine to send LPRARAX command to VIOC
282: Also used to probe if a port is on line.
283: return 1 if port is on line else return 0
284: */
285: v_initp(pno, ndbits, nsbits, baud, parity)
286: long pno, ndbits, nsbits, baud, parity;
287: {
288: short *flycmd(), stat_wd, *rsp_blk;
289:
290: cblok.opcode = LPARAX; /* Set opcode */
291: cblok.byte[0] = 0x0; /* not used */
292: cblok.byte[1] = (char)pno; /* Port no. */
293: cblok.byte[2] = 0x0; /* Enable port's transmitter */
294: cblok.byte[3] = 0x0;
295: cblok.byte[4] = (char)ndbits; /* no. data bit */
296: cblok.byte[5] = (char)nsbits; /* no. stop bit */
297: cblok.byte[6] = (char)baud; /* Baud rate */
298: cblok.byte[7] = (char)parity; /* Parity */
299:
300: if (! (rsp_blk=flycmd()) ) return(0); /* Send command to VIOC */
301: return(chk_stat(rsp_blk,"\nLPARAX")); /* Check status and rtn */
302: }
303: /*
304: Request port parameters
305: return code:
306: 0 ------------- command error
307: 1 ------------- good
308: */
309: short *
310: v_reqpar(pno)
311: long pno;
312: { short *flycmd(), *rsp_blk, stat_wd;
313:
314: cblok.opcode = RPARALX; /* Set opcode */
315: cblok.byte[0] = 0; /* unused */
316: cblok.byte[1] = (char)pno; /* port number */
317: /* Send command to VIOC */
318: if (! (rsp_blk=flycmd()) ) return(0);
319: if (chk_stat(rsp_blk,"\nRPARALX") == 0) return(0); /* error */
320: return(rsp_blk); /* good return */
321: }
322:
323: /* Routine to send AUTO loop back/local echo
324: command to VIOC;
325: return 1 if port is on line else return 0
326: */
327: v_autol(pno,on,op)
328: long pno,on, op;
329: {
330: short *flycmd(), stat_wd, *rsp_blk;
331:
332: cblok.opcode = AUTOLP; /* Set opcode */
333: cblok.byte[0] = on | op; /* enable/disable auto loopback/echo */
334: cblok.byte[1] = pno; /* port no */
335:
336: /* Send command to VIOC */
337: if (! (rsp_blk=flycmd()) ) return(0);
338: return(chk_stat(rsp_blk,"\nAUTOLP"));
339: }
340:
341: /*
342: Routine to send XMITIMM CMD to VIOC.
343: Used to put a char to port #pno
344: Return a 1 if command executed else return 0
345: */
346: pchar(pno,c)
347: long pno;
348: char c;
349: { register long slen, ix;
350: char str[3], *cptr;
351: register short *rsp_blk;
352:
353: str[0] = c;
354: slen = 0;
355: if (c=='\n') {
356: slen = 2;
357: str[1] = '\r';
358: str[2] = NULL; }
359: /* Fill command buffer */
360: cblok.opcode = (short)XMITIMM; /* XMIT immediate */
361: cblok.byte[0] = (char)pno; /* Port no. */
362: cblok.byte[1] = (char)slen; /* Byte count */
363:
364: cptr = (char *)&cblok.byte[2];
365: for (ix=0;ix <= slen; ix++) *cptr++ = str[ix];
366: if (! (rsp_blk=flycmd()) ) return(0);
367: return(chk_stat(rsp_blk,"\nXMITIMM"));
368: }
369: /*
370: Routine to send XMITDTA CMD to VIOC.
371: Used to send a string to port #pno
372: Return a 1 if command executed else return 0
373: */
374: pstr(pno,c)
375: long pno;
376: char *c;
377: { register long *lptr, slen, phys_adr;
378: char *cptr;
379: short *rsp_blk, stat_wd , *flycmd();
380:
381: /* Count length of string */
382: slen = 0;
383: for (cptr=c; *cptr++ != NULL; slen++);
384:
385: /* Fill command buffer */
386: cblok.opcode = XMITDTA; /* XMIT opcode */
387: cblok.byte[0] = pno; /* Port no. */
388: cblok.byte[1] = (char)slen; /* Byte count */
389:
390: lptr = (long *)&cblok.byte[2];
391: phys_adr = va2pa((long)c); /* Convert VA of string to phys. addr */
392: *lptr = (long)phys_adr; /* Set address of buffer */
393:
394: if (! (rsp_blk=flycmd()) ) return(0);
395:
396: return(chk_stat(rsp_blk,"\nXMITDTA"));
397: }
398: /*
399: Routine to check returned status of CMD
400: return 0 if error else return 1
401: */
402: chk_stat(rsp_blk,cmd)
403: short *rsp_blk;
404: char *cmd;
405: { short stat_wd;
406:
407: stat_wd = *rsp_blk; /* Get status word */
408: if (stat_wd & (short)C_ERR) { /* CMD Error */
409: if (msg_on) { /* Print error msg */
410: writes("\t"); writes(cmd); writes(" error ");
411: stat_wd = rsp_blk[1];
412: writeh((long)stat_wd); NL;
413: }
414: return(0); /* Return bad status */
415: }
416: return(1); /* Return good status */
417: }
418: /*
419: Send a command to VIOC, wait for respond and
420: (1) return pointer to respond buffer
421: (2) Check for matched CMD ID.
422: ** Routine that called this has to check for
423: cmd completion status itself. If cmd can not
424: be send, return a NULL pointer.
425: */
426: short *
427: flycmd()
428: { register long *r12;
429: short *sent_cmd(), *rsp_blk, stat_wd;
430:
431: rsp_blk = sent_cmd(&cblok); /* issue command to VIOC */
432: if (!rsp_blk) {
433: /*
434: Should try to abort this cmd, reset VIOC
435: to known state and continue
436: */
437: return(0); /* ERR : CMD cannot be sent. */
438: }
439: stat_wd = (*rsp_blk) & 0xffff;
440: rsp2v(rsp_blk); /* Send ACK interrupt to VIOC */
441: return(rsp_blk);
442: }
443: /*
444: Routine to send a command to VIOC, Command buffer should be
445: filled by HOST before calling this routine :
446: Issue CMD INP INT to VIOC, Wait for VIOC to send ACK INT
447: If VIOC ACK with INT ERR bit set, print INT ERR code and return 0
448: else wait for CMD RESP INT from VIOC
449: Return pointer to Command Respond block.
450: return code: 0-----------------VIOC/CMD busy flag set.
451: else--------------response buffer address.
452: */
453: short *
454: sent_cmd(cmdblk)
455: struct cmd_inp *cmdblk;
456: {
457: register long cnt, *r11;
458: register short *rsp_stat;
459: short *sptr, *gt_rspadr(), ix, sec;
460:
461: if (v_busy()) return(0); /* Test VIOC BUSY flag */
462: if (!v_rdy4cmd()) return(0); /* Test CMD BUSY flag */
463: set_cadr((long)cmdblk); /* Load CMD address in common buffer */
464: vioc_ack = vioc_rsp = 1;
465: VP->v_vcbsy = V_BSY; /* Set CMD BUSY FLAG */
466: v_int((char)V_CMDI); /* Send CMD INPUT INTERRUPT */
467: sec = 0x0000;
468: while ((vioc_ack != 0) && (sec <= 0x100)) {
469: DELAY(0x5000);
470: if (sec == 0x100) {
471: writes("\n\t*** Time out on CMD ACK interrupt ***\n");
472: return(0); /* no response */
473: }
474: sec++;
475: }
476: cmd_id = (long)(VP->v_vcid & 0xff);
477: if (cmd_id & V_ERR)
478: {
479: writes("\n\tCmd ID/ERR : ");
480: writeh((long)(cmd_id & 0x3C)); NL;
481: return(0);
482: }
483: sec = 0x0000;
484: while ((vioc_rsp != 0) && (sec <= 0x100)) {
485: DELAY(0x5000);
486: if (sec == 0x100) {
487: writes("\n\t*** Time out on CMD RESP interrupt ***\n");
488: return(0); /* no response ! */
489: }
490: sec++;
491: }
492: rsp_stat = gt_rspadr(); /* Get addr of Respond buffer */
493: /* For debugging only : Read command respond buffer from VIOC */
494: sptr = rsp_stat;
495: for (ix=0; ix <MAXRLEN; ix++) cmdrsp[ix] = *sptr++;
496:
497: return(rsp_stat);
498: }
499: /*
500: This routine send a command respond interrupt to VIOC
501: */
502: rsp2v(rsp_blk)
503: short *rsp_blk;
504: { register long cnt;
505:
506: if (v_busy()) panic("\n\t*** Rsp2v time out on VBSY flag ***\n");
507: *rsp_blk &= ~V_BSY; /* Clear RESP. BUSY Flag */
508: v_int((char)V_CMDRI); /* Send a cmd respond int. to VIOC */
509: }
510: /* Routine return the address of CMD RESP. Buffer in
511: shared area
512: */
513: short *
514: gt_rspadr()
515: {
516: return((short *)( ((char *)VP) + (VP->v_rsp & 0x7fff)));
517: }
518: /*
519: Routine to send an interrupt to VIOC
520: Input : Bit 0,1 of 'qual' indicate type of interrupt
521: */
522: v_int(qual)
523: char qual;
524: {
525: char vint;
526:
527: vint = (char)((V_BSY | qual) & 0xff);
528: VP->v_vioc = vint; /* Set busy flag, int. qualifier */
529: VP->v_hdwre = V_INTR; /* Interrupt VIOC */
530: }
531: /*
532: Routine to test if VIOC is ready to accept new command
533: Return 1 if ready Else return 0
534: */
535: v_rdy4cmd()
536: { register long cnt;
537:
538: cnt = 0x100;
539: while (VP->v_vcbsy & V_BSY) {
540: DELAY(0x5000);
541: if (--cnt == 0) {
542: writes("\n\t*** VIOC CMD BUSY flag set ***\n");
543: return(0); }
544: }
545: return(1);
546: }
547: /*
548: Routine to test if VIOC busy, Return 1
549: if not busy Else return 0
550: */
551: v_busy()
552: { register long cnt, *r12;
553:
554: cnt = 0x100;
555: while (VP->v_vioc & V_BSY) {
556: DELAY(0x5000);
557: if (--cnt == 0) {
558: writes("\n\t*** VIOC BUSY flag set ***\n");
559: return(1);
560: }
561: }
562: return(0);
563: }
564: /*
565: Handler of VIOC CMD RESP. INT
566: */
567: rsp_handlr()
568: {
569: asm(".align 2");
570: asm(".globl rsp_hdlr");
571: asm("rsp_hdlr:");
572: vioc_rsp = 0; /* Clear Vioc_rsp flag */
573: asm("rei");
574: }
575: /*
576: Handler of VIOC ACK INT
577: */
578: ack_handlr()
579: {
580: asm(".align 2");
581: asm(".globl ack_hdlr");
582: asm("ack_hdlr:");
583: vioc_ack = 0; /* Clear Vioc ack flag */
584: asm("rei");
585: }
586: /*
587: Global variables used in Unsolicited int. handler
588: */
589: long silo_no, no_char, cin, count;
590: char ascii;
591:
592: /*
593: Handler of VIOC UNSOLICITED interrupt : service on ISP
594: (1) Dump silo contents
595: */
596: unsol_handlr()
597: {
598: asm(".align 2");
599: asm(".globl unsol_hdlr");
600: asm("unsol_hdlr:");
601: asm("svpctx"); /* Save context, also switch to ISP */
602: dmp_silo();
603: asm("ldpctx"); /* Restore context, switch to KSP */
604: asm("rei");
605: }
606: dmp_silo()
607: { register long rsp_qual, pno, error, rec_err;
608: register long ptr2silo;
609: short ix;
610:
611: rec_err = 0;
612: if(init_flg) goto nomore;
613: /* ptr2silo = (long)*(short *)(&VP->v_usdata[0]);
614: ptr2silo &= 0x3fff; */
615: rsp_qual = VP->v_uqual & 0x7;
616: switch (rsp_qual) {
617: case 1 : {
618: writes("\n\t*** Received data error. ***");
619: goto nomore; }
620: case 2 : {
621: writes("\n\t*** VIOC process error. ***");
622: goto nomore; }
623: case 3 : {
624: error = VP->v_ustat & 0x3f;
625: writes("\n\t*** Data set change, STATUS ");
626: writeh(error); STAR;
627: goto nomore; }
628: case 4 : {
629: writes("\n\t*** Secondary receive change ***");
630: goto nomore; }
631: case 7 :
632: case 6 :
633: case 5 : {
634: writes("\n\t*** Undefined UNSOL INT QUAL ***");
635: writeh(rsp_qual);
636: goto nomore; }
637: }
638: /* Data available */
639: /*
640: s_entry = (short *) ((char *)VP) + ((char *)ptr2silo & 0xffff);
641: */
642: ptr2silo = (long)*(short *)(&VP->v_usdata[0]);
643: ptr2silo &= 0x3fff;
644: ptr2silo += (long)VP; /* VAX's Tahoe compiler sucks rock. */
645: s_entry = (short *)ptr2silo;
646: cin = (long)((*s_entry) & 0xffff); /* Get char. count */
647: if (cin==0) goto nomore;
648: /* Print contents of 1 SILO */
649: for(no_char=1; no_char<=cin; no_char++)
650: {
651: ascii = (char)((s_entry[no_char] >> 8) & 0xff);
652: if ( !(s_entry[no_char] & 0x00c0) ) {
653: pno = s_entry[no_char] & 0x3f;
654:
655: /* Check for port no out of bound */
656: if (!((pno>log_last) || (pno<log_first))) {
657: if (!fillc(pno,ascii))
658: goto nomore; /* exit */
659: }
660: else {
661: writes("\n\t*** Port out of bound : ");
662: writed(pno); STAR;
663: }
664: }
665: else {
666: /* Data receive error : parity,frame,overrun */
667: writes("\n\t*** data receive error ");
668: error = (long)(s_entry[no_char] & 0xc0) >> 6;
669: writeh(error & 0x3); STAR; NL;
670: }
671: }
672: *s_entry = 0; /* Clear char. count */
673: nomore:
674: if (v_busy())
675: panic("\n\t*** UNSOL hdlr : Time out on VIOC busy flag ***\n");
676:
677: VP->v_uqual = 0; /* Reset UNSOL BUSY FLAG */
678: v_int((char)V_URESP); /* Send ACK UNSOL interrupt to VIOC */
679: return(0);
680: }
681: fillc(pno,c)
682: long pno;
683: char c;
684: { struct vbuf *vb;
685:
686: vb = &vi_buf[pno-1];
687: if (vb->cnt >= BUFLEN) {
688: writes("\n\t*** Input overflow, port no. ");
689: writed(pno-1); STAR; NL;
690: /* dumpc(&(vb->buf[0]),100); /* dump input buffer */
691: return(0); }
692: vb->buf[vb->nxt_fill++] = c;
693: vb->cnt++;
694: if (vb->nxt_fill > BUFLEN) vb->nxt_fill = 0;
695: return(1);
696: }
697: char get1c(pno)
698: long pno;
699: { struct vbuf *vb;
700: char c;
701:
702: vb = &vi_buf[pno-1];
703: if (vb->cnt == 0) return((char)0xff);
704: c = vb->buf[vb->nxt_c++];
705: vb->cnt--;
706: if (vb->nxt_c > BUFLEN) vb->nxt_c = 0;
707: return(c);
708: }
709: /*
710: Routine to map VIOC :
711: VIOC space is map from 1st unused virtual page on
712: */
713: m_vioc(vbase)
714: long vbase;
715: { register long phys_pg, pte, which1;
716: long old_pte;
717: phys_pg = ((vbase+IOBASE) >> PGSHIFT) & 0x3fffff;
718: /* 1st physical page of VIOC in IO space */
719: pte = phys_pg | PG_KW | PG_V | PG_NC;
720: for (which1=unused; which1<(unused+VIOC_LEN); which1++) {
721: fix_pte(SBR,which1,&old_pte,pte);
722: pte++;}
723: VP = (struct vblok *)(unused << PGSHIFT);
724: IObase = (long)VP; /* Base addr of common buffer */
725: asm("mfpr $SLR,_savvec3"); /* Get number of PTE's */
726: savvec3 += VIOC_LEN; /* Add buffer pages */
727: asm("mtpr _savvec3,$SLR"); /* Set SBR */
728: asm("mtpr _savvec3,$P0LR"); /* Set P0LR also */
729: unused = which1; /* Next unused PTE in system map */
730: asm("mtpr $1,$TBIA"); /* Clear translation buffer */
731: asm("mtpr $1,$PADC"); /* Purge all data cache */
732: }
733: /*
734: Initialize Tahoe SCB vectors to handle VIOC interrupts
735: */
736: init_vec()
737: { long old_vec1, old_vec2, old_vec3;
738:
739: asm("movab ack_hdlr,_savvec3");
740: set_handler(ACK_VIOC,&old_vec1,savvec3); /* Set handler for VIOC ACK */
741: asm("movab rsp_hdlr,_savvec3");
742: set_handler(CMD_RESP,&old_vec2,savvec3); /* Set handler for VIOC RSP */
743: asm("movab unsol_hdlr,_savvec3");
744: set_handler(UNS_VEC,&old_vec3,savvec3); /* Set hdler for VIOC UNSOL */
745: }
746: /*
747: Routine translate virtual address to physical address
748: */
749: va2pa(va)
750: long va;
751: { register long *base, pte, pte_no, page_no, cmdadr;
752:
753: /* Translate virtual to physical address */
754: asm("mfpr $SBR,r12");
755: pte_no = (va >> PGSHIFT) & 0x3fffff; /* Virtual pgno of cmd addr */
756: pte = base[pte_no]; /* PTE for this page no */
757: page_no = pte & 0x3fffff;
758: cmdadr = (page_no << PGSHIFT) | (va & 0x3ff);
759: return(cmdadr);
760: }
761: panic(msg)
762: char *msg;
763: {
764: writes(msg);
765: asm("halt");
766: }
767: /*
768: Routine to set cmd address in common buffer.
769: Command address has to be translated to physical
770: address.
771: input : blkadr (virtual address)
772: */
773: set_cadr(blkadr)
774: long blkadr;
775: { register long word1, cmdadr;
776:
777: cmdadr = va2pa(blkadr); /* VA to physical address */
778: VP->v_vcp1 = (short)(cmdadr & 0xffff);
779: word1 = (cmdadr >> 16) & 0xffff;
780: VP->v_vcp0 = (short)word1;
781: }
782: /*
783: routine to initialize input buffer for port X
784: input : pno - logical port no. on VIOC
785: */
786: init_buf(pno)
787: long pno;
788: { struct vbuf *vb;
789: register long ix;
790:
791: vb = &vi_buf[pno-1];
792: vb->cnt = vb->nxt_c = vb->nxt_fill = 0;
793: for(ix=0; ix<BUFLEN; ix++) vb->buf[ix] = 0;
794: }
795: /*
796: Request current port parameters and print them to console
797: */
798: /*
799: Send a break command to vioc
800: return code:
801: 0 ------------- command error
802: 1 ------------- good return
803: */
804: v_break(pno,brklgth)
805: long pno;
806: short brklgth;
807: { short *flycmd(), *rsp_blk, stat_wd;
808:
809: cblok.opcode = SNDBRKX; /* Set opcode */
810: cblok.byte[0] = brklgth; /* break length*/
811: cblok.byte[1] = pno; /* port number */
812: /* Send command to VIOC */
813: if (! (rsp_blk=flycmd()) ) return(0);
814: if (chk_stat(rsp_blk,"\nSNDBRKX") == 0) return(0); /* error */
815: return(1); /* good return */
816: }
817: /*
818: Send a command to flush the hung xmit command
819: return code:
820: 0 ------------- command error
821: 1 ------------- good return
822: */
823: v_flush(pno)
824: long pno;
825: { short *flycmd(), *rsp_blk, stat_wd;
826:
827: cblok.opcode = FDTATOX; /* Set opcode */
828: cblok.byte[0] = 0; /* not used */
829: cblok.byte[1] = pno; /* port number */
830: /* Send command to VIOC */
831: if (! (rsp_blk=flycmd()) ) return(0);
832: if (chk_stat(rsp_blk,"\nFDTATOX") == 0) return(0); /* error */
833: return(1); /* good return */
834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.