📄 lance.c
字号:
/* * lance.c * * This file contains a ethernet device driver for AMD LANCE based ethernet * cards. * * The valid messages and their parameters are: * * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR * |------------+----------+---------+----------+---------+---------| * | HARDINT | | | | | | * |------------|----------|---------|----------|---------|---------| * | DL_WRITE | port nr | proc nr | count | mode | address | * |------------|----------|---------|----------|---------|---------| * | DL_WRITEV | port nr | proc nr | count | mode | address | * |------------|----------|---------|----------|---------|---------| * | DL_READ | port nr | proc nr | count | | address | * |------------|----------|---------|----------|---------|---------| * | DL_READV | port nr | proc nr | count | | address | * |------------|----------|---------|----------|---------|---------| * | DL_INIT | port nr | proc nr | mode | | address | * |------------|----------|---------|----------|---------|---------| * | DL_GETSTAT | port nr | proc nr | | | address | * |------------|----------|---------|----------|---------|---------| * | DL_STOP | port_nr | | | | | * |------------|----------|---------|----------|---------|---------| * * The messages sent are: * * m-type DL_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK * |------------|----------|---------|----------|---------|---------| * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock | * |------------|----------|---------|----------|---------|---------| * * m_type m3_i1 m3_i2 m3_ca1 * |------------+---------+-----------+---------------| * |DL_INIT_REPL| port nr | last port | ethernet addr | * |------------|---------|-----------|---------------| * * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp> * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl> */#define VERBOSE 0#include "../drivers.h"#include <minix/keymap.h>#include <net/hton.h>#include <net/gen/ether.h>#include <net/gen/eth_io.h>#include <assert.h>#include <minix/syslib.h>#include "lance.h"#include "../libpci/pci.h"/*#include "proc.h"*/#include <sys/ioc_memory.h>/* new I/O functions in Minix 3 */#define out_byte( x, y ) sys_outb( x, y )#define out_word( x, y ) sys_outw( x, y )static U8_t in_byte(U16_t port){ U8_t value; int s; if ((s=sys_inb(port, &value)) != OK) printf( "lance: warning, sys_inb failed: %d\n", s ); return value;}static U16_t in_word( U16_t port){ U16_t value; int s; if ((s=sys_inw(port, &value)) != OK) printf( "lance: warning, sys_inw failed: %d\n", s ); return value;}/*#define in_byte( x ) inb( x )#define in_word( x ) inw( x )*/static ether_card_t ec_table[EC_PORT_NR_MAX];static int eth_tasknr= ANY;static u16_t eth_ign_proto;/* Configuration */typedef struct ec_conf{ port_t ec_port; int ec_irq; phys_bytes ec_mem; char *ec_envvar;} ec_conf_t;/* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */ec_conf_t ec_conf[]= /* Card addresses */{ /* I/O port, IRQ, Buffer address, Env. var, Buf selector. */ { 0x1000, 9, 0x00000, "LANCE0" }, { 0xD000, 15, 0x00000, "LANCE1" },};/* Actually, we use PCI-BIOS info. */PRIVATE struct pcitab{ u16_t vid; u16_t did; int checkclass;} pcitab[]={ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 }, /* AMD LANCE */ { 0x0000, 0x0000, 0 }};/*struct pci_device pci_dev_list[] = { { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, "AMD Lance/PCI", 0, 0, 0, 0, 0, 0}, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, "AMD Lance/PCI", 0, 0, 0, 0, 0, 0}, {0, 0, NULL, 0, 0, 0, 0, 0, 0}};*//* General */_PROTOTYPE( static void do_init, (message *mp) );_PROTOTYPE( static void ec_init, (ether_card_t *ec) );_PROTOTYPE( static void ec_confaddr, (ether_card_t *ec) );_PROTOTYPE( static void ec_reinit, (ether_card_t *ec) );_PROTOTYPE( static void ec_check_ints, (ether_card_t *ec) );_PROTOTYPE( static void conf_hw, (ether_card_t *ec) );/*_PROTOTYPE( static int ec_handler, (irq_hook_t *hook) );*/_PROTOTYPE( static void update_conf, (ether_card_t *ec, ec_conf_t *ecp) );_PROTOTYPE( static void mess_reply, (message *req, message *reply) );_PROTOTYPE( static void do_int, (ether_card_t *ec) );_PROTOTYPE( static void reply, (ether_card_t *ec, int err, int may_block) );_PROTOTYPE( static void ec_reset, (ether_card_t *ec) );_PROTOTYPE( static void ec_send, (ether_card_t *ec) );_PROTOTYPE( static void ec_recv, (ether_card_t *ec) );_PROTOTYPE( static void do_vwrite, (message *mp, int from_int, int vectored) );_PROTOTYPE( static void do_vread, (message *mp, int vectored) );_PROTOTYPE( static void get_userdata, (int user_proc, vir_bytes user_addr, vir_bytes count, void *loc_addr) );_PROTOTYPE( static void ec_user2nic, (ether_card_t *dep, iovec_dat_t *iovp, vir_bytes offset, int nic_addr, vir_bytes count) );_PROTOTYPE( static void ec_nic2user, (ether_card_t *ec, int nic_addr, iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );_PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );_PROTOTYPE( static void do_getstat, (message *mp) );_PROTOTYPE( static void put_userdata, (int user_proc, vir_bytes user_addr, vir_bytes count, void *loc_addr) );_PROTOTYPE( static void do_stop, (message *mp) );_PROTOTYPE( static void do_getname, (message *mp) );_PROTOTYPE( static void lance_dump, (void) );_PROTOTYPE( static void lance_stop, (void) );_PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec) );/* probe+init LANCE cards */_PROTOTYPE( static int lance_probe, (ether_card_t *ec) );_PROTOTYPE( static void lance_init_card, (ether_card_t *ec) );/* --- LANCE --- *//* General */#define Address unsigned long/* Minix 3 */#define virt_to_bus(x) (vir2phys((unsigned long)x))unsigned long vir2phys( unsigned long x ){ int r; unsigned long value; if ( (r=sys_umap( SELF, D, x, 4, &value )) != OK ) panic( "lance", "sys_umap failed", r ); return value;}/* DMA limitations */#define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */#define CORRECT_DMA_MEM() ( (virt_to_bus(lance + sizeof(lance)) & ~DMA_ADDR_MASK) == 0 )#define ETH_FRAME_LEN 1518#define LANCE_MUST_PAD 0x00000001#define LANCE_ENABLE_AUTOSELECT 0x00000002#define LANCE_SELECT_PHONELINE 0x00000004#define LANCE_MUST_UNRESET 0x00000008static const struct lance_chip_type{ int id_number; const char *name; int flags;} chip_table[] = { {0x0000, "LANCE 7990", /* Ancient lance chip. */ LANCE_MUST_PAD + LANCE_MUST_UNRESET}, {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */ LANCE_ENABLE_AUTOSELECT}, {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */ LANCE_ENABLE_AUTOSELECT}, {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */ LANCE_ENABLE_AUTOSELECT}, {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */ LANCE_ENABLE_AUTOSELECT}, {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */ LANCE_ENABLE_AUTOSELECT}, {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */ LANCE_ENABLE_AUTOSELECT}, {0x2626, "PCnet/HomePNA 79C978", LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE}, {0x0, "PCnet (unknown)", LANCE_ENABLE_AUTOSELECT},};/* ############## for LANCE device ############## */#define LANCE_ETH_ADDR 0x0#define LANCE_DATA 0x10#define LANCE_ADDR 0x12#define LANCE_RESET 0x14#define LANCE_BUS_IF 0x16#define LANCE_TOTAL_SIZE 0x18/* Use 2^4=16 {Rx,Tx} buffers */#define LANCE_LOG_RX_BUFFERS 4#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)#define LANCE_LOG_TX_BUFFERS 4#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)/* for lance_interface */struct lance_init_block{ unsigned short mode; unsigned char phys_addr[6]; unsigned long filter[2]; Address rx_ring; Address tx_ring;};struct lance_rx_head{ union { Address base; unsigned char addr[4]; } u; short buf_length; /* 2s complement */ short msg_length;};struct lance_tx_head{ union { Address base; unsigned char addr[4]; } u; short buf_length; /* 2s complement */ short misc;};struct lance_interface{ struct lance_init_block init_block; struct lance_rx_head rx_ring[RX_RING_SIZE]; struct lance_tx_head tx_ring[TX_RING_SIZE]; unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN]; unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN];};/* =============== global variables =============== */static struct lance_interface *lp;static char lance[sizeof(struct lance_interface)+8];static int rx_slot_nr = 0; /* Rx-slot number */static int tx_slot_nr = 0; /* Tx-slot number */static int cur_tx_slot_nr = 0; /* Tx-slot number */static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */static char *progname;/*===========================================================================* * lance_task * *===========================================================================*/void main( int argc, char **argv ){ message m; int i,irq,r, tasknr; ether_card_t *ec; long v; int fkeys, sfkeys; (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); env_setargs( argc, argv ); fkeys = sfkeys = 0; bit_set( sfkeys, 7 ); if ( (r = fkey_map(&fkeys, &sfkeys)) != OK ) printf( "Error registering key\n" ); if((eth_tasknr=getprocnr()) < 0) panic("lance","couldn't get own proc nr", i); v= 0; (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL); eth_ign_proto= htons((u16_t) v); /* Try to notify inet that we are present (again) */ r = findproc("inet", &tasknr); if (r == OK) notify(tasknr); while (TRUE) { for (i=0;i<EC_PORT_NR_MAX;++i) { ec= &ec_table[i]; if (ec->ec_irq != 0) sys_irqenable(&ec->ec_hook); } if ((r= receive(ANY, &m)) != OK) panic( "lance", "receive failed", r); for (i=0;i<EC_PORT_NR_MAX;++i) { ec= &ec_table[i]; if (ec->ec_irq != 0) sys_irqdisable(&ec->ec_hook); }/*printf( "." );*/ switch (m.m_type){ case DEV_PING: notify(m.m_source); continue; case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break; case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break; case DL_READ: do_vread(&m, FALSE); break; case DL_READV: do_vread(&m, TRUE); break; case DL_INIT: do_init(&m); break; case DL_GETSTAT: do_getstat(&m); break; case DL_STOP: do_stop(&m); break; case DL_GETNAME: do_getname(&m); break; case FKEY_PRESSED: lance_dump(); break; /*case HARD_STOP: lance_stop(); break;*/ case SYS_SIG: { sigset_t set = m.NOTIFY_ARG; if ( sigismember( &set, SIGKSTOP ) ) lance_stop(); } break; case HARD_INT: for (i=0;i<EC_PORT_NR_MAX;++i) { ec= &ec_table[i]; if (ec->mode != EC_ENABLED) continue; /* printf( "#.\n" ); */ irq=ec->ec_irq; /*if (ec->ec_int_pending)*/ { ec->ec_int_pending = 0; ec_check_ints(ec); do_int(ec); } } break; default: panic( "lance", "illegal message", m.m_type); } }}/*===========================================================================* * lance_dump * *===========================================================================*/static void lance_dump(){ ether_card_t *ec; int i, isr; unsigned short ioaddr; printf("\n"); for (i= 0, ec = &ec_table[0]; i<EC_PORT_NR_MAX; i++, ec++) { if (ec->mode == EC_DISABLED) printf("lance port %d is disabled\n", i); else if (ec->mode == EC_SINK) printf("lance port %d is in sink mode\n", i); if (ec->mode != EC_ENABLED) continue; printf("lance statistics of port %d:\n", i); printf("recvErr :%8ld\t", ec->eth_stat.ets_recvErr); printf("sendErr :%8ld\t", ec->eth_stat.ets_sendErr); printf("OVW :%8ld\n", ec->eth_stat.ets_OVW); printf("CRCerr :%8ld\t", ec->eth_stat.ets_CRCerr); printf("frameAll :%8ld\t", ec->eth_stat.ets_frameAll); printf("missedP :%8ld\n", ec->eth_stat.ets_missedP); printf("packetR :%8ld\t", ec->eth_stat.ets_packetR); printf("packetT :%8ld\t", ec->eth_stat.ets_packetT); printf("transDef :%8ld\n", ec->eth_stat.ets_transDef); printf("collision :%8ld\t", ec->eth_stat.ets_collision); printf("transAb :%8ld\t", ec->eth_stat.ets_transAb); printf("carrSense :%8ld\n", ec->eth_stat.ets_carrSense); printf("fifoUnder :%8ld\t", ec->eth_stat.ets_fifoUnder); printf("fifoOver :%8ld\t", ec->eth_stat.ets_fifoOver); printf("CDheartbeat:%8ld\n", ec->eth_stat.ets_CDheartbeat); printf("OWC :%8ld\t", ec->eth_stat.ets_OWC); ioaddr = ec->ec_port; out_word(ioaddr+LANCE_ADDR, 0x00); isr=in_word(ioaddr+LANCE_DATA); printf("isr = 0x%x + 0x%x, flags = 0x%x\n", isr, in_word(ioaddr+LANCE_DATA), ec->flags); printf("irq = %d\tioadr = %d\n", ec->ec_irq, ec->ec_port); }}/*===========================================================================* * lance_stop * *===========================================================================*/static void lance_stop(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -