⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lance.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 + -