if_sip.c revision 1.1.2.1 1 1.1.2.1 thorpej /* $NetBSD: if_sip.c,v 1.1.2.1 1999/06/21 01:18:34 thorpej Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*-
4 1.1 thorpej * Copyright (c) 1999 Network Computer, Inc.
5 1.1 thorpej * All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * Redistribution and use in source and binary forms, with or without
8 1.1 thorpej * modification, are permitted provided that the following conditions
9 1.1 thorpej * are met:
10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
11 1.1 thorpej * notice, this list of conditions and the following disclaimer.
12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
14 1.1 thorpej * documentation and/or other materials provided with the distribution.
15 1.1 thorpej * 3. Neither the name of Network Computer, Inc. nor the names of its
16 1.1 thorpej * contributors may be used to endorse or promote products derived
17 1.1 thorpej * from this software without specific prior written permission.
18 1.1 thorpej *
19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS
20 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE.
30 1.1 thorpej */
31 1.1 thorpej
32 1.1 thorpej /*
33 1.1 thorpej * Device driver for the Silicon Integrated Systems SiS900 10/100 PCI
34 1.1 thorpej * Ethernet controller.
35 1.1 thorpej *
36 1.1 thorpej * Written by Jason R. Thorpe for Network Computer, Inc.
37 1.1 thorpej */
38 1.1 thorpej
39 1.1 thorpej #include "opt_inet.h"
40 1.1 thorpej #include "opt_ns.h"
41 1.1 thorpej #include "bpfilter.h"
42 1.1 thorpej
43 1.1 thorpej #include <sys/param.h>
44 1.1 thorpej #include <sys/systm.h>
45 1.1 thorpej #include <sys/mbuf.h>
46 1.1 thorpej #include <sys/malloc.h>
47 1.1 thorpej #include <sys/kernel.h>
48 1.1 thorpej #include <sys/socket.h>
49 1.1 thorpej #include <sys/ioctl.h>
50 1.1 thorpej #include <sys/errno.h>
51 1.1 thorpej #include <sys/device.h>
52 1.1 thorpej #include <sys/queue.h>
53 1.1 thorpej
54 1.1 thorpej #include <vm/vm.h> /* for PAGE_SIZE */
55 1.1 thorpej
56 1.1 thorpej #include <net/if.h>
57 1.1 thorpej #include <net/if_dl.h>
58 1.1 thorpej #include <net/if_media.h>
59 1.1 thorpej #include <net/if_ether.h>
60 1.1 thorpej
61 1.1 thorpej #if NBPFILTER > 0
62 1.1 thorpej #include <net/bpf.h>
63 1.1 thorpej #endif
64 1.1 thorpej
65 1.1 thorpej #ifdef INET
66 1.1 thorpej #include <netinet/in.h>
67 1.1 thorpej #include <netinet/if_inarp.h>
68 1.1 thorpej #endif
69 1.1 thorpej
70 1.1 thorpej #ifdef NS
71 1.1 thorpej #include <netns/ns.h>
72 1.1 thorpej #include <netns/ns_if.h>
73 1.1 thorpej #endif
74 1.1 thorpej
75 1.1 thorpej #include <machine/bus.h>
76 1.1 thorpej #include <machine/intr.h>
77 1.1 thorpej
78 1.1 thorpej #include <dev/mii/miivar.h>
79 1.1 thorpej
80 1.1 thorpej #include <dev/pci/pcireg.h>
81 1.1 thorpej #include <dev/pci/pcivar.h>
82 1.1 thorpej #include <dev/pci/pcidevs.h>
83 1.1 thorpej
84 1.1 thorpej #include <dev/pci/if_sipreg.h>
85 1.1 thorpej
86 1.1 thorpej /*
87 1.1 thorpej * Devices supported by this driver.
88 1.1 thorpej */
89 1.1 thorpej const struct sip_product {
90 1.1 thorpej pci_vendor_id_t sip_vendor;
91 1.1 thorpej pci_product_id_t sip_product;
92 1.1 thorpej const char *sip_name;
93 1.1 thorpej } sip_products[] = {
94 1.1 thorpej { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
95 1.1 thorpej "SiS 900 10/100 Ethernet" },
96 1.1 thorpej
97 1.1 thorpej { 0, 0,
98 1.1 thorpej NULL },
99 1.1 thorpej };
100 1.1 thorpej
101 1.1 thorpej /*
102 1.1 thorpej * Transmit descriptor list size. This is arbitrary, but allocate
103 1.1 thorpej * enough descriptors for 64 pending transmissions, and 16 segments
104 1.1 thorpej * per packet. This MUST work out to a power of 2.
105 1.1 thorpej */
106 1.1 thorpej #define SIP_NTXSEGS 16
107 1.1 thorpej
108 1.1 thorpej #define SIP_TXQUEUELEN 64
109 1.1 thorpej #define SIP_NTXDESC (SIP_TXQUEUELEN * SIP_NTXSEGS)
110 1.1 thorpej #define SIP_NTXDESC_MASK (SIP_NTXDESC - 1)
111 1.1 thorpej #define SIP_NEXTTX(x) (((x) + 1) & SIP_NTXDESC_MASK)
112 1.1 thorpej
113 1.1 thorpej /*
114 1.1 thorpej * Receive descriptor list size. We have one Rx buffer per incoming
115 1.1 thorpej * packet, so this logic is a little simpler.
116 1.1 thorpej */
117 1.1 thorpej #define SIP_NRXDESC 64
118 1.1 thorpej #define SIP_NRXDESC_MASK (SIP_NRXDESC - 1)
119 1.1 thorpej #define SIP_NEXTRX(x) (((x) + 1) & SIP_NRXDESC_MASK)
120 1.1 thorpej
121 1.1 thorpej /*
122 1.1 thorpej * Control structures are DMA'd to the SiS900 chip. We allocate them in
123 1.1 thorpej * a single clump that maps to a single DMA segment to make several things
124 1.1 thorpej * easier.
125 1.1 thorpej */
126 1.1 thorpej struct sip_control_data {
127 1.1 thorpej /*
128 1.1 thorpej * The transmit descriptors.
129 1.1 thorpej */
130 1.1 thorpej struct sip_desc scd_txdescs[SIP_NTXDESC];
131 1.1 thorpej
132 1.1 thorpej /*
133 1.1 thorpej * The receive descriptors.
134 1.1 thorpej */
135 1.1 thorpej struct sip_desc scd_rxdescs[SIP_NRXDESC];
136 1.1 thorpej };
137 1.1 thorpej
138 1.1 thorpej #define SIP_CDOFF(x) offsetof(struct sip_control_data, x)
139 1.1 thorpej #define SIP_CDTXOFF(x) SIP_CDOFF(scd_txdescs[(x)])
140 1.1 thorpej #define SIP_CDRXOFF(x) SIP_CDOFF(scd_rxdescs[(x)])
141 1.1 thorpej
142 1.1 thorpej /*
143 1.1 thorpej * Software state for transmit jobs.
144 1.1 thorpej */
145 1.1 thorpej struct sip_txsoft {
146 1.1 thorpej struct mbuf *txs_mbuf; /* head of our mbuf chain */
147 1.1 thorpej bus_dmamap_t txs_dmamap; /* our DMA map */
148 1.1 thorpej int txs_firstdesc; /* first descriptor in packet */
149 1.1 thorpej int txs_lastdesc; /* last descriptor in packet */
150 1.1 thorpej SIMPLEQ_ENTRY(sip_txsoft) txs_q;
151 1.1 thorpej };
152 1.1 thorpej
153 1.1 thorpej SIMPLEQ_HEAD(sip_txsq, sip_txsoft);
154 1.1 thorpej
155 1.1 thorpej /*
156 1.1 thorpej * Software state for receive jobs.
157 1.1 thorpej */
158 1.1 thorpej struct sip_rxsoft {
159 1.1 thorpej struct mbuf *rxs_mbuf; /* head of our mbuf chain */
160 1.1 thorpej bus_dmamap_t rxs_dmamap; /* our DMA map */
161 1.1 thorpej };
162 1.1 thorpej
163 1.1 thorpej /*
164 1.1 thorpej * Software state per device.
165 1.1 thorpej */
166 1.1 thorpej struct sip_softc {
167 1.1 thorpej struct device sc_dev; /* generic device information */
168 1.1 thorpej bus_space_tag_t sc_st; /* bus space tag */
169 1.1 thorpej bus_space_handle_t sc_sh; /* bus space handle */
170 1.1 thorpej bus_dma_tag_t sc_dmat; /* bus DMA tag */
171 1.1 thorpej struct ethercom sc_ethercom; /* ethernet common data */
172 1.1 thorpej void *sc_sdhook; /* shutdown hook */
173 1.1 thorpej
174 1.1 thorpej void *sc_ih; /* interrupt cookie */
175 1.1 thorpej
176 1.1 thorpej struct mii_data sc_mii; /* MII/media information */
177 1.1 thorpej
178 1.1 thorpej bus_dmamap_t sc_cddmamap; /* control data DMA map */
179 1.1 thorpej #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
180 1.1 thorpej
181 1.1 thorpej /*
182 1.1 thorpej * Software state for transmit and receive descriptors.
183 1.1 thorpej */
184 1.1 thorpej struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
185 1.1 thorpej struct sip_rxsoft sc_rxsoft[SIP_NRXDESC];
186 1.1 thorpej
187 1.1 thorpej /*
188 1.1 thorpej * Control data structures.
189 1.1 thorpej */
190 1.1 thorpej struct sip_control_data *sc_control_data;
191 1.1 thorpej #define sc_txdescs sc_control_data->scd_txdescs
192 1.1 thorpej #define sc_rxdescs sc_control_data->scd_rxdescs
193 1.1 thorpej
194 1.1 thorpej u_int32_t sc_txcfg; /* prototype TXCFG register */
195 1.1 thorpej u_int32_t sc_rxcfg; /* prototype RXCFG register */
196 1.1 thorpej u_int32_t sc_imr; /* prototype IMR register */
197 1.1 thorpej u_int32_t sc_rfcr; /* prototype RFCR register */
198 1.1 thorpej
199 1.1 thorpej u_int32_t sc_tx_fill_thresh; /* transmit fill threshold */
200 1.1 thorpej u_int32_t sc_tx_drain_thresh; /* transmit drain threshold */
201 1.1 thorpej
202 1.1 thorpej u_int32_t sc_rx_drain_thresh; /* receive drain threshold */
203 1.1 thorpej
204 1.1 thorpej int sc_flags; /* misc. flags; see below */
205 1.1 thorpej
206 1.1 thorpej int sc_txfree; /* number of free Tx descriptors */
207 1.1 thorpej int sc_txnext; /* next ready Tx descriptor */
208 1.1 thorpej
209 1.1 thorpej struct sip_txsq sc_txfreeq; /* free Tx descsofts */
210 1.1 thorpej struct sip_txsq sc_txdirtyq; /* dirty Tx descsofts */
211 1.1 thorpej
212 1.1 thorpej int sc_rxptr; /* next ready Rx descriptor/descsoft */
213 1.1 thorpej };
214 1.1 thorpej
215 1.1 thorpej /* sc_flags */
216 1.1 thorpej #define SIPF_PAUSED 0x00000001 /* paused (802.3x flow control) */
217 1.1 thorpej
218 1.1 thorpej #define SIP_CDTXADDR(sc, x) ((sc)->sc_cddma + SIP_CDTXOFF((x)))
219 1.1 thorpej #define SIP_CDRXADDR(sc, x) ((sc)->sc_cddma + SIP_CDRXOFF((x)))
220 1.1 thorpej
221 1.1 thorpej #define SIP_CDTXSYNC(sc, x, n, ops) \
222 1.1 thorpej do { \
223 1.1 thorpej int __x, __n; \
224 1.1 thorpej \
225 1.1 thorpej __x = (x); \
226 1.1 thorpej __n = (n); \
227 1.1 thorpej \
228 1.1 thorpej /* If it will wrap around, sync to the end of the ring. */ \
229 1.1 thorpej if ((__x + __n) > SIP_NTXDESC) { \
230 1.1 thorpej bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \
231 1.1 thorpej SIP_CDTXOFF(__x), sizeof(struct sip_desc) * \
232 1.1 thorpej (SIP_NTXDESC - __x), (ops)); \
233 1.1 thorpej __n -= (SIP_NTXDESC - __x); \
234 1.1 thorpej __x = 0; \
235 1.1 thorpej } \
236 1.1 thorpej \
237 1.1 thorpej /* Now sync whatever is left. */ \
238 1.1 thorpej bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \
239 1.1 thorpej SIP_CDTXOFF(__x), sizeof(struct sip_desc) * __n, (ops)); \
240 1.1 thorpej } while (0)
241 1.1 thorpej
242 1.1 thorpej #define SIP_CDRXSYNC(sc, x, ops) \
243 1.1 thorpej bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \
244 1.1 thorpej SIP_CDRXOFF((x)), sizeof(struct sip_desc), (ops))
245 1.1 thorpej
246 1.1 thorpej /*
247 1.1 thorpej * Note we rely on MCLBYTES being a power of two below.
248 1.1 thorpej */
249 1.1 thorpej #define SIP_INIT_RXDESC(sc, x) \
250 1.1 thorpej do { \
251 1.1 thorpej struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \
252 1.1 thorpej struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)]; \
253 1.1 thorpej \
254 1.1 thorpej __sipd->sipd_link = SIP_CDRXADDR((sc), SIP_NEXTRX((x))); \
255 1.1 thorpej __sipd->sipd_bufptr = __rxs->rxs_dmamap->dm_segs[0].ds_addr; \
256 1.1 thorpej __sipd->sipd_cmdsts = CMDSTS_INTR | \
257 1.1 thorpej ((MCLBYTES - 1) & CMDSTS_SIZE_MASK); \
258 1.1 thorpej SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
259 1.1 thorpej } while (0)
260 1.1 thorpej
261 1.1 thorpej void sip_start __P((struct ifnet *));
262 1.1 thorpej void sip_watchdog __P((struct ifnet *));
263 1.1 thorpej int sip_ioctl __P((struct ifnet *, u_long, caddr_t));
264 1.1 thorpej
265 1.1 thorpej void sip_shutdown __P((void *));
266 1.1 thorpej
267 1.1 thorpej void sip_reset __P((struct sip_softc *));
268 1.1 thorpej void sip_init __P((struct sip_softc *));
269 1.1 thorpej void sip_stop __P((struct sip_softc *));
270 1.1 thorpej int sip_add_rxbuf __P((struct sip_softc *, int));
271 1.1 thorpej void sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
272 1.1 thorpej void sip_set_filter __P((struct sip_softc *));
273 1.1 thorpej void sip_tick __P((void *));
274 1.1 thorpej
275 1.1 thorpej int sip_intr __P((void *));
276 1.1 thorpej void sip_txintr __P((struct sip_softc *));
277 1.1 thorpej void sip_rxintr __P((struct sip_softc *));
278 1.1 thorpej
279 1.1 thorpej int sip_mii_readreg __P((struct device *, int, int));
280 1.1 thorpej void sip_mii_writereg __P((struct device *, int, int, int));
281 1.1 thorpej void sip_mii_statchg __P((struct device *));
282 1.1 thorpej
283 1.1 thorpej int sip_mediachange __P((struct ifnet *));
284 1.1 thorpej void sip_mediastatus __P((struct ifnet *, struct ifmediareq *));
285 1.1 thorpej
286 1.1 thorpej int sip_match __P((struct device *, struct cfdata *, void *));
287 1.1 thorpej void sip_attach __P((struct device *, struct device *, void *));
288 1.1 thorpej
289 1.1 thorpej struct cfattach sip_ca = {
290 1.1 thorpej sizeof(struct sip_softc), sip_match, sip_attach,
291 1.1 thorpej };
292 1.1 thorpej
293 1.1 thorpej const struct sip_product *sip_lookup __P((const struct pci_attach_args *));
294 1.1 thorpej
295 1.1 thorpej const struct sip_product *
296 1.1 thorpej sip_lookup(pa)
297 1.1 thorpej const struct pci_attach_args *pa;
298 1.1 thorpej {
299 1.1 thorpej const struct sip_product *sip;
300 1.1 thorpej
301 1.1 thorpej for (sip = sip_products; sip->sip_name != NULL; sip++) {
302 1.1 thorpej if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&
303 1.1 thorpej PCI_PRODUCT(pa->pa_id) == sip->sip_product)
304 1.1 thorpej return (sip);
305 1.1 thorpej }
306 1.1 thorpej return (NULL);
307 1.1 thorpej }
308 1.1 thorpej
309 1.1 thorpej int
310 1.1 thorpej sip_match(parent, cf, aux)
311 1.1 thorpej struct device *parent;
312 1.1 thorpej struct cfdata *cf;
313 1.1 thorpej void *aux;
314 1.1 thorpej {
315 1.1 thorpej struct pci_attach_args *pa = aux;
316 1.1 thorpej
317 1.1 thorpej if (sip_lookup(pa) != NULL)
318 1.1 thorpej return (1);
319 1.1 thorpej
320 1.1 thorpej return (0);
321 1.1 thorpej }
322 1.1 thorpej
323 1.1 thorpej void
324 1.1 thorpej sip_attach(parent, self, aux)
325 1.1 thorpej struct device *parent, *self;
326 1.1 thorpej void *aux;
327 1.1 thorpej {
328 1.1 thorpej struct sip_softc *sc = (struct sip_softc *) self;
329 1.1 thorpej struct pci_attach_args *pa = aux;
330 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
331 1.1 thorpej pci_chipset_tag_t pc = pa->pa_pc;
332 1.1 thorpej pci_intr_handle_t ih;
333 1.1 thorpej const char *intrstr = NULL;
334 1.1 thorpej bus_space_tag_t iot, memt;
335 1.1 thorpej bus_space_handle_t ioh, memh;
336 1.1 thorpej bus_dma_segment_t seg;
337 1.1 thorpej int ioh_valid, memh_valid;
338 1.1 thorpej int i, rseg, error;
339 1.1 thorpej const struct sip_product *sip;
340 1.1 thorpej pcireg_t pmode;
341 1.1 thorpej u_int16_t enaddr[ETHER_ADDR_LEN / 2];
342 1.1 thorpej
343 1.1 thorpej sip = sip_lookup(pa);
344 1.1 thorpej if (sip == NULL) {
345 1.1 thorpej printf("\n");
346 1.1 thorpej panic("sip_attach: impossible");
347 1.1 thorpej }
348 1.1 thorpej
349 1.1 thorpej printf(": %s\n", sip->sip_name);
350 1.1 thorpej
351 1.1 thorpej /*
352 1.1 thorpej * Map the device.
353 1.1 thorpej */
354 1.1 thorpej ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,
355 1.1 thorpej PCI_MAPREG_TYPE_IO, 0,
356 1.1 thorpej &iot, &ioh, NULL, NULL) == 0);
357 1.1 thorpej memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
358 1.1 thorpej PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
359 1.1 thorpej &memt, &memh, NULL, NULL) == 0);
360 1.1 thorpej
361 1.1 thorpej if (memh_valid) {
362 1.1 thorpej sc->sc_st = memt;
363 1.1 thorpej sc->sc_sh = memh;
364 1.1 thorpej } else if (ioh_valid) {
365 1.1 thorpej sc->sc_st = iot;
366 1.1 thorpej sc->sc_sh = ioh;
367 1.1 thorpej } else {
368 1.1 thorpej printf("%s: unable to map device registers\n",
369 1.1 thorpej sc->sc_dev.dv_xname);
370 1.1 thorpej return;
371 1.1 thorpej }
372 1.1 thorpej
373 1.1 thorpej sc->sc_dmat = pa->pa_dmat;
374 1.1 thorpej
375 1.1 thorpej /* Enable bus mastering. */
376 1.1 thorpej pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
377 1.1 thorpej pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
378 1.1 thorpej PCI_COMMAND_MASTER_ENABLE);
379 1.1 thorpej
380 1.1 thorpej /* Get it out of power save mode if needed. */
381 1.1 thorpej if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, 0, 0)) {
382 1.1 thorpej pmode = pci_conf_read(pc, pa->pa_tag, SIP_PCI_CFGPMCSR) & 0x3;
383 1.1 thorpej if (pmode == 3) {
384 1.1 thorpej /*
385 1.1 thorpej * The card has lost all configuration data in
386 1.1 thorpej * this state, so punt.
387 1.1 thorpej */
388 1.1 thorpej printf("%s: unable to wake up from power state D3\n",
389 1.1 thorpej sc->sc_dev.dv_xname);
390 1.1 thorpej return;
391 1.1 thorpej }
392 1.1 thorpej if (pmode != 0) {
393 1.1 thorpej printf("%s: waking up from power state D%d\n",
394 1.1 thorpej sc->sc_dev.dv_xname, pmode);
395 1.1 thorpej pci_conf_write(pc, pa->pa_tag, SIP_PCI_CFGPMCSR, 0);
396 1.1 thorpej }
397 1.1 thorpej }
398 1.1 thorpej
399 1.1 thorpej /*
400 1.1 thorpej * Map and establish our interrupt.
401 1.1 thorpej */
402 1.1 thorpej if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
403 1.1 thorpej pa->pa_intrline, &ih)) {
404 1.1 thorpej printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
405 1.1 thorpej return;
406 1.1 thorpej }
407 1.1 thorpej intrstr = pci_intr_string(pc, ih);
408 1.1 thorpej sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sip_intr, sc);
409 1.1 thorpej if (sc->sc_ih == NULL) {
410 1.1 thorpej printf("%s: unable to establish interrupt",
411 1.1 thorpej sc->sc_dev.dv_xname);
412 1.1 thorpej if (intrstr != NULL)
413 1.1 thorpej printf(" at %s", intrstr);
414 1.1 thorpej printf("\n");
415 1.1 thorpej return;
416 1.1 thorpej }
417 1.1 thorpej printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
418 1.1 thorpej
419 1.1 thorpej SIMPLEQ_INIT(&sc->sc_txfreeq);
420 1.1 thorpej SIMPLEQ_INIT(&sc->sc_txdirtyq);
421 1.1 thorpej
422 1.1 thorpej /*
423 1.1 thorpej * Allocate the control data structures, and create and load the
424 1.1 thorpej * DMA map for it.
425 1.1 thorpej */
426 1.1 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat,
427 1.1 thorpej sizeof(struct sip_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
428 1.1 thorpej 0)) != 0) {
429 1.1 thorpej printf("%s: unable to allocate control data, error = %d\n",
430 1.1 thorpej sc->sc_dev.dv_xname, error);
431 1.1 thorpej goto fail_0;
432 1.1 thorpej }
433 1.1 thorpej
434 1.1 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
435 1.1 thorpej sizeof(struct sip_control_data), (caddr_t *)&sc->sc_control_data,
436 1.1 thorpej BUS_DMA_COHERENT)) != 0) {
437 1.1 thorpej printf("%s: unable to map control data, error = %d\n",
438 1.1 thorpej sc->sc_dev.dv_xname, error);
439 1.1 thorpej goto fail_1;
440 1.1 thorpej }
441 1.1 thorpej
442 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat,
443 1.1 thorpej sizeof(struct sip_control_data), 1,
444 1.1 thorpej sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
445 1.1 thorpej printf("%s: unable to create control data DMA map, "
446 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, error);
447 1.1 thorpej goto fail_2;
448 1.1 thorpej }
449 1.1 thorpej
450 1.1 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
451 1.1 thorpej sc->sc_control_data, sizeof(struct sip_control_data), NULL,
452 1.1 thorpej 0)) != 0) {
453 1.1 thorpej printf("%s: unable to load control data DMA map, error = %d\n",
454 1.1 thorpej sc->sc_dev.dv_xname, error);
455 1.1 thorpej goto fail_3;
456 1.1 thorpej }
457 1.1 thorpej
458 1.1 thorpej /*
459 1.1 thorpej * Create the transmit buffer DMA maps.
460 1.1 thorpej */
461 1.1 thorpej for (i = 0; i < SIP_TXQUEUELEN; i++) {
462 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
463 1.1 thorpej SIP_NTXSEGS, MCLBYTES, 0, 0,
464 1.1 thorpej &sc->sc_txsoft[i].txs_dmamap)) != 0) {
465 1.1 thorpej printf("%s: unable to create tx DMA map %d, "
466 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
467 1.1 thorpej goto fail_4;
468 1.1 thorpej }
469 1.1 thorpej }
470 1.1 thorpej
471 1.1 thorpej /*
472 1.1 thorpej * Create the receive buffer DMA maps.
473 1.1 thorpej */
474 1.1 thorpej for (i = 0; i < SIP_NRXDESC; i++) {
475 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
476 1.1 thorpej MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
477 1.1 thorpej printf("%s: unable to create rx DMA map %d, "
478 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
479 1.1 thorpej goto fail_5;
480 1.1 thorpej }
481 1.1 thorpej }
482 1.1 thorpej
483 1.1 thorpej /*
484 1.1 thorpej * Pre-allocate the receive buffers.
485 1.1 thorpej */
486 1.1 thorpej for (i = 0; i < SIP_NRXDESC; i++) {
487 1.1 thorpej if ((error = sip_add_rxbuf(sc, i)) != 0) {
488 1.1 thorpej printf("%s: unable to allocate or map rx buffer %d\n,"
489 1.1 thorpej " error = %d\n", sc->sc_dev.dv_xname, i, error);
490 1.1 thorpej goto fail_6;
491 1.1 thorpej }
492 1.1 thorpej }
493 1.1 thorpej
494 1.1 thorpej /*
495 1.1 thorpej * Reset the chip to a known state.
496 1.1 thorpej */
497 1.1 thorpej sip_reset(sc);
498 1.1 thorpej
499 1.1 thorpej /*
500 1.1 thorpej * Read the Ethernet address from the EEPROM.
501 1.1 thorpej */
502 1.1 thorpej sip_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
503 1.1 thorpej sizeof(enaddr) / sizeof(enaddr[0]), enaddr);
504 1.1 thorpej
505 1.1 thorpej printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
506 1.1 thorpej ether_sprintf((u_int8_t *)enaddr));
507 1.1 thorpej
508 1.1 thorpej /*
509 1.1 thorpej * Initialize our media structures and probe the MII.
510 1.1 thorpej */
511 1.1 thorpej sc->sc_mii.mii_ifp = ifp;
512 1.1 thorpej sc->sc_mii.mii_readreg = sip_mii_readreg;
513 1.1 thorpej sc->sc_mii.mii_writereg = sip_mii_writereg;
514 1.1 thorpej sc->sc_mii.mii_statchg = sip_mii_statchg;
515 1.1 thorpej ifmedia_init(&sc->sc_mii.mii_media, 0, sip_mediachange,
516 1.1 thorpej sip_mediastatus);
517 1.1 thorpej mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff);
518 1.1 thorpej if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
519 1.1 thorpej ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
520 1.1 thorpej ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
521 1.1 thorpej } else
522 1.1 thorpej ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
523 1.1 thorpej
524 1.1 thorpej ifp = &sc->sc_ethercom.ec_if;
525 1.1 thorpej strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
526 1.1 thorpej ifp->if_softc = sc;
527 1.1 thorpej ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
528 1.1 thorpej ifp->if_ioctl = sip_ioctl;
529 1.1 thorpej ifp->if_start = sip_start;
530 1.1 thorpej ifp->if_watchdog = sip_watchdog;
531 1.1 thorpej
532 1.1 thorpej /*
533 1.1 thorpej * Attach the interface.
534 1.1 thorpej */
535 1.1 thorpej if_attach(ifp);
536 1.1 thorpej ether_ifattach(ifp, (u_int8_t *)enaddr);
537 1.1 thorpej #if NBPFILTER > 0
538 1.1 thorpej bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
539 1.1 thorpej sizeof(struct ether_header));
540 1.1 thorpej #endif
541 1.1 thorpej
542 1.1 thorpej /*
543 1.1 thorpej * Make sure the interface is shutdown during reboot.
544 1.1 thorpej */
545 1.1 thorpej sc->sc_sdhook = shutdownhook_establish(sip_shutdown, sc);
546 1.1 thorpej if (sc->sc_sdhook == NULL)
547 1.1 thorpej printf("%s: WARNING: unable to establish shutdown hook\n",
548 1.1 thorpej sc->sc_dev.dv_xname);
549 1.1 thorpej return;
550 1.1 thorpej
551 1.1 thorpej /*
552 1.1 thorpej * Free any resources we've allocated during the failed attach
553 1.1 thorpej * attempt. Do this in reverse order and fall through.
554 1.1 thorpej */
555 1.1 thorpej fail_6:
556 1.1 thorpej for (i = 0; i < SIP_NRXDESC; i++) {
557 1.1 thorpej if (sc->sc_rxsoft[i].rxs_mbuf != NULL) {
558 1.1 thorpej bus_dmamap_unload(sc->sc_dmat,
559 1.1 thorpej sc->sc_rxsoft[i].rxs_dmamap);
560 1.1 thorpej m_freem(sc->sc_rxsoft[i].rxs_mbuf);
561 1.1 thorpej }
562 1.1 thorpej }
563 1.1 thorpej fail_5:
564 1.1 thorpej for (i = 0; i < SIP_NRXDESC; i++) {
565 1.1 thorpej if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
566 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
567 1.1 thorpej sc->sc_rxsoft[i].rxs_dmamap);
568 1.1 thorpej }
569 1.1 thorpej fail_4:
570 1.1 thorpej for (i = 0; i < SIP_TXQUEUELEN; i++) {
571 1.1 thorpej if (sc->sc_txsoft[i].txs_dmamap != NULL)
572 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
573 1.1 thorpej sc->sc_txsoft[i].txs_dmamap);
574 1.1 thorpej }
575 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
576 1.1 thorpej fail_3:
577 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
578 1.1 thorpej fail_2:
579 1.1 thorpej bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
580 1.1 thorpej sizeof(struct sip_control_data));
581 1.1 thorpej fail_1:
582 1.1 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg);
583 1.1 thorpej fail_0:
584 1.1 thorpej return;
585 1.1 thorpej }
586 1.1 thorpej
587 1.1 thorpej /*
588 1.1 thorpej * sip_shutdown:
589 1.1 thorpej *
590 1.1 thorpej * Make sure the interface is stopped at reboot time.
591 1.1 thorpej */
592 1.1 thorpej void
593 1.1 thorpej sip_shutdown(arg)
594 1.1 thorpej void *arg;
595 1.1 thorpej {
596 1.1 thorpej struct sip_softc *sc = arg;
597 1.1 thorpej
598 1.1 thorpej sip_stop(sc);
599 1.1 thorpej }
600 1.1 thorpej
601 1.1 thorpej /*
602 1.1 thorpej * sip_start: [ifnet interface function]
603 1.1 thorpej *
604 1.1 thorpej * Start packet transmission on the interface.
605 1.1 thorpej */
606 1.1 thorpej void
607 1.1 thorpej sip_start(ifp)
608 1.1 thorpej struct ifnet *ifp;
609 1.1 thorpej {
610 1.1 thorpej struct sip_softc *sc = ifp->if_softc;
611 1.1 thorpej struct mbuf *m0, *m;
612 1.1 thorpej struct sip_txsoft *txs;
613 1.1 thorpej bus_dmamap_t dmamap;
614 1.1 thorpej int error, firsttx, nexttx, lasttx, ofree, seg;
615 1.1 thorpej
616 1.1 thorpej /*
617 1.1 thorpej * If we've been told to pause, don't transmit any more packets.
618 1.1 thorpej */
619 1.1 thorpej if (sc->sc_flags & SIPF_PAUSED)
620 1.1 thorpej ifp->if_flags |= IFF_OACTIVE;
621 1.1 thorpej
622 1.1 thorpej if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
623 1.1 thorpej return;
624 1.1 thorpej
625 1.1 thorpej /*
626 1.1 thorpej * Remember the previous number of free descriptors and
627 1.1 thorpej * the first descriptor we'll use.
628 1.1 thorpej */
629 1.1 thorpej ofree = sc->sc_txfree;
630 1.1 thorpej firsttx = sc->sc_txnext;
631 1.1 thorpej
632 1.1 thorpej /*
633 1.1 thorpej * Loop through the send queue, setting up transmit descriptors
634 1.1 thorpej * until we drain the queue, or use up all available transmit
635 1.1 thorpej * descriptors.
636 1.1 thorpej */
637 1.1 thorpej while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL &&
638 1.1 thorpej sc->sc_txfree != 0) {
639 1.1 thorpej /*
640 1.1 thorpej * Grab a packet off the queue.
641 1.1 thorpej */
642 1.1 thorpej IF_DEQUEUE(&ifp->if_snd, m0);
643 1.1 thorpej if (m0 == NULL)
644 1.1 thorpej break;
645 1.1 thorpej
646 1.1 thorpej dmamap = txs->txs_dmamap;
647 1.1 thorpej
648 1.1 thorpej /*
649 1.1 thorpej * Load the DMA map. If this fails, the packet either
650 1.1 thorpej * didn't fit in the alloted number of segments, or we
651 1.1 thorpej * were short on resources. In this case, we'll copy
652 1.1 thorpej * and try again.
653 1.1 thorpej */
654 1.1 thorpej if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
655 1.1 thorpej BUS_DMA_NOWAIT) != 0) {
656 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
657 1.1 thorpej if (m == NULL) {
658 1.1 thorpej printf("%s: unable to allocate Tx mbuf\n",
659 1.1 thorpej sc->sc_dev.dv_xname);
660 1.1 thorpej IF_PREPEND(&ifp->if_snd, m0);
661 1.1 thorpej break;
662 1.1 thorpej }
663 1.1 thorpej if (m0->m_pkthdr.len > MHLEN) {
664 1.1 thorpej MCLGET(m, M_DONTWAIT);
665 1.1 thorpej if ((m->m_flags & M_EXT) == 0) {
666 1.1 thorpej printf("%s: unable to allocate Tx "
667 1.1 thorpej "cluster\n", sc->sc_dev.dv_xname);
668 1.1 thorpej m_freem(m);
669 1.1 thorpej IF_PREPEND(&ifp->if_snd, m0);
670 1.1 thorpej break;
671 1.1 thorpej }
672 1.1 thorpej }
673 1.1 thorpej m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
674 1.1 thorpej m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
675 1.1 thorpej m_freem(m0);
676 1.1 thorpej m0 = m;
677 1.1 thorpej error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
678 1.1 thorpej m0, BUS_DMA_NOWAIT);
679 1.1 thorpej if (error) {
680 1.1 thorpej printf("%s: unable to load Tx buffer, "
681 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, error);
682 1.1 thorpej IF_PREPEND(&ifp->if_snd, m0);
683 1.1 thorpej break;
684 1.1 thorpej }
685 1.1 thorpej }
686 1.1 thorpej
687 1.1 thorpej /*
688 1.1 thorpej * Ensure we have enough descriptors free to describe
689 1.1 thorpej * the packet.
690 1.1 thorpej */
691 1.1 thorpej if (dmamap->dm_nsegs > sc->sc_txfree) {
692 1.1 thorpej /*
693 1.1 thorpej * Not enough free descriptors to transmit this
694 1.1 thorpej * packet. We haven't committed anything yet,
695 1.1 thorpej * so just unload the DMA map, put the packet
696 1.1 thorpej * back on the queue, and punt. Notify the upper
697 1.1 thorpej * layer that there are not more slots left.
698 1.1 thorpej *
699 1.1 thorpej * XXX We could allocate an mbuf and copy, but
700 1.1 thorpej * XXX is it worth it?
701 1.1 thorpej */
702 1.1 thorpej ifp->if_flags |= IFF_OACTIVE;
703 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, dmamap);
704 1.1 thorpej IF_PREPEND(&ifp->if_snd, m0);
705 1.1 thorpej break;
706 1.1 thorpej }
707 1.1 thorpej
708 1.1 thorpej /*
709 1.1 thorpej * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
710 1.1 thorpej */
711 1.1 thorpej
712 1.1 thorpej /* Sync the DMA map. */
713 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
714 1.1 thorpej BUS_DMASYNC_PREWRITE);
715 1.1 thorpej
716 1.1 thorpej /*
717 1.1 thorpej * Initialize the transmit descriptors.
718 1.1 thorpej */
719 1.1 thorpej for (nexttx = sc->sc_txnext, seg = 0;
720 1.1 thorpej seg < dmamap->dm_nsegs;
721 1.1 thorpej seg++, nexttx = SIP_NEXTTX(nexttx)) {
722 1.1 thorpej /*
723 1.1 thorpej * If this is the first descriptor we're
724 1.1 thorpej * enqueueing, don't set the OWN bit just
725 1.1 thorpej * yet. That could cause a race condition.
726 1.1 thorpej * We'll do it below.
727 1.1 thorpej */
728 1.1 thorpej sc->sc_txdescs[nexttx].sipd_bufptr =
729 1.1 thorpej dmamap->dm_segs[seg].ds_addr;
730 1.1 thorpej sc->sc_txdescs[nexttx].sipd_cmdsts =
731 1.1 thorpej (nexttx == firsttx ? 0 : CMDSTS_OWN) |
732 1.1 thorpej CMDSTS_MORE | dmamap->dm_segs[seg].ds_len;
733 1.1 thorpej lasttx = nexttx;
734 1.1 thorpej }
735 1.1 thorpej
736 1.1 thorpej /* Clear the MORE bit on the last segment. */
737 1.1 thorpej sc->sc_txdescs[lasttx].sipd_cmdsts &= ~CMDSTS_MORE;
738 1.1 thorpej
739 1.1 thorpej /* Sync the descriptors we're using. */
740 1.1 thorpej SIP_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
741 1.1 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
742 1.1 thorpej
743 1.1 thorpej /*
744 1.1 thorpej * Store a pointer to the packet so we can free it later,
745 1.1 thorpej * and remember what txdirty will be once the packet is
746 1.1 thorpej * done.
747 1.1 thorpej */
748 1.1 thorpej txs->txs_mbuf = m0;
749 1.1 thorpej txs->txs_firstdesc = sc->sc_txnext;
750 1.1 thorpej txs->txs_lastdesc = lasttx;
751 1.1 thorpej
752 1.1 thorpej /* Advance the tx pointer. */
753 1.1 thorpej sc->sc_txfree -= dmamap->dm_nsegs;
754 1.1 thorpej sc->sc_txnext = nexttx;
755 1.1 thorpej
756 1.1 thorpej SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs, txs_q);
757 1.1 thorpej SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
758 1.1 thorpej
759 1.1 thorpej #if NBPFILTER > 0
760 1.1 thorpej /*
761 1.1 thorpej * Pass the packet to any BPF listeners.
762 1.1 thorpej */
763 1.1 thorpej if (ifp->if_bpf)
764 1.1 thorpej bpf_mtap(ifp->if_bpf, m0);
765 1.1 thorpej #endif /* NBPFILTER > 0 */
766 1.1 thorpej }
767 1.1 thorpej
768 1.1 thorpej if (txs == NULL || sc->sc_txfree == 0) {
769 1.1 thorpej /* No more slots left; notify upper layer. */
770 1.1 thorpej ifp->if_flags |= IFF_OACTIVE;
771 1.1 thorpej }
772 1.1 thorpej
773 1.1 thorpej if (sc->sc_txfree != ofree) {
774 1.1 thorpej /*
775 1.1 thorpej * Cause a descriptor interrupt to happen on the
776 1.1 thorpej * last packet we enqueued.
777 1.1 thorpej */
778 1.1 thorpej sc->sc_txdescs[lasttx].sipd_cmdsts |= CMDSTS_INTR;
779 1.1 thorpej SIP_CDTXSYNC(sc, lasttx, 1,
780 1.1 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
781 1.1 thorpej
782 1.1 thorpej /*
783 1.1 thorpej * The entire packet chain is set up. Give the
784 1.1 thorpej * first descrptor to the chip now.
785 1.1 thorpej */
786 1.1 thorpej sc->sc_txdescs[firsttx].sipd_cmdsts |= CMDSTS_OWN;
787 1.1 thorpej SIP_CDTXSYNC(sc, firsttx, 1,
788 1.1 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
789 1.1 thorpej
790 1.1 thorpej /* Start the transmit process. */
791 1.1 thorpej if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) &
792 1.1 thorpej CR_TXE) == 0) {
793 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP,
794 1.1 thorpej SIP_CDTXADDR(sc, firsttx));
795 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
796 1.1 thorpej }
797 1.1 thorpej
798 1.1 thorpej /* Set a watchdog timer in case the chip flakes out. */
799 1.1 thorpej ifp->if_timer = 5;
800 1.1 thorpej }
801 1.1 thorpej }
802 1.1 thorpej
803 1.1 thorpej /*
804 1.1 thorpej * sip_watchdog: [ifnet interface function]
805 1.1 thorpej *
806 1.1 thorpej * Watchdog timer handler.
807 1.1 thorpej */
808 1.1 thorpej void
809 1.1 thorpej sip_watchdog(ifp)
810 1.1 thorpej struct ifnet *ifp;
811 1.1 thorpej {
812 1.1 thorpej struct sip_softc *sc = ifp->if_softc;
813 1.1 thorpej
814 1.1 thorpej /*
815 1.1 thorpej * The chip seems to ignore the CMDSTS_INTR bit sometimes!
816 1.1 thorpej * If we get a timeout, try and sweep up transmit descriptors.
817 1.1 thorpej * If we manage to sweep them all up, ignore the lack of
818 1.1 thorpej * interrupt.
819 1.1 thorpej */
820 1.1 thorpej sip_txintr(sc);
821 1.1 thorpej
822 1.1 thorpej if (sc->sc_txfree != SIP_NTXDESC) {
823 1.1 thorpej printf("%s: device timeout\n", sc->sc_dev.dv_xname);
824 1.1 thorpej ifp->if_oerrors++;
825 1.1 thorpej
826 1.1 thorpej /* Reset the interface. */
827 1.1 thorpej sip_init(sc);
828 1.1 thorpej } else if (ifp->if_flags & IFF_DEBUG)
829 1.1 thorpej printf("%s: recovered from device timeout\n",
830 1.1 thorpej sc->sc_dev.dv_xname);
831 1.1 thorpej
832 1.1 thorpej /* Try to get more packets going. */
833 1.1 thorpej sip_start(ifp);
834 1.1 thorpej }
835 1.1 thorpej
836 1.1 thorpej /*
837 1.1 thorpej * sip_ioctl: [ifnet interface function]
838 1.1 thorpej *
839 1.1 thorpej * Handle control requests from the operator.
840 1.1 thorpej */
841 1.1 thorpej int
842 1.1 thorpej sip_ioctl(ifp, cmd, data)
843 1.1 thorpej struct ifnet *ifp;
844 1.1 thorpej u_long cmd;
845 1.1 thorpej caddr_t data;
846 1.1 thorpej {
847 1.1 thorpej struct sip_softc *sc = ifp->if_softc;
848 1.1 thorpej struct ifreq *ifr = (struct ifreq *)data;
849 1.1 thorpej struct ifaddr *ifa = (struct ifaddr *)data;
850 1.1 thorpej int s, error = 0;
851 1.1 thorpej
852 1.1 thorpej s = splnet();
853 1.1 thorpej
854 1.1 thorpej switch (cmd) {
855 1.1 thorpej case SIOCSIFADDR:
856 1.1 thorpej ifp->if_flags |= IFF_UP;
857 1.1 thorpej
858 1.1 thorpej switch (ifa->ifa_addr->sa_family) {
859 1.1 thorpej #ifdef INET
860 1.1 thorpej case AF_INET:
861 1.1 thorpej sip_init(sc);
862 1.1 thorpej arp_ifinit(ifp, ifa);
863 1.1 thorpej break;
864 1.1 thorpej #endif /* INET */
865 1.1 thorpej #ifdef NS
866 1.1 thorpej case AF_NS:
867 1.1 thorpej {
868 1.1 thorpej struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
869 1.1 thorpej
870 1.1 thorpej if (ns_nullhost(*ina))
871 1.1 thorpej ina->x_host = *(union ns_host *)
872 1.1 thorpej LLADDR(ifp->if_sadl);
873 1.1 thorpej else
874 1.1 thorpej memcpy(LLADDR(ifp->if_sadl),
875 1.1 thorpej ina->x_host.c_host, ifp->if_addrlen);
876 1.1 thorpej sip_init(sc);
877 1.1 thorpej break;
878 1.1 thorpej }
879 1.1 thorpej #endif /* NS */
880 1.1 thorpej default:
881 1.1 thorpej sip_init(sc);
882 1.1 thorpej break;
883 1.1 thorpej }
884 1.1 thorpej break;
885 1.1 thorpej
886 1.1 thorpej case SIOCSIFMTU:
887 1.1 thorpej if (ifr->ifr_mtu > ETHERMTU)
888 1.1 thorpej error = EINVAL;
889 1.1 thorpej else
890 1.1 thorpej ifp->if_mtu = ifr->ifr_mtu;
891 1.1 thorpej break;
892 1.1 thorpej
893 1.1 thorpej case SIOCSIFFLAGS:
894 1.1 thorpej if ((ifp->if_flags & IFF_UP) == 0 &&
895 1.1 thorpej (ifp->if_flags & IFF_RUNNING) != 0) {
896 1.1 thorpej /*
897 1.1 thorpej * If interface is marked down and it is running, then
898 1.1 thorpej * stop it.
899 1.1 thorpej */
900 1.1 thorpej sip_stop(sc);
901 1.1 thorpej } else if ((ifp->if_flags & IFF_UP) != 0 &&
902 1.1 thorpej (ifp->if_flags & IFF_RUNNING) == 0) {
903 1.1 thorpej /*
904 1.1 thorpej * If interfase it marked up and it is stopped, then
905 1.1 thorpej * start it.
906 1.1 thorpej */
907 1.1 thorpej sip_init(sc);
908 1.1 thorpej } else if ((ifp->if_flags & IFF_UP) != 0) {
909 1.1 thorpej /*
910 1.1 thorpej * Reset the interface to pick up changes in any other
911 1.1 thorpej * flags that affect the hardware state.
912 1.1 thorpej */
913 1.1 thorpej sip_init(sc);
914 1.1 thorpej }
915 1.1 thorpej break;
916 1.1 thorpej
917 1.1 thorpej case SIOCADDMULTI:
918 1.1 thorpej case SIOCDELMULTI:
919 1.1 thorpej error = (cmd == SIOCADDMULTI) ?
920 1.1 thorpej ether_addmulti(ifr, &sc->sc_ethercom) :
921 1.1 thorpej ether_delmulti(ifr, &sc->sc_ethercom);
922 1.1 thorpej
923 1.1 thorpej if (error == ENETRESET) {
924 1.1 thorpej /*
925 1.1 thorpej * Multicast list has changed; set the hardware filter
926 1.1 thorpej * accordingly.
927 1.1 thorpej */
928 1.1 thorpej sip_set_filter(sc);
929 1.1 thorpej error = 0;
930 1.1 thorpej }
931 1.1 thorpej break;
932 1.1 thorpej
933 1.1 thorpej case SIOCSIFMEDIA:
934 1.1 thorpej case SIOCGIFMEDIA:
935 1.1 thorpej error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
936 1.1 thorpej break;
937 1.1 thorpej
938 1.1 thorpej default:
939 1.1 thorpej error = EINVAL;
940 1.1 thorpej break;
941 1.1 thorpej }
942 1.1 thorpej
943 1.1 thorpej /* Try to get more packets going. */
944 1.1 thorpej sip_start(ifp);
945 1.1 thorpej
946 1.1 thorpej splx(s);
947 1.1 thorpej return (error);
948 1.1 thorpej }
949 1.1 thorpej
950 1.1 thorpej /*
951 1.1 thorpej * sip_intr:
952 1.1 thorpej *
953 1.1 thorpej * Interrupt service routine.
954 1.1 thorpej */
955 1.1 thorpej int
956 1.1 thorpej sip_intr(arg)
957 1.1 thorpej void *arg;
958 1.1 thorpej {
959 1.1 thorpej struct sip_softc *sc = arg;
960 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
961 1.1 thorpej u_int32_t isr;
962 1.1 thorpej int handled = 0;
963 1.1 thorpej
964 1.1 thorpej for (;;) {
965 1.1 thorpej /* Reading clears interrupt. */
966 1.1 thorpej isr = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ISR);
967 1.1 thorpej if ((isr & sc->sc_imr) == 0)
968 1.1 thorpej break;
969 1.1 thorpej
970 1.1 thorpej handled = 1;
971 1.1 thorpej
972 1.1 thorpej if (isr & (ISR_RXORN|ISR_RXIDLE|ISR_RXDESC)) {
973 1.1 thorpej /* Grab any new packets. */
974 1.1 thorpej sip_rxintr(sc);
975 1.1 thorpej
976 1.1 thorpej if (isr & ISR_RXORN) {
977 1.1 thorpej printf("%s: receive FIFO overrun\n",
978 1.1 thorpej sc->sc_dev.dv_xname);
979 1.1 thorpej
980 1.1 thorpej /* XXX adjust rx_drain_thresh? */
981 1.1 thorpej }
982 1.1 thorpej
983 1.1 thorpej if (isr & ISR_RXIDLE) {
984 1.1 thorpej printf("%s: receive ring overrun\n",
985 1.1 thorpej sc->sc_dev.dv_xname);
986 1.1 thorpej
987 1.1 thorpej /* Get the receive process going again. */
988 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
989 1.1 thorpej SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
990 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
991 1.1 thorpej SIP_CR, CR_RXE);
992 1.1 thorpej }
993 1.1 thorpej }
994 1.1 thorpej
995 1.1 thorpej if (isr & (ISR_TXURN|ISR_TXDESC)) {
996 1.1 thorpej /* Sweep up transmit descriptors. */
997 1.1 thorpej sip_txintr(sc);
998 1.1 thorpej
999 1.1 thorpej if (isr & ISR_TXURN) {
1000 1.1 thorpej u_int32_t thresh;
1001 1.1 thorpej
1002 1.1 thorpej printf("%s: transmit FIFO underrun",
1003 1.1 thorpej sc->sc_dev.dv_xname);
1004 1.1 thorpej
1005 1.1 thorpej thresh = sc->sc_tx_drain_thresh + 1;
1006 1.1 thorpej if (thresh <= TXCFG_DRTH &&
1007 1.1 thorpej (thresh * 32) <= (SIP_TXFIFO_SIZE -
1008 1.1 thorpej (sc->sc_tx_fill_thresh * 32))) {
1009 1.1 thorpej printf("; increasing Tx drain "
1010 1.1 thorpej "threshold to %u bytes\n",
1011 1.1 thorpej thresh * 32);
1012 1.1 thorpej sc->sc_tx_drain_thresh = thresh;
1013 1.1 thorpej sip_init(sc);
1014 1.1 thorpej } else {
1015 1.1 thorpej sip_init(sc);
1016 1.1 thorpej printf("\n");
1017 1.1 thorpej }
1018 1.1 thorpej }
1019 1.1 thorpej }
1020 1.1 thorpej
1021 1.1 thorpej if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {
1022 1.1 thorpej if (isr & ISR_PAUSE_ST) {
1023 1.1 thorpej sc->sc_flags |= SIPF_PAUSED;
1024 1.1 thorpej ifp->if_flags |= IFF_OACTIVE;
1025 1.1 thorpej }
1026 1.1 thorpej if (isr & ISR_PAUSE_END) {
1027 1.1 thorpej sc->sc_flags &= ~SIPF_PAUSED;
1028 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
1029 1.1 thorpej }
1030 1.1 thorpej }
1031 1.1 thorpej
1032 1.1 thorpej if (isr & ISR_HIBERR) {
1033 1.1 thorpej #define PRINTERR(bit, str) \
1034 1.1 thorpej if (isr & (bit)) \
1035 1.1 thorpej printf("%s: %s\n", sc->sc_dev.dv_xname, str)
1036 1.1 thorpej PRINTERR(ISR_DPERR, "parity error");
1037 1.1 thorpej PRINTERR(ISR_SSERR, "system error");
1038 1.1 thorpej PRINTERR(ISR_RMABT, "master abort");
1039 1.1 thorpej PRINTERR(ISR_RTABT, "target abort");
1040 1.1 thorpej PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
1041 1.1 thorpej sip_init(sc);
1042 1.1 thorpej #undef PRINTERR
1043 1.1 thorpej }
1044 1.1 thorpej }
1045 1.1 thorpej
1046 1.1 thorpej /* Try to get more packets going. */
1047 1.1 thorpej sip_start(ifp);
1048 1.1 thorpej
1049 1.1 thorpej return (handled);
1050 1.1 thorpej }
1051 1.1 thorpej
1052 1.1 thorpej /*
1053 1.1 thorpej * sip_txintr:
1054 1.1 thorpej *
1055 1.1 thorpej * Helper; handle transmit interrupts.
1056 1.1 thorpej */
1057 1.1 thorpej void
1058 1.1 thorpej sip_txintr(sc)
1059 1.1 thorpej struct sip_softc *sc;
1060 1.1 thorpej {
1061 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1062 1.1 thorpej struct sip_txsoft *txs;
1063 1.1 thorpej u_int32_t cmdsts;
1064 1.1 thorpej
1065 1.1 thorpej if ((sc->sc_flags & SIPF_PAUSED) == 0)
1066 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
1067 1.1 thorpej
1068 1.1 thorpej /*
1069 1.1 thorpej * Go through our Tx list and free mbufs for those
1070 1.1 thorpej * frames which have been transmitted.
1071 1.1 thorpej */
1072 1.1 thorpej while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
1073 1.1 thorpej SIP_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
1074 1.1 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1075 1.1 thorpej
1076 1.1 thorpej cmdsts = sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts;
1077 1.1 thorpej if (cmdsts & CMDSTS_OWN)
1078 1.1 thorpej break;
1079 1.1 thorpej
1080 1.1 thorpej SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs, txs_q);
1081 1.1 thorpej
1082 1.1 thorpej sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
1083 1.1 thorpej
1084 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
1085 1.1 thorpej 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1086 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
1087 1.1 thorpej m_freem(txs->txs_mbuf);
1088 1.1 thorpej txs->txs_mbuf = NULL;
1089 1.1 thorpej
1090 1.1 thorpej SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1091 1.1 thorpej
1092 1.1 thorpej /*
1093 1.1 thorpej * Check for errors and collisions.
1094 1.1 thorpej */
1095 1.1 thorpej if (cmdsts &
1096 1.1 thorpej (CMDSTS_Tx_TXA|CMDSTS_Tx_TFU|CMDSTS_Tx_ED|CMDSTS_Tx_EC)) {
1097 1.1 thorpej if (ifp->if_flags & IFF_DEBUG) {
1098 1.1 thorpej if (CMDSTS_Tx_ED)
1099 1.1 thorpej printf("%s: excessive deferral\n",
1100 1.1 thorpej sc->sc_dev.dv_xname);
1101 1.1 thorpej if (CMDSTS_Tx_EC) {
1102 1.1 thorpej printf("%s: excessive collisions\n",
1103 1.1 thorpej sc->sc_dev.dv_xname);
1104 1.1 thorpej ifp->if_collisions += 16;
1105 1.1 thorpej }
1106 1.1 thorpej }
1107 1.1 thorpej } else {
1108 1.1 thorpej /* Packet was transmitted successfully. */
1109 1.1 thorpej ifp->if_opackets++;
1110 1.1 thorpej ifp->if_collisions += CMDSTS_COLLISIONS(cmdsts);
1111 1.1 thorpej }
1112 1.1 thorpej }
1113 1.1 thorpej
1114 1.1 thorpej /*
1115 1.1 thorpej * If there are no more pending transmissions, cancel the watchdog
1116 1.1 thorpej * timer.
1117 1.1 thorpej */
1118 1.1 thorpej if (txs == NULL)
1119 1.1 thorpej ifp->if_timer = 0;
1120 1.1 thorpej }
1121 1.1 thorpej
1122 1.1 thorpej /*
1123 1.1 thorpej * sip_rxintr:
1124 1.1 thorpej *
1125 1.1 thorpej * Helper; handle receive interrupts.
1126 1.1 thorpej */
1127 1.1 thorpej void
1128 1.1 thorpej sip_rxintr(sc)
1129 1.1 thorpej struct sip_softc *sc;
1130 1.1 thorpej {
1131 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1132 1.1 thorpej struct ether_header *eh;
1133 1.1 thorpej struct sip_rxsoft *rxs;
1134 1.1 thorpej struct mbuf *m;
1135 1.1 thorpej u_int32_t cmdsts;
1136 1.1 thorpej int i, len;
1137 1.1 thorpej
1138 1.1 thorpej for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {
1139 1.1 thorpej rxs = &sc->sc_rxsoft[i];
1140 1.1 thorpej
1141 1.1 thorpej SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1142 1.1 thorpej
1143 1.1 thorpej cmdsts = sc->sc_rxdescs[i].sipd_cmdsts;
1144 1.1 thorpej
1145 1.1 thorpej /*
1146 1.1 thorpej * NOTE: OWN is set if owned by _consumer_. We're the
1147 1.1 thorpej * consumer of the receive ring, so if the bit is clear,
1148 1.1 thorpej * we have processed all of the packets.
1149 1.1 thorpej */
1150 1.1 thorpej if ((cmdsts & CMDSTS_OWN) == 0) {
1151 1.1 thorpej /*
1152 1.1 thorpej * We have processed all of the receive buffers.
1153 1.1 thorpej */
1154 1.1 thorpej break;
1155 1.1 thorpej }
1156 1.1 thorpej
1157 1.1 thorpej /*
1158 1.1 thorpej * If any collisions were seen on the wire, count one.
1159 1.1 thorpej */
1160 1.1 thorpej if (cmdsts & CMDSTS_Rx_COL)
1161 1.1 thorpej ifp->if_collisions++;
1162 1.1 thorpej
1163 1.1 thorpej /*
1164 1.1 thorpej * If an error occurred, update stats, clear the status
1165 1.1 thorpej * word, and leave the packet buffer in place. It will
1166 1.1 thorpej * simply be reused the next time the ring comes around.
1167 1.1 thorpej */
1168 1.1 thorpej if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_LONG|CMDSTS_Rx_RUNT|
1169 1.1 thorpej CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
1170 1.1 thorpej ifp->if_ierrors++;
1171 1.1 thorpej if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
1172 1.1 thorpej (cmdsts & CMDSTS_Rx_RXO) == 0) {
1173 1.1 thorpej /* Receive overrun handled elsewhere. */
1174 1.1 thorpej printf("%s: receive descriptor error\n",
1175 1.1 thorpej sc->sc_dev.dv_xname);
1176 1.1 thorpej }
1177 1.1 thorpej #define PRINTERR(bit, str) \
1178 1.1 thorpej if (cmdsts & (bit)) \
1179 1.1 thorpej printf("%s: %s\n", sc->sc_dev.dv_xname, str)
1180 1.1 thorpej PRINTERR(CMDSTS_Rx_LONG, "packet too long");
1181 1.1 thorpej PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
1182 1.1 thorpej PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
1183 1.1 thorpej PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
1184 1.1 thorpej PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
1185 1.1 thorpej #undef PRINTERR
1186 1.1 thorpej SIP_INIT_RXDESC(sc, i);
1187 1.1 thorpej continue;
1188 1.1 thorpej }
1189 1.1 thorpej
1190 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
1191 1.1 thorpej rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1192 1.1 thorpej
1193 1.1 thorpej /*
1194 1.1 thorpej * No errors; receive the packet. Note, the SiS 900
1195 1.1 thorpej * includes the CRC with every packet; trim it.
1196 1.1 thorpej */
1197 1.1 thorpej len = CMDSTS_SIZE(cmdsts) - ETHER_CRC_LEN;
1198 1.1 thorpej
1199 1.1 thorpej #ifdef __NO_STRICT_ALIGNMENT
1200 1.1 thorpej /*
1201 1.1 thorpej * Allocate a new mbuf cluster. If that fails, we are
1202 1.1 thorpej * out of memory, and must drop the packet and recycle
1203 1.1 thorpej * the buffer that's already attached to this descriptor.
1204 1.1 thorpej */
1205 1.1 thorpej m = rxs->rxs_mbuf;
1206 1.1 thorpej if (sip_add_rxbuf(sc, i) != 0) {
1207 1.1 thorpej ifp->if_ierrors++;
1208 1.1 thorpej SIP_INIT_RXDESC(sc, i);
1209 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
1210 1.1 thorpej rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1211 1.1 thorpej continue;
1212 1.1 thorpej }
1213 1.1 thorpej #else
1214 1.1 thorpej /*
1215 1.1 thorpej * The SiS 900's receive buffers must be 4-byte aligned.
1216 1.1 thorpej * But this means that the data after the Ethernet header
1217 1.1 thorpej * is misaligned. We must allocate a new buffer and
1218 1.1 thorpej * copy the data, shifted forward 2 bytes.
1219 1.1 thorpej */
1220 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
1221 1.1 thorpej if (m == NULL) {
1222 1.1 thorpej dropit:
1223 1.1 thorpej ifp->if_ierrors++;
1224 1.1 thorpej SIP_INIT_RXDESC(sc, i);
1225 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
1226 1.1 thorpej rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1227 1.1 thorpej continue;
1228 1.1 thorpej }
1229 1.1 thorpej if (len > (MHLEN - 2)) {
1230 1.1 thorpej MCLGET(m, M_DONTWAIT);
1231 1.1 thorpej if ((m->m_flags & M_EXT) == 0) {
1232 1.1 thorpej m_freem(m);
1233 1.1 thorpej goto dropit;
1234 1.1 thorpej }
1235 1.1 thorpej }
1236 1.1 thorpej m->m_data += 2;
1237 1.1 thorpej
1238 1.1 thorpej /*
1239 1.1 thorpej * Note that we use clusters for incoming frames, so the
1240 1.1 thorpej * buffer is virtually contiguous.
1241 1.1 thorpej */
1242 1.1 thorpej memcpy(mtod(m, caddr_t), mtod(rxs->rxs_mbuf, caddr_t), len);
1243 1.1 thorpej
1244 1.1 thorpej /* Allow the receive descriptor to continue using its mbuf. */
1245 1.1 thorpej SIP_INIT_RXDESC(sc, i);
1246 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
1247 1.1 thorpej rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1248 1.1 thorpej #endif /* __NO_STRICT_ALIGNMENT */
1249 1.1 thorpej
1250 1.1 thorpej ifp->if_ipackets++;
1251 1.1 thorpej eh = mtod(m, struct ether_header *);
1252 1.1 thorpej m->m_pkthdr.rcvif = ifp;
1253 1.1 thorpej m->m_pkthdr.len = m->m_len = len;
1254 1.1 thorpej
1255 1.1 thorpej #if NBPFILTER > 0
1256 1.1 thorpej /*
1257 1.1 thorpej * Pass this up to any BPF listeners, but only
1258 1.1 thorpej * pass if up the stack if it's for us.
1259 1.1 thorpej */
1260 1.1 thorpej if (ifp->if_bpf) {
1261 1.1 thorpej bpf_mtap(ifp->if_bpf, m);
1262 1.1 thorpej if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1263 1.1 thorpej (cmdsts & CMDSTS_Rx_DEST) == CMDSTS_Rx_DEST_REJ) {
1264 1.1 thorpej m_freem(m);
1265 1.1 thorpej continue;
1266 1.1 thorpej }
1267 1.1 thorpej }
1268 1.1 thorpej #endif /* NBPFILTER > 0 */
1269 1.1 thorpej
1270 1.1 thorpej /* Pass it on. */
1271 1.1 thorpej (*ifp->if_input)(ifp, m);
1272 1.1 thorpej }
1273 1.1 thorpej
1274 1.1 thorpej /* Update the receive pointer. */
1275 1.1 thorpej sc->sc_rxptr = i;
1276 1.1 thorpej }
1277 1.1 thorpej
1278 1.1 thorpej /*
1279 1.1 thorpej * sip_tick:
1280 1.1 thorpej *
1281 1.1 thorpej * One second timer, used to tick the MII.
1282 1.1 thorpej */
1283 1.1 thorpej void
1284 1.1 thorpej sip_tick(arg)
1285 1.1 thorpej void *arg;
1286 1.1 thorpej {
1287 1.1 thorpej struct sip_softc *sc = arg;
1288 1.1 thorpej int s;
1289 1.1 thorpej
1290 1.1 thorpej s = splnet();
1291 1.1 thorpej mii_tick(&sc->sc_mii);
1292 1.1 thorpej splx(s);
1293 1.1 thorpej
1294 1.1 thorpej timeout(sip_tick, sc, hz);
1295 1.1 thorpej }
1296 1.1 thorpej
1297 1.1 thorpej /*
1298 1.1 thorpej * sip_reset:
1299 1.1 thorpej *
1300 1.1 thorpej * Perform a soft reset on the SiS 900.
1301 1.1 thorpej */
1302 1.1 thorpej void
1303 1.1 thorpej sip_reset(sc)
1304 1.1 thorpej struct sip_softc *sc;
1305 1.1 thorpej {
1306 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1307 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1308 1.1 thorpej int i;
1309 1.1 thorpej
1310 1.1 thorpej bus_space_write_4(st, sh, SIP_CR, CR_RST);
1311 1.1 thorpej
1312 1.1 thorpej for (i = 0; i < 1000; i++) {
1313 1.1 thorpej if ((bus_space_read_4(st, sh, SIP_ISR) &
1314 1.1 thorpej (ISR_TXRCMP|ISR_RXRCMP)) == (ISR_TXRCMP|ISR_RXRCMP))
1315 1.1 thorpej return;
1316 1.1 thorpej delay(2);
1317 1.1 thorpej }
1318 1.1 thorpej
1319 1.1 thorpej printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
1320 1.1 thorpej }
1321 1.1 thorpej
1322 1.1 thorpej /*
1323 1.1 thorpej * sip_init:
1324 1.1 thorpej *
1325 1.1 thorpej * Initialize the interface. Must be called at splnet().
1326 1.1 thorpej */
1327 1.1 thorpej void
1328 1.1 thorpej sip_init(sc)
1329 1.1 thorpej struct sip_softc *sc;
1330 1.1 thorpej {
1331 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1332 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1333 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1334 1.1 thorpej struct sip_txsoft *txs;
1335 1.1 thorpej struct sip_desc *sipd;
1336 1.1 thorpej u_int32_t cfg;
1337 1.1 thorpej int i;
1338 1.1 thorpej
1339 1.1 thorpej /*
1340 1.1 thorpej * Cancel any pending I/O.
1341 1.1 thorpej */
1342 1.1 thorpej sip_stop(sc);
1343 1.1 thorpej
1344 1.1 thorpej /*
1345 1.1 thorpej * Reset the chip to a known state.
1346 1.1 thorpej */
1347 1.1 thorpej sip_reset(sc);
1348 1.1 thorpej
1349 1.1 thorpej /*
1350 1.1 thorpej * Initialize the transmit descriptor ring.
1351 1.1 thorpej */
1352 1.1 thorpej for (i = 0; i < SIP_NTXDESC; i++) {
1353 1.1 thorpej sipd = &sc->sc_txdescs[i];
1354 1.1 thorpej memset(sipd, 0, sizeof(struct sip_desc));
1355 1.1 thorpej sipd->sipd_link = SIP_CDTXADDR(sc, SIP_NEXTTX(i));
1356 1.1 thorpej }
1357 1.1 thorpej SIP_CDTXSYNC(sc, 0, SIP_NTXDESC,
1358 1.1 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1359 1.1 thorpej sc->sc_txfree = SIP_NTXDESC;
1360 1.1 thorpej sc->sc_txnext = 0;
1361 1.1 thorpej
1362 1.1 thorpej /*
1363 1.1 thorpej * Initialize the transmit job descriptors.
1364 1.1 thorpej */
1365 1.1 thorpej SIMPLEQ_INIT(&sc->sc_txfreeq);
1366 1.1 thorpej SIMPLEQ_INIT(&sc->sc_txdirtyq);
1367 1.1 thorpej for (i = 0; i < SIP_TXQUEUELEN; i++) {
1368 1.1 thorpej txs = &sc->sc_txsoft[i];
1369 1.1 thorpej txs->txs_mbuf = NULL;
1370 1.1 thorpej SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1371 1.1 thorpej }
1372 1.1 thorpej
1373 1.1 thorpej /*
1374 1.1 thorpej * Initialize the receive descriptor and receive job
1375 1.1 thorpej * descriptor rings. The buffers are already allocated.
1376 1.1 thorpej */
1377 1.1 thorpej for (i = 0; i < SIP_NRXDESC; i++)
1378 1.1 thorpej SIP_INIT_RXDESC(sc, i);
1379 1.1 thorpej sc->sc_rxptr = 0;
1380 1.1 thorpej
1381 1.1 thorpej /*
1382 1.1 thorpej * Initialize the configuration register: aggressive PCI
1383 1.1 thorpej * bus request algorithm, default backoff, default OW timer,
1384 1.1 thorpej * default parity error detection.
1385 1.1 thorpej */
1386 1.1 thorpej cfg = 0;
1387 1.1 thorpej #if BYTE_ORDER == BIG_ENDIAN
1388 1.1 thorpej /*
1389 1.1 thorpej * ...descriptors in big-endian mode.
1390 1.1 thorpej */
1391 1.1 thorpej cfg |= CFG_BEM;
1392 1.1 thorpej #endif
1393 1.1 thorpej bus_space_write_4(st, sh, SIP_CFG, cfg);
1394 1.1 thorpej
1395 1.1 thorpej /*
1396 1.1 thorpej * Initialize the transmit fill and drain thresholds if
1397 1.1 thorpej * we have never done so.
1398 1.1 thorpej */
1399 1.1 thorpej if (sc->sc_tx_fill_thresh == 0) {
1400 1.1 thorpej /*
1401 1.1 thorpej * XXX This value should be tuned. This is the
1402 1.1 thorpej * minimum (32 bytes), and we may be able to
1403 1.1 thorpej * improve performance by increasing it.
1404 1.1 thorpej */
1405 1.1 thorpej sc->sc_tx_fill_thresh = 1;
1406 1.1 thorpej }
1407 1.1 thorpej if (sc->sc_tx_drain_thresh == 0) {
1408 1.1 thorpej /*
1409 1.1 thorpej * Start at a drain threshold of 128 bytes. We will
1410 1.1 thorpej * increase it if a DMA underrun occurs.
1411 1.1 thorpej *
1412 1.1 thorpej * XXX The minimum value of this variable should be
1413 1.1 thorpej * tuned. We may be able to improve performance
1414 1.1 thorpej * by starting with a lower value. That, however,
1415 1.1 thorpej * may trash the first few outgoing packets if the
1416 1.1 thorpej * PCI bus is saturated.
1417 1.1 thorpej */
1418 1.1 thorpej sc->sc_tx_drain_thresh = 4;
1419 1.1 thorpej }
1420 1.1 thorpej
1421 1.1 thorpej /*
1422 1.1 thorpej * Initialize the prototype TXCFG register.
1423 1.1 thorpej */
1424 1.1 thorpej sc->sc_txcfg = TXCFG_ATP | TXCFG_MXDMA_512 |
1425 1.1 thorpej (sc->sc_tx_fill_thresh << TXCFG_FLTH_SHIFT) |
1426 1.1 thorpej sc->sc_tx_drain_thresh;
1427 1.1 thorpej bus_space_write_4(st, sh, SIP_TXCFG, sc->sc_txcfg);
1428 1.1 thorpej
1429 1.1 thorpej /*
1430 1.1 thorpej * Initialize the receive drain threshold if we have never
1431 1.1 thorpej * done so.
1432 1.1 thorpej */
1433 1.1 thorpej if (sc->sc_rx_drain_thresh == 0) {
1434 1.1 thorpej /*
1435 1.1 thorpej * XXX This value should be tuned. This is set to the
1436 1.1 thorpej * maximum of 248 bytes, and we may be able to improve
1437 1.1 thorpej * performance by decreasing it (although we should never
1438 1.1 thorpej * set this value lower than 2; 14 bytes are required to
1439 1.1 thorpej * filter the packet).
1440 1.1 thorpej */
1441 1.1 thorpej sc->sc_rx_drain_thresh = RXCFG_DRTH >> RXCFG_DRTH_SHIFT;
1442 1.1 thorpej }
1443 1.1 thorpej
1444 1.1 thorpej /*
1445 1.1 thorpej * Initialize the prototype RXCFG register.
1446 1.1 thorpej */
1447 1.1 thorpej sc->sc_rxcfg = RXCFG_MXDMA_512 |
1448 1.1 thorpej (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);
1449 1.1 thorpej bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
1450 1.1 thorpej
1451 1.1 thorpej /* Set up the receive filter. */
1452 1.1 thorpej sip_set_filter(sc);
1453 1.1 thorpej
1454 1.1 thorpej /*
1455 1.1 thorpej * Give the transmit and receive rings to the chip.
1456 1.1 thorpej */
1457 1.1 thorpej bus_space_write_4(st, sh, SIP_TXDP, SIP_CDTXADDR(sc, sc->sc_txnext));
1458 1.1 thorpej bus_space_write_4(st, sh, SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
1459 1.1 thorpej
1460 1.1 thorpej /*
1461 1.1 thorpej * Initialize the interrupt mask.
1462 1.1 thorpej */
1463 1.1 thorpej sc->sc_imr = ISR_DPERR|ISR_SSERR|ISR_RMABT|ISR_RTABT|ISR_RXSOVR|
1464 1.1 thorpej ISR_TXURN|ISR_TXDESC|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
1465 1.1 thorpej bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
1466 1.1 thorpej
1467 1.1 thorpej /*
1468 1.1 thorpej * Set the current media. Do this after initializing the prototype
1469 1.1 thorpej * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
1470 1.1 thorpej * control.
1471 1.1 thorpej */
1472 1.1 thorpej mii_mediachg(&sc->sc_mii);
1473 1.1 thorpej
1474 1.1 thorpej /*
1475 1.1 thorpej * Enable interrupts.
1476 1.1 thorpej */
1477 1.1 thorpej bus_space_write_4(st, sh, SIP_IER, IER_IE);
1478 1.1 thorpej
1479 1.1 thorpej /*
1480 1.1 thorpej * Start the transmit and receive processes.
1481 1.1 thorpej */
1482 1.1 thorpej bus_space_write_4(st, sh, SIP_CR, CR_RXE | CR_TXE);
1483 1.1 thorpej
1484 1.1 thorpej /*
1485 1.1 thorpej * Start the one second MII clock.
1486 1.1 thorpej */
1487 1.1 thorpej timeout(sip_tick, sc, hz);
1488 1.1 thorpej
1489 1.1 thorpej /*
1490 1.1 thorpej * ...all done!
1491 1.1 thorpej */
1492 1.1 thorpej ifp->if_flags |= IFF_RUNNING;
1493 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
1494 1.1 thorpej }
1495 1.1 thorpej
1496 1.1 thorpej /*
1497 1.1 thorpej * sip_stop:
1498 1.1 thorpej *
1499 1.1 thorpej * Stop transmission on the interface.
1500 1.1 thorpej */
1501 1.1 thorpej void
1502 1.1 thorpej sip_stop(sc)
1503 1.1 thorpej struct sip_softc *sc;
1504 1.1 thorpej {
1505 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1506 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1507 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1508 1.1 thorpej struct sip_txsoft *txs;
1509 1.1 thorpej u_int32_t cmdsts = 0; /* DEBUG */
1510 1.1 thorpej
1511 1.1 thorpej /*
1512 1.1 thorpej * Stop the one second clock.
1513 1.1 thorpej */
1514 1.1 thorpej untimeout(sip_tick, sc);
1515 1.1 thorpej
1516 1.1 thorpej /*
1517 1.1 thorpej * Disable interrupts.
1518 1.1 thorpej */
1519 1.1 thorpej bus_space_write_4(st, sh, SIP_IER, 0);
1520 1.1 thorpej
1521 1.1 thorpej /*
1522 1.1 thorpej * Stop receiver and transmitter.
1523 1.1 thorpej */
1524 1.1 thorpej bus_space_write_4(st, sh, SIP_CR, CR_RXD | CR_TXD);
1525 1.1 thorpej
1526 1.1 thorpej /*
1527 1.1 thorpej * Release any queued transmit buffers.
1528 1.1 thorpej */
1529 1.1 thorpej while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
1530 1.1 thorpej if ((ifp->if_flags & IFF_DEBUG) != 0 &&
1531 1.1 thorpej SIMPLEQ_NEXT(txs, txs_q) == NULL &&
1532 1.1 thorpej (sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts &
1533 1.1 thorpej CMDSTS_INTR) == 0)
1534 1.1 thorpej printf("%s: sip_stop: last descriptor does not "
1535 1.1 thorpej "have INTR bit set\n", sc->sc_dev.dv_xname);
1536 1.1 thorpej SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs, txs_q);
1537 1.1 thorpej #ifdef DIAGNOSTIC
1538 1.1 thorpej if (txs->txs_mbuf == NULL) {
1539 1.1 thorpej printf("%s: dirty txsoft with no mbuf chain\n",
1540 1.1 thorpej sc->sc_dev.dv_xname);
1541 1.1 thorpej panic("sip_stop");
1542 1.1 thorpej }
1543 1.1 thorpej #endif
1544 1.1 thorpej cmdsts |= /* DEBUG */
1545 1.1 thorpej sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts;
1546 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
1547 1.1 thorpej m_freem(txs->txs_mbuf);
1548 1.1 thorpej txs->txs_mbuf = NULL;
1549 1.1 thorpej SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1550 1.1 thorpej }
1551 1.1 thorpej
1552 1.1 thorpej /*
1553 1.1 thorpej * Mark the interface down and cancel the watchdog timer.
1554 1.1 thorpej */
1555 1.1 thorpej ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1556 1.1 thorpej ifp->if_timer = 0;
1557 1.1 thorpej
1558 1.1 thorpej if ((ifp->if_flags & IFF_DEBUG) != 0 &&
1559 1.1 thorpej (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != SIP_NTXDESC)
1560 1.1 thorpej printf("%s: sip_stop: no INTR bits set in dirty tx "
1561 1.1 thorpej "descriptors\n", sc->sc_dev.dv_xname);
1562 1.1 thorpej }
1563 1.1 thorpej
1564 1.1 thorpej /*
1565 1.1 thorpej * sip_read_eeprom:
1566 1.1 thorpej *
1567 1.1 thorpej * Read data from the serial EEPROM.
1568 1.1 thorpej */
1569 1.1 thorpej void
1570 1.1 thorpej sip_read_eeprom(sc, word, wordcnt, data)
1571 1.1 thorpej struct sip_softc *sc;
1572 1.1 thorpej int word, wordcnt;
1573 1.1 thorpej u_int16_t *data;
1574 1.1 thorpej {
1575 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1576 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1577 1.1 thorpej u_int16_t reg;
1578 1.1 thorpej int i, x;
1579 1.1 thorpej
1580 1.1 thorpej for (i = 0; i < wordcnt; i++) {
1581 1.1 thorpej /* Send CHIP SELECT. */
1582 1.1 thorpej reg = EROMAR_EECS;
1583 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1584 1.1 thorpej
1585 1.1 thorpej /* Shift in the READ opcode. */
1586 1.1 thorpej for (x = 3; x > 0; x--) {
1587 1.1 thorpej if (SIP_EEPROM_OPC_READ & (1 << (x - 1)))
1588 1.1 thorpej reg |= EROMAR_EEDI;
1589 1.1 thorpej else
1590 1.1 thorpej reg &= ~EROMAR_EEDI;
1591 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1592 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR,
1593 1.1 thorpej reg | EROMAR_EESK);
1594 1.1 thorpej delay(4);
1595 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1596 1.1 thorpej delay(4);
1597 1.1 thorpej }
1598 1.1 thorpej
1599 1.1 thorpej /* Shift in address. */
1600 1.1 thorpej for (x = 6; x > 0; x--) {
1601 1.1 thorpej if ((word + i) & (1 << (x - 1)))
1602 1.1 thorpej reg |= EROMAR_EEDI;
1603 1.1 thorpej else
1604 1.1 thorpej reg &= ~EROMAR_EEDI;
1605 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1606 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR,
1607 1.1 thorpej reg | EROMAR_EESK);
1608 1.1 thorpej delay(4);
1609 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1610 1.1 thorpej delay(4);
1611 1.1 thorpej }
1612 1.1 thorpej
1613 1.1 thorpej /* Shift out data. */
1614 1.1 thorpej reg = EROMAR_EECS;
1615 1.1 thorpej data[i] = 0;
1616 1.1 thorpej for (x = 16; x > 0; x--) {
1617 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR,
1618 1.1 thorpej reg | EROMAR_EESK);
1619 1.1 thorpej delay(4);
1620 1.1 thorpej if (bus_space_read_4(st, sh, SIP_EROMAR) & EROMAR_EEDO)
1621 1.1 thorpej data[i] |= (1 << (x - 1));
1622 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, reg);
1623 1.1 thorpej }
1624 1.1 thorpej
1625 1.1 thorpej /* Clear CHIP SELECT. */
1626 1.1 thorpej bus_space_write_4(st, sh, SIP_EROMAR, 0);
1627 1.1 thorpej delay(4);
1628 1.1 thorpej }
1629 1.1 thorpej }
1630 1.1 thorpej
1631 1.1 thorpej /*
1632 1.1 thorpej * sip_add_rxbuf:
1633 1.1 thorpej *
1634 1.1 thorpej * Add a receive buffer to the indicated descriptor.
1635 1.1 thorpej */
1636 1.1 thorpej int
1637 1.1 thorpej sip_add_rxbuf(sc, idx)
1638 1.1 thorpej struct sip_softc *sc;
1639 1.1 thorpej int idx;
1640 1.1 thorpej {
1641 1.1 thorpej struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];
1642 1.1 thorpej struct mbuf *m;
1643 1.1 thorpej int error;
1644 1.1 thorpej
1645 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
1646 1.1 thorpej if (m == NULL)
1647 1.1 thorpej return (ENOBUFS);
1648 1.1 thorpej
1649 1.1 thorpej MCLGET(m, M_DONTWAIT);
1650 1.1 thorpej if ((m->m_flags & M_EXT) == 0) {
1651 1.1 thorpej m_freem(m);
1652 1.1 thorpej return (ENOBUFS);
1653 1.1 thorpej }
1654 1.1 thorpej
1655 1.1 thorpej if (rxs->rxs_mbuf != NULL)
1656 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
1657 1.1 thorpej
1658 1.1 thorpej rxs->rxs_mbuf = m;
1659 1.1 thorpej
1660 1.1 thorpej error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
1661 1.1 thorpej m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
1662 1.1 thorpej if (error) {
1663 1.1 thorpej printf("%s: can't load rx DMA map %d, error = %d\n",
1664 1.1 thorpej sc->sc_dev.dv_xname, idx, error);
1665 1.1 thorpej panic("sip_add_rxbuf"); /* XXX */
1666 1.1 thorpej }
1667 1.1 thorpej
1668 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
1669 1.1 thorpej rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1670 1.1 thorpej
1671 1.1 thorpej SIP_INIT_RXDESC(sc, idx);
1672 1.1 thorpej
1673 1.1 thorpej return (0);
1674 1.1 thorpej }
1675 1.1 thorpej
1676 1.1 thorpej /*
1677 1.1 thorpej * sip_set_filter:
1678 1.1 thorpej *
1679 1.1 thorpej * Set up the receive filter.
1680 1.1 thorpej */
1681 1.1 thorpej void
1682 1.1 thorpej sip_set_filter(sc)
1683 1.1 thorpej struct sip_softc *sc;
1684 1.1 thorpej {
1685 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1686 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1687 1.1 thorpej struct ethercom *ec = &sc->sc_ethercom;
1688 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1689 1.1 thorpej struct ether_multi *enm;
1690 1.1 thorpej struct ether_multistep step;
1691 1.1 thorpej u_int8_t *cp;
1692 1.1 thorpej u_int32_t crc, mchash[8];
1693 1.1 thorpej int len;
1694 1.1 thorpej static const u_int32_t crctab[] = {
1695 1.1 thorpej 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1696 1.1 thorpej 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1697 1.1 thorpej 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1698 1.1 thorpej 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1699 1.1 thorpej };
1700 1.1 thorpej
1701 1.1 thorpej /*
1702 1.1 thorpej * Initialize the prototype RFCR.
1703 1.1 thorpej */
1704 1.1 thorpej sc->sc_rfcr = RFCR_RFEN;
1705 1.1 thorpej if (ifp->if_flags & IFF_BROADCAST)
1706 1.1 thorpej sc->sc_rfcr |= RFCR_AAB;
1707 1.1 thorpej if (ifp->if_flags & IFF_PROMISC) {
1708 1.1 thorpej sc->sc_rfcr |= RFCR_AAP;
1709 1.1 thorpej goto allmulti;
1710 1.1 thorpej }
1711 1.1 thorpej
1712 1.1 thorpej /*
1713 1.1 thorpej * Set up the multicast address filter by passing all multicast
1714 1.1 thorpej * addresses through a CRC generator, and then using the high-order
1715 1.1 thorpej * 6 bits as an index into the 128 bit multicast hash table (only
1716 1.1 thorpej * the lower 16 bits of each 32 bit multicast hash register are
1717 1.1 thorpej * valid). The high order bits select the register, while the
1718 1.1 thorpej * rest of the bits select the bit within the register.
1719 1.1 thorpej */
1720 1.1 thorpej
1721 1.1 thorpej memset(mchash, 0, sizeof(mchash));
1722 1.1 thorpej
1723 1.1 thorpej ETHER_FIRST_MULTI(step, ec, enm);
1724 1.1 thorpej while (enm != NULL) {
1725 1.1 thorpej if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1726 1.1 thorpej /*
1727 1.1 thorpej * We must listen to a range of multicast addresses.
1728 1.1 thorpej * For now, just accept all multicasts, rather than
1729 1.1 thorpej * trying to set only those filter bits needed to match
1730 1.1 thorpej * the range. (At this time, the only use of address
1731 1.1 thorpej * ranges is for IP multicast routing, for which the
1732 1.1 thorpej * range is big enough to require all bits set.)
1733 1.1 thorpej */
1734 1.1 thorpej goto allmulti;
1735 1.1 thorpej }
1736 1.1 thorpej
1737 1.1 thorpej cp = enm->enm_addrlo;
1738 1.1 thorpej crc = 0xffffffff;
1739 1.1 thorpej for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1740 1.1 thorpej crc ^= *cp++;
1741 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1742 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1743 1.1 thorpej }
1744 1.1 thorpej /* Just want the 7 most significant bits. */
1745 1.1 thorpej crc >>= 25;
1746 1.1 thorpej
1747 1.1 thorpej /* Set the corresponding bit in the hash table. */
1748 1.1 thorpej mchash[crc >> 4] |= 1 << (crc & 0xf);
1749 1.1 thorpej
1750 1.1 thorpej ETHER_NEXT_MULTI(step, enm);
1751 1.1 thorpej }
1752 1.1 thorpej
1753 1.1 thorpej ifp->if_flags &= ~IFF_ALLMULTI;
1754 1.1 thorpej goto setit;
1755 1.1 thorpej
1756 1.1 thorpej allmulti:
1757 1.1 thorpej ifp->if_flags |= IFF_ALLMULTI;
1758 1.1 thorpej sc->sc_rfcr |= RFCR_AAM;
1759 1.1 thorpej
1760 1.1 thorpej setit:
1761 1.1 thorpej #define FILTER_EMIT(addr, data) \
1762 1.1 thorpej bus_space_write_4(st, sh, SIP_RFCR, (addr)); \
1763 1.1 thorpej bus_space_write_4(st, sh, SIP_RFDR, (data))
1764 1.1 thorpej
1765 1.1 thorpej /*
1766 1.1 thorpej * Disable receive filter, and program the node address.
1767 1.1 thorpej */
1768 1.1 thorpej cp = LLADDR(ifp->if_sadl);
1769 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);
1770 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);
1771 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);
1772 1.1 thorpej
1773 1.1 thorpej if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
1774 1.1 thorpej /*
1775 1.1 thorpej * Program the multicast hash table.
1776 1.1 thorpej */
1777 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC0, mchash[0]);
1778 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC1, mchash[1]);
1779 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC2, mchash[2]);
1780 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC3, mchash[3]);
1781 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC4, mchash[4]);
1782 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC5, mchash[5]);
1783 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC6, mchash[6]);
1784 1.1 thorpej FILTER_EMIT(RFCR_RFADDR_MC7, mchash[7]);
1785 1.1 thorpej }
1786 1.1 thorpej #undef FILTER_EMIT
1787 1.1 thorpej
1788 1.1 thorpej /*
1789 1.1 thorpej * Re-enable the receiver filter.
1790 1.1 thorpej */
1791 1.1 thorpej bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
1792 1.1 thorpej }
1793 1.1 thorpej
1794 1.1 thorpej /*
1795 1.1 thorpej * sip_mii_readreg: [mii interface function]
1796 1.1 thorpej *
1797 1.1 thorpej * Read a PHY register on the MII.
1798 1.1 thorpej */
1799 1.1 thorpej int
1800 1.1 thorpej sip_mii_readreg(self, phy, reg)
1801 1.1 thorpej struct device *self;
1802 1.1 thorpej int phy, reg;
1803 1.1 thorpej {
1804 1.1 thorpej struct sip_softc *sc = (struct sip_softc *) self;
1805 1.1 thorpej u_int32_t enphy;
1806 1.1 thorpej
1807 1.1 thorpej /*
1808 1.1 thorpej * The SiS 900 has only an internal PHY on the MII. Only allow
1809 1.1 thorpej * MII address 0.
1810 1.1 thorpej */
1811 1.1 thorpej if (phy != 0)
1812 1.1 thorpej return (0);
1813 1.1 thorpej
1814 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
1815 1.1 thorpej (reg << ENPHY_REGADDR_SHIFT) | ENPHY_RWCMD | ENPHY_ACCESS);
1816 1.1 thorpej do {
1817 1.1 thorpej enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
1818 1.1 thorpej } while (enphy & ENPHY_ACCESS);
1819 1.1 thorpej return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
1820 1.1 thorpej }
1821 1.1 thorpej
1822 1.1 thorpej /*
1823 1.1 thorpej * sip_mii_writereg: [mii interface function]
1824 1.1 thorpej *
1825 1.1 thorpej * Write a PHY register on the MII.
1826 1.1 thorpej */
1827 1.1 thorpej void
1828 1.1 thorpej sip_mii_writereg(self, phy, reg, val)
1829 1.1 thorpej struct device *self;
1830 1.1 thorpej int phy, reg, val;
1831 1.1 thorpej {
1832 1.1 thorpej struct sip_softc *sc = (struct sip_softc *) self;
1833 1.1 thorpej u_int32_t enphy;
1834 1.1 thorpej
1835 1.1 thorpej /*
1836 1.1 thorpej * The SiS 900 has only an internal PHY on the MII. Only allow
1837 1.1 thorpej * MII address 0.
1838 1.1 thorpej */
1839 1.1 thorpej if (phy != 0)
1840 1.1 thorpej return;
1841 1.1 thorpej
1842 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
1843 1.1 thorpej (val << ENPHY_DATA_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
1844 1.1 thorpej ENPHY_ACCESS);
1845 1.1 thorpej do {
1846 1.1 thorpej enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
1847 1.1 thorpej } while (enphy & ENPHY_ACCESS);
1848 1.1 thorpej }
1849 1.1 thorpej
1850 1.1 thorpej /*
1851 1.1 thorpej * sip_mii_statchg: [mii interface function]
1852 1.1 thorpej *
1853 1.1 thorpej * Callback from MII layer when media changes.
1854 1.1 thorpej */
1855 1.1 thorpej void
1856 1.1 thorpej sip_mii_statchg(self)
1857 1.1 thorpej struct device *self;
1858 1.1 thorpej {
1859 1.1 thorpej struct sip_softc *sc = (struct sip_softc *) self;
1860 1.1 thorpej u_int32_t flowctl;
1861 1.1 thorpej
1862 1.1 thorpej /*
1863 1.1 thorpej * Update TXCFG for full-duplex operation.
1864 1.1 thorpej */
1865 1.1 thorpej if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0)
1866 1.1 thorpej sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
1867 1.1 thorpej else
1868 1.1 thorpej sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
1869 1.1 thorpej
1870 1.1 thorpej /*
1871 1.1 thorpej * Update RXCFG for full-duplex or loopback.
1872 1.1 thorpej */
1873 1.1 thorpej if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0 ||
1874 1.1 thorpej IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_LOOP)
1875 1.1 thorpej sc->sc_rxcfg |= RXCFG_ATX;
1876 1.1 thorpej else
1877 1.1 thorpej sc->sc_rxcfg &= ~RXCFG_ATX;
1878 1.1 thorpej
1879 1.1 thorpej /*
1880 1.1 thorpej * Update IMR for use of 802.3x flow control.
1881 1.1 thorpej */
1882 1.1 thorpej if ((sc->sc_mii.mii_media_active & IFM_FLOW) != 0) {
1883 1.1 thorpej sc->sc_imr |= (ISR_PAUSE_END|ISR_PAUSE_ST);
1884 1.1 thorpej flowctl = FLOWCTL_FLOWEN;
1885 1.1 thorpej } else {
1886 1.1 thorpej sc->sc_imr &= ~(ISR_PAUSE_END|ISR_PAUSE_ST);
1887 1.1 thorpej flowctl = 0;
1888 1.1 thorpej }
1889 1.1 thorpej
1890 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);
1891 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);
1892 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
1893 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
1894 1.1 thorpej
1895 1.1 thorpej /* XXX Update ifp->if_baudrate */
1896 1.1 thorpej }
1897 1.1 thorpej
1898 1.1 thorpej /*
1899 1.1 thorpej * sip_mediastatus: [ifmedia interface function]
1900 1.1 thorpej *
1901 1.1 thorpej * Get the current interface media status.
1902 1.1 thorpej */
1903 1.1 thorpej void
1904 1.1 thorpej sip_mediastatus(ifp, ifmr)
1905 1.1 thorpej struct ifnet *ifp;
1906 1.1 thorpej struct ifmediareq *ifmr;
1907 1.1 thorpej {
1908 1.1 thorpej struct sip_softc *sc = ifp->if_softc;
1909 1.1 thorpej
1910 1.1 thorpej mii_pollstat(&sc->sc_mii);
1911 1.1 thorpej ifmr->ifm_status = sc->sc_mii.mii_media_status;
1912 1.1 thorpej ifmr->ifm_active = sc->sc_mii.mii_media_active;
1913 1.1 thorpej }
1914 1.1 thorpej
1915 1.1 thorpej /*
1916 1.1 thorpej * sip_mediachange: [ifmedia interface function]
1917 1.1 thorpej *
1918 1.1 thorpej * Set hardware to newly-selected media.
1919 1.1 thorpej */
1920 1.1 thorpej int
1921 1.1 thorpej sip_mediachange(ifp)
1922 1.1 thorpej struct ifnet *ifp;
1923 1.1 thorpej {
1924 1.1 thorpej struct sip_softc *sc = ifp->if_softc;
1925 1.1 thorpej
1926 1.1 thorpej if (ifp->if_flags & IFF_UP)
1927 1.1 thorpej mii_mediachg(&sc->sc_mii);
1928 1.1 thorpej return (0);
1929 1.1 thorpej }
1930