📄 cs8900.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ *//* * Todo: * finish promiscious/multicast * test shared memory mode */#include <crys8900.h>#define NIC_INTERRUPT_EVENT 0#define NIC_TIMER_EVENT 1#define NIC_PRIORITY 21extern int variant_irq_init(void *handle);extern int cs8900_variant_load(void *handle);io_net_dll_entry_t io_net_dll_entry = { 2, cs8900_init, NULL };io_net_registrant_funcs_t cs8900_funcs = { 8, NULL, cs8900_send_packets, cs8900_receive_complete, cs8900_shutdown1, cs8900_shutdown2, cs8900_advertise, cs8900_devctl, cs8900_flush, NULL };io_net_registrant_t cs8900_entry = { _REG_PRODUCER_UP | _REG_TRACK_MCAST, "devn-cs8900", "en", NULL, NULL, &cs8900_funcs, 0 };int cs8900_init( void *dll_hdl, dispatch_t *dpp, io_net_self_t *ion, char *options){ int ret; dpp = dpp; if (ret = crys8900_detect(dll_hdl, ion, options)) { errno = ret; return -1; } return 0;}int cs8900_reset( void *handle ){ cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; int iobase; int cnt; iobase = cs8900->iobase; cs8900_wpktpage( iobase, CS8900_SELFCTL, cs8900_rpktpage( iobase, CS8900_SELFCTL ) | SELFCTL_RESET ); delay( 30 );#ifdef __X86__ if( cs8900->chip_id != CS8900 ) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ outle16( iobase + CS8900_PORT_PKTPG, CS8920_ISAINT ); out8( iobase + CS8900_PORT_PKTPG_DATA, cs8900->cfg.irq[0] ); out8( iobase + CS8900_PORT_PKTPG_DATA + 1, 0 ); outle16( iobase + CS8900_PORT_PKTPG, CS8920_MEM_BASE ); out8( iobase + CS8900_PORT_PKTPG_DATA, (cs8900->smem_addr >> 8) & 0xff ); out8( iobase + CS8900_PORT_PKTPG_DATA + 1, ( cs8900->smem_addr >> 24 ) & 0xff ); }#endif /* Wait until the chip is reset */ for (cnt = 1000; cnt && !( cs8900_rpktpage( iobase, CS8900_SELFST ) & SELFST_INIT_DONE ); cnt--) nsec_delay(10); return( 0 );}int cs8900_init_memory( void *handle ){ cs8900_dev_t *cs8900 = (cs8900_dev_t *) handle; int i,j; cs8900->num_rx_pkts = 16; cs8900->rx_pktq = calloc(cs8900->num_rx_pkts, sizeof(npkt_t *)); if (cs8900->rx_pktq == NULL) { perror("calloc"); return (-1); } cs8900->rx_max = cs8900->num_rx_pkts * 2; cs8900->rx_active = cs8900->num_rx_pkts; cs8900->rx_cidx = cs8900->rx_pidx = 0; for (i = 0; i < cs8900->num_rx_pkts; i++) { cs8900->rx_pktq[i] = cs8900_alloc_npkt(cs8900, 1518); if (cs8900->rx_pktq[i] == NULL) { for (j = 0; j < i; j++) { if (cs8900->rx_pktq[i]) { ion_free(cs8900->rx_pktq[i]->org_data); ion_free(cs8900->rx_pktq[i]); } } } }#ifdef __X86__ if( cs8900->mode & CS8900_DMA ) { cs8900->dmem_size = ( cs8900->isa_cnf & I_CNF_ISA_DMA_64K ) ? 0x10000 : 0x4000; /* receive DMA buffer memory */ if( ( cs8900->dmem = mmap( NULL, cs8900->dmem_size, PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_ANON | MAP_PHYS | MAP_BELOW16M, NOFD, 0 ) ) == MAP_FAILED ) { return( 1 ); } cs8900->dmem_cptr = cs8900->dmem; } if( cs8900->mode & CS8900_SHARED ) { /* map in shared memory */ if( !cs8900->smem_size ) { cs8900->smem_size = 4096; } if( ( cs8900->smem = mmap( NULL, cs8900->smem_size, PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_SHARED | MAP_PHYS, NOFD, cs8900->smem_addr ) ) == MAP_FAILED ) { return( 1 ); } }#endif return( 0 );}int cs8900_read_eeprom( int iobase, int off, int len, int *buffer ){ int i; int cnt; for( i = 0; i < len; i++ ) { for(cnt = 1000; cnt && (cs8900_rpktpage(iobase, CS8900_SELFST) & SELFST_SI_BUSY); cnt--) nsec_delay (10); /* send read command and location */ cs8900_wpktpage( iobase, CS8900_EEPROM_CMD, (off + i) | EEPROM_READ_CMD ); for(cnt = 1000; cnt && (cs8900_rpktpage(iobase, CS8900_SELFST) & SELFST_SI_BUSY); cnt--) nsec_delay (10); buffer[i] = cs8900_rpktpage( iobase, CS8900_EEPROM_DATA ); } return( 0 );}int cs8900_eeprom_config( void *handle ){ int i; cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; int cksum; int iobase; int rom[CHKSUM_LEN]; iobase = cs8900->iobase; /* check for EEPROM */ if( !( cs8900_rpktpage( iobase, CS8900_SELFST ) & SELFST_EEPROM_PRESENT ) ) { return( 1 ); } if( cs8900_read_eeprom( iobase, START_EEPROM_DATA, CHKSUM_LEN, rom ) ) { return( 1 ); } /* verify cksum */ for( i = 0, cksum = 0; i < CHKSUM_LEN; i++ ) { cksum += rom[i]; } if( cksum & 0xffff ) { return( 1 ); } if( !cs8900->auto_neg_cnf ) { /* get transmission control */ cs8900->auto_neg_cnf = rom[AUTO_NEG_CNF_OFFSET/2]; } if( !cs8900->adapter_cnf ) { /* get adapter configuration */ cs8900->adapter_cnf = rom[ADAPTER_CNF_OFFSET/2]; }#ifdef __X86__ /* get ISA config */ if( !cs8900->isa_cnf ) { cs8900->isa_cnf = rom[ISA_CNF_OFFSET/2]; } /* get shared memory address */ if( !cs8900->smem_addr ) { cs8900->smem_addr = rom[PACKET_PAGE_OFFSET/2] << 8; }#endif /* read MAC */ for( i = 0; i < ETH_MAC_LEN / 2; i++ ) { cs8900->cfg.permanent_address[i*2] = rom[i]; cs8900->cfg.permanent_address[i*2+1] = rom[i] >> 8; } /* Override with MAC address from syspage, if available */ nic_get_syspage_mac(cs8900->cfg.permanent_address); return( 0 );}int cs8900_config( void *handle ){ cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; int iobase; iobase = cs8900->iobase; strcpy( cs8900->cfg.device_description, "Crystal 89xx" ); cs8900->cfg.media = NIC_MEDIA_802_3; cs8900->cfg.media_rate = 10000; /* in kbits/sec */ cs8900->cfg.mac_length = ETH_MAC_LEN; if (cs8900->cfg.mtu == 0 || cs8900->cfg.mtu > ETH_MAX_PKT_LEN) cs8900->cfg.mtu = ETH_MAX_PKT_LEN; cs8900->chip_id = cs8900_rpktpage( iobase, CS8900_DEVICE_ID ) & ~REVISION_BITS; cs8900_reset( cs8900 ); if( cs8900_eeprom_config( cs8900 ) ) { if( !cs8900->auto_neg_cnf ) { cs8900->auto_neg_cnf = N_CNF_ALLOW_FDX | N_CNF_NEG_ENABLE; } if( !cs8900->adapter_cnf ) { cs8900->adapter_cnf = A_CNF_10B_T; } if( !cs8900->isa_cnf ) {/* cs8900->isa_cnf = I_CNF_ISA_DMA_64K | I_CNF_ISA_RXDMA | I_CNF_STREAM_TRANSFER; */ } } /* check for MAC command line override */ if( memcmp( cs8900->cfg.current_address, "\0\0\0\0\0\0", 6 ) == 0 ) { memcpy( cs8900->cfg.current_address, cs8900->cfg.permanent_address, ETH_MAC_LEN ); }#ifdef __X86__{ int irq; /* If this is a CS8900 then no pnp soft */ irq = cs8900_rpktpage( iobase, CS8920_ISAINT ); if( cs8900->chip_id != CS8900 && irq && irq < CS8920_NO_INTS ) { if( !cs8900->cfg.irq[0] ) { cs8900->cfg.irq[0] = irq; cs8900->cfg.num_irqs = 1; } } else { irq = cs8900->isa_cnf & I_CNF_INT_NO_MASK; if (cs8900->chip_id == CS8900) { /* mung irq using eval board mapping table */ switch (irq) { case 0: irq = 10; break; case 1: irq = 11; break; case 2: irq = 12; break; case 3: irq = 5; break; } } if (!cs8900->cfg.irq[0]) { cs8900->cfg.irq[0] = irq; cs8900->cfg.num_irqs = 1; } }}#endif if( cs8900_init_memory( cs8900 ) ) { return( 1 ); } if( cs8900->cfg.verbose ) { nic_dump_config( &cs8900->cfg ); } return( 0 );}int cs8900_initialize( void *handle ){ int i; int irq,temp_irq; int iobase; int i_cnf; cs8900_dev_t *cs8900 = (cs8900_dev_t *)handle; nic_config_t *cfg; int reg; cfg = &cs8900->cfg; iobase = cs8900->iobase; i_cnf = cs8900->isa_cnf; /* set ioport */ cs8900_wpktpage( iobase, CS8900_ISAIOB, (int)cfg->io_window_base[0]);/* cs8900_wpktpage( iobase, CS8900_ISAIOB, 0x300 ); */ /* set interrupt */ irq = cfg->irq[0]; if (cs8900->chip_id == CS8900) {#ifdef __X86__ switch (irq) { case 10: irq = 0; break; case 11: irq = 1; break; case 12: irq = 2; break; case 5: irq = 3; break; default: irq = 3; break; }#endif temp_irq = variant_irq_init(cs8900); if (temp_irq != -1) irq = temp_irq; cs8900_wpktpage( iobase, CS8900_ISAINT, irq ); } else cs8900_wpktpage( iobase, CS8920_ISAINT, irq ); /* set the MAC address */ for( i = 0; i < ETH_MAC_LEN / 2; i++ ) { cs8900_wpktpage( iobase, CS8900_IA + i * 2, cs8900->cfg.current_address[i*2] | (cs8900->cfg.current_address[i*2+1] << 8 ) ); }#ifdef __X86__ if( cs8900->mode & CS8900_DMA ) { cs8900_wpktpage( iobase, CS8900_ISADMA, cfg->dma_channel[0] - 5 ); } if( cs8900->mode & CS8900_SHARED ) { outle16( iobase + CS8900_PORT_PKTPG, CS8920_MEM_BASE ); out8( iobase + CS8900_PORT_PKTPG_DATA, (cs8900->smem_addr >> 8) & 0xff ); out8( iobase + CS8900_PORT_PKTPG_DATA + 1, ( cs8900->smem_addr >> 24 ) & 0xff );/* cs8900_wpktpage( iobase, CS8900_MEM_BASE, cs8900->smem_addr ); */ }#endif /* configure line settings */ cs8900_wpktpage( iobase, CS8900_LINECTL, LINECTL_RXON | LINECTL_TXON ); /* configure rx acceptance parameters */ reg = RXCTL_BRDCAST_OK | RXCTL_IA_OK | RXCTL_RX_OK; if( cs8900->cfg.flags & NIC_FLAG_PROMISCUOUS ) { reg |= RXCTL_PROM_OK; } if( cs8900->cfg.flags & NIC_FLAG_MULTICAST ) { reg |= RXCTL_MULTI_OK; } cs8900_wpktpage( iobase, CS8900_RXCTL, reg ); /* configure rx interrupt generation parameters */ cs8900_wpktpage( iobase, CS8900_RXCFG, ( ( i_cnf & I_CNF_ANY_ISA_DMA ) ? 0 : RXCFG_RXOK_IRQ ) | RXCFG_EXTRADATA_IRQ | RXCFG_CRCERR_IRQ | ( ( i_cnf & I_CNF_ANY_ISA_DMA ) ? RXCFG_DMA_ONLY : 0 ) | ( ( i_cnf & I_CNF_STREAM_TRANSFER ) ? RXCFG_STREAM_TXFR : 0 ) ); cs8900_wpktpage( iobase, CS8900_TXCFG, TXCFG_TXOK_IRQ | TXCFG_MAXCOL_IRQ | TXCFG_JABBER_IRQ | TXCFG_OOWCOL_IRQ | TXCFG_SQEERR_IRQ | TXCFG_NOCAR_IRQ ); cs8900_wpktpage( iobase, CS8900_BUFCFG, BUFCFG_TXRDY_IRQ | BUFCFG_TXUNDER_IRQ | BUFCFG_RXMISS_IRQ | ( ( i_cnf & I_CNF_ANY_ISA_DMA ) ? BUFCFG_RXDMA_IRQ: 0 ) );#ifdef __X86__ if( i_cnf & I_CNF_ANY_ISA_DMA ) { paddr_t paddr; mem_offset( (void *)cs8900->dmem, NOFD, 1, (off_t *)&paddr, NULL ); setup_8237( 0x14, cs8900->cfg.dma_channel[0], paddr, cs8900->dmem_size ); }#endif if( cs8900->chip_id != CS8900 ) { cs8900_wpktpage( iobase, CS8900_AUTONEGCTL, AUTONEGCTL_NLP ); } /* enable interrupts, and memory */ cs8900_wpktpage( iobase, CS8900_BUSCTL,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -