diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-02-18 16:48:14 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-02-18 16:48:14 +0000 |
commit | 0c04c377bc8ac177d28bd0e0096d7c6940d33cd4 (patch) | |
tree | ba3062eb819e89de2eee14397ffe61b202ad10de /c/src/lib/libbsp/powerpc/ppcn_60x/console | |
parent | ./clock/Makefile.in,v (diff) | |
download | rtems-0c04c377bc8ac177d28bd0e0096d7c6940d33cd4.tar.bz2 |
./clock/Makefile.in,v
./clock/clock.c,v
./console/Makefile.in,v
./console/config.c,v
./console/console.c,v
./console/console.h,v
./console/debugio.c,v
./console/i8042.c,v
./console/i8042_p.h,v
./console/i8042vga.c,v
./console/i8042vga.h,v
./console/ns16550.c,v
./console/ns16550.h,v
./console/ns16550_p.h,v
./console/ns16550cfg.c,v
./console/ns16550cfg.h,v
./console/vga.c,v
./console/vga_p.h,v
./console/z85c30.c,v
./console/z85c30.h,v
./console/z85c30_p.h,v
./console/z85c30cfg.c,v
./console/z85c30cfg.h,v
./include/Makefile.in,v
./include/bsp.h,v
./include/chain.h,v
./include/coverhd.h,v
./include/extisrdrv.h,v
./include/nvram.h,v
./include/pci.h,v
./include/tod.h,v
./network/Makefile.in,v
./network/amd79c970.c,v
./network/amd79c970.h,v
./nvram/Makefile.in,v
./nvram/ds1385.h,v
./nvram/mk48t18.h,v
./nvram/nvram.c,v
./nvram/prepnvr.h,v
./nvram/stk11c68.h,v
./pci/Makefile.in,v
./pci/pci.c,v
./start/Makefile.in,v
./start/start.s,v
./startup/Makefile.in,v
./startup/bspclean.c,v
./startup/bspstart.c,v
./startup/bsptrap.s,v
./startup/device-tree,v
./startup/genpvec.c,v
./startup/linkcmds,v
./startup/rtems-ctor.cc,v
./startup/sbrk.c,v
./startup/setvec.c,v
./startup/spurious.c,v
./startup/swap.c,v
./timer/Makefile.in,v
./timer/timer.c,v
./tod/Makefile.in,v
./tod/cmos.h,v
./tod/tod.c,v
./universe/Makefile.in,v
./universe/universe.c,v
./vectors/Makefile.in,v
./vectors/README,v
./vectors/align_h.s,v
./vectors/vectors.s,v
./wrapup/Makefile.in,v
./Makefile.in,v
./README,v
./STATUS,v
./bsp_specs,v
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ppcn_60x/console')
19 files changed, 4756 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/Makefile.in b/c/src/lib/libbsp/powerpc/ppcn_60x/console/Makefile.in new file mode 100644 index 0000000000..4c05c37698 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/Makefile.in @@ -0,0 +1,54 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +PGM=${ARCH}/console.rel + +# C source names, if any, go here -- minus the .c +C_PIECES=console ns16550 z85c30 i8042vga i8042 vga +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +H_FILES= + +SRCS=$(C_FILES) $(H_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +${PGM}: ${SRCS} ${OBJS} + $(make-rel) + +all: ${ARCH} $(SRCS) $(PGM) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +install: all diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.c new file mode 100644 index 0000000000..6b60503ec9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.c @@ -0,0 +1,358 @@ +/* + * This file contains the TTY driver for the PPCn_60x + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <stdlib.h> +#include <assert.h> +#include <termios.h> + +#include "console.h" + +/* + * Load configuration table + */ +#include "config.c" + +#define NUM_CONSOLE_PORTS (sizeof(Console_Port_Tbl)/sizeof(console_tbl)) + +console_data Console_Port_Data[NUM_CONSOLE_PORTS]; +unsigned long Console_Port_Count; +rtems_device_minor_number Console_Port_Minor; + +/* PAGE + * + * console_open + * + * open a port as a termios console. + * + */ +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_status_code status; + rtems_libio_open_close_args_t *args = arg; + rtems_libio_ioctl_args_t IoctlArgs; + struct termios Termios; + rtems_termios_callbacks Callbacks; + console_fns *c; + + /* + * Verify the port number is valid. + */ + if(minor>Console_Port_Count) + { + return RTEMS_INVALID_NUMBER; + } + + /* + * open the port as a termios console driver. + */ + c = Console_Port_Tbl[minor].pDeviceFns; + Callbacks.firstOpen = c->deviceFirstOpen; + Callbacks.lastClose = c->deviceLastClose; + Callbacks.pollRead = c->deviceRead; + Callbacks.write = c->deviceWrite; + Callbacks.setAttributes = c->deviceSetAttributes; + Callbacks.stopRemoteTx = + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx; + Callbacks.startRemoteTx = + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx; + Callbacks.outputUsesInterrupts = c->deviceOutputUsesInterrupts; + status = rtems_termios_open ( major, minor, arg, &Callbacks); + Console_Port_Data[minor].termios_data = args->iop->data1; + + /* + * Patch in flow control routines + */ +/* XXX */ +#if 0 + if((status==RTEMS_SUCCESSFUL) && + (Console_Port_Tbl[minor].pDeviceFlow)) + { + status=rtems_termios_flow_control( + major, minor, arg, + Console_Port_Tbl[minor].pDeviceFlow-> + deviceStartRemoteTx, + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx, + Console_Port_Tbl[minor].ulMargin, + Console_Port_Tbl[minor].ulHysteresis); + } +#endif + + if(minor!=Console_Port_Minor) + { + /* + * If this is not the console we do not want ECHO and + * so forth + */ + IoctlArgs.iop=args->iop; + IoctlArgs.command=RTEMS_IO_GET_ATTRIBUTES; + IoctlArgs.buffer=&Termios; + rtems_termios_ioctl(&IoctlArgs); + Termios.c_lflag=ICANON; + IoctlArgs.command=RTEMS_IO_SET_ATTRIBUTES; + rtems_termios_ioctl(&IoctlArgs); + } + + if((args->iop->flags&LIBIO_FLAGS_READ) && + Console_Port_Tbl[minor].pDeviceFlow && + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx) + { + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx(minor); + } + + return status; +} + +void console_reserve_resources( + rtems_configuration_table *configuration +) +{ + rtems_termios_reserve_resources( configuration, 2 ); +} + + +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_open_close_args_t *args = arg; + + if((args->iop->flags&LIBIO_FLAGS_READ) && + Console_Port_Tbl[minor].pDeviceFlow && + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx) + { + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx(minor); + } + + return rtems_termios_close (arg); +} + +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_read (arg); +} + +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_write (arg); +} + +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_ioctl (arg); +} + +/* PAGE + * + * console_initialize + * + * Routine called to initialize the console device driver. + */ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + /* + * initialize the termio interface. + */ + rtems_termios_initialize(); + + Console_Port_Count=NUM_CONSOLE_PORTS; + + for(minor=0; + minor<Console_Port_Count; + minor++) + { + /* + * First perform the configuration dependant probe, then the + * device dependant probe + */ + if((!Console_Port_Tbl[minor].deviceProbe || + Console_Port_Tbl[minor].deviceProbe(minor)) && + Console_Port_Tbl[minor].pDeviceFns->deviceProbe(minor)) + { + /* + * Use this device for the console + */ + break; + } + } + if(minor==Console_Port_Count) + { + /* + * Failed to find a working device + */ + rtems_fatal_error_occurred(RTEMS_IO_ERROR); + } + + Console_Port_Minor=minor; + + /* + * Register Device Names + */ + status = rtems_io_register_name("/dev/console", + major, + Console_Port_Minor ); + if (status != RTEMS_SUCCESSFUL) + { + rtems_fatal_error_occurred(status); + } + Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( + Console_Port_Minor); + + for(minor++;minor<Console_Port_Count;minor++) + { + /* + * First perform the configuration dependant probe, then the + * device dependant probe + */ + if((!Console_Port_Tbl[minor].deviceProbe || + Console_Port_Tbl[minor].deviceProbe(minor)) && + Console_Port_Tbl[minor].pDeviceFns->deviceProbe(minor)) + { + status = rtems_io_register_name( + Console_Port_Tbl[minor].sDeviceName, + major, + minor ); + if (status != RTEMS_SUCCESSFUL) + { + rtems_fatal_error_occurred(status); + } + + /* + * Initialize the hardware device. + */ + Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( + minor); + + } + } + + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * DEBUG_puts + * + * This should be safe in the event of an error. It attempts to ensure + * that no TX empty interrupts occur while it is doing polled IO. Then + * it restores the state of that external interrupt. + * + * Input parameters: + * string - pointer to debug output string + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void DEBUG_puts( + char *string +) +{ + char *s; + unsigned32 Irql; + + rtems_interrupt_disable(Irql); + + for ( s = string ; *s ; s++ ) + { + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, *s); + } + + rtems_interrupt_enable(Irql); +} + +/* PAGE + * + * DEBUG_puth + * + * This should be safe in the event of an error. It attempts to ensure + * that no TX empty interrupts occur while it is doing polled IO. Then + * it restores the state of that external interrupt. + * + * Input parameters: + * ulHexNum - value to display + * + * Output parameters: NONE + * + * Return values: NONE + */ +void +DEBUG_puth( + unsigned32 ulHexNum + ) +{ + unsigned long i,d; + unsigned32 Irql; + + rtems_interrupt_disable(Irql); + + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, '0'); + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, 'x'); + + for(i=32;i;) + { + i-=4; + d=(ulHexNum>>i)&0xf; + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, + (d<=9) ? d+'0' : d+'a'-0xa); + } + + rtems_interrupt_enable(Irql); +} + diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.h new file mode 100644 index 0000000000..1d6b6fc2b1 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/console.h @@ -0,0 +1,67 @@ +/* + * This file contains the TTY driver table definition for the PPCn_60x + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * $Id$ + */ + +#include <ringbuf.h> + +typedef struct _console_fns { + boolean (*deviceProbe)(int minor); + int (*deviceFirstOpen)(int major, int minor, void *arg); + int (*deviceLastClose)(int major, int minor, void *arg); + int (*deviceRead)(int minor); + int (*deviceWrite)(int minor, const char *buf, int len); + void (*deviceInitialize)(int minor); + int (*deviceSetAttributes)(int minor, const struct termios *); + void (*deviceWritePolled)(int minor, char cChar); + int deviceOutputUsesInterrupts; +} console_fns; + +typedef struct _console_flow { + int (*deviceStopRemoteTx)(int minor); + int (*deviceStartRemoteTx)(int minor); +} console_flow; + +typedef struct _console_tbl { + char *sDeviceName; + console_fns *pDeviceFns; + boolean (*deviceProbe)(int minor); + console_flow *pDeviceFlow; + unsigned32 ulMargin; + unsigned32 ulHysteresis; + void *pDeviceParams; + unsigned32 ulCtrlPort1; + unsigned32 ulCtrlPort2; + unsigned32 ulDataPort; + unsigned int ulIntVector; +} console_tbl; + +typedef struct _console_data { + void *termios_data; + volatile boolean bActive; + volatile Ring_buffer_t TxBuffer; + /* + * This field may be used for any purpose required by the driver + */ + void *pDeviceContext; +} console_data; + +extern console_tbl Console_Port_Tbl[]; +extern console_data Console_Port_Data[]; +extern unsigned long Console_Port_Count; diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c new file mode 100644 index 0000000000..dcfd68e72d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c @@ -0,0 +1,1073 @@ +/* + * This file contains the PS2 keyboard driver for the i8042 + * + * Note that this driver will only handle a single i8042 device + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * This driver uses the termios pseudo driver. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/libio.h> +#include <ringbuf.h> + +#include "console.h" +#include "i8042_p.h" +#include "vga_p.h" + +/* + * UK style keyboard + */ +char pcUKNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'" + "`\0#zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0" + "\000789-456+1230.\0\0\\"; +char pcUKShiftedLookup[]= "!\"£$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:" + "@\0\0~ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0" + "\0\000789-456+1230.\0\0|"; +/* + * US style keyboard + */ +char pcUSNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'" + "`\0\\zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0" + "\0\000789-456+1230.\0\0\\"; +char pcUSShiftedLookup[]= "!@#$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:@~" + "\0|ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0" + "\000789-456+1230.\0\0|"; + +static char *pcNormalLookup; +static char *pcShiftedLookup; + +/* + * This is exported to vga.c to provide flow control + */ +volatile boolean bScrollLock=FALSE; + +/* + * If multiple devices are to be supported then a private copy of + * the following will be required for each instance + */ +static boolean bCtrlPressed=FALSE; +static boolean bAltPressed=FALSE; +static boolean bAltGrPressed=FALSE; +static boolean bLShiftPressed=FALSE; +static boolean bRShiftPressed=FALSE; +static boolean bCapsLock=FALSE; +static boolean bNumLock=FALSE; +static boolean bTwoCode=FALSE; + +#if CONSOLE_USE_INTERRUPTS +static volatile Ring_buffer_t KbdOutputBuffer; +static volatile boolean bProcessInterruptInput=FALSE; +static boolean bInterruptsEnabled=FALSE; +static volatile boolean bReceivedAck=TRUE; + +static void i8042_process( + int minor +); + +static void i8042_scan_code( + int minor, + unsigned8 ucScan +); +#endif + +static volatile Ring_buffer_t KbdInputBuffer; + +/* + * The following routines enable an interrupt driver to switch + * to polled mode as required for command processing + */ +void i8042_polled_on( + int minor +) +{ +#if CONSOLE_USE_INTERRUPTS + bProcessInterruptInput=FALSE; +#endif +} + +void i8042_polled_off( + int minor +) +{ +#if CONSOLE_USE_INTERRUPTS + unsigned32 Irql; + unsigned8 ucScan; + + /* + * Make sure we have processed everything outstanding + */ + rtems_interrupt_disable(Irql); + while(!Ring_buffer_Is_empty(&KbdInputBuffer)) + { + rtems_interrupt_enable(Irql); + Ring_buffer_Remove_character(&KbdInputBuffer, + ucScan); + i8042_scan_code(minor, ucScan); + rtems_interrupt_disable(Irql); + } + bProcessInterruptInput=TRUE; + rtems_interrupt_enable(Irql); +#endif +} + +/* + * Send data to the keyboard + */ +static rtems_status_code +i8042_outbyte_raw( + int minor, + unsigned8 ucData +) +{ + unsigned32 i; + unsigned8 Status; + +#if CONSOLE_USE_INTERRUPTS + unsigned32 Irql; + + if(bInterruptsEnabled) + { + Ring_buffer_Add_character(&KbdOutputBuffer, + ucData); + if(!Console_Port_Data[minor].bActive) + { + /* + * Wake up the device + */ + rtems_interrupt_disable(Irql); + Console_Port_Data[minor].bActive=TRUE; + i8042_process(minor); + rtems_interrupt_enable(Irql); + + } + return RTEMS_SUCCESSFUL; + } +#endif + for (i=0; i<KBD_TIMEOUT; i++) + { + inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); + if((Status & KBD_IBF_MASK)==0) + { + outport_byte(Console_Port_Tbl[minor].ulDataPort, + ucData); + return RTEMS_SUCCESSFUL; + } + } + return RTEMS_TIMEOUT; +} + +/* + * Read data from the keyboard + */ +static rtems_status_code +i8042_inbyte_polled( + int minor, + unsigned8 *pucData +) +{ + unsigned8 Status; + + inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); + if(Status & KBD_OBF_MASK) + { + inport_byte(Console_Port_Tbl[minor].ulDataPort, + *pucData); + return RTEMS_SUCCESSFUL; + } + return RTEMS_TIMEOUT; +} + +/* + * Blocking read data from the keyboard + */ +static rtems_status_code +i8042_inbyte_raw( + int minor, + unsigned8 *pucData +) +{ + int i; + +#if CONSOLE_USE_INTERRUPTS + if(bInterruptsEnabled) + { + i=0; + while(Ring_buffer_Is_empty(&KbdInputBuffer)) + { + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + if(i++==KBD_TIMEOUT) + { + return RTEMS_TIMEOUT; + } + } + Ring_buffer_Remove_character(&KbdInputBuffer, + *pucData); + } + else +#endif + { + for (i=0; i<KBD_TIMEOUT; i++) + { + if(i8042_inbyte_polled(minor, pucData)== + RTEMS_SUCCESSFUL) + { + return RTEMS_SUCCESSFUL; + } + /* + * Wait for a character to be recieved + */ + } + + return RTEMS_TIMEOUT; + } + + return RTEMS_SUCCESSFUL; +} + +/* + * Send a command to the keyboard controller + */ +static rtems_status_code +i8042_outbyte_cmd_polled( + int minor, + unsigned8 ucCommand +) +{ + unsigned32 i; + unsigned8 Status; + + /* + * This routine may be called when no clock driver is available + * so the timeout is dependant on the ISA bus timing used to access + * the i8042 which will not vary (much) across platforms. + */ + for (i=0; i<KBD_TIMEOUT; i++) + { + inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); + if((Status & KBD_IBF_MASK)==0) + { + outport_byte(Console_Port_Tbl[minor].ulCtrlPort1, + ucCommand); + return RTEMS_SUCCESSFUL; + } + } + return RTEMS_TIMEOUT; +} + +void EnqueueKbdChar( + int minor, + char cChar +) +{ +#if CONSOLE_USE_INTERRUPTS + rtems_termios_enqueue_raw_characters( + Console_Port_Data[minor].termios_data, + &cChar, + 1); +#else + Ring_buffer_Add_character(&KbdInputBuffer, cChar); +#endif +} +/* + * Process second code in a two code sequence + */ +static void i8042_process_two_code( + int minor, + unsigned8 ucScan, + boolean bMakenBreak +) +{ + char cASCIICtrlCode; + char cASCIICode; + + cASCIICtrlCode='\0'; + cASCIICode='\0'; + + switch(ucScan) + { + case KEY_ALT: + { + bAltGrPressed=bMakenBreak; + break; + } + + case KEY_CONTROL: + { + bCtrlPressed=bMakenBreak; + break; + } + + case KEY_INSERT: + { + cASCIICtrlCode='@'; + break; + } + + case KEY_DELETE: + { + cASCIICode=ASCII_DEL; + break; + } + + case KEY_LEFT_ARROW: + { + cASCIICtrlCode='D'; + break; + } + + case KEY_HOME: + { + cASCIICtrlCode='H'; + break; + } + + case KEY_END: + { + cASCIICtrlCode='K'; + break; + } + + case KEY_UP_ARROW: + { + cASCIICtrlCode='A'; + break; + } + + case KEY_DOWN_ARROW: + { + cASCIICtrlCode='B'; + break; + } + + case KEY_PAGE_UP: + { + cASCIICtrlCode='?'; + break; + } + + case KEY_PAGE_DOWN: + { + cASCIICtrlCode='/'; + break; + } + + case KEY_RIGHT_ARROW: + { + cASCIICtrlCode='C'; + break; + } + + case KEY_KEYPAD_SLASH: + { + cASCIICode='/'; + break; + } + + case KEY_KEYPAD_ENTER: + { + cASCIICode=ASCII_CR; + break; + } + + case KEY_PRINT_SCREEN: + { + cASCIICode=ASCII_SYSRQ; + break; + } + + default: + { + /* + * Ignore this code + */ + break; + } + } + + if(bMakenBreak && cASCIICode) + { + EnqueueKbdChar(minor, cASCIICode); + } + else if(bMakenBreak && cASCIICtrlCode) + { + EnqueueKbdChar(minor, ASCII_CSI); + EnqueueKbdChar(minor, cASCIICtrlCode); + } +} + +static boolean i8042_process_qualifiers( + unsigned8 ucScan, + boolean bMakenBreak +) +{ + boolean bProcessed; + + /* + * Check for scan codes for shift, control, or alt keys. + */ + bProcessed=TRUE; + + switch (ucScan) + { + case KEY_LEFT_SHIFT: + { + bLShiftPressed=bMakenBreak; + break; + } + + case KEY_RIGHT_SHIFT: + { + bRShiftPressed=bMakenBreak; + break; + } + + case KEY_CONTROL: + { + bCtrlPressed=bMakenBreak; + break; + } + + case KEY_ALT: + { + bAltPressed=bMakenBreak; + break; + } + + default: + { + /* + * Something else needs to process this code + */ + bProcessed=FALSE; + break; + } + } + + return(bProcessed); +} + +static boolean i8042_process_top_row( + int minor, + unsigned8 ucScan +) +{ + boolean bProcessed; + char cASCIIFnCode; +#if CONSOLE_USE_INTERRUPTS==0 + unsigned8 ucKeyboardAck; +#endif + + /* + * Check for keys on the top row + */ + bProcessed=TRUE; + cASCIIFnCode='\0'; + + switch (ucScan) + { + case KEY_ESC: + { + EnqueueKbdChar(minor, ASCII_ESC); + break; + } + + case KEY_F1: + { + cASCIIFnCode='P'; + break; + } + + case KEY_F2: + { + cASCIIFnCode='Q'; + break; + } + + case KEY_F3: + { + cASCIIFnCode='w'; + break; + } + + case KEY_F4: + { + cASCIIFnCode='x'; + break; + } + + case KEY_F5: + { + cASCIIFnCode='t'; + break; + } + + case KEY_F6: + { + cASCIIFnCode='u'; + break; + } + + case KEY_F7: + { + cASCIIFnCode='q'; + break; + } + + case KEY_F8: + { + cASCIIFnCode='r'; + break; + } + + case KEY_F9: + { + cASCIIFnCode='p'; + break; + } + + case KEY_F10: + { + cASCIIFnCode='M'; + break; + } + + case KEY_F11: + { + cASCIIFnCode='A'; + break; + } + + case KEY_F12: + { + cASCIIFnCode='B'; + break; + } + + case KEY_SYS_REQUEST: + { + EnqueueKbdChar(minor, ASCII_SYSRQ); + break; + } + + case KEY_CAPS_LOCK: + case KEY_NUM_LOCK: + case KEY_SCROLL_LOCK: + { + switch(ucScan) + { + case KEY_CAPS_LOCK: + { + bCapsLock=!bCapsLock; + break; + } + + case KEY_NUM_LOCK: + { + bNumLock=!bNumLock; + break; + } + + case KEY_SCROLL_LOCK: + { +#if CONSOLE_USE_INTERRUPTS + bScrollLock=!bScrollLock; +#endif + break; + } + } + + i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS); +#if CONSOLE_USE_INTERRUPTS==0 + i8042_inbyte_raw(minor, &ucKeyboardAck); +#endif + i8042_outbyte_raw(minor, + (bCapsLock ? KBD_LED_CAPS : 0) | + (bNumLock ? KBD_LED_NUM : 0) | + (bScrollLock ? KBD_LED_SCROLL : 0)); +#if CONSOLE_USE_INTERRUPTS==0 + i8042_inbyte_raw(minor, &ucKeyboardAck); +#endif + + break; + } + + default: + { + /* + * Something else needs to process this code + */ + bProcessed=FALSE; + break; + } + } + + if(cASCIIFnCode) + { + EnqueueKbdChar(minor, ASCII_CSI); + EnqueueKbdChar(minor, 'O'); + EnqueueKbdChar(minor, cASCIIFnCode); + } + + return(bProcessed); +} + +static boolean i8042_process_keypad( + int minor, + unsigned8 ucScan +) +{ + char cASCIICtrlCode; + + /* + * Process keys on the keypad + */ + cASCIICtrlCode='\0'; + + switch(ucScan) + { + case KEY_UP_ARROW: + { + cASCIICtrlCode='A'; + break; + } + + case KEY_DOWN_ARROW: + { + cASCIICtrlCode='B'; + break; + } + + case KEY_RIGHT_ARROW: + { + cASCIICtrlCode='C'; + break; + } + + case KEY_LEFT_ARROW: + { + cASCIICtrlCode='D'; + break; + } + + case KEY_HOME: + { + cASCIICtrlCode='H'; + break; + } + + case KEY_END: + { + cASCIICtrlCode='K'; + break; + } + + case KEY_PAGE_UP: + { + cASCIICtrlCode='?'; + break; + } + + case KEY_PAGE_DOWN: + { + cASCIICtrlCode='/'; + break; + } + + case KEY_INSERT: + { + cASCIICtrlCode='@'; + break; + } + + case KEY_DELETE: + { + /* + * This is a special case not requiring an ASCII_CSI + */ + EnqueueKbdChar(minor, ASCII_DEL); + return(TRUE); + } + + default: + { + /* + * Something else needs to process this code + */ + break; + } + } + + if(cASCIICtrlCode) + { + EnqueueKbdChar(minor, ASCII_CSI); + EnqueueKbdChar(minor, cASCIICtrlCode); + return(TRUE); + } + else + { + return(FALSE); + } +} + +/* + * This routine translates the keyboard scan code into an + * ASCII character (or sequence) and queues it + */ +static void i8042_scan_code( + int minor, + unsigned8 ucScan +) +{ + char cChar; + boolean bMakenBreak; + + /* + * Check for code 0xe0, which introduces a two key sequence. + */ + + if(ucScan==KEY_TWO_KEY) + { + bTwoCode=TRUE; + return; + } + + /* + * Bit 7 of scan code indicates make or break + */ + if(ucScan & 0x80) + { + bMakenBreak=FALSE; + ucScan&=0x7f; + } + else + { + bMakenBreak=TRUE; + } + + /* + * If we are in a multikey sequence then process the second keypress + */ + if(bTwoCode) + { + i8042_process_two_code(minor, ucScan, bMakenBreak); + + /* + * Revert to prcessing single key sequences + */ + bTwoCode=FALSE; + return; + } + + if(i8042_process_qualifiers(ucScan, bMakenBreak)) + { + /* + * We are all done + */ + return; + } + + /* + * The remaining keys are only processed for make + */ + if(!bMakenBreak) + { + return; + } + + if(i8042_process_top_row(minor, ucScan)) + { + /* + * We are all done + */ + return; + } + + if(!bNumLock && i8042_process_keypad(minor, ucScan)) + { + /* + * We are all done + */ + return; + } + + /* + * Process "normal" keys + */ + + cChar=0; + + /* + * Check to see if the scan code corresponds to an ASCII + * character. + */ + if(((ucScan >= 16) && (ucScan <= 25)) || + ((ucScan >= 30) && (ucScan <= 38)) || + ((ucScan >= 44) && (ucScan <= 50))) + { + if(bCtrlPressed) + { + cChar=pcNormalLookup[ucScan - 2]-'a'+1; + } + else + { + if(((bLShiftPressed || bRShiftPressed) && !bCapsLock) || + (!(bLShiftPressed || bRShiftPressed) && bCapsLock)) + { + cChar=pcShiftedLookup[ucScan - 2]; + } + else + { + cChar=pcNormalLookup[ucScan - 2]; + } + } + } + else if((ucScan > 1) && (ucScan <= 0x56)) + { + /* + * Its ASCII but not alpha, so don't shift on CapsLock. + */ + if(bLShiftPressed || bRShiftPressed) + { + cChar=pcShiftedLookup[ucScan - 2]; + } + else + { + cChar=pcNormalLookup[ucScan - 2]; + } + } + + /* + * If we got a character then queue it + */ + if(cChar) + { + EnqueueKbdChar(minor, cChar); + } +} + +/* + * Console Device Driver Entry Points + */ +boolean i8042_probe(int minor) +{ + unsigned8 ucKeyboardAck; + unsigned8 ucKeyboardID1, ucKeyboardID2; + + if(!vga_probe(minor)) + { + /* + * There is no VGA adaptor so fail probe + */ + return(FALSE); + } + + Ring_buffer_Initialize(&KbdInputBuffer); +#if CONSOLE_USE_INTERRUPTS + Ring_buffer_Initialize(&KbdOutputBuffer); +#endif + + i8042_polled_on(minor); + /* + * Determine keyboard type + */ + i8042_outbyte_raw(minor, KBD_CMD_READ_ID); + ucKeyboardAck=0; + if((i8042_inbyte_raw(minor, &ucKeyboardAck)==RTEMS_TIMEOUT) || + (ucKeyboardAck==KBD_CMD_RESEND)) + { + /* + * No or incorrect keyboard response so fail probe + */ + return(FALSE); + } + + i8042_inbyte_raw(minor, &ucKeyboardID1); + i8042_inbyte_raw(minor, &ucKeyboardID2); + if((ucKeyboardID1==0xab) && (ucKeyboardID2==0x41)) + { + pcNormalLookup=&pcUKNormalLookup[0]; + pcShiftedLookup=&pcUKShiftedLookup[0]; + } + else + { + pcNormalLookup=&pcUSNormalLookup[0]; + pcShiftedLookup=&pcUSShiftedLookup[0]; + } + i8042_polled_off(minor); + + return(TRUE); +} + +void i8042_init(int minor) +{ + unsigned8 ucKeyboardAck; + + vga_init(minor); + + i8042_polled_on(minor); + /* + * Switch all LEDs off + */ + i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS); + i8042_inbyte_raw(minor, &ucKeyboardAck); + i8042_outbyte_raw(minor, 0); + i8042_inbyte_raw(minor, &ucKeyboardAck); + /* + * Select scan code set 1 + */ + i8042_outbyte_raw(minor, KBD_CMD_SEL_SCAN_CODE); + i8042_inbyte_raw(minor, &ucKeyboardAck); + i8042_outbyte_raw(minor, 1); + i8042_inbyte_raw(minor, &ucKeyboardAck); + i8042_polled_off(minor); +} + +/* PAGE + * + * i8042_inbyte_nonblocking_polled + * + * Console Termios polling input entry point. + */ + +int i8042_inbyte_nonblocking_polled( + int minor +) +{ + unsigned8 ucScan; + char ucData; + + if(i8042_inbyte_polled(minor, &ucScan)==RTEMS_SUCCESSFUL) + { + i8042_scan_code(minor, ucScan); + } + + if(!Ring_buffer_Is_empty(&KbdInputBuffer)) + { + Ring_buffer_Remove_character(&KbdInputBuffer, + ucData); + return(ucData); + } + + return(-1); +} + +#if CONSOLE_USE_INTERRUPTS +/* + * i8042_isr + * + * This routine is the console interrupt handler for the keyboard + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + */ +static void i8042_process( + int minor +) +{ + unsigned8 Status; + unsigned8 ucData; + + inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); + + if(Status & KBD_OBF_MASK) + { + inport_byte(Console_Port_Tbl[minor].ulDataPort, ucData); + + if(bProcessInterruptInput) + { + /* + * Every byte written to the keyboard should be followed + * by an acknowledge + */ + if(ucData==KBD_CMD_ACK) + { + bReceivedAck=TRUE; + } + else + { + i8042_scan_code(minor, ucData); + } + } + else + { + /* + * Store the scan code into the ring buffer where it + * can be read using i8042_inbyte_raw() + */ + Ring_buffer_Add_character(&KbdInputBuffer, ucData); + } + } + + if(((Status & KBD_IBF_MASK)==0) && + bReceivedAck) + { + if(Ring_buffer_Is_empty(&KbdOutputBuffer)) + { + Console_Port_Data[minor].bActive=FALSE; + } + else + { + Ring_buffer_Remove_character(&KbdOutputBuffer, + ucData); + outport_byte(Console_Port_Tbl[minor].ulDataPort, + ucData); + bReceivedAck=FALSE; + } + } +} + +static rtems_isr i8042_isr( + rtems_vector_number vector +) +{ + int minor; + + for(minor=0;minor<Console_Port_Count;minor++) + { + if(vector==Console_Port_Tbl[minor].ulIntVector) + { + i8042_process(minor); + } + } +} + +void i8042_initialize_interrupts(int minor) +{ + i8042_init(minor); + + Console_Port_Data[minor].bActive=FALSE; + + set_vector(i8042_isr, + Console_Port_Tbl[minor].ulIntVector, + 1); + + i8042_outbyte_cmd_polled(minor, KBD_CTR_WRITE_COMMAND); + i8042_outbyte_raw(minor, KBD_CMD_ENABLE_KBD_INT); + + /* + * At this point interrupts should spring into life + */ + bInterruptsEnabled=TRUE; +} + +#endif /* CONSOLE_USE_INTERRUPTS */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042_p.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042_p.h new file mode 100644 index 0000000000..57273fbe7f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042_p.h @@ -0,0 +1,196 @@ +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + */ + +#ifndef _I8042_P_H_ +#define _I8042_P_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define KBD_CTR_WRITE_COMMAND 0x60 +#define KBD_CTR_READ_COMMAND 0x20 +#define KBD_CTR_TEST_PASSWORD 0xA4 +#define KBD_CTR_LOAD_PASSWORD 0xA5 +#define KBD_CTR_ENABLE_PASSWORD 0xA6 +#define KBD_CTR_DISABLE_AUX 0xA7 +#define KBD_CTR_ENABLE_AUX 0xA8 +#define KBD_CTR_AUXLINES_TEST 0xA9 +#define KBD_CTR_SELFTEST 0xAA +#define KBD_CTR_KBDLINES_TEST 0xAB +#define KBD_CTR_DISABLE_KBD 0xAD +#define KBD_CTR_ENABLE_KBD 0xAE +#define KBD_CTR_WRITE_AUX 0xD4 +#define KBD_CTR_READ_REV 0xD5 +#define KBD_CTR_READ_VER 0xD6 +#define KBD_CTR_READ_MODEL 0xD7 + +/* Keyboard Controller Data */ +#define KBD_CTR_SELFTEST_PASSED 0x55 +#define KBD_CTR_PASSWORD_INSTALLED 0xFA +#define KBD_CTR_PASSWORD_NOT_INSTALLED 0xF1 + +/* Controller Command Byte bit definitions. */ +#define KBD_CMD_BYTE_DISABLE_AUX 0x20 +#define KBD_CMD_BYTE_DISABLE_KBD 0x10 +#define KBD_CMD_ENABLE_AUX_INT 0x02 +#define KBD_CMD_ENABLE_KBD_INT 0x01 + +/* Keyboard Controller Status byte masks */ +#define KBD_OBF_MASK 0x1 /* Output buffer full */ +#define KBD_IBF_MASK 0x2 /* Input buffer full */ +#define KBD_FROM_AUX_MASK 0x20 /* Byte from Aux Port. */ + +/* Interface Test Results */ +#define INTERFACE_NO_ERROR 0x00 +#define CLOCK_STUCK_LOW 0x01 +#define CLOCK_STUCK_HIGH 0x02 +#define DATA_STUCK_LOW 0x03 +#define DATA_STUCK_HIGH 0x04 + +/* Timeout */ +#define KBD_TIMEOUT 500000 /* Effectively ISA read access times */ + +/* Keyboard Commands */ +#define KBD_CMD_SET_LEDS 0xed /* Set/Reset LEDs */ +#define KBD_CMD_ECHO 0xee /* request keyboard echo resp. "EE" */ +#define KBD_CMD_SEL_SCAN_CODE 0xf0 /* Scan codes 1,2,3 or 0 = rquest current. */ +#define KBD_CMD_READ_ID 0xf2 /* Request for two byte response */ +#define KBD_CMD_SET_RATE 0xf3 /* Set tellematic Rate */ +#define KBD_CMD_ENABLE 0xf4 /* Clears Buffer and Starts Scanning. */ +#define KBD_CMD_DISABLE 0xf5 /* reset to power up */ + +#define KBD_CMD_SET_DEFAULT 0xf6 +#define KBD_CMD_SET_ALL_TLMTIC 0xf7 /* Set all keys telematic */ +#define KBD_CMD_SET_ALL_MKBR 0xf8 /* Set all keys Make /Break */ +#define KBD_CMD_SET_ALL_MAKE 0xf9 /* Set all keys Make only */ +#define KBD_CMD_SET_KEY_TLMTIC 0xfb /* Set individual key telemativ */ +#define KBD_CMD_SET_KEY_MKBR 0xfc /* set individual key make/break */ +#define KBD_CMD_SET_KEY_MK 0xfd /* set individual key make only */ +#define KBD_CMD_RESEND 0xfe /* request to resend last transfer */ +#define KBD_CMD_RESET 0xff /* request to start a program reset */ +#define KBD_CMD_ACK 0xfa /* keyboard ack after reset */ +#define KBD_CMD_BAT 0xaa /* Keyboard Bat completion Response */ + +/* + * Define LED encodings for use with the KbdSetLEDs command + */ +#define KBD_LED_CAPS 0x04 +#define KBD_LED_NUM 0x02 +#define KBD_LED_SCROLL 0x01 + +/* + * Define two code scan codes in keycode order + */ +#define KEY_TWO_KEY 0xe0 +#define KEY_ALT 0x38 +#define KEY_CONTROL 0x1d +#define KEY_INSERT 0x52 +#define KEY_DELETE 0x53 +#define KEY_LEFT_ARROW 0x4b +#define KEY_HOME 0x47 +#define KEY_END 0x4F +#define KEY_UP_ARROW 0x48 +#define KEY_DOWN_ARROW 0x50 +#define KEY_PAGE_UP 0x49 +#define KEY_PAGE_DOWN 0x51 +#define KEY_RIGHT_ARROW 0x4d +#define KEY_KEYPAD_SLASH 0x35 +#define KEY_KEYPAD_ENTER 0x1c +#define KEY_SYS_REQUEST 0x2a +#define KEY_PRINT_SCREEN 0x37 + +#define KEY_LEFT_SHIFT 0x2a +#define KEY_RIGHT_SHIFT 0x36 +#define KEY_TAB 0x0f +#define KEY_CAPS_LOCK 0x3a +#define KEY_NUM_LOCK 0x45 +#define KEY_SCROLL_LOCK 0x46 +#define KEY_ESC 0x01 +#define KEY_F1 0x3b +#define KEY_F2 0x3c +#define KEY_F3 0x3d +#define KEY_F4 0x3e +#define KEY_F5 0x3f +#define KEY_F6 0x40 +#define KEY_F7 0x41 +#define KEY_F8 0x42 +#define KEY_F9 0x43 +#define KEY_F10 0x44 +#define KEY_F11 0x57 +#define KEY_F12 0x58 + +/* + * ASCII control codes + */ +#define ASCII_NUL 0x00 +#define ASCII_SOH 0x01 +#define ASCII_STX 0x02 +#define ASCII_ETX 0x03 +#define ASCII_EOT 0x04 +#define ASCII_ENQ 0x05 +#define ASCII_ACK 0x06 +#define ASCII_BEL 0x07 +#define ASCII_BS 0x08 +#define ASCII_HT 0x09 +#define ASCII_LF 0x0a +#define ASCII_VT 0x0b +#define ASCII_FF 0x0c +#define ASCII_CR 0x0d +#define ASCII_SO 0x0e +#define ASCII_SI 0x0f +#define ASCII_DLE 0x10 +#define ASCII_XON 0x11 +#define ASCII_DC1 0x11 +#define ASCII_DC2 0x12 +#define ASCII_XOFF 0x13 +#define ASCII_DC3 0x13 +#define ASCII_DC4 0x14 +#define ASCII_NAK 0x15 +#define ASCII_SYN 0x16 +#define ASCII_ETB 0x17 +#define ASCII_CAN 0x18 +#define ASCII_EM 0x19 +#define ASCII_SUB 0x1a +#define ASCII_ESC 0x1b +#define ASCII_FS 0x1c +#define ASCII_GS 0x1d +#define ASCII_RS 0x1e +#define ASCII_US 0x1f +#define ASCII_DEL 0x7f +#define ASCII_SYSRQ 0x80 +#define ASCII_CSI 0x9b + +/* + * Exported functions + */ +extern boolean i8042_probe(int minor); + +extern void i8042_init(int minor); +#if CONSOLE_USE_INTERRUPTS +extern void i8042_initialize_interrupts(int minor); + +#else +extern int i8042_inbyte_nonblocking_polled( + int minor +); +#endif /* CONSOLE_USE_INTERRUPTS */ + +#ifdef __cplusplus +} +#endif + +#endif /* _I8042_P_H_ */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.c new file mode 100644 index 0000000000..59716da49a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.c @@ -0,0 +1,46 @@ +/* + * This file contains the TTY driver for the VGA/i8042 console + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * This driver uses the termios pseudo driver. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/libio.h> + +#include "console.h" +#include "vga_p.h" +#include "i8042_p.h" + +console_fns i8042vga_fns = +{ + i8042_probe, /* deviceProbe */ + NULL, /* deviceFirstOpen */ + NULL, /* deviceLastClose */ +#if CONSOLE_USE_INTERRUPTS + NULL, /* deviceRead */ + vga_write_support, /* deviceWrite */ + i8042_initialize_interrupts, /* deviceInitialize */ +#else + i8042_inbyte_nonblocking_polled, /* deviceRead */ + vga_write_support, /* deviceWrite */ + i8042_init, /* deviceInitialize */ +#endif + vga_write, /* deviceWritePolled */ + FALSE, /* deviceOutputUsesInterrupts */ +}; diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.h new file mode 100644 index 0000000000..6cbceb92de --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042vga.h @@ -0,0 +1,34 @@ +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * $Id$ + */ + +#ifndef _I8042VGA_H_ +#define _I8042VGA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Driver function table + */ +extern console_fns i8042vga_fns; + +#ifdef __cplusplus +} +#endif + +#endif /* _I8042VGA_H_ */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c new file mode 100644 index 0000000000..30c10f73b2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c @@ -0,0 +1,632 @@ +/* + * This file contains the TTY driver for the NS16550 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * This driver uses the termios pseudo driver. + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/libio.h> +#include <stdlib.h> + +#include "console.h" +#include "ns16550_p.h" + +/* + * Flow control is only supported when using interrupts + */ +console_flow ns16550_flow_RTSCTS = +{ + ns16550_negate_RTS, /* deviceStopRemoteTx */ + ns16550_assert_RTS /* deviceStartRemoteTx */ +}; + +console_flow ns16550_flow_DTRCTS = +{ + ns16550_negate_DTR, /* deviceStopRemoteTx */ + ns16550_assert_DTR /* deviceStartRemoteTx */ +}; + +console_fns ns16550_fns = +{ + ns16550_probe, /* deviceProbe */ + ns16550_open, /* deviceFirstOpen */ + ns16550_flush, /* deviceLastClose */ + NULL, /* deviceRead */ + ns16550_write_support_int, /* deviceWrite */ + ns16550_initialize_interrupts, /* deviceInitialize */ + ns16550_write_polled, /* deviceWritePolled */ + FALSE, /* deviceOutputUsesInterrupts */ +}; + +console_fns ns16550_fns_polled = +{ + ns16550_probe, /* deviceProbe */ + ns16550_open, /* deviceFirstOpen */ + ns16550_close, /* deviceLastClose */ + ns16550_inbyte_nonblocking_polled, /* deviceRead */ + ns16550_write_support_polled, /* deviceWrite */ + ns16550_init, /* deviceInitialize */ + ns16550_write_polled, /* deviceWritePolled */ + FALSE, /* deviceOutputUsesInterrupts */ +}; + +/* + * Console Device Driver Entry Points + */ +static boolean ns16550_probe(int minor) +{ + /* + * If the configuration dependant probe has located the device then + * assume it is there + */ + return(TRUE); +} + +static void ns16550_init(int minor) +{ + PSP_READ_REGISTERS pNS16550Read; + PSP_WRITE_REGISTERS pNS16550Write; + unsigned8 ucTrash; + unsigned8 ucDataByte; + unsigned32 ulBaudDivisor; + ns16550_context *pns16550Context; + + pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context)); + + Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context; + pns16550Context->ucModemCtrl=SP_MODEM_IRQ; + + pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; + + /* Clear the divisor latch, clear all interrupt enables, + * and reset and + * disable the FIFO's. + */ + + outport_byte(&pNS16550Write->LineControl, 0x0); + outport_byte(&pNS16550Write->InterruptEnable, 0x0); + + /* Set the divisor latch and set the baud rate. */ + + ulBaudDivisor=NS16550_Baud( + (unsigned32)Console_Port_Tbl[minor].pDeviceParams); + ucDataByte = SP_LINE_DLAB; + outport_byte(&pNS16550Write->LineControl, ucDataByte); + outport_byte(&pNS16550Write->TransmitBuffer, ulBaudDivisor&0xff); + outport_byte(&pNS16550Write->InterruptEnable, (ulBaudDivisor>>8)&0xff); + + /* Clear the divisor latch and set the character size to eight bits */ + /* with one stop bit and no parity checking. */ + + ucDataByte = EIGHT_BITS; + outport_byte(&pNS16550Write->LineControl, ucDataByte); + + /* Enable and reset transmit and receive FIFOs. TJA */ + ucDataByte = SP_FIFO_ENABLE; + outport_byte(&pNS16550Write->FifoControl, ucDataByte); + + ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; + outport_byte(&pNS16550Write->FifoControl, ucDataByte); + + /* + * Disable interrupts + */ + ucDataByte = 0; + outport_byte(&pNS16550Write->InterruptEnable, ucDataByte); + + /* Set data terminal ready. */ + /* And open interrupt tristate line */ + + outport_byte(&pNS16550Write->ModemControl, + pns16550Context->ucModemCtrl); + + inport_byte(&pNS16550Read->LineStatus, ucTrash); + inport_byte(&pNS16550Read->ReceiveBuffer, ucTrash); +} + +static int ns16550_open( + int major, + int minor, + void * arg +) +{ + PSP_WRITE_REGISTERS pNS16550Write; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Assert DTR + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&ns16550_flow_DTRCTS) + { + ns16550_assert_DTR(minor); + } + + return(RTEMS_SUCCESSFUL); +} + +static int ns16550_close( + int major, + int minor, + void * arg +) +{ + PSP_WRITE_REGISTERS pNS16550Write; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Negate DTR + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&ns16550_flow_DTRCTS) + { + ns16550_negate_DTR(minor); + } + + return(RTEMS_SUCCESSFUL); +} + +/* + * ns16550_write_polled + */ +static void ns16550_write_polled( + int minor, + char cChar +) +{ + PSP_READ_REGISTERS pNS16550Read; + PSP_WRITE_REGISTERS pNS16550Write; + unsigned char ucLineStatus; + int iTimeout; + + pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; + + /* + * wait for transmitter holding register to be empty + */ + iTimeout=1000; + inport_byte(&pNS16550Read->LineStatus, ucLineStatus); + while ((ucLineStatus & SP_LSR_THOLD) == 0) + { + /* + * Yield while we wait + */ + if(_System_state_Is_up(_System_state_Get())) + { + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + inport_byte(&pNS16550Read->LineStatus, ucLineStatus); + if(!--iTimeout) + { + break; + } + } + + /* + * transmit character + */ + outport_byte(&pNS16550Write->TransmitBuffer, cChar); +} + +/* + * These routines provide control of the RTS and DTR lines + */ +/* + * ns16550_assert_RTS + */ +static void ns16550_assert_RTS(int minor) +{ + PSP_WRITE_REGISTERS pNS16550Write; + unsigned32 Irql; + ns16550_context *pns16550Context; + + pns16550Context=(ns16550_context *) + Console_Port_Data[minor].pDeviceContext; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Assert RTS + */ + rtems_interrupt_disable(Irql); + pns16550Context->ucModemCtrl|=SP_MODEM_RTS; + outport_byte(&pNS16550Write->ModemControl, + pns16550Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * ns16550_negate_RTS + */ +static void ns16550_negate_RTS(int minor) +{ + PSP_WRITE_REGISTERS pNS16550Write; + unsigned32 Irql; + ns16550_context *pns16550Context; + + pns16550Context=(ns16550_context *) + Console_Port_Data[minor].pDeviceContext; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Negate RTS + */ + rtems_interrupt_disable(Irql); + pns16550Context->ucModemCtrl&=~SP_MODEM_RTS; + outport_byte(&pNS16550Write->ModemControl, + pns16550Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * These flow control routines utilise a connection from the local DTR + * line to the remote CTS line + */ +/* + * ns16550_assert_DTR + */ +static void ns16550_assert_DTR(int minor) +{ + PSP_WRITE_REGISTERS pNS16550Write; + unsigned32 Irql; + ns16550_context *pns16550Context; + + pns16550Context=(ns16550_context *) + Console_Port_Data[minor].pDeviceContext; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Assert DTR + */ + rtems_interrupt_disable(Irql); + pns16550Context->ucModemCtrl|=SP_MODEM_DTR; + outport_byte(&pNS16550Write->ModemControl, + pns16550Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * ns16550_negate_DTR + */ +static void ns16550_negate_DTR(int minor) +{ + PSP_WRITE_REGISTERS pNS16550Write; + unsigned32 Irql; + ns16550_context *pns16550Context; + + pns16550Context=(ns16550_context *) + Console_Port_Data[minor].pDeviceContext; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Negate DTR + */ + rtems_interrupt_disable(Irql); + pns16550Context->ucModemCtrl&=~SP_MODEM_DTR; + outport_byte(&pNS16550Write->ModemControl, + pns16550Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * ns16550_isr + * + * This routine is the console interrupt handler for COM1 and COM2 + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + */ + +static void ns16550_process( + int minor +) +{ + PSP_READ_REGISTERS pNS16550Read; + PSP_WRITE_REGISTERS pNS16550Write; + volatile unsigned8 ucLineStatus, ucInterruptId; + char cChar; + + pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; + + do + { + /* + * Deal with any received characters + */ + while(TRUE) + { + inport_byte(&pNS16550Read->LineStatus, ucLineStatus); + if(~ucLineStatus & SP_LSR_RDY) + { + break; + } + inport_byte(&pNS16550Read->ReceiveBuffer, cChar); + rtems_termios_enqueue_raw_characters( + Console_Port_Data[minor].termios_data, + &cChar, 1 ); + } + + while(TRUE) + { + if(Ring_buffer_Is_empty( + &Console_Port_Data[minor].TxBuffer)) + { + Console_Port_Data[minor].bActive=FALSE; + if(Console_Port_Tbl[minor].pDeviceFlow + !=&ns16550_flow_RTSCTS) + { + ns16550_negate_RTS(minor); + } + /* + * There is no data to transmit + */ + break; + } + + inport_byte(&pNS16550Read->LineStatus, ucLineStatus); + if(~ucLineStatus & SP_LSR_THOLD) + { + /* + * We'll get another interrupt when + * the transmitter holding reg. becomes + * free again + */ + break; + } + + Ring_buffer_Remove_character( + &Console_Port_Data[minor].TxBuffer, + cChar); + /* + * transmit character + */ + outport_byte(&pNS16550Write->TransmitBuffer, cChar); + } + + inport_byte(&pNS16550Read->InterruptId, ucInterruptId); + } + while((ucInterruptId&0xf)!=0x1); +} + +static rtems_isr ns16550_isr( + rtems_vector_number vector +) +{ + int minor; + + for(minor=0;minor<Console_Port_Count;minor++) + { + if(vector==Console_Port_Tbl[minor].ulIntVector) + { + ns16550_process(minor); + } + } +} + +/* + * ns16550_flush + */ +static int ns16550_flush(int major, int minor, void *arg) +{ + while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) + { + /* + * Yield while we wait + */ + if(_System_state_Is_up(_System_state_Get())) + { + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + } + + ns16550_close(major, minor, arg); + + return(RTEMS_SUCCESSFUL); +} + +/* + * ns16550_initialize_interrupts + * + * This routine initializes the console's receive and transmit + * ring buffers and loads the appropriate vectors to handle the interrupts. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +static void ns16550_enable_interrupts( + int minor +) +{ + PSP_WRITE_REGISTERS pNS16550Write; + unsigned8 ucDataByte; + + pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Enable interrupts + */ + ucDataByte = SP_INT_RX_ENABLE | SP_INT_TX_ENABLE; + outport_byte(&pNS16550Write->InterruptEnable, ucDataByte); + +} + +static void ns16550_initialize_interrupts(int minor) +{ + ns16550_init(minor); + + Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer); + + Console_Port_Data[minor].bActive = FALSE; + + set_vector(ns16550_isr, + Console_Port_Tbl[minor].ulIntVector, + 1); + + ns16550_enable_interrupts(minor); +} + +/* + * ns16550_write_support_int + * + * Console Termios output entry point. + * + */ +static int ns16550_write_support_int( + int minor, + const char *buf, + int len) +{ + int i; + unsigned32 Irql; + + for(i=0; i<len;) + { + if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) + { + if(!Console_Port_Data[minor].bActive) + { + /* + * Wake up the device + */ + rtems_interrupt_disable(Irql); + Console_Port_Data[minor].bActive = TRUE; + if(Console_Port_Tbl[minor].pDeviceFlow + !=&ns16550_flow_RTSCTS) + { + ns16550_assert_RTS(minor); + } + ns16550_process(minor); + rtems_interrupt_enable(Irql); + } + else + { + /* + * Yield + */ + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + + /* + * Wait for ring buffer to empty + */ + continue; + } + else + { + Ring_buffer_Add_character( + &Console_Port_Data[minor].TxBuffer, + buf[i]); + i++; + } + } + + /* + * Ensure that characters are on the way + */ + if(!Console_Port_Data[minor].bActive) + { + /* + * Wake up the device + */ + rtems_interrupt_disable(Irql); + Console_Port_Data[minor].bActive = TRUE; + if(Console_Port_Tbl[minor].pDeviceFlow + !=&ns16550_flow_RTSCTS) + { + ns16550_assert_RTS(minor); + } + ns16550_process(minor); + rtems_interrupt_enable(Irql); + } + + return (len); +} + +/* + * ns16550_write_support_polled + * + * Console Termios output entry point. + * + */ +static int ns16550_write_support_polled( + int minor, + const char *buf, + int len) +{ + int nwrite = 0; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) + { + /* + * transmit character + */ + ns16550_write_polled(minor, *buf++); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + +/* + * ns16550_inbyte_nonblocking_polled + * + * Console Termios polling input entry point. + */ + +static int ns16550_inbyte_nonblocking_polled( + int minor +) +{ + PSP_READ_REGISTERS pNS16550Read; + unsigned char ucLineStatus; + char cChar; + + pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; + + inport_byte(&pNS16550Read->LineStatus, ucLineStatus); + if(ucLineStatus & SP_LSR_RDY) + { + inport_byte(&pNS16550Read->ReceiveBuffer, cChar); + return((int)cChar); + } + else + { + return(-1); + } +} diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.h new file mode 100644 index 0000000000..e797ba2244 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.h @@ -0,0 +1,40 @@ +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + */ + +#ifndef _NS16550_H_ +#define _NS16550_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Driver function table + */ +extern console_fns ns16550_fns; +extern console_fns ns16550_fns_polled; + +/* + * Flow control function tables + */ +extern console_flow ns16550_flow_RTSCTS; +extern console_flow ns16550_flow_DTRCTS; + +#ifdef __cplusplus +} +#endif + +#endif /* _NS16550_H_ */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550_p.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550_p.h new file mode 100644 index 0000000000..7f7f51afa9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550_p.h @@ -0,0 +1,196 @@ +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + */ + +#ifndef _NS16550_P_H_ +#define _NS16550_P_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Define serial port read registers structure. + */ + +typedef volatile struct _SP_READ_REGISTERS { + unsigned char ReceiveBuffer; + unsigned char InterruptEnable; + unsigned char InterruptId; + unsigned char LineControl; + unsigned char ModemControl; + unsigned char LineStatus; + unsigned char ModemStatus; + unsigned char ScratchPad; +} SP_READ_REGISTERS, *PSP_READ_REGISTERS; + +/* + * Define serial port write registers structure. + */ + +typedef volatile struct _SP_WRITE_REGISTERS { + unsigned char TransmitBuffer; + unsigned char InterruptEnable; + unsigned char FifoControl; + unsigned char LineControl; + unsigned char ModemControl; + unsigned char Reserved1; + unsigned char ModemStatus; + unsigned char ScratchPad; +} SP_WRITE_REGISTERS, *PSP_WRITE_REGISTERS; + +/* + * Define serial port interrupt enable register structure. + */ + +#define SP_INT_RX_ENABLE 0x01 +#define SP_INT_TX_ENABLE 0x02 +#define SP_INT_LS_ENABLE 0x04 +#define SP_INT_MS_ENABLE 0x08 + +/* + * Define serial port interrupt id register structure. + */ + +typedef struct _SP_INTERRUPT_ID { + unsigned char InterruptPending : 1; + unsigned char Identification : 3; + unsigned char Reserved1 : 2; + unsigned char FifoEnabled : 2; +} SP_INTERRUPT_ID, *PSP_INTERRUPT_ID; + +/* + * Define serial port fifo control register structure. + */ +#define SP_FIFO_ENABLE 0x01 +#define SP_FIFO_RXRST 0x02 +#define SP_FIFO_TXRST 0x04 +#define SP_FIFO_DMA 0x08 +#define SP_FIFO_RXLEVEL 0xc0 + +/* + * Define serial port line control register structure. + */ +#define SP_LINE_SIZE 0x03 +#define SP_LINE_STOP 0x04 +#define SP_LINE_PAR 0x08 +#define SP_LINE_ODD 0x10 +#define SP_LINE_STICK 0x20 +#define SP_LINE_BREAK 0x40 +#define SP_LINE_DLAB 0x80 + +/* + * Line status register character size definitions. + */ +#define FIVE_BITS 0x0 /* five bits per character */ +#define SIX_BITS 0x1 /* six bits per character */ +#define SEVEN_BITS 0x2 /* seven bits per character */ +#define EIGHT_BITS 0x3 /* eight bits per character */ + +/* + * Line speed divisor definition. + */ +#define NS16550_Baud(baud_rate) (115200/baud_rate) + +/* + * Define serial port modem control register structure. + */ +#define SP_MODEM_DTR 0x01 +#define SP_MODEM_RTS 0x02 +#define SP_MODEM_IRQ 0x08 +#define SP_MODEM_LOOP 0x10 +#define SP_MODEM_DIV4 0x80 + +/* + * Define serial port line status register structure. + */ +#define SP_LSR_RDY 0x01 +#define SP_LSR_EOVRUN 0x02 +#define SP_LSR_EPAR 0x04 +#define SP_LSR_EFRAME 0x08 +#define SP_LSR_BREAK 0x10 +#define SP_LSR_THOLD 0x20 +#define SP_LSR_TX 0x40 +#define SP_LSR_EFIFO 0x80 + +typedef struct _ns16550_context +{ + unsigned8 ucModemCtrl; +} ns16550_context; + +/* + * Driver functions + */ +static boolean ns16550_probe(int minor); + +static void ns16550_init(int minor); + +static int ns16550_open( + int major, + int minor, + void * arg +); + +static int ns16550_close( + int major, + int minor, + void * arg +); + +static void ns16550_write_polled( + int minor, + char cChar +); + +static void ns16550_assert_RTS( + int minor +); + +static void ns16550_negate_RTS( + int minor +); + +static void ns16550_assert_DTR( + int minor +); + +static void ns16550_negate_DTR( + int minor +); + +static void ns16550_initialize_interrupts(int minor); + +static int ns16550_flush(int major, int minor, void *arg); + +static int ns16550_write_support_int( + int minor, + const char *buf, + int len +); + +static int ns16550_write_support_polled( + int minor, + const char *buf, + int len + ); + +static int ns16550_inbyte_nonblocking_polled( + int minor +); + +#ifdef __cplusplus +} +#endif + +#endif /* _NS16550_P_H_ */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.c new file mode 100644 index 0000000000..88cbde4bbe --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.c @@ -0,0 +1,53 @@ +/* nc16550cfg.c + * + * This include file contains all console driver definations for the nc16550 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> + +unsigned8 Read_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +) +{ + unsigned char *p = (unsigned char *)ulCtrlPort; + unsigned char ucData; + + inport_byte( &p[ucRegNum], ucData ); + return ucData; +} + +void Write_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +) +{ + unsigned char *p = (unsigned char *)ulCtrlPort; + + outport_byte( &p[ucRegNum], ucData ); +} diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.h new file mode 100644 index 0000000000..87235a80f2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550cfg.h @@ -0,0 +1,55 @@ +/* nc16550cfg.h + * + * This include file contains all console driver definations for the nc16550 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __NS16550_CONFIG_H +#define __NS16550_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Board specific register access routines + */ + +unsigned8 Read_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +); + +void Write_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga.c new file mode 100644 index 0000000000..ed7a867d1d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga.c @@ -0,0 +1,368 @@ +/* + * This file contains the TTY driver for VGA + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * This driver uses the termios pseudo driver. + */ +/*-------------------------------------------------------------------------+ +| (C) Copyright 1997 - +| - NavIST Group - Real-Time Distributed Systems and Industrial Automation +| +| http://pandora.ist.utl.pt +| +| Instituto Superior Tecnico * Lisboa * PORTUGAL ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------+ +| This code is based on: +| outch.c,v 1.4 1995/12/19 20:07:27 joel Exp - go32 BSP +| With the following copyright notice: +| ************************************************************************** +| * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. * +| * On-Line Applications Research Corporation (OAR). * +| * All rights assigned to U.S. Government, 1994. * +| * * +| * This material may be reproduced by or for the U.S. Government pursuant * +| * to the copyright license under the clause at DFARS 252.227-7013. This * +| * notice must appear in all copies of this file and its derivatives. * +| ************************************************************************** ++--------------------------------------------------------------------------*/ + + +#include <bsp.h> + +#include <stdlib.h> +#include <string.h> + +#include "vga_p.h" + +/*-------------------------------------------------------------------------+ +| Constants ++--------------------------------------------------------------------------*/ +#define DISPLAY_CELL_COUNT (VGA_NUM_ROWS * VGA_NUM_COLS) + /* Number of display cells. */ +#define TABSIZE 4 /* Number of spaces for TAB (\t) char. */ +#define WHITE 0x0007 /* White on Black background colour. */ +#define BLANK (WHITE | (' '<<8)) /* Blank character. */ + +/* + * This is imported from i8042.c to provide flow control + */ +extern volatile boolean bScrollLock; + +/*-------------------------------------------------------------------------+ +| Global Variables ++--------------------------------------------------------------------------*/ +/* Physical address of start of video text memory. */ +static unsigned16 *videoRam = (unsigned16 *)VGA_FB; +/* Pointer for current output position in display. */ +static unsigned16 *videoRamPtr = (unsigned16 *)VGA_FB; +static unsigned8 videoRows = VGA_NUM_ROWS; /* Number of rows in display. */ +static unsigned8 videoCols = VGA_NUM_COLS; /* Number of columns in display. */ +static unsigned8 cursRow = 0; /* Current cursor row. */ +static unsigned8 cursCol = 0; /* Current cursor column. */ + + +/*-------------------------------------------------------------------------+ +| Function: setHardwareCursorPos +| Description: Set hardware video cursor at given offset into video RAM. +| Global Variables: None. +| Arguments: videoCursor - Offset into video memory. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +setHardwareCursorPos(unsigned16 videoCursor) +{ + VGA_WRITE_CRTC(0x0e, (videoCursor >> 8) & 0xff); + VGA_WRITE_CRTC(0x0f, videoCursor & 0xff); +} /* setHardwareCursorPos */ + + +/*-------------------------------------------------------------------------+ +| Function: updateVideoRamPtr +| Description: Updates value of global variable "videoRamPtr" based on +| current window's cursor position. +| Global Variables: videoRamPtr, cursRow, cursCol. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +updateVideoRamPtr(void) +{ + videoRamPtr = videoRam + cursRow * videoCols + cursCol; +} /* updateVideoRamPtr */ + + +/*-------------------------------------------------------------------------+ +| Function: scrollUp +| Description: Scrolls display up n lines. +| Global Variables: None. +| Arguments: lines - number of lines to scroll. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static void +scrollUp(unsigned8 lines) +{ + /* Number of blank display cells on bottom of window. */ + unsigned16 blankCount; + + /* Source and destination pointers for memory copy operations. */ + unsigned16 *ptrDst, *ptrSrc; + + if(lines<videoRows) /* Move window's contents up. */ + { + /* + * Number of non-blank cells on upper part + * of display (total - blank). + */ + unsigned16 nonBlankCount; + + blankCount = lines * videoCols; + nonBlankCount = DISPLAY_CELL_COUNT - blankCount; + ptrSrc = videoRam + blankCount; + ptrDst = videoRam; + + while(nonBlankCount--) + { + *ptrDst++ = *ptrSrc++; + } + } + else + { + /* + * Clear the whole display. + */ + blankCount = DISPLAY_CELL_COUNT; + ptrDst = videoRam; + } + + /* Fill bottom with blanks. */ + while (blankCount-->0) + { + *ptrDst++ = BLANK; + } +} /* scrollUp */ + + +/*-------------------------------------------------------------------------+ +| Function: printCHAR +| Description: Print printable character to display. +| Global Variables: videoRamPtr, cursRow, cursCol. +| Arguments: c - character to write to display. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static void +printCHAR(char c) +{ + *videoRamPtr++ = (c<<8) | WHITE; + cursCol++; + if(cursCol==videoCols) + { + cursCol = 0; + cursRow++; + if(cursRow==videoRows) + { + cursRow--; + scrollUp(1); + videoRamPtr -= videoCols; + } + } +} /* printCHAR */ + +/*-------------------------------------------------------------------------+ +| Function: printBS +| Description: Print BS (BackSpace - '\b') character to display. +| Global Variables: videoRamPtr, cursRow, cursCol. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +printBS(void) +{ + /* Move cursor back one cell. */ + if(cursCol>0) + { + cursCol--; + } + else if(cursRow>0) + { + cursRow--; + cursCol = videoCols - 1; + } + else + { + return; + } + + /* Write a whitespace. */ + *(--videoRamPtr) = BLANK; +} /* printBS */ + + +/*-------------------------------------------------------------------------+ +| Function: printHT +| Description: Print HT (Horizontal Tab - '\t') character to display. +| Global Variables: cursCol. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +printHT(void) +{ + do + { + printCHAR(' '); + } + while (cursCol % TABSIZE); +} /* printHT */ + + +/*-------------------------------------------------------------------------+ +| Function: printLF +| Description: Print LF (Line Feed - '\n') character to display. +| Global Variables: cursRow. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +printLF(void) +{ + cursRow++; + if(cursRow==videoRows) + { + cursRow--; + scrollUp(1); + } + updateVideoRamPtr(); +} /* printLF */ + + +/*-------------------------------------------------------------------------+ +| Function: printCR +| Description: Print CR (Carriage Return - '\r') to display. +| Global Variables: cursCol. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static inline void +printCR(void) +{ + cursCol = 0; + updateVideoRamPtr(); +} /* printCR */ + +/* + * Console Device Driver Entry Points + */ +void +vga_write( + int minor, + char cChar) +{ + switch (cChar) + { + case '\b': + printBS(); + break; + case '\t': + printHT(); + break; + case '\n': + printLF(); + break; + case '\r': + printCR(); + break; + default: + printCHAR(cChar); + break; + } + + setHardwareCursorPos(videoRamPtr - videoRam); +} /* vga_write */ + +/* + * vga_write_support + * + * Console Termios output entry point. + * + */ +int vga_write_support( + int minor, + const char *buf, + int len +) +{ + int nwrite = 0; + + while(bScrollLock) + { + /* + * The Scroll lock on the keyboard is active + */ + /* + * Yield while we wait + */ + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + + /* + * Write each byte in the string to the display + */ + while (nwrite<len) + { + /* + * transmit character + */ + vga_write(minor, *buf++); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + +boolean vga_probe(int minor) +{ + unsigned8 ucMiscIn; + + /* + * Check for presence of VGA adaptor + */ + inport_byte(0x3cc, ucMiscIn); + if(ucMiscIn!=0xff) + { + /* + * VGA device is present + */ + return(TRUE); + } + return(FALSE); +} + +void vga_init(int minor) +{ + scrollUp(videoRows); /* Clear entire screen */ + setHardwareCursorPos(0); /* Cursor at upper left corner */ + /* + * Enable the cursor + */ + VGA_WRITE_CRTC(0x0a, 0x0e); /* Crt cursor start */ +} diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga_p.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga_p.h new file mode 100644 index 0000000000..591365a94f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/vga_p.h @@ -0,0 +1,70 @@ +/* + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + */ + +#ifndef _VGA_P_H_ +#define _VGA_P_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define VGA_FB ((unsigned32)PCI_MEM_BASE+0xb8000) +#define VGA_NUM_ROWS 25 +#define VGA_NUM_COLS 80 + +#define VGA_WRITE_SEQ(reg, val) \ + outport_byte(0x3c4, reg); \ + outport_byte(0x3c5, val) +#define VGA_READ_SEQ(reg, val) \ + outport_byte(0x3c4, reg); \ + inport_byte(0x3c5, val) +#define VGA_WRITE_CRTC(reg, val) \ + outport_byte(0x3d4, reg); \ + outport_byte(0x3d5, val) +#define VGA_WRITE_GRA(reg, val) \ + outport_byte(0x3ce, reg); \ + outport_byte(0x3cf, val) +#define VGA_WRITE_ATT(reg, val) \ + { \ + volatile unsigned8 ucDummy; \ + inport_byte(0x3da, ucDummy); \ + outport_byte(0x3c0, reg); \ + outport_byte(0x3c0, val); \ + } + +/* + * Exported functions + */ +extern boolean vga_probe(int minor); + +extern void vga_init(int minor); + +extern void vga_write( + int minor, + char cChar +); + +extern int vga_write_support( + int minor, + const char *buf, + int len +); + +#ifdef __cplusplus +} +#endif + +#endif /* _VGA_P_H_ */ diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.c new file mode 100644 index 0000000000..720117dc8d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.c @@ -0,0 +1,917 @@ +/* + * This file contains the console driver chip level routines for the + * z85c30 chip. + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: + */ + +#include <rtems.h> +#include <bsp.h> +#include <rtems/libio.h> +#include <stdlib.h> + +#include "console.h" +#include "z85c30_p.h" + +/* + * Flow control is only supported when using interrupts + */ +console_flow z85c30_flow_RTSCTS = +{ + z85c30_negate_RTS, /* deviceStopRemoteTx */ + z85c30_assert_RTS /* deviceStartRemoteTx */ +}; + +console_flow z85c30_flow_DTRCTS = +{ + z85c30_negate_DTR, /* deviceStopRemoteTx */ + z85c30_assert_DTR /* deviceStartRemoteTx */ +}; + +/* + * Exported driver function table + */ +console_fns z85c30_fns = +{ + z85c30_probe, /* deviceProbe */ + z85c30_open, /* deviceFirstOpen */ + z85c30_flush, /* deviceLastClose */ + NULL, /* deviceRead */ + z85c30_write_support_int, /* deviceWrite */ + z85c30_initialize_interrupts, /* deviceInitialize */ + z85c30_write_polled, /* deviceWritePolled */ + FALSE, /* deviceOutputUsesInterrupts */ +}; + +console_fns z85c30_fns_polled = +{ + z85c30_probe, /* deviceProbe */ + z85c30_open, /* deviceFirstOpen */ + z85c30_close, /* deviceLastClose */ + z85c30_inbyte_nonblocking_polled, /* deviceRead */ + z85c30_write_support_polled, /* deviceWrite */ + z85c30_init, /* deviceInitialize */ + z85c30_write_polled, /* deviceWritePolled */ + FALSE, /* deviceOutputUsesInterrupts */ +}; + +/* + * Read_85c30_register + * + * Read a Z85c30 register + */ +static unsigned8 Read_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +) +{ + unsigned8 ucData; + + outport_byte(ulCtrlPort, ucRegNum); + + inport_byte(ulCtrlPort, ucData); + + return ucData; +} + +/* + * Write_85c30_register + * + * Write a Z85c30 register + */ +static void Write_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +) +{ + if(ucRegNum!=SCC_WR0_SEL_WR0) + { + outport_byte(ulCtrlPort, ucRegNum); + } + outport_byte(ulCtrlPort, ucData); +} + +/* + * Read_85c30_data + * + * Read a Z85c30 data register + */ +static unsigned8 Read_85c30_data( + unsigned32 ulDataPort +) +{ + unsigned8 ucData; + + inport_byte(ulDataPort, ucData); + + return ucData; +} + +/* + * Write_85c30_data + * + * Write a Z85c30 data register + */ +static void Write_85c30_data( + unsigned32 ulDataPort, + unsigned8 ucData +) +{ + outport_byte(ulDataPort, ucData); +} + +/* + * z85c30_initialize_port + * + * initialize a z85c30 Port + */ +static void z85c30_initialize_port( + int minor +) +{ + unsigned32 ulCtrlPort; + unsigned32 ulBaudDivisor; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Using register 4 + * Set up the clock rate is 16 times the data + * rate, 8 bit sync char, 1 stop bit, no parity + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR4, + SCC_WR4_1_STOP | + SCC_WR4_16_CLOCK); + + /* + * Set up for 8 bits/character on receive with + * receiver disable via register 3 + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR3, + SCC_WR3_RX_8_BITS); + + /* + * Set up for 8 bits/character on transmit + * with transmitter disable via register 5 + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR5, + SCC_WR5_TX_8_BITS); + + /* + * Clear misc control bits + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR10, + 0x00); + + /* + * Setup the source of the receive and xmit + * clock as BRG output and the transmit clock + * as the output source for TRxC pin via register 11 + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR11, + SCC_WR11_OUT_BR_GEN | + SCC_WR11_TRXC_OI | + SCC_WR11_TX_BR_GEN | + SCC_WR11_RX_BR_GEN); + + ulBaudDivisor=Z85C30_Baud( + (unsigned32)Console_Port_Tbl[minor].pDeviceParams); + /* + * Setup the lower 8 bits time constants=1E. + * If the time constans=1E, then the desire + * baud rate will be equilvalent to 9600, via register 12. + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR12, + ulBaudDivisor&0xff); + + /* + * using register 13 + * Setup the upper 8 bits time constant + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR13, + (ulBaudDivisor>>8)&0xff); + + /* + * Enable the baud rate generator enable with clock from the + * SCC's PCLK input via register 14. + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR14, + SCC_WR14_BR_EN | + SCC_WR14_BR_SRC | + SCC_WR14_NULL); + + /* + * We are only interested in CTS state changes + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR15, + SCC_WR15_CTS_IE); + + /* + * Reset errors + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_INT); + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_ERR_RST); + + /* + * Enable the receiver via register 3 + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR3, + SCC_WR3_RX_8_BITS | + SCC_WR3_RX_EN); + + /* + * Enable the transmitter pins set via register 5. + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR5, + SCC_WR5_TX_8_BITS | + SCC_WR5_TX_EN); + + /* + * Disable interrupts + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR1, + 0); + + /* + * Reset TX CRC + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_TX_CRC); + + /* + * Reset interrupts + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_INT); +} + +static int z85c30_open( + int major, + int minor, + void * arg +) +{ + /* + * Assert DTR + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_DTRCTS) + { + z85c30_assert_DTR(minor); + } + + return(RTEMS_SUCCESSFUL); +} + +static int z85c30_close( + int major, + int minor, + void * arg +) +{ + /* + * Negate DTR + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_DTRCTS) + { + z85c30_negate_DTR(minor); + } + + return(RTEMS_SUCCESSFUL); +} + +/* + * z85c30_write_polled + * + * This routine transmits a character using polling. + */ +static void z85c30_write_polled( + int minor, + char cChar +) +{ + volatile unsigned8 z85c30_status; + unsigned32 ulCtrlPort; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Wait for the Transmit buffer to indicate that it is empty. + */ + z85c30_status=Read_85c30_register(ulCtrlPort, + SCC_WR0_SEL_RD0); + while(!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) + { + /* + * Yield while we wait + */ + if(_System_state_Is_up(_System_state_Get())) + { + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + z85c30_status=Read_85c30_register(ulCtrlPort, + SCC_WR0_SEL_RD0); + } + + /* + * Write the character. + */ + Write_85c30_data(Console_Port_Tbl[minor].ulDataPort, cChar); +} + +/* + * Console Device Driver Entry Points + */ +static boolean z85c30_probe(int minor) +{ + /* + * If the configuration dependant probe has located the device then + * assume it is there + */ + return(TRUE); +} + +static void z85c30_init(int minor) +{ + unsigned32 ulCtrlPort; + unsigned8 dummy; + z85c30_context *pz85c30Context; + + pz85c30Context=(z85c30_context *)malloc(sizeof(z85c30_context)); + + Console_Port_Data[minor].pDeviceContext=(void *)pz85c30Context; + pz85c30Context->ucModemCtrl=SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + if(ulCtrlPort==Console_Port_Tbl[minor].ulCtrlPort2) + { + /* + * This is channel A + */ + /* + * Ensure port state machine is reset + */ + inport_byte(ulCtrlPort, dummy); + + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR9, + SCC_WR9_CH_A_RST); + } + else + { + /* + * This is channel B + */ + /* + * Ensure port state machine is reset + */ + inport_byte(ulCtrlPort, dummy); + + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR9, + SCC_WR9_CH_B_RST); + } + + z85c30_initialize_port(minor); +} + +/* + * These routines provide control of the RTS and DTR lines + */ +/* + * z85c30_assert_RTS + */ +static void z85c30_assert_RTS(int minor) +{ + unsigned32 Irql; + z85c30_context *pz85c30Context; + + pz85c30Context=(z85c30_context *) + Console_Port_Data[minor].pDeviceContext; + + /* + * Assert RTS + */ + rtems_interrupt_disable(Irql); + pz85c30Context->ucModemCtrl|=SCC_WR5_RTS; + Write_85c30_register( + Console_Port_Tbl[minor].ulCtrlPort1, + SCC_WR0_SEL_WR5, + pz85c30Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * z85c30_negate_RTS + */ +static void z85c30_negate_RTS(int minor) +{ + unsigned32 Irql; + z85c30_context *pz85c30Context; + + pz85c30Context=(z85c30_context *) + Console_Port_Data[minor].pDeviceContext; + + /* + * Negate RTS + */ + rtems_interrupt_disable(Irql); + pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS; + Write_85c30_register( + Console_Port_Tbl[minor].ulCtrlPort1, + SCC_WR0_SEL_WR5, + pz85c30Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * These flow control routines utilise a connection from the local DTR + * line to the remote CTS line + */ +/* + * z85c30_assert_DTR + */ +static void z85c30_assert_DTR(int minor) +{ + unsigned32 Irql; + z85c30_context *pz85c30Context; + + pz85c30Context=(z85c30_context *) + Console_Port_Data[minor].pDeviceContext; + + /* + * Assert DTR + */ + rtems_interrupt_disable(Irql); + pz85c30Context->ucModemCtrl|=SCC_WR5_DTR; + Write_85c30_register( + Console_Port_Tbl[minor].ulCtrlPort1, + SCC_WR0_SEL_WR5, + pz85c30Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * z85c30_negate_DTR + */ +static void z85c30_negate_DTR(int minor) +{ + unsigned32 Irql; + z85c30_context *pz85c30Context; + + pz85c30Context=(z85c30_context *) + Console_Port_Data[minor].pDeviceContext; + + /* + * Negate DTR + */ + rtems_interrupt_disable(Irql); + pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR; + Write_85c30_register( + Console_Port_Tbl[minor].ulCtrlPort1, + SCC_WR0_SEL_WR5, + pz85c30Context->ucModemCtrl); + rtems_interrupt_enable(Irql); +} + +/* + * z85c30_isr + * + * This routine is the console interrupt handler for COM3 and COM4 + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + */ + +static void z85c30_process( + int minor, + unsigned8 ucIntPend +) +{ + unsigned32 ulCtrlPort, ulDataPort; + volatile unsigned8 z85c30_status; + char cChar; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + ulDataPort=Console_Port_Tbl[minor].ulDataPort; + + /* + * Deal with any received characters + */ + while(ucIntPend&SCC_RR3_B_RX_IP) + { + z85c30_status=Read_85c30_register(ulCtrlPort, SCC_WR0_SEL_RD0); + if(!Z85C30_Status_Is_RX_character_available(z85c30_status)) + { + break; + } + + /* + * Return the character read. + */ + cChar=Read_85c30_data(ulDataPort); + + rtems_termios_enqueue_raw_characters( + Console_Port_Data[minor].termios_data, + &cChar, + 1); + } + + while(TRUE) + { + z85c30_status=Read_85c30_register(ulCtrlPort, SCC_WR0_SEL_RD0); + if(!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) + { + /* + * We'll get another interrupt when + * the transmitter holding reg. becomes + * free again and we are clear to send + */ + break; + } + + if(!Z85C30_Status_Is_CTS_asserted(z85c30_status)) + { + /* + * We can't transmit yet + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_TX_INT); + /* + * The next state change of CTS will wake us up + */ + break; + } + + if(Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) + { + Console_Port_Data[minor].bActive=FALSE; + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_RTSCTS) + { + z85c30_negate_RTS(minor); + } + /* + * There is no data to transmit + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_TX_INT); + break; + } + + Ring_buffer_Remove_character( + &Console_Port_Data[minor].TxBuffer, + cChar); + /* + * transmit character + */ + Write_85c30_data(ulDataPort, cChar); + + /* + * Interrupt once FIFO has room + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_TX_INT); + break; + } + + if(ucIntPend&SCC_RR3_B_EXT_IP) + { + /* + * Clear the external status interrupt + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_INT); + z85c30_status=Read_85c30_register(ulCtrlPort, SCC_WR0_SEL_RD0); + } + + /* + * Reset interrupts + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_HI_IUS); +} + +static rtems_isr z85c30_isr( + rtems_vector_number vector +) +{ + int minor; + unsigned32 ulCtrlPort; + volatile unsigned8 ucIntPend; + volatile unsigned8 ucIntPendPort; + + for(minor=0;minor<Console_Port_Count;minor++) + { + if(vector==Console_Port_Tbl[minor].ulIntVector) + { + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort2; + do + { + ucIntPend=Read_85c30_register(ulCtrlPort, + SCC_WR0_SEL_RD3); + + /* + * If this is channel A select channel A status + */ + if(ulCtrlPort== + Console_Port_Tbl[minor].ulCtrlPort1) + { + ucIntPendPort=ucIntPend>>3; + ucIntPendPort=ucIntPendPort&=7; + } + else + { + ucIntPendPort=ucIntPend&=7; + } + + if(ucIntPendPort) + { + z85c30_process(minor, ucIntPendPort); + } + } while(ucIntPendPort); + } + } +} + +/* + * z85c30_flush + */ +static int z85c30_flush(int major, int minor, void *arg) +{ + while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) + { + /* + * Yield while we wait + */ + if(_System_state_Is_up(_System_state_Get())) + { + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + } + + z85c30_close(major, minor, arg); + + return(RTEMS_SUCCESSFUL); +} + +/* + * z85c30_initialize_interrupts + * + * This routine initializes the console's receive and transmit + * ring buffers and loads the appropriate vectors to handle the interrupts. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +static void z85c30_enable_interrupts( + int minor +) +{ + unsigned32 ulCtrlPort; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * Enable interrupts + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR1, + SCC_WR1_EXT_INT_EN | + SCC_WR1_TX_INT_EN | + SCC_WR1_INT_ALL_RX); + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR2, + 0); + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR9, + SCC_WR9_MIE); + + /* + * Reset interrupts + */ + Write_85c30_register(ulCtrlPort, + SCC_WR0_SEL_WR0, + SCC_WR0_RST_INT); +} + +static void z85c30_initialize_interrupts( + int minor +) +{ + z85c30_init(minor); + + Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer); + + Console_Port_Data[minor].bActive=FALSE; + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_RTSCTS) + { + z85c30_negate_RTS(minor); + } + + if(Console_Port_Tbl[minor].ulCtrlPort1== + Console_Port_Tbl[minor].ulCtrlPort2) + { + /* + * Only do this for Channel A + */ + set_vector(z85c30_isr, + Console_Port_Tbl[minor].ulIntVector, + 1); + } + + z85c30_enable_interrupts(minor); +} + +/* + * z85c30_write_support_int + * + * Console Termios output entry point. + * + */ +static int z85c30_write_support_int( + int minor, + const char *buf, + int len) +{ + int i; + unsigned32 Irql; + + for(i=0; i<len;) + { + if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) + { + if(!Console_Port_Data[minor].bActive) + { + /* + * Wake up the device + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_RTSCTS) + { + z85c30_assert_RTS(minor); + } + rtems_interrupt_disable(Irql); + Console_Port_Data[minor].bActive=TRUE; + z85c30_process(minor, SCC_RR3_B_TX_IP); + rtems_interrupt_enable(Irql); + } + else + { + /* + * Yield while we await an interrupt + */ + rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); + } + + /* + * Wait for ring buffer to empty + */ + continue; + } + else + { + Ring_buffer_Add_character( + &Console_Port_Data[minor].TxBuffer, + buf[i]); + i++; + } + } + + /* + * Ensure that characters are on the way + */ + if(!Console_Port_Data[minor].bActive) + { + /* + * Wake up the device + */ + if(Console_Port_Tbl[minor].pDeviceFlow + !=&z85c30_flow_RTSCTS) + { + z85c30_assert_RTS(minor); + } + rtems_interrupt_disable(Irql); + Console_Port_Data[minor].bActive=TRUE; + z85c30_process(minor, SCC_RR3_B_TX_IP); + rtems_interrupt_enable(Irql); + } + + return (len); +} + +/* + * z85c30_inbyte_nonblocking_polled + * + * This routine polls for a character. + */ +static int z85c30_inbyte_nonblocking_polled( + int minor +) +{ + volatile unsigned8 z85c30_status; + unsigned32 ulCtrlPort; + + ulCtrlPort=Console_Port_Tbl[minor].ulCtrlPort1; + + /* + * return -1 if a character is not available. + */ + z85c30_status=Read_85c30_register(ulCtrlPort, + SCC_WR0_SEL_RD0); + if(!Z85C30_Status_Is_RX_character_available(z85c30_status)) + { + return -1; + } + + /* + * Return the character read. + */ + return Read_85c30_data(Console_Port_Tbl[minor].ulDataPort); +} + +/* + * z85c30_write_support_polled + * + * Console Termios output entry point. + * + */ +static int z85c30_write_support_polled( + int minor, + const char *buf, + int len) +{ + int nwrite=0; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) + { + /* + * transmit character + */ + z85c30_write_polled(minor, *buf++); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.h new file mode 100644 index 0000000000..df05316347 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30.h @@ -0,0 +1,52 @@ +/* z85c30.h + * + * This include file contains all console driver definations for the z85c30 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: + */ + +#ifndef __Z85C30_H +#define __Z85C30_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Driver function table + */ +extern console_fns z85c30_fns; +extern console_fns z85c30_fns_polled; + +/* + * Flow control function tables + */ +extern console_flow z85c30_flow_RTSCTS; +extern console_flow z85c30_flow_DTRCTS; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30_p.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30_p.h new file mode 100644 index 0000000000..985c3b202b --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30_p.h @@ -0,0 +1,385 @@ +/* z85c30_p.h + * + * This include file contains all private driver definations for the z85c30 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id: + */ + +#ifndef __Z85C30_P_H +#define __Z85C30_P_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* bit values for write register 0 */ +/* command register */ + +#define SCC_WR0_SEL_WR0 0x00 +#define SCC_WR0_SEL_WR1 0x01 +#define SCC_WR0_SEL_WR2 0x02 +#define SCC_WR0_SEL_WR3 0x03 +#define SCC_WR0_SEL_WR4 0x04 +#define SCC_WR0_SEL_WR5 0x05 +#define SCC_WR0_SEL_WR6 0x06 +#define SCC_WR0_SEL_WR7 0x07 +#define SCC_WR0_SEL_WR8 0x08 +#define SCC_WR0_SEL_WR9 0x09 +#define SCC_WR0_SEL_WR10 0x0a +#define SCC_WR0_SEL_WR11 0x0b +#define SCC_WR0_SEL_WR12 0x0c +#define SCC_WR0_SEL_WR13 0x0d +#define SCC_WR0_SEL_WR14 0x0e +#define SCC_WR0_SEL_WR15 0x0f +#define SCC_WR0_SEL_RD0 0x00 +#define SCC_WR0_SEL_RD1 0x01 +#define SCC_WR0_SEL_RD2 0x02 +#define SCC_WR0_SEL_RD3 0x03 +#define SCC_WR0_SEL_RD4 0x04 +#define SCC_WR0_SEL_RD5 0x05 +#define SCC_WR0_SEL_RD6 0x06 +#define SCC_WR0_SEL_RD7 0x07 +#define SCC_WR0_SEL_RD8 0x08 +#define SCC_WR0_SEL_RD9 0x09 +#define SCC_WR0_SEL_RD10 0x0a +#define SCC_WR0_SEL_RD11 0x0b +#define SCC_WR0_SEL_RD12 0x0c +#define SCC_WR0_SEL_RD13 0x0d +#define SCC_WR0_SEL_RD14 0x0e +#define SCC_WR0_SEL_RD15 0x0f +#define SCC_WR0_NULL_CODE 0x00 +#define SCC_WR0_RST_INT 0x10 +#define SCC_WR0_SEND_ABORT 0x18 +#define SCC_WR0_EN_INT_RX 0x20 +#define SCC_WR0_RST_TX_INT 0x28 +#define SCC_WR0_ERR_RST 0x30 +#define SCC_WR0_RST_HI_IUS 0x38 +#define SCC_WR0_RST_RX_CRC 0x40 +#define SCC_WR0_RST_TX_CRC 0x80 +#define SCC_WR0_RST_TX_UND 0xc0 + +/* write register 2 */ +/* interrupt vector */ + +/* bit values for write register 1 */ +/* tx/rx interrupt and data transfer mode definition */ + +#define SCC_WR1_EXT_INT_EN 0x01 +#define SCC_WR1_TX_INT_EN 0x02 +#define SCC_WR1_PARITY 0x04 +#define SCC_WR1_RX_INT_DIS 0x00 +#define SCC_WR1_RX_INT_FIR 0x08 +#define SCC_WR1_INT_ALL_RX 0x10 +#define SCC_WR1_RX_INT_SPE 0x18 +#define SCC_WR1_RDMA_RECTR 0x20 +#define SCC_WR1_RDMA_FUNC 0x40 +#define SCC_WR1_RDMA_EN 0x80 + +/* bit values for write register 3 */ +/* receive parameters and control */ + +#define SCC_WR3_RX_EN 0x01 +#define SCC_WR3_SYNC_CHAR 0x02 +#define SCC_WR3_ADR_SEARCH 0x04 +#define SCC_WR3_RX_CRC_EN 0x08 +#define SCC_WR3_ENTER_HUNT 0x10 +#define SCC_WR3_AUTO_EN 0x20 +#define SCC_WR3_RX_5_BITS 0x00 +#define SCC_WR3_RX_7_BITS 0x40 +#define SCC_WR3_RX_6_BITS 0x80 +#define SCC_WR3_RX_8_BITS 0xc0 + +/* bit values for write register 4 */ +/* tx/rx misc parameters and modes */ + +#define SCC_WR4_PAR_EN 0x01 +#define SCC_WR4_PAR_EVEN 0x02 +#define SCC_WR4_SYNC_EN 0x00 +#define SCC_WR4_1_STOP 0x04 +#define SCC_WR4_2_STOP 0x0c +#define SCC_WR4_8_SYNC 0x00 +#define SCC_WR4_16_SYNC 0x10 +#define SCC_WR4_SDLC 0x20 +#define SCC_WR4_EXT_SYNC 0x30 +#define SCC_WR4_1_CLOCK 0x00 +#define SCC_WR4_16_CLOCK 0x40 +#define SCC_WR4_32_CLOCK 0x80 +#define SCC_WR4_64_CLOCK 0xc0 + +/* bit values for write register 5 */ +/* transmit parameter and controls */ + +#define SCC_WR5_TX_CRC_EN 0x01 +#define SCC_WR5_RTS 0x02 +#define SCC_WR5_SDLC 0x04 +#define SCC_WR5_TX_EN 0x08 +#define SCC_WR5_SEND_BRK 0x10 + +#define SCC_WR5_TX_5_BITS 0x00 +#define SCC_WR5_TX_7_BITS 0x20 +#define SCC_WR5_TX_6_BITS 0x40 +#define SCC_WR5_TX_8_BITS 0x60 +#define SCC_WR5_DTR 0x80 + +/* write register 6 */ +/* sync chars or sdlc address field */ + +/* write register 7 */ +/* sync char or sdlc flag */ + +/* write register 8 */ +/* transmit buffer */ + +/* bit values for write register 9 */ +/* master interrupt control */ + +#define SCC_WR9_VIS 0x01 +#define SCC_WR9_NV 0x02 +#define SCC_WR9_DLC 0x04 +#define SCC_WR9_MIE 0x08 +#define SCC_WR9_STATUS_HI 0x10 +#define SCC_WR9_NO_RST 0x00 +#define SCC_WR9_CH_B_RST 0x40 +#define SCC_WR9_CH_A_RST 0x80 +#define SCC_WR9_HDWR_RST 0xc0 + +/* bit values for write register 10 */ +/* misc tx/rx control bits */ + +#define SCC_WR10_6_BIT_SYNC 0x01 +#define SCC_WR10_LOOP_MODE 0x02 +#define SCC_WR10_ABORT_UND 0x04 +#define SCC_WR10_MARK_IDLE 0x08 +#define SCC_WR10_ACT_POLL 0x10 +#define SCC_WR10_NRZ 0x00 +#define SCC_WR10_NRZI 0x20 +#define SCC_WR10_FM1 0x40 +#define SCC_WR10_FM0 0x60 +#define SCC_WR10_CRC_PRESET 0x80 + +/* bit values for write register 11 */ +/* clock mode control */ + +#define SCC_WR11_OUT_XTAL 0x00 +#define SCC_WR11_OUT_TX_CLK 0x01 +#define SCC_WR11_OUT_BR_GEN 0x02 +#define SCC_WR11_OUT_DPLL 0x03 +#define SCC_WR11_TRXC_OI 0x04 +#define SCC_WR11_TX_RTXC 0x00 +#define SCC_WR11_TX_TRXC 0x08 +#define SCC_WR11_TX_BR_GEN 0x10 +#define SCC_WR11_TX_DPLL 0x18 +#define SCC_WR11_RX_RTXC 0x00 +#define SCC_WR11_RX_TRXC 0x20 +#define SCC_WR11_RX_BR_GEN 0x40 +#define SCC_WR11_RX_DPLL 0x60 +#define SCC_WR11_RTXC_XTAL 0x80 + +/* write register 12 */ +/* lower byte of baud rate generator time constant */ + +/* write register 13 */ +/* upper byte of baud rate generator time constant */ + +/* bit values for write register 14 */ +/* misc control bits */ + +#define SCC_WR14_BR_EN 0x01 +#define SCC_WR14_BR_SRC 0x02 +#define SCC_WR14_DTR_FUNC 0x04 +#define SCC_WR14_AUTO_ECHO 0x08 +#define SCC_WR14_LCL_LOOP 0x10 +#define SCC_WR14_NULL 0x00 +#define SCC_WR14_SEARCH 0x20 +#define SCC_WR14_RST_CLK 0x40 +#define SCC_WR14_DIS_DPLL 0x60 +#define SCC_WR14_SRC_BR 0x80 +#define SCC_WR14_SRC_RTXC 0xa0 +#define SCC_WR14_FM_MODE 0xc0 +#define SCC_WR14_NRZI 0xe0 + +/* bit values for write register 15 */ +/* external/status interrupt control */ + +#define SCC_WR15_ZERO_CNT 0x02 +#define SCC_WR15_CD_IE 0x08 +#define SCC_WR15_SYNC_IE 0x10 +#define SCC_WR15_CTS_IE 0x20 +#define SCC_WR15_TX_UND_IE 0x40 +#define SCC_WR15_BREAK_IE 0x80 + +/* bit values for read register 0 */ +/* tx/rx buffer status and external status */ + +#define SCC_RR0_RX_AVAIL 0x01 +#define SCC_RR0_ZERO_CNT 0x02 +#define SCC_RR0_TX_EMPTY 0x04 +#define SCC_RR0_CD 0x08 +#define SCC_RR0_SYNC 0x10 +#define SCC_RR0_CTS 0x20 +#define SCC_RR0_TX_UND 0x40 +#define SCC_RR0_BREAK 0x80 + +/* bit values for read register 1 */ + +#define SCC_RR1_ALL_SENT 0x01 +#define SCC_RR1_RES_CD_2 0x02 +#define SCC_RR1_RES_CD_1 0x01 +#define SCC_RR1_RES_CD_0 0x08 +#define SCC_RR1_PAR_ERR 0x10 +#define SCC_RR1_RX_OV_ERR 0x20 +#define SCC_RR1_CRC_ERR 0x40 +#define SCC_RR1_END_FRAME 0x80 + +/* read register 2 */ +/* interrupt vector */ + +/* bit values for read register 3 */ +/* interrupt pending register */ + +#define SCC_RR3_B_EXT_IP 0x01 +#define SCC_RR3_B_TX_IP 0x02 +#define SCC_RR3_B_RX_IP 0x04 +#define SCC_RR3_A_EXT_IP 0x08 +#define SCC_RR3_A_TX_IP 0x10 +#define SCC_RR3_A_RX_IP 0x20 + +/* read register 8 */ +/* receive data register */ + +/* bit values for read register 10 */ +/* misc status bits */ + +#define SCC_RR10_ON_LOOP 0x02 +#define SCC_RR10_LOOP_SEND 0x10 +#define SCC_RR10_2_CLK_MIS 0x40 +#define SCC_RR10_1_CLK_MIS 0x80 + +/* read register 12 */ +/* lower byte of time constant */ + +/* read register 13 */ +/* upper byte of time constant */ + +/* bit values for read register 15 */ +/* external/status ie bits */ + +#define SCC_RR15_ZERO_CNT 0x02 +#define SCC_RR15_CD_IE 0x08 +#define SCC_RR15_SYNC_IE 0x10 +#define SCC_RR15_CTS_IE 0x20 +#define SCC_RR15_TX_UND_IE 0x40 +#define SCC_RR15_BREAK_IE 0x80 + +typedef struct _z85c30_context +{ + unsigned8 ucModemCtrl; +} z85c30_context; + +/* + * The following macro calculates the Baud constant. For the Z85C30 chip. + * + * Note: baud constant = ((clock frequency / Clock_X) / (2 * Baud Rate)) - 2 + * eg ((10,000,000 / 16) / (2 * Baud Rate)) - 2 + */ +#define Z85C30_Baud( _baud_rate ) \ + ( (Z85C30_CLOCK /( 16 * 2 * _baud_rate)) - 2) + +#define Z85C30_Status_Is_RX_character_available(_status) \ + ((_status) & SCC_RR0_RX_AVAIL) + +#define Z85C30_Status_Is_TX_buffer_empty(_status) \ + ((_status) & SCC_RR0_TX_EMPTY) + +#define Z85C30_Status_Is_CTS_asserted(_status) \ + ((_status) & SCC_RR0_CTS) + +#define Z85C30_Status_Is_break_abort(_status) \ + ((_status) & SCC_RR0_BREAK) + +/* + * Private routines + */ +static boolean z85c30_probe(int minor); + +static void z85c30_init(int minor); + +static int z85c30_open( + int major, + int minor, + void * arg +); + +static int z85c30_close( + int major, + int minor, + void * arg +); + +static void z85c30_write_polled( + int minor, + char cChar +); + +static void z85c30_assert_RTS( + int minor +); + +static void z85c30_negate_RTS( + int minor +); + +static void z85c30_assert_DTR( + int minor +); + +static void z85c30_negate_DTR( + int minor +); + +static void z85c30_initialize_interrupts(int minor); + +static int z85c30_flush(int major, int minor, void *arg); + +static int z85c30_write_support_int( + int minor, + const char *buf, + int len +); + +static int z85c30_write_support_polled( + int minor, + const char *buf, + int len +); + +static int z85c30_inbyte_nonblocking_polled( + int minor +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.c new file mode 100644 index 0000000000..3a1a98c720 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.c @@ -0,0 +1,96 @@ +/* + * This file contains the console driver chip level routines for the + * z85c30 chip. + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> + +/* + * Read_85c30_register + * + * Read a Z85c30 register + */ + +unsigned8 Read_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +) +{ + unsigned8 ucData; + + outport_byte(ulCtrlPort, ucRegNum); + inport_byte(ulCtrlPort, ucData); + return ucData; +} + +/* + * Write_85c30_register + * + * Write a Z85c30 register + */ + +void Write_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +) +{ + if(ucRegNum) { + outport_byte(ulCtrlPort, ucRegNum); + } + outport_byte(ulCtrlPort, ucData); +} + +/* + * Read_85c30_data + * + * Read a Z85c30 data register + */ + +unsigned8 Read_85c30_data( + unsigned32 ulDataPort +) +{ + unsigned8 ucData; + + inport_byte(ulDataPort, ucData); + return ucData; +} + +/* + * Write_85c30_data + * + * Write a Z85c30 data register + */ + +void Write_85c30_data( + unsigned32 ulDataPort, + unsigned8 ucData +) +{ + outport_byte(ulDataPort, ucData); +} diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.h b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.h new file mode 100644 index 0000000000..3dfb96e048 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ppcn_60x/console/z85c30cfg.h @@ -0,0 +1,64 @@ +/* z85c30cfg.h + * + * This include file contains all console driver definations for the z85c30 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef __Z85C30_CONFIG_H +#define __Z85C30_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Board specific register access routines + */ + +unsigned8 Read_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +); + +void Write_85c30_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +); + +unsigned8 Read_85c30_data( + unsigned32 ulDataPort +); + +void Write_85c30_data( + unsigned32 ulDataPort, + unsigned8 ucData +); + +#ifdef __cplusplus +} +#endif + +#endif |