1 /* $NetBSD: sme.c,v 1.1 2008/05/31 01:43:57 nisimura Exp $ */
4 * Copyright (c) 2008 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 every CSR.
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) /* */
60 #define T0_ES (1U<<15) /* error summary */
61 #define T0_FL 0x7fff0000 /* frame length */
62 #define T1_LS (1U<<30) /* last descriptor of Tx frame */
63 #define T1_FS (1U<<29) /* first descriptor of Tx frame */
64 #define T1_TER (1U<<25) /* wrap mark to form a ring */
65 #define T1_TCH (1U<<24) /* TDES3 points the next desc */
66 #define T1_FL 0x00007ff /* Tx frame/segment length */
67 #define R0_OWN (1U<<31) /* */
68 #define R0_FL 0x3fff0000 /* frame length */
69 #define R0_ES (1U<<15) /* error summary */
70 #define R1_RER (1U<<25) /* wrap mark to form a ring */
71 #define R1_RCH (1U<<24) /* RDES3 points the next desc */
72 /* RDES1 will be never changed while operation */
75 #define TXPOLLD 0x04 /* start transmission */
76 #define RXPOLLD 0x08 /* start receiving */
77 #define RXDBASE 0x0c /* Rx descriptor list base */
78 #define TXDBASE 0x10 /* Tx descriptor list base */
79 #define DMACCTL 0x18 /* DMAC control */
80 #define DMACCTL_ST (1U<<13) /* start/stop Tx DMA */
81 #define DMACCTL_SR (1U<< 1) /* start/stop Rx DMA */
82 #define MAC_CR 0x80 /* MAC control */
83 #define MACCR_FDPX (1U<<20) /* full duplex operation */
84 #define MACCR_TXEN (1U<< 3) /* enable xmit */
85 #define MACCR_RXEN (1U<< 2) /* enable recv */
86 #define ADDRH 0x84 /* ea 5:4 */
87 #define ADDRL 0x88 /* ea 3:0 */
88 #define MIIADDR 0x94 /* MII control */
89 #define MIIDATA 0x98 /* MII data */
91 #define FRAMESIZE 1536
96 uint8_t rxstore
[2][FRAMESIZE
];
98 unsigned phy
, bmsr
, anlpar
;
101 static int mii_read(struct local
*, int, int);
102 static void mii_write(struct local
*, int, int, int);
103 static void mii_dealan(struct local
*, unsigned);
106 sme_match(unsigned tag
, void *data
)
110 v
= pcicfgread(tag
, PCI_ID_REG
);
112 case PCI_DEVICE(0x1055, 0xe940):
119 sme_init(unsigned tag
, void *data
)
122 struct desc
*txd
, *rxd
;
123 unsigned mac32
, mac16
, val
, fdx
;
126 l
= ALLOC(struct local
, sizeof(struct desc
)); /* desc alignment */
127 memset(l
, 0, sizeof(struct local
));
128 l
->csr
= DEVTOV(pcicfgread(tag
, 0x1c)); /* BAR3 mem space, LE */
129 l
->phy
= 1; /* 9420 internal PHY */
132 mac32
= CSR_READ(l
, ADDRL
);
133 mac16
= CSR_READ(l
, ADDRH
);
141 printf("MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
142 en
[0], en
[1], en
[2], en
[3], en
[4], en
[5]);
143 printf("PHY %d (%04x.%04x)\n", l
->phy
,
144 mii_read(l
, l
->phy
, 2), mii_read(l
, l
->phy
, 3));
149 /* speed and duplexity can be seen in MII 31 */
150 val
= mii_read(l
, l
->phy
, 31);
151 fdx
= !!(val
& (1U << 4));
152 printf("%s", (val
& (1U << 3)) ? "100Mbps" : "10Mbps");
159 rxd
[0].xd0
= htole32(R0_OWN
);
160 rxd
[0].xd1
= htole32(R1_RCH
| FRAMESIZE
);
161 rxd
[0].xd2
= htole32(VTOPHYS(l
->rxstore
[0]));
162 rxd
[0].xd3
= htole32(VTOPHYS(&rxd
[1]));
163 rxd
[1].xd0
= htole32(R0_OWN
);
164 rxd
[1].xd1
= htole32(R1_RER
| FRAMESIZE
);
165 rxd
[1].xd2
= htole32(VTOPHYS(l
->rxstore
[1]));
166 /* R1_RER neglects xd3 */
169 wbinv(l
, sizeof(struct local
));
171 CSR_WRITE(l
, TXDBASE
, VTOPHYS(txd
));
172 CSR_WRITE(l
, RXDBASE
, VTOPHYS(rxd
));
173 val
= MACCR_TXEN
| MACCR_RXEN
;
176 CSR_WRITE(l
, BUSMODE
, 0);
177 CSR_WRITE(l
, DMACCTL
, DMACCTL_ST
| DMACCTL_SR
);
178 CSR_WRITE(l
, MAC_CR
, val
); /* (FDX), Tx/Rx enable */
179 CSR_WRITE(l
, RXPOLLD
, 01); /* start receiving */
185 sme_send(void *dev
, char *buf
, unsigned len
)
187 struct local
*l
= dev
;
188 volatile struct desc
*txd
;
189 unsigned txstat
, loop
;
191 /* send a single frame with no T1_TER|T1_TCH designation */
194 txd
->xd2
= htole32(VTOPHYS(buf
));
195 txd
->xd1
= htole32(T1_FS
| T1_LS
| (len
& T1_FL
));
196 txd
->xd0
= htole32(T0_OWN
| (len
& T0_FL
) << 16);
197 wbinv(txd
, sizeof(struct desc
));
198 CSR_WRITE(l
, TXPOLLD
, 01); /* start transmission */
201 txstat
= le32toh(txd
->xd0
);
204 if ((txstat
& T0_OWN
) == 0)
207 inv(txd
, sizeof(struct desc
));
208 } while (--loop
!= 0);
209 printf("xmit failed\n");
216 sme_recv(void *dev
, char *buf
, unsigned maxlen
, unsigned timo
)
218 struct local
*l
= dev
;
219 volatile struct desc
*rxd
;
220 unsigned bound
, rxstat
, len
;
224 printf("recving with %u sec. timeout\n", timo
);
226 rxd
= &l
->rxd
[l
->rx
];
228 inv(rxd
, sizeof(struct desc
));
229 rxstat
= le32toh(rxd
->xd0
);
230 if ((rxstat
& R0_OWN
) == 0)
232 DELAY(1000); /* 1 milli second */
233 } while (--bound
> 0);
237 if (rxstat
& R0_ES
) {
238 rxd
->xd0
= htole32(R0_OWN
);
239 wbinv(rxd
, sizeof(struct desc
));
241 CSR_WRITE(l
, RXPOLLD
, 01); /* restart receiving */
245 len
= (rxstat
& R0_FL
) >> 16 /* no FCS included */;
248 ptr
= l
->rxstore
[l
->rx
];
250 memcpy(buf
, ptr
, len
);
251 rxd
->xd0
= htole32(R0_OWN
);
252 wbinv(rxd
, sizeof(struct desc
));
254 CSR_WRITE(l
, RXPOLLD
, 01); /* necessary? */
258 #define MII_BMCR 0x00 /* Basic mode control register (rw) */
259 #define BMCR_RESET 0x8000 /* reset */
260 #define BMCR_AUTOEN 0x1000 /* autonegotiation enable */
261 #define BMCR_ISO 0x0400 /* isolate */
262 #define BMCR_STARTNEG 0x0200 /* restart autonegotiation */
263 #define MII_BMSR 0x01 /* Basic mode status register (ro) */
264 #define BMSR_ACOMP 0x0020 /* Autonegotiation complete */
265 #define BMSR_LINK 0x0004 /* Link status */
266 #define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */
267 #define ANAR_FC 0x0400 /* local device supports PAUSE */
268 #define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */
269 #define ANAR_TX 0x0080 /* local device supports 100bTx */
270 #define ANAR_10_FD 0x0040 /* local device supports 10bT FD */
271 #define ANAR_10 0x0020 /* local device supports 10bT */
272 #define ANAR_CSMA 0x0001 /* protocol selector CSMA/CD */
273 #define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
276 mii_read(struct local
*l
, int phy
, int reg
)
281 ctl
= CSR_READ(l
, MIIADDR
);
283 ctl
= (phy
<< 11) | (reg
<< 6) | (0 << 1); /* READ op */
284 CSR_WRITE(l
, MIIADDR
, ctl
);
286 ctl
= CSR_READ(l
, MIIADDR
);
288 return CSR_READ(l
, MIIDATA
);
292 mii_write(struct local
*l
, int phy
, int reg
, int val
)
297 ctl
= CSR_READ(l
, MIIADDR
);
299 ctl
= (phy
<< 11) | (reg
<< 6) | (1 << 1); /* WRITE op */
300 CSR_WRITE(l
, MIIDATA
, val
);
304 mii_dealan(struct local
*l
, unsigned timo
)
306 unsigned anar
, bound
;
308 anar
= ANAR_TX_FD
| ANAR_TX
| ANAR_10_FD
| ANAR_10
| ANAR_CSMA
;
309 mii_write(l
, l
->phy
, MII_ANAR
, anar
);
310 mii_write(l
, l
->phy
, MII_BMCR
, BMCR_AUTOEN
| BMCR_STARTNEG
);
312 bound
= getsecs() + timo
;
314 l
->bmsr
= mii_read(l
, l
->phy
, MII_BMSR
) |
315 mii_read(l
, l
->phy
, MII_BMSR
); /* read twice */
316 if ((l
->bmsr
& BMSR_LINK
) && (l
->bmsr
& BMSR_ACOMP
)) {
317 l
->anlpar
= mii_read(l
, l
->phy
, MII_ANLPAR
);
321 } while (getsecs() < bound
);