OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/rtems/c/src/libchip
    from Rev 30 to Rev 173
    Reverse comparison

Rev 30 → Rev 173

/serial/mc68681_p.h
0,0 → 1,316
/*
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: mc68681_p.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef _MC68681_P_H_
#define _MC68681_P_H_
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* Define MC68681_STATIC to nothing while debugging so the entry points
* will show up in the symbol table.
*/
 
#define MC68681_STATIC
 
/* #define MC68681_STATIC static */
 
/*
* mc68681 register offsets Read/Write Addresses
*/
 
#define MC68681_MODE_REG_1A 0 /* MR1A-MR Prior to Read */
#define MC68681_MODE_REG_2A 0 /* MR2A-MR After Read */
 
#define MC68681_COUNT_MODE_CURRENT_MSB 6 /* CTU */
#define MC68681_COUNTER_TIMER_UPPER_REG 6 /* CTU */
#define MC68681_COUNT_MODE_CURRENT_LSB 7 /* CTL */
#define MC68681_COUNTER_TIMER_LOWER_REG 7 /* CTL */
#define MC68681_INTERRUPT_VECTOR_REG 12 /* IVR */
 
#define MC68681_MODE_REG_1B 8 /* MR1B-MR Prior to Read */
#define MC68681_MODE_REG_2B 8 /* MR2BA-MR After Read */
 
/*
* mc68681 register offsets Read Only Addresses
*/
 
#define MC68681_STATUS_REG_A 1 /* SRA */
#define MC68681_MASK_ISR_REG 2 /* MISR */
#define MC68681_RECEIVE_BUFFER_A 3 /* RHRA */
#define MC68681_INPUT_PORT_CHANGE_REG 4 /* IPCR */
#define MC68681_INTERRUPT_STATUS_REG 5 /* ISR */
#define MC68681_STATUS_REG_B 9 /* SRB */
#define MC68681_RECEIVE_BUFFER_B 11 /* RHRB */
#define MC68681_INPUT_PORT 13 /* IP */
#define MC68681_START_COUNT_CMD 14 /* SCC */
#define MC68681_STOP_COUNT_CMD 15 /* STC */
 
/*
* mc68681 register offsets Write Only Addresses
*/
 
#define MC68681_CLOCK_SELECT_REG_A 1 /* CSRA */
#define MC68681_COMMAND_REG_A 2 /* CRA */
#define MC68681_TRANSMIT_BUFFER_A 3 /* THRA */
#define MC68681_AUX_CTRL_REG 4 /* ACR */
#define MC68681_INTERRUPT_MASK_REG 5 /* IMR */
#define MC68681_CLOCK_SELECT_REG_B 9 /* CSRB */
#define MC68681_COMMAND_REG_B 10 /* CRB */
#define MC68681_TRANSMIT_BUFFER_B 11 /* THRB */
#define MC68681_OUTPUT_PORT_CONFIG_REG 13 /* OPCR */
#define MC68681_OUTPUT_PORT_SET_REG 14 /* SOPBC */
#define MC68681_OUTPUT_PORT_RESET_BITS 15 /* COPBC */
 
/*
* DUART Command Register Definitions:
*
* MC68681_COMMAND_REG_A,MC68681_COMMAND_REG_B
*/
 
#define MC68681_MODE_REG_ENABLE_RX 0x01
#define MC68681_MODE_REG_DISABLE_RX 0x02
#define MC68681_MODE_REG_ENABLE_TX 0x04
#define MC68681_MODE_REG_DISABLE_TX 0x08
#define MC68681_MODE_REG_RESET_MR_PTR 0x10
#define MC68681_MODE_REG_RESET_RX 0x20
#define MC68681_MODE_REG_RESET_TX 0x30
#define MC68681_MODE_REG_RESET_ERROR 0x40
#define MC68681_MODE_REG_RESET_BREAK 0x50
#define MC68681_MODE_REG_START_BREAK 0x60
#define MC68681_MODE_REG_STOP_BREAK 0x70
#define MC68681_MODE_REG_SET_RX_BRG 0x80
#define MC68681_MODE_REG_CLEAR_RX_BRG 0x90
#define MC68681_MODE_REG_SET_TX_BRG 0xa0
#define MC68681_MODE_REG_CLEAR_TX_BRG 0xb0
#define MC68681_MODE_REG_SET_STANDBY 0xc0
#define MC68681_MODE_REG_SET_ACTIVE 0xd0
 
/*
* Mode Register Definitions
*
* MC68681_MODE_REG_1A
* MC68681_MODE_REG_1B
*/
 
#define MC68681_5BIT_CHARS 0x00
#define MC68681_6BIT_CHARS 0x01
#define MC68681_7BIT_CHARS 0x02
#define MC68681_8BIT_CHARS 0x03
 
#define MC68681_ODD_PARITY 0x00
#define MC68681_EVEN_PARITY 0x04
 
#define MC68681_WITH_PARITY 0x00
#define MC68681_FORCE_PARITY 0x08
#define MC68681_NO_PARITY 0x10
#define MC68681_MULTI_DROP 0x18
 
#define MC68681_ERR_MODE_CHAR 0x00
#define MC68681_ERR_MODE_BLOCK 0x20
 
#define MC68681_RX_INTR_RX_READY 0x00
#define MC68681_RX_INTR_FFULL 0x40
 
#define MC68681_NO_RX_RTS_CTL 0x00
#define MC68681_RX_RTS_CTRL 0x80
 
/*
* Mode Register Definitions
*
* MC68681_MODE_REG_2A
* MC68681_MODE_REG_2B
*/
 
#define MC68681_STOP_BIT_LENGTH__563 0x00
#define MC68681_STOP_BIT_LENGTH__625 0x01
#define MC68681_STOP_BIT_LENGTH__688 0x02
#define MC68681_STOP_BIT_LENGTH__75 0x03
#define MC68681_STOP_BIT_LENGTH__813 0x04
#define MC68681_STOP_BIT_LENGTH__875 0x05
#define MC68681_STOP_BIT_LENGTH__938 0x06
#define MC68681_STOP_BIT_LENGTH_1 0x07
#define MC68681_STOP_BIT_LENGTH_1_563 0x08
#define MC68681_STOP_BIT_LENGTH_1_625 0x09
#define MC68681_STOP_BIT_LENGTH_1_688 0x0a
#define MC68681_STOP_BIT_LENGTH_1_75 0x0b
#define MC68681_STOP_BIT_LENGTH_1_813 0x0c
#define MC68681_STOP_BIT_LENGTH_1_875 0x0d
#define MC68681_STOP_BIT_LENGTH_1_938 0x0e
#define MC68681_STOP_BIT_LENGTH_2 0x0f
 
#define MC68681_CTS_ENABLE_TX 0x10
#define MC68681_TX_RTS_CTRL 0x20
 
#define MC68681_CHANNEL_MODE_NORMAL 0x00
#define MC68681_CHANNEL_MODE_ECHO 0x40
#define MC68681_CHANNEL_MODE_LOCAL_LOOP 0x80
#define MC68681_CHANNEL_MODE_REMOTE_LOOP 0xc0
 
/*
* Status Register Definitions
*
* MC68681_STATUS_REG_A, MC68681_STATUS_REG_B
*/
 
#define MC68681_RX_READY 0x01
#define MC68681_FFULL 0x02
#define MC68681_TX_READY 0x04
#define MC68681_TX_EMPTY 0x08
#define MC68681_OVERRUN_ERROR 0x10
#define MC68681_PARITY_ERROR 0x20
#define MC68681_FRAMING_ERROR 0x40
#define MC68681_RECEIVED_BREAK 0x80
 
#define MC68681_RX_ERRORS \
(MC68681_OVERRUN_ERROR|MC68681_PARITY_ERROR| \
MC68681_FRAMING_ERROR|MC68681_RECEIVED_BREAK)
 
/*
* Interupt Status Register Definitions.
*
* MC68681_INTERRUPT_STATUS_REG
*/
 
/*
* Interupt Mask Register Definitions
*
* MC68681_INTERRUPT_MASK_REG
*/
 
/* These are passed to mc68681_build_imr */
#define MC68681_IR_TX_READY 0x01
#define MC68681_IR_RX_READY 0x02
#define MC68681_IR_BREAK 0x04
#define MC68681_IMR_ENABLE_ALL 0x07
#define MC68681_IMR_DISABLE_ALL 0x00
#define MC68681_IMR_ENABLE_ALL_EXCEPT_TX 0x06
 
#define MC68681_IR_TX_READY_A 0x01
#define MC68681_IR_RX_READY_A 0x02
#define MC68681_IR_BREAK_A 0x04
#define MC68681_IR_COUNTER_READY 0x08
#define MC68681_IR_TX_READY_B 0x10
#define MC68681_IR_RX_READY_B 0x20
#define MC68681_IR_BREAK_B 0x40
#define MC68681_IR_INPUT_PORT_CHANGE 0x80
 
/*
* Status Register Definitions.
*
* MC68681_STATUS_REG_A,MC68681_STATUS_REG_B
*/
 
#define MC68681_STATUS_RXRDY 0x01
#define MC68681_STATUS_FFULL 0x02
#define MC68681_STATUS_TXRDY 0x04
#define MC68681_STATUS_TXEMT 0x08
#define MC68681_STATUS_OVERRUN_ERROR 0x10
#define MC68681_STATUS_PARITY_ERROR 0x20
#define MC68681_STATUS_FRAMING_ERROR 0x40
#define MC68681_STATUS_RECEIVED_BREAK 0x80
 
/*
* Definitions for the Interrupt Vector Register:
*
* MC68681_INTERRUPT_VECTOR_REG
*/
 
#define MC68681_INTERRUPT_VECTOR_INIT 0x0f
 
/*
* Definitions for the Auxiliary Control Register
*
* MC68681_AUX_CTRL_REG
*/
 
#define MC68681_AUX_BRG_SET1 0x00
#define MC68681_AUX_BRG_SET2 0x80
 
/*
* Per chip context control
*/
 
typedef struct _mc68681_context
{
int mate;
unsigned char imr;
} mc68681_context;
 
/*
* Driver functions
*/
MC68681_STATIC boolean mc68681_probe(int minor);
 
MC68681_STATIC int mc68681_set_attributes(
int minor,
const struct termios *t
);
 
MC68681_STATIC void mc68681_init(int minor);
 
MC68681_STATIC int mc68681_open(
int major,
int minor,
void * arg
);
 
MC68681_STATIC int mc68681_close(
int major,
int minor,
void * arg
);
 
MC68681_STATIC void mc68681_write_polled(
int minor,
char cChar
);
 
MC68681_STATIC void mc68681_initialize_interrupts(int minor);
 
MC68681_STATIC int mc68681_write_support_int(
int minor,
const char *buf,
int len
);
 
MC68681_STATIC int mc68681_write_support_polled(
int minor,
const char *buf,
int len
);
 
MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
int minor
);
 
MC68681_STATIC unsigned int mc68681_build_imr(
int minor,
int enable_flag
);
 
MC68681_STATIC void mc68681_process(
int minor
);
 
MC68681_STATIC void mc68681_enable_interrupts(
int minor,
int imr_mask
);
 
#ifdef __cplusplus
}
#endif
 
#endif /* _MC68681_P_H_ */
/serial/z85c30.h
0,0 → 1,78
/*
* This include file contains all console driver definitions for the
* Zilog 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;
 
/*
* Default register access routines
*/
 
unsigned8 z85c30_get_register( /* registers are byte-wide */
unsigned32 ulCtrlPort,
unsigned8 ucRegNum
);
 
void z85c30_set_register(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
);
 
unsigned8 z85c30_get_data(
unsigned32 ulDataPort
);
 
void z85c30_set_data(
unsigned32 ulDataPort,
unsigned8 ucData
);
 
#ifdef __cplusplus
}
#endif
 
#endif
/serial/mc68681_reg8.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 64-bit boundaries
*
* 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: mc68681_reg8.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _MC68681_MULTIPLIER 8
#define _MC68681_NAME(_X) _X##_8
#define _MC68681_TYPE unsigned8
 
#include "mc68681_reg.c"
 
/serial/STATUS
0,0 → 1,52
#
# $Id: STATUS,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
General
=======
 
+ Hardware flow control is not currently supported. Some of the chip
drivers (in particular the z8530) have support for hardware flow control
but this has not been tested in the libchip context. There will need
to be a way to totally disabled hardware flow control which is not
currently in this.
 
+ "ulClockSpeed" configuration item field to become a pointer to a table
of chip specific information. For example, the z8530 should specify
clock speed and clock divisor setting.
 
+ A termios structure should be included to specify the initial settings.
Right now all drivers default to 9600, 8N1.
+ Need to switch to passing pointers rather than a minor number to
functions which are strictly internal to each chip driver. This
should be a performance win.
 
+ Need a test which prompts you for termios settings and tests them. Until
this happens, testing for the variety of settings possible will be limited.
This test should be able to test any serial port while prompts come to the
console.
 
MC68681
=======
 
+ Works interrupt and polled.
 
+ Hardware flow control not included.
 
NS16650
=======
 
+ ns16550_set-attributes function is untested.
 
+ Hardware flow control included but is currently disabled in ISR.
 
Z85C30
======
 
+ Works polled and interrupt.
 
+ Hardware flow control included but is currently disabled in ISR.
 
+ Needs to support mode where more specific vectors are generated.
 
/serial/ns16550_p.h
0,0 → 1,239
/*
* 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: ns16550_p.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef _NS16550_P_H_
#define _NS16550_P_H_
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* Define NS16550_STATIC to nothing while debugging so the entry points
* will show up in the symbol table.
*/
 
#define NS16550_STATIC
 
/* #define NS16550_STATIC static */
 
/*
* 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 NS16550_RECEIVE_BUFFER 0
#define NS16550_INTERRUPT_ENABLE 1
#define NS16550_INTERRUPT_ID 2
#define NS16550_LINE_CONTROL 3
#define NS16550_MODEM_CONTROL 4
#define NS16550_LINE_STATUS 5
#define NS16550_MODEM_STATUS 6
#define NS16550_SCRATCH_PAD 7
 
/*
* 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 NS16550_TRANSMIT_BUFFER 0
#define NS16550_FIFO_CONTROL 2
 
/*
* 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 NS16550_ENABLE_ALL_INTR (SP_INT_RX_ENABLE | SP_INT_TX_ENABLE)
#define NS16550_DISABLE_ALL_INTR 0x00
#define NS16550_ENABLE_ALL_INTR_EXCEPT_TX (SP_INT_RX_ENABLE)
 
/*
* 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(_clock, _baud_rate) \
((((_clock) == 0) ? 115200 : (_clock))/(_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
*/
 
NS16550_STATIC boolean ns16550_probe(int minor);
 
NS16550_STATIC void ns16550_init(int minor);
 
NS16550_STATIC int ns16550_open(
int major,
int minor,
void * arg
);
 
NS16550_STATIC int ns16550_close(
int major,
int minor,
void * arg
);
 
NS16550_STATIC void ns16550_write_polled(
int minor,
char cChar
);
 
NS16550_STATIC int ns16550_assert_RTS(
int minor
);
 
NS16550_STATIC int ns16550_negate_RTS(
int minor
);
 
NS16550_STATIC int ns16550_assert_DTR(
int minor
);
 
NS16550_STATIC int ns16550_negate_DTR(
int minor
);
 
NS16550_STATIC void ns16550_initialize_interrupts(int minor);
 
NS16550_STATIC int ns16550_write_support_int(
int minor,
const char *buf,
int len
);
 
NS16550_STATIC int ns16550_write_support_polled(
int minor,
const char *buf,
int len
);
 
NS16550_STATIC int ns16550_inbyte_nonblocking_polled(
int minor
);
 
NS16550_STATIC void ns16550_enable_interrupts(
int minor,
int mask
);
 
NS16550_STATIC int ns16550_set_attributes(
int minor,
const struct termios *t
);
 
#ifdef __cplusplus
}
#endif
 
#endif /* _NS16550_P_H_ */
/serial/sersupp.h
0,0 → 1,22
/*
* $Id: sersupp.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __LIBCHIP_SERIAL_SUPPORT_h
#define __LIBCHIP_SERIAL_SUPPORT_h
 
int termios_baud_to_index(
int termios_baud
);
 
int termios_baud_to_number(
int termios_baud
);
 
boolean libchip_serial_default_probe(
int minor
);
 
 
#endif
/* end of include file */
/serial/README.z85c30
0,0 → 1,78
#
# $Id: README.z85c30,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
Configuration Table Use
=======================
 
sDeviceName
 
The name of this device.
 
deviceType
 
This field must be SERIAL_Z85C30.
 
pDeviceFns
 
The device interface control table. This may be:
+ z85c30_fns for interrupt driven IO
+ z85c30_fns_polled for polled IO
 
deviceProbe
 
This is the address of the routine which probes to see if the device
is present.
 
pDeviceFlow
 
This field is set to one of the following values:
+ NULL for no hardware flow control
+ z85c30_flow_RTSCTS for RTS/CTS based flow control
+ z85c30_flow_DTRCTS for DTR/CTS based flow control
 
ulMargin
 
This is currently unused.
 
ulHysteresis
 
This is currently unused.
 
pDeviceParams
 
This is set to the default settings.
 
ulCtrlPort1
 
This field is the address of the control register for this port.
 
ulCtrlPort2
 
This field is the address of the control register for chip.
 
ulDataPort
 
This field is the address of the data register for this port.
 
getRegister
setRegister
 
These follow standard conventions.
 
getData
setData
 
These follow standard conventions.
 
ulClock
 
This is the clock speed of the baud rate clock.
NULL, then the CSR/ACR/X bit mappings shown in the 68681 and 88681
manuals are used. Otherwise, the board specific baud rate mapping
is used.
 
ulIntVector
 
This is the interrupt vector number associated with this chip.
 
/serial/mc68681_baud.c
0,0 → 1,107
/*
* MC68681 Default Baud Rate Table
*
* $Id: mc68681_baud.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <libchip/serial.h>
#include <libchip/mc68681.h>
 
/* major index of 0 : ACR[7] = 0, X = 0 -- 68c681 only has these */
/* major index of 1 : ACR[7] = 1, X = 0 -- 68c681 only has these */
/* major index of 2 : ACR[7] = 0, X = 1 */
/* major index of 3 : ACR[7] = 1, X = 1 */
 
/* mc68681_baud_table_t mc68681_baud_rate_table[4] = { */
mc68681_baud_t mc68681_baud_rate_table[4][RTEMS_TERMIOS_NUMBER_BAUD_RATES] = {
{ /* ACR[7] = 0, X = 0 */
MC68681_BAUD_NOT_VALID, /* B0 */
0x00, /* B50 */
MC68681_BAUD_NOT_VALID, /* B75 */
0x01, /* B110 */
0x02, /* B134 */
MC68681_BAUD_NOT_VALID, /* B150 */
0x03, /* B200 */
0x04, /* B300 */
0x05, /* B600 */
0x06, /* B1200 */
MC68681_BAUD_NOT_VALID, /* B1800 */
0x08, /* B2400 */
0x09, /* B4800 */
0x0B, /* B9600 */
MC68681_BAUD_NOT_VALID, /* B19200 */
0x0C, /* B38400 */
MC68681_BAUD_NOT_VALID, /* B57600 */
MC68681_BAUD_NOT_VALID, /* B115200 */
MC68681_BAUD_NOT_VALID, /* B230400 */
MC68681_BAUD_NOT_VALID /* B460800 */
},
{ /* ACR[7] = 1, X = 0 */
MC68681_BAUD_NOT_VALID, /* B0 */
MC68681_BAUD_NOT_VALID, /* B50 */
0x00, /* B75 */
0x01, /* B110 */
0x02, /* B134 */
0x03, /* B150 */
MC68681_BAUD_NOT_VALID, /* B200 */
0x04, /* B300 */
0x05, /* B600 */
0x06, /* B1200 */
0x0A, /* B1800 */
0x08, /* B2400 */
0x09, /* B4800 */
0x0B, /* B9600 */
0x0C, /* B19200 */
MC68681_BAUD_NOT_VALID, /* B38400 */
MC68681_BAUD_NOT_VALID, /* B57600 */
MC68681_BAUD_NOT_VALID, /* B115200 */
MC68681_BAUD_NOT_VALID, /* B230400 */
MC68681_BAUD_NOT_VALID /* B460800 */
},
{ /* ACR[7] = 0, X = 1 */
MC68681_BAUD_NOT_VALID, /* B0 */
MC68681_BAUD_NOT_VALID, /* B50 */
0x00, /* B75 */
0x01, /* B110 */
0x02, /* B134 */
0x03, /* B150 */
MC68681_BAUD_NOT_VALID, /* B200 */
MC68681_BAUD_NOT_VALID, /* B300 */
MC68681_BAUD_NOT_VALID, /* B600 */
MC68681_BAUD_NOT_VALID, /* B1200 */
0x0A, /* B1800 */
MC68681_BAUD_NOT_VALID, /* B2400 */
0x08, /* B4800 */
0x0B, /* B9600 */
0x0C, /* B19200 */
MC68681_BAUD_NOT_VALID, /* B38400 */
0x07, /* B57600 */
0x08, /* B115200 */
MC68681_BAUD_NOT_VALID, /* B230400 */
MC68681_BAUD_NOT_VALID /* B460800 */
},
{ /* ACR[7] = 1, X = 1 */
MC68681_BAUD_NOT_VALID, /* B0 */
0x00, /* B50 */
MC68681_BAUD_NOT_VALID, /* B75 */
0x01, /* B110 */
0x02, /* B134 */
MC68681_BAUD_NOT_VALID, /* B150 */
0x03, /* B200 */
MC68681_BAUD_NOT_VALID, /* B300 */
MC68681_BAUD_NOT_VALID, /* B600 */
MC68681_BAUD_NOT_VALID, /* B1200 */
MC68681_BAUD_NOT_VALID, /* B1800 */
MC68681_BAUD_NOT_VALID, /* B2400 */
0x09, /* B4800 */
0x0B, /* B9600 */
MC68681_BAUD_NOT_VALID, /* B19200 */
0x0C, /* B38400 */
0x07, /* B57600 */
0x08, /* B115200 */
MC68681_BAUD_NOT_VALID, /* B230400 */
MC68681_BAUD_NOT_VALID /* B460800 */
},
};
 
/serial/mc68681_reg.c
0,0 → 1,61
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are only byte-aligned (no address gaps)
*
* 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: mc68681_reg.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
 
#ifndef _MC68681_MULTIPLIER
#define _MC68681_MULTIPLIER 1
#define _MC68681_NAME(_X) _X
#define _MC68681_TYPE unsigned8
#endif
 
#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \
(_MC68681_TYPE *)((_base) + ((_reg) * _MC68681_MULTIPLIER ))
 
/*
* MC68681 Get Register Routine
*/
 
unsigned8 _MC68681_NAME(mc68681_get_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum
)
{
_MC68681_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
return *port;
}
 
/*
* MC68681 Set Register Routine
*/
 
void _MC68681_NAME(mc68681_set_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
)
{
_MC68681_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
*port = ucData;
}
/serial/README
0,0 → 1,17
#
# $Id: README,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
This is the serial controller portion of the libchip library. This
directory contains the source code for reusable console driver
support code. Each individual driver is configured using the
console_tbl data structure. This structure is defined and explained
in the console.h file.
 
The reusable chip drivers do not directly access the serial controller.
They access the registers on the controller via a set of up to four
functions which are provided by the BSP. These functins set and get
general registers and data buffers. Some chips can access the data
buffers as general registers and thus the driver may not require
those interface routines.
 
/serial/mc68681.c
0,0 → 1,755
/*
* This file contains the termios TTY driver for the Motorola MC68681.
*
* This part is available from a number of secondary sources.
* In particular, we know about the following:
*
* + Exar 88c681 and 68c681
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: mc68681.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <rtems/libio.h>
#include <stdlib.h>
 
#include <libchip/serial.h>
#include <libchip/mc68681.h>
#include "sersupp.h"
#include "mc68681_p.h"
 
/*
* Flow control is only supported when using interrupts
*/
 
console_fns mc68681_fns =
{
libchip_serial_default_probe, /* deviceProbe */
mc68681_open, /* deviceFirstOpen */
NULL, /* deviceLastClose */
NULL, /* deviceRead */
mc68681_write_support_int, /* deviceWrite */
mc68681_initialize_interrupts, /* deviceInitialize */
mc68681_write_polled, /* deviceWritePolled */
mc68681_set_attributes, /* deviceSetAttributes */
TRUE /* deviceOutputUsesInterrupts */
};
 
