iPXE
ne2k_isa.c
Go to the documentation of this file.
1 /**************************************************************************
2  ETHERBOOT - BOOTP/TFTP Bootstrap Program
3 
4  Author: Martin Renters
5  Date: May/94
6 
7  This code is based heavily on David Greenman's if_ed.c driver
8 
9  Copyright (C) 1993-1994, David Greenman, Martin Renters.
10  This software may be used, modified, copied, distributed, and sold, in
11  both source and binary form provided that the above copyright and these
12  terms are retained. Under no circumstances are the authors responsible for
13  the proper functioning of this software, nor do the authors assume any
14  responsibility for damages incurred with its use.
15 
16  Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
17  Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
18  Card Detect support adapted from the eCos driver (Christian Plessl <cplessl@ee.ethz.ch>)
19  Extracted from ns8390.c and adapted by Pantelis Koukousoulas <pktoss@gmail.com>
20  **************************************************************************/
21 
22 FILE_LICENCE ( BSD2 );
23 
24 #include "ns8390.h"
25 #include "etherboot.h"
26 #include "nic.h"
27 #include <ipxe/ethernet.h>
28 #include <ipxe/isa.h>
29 #include <errno.h>
30 
31 #define ASIC_PIO NE_DATA
32 
33 static unsigned char eth_vendor, eth_flags;
34 static unsigned short eth_nic_base, eth_asic_base;
35 static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
37 static unsigned char eth_drain_receiver;
38 
40 static void ne_reset(struct nic *nic, struct isa_device *isa);
41 
42 static isa_probe_addr_t ne_probe_addrs[] = { 0x300, 0x280, 0x320, 0x340, 0x380, 0x220, };
43 
44 /**************************************************************************
45  ETH_PIO_READ - Read a frame via Programmed I/O
46  **************************************************************************/
47 static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {
50  outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
54  if (eth_flags & FLAG_16BIT)
55  cnt = (cnt + 1) >> 1;
56 
57  while (cnt--) {
58  if (eth_flags & FLAG_16BIT) {
59  *((unsigned short *) dst) = inw(eth_asic_base + ASIC_PIO);
60  dst += 2;
61  } else
62  *(dst++) = inb(eth_asic_base + ASIC_PIO);
63  }
64 }
65 
66 /**************************************************************************
67  ETH_PIO_WRITE - Write a frame via Programmed I/O
68  **************************************************************************/
69 static void eth_pio_write(const unsigned char *src, unsigned int dst,
70  unsigned int cnt) {
74  outb(cnt >> 8, eth_nic_base + D8390_P0_RBCR1);
76  outb(dst >> 8, eth_nic_base + D8390_P0_RSAR1);
78  if (eth_flags & FLAG_16BIT)
79  cnt = (cnt + 1) >> 1;
80 
81  while (cnt--) {
82 
83  if (eth_flags & FLAG_16BIT) {
84  outw(*((unsigned short *) src), eth_asic_base + ASIC_PIO);
85  src += 2;
86  } else
87  outb(*(src++), eth_asic_base + ASIC_PIO);
88  }
89 }
90 
91 /**************************************************************************
92  enable_multicast - Enable Multicast
93  **************************************************************************/
94 static void enable_multicast(unsigned short eth_nic_base) {
95  unsigned char mcfilter[8];
96  int i;
97 
98  memset(mcfilter, 0xFF, 8);
101  for (i = 0; i < 8; i++) {
102  outb(mcfilter[i], eth_nic_base + 8 + i);
103  if (inb(eth_nic_base + 8 + i) != mcfilter[i])
104  DBG("Error SMC 83C690 Multicast filter read/write mishap %d\n",
105  i);
106  }
108  outb(4 | 0x08, eth_nic_base + D8390_P0_RCR);
109 }
110 
111 /**************************************************************************
112  NE_PROBE1 - Look for an adapter on the ISA bus
113  **************************************************************************/
115  //From the eCos driver
116  unsigned int regd;
117  unsigned int state;
118 
119  state = inb(ioaddr);
121  regd = inb(ioaddr + D8390_P0_TCR);
122 
123  if (inb(ioaddr + D8390_P0_TCR)) {
124  outb(ioaddr, state);
125  outb(ioaddr + 0x0d, regd);
126  return 0;
127  }
128 
129  return 1;
130 }
131 
132 /**************************************************************************
133  NE_PROBE - Initialize an adapter ???
134  **************************************************************************/
135 static int ne_probe(struct nic *nic, struct isa_device *isa) {
136  int i;
137  unsigned char c;
138  unsigned char romdata[16];
139  unsigned char testbuf[32];
140 
142  eth_drain_receiver = 0;
143 
144  nic->irqno = 0;
145  nic->ioaddr = isa->ioaddr;
146  eth_nic_base = isa->ioaddr;
147 
148  /******************************************************************
149  Search for NE1000/2000 if no WD/SMC or 3com cards
150  ******************************************************************/
151  if (eth_vendor == VENDOR_NONE) {
152 
153  static unsigned char test[] = "NE*000 memory";
154 
155  eth_bmem = 0; /* No shared memory */
156 
160  eth_tx_start = 32;
164  (void) inb(0x84);
166  + D8390_P0_COMMAND);
171  eth_pio_write((unsigned char *) test, 8192, sizeof(test));
172  eth_pio_read(8192, testbuf, sizeof(test));
173  if (!memcmp(test, testbuf, sizeof(test)))
174  goto out;
177  eth_tx_start = 64;
180  + D8390_P0_DCR);
183  eth_pio_write((unsigned char *) test, 16384, sizeof(test));
184  eth_pio_read(16384, testbuf, sizeof(test));
185  if (!memcmp(testbuf, test, sizeof(test)))
186  goto out;
187 
188 
189 out:
190  if (eth_nic_base == 0)
191  return (0);
192  if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
195  eth_pio_read(0, romdata, sizeof(romdata));
196  for (i = 0; i < ETH_ALEN; i++) {
197  nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
198  }
200  DBG("\nNE%c000 base %4.4x, MAC Addr %s\n",
201  (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, eth_ntoa(
202  nic->node_addr));
203  }
204 
205  if (eth_vendor == VENDOR_NONE)
206  return (0);
207 
208  if (eth_vendor != VENDOR_3COM)
209  eth_rmem = eth_bmem;
210 
211  ne_reset(nic, isa);
213  return 1;
214 }
215 
216 
217 /**************************************************************************
218  NE_DISABLE - Turn off adapter
219  **************************************************************************/
220 static void ne_disable(struct nic *nic, struct isa_device *isa) {
221  ne_reset(nic, isa);
222 }
223 
224 
225 /**************************************************************************
226  NE_RESET - Reset adapter
227  **************************************************************************/
228 static void ne_reset(struct nic *nic, struct isa_device *isa __unused)
229 {
230  int i;
231 
232  eth_drain_receiver = 0;
235  if (eth_flags & FLAG_16BIT)
237  else
241  outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
245 
252 
253  for (i=0; i<ETH_ALEN; i++)
255  for (i=0; i<ETH_ALEN; i++)
261  outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
262  outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
263 
265 }
266 
267 
268 /**************************************************************************
269  NE_POLL - Wait for a frame
270  **************************************************************************/
271 static int ne_poll(struct nic *nic __unused, int retrieve __unused)
272 {
273  int ret = 0;
274  unsigned char rstat, curr, next;
275  unsigned short len, frag;
276  unsigned short pktoff;
277  unsigned char *p;
278  struct ringbuffer pkthdr;
279 
280  rstat = inb(eth_nic_base+D8390_P0_RSR);
281  if (!(rstat & D8390_RSTAT_PRX)) return(0);
283  if (next >= eth_memsize) next = eth_rx_start;
287  if (curr >= eth_memsize) curr=eth_rx_start;
288  if (curr == next) return(0);
289 
290  if ( ! retrieve ) return 1;
291 
292  pktoff = next << 8;
293  if (eth_flags & FLAG_PIO)
294  eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
295  else
296  memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
297  pktoff += sizeof(pkthdr);
298  /* incoming length includes FCS so must sub 4 */
299  len = pkthdr.len - 4;
300  if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
301  || len> ETH_FRAME_LEN) {
302  DBG("Bogus packet, ignoring\n");
303  return (0);
304  }
305  else {
306  p = nic->packet;
307  nic->packetlen = len; /* available to caller */
308  frag = (eth_memsize << 8) - pktoff;
309  if (len> frag) { /* We have a wrap-around */
310  /* read first part */
311  if (eth_flags & FLAG_PIO)
312  eth_pio_read(pktoff, p, frag);
313  else
314  memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
315  pktoff = eth_rx_start << 8;
316  p += frag;
317  len -= frag;
318  }
319  /* read second part */
320  if (eth_flags & FLAG_PIO)
321  eth_pio_read(pktoff, p, len);
322  else
323  memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
324  ret = 1;
325  }
326  next = pkthdr.next; /* frame number of next packet */
327  if (next == eth_rx_start)
328  next = eth_memsize;
330  return(ret);
331 }
332 
333 
334 /**************************************************************************
335  NE_TRANSMIT - Transmit a frame
336  **************************************************************************/
337 static void ne_transmit(struct nic *nic, const char *d, /* Destination */
338 unsigned int t, /* Type */
339 unsigned int s, /* size */
340 const char *p) { /* Packet */
341 
342  /* Programmed I/O */
343  unsigned short type;
344  type = (t >> 8) | (t << 8);
345  eth_pio_write((unsigned char *) d, eth_tx_start << 8, ETH_ALEN);
347  /* bcc generates worse code without (const+const) below */
348  eth_pio_write((unsigned char *) &type, (eth_tx_start << 8) + (ETH_ALEN
349  + ETH_ALEN), 2);
350  eth_pio_write((unsigned char *) p, (eth_tx_start << 8) + ETH_HLEN, s);
351  s += ETH_HLEN;
352  if (s < ETH_ZLEN)
353  s = ETH_ZLEN;
354 
359  outb(s >> 8, eth_nic_base + D8390_P0_TBCR1);
360 
363 }
364 
366  .poll = ne_poll, .transmit = ne_transmit, .irq = dummy_irq,
367 };
368 
369 ISA_DRIVER ( ne_driver, ne_probe_addrs, ne_probe1,
370  GENERIC_ISAPNP_VENDOR, 0x0600 );
371 
372 DRIVER ( "ne", nic_driver, isapnp_driver, ne_driver,
373  ne_probe, ne_disable );
374 
375 ISA_ROM("ne","NE1000/2000 and clones");
#define D8390_P0_RCR
Definition: ns8390.h:182
unsigned char irqno
Definition: nic.h:56
#define VENDOR_3COM
Definition: ns8390.h:14
ISA_DRIVER(ne_driver, ne_probe_addrs, ne_probe1, GENERIC_ISAPNP_VENDOR, 0x0600)
uint32_t c
Definition: md4.c:30
static unsigned char eth_vendor
Definition: ne2k_isa.c:33
uint16_t ioaddr
I/O address.
Definition: isa.h:16
An ISA device.
Definition: isa.h:12
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
#define D8390_P0_IMR
Definition: ns8390.h:185
#define VENDOR_NOVELL
Definition: ns8390.h:13
#define D8390_DCR_FT1
Definition: ns8390.h:208
uint8_t state
State.
Definition: eth_slow.h:47
An ISAPnP driver.
Definition: isapnp.h:209
uint32_t next
Next descriptor address.
Definition: myson.h:18
#define outw(data, io_addr)
Definition: io.h:319
#define FLAG_PIO
Definition: ns8390.h:16
Error codes.
#define MEM_16384
Definition: ns8390.h:21
static unsigned char eth_rx_start
Definition: ne2k_isa.c:35
static Address eth_rmem
Definition: ne2k_isa.c:36
#define D8390_COMMAND_PS1
Definition: ns8390.h:197
uint8_t type
Type.
Definition: ena.h:16
#define D8390_P0_RSAR1
Definition: ns8390.h:178
static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
Definition: ne2k_isa.c:69
static isa_probe_addr_t ne_probe_addrs[]
Definition: ne2k_isa.c:42
FILE_LICENCE(BSD2)
static void ne_disable(struct nic *nic, struct isa_device *isa)
Definition: ne2k_isa.c:220
#define NE_RESET
Definition: ns8390.h:160
#define MEM_8192
Definition: ns8390.h:20
#define D8390_RCR_MON
Definition: ns8390.h:206
#define D8390_P0_DCR
Definition: ns8390.h:184
int dummy_connect(struct nic *nic __unused)
Definition: legacy.c:151
static void ne_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
Definition: ne2k_isa.c:337
static __always_inline void * bus_to_virt(unsigned long bus_addr)
Convert bus address to a virtual address.
Definition: io.h:195
#define FLAG_16BIT
Definition: ns8390.h:17
#define D8390_COMMAND_RD0
Definition: ns8390.h:201
static unsigned long ioaddr
Definition: davicom.c:129
void * memcpy(void *dest, const void *src, size_t len) __nonnull
unsigned int ioaddr
Definition: nic.h:55
static void ne_reset(struct nic *nic, struct isa_device *isa)
#define ETH_HLEN
Definition: if_ether.h:9
Ethernet protocol.
#define ETH_FRAME_LEN
Definition: if_ether.h:11
#define NE_ASIC_OFFSET
Definition: ns8390.h:159
#define D8390_COMMAND_RD1
Definition: ns8390.h:200
uint16_t isa_probe_addr_t
Definition: isa.h:31
#define GENERIC_ISAPNP_VENDOR
Definition: isa_ids.h:38
__be32 out[4]
Definition: CIB_PRM.h:36
ISA_ROM("ne","NE1000/2000 and clones")
#define D8390_DCR_LS
Definition: ns8390.h:209
static unsigned char eth_drain_receiver
Definition: ne2k_isa.c:37
void dummy_irq(struct nic *nic __unused, irq_action_t irq_action __unused)
Definition: legacy.c:155
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
unsigned int packetlen
Definition: nic.h:54
#define ASIC_PIO
Definition: ne2k_isa.c:31
#define D8390_P0_TCR
Definition: ns8390.h:183
#define D8390_P0_RSR
Definition: ns8390.h:181
#define D8390_P1_CURR
Definition: ns8390.h:193
static void enable_multicast(unsigned short eth_nic_base)
Definition: ne2k_isa.c:94
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition: ethernet.c:175
#define D8390_ISR_RDC
Definition: ns8390.h:218
#define D8390_COMMAND_PS0
Definition: ns8390.h:196
uint8_t inb(volatile uint8_t *io_addr)
Read byte from I/O-mapped device.
static unsigned short eth_asic_base
Definition: ne2k_isa.c:34
#define ETH_ALEN
Definition: if_ether.h:8
#define ETH_ZLEN
Definition: if_ether.h:10
unsigned long Address
Definition: etherboot.h:21
#define D8390_P0_RBCR0
Definition: ns8390.h:179
Definition: nic.h:49
#define D8390_P1_PAR0
Definition: ns8390.h:187
#define D8390_P0_COMMAND
Definition: ns8390.h:168
#define D8390_COMMAND_RD2
Definition: ns8390.h:199
#define D8390_COMMAND_TXP
Definition: ns8390.h:202
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
unsigned char * packet
Definition: nic.h:53
#define VENDOR_NONE
Definition: ns8390.h:11
unsigned char * node_addr
Definition: nic.h:52
#define outb(data, io_addr)
Definition: io.h:309
#define D8390_P0_PSTOP
Definition: ns8390.h:170
#define D8390_P0_TBCR0
Definition: ns8390.h:174
#define D8390_P0_RBCR1
Definition: ns8390.h:180
uint32_t len
Length.
Definition: ena.h:14
#define ISA_MAX_ADDR
Definition: ns8390.h:24
static unsigned char eth_memsize
Definition: ne2k_isa.c:35
#define D8390_P1_MAR0
Definition: ns8390.h:194
#define D8390_COMMAND_STP
Definition: ns8390.h:204
static unsigned short eth_nic_base
Definition: ne2k_isa.c:34
#define MEM_32768
Definition: ns8390.h:22
static int ne_probe1(isa_probe_addr_t ioaddr)
Definition: ne2k_isa.c:114
uint32_t d
Definition: md4.c:31
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
Definition: ne2k_isa.c:47
#define D8390_P0_ISR
Definition: ns8390.h:176
#define D8390_P0_TPSR
Definition: ns8390.h:173
#define D8390_RSTAT_PRX
Definition: ns8390.h:221
#define D8390_TXBUF_SIZE
Definition: ns8390.h:226
#define D8390_P0_BOUND
Definition: ns8390.h:171
static unsigned char eth_tx_start
Definition: ne2k_isa.c:35
static Address eth_bmem
Definition: ne2k_isa.c:36
#define D8390_P0_PSTART
Definition: ns8390.h:169
static int ne_probe(struct nic *nic, struct isa_device *isa)
Definition: ne2k_isa.c:135
static int ne_poll(struct nic *nic __unused, int retrieve __unused)
Definition: ne2k_isa.c:271
#define D8390_P0_RSAR0
Definition: ns8390.h:177
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
struct nic_operations * nic_op
Definition: nic.h:50
DRIVER("ne", nic_driver, isapnp_driver, ne_driver, ne_probe, ne_disable)
int(* connect)(struct nic *)
Definition: nic.h:63
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define D8390_P0_TBCR1
Definition: ns8390.h:175
static int test
Definition: epic100.c:73
static unsigned char eth_flags
Definition: ne2k_isa.c:33
#define D8390_DCR_WTS
Definition: ns8390.h:210
static struct nic_operations ne_operations
Definition: ne2k_isa.c:39
#define D8390_COMMAND_STA
Definition: ns8390.h:203
void * memset(void *dest, int character, size_t len) __nonnull