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