console_fns mc68681_fns_polled =
{
libchip_serial_default_probe, /* deviceProbe */
mc68681_open, /* deviceFirstOpen */
mc68681_close, /* deviceLastClose */
mc68681_inbyte_nonblocking_polled, /* deviceRead */
mc68681_write_support_polled, /* deviceWrite */
mc68681_init, /* deviceInitialize */
mc68681_write_polled, /* deviceWritePolled */
mc68681_set_attributes, /* deviceSetAttributes */
FALSE, /* deviceOutputUsesInterrupts */
};
 
extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
 
/*
* Console Device Driver Entry Points
*/
 
/*
* mc68681_baud_rate
*
* This routine returns the proper ACR bit and baud rate field values
* based on the requested baud rate. The baud rate set to be used
* must be configured by the user.
*/
 
MC68681_STATIC int mc68681_baud_rate(
int minor,
int baud,
unsigned int *baud_mask_p,
unsigned int *acr_bit_p,
unsigned int *command
);
 
/*
* mc68681_set_attributes
*
* This function sets the DUART channel to reflect the requested termios
* port settings.
*/
 
MC68681_STATIC int mc68681_set_attributes(
int minor,
const struct termios *t
)
{
unsigned32 pMC68681_port;
unsigned32 pMC68681;
unsigned int mode1;
unsigned int mode2;
unsigned int baud_mask;
unsigned int acr_bit;
unsigned int cmd;
setRegister_f setReg;
rtems_interrupt_level Irql;
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Set the baud rate
*/
 
if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1)
return -1;
 
baud_mask |= baud_mask << 4;
acr_bit <<= 7;
 
/*
* Parity
*/
 
mode1 = 0;
mode2 = 0;
 
if (t->c_cflag & PARENB) {
if (t->c_cflag & PARODD)
mode1 |= 0x04;
else
mode1 |= 0x04;
} else {
mode1 |= 0x10;
}
 
/*
* Character Size
*/
 
if (t->c_cflag & CSIZE) {
switch (t->c_cflag & CSIZE) {
case CS5: break;
case CS6: mode1 |= 0x01; break;
case CS7: mode1 |= 0x02; break;
case CS8: mode1 |= 0x03; break;
}
} else {
mode1 |= 0x03; /* default to 9600,8,N,1 */
}
 
/*
* Stop Bits
*/
if (t->c_cflag & CSTOPB) {
mode2 |= 0x07; /* 2 stop bits */
} else {
if ((t->c_cflag & CSIZE) == CS5) /* CS5 and 2 stop bits not supported */
return -1;
mode2 |= 0x0F; /* 1 stop bit */
}
 
rtems_interrupt_disable(Irql);
(*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );
(*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );
if ( cmd ) {
(*setReg)( pMC68681_port, MC68681_COMMAND, cmd ); /* RX */
(*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 ); /* TX */
}
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
(*setReg)( pMC68681_port, MC68681_MODE, mode1 );
(*setReg)( pMC68681_port, MC68681_MODE, mode2 );
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* mc68681_initialize_context
*
* This function sets the default values of the per port context structure.
*/
 
MC68681_STATIC void mc68681_initialize_context(
int minor,
mc68681_context *pmc68681Context
)
{
int port;
unsigned int pMC68681;
unsigned int pMC68681_port;
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
 
pmc68681Context->mate = -1;
 
for (port=0 ; port<Console_Port_Count ; port++ ) {
if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 &&
Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) {
pmc68681Context->mate = port;
pmc68681Context->imr = 0;
break;
}
}
 
}
 
/*
* mc68681_init
*
* This function initializes the DUART to a quiecsent state.
*/
 
MC68681_STATIC void mc68681_init(int minor)
{
unsigned32 pMC68681_port;
unsigned32 pMC68681;
mc68681_context *pmc68681Context;
setRegister_f setReg;
getRegister_f getReg;
 
pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));
 
Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;
 
mc68681_initialize_context( minor, pmc68681Context );
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
getReg = Console_Port_Tbl[minor].getRegister;
 
/*
* Reset everything and leave this port disabled.
*/
 
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
 
 
(*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );
(*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );
 
/*
* Disable interrupts on RX and TX for this port
*/
 
mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );
}
 
/*
* mc68681_open
*
* This function opens a port for communication.
*
* Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
*/
 
MC68681_STATIC int mc68681_open(
int major,
int minor,
void *arg
)
{
unsigned32 pMC68681;
unsigned32 pMC68681_port;
unsigned int baud;
unsigned int acr;
unsigned int vector;
unsigned int command;
rtems_interrupt_level Irql;
setRegister_f setReg;
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
vector = Console_Port_Tbl[minor].ulIntVector;
 
/* XXX default baud rate should be from configuration table */
 
(void) mc68681_baud_rate( minor, B9600, &baud, &acr, &command );
 
/*
* Set the DUART channel to a default useable state
*/
 
rtems_interrupt_disable(Irql);
(*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr );
(*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );
if ( command ) {
(*setReg)( pMC68681_port, MC68681_COMMAND, command ); /* RX */
(*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 ); /* TX */
}
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );
(*setReg)( pMC68681_port, MC68681_MODE, 0x13 );
(*setReg)( pMC68681_port, MC68681_MODE, 0x07 );
rtems_interrupt_enable(Irql);
 
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );
 
(*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );
 
return RTEMS_SUCCESSFUL;
}
 
/*
* mc68681_close
*
* This function shuts down the requested port.
*/
 
MC68681_STATIC int mc68681_close(
int major,
int minor,
void *arg
)
{
unsigned32 pMC68681;
unsigned32 pMC68681_port;
setRegister_f setReg;
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Disable interrupts from this channel and then disable it totally.
*/
 
#if 0
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );
#endif
 
return(RTEMS_SUCCESSFUL);
}
 
/*
* mc68681_write_polled
*
* This routine polls out the requested character.
*/
 
MC68681_STATIC void mc68681_write_polled(
int minor,
char cChar
)
{
unsigned32 pMC68681_port;
unsigned char ucLineStatus;
int iTimeout;
getRegister_f getReg;
setRegister_f setReg;
 
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
getReg = Console_Port_Tbl[minor].getRegister;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* wait for transmitter holding register to be empty
*/
iTimeout = 1000;
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {
 
if ((ucLineStatus & 0xF0))
(*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );
 
/*
* Yield while we wait
*/
 
#if 0
if(_System_state_Is_up(_System_state_Get())) {
rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
}
#endif
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
if(!--iTimeout) {
break;
}
}
 
/*
* transmit character
*/
 
(*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar);
}
 
/*
* mc68681_isr
*
* This is the single interrupt entry point which parcels interrupts
* out to the various ports.
*/
 
MC68681_STATIC rtems_isr mc68681_isr(
rtems_vector_number vector
)
{
int minor;
 
for(minor=0 ; minor<Console_Port_Count ; minor++) {
if(Console_Port_Tbl[minor].ulIntVector == vector &&
Console_Port_Tbl[minor].deviceType == SERIAL_MC68681 ) {
mc68681_process(minor);
}
}
}
 
/*
* mc68681_initialize_interrupts
*
* This routine initializes the console's receive and transmit
* ring buffers and loads the appropriate vectors to handle the interrupts.
*/
 
MC68681_STATIC void mc68681_initialize_interrupts(int minor)
{
mc68681_init(minor);
 
Console_Port_Data[minor].bActive = FALSE;
 
set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
 
mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
}
 
/*
* mc68681_write_support_int
*
* Console Termios output entry point when using interrupt driven output.
*/
 
MC68681_STATIC int mc68681_write_support_int(
int minor,
const char *buf,
int len
)
{
unsigned32 Irql;
unsigned32 pMC68681_port;
setRegister_f setReg;
 
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* We are using interrupt driven output and termios only sends us
* one character at a time.
*/
 
if ( !len )
return 0;
 
/*
* Put the character out and enable interrupts if necessary.
*/
 
rtems_interrupt_disable(Irql);
if ( Console_Port_Data[minor].bActive == FALSE ) {
Console_Port_Data[minor].bActive = TRUE;
mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL);
}
(*setReg)(pMC68681_port, MC68681_TX_BUFFER, *buf);
rtems_interrupt_enable(Irql);
 
return 1;
}
 
/*
* mc68681_write_support_polled
*
* Console Termios output entry point when using polled output.
*
*/
 
MC68681_STATIC int mc68681_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
*/
mc68681_write_polled(minor, *buf++);
nwrite++;
}
 
/*
* return the number of bytes written.
*/
return nwrite;
}
 
/*
* mc68681_inbyte_nonblocking_polled
*
* Console Termios polling input entry point.
*/
 
MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
int minor
)
{
unsigned32 pMC68681_port;
unsigned char ucLineStatus;
unsigned char cChar;
getRegister_f getReg;
 
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
getReg = Console_Port_Tbl[minor].getRegister;
 
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
if(ucLineStatus & MC68681_RX_READY) {
cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
return (int)cChar;
} else {
return -1;
}
}
 
/*
* mc68681_baud_rate
*/
 
MC68681_STATIC int mc68681_baud_rate(
int minor,
int baud,
unsigned int *baud_mask_p,
unsigned int *acr_bit_p,
unsigned int *command
)
{
unsigned int baud_mask;
unsigned int acr_bit;
int status;
int is_extended;
int baud_requested;
mc68681_baud_table_t *baud_tbl;
 
baud_mask = 0;
acr_bit = 0;
status = 0;
 
if ( !(Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_1) )
acr_bit = 1;
 
is_extended = 0;
 
switch (Console_Port_Tbl[minor].ulDataPort & MC68681_XBRG_MASK) {
case MC68681_XBRG_IGNORED:
*command = 0x00;
break;
case MC68681_XBRG_ENABLED:
*command = 0x80;
is_extended = 1;
break;
case MC68681_XBRG_DISABLED:
*command = 0x90;
break;
}
 
baud_requested = baud & CBAUD;
if (!baud_requested)
baud_requested = B9600; /* default to 9600 baud */
baud_requested = termios_baud_to_index( baud_requested );
 
baud_tbl = (mc68681_baud_table_t *) Console_Port_Tbl[minor].ulClock;
if (!baud_tbl)
rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS);
 
if ( is_extended )
baud_mask = (unsigned int)baud_tbl[ acr_bit + 2 ][ baud_requested ];
else
baud_mask = baud_tbl[ acr_bit ][ baud_requested ];
 
if ( baud_mask == MC68681_BAUD_NOT_VALID )
status = -1;
 
/*
* upper nibble is receiver and lower nibble is transmitter
*/
 
*baud_mask_p = (baud_mask << 4) | baud_mask;
*acr_bit_p = acr_bit;
return status;
}
 
/*
* mc68681_process
*
* This routine is the per port console interrupt handler.
*/
 
MC68681_STATIC void mc68681_process(
int minor
)
{
unsigned32 pMC68681;
unsigned32 pMC68681_port;
volatile unsigned8 ucLineStatus;
unsigned char cChar;
getRegister_f getReg;
setRegister_f setReg;
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
getReg = Console_Port_Tbl[minor].getRegister;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Deal with any received characters
*/
while(TRUE) {
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
if(!(ucLineStatus & MC68681_RX_READY)) {
break;
}
/*
* If there is a RX error, then dump all the data.
*/
if ( ucLineStatus & MC68681_RX_ERRORS ) {
do {
cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
} while ( ucLineStatus & MC68681_RX_READY );
continue;
}
cChar = (*getReg)(pMC68681_port, MC68681_RX_BUFFER);
rtems_termios_enqueue_raw_characters(
Console_Port_Data[minor].termios_data,
&cChar,
1
);
}
 
/*
* Deal with the transmitter
*/
 
ucLineStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
if (pMC68681 != pMC68681_port)
ucLineStatus >>= 4;
 
if(ucLineStatus & MC68681_IR_TX_READY) {
if (rtems_termios_dequeue_characters(
Console_Port_Data[minor].termios_data, 1)) {
Console_Port_Data[minor].bActive = FALSE;
mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
}
}
 
}
 
/*
* mc68681_build_imr
*
* This function returns the value for the interrupt mask register for this
* DUART. Since this is a shared register, we must look at the other port
* on this chip to determine whether or not it is using interrupts.
*/
 
MC68681_STATIC unsigned int mc68681_build_imr(
int minor,
int enable_flag
)
{
int mate;
int is_a;
unsigned int mask;
unsigned int mate_mask;
unsigned int pMC68681;
unsigned int pMC68681_port;
mc68681_context *pmc68681Context;
mc68681_context *mateContext;
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
mate = pmc68681Context->mate;
 
mask = 0;
mate_mask = 0;
 
is_a = (pMC68681 == pMC68681_port);
/*
* If there is a mate for this port, get its IMR mask.
*/
 
if ( mate != -1 ) {
mateContext = Console_Port_Data[mate].pDeviceContext;
if (mateContext)
mate_mask = mateContext->imr;
}
 
/*
* Calculate this port's IMR mask and save it in the context area.
*/
 
if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts )
mask = enable_flag;
 
pmc68681Context->imr = mask;
 
/*
* Now return the full IMR value
*/
 
if (is_a)
return (mate_mask << 4) | mask;
 
return (mask << 4) | mate_mask;
}
 
/*
* mc68681_enable_interrupts
*
* This function enables specific interrupt sources on the DUART.
*/
 
MC68681_STATIC void mc68681_enable_interrupts(
int minor,
int imr_mask
)
{
unsigned32 pMC68681;
setRegister_f setReg;
 
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Enable interrupts on RX and TX -- not break
*/
 
(*setReg)(
pMC68681,
MC68681_INTERRUPT_MASK_REG,
mc68681_build_imr(minor, imr_mask)
);
}
/serial/termios_baud2num.c
0,0 → 1,39
/*
* $Id: termios_baud2num.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <sys/termios.h>
 
int termios_baud_to_number(
int termios_baud
)
{
int baud;
 
switch (termios_baud) {
case B0: baud = 0; break;
case B50: baud = 50; break;
case B75: baud = 75; break;
case B110: baud = 110; break;
case B134: baud = 135; break;
case B150: baud = 150; break;
case B200: baud = 200; break;
case B300: baud = 300; break;
case B600: baud = 600; break;
case B1200: baud = 1200; break;
case B1800: baud = 1800; break;
case B2400: baud = 2400; break;
case B4800: baud = 4800; break;
case B9600: baud = 9600; break;
case B19200: baud = 19200; break;
case B38400: baud = 38400; break;
case B57600: baud = 57600; break;
case B115200: baud = 115200; break;
case B230400: baud = 230400; break;
case B460800: baud = 460800; break;
default: baud = -1; break;
}
 
return baud;
}
 
/serial/z85c30_p.h
0,0 → 1,410
/*
* This include file contains all private driver definitions for the
* Zilog 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: z85c30_p.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __Z85C30_P_H
#define __Z85C30_P_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* Define Z85C30_STATIC to nothing while debugging so the entry points
* will show up in the symbol table.
*/
 
#define Z85C30_STATIC
 
/* #define Z85C30_STATIC static */
 
/* 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
 
#define SCC_ENABLE_ALL_INTR \
(SCC_WR1_EXT_INT_EN | SCC_WR1_TX_INT_EN | SCC_WR1_INT_ALL_RX)
 
#define SCC_DISABLE_ALL_INTR 0x00
 
#define SCC_ENABLE_ALL_INTR_EXCEPT_TX \
(SCC_WR1_EXT_INT_EN | SCC_WR1_INT_ALL_RX)
 
/* 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( _clock, _baud_rate ) \
( ((_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
*/
 
Z85C30_STATIC void z85c30_init(int minor);
 
Z85C30_STATIC int z85c30_set_attributes(
int minor,
const struct termios *t
);
 
Z85C30_STATIC int z85c30_open(
int major,
int minor,
void * arg
);
 
Z85C30_STATIC int z85c30_close(
int major,
int minor,
void * arg
);
 
Z85C30_STATIC void z85c30_write_polled(
int minor,
char cChar
);
 
Z85C30_STATIC int z85c30_assert_RTS(
int minor
);
 
Z85C30_STATIC int z85c30_negate_RTS(
int minor
);
 
Z85C30_STATIC int z85c30_assert_DTR(
int minor
);
 
Z85C30_STATIC int z85c30_negate_DTR(
int minor
);
 
Z85C30_STATIC void z85c30_initialize_interrupts(int minor);
 
Z85C30_STATIC int z85c30_write_support_int(
int minor,
const char *buf,
int len
);
 
Z85C30_STATIC int z85c30_write_support_polled(
int minor,
const char *buf,
int len
);
 
Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
int minor
);
 
Z85C30_STATIC void z85c30_enable_interrupts(
int minor,
int interrupt_mask
);
 
#ifdef __cplusplus
}
#endif
 
#endif
/serial/serprobe.c
0,0 → 1,20
/*
* $Id: serprobe.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <libchip/serial.h>
#include "sersupp.h"
 
boolean libchip_serial_default_probe(int minor)
{
/*
* If the configuration dependent probe has located the device then
* assume it is there
*/
 
return TRUE;
}
 
 
 
/serial/mc68681.h
0,0 → 1,122
/*
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: mc68681.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef _MC68681_H_
#define _MC68681_H_
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* These are just used in the interface between this driver and
* the read/write register routines when accessing the first
* control port.
*/
 
#define MC68681_STATUS 1
#define MC68681_RX_BUFFER 3
 
#define MC68681_MODE 0
#define MC68681_CLOCK_SELECT 1
#define MC68681_COMMAND 2
#define MC68681_TX_BUFFER 3
 
/*
* Data Port bit map configuration
*
* D0 : Baud Rate Set Selection
* D1 - D2 : Extended Baud Rate Setting
*/
 
#define MC68681_DATA_BAUD_RATE_SET_1 0 /* ACR[7] = 0 */
#define MC68681_DATA_BAUD_RATE_SET_2 1 /* ACR[7] = 1 */
 
#define MC68681_XBRG_IGNORED (0 << 1)
#define MC68681_XBRG_ENABLED (1 << 1)
#define MC68681_XBRG_DISABLED (2 << 1)
#define MC68681_XBRG_MASK (3 << 1)
 
/*
* Custom baud rate table information
*/
 
typedef unsigned char mc68681_baud_t;
typedef mc68681_baud_t mc68681_baud_table_t[RTEMS_TERMIOS_NUMBER_BAUD_RATES];
 
#define MC68681_BAUD_NOT_VALID 0xFF
 
extern mc68681_baud_t
mc68681_baud_rate_table[4][RTEMS_TERMIOS_NUMBER_BAUD_RATES];
 
 
/*
* Driver function table
*/
 
extern console_fns mc68681_fns;
extern console_fns mc68681_fns_polled;
 
/*
* Default register access routines
*/
 
unsigned8 mc68681_get_register( /* registers are at 1 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void mc68681_set_register(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
);
 
unsigned8 mc68681_get_register_2( /* registers are at 2 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void mc68681_set_register_2(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
);
 
unsigned8 mc68681_get_register_4( /* registers are at 4 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void mc68681_set_register_4(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
);
 
unsigned8 mc68681_get_register_8( /* registers are at 8 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void mc68681_set_register_8(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* _MC68681_H_ */
/serial/ns16550.c
0,0 → 1,667
/*
* This file contains the TTY driver for the National Semiconductor NS16550.
*
* This part is widely cloned and second sourced. It is found in a number
* of "Super IO" controllers.
*
* 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 <rtems/libio.h>
#include <stdlib.h>
#include <ringbuf.h>
 
#include <libchip/serial.h>
#include "ns16550_p.h"
#include "sersupp.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 = {
libchip_serial_default_probe, /* deviceProbe */
ns16550_open, /* deviceFirstOpen */
NULL, /* deviceLastClose */
NULL, /* deviceRead */
ns16550_write_support_int, /* deviceWrite */
ns16550_initialize_interrupts, /* deviceInitialize */
ns16550_write_polled, /* deviceWritePolled */
ns16550_set_attributes, /* deviceSetAttributes */
TRUE /* deviceOutputUsesInterrupts */
};
 
console_fns ns16550_fns_polled = {
libchip_serial_default_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 */
ns16550_set_attributes, /* deviceSetAttributes */
FALSE /* deviceOutputUsesInterrupts */
};
 
extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
 
/*
* ns16550_init
*/
 
