diff options
Diffstat (limited to 'c/src/lib/libbsp/m68k/mvme167/network/network.c')
-rw-r--r-- | c/src/lib/libbsp/m68k/mvme167/network/network.c | 3753 |
1 files changed, 1960 insertions, 1793 deletions
diff --git a/c/src/lib/libbsp/m68k/mvme167/network/network.c b/c/src/lib/libbsp/m68k/mvme167/network/network.c index bcfc07ef00..c8a2e71734 100644 --- a/c/src/lib/libbsp/m68k/mvme167/network/network.c +++ b/c/src/lib/libbsp/m68k/mvme167/network/network.c @@ -1,4 +1,4 @@ -/* uti596.c: An 82596 ethernet driver for rtems-bsd. +/* network.c: An 82596 ethernet driver for rtems-bsd. * * $Id$ */ @@ -9,36 +9,36 @@ * Selectively define to debug the network driver. If you define any of these * you must run with polled console I/O. */ - -#define DBG_596 -#define DBG_596_RFA + +/* +#define DBG_ADD_CMD +#define DBG_WAIT +#define DBG_SEND +#define DBG_MEM +#define DBG_SELFTEST_CMD +#define DBG_DUMP_CMD +#define DBG_RESET +#define DBG_ATTACH #define DBG_START #define DBG_INIT -#define DBG_INIT_2 -/*#define DBG_INIT_3*/ -#define DBG_RESET -#define DBG_VERSION +#define DBG_STOP +#define DBG_RX #define DBG_ISR -#define DBG_RAW_ISR -#define DBG_596_RFD -#define DBG_FR -#define DBG_RAW -#define DBG_ATTACH -#define DBG_POLLED_CMD -#define DBG_ADD -#define DBG_SUPPLY_FD - +#define DBG_IOCTL +#define DBG_STAT +#define DBG_PACKETS +*/ /* * Default number of buffer descriptors and buffer sizes. */ -#define RX_BUF_COUNT 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 +#define RX_BUF_COUNT 15 +#define TX_BUF_COUNT 4 +#define TX_BD_PER_BUF 4 -#define RBUF_SIZE 1520 +#define RBUF_SIZE 1520 -#define UTI_596_ETH_MIN_SIZE 60 +#define UTI_596_ETH_MIN_SIZE 60 /* * RTEMS events @@ -62,21 +62,33 @@ #include <netinet/if_ether.h> #include "uti596.h" -#include "netexterns.h" +/* If we are running interrupt driven I/O no debug output is printed */ #if CD2401_POLLED_IO == 1 - #define printk(arglist) printk arglist; + #define printk(arglist) printk arglist; #else - #define printk(arglist) + #define printk(arglist) #endif -#define UTI_596_ASSERT( condition, str ) if (!( condition ) ) { printk((str)) } +#define UTI_596_ASSERT( condition, str ) if (!( condition ) ) { printk((str)) } + +/* Types of PORT commands */ +#define UTI596_RESET_PORT_FUNCTION 0 +#define UTI596_SELFTEST_PORT_FUNCTION 1 +#define UTI596_SCP_PORT_FUNCTION 2 +#define UTI596_DUMP_PORT_FUNCTION 3 -int count_rx = 0; -i596_rfd *pISR_Rfd; +/* Types of waiting for commands */ +#define UTI596_NO_WAIT 0 +#define UTI596_WAIT_FOR_CU_ACCEPT 1 +#define UTI596_WAIT_FOR_INITIALIZATION 2 +#define UTI596_WAIT_FOR_STAT_C 3 +/* Device dependent data structure */ static uti596_softc_ uti596_softc; +/* Globals */ +int count_rx = 0; static int scbStatus; static rtems_status_code sc; static i596_cmd *pIsrCmd; @@ -86,131 +98,1576 @@ static i596_rfd *pIsrRfd; * Initial 596 configuration */ char uti596initSetup[] = { - 0x0E, /* Byte 0: length, prefetch off ( no RBD's ) */ - 0xC8, /* Byte 1: fifo to 8, monitor off */ - 0x40, /* Byte 2: don't save bad frames ( was save= 80, use intel's 40 )*/ - 0x2E, /* Byte 3: No source address insertion, 8 byte preamble */ - 0x00, /* Byte 4: priority and backoff defaults */ - 0x60, /* Byte 5: interframe spacing */ - 0x00, /* Byte 6: slot time LSB */ - 0xf2, /* Byte 7: slot time and retries */ - 0x0E, /* Byte 8: not promisc, disable bcast, tx no crs, crc inserted 32bit, 802.3 framing */ - 0x08, /* Byte 9: collision detect */ - 0x40, /* Byte 10: minimum frame length */ - 0xfb, /* Byte 11: tried C8 same as byte 1 in bits 6-7, else ignored*/ - 0x00, /* Byte 12: disable full duplex */ - 0x3f /* Byte 13: no multi IA, backoff enabled */ + 0x0E, /* Byte 0: length, prefetch off ( no RBD's ) */ + 0xC8, /* Byte 1: fifo to 8, monitor off */ + 0x40, /* Byte 2: don't save bad frames ( was save= 80, use intel's 40 )*/ + 0x2E, /* Byte 3: No source address insertion, 8 byte preamble */ + 0x00, /* Byte 4: priority and backoff defaults */ + 0x60, /* Byte 5: interframe spacing */ + 0x00, /* Byte 6: slot time LSB */ + 0xf2, /* Byte 7: slot time and retries */ + 0x0C, /* Byte 8: not promisc, enable bcast, tx no crs, crc inserted 32bit, 802.3 framing */ + 0x08, /* Byte 9: collision detect */ + 0x40, /* Byte 10: minimum frame length */ + 0xfb, /* Byte 11: tried C8 same as byte 1 in bits 6-7, else ignored*/ + 0x00, /* Byte 12: disable full duplex */ + 0x3f /* Byte 13: no multi IA, backoff enabled */ }; -/* Required RTEMS network driver functions and tasks (reset daemon extra) */ - -static void uti596_start( struct ifnet * ); -void uti596_init( void * ); -void uti596_stop( uti596_softc_ * ); -void uti596_txDaemon( void * ); -void uti596_rxDaemon( void * ); -void uti596_resetDaemon( void * ); -rtems_isr uti596_DynamicInterruptHandler (rtems_vector_number ); -static int uti596_ioctl( struct ifnet *, int, caddr_t ); -void uti596_stats( uti596_softc_ * ); - /* Local Routines */ -void uti596_initialize_hardware( uti596_softc_ * ); -void uti596_initMem( uti596_softc_ * ); -int uti596_initRFA( int ); -void uti596addPolledCmd( i596_cmd * ); -void uti596Diagnose( int ); -i596_rfd * uti596dequeue( i596_rfd ** ); -void uti596reset( void ); -void uti596_reset_hardware( uti596_softc_ *); -void uti596clearListStatus( i596_rfd * ); -void send_packet( struct ifnet *, struct mbuf * ); -void uti596addCmd( i596_cmd *pCmd ); -void uti596supplyFD( i596_rfd * ); -void uti596append( i596_rfd ** , i596_rfd * ); - -void printk_time( void ); -void dump_scb( void ); - -#ifdef DBG_INIT_3 +static unsigned long word_swap ( unsigned long ); +static void * malloc_16byte_aligned ( void **, void ** adjusted_pointer, size_t ); +RTEMS_INLINE_ROUTINE void uti596_writePortFunction ( void *, unsigned long ); +RTEMS_INLINE_ROUTINE void uti596_portReset( void ); +static unsigned long uti596_portSelfTest( i596_selftest * ); +static int uti596_portDump ( i596_dump_result * ); +static int uti596_wait ( uti596_softc_ *, unsigned8 ); +static int uti596_issueCA ( uti596_softc_ *, unsigned8 ); +static void uti596_addCmd ( i596_cmd * ); +static void uti596_addPolledCmd ( i596_cmd * ); +static void uti596_CU_dump ( i596_dump_result * ); +static void uti596_dump_scb ( void ); +static int uti596_setScpAndScb ( uti596_softc_ * ); +static int uti596_diagnose ( void ); +static int uti596_configure ( uti596_softc_ * ); +static int uti596_IAsetup ( uti596_softc_ * ); +static int uti596_initTBD ( uti596_softc_ * ); +static int uti596_initRFA ( int ); +static void uti596_initMem ( uti596_softc_ * ); +static void uti596_initialize ( uti596_softc_ * ); +static void uti596_initialize_hardware ( uti596_softc_ * ); +static void uti596_reset_hardware ( uti596_softc_ *); +static void uti596_reset ( void ); +static void uti596_clearListStatus ( i596_rfd * ); +static i596_rfd * uti596_dequeue ( i596_rfd ** ); +static void uti596_append ( i596_rfd ** , i596_rfd * ); +static void uti596_supplyFD ( i596_rfd * ); +static void send_packet ( struct ifnet *, struct mbuf * ); + + +/* Required RTEMS network driver functions and tasks (plus reset daemon) */ + +static void uti596_start ( struct ifnet * ); +void uti596_init ( void * ); +void uti596_stop ( uti596_softc_ * ); +void uti596_txDaemon ( void * ); +void uti596_rxDaemon ( void * ); +void uti596_resetDaemon( void * ); +rtems_isr uti596_DynamicInterruptHandler ( rtems_vector_number ); +static int uti596_ioctl ( struct ifnet *, int, caddr_t ); +void uti596_stats ( uti596_softc_ * ); + +#ifdef DBG_PACKETS +static void dumpQ( void ); +static void show_buffers( void ); +static void show_queues( void ); static void print_eth ( unsigned char * ); static void print_hdr ( unsigned char * ); static void print_pkt ( unsigned char * ); static void print_echo ( unsigned char * ); #endif -int uti596dump( char * ); -void dumpQ( void ); -void show_buffers( void ); -void show_queues( void ); -/* Helper function for reading/writing big endian memory structures */ -unsigned long word_swap(unsigned long); + +/* + * word_swap + * + * Return a 32 bit value, swapping the upper and lower words first. + * + * Input parameters: + * val - 32 bit value to swap + * + * Output parameters: NONE + * + * Return value: + * Input value with upper and lower 16-bit words swapped + */ +static unsigned long word_swap( + unsigned long val +) +{ + return (((val >> 16)&(0x0000ffff)) | ((val << 16)&(0xffff0000))); +} + + +/* + * malloc_16byte_aligned + * + * Allocate a block of a least nbytes aligned on a 16-byte boundary. + * Clients are responsible to store both the real address and the adjusted + * address. The real address must be used to free the block. + * + * Input parameters: + * real_pointer - pointer to a void * pointer in which to store the starting + * address of the block. Required for free. + * adjusted_pointer - pointer to a void * pointer in which to store the + * starting address of the block rounded up to the next + * 16 byte boundary. + * nbytes - number of bytes of storage requested + * + * Output parameters: + * real_pointer - starting address of the block. + * adjusted_pointer - starting address of the block rounded up to the next + * 16 byte boundary. + * + * Return value: + * starting address of the block rounded up to the next 16 byte boundary. + * NULL if no storage was allocated. + */ +static void * malloc_16byte_aligned( + void ** real_pointer, + void ** adjusted_pointer, + size_t nbytes +) +{ + *real_pointer = malloc( nbytes + 0xF, 0, M_NOWAIT ); + *adjusted_pointer = (void *)(((unsigned long)*real_pointer + 0xF ) & 0xFFFFFFF0 ); + return *adjusted_pointer; +} + + +/* + * uti596_scp_alloc + * + * Allocate a new scp, possibly freeing a previously allocated one. + * + * Input parameters: + * sc - pointer to the global uti596_softc in which to store pointers + * to the newly allocated block. + * + * Output parameters: NONE + * + * Return value: + * Pointer to the newly allocated, 16-byte aligned scp. + */ +static i596_scp * uti596_scp_alloc( + uti596_softc_ * sc +) +{ + if( sc->base_scp != NULL ) { + #ifdef DBG_MEM + printk(("uti596_scp_alloc: Already have an SCP at %p\n", sc->base_scp)) + #endif + return sc->pScp; + } + + /* allocate enough memory for the Scp block to be aligned on 16 byte boundary */ + malloc_16byte_aligned( (void *)&(sc->base_scp), (void *)&(sc->pScp), sizeof( i596_scp ) ); + + #ifdef DBG_MEM + printk(("uti596_scp_alloc: Scp base address is %p\n", sc->base_scp)) + printk(("uti596_scp_alloc: Scp aligned address is : %p\n",sc->pScp)) + #endif + + return sc->pScp; +} + + +/* + * uti596_writePortFunction + * + * Write the command into the PORT. + * + * Input parameters: + * addr - 16-byte aligned address to write into the PORT. + * cmd - 4-bit cmd to write into the PORT + * + * Output parameters: NONE + * + * Return value: NONE + * + * The Motorola manual swapped the high and low registers. + */ +RTEMS_INLINE_ROUTINE void uti596_writePortFunction( + void * addr, + unsigned long cmd +) +{ + i82596->port_lower = (unsigned short)(((unsigned long)addr & 0xFFF0) | cmd); + i82596->port_upper = (unsigned short)(((unsigned long)addr >> 16 ) & 0xFFFF); +} + + +/* + * uti596_portReset + * + * Issue a port Reset to the uti596 + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return value: NONE + */ +RTEMS_INLINE_ROUTINE void uti596_portReset( void ) +{ + uti596_writePortFunction( NULL, UTI596_RESET_PORT_FUNCTION ); +} + + +/* + * uti596_portSelfTest + * + * Perform a self-test. Wait for up to 1 second for the test to + * complete. Normally, the test should complete in a very short time, + * so busy waiting is not an issue. + * + * Input parameters: + * stp - pointer to a 16-byte aligned uti596_selftest structure. + * + * Output parameters: NONE + * + * Return value: + * 32-bit result field if successful, -1 otherwise. + */ +static unsigned long uti596_portSelfTest( + i596_selftest * stp +) +{ + rtems_interval ticks_per_second, start_ticks, end_ticks; + + stp->results = 0xFFFFFFFF; + uti596_writePortFunction( stp, UTI596_SELFTEST_PORT_FUNCTION ); + + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + end_ticks = start_ticks + ticks_per_second; + + do { + if( stp->results != 0xFFFFFFFF ) + break; + else + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + } while (start_ticks <= end_ticks); + + if (start_ticks > end_ticks ) { + #ifdef DBG_SELFTEST_CMD + printk(("uti596_selftest: Timed out\n" )) + #endif + return -1; + } + else { + #ifdef DBG_SELFTEST_CMD + printk(("uti596_selftest: Succeeded with signature = 0x%08x, result = 0x%08x\n", + stp->signature, + stp->results)) + #endif + return stp->results; + } +} + + +/* + * uti596_portDump + * + * Perform a dump Wait for up to 1 second for the test to + * complete. Normally, the test should complete in a very short time, + * so busy waiting is not an issue. + * + * Input parameters: + * dp - pointer to a 16-byte aligned uti596_dump structure. + * + * Output parameters: NONE + * + * Return value: + * 16-bit dump_status field if successful, -1 otherwise. + */ +static int uti596_portDump( + i596_dump_result * dp +) +{ + rtems_interval ticks_per_second, start_ticks, end_ticks; + + dp->dump_status = 0; + uti596_writePortFunction( dp, UTI596_DUMP_PORT_FUNCTION ); + + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + end_ticks = start_ticks + ticks_per_second; + + do { + if( dp->dump_status != 0xA006 ) + break; + else + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + } while (start_ticks <= end_ticks); + + if (start_ticks > end_ticks ) { + #ifdef DBG_DUMP_CMD + printk(("uti596_dump: Timed out with dump at 0x%08x\n", (unsigned long)dp )) + #endif + return -1; + } + else { + #ifdef DBG_DUMP_CMD + printk(("uti596_dump: Succeeded with dump at = 0x%08x\n", (unsigned long)dp )) + #endif + return dp->dump_status; + } +} + + +/* + * uti596_wait + * + * Wait for a certain condition. + * + * Input parameters: + * sc - pointer to the uti596_softc struct + * wait_type - UTI596_NO_WAIT + * UTI596_WAIT_FOR_CU_ACCEPT + * UTI596_WAIT_FOR_INITIALIZATION + * UTI596_WAIT_FOR_STAT_C + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise. + */ +static int uti596_wait( + uti596_softc_ *sc, + unsigned8 waitType +) +{ + rtems_interval ticks_per_second, start_ticks, end_ticks; + + switch( waitType ) { + case UTI596_NO_WAIT: + return 0; + + case UTI596_WAIT_FOR_CU_ACCEPT: + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + end_ticks = start_ticks + ticks_per_second; + + do { + if (sc->scb.command == 0) + break; + else + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + + } while (start_ticks <= end_ticks); + + if( (sc->scb.command != 0) || (start_ticks > end_ticks) ) { + printf("i82596 timed out with status %x, cmd %x.\n", + sc->scb.status, sc->scb.command); + return -1; + } + else + return 0; + + case UTI596_WAIT_FOR_INITIALIZATION: + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + end_ticks = start_ticks + ticks_per_second; + + do { + if( !sc->iscp.busy ) + break; + else + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + } while (start_ticks <= end_ticks); + + if (start_ticks > end_ticks ) { + #ifdef DBG_WAIT + printk(("uti596_setScpAndScb: Timed out\n" )) + #endif + return -1; + } + else { + #ifdef DBG_WAIT + printk(("uti596_setScpAndScb: Succeeded\n" )) + #endif + return 0; + } + + case UTI596_WAIT_FOR_STAT_C: + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + end_ticks = start_ticks + ticks_per_second; + + do { + if( *sc->pCurrent_command_status & STAT_C ) + break; + else + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); + } while (start_ticks <= end_ticks); + + if (start_ticks > end_ticks ) { + #ifdef DBG_WAIT + printk(("uti596_initMem: timed out - STAT_C not obtained\n" )) + #endif + return -1; + } + else { + #ifdef DBG_WAIT + printk(("uti596_initMem: STAT_C obtained OK\n" )) + #endif + return 0; + } + } + return -1; +} + + +/* + * uti596_issueCA + * + * Issue a Channel Attention command. Possibly wait for the + * command to start or complete. + * + * Input parameters: + * sc - pointer to the uti596_softc + * wait_type - UTI596_NO_WAIT + * UTI596_WAIT_BEGIN + * UTI596_WAIT_COMPLETION + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise. + */ +static int uti596_issueCA( + uti596_softc_ *sc, + unsigned8 waitType +) +{ + /* Issue Channel Attention */ + i82596->chan_attn = 0x00000000; + + return (uti596_wait ( sc, waitType )); +} + + +/* + * uti596_addCmd + * + * Add a uti596_cmd onto the end of the CBL command chain, + * or to the start if the chain is empty. + * + * Input parameters: + * pCmd - a pointer to the command to be added. + * + * Output parameters: NONE + * + * Return value: NONE + */ +static void uti596_addCmd( + i596_cmd *pCmd +) +{ + ISR_Level level; + + #ifdef DBG_ADD_CMD + printk(("uti596_addCmd: Adding command 0x%x\n", pCmd -> command )) + #endif + + /* Mark command as last in list, to return an interrupt */ + pCmd->command |= (CMD_EOL | CMD_INTR ); + pCmd->status = 0; + pCmd->next = I596_NULL; + + _ISR_Disable(level); + + if (uti596_softc.pCmdHead == I596_NULL) { + uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; + uti596_softc.scb.cmd_pointer = word_swap ((unsigned long)pCmd); + + uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); + uti596_softc.scb.command = CUC_START; + uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); + + _ISR_Enable(level); + } + else { + uti596_softc.pCmdTail->next = (i596_cmd *) word_swap ((unsigned long)pCmd); + uti596_softc.pCmdTail = pCmd; + _ISR_Enable(level); + } + + #ifdef DBG_ADD_CMD + printk(("uti596_addCmd: Scb status & command 0x%x 0x%x\n", + uti596_softc.scb.status, + uti596_softc.scb.command )) + #endif +} + + +/* + * uti596_addPolledCmd + * + * Add a single uti596_cmd to the end of the command block list + * for processing, send a CU_START and wait for its acceptance + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_addPolledCmd( + i596_cmd *pCmd +) +{ + + #ifdef DBG_ADD_CMD + printk(("uti596_addPolledCmd: Adding command 0x%x\n", pCmd -> command )) + #endif + + pCmd->status = 0; + pCmd->command |= CMD_EOL ; /* only command in list*/ + pCmd->next = I596_NULL; + + uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); + + uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; + uti596_softc.scb.cmd_pointer = word_swap((unsigned long)pCmd); + uti596_softc.scb.command = CUC_START; + uti596_issueCA ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); + + uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL; + uti596_softc.scb.cmd_pointer = (unsigned long) I596_NULL; + + #ifdef DBG_ADD_CMD + printk(("uti596_addPolledCmd: Scb status & command 0x%x 0x%x\n", + uti596_softc.scb.status, + uti596_softc.scb.command )) + #endif +} + + +/* + * uti596_CU_dump + * + * Dump the LANC 82596 registers + * The outcome is the same as the portDump() but executed + * via the CU instead of via a PORT access. + * + * Input parameters: + * drp - a pointer to a i596_dump_result structure. + * + * Output parameters: NONE + * + * Return value: NONE + */ +static void uti596_CU_dump ( i596_dump_result * drp) +{ + i596_dump dumpCmd; + + dumpCmd.cmd.command = CmdDump; + dumpCmd.cmd.next = I596_NULL; + dumpCmd.pData = (char *) drp; + uti596_softc.cmdOk = 0; + uti596_addCmd ( (i596_cmd *) &dumpCmd ); + +} + + +/* + * uti596_dump_scb + * + * Dump the system control block + * This function expands to nothing when using interrupt driven I/O + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return value: NONE + */ +static void uti596_dump_scb ( void ) +{ + printk(("status 0x%x\n",uti596_softc.scb.status)) + printk(("command 0x%x\n",uti596_softc.scb.command)) + printk(("cmd 0x%x\n",(int)uti596_softc.scb.pCmd)) + printk(("rfd 0x%x\n",(int)uti596_softc.scb.pRfd)) + printk(("crc_err 0x%x\n",uti596_softc.scb.crc_err)) + printk(("align_err 0x%x\n",uti596_softc.scb.align_err)) + printk(("resource_err 0x%x\n",uti596_softc.scb.resource_err )) + printk(("over_err 0x%x\n",uti596_softc.scb.over_err)) + printk(("rcvdt_err 0x%x\n",uti596_softc.scb.rcvdt_err)) + printk(("short_err 0x%x\n",uti596_softc.scb.short_err)) + printk(("t_on 0x%x\n",uti596_softc.scb.t_on)) + printk(("t_off 0x%x\n",uti596_softc.scb.t_off)) +} + + +/* + * uti596_setScpAndScb + * + * Issue the first channel attention after reset and wait for the busy + * field to clear in the iscp. + * + * Input parameters: + * sc - pointer to the global uti596_softc + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise. + */ +static int uti596_setScpAndScb( + uti596_softc_ * sc +) +{ + /* set the busy flag in the iscp */ + sc->iscp.busy = 1; + + /* the command block list (CBL) is empty */ + sc->scb.command = 0; + sc->scb.cmd_pointer = (unsigned long) I596_NULL; /* all 1's */ + sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ + + uti596_writePortFunction( sc->pScp, UTI596_SCP_PORT_FUNCTION ); + + /* Issue CA: pass the scb address to the 596 */ + return ( uti596_issueCA ( sc, UTI596_WAIT_FOR_INITIALIZATION ) ); +} + + +/* + * uti596_diagnose + * + * Send a diagnose command to the CU + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise + */ +static int uti596_diagnose( void ) +{ + i596_cmd diagnose; + + diagnose.command = CmdDiagnose; + diagnose.status = 0; + uti596_softc.pCurrent_command_status = &diagnose.status; + uti596_addPolledCmd(&diagnose); + return (uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_STAT_C )); + + #ifdef DBG_INIT + printk(("Status diagnostic: 0xa000 is a success ... 0x%2.2x\n", diagnose.status)) + #endif +} + + +/* + * uti596_configure + * + * Send the CU a configure command with the desired + * configuration structure + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise + */ +static int uti596_configure ( + uti596_softc_ * sc +) +{ + sc->set_conf.cmd.command = CmdConfigure; + memcpy (sc->set_conf.data, uti596initSetup, 14); + uti596_addPolledCmd( (i596_cmd *) &sc->set_conf); + + /* Poll for successful command completion */ + sc->pCurrent_command_status = &(sc->set_conf.cmd.status); + return ( uti596_wait ( sc, UTI596_WAIT_FOR_STAT_C ) ); +} + + +/* + * uti596_IAsetup + * + * Send the CU an Individual Address setup command with + * the ethernet hardware address + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise + */ +static int uti596_IAsetup ( + uti596_softc_ * sc +) +{ + int i; + + sc->set_add.cmd.command = CmdSASetup; + for ( i=0; i<6; i++) { + sc->set_add.data[i]=sc->arpcom.ac_enaddr[i]; + } + sc->cmdOk = 0; + uti596_addPolledCmd((i596_cmd *)&sc->set_add); + + /* Poll for successful command completion */ + sc->pCurrent_command_status = &(sc->set_add.cmd.status); + return ( uti596_wait ( sc, UTI596_WAIT_FOR_STAT_C ) ); +} + + +/* + * uti596_initTBD + * + * Initialize transmit buffer descriptors + * dynamically allocate mem for the number of tbd's required + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: + * 0 if successful, -1 otherwise + */ +static int uti596_initTBD ( uti596_softc_ * sc ) +{ + int i; + i596_tbd *pTbd, *pPrev; + + /* Set up a transmit command with a tbd ready */ + sc->pLastUnkRFD = I596_NULL; + sc->pTxCmd = (i596_tx *) calloc (1,sizeof (struct i596_tx) ); + sc->pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); + if ((sc->pTxCmd == NULL) || (sc->pTbd == NULL)) { + return -1; + } + sc->pTxCmd->pTbd = (i596_tbd *) word_swap ((unsigned long) sc->pTbd); + sc->pTxCmd->cmd.command = CMD_FLEX|CmdTx; + sc->pTxCmd->pad = 0; + sc->pTxCmd->count = 0; /* all bytes are in list of TBD's */ + + pPrev = pTbd = sc->pTbd; + + /* Allocate a linked list of tbd's each with it's 'next' field written + * with upper and lower words swapped (for big endian), and mark the end. + */ + for ( i=0; i<sc->txBdCount; i++) { + if ( (pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) )) == NULL ) { + return -1; + } + pPrev->next = (i596_tbd *) word_swap ((unsigned long) pTbd); + pPrev = pTbd; + } + pTbd->next = I596_NULL; + return 0; +} + + +/* + * uti596_initRFA + * + * Initialize the Receive Frame Area + * dynamically allocate mem for the number of rfd's required + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: + * # of buffer descriptors successfully allocated + */ +static int uti596_initRFA( int num ) +{ + i596_rfd *pRfd; + int i = 0; + + #ifdef DBG_INIT + printk(("uti596_initRFA: begins\n Requested frame descriptors ... %d.\n", num)) + #endif + + /* + * Create the first RFD in the RFA + */ + pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd)); + if ( !pRfd ) { + printk(("Can't allocate first buffer.\n")) + return 0; + } + else { + uti596_softc.countRFD = 1; + uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; + } + + /* Create remaining RFDs */ + for (i = 1; i < num; i++) { + pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd) ); + if ( pRfd != NULL ) { + uti596_softc.countRFD++; /* update count */ + uti596_softc.pEndRFA->next = + (i596_rfd *) word_swap ((unsigned long) pRfd); /* write the link */ + uti596_softc.pEndRFA = pRfd; /* move the end */ + } + else { + printk(("Can't allocate all buffers: only %d allocated\n", i)) + break; + } + } /* end for */ + + uti596_softc.pEndRFA->next = I596_NULL; + UTI_596_ASSERT(uti596_softc.countRFD == RX_BUF_COUNT,"INIT:WRONG RFD COUNT\n" ) + + #ifdef DBG_INIT + printk (("uti596_initRFA: Head of RFA is buffer %p \n\ + uti596_initRFA: End of RFA is buffer %p \n", + uti596_softc.pBeginRFA, uti596_softc.pEndRFA )) + #endif + + /* Walk and initialize the RFD's */ + for ( pRfd = uti596_softc.pBeginRFA; + pRfd != I596_NULL; + pRfd = (i596_rfd *) word_swap ((unsigned long)pRfd->next) ) + { + pRfd->cmd = 0x0000; + pRfd->stat = 0x0000; + pRfd->pRbd = I596_NULL; + pRfd->count = 0; /* number of bytes in buffer: usually less than size */ + pRfd->size = 1532; /* was 1532; buffer size ( All RBD ) */ + } /* end for */ + + /* mark the last RFD as the last one in the RDL */ + uti596_softc.pEndRFA -> cmd = CMD_EOL; + uti596_softc.pSavedRfdQueue = + uti596_softc.pEndSavedQueue = I596_NULL; /* initially empty */ + + uti596_softc.savedCount = 0; + uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */ + + return (i); /* the number of allocated buffers */ +} + + +/* + * uti596_initMem + * + * Initialize the 82596 memory structures for Tx and Rx + * dynamically allocate mem for the number of tbd's required + * + * Input parameters: + * sc - a pointer to the uti596_softc struct + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_initMem( + uti596_softc_ * sc +) +{ + int i; + + #ifdef DBG_INIT + printk(("uti596_initMem: begins\n")) + #endif + + sc->resetDone = 0; + + /* + * Set up receive frame area (RFA) + */ + i = uti596_initRFA( sc->rxBdCount ); + if ( i < sc->rxBdCount ) { + printk(("init_rfd: only able to allocate %d receive frame descriptors\n", i)) + } + + /* + * Write the SCB with a pointer to the receive frame area + * and keep a pointer for our use. + */ + sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); + sc->scb.pRfd = sc->pBeginRFA; + + /* + * Diagnose the health of the board + */ + uti596_diagnose(); + + /* + * Configure the 82596 + */ + uti596_configure( sc ); + + /* + * Set up the Individual (hardware) Address + */ + uti596_IAsetup ( sc ); + + /* + * Initialize the transmit buffer descriptors + */ + uti596_initTBD( sc ); + + /* Padding used to fill short tx frames */ + memset ( &sc->zeroes, 0, 64); + + /* now need ISR */ + sc->resetDone = 1; +} + +/* + * uti596_initialize + * + * Reset the 82596 and initialize it with a new SCP. + * + * Input parameters: + * sc - pointer to the uti596_softc + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_initialize( + uti596_softc_ *sc +) +{ + /* Reset the device. Stops it from doing whatever it might be doing. */ + uti596_portReset(); + + /* Get a new System Configuration Pointer */ + uti596_scp_alloc( sc ); + + /* write the SYSBUS: interrupt pin active high, LOCK disabled, + * internal triggering, linear mode + */ + sc->pScp->sysbus = 0x54; + + /* provide the iscp to the scp, keep a pointer for our use */ + sc->pScp->iscp_pointer = word_swap((unsigned long)&sc->iscp); + sc->pScp->iscp = &sc->iscp; + + /* provide the scb to the iscp, keep a pointer for our use */ + sc->iscp.scb_pointer = word_swap((unsigned long)&sc->scb); + sc->iscp.scb = &sc->scb; + + #ifdef DBG_INIT + printk(("uti596_initialize: Starting i82596.\n")) + #endif + + /* Set up the 82596 */ + uti596_setScpAndScb( sc ); + + /* clear the scb command word */ + sc->scb.command = 0; +} + + +/* + * uti596_initialize_hardware + * + * Reset the 82596 and initialize it with a new SCP. Enable bus snooping. + * Install the interrupt handlers. + * + * Input parameters: + * sc - pointer to the uti596_softc + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_initialize_hardware( + uti596_softc_ *sc +) +{ + rtems_isr_entry dummy; + + printk(("uti596_initialize_hardware: begins\n")) + + /* Get the PCCChip2 to assert bus snooping signals on behalf of the i82596 */ + pccchip2->LANC_berr_ctl = 0x40; + + uti596_initialize( sc ); + + /* + * Configure interrupt control in PCCchip2 + */ + pccchip2->LANC_error = 0xff; /* clear status register */ + pccchip2->LANC_int_ctl = 0x5d; /* lvl 5, enabled, edge-sensitive rising */ + pccchip2->LANC_berr_ctl = 0x5d; /* bus error: lvl 5, enabled, snoop control + * will supply dirty data and leave dirty data + * on read access and sink any data on write + */ + /* + * Install the interrupt handler + * calls rtems_interrupt_catch + */ + dummy = (rtems_isr_entry) set_vector( uti596_DynamicInterruptHandler, 0x57, 1 ); + + /* Initialize the 82596 memory */ + uti596_initMem(sc); + + #ifdef DBG_INIT + printk(("uti596_initialize_hardware: After attach, status of board = 0x%x\n", sc->scb.status )) + #endif +} + + +/* + * uti596_reset_hardware + * + * Reset the 82596 and initialize it with an SCP. + * + * Input parameters: + * sc - pointer to the uti596_softc + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_reset_hardware( + uti596_softc_ *sc +) +{ + rtems_status_code status_code; + i596_cmd *pCmd; + + pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */ + + /* the command block list (CBL) is empty */ + sc->scb.cmd_pointer = (unsigned long) I596_NULL; /* all 1's */ + sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ + + #ifdef DBG_RESET + printk(("uti596_reset_hardware\n")) + #endif + uti596_initialize( sc ); + + /* + * Wake the transmitter if needed. + */ + if ( sc->txDaemonTid && pCmd != I596_NULL ) { + printk(("****RESET: wakes transmitter!\n")) + status_code = rtems_event_send (sc->txDaemonTid, + INTERRUPT_EVENT); + + if ( status_code != RTEMS_SUCCESSFUL ) { + printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n", + sc->txDaemonTid, rtems_status_text (status_code) )) + } + } + + #ifdef DBG_RESET + printk(("uti596_reset_hardware: After reset_hardware, status of board = 0x%x\n", sc->scb.status )) + #endif +} + + +/* + * uti596_clearListStatus + * + * Clear the stat fields for all RFDs + * + * Input parameters: + * pRfd - a pointer to the head of the RFA + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_clearListStatus( + i596_rfd *pRfd +) +{ + while ( pRfd != I596_NULL ) { + pRfd -> stat = 0; + pRfd = (i596_rfd *) word_swap((unsigned long)pRfd-> next); + } +} + + +/* + * uti596_reset + * + * Reset the 82596 and reconfigure + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return value: NONE + */ +void uti596_reset( void ) +{ + uti596_softc_ *sc = &uti596_softc; + + #ifdef DBG_RESET + printk(("uti596_reset: begin\n")) + #endif + + /* Wait for the CU to be available, then + * reset the ethernet hardware. Must re-config. + */ + sc->resetDone = 0; + uti596_wait ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); + uti596_reset_hardware ( &uti596_softc ); + + #ifdef DBG_RESET + uti596_diagnose(); + #endif + + /* + * Configure the 82596 + */ + uti596_configure( sc ); + + /* + * Set up the Individual (hardware) Address + */ + uti596_IAsetup ( sc ); + + sc->pCmdHead = sc->pCmdTail = sc->scb.pCmd = I596_NULL; + + + /* restore the RFA */ + + if ( sc->pLastUnkRFD != I596_NULL ) { + sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */ + sc-> pLastUnkRFD = I596_NULL; + } + + sc->pEndRFA->next = sc->pSavedRfdQueue; + if ( sc->pSavedRfdQueue != I596_NULL ) { + sc->pEndRFA = sc->pEndSavedQueue; + sc->pSavedRfdQueue = sc->pEndSavedQueue = I596_NULL; + sc -> countRFD = sc->rxBdCount ; + } + + /* Re-address the head of the RFA in the SCB */ + sc->scb.pRfd = sc->pBeginRFA; + sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); + + /* Clear the status of all RFDs */ + uti596_clearListStatus( sc->pBeginRFA ); + + printk(("uti596_reset: Starting NIC\n")) + + /* Start the receiver */ + sc->scb.command = RX_START; + sc->started = 1; /* assume that the start is accepted */ + sc->resetDone = 1; + uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); + + UTI_596_ASSERT(sc->pCmdHead == I596_NULL, "Reset: CMD not cleared\n") + + #ifdef DBG_RESET + printk(("uti596_reset: completed\n")) + #endif +} + + +/* + * uti596_dequeue + * + * Remove an RFD from the received fram queue + * + * Input parameters: + * ppQ - a pointer to a i596_rfd pointer + * + * Output parameters: NONE + * + * Return value: + * pRfd - a pointer to the dequeued RFD + */ +i596_rfd * uti596_dequeue( + i596_rfd ** ppQ +) +{ + ISR_Level level; + i596_rfd * pRfd; + + _ISR_Disable(level); + + /* invalid address, or empty queue or emptied queue */ + if( ppQ == NULL || *ppQ == NULL || *ppQ == I596_NULL) { + _ISR_Enable(level); + return I596_NULL; + } + + /* + * Point to the dequeued buffer, then + * adjust the queue pointer and detach the buffer + */ + pRfd = *ppQ; + *ppQ = (i596_rfd *) word_swap ((unsigned long) pRfd->next); + pRfd->next = I596_NULL; /* unlink the rfd being returned */ + + _ISR_Enable(level); + return pRfd; +} + + +/* + * uti596_append + * + * Remove an RFD buffer from the RFA and tack it on to + * the received frame queue for processing. + * + * Input parameters: + * ppQ - a pointer to the queue pointer + * pRfd - a pointer to the buffer to be returned + * + * Output parameters: NONE + * + * Return value: NONE + */ + +void uti596_append( + i596_rfd ** ppQ, + i596_rfd * pRfd +) +{ + + i596_rfd *p; + + if ( pRfd != NULL && pRfd != I596_NULL) { + pRfd -> next = I596_NULL; + pRfd -> cmd |= CMD_EOL; /* set EL bit */ + + if ( *ppQ == NULL || *ppQ == I596_NULL ) { + /* empty list */ + *ppQ = pRfd; + } + else { + /* walk to the end of the list */ + for ( p=*ppQ; + p->next != I596_NULL; + p=(i596_rfd *) word_swap ((unsigned long)p->next) ); + + /* append the rfd */ + p->cmd &= ~CMD_EOL; /* Clear EL bit at end */ + p->next = (i596_rfd *) word_swap ((unsigned long)pRfd); + } + } + else { + printk(("Illegal attempt to append: %p\n", pRfd)) + } +} -/* Waits for the command word to clear. The command word is cleared AFTER the interrupt is - * generated. This allows the CPU to issue the next command +/* + * uti596_supplyFD + * + * Return a buffer (RFD) to the receive frame area (RFA). + * Call with interrupts disabled. + * + * Input parameters: + * pRfd - a pointer to the buffer to be returned + * + * Output parameters: NONE + * + * Return value: NONE */ -#define UTI_WAIT_COMMAND_ACCEPTED(duration,function) \ -{ rtems_interval ticks_per_second, start_ticks, end_ticks; \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); \ - end_ticks = start_ticks + ticks_per_second; \ - do { \ - if (uti596_softc.scb.command == 0) \ - break; \ - else { \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); \ - } \ - } while (start_ticks <= end_ticks); \ - if ((uti596_softc.scb.command != 0) || (start_ticks > end_ticks)) \ - printf("%s: i82596 timed out with status %x, cmd %x.\n", function, \ - uti596_softc.scb.status, uti596_softc.scb.command); \ +void uti596_supplyFD ( + i596_rfd * pRfd +) +{ + i596_rfd *pLastRfd; + + UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n") + + pRfd -> cmd = CMD_EOL; + pRfd -> pRbd = I596_NULL; + pRfd -> next = I596_NULL; + pRfd -> stat = 0x0000; /* clear STAT_C and STAT_B bits */ + + /* + * Check if the list is empty: + */ + if ( uti596_softc.pBeginRFA == I596_NULL ) { + + /* Start a list with one entry */ + uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; + UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n") + if ( uti596_softc.pLastUnkRFD != I596_NULL ) { + printk(("LastUnkRFD is NOT NULL!!\n")) + } + uti596_softc.countRFD = 1; + return; + } + + /* + * Check if the last RFD is used/read by the 596. + */ + pLastRfd = uti596_softc.pEndRFA; + + /* C = complete, B = busy (prefetched) */ + if ( pLastRfd != I596_NULL && ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { + + /* + * Not yet too late to add it + */ + pLastRfd -> next = (i596_rfd *) word_swap ((unsigned long)pRfd); + pLastRfd -> cmd &= ~CMD_EOL; /* RESET_EL : reset EL bit to 0 */ + uti596_softc.countRFD++; /* Lets assume we add it successfully + If not, the RFD may be used, and may + decrement countRFD < 0 !! */ + /* + * Check if the last RFD was used while appending. + */ + if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */ + /* + * Either the EL bit of the last rfd has been read by the 82596, + * and it will stop after reception,( true when RESET_EL not reached ) or + * the EL bit was NOT read by the 82596 and it will use the linked + * RFD for the next reception. ( true when RESET_EL was reached ) + * So, it is unknown whether or not the linked rfd will be used. + * Therefore, the end of list CANNOT be updated. + */ + UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" ) + uti596_softc.pLastUnkRFD = pRfd; + return; + } + else { + /* + * The RFD being added was not touched by the 82596 + */ + if (uti596_softc.pLastUnkRFD != I596_NULL ) { + + uti596_append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */ + uti596_softc.pEndSavedQueue = pRfd; + uti596_softc.savedCount++; + uti596_softc.countRFD--; + + } + else { + + uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */ + + if ( ( uti596_softc.scb.status & SCB_STAT_RNR || + uti596_softc.scb.status & RU_NO_RESOURCES ) && + uti596_softc.countRFD > 1 ) { + + /* Ensure that beginRFA is not EOL */ + uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; + + UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n") + UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n") + UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n") + + #ifdef DBG_MEM + printk(("uti596_supplyFD: starting receiver")) + #endif + + /* start the receiver */ + UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n") + uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; + uti596_softc.scb.rfd_pointer = word_swap ((unsigned long) uti596_softc.pBeginRFA); + + /* Don't ack RNR! The receiver should be stopped in this case */ + uti596_softc.scb.command = RX_START | SCB_STAT_RNR; + + UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n") + + /* send CA signal */ + uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); + } + } + return; + } + } + else { + /* + * too late , pLastRfd in use ( or NULL ), + * in either case, EL bit has been read, and RNR condition will occur + */ + uti596_append( &uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */ + + uti596_softc.pEndSavedQueue = pRfd; /* reset end of saved queue */ + uti596_softc.savedCount++; + + return; + } } -#define UTI_WAIT_TICKS \ -{ rtems_interval ticks_per_second, start_ticks, end_ticks; \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); \ - end_ticks = start_ticks + ticks_per_second; \ - do { \ - rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks); \ - } while (start_ticks <= end_ticks); \ + +/* + * send_packet + * + * Send a raw ethernet packet, add a + * transmit command to the CBL + * + * Input parameters: + * ifp - a pointer to the ifnet structure + * m - a pointer to the mbuf being sent + * + * Output parameters: NONE + * + * Return value: NONE + */ +void send_packet( + struct ifnet *ifp, struct mbuf *m +) +{ + i596_tbd *pPrev = I596_NULL; + i596_tbd *pRemainingTbdList; + i596_tbd *pTbd; + struct mbuf *n, *input_m = m; + uti596_softc_ *sc = ifp->if_softc; + struct mbuf *l = NULL; + unsigned int length = 0; + rtems_status_code status; + int bd_count = 0; + rtems_event_set events; + + /* + * For all mbufs in the chain, + * fill a transmit buffer descriptor for each + */ + pTbd = (i596_tbd*) word_swap ((unsigned long)sc->pTxCmd->pTbd); + + do { + if (m->m_len) { + /* + * Fill in the buffer descriptor + */ + length += m->m_len; + pTbd->data = (char *) word_swap ((unsigned long) mtod (m, void *)); + pTbd->size = m->m_len; + pPrev = pTbd; + pTbd = (i596_tbd *) word_swap ((unsigned long) pTbd->next); + l = m; + m = m->m_next; + } + else { + /* + * Just toss empty mbufs + */ + MFREE (m, n); + m = n; + if (l != NULL) + l->m_next = m; + } + } while( m != NULL && ++bd_count < 16 ); + + /* This should never happen */ + if ( bd_count == 16 ) { + printk(("TX ERROR:Too many mbufs in the packet!!!\n")) + printk(("Must coalesce!\n")) + } + + if ( length < UTI_596_ETH_MIN_SIZE ) { + pTbd->data = (char *) word_swap ((unsigned long) sc->zeroes); /* add padding to pTbd */ + pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */ + } + else /* Don't use pTbd in the send routine */ + pTbd = pPrev; + + /* Disconnect the packet from the list of Tbd's */ + pRemainingTbdList = (i596_tbd *) word_swap ((unsigned long)pTbd->next); + pTbd->next = I596_NULL; + pTbd->size |= UTI_596_END_OF_FRAME; + + sc->rawsndcnt++; + + #ifdef DBG_SEND + printk(("send_packet: sending packet\n")) + #endif + + /* Sending Zero length packet: shouldn't happen */ + if (pTbd->size <= 0) return; + + #ifdef DBG_PACKETS + printk (("\nsend_packet: Transmitter adds packet\n")) + print_hdr ( sc->pTxCmd->pTbd->data ); /* print the first part */ + print_pkt ( sc->pTxCmd->pTbd->next->data ); /* print the first part */ + print_echo (sc->pTxCmd->pTbd->data); + #endif + + /* add the command to the output command queue */ + uti596_addCmd ( (i596_cmd *) sc->pTxCmd ); + + /* sleep until the command has been processed or Timeout encountered. */ + status= rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + + if ( status != RTEMS_SUCCESSFUL ) { + printk(("Could not sleep %s\n", rtems_status_text(status))) + } + + #ifdef DBG_SEND + printk(("send_packet: RAW - wake\n")) + #endif + + sc->txInterrupts++; + + if ( sc->pTxCmd -> cmd.status & STAT_OK ) { + sc->stats.tx_packets++; + } + else { + + printk(("*** send_packet: Driver Error 0x%x\n", sc->pTxCmd -> cmd.status )) + + sc->stats.tx_errors++; + if ( sc->pTxCmd->cmd.status & 0x0020 ) + sc->stats.tx_retries_exceeded++; + if (!(sc->pTxCmd->cmd.status & 0x0040)) + sc->stats.tx_heartbeat_errors++; + if ( sc->pTxCmd->cmd.status & 0x0400 ) + sc->stats.tx_carrier_errors++; + if ( sc->pTxCmd->cmd.status & 0x0800 ) + sc->stats.collisions++; + if ( sc->pTxCmd->cmd.status & 0x1000 ) + sc->stats.tx_aborted_errors++; + } /* end if stat_ok */ + + /* + * Restore the transmitted buffer descriptor chain. + */ + pTbd -> next = (i596_tbd *) word_swap ((unsigned long)pRemainingTbdList); + + /* + * Free the mbufs used by the sender. + */ + m = input_m; + while ( m != NULL ) { + MFREE(m,n); + m = n; + } } -/************************************************************************/ - - - /*********************************************************************** - * Function: uti596_attach - * - * Description: - * Configure the driver, and connect to the network stack - * - * Algorithm: - * - * Check parameters in the ifconfig structure, and - * set driver parameters accordingly. - * initialize required rx and tx buffers - * link driver data structure onto device list - * return 1 on successful completion - * - ***********************************************************************/ + + +/*********************************************************************** + * Function: uti596_attach + * + * Description: + * Configure the driver, and connect to the network stack + * + * Algorithm: + * + * Check parameters in the ifconfig structure, and + * set driver parameters accordingly. + * Initialize required rx and tx buffers. + * Link driver data structure onto device list. + * Return 1 on successful completion. + * + ***********************************************************************/ int uti596_attach( struct rtems_bsdnet_ifconfig * pConfig ) { - uti596_softc_ *sc = &uti596_softc; /* device dependent data structure */ - struct ifnet * ifp = &sc->arpcom.ac_if; /* ifnet structure */ + uti596_softc_ *sc = &uti596_softc; /* device dependent data structure */ + struct ifnet * ifp = &sc->arpcom.ac_if; /* ifnet structure */ - int unitNumber; - char *unitName; + int unitNumber; + char *unitName; -#ifdef DBG_ATTACH + #ifdef DBG_ATTACH printk(("uti596_attach: begins\n")) -#endif + #endif /* The NIC is not started yet */ sc->started = 0; @@ -219,9 +1676,9 @@ int uti596_attach( ifp->if_softc = sc; sc->pScp = NULL; - /* Parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (pConfig, &unitName)) < 0) - return 0; + /* Parse driver name */ + if ((unitNumber = rtems_bsdnet_parse_driver_name (pConfig, &unitName)) < 0) + return 0; ifp->if_name = unitName; ifp->if_unit = unitNumber; @@ -232,13 +1689,16 @@ int uti596_attach( else ifp->if_mtu = ETHERMTU; - /* For now the ethernet address must be specified in the ifconfig structure, - * else FIXME so it can be read in from BBRAM at $FFFC1F2C (6 bytes) + /* Ethernet address can be specified in the ifconfig structure or + * it can be read in from BBRAM at $FFFC1F2C (6 bytes) * mvme167 manual p. 1-47 */ if ( pConfig->hardware_address) { memcpy (sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN); } + else { + memcpy (sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN); + } /* Assign requested receive buffer descriptor count */ if (pConfig->rbuf_count) @@ -253,9 +1713,9 @@ int uti596_attach( sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; /* Set up fields in the ifnet structure*/ - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_init = uti596_init; + ifp->if_init = uti596_init; ifp->if_ioctl = uti596_ioctl; ifp->if_start = uti596_start; ifp->if_output = ether_output; @@ -280,7 +1740,7 @@ int uti596_attach( * start the driver * * Algorithm: - * send an event to the tx task + * send an event to the tx task * set the if_flags * ***********************************************************************/ @@ -289,9 +1749,11 @@ static void uti596_start( ) { uti596_softc_ *sc = ifp->if_softc; -#ifdef DBG_INIT + + #ifdef DBG_START printk(("uti596_start: begins\n")) -#endif + #endif + rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); ifp->if_flags |= IFF_OACTIVE; } @@ -322,43 +1784,42 @@ void uti596_init( /* * Initialize the 82596 */ -#ifdef DBG_INIT + #ifdef DBG_INIT printk(("uti596_init: begins\nuti596_init: initializing the 82596...\n")) -#endif + #endif uti596_initialize_hardware(sc); /* * Start driver tasks */ -#ifdef DBG_INIT + #ifdef DBG_INIT printk(("uti596_init: starting driver tasks...\n")) -#endif + #endif sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, sc); sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, sc); sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096, uti596_resetDaemon, sc); -#ifdef DBG_INIT + #ifdef DBG_INIT printk(("uti596_init: After attach, status of board = 0x%x\n", sc->scb.status )) -#endif + #endif } /* * Enable receiver */ -#ifdef DBG_INIT + #ifdef DBG_INIT printk(("uti596_init: enabling the reciever...\n" )) -#endif + #endif sc->scb.command = RX_START; - i82596->chan_attn = 0x00000000; - UTI_WAIT_COMMAND_ACCEPTED(4000,"uti596_init: RX_START"); + uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); /* * Tell the world that we're running. */ ifp->if_flags |= IFF_RUNNING; -#ifdef DBG_INIT + #ifdef DBG_INIT printk(("uti596_init: completed.\n")) -#endif + #endif } /*********************************************************************** @@ -374,23 +1835,21 @@ void uti596_init( * clean-up all buffers ( RFD's et. al. ) * * - * - * ***********************************************************************/ /* static */ void uti596_stop( uti596_softc_ *sc ) { - struct ifnet *ifp = &sc->arpcom.ac_if; + struct ifnet *ifp = &sc->arpcom.ac_if; - ifp->if_flags &= ~IFF_RUNNING; + ifp->if_flags &= ~IFF_RUNNING; sc->started = 0; -#ifdef DBG_596 + #ifdef DBG_STOP printk(("uti596stop: %s: Shutting down ethercard, status was %4.4x.\n", uti596_softc.arpcom.ac_if.if_name, uti596_softc.scb.status)) -#endif + #endif printk(("Stopping interface\n")) sc->scb.command = CUC_ABORT | RX_ABORT; @@ -468,144 +1927,126 @@ void uti596_txDaemon( struct ether_header *eh; int frames = 0; -#ifdef DBG_INIT_3 - int i; -#endif -#ifdef DBG_596 + #ifdef DBG_RX printk(("uti596_rxDaemon: begin\n")) printk(("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd)) -#endif + #endif rtems_task_ident (0, 0, &tid); -#ifdef DBG_596 - printk(("uti596_rxDaemon: RX tid = 0x%x\n", tid)) -#endif + for(;;) { + /* + * Wait for packet. + */ + #ifdef DBG_RX + printk(("uti596_rxDaemon: Receiver sleeps\n")) + #endif + + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + + #ifdef DBG_RX + printk(("uti596_rxDaemon: Receiver wakes\n")) + #endif + /* + * While received frames are available. Note that the frame may be + * a fragment, so it is NOT a complete packet. + */ + pRfd = uti596_dequeue( &sc->pInboundFrameQueue); + while ( pRfd && + pRfd != I596_NULL && + pRfd -> stat & STAT_C ) + { - for(;;) { - /* - * Wait for packet. - */ -#ifdef DBG_596 - printk(("uti596_rxDaemon: Receiver sleeps\n")) -#endif + if ( pRfd->stat & STAT_OK) { /* a good frame */ + int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */ - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); + #ifdef DBG_RX + printk(("uti596_rxDaemon: Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len)) + #endif + frames++; -#ifdef DBG_596 - printk(("uti596_rxDaemon: Receiver wakes\n")) -#endif - /* - * While received frames are available. Note that the frame may be - * a fragment, so it is NOT a complete packet. - */ - pRfd = uti596dequeue( &sc->pInboundFrameQueue); - while ( pRfd && - pRfd != I596_NULL && - pRfd -> stat & STAT_C ) - { - -#ifdef DBG_INIT_3 - printk(("\nuti596_rxDaemon: Received packet:\n")) - print_eth( pRfd->data); -#endif - if ( pRfd->stat & STAT_OK) { /* a good frame */ - int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */ - -#ifdef DBG_596 - printk(("uti596_rxDaemon: Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len)) -#endif - frames++; - - /* - * Allocate an mbuf to give to the stack - * The format of the data portion of the RFD is: - * <ethernet header, payload>. - * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596. - * This is to be optimized later.... should not have to memcopy! - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - - m->m_pkthdr.rcvif = ifp; - /* move everything into an mbuf */ - memcpy(m->m_data, - pRfd->data, - pkt_len); - - m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4; - - /* move the header to an mbuf */ - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - -#ifdef DBG_596 - printk(("uti596_rxDaemon: m->m_ext: %p pRfd -> data: %p\n", - m->m_ext, pRfd->data)) -#endif -#ifdef DBG_INIT_3 - printk(("uti596_rxDaemon: mbuf contains:\n")) - print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header))); - for ( i = 0; i<20; i++) { - printk((".")) - } -#endif - ether_input (ifp, eh, m); - - } /* end if STAT_OK */ + /* + * Allocate an mbuf to give to the stack + * The format of the data portion of the RFD is: + * <ethernet header, payload>. + * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596. + * This is to be optimized later.... should not have to memcopy! + */ + MGETHDR(m, M_WAIT, MT_DATA); + MCLGET(m, M_WAIT); + + m->m_pkthdr.rcvif = ifp; + /* move everything into an mbuf */ + memcpy(m->m_data, pRfd->data, pkt_len); + m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4; + + /* move the header to an mbuf */ + eh = mtod (m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + + #ifdef DBG_PACKETS + { + int i; + printk(("uti596_rxDaemon: mbuf contains:\n")) + print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header))); + for ( i = 0; i<20; i++) { + printk((".")) + } + } + #endif + + ether_input (ifp, eh, m); + + } /* end if STAT_OK */ + + else { + /* + * A bad frame is present: Note that this could be the last RFD! + */ + #ifdef DBG_RX + printk(("uti596_rxDaemon: Bad frame\n")) + #endif + /* + * FIX ME: use the statistics from the SCB + */ + sc->stats.rx_errors++; + if ((sc->scb.pRfd->stat) & 0x0001) + sc->stats.collisions++; + if ((sc->scb.pRfd->stat) & 0x0080) + sc->stats.rx_length_errors++; + if ((sc->scb.pRfd->stat) & 0x0100) + sc->stats.rx_over_errors++; + if ((sc->scb.pRfd->stat) & 0x0200) + sc->stats.rx_fifo_errors++; + if ((sc->scb.pRfd->stat) & 0x0400) + sc->stats.rx_frame_errors++; + if ((sc->scb.pRfd->stat) & 0x0800) + sc->stats.rx_crc_errors++; + if ((sc->scb.pRfd->stat) & 0x1000) + sc->stats.rx_length_errors++; + } - else { - /* - * A bad frame is present: Note that this could be the last RFD! - */ -#ifdef DBG_596 - printk(("uti596_rxDaemon: Bad frame\n")) -#endif - /* - * FIX ME: use the statistics from the SCB - */ - sc->stats.rx_errors++; - if ((sc->scb.pRfd->stat) & 0x0001) - sc->stats.collisions++; - if ((sc->scb.pRfd->stat) & 0x0080) - sc->stats.rx_length_errors++; - if ((sc->scb.pRfd->stat) & 0x0100) - sc->stats.rx_over_errors++; - if ((sc->scb.pRfd->stat) & 0x0200) - sc->stats.rx_fifo_errors++; - if ((sc->scb.pRfd->stat) & 0x0400) - sc->stats.rx_frame_errors++; - if ((sc->scb.pRfd->stat) & 0x0800) - sc->stats.rx_crc_errors++; - if ((sc->scb.pRfd->stat) & 0x1000) - sc->stats.rx_length_errors++; - } + UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n") - UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n") + _ISR_Disable(level); + uti596_supplyFD ( pRfd ); /* Return RFD to RFA. */ + _ISR_Enable(level); -#ifdef DBG_SUPPLY_FD - printk(("uti596_rxDaemon: Supply FD Starting\n")) -#endif - _ISR_Disable(level); - uti596supplyFD ( pRfd ); /* Return RFD to RFA. */ - _ISR_Enable(level); -#ifdef DBG_SUPPLY_FD - printk(("uti596_rxDaemon: Supply FD Complete\n")) -#endif - pRfd = uti596dequeue( &sc->pInboundFrameQueue); /* grab next frame */ + pRfd = uti596_dequeue( &sc->pInboundFrameQueue); /* grab next frame */ - } /* end while */ - } /* end for(;;) */ + } /* end while */ + } /* end for() */ -#ifdef DBG_596 - printk (("uti596_rxDaemon: frames ... %d\n", frames)) -#endif + #ifdef DBG_RX + printk (("uti596_rxDaemon: frames ... %d\n", frames)) + #endif } + /*********************************************************************** * Function: void uti596_resetDaemon * @@ -634,31 +2075,29 @@ void uti596_resetDaemon( sc->stats.nic_reset_count++; /* Reinitialize the LANC */ rtems_bsdnet_semaphore_obtain (); - uti596reset(); + uti596_reset(); rtems_bsdnet_semaphore_release (); } } - /*********************************************************************** - * Function: uti596_DynamicInterruptHandler - * - * Description: - * This is the interrupt handler for the uti596 board - * - * Algorithm: - * - ***********************************************************************/ +/*********************************************************************** + * Function: uti596_DynamicInterruptHandler + * + * Description: + * This is the interrupt handler for the uti596 board + * + ***********************************************************************/ /* static */ rtems_isr uti596_DynamicInterruptHandler( rtems_vector_number irq ) { -#ifdef DEBUG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: begins")) -#endif + #endif - UTI_WAIT_COMMAND_ACCEPTED(20000,"****ERROR:on ISR entry"); + uti596_wait (&uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT); scbStatus = uti596_softc.scb.status & 0xf000; @@ -676,14 +2115,14 @@ void uti596_resetDaemon( /* Send the CA signal to acknowledge interrupt */ uti596_softc.scb.command = scbStatus; - i82596->chan_attn = 0x00000000; + uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); if( uti596_softc.resetDone ) { /* stack is attached */ - UTI_WAIT_COMMAND_ACCEPTED(20000,"****ERROR:ACK"); + uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); } else { - /* printk(("***INFO: ACK'd w/o processing. status = %x\n", scbStatus)) */ + printk(("***INFO: ACK'd w/o processing. status = %x\n", scbStatus)) return; } } @@ -693,43 +2132,38 @@ void uti596_resetDaemon( } - if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ){ - printk_time(); + if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ) { printk(("\n*****ERROR: Command Complete, and CNA available: 0x%x\nResetting...", scbStatus)) uti596_softc.nic_reset = 1; return; } if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) ) { - printk_time(); printk(("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus)) uti596_softc.nic_reset = 1; return; } if ( scbStatus & SCB_CUS_SUSPENDED ) { - printk_time(); printk(("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus)) uti596_softc.nic_reset = 1; return; } if ( scbStatus & RU_SUSPENDED ) { - printk_time(); printk(("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus)) uti596_softc.nic_reset = 1; return; } if ( scbStatus & SCB_STAT_RNR ) { - printk_time(); printk(("\n*****WARNING: RNR %x\n",scbStatus)) if (uti596_softc.pBeginRFA != I596_NULL) { - printk(("*****INFO: RFD cmd: %x status:%x\n", uti596_softc.pBeginRFA->cmd, - uti596_softc.pBeginRFA->stat)) + printk(("*****INFO: RFD cmd: %x status:%x\n", uti596_softc.pBeginRFA->cmd, + uti596_softc.pBeginRFA->stat)) } else { - printk(("*****WARNING: RNR condition with NULL BeginRFA\n")) + printk(("*****WARNING: RNR condition with NULL BeginRFA\n")) } } @@ -740,37 +2174,37 @@ void uti596_resetDaemon( if ( scbStatus & SCB_STAT_FR ) { uti596_softc.rxInterrupts++; -#ifdef DBG_FR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: Frame received\n")) -#endif + #endif if ( uti596_softc.pBeginRFA == I596_NULL || - !( uti596_softc.pBeginRFA -> stat & STAT_C)) { - dump_scb(); - uti596_softc.nic_reset = 1; + !( uti596_softc.pBeginRFA -> stat & STAT_C)) { + uti596_dump_scb(); + uti596_softc.nic_reset = 1; } else { while ( uti596_softc.pBeginRFA != I596_NULL && ( uti596_softc.pBeginRFA -> stat & STAT_C)) { -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: pBeginRFA != NULL\n")) -#endif + #endif count_rx ++; if ( count_rx > 1) { printk(("****WARNING: Received 2 frames on 1 interrupt \n")) - } + } /* Give Received Frame to the ULCS */ uti596_softc.countRFD--; if ( uti596_softc.countRFD < 0 ) { printk(("ISR: Count < 0 !!! count == %d, beginRFA = %p\n", uti596_softc.countRFD, uti596_softc.pBeginRFA)) - } + } uti596_softc.stats.rx_packets++; /* the rfd next link is stored with upper and lower words swapped so read it that way */ pIsrRfd = (i596_rfd *) word_swap ((unsigned long)uti596_softc.pBeginRFA->next); /* the append destroys the link */ - uti596append( &uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA ); + uti596_append( &uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA ); /* * if we have just received the a frame in the last unknown RFD, @@ -781,19 +2215,19 @@ void uti596_resetDaemon( uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD = I596_NULL; } -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: Wake %#x\n",uti596_softc.rxDaemonTid)) -#endif + #endif sc = rtems_event_send(uti596_softc.rxDaemonTid, INTERRUPT_EVENT); if ( sc != RTEMS_SUCCESSFUL ) { rtems_panic("Can't notify rxDaemon: %s\n", rtems_status_text (sc)); } -#ifdef DBG_RAW_ISR + #ifdef DBG_ISR else { printk(("uti596_DynamicInterruptHandler: Rx Wake: %#x\n",uti596_softc.rxDaemonTid)) - } -#endif + } + #endif uti596_softc.pBeginRFA = pIsrRfd; } /* end while */ @@ -804,7 +2238,7 @@ void uti596_resetDaemon( if ( uti596_softc.pLastUnkRFD == I596_NULL && uti596_softc.countRFD != 0 ) { printk(("Last Unk is NULL, BeginRFA is null, and count == %d\n", uti596_softc.countRFD)) - } + } uti596_softc.pEndRFA = I596_NULL; if ( uti596_softc.countRFD != 0 ) { printk(("****ERROR:Count is %d, but begin ptr is NULL\n", @@ -819,18 +2253,18 @@ void uti596_resetDaemon( * a command is completed */ if ( scbStatus & SCB_STAT_CX ) { -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: CU\n")) -#endif + #endif pIsrCmd = uti596_softc.pCmdHead; /* For ALL completed commands */ if ( pIsrCmd != I596_NULL && pIsrCmd->status & STAT_C ) { -#ifdef DBG_RAW_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: pIsrCmd != NULL\n")) -#endif + #endif /* Adjust the command block list */ uti596_softc.pCmdHead = (i596_cmd *) word_swap ((unsigned long)pIsrCmd->next); @@ -846,21 +2280,20 @@ void uti596_resetDaemon( switch ( pIsrCmd->command & 0x7) { case CmdConfigure: - /* printk(("****INFO:Configure OK\n")) */ uti596_softc.cmdOk = 1; break; case CmdDump: -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: dump!\n")) -#endif + #endif uti596_softc.cmdOk = 1; break; case CmdDiagnose: -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: diagnose!\n")) -#endif + #endif uti596_softc.cmdOk = 1; break; @@ -871,14 +2304,14 @@ void uti596_resetDaemon( } else { printk(("****ERROR:SET ADD FAILED\n")) - } + } break; case CmdTx: UTI_596_ASSERT(uti596_softc.txDaemonTid, "****ERROR:Null txDaemonTid\n") -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: wake TX:0x%x\n",uti596_softc.txDaemonTid)) -#endif + #endif if ( uti596_softc.txDaemonTid ) { /* Ensure that the transmitter is present */ sc = rtems_event_send (uti596_softc.txDaemonTid, @@ -888,11 +2321,11 @@ void uti596_resetDaemon( printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n", uti596_softc.txDaemonTid, rtems_status_text (sc) )) } -#ifdef DBG_RAW_ISR + #ifdef DBG_ISR else { printk(("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid)) } -#endif + #endif } break; @@ -902,25 +2335,25 @@ void uti596_resetDaemon( break; case CmdTDR: { - unsigned long status = *( (unsigned long *)pIsrCmd)+1; - printk(("****ERROR:TDR?!\n")) - - if (status & STAT_C) { - /* mark the TDR command successful */ - uti596_softc.cmdOk = 1; - } - else { - if (status & 0x4000) { - printk(("****WARNING:Transceiver problem.\n")) - } - if (status & 0x2000) { - printk(("****WARNING:Termination problem.\n")) - } - if (status & 0x1000) { - printk(("****WARNING:Short circuit.\n")) - /* printk(("****INFO:Time %ld.\n", status & 0x07ff)) */ - } - } + unsigned long status = *( (unsigned long *)pIsrCmd)+1; + printk(("****ERROR:TDR?!\n")) + + if (status & STAT_C) { + /* mark the TDR command successful */ + uti596_softc.cmdOk = 1; + } + else { + if (status & 0x4000) { + printk(("****WARNING:Transceiver problem.\n")) + } + if (status & 0x2000) { + printk(("****WARNING:Termination problem.\n")) + } + if (status & 0x1000) { + printk(("****WARNING:Short circuit.\n")) + /* printk(("****INFO:Time %ld.\n", status & 0x07ff)) */ + } + } } break; @@ -942,7 +2375,6 @@ void uti596_resetDaemon( if ( pIsrCmd != I596_NULL ) { /* The command MAY be NULL from a RESET */ /* Reset the ethernet card, and wake the transmitter (if necessary) */ - printk_time(); printk(("****INFO: Request board reset ( tx )\n")) uti596_softc.nic_reset = 1; if ( uti596_softc.txDaemonTid) { @@ -950,13 +2382,15 @@ void uti596_resetDaemon( sc = rtems_event_send (uti596_softc.txDaemonTid, INTERRUPT_EVENT); if ( sc != RTEMS_SUCCESSFUL ) { - printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n",uti596_softc.txDaemonTid, rtems_status_text (sc) )) - } -#ifdef DBG_RAW_ISR + printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n", + uti596_softc.txDaemonTid, rtems_status_text (sc) )) + } + #ifdef DBG_ISR else { - printk(("uti596_DynamicInterruptHandler: ****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid)) - } -#endif + printk(("uti596_DynamicInterruptHandler: ****INFO:Tx wake: %#x\n", + uti596_softc.txDaemonTid)) + } + #endif } } } @@ -970,9 +2404,10 @@ void uti596_resetDaemon( */ if ( uti596_softc.started ) { if ( scbStatus & SCB_STAT_RNR ) { -#ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: INFO:RNR: status %#x \n", uti596_softc.scb.status )) -#endif + #ifdef DBG_ISR + printk(("uti596_DynamicInterruptHandler: INFO:RNR: status %#x \n", + uti596_softc.scb.status )) + #endif /* * THE RECEIVER IS OFF! */ @@ -990,7 +2425,7 @@ void uti596_resetDaemon( if ( uti596_softc.pEndRFA != I596_NULL ) { /* check added feb24. */ -#ifdef DEBUG_RFA + #ifdef DBG_ISR if ((i596_rfd *)word_swap((unsigned long)uti596_softc.pEndRFA->next) != uti596_softc.pLastUnkRFD) { printk(("***ERROR:UNK: %p not end->next: %p, end: %p\n", uti596_softc.pLastUnkRFD, @@ -1000,10 +2435,10 @@ void uti596_resetDaemon( uti596_softc.countRFD)) printk(("\n\n")) } -#endif + #endif uti596_softc.pEndRFA -> next = I596_NULL; /* added feb 16 */ } - uti596append( &uti596_softc.pSavedRfdQueue, uti596_softc.pLastUnkRFD ); + uti596_append( &uti596_softc.pSavedRfdQueue, uti596_softc.pLastUnkRFD ); uti596_softc.savedCount++; uti596_softc.pEndSavedQueue = uti596_softc.pLastUnkRFD; uti596_softc.countRFD--; /* It was not in the RFA */ @@ -1012,12 +2447,12 @@ void uti596_resetDaemon( * with the chip. */ if ( uti596_softc.pBeginRFA == uti596_softc.pLastUnkRFD ) { -#ifdef DEBUG_RFA + #ifdef DBG_ISR if ( uti596_softc.countRFD != 0 ) { printk(("****INFO:About to set begin to NULL, with count == %d\n\n", uti596_softc.countRFD )) } -#endif + #endif uti596_softc.pBeginRFA = I596_NULL; UTI_596_ASSERT(uti596_softc.countRFD == 0, "****ERROR:Count must be zero here!\n") } @@ -1034,23 +2469,23 @@ void uti596_resetDaemon( /* entries to add */ if ( uti596_softc.pBeginRFA == I596_NULL ) { /* add at beginning to list */ -#ifdef DEBUG_RFA + #ifdef DBG_ISR if(uti596_softc.countRFD != 0) { printk(("****ERROR:Begin pointer is NULL, but count == %d\n", uti596_softc.countRFD)) } -#endif + #endif uti596_softc.pBeginRFA = uti596_softc.pSavedRfdQueue; uti596_softc.pEndRFA = uti596_softc.pEndSavedQueue; uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */ } else { -#ifdef DEBUG_RFA + #ifdef DBG_ISR if ( uti596_softc.countRFD <= 0) { printk(("****ERROR:Begin pointer is not NULL, but count == %d\n", uti596_softc.countRFD)) } -#endif + #endif UTI_596_ASSERT( uti596_softc.pEndRFA != I596_NULL, "****WARNING: END RFA IS NULL\n") UTI_596_ASSERT( uti596_softc.pEndRFA->next == I596_NULL, "****ERROR:END RFA -> next must be NULL\n") @@ -1058,11 +2493,11 @@ void uti596_resetDaemon( uti596_softc.pEndRFA->cmd &= ~CMD_EOL; /* clear the end of list */ uti596_softc.pEndRFA = uti596_softc.pEndSavedQueue; uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */ -#ifdef DEBUG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: count... %d, saved ... %d \n", uti596_softc.countRFD, uti596_softc.savedCount)) -#endif + #endif } /* printk(("Isr: countRFD = %d\n",uti596_softc.countRFD)) */ uti596_softc.countRFD += uti596_softc.savedCount; @@ -1070,18 +2505,17 @@ void uti596_resetDaemon( uti596_softc.savedCount = 0; } -#ifdef DBG_596_RFD + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: The list starts here %p\n",uti596_softc.pBeginRFA )) -#endif + #endif if ( uti596_softc.countRFD > 1) { - printk_time(); printk(("****INFO: pBeginRFA -> stat = 0x%x\n",uti596_softc.pBeginRFA -> stat)) printk(("****INFO: pBeginRFA -> cmd = 0x%x\n",uti596_softc.pBeginRFA -> cmd)) uti596_softc.pBeginRFA -> stat = 0; UTI_596_ASSERT(uti596_softc.scb.command == 0, "****ERROR:scb command must be zero\n") uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; - uti596_softc.scb.Rfd_val = word_swap((unsigned long)uti596_softc.pBeginRFA); + uti596_softc.scb.rfd_pointer = word_swap((unsigned long)uti596_softc.pBeginRFA); /* start RX here */ printk(("****INFO: ISR Starting receiver\n")) uti596_softc.scb.command = RX_START; /* should this also be CU start? */ @@ -1090,9 +2524,9 @@ void uti596_resetDaemon( } /* end stat_rnr */ } /* end if receiver started */ -#ifdef DBG_ISR + #ifdef DBG_ISR printk(("uti596_DynamicInterruptHandler: X\n")) -#endif + #endif count_rx=0; @@ -1106,6 +2540,7 @@ void uti596_resetDaemon( return; } + /*********************************************************************** * Function: uti596_ioctl * @@ -1113,8 +2548,6 @@ void uti596_resetDaemon( * driver ioctl function * handles SIOCGIFADDR, SIOCSIFADDR, SIOCSIFFLAGS * - * Algorithm: - * ***********************************************************************/ static int uti596_ioctl( @@ -1125,9 +2558,9 @@ static int uti596_ioctl( uti596_softc_ *sc = ifp->if_softc; int error = 0; -#ifdef DBG_INIT + #ifdef DBG_IOCTL printk(("uti596_ioctl: begins\n", sc->pScp)) -#endif + #endif switch (command) { case SIOCGIFADDR: @@ -1176,6 +2609,7 @@ static int uti596_ioctl( return error; } + /*********************************************************************** * Function: uti596_stats * @@ -1191,7 +2625,7 @@ void uti596_stats( uti596_softc_ *sc ) { - printf("CPU Reports:\n"); + printf ("CPU Reports:\n"); printf (" Tx raw send count:%-8lu", sc->rawsndcnt); printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); printf (" Tx Interrupts:%-8lu\n", sc->txInterrupts); @@ -1219,1221 +2653,143 @@ void uti596_stats( printf (" NIC resets: %-8u\n", sc->stats.nic_reset_count); - printf(" NIC reports\n"); + printf (" NIC reports\n"); - dump_scb(); + #ifdef DBG_STAT + uti596_dump_scb(); + #endif } -/*********************************************************************** - *************************** LOCAL ROUTINES **************************** - ***********************************************************************/ -/*********************************************************************** - * Function: void uti596_initialize_hardware - * - * Description: - ***********************************************************************/ -void uti596_initialize_hardware( - uti596_softc_ *sc -) -{ - int boguscnt = 1000; - rtems_isr_entry dummy; +/************************ PACKET DEBUG ROUTINES ************************/ - printk(("uti596_initialize_hardware: begins\n")) - - pccchip2->LANC_berr_ctl = 0x40; /* Enable snooping */ - - /* reset the board */ - i82596->port_lower = 0x0000; /* Each Port access must consist of two 16-bit writes */ - i82596->port_upper = 0x0000; - - /* allocate enough memory for the Scp block to be aligned on 16 bit boundary */ - uti596_softc.pScp = (i596_scp *) calloc(1,sizeof(struct i596_scp) + 0xf); - -#ifdef DBG_INIT - printk(("uti596_initialize_hardware: Scp address initially %p\n", sc->pScp)) -#endif - - /* align the block */ - sc->pScp = (i596_scp *) - ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0); - -#ifdef DBG_INIT - printk(("uti596_initialize_hardware: change scp address to : %p\n",sc->pScp)) -#endif - - /* change the scp address */ -#ifdef DBG_INIT - printk(("uti596_initialize_hardware: Change the SCP address\n")) -#endif - - /* reset the board */ - i82596->port_lower = 0x0000; - i82596->port_upper = 0x0000; - - /* supply the Scp address - * Lower Command Word D31-D16; Upper Command Word D15-D0 - */ - i82596->port_lower = (((int)sc->pScp) & 0xfff0) | 0x0002; - i82596->port_upper = (((int)sc->pScp) >> 16 ) & 0xffff; - - - /* write the SYSBUS: interrupt pin active high, LOCK disabled, - * internal triggering, linear mode - */ - sc->pScp->sysbus = word_swap(0x00540000); - - /* provide the iscp to the scp, keep a pointer for our use */ - sc->pScp->iscp_val = word_swap((unsigned long)&sc->iscp); - sc->pScp->iscp = &sc->iscp; - - /* provide the scb to the iscp, keep a pointer for our use */ - sc->iscp.scb_val = word_swap((unsigned long)&sc->scb); - sc->iscp.scb = &sc->scb; - - /* set the busy flag in the iscp */ - sc->iscp.stat = word_swap(0x00000001); - - /* the command block list (CBL) is empty */ - sc->scb.Cmd_val = (unsigned long) I596_NULL; /* all 1's */ - sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ - -#ifdef DBG_596 - printk(("uti596_initialize_hardware: Starting i82596.\n")) -#endif - - /* Issue CA: pass the scb address to the 596 */ - i82596->chan_attn = 0x00000000; - - UTI_WAIT_TICKS - - /* Wait for the 596 to read the SCB address and clear 'stat' */ - while (sc->iscp.stat) { - if (--boguscnt == 0) { - printk(("initialize_hardware: timed out with status %4.4lx\n", - sc->iscp.stat )) - break; - } - } /* end while */ - - /* clear the scb command word */ - sc->scb.command = 0; - - /* - * Configure interrupt control in PCCchip2 - */ - pccchip2->LANC_error = 0xff; /* clear status register */ - pccchip2->LANC_int_ctl = 0x5d; /* lvl 5, enabled, edge-sensitive rising */ - pccchip2->LANC_berr_ctl = 0x5d; /* bus error: lvl 5, enabled, snoop control - * will supply dirty data and leave dirty data - * on read access and sink any data on write - */ - - /* - * Install the interrupt handler - * calls rtems_interrupt_catch - */ - dummy = (rtems_isr_entry) set_vector( uti596_DynamicInterruptHandler, 0x57, 1 ); - - - /* Initialize the 82596 memory */ - uti596_initMem(sc); - -#ifdef DBG_INIT - printk(("uti596_initialize_hardware: After attach, status of board = 0x%x\n", sc->scb.status )) -#endif -} - -/*********************************************************************** - * Function: uti596_initMem - * - * Description: - * creates the necessary descriptors for the - * uti596 board, hooks the interrupt, and starts the board. - * Assumes that interrupts are hooked. - * - * Algorithm: - * - ***********************************************************************/ - -void uti596_initMem( - uti596_softc_ * sc -) -{ - int i,count; - i596_tbd *pTbd, *pPrev; - -#ifdef DBG_INIT - printk(("uti596_initMem: begins\n")) -#endif - - sc->resetDone = 0; - - /* - * Set up receive frame area (RFA) - */ -#ifdef DBG_INIT - printk(("uti596_initMem: Initializing the RFA...\n")) -#endif - i = uti596_initRFA( sc->rxBdCount ); - if ( i < sc->rxBdCount ) { - printk(("init_rfd: only able to allocate %d receive frame descriptors\n", i)) - } - - sc->scb.Rfd_val = word_swap((unsigned long)sc->pBeginRFA); - sc->scb.pRfd = sc->pBeginRFA; - - /* - * Diagnose the health of the board - * send the CU a diagnostic command - */ -#ifdef DBG_INIT - printk(("uti596_initMem: Running diagnostics...\n")) -#endif - uti596Diagnose(1); - - /* - * Configure the 82596 - * send the CU a configure command with our initial setup - */ -#ifdef DBG_INIT - printk(("uti596_initMem: Configuring...\n")) -#endif - sc->set_conf.cmd.command = CmdConfigure; - memcpy (sc->set_conf.data, uti596initSetup, 14); - uti596addPolledCmd( (i596_cmd *) &sc->set_conf); - - /* Poll for successful command completion */ - count = 2000; - while( !( sc->set_conf.cmd.status & STAT_C ) && --count ) { - printk((".")) - } - - if ( count ) { - printk(("Configure OK, count = %d\n",count)) - } - else { - printk(("***Configure failed\n")) - } - /* - * Set up the Internet Address - * send the CU an IA-setup command - */ -#ifdef DBG_INIT - printk(("uti596_initMem: Setting Address...\n")) -#endif - sc->set_add.cmd.command = CmdSASetup; - for ( i=0; i<6; i++) { - sc->set_add.data[i]=sc->arpcom.ac_enaddr[i]; -#ifdef DBG_INIT - printk(("uti596_initMem: copying byte %d: 0x%x\n", i, sc->set_add.data[i])) -#endif - } - sc->cmdOk = 0; - uti596addPolledCmd((i596_cmd *)&sc->set_add); - - /* Poll for successful command completion */ - count = 2000; - while( !(sc->set_add.cmd.status & STAT_C ) && --count) { - printk((".")) - } - - if ( count ) { - printk(("Set Address OK, count= %d\n",count)) - } - else { - printk(("Set Address Failed\n")) - } -#ifdef DBG_INIT - printk(( "uti596_initMem: After initialization, status and command: 0x%x, 0x%x\n", - sc->scb.status, sc->scb.status)) -#endif +#ifdef DBG_PACKETS - /* - *Initialize transmit buffer descriptors - */ -#ifdef DBG_INIT - printk(( "uti596_initMem:Initializing TBDs...\n")) -#endif - sc->pLastUnkRFD = I596_NULL; - sc->pTxCmd = (i596_tx *) calloc (1,sizeof (struct i596_tx) ); - sc->pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); - sc->pTxCmd->pTbd = (i596_tbd *) word_swap ((unsigned long) sc->pTbd); - sc->pTxCmd->cmd.command = CMD_FLEX|CmdTx; - sc->pTxCmd->pad = 0; - sc->pTxCmd->count = 0; /* all bytes are in list of TBD's */ - - pPrev = pTbd = sc->pTbd; - - /* Allocate a linked list of tbd's each with it's 'next' field written - * with upper and lower words swapped (for big endian), and mark the end. - */ - for ( i=0; i<sc->txBdCount; i++) { - pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); - pPrev->next = (i596_tbd *) word_swap ((unsigned long) pTbd); - pPrev = pTbd; - } - pTbd->next = I596_NULL; - - /* Padding used to fill short tx frames */ - memset ( &sc->zeroes, 0, 64); - -#ifdef DBG_596 - printk(( "uti596_initMem: After receiver start, status and command: 0x%x, 0x%x\n", - sc->scb.status, sc->scb.status)) -#endif - -#ifdef DBG_596 - printk(("uti596_initMem allows ISR's\n")) -#endif - sc->resetDone = 1; /* now need ISR */ -} - -/*********************************************************************** - * Function: uti596initRFA(int num) - * - * Description: - * attempts to allocate and initialize ( chain together ) - * the requested number of FD's - * - * Algorithm: - * - ***********************************************************************/ - -int uti596_initRFA( int num ) -{ - i596_rfd *pRfd; - int i = 0; - -#ifdef DBG_596 - printk(("uti596_initRFA: begins\n Requested frame descriptors ... %d.\n", num)) -#endif - - /* - * Create the first RFD in the RFA - */ - pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd)); - if ( !pRfd ) { - printk(("Can't allocate first buffer.\n")) - return 0; - } - else { - uti596_softc.countRFD = 1; - uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; - printk(("First Rfd allocated @: %p\n", - uti596_softc.pBeginRFA)) - } - - /* Create remaining RFAs */ - for (i = 1; i < num; i++) { - pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd) ); - if ( pRfd != NULL ) { - uti596_softc.countRFD++; /* update count */ - uti596_softc.pEndRFA->next = - (i596_rfd *) word_swap ((unsigned long) pRfd); /* write the link */ - uti596_softc.pEndRFA = pRfd; /* move the end */ -#ifdef DBG_596_RFA - printk(("uti596_initRFA: Allocated RFD @ %p\n", pRfd)) -#endif - } - else { - printk(("Can't allocate all buffers: only %d allocated\n", i)) - break; - } - } /* end for */ - - uti596_softc.pEndRFA->next = I596_NULL; - UTI_596_ASSERT(uti596_softc.countRFD == RX_BUF_COUNT,"INIT:WRONG RFD COUNT\n" ) - -#ifdef DBG_596_RFA - printk (("uti596_initRFA: Head of RFA is buffer %p \n\ - uti596_initRFA: End of RFA is buffer %p \n", - uti596_softc.pBeginRFA, - uti596_softc.pEndRFA )) -#endif - /* Initialize the RFD's */ - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = (i596_rfd *) word_swap ((unsigned long)pRfd->next) ) { - - pRfd->cmd = 0x0000; - pRfd->stat = 0x0000; - pRfd->pRbd = I596_NULL; - pRfd->count = 0; /* number of bytes in buffer: usually less than size */ - pRfd->size = 1532; /* was 1532; buffer size ( All RBD ) */ - if ( pRfd -> data == NULL ) { - printk(("Can't allocate the RFD data buffer\n")) - } - } - - /* mark the last RFD as the last one in the RDL */ - uti596_softc.pEndRFA -> cmd = CMD_EOL; - - uti596_softc.pSavedRfdQueue = - uti596_softc.pEndSavedQueue = I596_NULL; /* initially empty */ - - uti596_softc.savedCount = 0; - - uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */ - - return (i); /* the number of allocated buffers */ -} - - /*********************************************************************** - * Function: uti596addPolledCmd - * - * Description: - * This routine issues a single command then polls for it's - * completion. - * - * Algorithm: - * Give the command to the driver. ( CUC_START is ALWAYS required ) - * Poll for completion. - * - ***********************************************************************/ - -void uti596addPolledCmd( - i596_cmd *pCmd -) -{ - - #ifdef DBG_596 - printk(("uti596addPolledCmd: Adding command 0x%x\n", pCmd -> command )) - #endif - -#ifdef DBG_POLLED_CMD - - switch ( pCmd -> command & 0x7 ) { /* check bottom 3 bits */ - case CmdConfigure: - printk(("uti596addPolledCmd: Configure Command 0x%x\n", pCmd->command)) - break; - case CmdSASetup: - printk(("uti596addPolledCmd: Set CMDress Command 0x%x\n", pCmd->command)) - break; - case CmdMulticastList: - printk(("uti596addPolledCmd: Multi-cast list 0x%x\n", pCmd->command)) - break; - case CmdNOp: - printk(("uti596addPolledCmd: NO op 0x%x\n", pCmd->command)) - break; - case CmdTDR: - printk(("uti596addPolledCmd: TDR 0x%x\n", pCmd->command)) - break; - case CmdDump: - printk(("uti596addPolledCmd: Dump 0x%x\n", pCmd->command)) - break; - case CmdDiagnose: - printk(("uti596addPolledCmd: Diagnose 0x%x\n", pCmd->command)) - break; - case CmdTx: - break; - default: - printk(("PolledCMD: ****Unknown Command encountered 0x%x\n", pCmd->command)) - break; - } /* end switch */ - -#endif - - pCmd->status = 0; - pCmd->command |= CMD_EOL ; /* only command in list*/ - - pCmd->next = I596_NULL; - - UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: wait prev"); - - uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; - uti596_softc.scb.Cmd_val = word_swap((unsigned long)pCmd); - uti596_softc.scb.command = CUC_START; - i82596->chan_attn = 0x00000000; - - UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: start"); - uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL; - uti596_softc.scb.Cmd_val = (unsigned long) I596_NULL; - -#ifdef DBG_POLLED_CMD - printk(("uti596addPolledCmd: Scb status & command 0x%x 0x%x\n", - uti596_softc.scb.status, - uti596_softc.scb.command )) -#endif -} - - -/*********************************************************************** - * Function: void uti596Diagnose - * - * Description: - * - ***********************************************************************/ -void uti596Diagnose( - int verbose -) -{ - i596_cmd diagnose; - int count=10000; - - diagnose.command = CmdDiagnose; - diagnose.status = 0; - uti596addPolledCmd(&diagnose); - while( !( diagnose.status & STAT_C ) && count ) { - if(verbose) { - printk((".")) - } - count --; - } - if(verbose) { - printk(("Status diagnostic: 0xa000 is a success ... 0x%2.2x\n", diagnose.status)) - } -} - -/*********************************************************************** - * Function: void uti596dequeue - * - * Description: - * removes an RFD from the received frame queue, - * - * Algorithm: - * - ***********************************************************************/ -i596_rfd * uti596dequeue( - i596_rfd ** ppQ -) -{ - ISR_Level level; - - i596_rfd * pRfd; - _ISR_Disable(level); - - /* invalid address, or empty queue or emptied queue */ - if( ppQ == NULL || *ppQ == NULL || *ppQ == I596_NULL) { - _ISR_Enable(level); - return I596_NULL; - } - - pRfd = *ppQ; /* The dequeued buffer */ - *ppQ = (i596_rfd *) \ - word_swap ((unsigned long) pRfd->next); /* advance the queue pointer */ - pRfd->next = I596_NULL; /* unlink the rfd being returned */ - - _ISR_Enable(level); - return pRfd; -} - -/*********************************************************************** - * Function: void uti596reset +/* + * dumpQ * - * Description: - ***********************************************************************/ -void uti596reset( void ) + * Dumps frame queues for debugging + */ +static void dumpQ( void ) { - int i,count; - uti596_softc_ *sc = &uti596_softc; - /* i596_rfd * pRfd; */ - -#ifdef DBG_RESET - printk(("uti596reset: begin\n")) -#endif - - sc->resetDone = 0; - UTI_WAIT_COMMAND_ACCEPTED(10000, "reset: wait for previous command complete"); - uti596_reset_hardware(&uti596_softc); /* reset the ethernet hardware. must re-config */ - -#ifdef DBG_RESET - uti596Diagnose(1); -#endif - - sc->set_conf.cmd.command = CmdConfigure; - memcpy (sc->set_conf.data, uti596initSetup, 14); - uti596addPolledCmd( (i596_cmd *) &sc->set_conf); - - /* POLL */ - count = 2000; - while( !( sc->set_conf.cmd.status & STAT_C ) && --count ) { - printk((".")) - } - - if ( count ) { - printk(("Configure OK, count = %d\n",count)) - } - else { - printk(("reset: Configure failed\n")) - } - - /* - * Create the IA setup command - */ - -#ifdef DBG_RESET - printk(("uti596reset: Setting Address\n")) -#endif - sc->set_add.cmd.command = CmdSASetup; - for ( i=0; i<6; i++) { - sc->set_add.data[i]=sc->arpcom.ac_enaddr[i]; - } - sc->cmdOk = 0; - uti596addPolledCmd((i596_cmd *)&sc->set_add); + i596_rfd *pRfd; - count = 2000; - while( !(sc->set_add.cmd.status & STAT_C ) && --count) { - printk((".")) - } - if ( count ) { - printk(("Reset Set Address OK, count= %d\n",count)) - } - else { - printk(("Reset Set Address Failed\n")) + printk(("savedQ:\n")) + + for( pRfd = uti596_softc.pSavedRfdQueue; + pRfd != I596_NULL; + pRfd = pRfd -> next) { + printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) } - - sc->pCmdHead = sc->pCmdTail = sc->scb.pCmd = I596_NULL; - -#ifdef DBG_RESET - printk(( "uti596reset: After reset, status and command: 0x%x, 0x%x\n", - sc->scb.status, sc->scb.status)) -#endif - - /* restore the RFA */ - - /* dumpQ(); */ - - if ( sc->pLastUnkRFD != I596_NULL ) { - sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */ - sc-> pLastUnkRFD = I596_NULL; + + printk(("Inbound:\n")) + + for( pRfd = uti596_softc.pInboundFrameQueue; + pRfd != I596_NULL; + pRfd = pRfd -> next) { + printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) } - - sc->pEndRFA->next = sc->pSavedRfdQueue; - if ( sc->pSavedRfdQueue != I596_NULL ) { - sc->pEndRFA = sc->pEndSavedQueue; - sc->pSavedRfdQueue = sc->pEndSavedQueue = I596_NULL; - sc -> countRFD = sc->rxBdCount ; + + printk(("Last Unk: %p\n", uti596_softc.pLastUnkRFD )) + printk(("RFA:\n")) + + for( pRfd = uti596_softc.pBeginRFA; + pRfd != I596_NULL; + pRfd = pRfd -> next) { + printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) } - - sc->scb.pRfd = sc->pBeginRFA; /* readdress the head of the RFA in the SCB */ - sc->scb.Rfd_val = word_swap((unsigned long)sc->pBeginRFA); - - uti596clearListStatus(sc->pBeginRFA ); - - /* dumpQ(); */ - - printk(("Reset:Starting NIC\n")) - sc->scb.command = RX_START; - sc->started = 1; /* we assume that the start works */ - sc->resetDone = 1; - i82596->chan_attn = 0x00000000; - UTI_WAIT_COMMAND_ACCEPTED(4000, "reset"); - printk(("Reset:Start complete \n")) - UTI_596_ASSERT(sc->pCmdHead == I596_NULL, "Reset: CMD not cleared\n") - -#ifdef DBG_RESET - printk(("uti596reset: completed\n")) -#endif } -/*********************************************************************** - * Function: void uti596_reset_hardware - * - * Description: - ***********************************************************************/ -void uti596_reset_hardware( - uti596_softc_ *sc -) +/* + * show_buffers + * + * Print out the RFA and frame queues + */ +static void show_buffers (void) { - int boguscnt = 1000; - rtems_status_code status_code; - i596_cmd *pCmd; - - - printk(("uti596_reset_hardware\n")) - pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */ - - /* reset the board */ - i82596->port_lower = 0x0000; - i82596->port_upper = 0x0000; - - if ( sc->pScp == NULL ) { - printk(("Calloc scp\n")) - uti596_softc.pScp = (i596_scp *) calloc(1,sizeof(struct i596_scp) + 0xf); - } - -#ifdef DBG_RESET - printk(("uti596_reset_hardware: Scp address %p\n", sc->pScp)) -#endif - - /* align the block */ - sc->pScp = (i596_scp *) - ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0); - -#ifdef DBG_RESET - printk(("uti596_reset_hardware: change scp address to : %p\n",sc->pScp)) -#endif + i596_rfd *pRfd; - /* change the scp address */ -#ifdef DBG_RESET - printk(("uti596_reset_hardware: Change the SCP address\n")) -#endif + printk(("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n", + uti596_softc.scb.command, + uti596_softc.scb.status, + uti596_softc.countRFD)) - /* reset the board */ - i82596->port_lower = 0x0000; - i82596->port_upper = 0x0000; + printk(("\nRFA: \n")) - /* supply the Scp address - * Lower Command Word D31-D16; Upper Command Word D15-D0 - */ - i82596->port_lower = (((int)sc->pScp) & 0xfff0) | 0x0002; - i82596->port_upper = (((int)sc->pScp) >> 16 ) & 0xffff; - - /* write the SYSBUS: interrupt pin active high, LOCK disabled, - * internal triggering, linear mode - */ - sc->pScp->sysbus = word_swap(0x00540000); + for ( pRfd = uti596_softc.pBeginRFA; + pRfd != I596_NULL; + pRfd = pRfd->next) { + printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", + pRfd, pRfd->stat, pRfd->cmd)) + } + printk(("\nInbound: \n")) - /* provide the iscp to the scp, keep a pointer for our use */ - sc->pScp->iscp_val = word_swap((unsigned long)&sc->iscp); - sc->pScp->iscp = &sc->iscp; - - /* provide the scb to the iscp, keep a pointer for our use */ - sc->iscp.scb_val = word_swap((unsigned long)&sc->scb); - sc->iscp.scb = &sc->scb; - - /* set the busy flag in the iscp */ - sc->iscp.stat = word_swap(0x00000001); - - /* the command block list (CBL) is empty */ - sc->scb.Cmd_val = (unsigned long) I596_NULL; /* all 1's */ - sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ - - /* - * Wake the transmitter if needed. - */ - if ( uti596_softc.txDaemonTid && pCmd != I596_NULL ) { - printk(("****RESET: wakes transmitter!\n")) - status_code = rtems_event_send (uti596_softc.txDaemonTid, - INTERRUPT_EVENT); - - if ( status_code != RTEMS_SUCCESSFUL ) { - printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n", - uti596_softc.txDaemonTid, rtems_status_text (status_code) )) - } - } - -#ifdef DBG_596 - printk(("uti596_reset_hardware: starting i82596.\n")) -#endif - - /* Pass the scb address to the 596 */ - i82596->chan_attn = 0x00000000; - - while (sc->iscp.stat) - if (--boguscnt == 0) - { - printk(("reset_hardware: timed out with status %4.4lx\n", - sc->iscp.stat )) - break; - } - - /* clear the command word */ - sc->scb.command = 0; - -#ifdef DBG_RESET - printk(("uti596_reset_hardware: After reset_hardware, status of board = 0x%x\n", sc->scb.status )) -#endif -} - - /*********************************************************************** - * Function: uti596clearListStatus - * - * Description: - * Clear the stat fields for all rfd's - * Algorithm: - * - ***********************************************************************/ + for ( pRfd = uti596_softc.pInboundFrameQueue; + pRfd != I596_NULL; + pRfd = pRfd->next) { + printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", + pRfd, pRfd->stat, pRfd->cmd)) + } -void uti596clearListStatus( - i596_rfd *pRfd -) -{ - while ( pRfd != I596_NULL ) { - pRfd -> stat = 0; - pRfd = (i596_rfd *) word_swap((unsigned long)pRfd-> next); + printk(("\nSaved: \n")) + + for ( pRfd = uti596_softc.pSavedRfdQueue; + pRfd != I596_NULL; + pRfd = pRfd->next) { + printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", + pRfd, pRfd->stat, pRfd->cmd)) } + + printk(("\nUnknown: %p\n",uti596_softc.pLastUnkRFD)) } - /*********************************************************************** - * Function: send_packet - * - * Description: Send a raw ethernet packet - * - * Algorithm: - * increment some stats counters, - * create the transmit command, - * add the command to the CBL, - * wait for event - * - ***********************************************************************/ -void send_packet( - struct ifnet *ifp, struct mbuf *m -) +/* + * show_queues + * + * Print out the saved frame queue and the RFA + */ +static void show_queues(void) { - i596_tbd *pPrev = I596_NULL; - i596_tbd *pRemainingTbdList; - i596_tbd *pTbd; - struct mbuf *n, *input_m = m; - - uti596_softc_ *sc = ifp->if_softc; - - struct mbuf *l = NULL; - unsigned int length = 0; - rtems_status_code status; - int bd_count = 0; - rtems_event_set events; - - /* - * For all mbufs in the chain, - * fill a transmit buffer descriptor for each - */ - pTbd = (i596_tbd*) word_swap ((unsigned long)sc->pTxCmd->pTbd); - - do { - if (m->m_len) { - /* - * Fill in the buffer descriptor - */ - length += m->m_len; - pTbd->data = (char *) word_swap ((unsigned long) mtod (m, void *)); - pTbd->size = m->m_len; - pPrev = pTbd; - pTbd = (i596_tbd *) word_swap ((unsigned long) pTbd->next); - l = m; - m = m->m_next; - } - else { - /* - * Just toss empty mbufs - */ - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - } while( m != NULL && ++bd_count < 16 ); - - /* This should never happen */ - if ( bd_count == 16 ) { - printk(("TX ERROR:Too many mbufs in the packet!!!\n")) - printk(("Must coalesce!\n")) - } - - if ( length < UTI_596_ETH_MIN_SIZE ) { - pTbd->data = (char *) word_swap ((unsigned long) sc->zeroes); /* add padding to pTbd */ - pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */ - } - else - pTbd = pPrev; /* Don't use pTbd in the send routine */ - - /* Disconnect the packet from the list of Tbd's */ - pRemainingTbdList = (i596_tbd *) word_swap ((unsigned long)pTbd->next); - pTbd->next = I596_NULL; - pTbd->size |= UTI_596_END_OF_FRAME; - -#ifdef DBG_RAW - printk(("send_packet: RAW - Add cmd and sleep\n")) -#endif - - sc->rawsndcnt++; - -#ifdef DBG_RAW - printk(("send_packet: RAW - sending packet\n")) -#endif - - /* Sending Zero length packet: shouldn't happen */ - if (pTbd->size <= 0) return ; - -#ifdef DBG_INIT_3 - printk(("\nsend_packet: Transmitter adds packet\n")) - print_hdr ( sc->pTxCmd->pTbd->data ); /* print the first part */ - print_pkt ( sc->pTxCmd->pTbd->next->data ); /* print the first part */ - /* print_echo(sc->pTxCmd->pTbd->data); */ -#endif - - /* add the command to the output command queue */ - uti596addCmd ( (i596_cmd *) sc->pTxCmd ); - - /* sleep until the command has been processed or Timeout encountered. */ - status= rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - if ( status != RTEMS_SUCCESSFUL ) { - printk(("Could not sleep %s\n", rtems_status_text(status))) - } - -#ifdef DBG_RAW - printk(("send_packet: RAW - wake\n")) -#endif - - sc->txInterrupts++; + i596_rfd *pRfd; -#ifdef DBG_INIT_3 - printk(("\nsend_packet: Transmitter issued packet\n")) - print_hdr ( sc->pTxCmd->pTbd -> data ); /* print the first part */ - print_pkt ( sc->pTxCmd->pTbd ->next-> data ); /* print the first part */ -#endif + printk(("CMD: 0x%x, Status: 0x%x\n", + uti596_softc.scb.command, + uti596_softc.scb.status)) + printk(("saved Q\n")) - if ( sc->pTxCmd -> cmd.status & STAT_OK ) { - sc->stats.tx_packets++; + for ( pRfd = uti596_softc.pSavedRfdQueue; + pRfd != I596_NULL && + pRfd != NULL; + pRfd = pRfd->next) { + printk(("0x%p\n", pRfd)) } - else { -#ifdef DBG_RAW - printk(("******send_packet: Driver Error 0x%x\n", sc->pTxCmd -> cmd.status )) -#endif - sc->stats.tx_errors++; - if ( sc->pTxCmd->cmd.status & 0x0020 ) - sc->stats.tx_retries_exceeded++; - if (!(sc->pTxCmd->cmd.status & 0x0040)) - sc->stats.tx_heartbeat_errors++; - if ( sc->pTxCmd->cmd.status & 0x0400 ) - sc->stats.tx_carrier_errors++; - if ( sc->pTxCmd->cmd.status & 0x0800 ) - sc->stats.collisions++; - if ( sc->pTxCmd->cmd.status & 0x1000 ) - sc->stats.tx_aborted_errors++; - } /* end if stat_ok */ - /* - * Restore the transmited buffer descriptor chain. - */ - pTbd -> next = (i596_tbd *) word_swap ((unsigned long)pRemainingTbdList); + printk(("End saved Q 0x%p\n", uti596_softc.pEndSavedQueue)) - /* - * Free the mbufs used by the sender. - */ - m = input_m; - while ( m != NULL ) { - MFREE(m,n); - m = n; + printk(("\nRFA:\n")) + + for ( pRfd = uti596_softc.pBeginRFA; + pRfd != I596_NULL && + pRfd != NULL; + pRfd = pRfd->next) { + printk(("0x%p\n", pRfd)) } -} - - /*********************************************************************** - * Function: uti596addCmd - * - * Description: - * This routine adds a command onto the end of the - * command chain - * - * Algorithm: - * Add the command to the end of an existing chain, - * or start the chain and issue a CUC_START - * - * - ***********************************************************************/ - -/* static */ void uti596addCmd( - i596_cmd *pCmd -) -{ - ISR_Level level; - - #ifdef DBG_596 - printk(("uti596addCmd: Adding command 0x%x\n", pCmd -> command )) - #endif - -#ifdef DBG_ADD - - switch ( pCmd -> command & 0x7 ){ /* check bottom 3 bits */ - case CmdConfigure: - printk(("uti596addCmd: Configure Command 0x%x\n", pCmd->command)) - break; - case CmdSASetup: - printk(("uti596addCmd: Set Address Command 0x%x\n", pCmd->command)) - break; - case CmdMulticastList: - printk(("uti596addCmd: Multi-cast list 0x%x\n", pCmd->command)) - break; - case CmdNOp: - printk(("uti596addCmd: NO op 0x%x\n", pCmd->command)) - break; - case CmdTDR: - printk(("uti596addCmd: TDR 0x%x\n", pCmd->command)) - break; - case CmdDump: - printk(("uti596addCmd: Dump 0x%x\n", pCmd->command)) - break; - case CmdDiagnose: - printk(("uti596addCmd: Diagnose 0x%x\n", pCmd->command)) - break; - case CmdTx: - break; - default: - printk(("****Unknown Command encountered 0x%x\n", pCmd->command)) - break; - } /* end switch */ -#endif - - pCmd->status = 0; - pCmd->command |= (CMD_EOL | CMD_INTR ); /* all commands last in list & return an interrupt */ - - pCmd->next = I596_NULL; - - _ISR_Disable(level); - if (uti596_softc.pCmdHead == I596_NULL) - { - uti596_softc.pCmdHead = - uti596_softc.pCmdTail = - uti596_softc.scb.pCmd = pCmd; - uti596_softc.scb.Cmd_val = word_swap ((unsigned long)pCmd); -#ifdef DBG_596 - printk(("uti596addCmd: First Cmd\n")) -#endif - UTI_WAIT_COMMAND_ACCEPTED(10000,"add command"); /* wait for acceptance of previous command */ - uti596_softc.scb.command = CUC_START; - i82596->chan_attn = 0x00000000; - _ISR_Enable(level); - } - else - { -#ifdef DBG_596 - printk(("uti596addCmd: Chained Cmd\n")) -#endif - uti596_softc.pCmdTail->next = (i596_cmd *) word_swap ((unsigned long)pCmd); - uti596_softc.pCmdTail = pCmd; - _ISR_Enable(level); - } - -#ifdef DBG_596 - printk(("uti596addCmd: Scb status & command 0x%x 0x%x\n", - uti596_softc.scb.status, - uti596_softc.scb.command )) -#endif -} - - -/*********************************************************************** - * Function: uti596supplyFD - * - * Description: returns a buffer to the receive frame pool. - * call this with Inetrrupts disabled! - * - * Algorithm: - * - ***********************************************************************/ - -void uti596supplyFD( - i596_rfd * pRfd -) -{ - i596_rfd *pLastRfd; - - UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n") - pRfd -> cmd = CMD_EOL; - pRfd -> pRbd = I596_NULL; - pRfd -> next = I596_NULL; - pRfd -> stat = 0x0000; /* clear STAT_C and STAT_B bits */ - - /* - * Check if the list is empty: - */ - if ( uti596_softc.pBeginRFA == I596_NULL ) { - /* Init a list w/ one entry */ - uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; - UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n") - if ( uti596_softc.pLastUnkRFD != I596_NULL ) { - printk(("LastUnkRFD is NOT NULL!!\n")) - } - uti596_softc.countRFD = 1; - return; - } - /* - * Check if the last RFD is used/read by the 596. - */ - pLastRfd = uti596_softc.pEndRFA; - - if ( pLastRfd != I596_NULL && - ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { /* C = complete, B = busy (prefetched) */ - - /* - * Not yet too late to add it - */ - pLastRfd -> next = (i596_rfd *) word_swap ((unsigned long)pRfd); - pLastRfd -> cmd &= ~CMD_EOL; /* RESET_EL : reset EL bit to 0 */ - uti596_softc.countRFD++; /* Lets assume we add it successfully - If not, the RFD may be used, and may decrement countRFD < 0 !!*/ - /* - * Check if the last RFD was used while appending. - */ - if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */ - /* - * Either the EL bit of the last rfd has been read by the 82596, - * and it will stop after reception,( true when RESET_EL not reached ) or - * the EL bit was NOT read by the 82596 and it will use the linked - * RFD for the next reception. ( true is RESET_EL was reached ) - * So, it is unknown whether or not the linked rfd will be used. - * Therefore, the end of list CANNOT be updated. - */ - UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" ) - uti596_softc.pLastUnkRFD = pRfd; - return; - } - else { - /* - * The RFD being added was not touched by the 82596 - */ - if (uti596_softc.pLastUnkRFD != I596_NULL ) { - - uti596append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */ - uti596_softc.pEndSavedQueue = pRfd; - uti596_softc.savedCount++; - uti596_softc.countRFD--; - - } - else { - uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */ - if ( ( uti596_softc.scb.status & SCB_STAT_RNR || - uti596_softc.scb.status & RU_NO_RESOURCES ) && - uti596_softc.countRFD > 1 ) { - uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; /* Ensure that beginRFA is not EOL */ - - UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n") - UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n") - UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n") -#ifdef DBG_START - printk(("uti596supplyFD: starting receiver")) -#endif - /* start the receiver */ - UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n") - uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; - uti596_softc.scb.Rfd_val = word_swap ((unsigned long) uti596_softc.pBeginRFA); - uti596_softc.scb.command = RX_START | SCB_STAT_RNR; /* Don't ack RNR! The receiver - * should be stopped in this case */ - UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n") - i82596->chan_attn = 0x00000000; /* send CA signal */ - } - } - return; - - } - } - else { - /* - * too late , pLastRfd in use ( or NULL ), - * in either case, EL bit has been read, and RNR condition will occur - */ - uti596append( &uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */ - - uti596_softc.pEndSavedQueue = pRfd; /* reset end of saved queue */ - uti596_softc.savedCount++; - - return; - } -} -/*********************************************************************** - * Function: void uti596append - * - * Description: - * adds an RFD to the end of the received frame queue, - * for processing by the rxproc. - * Also removes this RFD from the RFA - * - * Algorithm: - * - ***********************************************************************/ -void uti596append( - i596_rfd ** ppQ, - i596_rfd * pRfd -) -{ - - i596_rfd *p; - - if ( pRfd != NULL && pRfd != I596_NULL) { - pRfd -> next = I596_NULL; - pRfd -> cmd |= CMD_EOL; /* set EL bit */ - - if ( *ppQ == NULL || *ppQ == I596_NULL ) { - /* empty list */ - *ppQ = pRfd; - } - else { - /* walk to the end of the list */ - for ( p=*ppQ; - p->next != I596_NULL; - p=(i596_rfd *) word_swap ((unsigned long)p->next) ); - - /* append the rfd */ - p->cmd &= ~CMD_EOL; /* Clear EL bit at end */ - p->next = (i596_rfd *) word_swap ((unsigned long)pRfd); - } - } - else { - printk(("Illegal attempt to append: %p\n", pRfd)) - } + printk(("uti596_softc.pEndRFA: %p\n",uti596_softc.pEndRFA)) } -/*********************************************************************** - * Function: void printk_time - * - * Description: - ***********************************************************************/ -void printk_time( void ) -{ - rtems_time_of_day tm_struct; - rtems_clock_get(RTEMS_CLOCK_GET_TOD, &tm_struct); - printk(("Current time: %d:%d:%d \n", - tm_struct.hour, - tm_struct.minute, - tm_struct.second)) -} - -/*********************************************************************** - * Function: void dump_scb +/* + * print_eth * - * Description: - ***********************************************************************/ -void dump_scb( void ) -{ - printk(("status 0x%x\n",uti596_softc.scb.status)) - printk(("command 0x%x\n",uti596_softc.scb.command)) - printk(("cmd 0x%x\n",(int)uti596_softc.scb.pCmd)) - printk(("rfd 0x%x\n",(int)uti596_softc.scb.pRfd)) - printk(("crc_err 0x%x\n",uti596_softc.scb.crc_err)) - printk(("align_err 0x%x\n",uti596_softc.scb.align_err)) - printk(("resource_err 0x%x\n",uti596_softc.scb.resource_err )) - printk(("over_err 0x%x\n",uti596_softc.scb.over_err)) - printk(("rcvdt_err 0x%x\n",uti596_softc.scb.rcvdt_err)) - printk(("short_err 0x%x\n",uti596_softc.scb.short_err)) - printk(("t_on 0x%x\n",uti596_softc.scb.t_on)) - printk(("t_off 0x%x\n",uti596_softc.scb.t_off)) -} - - -#ifdef DBG_INIT_3 - - /*********************************************************************** - ** - ** Debugging Functions - ** - ***********************************************************************/ - - - /*********************************************************************** - * Function: print_eth - * - * Description: - * Print the contents of an ethernet packet header - * CANNOT BE CALLED FROM ISR - * - * Algorithm: - * Print Destination, Src, and type of packet - * - ***********************************************************************/ - -/* static */ void print_eth( + * Print the contents of an ethernet packet + * CANNOT BE CALLED FROM ISR + */ +static void print_eth( unsigned char *add ) { @@ -2445,12 +2801,12 @@ void dump_scb( void ) for (i = 0; i < 6; i++) { printk ((" %2.2X", add[i])) - } + } printk (("\n")) printk (("Source")) for (i = 6; i < 12; i++) { - printk ((" %2.2X", add[i])) + printk ((" %2.2X", add[i])) } printk (("\n")) @@ -2467,19 +2823,19 @@ void dump_scb( void ) for ( i=0; i< 5 ; i++) { printk (("%x:", add[22 + i])) - } + } printk (("%x\n", add[27])) printk (("Sender IP addr: ")) for ( i=0; i< 3 ; i++) { printk (("%u.", add[28 + i])) - } + } printk (("%u\n", add[31])) printk (("Target Enet addr: ")) for ( i=0; i< 5 ; i++) { printk (( "%x:", add[32 + i])) - } + } printk (("%x\n", add[37])) printk (("Target IP addr: ")) @@ -2489,7 +2845,9 @@ void dump_scb( void ) printk (("%u\n", add[41])) } - if ( add[12] == 0x08 && add[13] == 0x00 ) { /* an IP packet */ + + if ( add[12] == 0x08 && add[13] == 0x00 ) { + /* an IP packet */ printk (("*********************IP HEADER******************\n")) printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15])) printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] ))) @@ -2502,41 +2860,25 @@ void dump_scb( void ) for ( i=0; i< 3 ; i++) { printk (("%u.", add[26 + i])) - } + } printk (("%u\n", add[29])) printk (("Destination IP address: ")) for ( i=0; i< 3 ; i++) { printk (("%u.", add[30 + i])) - } - printk (("%u\n", add[33])) - /* printk(("********************IP Packet Data*******************\n")) - length -=20; - for ( i=0; i < length ; i++) { - printk(("0x%2.2x ", add[34+i])) } - printk(("\n")) - - printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37])) - printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39])) - printk(("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41])) - */ + printk (("%u\n", add[33])) } } - /*********************************************************************** - * Function: print_hdr - * - * Description: - * Print the contents of an ethernet packet header - * CANNOT BE CALLED FROM ISR - * - * Algorithm: - * Print Destination, Src, and type of packet - * - ***********************************************************************/ - -/* static */ void print_hdr( + +/* + * print_hdr + * + * Print the contents of an ethernet packet header + * CANNOT BE CALLED FROM ISR + */ +static void print_hdr( unsigned char *add ) { @@ -2548,29 +2890,24 @@ void dump_scb( void ) for (i = 0; i < 6; i++) { printk ((" %2.2X", add[i])) - } + } printk (("\nSource")) for (i = 6; i < 12; i++) { printk ((" %2.2X", add[i])) - } + } printk (("\nframe type %2.2X%2.2X\n", add[12], add[13])) printk (("print_hdr: completed")) } - /*********************************************************************** - * Function: print_pkt - * - * Description: - * Print the contents of an ethernet packet header - * CANNOT BE CALLED FROM ISR - * - * Algorithm: - * Print Destination, Src, and type of packet - * - ***********************************************************************/ - -/* static */ void print_pkt( + +/* + * Function: print_pkt + * + * Print the contents of an ethernet packet & data + * CANNOT BE CALLED FROM ISR + */ +static void print_pkt( unsigned char *add ) { @@ -2591,18 +2928,18 @@ void dump_scb( void ) for ( i=0; i< 5 ; i++) { printk (( "%x:", add[22 + i])) - } + } printk (("%x\n", add[27])) printk (("Sender IP addr: ")) for ( i=0; i< 3 ; i++) { printk (("%u.", add[28 + i])) - } + } printk (("%u\n", add[31])) printk (("Target Enet addr: ")) for ( i=0; i< 5 ; i++) { - printk (( "%x:", add[32 + i])) + printk (( "%x:", add[32 + i])) } printk (("%x\n", add[37])) printk (("Target IP addr: ")) @@ -2627,7 +2964,7 @@ void dump_scb( void ) for ( i=0; i< 3 ; i++) { printk(( "%u.", add[26 + i])) - } + } printk(("%u\n", add[29])) printk(("Destination IP address: ")) @@ -2649,19 +2986,14 @@ void dump_scb( void ) } } - /*********************************************************************** - * Function: print_echo - * - * Description: - * Print the contents of an ethernet packet header - * CANNOT BE CALLED FROM ISR - * - * Algorithm: - * Prints only echo packets - * - ***********************************************************************/ - -/* static */ void print_echo( + +/* + * print_echo + * + * Print the contents of an echo packet + * CANNOT BE CALLED FROM ISR + */ +static void print_echo( unsigned char *add ) { @@ -2677,13 +3009,13 @@ void dump_scb( void ) for (i = 0; i < 6; i++) { printk ((" %2.2X", add[i])) - } + } printk (("\n")) printk (("Source")) for (i = 6; i < 12; i++) { printk ((" %2.2X", add[i])) - } + } printk (("\n")) printk (("frame type %2.2X%2.2X\n", add[12], add[13])) @@ -2699,7 +3031,7 @@ void dump_scb( void ) for ( i=0; i< 3 ; i++) { printk (("%u.", add[26 + i])) - } + } printk (("%u\n", add[29])) printk (("Destination IP address: ")) @@ -2712,7 +3044,7 @@ void dump_scb( void ) for ( i=0; i < length ; i++) { printk(("0x%2.2x ", add[34+i])) - } + } printk(("\n")) printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37])) printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39])) @@ -2721,169 +3053,4 @@ void dump_scb( void ) } } -#endif - -/*********************************************************************** - * Function: uti596dump - * - * Description: Dump 596 registers - * - * Algorithm: - ***********************************************************************/ -/* static */ int uti596dump( - char * pDumpArea -) -{ - i596_dump dumpCmd; - int boguscnt = 25000000; /* over a second! */ - -#ifdef DBG_596 - printk(("uti596dump: begin\n")) -#endif - - dumpCmd.cmd.command = CmdDump; - dumpCmd.cmd.next = I596_NULL; - dumpCmd.pData = pDumpArea; - uti596_softc.cmdOk = 0; - uti596addCmd ( (i596_cmd *)&dumpCmd); - while (1) { - if ( --boguscnt == 0) { - printk(("Dump command was not processed within spin loop delay\n")) - return 0; - } - else { - if ( uti596_softc.cmdOk ) { - return 1; /* successful completion */ - } - } - } -} - -/*********************************************************************** - * Function: void dumpQ - * - * Description: - ***********************************************************************/ -void dumpQ( void ) -{ - i596_rfd *pRfd; - - printk(("savedQ:\n")) - - for( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL; - pRfd = pRfd -> next) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } - - printk(("Inbound:\n")) - - for( pRfd = uti596_softc.pInboundFrameQueue; - pRfd != I596_NULL; - pRfd = pRfd -> next) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } - - printk(("Last Unk: %p\n", uti596_softc.pLastUnkRFD )) - printk(("RFA:\n")) - - for( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = pRfd -> next) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } -} - - -/*********************************************************************** - * Function: void show_buffers - * - * Description: - ***********************************************************************/ -void show_buffers (void) -{ - i596_rfd *pRfd; - - printk(("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n", - uti596_softc.scb.command, - uti596_softc.scb.status, - uti596_softc.countRFD)) - - printk(("\nRFA: \n")) - - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = pRfd->next) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - printk(("\nInbound: \n")) - - for ( pRfd = uti596_softc.pInboundFrameQueue; - pRfd != I596_NULL; - pRfd = pRfd->next) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - - printk(("\nSaved: \n")) - - for ( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL; - pRfd = pRfd->next) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - - printk(("\nUnknown: %p\n",uti596_softc.pLastUnkRFD)) -} - -/*********************************************************************** - * Function: void show_queues - * - * Description: - ***********************************************************************/ -void show_queues(void) -{ - i596_rfd *pRfd; - - printk(("CMD: 0x%x, Status: 0x%x\n", - uti596_softc.scb.command, - uti596_softc.scb.status)) - printk(("saved Q\n")) - - for ( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL && - pRfd != NULL; - pRfd = pRfd->next) { - printk(("0x%p\n", pRfd)) - } - - printk(("End saved Q 0x%p\n", uti596_softc.pEndSavedQueue)) - - printk(("\nRFA:\n")) - - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL && - pRfd != NULL; - pRfd = pRfd->next) { - printk(("0x%p\n", pRfd)) - } - - printk(("uti596_softc.pEndRFA: %p\n",uti596_softc.pEndRFA)) -} - - /*********************************************************************** - * Function: word_swap - * - * Description: - * Return a 32 bit value, swapping the upper - * and lower words first. - * - ***********************************************************************/ -unsigned long word_swap (unsigned long val) -{ - return (((val >> 16)&(0x0000ffff)) | ((val << 16)&(0xffff0000))); -} - - +#endif
\ No newline at end of file |