/* SCN2681_DUART.c, Copyright (c) by George Fankhauser, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/IO/Drivers/SCN2681_DUART.c,v $ Author(s): George Fankhauser Affiliation: ETH Zuerich, TIK Version: $Revision: 1.20 $ Creation Date: Last Date of Change: $Date: 1999/12/13 21:48:26 $ by: $Author: ruf $ $Log: SCN2681_DUART.c,v $ Revision 1.20 1999/12/13 21:48:26 ruf GNU General Public Licence Update Revision 1.19 1999/10/23 14:19:42 jeker first cleanup for R4k support Revision 1.18 1999/10/21 20:22:24 jeker first commit for the R4k support Revision 1.17 1999/03/22 15:13:31 jeker helloworld bugfix (endlich :) Revision 1.16 1999/01/06 17:47:34 cjeker code cleaning Revision 1.15 1998/04/08 15:08:22 gfa *** empty log message *** Revision 1.14 1997/04/23 18:20:38 conrad Sending of a \r in addition to each \n * Revision 1.13 1997/04/21 07:05:41 conrad * *** empty log message *** * * Revision 1.12 1997/04/18 16:28:21 conrad * *** empty log message *** * * Revision 1.11 1997/04/17 12:03:34 conrad * *** empty log message *** * * Revision 1.10 1997/04/17 11:06:53 conrad * use of ioDelayAtLeastCycles() * still a problem with a consolePutString() ... * * Revision 1.9 1997/04/15 10:25:24 conrad * *** empty log message *** * * Revision 1.8 1997/04/14 21:08:16 conrad * *** empty log message *** * * Revision 1.7 1997/04/12 15:58:31 gfa * interrupt/buffer version, uses a n-1 byte bounded buffer * * Revision 1.6 1997/04/07 13:26:00 gfa * new version using driver framework * * Revision 1.5 1997/03/23 12:45:23 gfa * first crude polling version for simulator, needs to be changed to * shared interrupt mode... * * Revision 1.4 1997/03/19 07:26:05 gfa * first hack using ioCOnsole... * * Revision 1.3 1997/02/24 07:40:03 gfa * *** empty log message *** * * Revision 1.2 1997/02/23 16:14:57 gfa * *** empty log message *** * * driver code for the philips SCN2681 dual universal asynchronous * receiver and transmitter (short: serial device chip :-) */ #include "Drivers/SCN2681_DUART.h" #include "Messages.h" #include "IODevice.h" #include "Lock.h" #include "Configuration.h" void devSCN2681_interruptHandler(IODevice this) { devSCN2681 uartA, uartB; IODevice devA, devB; char* rxA; char* rxB; char* statusA; char* statusB; devA = this; uartA = (devSCN2681)(this->extension); devB = uartA->otherChannel; uartB = (devSCN2681)(devB->extension); rxA = (char*)((unsigned long)(devA->base) + RX_REGISTER); rxB = (char*)((unsigned long)(devB->base) + RX_REGISTER); statusA = (char*)((unsigned long)(devA->base) + STATUS_REGISTER); statusB = (char*)((unsigned long)(devB->base) + STATUS_REGISTER); /* Since the interrupt on this device is shared, we need to check which * channel received a character */ if ((*statusA & RECV_MASK) == RECV_MASK) { if ((uartA->in + 1) % SCN2681_BUFSIZE == uartA->out) { WARNING("UARTA overflow\n"); return; } devA->buffer[uartA->in] = *rxA; uartA->in = ((uartA->in + 1) % SCN2681_BUFSIZE); } if ((*statusB & RECV_MASK) == RECV_MASK) { if ((uartB->in + 1) % SCN2681_BUFSIZE == uartB->out) { WARNING("UARTB overflow\n"); return; } devB->buffer[uartB->in] = *rxB; uartB->in = ((uartB->in + 1) % SCN2681_BUFSIZE); } } Error devSCN2681_init(IODevice this) { char* command = (char*)((unsigned long)(this->base) + COMMAND_REGISTER); char* mode = (char*)((unsigned long)(this->base) + MODE_REGISTER); char* status = (char*)((unsigned long)(this->base) + STATUS_REGISTER); void* tmp; char* interrupt = (char*)((unsigned long)(this->base) + INTERRUPT_REGISTER); devSCN2681 uart; /* Both UART register sets are identical, except for the interrupt * mask register */ if (this->interruptHandler == NULL) { interrupt -= UART_REGISTER_SET_SIZE; } /* device init */ *command = 0xa; /* disable rx/tx */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); *mode = 0x13; /* no parity - 8 bits/char */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); *mode = 0x7; /* 1 stop bit */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); *status = 0xbb; /* 9600 baud */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); *interrupt = 0x22; /* both receiver interrupts enabled */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); *command = 0x5; /* enable receive/transmit */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); /* buffers init - be careful to check for existing buffers */ if (!this->isInitialised) { tmp = this->extension; hmAlloc(&(this->extension), sizeof(devSCN2681Desc)); hmAlloc((Address*)&(this->buffer), SCN2681_BUFSIZE); uart = (devSCN2681)this->extension; uart->otherChannel = (IODevice)tmp; this->isInitialised = TRUE; } else { uart = (devSCN2681)this->extension; } uart->in = 0; uart->out = 0; return IO_INITOK; } Error devSCN2681_read(IODevice this, ThreadId threadId, char* buffer, long int* size) { long int i = 0; devSCN2681 uart; uart = (devSCN2681)this->extension; while (TRUE) { /* no more characters available, buffer empty */ if (uart->in == uart->out) { break; } /* user is satisfied */ if (i >= *size) { break; } buffer[i++] = this->buffer[uart->out]; uart->out = ((uart->out + 1) % SCN2681_BUFSIZE); } *size = i; return IO_READOK; } Error devSCN2681_write(IODevice this, ThreadId threadId, char* buffer, long int* size) { char* transmit = (char*)((unsigned long)(this->base) + TX_REGISTER); char* status = (char*)((unsigned long)(this->base) + STATUS_REGISTER); long int i; for (i = 0; i < *size; i++) { while ((*status & READY_TO_SEND) != READY_TO_SEND) { ioDelayAtLeastCycles( NBCYCLESFORDELAY); } /* wait for uart to become ready */ *transmit = buffer[i]; /* send it finally */ /* Will be moved into a user stringlib * * Translate newlines into carriage returns plus newlines for * correct terminal output * * if (buffer[i] == '\n') { * while ((*status & READY_TO_SEND) != READY_TO_SEND) { * ioDelayAtLeastCycles( NBCYCLESFORDELAY); * } *//* wait for uart to become ready *//* * *transmit = '\r'; *//* send it finally *//* * } */ ioDelayAtLeastCycles( NBCYCLESFORDELAY); } return IO_WRITEOK; } Error devSCN2681_close(IODevice this) { /* this message is forwarded from ioThread */ /* release buffers if any */ /* this does not work at the moment (you get starnge errors) */ /* if (this->isInitialised) { hmFree((Address)this->buffer); *//* Deallocate buffer space *//* hmFree((Address)this->extension); *//* Deallocate descriptor space *//* this->isInitialised = FALSE; *//* Set Initialized flag *//* } */ return IO_CLOSEOK; }