NS16550_STATIC void ns16550_init(int minor)
{
unsigned32 pNS16550;
unsigned8 ucTrash;
unsigned8 ucDataByte;
unsigned32 ulBaudDivisor;
ns16550_context *pns16550Context;
setRegister_f setReg;
getRegister_f getReg;
 
pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
 
Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
getReg = Console_Port_Tbl[minor].getRegister;
 
/* Clear the divisor latch, clear all interrupt enables,
* and reset and
* disable the FIFO's.
*/
 
(*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
 
/* Set the divisor latch and set the baud rate. */
 
ulBaudDivisor = NS16550_Baud(
(unsigned32) Console_Port_Tbl[minor].ulClock,
(unsigned32) Console_Port_Tbl[minor].pDeviceParams
);
ucDataByte = SP_LINE_DLAB;
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
 
/* XXX */
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (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;
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
 
/* Enable and reset transmit and receive FIFOs. TJA */
ucDataByte = SP_FIFO_ENABLE;
(*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
 
ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
(*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
 
ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
 
/* Set data terminal ready. */
/* And open interrupt tristate line */
(*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
 
ucTrash = (*getReg)(pNS16550, NS16550_LINE_STATUS );
ucTrash = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
}
 
/*
* ns16550_open
*/
 
NS16550_STATIC int ns16550_open(
int major,
int minor,
void * arg
)
{
/*
* Assert DTR
*/
 
if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
ns16550_assert_DTR(minor);
}
 
return(RTEMS_SUCCESSFUL);
}
 
/*
* ns16550_close
*/
 
NS16550_STATIC int ns16550_close(
int major,
int minor,
void * arg
)
{
/*
* Negate DTR
*/
if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
ns16550_negate_DTR(minor);
}
 
return(RTEMS_SUCCESSFUL);
}
 
/*
* ns16550_write_polled
*/
 
NS16550_STATIC void ns16550_write_polled(
int minor,
char cChar
)
{
unsigned32 pNS16550;
unsigned char ucLineStatus;
int iTimeout;
getRegister_f getReg;
setRegister_f setReg;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
getReg = Console_Port_Tbl[minor].getRegister;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* wait for transmitter holding register to be empty
*/
iTimeout=1000;
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
while ((ucLineStatus & SP_LSR_THOLD) == 0) {
/*
* Yield while we wait
*/
#if 0
if(_System_state_Is_up(_System_state_Get())) {
rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
}
#endif
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
if(!--iTimeout) {
break;
}
}
 
/*
* transmit character
*/
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, cChar);
}
 
/*
* These routines provide control of the RTS and DTR lines
*/
 
/*
* ns16550_assert_RTS
*/
 
NS16550_STATIC int ns16550_assert_RTS(int minor)
{
unsigned32 pNS16550;
unsigned32 Irql;
ns16550_context *pns16550Context;
setRegister_f setReg;
 
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Assert RTS
*/
rtems_interrupt_disable(Irql);
pns16550Context->ucModemCtrl|=SP_MODEM_RTS;
(*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* ns16550_negate_RTS
*/
 
NS16550_STATIC int ns16550_negate_RTS(int minor)
{
unsigned32 pNS16550;
unsigned32 Irql;
ns16550_context *pns16550Context;
setRegister_f setReg;
 
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Negate RTS
*/
rtems_interrupt_disable(Irql);
pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;
(*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* These flow control routines utilise a connection from the local DTR
* line to the remote CTS line
*/
 
/*
* ns16550_assert_DTR
*/
 
NS16550_STATIC int ns16550_assert_DTR(int minor)
{
unsigned32 pNS16550;
unsigned32 Irql;
ns16550_context *pns16550Context;
setRegister_f setReg;
 
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Assert DTR
*/
rtems_interrupt_disable(Irql);
pns16550Context->ucModemCtrl|=SP_MODEM_DTR;
(*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* ns16550_negate_DTR
*/
 
NS16550_STATIC int ns16550_negate_DTR(int minor)
{
unsigned32 pNS16550;
unsigned32 Irql;
ns16550_context *pns16550Context;
setRegister_f setReg;
 
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Negate DTR
*/
rtems_interrupt_disable(Irql);
pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;
(*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* ns16550_set_attributes
*
* This function sets the channel to reflect the requested termios
* port settings.
*/
 
NS16550_STATIC int ns16550_set_attributes(
int minor,
const struct termios *t
)
{
unsigned32 pNS16550;
unsigned32 ulBaudDivisor;
unsigned8 ucLineControl;
unsigned32 baud_requested;
setRegister_f setReg;
getRegister_f getReg;
unsigned32 Irql;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
getReg = Console_Port_Tbl[minor].getRegister;
 
/*
* Calculate the baud rate divisor
*/
 
baud_requested = t->c_cflag & CBAUD;
if (!baud_requested)
baud_requested = B9600; /* default to 9600 baud */
 
ulBaudDivisor = NS16550_Baud(
(unsigned32) Console_Port_Tbl[minor].ulClock,
termios_baud_to_number(baud_requested)
);
 
ucLineControl = 0;
 
/*
* Parity
*/
 
if (t->c_cflag & PARENB) {
ucLineControl |= SP_LINE_PAR;
if (!(t->c_cflag & PARODD))
ucLineControl |= SP_LINE_ODD;
}
 
/*
* Character Size
*/
 
if (t->c_cflag & CSIZE) {
switch (t->c_cflag & CSIZE) {
case CS5: ucLineControl |= FIVE_BITS; break;
case CS6: ucLineControl |= SIX_BITS; break;
case CS7: ucLineControl |= SEVEN_BITS; break;
case CS8: ucLineControl |= EIGHT_BITS; break;
}
} else {
ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */
}
 
/*
* Stop Bits
*/
 
if (t->c_cflag & CSTOPB) {
ucLineControl |= SP_LINE_STOP; /* 2 stop bits */
} else {
; /* 1 stop bit */
}
 
/*
* Now actually set the chip
*/
 
rtems_interrupt_disable(Irql);
 
/*
* Set the baud rate
*/
 
(*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
/* XXX are these registers right? */
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
 
/*
* Now write the line control
*/
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
 
rtems_interrupt_enable(Irql);
 
return 0;
}
 
/*
* ns16550_process
*
* This routine is the console interrupt handler for A port.
*/
 
NS16550_STATIC void ns16550_process(
int minor
)
{
unsigned32 pNS16550;
volatile unsigned8 ucLineStatus;
volatile unsigned8 ucInterruptId;
unsigned char cChar;
getRegister_f getReg;
setRegister_f setReg;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
getReg = Console_Port_Tbl[minor].getRegister;
setReg = Console_Port_Tbl[minor].setRegister;
 
do {
/*
* Deal with any received characters
*/
while(TRUE) {
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
if(~ucLineStatus & SP_LSR_RDY) {
break;
}
cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
rtems_termios_enqueue_raw_characters(
Console_Port_Data[minor].termios_data,
&cChar,
1
);
}
 
/*
* TX all the characters we can
*/
 
while(TRUE) {
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
if(~ucLineStatus & SP_LSR_THOLD) {
/*
* We'll get another interrupt when
* the transmitter holding reg. becomes
* free again
*/
break;
}
 
#if 0
/* XXX flow control not completely supported in libchip */
 
if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
ns16550_negate_RTS(minor);
}
#endif
 
rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
if (rtems_termios_dequeue_characters(
Console_Port_Data[minor].termios_data, 1)) {
if (Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
ns16550_negate_RTS(minor);
}
Console_Port_Data[minor].bActive = FALSE;
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
break;
}
 
ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);
}
} while((ucInterruptId&0xf)!=0x1);
}
 
/*
* ns16550_isr
*/
 
NS16550_STATIC rtems_isr ns16550_isr(
rtems_vector_number vector
)
{
int minor;
 
for(minor=0;minor<Console_Port_Count;minor++) {
if(Console_Port_Tbl[minor].ulIntVector == vector &&
Console_Port_Tbl[minor].deviceType == SERIAL_NS16550 ) {
ns16550_process(minor);
}
}
}
 
/*
* ns16550_enable_interrupts
*
* This routine initializes the port to have the specified interrupts masked.
*/
 
NS16550_STATIC void ns16550_enable_interrupts(
int minor,
int mask
)
{
unsigned32 pNS16550;
setRegister_f setReg;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
}
 
/*
* ns16550_initialize_interrupts
*
* This routine initializes the port to operate in interrupt driver mode.
*/
 
NS16550_STATIC void ns16550_initialize_interrupts(int minor)
{
ns16550_init(minor);
 
Console_Port_Data[minor].bActive = FALSE;
 
set_vector(ns16550_isr, Console_Port_Tbl[minor].ulIntVector, 1);
 
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
}
 
/*
* ns16550_write_support_int
*
* Console Termios output entry point.
*/
 
NS16550_STATIC int ns16550_write_support_int(
int minor,
const char *buf,
int len
)
{
unsigned32 Irql;
unsigned32 pNS16550;
setRegister_f setReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
 
/*
* We are using interrupt driven output and termios only sends us
* one character at a time.
*/
 
if ( !len )
return 0;
 
if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
ns16550_assert_RTS(minor);
}
 
rtems_interrupt_disable(Irql);
if ( Console_Port_Data[minor].bActive == FALSE) {
Console_Port_Data[minor].bActive = TRUE;
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
}
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);
rtems_interrupt_enable(Irql);
 
return 1;
}
 
/*
* ns16550_write_support_polled
*
* Console Termios output entry point.
*
*/
 
NS16550_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.
*/
 
NS16550_STATIC int ns16550_inbyte_nonblocking_polled(
int minor
)
{
unsigned32 pNS16550;
unsigned char ucLineStatus;
char cChar;
getRegister_f getReg;
 
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
getReg = Console_Port_Tbl[minor].getRegister;
 
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
if(ucLineStatus & SP_LSR_RDY) {
cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
return (int)cChar;
} else {
return -1;
}
}
/serial/README.xr88681
0,0 → 1,6
#
# $Id: README.xr88681,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
The Exar XR88681 is an enhanced version of the Motorola MC68681 and is
supported by the mc68681 driver.
/serial/serial.h
0,0 → 1,151
/*
* This file contains the TTY driver table definition
*
* This driver uses the termios pseudo driver.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: serial.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __LIBCHIP_SERIAL_h
#define __LIBCHIP_SERIAL_h
 
#include <termios.h>
 
/*
* Types for get and set register routines
*/
 
typedef unsigned8 (*getRegister_f)(unsigned32 port, unsigned8 register);
typedef void (*setRegister_f)(
unsigned32 port, unsigned8 reg, unsigned8 value);
typedef unsigned8 (*getData_f)(unsigned32 port);
typedef void (*setData_f)(unsigned32 port, unsigned8 value);
 
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);
void (*deviceWritePolled)(int minor, char cChar);
int (*deviceSetAttributes)(int minor, const struct termios *t);
int deviceOutputUsesInterrupts;
} console_fns;
 
typedef struct _console_flow {
int (*deviceStopRemoteTx)(int minor);
int (*deviceStartRemoteTx)(int minor);
} console_flow;
 
typedef enum {
SERIAL_MC68681, /* Motorola MC68681 or Exar 88681 */
SERIAL_NS16550, /* National Semiconductor NS16550 */
SERIAL_Z85C30, /* Zilog Z85C30 */
SERIAL_CUSTOM /* BSP specific driver */
} console_devs;
 
/*
* Each field is interpreted thus:
*
* sDeviceName This is the name of the device.
*
* deviceType This indicates the chip type. It is especially important when
* multiple devices share the same interrupt vector and must be
* distinguished.
*
* pDeviceFns This is a pointer to the set of driver routines to use.
*
* pDeviceFlow This is a pointer to the set of flow control routines to
* use. Serial device drivers will typically supply RTSCTS
* and DTRCTS handshake routines for DCE to DCE communication,
* however for DCE to DTE communication, no such routines
* should be necessary as RTS will be driven automatically
* when the transmitter is active.
*
* ulMargin The high water mark in the input buffer is set to the buffer
* size less ulMargin. Once this level is reached, the driver's
* flow control routine used to stop the remote transmitter will
* be called. This figure should be greater than or equal to
* the number of stages of FIFO between the transmitter and
* receiver.
*
* NOTE: At the current time, this parameter is hard coded
* in termios and this number is ignored.
*
* ulHysteresis After the high water mark specified by ulMargin has been
* reached, the driver's routine to re-start the remote
* transmitter will be called once the level in the input
* buffer has fallen by ulHysteresis bytes.
*
* NOTE: At the current time, this parameter is hard coded
* in termios and this number is ignored.
*
* pDeviceParams This contains either device specific data or a pointer to a
* device specific structure containing additional information
* not provided in this table.
*
* ulCtrlPort1 This is the primary control port number for the device. This
* may be used to specify different instances of the same device
* type.
*
* ulCtrlPort2 This is the secondary control port number, of use when a given
* device has more than one available channel.
*
* ulDataPort This is the port number for the data port of the device
*
* getRegister This is the routine used to read register values.
*
* setRegister This is the routine used to write register values.
*
* getData This is the routine used to read the data register (RX).
*
* setData This is the routine used to write the data register (TX).
*
* ulClock This is the baud rate clock speed.
*
* ulIntVector This encodes the interrupt vector of the device.
*/
 
typedef struct _console_tbl {
char *sDeviceName;
console_devs deviceType;
console_fns *pDeviceFns;
boolean (*deviceProbe)(int minor);
console_flow *pDeviceFlow;
unsigned32 ulMargin;
unsigned32 ulHysteresis;
void *pDeviceParams;
unsigned32 ulCtrlPort1;
unsigned32 ulCtrlPort2;
unsigned32 ulDataPort;
getRegister_f getRegister;
setRegister_f setRegister;
getData_f getData;
setData_f setData;
unsigned32 ulClock;
unsigned int ulIntVector;
} console_tbl;
 
typedef struct _console_data {
void *termios_data;
volatile boolean bActive;
/*
* 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;
 
#endif
/* end of include file */
/serial/ns16550.h
0,0 → 1,42
/*
* 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_ */
/serial/README.mc68681
0,0 → 1,87
#
# $Id: README.mc68681,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
Configuration Table Use
=======================
 
sDeviceName
 
The name of this device.
 
deviceType
 
This field must be SERIAL_MC68681.
 
pDeviceFns
 
The device interface control table. This may be:
+ mc68681_fns for interrupt driven IO
+ mc68681_fns_polled for polled IO
 
deviceProbe
 
This is the address of the routine which probes to see if the device
is present.
 
pDeviceFlow
 
This field is ignored as hardware flow control is not currently supported.
 
ulMargin
 
This is currently unused.
 
ulHysteresis
 
This is currently unused.
 
pDeviceParams
 
This is set to the default settings.
 
ulCtrlPort1
 
This field is the base address of the entire DUART.
 
ulCtrlPort2
 
This field is the base address of the port specific registers.
 
ulDataPort
 
This field is bit mapped as follows:
bit 0: baud rate set a or b
bit 1-2: BRG selection ("Select Extend bit")
 
Note: If both ports on single DUART are not configured for the same
baud rate set, then unexpected results will occur.
 
Note: On the Exar 88c681, if a standard clock of 3.6864 Mhz is used
and the "Select Extend bit" is 0 (disabled), then the default
MC68681 baud rate table is selected.
 
getRegister
setRegister
 
These follow standard conventions.
 
getData
setData
 
These are unused since the TX and RX data registers can be accessed
as regular registers.
 
ulClock
 
This is a pointer to a baud rate mapping table. If set to
mc68681_baud_rate_table, then the CSR/ACR/X bit mappings shown
in the 68681 and 88681 manuals are used. Otherwise, the board
specific baud rate mapping is used.
 
NULL is not a valid value.
 
ulIntVector
 
This is the interrupt vector number associated with this chip.
 
/serial/termios_baud2index.c
0,0 → 1,39
/*
* $Id: termios_baud2index.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <sys/termios.h>
 
int termios_baud_to_index(
int termios_baud
)
{
int baud_index;
 
switch (termios_baud) {
case B0: baud_index = 0; break;
case B50: baud_index = 1; break;
case B75: baud_index = 2; break;
case B110: baud_index = 3; break;
case B134: baud_index = 4; break;
case B150: baud_index = 5; break;
case B200: baud_index = 6; break;
case B300: baud_index = 7; break;
case B600: baud_index = 8; break;
case B1200: baud_index = 9; break;
case B1800: baud_index = 10; break;
case B2400: baud_index = 11; break;
case B4800: baud_index = 12; break;
case B9600: baud_index = 13; break;
case B19200: baud_index = 14; break;
case B38400: baud_index = 15; break;
case B57600: baud_index = 16; break;
case B115200: baud_index = 17; break;
case B230400: baud_index = 18; break;
case B460800: baud_index = 19; break;
default: baud_index = -1; break;
}
 
return baud_index;
}
 
/serial/Makefile.am
0,0 → 1,53
#
# $Id: Makefile.am,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
AUTOMAKE_OPTIONS = foreign 1.4
 
LIBNAME = libserialio
LIB = ${ARCH}/${LIBNAME}.a
 
C_FILES = mc68681.c mc68681_baud.c mc68681_reg.c mc68681_reg2.c \
mc68681_reg4.c mc68681_reg8.c ns16550.c z85c30.c z85c30_reg.c serprobe.c \
termios_baud2index.c termios_baud2num.c
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
 
H_FILES = mc68681_p.h ns16550_p.h sersupp.h z85c30_p.h
INSTALLED_H_FILES = mc68681.h ns16550.h z85c30.h serial.h
noinst_HEADERS = $(H_FILES) $(INSTALLED_H_FILES)
 
OBJS = $(C_O_FILES)
 
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../automake/lib.am
 
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip \
$(INSTALLED_H_FILES:%=$(PROJECT_INCLUDE)/libchip/%)
 
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
 
$(PROJECT_INCLUDE)/libchip:
@$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/libchip/%.h: %.h
$(INSTALL_DATA) $< $@
 
#
# Add local stuff here using +=
#
 
AM_CFLAGS += $(LIBC_DEFINES)
 
$(LIB): ${OBJS}
$(make-library)
 
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
$(INSTALL_DATA) $< $@
 
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
 
DOC_FILES = README.mc68681 README.ns16550 README.xr88681 README.z85c30 \
STATUS
 
EXTRA_DIST = $(C_FILES) $(DOC_FILES)
 
include $(top_srcdir)/../../../automake/local.am
/serial/z85c30_reg.c
0,0 → 1,73
/*
* This file contains a typical set of register access routines which may be
* used with the z85c30 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
*
* 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: z85c30_reg.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
 
#ifndef _Z85C30_MULTIPLIER
#define _Z85C30_MULTIPLIER 1
#define _Z85C30_NAME(_X) _X
#define _Z85C30_TYPE unsigned8
#endif
 
/*
* Z85C30 Get Register Routine
*/
 
unsigned8 _Z85C30_NAME(z85c30_get_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum
)
{
_Z85C30_TYPE *port;
unsigned8 data;
rtems_interrupt_level level;
 
port = (_Z85C30_TYPE *)ulCtrlPort;
 
rtems_interrupt_disable(level);
 
if(ucRegNum) {
*port = ucRegNum;
}
data = *port;
rtems_interrupt_enable(level);
 
return data;
}
 
/*
* Z85C30 Set Register Routine
*/
 
void _Z85C30_NAME(z85c30_set_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned8 ucData
)
{
_Z85C30_TYPE *port;
rtems_interrupt_level level;
 
port = (_Z85C30_TYPE *)ulCtrlPort;
 
rtems_interrupt_disable(level);
if(ucRegNum) {
*port = ucRegNum;
}
*port = ucData;
rtems_interrupt_enable(level);
}
/serial/mc68681_reg2.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 16-bit boundaries
*
* 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: mc68681_reg2.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _MC68681_MULTIPLIER 2
#define _MC68681_NAME(_X) _X##_2
#define _MC68681_TYPE unsigned8
 
#include "mc68681_reg.c"
 
/serial/README.ns16550
0,0 → 1,95
#
# $Id: README.ns16550,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
Status
======
 
This driver appears to work OK for polled output at this point.
 
It needs to be tested for:
 
+ polled input
+ interrupt driver output
+ interrupt driver input
 
This driver does not support the new style RTEMS interrupt processing
used on the i386 and some PowerPC models.
 
Configuration Table Use
=======================
 
sDeviceName
 
The name of this device.
 
deviceType
 
This field must be SERIAL_NS16550.
 
pDeviceFns
 
The device interface control table. This may be:
+ ns16550_fns for interrupt driven IO
+ ns16550_fns_polled for polled IO
 
deviceProbe
 
This is the address of the routine which probes to see if the device
is present.
 
pDeviceFlow
 
This field is ignored as hardware flow control is not currently supported.
 
ulMargin
 
This is currently unused.
 
ulHysteresis
 
This is currently unused.
 
pDeviceParams
 
This is set to the default settings. At this point, it is the default
baud rate cast as a (void *).
 
ulCtrlPort1
 
This field is the base address of this port on the UART.
 
ulCtrlPort2
 
This field is unused for the NS16550.
 
ulDataPort
 
This field is the base address of this port on the UART.
 
getRegister
setRegister
 
These follow standard conventions.
 
getData
setData
 
These are unused since the TX and RX data registers can be accessed
as regular registers.
 
ulClock
 
This is the clock constant which is divided by the desired baud
to get the value programmed into the part. The formula for this
for 9600 baud is:
 
chip_divisor_value = ulClock / 9600.
 
NOTE: When ulClock is 0, the correct value for a PC (115,200) is
used.
 
ulIntVector
 
This is the interrupt vector number associated with this chip.
 
/serial/z85c30.c
0,0 → 1,889
/*
* This file contains the console driver chip level routines for the
* Zilog z85c30 chip.
*
* The Zilog Z8530 is also available as:
*
* + Intel 82530
* + AMD ???
*
* 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: z85c30.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <rtems/libio.h>
#include <stdlib.h>
 
#include <libchip/serial.h>
#include "z85c30_p.h"
#include "sersupp.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 = {
libchip_serial_default_probe, /* deviceProbe */
z85c30_open, /* deviceFirstOpen */
NULL, /* deviceLastClose */
NULL, /* deviceRead */
z85c30_write_support_int, /* deviceWrite */
z85c30_initialize_interrupts, /* deviceInitialize */
z85c30_write_polled, /* deviceWritePolled */
NULL, /* deviceSetAttributes */
TRUE /* deviceOutputUsesInterrupts */
};
 
console_fns z85c30_fns_polled = {
libchip_serial_default_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 */
NULL, /* deviceSetAttributes */
FALSE /* deviceOutputUsesInterrupts */
};
 
extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
 
/*
* z85c30_initialize_port
*
* initialize a z85c30 Port
*/
 
Z85C30_STATIC void z85c30_initialize_port(
int minor
)
{
unsigned32 ulCtrlPort;
unsigned32 ulBaudDivisor;
setRegister_f setReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Using register 4
* Set up the clock rate is 16 times the data
* rate, 8 bit sync char, 1 stop bit, no parity
*/
 
(*setReg)( 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
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS );
 
/*
* Set up for 8 bits/character on transmit
* with transmitter disable via register 5
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS );
 
/*
* Clear misc control bits
*/
(*setReg)( 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
*/
(*setReg)(
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].ulClock,
(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.
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
 
/*
* using register 13
* Setup the upper 8 bits time constant
*/
(*setReg)( 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.
*/
(*setReg)(
ulCtrlPort,
SCC_WR0_SEL_WR14,
SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_NULL
);
 
/*
* We are only interested in CTS state changes
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR15, SCC_WR15_CTS_IE );
 
/*
* Reset errors
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
 
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_ERR_RST );
 
/*
* Enable the receiver via register 3
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN );
 
/*
* Enable the transmitter pins set via register 5.
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN );
 
/*
* Disable interrupts
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR1, 0 );
 
/*
* Reset TX CRC
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_CRC );
 
/*
* Reset interrupts
*/
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
}
 
/*
* z85c30_open
*/
 
Z85C30_STATIC int z85c30_open(
int major,
int minor,
void *arg
)
{
 
z85c30_initialize_port(minor);
 
/*
* Assert DTR
*/
 
if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
z85c30_assert_DTR(minor);
}
 
return(RTEMS_SUCCESSFUL);
}
 
/*
* z85c30_close
*/
 
Z85C30_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_init
*/
 
Z85C30_STATIC void z85c30_init(int minor)
{
unsigned32 ulCtrlPort;
unsigned8 dummy;
z85c30_context *pz85c30Context;
setRegister_f setReg;
getRegister_f getReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
getReg = Console_Port_Tbl[minor].getRegister;
 
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
*/
dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
 
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_A_RST);
 
} else {
/*
* This is channel B
*/
/*
* Ensure port state machine is reset
*/
dummy = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
 
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
}
}
 
/*
* These routines provide control of the RTS and DTR lines
*/
 
/*
* z85c30_assert_RTS
*/
 
Z85C30_STATIC int z85c30_assert_RTS(int minor)
{
rtems_interrupt_level Irql;
z85c30_context *pz85c30Context;
setRegister_f setReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
 
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
/*
* Assert RTS
*/
 
rtems_interrupt_disable(Irql);
pz85c30Context->ucModemCtrl|=SCC_WR5_RTS;
(*setReg)(
Console_Port_Tbl[minor].ulCtrlPort1,
SCC_WR0_SEL_WR5,
pz85c30Context->ucModemCtrl
);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* z85c30_negate_RTS
*/
 
Z85C30_STATIC int z85c30_negate_RTS(int minor)
{
rtems_interrupt_level Irql;
z85c30_context *pz85c30Context;
setRegister_f setReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
 
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
/*
* Negate RTS
*/
 
rtems_interrupt_disable(Irql);
pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS;
(*setReg)(
Console_Port_Tbl[minor].ulCtrlPort1,
SCC_WR0_SEL_WR5,
pz85c30Context->ucModemCtrl
);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* These flow control routines utilise a connection from the local DTR
* line to the remote CTS line
*/
 
/*
* z85c30_assert_DTR
*/
 
Z85C30_STATIC int z85c30_assert_DTR(int minor)
{
rtems_interrupt_level Irql;
z85c30_context *pz85c30Context;
setRegister_f setReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
 
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
/*
* Assert DTR
*/
 
rtems_interrupt_disable(Irql);
pz85c30Context->ucModemCtrl|=SCC_WR5_DTR;
(*setReg)(
Console_Port_Tbl[minor].ulCtrlPort1,
SCC_WR0_SEL_WR5,
pz85c30Context->ucModemCtrl
);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* z85c30_negate_DTR
*/
 
Z85C30_STATIC int z85c30_negate_DTR(int minor)
{
rtems_interrupt_level Irql;
z85c30_context *pz85c30Context;
setRegister_f setReg;
 
setReg = Console_Port_Tbl[minor].setRegister;
 
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
/*
* Negate DTR
*/
 
rtems_interrupt_disable(Irql);
pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR;
(*setReg)(
Console_Port_Tbl[minor].ulCtrlPort1,
SCC_WR0_SEL_WR5,
pz85c30Context->ucModemCtrl
);
rtems_interrupt_enable(Irql);
return 0;
}
 
/*
* z85c30_set_attributes
*
* This function sets the SCC channel to reflect the requested termios
* port settings.
*/
 
Z85C30_STATIC int z85c30_set_attributes(
int minor,
const struct termios *t
)
{
unsigned32 ulCtrlPort;
unsigned32 ulBaudDivisor;
unsigned32 wr3;
unsigned32 wr4;
unsigned32 wr5;
int baud_requested;
setRegister_f setReg;
rtems_interrupt_level Irql;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Calculate the baud rate divisor
*/
 
baud_requested = t->c_cflag & CBAUD;
if (!baud_requested)
baud_requested = B9600; /* default to 9600 baud */
 
ulBaudDivisor = Z85C30_Baud(
(unsigned32) Console_Port_Tbl[minor].ulClock,
(unsigned32) termios_baud_to_number( baud_requested )
);
 
wr3 = SCC_WR3_RX_EN;
wr4 = SCC_WR4_16_CLOCK;
wr5 = SCC_WR5_TX_EN;
 
/*
* Parity
*/
 
if (t->c_cflag & PARENB) {
wr4 |= SCC_WR4_PAR_EN;
if (!(t->c_cflag & PARODD))
wr4 |= SCC_WR4_PAR_EVEN;
}
 
/*
* Character Size
*/
 
if (t->c_cflag & CSIZE) {
switch (t->c_cflag & CSIZE) {
case CS5: break;
case CS6: wr3 |= SCC_WR3_RX_6_BITS; wr5 |= SCC_WR5_TX_6_BITS; break;
case CS7: wr3 |= SCC_WR3_RX_7_BITS; wr5 |= SCC_WR5_TX_7_BITS; break;
case CS8: wr3 |= SCC_WR3_RX_8_BITS; wr5 |= SCC_WR5_TX_8_BITS; break;
}
} else {
wr3 |= SCC_WR3_RX_8_BITS; /* default to 9600,8,N,1 */
wr5 |= SCC_WR5_TX_8_BITS; /* default to 9600,8,N,1 */
}
 
/*
* Stop Bits
*/
 
if (t->c_cflag & CSTOPB) {
wr4 |= SCC_WR4_2_STOP; /* 2 stop bits */
} else {
wr4 |= SCC_WR4_1_STOP; /* 1 stop bits */
}
 
/*
* Now actually set the chip
*/
 
rtems_interrupt_disable(Irql);
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );
 
/*
* 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.
*/
 
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
 
/*
* using register 13
* Setup the upper 8 bits time constant
*/
 
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
 
rtems_interrupt_enable(Irql);
 
return 0;
}
 
/*
* z85c30_process
*
* This is the per port ISR handler.
*/
 
Z85C30_STATIC void z85c30_process(
int minor,
unsigned8 ucIntPend
)
{
unsigned32 ulCtrlPort;
volatile unsigned8 z85c30_status;
unsigned char cChar;
setRegister_f setReg;
getRegister_f getReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
getReg = Console_Port_Tbl[minor].getRegister;
 
/*
* Deal with any received characters
*/
 
while (ucIntPend&SCC_RR3_B_RX_IP)
{
z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
break;
}
 
/*
* Return the character read.
*/
 
cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
 
rtems_termios_enqueue_raw_characters(
Console_Port_Data[minor].termios_data,
&cChar,
1
);
}
 
/*
* There could be a race condition here if there is not yet a TX
* interrupt pending but the buffer is empty. This condition has
* been seen before on other z8530 drivers but has not been seen
* with this one. The typical solution is to use "vector includes
* status" or to only look at the interrupts actually pending
* in RR3.
*/
 
while (TRUE) {
z85c30_status = (*getReg)(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 0
if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
/*
* We can't transmit yet
*/
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
/*
* The next state change of CTS will wake us up
*/
break;
}
#endif
rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
if (rtems_termios_dequeue_characters(
Console_Port_Data[minor].termios_data, 1)) {
if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
z85c30_negate_RTS(minor);
}
Console_Port_Data[minor].bActive = FALSE;
z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
break;
}
 
}
 
if (ucIntPend & SCC_RR3_B_EXT_IP) {
/*
* Clear the external status interrupt
*/
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
}
 
/*
* Reset interrupts
*/
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
}
 
/*
* z85c30_isr
*
* This is the ISR handler for each Z8530.
*/
 
Z85C30_STATIC rtems_isr z85c30_isr(
rtems_vector_number vector
)
{
int minor;
unsigned32 ulCtrlPort;
volatile unsigned8 ucIntPend;
volatile unsigned8 ucIntPendPort;
getRegister_f getReg;
 
for (minor=0;minor<Console_Port_Count;minor++) {
if(Console_Port_Tbl[minor].ulIntVector == vector &&
Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
getReg = Console_Port_Tbl[minor].getRegister;
do {
ucIntPend = (*getReg)(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_enable_interrupts
*
* This routine enables the specified interrupts for this minor.
*/
 
Z85C30_STATIC void z85c30_enable_interrupts(
int minor,
int interrupt_mask
)
{
unsigned32 ulCtrlPort;
setRegister_f setReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
}
 
/*
* z85c30_initialize_interrupts
*
* This routine initializes the port to use interrupts.
*/
 
Z85C30_STATIC void z85c30_initialize_interrupts(
int minor
)
{
unsigned32 ulCtrlPort1;
unsigned32 ulCtrlPort2;
setRegister_f setReg;
 
ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
setReg = Console_Port_Tbl[minor].setRegister;
 
 
z85c30_init(minor);
 
Console_Port_Data[minor].bActive=FALSE;
 
z85c30_initialize_port( minor );
 
if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
z85c30_negate_RTS(minor);
}
 
set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
 
z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
 
(*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0); /* XXX vector */
(*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
 
/*
* Reset interrupts
*/
 
(*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
}
 
/*
* z85c30_write_support_int
*
* Console Termios output entry point.
*
*/
 
Z85C30_STATIC int z85c30_write_support_int(
int minor,
const char *buf,
int len)
{
unsigned32 Irql;
unsigned32 ulCtrlPort;
setRegister_f setReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* We are using interrupt driven output and termios only sends us
* one character at a time.
*/
 
if ( !len )
return 0;
 
/*
* Put the character out and enable interrupts if necessary.
*/
 
if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
z85c30_assert_RTS(minor);
}
rtems_interrupt_disable(Irql);
if ( Console_Port_Data[minor].bActive == FALSE) {
Console_Port_Data[minor].bActive = TRUE;
z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
}
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
rtems_interrupt_enable(Irql);
 
return 1;
}
 
/*
* z85c30_inbyte_nonblocking_polled
*
* This routine polls for a character.
*/
 
Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
int minor
)
{
volatile unsigned8 z85c30_status;
unsigned32 ulCtrlPort;
getRegister_f getReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
getReg = Console_Port_Tbl[minor].getRegister;
 
/*
* return -1 if a character is not available.
*/
z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
return -1;
}
 
/*
* Return the character read.
*/
 
return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
}
 
/*
* z85c30_write_support_polled
*
* Console Termios output entry point.
*
*/
 
Z85C30_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) {
z85c30_write_polled(minor, *buf++);
nwrite++;
}
 
/*
* return the number of bytes written.
*/
return nwrite;
}
 
/*
* z85c30_write_polled
*
* This routine transmits a character using polling.
*/
 
Z85C30_STATIC void z85c30_write_polled(
int minor,
char cChar
)
{
volatile unsigned8 z85c30_status;
unsigned32 ulCtrlPort;
getRegister_f getReg;
setRegister_f setReg;
 
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
getReg = Console_Port_Tbl[minor].getRegister;
setReg = Console_Port_Tbl[minor].setRegister;
 
/*
* Wait for the Transmit buffer to indicate that it is empty.
*/
 
z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );
 
while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
/*
* Yield while we wait
*/
#if 0
if (_System_state_Is_up(_System_state_Get())) {
rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
}
#endif
z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
}
 
/*
* Write the character.
*/
 
(*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );
}
 
/serial/mc68681_reg4.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 32-bit boundaries
*
* 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: mc68681_reg4.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _MC68681_MULTIPLIER 4
#define _MC68681_NAME(_X) _X##_4
#define _MC68681_TYPE unsigned8
 
#include "mc68681_reg.c"
 
/configure.in
0,0 → 1,44
dnl Process this file with autoconf to produce a configure script.
dnl
dnl $Id: configure.in,v 1.2 2001-09-27 12:01:40 chris Exp $
 
AC_PREREQ(2.13)
AC_INIT(rtc)
RTEMS_TOP(../../..)
AC_CONFIG_AUX_DIR(../../..)
 
RTEMS_CANONICAL_TARGET_CPU
AM_INIT_AUTOMAKE(rtems-c-src-libchip,$RTEMS_VERSION,no)
AM_MAINTAINER_MODE
 
RTEMS_ENABLE_NETWORKING
RTEMS_ENABLE_BARE
 
RTEMS_ENV_RTEMSBSP
 
RTEMS_CHECK_CPU
RTEMS_CANONICAL_HOST
 
RTEMS_PROJECT_ROOT
 
RTEMS_PROG_CC_FOR_TARGET
RTEMS_CANONICALIZE_TOOLS
 
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
RTEMS_CHECK_NETWORKING(RTEMS_BSP)
 
# pick up all the Makefiles in required parts of the tree
if test "$RTEMS_CPU" = "unix"; then
## HACK: Suppress libchip for unix
AC_MSG_ERROR(Can't build libchip for $RTEMS_CPU)
fi
 
AM_CONDITIONAL(HAS_NETWORKING, test "$HAS_NETWORKING" = "yes")
 
# Explicitly list all Makefiles here
AC_OUTPUT(
Makefile
network/Makefile
rtc/Makefile
serial/Makefile
)
/rtc/README.ds1643
0,0 → 1,7
#
# $Id: README.ds1643,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
The Mostek M48T08 is compatible with the Dallas Semiconductor DS1643. Please
use that driver.
 
/rtc/m48t08_reg.c
0,0 → 1,61
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are only byte-aligned (no address gaps)
*
* 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: m48t08_reg.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
 
#ifndef _M48T08_MULTIPLIER
#define _M48T08_MULTIPLIER 1
#define _M48T08_NAME(_X) _X
#define _M48T08_TYPE unsigned8
#endif
 
#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \
(_M48T08_TYPE *)((_base) + ((_reg) * _M48T08_MULTIPLIER ))
 
/*
* M48T08 Get Register Routine
*/
 
unsigned32 _M48T08_NAME(m48t08_get_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum
)
{
_M48T08_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
return *port;
}
 
/*
* M48T08 Set Register Routine
*/
 
void _M48T08_NAME(m48t08_set_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
)
{
_M48T08_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
*port = ucData;
}
/rtc/README.icm7170
0,0 → 1,52
#
# $Id: README.icm7170,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
 
Configuration Table Use
=======================
 
sDeviceName
 
The name of this device.
 
deviceType
 
This field must be RTC_ICM7170.
 
pDeviceFns
 
The device interface control table. This must be icm7170_fns.
 
deviceProbe
 
This is the address of the routine which probes to see if the device
is present.
 
pDeviceParams
 
This field specifies the clock frequency. It may be one of the
following:
ICM7170_AT_32_KHZ
ICM7170_AT_1_MHZ
ICM7170_AT_2_MHZ
ICM7170_AT_4_MHZ
 
ulCtrlPort1
 
This field is the base address of the RTC area of the chip.
 
ulCtrlPort2
 
This field is ignored.
 
ulDataPort
 
This field is ignored.
 
 
getRegister
setRegister
 
These follow standard conventions.
 
/rtc/STATUS
0,0 → 1,37
#
# $Id: STATUS,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
General
=======
 
+ It would be nice to utilize the interrupt capabilities of some
RTC parts. This could be used to trigger checking the software
clock against the hardware clock.
 
+ The periodic capability of most RTCs is not suitable for use
as a general purpose flexible clock tick source. For example,
many RTCs generate only a handful of periods with 100 Hz being the
most frequent.
 
+ The tick field is not set on get. Anything smaller than a second
is ignored on set and get operations.
 
+ Day of week is ignored since RTEMS does not set it internally.
 
+ There is no attempt in RTEMS to know about time zones.
 
Harris ICM7170
==============
 
+ Tested on a DMV177.
 
+ Interrupt capabilities are ignored.
 
Mostek 48T08
============
 
+ Untested.
 
+ NVRAM is ignored.
 
/rtc/m48t08.c
0,0 → 1,164
/*
* This file interfaces with the real-time clock found in
* a Mostek M48T08 or M48T18 or compatibles.
*
* Year 2K Notes:
*
* This chip only uses a two digit field to store the year. This
* code uses the RTEMS Epoch as a pivot year. This lets us map the
* two digit year field as follows:
*
* + two digit years 0-87 are mapped to 2000-2087.
* + two digit years 88-99 are mapped to 1988-1999.
*
* This is less than the time span supported by RTEMS.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: m48t08.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <libchip/rtc.h>
#include <libchip/m48t08.h>
 
/*
* Control register bits
*/
 
#define M48T08_CONTROL_WRITE 0x80
#define M48T08_CONTROL_READ 0x40
#define M48T08_CONTROL_SIGN 0x20
 
/*
* m48t08_initialize
*/
 
void m48t08_initialize(
int minor
)
{
}
 
/*
* m48t08_get_time
*/
 
#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10))
 
int m48t08_get_time(
int minor,
rtems_time_of_day *time
)
{
unsigned32 m48t08;
getRegister_f getReg;
setRegister_f setReg;
unsigned8 controlReg;
unsigned32 value1;
unsigned32 value2;
 
m48t08 = RTC_Table[ minor ].ulCtrlPort1;
getReg = RTC_Table[ minor ].getRegister;
setReg = RTC_Table[ minor ].setRegister;
 
/*
* Put the RTC into read mode
*/
 
controlReg = (*getReg)( m48t08, M48T08_CONTROL );
(*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_READ );
value1 = (*getReg)( m48t08, M48T08_YEAR );
value2 = From_BCD( value1 );
if ( value2 < 88 )
time->year = 2000 + value2;
else
time->year = 1900 + value2;
 
value1 = (*getReg)( m48t08, M48T08_MONTH );
time->month = From_BCD( value1 );
 
value1 = (*getReg)( m48t08, M48T08_DATE );
time->day = From_BCD( value1 );
 
value1 = (*getReg)( m48t08, M48T08_HOUR );
time->hour = From_BCD( value1 );
 
value1 = (*getReg)( m48t08, M48T08_MINUTE );
time->minute = From_BCD( value1 );
 
value1 = (*getReg)( m48t08, M48T08_SECOND );
time->second = From_BCD( value1 );
time->ticks = 0;
 
/*
* Put the RTC back into normal mode.
*/
 
(*setReg)( m48t08, M48T08_CONTROL, controlReg );
 
return 0;
}
 
/*
* m48t08_set_time
*/
 
int m48t08_set_time(
int minor,
rtems_time_of_day *time
)
{
unsigned32 m48t08;
getRegister_f getReg;
setRegister_f setReg;
unsigned8 controlReg;
 
m48t08 = RTC_Table[ minor ].ulCtrlPort1;
getReg = RTC_Table[ minor ].getRegister;
setReg = RTC_Table[ minor ].setRegister;
 
/*
* Put the RTC into read mode
*/
 
controlReg = (*getReg)( m48t08, M48T08_CONTROL );
(*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_WRITE );
if ( time->year >= 2088 )
rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
 
(*setReg)( m48t08, M48T08_YEAR, To_BCD(time->year % 100) );
(*setReg)( m48t08, M48T08_MONTH, To_BCD(time->month) );
(*setReg)( m48t08, M48T08_DATE, To_BCD(time->day) );
(*setReg)( m48t08, M48T08_HOUR, To_BCD(time->hour) );
(*setReg)( m48t08, M48T08_MINUTE, To_BCD(time->minute) );
(*setReg)( m48t08, M48T08_SECOND, To_BCD(time->second) );
/*
* Put the RTC back into normal mode.
*/
 
(*setReg)( m48t08, M48T08_CONTROL, controlReg );
 
return 0;
}
 
/*
* Driver function table
*/
 
rtc_fns m48t08_fns = {
m48t08_initialize,
m48t08_get_time,
m48t08_set_time
};
 
/rtc/icm7170_reg2.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 16-bit boundaries
*
* 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: icm7170_reg2.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _ICM7170_MULTIPLIER 2
#define _ICM7170_NAME(_X) _X##_2
#define _ICM7170_TYPE unsigned8
 
#include "icm7170_reg.c"
 
/rtc/icm7170_reg4.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 32-bit boundaries
*
* 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: icm7170_reg4.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _ICM7170_MULTIPLIER 4
#define _ICM7170_NAME(_X) _X##_4
#define _ICM7170_TYPE unsigned8
 
#include "icm7170_reg.c"
 
/rtc/m48t08.h
0,0 → 1,89
/*
* This file contains the definitions for the following real-time clocks:
*
* + Mostek M48T08
* + Mostek M48T18
* + Dallas Semiconductor DS1643
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: m48t08.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __LIBCHIP_M48T08_h
#define __LIBCHIP_M48T08_h
 
/*
* Register indices
*/
 
#define M48T08_CONTROL 0
#define M48T08_SECOND 1
#define M48T08_MINUTE 2
#define M48T08_HOUR 3
#define M48T08_DAY_OF_WEEK 4
#define M48T08_DATE 5
#define M48T08_MONTH 6
#define M48T08_YEAR 7
/*
* Driver function table
*/
 
extern rtc_fns m48t08_fns;
 
/*
* Default register access routines
*/
 
unsigned32 m48t08_get_register( /* registers are at 1 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void m48t08_set_register(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 m48t08_get_register_2( /* registers are at 2 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void m48t08_set_register_2(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 m48t08_get_register_4( /* registers are at 4 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void m48t08_set_register_4(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 m48t08_get_register_8( /* registers are at 8 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void m48t08_set_register_8(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
#endif
/* end of include file */
/rtc/icm7170_reg8.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 64-bit boundaries
*
* 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: icm7170_reg8.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _ICM7170_MULTIPLIER 8
#define _ICM7170_NAME(_X) _X##_8
#define _ICM7170_TYPE unsigned8
 
#include "icm7170_reg.c"
 
/rtc/README.m48t08
0,0 → 1,48
#
# $Id: README.m48t08,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
 
Configuration Table Use
=======================
 
sDeviceName
 
The name of this device.
 
deviceType
 
This field must be RTC_M48T08.
 
pDeviceFns
 
The device interface control table. This must be m48t08_fns.
 
deviceProbe
 
This is the address of the routine which probes to see if the device
is present.
 
pDeviceParams
 
This is ignored and should be NULL.
 
ulCtrlPort1
 
This field is the base address of the RTC area of the chip. The
NVRAM portion of the chip is ignored.
 
ulCtrlPort2
 
This field is ignored.
 
ulDataPort
 
This field is ignored.
 
 
getRegister
setRegister
 
These follow standard conventions.
 
/rtc/rtcprobe.c
0,0 → 1,23
/*
* This file contains the default Real-Time Clock probe routine.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: rtcprobe.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <libchip/rtc.h>
 
 
boolean rtc_probe(
int minor
)
{
return TRUE;
}
/rtc/README.m48t18
0,0 → 1,5
#
# $Id: README.m48t18,v 1.2 2001-09-27 12:01:42 chris Exp $
#
 
This is supported by the m48t08 driver.
/rtc/m48t08_reg2.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 16-bit boundaries
*
* 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: m48t08_reg2.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _M48T08_MULTIPLIER 2
#define _M48T08_NAME(_X) _X##_2
#define _M48T08_TYPE unsigned8
 
#include "m48t08_reg.c"
 
/rtc/icm7170_reg.c
0,0 → 1,61
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are only byte-aligned (no address gaps)
*
* 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: icm7170_reg.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
 
#ifndef _ICM7170_MULTIPLIER
#define _ICM7170_MULTIPLIER 1
#define _ICM7170_NAME(_X) _X
#define _ICM7170_TYPE unsigned8
#endif
 
#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \
(_ICM7170_TYPE *)((_base) + ((_reg) * _ICM7170_MULTIPLIER ))
 
/*
* ICM7170 Get Register Routine
*/
 
unsigned32 _ICM7170_NAME(icm7170_get_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum
)
{
_ICM7170_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
return *port;
}
 
/*
* ICM7170 Set Register Routine
*/
 
void _ICM7170_NAME(icm7170_set_register)(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
)
{
_ICM7170_TYPE *port;
 
port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
 
*port = ucData;
}
/rtc/m48t08_reg4.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 32-bit boundaries
*
* 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: m48t08_reg4.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _M48T08_MULTIPLIER 4
#define _M48T08_NAME(_X) _X##_4
#define _M48T08_TYPE unsigned8
 
#include "m48t08_reg.c"
 
/rtc/icm7170.c
0,0 → 1,175
/*
* This file interfaces with the real-time clock found in
* a Harris ICM7170
*
* Year 2K Notes:
*
* This chip only uses a two digit field to store the year. This
* code uses the RTEMS Epoch as a pivot year. This lets us map the
* two digit year field as follows:
*
* + two digit years 0-87 are mapped to 2000-2087.
* + two digit years 88-99 are mapped to 1988-1999.
*
* This is less than the time span supported by RTEMS.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: icm7170.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#include <rtems.h>
#include <libchip/rtc.h>
#include <libchip/icm7170.h>
 
/*
* Control register bits
*/
 
/* XXX */
 
/*
* icm7170_initialize
*/
 
void icm7170_initialize(
int minor
)
{
unsigned32 icm7170;
setRegister_f setReg;
unsigned32 clock;
 
icm7170 = RTC_Table[ minor ].ulCtrlPort1;
setReg = RTC_Table[ minor ].setRegister;
 
/*
* Initialize the RTC with the proper clock frequency
*/
 
clock = (unsigned32) RTC_Table[ minor ].pDeviceParams;
(*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock );
}
 
/*
* icm7170_get_time
*/
 
int icm7170_get_time(
int minor,
rtems_time_of_day *time
)
{
unsigned32 icm7170;
getRegister_f getReg;
setRegister_f setReg;
unsigned32 year;
 
icm7170 = RTC_Table[ minor ].ulCtrlPort1;
getReg = RTC_Table[ minor ].getRegister;
setReg = RTC_Table[ minor ].setRegister;
 
/*
* Put the RTC into read mode
*/
 
(void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS );
 
/*
* Now get the time
*/
 
 
year = (*getReg)( icm7170, ICM7170_YEAR );
if ( year < 88 )
year += 2000;
else
year += 1900;
 
time->year = year;
time->month = (*getReg)( icm7170, ICM7170_MONTH );
time->day = (*getReg)( icm7170, ICM7170_DATE );
time->hour = (*getReg)( icm7170, ICM7170_HOUR );
time->minute = (*getReg)( icm7170, ICM7170_MINUTE );
time->second = (*getReg)( icm7170, ICM7170_SECOND );
time->ticks = 0;
 
/*
* Put the RTC back into normal mode.
*/
 
(void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS );
 
return 0;
}
 
/*
* icm7170_set_time
*/
 
int icm7170_set_time(
int minor,
rtems_time_of_day *time
)
{
unsigned32 icm7170;
getRegister_f getReg;
setRegister_f setReg;
unsigned32 year;
unsigned32 clock;
 
icm7170 = RTC_Table[ minor ].ulCtrlPort1;
getReg = RTC_Table[ minor ].getRegister;
setReg = RTC_Table[ minor ].setRegister;
clock = (unsigned32) RTC_Table[ minor ].pDeviceParams;
 
year = time->year;
 
if ( year >= 2088 )
rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
 
if ( year >= 2000 )
year -= 2000;
else
year -= 1900;
 
(*setReg)( icm7170, ICM7170_CONTROL, 0x04 | clock );
 
(*setReg)( icm7170, ICM7170_YEAR, year );
(*setReg)( icm7170, ICM7170_MONTH, time->month );
(*setReg)( icm7170, ICM7170_DATE, time->day );
(*setReg)( icm7170, ICM7170_HOUR, time->hour );
(*setReg)( icm7170, ICM7170_MINUTE, time->minute );
(*setReg)( icm7170, ICM7170_SECOND, time->second );
/*
* This is not really right.
*/
 
(*setReg)( icm7170, ICM7170_DAY_OF_WEEK, 1 );
 
/*
* Put the RTC back into normal mode.
*/
 
(*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock );
 
return 0;
}
 
/*
* Driver function table
*/
 
rtc_fns icm7170_fns = {
icm7170_initialize,
icm7170_get_time,
icm7170_set_time
};
 
/rtc/Makefile.am
0,0 → 1,52
##
## $Id: Makefile.am,v 1.2 2001-09-27 12:01:42 chris Exp $
##
 
AUTOMAKE_OPTIONS = foreign 1.4
 
LIBNAME = librtcio
LIB = ${ARCH}/${LIBNAME}.a
 
C_FILES = rtcprobe.c icm7170.c icm7170_reg.c icm7170_reg2.c icm7170_reg4.c \
icm7170_reg8.c m48t08.c m48t08_reg.c m48t08_reg2.c m48t08_reg4.c \
m48t08_reg8.c
 
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
 
H_FILES = rtc.h icm7170.h m48t08.h
noinst_HEADERS = $(H_FILES)
 
OBJS = $(C_O_FILES)
 
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../automake/lib.am
 
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip \
$(noinst_HEADERS:%=$(PROJECT_INCLUDE)/libchip/%)
 
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
 
$(PROJECT_INCLUDE)/libchip:
@$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/libchip/%.h: %.h
$(INSTALL_DATA) $< $@
 
#
# Add local stuff here using +=
#
 
AM_CFLAGS += $(LIBC_DEFINES)
 
$(LIB): ${OBJS}
$(make-library)
 
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
$(INSTALL_DATA) $< $@
 
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
 
DOC_FILES = README.ds1643 README.icm7170 README.m48t08 README.m48t18 STATUS
 
EXTRA_DIST = $(C_FILES) $(DOC_FILES)
 
include $(top_srcdir)/../../../automake/local.am
/rtc/m48t08_reg8.c
0,0 → 1,24
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
*
* + registers are accessed as bytes
* + registers are on 64-bit boundaries
*
* 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: m48t08_reg8.c,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#define _M48T08_MULTIPLIER 8
#define _M48T08_NAME(_X) _X##_8
#define _M48T08_TYPE unsigned8
 
#include "m48t08_reg.c"
 
/rtc/icm7170.h
0,0 → 1,99
/*
* This file contains the definitions for the following real-time clocks:
*
* + Harris Semiconduction ICM7170
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: icm7170.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __LIBCHIP_ICM7170_h
#define __LIBCHIP_ICM7170_h
 
/*
* Register indices
*/
 
#define ICM7170_CONTROL 0x11
 
 
#define ICM7170_COUNTER_HUNDREDTHS 0x00
#define ICM7170_HOUR 0x01
#define ICM7170_MINUTE 0x02
#define ICM7170_SECOND 0x03
#define ICM7170_MONTH 0x04
#define ICM7170_DATE 0x05
#define ICM7170_YEAR 0x06
#define ICM7170_DAY_OF_WEEK 0x07
 
/*
* Configuration information in the parameters field
*/
 
#define ICM7170_AT_32_KHZ 0x00
#define ICM7170_AT_1_MHZ 0x01
#define ICM7170_AT_2_MHZ 0x02
#define ICM7170_AT_4_MHZ 0x03
 
/*
* Driver function table
*/
 
extern rtc_fns icm7170_fns;
 
/*
* Default register access routines
*/
 
unsigned32 icm7170_get_register( /* registers are at 1 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void icm7170_set_register(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 icm7170_get_register_2( /* registers are at 2 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void icm7170_set_register_2(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 icm7170_get_register_4( /* registers are at 4 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void icm7170_set_register_4(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
unsigned32 icm7170_get_register_8( /* registers are at 8 byte boundaries */
unsigned32 ulCtrlPort, /* and accessed as bytes */
unsigned8 ucRegNum
);
 
void icm7170_set_register_8(
unsigned32 ulCtrlPort,
unsigned8 ucRegNum,
unsigned32 ucData
);
 
#endif
/* end of include file */
/rtc/rtc.h
0,0 → 1,80
/*
* This file contains the Real-Time Clock definitions.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* 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: rtc.h,v 1.2 2001-09-27 12:01:42 chris Exp $
*/
 
#ifndef __LIBCHIP_RTC_h
#define __LIBCHIP_RTC_h
 
/*
* Types for get and set register routines
*/
 
typedef unsigned32 (*getRegister_f)(unsigned32 port, unsigned8 register);
typedef void (*setRegister_f)(
unsigned32 port, unsigned8 reg, unsigned32 value);
 
typedef struct _rtc_fns {
void (*deviceInitialize)(int minor);
int (*deviceGetTime)(int minor, rtems_time_of_day *time);
int (*deviceSetTime)(int minor, rtems_time_of_day *time);
} rtc_fns;
 
typedef enum {
RTC_M48T08, /* SGS-Thomsom M48T08 or M48T18 */
RTC_ICM7170, /* Harris ICM-7170 */
RTC_CUSTOM /* BSP specific driver */
} rtc_devs;
 
/*
* Each field is interpreted thus:
*
* sDeviceName This is the name of the device.
*
* deviceType This indicates the chip type.
*
* pDeviceFns This is a pointer to the set of driver routines to use.
*
* pDeviceParams This contains either device specific data or a pointer to a
* device specific information table.
*
* ulCtrlPort1 This is the primary control port number for the device.
*
* ulCtrlPort2 This is the secondary control port number.
*
* ulDataPort This is the port number for the data port of the device
*
* getRegister This is the routine used to read register values.
*
* setRegister This is the routine used to write register values.
*/
 
typedef struct _rtc_tbl {
char *sDeviceName;
rtc_devs deviceType;
rtc_fns *pDeviceFns;
boolean (*deviceProbe)(int minor);
void *pDeviceParams;
unsigned32 ulCtrlPort1;
unsigned32 ulDataPort;
getRegister_f getRegister;
setRegister_f setRegister;
} rtc_tbl;
 
extern rtc_tbl RTC_Table[];
extern unsigned long RTC_Count;
 
 
boolean rtc_probe( int minor );
 
#endif
/* end of include file */
/Makefile.am
0,0 → 1,11
##
## $Id: Makefile.am,v 1.2 2001-09-27 12:01:40 chris Exp $
##
 
AUTOMAKE_OPTIONS = foreign 1.4
ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal
 
SUBDIRS = rtc serial network
 
include $(top_srcdir)/../../../automake/subdirs.am
include $(top_srcdir)/../../../automake/local.am
/network/README.dec21140
0,0 → 1,120
#
# $Id: README.dec21140,v 1.2 2001-09-27 12:01:41 chris Exp $
#
 
This TULIP driver can be used on BSPs that support PCI bus.
 
It can handle any DEC21140 and DEC21143 based Ethernet controller
although the DEC21143 support has only been tested on Intel.
It works on big or little endian target.
 
The DEC21140 has been tested with powerpc/mcp750 BSP (OnBoard Ethernet
controller) and i386/pc386 BSP (D-Link DFE-500TX Ethernet board).
 
The DEC21143 has been tested only on the i386/pc386 using
the Kingston KNE100TX with 21143PD chip.
 
*****************************************************************
******** ***************
******** tests with ttcp benchmark for DEC driver ***************
******** optimization ***************
******** ***************
*****************************************************************
 
 
LINUX -> LINUX-ix86
 
Transmitter :
 
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> genesis
ttcp-t: 16777216 bytes in 1.87 real seconds = 8775.25 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.93, calls/sec = 1096.91
ttcp-t: 0.0user 0.9sys 0:01real 51% 0i+0d 0maxrss 0+2pf 0+0csw
 
Receiver :
 
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 1.88 real seconds = 8706.53 KB/sec +++
ttcp-r: 10802 I/O calls, msec/call = 0.18, calls/sec = 5740.23
ttcp-r: 0.0user 0.2sys 0:01real 13% 0i+0d 0maxrss 0+2pf 0+0csw
 
==============================================================
==============================================================
==============================================================
 
LINUX -> RTEMS-ix86 with tulip driver from pc386 bsp
 
Transmitter :
 
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100
ttcp-t: 16777216 bytes in 1.98 real seconds = 8294.76 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.99, calls/sec = 1036.85
ttcp-t: 0.0user 0.1sys 0:01real 9% 0i+0d 0maxrss 0+2pf 0+0csw
 
Receiver :
 
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.03 real seconds = 8065.14 KB/sec +++
ttcp-r: 3088 I/O calls, msec/call = 0.67, calls/sec = 1520.09
ttcp-r: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
 
==============================================================
==============================================================
==============================================================
 
RTEMS-ix86 with tulip driver from pc386 bsp -> LINUX
 
Transmitter :
 
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126
ttcp-t: 16777216 bytes in 2.76 real seconds = 5938.77 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 1.38, calls/sec = 742.35
ttcp-t: 0.0user 2.5sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
 
Receiver :
 
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.75 real seconds = 5948.53 KB/sec +++
ttcp-r: 11349 I/O calls, msec/call = 0.25, calls/sec = 4120.48
ttcp-r: 0.0user 0.1sys 0:02real 6% 0i+0d 0maxrss 0+2pf 0+0csw
 
==============================================================
==============================================================
==============================================================
 
LINUX -> RTEMS-ix86 with optimized tulip driver
 
Transmitter :
 
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> neil-young-100
ttcp-t: 16777216 bytes in 1.73 real seconds = 9470.13 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 0.87, calls/sec = 1183.77
ttcp-t: 0.0user 0.1sys 0:01real 6% 0i+0d 0maxrss 0+2pf 0+0csw
 
Receiver :
 
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 1.76 real seconds = 9315.33 KB/sec +++
ttcp-r: 4558 I/O calls, msec/call = 0.40, calls/sec = 2591.51
ttcp-r: 0.0user 1.7sys 0:01real 100% 0i+0d 0maxrss 0+0pf 0+0csw
 
==============================================================
==============================================================
==============================================================
 
RTEMS-ix86 with optimized tulip driver -> LINUX
 
Transmitter :
 
ttcp-t: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp -> 194.2.81.126
ttcp-t: 16777216 bytes in 2.09 real seconds = 7847.80 KB/sec +++
ttcp-t: 2048 I/O calls, msec/call = 1.04, calls/sec = 980.98
ttcp-t: 0.0user 2.0sys 0:02real 100% 0i+0d 0maxrss 0+0pf 0+0csw
 
Receiver :
 
ttcp-r: buflen=8192, nbuf=2048, align=16384/0, port=5001 tcp
ttcp-r: 16777216 bytes in 2.08 real seconds = 7874.23 KB/sec +++
ttcp-r: 11404 I/O calls, msec/call = 0.19, calls/sec = 5480.82
ttcp-r: 0.0user 0.1sys 0:02real 8% 0i+0d 0maxrss 0+2pf 0+0csw
/network/sonic.h
0,0 → 1,461
/*
* RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC'
* SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER
*
* REUSABLE CHIP DRIVER CONFIGURATION
*
* References:
*
* 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface
* Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor,
* 1995.
*
* 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM),
* Application Note 746, Wesley Lee and Mike Lui, TL/F/11140,
* RRD-B30M75, National Semiconductor, March, 1991.
*
* 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: sonic.h,v 1.2 2001-09-27 12:01:41 chris Exp $
*/
 
#ifndef _SONIC_DP83932_
#define _SONIC_DP83932_
 
 
/*
* Debug levels
*
*/
 
#define SONIC_DEBUG_NONE 0x0000
#define SONIC_DEBUG_ALL 0xFFFF
#define SONIC_DEBUG_PRINT_REGISTERS 0x0001
#define SONIC_DEBUG_MEMORY 0x0002
#define SONIC_DEBUG_MEMORY_ALLOCATE 0x0004
#define SONIC_DEBUG_MEMORY_DESCRIPTORS 0x0008
#define SONIC_DEBUG_FRAGMENTS 0x0008
#define SONIC_DEBUG_CAM 0x0010
#define SONIC_DEBUG_DESCRIPTORS 0x0020
#define SONIC_DEBUG_ERRORS 0x0040
#define SONIC_DEBUG_DUMP_TX_MBUFS 0x0080
#define SONIC_DEBUG_DUMP_RX_MBUFS 0x0100
 
#define SONIC_DEBUG_DUMP_MBUFS \
(SONIC_DEBUG_DUMP_TX_MBUFS|SONIC_DEBUG_DUMP_RX_MBUFS)
 
#define SONIC_DEBUG (SONIC_DEBUG_NONE)
/*
#define SONIC_DEBUG (SONIC_DEBUG_ERRORS | SONIC_DEBUG_PRINT_REGISTERS |\
SONIC_DEBUG_DESCRIPTORS)
*/
 
/*
((SONIC_DEBUG_ALL) & ~(SONIC_DEBUG_PRINT_REGISTERS|SONIC_DEBUG_DUMP_MBUFS))
((SONIC_DEBUG_ALL) & ~(SONIC_DEBUG_DUMP_MBUFS))
*/
 
#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
extern char SONIC_Reg_name[64][6];
#endif
 
 
/*
* Configuration Information
*/
 
typedef void (*sonic_write_register_t)(
void *base,
unsigned32 regno,
unsigned32 value
);
 
typedef unsigned32 (*sonic_read_register_t)(
void *base,
unsigned32 regno
);
 
typedef struct {
unsigned32 base_address;
unsigned32 vector;
unsigned32 dcr_value;
unsigned32 dc2_value;
unsigned32 tda_count;
unsigned32 rda_count;
sonic_write_register_t write_register;
sonic_read_register_t read_register;
} sonic_configuration_t;
 
/*
******************************************************************
* *
* Device Registers *
* *
******************************************************************
*/
#define SONIC_REG_CR 0x00 /* Command */
#define SONIC_REG_DCR 0x01 /* Data configuration */
#define SONIC_REG_RCR 0x02 /* Receive control */
#define SONIC_REG_TCR 0x03 /* Transmit control */
#define SONIC_REG_IMR 0x04 /* Interrupt mask */
#define SONIC_REG_ISR 0x05 /* Interrupt status */
#define SONIC_REG_UTDA 0x06 /* Upper transmit descriptor address */
#define SONIC_REG_CTDA 0x07 /* Current transmit descriptor address */
#define SONIC_REG_URDA 0x0D /* Upper receive descriptor address */
#define SONIC_REG_CRDA 0x0E /* Current receive descriptor address */
#define SONIC_REG_EOBC 0x13 /* End of buffer word count */
#define SONIC_REG_URRA 0x14 /* Upper receive resource */
#define SONIC_REG_RSA 0x15 /* Resource start address */
#define SONIC_REG_REA 0x16 /* Resource end address */
#define SONIC_REG_RRP 0x17 /* Resouce read pointer */
#define SONIC_REG_RWP 0x18 /* Resouce write pointer */
#define SONIC_REG_CEP 0x21 /* CAM entry pointer */
#define SONIC_REG_CAP2 0x22 /* CAM address port 2 */
#define SONIC_REG_CAP1 0x23 /* CAM address port 1 */
#define SONIC_REG_CAP0 0x24 /* CAM address port 0 */
#define SONIC_REG_CE 0x25 /* CAM enable */
#define SONIC_REG_CDP 0x26 /* CAM descriptor pointer */
#define SONIC_REG_CDC 0x27 /* CAM descriptor count */
#define SONIC_REG_SR 0x28 /* Silicon revision */
#define SONIC_REG_WT0 0x29 /* Watchdog timer 0 */
#define SONIC_REG_WT1 0x2A /* Watchdog timer 1 */
#define SONIC_REG_RSC 0x2B /* Receive sequence counter */
#define SONIC_REG_CRCT 0x2C /* CRC error tally */
#define SONIC_REG_FAET 0x2D /* FAE tally */
#define SONIC_REG_MPT 0x2E /* Missed packet tally */
#define SONIC_REG_MDT 0x2F /* TX Maximum Deferral */
#define SONIC_REG_DCR2 0x3F /* Data configuration 2 */
 
/*
* Command register
*/
#define CR_LCAM 0x0200
#define CR_RRRA 0x0100
#define CR_RST 0x0080
#define CR_ST 0x0020
#define CR_STP 0x0010
#define CR_RXEN 0x0008
#define CR_RXDIS 0x0004
#define CR_TXP 0x0002
#define CR_HTX 0x0001
 
/*
* Data configuration register
*/
#define DCR_EXBUS 0x8000
#define DCR_LBR 0x2000
#define DCR_PO1 0x1000
#define DCR_PO0 0x0800
#define DCR_SBUS 0x0400
#define DCR_USR1 0x0200
#define DCR_USR0 0x0100
#define DCR_WC1 0x0080
#define DCR_WC0 0x0040
#define DCR_DW 0x0020
#define DCR_BMS 0x0010
#define DCR_RFT1 0x0008
#define DCR_RFT0 0x0004
#define DCR_TFT1 0x0002
#define DCR_TFT0 0x0001
 
/* data configuration register aliases */
#define DCR_SYNC DCR_SBUS /* synchronous (memory cycle 2 clocks) */
#define DCR_ASYNC 0 /* asynchronous (memory cycle 3 clocks) */
 
#define DCR_WAIT0 0 /* 0 wait states added */
#define DCR_WAIT1 DCR_WC0 /* 1 wait state added */
#define DCR_WAIT2 DCR_WC1 /* 2 wait states added */
#define DCR_WAIT3 (DCR_WC1|DCR_WC0) /* 3 wait states added */
 
#define DCR_DW16 0 /* use 16-bit DMA accesses */
#define DCR_DW32 DCR_DW /* use 32-bit DMA accesses */
 
#define DCR_DMAEF 0 /* DMA until TX/RX FIFO has emptied/filled */
#define DCR_DMABLOCK DCR_BMS /* DMA until RX/TX threshold crossed */
 
#define DCR_RFT4 0 /* receive threshold 4 bytes */
#define DCR_RFT8 DCR_RFT0 /* receive threshold 8 bytes */
#define DCR_RFT16 DCR_RFT1 /* receive threshold 16 bytes */
#define DCR_RFT24 (DCR_RFT1|DCR_RFT0) /* receive threshold 24 bytes */
 
#define DCR_TFT8 0 /* transmit threshold 8 bytes */
#define DCR_TFT16 DCR_TFT0 /* transmit threshold 16 bytes */
#define DCR_TFT24 DCR_TFT1 /* transmit threshold 24 bytes */
#define DCR_TFT28 (DCR_TFT1|DCR_TFT0) /* transmit threshold 28 bytes */
 
/*
* Receive control register
*/
#define RCR_ERR 0x8000
#define RCR_RNT 0x4000
#define RCR_BRD 0x2000
#define RCR_PRO 0x1000
#define RCR_AMC 0x0800
#define RCR_LB1 0x0400
#define RCR_LB0 0x0200
#define RCR_MC 0x0100
#define RCR_BC 0x0080
#define RCR_LPKT 0x0040
#define RCR_CRS 0x0020
#define RCR_COL 0x0010
#define RCR_CRCR 0x0008
#define RCR_FAER 0x0004
#define RCR_LBK 0x0002
#define RCR_PRX 0x0001
 
/*
* Transmit control register
*/
#define TCR_PINT 0x8000
#define TCR_POWC 0x4000
#define TCR_CRCI 0x2000
#define TCR_EXDIS 0x1000
#define TCR_EXD 0x0400
#define TCR_DEF 0x0200
#define TCR_NCRS 0x0100
#define TCR_CRSL 0x0080
#define TCR_EXC 0x0040
#define TCR_OWC 0x0020
#define TCR_PMB 0x0008
#define TCR_FU 0x0004
#define TCR_BCM 0x0002
#define TCR_PTX 0x0001
 
/*
* Interrupt mask register
*/
#define IMR_BREN 0x4000
#define IMR_HBLEN 0x2000
#define IMR_LCDEN 0x1000
#define IMR_PINTEN 0x0800
#define IMR_PRXEN 0x0400
#define IMR_PTXEN 0x0200
#define IMR_TXEREN 0x0100
#define IMR_TCEN 0x0080
#define IMR_RDEEN 0x0040
#define IMR_RBEEN 0x0020
#define IMR_RBAEEN 0x0010
#define IMR_CRCEN 0x0008
#define IMR_FAEEN 0x0004
#define IMR_MPEN 0x0002
#define IMR_RFOEN 0x0001
 
/*
* Interrupt status register
*/
#define ISR_BR 0x4000
#define ISR_HBL 0x2000
#define ISR_LCD 0x1000
#define ISR_PINT 0x0800
#define ISR_PKTRX 0x0400
#define ISR_TXDN 0x0200
#define ISR_TXER 0x0100
#define ISR_TC 0x0080
#define ISR_RDE 0x0040
#define ISR_RBE 0x0020
#define ISR_RBAE 0x0010
#define ISR_CRC 0x0008
#define ISR_FAE 0x0004
#define ISR_MP 0x0002
#define ISR_RFO 0x0001
 
/*
* Data configuration register 2
*/
#define DCR2_EXPO3 0x8000
#define DCR2_EXPO2 0x4000
#define DCR2_EXPO1 0x2000
#define DCR2_EXPO0 0x1000
#define DCR2_HBDIS 0x0800
#define DCR2_PH 0x0010
#define DCR2_PCM 0x0004
#define DCR2_PCNM 0x0002
#define DCR2_RJCM 0x0001
 
/*
* Known values for the Silicon Revision Register.
* Note that DP83934 has revision 5 and seems to work.
*/
 
#define SONIC_REVISION_B 4
#define SONIC_REVISION_DP83934 5
#define SONIC_REVISION_C 6
 
/*
******************************************************************
* *
* Transmit Buffer Management *
* *
******************************************************************
*/
 
/*
* Transmit descriptor area entry.
* There is one transmit descriptor for each packet to be transmitted.
* Statically reserve space for up to MAXIMUM_FRAGS_PER_PACKET fragments
* per descriptor.
*/
#define MAXIMUM_FRAGS_PER_DESCRIPTOR 6
struct TransmitDescriptor {
rtems_unsigned32 status;
rtems_unsigned32 pkt_config;
rtems_unsigned32 pkt_size;
rtems_unsigned32 frag_count;
 
/*
* Packet fragment pointers
*/
struct TransmitDescriptorFragLink {
rtems_unsigned32 frag_lsw; /* LSW of fragment address */
#define frag_link frag_lsw
rtems_unsigned32 frag_msw; /* MSW of fragment address */
rtems_unsigned32 frag_size;
} frag[MAXIMUM_FRAGS_PER_DESCRIPTOR];
 
/*
* Space for link if all fragment pointers are used.
*/
rtems_unsigned32 link_pad;
 
/*
* Extra RTEMS stuff
*/
struct TransmitDescriptor *next; /* Circularly-linked list */
struct mbuf *mbufp; /* First mbuf in packet */
volatile rtems_unsigned32 *linkp; /* Pointer to un[xxx].link */
};
typedef struct TransmitDescriptor TransmitDescriptor_t;
typedef volatile TransmitDescriptor_t *TransmitDescriptorPointer_t;
 
/*
* Transmit Configuration.
* For standard Ethernet transmission, all bits in the transmit
* configuration field are set to 0.
*/
#define TDA_CONFIG_PINT 0x8000
#define TDA_CONFIG_POWC 0x4000
#define TDA_CONFIG_CRCI 0x2000
#define TDA_CONFIG_EXDIS 0x1000
 
/*
* Transmit status
*/
#define TDA_STATUS_COLLISION_MASK 0xF800
#define TDA_STATUS_COLLISION_SHIFT 11
#define TDA_STATUS_EXD 0x0400
#define TDA_STATUS_DEF 0x0200
#define TDA_STATUS_NCRS 0x0100
#define TDA_STATUS_CRSL 0x0080
#define TDA_STATUS_EXC 0x0040
#define TDA_STATUS_OWC 0x0020
#define TDA_STATUS_PMB 0x0008
#define TDA_STATUS_FU 0x0004
#define TDA_STATUS_BCM 0x0002
#define TDA_STATUS_PTX 0x0001
 
#define TDA_LINK_EOL 0x0001
#define TDA_LINK_EOL_MASK 0xFFFE
 
 
 
/*
******************************************************************
* *
* Receive Buffer Management *
* *
******************************************************************
*/
 
/*
* Receive resource area entry.
* There is one receive resource entry for each receive buffer area (RBA).
* This driver allows only one packet per receive buffer area, so one
* receive resource entry corresponds to one correctly-received packet.
*/
struct ReceiveResource {
rtems_unsigned32 buff_ptr_lsw; /* LSW of RBA address */
rtems_unsigned32 buff_ptr_msw; /* MSW of RBA address */
rtems_unsigned32 buff_wc_lsw; /* LSW of RBA size (16-bit words) */
rtems_unsigned32 buff_wc_msw; /* MSW of RBA size (16-bit words) */
};
typedef struct ReceiveResource ReceiveResource_t;
typedef volatile ReceiveResource_t *ReceiveResourcePointer_t;
 
/*
* Receive descriptor area entry.
* There is one receive descriptor for each packet received.
*/
struct ReceiveDescriptor {
rtems_unsigned32 status;
rtems_unsigned32 byte_count;
rtems_unsigned32 pkt_lsw; /* LSW of packet address */
rtems_unsigned32 pkt_msw; /* MSW of packet address */
rtems_unsigned32 seq_no;
rtems_unsigned32 link;
rtems_unsigned32 in_use;
 
/*
* Extra RTEMS stuff
*/
volatile struct ReceiveDescriptor *next; /* Circularly-linked list */
struct mbuf *mbufp; /* First mbuf in packet */
};
typedef struct ReceiveDescriptor ReceiveDescriptor_t;
typedef volatile ReceiveDescriptor_t *ReceiveDescriptorPointer_t;
 
typedef struct {
rtems_unsigned32 cep; /* CAM Entry Pointer */
rtems_unsigned32 cap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
rtems_unsigned32 cap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
rtems_unsigned32 cap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
rtems_unsigned32 ce;
} CamDescriptor_t;
 
typedef volatile CamDescriptor_t *CamDescriptorPointer_t;
 
/*
* Receive status
*/
#define RDA_STATUS_ERR 0x8800
#define RDA_STATUS_RNT 0x4000
#define RDA_STATUS_BRD 0x2000
#define RDA_STATUS_PRO 0x1000
#define RDA_STATUS_AMC 0x0800
#define RDA_STATUS_LB1 0x0400
#define RDA_STATUS_LB0 0x0200
#define RDA_STATUS_MC 0x0100
#define RDA_STATUS_BC 0x0080
#define RDA_STATUS_LPKT 0x0040
#define RDA_STATUS_CRS 0x0020
#define RDA_STATUS_COL 0x0010
#define RDA_STATUS_CRCR 0x0008
#define RDA_STATUS_FAER 0x0004
#define RDA_STATUS_LBK 0x0002
#define RDA_STATUS_PRX 0x0001
 
#define RDA_LINK_EOL 0x0001
#define RDA_LINK_EOL_MASK 0xFFFE
#define RDA_IN_USE 0x0000 /* SONIC has finished with the packet */
/* and the driver can process it */
#define RDA_FREE 0xFFFF /* SONIC can use it */
/*
* Attatch routine
*/
 
int rtems_sonic_driver_attach (
struct rtems_bsdnet_ifconfig *config,
sonic_configuration_t *chip
);
 
#ifdef CPU_U32_FIX
void ipalign(struct mbuf *m);
#endif
 
#endif /* _SONIC_DP83932_ */
/network/dec21140.c
0,0 → 1,962
/*
* RTEMS driver for TULIP based Ethernet Controller
*
* Copyright (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id: dec21140.c,v 1.2 2001-09-27 12:01:41 chris Exp $
*
* ------------------------------------------------------------------------
* [22.05.2000,StWi/CWA] added support for the DEC/Intel 21143 chip
*
* The 21143 support is (for now) only available for the __i386 target,
* because that's the only testing platform I have. It should (to my best
* knowledge) work in the same way for the "__PPC" target, but someone
* should test this first before it's put into the code. Thanks go to
* Andrew Klossner who provided the vital information about the
* Intel 21143 chip.
* (FWIW: I tested this driver using a Kingston KNE100TX with 21143PD chip)
*
* The driver will automatically detect whether there is a 21140 or 21143
* network card in the system and activate support accordingly. It will
* look for the 21140 first. If the 21140 is not found the driver will
* look for the 21143.
* ------------------------------------------------------------------------
*/
 
#include <rtems.h>
 
/*
* This driver only supports architectures with the new style
* exception processing. The following checks try to keep this
* from being compiled on systems which can't support this driver.
*/
 
#if defined(__i386)
#define DEC21140_SUPPORTED
#endif
 
#if defined(__PPC) && (defined(mpc604) || defined(mpc750))
#define DEC21140_SUPPORTED
#endif
 
#if defined(DEC21140_SUPPORTED)
#include <bsp.h>
#if defined(i386)
#include <pcibios.h>
#endif
#if defined(__PPC)
#include <bsp/pci.h>
#include <libcpu/byteorder.h>
#include <libcpu/io.h>
#endif
 
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
 
#include <libcpu/cpu.h>
 
#include <sys/param.h>
#include <sys/mbuf.h>
 
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#if defined(i386)
#include <irq.h>
#endif
#if defined(__PPC)
#include <bsp/irq.h>
#endif
 
#ifdef malloc
#undef malloc
#endif
#ifdef free
#undef free
#endif
 
#define DEC_DEBUG
 
/* note: the 21143 isn't really a DEC, it's an Intel chip */
#define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_VENDOR_ID_DEC 0x1011
#define PCI_DEVICE_ID_DEC_21140 0x0009
#define PCI_DEVICE_ID_DEC_21143 0x0019
 
#define IO_MASK 0x3
#define MEM_MASK 0xF
 
/* command and status registers, 32-bit access, only if IO-ACCESS */
#define ioCSR0 0x00 /* bus mode register */
#define ioCSR1 0x08 /* transmit poll demand */
#define ioCSR2 0x10 /* receive poll demand */
#define ioCSR3 0x18 /* receive list base address */
#define ioCSR4 0x20 /* transmit list base address */
#define ioCSR5 0x28 /* status register */
#define ioCSR6 0x30 /* operation mode register */
#define ioCSR7 0x38 /* interrupt mask register */
#define ioCSR8 0x40 /* missed frame counter */
#define ioCSR9 0x48 /* Ethernet ROM register */
#define ioCSR10 0x50 /* reserved */
#define ioCSR11 0x58 /* full-duplex register */
#define ioCSR12 0x60 /* SIA status register */
#define ioCSR13 0x68
#define ioCSR14 0x70
#define ioCSR15 0x78 /* SIA general register */
 
/* command and status registers, 32-bit access, only if MEMORY-ACCESS */
#define memCSR0 0x00 /* bus mode register */
#define memCSR1 0x02 /* transmit poll demand */
#define memCSR2 0x04 /* receive poll demand */
#define memCSR3 0x06 /* receive list base address */
#define memCSR4 0x08 /* transmit list base address */
#define memCSR5 0x0A /* status register */
#define memCSR6 0x0C /* operation mode register */
#define memCSR7 0x0E /* interrupt mask register */
#define memCSR8 0x10 /* missed frame counter */
#define memCSR9 0x12 /* Ethernet ROM register */
#define memCSR10 0x14 /* reserved */
#define memCSR11 0x16 /* full-duplex register */
#define memCSR12 0x18 /* SIA status register */
#define memCSR13 0x1A
#define memCSR14 0x1C
#define memCSR15 0x1E /* SIA general register */
 
#define DEC_REGISTER_SIZE 0x100 /* to reserve virtual memory */
 
#define RESET_CHIP 0x00000001
#if defined(__PPC)
#define CSR0_MODE 0x0030e002 /* 01b08000 */
#else
#define CSR0_MODE 0x0020e002 /* 01b08000 */
#endif
#define ROM_ADDRESS 0x00004800
#define CSR6_INIT 0x022cc000 /* 022c0000 020c0000 */
#define CSR6_TX 0x00002000
#define CSR6_TXRX 0x00002002
#define IT_SETUP 0x000100c0 /* 000100e0 */
#define CLEAR_IT 0xFFFFFFFF
#define NO_IT 0x00000000
 
#define NRXBUFS 32 /* number of receive buffers */
#define NTXBUFS 16 /* number of transmit buffers */
 
/* message descriptor entry */
struct MD {
/* used by hardware */
volatile unsigned32 status;
volatile unsigned32 counts;
unsigned32 buf1, buf2;
/* used by software */
volatile struct mbuf *m;
volatile struct MD *next;
};
 
/*
* Number of DECs supported by this driver
*/
#define NDECDRIVER 1
 
/*
* Receive buffer size -- Allow for a full ethernet packet including CRC
*/
#define RBUF_SIZE 1536
 
#define ET_MINLEN 60 /* minimum message length */
 
/*
* RTEMS event used by interrupt handler to signal driver tasks.
* This must not be any of the events used by the network task synchronization.
*/
#define INTERRUPT_EVENT RTEMS_EVENT_1
 
/*
* RTEMS event used to start transmit daemon.
* This must not be the same as INTERRUPT_EVENT.
*/
#define START_TRANSMIT_EVENT RTEMS_EVENT_2
 
#if defined(__PPC)
#define phys_to_bus(address) ((unsigned int)((address)) + PREP_PCI_DRAM_OFFSET)
#define bus_to_phys(address) ((unsigned int)((address)) - PREP_PCI_DRAM_OFFSET)
#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT
#else
extern void Wait_X_ms( unsigned int timeToWait );
#define phys_to_bus(address) ((unsigned int) ((address)))
#define bus_to_phys(address) ((unsigned int) ((address)))
#define delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 )
#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE
 
inline void st_le32(volatile unsigned32 *addr, unsigned32 value)
{
*(addr)=value ;
}
 
inline unsigned32 ld_le32(volatile unsigned32 *addr)
{
return(*addr);
}
 
#endif
 
#if (MCLBYTES < RBUF_SIZE)
# error "Driver must have MCLBYTES > RBUF_SIZE"
#endif
 
/*
* Per-device data
*/
struct dec21140_softc {
 
struct arpcom arpcom;
 
rtems_irq_connect_data irqInfo;
 
volatile struct MD *MDbase;
volatile unsigned char *bufferBase;
int acceptBroadcast;
rtems_id rxDaemonTid;
rtems_id txDaemonTid;
volatile struct MD *TxMD;
volatile struct MD *SentTxMD;
int PendingTxCount;
int TxSuspended;
 
unsigned int port;
volatile unsigned int *base;
/*
* Statistics
*/
unsigned long rxInterrupts;
unsigned long rxNotFirst;
unsigned long rxNotLast;
unsigned long rxGiant;
unsigned long rxNonOctet;
unsigned long rxRunt;
unsigned long rxBadCRC;
unsigned long rxOverrun;
unsigned long rxCollision;
unsigned long txInterrupts;
unsigned long txDeferred;
unsigned long txHeartbeat;
unsigned long txLateCollision;
unsigned long txRetryLimit;
unsigned long txUnderrun;
unsigned long txLostCarrier;
unsigned long txRawWait;
};
 
static struct dec21140_softc dec21140_softc[NDECDRIVER];
 
/*
* DEC21140 interrupt handler
*/
static rtems_isr
dec21140Enet_interrupt_handler (rtems_vector_number v)
{
volatile unsigned32 *tbase;
unsigned32 status;
struct dec21140_softc *sc;
 
sc = &dec21140_softc[0];
tbase = (unsigned32 *)(sc->base) ;
 
/*
* Read status
*/
status = ld_le32(tbase+memCSR5);
st_le32((tbase+memCSR5), status); /* clear the bits we've read */
 
/*
* Frame received?
*/
if (status & 0x000000c0){
sc->rxInterrupts++;
rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
}
}
 
static void nopOn(const rtems_irq_connect_data* notUsed)
{
/*
* code should be moved from dec21140Enet_initialize_hardware
* to this location
*/
}
 
static int dec21140IsOn(const rtems_irq_connect_data* irq)
{
return BSP_irq_enabled_at_i8259s (irq->name);
}
 
 
/*
* This routine reads a word (16 bits) from the serial EEPROM.
*/
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
#define EE_CS 0x01 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
#define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
#define EE_ENB (0x4800 | EE_CS)
 
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
#define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6)
 
static int eeget16(volatile unsigned int *ioaddr, int location)
{
int i;
unsigned short retval = 0;
int read_cmd = location | EE_READ_CMD;
st_le32(ioaddr, EE_ENB & ~EE_CS);
st_le32(ioaddr, EE_ENB);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
st_le32(ioaddr, EE_ENB | dataval);
delay_in_bus_cycles(200);
st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK);
delay_in_bus_cycles(200);
st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */
delay_in_bus_cycles(200);
}
st_le32(ioaddr, EE_ENB);
for (i = 16; i > 0; i--) {
st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK);
delay_in_bus_cycles(200);
retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0);
st_le32(ioaddr, EE_ENB);
delay_in_bus_cycles(200);
}
 
/* Terminate the EEPROM access. */
st_le32(ioaddr, EE_ENB & ~EE_CS);
return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) );
}
 
