Mercurial > ecos
diff packages/hal/powerpc/cogent/current/src/hal_diag.c @ 0:3111d98ba7b3 ecos-v1_1-release
Initial commit of eCos version 1.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 11:16:07 +0000 |
| parents | |
| children | 443894e2e912 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/hal/powerpc/cogent/current/src/hal_diag.c @@ -0,0 +1,464 @@ +//============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Cygnus eCos Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://sourceware.cygnus.com/ecos +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Cygnus Operating System, released +// September 30, 1998. +// +// The Initial Developer of the Original Code is Cygnus. Portions created +// by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, jskov +// Contributors: nickg +// Date: 1998-03-02 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> + +#include <cyg/infra/cyg_type.h> // base types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_diag.h> + +#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) +#include <cyg/hal/hal_stub.h> // __output_gdb_string +#endif + +#include <cyg/hal/ppc_regs.h> + + +//----------------------------------------------------------------------------- +// Select default diag channel to use + +//#define CYG_KERNEL_DIAG_ROMART +//#define CYG_KERNEL_DIAG_LCD +//#define CYG_KERNEL_DIAG_SERIAL + +#if !defined(CYG_KERNEL_DIAG_SERIAL) && \ + !defined(CYG_KERNEL_DIAG_LCD) && \ + !defined(CYG_KERNEL_DIAG_ROMART) + +#define CYG_KERNEL_DIAG_SERIAL + +#endif + +//----------------------------------------------------------------------------- +// Cogent board specific 16550 code. + +#if defined(CYG_KERNEL_DIAG_SERIAL) + +//----------------------------------------------------------------------------- +// From serial_16550.h +#define CYG_DEVICE_SERIAL_RS232_T1_VALUE_B38400 0x00 +#define CYG_DEVICE_SERIAL_RS232_T2_VALUE_B38400 0x06 + +// FIXME: This is the base address of the B-channel on the PowerPC +// Cogent board. +#define CYG_DEVICE_SERIAL_RS232_16550_BASE 0xe900007 + + +// Define the serial registers. +#define CYG_DEVICE_SERIAL_RS232_16550_RBR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) + // receiver buffer register, read, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_THR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) + // transmitter holding register, write, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_DLL \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x00) + // divisor latch (LS), read/write, dlab = 1 +#define CYG_DEVICE_SERIAL_RS232_16550_IER \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x08) + // interrupt enable register, read/write, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_DLM \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x08) + // divisor latch (MS), read/write, dlab = 1 +#define CYG_DEVICE_SERIAL_RS232_16550_IIR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) + // interrupt identification register, read, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_FCR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) + // fifo control register, write, dlab = 0 +#define CYG_DEVICE_SERIAL_RS232_16550_AFR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x10) + // alternate function register, read/write, dlab = 1 +#define CYG_DEVICE_SERIAL_RS232_16550_LCR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x18) + // line control register, read/write +#define CYG_DEVICE_SERIAL_RS232_16550_MCR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x20) + // modem control register, read/write +#define CYG_DEVICE_SERIAL_RS232_16550_LSR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x28) + // line status register, read +#define CYG_DEVICE_SERIAL_RS232_16550_MSR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x30) + // modem status register, read +#define CYG_DEVICE_SERIAL_RS232_16550_SCR \ + ((volatile cyg_uint8 *) CYG_DEVICE_SERIAL_RS232_16550_BASE + 0x38) + // scratch pad register + +// FIXME: Naming convention? +// The interrupt enable register bits. +#define SIO_IER_ERDAI 0x01 // enable received data available irq +#define SIO_IER_ETHREI 0x02 // enable THR empty interrupt +#define SIO_IER_ELSI 0x04 // enable receiver line status irq +#define SIO_IER_EMSI 0x08 // enable modem status interrupt + +// The interrupt identification register bits. +#define SIO_IIR_IP 0x01 // 0 if interrupt pending +#define SIO_IIR_ID_MASK 0x0e // mask for interrupt ID bits + +// The line status register bits. +#define SIO_LSR_DR 0x01 // data ready +#define SIO_LSR_OE 0x02 // overrun error +#define SIO_LSR_PE 0x04 // parity error +#define SIO_LSR_FE 0x08 // framing error +#define SIO_LSR_BI 0x10 // break interrupt +#define SIO_LSR_THRE 0x20 // transmitter holding register empty +#define SIO_LSR_TEMT 0x40 // transmitter register empty +#define SIO_LSR_ERR 0x80 // any error condition + +// The modem status register bits. +#define SIO_MSR_DCTS 0x01 // delta clear to send +#define SIO_MSR_DDSR 0x02 // delta data set ready +#define SIO_MSR_TERI 0x04 // trailing edge ring indicator +#define SIO_MSR_DDCD 0x08 // delta data carrier detect +#define SIO_MSR_CTS 0x10 // clear to send +#define SIO_MSR_DSR 0x20 // data set ready +#define SIO_MSR_RI 0x40 // ring indicator +#define SIO_MSR_DCD 0x80 // data carrier detect + +// The line control register bits. +#define SIO_LCR_WLS0 0x01 // word length select bit 0 +#define SIO_LCR_WLS1 0x02 // word length select bit 1 +#define SIO_LCR_STB 0x04 // number of stop bits +#define SIO_LCR_PEN 0x08 // parity enable +#define SIO_LCR_EPS 0x10 // even parity select +#define SIO_LCR_SP 0x20 // stick parity +#define SIO_LCR_SB 0x40 // set break +#define SIO_LCR_DLAB 0x80 // divisor latch access bit + +void hal_diag_init(void) +{ +#if !defined(CYGDBG_KERNEL_DEBUG_GDB_INCLUDE_STUBS) + cyg_uint8 lcr; + + // 8-1-no parity. + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, + SIO_LCR_WLS0 | SIO_LCR_WLS1); + + // Set speed to 38400. + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); + lcr |= SIO_LCR_DLAB; + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_DLL, + CYG_DEVICE_SERIAL_RS232_T2_VALUE_B38400); + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_DLM, + CYG_DEVICE_SERIAL_RS232_T1_VALUE_B38400); + lcr &= ~SIO_LCR_DLAB; + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LCR, lcr); +#endif +} + +void hal_diag_write_char(char c) +{ +#if !defined(CYGDBG_KERNEL_DEBUG_GDB_INCLUDE_STUBS) + cyg_uint8 lsr; + + do { + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); + } while ((lsr & SIO_LSR_THRE) == 0); + + HAL_WRITE_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_THR, c); +#else + __output_gdb_string (&c, 1); +#endif +} + +void hal_diag_read_char(char *c) +{ + cyg_uint8 lsr; + + do { + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_LSR, lsr); + } while ((lsr & SIO_LSR_DR) == 0); + + HAL_READ_UINT8 (CYG_DEVICE_SERIAL_RS232_16550_RBR, *c); +} +#endif + +//----------------------------------------------------------------------------- +// Cogent board specific LCD code + +#if defined(CYG_KERNEL_DIAG_LCD) + +// FEMA 162B 16 character x 2 line LCD +// base addresses and register offsets * + +#define MBD_BASE 0 + +#define LCD_BASE (MBD_BASE + 0xEB00007) + +#define LCD_DATA (LCD_BASE + 0x00) // read/write lcd data +#define LCD_STAT (LCD_BASE + 0x08) // read lcd busy status +#define LCD_CMD (LCD_BASE + 0x08) // write lcd command + +// status register bit definitions +#define LCD_STAT_BUSY 0x80 // 1 = display busy +#define LCD_STAT_ADD 0x7F // bits 0-6 return current display address + +// command register definitions +#define LCD_CMD_RST 0x01 // clear entire display and reset display address +#define LCD_CMD_HOME 0x02 // reset display address and reset any shifting +#define LCD_CMD_ECL 0x04 // move cursor left one position on next data write +#define LCD_CMD_ESL 0x05 // shift display left one position on next data write +#define LCD_CMD_ECR 0x06 // move cursor right one position on next data write +#define LCD_CMD_ESR 0x07 // shift display right one position on next data write +#define LCD_CMD_DOFF 0x08 // display off, cursor off, blinking off +#define LCD_CMD_BL 0x09 // blink character at current cursor position +#define LCD_CMD_CUR 0x0A // enable cursor on +#define LCD_CMD_DON 0x0C // turn display on +#define LCD_CMD_CL 0x10 // move cursor left one position +#define LCD_CMD_SL 0x14 // shift display left one position +#define LCD_CMD_CR 0x18 // move cursor right one position +#define LCD_CMD_SR 0x1C // shift display right one position +#define LCD_CMD_MODE 0x38 // sets 8 bits, 2 lines, 5x7 characters +#define LCD_CMD_ACG 0x40 // bits 0-5 sets the character generator address +#define LCD_CMD_ADD 0x80 // bits 0-6 sets the display data address to line 1 + + +// LCD status values +#define LCD_OK 0x00 +#define LCD_ERR 0x01 + +#define LCD_LINE0 0x00 +#define LCD_LINE1 0x40 + +#define LCD_LINE_LENGTH 16 + +static char lcd_line0[LCD_LINE_LENGTH+1]; +static char lcd_line1[LCD_LINE_LENGTH+1]; +static char *lcd_line[2] = { lcd_line0, lcd_line1 }; +static int lcd_curline = 0; +static int lcd_linepos = 0; + + +static void lcd_dis(int add, char *string); + +void hal_diag_init() +{ + cyg_uint8 stat; + int i; + + // wait for not busy + do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + + // configure the lcd for 8 bits/char, 2 lines + // and 5x7 dot matrix + HAL_WRITE_UINT8 (LCD_CMD, LCD_CMD_MODE); + + // wait for not busy + do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + + // turn the LCD display on + HAL_WRITE_UINT8 (LCD_CMD, LCD_CMD_DON); + + lcd_curline = 0; + lcd_linepos = 0; + + for( i = 0; i < LCD_LINE_LENGTH; i++ ) + lcd_line[0][i] = lcd_line[1][i] = ' '; + + lcd_line[0][LCD_LINE_LENGTH] = lcd_line[1][LCD_LINE_LENGTH] = 0; + + lcd_dis( LCD_LINE0, lcd_line[0] ); + lcd_dis( LCD_LINE1, lcd_line[1] ); + + +#if defined(CYG_HAL_ROM_MONITOR) + // It's handy to have the LCD initialized at reset when using it + for debugging output. + { + extern void diag_write_string (const char*); + diag_write_string ("eCos ROM " __TIME__ "\n"); + diag_write_string (__DATE__ "\n"); + } +#endif +} + +// this routine writes the string to the LCD +// display after setting the address to add +static void lcd_dis(int add, char *string) +{ + cyg_uint8 stat; + int i; + + // write the string out to the display stopping when we reach 0 + for (i = 0; *string != '\0'; i++) + { + // wait for not busy + do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + + // write the address + HAL_WRITE_UINT8 (LCD_CMD, (LCD_CMD_ADD + add)); + add++; + + // wait for not busy + do { HAL_READ_UINT8 (LCD_STAT, stat); } while (stat & LCD_STAT_BUSY); + + // write the data + HAL_WRITE_UINT8 (LCD_DATA, *string++); + } +} + +void hal_diag_write_char(char c) +{ + int i; + + // ignore CR + if( c == '\r' ) return; + + if( c == '\n' ) + { + lcd_dis( LCD_LINE0, &lcd_line[lcd_curline^1][0] ); + lcd_dis( LCD_LINE1, &lcd_line[lcd_curline][0] ); + + // Do a line feed + lcd_curline ^= 1; + lcd_linepos = 0; + + for( i = 0; i < LCD_LINE_LENGTH; i++ ) + lcd_line[lcd_curline][i] = ' '; + + return; + } + + // Truncate long lines + if( lcd_linepos >= LCD_LINE_LENGTH ) return; + + lcd_line[lcd_curline][lcd_linepos++] = c; +} + +char hal_diag_read_char(void) +{ + return 0; +} + +#endif + + +//---------------------------------------------------------------------------*/ +// PromICE AI interface + + +#if defined(CYG_KERNEL_DIAG_ROMART) + +#ifdef CYG_HAL_POWERPC_COGENT +#define PROMICE_AILOC 0xfff00020 +#endif + +// Add this to the LoadICE config file: ailoc 20 19200 +// FIXME: I couldn't get this to work. jskov + +#define PROMICE_BUS_SIZE 16 +#define PROMICE_BURST_SIZE 1 + +#if PROMICE_BUS_SIZE == 16 + +typedef volatile struct +{ + volatile cyg_uint16 zero; +// cyg_uint16 pad1[PROMICE_BURST_SIZE]; + volatile cyg_uint16 one; +// cyg_uint16 pad2[PROMICE_BURST_SIZE]; + volatile cyg_uint16 data; +// cyg_uint16 pad3[PROMICE_BURST_SIZE]; + volatile cyg_uint16 status; + +} AISTRUCT; + +#endif + +AISTRUCT *AI = (AISTRUCT *)PROMICE_AILOC; + +#define PROMICE_STATUS_TDA 0x01 +#define PROMICE_STATUS_HDA 0x02 +#define PROMICE_STATUS_OVR 0x04 + +void hal_diag_init() +{ + volatile cyg_uint8 junk; + + while( AI->status == 0xCC ) + continue; + + junk = AI->data; +} + +static void ai_write_char(cyg_uint8 data) +{ + volatile cyg_uint8 junk; + int i; + + // Wait for tda == 0 + while( (AI->status & PROMICE_STATUS_TDA) == PROMICE_STATUS_TDA ) + continue; + + // Send start bit + junk = AI->one; + + for( i = 0; i < 8; i++ ) + { + // send ls bit of data + if( (data & 1) == 1 ) + junk = AI->one; + else + junk = AI->zero; + + // shift down for next bit + data >>= 1; + } + + // Send stop bit + junk = AI->one; + + // all done +} + +void hal_diag_write_char(char c) +{ + ai_write_char((cyg_uint8)c); +} + +#endif + +//----------------------------------------------------------------------------- +// End of hal_diag.c
