1 /* $NetBSD: fxp.c,v 1.9 2008/05/14 23:14:11 nisimura Exp $ */
4 * most of the following code was imported from dev/ic/i82557.c; the
5 * original copyright notice is as below.
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
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
46 * 1. Redistributions of source code must retain the above copyright
47 * notice unmodified, this list of conditions, and the following
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
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>
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))
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 */
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
;
127 uint8_t store
[sizeof(struct rxdesc
) + FRAMESIZE
];
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 */
169 static struct fxp_cb_config store_cbc
;
170 static struct fxp_cb_ias store_cbi
;
173 fxp_match(unsigned tag
, void *data
)
177 v
= pcicfgread(tag
, PCI_ID_REG
);
179 case PCI_DEVICE(0x8086, 0x1209):
180 case PCI_DEVICE(0x8086, 0x1229):
187 fxp_init(unsigned tag
, void *data
)
191 struct fxp_cb_config
*cbp
= &store_cbc
;
192 struct fxp_cb_ias
*cb_ias
= &store_cbi
;
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
);
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
);
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
));
232 #define phy_10Mbps_only 0
235 cbp
->cb_command
= htole16(FXP_CB_COMMAND_CONFIG
|
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 */
269 #undef phy_10Mbps_only
272 wbinv(cbp
, sizeof(*cbp
));
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
);
277 while (!(le16toh(cbp
->cb_status
) & FXP_CB_STATUS_C
) && --i
> 0) {
279 inv(&cbp
->cb_status
, sizeof(cbp
->cb_status
));
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
));
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
);
301 while (!(le16toh(cb_ias
->cb_status
) & FXP_CB_STATUS_C
) && --i
> 0) {
303 inv(&cb_ias
->cb_status
, sizeof(cb_ias
->cb_status
));
306 printf("ias config timeout\n");
308 rfa
= (struct rxdesc
*)sc
->store
;
310 rfa
->rfa_control
= htole16(FXP_RFA_CONTROL_S
);
311 rfa
->link_addr
= htole32(VTOPHYS(rfa
));
313 rfa
->actual_size
= 0;
314 rfa
->size
= htole16(sizeof(sc
->store
) - sizeof(struct rxdesc
));
315 wbinv(rfa
, sizeof(sc
->store
));
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
);
325 fxp_send(void *dev
, char *buf
, unsigned len
)
327 struct local
*l
= dev
;
332 printf("fxp_send: len > 1520 (%u)\n", len
);
337 htole16(FXP_CB_COMMAND_XMIT
|FXP_CB_COMMAND_SF
|FXP_CB_COMMAND_EL
);
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;
346 wbinv(txd
, sizeof(*txd
));
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
);
353 while (!(le16toh(txd
->cb_status
) & FXP_CB_STATUS_C
) && --loop
> 0) {
355 inv(txd
, sizeof(struct txdesc
));
358 printf("send timeout\n");
364 fxp_recv(void *dev
, char *buf
, unsigned maxlen
, unsigned timo
)
366 struct local
*l
= dev
;
368 unsigned bound
, ruscus
, len
;
371 CSR_WRITE_1(l
, FXP_CSR_SCB_COMMAND
, FXP_SCB_COMMAND_RU_RESUME
);
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
))
379 DELAY(1000); /* 1 milli second */
380 } while (--bound
> 0);
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)
388 len
= le16toh(rfa
->actual_size
) & 0x7ff;
391 memcpy(buf
, &l
->store
[sizeof(struct rxdesc
)], len
);
394 rfa
->rfa_control
= htole16(FXP_RFA_CONTROL_S
);
395 rfa
->actual_size
= 0;
396 wbinv(rfa
, sizeof(struct rxdesc
));
399 CSR_WRITE_1(l
, FXP_CSR_SCB_COMMAND
, FXP_SCB_COMMAND_RU_RESUME
);
405 eeprom_shiftin(struct local
*sc
, int data
, int len
)
410 for (x
= 1 << (len
- 1); x
!= 0; x
>>= 1) {
413 reg
= FXP_EEPROM_EECS
| FXP_EEPROM_EEDI
;
415 reg
= FXP_EEPROM_EECS
;
416 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, reg
);
418 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
,
419 reg
| FXP_EEPROM_EESK
);
421 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, reg
);
427 autosize_eeprom(struct local
*sc
)
431 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, FXP_EEPROM_EECS
);
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
441 for (x
= 1; x
<= 8; x
++) {
442 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, FXP_EEPROM_EECS
);
444 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
,
445 FXP_EEPROM_EECS
| FXP_EEPROM_EESK
);
447 if ((CSR_READ_2(sc
, FXP_CSR_EEPROMCONTROL
) &
448 FXP_EEPROM_EEDO
) == 0)
451 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, FXP_EEPROM_EECS
);
454 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, 0);
456 if (x
!= 6 && x
!= 8)
457 printf("fxp: strange EEPROM address size (%d)\n", x
);
463 read_eeprom(struct local
*sc
, int offset
)
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
;
481 for (x
= 16; x
> 0; x
--) {
482 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
,
483 reg
| FXP_EEPROM_EESK
);
485 if (CSR_READ_2(sc
, FXP_CSR_EEPROMCONTROL
) &
487 val
|= (1 << (x
- 1));
488 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, reg
);
491 CSR_WRITE_2(sc
, FXP_CSR_EEPROMCONTROL
, 0);
498 fxp_scb_wait(struct local
*sc
)
502 while (CSR_READ_1(sc
, FXP_CSR_SCB_COMMAND
) && --loop
> 0)
505 printf("SCB timeout\n");
509 fxp_mdi_read(struct local
*sc
, int phy
, int reg
)
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
--)
522 printf("fxp_mdi_read: timed out\n");
524 return (value
& 0xffff);