/*
* Initialize the ethernet hardware
*/
static void
dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
{
rtems_status_code st;
volatile unsigned int *tbase;
int i;
volatile unsigned char *cp, *setup_frm, *eaddrs;
volatile unsigned char *buffer;
volatile struct MD *rmd;
 
tbase = sc->base;
 
/*
* WARNING : First write in CSR6
* Then Reset the chip ( 1 in CSR0)
*/
st_le32( (tbase+memCSR6), CSR6_INIT);
st_le32( (tbase+memCSR0), RESET_CHIP);
delay_in_bus_cycles(200);
 
/*
* Init CSR0
*/
st_le32( (tbase+memCSR0), CSR0_MODE);
 
#ifdef DEC_DEBUG
printk("DC2114x %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
sc->irqInfo.name, sc->port, (unsigned) sc->base);
#endif
/*
* Init RX ring
*/
cp = (volatile unsigned char *)malloc(((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE)
+ CPU_CACHE_ALIGNMENT_FOR_BUFFER);
sc->bufferBase = cp;
cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp)
& (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1);
#if defined(__i386)
#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA
if (_CPU_is_paging_enabled())
_CPU_change_memory_mapping_attribute
(NULL, cp,
((NRXBUFS+NTXBUFS)*sizeof(struct MD))
+ (NTXBUFS*RBUF_SIZE),
PTE_CACHE_DISABLE | PTE_WRITABLE);
#endif
#endif
rmd = (volatile struct MD*)cp;
sc->MDbase = rmd;
buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase))));
for (i=0 ; i<NRXBUFS; i++){
struct mbuf *m;
/* allocate an mbuf for each receive descriptor */
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
rmd->m = m;
 
rmd->buf2 = phys_to_bus(rmd+1);
rmd->buf1 = phys_to_bus(mtod(m, void *));
rmd->counts = 0xfdc00000 | (RBUF_SIZE);
rmd->status = 0x80000000;
rmd->next = rmd + 1;
rmd++;
}
/*
* mark last RX buffer.
*/
sc->MDbase [NRXBUFS-1].counts = 0xfec00000 | (RBUF_SIZE);
sc->MDbase [NRXBUFS-1].next = sc->MDbase;
 
/*
* Init TX ring
*/
st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) );
for (i=0 ; i<NTXBUFS; i++){
(rmd+i)->buf2 = phys_to_bus(rmd+i+1);
(rmd+i)->buf1 = phys_to_bus(buffer + (i*RBUF_SIZE));
(rmd+i)->counts = 0x01000000;
(rmd+i)->status = 0x0;
(rmd+i)->next = rmd+i+1;
(rmd+i)->m = 0;
}
 
/*
* mark last TX buffer.
*/
(rmd+NTXBUFS-1)->buf2 = phys_to_bus(rmd);
(rmd+NTXBUFS-1)->next = rmd;
/*
* Set up interrupts
*/
sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
sc->irqInfo.on = nopOn;
sc->irqInfo.off = nopOn;
sc->irqInfo.isOn = dec21140IsOn;
st = BSP_install_rtems_irq_handler (&sc->irqInfo);
if (!st)
rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
sc->irqInfo.name);
 
st_le32( (tbase+memCSR7), NO_IT);
 
/*
* Build setup frame
*/
setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1));
eaddrs = (char *)(sc->arpcom.ac_enaddr);
/* Fill the buffer with our physical address. */
for (i = 1; i < 16; i++) {
*setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
*setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
*setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3];
*setup_frm++ = eaddrs[2];
*setup_frm++ = eaddrs[3];
*setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5];
*setup_frm++ = eaddrs[4];
*setup_frm++ = eaddrs[5];
}
/* Add the broadcast address when doing perfect filtering */
memset((void*) setup_frm, 0xff, 12);
rmd->counts = 0x09000000 | 192 ;
rmd->status = 0x80000000;
st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX);
st_le32( (tbase+memCSR1), 1);
while (rmd->status != 0x7fffffff);
rmd->counts = 0x01000000;
sc->TxMD = rmd+1;
/*
* Enable RX and TX
*/
st_le32( (tbase+memCSR5), IT_SETUP);
st_le32( (tbase+memCSR7), IT_SETUP);
st_le32( (unsigned int*)(tbase+memCSR6), CSR6_INIT | CSR6_TXRX);
}
 
