t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 newln, i, t; t_stat r; if (cptr == NULL) return SCPE_ARG; newln = get_uint (cptr, 10, MUX_LINES, &r); if ((r != SCPE_OK) || (newln == MUX_NUMLIN)) return r; if (newln == 0) return SCPE_ARG; if (newln < MUX_NUMLIN) { for (i = newln, t = 0; i < MUX_NUMLIN; i++) t = t | mux_ldsc[i].conn; if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) return SCPE_OK; for (i = newln; i < MUX_NUMLIN; i++) { if (mux_ldsc[i].conn) { tmxr_linemsg (&mux_ldsc[i], "\r\nOperator disconnected line\r\n"); tmxr_reset_ln (&mux_ldsc[i]); /* reset line */ } muxl_unit[i].flags = muxl_unit[i].flags | UNIT_DIS; mux_reset_ln (i); } } else { for (i = MUX_NUMLIN; i < newln; i++) { muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS; mux_reset_ln (i); } } MUX_NUMLIN = newln; return SCPE_OK; }
t_stat qty_setnl( UNIT * uptr, int32 val, char * cptr, void * desc ) { int32 newln, i, t ; t_stat r ; if ( cptr == NULL ) { return ( SCPE_ARG ) ; } newln = (int32) get_uint( cptr, 10, QTY_MAX, &r ) ; if ( (r != SCPE_OK) || (newln == qty_desc.lines) ) { return ( r ) ; } if ( (newln == 0) || (newln > QTY_MAX) ) { return ( SCPE_ARG ) ; } if ( newln < qty_desc.lines ) { for ( i = newln, t = 0 ; i < qty_desc.lines ; ++i ) { t = t | qty_ldsc[i].conn ; } if ( t && ! get_yn("This will disconnect users; proceed [N]?", FALSE) ) { return ( SCPE_OK ) ; } for ( i = newln ; i < qty_desc.lines ; ++i ) { if ( qty_ldsc[i].conn ) { /* reset line */ tmxr_msg( qty_ldsc[i].conn, "\r\nOperator disconnected line\r\n" ) ; tmxr_reset_ln( &qty_ldsc[i] ) ; } qty_clear( TRUE ) ; /* reset mux */ } } qty_max = qty_desc.lines = newln ; /* Huh, I don't understand this yet... qty_max = ((qty_dev.flags & DEV_DIS)? 0 : (qty_desc.lines / QTY_MAX)) ; */ return ( SCPE_OK ) ; } /* end of 'qty_setnl' */
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; }
uint32 mux_dio (uint32 op, uint32 rn, uint32 ad) { int32 ln; uint32 fnc = MUXDIO_GETFNC (ad); uint32 coc = MUXDIO_GETCOC (ad); if (op == OP_RD) { /* read direct */ if (coc != 0) /* nx COC? */ return 0; R[rn] = mux_scan | 0x40; /* return line num */ mux_sta[mux_scan] &= ~MUXL_XIR; /* clear int req */ return 0; } ln = MUXDAT_GETLIN (R[rn]); /* get line num */ if (fnc & 0x4) { /* transmit */ if ((coc != 0) || /* nx COC or */ (ln >= MUX_NUMLIN)) { /* nx line? */ CC |= CC4; return 0; } if ((fnc & 0x7) == 0x5) { /* send char? */ if (fnc & 0x8) /* space? */ mux_xbuf[ln] = 0; else mux_xbuf[ln] = MUXDAT_GETCHR (R[rn]); /* no, get char */ sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); mux_sta[ln] = (mux_sta[ln] | MUXL_XIA) & ~MUXL_XIR; mux_scan_next (1); /* unlock scanner */ } else if (fnc == 0x06) { /* stop transmit */ mux_sta[ln] &= ~MUXL_XIA|MUXL_XIR; /* disable int */ mux_scan_next (1); /* unlock scanner */ } else if (fnc == 0x07) { /* disconnect */ tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ mux_reset_ln (ln); /* reset state */ } CC = (sim_is_active (&muxl_unit[ln])? 0: CC4) | (mux_ldsc[ln].conn? CC3: 0); } else { /* receive */ if ((coc != 0) || /* nx COC or */ (ln >= MUX_NUMLIN)) /* nx line */ return 0; if (fnc == 0x01) { /* set rcv enable */ if (mux_ldsc[ln].conn) /* connected? */ mux_ldsc[ln].rcve = 1; /* just enable */ else mux_sta[ln] |= MUXL_REP; /* enable pending */ } else if (fnc == 0x02) { /* clr rcv enable */ mux_ldsc[ln].rcve = 0; mux_sta[ln] &= ~MUXL_REP; } else if (fnc == 0x03) { /* disconnect */ tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ mux_reset_ln (ln); /* reset state */ } if (mux_sta[ln] & MUXL_RBP) /* break pending? */ CC = CC3|CC4; else CC = mux_ldsc[ln].rcve? CC4: CC3; } return 0; }