unstack - fix ipcvecs
[minix.git] / sys / arch / i386 / stand / lib / netif / i82557.c
blob6579c974dcbfd41dc39db185c472c77c9c9372c8
1 /* $NetBSD: i82557.c,v 1.11 2008/12/14 18:46:33 christos Exp $ */
3 /*
4 * Copyright (c) 1998, 1999
5 * Matthias Drochner. All rights reserved.
6 * Copyright (c) 1995, David Greenman
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
14 * disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <machine/pio.h>
35 #include <dev/ic/i82557reg.h>
37 #include <lib/libsa/stand.h>
39 #include <libi386.h>
40 #include <pcivar.h>
42 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
43 #include <lib/libkern/libkern.h>
44 #include <bootinfo.h>
45 #endif
47 #include "etherdrv.h"
49 #define RECVBUF_SIZE 1600 /* struct fxp_rfa + packet */
51 #ifdef _STANDALONE
52 static pcihdl_t mytag;
53 static char recvbuf[RECVBUF_SIZE];
54 #define RECVBUF_PHYS vtophys(recvbuf)
55 #define RECVBUF_VIRT ((void *)recvbuf)
56 static union _sndbuf {
57 struct fxp_cb_config cbp;
58 struct fxp_cb_ias cb_ias;
59 struct fxp_cb_tx txp;
60 } sndbuf;
61 #define SNDBUF_PHYS vtophys(&sndbuf)
62 #define SNDBUF_VIRT ((void *)&sndbuf)
63 #else /* !standalone, userspace testing environment */
64 #define PCI_MODE1_ENABLE 0x80000000UL
65 static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIDEVNO << 11);
67 extern void *mapmem(int, int);
68 void *dmamem; /* virtual */
69 #define RECVBUF_PHYS DMABASE
70 #define RECVBUF_VIRT dmamem
71 #define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE)
72 #define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE))
73 #endif /* _STANDALONE */
75 static void fxp_read_eeprom(uint16_t *, int, int);
76 static inline void fxp_scb_wait(void);
77 #ifdef DEBUG
78 static void fxp_checkintr(char *);
79 #else
80 #define fxp_checkintr(x)
81 #endif
82 static void fxp_startreceiver(void);
85 * Template for default configuration parameters.
86 * See struct fxp_cb_config for the bit definitions.
88 static uint8_t fxp_cb_config_template[] = {
89 0x0, 0x0, /* cb_status */
90 0x80, 0x2, /* cb_command */
91 0xff, 0xff, 0xff, 0xff, /* link_addr */
92 0x16, /* 0 */
93 0x8, /* 1 */
94 0x0, /* 2 */
95 0x0, /* 3 */
96 0x0, /* 4 */
97 0x80, /* 5 */
98 0xb2, /* 6 */
99 0x3, /* 7 */
100 0x1, /* 8 */
101 0x0, /* 9 */
102 0x26, /* 10 */
103 0x0, /* 11 */
104 0x60, /* 12 */
105 0x0, /* 13 */
106 0xf2, /* 14 */
107 0x48, /* 15 */
108 0x0, /* 16 */
109 0x40, /* 17 */
110 0xf3, /* 18 */
111 0x0, /* 19 */
112 0x3f, /* 20 */
113 0x5 /* 21 */
116 static int tx_threshold = 64; /* x8, max 192 */
118 #define CSR_READ_1(reg) inb(iobase + (reg))
119 #define CSR_READ_2(reg) inw(iobase + (reg))
120 #define CSR_WRITE_1(reg, val) outb(iobase + (reg), val)
121 #define CSR_WRITE_2(reg, val) outw(iobase + (reg), val)
122 #define CSR_WRITE_4(reg, val) outl(iobase + (reg), val)
123 #define DELAY(n) delay(n)
125 static int iobase;
127 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
128 static struct btinfo_netif bi_netif;
129 #endif
132 * Wait for the previous command to be accepted (but not necessarily
133 * completed).
135 static inline void
136 fxp_scb_wait(void)
138 int i = 10000;
140 while (CSR_READ_1(FXP_CSR_SCB_COMMAND) && --i)
141 DELAY(1);
142 if (i == 0)
143 printf("fxp: WARNING: SCB timed out!\n");
146 #ifdef DEBUG
147 static void
148 fxp_checkintr(char *msg)
150 uint8_t statack;
151 int i = 10000;
153 do {
154 statack = CSR_READ_1(FXP_CSR_SCB_STATACK);
155 } while ((statack == 0) && (--i > 0));
157 if (statack != 0) {
158 CSR_WRITE_1(FXP_CSR_SCB_STATACK, statack);
159 printf("%s: ack'd irq %x, i=%d\n", msg, statack, i);
162 #endif
165 EtherInit(unsigned char *myadr)
167 #ifndef _STANDALONE
168 uint32_t id;
169 #endif
170 volatile struct fxp_cb_config *cbp;
171 volatile struct fxp_cb_ias *cb_ias;
172 int i;
174 if (pcicheck()) {
175 printf("pcicheck failed\n");
176 return 0;
178 #ifdef _STANDALONE
179 if (pcifinddev(0x8086, 0x1229, &mytag)) {
180 printf("no fxp\n");
181 return 0;
183 #else
184 pcicfgread(&mytag, 0, &id);
185 if (id != 0x12298086) {
186 printf("no fxp\n");
187 return 0;
189 #endif
191 pcicfgread(&mytag, FXP_PCI_IOBA, &iobase);
192 iobase &= ~3;
194 #ifndef _STANDALONE
195 dmamem = mapmem(DMABASE, DMASIZE);
196 if (!dmamem)
197 return 0;
198 #endif
200 fxp_read_eeprom((void *)myadr, 0, 3);
203 * Initialize base of CBL and RFA memory. Loading with zero
204 * sets it up for regular linear addressing.
206 CSR_WRITE_4(FXP_CSR_SCB_GENERAL, 0);
207 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
209 fxp_scb_wait();
210 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
212 cbp = SNDBUF_VIRT;
214 * This memcpy is kind of disgusting, but there are a bunch of must be
215 * zero and must be one bits in this structure and this is the easiest
216 * way to initialize them all to proper values.
218 memcpy((void *)cbp, fxp_cb_config_template,
219 sizeof(fxp_cb_config_template));
221 #define prm 0
222 #define phy_10Mbps_only 0
223 #define all_mcasts 0
224 cbp->cb_status = 0;
225 cbp->cb_command = FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL;
226 cbp->link_addr = -1; /* (no) next command */
227 cbp->byte_count = 22; /* (22) bytes to config */
228 cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */
229 cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */
230 cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */
231 cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */
232 cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */
233 cbp->dma_mbce = 0; /* (disable) dma max counters */
234 cbp->late_scb = 0; /* (don't) defer SCB update */
235 cbp->tno_int_or_tco_en = 0; /* (disable) tx not okay interrupt */
236 cbp->ci_int = 0; /* interrupt on CU not active */
237 cbp->save_bf = prm; /* save bad frames */
238 cbp->disc_short_rx = !prm; /* discard short packets */
239 cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */
240 cbp->mediatype = !phy_10Mbps_only; /* interface mode */
241 cbp->nsai = 1; /* (don't) disable source addr insert */
242 cbp->preamble_length = 2; /* (7 byte) preamble */
243 cbp->loopback = 0; /* (don't) loopback */
244 cbp->linear_priority = 0; /* (normal CSMA/CD operation) */
245 cbp->linear_pri_mode = 0; /* (wait after xmit only) */
246 cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */
247 cbp->promiscuous = prm; /* promiscuous mode */
248 cbp->bcast_disable = 0; /* (don't) disable broadcasts */
249 cbp->crscdt = 0; /* (CRS only) */
250 cbp->stripping = !prm; /* truncate rx packet to byte count */
251 cbp->padding = 1; /* (do) pad short tx packets */
252 cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */
253 cbp->force_fdx = 0; /* (don't) force full duplex */
254 cbp->fdx_pin_en = 1; /* (enable) FDX# pin */
255 cbp->multi_ia = 0; /* (don't) accept multiple IAs */
256 cbp->mc_all = all_mcasts;/* accept all multicasts */
257 #undef prm
258 #undef phy_10Mbps_only
259 #undef all_mcasts
262 * Start the config command/DMA.
264 fxp_scb_wait();
265 CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
266 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
267 /* ...and wait for it to complete. */
268 i = 10000;
269 while (!(cbp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
270 DELAY(1);
271 if (i == 0)
272 printf("config timeout");
274 fxp_checkintr("config");
276 cb_ias = SNDBUF_VIRT;
278 * Now initialize the station address. Temporarily use the TxCB
279 * memory area like we did above for the config CB.
281 cb_ias->cb_status = 0;
282 cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL;
283 cb_ias->link_addr = -1;
284 memcpy((void *)cb_ias->macaddr, myadr, 6);
287 * Start the IAS (Individual Address Setup) command/DMA.
289 fxp_scb_wait();
290 /* address is still there */
291 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
292 /* ...and wait for it to complete. */
293 i = 10000;
294 while (!(cb_ias->cb_status & FXP_CB_STATUS_C) && (--i > 0))
295 DELAY(1);
296 if (i == 0)
297 printf("ias timeout");
299 fxp_checkintr("ias");
301 fxp_startreceiver();
303 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
304 strncpy(bi_netif.ifname, "fxp", sizeof(bi_netif.ifname));
305 bi_netif.bus = BI_BUS_PCI;
306 bi_netif.addr.tag = mytag;
308 BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
309 #endif
311 return 1;
314 void
315 EtherStop(void)
319 * Issue software reset
321 CSR_WRITE_4(FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
322 DELAY(10);
326 EtherSend(char *pkt, int len)
328 volatile struct fxp_cb_tx *txp;
329 #ifdef _STANDALONE
330 static volatile struct fxp_tbd tbd;
331 #endif
332 volatile struct fxp_tbd *tbdp;
333 int i;
335 txp = SNDBUF_VIRT;
336 #ifdef _STANDALONE
337 tbdp = &tbd;
338 txp->tbd_array_addr = vtophys((void *)&tbd);
339 tbdp->tb_addr = vtophys(pkt);
340 #else
341 /* XXX assuming we send at max 400 bytes */
342 tbdp = (struct fxp_tbd *)(SNDBUF_VIRT + 440);
343 txp->tbd_array_addr = SNDBUF_PHYS + 440;
344 memcpy(SNDBUF_VIRT + 400, pkt, len);
345 tbdp->tb_addr = SNDBUF_PHYS + 400;
346 #endif
347 tbdp->tb_size = len;
348 txp->tbd_number = 1;
349 txp->cb_status = 0;
350 txp->cb_command =
351 FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_EL;
352 txp->tx_threshold = tx_threshold;
354 txp->link_addr = -1;
355 txp->byte_count = 0;
357 fxp_scb_wait();
358 CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
359 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
360 /* ...and wait for it to complete. */
361 i = 10000;
362 while (!(txp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
363 DELAY(1);
364 if (i == 0)
365 printf("send timeout");
367 fxp_checkintr("send");
369 return len;
372 static void
373 fxp_startreceiver(void)
375 volatile struct fxp_rfa *rfa;
376 uint32_t v;
378 rfa = RECVBUF_VIRT;
379 rfa->size = RECVBUF_SIZE - sizeof(struct fxp_rfa);
380 rfa->rfa_status = 0;
381 rfa->rfa_control = FXP_RFA_CONTROL_S;
382 rfa->actual_size = 0;
383 v = RECVBUF_PHYS; /* close the "ring" */
384 memcpy((void *)&rfa->link_addr, &v, sizeof(v));
385 v = -1;
386 memcpy((void *)&rfa->rbd_addr, &v, sizeof(v));
388 fxp_scb_wait();
389 CSR_WRITE_4(FXP_CSR_SCB_GENERAL, RECVBUF_PHYS);
390 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
394 EtherReceive(char *pkt, int maxlen)
396 uint8_t ruscus;
397 volatile struct fxp_rfa *rfa;
398 int len = 0;
400 ruscus = CSR_READ_1(FXP_CSR_SCB_RUSCUS);
401 if (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_READY)
402 return 0;
403 if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED) {
404 printf("rcv: ruscus=%x\n", ruscus);
405 return 0;
408 rfa = RECVBUF_VIRT;
409 if (rfa->rfa_status & FXP_RFA_STATUS_C) {
410 len = rfa->actual_size & 0x7ff;
411 if (len <= maxlen) {
412 memcpy(pkt, (char *) rfa + RFA_SIZE, maxlen);
413 #if 0
414 printf("rfa status=%x, len=%x\n",
415 rfa->rfa_status, len);
416 #endif
417 } else
418 len = 0;
421 fxp_scb_wait();
422 CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
424 return len;
428 * Read from the serial EEPROM. Basically, you manually shift in
429 * the read opcode (one bit at a time) and then shift in the address,
430 * and then you shift out the data (all of this one bit at a time).
431 * The word size is 16 bits, so you have to provide the address for
432 * every 16 bits of data.
434 static void
435 fxp_read_eeprom(uint16_t *data, int offset, int words)
437 uint16_t reg;
438 int i, x;
440 for (i = 0; i < words; i++) {
441 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
443 * Shift in read opcode.
445 for (x = 3; x > 0; x--) {
446 if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
447 reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
448 } else {
449 reg = FXP_EEPROM_EECS;
451 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
452 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
453 reg | FXP_EEPROM_EESK);
454 DELAY(1);
455 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
456 DELAY(1);
459 * Shift in address.
461 for (x = 6; x > 0; x--) {
462 if ((i + offset) & (1 << (x - 1))) {
463 reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
464 } else {
465 reg = FXP_EEPROM_EECS;
467 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
468 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
469 reg | FXP_EEPROM_EESK);
470 DELAY(1);
471 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
472 DELAY(1);
474 reg = FXP_EEPROM_EECS;
475 data[i] = 0;
477 * Shift out data.
479 for (x = 16; x > 0; x--) {
480 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
481 reg | FXP_EEPROM_EESK);
482 DELAY(1);
483 if (CSR_READ_2(FXP_CSR_EEPROMCONTROL) &
484 FXP_EEPROM_EEDO)
485 data[i] |= (1 << (x - 1));
486 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
487 DELAY(1);
489 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, 0);
490 DELAY(1);