static void
dec21140_rxDaemon (void *arg)
{
volatile unsigned int *tbase;
struct ether_header *eh;
struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
struct ifnet *ifp = &dp->arpcom.ac_if;
struct mbuf *m;
volatile struct MD *rmd;
unsigned int len;
rtems_event_set events;
tbase = dec21140_softc[0].base ;
rmd = dec21140_softc[0].MDbase;
 
for (;;){
 
rtems_bsdnet_event_receive (INTERRUPT_EVENT,
RTEMS_WAIT|RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT,
&events);
while((rmd->status & 0x80000000) == 0){
/* pass on the packet in the mbuf */
len = (rmd->status >> 16) & 0x7ff;
m = (struct mbuf *)(rmd->m);
m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
eh = mtod (m, struct ether_header *);
m->m_data += sizeof(struct ether_header);
ether_input (ifp, eh, m);
/* get a new mbuf for the 21140 */
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = ifp;
rmd->m = m;
rmd->buf1 = phys_to_bus(mtod(m, void *));
 
rmd->status = 0x80000000;
rmd=rmd->next;
}
}
}
 
static void
sendpacket (struct ifnet *ifp, struct mbuf *m)
{
struct dec21140_softc *dp = ifp->if_softc;
volatile struct MD *tmd;
volatile unsigned char *temp;
struct mbuf *n;
unsigned int len;
volatile unsigned int *tbase;
 
tbase = dp->base;
/*
* Waiting for Transmitter ready
*/
tmd = dec21140_softc[0].TxMD;
n = m;
 
while ((tmd->status & 0x80000000) != 0){
tmd=tmd->next;
}
 
len = 0;
temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1));
for (;;){
len += m->m_len;
memcpy((void*) temp, (char *)m->m_data, m->m_len);
temp += m->m_len ;
if ((m = m->m_next) == NULL)
break;
}
 
if (len < ET_MINLEN) len = ET_MINLEN;
tmd->counts = 0xe1000000 | (len & 0x7ff);
tmd->status = 0x80000000;
 
st_le32( (tbase+memCSR1), 0x1);
 
m_freem(n);
dec21140_softc[0].TxMD = tmd->next;
}
 
/*
* Driver transmit daemon
*/
void
dec21140_txDaemon (void *arg)
{
struct dec21140_softc *sc = (struct dec21140_softc *)arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct mbuf *m;
rtems_event_set events;
 
for (;;) {
/*
* Wait for packet
*/
 
rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
 
/*
* Send packets till queue is empty
*/
for (;;) {
/*
* Get the next mbuf chain to transmit.
*/
IF_DEQUEUE(&ifp->if_snd, m);
if (!m)
break;
sendpacket (ifp, m);
}
ifp->if_flags &= ~IFF_OACTIVE;
}
}
 
 
static void
dec21140_start (struct ifnet *ifp)
{
struct dec21140_softc *sc = ifp->if_softc;
 
rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
ifp->if_flags |= IFF_OACTIVE;
}
 
/*
* Initialize and start the device
*/
static void
dec21140_init (void *arg)
{
struct dec21140_softc *sc = arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
 
if (sc->txDaemonTid == 0) {
/*
* Set up DEC21140 hardware
*/
dec21140Enet_initialize_hardware (sc);
/*
* Start driver tasks
*/
sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096,
dec21140_rxDaemon, sc);
sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096,
dec21140_txDaemon, sc);
}
 
/*
* Tell the world that we're running.
*/
ifp->if_flags |= IFF_RUNNING;
 
}
 
/*
* Stop the device
*/
static void
dec21140_stop (struct dec21140_softc *sc)
{
volatile unsigned int *tbase;
struct ifnet *ifp = &sc->arpcom.ac_if;
 
ifp->if_flags &= ~IFF_RUNNING;
 
/*
* Stop the transmitter
*/
tbase=dec21140_softc[0].base ;
st_le32( (tbase+memCSR7), NO_IT);
st_le32( (tbase+memCSR6), CSR6_INIT);
free((void*)sc->bufferBase);
}
 
 
/*
* Show interface statistics
*/
static void
dec21140_stats (struct dec21140_softc *sc)
{
printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
printf (" Not First:%-8lu", sc->rxNotFirst);
printf (" Not Last:%-8lu\n", sc->rxNotLast);
printf (" Giant:%-8lu", sc->rxGiant);
printf (" Runt:%-8lu", sc->rxRunt);
printf (" Non-octet:%-8lu\n", sc->rxNonOctet);
printf (" Bad CRC:%-8lu", sc->rxBadCRC);
printf (" Overrun:%-8lu", sc->rxOverrun);
printf (" Collision:%-8lu\n", sc->rxCollision);
 
printf (" Tx Interrupts:%-8lu", sc->txInterrupts);
printf (" Deferred:%-8lu", sc->txDeferred);
printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
printf (" No Carrier:%-8lu", sc->txLostCarrier);
printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
printf (" Late Collision:%-8lu\n", sc->txLateCollision);
printf (" Underrun:%-8lu", sc->txUnderrun);
printf (" Raw output wait:%-8lu\n", sc->txRawWait);
}
 
/*
* Driver ioctl handler
*/
static int
dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
{
struct dec21140_softc *sc = ifp->if_softc;
int error = 0;
 
switch (command) {
case SIOCGIFADDR:
case SIOCSIFADDR:
ether_ioctl (ifp, command, data);
break;
 
case SIOCSIFFLAGS:
switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
case IFF_RUNNING:
dec21140_stop (sc);
break;
 
case IFF_UP:
dec21140_init (sc);
break;
 
case IFF_UP | IFF_RUNNING:
dec21140_stop (sc);
dec21140_init (sc);
break;
 
default:
break;
}
break;
 
case SIO_RTEMS_SHOW_STATS:
dec21140_stats (sc);
break;
/*
* FIXME: All sorts of multicast commands need to be added here!
*/
default:
error = EINVAL;
break;
}
 
return error;
}
 
/*
* Attach an DEC21140 driver to the system
*/
int
rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
{
struct dec21140_softc *sc;
struct ifnet *ifp;
int mtu;
int i;
int deviceId = PCI_DEVICE_ID_DEC_21140; /* network card device ID */
/*
* First, find a DEC board
*/
#if defined(__i386)
int signature;
int value;
char interrupt;
int diag;
 
if (pcib_init() == PCIB_ERR_NOTPRESENT)
rtems_panic("PCI BIOS not found !!");
/*
* Try to find the network card on the PCI bus. Probe for a DEC 21140
* card first. If not found probe the bus for a DEC/Intel 21143 card.
*/
deviceId = PCI_DEVICE_ID_DEC_21140;
diag = pcib_find_by_devid( PCI_VENDOR_ID_DEC, deviceId,
0, &signature);
if ( diag == PCIB_ERR_SUCCESS)
printk( "DEC 21140 PCI network card found\n" );
else
{
deviceId = PCI_DEVICE_ID_DEC_21143;
diag = pcib_find_by_devid( PCI_VENDOR_ID_DEC, deviceId,
0, &signature);
if ( diag == PCIB_ERR_SUCCESS)
printk( "DEC/Intel 21143 PCI network card found\n" );
else
rtems_panic("DEC PCI network card not found !!\n");
}
#endif
#if defined(__PPC)
unsigned char ucSlotNumber, ucFnNumber;
unsigned int ulDeviceID, lvalue, tmp;
unsigned char cvalue;
 
for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
for(ucFnNumber=0;ucFnNumber<PCI_MAX_FUNCTIONS;ucFnNumber++) {
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_VENDOR_ID,
&ulDeviceID);
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
/*
* This slot is empty
*/
continue;
}
if (ulDeviceID == ((PCI_DEVICE_ID_DEC_21140<<16) + PCI_VENDOR_ID_DEC))
break;
}
if (ulDeviceID == ((PCI_DEVICE_ID_DEC_21140<<16) + PCI_VENDOR_ID_DEC)){
printk("DEC Adapter found !!\n");
break;
}
}
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
rtems_panic("DEC PCI board not found !!\n");
#endif
/*
* Find a free driver
*/
for (i = 0 ; i < NDECDRIVER ; i++) {
sc = &dec21140_softc[i];
ifp = &sc->arpcom.ac_if;
if (ifp->if_softc == NULL)
break;
}
if (i >= NDECDRIVER) {
printk ("Too many DEC drivers.\n");
return 0;
}
 
/*
* Process options
*/
#if defined(__i386)
 
/* the 21143 chip must be enabled before it can be accessed */
if ( deviceId == PCI_DEVICE_ID_DEC_21143 )
pcib_conf_write32( signature, 0x40, 0 );
 
pcib_conf_read32(signature, 16, &value);
sc->port = value & ~IO_MASK;
pcib_conf_read32(signature, 20, &value);
if (_CPU_is_paging_enabled())
_CPU_map_phys_address((void **) &(sc->base),
(void *)(value & ~MEM_MASK),
DEC_REGISTER_SIZE ,
PTE_CACHE_DISABLE | PTE_WRITABLE);
else
sc->base = (unsigned int *)(value & ~MEM_MASK);
pcib_conf_read8(signature, 60, &interrupt);
sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;
#endif
#if defined(__PPC)
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_BASE_ADDRESS_0,
&lvalue);
 
sc->port = lvalue & (unsigned int)(~IO_MASK);
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_BASE_ADDRESS_1 ,
&lvalue);
 
 
tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK))
+ (unsigned int)PREP_ISA_MEM_BASE;
sc->base = (unsigned int *)(tmp);
 
(void)pci_read_config_byte(0,
ucSlotNumber,
ucFnNumber,
PCI_INTERRUPT_LINE,
&cvalue);
sc->irqInfo.name = (rtems_irq_symbolic_name)cvalue;
#endif
if (config->hardware_address) {
memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
ETHER_ADDR_LEN);
}
else {
union {char c[64]; unsigned short s[32];} rombuf;
int i;
 
for (i=0; i<32; i++){
rombuf.s[i] = eeget16(sc->base+memCSR9, i);
}
#if defined(__i386)
for (i=0 ; i<(ETHER_ADDR_LEN/2); i++){
sc->arpcom.ac_enaddr[2*i] = rombuf.c[20+2*i+1];
sc->arpcom.ac_enaddr[2*i+1] = rombuf.c[20+2*i];
}
#endif
#if defined(__PPC)
memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN);
#endif
}
 
if (config->mtu)
mtu = config->mtu;
else
mtu = ETHERMTU;
 
sc->acceptBroadcast = !config->ignore_broadcast;
 
/*
* Set up network interface values
*/
ifp->if_softc = sc;
ifp->if_unit = i + 1;
ifp->if_name = "dc";
ifp->if_mtu = mtu;
ifp->if_init = dec21140_init;
ifp->if_ioctl = dec21140_ioctl;
ifp->if_start = dec21140_start;
ifp->if_output = ether_output;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
if (ifp->if_snd.ifq_maxlen == 0)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
 
/*
* Attach the interface
*/
if_attach (ifp);
ether_ifattach (ifp);
 
printk( "DC2114x : driver has been attached\n" );
return 1;
};
#endif /* DEC21140_SUPPORTED */
 
/network/README.sonic
0,0 → 1,21
#
# $Id: README.sonic,v 1.2 2001-09-27 12:01:41 chris Exp $
#
 
