1 /* $NetBSD: tlp.c,v 1.23 2009/07/03 10:31:19 nisimura Exp $ */
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/param.h>
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
37 #include <lib/libsa/stand.h>
38 #include <lib/libsa/net.h>
43 * - reverse endian access for CSR register.
44 * - no vtophys() translation, vaddr_t == paddr_t.
45 * - PIPT writeback cache aware.
47 #define CSR_READ(l, r) in32rb((l)->csr+(r))
48 #define CSR_WRITE(l, r, v) out32rb((l)->csr+(r), (v))
49 #define VTOPHYS(va) (uint32_t)(va)
50 #define DEVTOV(pa) (uint32_t)(pa)
51 #define wbinv(adr, siz) _wbinv(VTOPHYS(adr), (uint32_t)(siz))
52 #define inv(adr, siz) _inv(VTOPHYS(adr), (uint32_t)(siz))
53 #define DELAY(n) delay(n)
54 #define ALLOC(T,A) (T *)((unsigned)alloc(sizeof(T) + (A)) &~ ((A) - 1))
57 uint32_t xd0
, xd1
, xd2
, xd3
;
59 #define T0_OWN (1U<<31) /* desc is ready to tx */
60 #define T0_ES (1U<<15) /* Tx error summary */
61 #define T1_LS (1U<<30) /* last segment */
62 #define T1_FS (1U<<29) /* first segment */
63 #define T1_TER (1U<<25) /* end of ring mark */
64 #define T1_TCH (1U<<24) /* TDES3 points the next desc */
65 #define T1_TBS_MASK 0x7ff /* segment size 10:0 */
66 #define R0_OWN (1U<<31) /* desc is empty */
67 #define R0_FS (1U<<30) /* first desc of frame */
68 #define R0_LS (1U<<8) /* last desc of frame */
69 #define R0_ES (1U<<15) /* Rx error summary */
70 #define R1_RER (1U<<25) /* end of ring mark */
71 #define R1_RCH (1U<<24) /* RDES3 points the next desc */
72 #define R0_FLMASK 0x3fff0000 /* frame length 29:16 */
73 #define R1_RBS_MASK 0x7ff /* segment size 10:0 */
75 #define PAR_CSR0 0x00 /* bus mode */
76 #define PAR_DEFAULTS 0x00001000 /* PDF sez it should be ... */
78 #define TDR_CSR1 0x08 /* T0_OWN poll demand */
79 #define RDR_CSR2 0x10 /* R0_OWN poll demand */
80 #define RDB_CSR3 0x18 /* Rx descriptor base */
81 #define TDB_CSR4 0x20 /* Tx descriptor base */
82 #define SR_CSR5 0x28 /* interrupt stauts */
83 #define NAR_CSR6 0x30 /* operation mode */
84 #define NAR_NOSQE (1U<<19) /* _not_ use SQE signal */
85 #define NAR_TEN (1U<<13) /* instruct start/stop Tx */
86 #define NAR_REN (1U<< 1) /* instruct start/stop Rx */
87 #define IER_CSR7 0x38 /* interrupt enable mask */
88 #define SPR_CSR9 0x48 /* SEEPROM and MII management */
89 #define MII_MDI (1U<<19) /* 0/1 presense after read op */
90 #define MII_MIDIR (1U<<18) /* 1 for PHY->HOST */
91 #define MII_MDO (1U<<17) /* 0/1 for write op */
92 #define MII_MDC (1U<<16) /* MDIO clock */
93 #define SROM_RD (1U<<14) /* read operation */
94 #define SROM_WR (1U<<13) /* write openration */
95 #define SROM_SR (1U<<11) /* SEEPROM select */
96 #define PAR0_CSR25 0xa4 /* MAC 3:0 */
97 #define PAR1_CSR26 0xa8 /* MAC 5:4 */
98 #define AN_OMODE 0xfc /* operation mode */
100 #define FRAMESIZE 1536
105 uint8_t rxstore
[2][FRAMESIZE
];
106 unsigned csr
, omr
, tx
, rx
;
107 unsigned phy
, bmsr
, anlpar
;
110 static unsigned mii_read(struct local
*, int, int);
111 static void mii_write(struct local
*, int, int, int);
112 static void mii_initphy(struct local
*);
113 static void mii_dealan(struct local
*, unsigned);
116 tlp_match(unsigned tag
, void *data
)
120 v
= pcicfgread(tag
, PCI_ID_REG
);
122 case PCI_DEVICE(0x1317, 0x0985): /* ADMTek/Infineon 983B/BX */
129 tlp_init(unsigned tag
, void *data
)
132 struct desc
*txd
, *rxd
;
133 unsigned i
, val
, fdx
;
136 l
= ALLOC(struct local
, 2 * sizeof(struct desc
)); /* desc alignment */
137 memset(l
, 0, sizeof(struct local
));
138 l
->csr
= DEVTOV(pcicfgread(tag
, 0x14)); /* use mem space */
140 CSR_WRITE(l
, PAR_CSR0
, PAR_SWR
);
144 } while (i
-- > 0 && (CSR_READ(l
, PAR_CSR0
) & PAR_SWR
) != 0);
145 CSR_WRITE(l
, PAR_CSR0
, PAR_DEFAULTS
);
148 CSR_WRITE(l
, NAR_CSR6
, l
->omr
);
149 CSR_WRITE(l
, SR_CSR5
, ~0);
150 CSR_WRITE(l
, IER_CSR7
, 0);
153 val
= CSR_READ(l
, PAR0_CSR25
);
155 en
[1] = (val
>> 8) & 0xff;
156 en
[2] = (val
>> 16) & 0xff;
157 en
[3] = (val
>> 24) & 0xff;
158 val
= CSR_READ(l
, PAR1_CSR26
);
160 en
[5] = (val
>> 8) & 0xff;
162 printf("MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
163 en
[0], en
[1], en
[2], en
[3], en
[4], en
[5]);
169 val
= CSR_READ(l
, AN_OMODE
);
170 if (val
& (1U << 29)) {
171 printf("%s", (val
& (1U << 31)) ? "100Mbps" : "10Mbps");
172 fdx
= !!(val
& (1U << 30));
179 txd
[1].xd1
= htole32(T1_TER
);
181 rxd
[0].xd0
= htole32(R0_OWN
);
182 rxd
[0].xd1
= htole32(FRAMESIZE
);
183 rxd
[0].xd2
= htole32(VTOPHYS(l
->rxstore
[0]));
184 rxd
[1].xd0
= htole32(R0_OWN
);
185 rxd
[1].xd1
= htole32(R1_RER
| FRAMESIZE
);
186 rxd
[1].xd2
= htole32(VTOPHYS(l
->rxstore
[1]));
189 /* make sure the entire descriptors transfered to memory */
190 wbinv(l
, sizeof(struct local
));
192 CSR_WRITE(l
, TDB_CSR4
, VTOPHYS(txd
));
193 CSR_WRITE(l
, RDB_CSR3
, VTOPHYS(rxd
));
196 CSR_WRITE(l
, NAR_CSR6
, l
->omr
| NAR_TEN
| NAR_REN
);
202 tlp_send(void *dev
, char *buf
, unsigned len
)
204 struct local
*l
= dev
;
205 volatile struct desc
*txd
;
206 unsigned txstat
, loop
;
209 txd
= &l
->txd
[l
->tx
];
210 txd
->xd2
= htole32(VTOPHYS(buf
));
211 txd
->xd1
&= htole32(T1_TER
);
212 txd
->xd1
|= htole32(T1_FS
| T1_LS
| (len
& T1_TBS_MASK
));
213 txd
->xd0
= htole32(T0_OWN
);
214 wbinv(txd
, sizeof(struct desc
));
215 CSR_WRITE(l
, TDR_CSR1
, 01);
218 txstat
= le32toh(txd
->xd0
);
219 if ((txstat
& T0_OWN
) == 0)
222 inv(txd
, sizeof(struct desc
));
223 } while (--loop
!= 0);
224 printf("xmit failed\n");
232 tlp_recv(void *dev
, char *buf
, unsigned maxlen
, unsigned timo
)
234 struct local
*l
= dev
;
235 volatile struct desc
*rxd
;
236 unsigned bound
, rxstat
, len
;
241 printf("recving with %u sec. timeout\n", timo
);
244 rxd
= &l
->rxd
[l
->rx
];
246 inv(rxd
, sizeof(struct desc
));
247 rxstat
= le32toh(rxd
->xd0
);
248 if ((rxstat
& R0_OWN
) == 0)
250 DELAY(1000); /* 1 milli second */
251 } while (--bound
> 0);
255 if (rxstat
& R0_ES
) {
256 rxd
->xd0
= htole32(R0_OWN
);
257 wbinv(rxd
, sizeof(struct desc
));
262 len
= ((rxstat
& R0_FLMASK
) >> 16) - 4 /* HASFCS */;
265 ptr
= l
->rxstore
[l
->rx
];
267 memcpy(buf
, ptr
, len
);
268 rxd
->xd0
= htole32(R0_OWN
);
269 wbinv(rxd
, sizeof(struct desc
));
275 * bare MII access with bitbang'ing
277 #define R110 6 /* SEEPROM/MDIO read op */
278 #define W101 5 /* SEEPROM/MDIO write op */
279 #define CS (1U << 0) /* hold chip select */
280 #define CLK (1U << 1) /* clk bit */
281 #define D1 (1U << 2) /* bit existence */
282 #define VV (1U << 3) /* taken 0/1 from SEEPROM */
285 mii_read(struct local
*l
, int phy
, int reg
)
287 unsigned data
, rv
, v
, i
;
289 data
= (R110
<< 10) | (phy
<< 5) | reg
;
290 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
);
291 for (i
= 0; i
< 32; i
++) {
292 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
| MII_MDC
);
294 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
);
297 CSR_WRITE(l
, SPR_CSR9
, 0);
298 v
= 0; /* 4OP + 5ADDR + 5REG */
299 for (i
= (1 << 13); i
!= 0; i
>>= 1) {
304 CSR_WRITE(l
, SPR_CSR9
, v
);
306 CSR_WRITE(l
, SPR_CSR9
, v
| MII_MDC
);
308 CSR_WRITE(l
, SPR_CSR9
, v
);
311 rv
= 0; /* 2TA + 16MDI */
312 for (i
= 0; i
< 18; i
++) {
313 CSR_WRITE(l
, SPR_CSR9
, MII_MIDIR
);
315 rv
= (rv
<< 1) | !!(CSR_READ(l
, SPR_CSR9
) & MII_MDI
);
316 CSR_WRITE(l
, SPR_CSR9
, MII_MIDIR
| MII_MDC
);
319 CSR_WRITE(l
, SPR_CSR9
, 0);
324 mii_write(struct local
*l
, int phy
, int reg
, int val
)
328 data
= (W101
<< 28) | (phy
<< 23) | (reg
<< 18) | (02 << 16);
329 data
|= val
& 0xffff;
330 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
);
331 for (i
= 0; i
< 32; i
++) {
332 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
| MII_MDC
);
334 CSR_WRITE(l
, SPR_CSR9
, MII_MDO
);
337 CSR_WRITE(l
, SPR_CSR9
, 0);
338 v
= 0; /* 4OP + 5ADDR + 5REG + 2TA + 16DATA */
339 for (i
= (1 << 31); i
!= 0; i
>>= 1) {
344 CSR_WRITE(l
, SPR_CSR9
, v
);
346 CSR_WRITE(l
, SPR_CSR9
, v
| MII_MDC
);
348 CSR_WRITE(l
, SPR_CSR9
, v
);
351 CSR_WRITE(l
, SPR_CSR9
, 0);
354 #define MII_BMCR 0x00 /* Basic mode control register (rw) */
355 #define BMCR_RESET 0x8000 /* reset */
356 #define BMCR_AUTOEN 0x1000 /* autonegotiation enable */
357 #define BMCR_ISO 0x0400 /* isolate */
358 #define BMCR_STARTNEG 0x0200 /* restart autonegotiation */
359 #define MII_BMSR 0x01 /* Basic mode status register (ro) */
360 #define BMSR_ACOMP 0x0020 /* Autonegotiation complete */
361 #define BMSR_LINK 0x0004 /* Link status */
362 #define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */
363 #define ANAR_FC 0x0400 /* local device supports PAUSE */
364 #define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */
365 #define ANAR_TX 0x0080 /* local device supports 100bTx */
366 #define ANAR_10_FD 0x0040 /* local device supports 10bT FD */
367 #define ANAR_10 0x0020 /* local device supports 10bT */
368 #define ANAR_CSMA 0x0001 /* protocol selector CSMA/CD */
369 #define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
372 mii_initphy(struct local
*l
)
374 int phy
, ctl
, sts
, bound
;
376 for (phy
= 0; phy
< 32; phy
++) {
377 ctl
= mii_read(l
, phy
, MII_BMCR
);
378 sts
= mii_read(l
, phy
, MII_BMSR
);
379 if (ctl
!= 0xffff && sts
!= 0xffff)
382 printf("MII: no PHY found\n");
385 ctl
= mii_read(l
, phy
, MII_BMCR
);
386 mii_write(l
, phy
, MII_BMCR
, ctl
| BMCR_RESET
);
390 ctl
= mii_read(l
, phy
, MII_BMCR
);
392 printf("MII: PHY %d has died after reset\n", phy
);
395 } while (bound
-- > 0 && (ctl
& BMCR_RESET
));
397 printf("PHY %d reset failed\n", phy
);
400 mii_write(l
, phy
, MII_BMCR
, ctl
);
401 sts
= mii_read(l
, phy
, MII_BMSR
) |
402 mii_read(l
, phy
, MII_BMSR
); /* read twice */
408 mii_dealan(struct local
*l
, unsigned timo
)
410 unsigned anar
, bound
;
412 anar
= ANAR_TX_FD
| ANAR_TX
| ANAR_10_FD
| ANAR_10
| ANAR_CSMA
;
413 mii_write(l
, l
->phy
, MII_ANAR
, anar
);
414 mii_write(l
, l
->phy
, MII_BMCR
, BMCR_AUTOEN
| BMCR_STARTNEG
);
416 bound
= getsecs() + timo
;
418 l
->bmsr
= mii_read(l
, l
->phy
, MII_BMSR
) |
419 mii_read(l
, l
->phy
, MII_BMSR
); /* read twice */
420 if ((l
->bmsr
& BMSR_LINK
) && (l
->bmsr
& BMSR_ACOMP
)) {
421 l
->anlpar
= mii_read(l
, l
->phy
, MII_ANLPAR
);
425 } while (getsecs() < bound
);