Number: 1528

Date: 27-Jun-84 15':33':50

Submitter: Sannella.PA

Source: masinter.pa

Subject: Want complete set of serial-port primitives

Assigned To: 

Attn: Jonl

Status: Declined

In/By: 

Problem Type: Design - UI

Impact: Moderate

Difficulty: Moderate

Frequency: Everytime

Priority: 

System: Communications

Subsystem: RS232

Machine: 

Disk: 

Lisp Version: 

Source Files: 

Microcode Version: 

Memory Size: 

File Server: 

Server Software Version: 

Disposition: 

Description: '
Date': 25 Jun 84 18':03 PDT'
From': masinter.pa'
Subject': [Deutsch.pa': Serial i/o primitives for Smalltalk-80]'
To': lispsupport, jonl, lichtenberg.wbst'
cc': masinter.pa'
'
these are the Smalltalk-80 primitives for supporting RS232 etc. They are the ''primitives'' out of which Smalltalk programmers are expected to build their own applications. Could we support a similar set of primitives?'
'
[Ar, subject': Want complete set of serial-port primitives]'
'
My impression is that the current RS232 package supplies a high-level service, but no low-level entry points which don''t have some built in buffering, etc.'
'
'
     ----- Begin Forwarded Messages -----'
'
Date': Thu, 14 Jun 84 12':21':41 PDT'
From': Deutsch.pa'
Subject': Serial i/o primitives for Smalltalk-80'
To': Smalltalk80Users↑.pa'
Reply-To': Deutsch.pa'
'
Here are the specifications for the serial i/o primitives implemented in ST68K.  A VM with these primitives will be available soon -- we have one running at PARC.  One known problem is that you can''t have receives pending for both ports simultaneously.  Also, SDLC operation is not implemented yet.'
'
----------------------------------------------------------------------------'
'
The following specifications for serial i/o primitives for Smalltalk-80 are designed for low overhead when you want to transfer a lot of data, and for maximum flexibility.  Unfortunately, because UARTs vary enormously in their capabilities and specifications, the primitives include both an implementation-independent and an implementation-dependent part.  I have tried to include enough capability in the implementation-independent part so that implementation-dependent manipulations can be confined to initialization and diagnostics.'
'
These primitives are meant to be used only by a fairly low-level device manager, similar to the way that the Ethernet primitives are used only by Etherworld and Socket, the terminal input primitives by InputSensor, etc.'
'
'
We define a new system object called a SerialPort.  It has one instance variable of interest to the primitives':'
	portNumber - an integer that says which of several serial ports this instance is concerned with.'
'
portNumber must be the first instance variable.  There may be other instance variables as well, but the primitives are not concerned with them.  All of the primitives described below fail if portNumber is not a valid serial port number': ports are numbered by consecutive integers starting at 1.'
'
Here are the primitives for communicating with a serial port.'
'
(SerialPort class)maxPortNumber -> maxPortNumber <primitive': 210>'
	Returns the number of serial ports available to Smalltalk.  (No claim is made that anything is actually connected to any of these ports.)'
'
(SerialPort)reset <primitive': 211>'
	Does whatever is necessary to put the hardware for this port into some known state, and clears any software buffers associated with this line.'
'
(SerialPort)readStatus': index -> value <primitive': 212>'
	Reads status or statistical information from a given port.  Negative indices are reserved for implementation-dependent quantities and are not documented here.  In the Sun implementation, index=-N refers to register N-1 on the UART chip (NEC pd7201 on the Sun-1/1.5, Zilog Z8530 on the Sun-2).  The defined indices and their meaning are as follows -- information that can be altered with writeStatus': is marked with a *':'
	0* - minimum number of input bytes before signalling the receive': semaphore (see the receive': primitive below)'
	1* - alterable status bits':'
		bit 0 - DTR'
		bit 1 - local loopback'
		bit 2 - RTS'
		bit 3 - send BREAK'
		other bits - reserved'
	2* - current line speed of the port (baud)'
	3* - transmission mode - 0=asynchronous, 1=SDLC, ...'
	4-9* - reserved'
	10 - non-zero iff a receive is pending on this port'
	11 - read-only status bits':'
		bit 0  - DCD (carrier detect)'
		bit 1 - CTS'
		bit 2 - receiving BREAK'
		other bits - reserved'
	12 - maximum size for a send'
	13-19 - reserved'
	20 - total number of bytes received through this port'
	21 - total number of bytes sent through this port'
	22 - total number of frames received (synchronous operation)'
	23 - total number of frames sent (synchronous operation)'
	24 - total number of received bytes discarded for lack of buffer space'
'
(SerialPort) writeStatus': index with': newValue <primitive': 213>'
	Sets status information for a given port.  Negative values have the same meaning as for readStatus':.'
'
(SerialPort)receive': aByteArrayOrString startingAt': startIndex signal': aSemaphore <primitive': 214>'
	Provides a buffer for reading from the serial port.  Information read from the port is written into the byte array or string until either (a1) a specified minimum number of bytes has been read, as specified by status value 0 (non-framed operation only), or (a2) an entire frame has been read (framed operation only), or (b) some external signal associated with the port changes (e.g. CD or BREAK), or (c) the buffer becomes full.  As soon as any of these conditions obtains, writes the port status and byte count into the buffer as described below, and signals the semaphore.  Further input data from this port may be buffered internally until another receive': command is issued.'
'
Information read from the port is stored in the buffer starting at index startIndex+4.  When a receive': operation completes, status information is stored at startIndex and startIndex+1, and the number of data bytes read is stored in the word at startIndex+2 and startIndex+3.  startIndex must be odd, and the size of the buffer must be at least startIndex+4 bytes.  The status bytes at startIndex and startIndex+1 are defined as follows (bit 0 is rightmost)':'
	startIndex - reflects what terminated the receive': operation'
		0 - normal termination (no special conditions in unframed operation, normal end of frame in framed operation)'
		1 - an external signal changed state'
		2 - the internal buffer overflowed, data was lost'
		3 - some error occurred in framed operation'
	startIndex+1'
		the value of readStatus': 11 just after the last data byte was read'
Note that if the port changes status before any data has been read, the number of data bytes may be zero.'
'
Note that if the minimum byte count (status value 0) is reset to a smaller value while a receive': is pending, and the port is being operated asynchronously, this will cause the receive': to complete as soon as the smaller number of bytes has been read, which may be immediately.  One possible application for this is to provide for better interactive response to asynchronous input': a receive': can be set up with a large value for the minimum byte count, and a timer process can periodically reset the minimum byte count to 1 and back to the larger value.'
'
The Smalltalk kernel has a fixed amount of input buffering, currently 200 events for each line (a configuration-time parameter).  The input buffer contains a sequence of events, each of which may be either a data byte or a change in the state of the control signals.  Input characters that are never read, or not read quickly enough, are lost if they overflow the fixed-size kernel buffer; this is reflected in the termination code stored in the receive': buffer.'
'
This primitive may be implemented by any combination of direct input to the user''s buffer and internal buffering in the kernel.'
'
(SerialPort)send': aByteArrayOrString startingAt': startIndex size': sizeInteger signal': aSemaphore <primitive': 215>'
	Queues a byte array or string for output.  The output semaphore will be signalled when the bytes have all been sent.  Fails if output is still in progress on this port.  Note that the caller does not have to actually wait on the semaphore and pay the cost of two process switches': it can busy-wait testing the signal count in the semaphore.'
'
This primitive may be implemented by copying the data into a private buffer (this is the current implementation), by sending it directly from the argument string, or a combination of the two.  If the caller of the primitive stores into the string before the output is complete, it is not possible to predict whether the old or new contents will actually be sent out.'
'
If this port is operating in a synchronous mode that includes the notion of framing (such as SDLC), each call on the send primitive produces a single frame.'
'
     ----- End Forwarded Messages -----'
'
-----'
'
Date': 25 Jun 84 19':49 PDT'
From': JonL.pa'
Subject': Re': [Deutsch.pa': Serial i/o primitives for Smalltalk-80]'
In-reply-to': masinter.pa''s message of 25 Jun 84 18':03 PDT'
To': masinter.pa'
cc': lispsupport.pa, jonl.pa, lichtenberg.wbst'
'
I think you have it turned around as to which has the  more primitive "primitives".  Lisp''s RS232 interface generally allows the user to ignore buffering, the only intrusions being RS232FORCEOUTPUT for the output side (i.e., so that one can block until the data sent out is actually "out") and the choice of unit or block input functions (RS232READBYTE or RS232READSTRING).  '
'
Contrast this with the Triple-buffering required in the Mesa Face, which this SmallTalk proposal resembles very closely (probably because both are addressing point [3] below)':  (1) Client data is packed into a Physical Record, (2) which record is then copied into the locked-down segment-zero buffers, (3) which are then copied via DMA to the IOP''s buffers, until finally (4) interrupt-level asynchrony depletes or fills these buffers from the serial i/o chip.'
'
I think only one or two of the true serial i/o primitives are missing from the Lisp Face; they indeed are there in the "Head", and could easily be made available.  I''m referring to  "Hardware reset" and a way to communicate the DCD signal.'
'
	'
Note also three differences between the 68000 SmallTalk goals and Lisp''s goals':'
'
[1] To quote from Peter "These primitives are meant to be used only by a fairly low-level device manager, similar to the way that the Ethernet primitives are used only by Etherworld ...".  We have a large number of users who are driving a motley array of devices off the serial port, and they need something simpler than the "device manager" -- i.e., complicated buffering -- tools mentioned above.'
'
[2] SmallTalk, as well as Mesa, has cheap processes, priority interrupts, and pre-emptive scheduling.  It makes good sense that their interface would be different from Lisp''s.  Lisp has . . . '
'
[3] The SmallTalk proposal is for a generality of simultaneous multiple ports -- similar to what the Mesa Face describes.  Is there any real need for such generality now in Lisp?  The main benefactor is SDLC-type communications and  gateway servers;  we probably can place that on next year''s queue rather than this year''s.'
'
'
Perhaps the most compelling reason why the simpler model is good for Lisp is that it makes sense, when not worrying about SDLC framing, to have the same interface to the non-buffered TTYPort, the RickMartin Board, and the RS232C fully-buffered port.  Even when the minimal piece of TTYPort driver is copied into the FXPRINTER file, it will still be possible to do RS232 out that port just like the other two ports.'
'
'
-- JonL --'


Workaround: 

Test Case: 

Edit-By: masinter

Edit-Date: 10-Jul-84 12':30':18