diff --git a/HP3000/hp3000_atc.c b/HP3000/hp3000_atc.c index a49ef9bd..68aa1e9f 100644 --- a/HP3000/hp3000_atc.c +++ b/HP3000/hp3000_atc.c @@ -26,6 +26,9 @@ ATCD,ATCC HP 30032B Asynchronous Terminal Controller + 18-Dec-17 JDB Return event time instead of status from "activate_unit" + 11-Dec-17 JDB Reschedule "line_service" if receive buffer has data + 26-Oct-17 JDB Call "tmxr_poll_tx" if transmit buffer is full 05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X 16-Sep-16 JDB Fixed atcd_detach to skip channel cancel if SIM_SW_REST 12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG @@ -783,7 +786,7 @@ static void tci_master_reset (void); static t_stat line_service (UNIT *uptr); static t_stat poll_service (UNIT *uptr); -static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason); +static int32 activate_unit (UNIT *uptr, ACTIVATOR reason); static uint32 service_time (HP_WORD control, ACTIVATOR reason); static void store (HP_WORD control, HP_WORD data); static void receive (int32 channel, int32 data, t_bool loopback); @@ -1724,6 +1727,7 @@ tdi_master_reset (); /* perform a master rese if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */ sim_rtcn_init (poll_unit.wait, TMR_ATC); /* then initialize the poll timer */ fast_data_time = FAST_IO_TIME; /* restore the initial fast data time */ + atcd_ldsc [0].xmte = 1; /* enable transmission on the system console port */ } if (atc_is_polling) { /* if we're polling for the simulation console */ @@ -1826,6 +1830,14 @@ return status; unit 16 if it is attached. In all cases, it is imperative that we not reject the request for unit 16; otherwise any remaining device detaches will not be performed. + + + Implementation notes: + + 1. Detaching the multiplexer resets each line first, which flushes the + output buffer. This ensures that buffered data that has not been output + via a poll_service entry before the DETACH command was issued is written + before the line is disconnected. */ static t_stat atcd_detach (UNIT *uptr) @@ -1976,8 +1988,9 @@ return; The channel service routine runs only when there are characters to read or write. It is scheduled either at a realistic rate corresponding to the programmed baud rate of the channel to be serviced, or at a somewhat faster - optimized rate. It is entered when a channel buffer is ready for output or - when the poll routine determines that there are characters ready for input. + optimized rate. It is entered when a channel buffer is ready for output, + when the poll routine determines that there are characters ready for input, + or while waiting for an ACK to complete an ENQ/ACK handshake. On entry, the receive channel buffer is checked for a character. If one is not already present, then the terminal multiplexer library is called to @@ -1985,6 +1998,12 @@ return; processed. If the receive channel has its "diagnose" bit set, the character is also passed to the auxiliary channels. + If a received character is not available, then the unit's "wait" field is + checked to see if an ACK is expected in reply to an earlier ENQ. If a wait + time is present, it is doubled, and the service is rescheduled. However, if + the new wait time is longer than the current poll time, service rescheduling + is abandoned in favor of the normal poll for received characters. + The send channel buffer is then checked for a character to output. If one is present, then if it is an all-mark (sync) character, it is discarded, as the receiver would never see it. Otherwise, if the TDI is in diagnostic mode, @@ -1999,18 +2018,36 @@ return; simulation console (if output is to channel 0) or to the terminal multiplexer library for output via Telnet or a serial port on the host machine. If the channel has its "diagnose" bit set, the character is also passed to the - auxiliary channels. + auxiliary channels. If an ENQ was transmitted, service is rescheduled to + wait for reception of the ACK. If the data flag is clear, the indicated receive and send channels are checked for completion flags. If either is set, an interrupt is requested. + If characters remain in the Telnet receive buffer, the service routine is + rescheduled to receive the next one. Otherwise, the routine goes idle until + the next character is output or the next poll determines that there are + characters to receive. + Implementation notes: - 1. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by + 1. The "wait" fields of the channel units are not used (i.e., are set to + zero) except when channels are waiting for ACKs. Because we want to + retrieve the ACK as quickly as possible but also minimize the load on the + host system, we initially wait the normal reception time (fast or + realistic) and then double the wait each time it expires without + reception. Therefore, a non-zero "wait" value indicates that an ACK is + expected. + + 2. Receipt of any character cancels a pending ACK wait, even though it is + possible that the character is not an ACK (for example, if the character + was received but not processed before the ENQ was sent). + + 3. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by default and therefore will return 0. - 2. The send channel buffer will always be non-zero if a character is present + 4. The send channel buffer will always be non-zero if a character is present (even a NUL) because the data word will have DDS_IS_SEND set. The receive buffer will always be non-zero if a character is present @@ -2019,27 +2056,45 @@ return; TMXR_VALID set, and characters looped back from sending will have DDS_IS_SEND set. - 3. Reception of a loopback character is performed immediately because the + 5. Reception of a loopback character is performed immediately because the reception occurs concurrently with transmission. Reception of a locally generated ACK is scheduled with a one-character delay to reflect the remote device transmission delay. - 4. If storing an ACK locally overwrites a character already present but not + 6. If storing an ACK locally overwrites a character already present but not yet processed, then the receive routine will set the character lost flag. - 5. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only + 7. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only so that a debug trace will record the generation correctly. - 6. The console library "sim_putchar_s" routine and the terminal multiplexer - library "tmxr_putc_ln" routine return SCPE_STALL if the Telnet output - buffer is full. In this case, transmission is rescheduled with a delay - to allow the buffer to drain. + 8. The console library "sim_putchar_s" routine and the terminal multiplexer + library "tmxr_putc_ln" routine return SCPE_STALL if they are called when + the transmit buffer is full. When called to add the last character to + the buffer, the routines return SCPE_OK but also change the "xmte" field + of the terminal multiplexer line (TMLN) structure from 1 to 0 to indicate + that further calls will be rejected; the value is set back to 1 when the + transmit buffer empties. - They also return SCPE_LOST if the line has been dropped on the remote - end. We ignore the error here to allow the simulation to continue while - ignoring the output. + Entry with the transmit buffer full causes the service to be rescheduled + to retry the write after a short delay. The "tmxr_poll_tx" routine must + be called in this case, as it is responsible for transmitting the buffer + contents and therefore freeing space in the buffer. - 7. The receive/send completion flag (buffer flag) will not set unless the + Both library "put" routines also return SCPE_LOST if the line has been + dropped on the remote end. We ignore that error here to allow the + simulation to continue while ignoring the output to a disconnected + terminal. + + 9. Characters written using "tmxr_putc_ln" are buffered and not transmitted + until the buffer is full, the character is an ENQ (and so we will be + waiting to receive an ACK), or the next input poll is performed. The + last case ensures that the buffer is flushed when output is complete, as + there is no indication from the CPU that the last character has been + sent. This does incur a delay of up to 10 milliseconds, but this is + imperceptible by the user. Buffering offers significantly better + throughput compared to transmitting each character as it is written. + + 10. The receive/send completion flag (buffer flag) will not set unless the interrupt enable flag for that channel is also set. If enable is not set, the completion indication will be lost. */ @@ -2058,18 +2113,36 @@ dprintf (atcd_dev, DEB_SERV, "Channel %d service entered\n", /* Reception service */ -recv_data = recv_buffer [channel]; /* get the current buffer character */ +recv_data = recv_buffer [channel]; /* get the current buffer character */ -if (recv_data == 0) /* if there's none present */ - recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* then see if there's a character ready via Telnet */ +if (recv_data == 0) { /* if no character is present */ + if (uptr->wait) /* then if the channel is waiting for an ACK */ + tmxr_poll_rx (&atcd_mdsc); /* then poll the line to see if it has arrived */ -if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */ - receive (channel, recv_data, loopback); /* then process the reception */ - - if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */ - diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */ + recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* see if there's now a character ready */ } +if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */ + receive (channel, recv_data, loopback); /* then process the reception */ + + if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */ + diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */ + + uptr->wait = 0; /* clear any pending ACK wait */ + } + +else if (uptr->wait) { /* otherwise if an ACK is expected but has not arrived */ + uptr->wait = uptr-> wait * 2; /* then double the wait time for the next check */ + + if (uptr->wait < poll_unit.wait) { /* if the wait is shorter than the standard poll wait */ + sim_activate (uptr, uptr->wait); /* then reschedule the line service */ + + dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service rescheduled for ACK\n", + channel, uptr->wait); + } + } + + /* Transmission service */ if (send_buffer [channel]) { /* if data is available to send */ @@ -2133,43 +2206,56 @@ if (send_buffer [channel]) { /* if data is availa cvtd_data = sim_tt_outcvt (LOWER_BYTE (send_data), /* so convert it as directed */ TT_GET_MODE (uptr->flags)); /* by the output mode flag */ - if (cvtd_data >= 0) /* if the converted character is printable */ - if (channel == 0) /* then if we are writing to channel 0 */ - result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */ - else /* otherwise */ - result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */ - cvtd_data); - - if (result == SCPE_STALL) { /* if the buffer is full */ + if (cvtd_data >= 0 && atcd_ldsc [channel].xmte == 0) { /* if it's printable but the transmit buffer is full */ activate_unit (uptr, Stall); /* then retry the output a while later */ - result = SCPE_OK; /* and return OK to continue */ + + tmxr_poll_tx (&atcd_mdsc); /* transmit the line buffer */ + + dprintf (atcd_dev, DEB_XFER, "Channel %d character %s transmission stalled for full buffer\n", + channel, fmt_char (cvtd_data)); } - else if (result == SCPE_OK || result == SCPE_LOST) { /* otherwise if the character is queued to transmit */ - tmxr_poll_tx (&atcd_mdsc); /* then send (or ignore) it */ + else { /* otherwise the character will be consumed */ + if (cvtd_data >= 0) /* if the converted character is printable */ + if (channel == 0) /* then if we are writing to channel 0 */ + result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */ - if (DPRINTING (atcd_dev, DEB_XFER)) - if (result == SCPE_LOST) - hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n", - channel, fmt_char (char_data)); + else { /* otherwise */ + result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */ + cvtd_data); - else if (cvtd_data >= 0) - hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n", - channel, fmt_char (cvtd_data)); + if (char_data == ENQ /* if sending an ENQ */ + || atcd_ldsc [channel].xmte == 0) /* or the output buffer is full */ + tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */ + } - else - hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n", - channel, fmt_char (char_data)); + if (result == SCPE_OK || result == SCPE_LOST) { /* if the character is queued to transmit */ + if (DPRINTING (atcd_dev, DEB_XFER)) + if (result == SCPE_LOST) + hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n", + channel, fmt_char (char_data)); - if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */ - diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */ + else if (cvtd_data >= 0) + hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n", + channel, fmt_char (cvtd_data)); - send_buffer [channel] = 0; /* clear the buffer */ + else + hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n", + channel, fmt_char (char_data)); - if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */ - send_status [channel] |= DST_COMPLETE; /* then set the completion flag */ + if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */ + diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */ - result = SCPE_OK; /* return OK in case the connection was lost */ + send_buffer [channel] = 0; /* clear the buffer */ + + if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */ + send_status [channel] |= DST_COMPLETE; /* then set the completion flag */ + + if (cvtd_data == ENQ && result == SCPE_OK) /* if an ENQ was successfully sent */ + uptr->wait = activate_unit (uptr, Receive); /* then schedule the ACK reception */ + + result = SCPE_OK; /* return OK in case the connection was lost */ + } } } } @@ -2178,6 +2264,9 @@ if (send_buffer [channel]) { /* if data is availa if (tdi_data_flag == CLEAR) /* if an interrupt is not currently pending */ scan_channels (channel); /* then scan the channels for completion flags */ +if (tmxr_rqln (&atcd_ldsc [channel])) /* if characters are still available on this channel */ + activate_unit (uptr, Receive); /* then reschedule the line service */ + return result; /* return the result of the service */ } @@ -2185,10 +2274,9 @@ return result; /* return the result of /* Multiplexer poll service. The poll service routine is used to poll for Telnet connections and incoming - characters. It also polls the simulation console for channel 0. Polling - starts at simulator startup or when the TDI is enabled and stops when it is - disabled. - + characters. It also polls the simulation console for channel 0 and flushes + the output buffers for all channels. Polling starts at simulator startup or + when the TDI is enabled and stops when it is disabled. Implementation notes: @@ -2201,20 +2289,30 @@ return result; /* return the result of may be shorter than the channel service time, and as the console provides no buffering, a second character received before the channel service had been entered would be lost. + + 3. A channel that is waiting for an ACK to complete an ENQ/ACK handshake has + its unit "wait" field set non-zero. If the field value is greater than + the realistic reception time, then the line service is scheduled + immediately, as the channel has already waited the minimum time necessary + (the "wait" field value is doubled each time the line service is entered + before the ACK has been received). Otherwise, the service is scheduled + using the normal reception time. */ static t_stat poll_service (UNIT *uptr) { -int32 chan, line_state; +int32 chan, line_state; t_stat status = SCPE_OK; -dprintf (atcd_dev, DEB_PSERV, "Poll service entered\n"); +dprintf (atcd_dev, DEB_PSERV, "Poll delay %d service entered\n", + uptr->wait); if ((atcc_dev.flags & DEV_DIS) == 0) - dprintf (atcc_dev, DEB_PSERV, "Poll service entered\n"); + dprintf (atcc_dev, DEB_PSERV, "Poll delay %d service entered\n", + uptr->wait); if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagnostic mode */ - chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplex connection */ + chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplexer connection */ if (chan != -1) { /* if a new connection was established */ atcd_ldsc [chan].rcve = TRUE; /* then enable the channel to receive */ @@ -2224,7 +2322,8 @@ if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagn } } -tmxr_poll_rx (&atcd_mdsc); /* poll the multiplex connections for input */ +tmxr_poll_tx (&atcd_mdsc); /* flush the multiplexer output buffers */ +tmxr_poll_rx (&atcd_mdsc); /* and poll the multiplexer connections for input */ if ((atcc_dev.flags & (DEV_DIAG | DEV_DIS)) == 0) /* if we're not in diagnostic mode or are disabled */ for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* then scan the channels for line state changes */ @@ -2258,9 +2357,15 @@ if (status >= SCPE_KFLAG) { /* if a character was pr line_service (&line_unit [0]); /* run the system console's I/O service */ } -for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the receive channels for available input */ - if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */ - activate_unit (&line_unit [chan], Receive); /* then activate the channel's I/O service */ +for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the channels for available input */ + if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */ + if (line_unit [chan].wait > line_unit [chan].recv_time) { /* then if the channel is waiting for an ACK */ + sim_cancel (&line_unit [chan]); /* then cancel any current wait */ + activate_unit (&line_unit [chan], Loop); /* and activate the line service immediately */ + } + + else /* otherwise this is a normal input */ + activate_unit (&line_unit [chan], Receive); /* so schedule with the normal receive timing */ if (cpu_is_calibrated) /* if the process clock is calibrated */ uptr->wait = sim_activate_time (cpu_pclk_uptr); /* then synchronize with it */ @@ -2292,7 +2397,7 @@ return status; /* return the service st called. */ -static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason) +static int32 activate_unit (UNIT *uptr, ACTIVATOR reason) { const int32 channel = (int32) (uptr - line_unit); /* the channel number */ int32 delay = 0; @@ -2340,7 +2445,8 @@ else /* otherwise, we are in dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service scheduled\n", channel, delay); -return sim_activate (uptr, delay); /* activate the unit and return the activation status */ +sim_activate (uptr, delay); /* activate the unit */ +return delay; /* and return the activation delay */ } @@ -2640,17 +2746,20 @@ else { /* otherwise a normal ch recv_buffer [channel] = recv_data | pad; /* and replace the character in the buffer */ } - if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */ - char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */ + if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */ + char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */ TT_GET_MODE (line_unit [channel].flags)); - if (char_echo >= 0) { /* if the converted character is valid for the mode */ - if (channel == 0) /* then if this is for channel 0 */ - sim_putchar (char_echo); /* then write it back to the simulation console */ + if (char_echo >= 0) { /* if the converted character is valid for the mode */ + if (channel == 0) /* then if this is for channel 0 */ + sim_putchar (char_echo); /* then write it back to the simulation console */ - else { /* otherwise */ - tmxr_putc_ln (&atcd_ldsc [channel], char_echo); /* write it to the multiplexer output line */ - tmxr_poll_tx (&atcd_mdsc); /* and poll to transmit it now */ + else { /* otherwise */ + tmxr_putc_ln (&atcd_ldsc [channel], /* write it to the multiplexer output line */ + char_echo); + + if (atcd_ldsc [channel].xmte == 0) /* if the output buffer is full */ + tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */ } dprintf (atcd_dev, DEB_XFER, ("Channel %d character %s echoed\n"), diff --git a/HP3000/hp3000_defs.h b/HP3000/hp3000_defs.h index 33313bd7..dbf98aaf 100644 --- a/HP3000/hp3000_defs.h +++ b/HP3000/hp3000_defs.h @@ -1,6 +1,6 @@ /* hp3000_defs.h: HP 3000 simulator general declarations - Copyright (c) 2016, J. David Bryan + Copyright (c) 2016-2017, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,8 @@ in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. - 29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T + 16-Oct-17 JDB Suppressed logical-not-parentheses warning on clang + 29-Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T 20-Nov-16 JDB Added mapped memory access classes 24-Oct-16 JDB Added half-byte definitions for CIS decoding 10-Oct-16 JDB Moved ACCESS_CLASS definition here from hp3000_cpu.h @@ -134,6 +135,7 @@ */ #if defined (__clang__) + #pragma clang diagnostic ignored "-Wlogical-not-parentheses" #pragma clang diagnostic ignored "-Wlogical-op-parentheses" #pragma clang diagnostic ignored "-Wbitwise-op-parentheses" #pragma clang diagnostic ignored "-Wshift-op-parentheses" diff --git a/HP3000/hp3000_io.h b/HP3000/hp3000_io.h index 35332635..e31b534e 100644 --- a/HP3000/hp3000_io.h +++ b/HP3000/hp3000_io.h @@ -321,15 +321,15 @@ struct dib { /* the Device Information Block }; #define DIB_REGS(dib) \ -/* Macro Name Location Width Flags */ \ -/* ------ ------- -------------------------- ----- ------- */ \ - { DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \ - { DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \ - { DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \ - { ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \ - { ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \ - { ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \ - { ORDATA (DIBSR, dib.service_request, 32), REG_HRO } +/* Macro Name Location Width Flags */ \ +/* ------ ------- -------------------------- ----- ------- */ \ + { DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \ + { DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \ + { DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \ + { ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \ + { ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \ + { ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \ + { ORDATA (DIBSR, dib.service_request, 32), REG_HRO } /* Calibrated timer numbers */ diff --git a/HP3000/hp3000_release.txt b/HP3000/hp3000_release.txt index 07af60e5..04a83ca2 100644 --- a/HP3000/hp3000_release.txt +++ b/HP3000/hp3000_release.txt @@ -1,6 +1,6 @@ SIMH/HP 3000 RELEASE NOTES ========================== - Last update: 2017-09-07 + Last update: 2018-01-12 This file documents the release history of the Hewlett-Packard 3000 simulator. @@ -47,7 +47,7 @@ General Information The simulator passes the HP 32230 offline diagnostic suite with some expected failures due to unimplemented features. For example, the disc diagnostic error-correction logic tests and the tape diagnostic CRCC and LRCC tests fail, -as these features are not supported. However, all features that are required +as these features are not simulated. However, all features that are required for MPE operation pass their respective diagnostic tests. The simulator has been tested with MPE-V/R version E.01.00. Specifically: @@ -176,6 +176,79 @@ the MPE version used: +===================== +Release 7, 2018-01-12 +===================== + +This release of the HP 3000 simulator adds the following features: + + - Reading and writing to terminal sessions connected to the ATC have been + improved significantly. File uploads via Telnet using the Reflection + terminal emulator are now over 100 times faster than before, e.g., the + transfer time for a one-megabyte file has decreased from 69 minutes to 30 + seconds. Block mode reads show similar speed improvements. Copy-and-paste + into the terminal window, Reflection file downloads, and output to the + terminal window in REMOTEACK mode show speed improvements of five to fifteen + times. Output in LOCALACK mode has been improved by around 50%. + + - Information regarding Reflection file transfers and serial port disconnection + options has been added to Section 4.1.1, "Terminal Data Interface," of the HP + 3000 Simulator User's Guide. + + +-------------------- +Implementation Notes +-------------------- + + - File transfer using the Reflection terminal emulator requires an 8-bit data + path. To achieve this, the session must use MPE terminal type 12 (this may + be configured either during a system reload or by specifying the TERM=12 + parameter when logging on with :HELLO), and the channel must be set to 8B, + REMOTEACK, and NOCAPSLOCK modes. Note that MPE's default terminal type 10 + writes 7-bit data with odd parity, and characters with the parity bit on may + be displayed by the terminal emulator as extended characters in the Roman-8 + symbol set. To avoid a garbled display when using the TERM=12 parameter to + override the default, the channel should be set to 8B mode after logging on + and back to 7B after logging off. + + - The MPE-V/R software kit has been updated to increase the number of terminal + buffers per port from 3 to 5. Using the default of 3 may cause the system + to report "MPE Table TBUF has overflowed!!!" to the system console while + performing Reflection file uploads. + + +---------- +Bugs Fixed +---------- + + 1. PROBLEM: Serial port output stalls are not handled properly. + + VERSION: Release 6. + + OBSERVATION: The ATCD device supports I/O via host serial ports as well as + via Telnet connections. While output via Telnet works correctly, output + via serial ports fails. Attempting to output to the ATCD results in a few + characters written, and then the line hangs. Sometimes pressing ENTER at + the system console (ATCD channel 0) causes a few more characters to appear + on the serial terminal. Eventually, the line hangs permanently. + + CAUSE: The terminal multiplexer library (sim_tmxr.c, part of the SIMH + framework) had provided a 256-byte output buffer for each line, independent + of the connection type (Telnet or serial). The library was changed to + reduce the serial buffer size to one byte. If the library output routine + receives the second character before the first one has been written to the + serial port, it returns SCPE_STALL status to indicate a buffer overflow. + The ATCD simulation correctly responds to this status by rescheduling the + output attempt. However, it fails to call the "tmxr_poll_tx" routine to + write to the serial port, so the rescheduled attempt fails as well. + + RESOLUTION: Modify "line_service" (hp3000_atc.c) to call "tmxr_poll_tx" if + a buffer overflow occurs. + + STATUS: Fixed in Release 7. + + + ===================== Release 6, 2017-09-07 ===================== diff --git a/doc/hp3000_doc.doc b/doc/hp3000_doc.doc index e160d23d..84fa9fa1 100644 Binary files a/doc/hp3000_doc.doc and b/doc/hp3000_doc.doc differ