t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) { int line ; int newln ; TMLN * tmlnp ; ++qty_polls ; /* another time 'round the track */ newln = tmxr_poll_conn( &qty_desc ) ; /* anybody knocking at the door? */ if ( (newln >= 0) && qty_mdm ) if ( newln >= qty_max ) { return SCPE_IERR; /* WTF - sanity check failed, over? */ } else { line = newln ; /* handle modem control */ tmlnp =&qty_ldsc[ line ] ; tmlnp->rcve = tmlnp->xmte = 1 ; /* do QTY_LINE_ bit fiddling and state machine * manipulation with modem control signals */ } tmxr_poll_rx( &qty_desc ) ; /* poll input */ qty_update_rcvi( &qty_desc ) ; /* update receiver interrupt status */ tmxr_poll_tx( &qty_desc ) ; /* poll output */ qty_update_xmti( &qty_desc ) ; /* update transmitter interrupt status */ qty_update_status( dibp, &qty_desc ) ; /* update device status */ sim_activate( unitp, tmxr_poll ) ; /* restart the bubble machine */ return ( SCPE_OK ) ; } /* end of 'qty_common_svc' */
t_stat ttox_svc (UNIT *uptr) { int32 c, ln = uptr - ttox_unit; /* line # */ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags) | TTUF_KSR); if (c >= 0) /* output char */ tmxr_putc_ln (lp, c); tmxr_poll_tx (&ttx_desc); /* poll xmt */ } else { tmxr_poll_tx (&ttx_desc); /* poll xmt */ sim_activate (uptr, ttox_unit[ln].wait); /* wait */ return SCPE_OK; } } ttox_set_done (ln); /* set done */ return SCPE_OK; }
t_stat muxo_svc (UNIT *uptr) { int32 c; uint32 ln = uptr - muxl_unit; /* line # */ if (mux_ldsc[ln].conn) { /* connected? */ if (mux_ldsc[ln].xmte) { /* xmt enabled? */ c = sim_tt_outcvt (mux_xbuf[ln], TT_GET_MODE (muxl_unit[ln].flags)); if (c >= 0) tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */ tmxr_poll_tx (&mux_desc); /* poll xmt */ if (mux_sta[ln] & MUXL_XIA) { /* armed? */ mux_sta[ln] |= MUXL_XIR; /* req intr */ mux_scan_next (0); /* kick scanner */ } } else { /* buf full */ tmxr_poll_tx (&mux_desc); /* poll xmt */ sim_activate (uptr, muxl_unit[ln].wait); /* wait */ return SCPE_OK; } } return SCPE_OK; }
t_stat dtco_srv(UNIT * uptr) { int c, ln, t, c1; sim_clock_coschedule(uptr, tmxr_poll); ln = tmxr_poll_conn(&dtc_desc); /* look for connect */ if (ln >= 0) { /* got one? */ dtc_ldsc[ln].rcve = 1; dtc_blimit[ln] = dtc_bufsize-1; dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufWriteRdy; IAR |= IRQ_12; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm connect %d\n", ln); } /* For each line that is in idle state enable recieve */ for (ln = 0; ln < dtc_desc.lines; ln++) { dtc_ldsc[ln].rcve = 0; if (dtc_ldsc[ln].conn && (dtc_lstatus[ln] & BufSMASK) < BufWrite) { dtc_ldsc[ln].rcve = 1; } } tmxr_poll_rx(&dtc_desc); /* poll for input */ for (ln = 0; ln < DTC_MLINES; ln++) { /* loop thru mux */ /* Check for disconnect */ if (dtc_ldsc[ln].conn == 0 && (dtc_lstatus[ln] & BufDisco) == 0) { /* connected? */ dtc_ldsc[ln].rcve = 0; switch(dtc_lstatus[ln] & BufSMASK) { case BufIdle: /* Idle Flag as disconnected */ dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufIdle|BufDisco; dtc_bsize[ln] = 0; IAR |= IRQ_12; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d idle\n", ln); break; case BufWriteRdy: /* Awaiting output, terminate */ dtc_bufptr[ln] = 0; /* Fall through */ case BufInputBusy: /* reading, terminate with EOT */ dtc_buf[ln][dtc_bufptr[ln]++] = 017; dtc_bsize[ln] = dtc_bufptr[ln]+1; dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufReadRdy; IAR |= IRQ_12; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d write\n", ln); break; case BufOutBusy: /* Terminate Output */ dtc_lstatus[ln] = BufIRQ|BufIdle|BufAbnormal; dtc_bsize[ln] = 0; IAR |= IRQ_12; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d out\n", ln); break; default: /* Other cases, ignore until in better state */ break; break; } continue; /* Skip if not connected */ } switch(dtc_lstatus[ln] & BufSMASK) { case BufIdle: /* If we have any data to receive */ if (tmxr_rqln(&dtc_ldsc[ln]) > 0) { dtc_lstatus[ln] &= ~(BufSMASK); dtc_lstatus[ln] |= BufInputBusy; } else break; /* Nothing to do */ sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d idle\n", ln); dtc_bufptr[ln] = 0; dtc_bsize[ln] = 0; /* Fall through */ case BufInputBusy: t = 1; while (t) { c = tmxr_getc_ln(&dtc_ldsc[ln]); /* get char */ if (c == 0) break; c &= 0x7f; c1 = ascii_to_con[c]; switch(c) { case '\005': /* ^E ENQ who-are-you */ dtc_lstatus[ln] &= ~(BufSMASK); dtc_lstatus[ln] |= BufIRQ|BufWriteRdy|BufAbnormal; IAR |= IRQ_12; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve ENQ %d\n", ln); t = 0; break; case '\003': /* ^B send STX */ dtc_lstatus[ln] &= ~BufSMASK; dtc_lstatus[ln] |= BufIRQ|BufReadRdy|BufAbnormal; dtc_buf[ln][0] = 0; dtc_buf[ln][1] = 017; dtc_buf[ln][2] = 077; dtc_bsize[ln] = 1; IAR |= IRQ_12; t = 0; break; case '}': dtc_buf[ln][dtc_bufptr[ln]++] = 017; dtc_lstatus[ln] |= BufAbnormal; /* Fall through to next */ case '\r': /* Fall through */ case '\n': /* Fall through */ case '~': dtc_lstatus[ln] &= ~BufSMASK; dtc_lstatus[ln] |= BufIRQ|BufReadRdy; /* Force at least one character for GM */ dtc_buf[ln][dtc_bufptr[ln]++] = 077; dtc_bsize[ln] = dtc_bufptr[ln]; IAR |= IRQ_12; t = 0; c1 = 0; sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d return\n", ln); break; case '\025': /* Control U clear input buffer. */ dtc_bsize[ln] = 0; c1 = 0; break; case '\b': case 0x7f: if (dtc_bufptr[ln] > 0) { tmxr_putc_ln(&dtc_ldsc[ln], '\b'); tmxr_putc_ln(&dtc_ldsc[ln], ' '); tmxr_putc_ln(&dtc_ldsc[ln], '\b'); dtc_bufptr[ln]--; } else { tmxr_putc_ln(&dtc_ldsc[ln], '\007'); } c1 = 0; sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm recieve %d backspace %d\n", ln, dtc_bufptr[ln]); break; case '?': sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm recieve %d ?\n", ln); dtc_lstatus[ln] |= BufAbnormal; tmxr_putc_ln(&dtc_ldsc[ln], '?'); dtc_buf[ln][dtc_bufptr[ln]++] = c1; break; default: sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm recieve %d %02x %c %02o %d\n", ln, c, c, c1, dtc_bufptr[ln]); } if (t && c1) { tmxr_putc_ln(&dtc_ldsc[ln], con_to_ascii[c1]); dtc_buf[ln][dtc_bufptr[ln]++] = c1; } if (dtc_bufptr[ln] >= dtc_blimit[ln]) { sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d full\n", ln); dtc_lstatus[ln] &= ~(BufSMASK); dtc_lstatus[ln] |= BufGM|BufIRQ|BufReadRdy; dtc_bsize[ln] = dtc_bufptr[ln]; IAR |= IRQ_12; t = 0; break; } } break; case BufOutBusy: /* Get next char and send to output */ t = 1; while(t && dtc_bufptr[ln] < dtc_bsize[ln] && dtc_ldsc[ln].xmte) { c = dtc_buf[ln][dtc_bufptr[ln]++]; c1 = con_to_ascii[c]; switch(c) { case 057: /* { */ c1 = '\r'; /* CR */ break; case 032: /* ! */ c1 = '\n'; /* LF */ break; case 076: /* < */ c1 = 0; /* X-ON */ break; case 016: /* > */ c1 = 0; /* DEL */ break; case 017: /* } */ /* Disconnect line */ tmxr_reset_ln(&dtc_ldsc[ln]); sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d\n", ln); t = 0; continue; /* On to next line */ } sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm transmit %d %02o %c\n", ln, c&077, c1); tmxr_putc_ln(&dtc_ldsc[ln], c1); if (c1 == '\n') { tmxr_putc_ln(&dtc_ldsc[ln], '\r'); } } if (dtc_bufptr[ln] >= dtc_bsize[ln]) { if (dtc_lstatus[ln] & BufGM) { sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm idle %d\n", ln); dtc_lstatus[ln] = BufIRQ|BufIdle; } else { sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm writerdy %d\n", ln); dtc_lstatus[ln] = BufIRQ|BufWriteRdy; } IAR |= IRQ_12; } break; default: /* Other states are an ignore */ break; } } /* end for */ tmxr_poll_tx(&dtc_desc); /* poll xmt */ return SCPE_OK; }
t_stat ports_xmt_svc(UNIT *uptr) { uint8 cid, ln; char c; t_bool tx = FALSE; /* Did a tx ever occur? */ cio_entry centry = {0}; uint8 app_data[4] = {0}; uint32 wait = 0x7fffffff; /* Scan all lines for output */ for (ln = 0; ln < ports_desc.lines; ln++) { cid = LCID(ln); if (ports_ldsc[ln].conn && ports_state[ln].tx_chars > 0) { tx = TRUE; /* Even an attempt at TX counts for rescheduling */ c = sim_tt_outcvt(pread_b(ports_state[ln].tx_addr), TT_GET_MODE(ports_unit[0].flags)); /* The PORTS card optionally handles NL->CRLF */ if (c == 0xa && (ports_state[ln].oflag & ONLCR) && !(ports_state[ln].crlf)) { if (tmxr_putc_ln(&ports_ldsc[ln], 0xd) == SCPE_OK) { wait = MIN(wait, ports_ldsc[ln].txdeltausecs); sim_debug(IO_DBG, &ports_dev, "[%08x] [ports_xmt_svc] [LINE %d] XMIT (crlf): %02x (%c)\n", R[NUM_PC], ln, 0xd, 0xd); /* Indicate that we're in a CRLF translation */ ports_state[ln].crlf = TRUE; } break; } ports_state[ln].crlf = FALSE; if (tmxr_putc_ln(&ports_ldsc[ln], c) == SCPE_OK) { wait = MIN(wait, ports_ldsc[ln].txdeltausecs); ports_state[ln].tx_chars--; ports_state[ln].tx_addr++; sim_debug(IO_DBG, &ports_dev, "[%08x] [ports_xmt_svc] [LINE %d] XMIT: %02x (%c)\n", R[NUM_PC], ln, c, c); } if (ports_state[ln].tx_chars == 0) { sim_debug(TRACE_DBG, &ports_dev, "[%08x] [ports_xmt_svc] Done with xmit, card=%d port=%d. Interrupting.\n", R[NUM_PC], cid, LPORT(ln)); centry.byte_count = ports_state[ln].tx_req_chars; centry.subdevice = LPORT(ln); centry.opcode = PPC_XMIT; centry.address = ports_state[ln].tx_req_addr; app_data[0] = RC_FLU; cio_cqueue(cid, CIO_STAT, PPQESIZE, ¢ry, app_data); cio[cid].intr = TRUE; } } } tmxr_poll_tx(&ports_desc); if (tx) { tmxr_activate_after(uptr, wait); } return SCPE_OK; }