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