📄 lan_am79c973.c
字号:
if (rcode != OK) { return( rcode ) ; } ptmp = KSEG1( ptmp ) ; for (i=0; i<LAN_AM79C973_RDRE_COUNT; i++) { pdevice->RXDRE[i] = ptmp ; ptmp += LAN_AM79C973_RDRE_SIZE ; } /* 4: allocate TX Data Buffers */ mem.size = LAN_AM79C973_TX_BUFFERS * LAN_AM79C973_BUFFER_SIZE ; mem.boundary = CACHE_LINE_SIZE ; mem.memory = (void*)&ptmp ; rcode = SYSCON_read( SYSCON_BOARD_MALLOC_ID, &mem, sizeof(t_sys_malloc) ) ; if (rcode != OK) { return( rcode ) ; } ptmp = KSEG1( ptmp ) ; for (i=0; i<LAN_AM79C973_TX_BUFFERS; i++) { pdevice->TxBuffer[i] = ptmp ; ptmp += LAN_AM79C973_BUFFER_SIZE ; } /* 5: allocate RX Data Buffers */ mem.size = LAN_AM79C973_RX_BUFFERS * LAN_AM79C973_BUFFER_SIZE ; mem.boundary = CACHE_LINE_SIZE ; mem.memory = (void*)&ptmp ; rcode = SYSCON_read( SYSCON_BOARD_MALLOC_ID, &mem, sizeof(t_sys_malloc) ) ; if (rcode != OK) { return( rcode ) ; } ptmp = KSEG1( ptmp ) ; for (i=0; i<LAN_AM79C973_RX_BUFFERS; i++) { pdevice->RxBuffer[i] = ptmp ; ptmp += LAN_AM79C973_BUFFER_SIZE ; } /* register this event */ first_time_init = 1 ; } /* Clear init block */ memset( pdevice->pInitBlock, 0, LAN_AM79C973_INITBLOCK_SIZE ) ; /* Clear TX Descriptor Ring */ for (i=0; i<LAN_AM79C973_TDRE_COUNT; i++) { memset( (void*)pdevice->TXDRE[i], 0, LAN_AM79C973_TDRE_SIZE ) ; } /* Clear RX Descriptor Ring */ for (i=0; i<LAN_AM79C973_RDRE_COUNT; i++) { memset( (void*)pdevice->RXDRE[i], 0, LAN_AM79C973_RDRE_SIZE ) ; } /* Clear TX Data Buffers */ for (i=0; i<LAN_AM79C973_TX_BUFFERS; i++) { memset( (void*)pdevice->TxBuffer[i], 0, LAN_AM79C973_BUFFER_SIZE ) ; } /* Clear RX Data Buffers */ for (i=0; i<LAN_AM79C973_RX_BUFFERS; i++) { memset( (void*)pdevice->RxBuffer[i], 0, LAN_AM79C973_BUFFER_SIZE ) ; } return( OK );}/************************************************************************ * * LAN_AM79C973_init_initblock * Description : * ------------- * This routine initializes the AM79C973 Init Block data structure. * * * Parameters : * ------------ * * 'pdevice', IN, reference for this device context * * * Return values : * --------------- * * 'OK'(=0) * * * ************************************************************************/staticINT32 LAN_AM79C973_init_initblock( t_LAN_AM79C973_device *pdevice ) { volatile UINT32 *pib, *amd_base ; UINT32 tmp; pib = pdevice->pInitBlock ; /* Initialize Init Block word 0: TLEN=RLEN=4 (16), disable ring access */ pib[0] = CPU_TO_LE32((LAN_AM79C973_INITBLOCK_TLEN<<INIT_WORD0_TLEN_SHF) | (LAN_AM79C973_INITBLOCK_RLEN<<INIT_WORD0_RLEN_SHF) | ( 0<<INIT_WORD0_DTX_SHF) | ( 0<<INIT_WORD0_DRX_SHF) | ( 3<<INIT_WORD0_PORTSEL_SHF)); /* Initialize Init Block word 1&2: MAC-addres */ amd_base = (UINT32 *) pdevice->p79C973Regs ; tmp = REG( amd_base, WORD0 ) ; pib[1] = LE32_TO_CPU( tmp ); tmp = REG( amd_base, WORD1 ) ; pib[2] = LE32_TO_CPU( tmp ); /* Initialize Init Block word 3&4: Logical filter-addres */ pib[3] = 0; pib[4] = 0; /* Initialize Init Block word 5: Start of RX Descriptor Ring */ tmp = PHYS( pdevice->RXDRE[0] ); pib[5] = LE32_TO_CPU( tmp ); /* Initialize Init Block word 6: Start of TX Descriptor Ring */ tmp = PHYS( pdevice->TXDRE[0] ); pib[6] = LE32_TO_CPU( tmp ); return( OK );}/************************************************************************ * * LAN_AM79C973_init_ring_descriptors * Description : * ------------- * This routine initializes the AM79C973 ring descriptor * data structures. * * * Parameters : * ------------ * * 'pdevice', IN, reference for this device context * * * Return values : * --------------- * * 'OK'(=0) * * * ************************************************************************/staticINT32 LAN_AM79C973_init_ring_descriptors( t_LAN_AM79C973_device *pdevice ) { int i ; UINT32 tmp; /* Init TX Descriptor Ring */ for (i=0; i<LAN_AM79C973_TDRE_COUNT; i++) { /* Link data buffer to descriptor */ tmp = PHYS( pdevice->TxBuffer[i] ) ; REG( pdevice->TXDRE[i], TDE_WORD0 ) = CPU_TO_LE32( tmp ) ; /* Clear any status and control bits */ REG( pdevice->TXDRE[i], TDE_WORD1 ) = 0 ; REG( pdevice->TXDRE[i], TDE_WORD2 ) = 0 ; } pdevice->NextTDREIndex = 0 ; /* Init RX Descriptor Ring */ for (i=0; i<LAN_AM79C973_RDRE_COUNT; i++) { /* Link data buffer to descriptor */ tmp = PHYS( pdevice->RxBuffer[i] ) ; REG( pdevice->RXDRE[i], RDE_WORD0 ) = CPU_TO_LE32( tmp ) ; /* Set buffer size, owner=controller */ REG( pdevice->RXDRE[i], RDE_WORD1 ) = CPU_TO_LE32( ((-LAN_AM79C973_BUFFER_SIZE) << RDE_WORD1_BCNT_SHF) | ( 0xf << RDE_WORD1_ONES_SHF) | ( 1 << RDE_WORD1_OWN_SHF) ); } pdevice->NextRDREIndex = 0 ; return( OK );}/************************************************************************ * * LAN_AM79C973_stop * Description : * ------------- * This routine stops the AM79C973 LAN controller * by stoping DMA transfer and resetting the chip. * * * Parameters : * ------------ * * 'pdevice', IN, reference for this device context * * * Return values : * --------------- * * 'OK'(=0) * * * ************************************************************************/staticINT32 LAN_AM79C973_stop( t_LAN_AM79C973_device *pdevice ) { UINT32 rvar ; /* CSR0: STOP=1 deassert any DMA activity, and disable interrupt */ CSR_WRITE( pdevice->p79C973Regs, 0, 0x0004 ) /* make a soft RESET of AM79C973 */ LAN_AM79C973_RESET( pdevice->p79C973Regs, rvar ) LAN_AM79C973_state = LAN_AM79C973_DRIVER_IS_STOPPED ; return( rvar ); /* keep compiler happy - return value is not used */}/************************************************************************ * Implementation : Device driver services ************************************************************************//************************************************************************ * * LAN_AM79C973_init * Description : * ------------- * This service initializes the lan driver and configures * the MAC-address for the 'EN0' LAN interface. * The MAC-address is read during 'init' via the 'syscon' parameter: * -'SYSCON_COM_EN0_MAC_ADDR_ID'. * * * Parameters : * ------------ * * 'major', IN, major device number * 'minor', IN, not used * 'p_param', INOUT, not used * * * Return values : * --------------- * * 'OK'(=0) * * * ************************************************************************/staticINT32 LAN_AM79C973_init( UINT32 major, /* IN: major device number */ UINT32 minor, /* IN: minor device number */ void *p_param ) /* INOUT: device parameter block */{ bool ic_in_use ; UINT32 int_line ; INT32 rcode ; UINT32 rvar ; t_LAN_AM79C973_device *pdevice ; /* get device context for this minor device */ pdevice = &minor_device[minor] ; /* initialize shared services */ LAN_error_lookup_init() ; /* get AM79C973 memory mapped base address */ IF_ERROR( (rcode), (SYSCON_read(SYSCON_BOARD_AM79C973_BASE_ID, &(pdevice->p79C973Regs), sizeof(pdevice->p79C973Regs)) ) ) pdevice->p79C973Regs = (void *)KSEG1(pdevice->p79C973Regs) ; /* make a soft RESET of AM79C973 */ LAN_AM79C973_RESET( pdevice->p79C973Regs, rvar ) /* BCR20: Set softare style to 32 bit mode; i.e. Init Block and DRE's are 32 bit structures */ BCR_WRITE( pdevice->p79C973Regs, 20, 2) /* Setup PHY */ IF_ERROR( (rcode), (LAN_AM79C973_MII_setup(pdevice)) ) /* allocate memory for LAN Init Block, ring descriptors, data buffers */ IF_ERROR( (rcode), (LAN_AM79C973_allocate_memory(pdevice)) ) /* Init Init Block */ IF_ERROR( (rcode), (LAN_AM79C973_init_initblock(pdevice)) ) /* Init ring descriptors */ IF_ERROR( (rcode), (LAN_AM79C973_init_ring_descriptors(pdevice)) ) /* CSR1(LSA) & CSR2(MSA): Register Init Block */ CSR_WRITE( pdevice->p79C973Regs, 1, PHYS( pdevice->pInitBlock ) ) CSR_WRITE( pdevice->p79C973Regs, 2, (PHYS( pdevice->pInitBlock ) >> 16) ) /* Setup BCR registers; values expected to be present in EEPROM */ rvar = 0 ; BCR_WRITE( pdevice->p79C973Regs, 9, rvar) rvar = 0x9ae1 ; BCR_WRITE( pdevice->p79C973Regs, 18, rvar) rvar = 0x1818 ; BCR_WRITE( pdevice->p79C973Regs, 22, rvar) rvar = 0x17 ; BCR_WRITE( pdevice->p79C973Regs, 25, rvar) rvar = 0x8 ; BCR_WRITE( pdevice->p79C973Regs, 26, rvar) rvar = 0 ; BCR_WRITE( pdevice->p79C973Regs, 27, rvar) /* * Set the No Underflow on Transmit (NOUFLO) bit, to avoid tx fifo errors * on 100Mbit, full duplex ethernets. This way the whole packet is * buffered in the fifo/sram before it is send. * Note the NOUFLO isn't implemented on all the supported controllers, * but as far as I can tell it is implemented on the 79C973 and 79C975 * chips, if SRAM_SIZE > 0. For all others the transmit fifo threshold * value is set to max. carstenl@mips.com */ BCR_READ( pdevice->p79C973Regs, 18, rvar) rvar = rvar | (1<<11) ; BCR_WRITE( pdevice->p79C973Regs, 18, rvar) CSR_READ( pdevice->p79C973Regs, 80, rvar) rvar = rvar | (3<<10) ; CSR_WRITE( pdevice->p79C973Regs, 80, rvar) /* CSR0: INIT=1 assert initialization procedure */ CSR_WRITE( pdevice->p79C973Regs, 0, 0x0001 ) /* Await Initialization done */ sys_wait_ms( 10 ) ; /* wait 10 ms */ CSR_READ( pdevice->p79C973Regs, 0, rvar) if ( !(rvar & 0x0100) ) { printf(" LAN_AM79C973_init: initialization failed\n") ; return( ERROR_LAN_INIT_FAILED ) ; } /* CSR0: STRT=1 start transmit and receive frame procedures */ CSR_WRITE( pdevice->p79C973Regs, 0, 0x0002 ) if (usr_receive == NULL) { /* get interrupt profile */ IF_ERROR( (rcode), (SYSCON_read( SYSCON_COM_EN0_IC_ID, &(ic_in_use), sizeof(ic_in_use)) ) ) IF_ERROR( (rcode), (SYSCON_read( SYSCON_COM_EN0_INTLINE_ID, &(int_line), sizeof(int_line)) ) ) /* Register interrupt handler */ if( ic_in_use ) { EXCEP_register_ic_isr( int_line, (t_inthandler)LAN_AM79C973_receive, pdevice, NULL ); } else { EXCEP_register_cpu_isr( int_line, (t_inthandler)LAN_AM79C973_receive, pdevice, NULL ); } } /* CSR4: APAD_XMT=1 i.e. controller pads to minimum frame length (60 bytes) */ CSR_WRITE( pdevice->p79C973Regs, 4, 0x0914 ) /* mask out TX interrupt: CSR3, bit 9 */ CSR_WRITE( pdevice->p79C973Regs, 3, (1 << 9) ) CSR_WRITE( pdevice->p79C973Regs, 5, (1 << 15) ) /* enable interrupt: CSR0, bit 6 */ CSR_WRITE( pdevice->p79C973Regs, 0, (1 << 6) ) LAN_AM79C973_state = LAN_AM79C973_DRIVER_IS_STARTED ; return( OK ) ;}/************************************************************************ * * LAN_AM79C973_open * Description :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -