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