forked from Imagelibrary/rtems
Changes made to support the DIMMPC. This is a pc396 target with IO port
support. Minor formating clean up. Add documentation to the header file.
This commit is contained in:
@@ -1,23 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
$Id$
|
cs8900.c,v 1.5 2002/11/13 15:34:39 joel Exp
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
My Right Boot, a boot ROM for embedded hardware.
|
|
||||||
|
|
||||||
Copyright Cybertec Pty Ltd, 2000
|
Copyright Cybertec Pty Ltd, 2000
|
||||||
All rights reserved Cybertec Pty Ltd, 2000
|
All rights reserved Cybertec Pty Ltd, 2000
|
||||||
|
|
||||||
|
Port to the DIMM PC copyright (c) 2004 Angelo Fraietta
|
||||||
|
This project has been assisted by the Commonwealth Government
|
||||||
|
through the Australia Council, its arts funding and advisory body.
|
||||||
|
|
||||||
COPYRIGHT (c) 1989-1998.
|
COPYRIGHT (c) 1989-1998.
|
||||||
On-Line Applications Research Corporation (OAR).
|
On-Line Applications Research Corporation (OAR).
|
||||||
|
Copyright assigned to U.S. Government, 1994.
|
||||||
|
|
||||||
The license and distribution terms for this file may be
|
The license and distribution terms for this file may be
|
||||||
found in the file LICENSE in this distribution or at
|
found in the file LICENSE in this distribution or at
|
||||||
http://www.rtems.com/license/LICENSE.
|
http://www.OARcorp.com/rtems/license.html.
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
CS8900 net boot driver.
|
CS8900 RTEMS driver.
|
||||||
|
|
||||||
|
See the header file for details.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -25,67 +30,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* #include <target.h>
|
|
||||||
chris explain what this is to contain and provide a default one */
|
|
||||||
#include "cs8900.h"
|
#include "cs8900.h"
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
***********************************************************
|
|
||||||
BEGIN SECTION OF DEFAULT DEFINES
|
|
||||||
***********************************************************
|
|
||||||
***********************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Number of devices supported by this driver
|
|
||||||
*/
|
|
||||||
#ifndef CS8900_DEVICES
|
|
||||||
#define CS8900_DEVICES 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This variable really should come from a per device configuration
|
|
||||||
* table so the base can vary by adapter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CS8900_IO_BASE
|
|
||||||
extern unsigned int bsp_cs8900_io_base;
|
|
||||||
#define CS8900_IO_BASE bsp_cs8900_io_base
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This variable really should come from a per device configuration
|
|
||||||
* table so the base can vary by adapter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CS8900_MEMORY_BASE
|
|
||||||
extern unsigned int bsp_cs8900_memory_base;
|
|
||||||
#define CS8900_MEMORY_BASE bsp_cs8900_memory_base
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This could go to a BSP provided callout.
|
|
||||||
*/
|
|
||||||
#ifndef WATCHDOG_TOGGLE
|
|
||||||
#define WATCHDOG_TOGGLE()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This variable really should come from a per device configuration
|
|
||||||
* table so the base can vary by adapter.
|
|
||||||
*
|
|
||||||
* chris this is probably not a good default --joel
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CS8900_RX_QUEUE_SIZE
|
|
||||||
#define CS8900_RX_QUEUE_SIZE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
***********************************************************
|
|
||||||
END SECTION OF DEFAULT DEFINES
|
|
||||||
***********************************************************
|
|
||||||
***********************************************************/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We expect to be able to read a complete packet into an mbuf.
|
* We expect to be able to read a complete packet into an mbuf.
|
||||||
*/
|
*/
|
||||||
@@ -103,88 +49,124 @@ extern unsigned int bsp_cs8900_memory_base;
|
|||||||
#define CS8900_TX_OK_EVENT RTEMS_EVENT_2
|
#define CS8900_TX_OK_EVENT RTEMS_EVENT_2
|
||||||
#define CS8900_TX_WAIT_EVENT RTEMS_EVENT_3
|
#define CS8900_TX_WAIT_EVENT RTEMS_EVENT_3
|
||||||
|
|
||||||
/*
|
|
||||||
* Our local data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static cs8900_device cs8900[CS8900_DEVICES];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IO Packet Page inteface.
|
* IO Packet Page inteface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline unsigned short
|
static inline unsigned short
|
||||||
io_pp_get_reg_16 (int dev, unsigned short reg)
|
io_pp_get_reg_16 (cs8900_device *cs, unsigned short reg)
|
||||||
{
|
{
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,
|
rtems_interrupt_level level;
|
||||||
|
unsigned short data;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR,
|
||||||
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
||||||
return cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0);
|
data = cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long
|
static inline unsigned long
|
||||||
io_pp_get_reg_32 (int dev, unsigned short reg)
|
io_pp_get_reg_32 (cs8900_device *cs, unsigned short reg)
|
||||||
{
|
{
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,
|
rtems_interrupt_level level;
|
||||||
|
unsigned long data;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR,
|
||||||
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
||||||
return ((cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0) << 16) |
|
data = ((cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT0) << 16) |
|
||||||
cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1));
|
cs8900_io_get_reg (cs, CS8900_IO_PP_DATA_PORT1));
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
io_pp_set_reg_16 (int dev, unsigned short reg, unsigned short data)
|
io_pp_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short data)
|
||||||
{
|
{
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,
|
rtems_interrupt_level level;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR,
|
||||||
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data);
|
cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
io_pp_set_reg_32 (int dev, unsigned short reg, unsigned long data)
|
io_pp_set_reg_32 (cs8900_device *cs, unsigned short reg, unsigned long data)
|
||||||
{
|
{
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR,
|
cs8900_io_set_reg (cs, CS8900_IO_PACKET_PAGE_PTR,
|
||||||
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
0x3000 | CS8900_PPP_AUTO_INCREMENT | reg);
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data >> 16);
|
cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT0, data >> 16);
|
||||||
cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1, data);
|
cs8900_io_set_reg (cs, CS8900_IO_PP_DATA_PORT1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
io_pp_bit_set_reg_16 (int dev, unsigned short reg, unsigned short mask)
|
io_pp_bit_set_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask)
|
||||||
{
|
{
|
||||||
io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) | mask);
|
rtems_interrupt_level level;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) | mask);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
io_pp_bit_clear_reg_16 (int dev, unsigned short reg, unsigned short mask)
|
io_pp_bit_clear_reg_16 (cs8900_device *cs, unsigned short reg, unsigned short mask)
|
||||||
{
|
{
|
||||||
io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) & ~mask);
|
rtems_interrupt_level level;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
io_pp_set_reg_16 (cs, reg, io_pp_get_reg_16 (cs, reg) & ~mask);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory Mapped Packet Page interface.
|
* Memory Mapped Packet Page interface.
|
||||||
|
*
|
||||||
|
* If the BSP does not configure mem_base use the I/O register accesses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline unsigned short
|
static inline unsigned short
|
||||||
mem_pp_get_reg (int dev, unsigned short reg)
|
mem_pp_get_reg (cs8900_device *cs, unsigned short reg)
|
||||||
{
|
{
|
||||||
return cs8900_mem_get_reg (dev, CS8900_MEMORY_BASE + reg);
|
if (!cs->mem_base)
|
||||||
|
return io_pp_get_reg_16 (cs, reg);
|
||||||
|
return cs8900_mem_get_reg (cs, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
mem_pp_set_reg (int dev, unsigned short reg, unsigned short data)
|
mem_pp_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data)
|
||||||
{
|
{
|
||||||
cs8900_mem_set_reg (dev, CS8900_MEMORY_BASE + reg, data);
|
if (!cs->mem_base)
|
||||||
|
io_pp_set_reg_16 (cs, reg, data);
|
||||||
|
else
|
||||||
|
cs8900_mem_set_reg (cs, reg, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
mem_pp_bit_set_reg (int dev, unsigned short reg, unsigned short mask)
|
mem_pp_bit_set_reg (cs8900_device *cs, unsigned short reg, unsigned short mask)
|
||||||
{
|
{
|
||||||
mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) | mask);
|
if (!cs->mem_base)
|
||||||
|
io_pp_bit_set_reg_16 (cs, reg, mask);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtems_interrupt_level level;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) | mask);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
mem_pp_bit_clear_reg (int dev, unsigned short reg, unsigned short mask)
|
mem_pp_bit_clear_reg (cs8900_device *cs, unsigned short reg, unsigned short mask)
|
||||||
{
|
{
|
||||||
mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) & ~mask);
|
if (!cs->mem_base)
|
||||||
|
io_pp_bit_clear_reg_16 (cs, reg, mask);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtems_interrupt_level level;
|
||||||
|
rtems_interrupt_disable (level);
|
||||||
|
mem_pp_set_reg (cs, reg, mem_pp_get_reg (cs, reg) & ~mask);
|
||||||
|
rtems_interrupt_enable (level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -239,6 +221,28 @@ cs8900_trace (cs8900_device *cs, unsigned short key, unsigned long var)
|
|||||||
#define cs8900_trace(c, k, v)
|
#define cs8900_trace(c, k, v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void cs8900_get_mac_addr (cs8900_device *cs, unsigned char *mac_address)
|
||||||
|
{
|
||||||
|
unsigned short ma;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only ever use IO calls for this function as it can be
|
||||||
|
* called before memory mode has been enabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ma = io_pp_get_reg_16 (cs, CS8900_PP_IA);
|
||||||
|
mac_address[0] = ma >> 8;
|
||||||
|
mac_address[1] = ma;
|
||||||
|
|
||||||
|
ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 2);
|
||||||
|
mac_address[2] = ma >> 8;
|
||||||
|
mac_address[3] = ma;
|
||||||
|
|
||||||
|
ma = io_pp_get_reg_16 (cs, CS8900_PP_IA + 4);
|
||||||
|
mac_address[4] = ma >> 8;
|
||||||
|
mac_address[5] = ma;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bring the chip online.
|
* Bring the chip online.
|
||||||
*/
|
*/
|
||||||
@@ -248,21 +252,20 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
{
|
{
|
||||||
unsigned long prod_id;
|
unsigned long prod_id;
|
||||||
unsigned short status;
|
unsigned short status;
|
||||||
int dev = cs->dev;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do nothing while the device is calibrating and checking the EEPROM.
|
* Do nothing while the device is calibrating and checking the EEPROM.
|
||||||
* We must wait 20msecs.
|
* We must wait 20msecs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
io_pp_bit_set_reg_16 (dev, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET);
|
io_pp_bit_set_reg_16 (cs, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET);
|
||||||
|
|
||||||
rtems_task_wake_after (TOD_MILLISECONDS_TO_TICKS (20));
|
rtems_task_wake_after (TOD_MILLISECONDS_TO_TICKS (20));
|
||||||
|
|
||||||
status = io_pp_get_reg_16 (dev, CS8900_PP_SelfST);
|
status = io_pp_get_reg_16 (cs, CS8900_PP_SelfST);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
printf("Reading status register again\n");
|
printf("Reading status register again\n");
|
||||||
status = io_pp_get_reg_16 (dev, CS8900_PP_SelfST);
|
status = io_pp_get_reg_16 (cs, CS8900_PP_SelfST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((status & CS8900_SELF_STATUS_INITD) == 0) ||
|
if (((status & CS8900_SELF_STATUS_INITD) == 0) ||
|
||||||
@@ -277,19 +280,24 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the RX queue size if not set by the BSP. */
|
||||||
|
|
||||||
|
if (cs->rx_queue_size == 0)
|
||||||
|
cs->rx_queue_size = 10;
|
||||||
|
|
||||||
/* Probe the device for its ID */
|
/* Probe the device for its ID */
|
||||||
|
|
||||||
prod_id = io_pp_get_reg_32 (dev, CS8900_PP_PROD_ID);
|
prod_id = io_pp_get_reg_32 (cs, CS8900_PP_PROD_ID);
|
||||||
|
|
||||||
if ((prod_id >> 16) != CS8900_ESIA_ID)
|
if ((prod_id >> 16) != CS8900_ESIA_ID)
|
||||||
{
|
{
|
||||||
printf ("CS9800: Invalid EISA ID, read product code 0x%08lx\n", prod_id);
|
printf ("CS8900: Invalid EISA ID, read product code 0x%08lx\n", prod_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prod_id & 0x000000ff) != 0)
|
if ((prod_id & 0x000000ff) != 0)
|
||||||
{
|
{
|
||||||
printf ("CS9800: Unsupported product id, read product code 0x%08lx\n",
|
printf ("CS8900: Unsupported product id, read product code 0x%08lx\n",
|
||||||
prod_id);
|
prod_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -304,18 +312,21 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Switch to memory base accesses as they are faster. No indirect access.
|
* Switch to memory base accesses as they are faster. No indirect access.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE, CS8900_MEMORY_BASE);
|
if (cs->mem_base)
|
||||||
io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE + 2, (CS8900_MEMORY_BASE >> 16) & 0xf);
|
{
|
||||||
|
io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE, cs->mem_base);
|
||||||
|
io_pp_set_reg_16 (cs, CS8900_PP_MEM_BASE + 2, (cs->mem_base >> 16) & 0xf);
|
||||||
|
|
||||||
io_pp_set_reg_16 (dev,
|
io_pp_set_reg_16 (cs,
|
||||||
CS8900_PP_BusCTL,
|
CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_RESET_RX_DMA |
|
CS8900_BUS_CTRL_RESET_RX_DMA |
|
||||||
CS8900_BUS_CTRL_USE_SA |
|
CS8900_BUS_CTRL_USE_SA |
|
||||||
CS8900_BUS_CTRL_MEMORY_ENABLE);
|
CS8900_BUS_CTRL_MEMORY_ENABLE);
|
||||||
io_pp_set_reg_16 (dev,
|
io_pp_set_reg_16 (cs,
|
||||||
CS8900_PP_BusCTL,
|
CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_USE_SA |
|
CS8900_BUS_CTRL_USE_SA |
|
||||||
CS8900_BUS_CTRL_MEMORY_ENABLE);
|
CS8900_BUS_CTRL_MEMORY_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are now in memory mapped mode.
|
* We are now in memory mapped mode.
|
||||||
@@ -327,7 +338,7 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* No auto detect support at the moment. Only 10BaseT.
|
* No auto detect support at the moment. Only 10BaseT.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_LineCFG, CS8900_LINE_CTRL_10BASET);
|
mem_pp_set_reg (cs, CS8900_PP_LineCFG, CS8900_LINE_CTRL_10BASET);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ask the user for the MAC address, the program into the device.
|
* Ask the user for the MAC address, the program into the device.
|
||||||
@@ -335,13 +346,13 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
|
|
||||||
#define MACO(o) cs->arpcom.ac_enaddr[o]
|
#define MACO(o) cs->arpcom.ac_enaddr[o]
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_IA,
|
mem_pp_set_reg (cs, CS8900_PP_IA,
|
||||||
(((unsigned int) MACO (1)) << 8) |
|
(((unsigned int) MACO (1)) << 8) |
|
||||||
((unsigned int) MACO (0)));
|
((unsigned int) MACO (0)));
|
||||||
mem_pp_set_reg (dev, CS8900_PP_IA + 2,
|
mem_pp_set_reg (cs, CS8900_PP_IA + 2,
|
||||||
(((unsigned int) MACO (3)) << 8) |
|
(((unsigned int) MACO (3)) << 8) |
|
||||||
((unsigned int) MACO (2)));
|
((unsigned int) MACO (2)));
|
||||||
mem_pp_set_reg (dev, CS8900_PP_IA + 4,
|
mem_pp_set_reg (cs, CS8900_PP_IA + 4,
|
||||||
(((unsigned int) MACO (5)) << 8) |
|
(((unsigned int) MACO (5)) << 8) |
|
||||||
((unsigned int) MACO (4)));
|
((unsigned int) MACO (4)));
|
||||||
|
|
||||||
@@ -349,7 +360,7 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Set the Buffer configuration.
|
* Set the Buffer configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_BufCFG,
|
mem_pp_set_reg (cs, CS8900_PP_BufCFG,
|
||||||
CS8900_BUFFER_CONFIG_RDY_FOR_TX |
|
CS8900_BUFFER_CONFIG_RDY_FOR_TX |
|
||||||
CS8900_BUFFER_CONFIG_TX_UNDERRUN |
|
CS8900_BUFFER_CONFIG_TX_UNDERRUN |
|
||||||
CS8900_BUFFER_CONFIG_TX_COL_OVF |
|
CS8900_BUFFER_CONFIG_TX_COL_OVF |
|
||||||
@@ -359,7 +370,7 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Set the Receiver configuration.
|
* Set the Receiver configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_RxCFG,
|
mem_pp_set_reg (cs, CS8900_PP_RxCFG,
|
||||||
CS8900_RX_CONFIG_RX_OK |
|
CS8900_RX_CONFIG_RX_OK |
|
||||||
CS8900_RX_CONFIG_CRC_ERROR |
|
CS8900_RX_CONFIG_CRC_ERROR |
|
||||||
CS8900_RX_CONFIG_RUNT|
|
CS8900_RX_CONFIG_RUNT|
|
||||||
@@ -369,7 +380,7 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Set the Receiver control.
|
* Set the Receiver control.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_RxCTL,
|
mem_pp_set_reg (cs, CS8900_PP_RxCTL,
|
||||||
CS8900_RX_CTRL_RX_OK |
|
CS8900_RX_CTRL_RX_OK |
|
||||||
CS8900_RX_CTRL_MULTICAST |
|
CS8900_RX_CTRL_MULTICAST |
|
||||||
CS8900_RX_CTRL_INDIVIDUAL |
|
CS8900_RX_CTRL_INDIVIDUAL |
|
||||||
@@ -379,7 +390,7 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Set the Transmitter configuration.
|
* Set the Transmitter configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_TxCFG,
|
mem_pp_set_reg (cs, CS8900_PP_TxCFG,
|
||||||
CS8900_TX_CONFIG_TX_OK |
|
CS8900_TX_CONFIG_TX_OK |
|
||||||
CS8900_TX_CONFIG_OUT_OF_WINDOW |
|
CS8900_TX_CONFIG_OUT_OF_WINDOW |
|
||||||
CS8900_TX_CONFIG_JABBER |
|
CS8900_TX_CONFIG_JABBER |
|
||||||
@@ -389,15 +400,17 @@ cs8900_hardware_init (cs8900_device *cs)
|
|||||||
* Attach the interrupt handler.
|
* Attach the interrupt handler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cs8900_attach_interrupt (dev, cs);
|
cs8900_attach_interrupt (cs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program the interrupt level we require then enable interrupts.
|
* Program the interrupt level we require then enable interrupts.
|
||||||
|
*
|
||||||
|
* Note, this will need to change to support other levels.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_INT, 0);
|
mem_pp_set_reg (cs, CS8900_PP_INT, cs->irq_level & 3);
|
||||||
|
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL,
|
mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_ENABLE_INT);
|
CS8900_BUS_CTRL_ENABLE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +418,6 @@ rtems_isr
|
|||||||
cs8900_interrupt (rtems_vector_number v, void *csp)
|
cs8900_interrupt (rtems_vector_number v, void *csp)
|
||||||
{
|
{
|
||||||
cs8900_device *cs = csp;
|
cs8900_device *cs = csp;
|
||||||
int dev = cs->dev;
|
|
||||||
unsigned short isq = 0;
|
unsigned short isq = 0;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
@@ -414,12 +426,10 @@ cs8900_interrupt (rtems_vector_number v, void *csp)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
isq = mem_pp_get_reg (dev, CS8900_PP_ISQ);
|
isq = mem_pp_get_reg (cs, CS8900_PP_ISQ);
|
||||||
|
|
||||||
cs8900_trace (cs, CS8900_T_INT, isq);
|
cs8900_trace (cs, CS8900_T_INT, isq);
|
||||||
|
|
||||||
WATCHDOG_TOGGLE ();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No more interrupts to service.
|
* No more interrupts to service.
|
||||||
*/
|
*/
|
||||||
@@ -450,7 +460,7 @@ cs8900_interrupt (rtems_vector_number v, void *csp)
|
|||||||
|
|
||||||
p = mtod (m, unsigned char *);
|
p = mtod (m, unsigned char *);
|
||||||
|
|
||||||
m->m_pkthdr.len = cs8900_get_data_block (dev, p);
|
m->m_pkthdr.len = cs8900_get_data_block (cs, p);
|
||||||
|
|
||||||
if (cs->rx_loaded_tail == 0)
|
if (cs->rx_loaded_tail == 0)
|
||||||
cs->rx_loaded_head = m;
|
cs->rx_loaded_head = m;
|
||||||
@@ -540,7 +550,7 @@ cs8900_interrupt (rtems_vector_number v, void *csp)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
cs->eth_stats.rx_missed_errors +=
|
cs->eth_stats.rx_missed_errors +=
|
||||||
mem_pp_get_reg (dev, CS8900_PP_RxMISS) >> 6;
|
mem_pp_get_reg (cs, CS8900_PP_RxMISS) >> 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12:
|
case 0x12:
|
||||||
@@ -550,7 +560,7 @@ cs8900_interrupt (rtems_vector_number v, void *csp)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
cs->eth_stats.tx_collisions +=
|
cs->eth_stats.tx_collisions +=
|
||||||
mem_pp_get_reg (dev, CS8900_PP_TxCol) >> 6;
|
mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -561,9 +571,9 @@ cs8900_interrupt (rtems_vector_number v, void *csp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cs8900_link_active (int dev)
|
cs8900_link_active (cs8900_device *cs)
|
||||||
{
|
{
|
||||||
return ((mem_pp_get_reg (dev, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ?
|
return ((mem_pp_get_reg (cs, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ?
|
||||||
1 : 0);
|
1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,7 +589,7 @@ cs8900_rx_refill_queue (cs8900_device *cs)
|
|||||||
* will lower the latency of the driver.
|
* will lower the latency of the driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (cs->rx_ready_len < CS8900_RX_QUEUE_SIZE)
|
while (cs->rx_ready_len < cs->rx_queue_size)
|
||||||
{
|
{
|
||||||
MGETHDR (m, M_DONTWAIT, MT_DATA);
|
MGETHDR (m, M_DONTWAIT, MT_DATA);
|
||||||
|
|
||||||
@@ -619,7 +629,6 @@ static void
|
|||||||
cs8900_rx_task (void *arg)
|
cs8900_rx_task (void *arg)
|
||||||
{
|
{
|
||||||
cs8900_device *cs = arg;
|
cs8900_device *cs = arg;
|
||||||
int dev = cs->dev;
|
|
||||||
struct ifnet *ifp = &cs->arpcom.ac_if;
|
struct ifnet *ifp = &cs->arpcom.ac_if;
|
||||||
rtems_event_set events;
|
rtems_event_set events;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
@@ -631,7 +640,7 @@ cs8900_rx_task (void *arg)
|
|||||||
* Turn the receiver and transmitter on.
|
* Turn the receiver and transmitter on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_LineCFG,
|
mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG,
|
||||||
CS8900_LINE_CTRL_RX_ON |
|
CS8900_LINE_CTRL_RX_ON |
|
||||||
CS8900_LINE_CTRL_TX_ON);
|
CS8900_LINE_CTRL_TX_ON);
|
||||||
|
|
||||||
@@ -639,11 +648,9 @@ cs8900_rx_task (void *arg)
|
|||||||
* Start the software interrupt watchdog.
|
* Start the software interrupt watchdog.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rtems_interrupt_disable (level);
|
mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG,
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_BufCFG,
|
|
||||||
CS8900_BUFFER_CONFIG_SW_INT);
|
CS8900_BUFFER_CONFIG_SW_INT);
|
||||||
++cs->eth_stats.int_swint_req;
|
++cs->eth_stats.int_swint_req;
|
||||||
rtems_interrupt_enable (level);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop reading packets.
|
* Loop reading packets.
|
||||||
@@ -675,23 +682,21 @@ cs8900_rx_task (void *arg)
|
|||||||
{
|
{
|
||||||
printf ("cs8900: int lockup, isq flush\n");
|
printf ("cs8900: int lockup, isq flush\n");
|
||||||
|
|
||||||
mem_pp_bit_clear_reg (dev, CS8900_PP_BusCTL,
|
mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_ENABLE_INT);
|
CS8900_BUS_CTRL_ENABLE_INT);
|
||||||
|
|
||||||
while (mem_pp_get_reg (dev, CS8900_PP_ISQ) != 0);
|
while (mem_pp_get_reg (cs, CS8900_PP_ISQ) != 0);
|
||||||
|
|
||||||
cs->eth_stats.int_swint_req = cs->eth_stats.int_swint_res = 0;
|
cs->eth_stats.int_swint_req = cs->eth_stats.int_swint_res = 0;
|
||||||
++cs->eth_stats.int_lockup;
|
++cs->eth_stats.int_lockup;
|
||||||
|
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL,
|
mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_ENABLE_INT);
|
CS8900_BUS_CTRL_ENABLE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_interrupt_disable (level);
|
mem_pp_bit_set_reg (cs, CS8900_PP_BufCFG,
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_BufCFG,
|
|
||||||
CS8900_BUFFER_CONFIG_SW_INT);
|
CS8900_BUFFER_CONFIG_SW_INT);
|
||||||
++cs->eth_stats.int_swint_req;
|
++cs->eth_stats.int_swint_req;
|
||||||
rtems_interrupt_enable (level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cs8900_trace (cs, CS8900_T_RX_BEGIN, cs->rx_loaded_len);
|
cs8900_trace (cs, CS8900_T_RX_BEGIN, cs->rx_loaded_len);
|
||||||
@@ -737,7 +742,6 @@ static void
|
|||||||
cs8900_tx_task (void *arg)
|
cs8900_tx_task (void *arg)
|
||||||
{
|
{
|
||||||
cs8900_device *cs = arg;
|
cs8900_device *cs = arg;
|
||||||
int dev = cs->dev;
|
|
||||||
struct ifnet *ifp = &cs->arpcom.ac_if;
|
struct ifnet *ifp = &cs->arpcom.ac_if;
|
||||||
rtems_event_set events;
|
rtems_event_set events;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
@@ -776,7 +780,7 @@ cs8900_tx_task (void *arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cs8900_link_active (dev))
|
if (cs8900_link_active (cs))
|
||||||
{
|
{
|
||||||
int resending;
|
int resending;
|
||||||
|
|
||||||
@@ -788,12 +792,12 @@ cs8900_tx_task (void *arg)
|
|||||||
|
|
||||||
cs->tx_active = 1;
|
cs->tx_active = 1;
|
||||||
|
|
||||||
mem_pp_set_reg (dev, CS8900_PP_TxCMD,
|
mem_pp_set_reg (cs, CS8900_PP_TxCMD,
|
||||||
CS8900_TX_CMD_STATUS_TX_START_ENTIRE |
|
CS8900_TX_CMD_STATUS_TX_START_ENTIRE |
|
||||||
CS8900_TX_CMD_STATUS_FORCE);
|
CS8900_TX_CMD_STATUS_FORCE);
|
||||||
mem_pp_set_reg (dev, CS8900_PP_TxLength, m->m_pkthdr.len);
|
mem_pp_set_reg (cs, CS8900_PP_TxLength, m->m_pkthdr.len);
|
||||||
|
|
||||||
buf_status = mem_pp_get_reg (dev, CS8900_PP_BusST);
|
buf_status = mem_pp_get_reg (cs, CS8900_PP_BusST);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the bid for memory in the device fails trash the
|
* If the bid for memory in the device fails trash the
|
||||||
@@ -830,7 +834,7 @@ cs8900_tx_task (void *arg)
|
|||||||
|
|
||||||
if (!resending)
|
if (!resending)
|
||||||
{
|
{
|
||||||
cs8900_tx_load (dev, m);
|
cs8900_tx_load (cs, m);
|
||||||
cs->eth_stats.tx_packets++;
|
cs->eth_stats.tx_packets++;
|
||||||
cs->eth_stats.tx_bytes += m->m_pkthdr.len;
|
cs->eth_stats.tx_bytes += m->m_pkthdr.len;
|
||||||
}
|
}
|
||||||
@@ -875,13 +879,11 @@ cs8900_start (struct ifnet *ifp)
|
|||||||
static void
|
static void
|
||||||
cs8900_stop (cs8900_device *cs)
|
cs8900_stop (cs8900_device *cs)
|
||||||
{
|
{
|
||||||
int dev = cs->dev;
|
mem_pp_bit_clear_reg (cs, CS8900_PP_LineCFG,
|
||||||
|
|
||||||
mem_pp_bit_clear_reg (dev, CS8900_PP_LineCFG,
|
|
||||||
CS8900_LINE_CTRL_RX_ON |
|
CS8900_LINE_CTRL_RX_ON |
|
||||||
CS8900_LINE_CTRL_TX_ON);
|
CS8900_LINE_CTRL_TX_ON);
|
||||||
|
|
||||||
mem_pp_bit_clear_reg (dev, CS8900_PP_BusCTL,
|
mem_pp_bit_clear_reg (cs, CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_ENABLE_INT);
|
CS8900_BUS_CTRL_ENABLE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,17 +919,16 @@ static const char *eth_statistics_labels[] =
|
|||||||
static void
|
static void
|
||||||
cs8900_stats (cs8900_device *cs)
|
cs8900_stats (cs8900_device *cs)
|
||||||
{
|
{
|
||||||
int dev = cs->dev;
|
|
||||||
int i;
|
int i;
|
||||||
int max_label = 0;
|
int max_label = 0;
|
||||||
int len;
|
int len;
|
||||||
unsigned long *value = (unsigned long*) &cs->eth_stats.rx_packets;
|
unsigned long *value = (unsigned long*) &cs->eth_stats.rx_packets;
|
||||||
|
|
||||||
cs->eth_stats.rx_missed_errors +=
|
cs->eth_stats.rx_missed_errors +=
|
||||||
mem_pp_get_reg (dev, CS8900_PP_RxMISS) >> 6;
|
mem_pp_get_reg (cs, CS8900_PP_RxMISS) >> 6;
|
||||||
|
|
||||||
cs->eth_stats.tx_collisions +=
|
cs->eth_stats.tx_collisions +=
|
||||||
mem_pp_get_reg (dev, CS8900_PP_TxCol) >> 6;
|
mem_pp_get_reg (cs, CS8900_PP_TxCol) >> 6;
|
||||||
|
|
||||||
printf ("Network Driver Stats for CS8900 :\n");
|
printf ("Network Driver Stats for CS8900 :\n");
|
||||||
|
|
||||||
@@ -1032,7 +1033,6 @@ static void
|
|||||||
cs8900_init (void *arg)
|
cs8900_init (void *arg)
|
||||||
{
|
{
|
||||||
cs8900_device *cs = arg;
|
cs8900_device *cs = arg;
|
||||||
int dev = cs->dev;
|
|
||||||
struct ifnet *ifp = &cs->arpcom.ac_if;
|
struct ifnet *ifp = &cs->arpcom.ac_if;
|
||||||
|
|
||||||
if (cs->rx_task == 0)
|
if (cs->rx_task == 0)
|
||||||
@@ -1070,11 +1070,11 @@ cs8900_init (void *arg)
|
|||||||
* Set the Line Control to bring the receive and transmitter online.
|
* Set the Line Control to bring the receive and transmitter online.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_LineCFG,
|
mem_pp_bit_set_reg (cs, CS8900_PP_LineCFG,
|
||||||
CS8900_LINE_CTRL_RX_ON |
|
CS8900_LINE_CTRL_RX_ON |
|
||||||
CS8900_LINE_CTRL_TX_ON);
|
CS8900_LINE_CTRL_TX_ON);
|
||||||
|
|
||||||
mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL,
|
mem_pp_bit_set_reg (cs, CS8900_PP_BusCTL,
|
||||||
CS8900_BUS_CTRL_ENABLE_INT);
|
CS8900_BUS_CTRL_ENABLE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1148,17 +1148,7 @@ cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching)
|
|||||||
if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0)
|
if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
cs = config->drv_ctrl;
|
||||||
* Is driver free?
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (unit >= CS8900_DEVICES)
|
|
||||||
{
|
|
||||||
printf ("Bad CS8900 unit number for device `%s'.\n", config->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cs = &cs8900[unit];
|
|
||||||
cs->dev = unit;
|
cs->dev = unit;
|
||||||
ifp = &cs->arpcom.ac_if;
|
ifp = &cs->arpcom.ac_if;
|
||||||
|
|
||||||
@@ -1177,7 +1167,7 @@ cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching)
|
|||||||
if (config->hardware_address)
|
if (config->hardware_address)
|
||||||
memcpy (cs->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
|
memcpy (cs->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
|
||||||
else
|
else
|
||||||
cs8900_get_mac_addr (unit, cs->arpcom.ac_enaddr);
|
cs8900_get_mac_addr (cs, cs->arpcom.ac_enaddr);
|
||||||
|
|
||||||
if (config->mtu)
|
if (config->mtu)
|
||||||
mtu = config->mtu;
|
mtu = config->mtu;
|
||||||
@@ -1219,9 +1209,8 @@ cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cs8900_stop (cs);
|
cs8900_stop (cs);
|
||||||
cs8900_detach_interrupt (unit);
|
cs8900_detach_interrupt (cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,148 @@
|
|||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
$Id$
|
cs8900.h,v 1.3 2002/09/07 23:09:47 joel Exp
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
My Right Boot, a boot ROM for embedded hardware.
|
|
||||||
|
|
||||||
Copyright Cybertec Pty Ltd, 2000
|
Copyright Cybertec Pty Ltd, 2000
|
||||||
All rights reserved Cybertec Pty Ltd, 2000
|
All rights reserved Cybertec Pty Ltd, 2000
|
||||||
|
|
||||||
|
Port to the DIMM PC copyright (c) 2004 Angelo Fraietta
|
||||||
|
This project has been assisted by the Commonwealth Government
|
||||||
|
through the Australia Council, its arts funding and advisory body.
|
||||||
|
|
||||||
COPYRIGHT (c) 1989-1998.
|
COPYRIGHT (c) 1989-1998.
|
||||||
On-Line Applications Research Corporation (OAR).
|
On-Line Applications Research Corporation (OAR).
|
||||||
|
|
||||||
The license and distribution terms for this file may be
|
The license and distribution terms for this file may be
|
||||||
found in the file LICENSE in this distribution or at
|
found in the file LICENSE in this distribution or at
|
||||||
http://www.rtems.com/license/LICENSE.
|
http://www.OARcorp.com/rtems/license.html.
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
CS8900 net boot driver.
|
CS8900 RTEMS driver.
|
||||||
|
|
||||||
|
This is a generic driver that requires a BSP backend. The BSP backend
|
||||||
|
provides the glue to the specific bus for the target hardware. It has
|
||||||
|
been tested with Coldfire processors, and the PC. These targets have
|
||||||
|
completely different bus, byte order and interrupt structures.
|
||||||
|
|
||||||
|
An example BSP backend is provided in the pci386 BSP.
|
||||||
|
|
||||||
|
The BSP provides the following functions:
|
||||||
|
|
||||||
|
cs8900_io_set_reg
|
||||||
|
cs8900_io_get_reg
|
||||||
|
cs8900_mem_set_reg
|
||||||
|
cs8900_mem_get_reg
|
||||||
|
cs8900_put_data_block
|
||||||
|
cs8900_get_data_block
|
||||||
|
cs8900_tx_load
|
||||||
|
cs8900_attach_interrupt
|
||||||
|
cs8900_detach_interrupt
|
||||||
|
|
||||||
|
The header file provides documentation for these functions. There
|
||||||
|
are four types of functions.
|
||||||
|
|
||||||
|
The I/O set/get functions access the CS8900 I/O registers via the
|
||||||
|
I/O Mode. For example on a PC with an ISA bus you would use the
|
||||||
|
IA32 in/out port instructions. The cs8900_device structure passed
|
||||||
|
to these functions provide these functions with the I/O base
|
||||||
|
address. The BSP must provide these functions.
|
||||||
|
|
||||||
|
The Memory set/get functions access the CS8900 internal registers
|
||||||
|
and frame buffers directly from a 4K byte block of host memory.
|
||||||
|
Memory mode provides a faster access to the CS8900. The cs8900_device
|
||||||
|
structure passed to these functions provides the memory base
|
||||||
|
address. The BSP needs to provide these functions but they do not
|
||||||
|
need to be implemented if the mem_base field is set to 0. The
|
||||||
|
driver will use I/O mode only.
|
||||||
|
|
||||||
|
The Block transfer functions are used to read or write a block
|
||||||
|
of memory from the CS8900. This saves the driver making a number
|
||||||
|
of small calls. The BSP driver must know if I/O or Memory mode
|
||||||
|
can be used.
|
||||||
|
|
||||||
|
The final group of functions is to handle interrupts. The BSP
|
||||||
|
must take care of save and restoring any interrupt state
|
||||||
|
information.
|
||||||
|
|
||||||
|
The BSP declares a 'cs8900_device' structure for each device being
|
||||||
|
attached to the networking stack. It also creates a
|
||||||
|
'struct rtems_bsdnet_ifconfig' which is used to attach the interface
|
||||||
|
to the networking stack. The following code declares the BSD config:
|
||||||
|
|
||||||
|
static cs8900_device cs8900;
|
||||||
|
|
||||||
|
static struct rtems_bsdnet_ifconfig cs8900_ifconfig =
|
||||||
|
{
|
||||||
|
"cs0",
|
||||||
|
cs8900_driver_attach,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
The device linked to the BSD config structure with:
|
||||||
|
|
||||||
|
cs8900_ifconfig.drv_ctrl = &cs8900;
|
||||||
|
|
||||||
|
If you have a specific hardware address you should point the BSD
|
||||||
|
config structure to that address. If you do not the driver will read
|
||||||
|
the MAC address from the CS8900. This assumes the CS8900 has read
|
||||||
|
the address from an external EEPROM or has been setup by a BIOS or
|
||||||
|
boot monitor. For EEPROM less you need to supply the MAC address.
|
||||||
|
|
||||||
|
Set the I/O and Memory base addresses. If the Memory base address
|
||||||
|
is 0 the driver will use I/O mode only. A typical initialisation
|
||||||
|
looks like:
|
||||||
|
|
||||||
|
printf ("RTEMS BSD Network initialisation.\n");
|
||||||
|
rtems_bsdnet_initialize_network ();
|
||||||
|
|
||||||
|
#define ETHERNET_IO_BASE 0x300
|
||||||
|
#define ETHERNET_MEM_BASE 0
|
||||||
|
#define ETHERNET_IRQ_LEVEL 0
|
||||||
|
|
||||||
|
cs8900_device *cs = &cs8900;
|
||||||
|
|
||||||
|
memset (cs, 0, sizeof (cs8900_device));
|
||||||
|
|
||||||
|
cs->dev = 0;
|
||||||
|
cs->io_base = ETHERNET_IO_BASE;
|
||||||
|
cs->mem_base = ETHERNET_MEM_BASE;
|
||||||
|
cs->irq_level = ETHERNET_IRQ_LEVEL;
|
||||||
|
cs->rx_queue_size = 30;
|
||||||
|
|
||||||
|
cs8900_ifconfig.drv_ctrl = &cs8900;
|
||||||
|
|
||||||
|
printf ("CS8900 initialisation\n");
|
||||||
|
|
||||||
|
rtems_bsdnet_attach (&cs8900_ifconfig);
|
||||||
|
|
||||||
|
flags = IFF_UP;
|
||||||
|
if (rtems_bsdnet_ifconfig (cs8900_ifconfig.name,
|
||||||
|
SIOCSIFFLAGS,
|
||||||
|
&flags) < 0)
|
||||||
|
{
|
||||||
|
printf ("error: can't bring up %s: %s\n",
|
||||||
|
cs8900_ifconfig.name, strerror (errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_bsdnet_do_bootp_and_rootfs ();
|
||||||
|
|
||||||
|
The IRQ level is the one documented in the CS8900 datasheet and below
|
||||||
|
in the CS8900 device structure. You need to map your target IRQ to the
|
||||||
|
CS8900 in the BSP driver.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -327,6 +452,12 @@
|
|||||||
#define CS8900_TRACE 0
|
#define CS8900_TRACE 0
|
||||||
#define CS8900_TRACE_SIZE (400)
|
#define CS8900_TRACE_SIZE (400)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default receive queue size. If the BSP sets this field to
|
||||||
|
* 0 this default is used.
|
||||||
|
*/
|
||||||
|
#define CS8900_RX_QUEUE_SIZE (30)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stats, more for debugging than anything else.
|
* Stats, more for debugging than anything else.
|
||||||
*/
|
*/
|
||||||
@@ -380,6 +511,32 @@ typedef struct
|
|||||||
|
|
||||||
int dev;
|
int dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory base addresses. Making mem_base 0 forces the
|
||||||
|
* driver to perform only I/O space accesses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned long io_base;
|
||||||
|
unsigned long mem_base;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IRQ level as defined in the datasheet for the CS8900.
|
||||||
|
*
|
||||||
|
* ISA BUS Pin Value
|
||||||
|
* IRQ10 INTRQ0 0
|
||||||
|
* IRQ11 INTRQ1 1
|
||||||
|
* IRQ12 INTRQ2 2
|
||||||
|
* IRQ5 INTRQ3 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
int irq_level;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MAC address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char mac_address[6];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The bsdnet information structure.
|
* The bsdnet information structure.
|
||||||
*/
|
*/
|
||||||
@@ -399,6 +556,7 @@ typedef struct
|
|||||||
/*
|
/*
|
||||||
* The queues. FIXME : these should be changed to be mbuf lists.
|
* The queues. FIXME : these should be changed to be mbuf lists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct mbuf *rx_ready_head;
|
struct mbuf *rx_ready_head;
|
||||||
struct mbuf *rx_ready_tail;
|
struct mbuf *rx_ready_tail;
|
||||||
int rx_ready_len;
|
int rx_ready_len;
|
||||||
@@ -407,6 +565,13 @@ typedef struct
|
|||||||
struct mbuf *rx_loaded_tail;
|
struct mbuf *rx_loaded_tail;
|
||||||
int rx_loaded_len;
|
int rx_loaded_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of mbufs queued for the interrupt handler to
|
||||||
|
* loop reading.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int rx_queue_size;
|
||||||
|
|
||||||
#if CS8900_TRACE
|
#if CS8900_TRACE
|
||||||
unsigned short trace_key[CS8900_TRACE_SIZE];
|
unsigned short trace_key[CS8900_TRACE_SIZE];
|
||||||
unsigned long trace_var[CS8900_TRACE_SIZE];
|
unsigned long trace_var[CS8900_TRACE_SIZE];
|
||||||
@@ -414,7 +579,7 @@ typedef struct
|
|||||||
int trace_in;
|
int trace_in;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Standard(!) ethernet statistics
|
* Standard(!) ethernet statistics
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -423,27 +588,176 @@ typedef struct
|
|||||||
} cs8900_device;
|
} cs8900_device;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Link is active, and RX count.
|
* Link active returns the state of the PHY.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cs8900_link_active (cs8900_device *cs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RTEMS network stack driver attach function that is loaded into the
|
||||||
|
* the rtems_bsdnet_ifconfig struct. The network stack will call this
|
||||||
|
* function when attaching the driver. The BSP must load the 'drv_ctrl'
|
||||||
|
* field of the structure before calling the 'rtems_bsdnet_attach'
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* @param config The RTEMS BSD config structure.
|
||||||
|
*
|
||||||
|
* @param attaching True is the stack is attaching the interface.
|
||||||
|
*
|
||||||
|
* @retval int Set to 1 if the device has attached.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int cs8900_link_active (int dev);
|
|
||||||
int cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config,
|
int cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config,
|
||||||
int attaching);
|
int attaching);
|
||||||
rtems_isr cs8900_interrupt (rtems_vector_number v, void *cs);
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Functions Users Provide to implement the driver.
|
* The BSP specific interrupt wrapper calls this function when a device
|
||||||
|
* interrupt occurs.
|
||||||
|
*
|
||||||
|
* @param v The RTEMS vector number that generated the interrupt.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure passed to the interrupt
|
||||||
|
* catch function provided by the BSP.
|
||||||
|
*
|
||||||
|
* @retval rtems_isr The standard ISR return type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void cs8900_attach_interrupt (int dev, cs8900_device *cs);
|
rtems_isr cs8900_interrupt (rtems_vector_number v, void *cs);
|
||||||
void cs8900_detach_interrupt (int dev);
|
|
||||||
void cs8900_get_mac_addr (int dev, unsigned char *mac_address);
|
/**
|
||||||
void cs8900_io_set_reg (int dev, unsigned short reg, unsigned short data);
|
* Get the MAC address for the interface.
|
||||||
unsigned short cs8900_io_get_reg (int dev, unsigned short reg);
|
*
|
||||||
void cs8900_mem_set_reg (int dev, unsigned long reg, unsigned short data);
|
* @param cs Pointer to the device structure.
|
||||||
unsigned short cs8900_mem_get_reg (int dev, unsigned long reg);
|
*
|
||||||
void cs8900_put_data_block (int dev, int len, unsigned char *data);
|
* @param mac_address Pointer to the memory to load the MAC address. This
|
||||||
unsigned short cs8900_get_data_block (int dev, unsigned char *data);
|
* is a 6 byte buffer so do not exceeed the bounds.
|
||||||
void cs8900_tx_load (int dev, struct mbuf *m);
|
*/
|
||||||
|
|
||||||
|
void cs8900_get_mac_addr (cs8900_device *cs, unsigned char *mac_address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Catch the device interrupt. When the interrupt is called call the
|
||||||
|
* function 'cs8900_interrupt'.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_attach_interrupt (cs8900_device *cs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach the device interrupt.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_detach_interrupt (cs8900_device *cs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to an IO space register.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param reg Register offset from the IO base.
|
||||||
|
*
|
||||||
|
* @param data The data to be written to the register.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_io_set_reg (cs8900_device *cs,
|
||||||
|
unsigned short reg, unsigned short data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an IO space register.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param reg Register offset from the IO base.
|
||||||
|
*
|
||||||
|
* @retval unsigned short The register data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to a memory space register. Will only be called is the mem_base
|
||||||
|
* field of the 'cs' struct is not 0.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param reg Register offset from the memory base.
|
||||||
|
*
|
||||||
|
* @param data The data to be written to the register.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_mem_set_reg (cs8900_device *cs,
|
||||||
|
unsigned long reg, unsigned short data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a memory space register. Will only be called is the mem_base
|
||||||
|
* field of the 'cs' struct is not 0.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param reg Register offset from the IO base.
|
||||||
|
*
|
||||||
|
* @retval unsigned short The register data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a block of data to the interface. The BSP codes if this is an IO or
|
||||||
|
* memory space write.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param len The length of data to write.
|
||||||
|
*
|
||||||
|
* @param data Pointer to the data to be written.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_put_data_block (cs8900_device *cs, int len, unsigned char *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a block of data from the interface. The BSP codes if this is an IO or
|
||||||
|
* memory space write. The read must not be longer than the MTU size.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param data Pointer to the buffer where the data is to be written.
|
||||||
|
*
|
||||||
|
* @retval unsigned short The number of bytes read from the device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a mbuf chain to the device ready for tranmission.
|
||||||
|
*
|
||||||
|
* BSP to provide this function.
|
||||||
|
*
|
||||||
|
* @param cs Pointer to the device structure.
|
||||||
|
*
|
||||||
|
* @param m Pointer to the head of an mbuf chain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cs8900_tx_load (cs8900_device *cs, struct mbuf *m);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user