This SONIC driver does not make any attempt to support the SONIC chip
in any of the following modes:
 
+ 16-bit
+ little endian
It does not attempt to handle SONIC's older than Revision C. There is
a bug in chips before that revision that must be handled in the driver.
 
The configuration table should be discussed here but if you look in the
include file for the sonic, it is reasonably obvious. :)
 
The performance impact of transforming this driver into libchip format
was minimal.
 
The powerpc/dmv177 BSP uses this driver and can serve as an example
configuration table.
/network/Makefile.am
0,0 → 1,53
##
## $Id: Makefile.am,v 1.2 2001-09-27 12:01:41 chris Exp $
##
 
AUTOMAKE_OPTIONS = foreign 1.4
 
LIBNAME = libnetchip
LIB = $(ARCH)/$(LIBNAME).a
 
C_FILES = dec21140.c sonic.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
 
H_FILES = sonic.h
 
OBJS = $(C_O_FILES)
 
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../automake/lib.am
 
$(PROJECT_INCLUDE)/libchip:
@$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/libchip/%.h: %.h
$(INSTALL_DATA) $< $@
 
#
# Add local stuff here using +=
#
 
AM_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
AM_CFLAGS = $(LIBC_DEFINES)
 
$(LIB): $(OBJS)
$(make-library)
 
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
$(INSTALL_DATA) $< $@
 
if HAS_NETWORKING
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip \
$(PROJECT_INCLUDE)/libchip/sonic.h
endif
 
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
 
if HAS_NETWORKING
all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) $(LIB) $(TMPINSTALL_FILES)
endif
 
.PRECIOUS: $(LIB)
 
EXTRA_DIST = README README.dec21140 README.sonic dec21140.c sonic.c sonic.h
 
include $(top_srcdir)/../../../automake/local.am
/network/sonic.c
0,0 → 1,1657
/*
* RTEMS NETWORK DRIVER FOR NATIONAL DP83932 `SONIC'
* SYSTEMS-ORIENTED NETWORK INTERFACE CONTROLLER
*
* REUSABLE CHIP DRIVER
*
* References:
*
* 1) DP83932C-20/25/33 MHz SONIC(TM) Systems-Oriented Network Interface
* Controller data sheet. TL/F/10492, RRD-B30M105, National Semiconductor,
* 1995.
*
* 2) Software Driver Programmer's Guide for the DP83932 SONIC(TM),
* Application Note 746, Wesley Lee and Mike Lui, TL/F/11140,
* RRD-B30M75, National Semiconductor, March, 1991.
*
* 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: sonic.c,v 1.2 2001-09-27 12:01:41 chris Exp $
*
* This driver was originally written and tested on a DY-4 DMV177,
* which had a 100 Mhz PPC603e.
*
* This driver also works with DP83934CVUL-20/25 MHz, tested on
* Tharsys ERC32 VME board.
*
* Rehaul to fix lost interrupts and buffers, and to use to use
* interrupt-free transmission by Jiri, 22/03/1999.
*/
 
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include <libchip/sonic.h>
 
#include <stdio.h>
 
#include <errno.h>
#include <rtems/error.h>
 
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sockio.h>
 
#include <net/if.h>
 
#include <netinet/in.h>
#include <netinet/if_ether.h>
 
/*
* XXX fix this
*/
 
void *set_vector(void *, unsigned32, unsigned32);
 
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_MBUFS)
#include <rtems/dumpbuf.h>
#endif
 
/*
* Use the top line if you want more symbols.
*/
 
#define SONIC_STATIC
/* #define SONIC_STATIC static */
 
/*
* Number of devices supported by this driver
*/
#ifndef NSONIC
# define NSONIC 1
#endif
 
/*
*
* As suggested by National Application Note 746, make the
* receive resource area bigger than the receive descriptor area.
*
* NOTE: Changing this may break this driver since it currently
* assumes a 1<->1 mapping.
*/
#define RRA_EXTRA_COUNT 0
 
/*
* RTEMS event used by interrupt handler to signal daemons.
*/
#define INTERRUPT_EVENT RTEMS_EVENT_1
 
/*
* RTEMS event used to start transmit daemon.
* This must not be the same as INTERRUPT_EVENT.
*/
#define START_TRANSMIT_EVENT RTEMS_EVENT_2
 
/*
* Largest Ethernet frame.
*/
#define MAXIMUM_FRAME_SIZE 1518
 
/*
* Receive buffer size.
* Allow for a pointer, plus a full ethernet frame (including Frame
* Check Sequence) rounded up to a 4-byte boundary.
*/
#define RBUF_SIZE ((sizeof (void *) + (MAXIMUM_FRAME_SIZE) + 3) & ~3)
/* #define RBUF_WC ((((MAXIMUM_FRAME_SIZE) + 3) & ~3) / 2) */
#define RBUF_WC (RBUF_SIZE / 2)
 
/*
* Macros for manipulating 32-bit pointers as 16-bit fragments
*/
#define LSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p)))
#define MSW(p) ((rtems_unsigned16)((rtems_unsigned32)(p) >> 16))
#define PTR(m,l) ((void*)(((rtems_unsigned16)(m)<<16)|(rtems_unsigned16)(l)))
 
/*
* Hardware-specific storage
*/
struct sonic_softc {
/*
* Connection to networking code
* This entry *must* be the first in the sonic_softc structure.
*/
struct arpcom arpcom;
 
/*
* Default location of device registers
* ===CACHE===
* This area must be non-cacheable, guarded.
*/
void *sonic;
 
/*
* Register access routines
*/
sonic_write_register_t write_register;
sonic_read_register_t read_register;
/*
* Interrupt vector
*/
rtems_vector_number vector;
 
/*
* Data Configuration Register values
*/
rtems_unsigned32 dcr_value;
rtems_unsigned32 dc2_value;
 
/*
* Indicates configuration
*/
int acceptBroadcast;
 
/*
* Task waiting for interrupts
*/
rtems_id rxDaemonTid;
rtems_id txDaemonTid;
 
/*
* Receive resource area
*/
int rdaCount;
ReceiveResourcePointer_t rsa;
ReceiveResourcePointer_t rea;
CamDescriptorPointer_t cdp;
ReceiveDescriptorPointer_t rda;
ReceiveDescriptorPointer_t rdp_last;
 
/*
* Transmit descriptors
*/
int tdaCount;
TransmitDescriptorPointer_t tdaHead; /* Last filled */
TransmitDescriptorPointer_t tdaTail; /* Next to retire */
 
/*
* Statistics
*/
unsigned long Interrupts;
unsigned long rxInterrupts;
unsigned long rxMissed;
unsigned long rxGiant;
unsigned long rxNonOctet;
unsigned long rxBadCRC;
unsigned long rxCollision;
 
unsigned long txInterrupts;
unsigned long txSingleCollision;
unsigned long txMultipleCollision;
unsigned long txCollision;
unsigned long txDeferred;
unsigned long txUnderrun;
unsigned long txLateCollision;
unsigned long txExcessiveCollision;
unsigned long txExcessiveDeferral;
unsigned long txLostCarrier;
unsigned long txRawWait;
};
SONIC_STATIC struct sonic_softc sonic_softc[NSONIC];
 
 
/*
******************************************************************
* *
* Debug Routines *
* *
******************************************************************
*/
 
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
void sonic_print_tx_descriptor(
TransmitDescriptorPointer_t tdp
)
{
printf( "TXD ==> %p", tdp );
printf( " pkt_config = 0x%04x", tdp->pkt_config & 0xffff);
printf( " pkt_size = 0x%04x\n", tdp->pkt_size & 0xffff );
printf( " frag_count = %d", tdp->frag_count & 0xffff );
/* could print all the fragments */
printf( " next = %p", tdp->next );
printf( " linkp = %p\n", tdp->linkp );
printf( " mbufp = %p", tdp->mbufp );
if ( tdp->mbufp )
printf( " mbufp->data = %p", mtod ( tdp->mbufp, void *) );
puts("");
}
 
void sonic_print_rx_descriptor(
ReceiveDescriptorPointer_t rdp
)
{
printf( "RXD ==> %p\n", rdp );
printf( " status = 0x%04x", rdp->status & 0xffff );
printf( " byte_count = 0x%04x\n", rdp->byte_count & 0xffff );
printf( " pkt = 0x%04x%04x", rdp->pkt_msw, rdp->pkt_lsw );
printf( " seq_no = %d", rdp->seq_no );
printf( " link = %d\n", rdp->link );
printf( " in_use = %d", rdp->in_use );
printf( " next = %p", rdp->next );
printf( " mbufp = %p", rdp->mbufp );
if ( rdp->mbufp )
printf( " mbufp->data = %p", mtod ( rdp->mbufp, void *) );
puts("");
}
#endif
 
/*
******************************************************************
* *
* Support Routines *
* *
******************************************************************
*/
 
void sonic_enable_interrupts(
struct sonic_softc *sc,
unsigned32 mask
)
{
void *rp = sc->sonic;
rtems_interrupt_level level;
 
rtems_interrupt_disable( level );
(*sc->write_register)(
rp,
SONIC_REG_IMR,
(*sc->read_register)(rp, SONIC_REG_IMR) | mask
);
rtems_interrupt_enable( level );
}
 
void sonic_disable_interrupts(
struct sonic_softc *sc,
unsigned32 mask
)
{
void *rp = sc->sonic;
rtems_interrupt_level level;
 
rtems_interrupt_disable( level );
(*sc->write_register)(
rp,
SONIC_REG_IMR,
(*sc->read_register)(rp, SONIC_REG_IMR) & ~mask
);
rtems_interrupt_enable( level );
}
 
void sonic_clear_interrupts(
struct sonic_softc *sc,
unsigned32 mask
)
{
void *rp = sc->sonic;
rtems_interrupt_level level;
 
rtems_interrupt_disable( level );
(*sc->write_register)( rp, SONIC_REG_ISR, mask);
rtems_interrupt_enable( level );
}
 
void sonic_command(
struct sonic_softc *sc,
unsigned32 mask
)
{
void *rp = sc->sonic;
rtems_interrupt_level level;
 
rtems_interrupt_disable( level );
(*sc->write_register)( rp, SONIC_REG_CR, mask);
rtems_interrupt_enable( level );
}
 
/*
* Allocate non-cacheable memory on a single 64k page.
* Very simple minded -- just keeps trying till the memory is on a single page.
*/
SONIC_STATIC void * sonic_allocate(unsigned int nbytes)
{
void *p;
unsigned long a1, a2;
 
for (;;) {
/*
* ===CACHE===
* Change malloc to malloc_noncacheable_guarded.
*/
p = malloc( nbytes, M_MBUF, M_NOWAIT );
if (p == NULL)
rtems_panic ("No memory!");
memset (p, '\0', nbytes);
a1 = (unsigned long)p;
a2 = a1 + nbytes - 1;
if ((a1 >> 16) == (a2 >> 16))
break;
}
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_ALLOCATE)
printf( "sonic_allocate %d bytes at %p\n", nbytes, p );
#endif
return p;
}
 
/*
* Shut down the interface.
*/
 
SONIC_STATIC void sonic_stop (struct sonic_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
 
ifp->if_flags &= ~IFF_RUNNING;
 
/*
* Stop the transmitter and receiver.
*/
sonic_command(sc, CR_HTX | CR_RXDIS );
}
 
/*
* Show interface statistics
*/
SONIC_STATIC void sonic_stats (struct sonic_softc *sc)
{
printf (" Total Interrupts:%-8lu", sc->Interrupts);
printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
printf (" Giant:%-8lu", sc->rxGiant);
printf (" Non-octet:%-8lu\n", sc->rxNonOctet);
printf (" Bad CRC:%-8lu", sc->rxBadCRC);
printf (" Collision:%-8lu", sc->rxCollision);
printf (" Missed:%-8lu\n", sc->rxMissed);
 
printf ( " Tx Interrupts:%-8lu", sc->txInterrupts);
printf ( " Deferred:%-8lu", sc->txDeferred);
printf (" Lost Carrier:%-8lu\n", sc->txLostCarrier);
printf ( "Single Collisions:%-8lu", sc->txSingleCollision);
printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision);
printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision);
printf ( " Total Collisions:%-8lu", sc->txCollision);
printf ( " Late Collision:%-8lu", sc->txLateCollision);
printf (" Underrun:%-8lu\n", sc->txUnderrun);
printf ( " Raw output wait:%-8lu\n", sc->txRawWait);
}
 
/*
******************************************************************
* *
* Interrupt Handler *
* *
******************************************************************
*/
 
SONIC_STATIC rtems_isr sonic_interrupt_handler (rtems_vector_number v)
{
struct sonic_softc *sc = sonic_softc;
unsigned32 isr, imr;
void *rp;
 
#if (NSONIC > 1)
/*
* Find the device which requires service
*/
for (;;) {
if (sc->vector == v)
break;
if (++sc == &sonic[NSONIC])
return; /* Spurious interrupt? */
}
#endif /* NSONIC > 1 */
 
/*
* Get pointer to SONIC registers
*/
rp = sc->sonic;
 
sc->Interrupts++;
 
isr = (*sc->read_register)( rp, SONIC_REG_ISR );
imr = (*sc->read_register)( rp, SONIC_REG_IMR );
 
/*
* Packet received or receive buffer area exceeded?
*/
if (imr & isr & (IMR_PRXEN | IMR_RBAEEN)) {
imr &= ~(IMR_PRXEN | IMR_RBAEEN);
sc->rxInterrupts++;
rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
(*sc->write_register)( rp, SONIC_REG_IMR, imr );
(*sc->write_register)( rp, SONIC_REG_ISR, isr & ISR_PKTRX );
}
 
/*
* Packet started, transmitter done or transmitter error?
* TX interrupts only occur after an error or when all TDA's are
* exhausted and we are waiting for buffer to come free.
*/
if (imr & isr & (IMR_PINTEN | IMR_TXEREN)) {
sc->txInterrupts++;
rtems_event_send (sc->txDaemonTid, INTERRUPT_EVENT);
(*sc->write_register)( rp, SONIC_REG_ISR, ISR_PINT | ISR_TXDN | ISR_TXER );
}
 
}
 
/*
******************************************************************
* *
* Transmitter Routines *
* *
******************************************************************
*/
 
/*
* Soak up transmit descriptors that have been sent.
*/
 
SONIC_STATIC void sonic_retire_tda (struct sonic_softc *sc)
{
rtems_unsigned16 status;
unsigned int collisions;
struct mbuf *m, *n;
 
/*
* Repeat for all completed transmit descriptors.
*/
while ((status = sc->tdaTail->status) != 0) {
 
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
printf( "retire TDA %p (0x%04x)\n", sc->tdaTail, status );
#endif
 
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
/*
* If there is an error that was not a collision,
* then someone may want to see it.
*/
 
if ( (status & ~(TDA_STATUS_COLLISION_MASK|TDA_STATUS_DEF)) != 0x0001 )
printf( "ERROR: retire TDA %p (0x%08x)\n",
sc->tdaTail, sc->tdaTail->status );
#endif
 
/*
* Check for errors which stop the transmitter.
*/
if (status & (TDA_STATUS_EXD |
TDA_STATUS_EXC |
TDA_STATUS_FU |
TDA_STATUS_BCM)) {
/*
* Restart the transmitter if there are
* packets waiting to go.
*/
rtems_unsigned16 link;
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
printf("restarting sonic after error\n");
#endif
 
link = *(sc->tdaTail->linkp);
 
if ((link & TDA_LINK_EOL) == 0) {
void *rp = sc->sonic;
 
(*sc->write_register)( rp, SONIC_REG_CTDA, link );
sonic_command(sc, CR_TXP );
}
}
 
/*
* Update network statistics
*/
collisions = (status & TDA_STATUS_COLLISION_MASK) >> TDA_STATUS_COLLISION_SHIFT;
if (collisions) {
if (collisions == 1)
sc->txSingleCollision++;
else
sc->txMultipleCollision++;
sc->txCollision += collisions;
}
if (status & TDA_STATUS_EXC)
sc->txExcessiveCollision++;
if (status & TDA_STATUS_OWC)
sc->txLateCollision++;
if (status & TDA_STATUS_EXD)
sc->txExcessiveDeferral++;
if (status & TDA_STATUS_DEF)
sc->txDeferred++;
if (status & TDA_STATUS_FU)
sc->txUnderrun++;
if (status & TDA_STATUS_CRSL)
sc->txLostCarrier++;
 
/*
* Free the packet and reset a couple of fields
*/
m = sc->tdaTail->mbufp;
while ( m ) {
MFREE(m, n);
m = n;
}
 
/*
sc->tdaTail->frag[0].frag_link = LSW(sc->tdaTail->link_pad);
sc->tdaTail->frag_count = 0;
*/
sc->tdaTail->status = 0;
 
/*
* Move to the next transmit descriptor
*/
sc->tdaTail = sc->tdaTail->next;
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
printf( "next TDA %p\n", sc->tdaTail );
#endif
}
}
 
/*
* Send packet
*/
SONIC_STATIC void sonic_sendpacket (struct ifnet *ifp, struct mbuf *m)
{
struct sonic_softc *sc = ifp->if_softc;
struct mbuf *l = NULL;
TransmitDescriptorPointer_t tdp;
volatile struct TransmitDescriptorFragLink *fp;
unsigned int packetSize;
int i;
rtems_event_set events;
static char padBuf[64];
 
/* printf( "sonic_sendpacket %p\n", m ); */
 
 
/*
* Wait for transmit descriptor to become available. Only retire TDA's
* if there are no more free buffers to minimize TX latency. Retire TDA'a
* on the way out.
*/
 
while (sc->tdaHead->next->status != 0) {
/*
* Free up transmit descriptors
*/
sonic_retire_tda (sc);
 
if (sc->tdaHead->next->status == 0)
break;
 
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
printf("blocking until TDAs are available\n");
#endif
/*
* Enable PINT interrupts.
sonic_clear_interrupts( sc, ISR_PINT );
sonic_enable_interrupts( sc, IMR_PINTEN );
*/
 
/*
* Wait for PINT TX interrupt. Every fourth TX buffer will raise PINT.
*/
rtems_bsdnet_event_receive (INTERRUPT_EVENT,
RTEMS_WAIT|RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT,
&events);
sonic_disable_interrupts( sc, IMR_PINTEN );
sonic_retire_tda (sc);
}
 
/*
* Fill in the transmit descriptor fragment descriptors.
* ===CACHE===
* If data cache is operating in write-back mode, flush cached
* data to memory.
*/
tdp = sc->tdaHead->next;
tdp->mbufp = m;
packetSize = 0;
fp = tdp->frag;
for (i = 0 ; i < MAXIMUM_FRAGS_PER_DESCRIPTOR ; i++, fp++) {
/*
* Throw away empty mbufs
*/
if (m->m_len) {
void *p = mtod (m, void *);
fp->frag_lsw = LSW(p);
fp->frag_msw = MSW(p);
fp->frag_size = m->m_len;
packetSize += m->m_len;
#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
printf( "fp %p 0x%04x%04x %d=%d .. %d\n",
fp, fp->frag_msw, fp->frag_lsw, fp->frag_size, m->m_len, packetSize );
#endif
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_TX_MBUFS)
Dump_Buffer(
p,
(fp->frag_size > MAXIMUM_FRAME_SIZE) ? MAXIMUM_FRAME_SIZE : fp->frag_size
);
#endif
l = m;
m = m->m_next;
}
else {
struct mbuf *n;
MFREE (m, n);
m = n;
if (l != NULL)
l->m_next = m;
}
/*
* Break out of the loop if this mbuf is the last in the frame.
*/
if (m == NULL)
break;
}
 
/*
* Pad short packets.
*/
if ((packetSize < 64) && (i < MAXIMUM_FRAGS_PER_DESCRIPTOR)) {
int padSize = 64 - packetSize;
fp++;
fp->frag_lsw = LSW(padBuf);
fp->frag_msw = MSW(padBuf);
fp->frag_size = padSize;
#if (SONIC_DEBUG & SONIC_DEBUG_FRAGMENTS)
printf( "PAD fp %p 0x%04x%04x %d\n",
fp, fp->frag_msw, fp->frag_lsw, fp->frag_size );
#endif
packetSize += padSize;
i++;
}
 
/*
* Fill Transmit Descriptor
*/
tdp->pkt_size = packetSize;
tdp->frag_count = i + 1;
tdp->status = 0;
 
/*
* Chain onto list and start transmission.
*/
 
tdp->linkp = &(fp+1)->frag_link;
*tdp->linkp = LSW(tdp->next) | TDA_LINK_EOL;
if ( sc->tdaHead->frag_count )
*sc->tdaHead->linkp &= ~TDA_LINK_EOL;
sc->tdaHead = tdp;
 
/* Start transmission */
 
sonic_command(sc, CR_TXP );
 
/*
* Free up transmit descriptors on the way out.
*/
sonic_retire_tda (sc);
}
 
/*
* Driver transmit daemon
*/
SONIC_STATIC void sonic_txDaemon (void *arg)
{
struct sonic_softc *sc = (struct sonic_softc *)arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
struct mbuf *m;
rtems_event_set events;
 
for (;;) {
/*
* Wait for packet
*/
rtems_bsdnet_event_receive (
START_TRANSMIT_EVENT,
RTEMS_EVENT_ANY | RTEMS_WAIT,
RTEMS_NO_TIMEOUT,
&events
);
 
/*
* Send packets till queue is empty
*/
for (;;) {
/*
* Get the next mbuf chain to transmit.
*/
IF_DEQUEUE(&ifp->if_snd, m);
if (!m)
break;
sonic_sendpacket (ifp, m);
}
ifp->if_flags &= ~IFF_OACTIVE;
}
}
 
/*
******************************************************************
* *
* Receiver Routines *
* *
******************************************************************
*/
 
/*
* Wait for SONIC to hand over a Receive Descriptor.
*/
 
SONIC_STATIC void sonic_rda_wait(
struct sonic_softc *sc,
ReceiveDescriptorPointer_t rdp
)
{
int i;
void *rp = sc->sonic;
rtems_event_set events;
 
/*
* Wait for Receive Descriptor.
* The order of the tests is very important.
* The RDA is checked after RBAE is detected. This ensures that
* the driver processes all RDA entries before reusing the RRA
* entry holding the giant packet.
* The event wait is done after the RDA and RBAE checks. This
* catches the possibility that a Receive Descriptor became ready
* between the call to this function and the clearing of the
* interrupt status register bit.
*/
for (;;) {
/*
* Has a giant packet arrived?
* The National DP83932C data sheet is very vague on what
* happens under this condition. The description of the
* Interrupt Status Register (Section 4.3.6) states,
* ``Reception is aborted and the SONIC fetches the next
* available resource descriptors in the RRA. The buffer
* space is not re-used and an RDA is not setup for the
* truncated packet.''
* I take ``Reception is aborted'' to mean that the RXEN
* bit in the Command Register is cleared and must be set
* by the driver to begin reception again.
* Unfortunately, an alternative interpretation could be
* that only reception of the current packet is aborted.
* This would be more difficult to recover from....
*/
if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBAE) {
 
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
printf( "ERROR: looks like a giant packet -- RBAE\n" );
#endif
 
/*
* One more check to soak up any Receive Descriptors
* that may already have been handed back to the driver.
*/
if (rdp->in_use == RDA_IN_USE) {
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
printf( "ERROR: nope just an RBAE\n" );
#endif
break;
}
 
/*
* Check my interpretation of the SONIC manual.
*/
if ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RXEN)
rtems_panic ("SONIC RBAE/RXEN");
 
/*
* Update statistics
*/
sc->rxGiant++;
 
/*
* Reuse receive buffer.
* Again, the manual is subject to interpretation. The
* RRP register is described as, `the lower address of
* the next descriptor the SONIC will read.''
* Since, acording to the ISR/RBAE notes, the SONIC has
* ``fetched the next available resource descriptor in
* the RRA'', I interpret this to mean that that the
* driver has to move the RRP back *two* entries to
* reuse the receive buffer holding the giant packet.
*/
for (i = 0 ; i < 2 ; i++) {
if ((*sc->read_register)( rp, SONIC_REG_RRP ) ==
(*sc->read_register)( rp, SONIC_REG_RSA ))
(*sc->write_register)(
rp,
SONIC_REG_RRP,
(*sc->read_register)( rp, SONIC_REG_REA )
);
(*sc->write_register)(
rp,
SONIC_REG_RRP,
(*sc->read_register)(rp, SONIC_REG_RRP) - sizeof(ReceiveResource_t)
);
}
 
/*
* Restart reception
*/
sonic_clear_interrupts( sc, ISR_RBAE );
sonic_command( sc, CR_RXEN );
}
 
/*
* Has Receive Descriptor become available?
*/
if (rdp->in_use == RDA_IN_USE)
break;
 
