1 /* $NetBSD: i82557.c,v 1.11 2008/12/14 18:46:33 christos Exp $ */
4 * Copyright (c) 1998, 1999
5 * Matthias Drochner. All rights reserved.
6 * Copyright (c) 1995, David Greenman
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
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
32 #include <sys/types.h>
33 #include <machine/pio.h>
35 #include <dev/ic/i82557reg.h>
37 #include <lib/libsa/stand.h>
42 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
43 #include <lib/libkern/libkern.h>
49 #define RECVBUF_SIZE 1600 /* struct fxp_rfa + packet */
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
;
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);
78 static void fxp_checkintr(char *);
80 #define fxp_checkintr(x)
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 */
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)
127 #if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
128 static struct btinfo_netif bi_netif
;
132 * Wait for the previous command to be accepted (but not necessarily
140 while (CSR_READ_1(FXP_CSR_SCB_COMMAND
) && --i
)
143 printf("fxp: WARNING: SCB timed out!\n");
148 fxp_checkintr(char *msg
)
154 statack
= CSR_READ_1(FXP_CSR_SCB_STATACK
);
155 } while ((statack
== 0) && (--i
> 0));
158 CSR_WRITE_1(FXP_CSR_SCB_STATACK
, statack
);
159 printf("%s: ack'd irq %x, i=%d\n", msg
, statack
, i
);
165 EtherInit(unsigned char *myadr
)
170 volatile struct fxp_cb_config
*cbp
;
171 volatile struct fxp_cb_ias
*cb_ias
;
175 printf("pcicheck failed\n");
179 if (pcifinddev(0x8086, 0x1229, &mytag
)) {
184 pcicfgread(&mytag
, 0, &id
);
185 if (id
!= 0x12298086) {
191 pcicfgread(&mytag
, FXP_PCI_IOBA
, &iobase
);
195 dmamem
= mapmem(DMABASE
, DMASIZE
);
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
);
210 CSR_WRITE_1(FXP_CSR_SCB_COMMAND
, FXP_SCB_COMMAND_RU_BASE
);
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
));
222 #define phy_10Mbps_only 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 */
258 #undef phy_10Mbps_only
262 * Start the config command/DMA.
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. */
269 while (!(cbp
->cb_status
& FXP_CB_STATUS_C
) && (--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.
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. */
294 while (!(cb_ias
->cb_status
& FXP_CB_STATUS_C
) && (--i
> 0))
297 printf("ias timeout");
299 fxp_checkintr("ias");
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
));
319 * Issue software reset
321 CSR_WRITE_4(FXP_CSR_PORT
, FXP_PORT_SELECTIVE_RESET
);
326 EtherSend(char *pkt
, int len
)
328 volatile struct fxp_cb_tx
*txp
;
330 static volatile struct fxp_tbd tbd
;
332 volatile struct fxp_tbd
*tbdp
;
338 txp
->tbd_array_addr
= vtophys((void *)&tbd
);
339 tbdp
->tb_addr
= vtophys(pkt
);
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;
351 FXP_CB_COMMAND_XMIT
| FXP_CB_COMMAND_SF
| FXP_CB_COMMAND_EL
;
352 txp
->tx_threshold
= tx_threshold
;
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. */
362 while (!(txp
->cb_status
& FXP_CB_STATUS_C
) && (--i
> 0))
365 printf("send timeout");
367 fxp_checkintr("send");
373 fxp_startreceiver(void)
375 volatile struct fxp_rfa
*rfa
;
379 rfa
->size
= RECVBUF_SIZE
- sizeof(struct fxp_rfa
);
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
));
386 memcpy((void *)&rfa
->rbd_addr
, &v
, sizeof(v
));
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
)
397 volatile struct fxp_rfa
*rfa
;
400 ruscus
= CSR_READ_1(FXP_CSR_SCB_RUSCUS
);
401 if (((ruscus
>> 2) & 0x0f) == FXP_SCB_RUS_READY
)
403 if (((ruscus
>> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED
) {
404 printf("rcv: ruscus=%x\n", ruscus
);
409 if (rfa
->rfa_status
& FXP_RFA_STATUS_C
) {
410 len
= rfa
->actual_size
& 0x7ff;
412 memcpy(pkt
, (char *) rfa
+ RFA_SIZE
, maxlen
);
414 printf("rfa status=%x, len=%x\n",
415 rfa
->rfa_status
, len
);
422 CSR_WRITE_1(FXP_CSR_SCB_COMMAND
, FXP_SCB_COMMAND_RU_RESUME
);
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.
435 fxp_read_eeprom(uint16_t *data
, int offset
, int words
)
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
;
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
);
455 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL
, reg
);
461 for (x
= 6; x
> 0; x
--) {
462 if ((i
+ offset
) & (1 << (x
- 1))) {
463 reg
= FXP_EEPROM_EECS
| FXP_EEPROM_EEDI
;
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
);
471 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL
, reg
);
474 reg
= FXP_EEPROM_EECS
;
479 for (x
= 16; x
> 0; x
--) {
480 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL
,
481 reg
| FXP_EEPROM_EESK
);
483 if (CSR_READ_2(FXP_CSR_EEPROMCONTROL
) &
485 data
[i
] |= (1 << (x
- 1));
486 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL
, reg
);
489 CSR_WRITE_2(FXP_CSR_EEPROMCONTROL
, 0);