summaryrefslogtreecommitdiff
path: root/kernel/old/sio.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-08 10:49:18 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-08 10:49:18 -0400
commitc8a1e0531d7ccdce5f76aec8a5b6147c686d3403 (patch)
tree2a68ab7da901a96fea975ca2ec02a9c77137686b /kernel/old/sio.c
parenttty => term (diff)
downloadcomus-c8a1e0531d7ccdce5f76aec8a5b6147c686d3403.tar.gz
comus-c8a1e0531d7ccdce5f76aec8a5b6147c686d3403.tar.bz2
comus-c8a1e0531d7ccdce5f76aec8a5b6147c686d3403.zip
fix old checkout
Diffstat (limited to '')
-rw-r--r--kernel/old/sio.c (renamed from kernel/old/drivers/serial.c)329
1 files changed, 197 insertions, 132 deletions
diff --git a/kernel/old/drivers/serial.c b/kernel/old/sio.c
index d6572e5..a5c7b75 100644
--- a/kernel/old/drivers/serial.c
+++ b/kernel/old/sio.c
@@ -1,3 +1,64 @@
+/**
+** @file sio.c
+**
+** @author Warren R. Carithers
+**
+** @brief SIO module
+**
+** For maximum compatibility from semester to semester, this code uses
+** several "stand-in" type names and macros which should be defined
+** in the accompanying "compat.h" header file if they're not part of
+** the baseline system:
+**
+** standard-sized integer types: intN_t, uintN_t
+** other types: PCBTYPE, QTYPE
+** scheduler functions: SCHED, DISPATCH
+** queue functions: QCREATE, QLENGTH, QDEQUE
+** other functions: SLENGTH
+** sio read queue: QNAME
+**
+** Our SIO scheme is very simple:
+**
+** Input: We maintain a buffer of incoming characters that haven't
+** yet been read by processes. When a character comes in, if
+** there is no process waiting for it, it goes in the buffer;
+** otherwise, the first waiting process is awakeneda and it
+** gets the character.
+**
+** When a process invokes readch(), if there is a character in
+** the input buffer, the process gets it; otherwise, it is
+** blocked until input appears
+**
+** Communication with system calls is via two routines.
+** sio_readc() returns the first available character (if
+** there is one), resetting the input variables if this was
+** the last character in the buffer. If there are no
+** characters in the buffer, sio_read() returns a -1
+** (presumably so the requesting process can be blocked).
+**
+** sio_read() copies the contents of the input buffer into
+** a user-supplied buffer. It returns the number of characters
+** copied. If there are no characters available, return a -1.
+**
+** Output: We maintain a buffer of outgoing characters that haven't
+** yet been sent to the device, and an indication of whether
+** or not we are in the middle of a transmit sequence. When
+** an interrupt comes in, if there is another character to
+** send we copy it to the transmitter buffer; otherwise, we
+** end the transmit sequence.
+**
+** Communication with user processes is via three functions.
+** sio_writec() writes a single character; sio_write()
+** writes a sized buffer full of characters; sio_puts()
+** prints a NUL-terminated string. If we are in the middle
+** of a transmit sequence, all characters will be added
+** to the output buffer (from where they will be sent
+** automatically); otherwise, we send the first character
+** directly, add the rest of the characters (if there are
+** any) to the output buffer, and set the "sending" flag
+** to indicate that we're expecting a transmitter interrupt.
+*/
+
#define KERNEL_SRC
// this should do all includes required for this OS
@@ -15,28 +76,28 @@
** PRIVATE DEFINITIONS
*/
-#define BUF_SIZE 2048
+#define BUF_SIZE 2048
/*
** PRIVATE GLOBALS
*/
-// input character buffer
-static char inbuffer[BUF_SIZE];
+ // input character buffer
+static char inbuffer[ BUF_SIZE ];
static char *inlast;
static char *innext;
static uint32_t incount;
-// output character buffer
-static char outbuffer[BUF_SIZE];
+ // output character buffer
+static char outbuffer[ BUF_SIZE ];
static char *outlast;
static char *outnext;
static uint32_t outcount;
-// output control flag
+ // output control flag
static int sending;
-// interrupt register status
+ // interrupt register status
static uint8_t ier;
/*
@@ -45,7 +106,7 @@ static uint8_t ier;
// queue for read-blocked processes
#ifdef QNAME
-extern QTYPE QNAME;
+QTYPE QNAME;
#endif
/*
@@ -61,40 +122,41 @@ extern QTYPE QNAME;
** @param vector The interrupt vector number for this interrupt
** @param ecode The error code associated with this interrupt
*/
-static void sio_isr(int vector, int ecode)
-{
+static void sio_isr( int vector, int ecode ) {
int ch;
#if TRACING_SIO_ISR
- cio_puts("SIO: int:");
+ cio_puts( "SIO: int:" );
#endif
//
// Must process all pending events; loop until the IRR
// says there's nothing else to do.
//
- for (;;) {
+ for(;;) {
+
// get the "pending event" indicator
- int iir = inb(UA4_IIR) & UA4_IIR_INT_PRI_MASK;
+ int iir = inb( UA4_IIR ) & UA4_IIR_INT_PRI_MASK;
// process this event
- switch (iir) {
+ switch( iir ) {
+
case UA4_IIR_LINE_STATUS:
// shouldn't happen, but just in case....
- cio_printf("** SIO int, LSR = %02x\n", inb(UA4_LSR));
+ cio_printf( "** SIO int, LSR = %02x\n", inb(UA4_LSR) );
break;
case UA4_IIR_RX:
#if TRACING_SIO_ISR
- cio_puts(" RX");
+ cio_puts( " RX" );
#endif
// get the character
- ch = inb(UA4_RXD);
- if (ch == '\r') { // map CR to LF
+ ch = inb( UA4_RXD );
+ if( ch == '\r' ) { // map CR to LF
ch = '\n';
}
#if TRACING_SIO_ISR
- cio_printf(" ch %02x", ch);
+ cio_printf( " ch %02x", ch );
#endif
#ifdef QNAME
@@ -104,18 +166,18 @@ static void sio_isr(int vector, int ecode)
// process and awaken the process.
//
- if (!QEMPTY(QNAME)) {
+ if( !QEMPTY(QNAME) ) {
PCBTYPE *pcb;
- QDEQUE(QNAME, pcb);
+ QDEQUE( QNAME, pcb );
// make sure we got a non-NULL result
- assert(pcb);
+ assert( pcb );
// return char via arg #2 and count in EAX
- char *buf = (char *)ARG(pcb, 2);
+ char *buf = (char *) ARG(pcb,2);
*buf = ch & 0xff;
RET(pcb) = 1;
- SCHED(pcb);
+ SCHED( pcb );
} else {
#endif /* QNAME */
@@ -125,7 +187,7 @@ static void sio_isr(int vector, int ecode)
// if there is room, otherwise just ignore it.
//
- if (incount < BUF_SIZE) {
+ if( incount < BUF_SIZE ) {
*inlast++ = ch;
++incount;
}
@@ -137,64 +199,65 @@ static void sio_isr(int vector, int ecode)
case UA5_IIR_RX_FIFO:
// shouldn't happen, but just in case....
- ch = inb(UA4_RXD);
- cio_printf("** SIO FIFO timeout, RXD = %02x\n", ch);
+ ch = inb( UA4_RXD );
+ cio_printf( "** SIO FIFO timeout, RXD = %02x\n", ch );
break;
case UA4_IIR_TX:
#if TRACING_SIO_ISR
- cio_puts(" TX");
+ cio_puts( " TX" );
#endif
// if there is another character, send it
- if (sending && outcount > 0) {
+ if( sending && outcount > 0 ) {
#if TRACING_SIO_ISR
- cio_printf(" ch %02x", *outnext);
+ cio_printf( " ch %02x", *outnext );
#endif
- outb(UA4_TXD, *outnext);
+ outb( UA4_TXD, *outnext );
++outnext;
// wrap around if necessary
- if (outnext >= (outbuffer + BUF_SIZE)) {
+ if( outnext >= (outbuffer + BUF_SIZE) ) {
outnext = outbuffer;
}
--outcount;
#if TRACING_SIO_ISR
- cio_printf(" (outcount %d)", outcount);
+ cio_printf( " (outcount %d)", outcount );
#endif
} else {
#if TRACING_SIO_ISR
- cio_puts(" EOS");
+ cio_puts( " EOS" );
#endif
// no more data - reset the output vars
outcount = 0;
outlast = outnext = outbuffer;
sending = 0;
// disable TX interrupts
- sio_disable(SIO_TX);
+ sio_disable( SIO_TX );
}
break;
case UA4_IIR_NO_INT:
#if TRACING_SIO_ISR
- cio_puts(" EOI\n");
+ cio_puts( " EOI\n" );
#endif
// nothing to do - tell the PIC we're done
- outb(PIC1_CMD, PIC_EOI);
+ outb( PIC1_CMD, PIC_EOI );
return;
case UA4_IIR_MODEM_STATUS:
// shouldn't happen, but just in case....
- cio_printf("** SIO int, MSR = %02x\n", inb(UA4_MSR));
+ cio_printf( "** SIO int, MSR = %02x\n", inb(UA4_MSR) );
break;
default:
// uh-oh....
- sprint(b256, "sio isr: IIR %02x\n", ((uint32_t)iir) & 0xff);
- PANIC(0, b256);
+ sprint( b256, "sio isr: IIR %02x\n", ((uint32_t) iir) & 0xff );
+ PANIC( 0, b256 );
}
+
}
// should never reach this point!
- assert(false);
+ assert( false );
}
/*
@@ -206,27 +269,27 @@ static void sio_isr(int vector, int ecode)
**
** Initialize the UART chip.
*/
-void sio_init(void)
-{
+void sio_init( void ) {
+
#if TRACING_INIT
- cio_puts(" Sio");
+ cio_puts( " Sio" );
#endif
/*
** Initialize SIO variables.
*/
- memclr((void *)inbuffer, sizeof(inbuffer));
+ memclr( (void *) inbuffer, sizeof(inbuffer) );
inlast = innext = inbuffer;
incount = 0;
- memclr((void *)outbuffer, sizeof(outbuffer));
+ memclr( (void *) outbuffer, sizeof(outbuffer) );
outlast = outnext = outbuffer;
outcount = 0;
sending = 0;
// queue of read-blocked processes
- QCREATE(QNAME);
+ QCREATE( QNAME );
/*
** Next, initialize the UART.
@@ -236,11 +299,11 @@ void sio_init(void)
** this is a bizarre little sequence of operations
*/
- outb(UA5_FCR, 0x20);
- outb(UA5_FCR, UA5_FCR_FIFO_RESET); // 0x00
- outb(UA5_FCR, UA5_FCR_FIFO_EN); // 0x01
- outb(UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR); // 0x03
- outb(UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR | UA5_FCR_TXSR); // 0x07
+ outb( UA5_FCR, 0x20 );
+ outb( UA5_FCR, UA5_FCR_FIFO_RESET ); // 0x00
+ outb( UA5_FCR, UA5_FCR_FIFO_EN ); // 0x01
+ outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR ); // 0x03
+ outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR | UA5_FCR_TXSR ); // 0x07
/*
** disable interrupts
@@ -249,36 +312,36 @@ void sio_init(void)
** called to switch them back on
*/
- outb(UA4_IER, 0);
+ outb( UA4_IER, 0 );
ier = 0;
/*
** select the divisor latch registers and set the data rate
*/
- outb(UA4_LCR, UA4_LCR_DLAB);
- outb(UA4_DLL, BAUD_LOW_BYTE(DL_BAUD_9600));
- outb(UA4_DLM, BAUD_HIGH_BYTE(DL_BAUD_9600));
+ outb( UA4_LCR, UA4_LCR_DLAB );
+ outb( UA4_DLL, BAUD_LOW_BYTE( DL_BAUD_9600 ) );
+ outb( UA4_DLM, BAUD_HIGH_BYTE( DL_BAUD_9600 ) );
/*
** deselect the latch registers, by setting the data
** characteristics in the LCR
*/
- outb(UA4_LCR, UA4_LCR_WLS_8 | UA4_LCR_1_STOP_BIT | UA4_LCR_NO_PARITY);
-
+ outb( UA4_LCR, UA4_LCR_WLS_8 | UA4_LCR_1_STOP_BIT | UA4_LCR_NO_PARITY );
+
/*
** Set the ISEN bit to enable the interrupt request signal,
** and the DTR and RTS bits to enable two-way communication.
*/
- outb(UA4_MCR, UA4_MCR_ISEN | UA4_MCR_DTR | UA4_MCR_RTS);
+ outb( UA4_MCR, UA4_MCR_ISEN | UA4_MCR_DTR | UA4_MCR_RTS );
/*
** Install our ISR
*/
- install_isr(VEC_COM1, sio_isr);
+ install_isr( VEC_COM1, sio_isr );
}
/**
@@ -292,8 +355,7 @@ void sio_init(void)
**
** @return the prior IER setting
*/
-uint8_t sio_enable(uint8_t which)
-{
+uint8_t sio_enable( uint8_t which ) {
uint8_t old;
// remember the current status
@@ -302,23 +364,23 @@ uint8_t sio_enable(uint8_t which)
// figure out what to enable
- if (which & SIO_TX) {
+ if( which & SIO_TX ) {
ier |= UA4_IER_TX_IE;
}
- if (which & SIO_RX) {
+ if( which & SIO_RX ) {
ier |= UA4_IER_RX_IE;
}
// if there was a change, make it
- if (old != ier) {
- outb(UA4_IER, ier);
+ if( old != ier ) {
+ outb( UA4_IER, ier );
}
// return the prior settings
- return (old);
+ return( old );
}
/**
@@ -332,8 +394,7 @@ uint8_t sio_enable(uint8_t which)
**
** @return the prior IER setting
*/
-uint8_t sio_disable(uint8_t which)
-{
+uint8_t sio_disable( uint8_t which ) {
uint8_t old;
// remember the current status
@@ -342,23 +403,23 @@ uint8_t sio_disable(uint8_t which)
// figure out what to disable
- if (which & SIO_TX) {
+ if( which & SIO_TX ) {
ier &= ~UA4_IER_TX_IE;
}
- if (which & SIO_RX) {
+ if( which & SIO_RX ) {
ier &= ~UA4_IER_RX_IE;
}
// if there was a change, make it
- if (old != ier) {
- outb(UA4_IER, ier);
+ if( old != ier ) {
+ outb( UA4_IER, ier );
}
// return the prior settings
- return (old);
+ return( old );
}
/**
@@ -370,9 +431,8 @@ uint8_t sio_disable(uint8_t which)
**
** @return the count of characters still in the input queue
*/
-int sio_inq_length(void)
-{
- return (incount);
+int sio_inq_length( void ) {
+ return( incount );
}
/**
@@ -384,29 +444,31 @@ int sio_inq_length(void)
**
** @return the next character, or -1 if no character is available
*/
-int sio_readc(void)
-{
+int sio_readc( void ) {
int ch;
// assume there is no character available
ch = -1;
- //
+ //
// If there is a character, return it
//
- if (incount > 0) {
+ if( incount > 0 ) {
+
// take it out of the input buffer
ch = ((int)(*innext++)) & 0xff;
--incount;
// reset the buffer variables if this was the last one
- if (incount < 1) {
+ if( incount < 1 ) {
inlast = innext = inbuffer;
}
+
}
- return (ch);
+ return( ch );
+
}
/**
@@ -422,15 +484,14 @@ int sio_readc(void)
** @return the number of bytes copied, or 0 if no characters were available
*/
-int sio_read(char *buf, int length)
-{
+int sio_read( char *buf, int length ) {
char *ptr = buf;
int copied = 0;
// if there are no characters, just return 0
- if (incount < 1) {
- return (0);
+ if( incount < 1 ) {
+ return( 0 );
}
//
@@ -438,9 +499,9 @@ int sio_read(char *buf, int length)
// buffer as will fit.
//
- while (incount > 0 && copied < length) {
+ while( incount > 0 && copied < length ) {
*ptr++ = *innext++ & 0xff;
- if (innext > (inbuffer + BUF_SIZE)) {
+ if( innext > (inbuffer + BUF_SIZE) ) {
innext = inbuffer;
}
--incount;
@@ -449,15 +510,16 @@ int sio_read(char *buf, int length)
// reset the input buffer if necessary
- if (incount < 1) {
+ if( incount < 1 ) {
inlast = innext = inbuffer;
}
// return the copy count
- return (copied);
+ return( copied );
}
+
/**
** sio_writec( ch )
**
@@ -467,21 +529,22 @@ int sio_read(char *buf, int length)
**
** @param ch Character to be written (in the low-order 8 bits)
*/
-void sio_writec(int ch)
-{
+void sio_writec( int ch ){
+
+
//
// Must do LF -> CRLF mapping
//
- if (ch == '\n') {
- sio_writec('\r');
+ if( ch == '\n' ) {
+ sio_writec( '\r' );
}
//
// If we're currently transmitting, just add this to the buffer
//
- if (sending) {
+ if( sending ) {
*outlast++ = ch;
++outcount;
return;
@@ -492,11 +555,12 @@ void sio_writec(int ch)
//
sending = 1;
- outb(UA4_TXD, ch);
+ outb( UA4_TXD, ch );
// Also must enable transmitter interrupts
- sio_enable(SIO_TX);
+ sio_enable( SIO_TX );
+
}
/**
@@ -511,8 +575,7 @@ void sio_writec(int ch)
**
** @return the number of characters copied into the SIO output buffer
*/
-int sio_write(const char *buffer, int length)
-{
+int sio_write( const char *buffer, int length ) {
int first = *buffer;
const char *ptr = buffer;
int copied = 0;
@@ -524,15 +587,15 @@ int sio_write(const char *buffer, int length)
// sio_writec() to send the first one out.
//
- if (!sending) {
+ if( !sending ) {
ptr += 1;
copied++;
}
- while (copied < length && outcount < BUF_SIZE) {
+ while( copied < length && outcount < BUF_SIZE ) {
*outlast++ = *ptr++;
// wrap around if necessary
- if (outlast >= (outbuffer + BUF_SIZE)) {
+ if( outlast >= (outbuffer + BUF_SIZE) ) {
outlast = outbuffer;
}
++outcount;
@@ -545,13 +608,15 @@ int sio_write(const char *buffer, int length)
// variables for us.
//
- if (!sending) {
- sio_writec(first);
+ if( !sending ) {
+ sio_writec( first );
}
// Return the transfer count
- return (copied);
+
+ return( copied );
+
}
/**
@@ -565,14 +630,13 @@ int sio_write(const char *buffer, int length)
**
** @return the count of bytes transferred
*/
-int sio_puts(const char *buffer)
-{
- int n; // must be outside the loop so we can return it
+int sio_puts( const char *buffer ) {
+ int n; // must be outside the loop so we can return it
- n = SLENGTH(buffer);
- sio_write(buffer, n);
+ n = SLENGTH( buffer );
+ sio_write( buffer, n );
- return (n);
+ return( n );
}
/**
@@ -587,43 +651,44 @@ int sio_puts(const char *buffer)
** of the queues)
*/
-void sio_dump(bool_t full)
-{
+void sio_dump( bool_t full ) {
int n;
char *ptr;
// dump basic info into the status region
- cio_printf_at(48, 0, "SIO: IER %02x (%c%c%c) in %d ot %d",
- ((uint32_t)ier) & 0xff, sending ? '*' : '.',
- (ier & UA4_IER_TX_IE) ? 'T' : 't',
- (ier & UA4_IER_RX_IE) ? 'R' : 'r', incount, outcount);
+ cio_printf_at( 48, 0,
+ "SIO: IER %02x (%c%c%c) in %d ot %d",
+ ((uint32_t)ier) & 0xff, sending ? '*' : '.',
+ (ier & UA4_IER_TX_IE) ? 'T' : 't',
+ (ier & UA4_IER_RX_IE) ? 'R' : 'r',
+ incount, outcount );
// if we're not doing a full dump, stop now
- if (!full) {
+ if( !full ) {
return;
}
// also want the queue contents, but we'll
// dump them into the scrolling region
- if (incount) {
- cio_puts("SIO input queue: \"");
- ptr = innext;
- for (n = 0; n < incount; ++n) {
- put_char_or_code(*ptr++);
+ if( incount ) {
+ cio_puts( "SIO input queue: \"" );
+ ptr = innext;
+ for( n = 0; n < incount; ++n ) {
+ put_char_or_code( *ptr++ );
}
- cio_puts("\"\n");
+ cio_puts( "\"\n" );
}
- if (outcount) {
- cio_puts("SIO output queue: \"");
- cio_puts(" ot: \"");
- ptr = outnext;
- for (n = 0; n < outcount; ++n) {
- put_char_or_code(*ptr++);
+ if( outcount ) {
+ cio_puts( "SIO output queue: \"" );
+ cio_puts( " ot: \"" );
+ ptr = outnext;
+ for( n = 0; n < outcount; ++n ) {
+ put_char_or_code( *ptr++ );
}
- cio_puts("\"\n");
+ cio_puts( "\"\n" );
}
}