/*
* Enable interrupts.
*/
sonic_enable_interrupts( sc, (IMR_PRXEN | IMR_RBAEEN) );
 
/*
* Wait for interrupt.
*/
rtems_bsdnet_event_receive(
INTERRUPT_EVENT,
RTEMS_WAIT|RTEMS_EVENT_ANY,
RTEMS_NO_TIMEOUT,
&events
);
}
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
printf( "RDA %p\n", rdp );
#endif
 
#if (SONIC_DEBUG & SONIC_DEBUG_ERRORS)
if (rdp->status & 0x000E)
printf( "ERROR: RDA %p (0x%04x)\n", rdp, rdp->status );
#endif
 
}
 
/*
* SONIC reader task
*/
SONIC_STATIC void sonic_rxDaemon (void *arg)
{
struct sonic_softc *sc = (struct sonic_softc *)arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
void *rp = sc->sonic;
struct mbuf *m;
rtems_unsigned16 status;
ReceiveDescriptorPointer_t rdp;
ReceiveResourcePointer_t rwp, rea;
rtems_unsigned16 newMissedTally, oldMissedTally;
 
rwp = sc->rsa;
rea = sc->rea;
rdp = sc->rda;
 
/*
* Start the receiver
*/
oldMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );
 
/*
* Input packet handling loop
*/
for (;;) {
/*
* Wait till SONIC supplies a Receive Descriptor.
*/
if (rdp->in_use == RDA_FREE) {
sonic_rda_wait (sc, rdp);
}
 
#if (SONIC_DEBUG & SONIC_DEBUG_DESCRIPTORS)
printf( "Incoming packet %p status=0x%04x\n", rdp, rdp->status );
#endif
 
/*
* Check that packet is valid
*/
status = rdp->status;
if (status & RDA_STATUS_PRX) {
struct ether_header *eh;
void *p;
 
/*
* Pass the packet up the chain.
* The mbuf count is reduced to remove
* the frame check sequence at the end
* of the packet.
* ===CACHE===
* Invalidate cache entries for this memory.
*/
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
sonic_print_rx_descriptor( rdp );
if ((LSW(rdp->mbufp->m_data) != rdp->pkt_lsw)
|| (MSW(rdp->mbufp->m_data) != rdp->pkt_msw))
printf ("SONIC RDA/RRA %p, %08x\n",rdp->mbufp->m_data,(rdp->pkt_msw << 16) |
(rdp->pkt_lsw & 0x0ffff));
#endif
rdp->byte_count &= 0x0ffff; /* ERC32 pollutes msb of byte_count */
m = rdp->mbufp;
m->m_len = m->m_pkthdr.len = rdp->byte_count -
sizeof(rtems_unsigned32) -
sizeof(struct ether_header);
eh = mtod (m, struct ether_header *);
m->m_data += sizeof(struct ether_header);
#ifdef CPU_U32_FIX
ipalign(m); /* Align packet on 32-bit boundary */
#endif
 
#if (SONIC_DEBUG & SONIC_DEBUG_DUMP_RX_MBUFS)
Dump_Buffer( (void *) eh, sizeof(struct ether_header) );
Dump_Buffer( (void *) m, 96 /* m->m_len*/ );
#endif
 
/* printf( "ether_input %p\n", m ); */
/*
printf( "pkt %p, seq %04x, mbuf %p, m_data %p\n", rdp, rdp->seq_no, m, m->m_data );
printf( "%u, %u\n", ((int*)m->m_data)[6], ((int*)m->m_data)[7]);
*/
ether_input (ifp, eh, m);
/*
*/
 
/*
* Sanity check that Receive Resource Area is
* still in sync with Receive Descriptor Area
* The buffer reported in the Receive Descriptor
* should be the same as the buffer in the Receive
* Resource we are about to reuse.
*/
/* XXX figure out whether this is valid or not */
#if 0
if ((LSW(p) != rwp->buff_ptr_lsw)
|| (MSW(p) != rwp->buff_ptr_msw))
rtems_panic ("SONIC RDA/RRA");
#endif
 
/*
* Allocate a new mbuf.
*/
 
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = ifp;
rdp->mbufp = m;
p = mtod (m, void *);
 
/*
* Reuse Receive Resource.
*/
 
rwp->buff_ptr_lsw = LSW(p);
rwp->buff_ptr_msw = MSW(p);
rwp->buff_wc_lsw = RBUF_WC;
rwp->buff_wc_msw = 0;
rwp++;
 
if (rwp == rea) {
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
printf( "Wrapping RWP from %p to %p\n", rwp, sc->rsa );
#endif
rwp = sc->rsa;
}
(*sc->write_register)( rp, SONIC_REG_RWP , LSW(rwp) );
 
/*
* Tell the SONIC to reread the RRA.
*/
if ((*sc->read_register)( rp, SONIC_REG_ISR ) & ISR_RBE)
sonic_clear_interrupts( sc, ISR_RBE );
}
else {
if (status & RDA_STATUS_COL)
sc->rxCollision++;
if (status & RDA_STATUS_FAER)
sc->rxNonOctet++;
else if (status & RDA_STATUS_CRCR)
sc->rxBadCRC++;
}
 
/*
* Count missed packets
*/
newMissedTally = (*sc->read_register)( rp, SONIC_REG_MPT );
if (newMissedTally != oldMissedTally) {
sc->rxMissed += (newMissedTally - oldMissedTally) & 0xFFFF;
newMissedTally = oldMissedTally;
}
 
/*
* Move to next receive descriptor and update EOL
*/
 
rdp->link |= RDA_LINK_EOL;
rdp->in_use = RDA_FREE;
sc->rdp_last->link &= ~RDA_LINK_EOL;
sc->rdp_last = rdp;
rdp = rdp->next;
 
}
}
 
/*
******************************************************************
* *
* Initialization Routines *
* *
******************************************************************
*/
 
/*
* Initialize the SONIC hardware
*/
SONIC_STATIC void sonic_initialize_hardware(struct sonic_softc *sc)
{
void *rp = sc->sonic;
int i;
unsigned char *hwaddr;
rtems_isr_entry old_handler;
TransmitDescriptorPointer_t tdp;
ReceiveDescriptorPointer_t ordp, rdp;
ReceiveResourcePointer_t rwp;
struct mbuf *m;
void *p;
CamDescriptorPointer_t cdp;
 
/*
* The Revision B SONIC has a horrible bug known as the "Zero
* Length Packet bug". The initial board used to develop this
* driver had a newer revision of the SONIC so there was no reason
* to check for this. If you have the Revision B SONIC chip, then
* you need to add some code to the RX path to handle this weirdness.
*/
 
if ( (*sc->read_register)( rp, SONIC_REG_SR ) <= SONIC_REVISION_B ) {
rtems_fatal_error_occurred( 0x0BADF00D ); /* don't eat this part :) */
}
/*
* Set up circular linked list in Transmit Descriptor Area.
* Use the PINT bit in the transmit configuration field to
* request an interrupt on every other transmitted packet.
*
* NOTE: sonic_allocate() zeroes all of the memory allocated.
*/
 
sc->tdaTail = sonic_allocate(sc->tdaCount * sizeof *tdp);
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
printf( "tdaTail = %p\n", sc->tdaTail );
#endif
tdp = sc->tdaTail;
for (i = 0 ; i < sc->tdaCount ; i++) {
/*
* Start off with the table of outstanding mbuf's
*/
 
/*
* status, pkt_config, pkt_size, and all fragment fields
* are set to zero by sonic_allocate.
*/
 
/* XXX not used by the BSD drivers
tdp->frag[0].frag_link = LSW(tdp + 1);
*/
if (i & 3)
tdp->pkt_config = TDA_CONFIG_PINT;
 
tdp->status = 0;
tdp->frag_count = 0;
tdp->link_pad = LSW(tdp + 1) | TDA_LINK_EOL;
tdp->linkp = &((tdp + 1)->frag[0].frag_link);
tdp->next = (TransmitDescriptor_t *)(tdp + 1);
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
sonic_print_tx_descriptor( tdp );
#endif
tdp++;
}
tdp--;
sc->tdaHead = tdp;
tdp->link_pad = LSW(sc->tdaTail) | TDA_LINK_EOL;
tdp->next = (TransmitDescriptor_t *)sc->tdaTail;
tdp->linkp = &sc->tdaTail->frag[0].frag_link;
 
/*
* Set up circular linked list in Receive Descriptor Area.
* Leaves sc->rda pointing at the `beginning' of the list.
*
* NOTE: The RDA and CDP must have the same MSW for their addresses.
*/
 
sc->rda = sonic_allocate(
(sc->rdaCount * sizeof(ReceiveDescriptor_t)) +
sizeof(CamDescriptor_t) );
sc->cdp = (CamDescriptorPointer_t) ((unsigned char *)sc->rda +
(sc->rdaCount * sizeof(ReceiveDescriptor_t)));
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
printf( "rda area = %p\n", sc->rda );
printf( "cdp area = %p\n", sc->cdp );
#endif
 
ordp = rdp = sc->rda;
for (i = 0 ; i < sc->rdaCount ; i++) {
/*
* status, byte_count, pkt_ptr0, pkt_ptr1, and seq_no are set
* to zero by sonic_allocate.
*/
rdp->link = LSW(rdp + 1);
rdp->in_use = RDA_FREE;
rdp->next = (ReceiveDescriptor_t *)(rdp + 1);
ordp = rdp;
rdp++;
}
/*
* Link the last desriptor to the 1st one and mark it as the end
* of the list.
*/
ordp->next = sc->rda;
ordp->link = LSW(sc->rda) | RDA_LINK_EOL;
sc->rdp_last = ordp;
/*
* Allocate the receive resource area.
* In accordance with National Application Note 746, make the
* receive resource area bigger than the receive descriptor area.
* This has the useful side effect of making the receive resource
* area big enough to hold the CAM descriptor area.
*/
 
sc->rsa = sonic_allocate((sc->rdaCount + RRA_EXTRA_COUNT) * sizeof *sc->rsa);
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
printf( "rsa area = %p\n", sc->rsa );
#endif
 
/*
* Set up list in Receive Resource Area.
* Allocate space for incoming packets.
*/
 
rwp = sc->rsa;
for (i = 0 ; i < (sc->rdaCount + RRA_EXTRA_COUNT) ; i++, rwp++) {
 
/*
* Allocate memory for buffer.
* Place a pointer to the mbuf at the beginning of the buffer
* so we can find the mbuf when the SONIC returns the buffer
* to the driver.
*/
MGETHDR (m, M_WAIT, MT_DATA);
MCLGET (m, M_WAIT);
m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
sc->rda[i].mbufp = m;
 
p = mtod (m, void *);
 
/*
* Set up RRA entry
*/
rwp->buff_ptr_lsw = LSW(p);
rwp->buff_ptr_msw = MSW(p);
rwp->buff_wc_lsw = RBUF_WC;
rwp->buff_wc_msw = 0;
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY_DESCRIPTORS)
sonic_print_rx_descriptor( &sc->rda[i] );
#endif
}
sc->rea = rwp;
#if (SONIC_DEBUG & SONIC_DEBUG_MEMORY)
printf( "rea area = %p\n", sc->rea );
#endif
 
 
/*
* Issue a software reset.
*/
(*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
 
/*
* Set up data configuration registers.
*/
(*sc->write_register)( rp, SONIC_REG_DCR, sc->dcr_value );
(*sc->write_register)( rp, SONIC_REG_DCR2, sc->dc2_value );
 
(*sc->write_register)( rp, SONIC_REG_CR, CR_STP | CR_RXDIS | CR_HTX );
 
/*
* Mask all interrupts
*/
(*sc->write_register)( rp, SONIC_REG_IMR, 0x0 ); /* XXX was backwards */
 
/*
* Clear outstanding interrupts.
*/
(*sc->write_register)( rp, SONIC_REG_ISR, 0x7FFF );
 
/*
* Clear the tally counters
*/
 
(*sc->write_register)( rp, SONIC_REG_CRCT, 0xFFFF );
(*sc->write_register)( rp, SONIC_REG_FAET, 0xFFFF );
(*sc->write_register)( rp, SONIC_REG_MPT, 0xFFFF );
(*sc->write_register)( rp, SONIC_REG_RSC, 0 );
 
/*
* Set the Receiver mode
*
* Enable/disable reception of broadcast packets
*/
 
if (sc->acceptBroadcast)
(*sc->write_register)( rp, SONIC_REG_RCR, RCR_BRD );
else
(*sc->write_register)( rp, SONIC_REG_RCR, 0 );
 
/*
* Set up Resource Area pointers
*/
 
(*sc->write_register)( rp, SONIC_REG_URRA, MSW(sc->rsa) );
(*sc->write_register)( rp, SONIC_REG_RSA, LSW(sc->rsa) );
 
(*sc->write_register)( rp, SONIC_REG_REA, LSW(sc->rea) );
 
(*sc->write_register)( rp, SONIC_REG_RRP, LSW(sc->rsa) );
(*sc->write_register)( rp, SONIC_REG_RWP, LSW(sc->rsa) ); /* XXX was rea */
 
(*sc->write_register)( rp, SONIC_REG_URDA, MSW(sc->rda) );
(*sc->write_register)( rp, SONIC_REG_CRDA, LSW(sc->rda) );
 
(*sc->write_register)( rp, SONIC_REG_UTDA, MSW(sc->tdaTail) );
(*sc->write_register)( rp, SONIC_REG_CTDA, LSW(sc->tdaTail) );
 
/*
* Set End Of Buffer Count register to the value recommended
* in Note 1 of Section 3.4.4.4 of the SONIC data sheet.
*/
 
(*sc->write_register)( rp, SONIC_REG_EOBC, RBUF_WC - 2 );
 
/*
* Issue the load RRA command
*/
 
(*sc->write_register)( rp, SONIC_REG_CR, CR_RRRA );
while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_RRRA)
continue;
 
/*
* Remove device reset
*/
 
(*sc->write_register)( rp, SONIC_REG_CR, 0 );
 
/*
* Set up the SONIC CAM with our hardware address.
*/
 
hwaddr = sc->arpcom.ac_enaddr;
cdp = sc->cdp;
 
#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
printf( "hwaddr: %2x:%2x:%2x:%2x:%2x:%2x\n",
hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5] );
#endif
 
cdp->cep = 0; /* Fill first and only entry in CAM */
cdp->cap0 = hwaddr[1] << 8 | hwaddr[0];
cdp->cap1 = hwaddr[3] << 8 | hwaddr[2];
cdp->cap2 = hwaddr[5] << 8 | hwaddr[4];
cdp->ce = 0x0001; /* Enable first entry in CAM */
 
(*sc->write_register)( rp, SONIC_REG_CDC, 1 ); /* 1 entry in CDA */
(*sc->write_register)( rp, SONIC_REG_CDP, LSW(cdp) );
(*sc->write_register)( rp, SONIC_REG_CR, CR_LCAM ); /* Load the CAM */
 
while ((*sc->read_register)( rp, SONIC_REG_CR ) & CR_LCAM)
continue;
 
/*
* Verify that CAM was properly loaded.
*/
 
(*sc->write_register)( rp, SONIC_REG_CR, CR_RST | CR_STP | CR_RXDIS | CR_HTX );
 
#if (SONIC_DEBUG & SONIC_DEBUG_CAM)
(*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */
printf ("Loaded Ethernet address into SONIC CAM.\n"
" Wrote %04x%04x%04x - %#x\n"
" Read %04x%04x%04x - %#x\n",
cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
(*sc->read_register)( rp, SONIC_REG_CAP2 ),
(*sc->read_register)( rp, SONIC_REG_CAP1 ),
(*sc->read_register)( rp, SONIC_REG_CAP0 ),
(*sc->read_register)( rp, SONIC_REG_CE ));
 
(*sc->write_register)( rp, SONIC_REG_CEP, 0 ); /* Select first entry in CAM */
if (((*sc->read_register)( rp, SONIC_REG_CAP2 ) != cdp->cap2)
|| ((*sc->read_register)( rp, SONIC_REG_CAP1 ) != cdp->cap1)
|| ((*sc->read_register)( rp, SONIC_REG_CAP0 ) != cdp->cap0)
|| ((*sc->read_register)( rp, SONIC_REG_CE ) != cdp->ce)) {
printf ("Failed to load Ethernet address into SONIC CAM.\n"
" Wrote %04x%04x%04x - %#x\n"
" Read %04x%04x%04x - %#x\n",
cdp->cap2, cdp->cap1, cdp->cap0, cdp->ce,
(*sc->read_register)( rp, SONIC_REG_CAP2 ),
(*sc->read_register)( rp, SONIC_REG_CAP1 ),
(*sc->read_register)( rp, SONIC_REG_CAP0 ),
(*sc->read_register)( rp, SONIC_REG_CE ));
rtems_panic ("SONIC LCAM");
}
#endif
 
(*sc->write_register)(rp, SONIC_REG_CR, /* CR_TXP | */CR_RXEN | CR_STP);
 
/*
* Attach SONIC interrupt handler
*/
/* XXX
(*sc->write_register)( rp, SONIC_REG_IMR, 0 );
*/
old_handler = set_vector(sonic_interrupt_handler, sc->vector, 1);
 
/*
* Remainder of hardware initialization is
* done by the receive and transmit daemons.
*/
}
 
/*
* Send packet (caller provides header).
*/
 
SONIC_STATIC void sonic_start(struct ifnet *ifp)
{
struct sonic_softc *sc = ifp->if_softc;
 
rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT);
ifp->if_flags |= IFF_OACTIVE;
}
 
/*
* Initialize and start the device
*/
 
SONIC_STATIC void sonic_init (void *arg)
{
struct sonic_softc *sc = arg;
struct ifnet *ifp = &sc->arpcom.ac_if;
void *rp = sc->sonic;
int rcr;
 
if (sc->txDaemonTid == 0) {
 
/*
* Set up SONIC hardware
*/
sonic_initialize_hardware (sc);
 
/*
* Start driver tasks
*/
sc->rxDaemonTid = rtems_bsdnet_newproc ("SNrx", 4096, sonic_rxDaemon, sc);
sc->txDaemonTid = rtems_bsdnet_newproc ("SNtx", 4096, sonic_txDaemon, sc);
}
 
/*
* Set flags appropriately
*/
rcr = (*sc->read_register)( rp, SONIC_REG_RCR );
if (ifp->if_flags & IFF_PROMISC)
rcr |= RCR_PRO;
else
rcr &= ~RCR_PRO;
(*sc->write_register)( rp, SONIC_REG_RCR, rcr);
 
/*
* Tell the world that we're running.
*/
ifp->if_flags |= IFF_RUNNING;
 
/*
* Enable receiver and transmitter
*/
sonic_enable_interrupts( sc, IMR_TXEREN | (IMR_PRXEN | IMR_RBAEEN) );
sonic_command( sc, CR_RXEN );
}
 
/*
* Driver ioctl handler
*/
static int
sonic_ioctl (struct ifnet *ifp, int command, caddr_t data)
{
struct sonic_softc *sc = ifp->if_softc;
int error = 0;
 
switch (command) {
case SIOCGIFADDR:
case SIOCSIFADDR:
ether_ioctl (ifp, command, data);
break;
 
case SIOCSIFFLAGS:
switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
case IFF_RUNNING:
sonic_stop (sc);
break;
 
case IFF_UP:
sonic_init (sc);
break;
 
case IFF_UP | IFF_RUNNING:
sonic_stop (sc);
sonic_init (sc);
break;
 
default:
break;
}
break;
 
case SIO_RTEMS_SHOW_STATS:
sonic_stats (sc);
break;
/*
* FIXME: All sorts of multicast commands need to be added here!
*/
default:
error = EINVAL;
break;
}
return error;
}
 
/*
* Attach an SONIC driver to the system
* This is the only `extern' function in the driver.
*/
 
int
rtems_sonic_driver_attach (
struct rtems_bsdnet_ifconfig *config,
sonic_configuration_t *chip
)
{
struct sonic_softc *sc;
struct ifnet *ifp;
int mtu;
int unitNumber;
char *unitName;
 
/*
* Parse driver name
*/
if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
return 0;
 
/*
* Is driver free?
*/
if ((unitNumber <= 0) || (unitNumber > NSONIC)) {
printf ("Bad SONIC unit number.\n");
return 0;
}
sc = &sonic_softc[unitNumber - 1];
ifp = &sc->arpcom.ac_if;
if (ifp->if_softc != NULL) {
printf ("Driver already in use.\n");
return 0;
}
 
/*
* zero out the control structure
*/
 
memset( sc, 0, sizeof(*sc) );
 
 
/*
* Process options
*/
if (config->hardware_address) {
memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
}
else {
memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN);
}
if (config->mtu)
mtu = config->mtu;
else
mtu = ETHERMTU;
if (config->rbuf_count)
sc->rdaCount = config->rbuf_count;
else
sc->rdaCount = chip->rda_count;
if (config->xbuf_count)
sc->tdaCount = config->xbuf_count;
else
sc->tdaCount = chip->tda_count;
sc->acceptBroadcast = !config->ignore_broadcast;
 
sc->sonic = (void *) chip->base_address;
sc->vector = chip->vector;
sc->dcr_value = chip->dcr_value;
sc->dc2_value = chip->dc2_value;
sc->write_register = chip->write_register;
sc->read_register = chip->read_register;
 
/*
* Set up network interface values
*/
ifp->if_softc = sc;
ifp->if_unit = unitNumber;
ifp->if_name = unitName;
ifp->if_mtu = mtu;
ifp->if_init = sonic_init;
ifp->if_ioctl = sonic_ioctl;
ifp->if_start = sonic_start;
ifp->if_output = ether_output;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
if (ifp->if_snd.ifq_maxlen == 0)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
 
/*
* Attach the interface
*/
if_attach (ifp);
ether_ifattach (ifp);
return 1;
}
 
#if (SONIC_DEBUG & SONIC_DEBUG_PRINT_REGISTERS)
#include <stdio.h>
 
char SONIC_Reg_name[64][6]= {
"CR", /* 0x00 */
"DCR", /* 0x01 */
"RCR", /* 0x02 */
"TCR", /* 0x03 */
"IMR", /* 0x04 */
"ISR", /* 0x05 */
"UTDA", /* 0x06 */
"CTDA", /* 0x07 */
"0x08", /* 0x08 */
"0x09", /* 0x09 */
"0x0A", /* 0x0A */
"0x0B", /* 0x0B */
"0x0C", /* 0x0C */
"URDA", /* 0x0D */
"CRDA", /* 0x0E */
"0x0F", /* 0x0F */
"0x10", /* 0x10 */
"0x11", /* 0x11 */
"0x12", /* 0x12 */
"EOBC", /* 0x13 */
"URRA", /* 0x14 */
"RSA", /* 0x15 */
"REA", /* 0x16 */
"RRP", /* 0x17 */
"RWP", /* 0x18 */
"0x19", /* 0x19 */
"0x1A", /* 0x1A */
"0x1B", /* 0x1B */
"0x1C", /* 0x1C */
"0x0D", /* 0x1D */
"0x1E", /* 0x1E */
"0x1F", /* 0x1F */
"0x20", /* 0x20 */
"CEP", /* 0x21 */
"CAP2", /* 0x22 */
"CAP1", /* 0x23 */
"CAP0", /* 0x24 */
"CE", /* 0x25 */
"CDP", /* 0x26 */
"CDC", /* 0x27 */
"SR", /* 0x28 */
"WT0", /* 0x29 */
"WT1", /* 0x2A */
"RSC", /* 0x2B */
"CRCT", /* 0x2C */
"FAET", /* 0x2D */
"MPT", /* 0x2E */
"MDT", /* 0x2F */
"0x30", /* 0x30 */
"0x31", /* 0x31 */
"0x32", /* 0x32 */
"0x33", /* 0x33 */
"0x34", /* 0x34 */
"0x35", /* 0x35 */
"0x36", /* 0x36 */
"0x37", /* 0x37 */
"0x38", /* 0x38 */
"0x39", /* 0x39 */
"0x3A", /* 0x3A */
"0x3B", /* 0x3B */
"0x3C", /* 0x3C */
"0x3D", /* 0x3D */
"0x3E", /* 0x3E */
"DCR2" /* 0x3F */
};
#endif
/network/README
0,0 → 1,16
#
# $Id: README,v 1.2 2001-09-27 12:01:41 chris Exp $
#
 
This is the network interface controller portion of the libchip library.
This directory contains the source code for reusable TCP/IP network driver
support code. Each driver has its own configuration table and its
chip specific attach routine must be called by a board specific
attach routine. The board specific chip routine passes the chip
configuration and network configuration to the resuable device driver.
 
The reusable chip drivers do not directly access the controller.
They access the registers on the controller via a set of
functions which are provided by the BSP. These functions set and get
general registers and data buffers.
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.