📄 sk_g16.c
字号:
* Two different registers which share the same address, Status is * read-only, Control is write-only. * * I/O Command: * Any bitcombination written in here starts the transmission between * Host and LANCE. */typedef struct{ unsigned char ram[0x3fc0]; /* 16KB dual ported ram */ unsigned char rom[0x0020]; /* 32Byte PROM containing 6Byte MAC */ unsigned char res1[0x0010]; /* reserved */ unsigned volatile short ioreg;/* LANCE I/O Register */ unsigned volatile char port; /* Statusregister and Controlregister */ unsigned char iocom; /* I/O Command Register */} SK_RAM;/* struct *//* * This is the structure for the dual ported ram. We * have exactly 16 320 Bytes. In here there must be: * * - Initialize Block (starting at a word boundary) * - Receive and Transmit Descriptor Rings (quadword boundary) * - Data Buffers (arbitrary boundary) * * This is because LANCE has on SK_G16 only access to the dual ported * RAM and nowhere else. */struct SK_ram{ struct init_block ib; struct tmd tmde[TMDNUM]; struct rmd rmde[RMDNUM]; char tmdbuf[TMDNUM][PKT_BUF_SZ]; char rmdbuf[RMDNUM][PKT_BUF_SZ];};/* * Structure where all necessary information is for ring buffer * management and statistics. */struct priv{ struct SK_ram *ram; /* dual ported ram structure */ struct rmd *rmdhead; /* start of receive ring descriptors */ struct tmd *tmdhead; /* start of transmit ring descriptors */ int rmdnum; /* actual used ring descriptor */ int tmdnum; /* actual transmit descriptor for transmitting data */ int tmdlast; /* last sent descriptor used for error handling, etc */ void *rmdbufs[RMDNUM]; /* pointer to the receive buffers */ void *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */};/* global variable declaration *//* static variables */static SK_RAM *board; /* pointer to our memory mapped board components */static unsigned short ioaddr; /* base io address */static struct priv p_data;/* Macros *//* Function Prototypes *//* * Device Driver functions * ----------------------- * See for short explanation of each function its definitions header. */static int SK_probe1(struct nic *nic, short ioaddr1);static void SK_reset(struct nic *nic);static int SK_poll(struct nic *nic);static void SK_transmit(struct nic *nic,const char *d, /* Destination */unsigned int t, /* Type */unsigned int s, /* size */const char *p); /* Packet */static void SK_disable(struct nic *nic);struct nic *SK_probe(struct nic *nic, unsigned short *probe_addrs);/* * LANCE Functions * --------------- */static int SK_lance_init(struct nic *nic, unsigned short mode);static void SK_reset_board(void);static void SK_set_RAP(int reg_number);static int SK_read_reg(int reg_number);static int SK_rread_reg(void);static void SK_write_reg(int reg_number, int value);/* * Debugging functions * ------------------- */static void SK_print_pos(struct nic *nic, char *text);static void SK_print_ram(struct nic *nic);/**************************************************************************RESET - Reset adapter***************************************************************************/static void SK_reset(struct nic *nic){ /* put the card in its initial state */ SK_lance_init(nic, MODE_NORMAL);}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int SK_poll(struct nic *nic){ /* return true if there's an ethernet packet ready to read */ struct priv *p; /* SK_G16 private structure */ struct rmd *rmdp; int csr0, rmdstat, packet_there; PRINTF2(("## %s: At beginning of SK_poll(). CSR0: %#hX\n", SK_NAME, SK_read_reg(CSR0))); p = nic->priv_data; csr0 = SK_read_reg(CSR0); /* store register for checking */ /* * Acknowledge all of the current interrupt sources, disable * Interrupts (INEA = 0) */ SK_write_reg(CSR0, csr0 & CSR0_CLRALL); if (csr0 & CSR0_ERR) /* LANCE Error */ { printf("%s: error: %#hX", SK_NAME, csr0); if (csr0 & CSR0_MISS) /* No place to store packet ? */ { printf(", Packet dropped."); } putchar('\n'); } rmdp = p->rmdhead + p->rmdnum; packet_there = 0; /* As long as we own the next entry, check status and send * it up to higher layer */ while (!( (rmdstat = rmdp->u.s.status) & RX_OWN)) { /* * Start and end of packet must be set, because we use * the ethernet maximum packet length (1518) as buffer size. * * Because our buffers are at maximum OFLO and BUFF errors are * not to be concerned (see Data sheet) */ if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP)) { /* Start of a frame > 1518 Bytes ? */ if (rmdstat & RX_STP) { printf("%s: packet too long\n", SK_NAME); } /* * All other packets will be ignored until a new frame with * start (RX_STP) set follows. * * What we do is just give descriptor free for new incoming * packets. */ rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ } else if (rmdstat & RX_ERR) /* Receive Error ? */ { printf("%s: RX error: %#hX\n", SK_NAME, (int) rmdstat); rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */ } else /* We have a packet which can be queued for the upper layers */ { int len = (rmdp->mlen & 0x0fff); /* extract message length from receive buffer */ /* * Copy data out of our receive descriptor into nic->packet. * * (rmdp->u.buffer & 0x00ffffff) -> get address of buffer and * ignore status fields) */ memcpy(nic->packet, (unsigned char *) (rmdp->u.buffer & 0x00ffffff), nic->packetlen = len); packet_there = 1; /* * Packet is queued and marked for processing so we * free our descriptor */ rmdp->u.s.status = RX_OWN; p->rmdnum++; p->rmdnum %= RMDNUM; rmdp = p->rmdhead + p->rmdnum; } } SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ return (packet_there);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void SK_transmit(struct nic *nic,const char *d, /* Destination */unsigned int t, /* Type */unsigned int s, /* size */const char *pack) /* Packet */{ /* send the packet to destination */ struct priv *p; /* SK_G16 private structure */ struct tmd *tmdp; short len; int csr0, i, tmdstat; PRINTF2(("## %s: At beginning of SK_transmit(). CSR0: %#hX\n", SK_NAME, SK_read_reg(CSR0))); p = nic->priv_data; tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */ /* Copy data into dual ported ram */ memcpy(&p->ram->tmdbuf[p->tmdnum][0], d, ETH_ALEN); /* dst */ memcpy(&p->ram->tmdbuf[p->tmdnum][ETH_ALEN], nic->node_addr, ETH_ALEN); /* src */ p->ram->tmdbuf[p->tmdnum][ETH_ALEN + ETH_ALEN] = t >> 8; /* type */ p->ram->tmdbuf[p->tmdnum][ETH_ALEN + ETH_ALEN + 1] = t; /* type */ memcpy(&p->ram->tmdbuf[p->tmdnum][ETH_HLEN], pack, s); s += ETH_HLEN; while (s < ETH_ZLEN) /* pad to min length */ p->ram->tmdbuf[p->tmdnum][s++] = 0; p->ram->tmde[p->tmdnum].status2 = 0x0; /* Evaluate Packet length */ len = ETH_ZLEN < s ? s : ETH_ZLEN; /* Fill in Transmit Message Descriptor */ tmdp->blen = -len; /* set length to transmit */ /* * Packet start and end is always set because we use the maximum * packet length as buffer length. * Relinquish ownership to LANCE */ tmdp->u.s.status = TX_OWN | TX_STP | TX_ENP; /* Start Demand Transmission */ SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA); csr0 = SK_read_reg(CSR0); /* store register for checking */ /* * Acknowledge all of the current interrupt sources, disable * Interrupts (INEA = 0) */ SK_write_reg(CSR0, csr0 & CSR0_CLRALL); if (csr0 & CSR0_ERR) /* LANCE Error */ { printf("%s: error: %#hX", SK_NAME, csr0); if (csr0 & CSR0_MISS) /* No place to store packet ? */ { printf(", Packet dropped."); } putchar('\n'); } /* Set next buffer */ p->tmdlast++; p->tmdlast &= TMDNUM-1; tmdstat = tmdp->u.s.status & 0xff00; /* filter out status bits 15:08 */ /* * We check status of transmitted packet. * see LANCE data-sheet for error explanation */ if (tmdstat & TX_ERR) /* Error occurred */ { printf("%s: TX error: %#hX %#hX\n", SK_NAME, (int) tmdstat, (int) tmdp->status2); if (tmdp->status2 & TX_TDR) /* TDR problems? */ { printf("%s: tdr-problems \n", SK_NAME); } if (tmdp->status2 & TX_UFLO) /* Underflow error ? */ { /* * If UFLO error occurs it will turn transmitter of. * So we must reinit LANCE */ SK_lance_init(nic, MODE_NORMAL); } tmdp->status2 = 0; /* Clear error flags */ } SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */ /* Set pointer to next transmit buffer */ p->tmdnum++; p->tmdnum &= TMDNUM-1;}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void SK_disable(struct nic *nic){ PRINTF(("## %s: At beginning of SK_disable(). CSR0: %#hX\n", SK_NAME, SK_read_reg(CSR0))); PRINTF(("%s: Shutting %s down CSR0 %#hX\n", SK_NAME, SK_NAME, (int) SK_read_reg(CSR0))); SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/struct nic *SK_probe(struct nic *nic, unsigned short *probe_addrs){ unsigned short *p; static unsigned short io_addrs[] = SK_IO_PORTS; /* if probe_addrs is 0, then routine can use a hardwired default */ putchar('\n'); nic->priv_data = &p_data; if (probe_addrs == 0) probe_addrs = io_addrs; for (p = probe_addrs; (ioaddr = *p) != 0; ++p) { long offset1, offset0 = inb(ioaddr); if ((offset0 == SK_IDLOW) && ((offset1 = inb(ioaddr + 1)) == SK_IDHIGH)) if (SK_probe1(nic, ioaddr) >= 0) break; } /* if board found */ if (ioaddr != 0) { /* point to NIC specific routines */ nic->reset = SK_reset; nic->poll = SK_poll; nic->transmit = SK_transmit; nic->disable = SK_disable; return nic; } /* else */ { return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -