This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Atlas ethernet update
- From: Nick Garnett <nickg at ecoscentric dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: 21 Mar 2003 18:21:01 +0000
- Subject: Atlas ethernet update
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/mips/atlas/current/ChangeLog,v
retrieving revision 1.7
diff -u -5 -r1.7 ChangeLog
--- ChangeLog 13 Mar 2003 18:49:37 -0000 1.7
+++ ChangeLog 21 Mar 2003 18:15:47 -0000
@@ -1,5 +1,11 @@
+2003-03-21 Nick Garnett <nickg at balti dot calivar dot com>
+
+ * src/saa9730.h:
+ * src/if_atlas.c:
+ Many small changes to make this driver work correctly in eCos.
+
2003-03-13 Nick Garnett <nickg at balti dot calivar dot com>
* cdl/atlas_eth_drivers.cdl:
Changed CYGPKG_DEVS_ETH_ARM_ATLAS_OPTIONS to
CYGPKG_DEVS_ETH_MIPS_ATLAS_OPTIONS.
Index: src/if_atlas.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/mips/atlas/current/src/if_atlas.c,v
retrieving revision 1.7
diff -u -5 -r1.7 if_atlas.c
--- src/if_atlas.c 13 Mar 2003 18:49:37 -0000 1.7
+++ src/if_atlas.c 21 Mar 2003 18:15:48 -0000
@@ -7,10 +7,11 @@
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Nick Garnett <nickg at calivar dot com>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -31,12 +32,12 @@
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
+// Alternative licenses for eCos may be arranged by contacting the copyright
+// holders.
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
@@ -49,11 +50,11 @@
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): msalter
-// Contributors: msalter
+// Contributors: msalter, nickg
// Date: 2000-12-06
// Purpose:
// Description: hardware driver for SAA9730 ethernet
//
//
@@ -75,10 +76,11 @@
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_endian.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_if.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/drv_api.h>
#include <cyg/io/eth/netdev.h>
#include <cyg/io/eth/eth_drv.h>
@@ -110,10 +112,13 @@
#include "saa9730.h"
// Exported statistics and the like
#include <cyg/io/eth/eth_drv_stats.h>
+#ifndef CYGPKG_REDBOOT
+//#define DEBUG
+#endif
#define db_printf diag_printf
#define ETHER_ADDR_LEN 6
static unsigned poll_count = 0; // for bug workaround
@@ -165,35 +170,46 @@
NETDEVTAB_ENTRY(atlas_netdev,
"atlas",
atlas_saa9730_init,
&atlas_sc);
-#ifdef CYGSEM_ARM_ATLAS_SET_ESA
-static unsigned char enaddr[] = CYGDAT_ARM_ATLAS_ESA;
+#ifdef CYGSEM_MIPS_ATLAS_SET_ESA
+static unsigned char enaddr[] = CYGDAT_MIPS_ATLAS_ESA;
#else
static unsigned char enaddr[ETHER_ADDR_LEN];
#endif
static void saa9730_poll(struct eth_drv_sc *sc);
// This ISR is called when the ethernet interrupt occurs
static int
saa9730_isr(cyg_vector_t vector, cyg_addrword_t data)
{
+ struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
+ unsigned long __base = spd->base;
+
#ifndef CYGPKG_REDBOOT
+ SAA9730_EVM_IER_SW &= ~(SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
+ SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
cyg_drv_interrupt_mask(vector);
-#endif
+#endif
+#ifdef DEBUG
+ db_printf("saa9730_isr\n");
+#endif
return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
}
#ifndef CYGPKG_REDBOOT
static
void saa9730_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)data;
struct cyg_netdevtab_entry *ndp = (struct cyg_netdevtab_entry *)(spd->ndp);
struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance);
+#ifdef DEBUG
+ db_printf("saa9730_dsr\n");
+#endif
eth_drv_dsr(vector, count, (cyg_addrword_t)sc);
}
#endif
@@ -249,10 +265,11 @@
if (buf_nr)
SAA9730_OK2USE |= SAA9730_OK2USE_RXB;
else
SAA9730_OK2USE |= SAA9730_OK2USE_RXA;
+
}
static void
__init_cam(struct saa9730_priv_data *spd)
{
@@ -313,22 +330,25 @@
SAA9730_PKTCNT = ((SAA9730_TXPKTS_PER_BUFFER << 24) |
(SAA9730_TXPKTS_PER_BUFFER << 16) |
(SAA9730_RXPKTS_PER_BUFFER << 8) |
(SAA9730_RXPKTS_PER_BUFFER << 0));
- SAA9730_OK2USE = SAA9730_OK2USE_RXA | SAA9730_OK2USE_RXB;
+ SAA9730_OK2USE = 0;
__select_buffer(spd, 0);
// initialize DMA control register
SAA9730_DMACTL = SAA9730_DMACTL_BLKINT |
SAA9730_DMACTL_MAXXFER_ANY |
SAA9730_DMACTL_ENDIAN_LITTLE;
-#ifdef CYGPKG_REDBOOT
+
SAA9730_DMACTL |= SAA9730_DMACTL_RXINT;
SAA9730_DMACTL |= (1<<SAA9730_DMACTL_RXINTCNT_SHIFT);
SAA9730_DMACTL &= ~SAA9730_DMACTL_BLKINT;
+
+#ifndef CYGPKG_REDBOOT
+ SAA9730_DMACTL |= SAA9730_DMACTL_TXINT;
#endif
SAA9730_TIMOUT = 200;
// accept broadcast packets */
@@ -337,18 +357,23 @@
SAA9730_TXCTL = 0;
SAA9730_RXCTL |= SAA9730_RXCTL_STRIPCRC;
SAA9730_CAMENA = 1;
+
}
static void
__check_mii(struct saa9730_priv_data *spd)
{
unsigned long __base = spd->base;
cyg_uint32 opmode;
+#ifdef DEBUG
+ db_printf("__check_mii\n");
+#endif
+
// spin till station is not busy
while (SAA9730_MDCTL & SAA9730_MDCTL_BUSY)
;
// set PHY address = 'STATUS'
@@ -376,22 +401,22 @@
hal_delay_us(1000);
opmode = (SAA9730_MDDATA & PHY_REG31_OPMODE_MSK) >> PHY_REG31_OPMODE_SHIFT;
#ifdef DEBUG
- diag_printf("MII mode %d\n", opmode);
+ db_printf("MII mode %d\n", opmode);
#endif
if ((opmode == OPMODE_10BASET_FULLDUPLEX) ||
(opmode == OPMODE_100BASEX_FULLDUPLEX))
SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII | SAA9730_MACCTL_FULLDUP;
else
SAA9730_MACCTL = SAA9730_MACCTL_CONMODE_FORCE_MII;
}
#ifdef DEBUG
else
- diag_printf("Link is down\n");
+ db_printf("Link is down\n");
#endif
}
static void
@@ -428,11 +453,11 @@
static int initialized = 0; // only probe PCI et al *once*
struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
#ifdef DEBUG
- diag_printf("atlas_saa9730_init\n");
+ db_printf("atlas_saa9730_init\n");
#endif
if (0 == initialized) {
cyg_pci_device_id devid;
cyg_pci_device dev_info;
@@ -479,10 +504,12 @@
CYG_PCI_DEV_GET_BUS(devid),
CYG_PCI_DEV_GET_DEV(CYG_PCI_DEV_GET_DEVFN(devid)),
spd->base, spd->vector);
#endif
+ spd->ndp = tab;
+
#ifndef CYGPKG_REDBOOT
cyg_drv_interrupt_create(
spd->vector,
0, // Priority - unused
(CYG_ADDRWORD)spd, // Data item passed to ISR & DSR
@@ -492,21 +519,20 @@
&spd->interrupt_object ); // space for int obj
cyg_drv_interrupt_attach(spd->interrupt_handle);
cyg_drv_interrupt_acknowledge(spd->vector);
cyg_drv_interrupt_unmask(spd->vector);
-#else
+#endif
{
// When in Redboot we want to get RX interrupts. These
// will be picked up by the default interrupt handler and
// checked for ^C.
unsigned long __base = spd->base;
SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
SAA9730_EVM_IER |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
SAA9730_EVM_ISR |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
}
-#endif
#ifdef DEBUG
db_printf(" **** Device enabled for I/O and Memory and Bus Master\n");
#endif
@@ -514,27 +540,29 @@
#ifdef DEBUG
db_printf("eth0 not found\n");
#endif
}
+ saa9730_stop(sc);
+
spd->active = 0;
initialized = 1;
}
// Fetch hardware address
#if defined(CYGPKG_REDBOOT) && \
defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
- !defined(CYGSEM_ARM_ATLAS_SET_ESA)
+ !defined(CYGSEM_MIPS_ATLAS_SET_ESA)
flash_get_config("atlas_esa", enaddr, CONFIG_ESA);
#else
-#if 0
- for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
- unsigned short esa_reg = get_reg(PP_IA+i);
- enaddr[i] = esa_reg & 0xFF;
- enaddr[i+1] = esa_reg >> 8;
- }
+#define CONFIG_ESA 6
+ CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET,
+ "atlas_esa", enaddr, CONFIG_ESA );
+#ifdef DEBUG
+ db_printf("ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ enaddr[0],enaddr[1],enaddr[2],enaddr[3],enaddr[4],enaddr[5]);
#endif
#endif
saa9730_reset(spd);
@@ -581,10 +609,12 @@
SAA9730_DMACTL |= SAA9730_DMACTL_ENTX;
// for rx, turn on DMA first
SAA9730_DMACTL |= SAA9730_DMACTL_ENRX;
SAA9730_RXCTL |= SAA9730_RXCTL_ENRX;
+
+ __select_buffer(spd, spd->next_rx_bindex);
}
//
// This function is called to "start up" the interface. It may be called
// multiple times, even when the hardware is already running. It will be
@@ -736,21 +766,25 @@
unsigned long __base = spd->base;
cyg_uint32 status, flag, size;
cyg_uint32 *pkt;
int i, j;
-#ifdef CYGPKG_REDBOOT
+#ifdef DEBUG
+ db_printf("__check_rxstate\n");
+#endif
+
+#ifdef CYGPKG_REDBOOT
// Clear SAA9730 LAN interrupt and re-enable interrupts.
SAA9730_EVM_ISR = SAA9730_EVM_LAN_INT;
SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
#endif
if ((SAA9730_DBGRXS & SAA9730_DBGRXS_RXDII_MASK) == SAA9730_DBGRXS_RXDII_ERROR) {
// re-init driver and controller
#ifdef DEBUG
db_printf("DBGRXS: reset\n");
-#endif
+#endif
saa9730_reset(spd);
__do_start(spd);
return;
}
@@ -763,11 +797,11 @@
flag = status & RXPACKET_STATUS_FLAG_MASK;
if (flag == RX_INVALID_STAT || size > 1514 || *(pkt - 1)) {
// re-init driver and controller
#ifdef DEBUG
db_printf("rxpkt: reset\n");
-#endif
+#endif
saa9730_reset(spd);
__do_start(spd);
return;
}
}
@@ -857,10 +891,13 @@
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
int bindex, pindex, done;
volatile cyg_uint32 *pkt;
cyg_uint32 status, pktlen;
+#ifdef DEBUG
+ db_printf("__rx_poll\n");
+#endif
if (!spd->active)
return;
done = 0;
while (!done) {
@@ -873,11 +910,13 @@
pkt = spd->rx_buffer[bindex][pindex];
// stop now if no more packets
if (((status = CYG_LE32_TO_CPU(*pkt)) & RXPACKET_STATUS_FLAG_MASK) == RX_READY)
break;
-
+#ifdef DEBUG
+ db_printf("__rx_poll pkt %08x status %08x\n",pkt,status);
+#endif
// if this is the first packet in a buffer, switch the SAA9730 to
// use the next buffer for subsequent incoming packets.
if (pindex == 0)
__select_buffer(spd, bindex == 0);
@@ -889,11 +928,15 @@
if (pktlen > 0) {
(sc->funs->eth_drv->recv)(sc, pktlen);
// done = 1;
}
}
-
+#ifdef DEBUG
+ else
+ db_printf("rx bad: %08x %08x\n",pkt,status);
+#endif
+
/* go to next packet in sequence */
spd->next_rx_pindex++;
if (spd->next_rx_pindex >= SAA9730_RXPKTS_PER_BUFFER) {
spd->next_rx_pindex = 0;
spd->next_rx_bindex++;
@@ -974,11 +1017,11 @@
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
#ifndef CYGPKG_REDBOOT
cyg_drv_interrupt_mask(spd->vector);
#endif
-
+
(void)saa9730_isr(spd->vector, (cyg_addrword_t)spd);
__do_deliver(sc);
cyg_drv_interrupt_acknowledge(spd->vector);
@@ -992,11 +1035,20 @@
// The deliver function (ex-DSR) handles the ethernet [logical] processing
static void
saa9730_deliver(struct eth_drv_sc *sc)
{
struct saa9730_priv_data *spd = (struct saa9730_priv_data *)sc->driver_private;
+ unsigned long __base = spd->base;
if (spd->active)
__do_deliver(sc);
+
+ cyg_drv_interrupt_acknowledge(spd->vector);
+
+#ifndef CYGPKG_REDBOOT
+ // Clear SAA9730 LAN interrupt and re-enable interrupts.
+ SAA9730_EVM_IER_SW |= (SAA9730_EVM_LAN_INT|SAA9730_EVM_MASTER);
+ cyg_drv_interrupt_unmask(spd->vector);
+#endif
}
Index: src/saa9730.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/mips/atlas/current/src/saa9730.h,v
retrieving revision 1.4
diff -u -5 -r1.4 saa9730.h
--- src/saa9730.h 23 May 2002 23:00:44 -0000 1.4
+++ src/saa9730.h 21 Mar 2003 18:15:48 -0000
@@ -9,10 +9,11 @@
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Nick Garnett <nickg at calivar dot com>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -33,19 +34,19 @@
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
+// Alternative licenses for eCos may be arranged by contacting the copyright
+// holders.
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): msalter
-// Contributors: msalter
+// Contributors: msalter, nickg
// Date: 2000-12-09
// Description: Definitions for Philips SAA9730 Ethernet module.
//
//####DESCRIPTIONEND####
*/
@@ -306,10 +307,14 @@
# define SAA9730_DBGRXS_RXPI_MASK (0x3ff << 16)
# define SAA9730_DBGRXS_RXPI_ERROR (0x001 << 16)
# define SAA9730_DBGRXS_RXDII_MASK 0x1ff
# define SAA9730_DBGRXS_RXDII_ERROR 8
+
+#define SAA9730_DBGRXFIFO *((volatile unsigned *)(__base + 0x20510)) // DEBUG
+
+#define SAA9730_DBGLANSTA *((volatile unsigned *)(__base + 0x20514)) // DEBUG
// ******** Packet control/status **********
#define TXPACKET_CTL_FLAG_MASK (0x3 << 30)
# define TX_EMPTY (0 << 30)
--
Nick Garnett eCos Kernel Architect
http://www.ecoscentric.com/ The eCos and RedBoot experts