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