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