Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / sandpoint / stand / netboot / fxp.c
blob0a1773eb541356e9fc979c94765c815f53e069e1
1 /* $NetBSD: fxp.c,v 1.9 2008/05/14 23:14:11 nisimura Exp $ */
3 /*
4 * most of the following code was imported from dev/ic/i82557.c; the
5 * original copyright notice is as below.
6 */
8 /*-
9 * Copyright (c) 1997, 1998, 1999, 2001, 2002 The NetBSD Foundation, Inc.
10 * All rights reserved.
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
14 * NASA Ames Research Center.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright (c) 1995, David Greenman
40 * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org>
41 * All rights reserved.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice unmodified, this list of conditions, and the following
48 * disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
65 * Id: if_fxp.c,v 1.113 2001/05/17 23:50:24 jlemon
68 #include <sys/param.h>
70 #include <netinet/in.h>
71 #include <netinet/in_systm.h>
73 #include <lib/libsa/stand.h>
74 #include <lib/libsa/net.h>
76 #include <dev/ic/i82557reg.h>
78 #include "globals.h"
80 #define FRAMESIZE 1536
83 * 82559ER 8086.1209/1229
85 * - reverse endian access for 16bit/32bit register.
86 * - no vtophys() translation, vaddr_t == paddr_t.
87 * - PIPT writeback cache aware.
89 #define CSR_WRITE_1(l, r, v) *(volatile uint8_t *)((l)->iobase+(r)) = (v)
90 #define CSR_READ_1(l, r) *(volatile uint8_t *)((l)->iobase+(r))
91 #define CSR_WRITE_2(l, r, v) out16rb((l)->iobase+(r), (v))
92 #define CSR_READ_2(l, r) in16rb((l)->iobase+(r))
93 #define CSR_WRITE_4(l, r, v) out32rb((l)->iobase+(r), (v))
94 #define CSR_READ_4(l, r) in32rb((l)->iobase+(r))
95 #define VTOPHYS(va) (uint32_t)(va)
96 #define DEVTOV(pa) (uint32_t)(pa)
97 #define wbinv(adr, siz) _wbinv(VTOPHYS(adr), (uint32_t)(siz))
98 #define inv(adr, siz) _inv(VTOPHYS(adr), (uint32_t)(siz))
99 #define DELAY(n) delay(n)
100 #define ALLOC(T,A) (T *)((unsigned)alloc(sizeof(T) + (A)) &~ ((A) - 1))
102 struct txdesc {
103 volatile uint16_t cb_status;
104 volatile uint16_t cb_command;
105 volatile uint32_t link_addr;
106 volatile uint32_t tbd_array_addr;
107 volatile uint16_t byte_count;
108 volatile uint8_t tx_threshold;
109 volatile uint8_t tbd_number;
110 volatile uint32_t tx_buf_addr0;
111 volatile uint32_t tx_buf_size0;
112 volatile uint32_t tx_buf_addr1;
113 volatile uint32_t tx_buf_size1;
114 }; /* mimic extended TxCB layout */
116 struct rxdesc {
117 volatile uint16_t rfa_status;
118 volatile uint16_t rfa_control;
119 volatile uint32_t link_addr;
120 volatile uint32_t rbd_addr;
121 volatile uint16_t actual_size;
122 volatile uint16_t size;
123 }; /* 16B rfa */
125 struct local {
126 struct txdesc txd;
127 uint8_t store[sizeof(struct rxdesc) + FRAMESIZE];
128 unsigned iobase;
129 unsigned eeprom_addr;
132 static void autosize_eeprom(struct local *);
133 static int read_eeprom(struct local *, int);
134 static void fxp_scb_wait(struct local *);
135 static int fxp_mdi_read(struct local *, int, int);
138 * Template for default configuration parameters.
139 * See struct fxp_cb_config for the bit definitions.
141 static uint8_t fxp_cb_config_template[] = {
142 0x0, 0x0, /* cb_status */
143 0x80, 0x2, /* cb_command */
144 0xff, 0xff, 0xff, 0xff, /* link_addr */
145 0x16, /* 0 */
146 0x8, /* 1 */
147 0x0, /* 2 */
148 0x0, /* 3 */
149 0x0, /* 4 */
150 0x80, /* 5 */
151 0xb2, /* 6 */
152 0x3, /* 7 */
153 0x1, /* 8 */
154 0x0, /* 9 */
155 0x26, /* 10 */
156 0x0, /* 11 */
157 0x60, /* 12 */
158 0x0, /* 13 */
159 0xf2, /* 14 */
160 0x48, /* 15 */
161 0x0, /* 16 */
162 0x40, /* 17 */
163 0xf3, /* 18 */
164 0x0, /* 19 */
165 0x3f, /* 20 */
166 0x5 /* 21 */
169 static struct fxp_cb_config store_cbc;
170 static struct fxp_cb_ias store_cbi;
173 fxp_match(unsigned tag, void *data)
175 unsigned v;
177 v = pcicfgread(tag, PCI_ID_REG);
178 switch (v) {
179 case PCI_DEVICE(0x8086, 0x1209):
180 case PCI_DEVICE(0x8086, 0x1229):
181 return 1;
183 return 0;
186 void *
187 fxp_init(unsigned tag, void *data)
189 struct local *sc;
190 uint8_t *en = data;
191 struct fxp_cb_config *cbp = &store_cbc;
192 struct fxp_cb_ias *cb_ias = &store_cbi;
193 struct rxdesc *rfa;
194 unsigned v, i;
196 sc = ALLOC(struct local, sizeof(struct txdesc)); /* desc alignment */
197 memset(sc, 0, sizeof(struct local));
198 sc->iobase = DEVTOV(pcicfgread(tag, 0x10)); /* use mem space */
200 CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
201 DELAY(100);
203 autosize_eeprom(sc);
204 v = read_eeprom(sc, 0); en[0] = v; en[1] = v >> 8;
205 v = read_eeprom(sc, 1); en[2] = v; en[3] = v >> 8;
206 v = read_eeprom(sc, 2); en[4] = v; en[5] = v >> 8;
208 printf("MAC address %02x:%02x:%02x:%02x:%02x:%02x, ",
209 en[0], en[1], en[2], en[3], en[4], en[5]);
211 printf("PHY %d (%04x.%04x)\n", fxp_mdi_read(sc, 1, 18),
212 fxp_mdi_read(sc, 1, 2), fxp_mdi_read(sc, 1, 3));
215 * Initialize base of CBL and RFA memory. Loading with zero
216 * sets it up for regular linear addressing.
218 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);
219 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
221 fxp_scb_wait(sc);
222 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
225 * This memcpy is kind of disgusting, but there are a bunch of must be
226 * zero and must be one bits in this structure and this is the easiest
227 * way to initialize them all to proper values.
229 memcpy(cbp, fxp_cb_config_template, sizeof(fxp_cb_config_template));
231 #define prm 0
232 #define phy_10Mbps_only 0
233 #define all_mcasts 0
234 cbp->cb_status = 0;
235 cbp->cb_command = htole16(FXP_CB_COMMAND_CONFIG |
236 FXP_CB_COMMAND_EL);
237 cbp->link_addr = -1; /* (no) next command */
238 cbp->byte_count = 22; /* (22) bytes to config */
239 cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */
240 cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */
241 cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */
242 cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */
243 cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */
244 cbp->dma_mbce = 0; /* (disable) dma max counters */
245 cbp->late_scb = 0; /* (don't) defer SCB update */
246 cbp->tno_int_or_tco_en = 0; /* (disable) tx not okay interrupt */
247 cbp->ci_int = 0; /* interrupt on CU not active */
248 cbp->save_bf = prm; /* save bad frames */
249 cbp->disc_short_rx = !prm; /* discard short packets */
250 cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */
251 cbp->mediatype = !phy_10Mbps_only; /* interface mode */
252 cbp->nsai = 1; /* (don't) disable source addr insert */
253 cbp->preamble_length = 2; /* (7 byte) preamble */
254 cbp->loopback = 0; /* (don't) loopback */
255 cbp->linear_priority = 0; /* (normal CSMA/CD operation) */
256 cbp->linear_pri_mode = 0; /* (wait after xmit only) */
257 cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */
258 cbp->promiscuous = prm; /* promiscuous mode */
259 cbp->bcast_disable = 0; /* (don't) disable broadcasts */
260 cbp->crscdt = 0; /* (CRS only) */
261 cbp->stripping = !prm; /* truncate rx packet to byte count */
262 cbp->padding = 1; /* (do) pad short tx packets */
263 cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */
264 cbp->force_fdx = 0; /* (don't) force full duplex */
265 cbp->fdx_pin_en = 1; /* (enable) FDX# pin */
266 cbp->multi_ia = 0; /* (don't) accept multiple IAs */
267 cbp->mc_all = all_mcasts;/* accept all multicasts */
268 #undef prm
269 #undef phy_10Mbps_only
270 #undef all_mcasts
272 wbinv(cbp, sizeof(*cbp));
273 fxp_scb_wait(sc);
274 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(cbp));
275 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
276 i = 1000;
277 while (!(le16toh(cbp->cb_status) & FXP_CB_STATUS_C) && --i > 0) {
278 DELAY(1);
279 inv(&cbp->cb_status, sizeof(cbp->cb_status));
281 if (i == 0)
282 printf("cbp config timeout\n");
285 * Initialize the station address.
287 cb_ias->cb_status = 0;
288 cb_ias->cb_command = htole16(FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL);
289 cb_ias->link_addr = -1;
290 memcpy(cb_ias->macaddr, en, 6);
293 * Start the IAS (Individual Address Setup) command/DMA.
295 wbinv(cb_ias, sizeof(*cb_ias));
296 fxp_scb_wait(sc);
297 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(cb_ias));
298 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
300 i = 1000;
301 while (!(le16toh(cb_ias->cb_status) & FXP_CB_STATUS_C) && --i > 0) {
302 DELAY(1);
303 inv(&cb_ias->cb_status, sizeof(cb_ias->cb_status));
305 if (i == 0)
306 printf("ias config timeout\n");
308 rfa = (struct rxdesc *)sc->store;
309 rfa->rfa_status = 0;
310 rfa->rfa_control = htole16(FXP_RFA_CONTROL_S);
311 rfa->link_addr = htole32(VTOPHYS(rfa));
312 rfa->rbd_addr = -1;
313 rfa->actual_size = 0;
314 rfa->size = htole16(sizeof(sc->store) - sizeof(struct rxdesc));
315 wbinv(rfa, sizeof(sc->store));
317 fxp_scb_wait(sc);
318 CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, VTOPHYS(rfa));
319 CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
321 return sc;
325 fxp_send(void *dev, char *buf, unsigned len)
327 struct local *l = dev;
328 struct txdesc *txd;
329 int loop;
331 if (len > 1520)
332 printf("fxp_send: len > 1520 (%u)\n", len);
334 txd = &l->txd;
335 txd->cb_status = 0;
336 txd->cb_command =
337 htole16(FXP_CB_COMMAND_XMIT|FXP_CB_COMMAND_SF|FXP_CB_COMMAND_EL);
338 txd->link_addr = -1;
339 txd->tbd_array_addr = htole32(VTOPHYS(&txd->tx_buf_addr0));
340 txd->tx_buf_addr0 = htole32(VTOPHYS(buf));
341 txd->tx_buf_size0 = htole32(len);
342 txd->byte_count = htole16(0x8000);
343 txd->tx_threshold = 0x20;
344 txd->tbd_number = 1;
345 wbinv(buf, len);
346 wbinv(txd, sizeof(*txd));
348 fxp_scb_wait(l);
349 CSR_WRITE_4(l, FXP_CSR_SCB_GENERAL, VTOPHYS(txd));
350 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
352 loop = 10000;
353 while (!(le16toh(txd->cb_status) & FXP_CB_STATUS_C) && --loop > 0) {
354 DELAY(1);
355 inv(txd, sizeof(struct txdesc));
357 if (loop == 0)
358 printf("send timeout\n");
360 return len;
364 fxp_recv(void *dev, char *buf, unsigned maxlen, unsigned timo)
366 struct local *l = dev;
367 struct rxdesc *rfa;
368 unsigned bound, ruscus, len;
370 fxp_scb_wait(l);
371 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
373 bound = 1000 * timo;
374 do {
375 ruscus = CSR_READ_1(l, FXP_CSR_SCB_RUSCUS);
376 if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_READY
377 && (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_SUSPENDED))
378 goto gotone;
379 DELAY(1000); /* 1 milli second */
380 } while (--bound > 0);
381 errno = 0;
382 return -1;
383 gotone:
384 rfa = (struct rxdesc *)l->store;
385 inv(rfa, sizeof(l->store)); /* whole including received frame */
386 if ((le16toh(rfa->rfa_status) & FXP_RFA_STATUS_C) == 0)
387 return 0;
388 len = le16toh(rfa->actual_size) & 0x7ff;
389 if (len > maxlen)
390 len = maxlen;
391 memcpy(buf, &l->store[sizeof(struct rxdesc)], len);
393 rfa->rfa_status = 0;
394 rfa->rfa_control = htole16(FXP_RFA_CONTROL_S);
395 rfa->actual_size = 0;
396 wbinv(rfa, sizeof(struct rxdesc));
397 #if 0
398 fxp_scb_wait(l);
399 CSR_WRITE_1(l, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
400 #endif
401 return len;
404 static void
405 eeprom_shiftin(struct local *sc, int data, int len)
407 uint16_t reg;
408 int x;
410 for (x = 1 << (len - 1); x != 0; x >>= 1) {
411 DELAY(40);
412 if (data & x)
413 reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
414 else
415 reg = FXP_EEPROM_EECS;
416 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
417 DELAY(40);
418 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
419 reg | FXP_EEPROM_EESK);
420 DELAY(40);
421 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
423 DELAY(40);
426 void
427 autosize_eeprom(struct local *sc)
429 int x;
431 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
432 DELAY(40);
434 /* Shift in read opcode. */
435 eeprom_shiftin(sc, FXP_EEPROM_OPC_READ, 3);
438 * Shift in address, wait for the dummy zero following a correct
439 * address shift.
441 for (x = 1; x <= 8; x++) {
442 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
443 DELAY(40);
444 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
445 FXP_EEPROM_EECS | FXP_EEPROM_EESK);
446 DELAY(40);
447 if ((CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) &
448 FXP_EEPROM_EEDO) == 0)
449 break;
450 DELAY(40);
451 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
452 DELAY(40);
454 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
455 DELAY(40);
456 if (x != 6 && x != 8)
457 printf("fxp: strange EEPROM address size (%d)\n", x);
458 else
459 sc->eeprom_addr = x;
462 static int
463 read_eeprom(struct local *sc, int offset)
465 uint16_t reg;
466 int x, val;
468 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
470 /* Shift in read opcode. */
471 eeprom_shiftin(sc, FXP_EEPROM_OPC_READ, 3);
473 /* Shift in address. */
474 eeprom_shiftin(sc, offset, sc->eeprom_addr);
476 reg = FXP_EEPROM_EECS;
477 val = 0;
479 * Shift out data.
481 for (x = 16; x > 0; x--) {
482 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL,
483 reg | FXP_EEPROM_EESK);
484 DELAY(1);
485 if (CSR_READ_2(sc, FXP_CSR_EEPROMCONTROL) &
486 FXP_EEPROM_EEDO)
487 val |= (1 << (x - 1));
488 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, reg);
489 DELAY(1);
491 CSR_WRITE_2(sc, FXP_CSR_EEPROMCONTROL, 0);
492 DELAY(1);
494 return val;
497 static void
498 fxp_scb_wait(struct local *sc)
500 int loop = 5000;
502 while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --loop > 0)
503 DELAY(2);
504 if (loop == 0)
505 printf("SCB timeout\n");
508 static int
509 fxp_mdi_read(struct local *sc, int phy, int reg)
511 int count = 10000;
512 int value;
514 CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,
515 (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21));
517 while (((value = CSR_READ_4(sc, FXP_CSR_MDICONTROL)) &
518 0x10000000) == 0 && count--)
519 DELAY(10);
521 if (count <= 0)
522 printf("fxp_mdi_read: timed out\n");
524 return (value & 0xffff);