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