1 /* $OpenBSD: if_vic.c,v 1.106 2024/05/24 06:02:57 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * Driver for the VMware Virtual NIC ("vmxnet")
22 */
23
24 #include "bpfilter.h"
25
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/sockio.h>
29 #include <sys/mbuf.h>
30 #include <sys/socket.h>
31 #include <sys/malloc.h>
32 #include <sys/timeout.h>
33 #include <sys/device.h>
34
35 #include <machine/bus.h>
36 #include <machine/intr.h>
37
38 #include <net/if.h>
39 #include <net/if_media.h>
40
41 #if NBPFILTER > 0
42 #include <net/bpf.h>
43 #endif
44
45 #include <netinet/in.h>
46 #include <netinet/if_ether.h>
47
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pcidevs.h>
51
52 #define VIC_PCI_BAR PCI_MAPREG_START /* Base Address Register */
53
54 #define VIC_LANCE_SIZE 0x20
55 #define VIC_MORPH_SIZE 0x04
56 #define VIC_MORPH_MASK 0xffff
57 #define VIC_MORPH_LANCE 0x2934
58 #define VIC_MORPH_VMXNET 0x4392
59 #define VIC_VMXNET_SIZE 0x40
60 #define VIC_LANCE_MINLEN (VIC_LANCE_SIZE + VIC_MORPH_SIZE + \
61 VIC_VMXNET_SIZE)
62
63 #define VIC_MAGIC 0xbabe864f
64
65 /* Register address offsets */
66 #define VIC_DATA_ADDR 0x0000 /* Shared data address */
67 #define VIC_DATA_LENGTH 0x0004 /* Shared data length */
68 #define VIC_Tx_ADDR 0x0008 /* Tx pointer address */
69
70 /* Command register */
71 #define VIC_CMD 0x000c /* Command register */
72 #define VIC_CMD_INTR_ACK 0x0001 /* Acknowledge interrupt */
73 #define VIC_CMD_MCASTFIL 0x0002 /* Multicast address filter */
74 #define VIC_CMD_MCASTFIL_LENGTH 2
75 #define VIC_CMD_IFF 0x0004 /* Interface flags */
76 #define VIC_CMD_IFF_PROMISC 0x0001 /* Promiscuous enabled */
77 #define VIC_CMD_IFF_BROADCAST 0x0002 /* Broadcast enabled */
78 #define VIC_CMD_IFF_MULTICAST 0x0004 /* Multicast enabled */
79 #define VIC_CMD_INTR_DISABLE 0x0020 /* Disable interrupts */
80 #define VIC_CMD_INTR_ENABLE 0x0040 /* Enable interrupts */
81 #define VIC_CMD_Tx_DONE 0x0100 /* Tx done register */
82 #define VIC_CMD_NUM_Rx_BUF 0x0200 /* Number of Rx buffers */
83 #define VIC_CMD_NUM_Tx_BUF 0x0400 /* Number of Tx buffers */
84 #define VIC_CMD_NUM_PINNED_BUF 0x0800 /* Number of pinned buffers */
85 #define VIC_CMD_HWCAP 0x1000 /* Capability register */
86 #define VIC_CMD_HWCAP_SG (1<<0) /* Scatter-gather transmits */
87 #define VIC_CMD_HWCAP_CSUM_IPv4 (1<<1) /* TCP/UDP cksum */
88 #define VIC_CMD_HWCAP_CSUM_ALL (1<<3) /* Hardware cksum */
89 #define VIC_CMD_HWCAP_CSUM \
90 (VIC_CMD_HWCAP_CSUM_IPv4 | VIC_CMD_HWCAP_CSUM_ALL)
91 #define VIC_CMD_HWCAP_DMA_HIGH (1<<4) /* High DMA mapping */
92 #define VIC_CMD_HWCAP_TOE (1<<5) /* TCP offload engine */
93 #define VIC_CMD_HWCAP_TSO (1<<6) /* TCP segmentation offload */
94 #define VIC_CMD_HWCAP_TSO_SW (1<<7) /* Software TCP segmentation */
95 #define VIC_CMD_HWCAP_VPROM (1<<8) /* Virtual PROM available */
96 #define VIC_CMD_HWCAP_VLAN_Tx (1<<9) /* Hardware VLAN MTU Rx */
97 #define VIC_CMD_HWCAP_VLAN_Rx (1<<10) /* Hardware VLAN MTU Tx */
98 #define VIC_CMD_HWCAP_VLAN_SW (1<<11) /* Software VLAN MTU */
99 #define VIC_CMD_HWCAP_VLAN \
100 (VIC_CMD_HWCAP_VLAN_Tx | VIC_CMD_HWCAP_VLAN_Rx | \
101 VIC_CMD_HWCAP_VLAN_SW)
102 #define VIC_CMD_HWCAP_BITS \
103 "\20\01SG\02CSUM4\03CSUM\04HDMA\05TOE\06TSO" \
104 "\07TSOSW\10VPROM\13VLANTx\14VLANRx\15VLANSW"
105 #define VIC_CMD_FEATURE 0x2000 /* Additional feature register */
106 #define VIC_CMD_FEATURE_0_Tx (1<<0)
107 #define VIC_CMD_FEATURE_TSO (1<<1)
108
109 #define VIC_LLADDR 0x0010 /* MAC address register */
110 #define VIC_VERSION_MINOR 0x0018 /* Minor version register */
111 #define VIC_VERSION_MAJOR 0x001c /* Major version register */
112 #define VIC_VERSION_MAJOR_M 0xffff0000
113
114 /* Status register */
115 #define VIC_STATUS 0x0020
116 #define VIC_STATUS_CONNECTED (1<<0)
117 #define VIC_STATUS_ENABLED (1<<1)
118
119 #define VIC_TOE_ADDR 0x0024 /* TCP offload address */
120
121 /* Virtual PROM address */
122 #define VIC_VPROM 0x0028
123 #define VIC_VPROM_LENGTH 6
124
125 /* Shared DMA data structures */
126
127 struct vic_sg {
128 u_int32_t sg_addr_low;
129 u_int16_t sg_addr_high;
130 u_int16_t sg_length;
131 } __packed;
132
133 #define VIC_SG_MAX 6
134 #define VIC_SG_ADDR_MACH 0
135 #define VIC_SG_ADDR_PHYS 1
136 #define VIC_SG_ADDR_VIRT 3
137
138 struct vic_sgarray {
139 u_int16_t sa_addr_type;
140 u_int16_t sa_length;
141 struct vic_sg sa_sg[VIC_SG_MAX];
142 } __packed;
143
144 struct vic_rxdesc {
145 u_int64_t rx_physaddr;
146 u_int32_t rx_buflength;
147 u_int32_t rx_length;
148 u_int16_t rx_owner;
149 u_int16_t rx_flags;
150 u_int32_t rx_priv;
151 } __packed;
152
153 #define VIC_RX_FLAGS_CSUMHW_OK 0x0001
154
155 struct vic_txdesc {
156 u_int16_t tx_flags;
157 u_int16_t tx_owner;
158 u_int32_t tx_priv;
159 u_int32_t tx_tsomss;
160 struct vic_sgarray tx_sa;
161 } __packed;
162
163 #define VIC_TX_FLAGS_KEEP 0x0001
164 #define VIC_TX_FLAGS_TXURN 0x0002
165 #define VIC_TX_FLAGS_CSUMHW 0x0004
166 #define VIC_TX_FLAGS_TSO 0x0008
167 #define VIC_TX_FLAGS_PINNED 0x0010
168 #define VIC_TX_FLAGS_QRETRY 0x1000
169
170 struct vic_stats {
171 u_int32_t vs_tx_count;
172 u_int32_t vs_tx_packets;
173 u_int32_t vs_tx_0copy;
174 u_int32_t vs_tx_copy;
175 u_int32_t vs_tx_maxpending;
176 u_int32_t vs_tx_stopped;
177 u_int32_t vs_tx_overrun;
178 u_int32_t vs_intr;
179 u_int32_t vs_rx_packets;
180 u_int32_t vs_rx_underrun;
181 } __packed;
182
183 #define VIC_NRXRINGS 2
184
185 struct vic_data {
186 u_int32_t vd_magic;
187
188 struct {
189 u_int32_t length;
190 u_int32_t nextidx;
191 } vd_rx[VIC_NRXRINGS];
192
193 u_int32_t vd_irq;
194 u_int32_t vd_iff;
195
196 u_int32_t vd_mcastfil[VIC_CMD_MCASTFIL_LENGTH];
197
198 u_int32_t vd_reserved1[1];
199
200 u_int32_t vd_tx_length;
201 u_int32_t vd_tx_curidx;
202 u_int32_t vd_tx_nextidx;
203 u_int32_t vd_tx_stopped;
204 u_int32_t vd_tx_triggerlvl;
205 u_int32_t vd_tx_queued;
206 u_int32_t vd_tx_minlength;
207
208 u_int32_t vd_reserved2[6];
209
210 u_int32_t vd_rx_saved_nextidx[VIC_NRXRINGS];
211 u_int32_t vd_tx_saved_nextidx;
212
213 u_int32_t vd_length;
214 u_int32_t vd_rx_offset[VIC_NRXRINGS];
215 u_int32_t vd_tx_offset;
216 u_int32_t vd_debug;
217 u_int32_t vd_tx_physaddr;
218 u_int32_t vd_tx_physaddr_length;
219 u_int32_t vd_tx_maxlength;
220
221 struct vic_stats vd_stats;
222 } __packed;
223
224 #define VIC_OWNER_DRIVER 0
225 #define VIC_OWNER_DRIVER_PEND 1
226 #define VIC_OWNER_NIC 2
227 #define VIC_OWNER_NIC_PEND 3
228
229 #define VIC_JUMBO_FRAMELEN 9018
230 #define VIC_JUMBO_MTU (VIC_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
231
232 #define VIC_NBUF 100
233 #define VIC_NBUF_MAX 128
234 #define VIC_MAX_SCATTER 1 /* 8? */
235 #define VIC_QUEUE_SIZE VIC_NBUF_MAX
236 #define VIC_INC(_x, _y) (_x) = ((_x) + 1) % (_y)
237 #define VIC_TX_TIMEOUT 5
238
239 #define VIC_MIN_FRAMELEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
240
241 #define VIC_TXURN_WARN(_sc) ((_sc)->sc_txpending >= ((_sc)->sc_ntxbuf - 5))
242 #define VIC_TXURN(_sc) ((_sc)->sc_txpending >= (_sc)->sc_ntxbuf)
243
244 struct vic_rxbuf {
245 bus_dmamap_t rxb_dmamap;
246 struct mbuf *rxb_m;
247 };
248
249 struct vic_txbuf {
250 bus_dmamap_t txb_dmamap;
251 struct mbuf *txb_m;
252 };
253
254 struct vic_softc {
255 struct device sc_dev;
256
257 pci_chipset_tag_t sc_pc;
258 pcitag_t sc_tag;
259
260 bus_space_tag_t sc_iot;
261 bus_space_handle_t sc_ioh;
262 bus_size_t sc_ios;
263 bus_dma_tag_t sc_dmat;
264
265 void *sc_ih;
266
267 struct timeout sc_tick;
268
269 struct arpcom sc_ac;
270 struct ifmedia sc_media;
271
272 u_int32_t sc_nrxbuf;
273 u_int32_t sc_ntxbuf;
274 u_int32_t sc_cap;
275 u_int32_t sc_feature;
276 u_int8_t sc_lladdr[ETHER_ADDR_LEN];
277
278 bus_dmamap_t sc_dma_map;
279 bus_dma_segment_t sc_dma_seg;
280 size_t sc_dma_size;
281 caddr_t sc_dma_kva;
282 #define VIC_DMA_DVA(_sc) ((_sc)->sc_dma_map->dm_segs[0].ds_addr)
283 #define VIC_DMA_KVA(_sc) ((void *)(_sc)->sc_dma_kva)
284
285 struct vic_data *sc_data;
286
287 struct {
288 struct if_rxring ring;
289 struct vic_rxbuf *bufs;
290 struct vic_rxdesc *slots;
291 int end;
292 u_int pktlen;
293 } sc_rxq[VIC_NRXRINGS];
294
295 struct vic_txbuf *sc_txbuf;
296 struct vic_txdesc *sc_txq;
297 volatile u_int sc_txpending;
298 };
299
300 struct cfdriver vic_cd = {
301 NULL, "vic", DV_IFNET
302 };
303
304 int vic_match(struct device *, void *, void *);
305 void vic_attach(struct device *, struct device *, void *);
306
307 const struct cfattach vic_ca = {
308 sizeof(struct vic_softc), vic_match, vic_attach
309 };
310
311 int vic_intr(void *);
312
313 int vic_query(struct vic_softc *);
314 int vic_alloc_data(struct vic_softc *);
315 int vic_init_data(struct vic_softc *sc);
316 int vic_uninit_data(struct vic_softc *sc);
317
318 u_int32_t vic_read(struct vic_softc *, bus_size_t);
319 void vic_write(struct vic_softc *, bus_size_t, u_int32_t);
320
321 u_int32_t vic_read_cmd(struct vic_softc *, u_int32_t);
322
323 int vic_alloc_dmamem(struct vic_softc *);
324 void vic_free_dmamem(struct vic_softc *);
325
326 void vic_link_state(struct vic_softc *);
327 void vic_rx_fill(struct vic_softc *, int);
328 void vic_rx_proc(struct vic_softc *, int);
329 void vic_tx_proc(struct vic_softc *);
330 void vic_iff(struct vic_softc *);
331 void vic_getlladdr(struct vic_softc *);
332 void vic_setlladdr(struct vic_softc *);
333 int vic_media_change(struct ifnet *);
334 void vic_media_status(struct ifnet *, struct ifmediareq *);
335 void vic_start(struct ifnet *);
336 int vic_load_txb(struct vic_softc *, struct vic_txbuf *,
337 struct mbuf *);
338 void vic_watchdog(struct ifnet *);
339 int vic_ioctl(struct ifnet *, u_long, caddr_t);
340 int vic_rxrinfo(struct vic_softc *, struct if_rxrinfo *);
341 void vic_init(struct ifnet *);
342 void vic_stop(struct ifnet *);
343 void vic_tick(void *);
344
345 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
346
347 struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t, u_int);
348
349 const struct pci_matchid vic_devices[] = {
350 { PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET }
351 };
352
353 int
vic_match(struct device * parent,void * match,void * aux)354 vic_match(struct device *parent, void *match, void *aux)
355 {
356 struct pci_attach_args *pa = aux;
357 pcireg_t memtype;
358 bus_size_t pcisize;
359 bus_addr_t pciaddr;
360
361 switch (pa->pa_id) {
362 case PCI_ID_CODE(PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET):
363 return (1);
364
365 case PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNET_PCI):
366 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, VIC_PCI_BAR);
367 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, VIC_PCI_BAR,
368 memtype, &pciaddr, &pcisize, NULL) != 0)
369 break;
370
371 if (pcisize > VIC_LANCE_MINLEN)
372 return (2);
373
374 break;
375 }
376
377 return (0);
378 }
379
380 void
vic_attach(struct device * parent,struct device * self,void * aux)381 vic_attach(struct device *parent, struct device *self, void *aux)
382 {
383 struct vic_softc *sc = (struct vic_softc *)self;
384 struct pci_attach_args *pa = aux;
385 bus_space_handle_t ioh;
386 pcireg_t r;
387 pci_intr_handle_t ih;
388 struct ifnet *ifp;
389
390 sc->sc_pc = pa->pa_pc;
391 sc->sc_tag = pa->pa_tag;
392 sc->sc_dmat = pa->pa_dmat;
393
394 r = pci_mapreg_type(sc->sc_pc, sc->sc_tag, VIC_PCI_BAR);
395 if (pci_mapreg_map(pa, VIC_PCI_BAR, r, 0, &sc->sc_iot,
396 &ioh, NULL, &sc->sc_ios, 0) != 0) {
397 printf(": unable to map system interface register\n");
398 return;
399 }
400
401 switch (pa->pa_id) {
402 case PCI_ID_CODE(PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET):
403 if (bus_space_subregion(sc->sc_iot, ioh, 0, sc->sc_ios,
404 &sc->sc_ioh) != 0) {
405 printf(": unable to map register window\n");
406 goto unmap;
407 }
408 break;
409
410 case PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNET_PCI):
411 if (bus_space_subregion(sc->sc_iot, ioh,
412 VIC_LANCE_SIZE + VIC_MORPH_SIZE, VIC_VMXNET_SIZE,
413 &sc->sc_ioh) != 0) {
414 printf(": unable to map register window\n");
415 goto unmap;
416 }
417
418 bus_space_barrier(sc->sc_iot, ioh, VIC_LANCE_SIZE, 4,
419 BUS_SPACE_BARRIER_READ);
420 r = bus_space_read_4(sc->sc_iot, ioh, VIC_LANCE_SIZE);
421
422 if ((r & VIC_MORPH_MASK) == VIC_MORPH_VMXNET)
423 break;
424 if ((r & VIC_MORPH_MASK) != VIC_MORPH_LANCE) {
425 printf(": unexpected morph value (0x%08x)\n", r);
426 goto unmap;
427 }
428
429 r &= ~VIC_MORPH_MASK;
430 r |= VIC_MORPH_VMXNET;
431
432 bus_space_write_4(sc->sc_iot, ioh, VIC_LANCE_SIZE, r);
433 bus_space_barrier(sc->sc_iot, ioh, VIC_LANCE_SIZE, 4,
434 BUS_SPACE_BARRIER_WRITE);
435
436 bus_space_barrier(sc->sc_iot, ioh, VIC_LANCE_SIZE, 4,
437 BUS_SPACE_BARRIER_READ);
438 r = bus_space_read_4(sc->sc_iot, ioh, VIC_LANCE_SIZE);
439
440 if ((r & VIC_MORPH_MASK) != VIC_MORPH_VMXNET) {
441 printf(": unable to morph vlance chip\n");
442 goto unmap;
443 }
444
445 break;
446 }
447
448 if (pci_intr_map(pa, &ih) != 0) {
449 printf(": unable to map interrupt\n");
450 goto unmap;
451 }
452
453 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
454 vic_intr, sc, DEVNAME(sc));
455 if (sc->sc_ih == NULL) {
456 printf(": unable to establish interrupt\n");
457 goto unmap;
458 }
459
460 if (vic_query(sc) != 0) {
461 /* error printed by vic_query */
462 goto unmap;
463 }
464
465 if (vic_alloc_data(sc) != 0) {
466 /* error printed by vic_alloc */
467 goto unmap;
468 }
469
470 timeout_set(&sc->sc_tick, vic_tick, sc);
471
472 bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
473
474 ifp = &sc->sc_ac.ac_if;
475 ifp->if_softc = sc;
476 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
477 ifp->if_ioctl = vic_ioctl;
478 ifp->if_start = vic_start;
479 ifp->if_watchdog = vic_watchdog;
480 ifp->if_hardmtu = VIC_JUMBO_MTU;
481 strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
482 ifq_init_maxlen(&ifp->if_snd, sc->sc_ntxbuf - 1);
483
484 ifp->if_capabilities = IFCAP_VLAN_MTU;
485
486 #if 0
487 /* XXX interface capabilities */
488 if (sc->sc_cap & VIC_CMD_HWCAP_VLAN)
489 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
490 if (sc->sc_cap & VIC_CMD_HWCAP_CSUM)
491 ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
492 IFCAP_CSUM_UDPv4;
493 #endif
494
495 ifmedia_init(&sc->sc_media, 0, vic_media_change, vic_media_status);
496 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
497 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
498
499 if_attach(ifp);
500 ether_ifattach(ifp);
501
502 printf(": %s, address %s\n", pci_intr_string(pa->pa_pc, ih),
503 ether_sprintf(sc->sc_lladdr));
504
505 #ifdef VIC_DEBUG
506 printf("%s: feature 0x%8x, cap 0x%8x, rx/txbuf %d/%d\n", DEVNAME(sc),
507 sc->sc_feature, sc->sc_cap, sc->sc_nrxbuf, sc->sc_ntxbuf);
508 #endif
509
510 return;
511
512 unmap:
513 bus_space_unmap(sc->sc_iot, ioh, sc->sc_ios);
514 sc->sc_ios = 0;
515 }
516
517 int
vic_query(struct vic_softc * sc)518 vic_query(struct vic_softc *sc)
519 {
520 u_int32_t major, minor;
521
522 major = vic_read(sc, VIC_VERSION_MAJOR);
523 minor = vic_read(sc, VIC_VERSION_MINOR);
524
525 /* Check for a supported version */
526 if ((major & VIC_VERSION_MAJOR_M) !=
527 (VIC_MAGIC & VIC_VERSION_MAJOR_M)) {
528 printf(": magic mismatch\n");
529 return (1);
530 }
531
532 if (VIC_MAGIC > major || VIC_MAGIC < minor) {
533 printf(": unsupported version (%X)\n",
534 major & ~VIC_VERSION_MAJOR_M);
535 return (1);
536 }
537
538 sc->sc_nrxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Rx_BUF);
539 sc->sc_ntxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Tx_BUF);
540 sc->sc_feature = vic_read_cmd(sc, VIC_CMD_FEATURE);
541 sc->sc_cap = vic_read_cmd(sc, VIC_CMD_HWCAP);
542
543 vic_getlladdr(sc);
544
545 if (sc->sc_nrxbuf > VIC_NBUF_MAX || sc->sc_nrxbuf == 0)
546 sc->sc_nrxbuf = VIC_NBUF;
547 if (sc->sc_ntxbuf > VIC_NBUF_MAX || sc->sc_ntxbuf == 0)
548 sc->sc_ntxbuf = VIC_NBUF;
549
550 return (0);
551 }
552
553 int
vic_alloc_data(struct vic_softc * sc)554 vic_alloc_data(struct vic_softc *sc)
555 {
556 u_int8_t *kva;
557 u_int offset;
558 struct vic_rxdesc *rxd;
559 int i, q;
560
561 sc->sc_rxq[0].pktlen = MCLBYTES;
562 sc->sc_rxq[1].pktlen = 4096;
563
564 for (q = 0; q < VIC_NRXRINGS; q++) {
565 sc->sc_rxq[q].bufs = mallocarray(sc->sc_nrxbuf,
566 sizeof(struct vic_rxbuf), M_DEVBUF, M_NOWAIT | M_ZERO);
567 if (sc->sc_rxq[q].bufs == NULL) {
568 printf(": unable to allocate rxbuf for ring %d\n", q);
569 goto freerx;
570 }
571 }
572
573 sc->sc_txbuf = mallocarray(sc->sc_ntxbuf, sizeof(struct vic_txbuf),
574 M_DEVBUF, M_NOWAIT);
575 if (sc->sc_txbuf == NULL) {
576 printf(": unable to allocate txbuf\n");
577 goto freerx;
578 }
579
580 sc->sc_dma_size = sizeof(struct vic_data) +
581 (sc->sc_nrxbuf * VIC_NRXRINGS) * sizeof(struct vic_rxdesc) +
582 sc->sc_ntxbuf * sizeof(struct vic_txdesc);
583
584 if (vic_alloc_dmamem(sc) != 0) {
585 printf(": unable to allocate dma region\n");
586 goto freetx;
587 }
588 kva = VIC_DMA_KVA(sc);
589
590 /* set up basic vic data */
591 sc->sc_data = VIC_DMA_KVA(sc);
592
593 sc->sc_data->vd_magic = VIC_MAGIC;
594 sc->sc_data->vd_length = sc->sc_dma_size;
595
596 offset = sizeof(struct vic_data);
597
598 /* set up the rx rings */
599
600 for (q = 0; q < VIC_NRXRINGS; q++) {
601 sc->sc_rxq[q].slots = (struct vic_rxdesc *)&kva[offset];
602 sc->sc_data->vd_rx_offset[q] = offset;
603 sc->sc_data->vd_rx[q].length = sc->sc_nrxbuf;
604
605 for (i = 0; i < sc->sc_nrxbuf; i++) {
606 rxd = &sc->sc_rxq[q].slots[i];
607
608 rxd->rx_physaddr = 0;
609 rxd->rx_buflength = 0;
610 rxd->rx_length = 0;
611 rxd->rx_owner = VIC_OWNER_DRIVER;
612
613 offset += sizeof(struct vic_rxdesc);
614 }
615 }
616
617 /* set up the tx ring */
618 sc->sc_txq = (struct vic_txdesc *)&kva[offset];
619
620 sc->sc_data->vd_tx_offset = offset;
621 sc->sc_data->vd_tx_length = sc->sc_ntxbuf;
622
623 return (0);
624 freetx:
625 free(sc->sc_txbuf, M_DEVBUF, 0);
626 q = VIC_NRXRINGS;
627 freerx:
628 while (q--)
629 free(sc->sc_rxq[q].bufs, M_DEVBUF, 0);
630
631 return (1);
632 }
633
634 void
vic_rx_fill(struct vic_softc * sc,int q)635 vic_rx_fill(struct vic_softc *sc, int q)
636 {
637 struct vic_rxbuf *rxb;
638 struct vic_rxdesc *rxd;
639 u_int slots;
640
641 for (slots = if_rxr_get(&sc->sc_rxq[q].ring, sc->sc_nrxbuf);
642 slots > 0; slots--) {
643 rxb = &sc->sc_rxq[q].bufs[sc->sc_rxq[q].end];
644 rxd = &sc->sc_rxq[q].slots[sc->sc_rxq[q].end];
645
646 rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap,
647 sc->sc_rxq[q].pktlen);
648 if (rxb->rxb_m == NULL)
649 break;
650
651 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
652 rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
653
654 rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr;
655 rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len;
656 rxd->rx_length = 0;
657 rxd->rx_owner = VIC_OWNER_NIC;
658
659 VIC_INC(sc->sc_rxq[q].end, sc->sc_data->vd_rx[q].length);
660 }
661 if_rxr_put(&sc->sc_rxq[q].ring, slots);
662 }
663
664 int
vic_init_data(struct vic_softc * sc)665 vic_init_data(struct vic_softc *sc)
666 {
667 struct vic_rxbuf *rxb;
668 struct vic_rxdesc *rxd;
669 struct vic_txbuf *txb;
670
671 int q, i;
672
673 for (q = 0; q < VIC_NRXRINGS; q++) {
674 for (i = 0; i < sc->sc_nrxbuf; i++) {
675 rxb = &sc->sc_rxq[q].bufs[i];
676 rxd = &sc->sc_rxq[q].slots[i];
677
678 if (bus_dmamap_create(sc->sc_dmat,
679 sc->sc_rxq[q].pktlen, 1, sc->sc_rxq[q].pktlen, 0,
680 BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) {
681 printf("%s: unable to create dmamap for "
682 "ring %d slot %d\n", DEVNAME(sc), q, i);
683 goto freerxbs;
684 }
685
686 /* scrub the ring */
687 rxd->rx_physaddr = 0;
688 rxd->rx_buflength = 0;
689 rxd->rx_length = 0;
690 rxd->rx_owner = VIC_OWNER_DRIVER;
691 }
692 sc->sc_rxq[q].end = 0;
693
694 if_rxr_init(&sc->sc_rxq[q].ring, 2, sc->sc_nrxbuf - 1);
695 vic_rx_fill(sc, q);
696 }
697
698 for (i = 0; i < sc->sc_ntxbuf; i++) {
699 txb = &sc->sc_txbuf[i];
700 if (bus_dmamap_create(sc->sc_dmat, VIC_JUMBO_FRAMELEN,
701 (sc->sc_cap & VIC_CMD_HWCAP_SG) ? VIC_SG_MAX : 1,
702 VIC_JUMBO_FRAMELEN, 0, BUS_DMA_NOWAIT,
703 &txb->txb_dmamap) != 0) {
704 printf("%s: unable to create dmamap for tx %d\n",
705 DEVNAME(sc), i);
706 goto freetxbs;
707 }
708 txb->txb_m = NULL;
709 }
710
711 return (0);
712
713 freetxbs:
714 while (i--) {
715 txb = &sc->sc_txbuf[i];
716 bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
717 }
718
719 i = sc->sc_nrxbuf;
720 q = VIC_NRXRINGS - 1;
721 freerxbs:
722 while (q >= 0) {
723 while (i--) {
724 rxb = &sc->sc_rxq[q].bufs[i];
725
726 if (rxb->rxb_m != NULL) {
727 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap,
728 0, rxb->rxb_m->m_pkthdr.len,
729 BUS_DMASYNC_POSTREAD);
730 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
731 m_freem(rxb->rxb_m);
732 rxb->rxb_m = NULL;
733 }
734 bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
735 }
736 q--;
737 }
738
739 return (1);
740 }
741
742 int
vic_uninit_data(struct vic_softc * sc)743 vic_uninit_data(struct vic_softc *sc)
744 {
745 struct vic_rxbuf *rxb;
746 struct vic_rxdesc *rxd;
747 struct vic_txbuf *txb;
748
749 int i, q;
750
751 for (q = 0; q < VIC_NRXRINGS; q++) {
752 for (i = 0; i < sc->sc_nrxbuf; i++) {
753 rxb = &sc->sc_rxq[q].bufs[i];
754 rxd = &sc->sc_rxq[q].slots[i];
755
756 if (rxb->rxb_m != NULL) {
757 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap,
758 0, rxb->rxb_m->m_pkthdr.len,
759 BUS_DMASYNC_POSTREAD);
760 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
761 m_freem(rxb->rxb_m);
762 rxb->rxb_m = NULL;
763 }
764 bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
765 }
766 }
767
768 for (i = 0; i < sc->sc_ntxbuf; i++) {
769 txb = &sc->sc_txbuf[i];
770 bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
771 }
772
773 return (0);
774 }
775
776 void
vic_link_state(struct vic_softc * sc)777 vic_link_state(struct vic_softc *sc)
778 {
779 struct ifnet *ifp = &sc->sc_ac.ac_if;
780 u_int32_t status;
781 int link_state = LINK_STATE_DOWN;
782
783 status = vic_read(sc, VIC_STATUS);
784 if (status & VIC_STATUS_CONNECTED)
785 link_state = LINK_STATE_FULL_DUPLEX;
786 if (ifp->if_link_state != link_state) {
787 ifp->if_link_state = link_state;
788 if_link_state_change(ifp);
789 }
790 }
791
792 int
vic_intr(void * arg)793 vic_intr(void *arg)
794 {
795 struct vic_softc *sc = (struct vic_softc *)arg;
796 int q;
797
798 vic_write(sc, VIC_CMD, VIC_CMD_INTR_ACK);
799
800 for (q = 0; q < VIC_NRXRINGS; q++)
801 vic_rx_proc(sc, q);
802 vic_tx_proc(sc);
803
804 return (-1);
805 }
806
807 void
vic_rx_proc(struct vic_softc * sc,int q)808 vic_rx_proc(struct vic_softc *sc, int q)
809 {
810 struct ifnet *ifp = &sc->sc_ac.ac_if;
811 struct vic_rxdesc *rxd;
812 struct vic_rxbuf *rxb;
813 struct mbuf_list ml = MBUF_LIST_INITIALIZER();
814 struct mbuf *m;
815 int len, idx;
816
817 if ((ifp->if_flags & IFF_RUNNING) == 0)
818 return;
819
820 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
821 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
822
823 while (if_rxr_inuse(&sc->sc_rxq[q].ring) > 0) {
824 idx = sc->sc_data->vd_rx[q].nextidx;
825 if (idx >= sc->sc_data->vd_rx[q].length) {
826 ifp->if_ierrors++;
827 if (ifp->if_flags & IFF_DEBUG)
828 printf("%s: receive index error\n",
829 sc->sc_dev.dv_xname);
830 break;
831 }
832
833 rxd = &sc->sc_rxq[q].slots[idx];
834 if (rxd->rx_owner != VIC_OWNER_DRIVER)
835 break;
836
837 rxb = &sc->sc_rxq[q].bufs[idx];
838
839 if (rxb->rxb_m == NULL) {
840 ifp->if_ierrors++;
841 printf("%s: rxb %d has no mbuf\n", DEVNAME(sc), idx);
842 break;
843 }
844
845 bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
846 rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
847 bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
848
849 m = rxb->rxb_m;
850 rxb->rxb_m = NULL;
851 len = rxd->rx_length;
852
853 if (len < VIC_MIN_FRAMELEN) {
854 m_freem(m);
855
856 ifp->if_iqdrops++;
857 goto nextp;
858 }
859
860 m->m_pkthdr.len = m->m_len = len;
861
862 ml_enqueue(&ml, m);
863
864 nextp:
865 if_rxr_put(&sc->sc_rxq[q].ring, 1);
866 VIC_INC(sc->sc_data->vd_rx[q].nextidx, sc->sc_nrxbuf);
867 }
868
869 if (ifiq_input(&ifp->if_rcv, &ml))
870 if_rxr_livelocked(&sc->sc_rxq[q].ring);
871
872 vic_rx_fill(sc, q);
873
874 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
875 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
876 }
877
878 void
vic_tx_proc(struct vic_softc * sc)879 vic_tx_proc(struct vic_softc *sc)
880 {
881 struct ifnet *ifp = &sc->sc_ac.ac_if;
882 struct vic_txdesc *txd;
883 struct vic_txbuf *txb;
884 int idx;
885
886 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
887 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
888
889 while (sc->sc_txpending > 0) {
890 idx = sc->sc_data->vd_tx_curidx;
891 if (idx >= sc->sc_data->vd_tx_length) {
892 ifp->if_oerrors++;
893 break;
894 }
895
896 txd = &sc->sc_txq[idx];
897 if (txd->tx_owner != VIC_OWNER_DRIVER)
898 break;
899
900 txb = &sc->sc_txbuf[idx];
901 if (txb->txb_m == NULL) {
902 printf("%s: tx ring is corrupt\n", DEVNAME(sc));
903 ifp->if_oerrors++;
904 break;
905 }
906
907 bus_dmamap_sync(sc->sc_dmat, txb->txb_dmamap, 0,
908 txb->txb_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
909 bus_dmamap_unload(sc->sc_dmat, txb->txb_dmamap);
910
911 m_freem(txb->txb_m);
912 txb->txb_m = NULL;
913 ifq_clr_oactive(&ifp->if_snd);
914
915 sc->sc_txpending--;
916 sc->sc_data->vd_tx_stopped = 0;
917
918 VIC_INC(sc->sc_data->vd_tx_curidx, sc->sc_data->vd_tx_length);
919 }
920
921 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
922 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
923
924 vic_start(ifp);
925 }
926
927 void
vic_iff(struct vic_softc * sc)928 vic_iff(struct vic_softc *sc)
929 {
930 struct arpcom *ac = &sc->sc_ac;
931 struct ifnet *ifp = &sc->sc_ac.ac_if;
932 struct ether_multi *enm;
933 struct ether_multistep step;
934 u_int32_t crc;
935 u_int16_t *mcastfil = (u_int16_t *)sc->sc_data->vd_mcastfil;
936 u_int flags;
937
938 ifp->if_flags &= ~IFF_ALLMULTI;
939
940 /* Always accept broadcast frames. */
941 flags = VIC_CMD_IFF_BROADCAST;
942
943 if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
944 ifp->if_flags |= IFF_ALLMULTI;
945 if (ifp->if_flags & IFF_PROMISC)
946 flags |= VIC_CMD_IFF_PROMISC;
947 else
948 flags |= VIC_CMD_IFF_MULTICAST;
949 memset(&sc->sc_data->vd_mcastfil, 0xff,
950 sizeof(sc->sc_data->vd_mcastfil));
951 } else {
952 flags |= VIC_CMD_IFF_MULTICAST;
953
954 bzero(&sc->sc_data->vd_mcastfil,
955 sizeof(sc->sc_data->vd_mcastfil));
956
957 ETHER_FIRST_MULTI(step, ac, enm);
958 while (enm != NULL) {
959 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
960
961 crc >>= 26;
962
963 mcastfil[crc >> 4] |= htole16(1 << (crc & 0xf));
964
965 ETHER_NEXT_MULTI(step, enm);
966 }
967 }
968
969 vic_write(sc, VIC_CMD, VIC_CMD_MCASTFIL);
970 sc->sc_data->vd_iff = flags;
971 vic_write(sc, VIC_CMD, VIC_CMD_IFF);
972 }
973
974 void
vic_getlladdr(struct vic_softc * sc)975 vic_getlladdr(struct vic_softc *sc)
976 {
977 u_int32_t reg;
978
979 /* Get MAC address */
980 reg = (sc->sc_cap & VIC_CMD_HWCAP_VPROM) ? VIC_VPROM : VIC_LLADDR;
981
982 bus_space_barrier(sc->sc_iot, sc->sc_ioh, reg, ETHER_ADDR_LEN,
983 BUS_SPACE_BARRIER_READ);
984 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, reg, sc->sc_lladdr,
985 ETHER_ADDR_LEN);
986
987 /* Update the MAC address register */
988 if (reg == VIC_VPROM)
989 vic_setlladdr(sc);
990 }
991
992 void
vic_setlladdr(struct vic_softc * sc)993 vic_setlladdr(struct vic_softc *sc)
994 {
995 bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, VIC_LLADDR,
996 sc->sc_lladdr, ETHER_ADDR_LEN);
997 bus_space_barrier(sc->sc_iot, sc->sc_ioh, VIC_LLADDR, ETHER_ADDR_LEN,
998 BUS_SPACE_BARRIER_WRITE);
999 }
1000
1001 int
vic_media_change(struct ifnet * ifp)1002 vic_media_change(struct ifnet *ifp)
1003 {
1004 /* Ignore */
1005 return (0);
1006 }
1007
1008 void
vic_media_status(struct ifnet * ifp,struct ifmediareq * imr)1009 vic_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1010 {
1011 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
1012
1013 imr->ifm_active = IFM_ETHER | IFM_AUTO;
1014 imr->ifm_status = IFM_AVALID;
1015
1016 vic_link_state(sc);
1017
1018 if (LINK_STATE_IS_UP(ifp->if_link_state) &&
1019 ifp->if_flags & IFF_UP)
1020 imr->ifm_status |= IFM_ACTIVE;
1021 }
1022
1023 void
vic_start(struct ifnet * ifp)1024 vic_start(struct ifnet *ifp)
1025 {
1026 struct vic_softc *sc;
1027 struct mbuf *m;
1028 struct vic_txbuf *txb;
1029 struct vic_txdesc *txd;
1030 struct vic_sg *sge;
1031 bus_dmamap_t dmap;
1032 int i, idx;
1033 int tx = 0;
1034
1035 if (!(ifp->if_flags & IFF_RUNNING))
1036 return;
1037
1038 if (ifq_is_oactive(&ifp->if_snd))
1039 return;
1040
1041 if (ifq_empty(&ifp->if_snd))
1042 return;
1043
1044 sc = (struct vic_softc *)ifp->if_softc;
1045
1046 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
1047 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1048
1049 for (;;) {
1050 if (VIC_TXURN(sc)) {
1051 ifq_set_oactive(&ifp->if_snd);
1052 break;
1053 }
1054
1055 idx = sc->sc_data->vd_tx_nextidx;
1056 if (idx >= sc->sc_data->vd_tx_length) {
1057 printf("%s: tx idx is corrupt\n", DEVNAME(sc));
1058 ifp->if_oerrors++;
1059 break;
1060 }
1061
1062 txd = &sc->sc_txq[idx];
1063 txb = &sc->sc_txbuf[idx];
1064
1065 if (txb->txb_m != NULL) {
1066 printf("%s: tx ring is corrupt\n", DEVNAME(sc));
1067 sc->sc_data->vd_tx_stopped = 1;
1068 ifp->if_oerrors++;
1069 break;
1070 }
1071
1072 m = ifq_dequeue(&ifp->if_snd);
1073 if (m == NULL)
1074 break;
1075
1076 if (vic_load_txb(sc, txb, m) != 0) {
1077 m_freem(m);
1078 ifp->if_oerrors++;
1079 continue;
1080 }
1081
1082 #if NBPFILTER > 0
1083 if (ifp->if_bpf)
1084 bpf_mtap(ifp->if_bpf, txb->txb_m, BPF_DIRECTION_OUT);
1085 #endif
1086
1087 dmap = txb->txb_dmamap;
1088 txd->tx_flags = VIC_TX_FLAGS_KEEP;
1089 txd->tx_owner = VIC_OWNER_NIC;
1090 txd->tx_sa.sa_addr_type = VIC_SG_ADDR_PHYS;
1091 txd->tx_sa.sa_length = dmap->dm_nsegs;
1092 for (i = 0; i < dmap->dm_nsegs; i++) {
1093 sge = &txd->tx_sa.sa_sg[i];
1094 sge->sg_length = dmap->dm_segs[i].ds_len;
1095 sge->sg_addr_low = dmap->dm_segs[i].ds_addr;
1096 }
1097
1098 if (VIC_TXURN_WARN(sc)) {
1099 txd->tx_flags |= VIC_TX_FLAGS_TXURN;
1100 }
1101
1102 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1103 BUS_DMASYNC_PREWRITE);
1104
1105 sc->sc_txpending++;
1106
1107 VIC_INC(sc->sc_data->vd_tx_nextidx, sc->sc_data->vd_tx_length);
1108
1109 tx = 1;
1110 }
1111
1112 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
1113 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1114
1115 if (tx)
1116 vic_read(sc, VIC_Tx_ADDR);
1117 }
1118
1119 int
vic_load_txb(struct vic_softc * sc,struct vic_txbuf * txb,struct mbuf * m)1120 vic_load_txb(struct vic_softc *sc, struct vic_txbuf *txb, struct mbuf *m)
1121 {
1122 bus_dmamap_t dmap = txb->txb_dmamap;
1123 int error;
1124
1125 error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m, BUS_DMA_NOWAIT);
1126 switch (error) {
1127 case 0:
1128 txb->txb_m = m;
1129 break;
1130
1131 case EFBIG:
1132 if (m_defrag(m, M_DONTWAIT) == 0 &&
1133 bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m,
1134 BUS_DMA_NOWAIT) == 0) {
1135 txb->txb_m = m;
1136 break;
1137 }
1138
1139 /* FALLTHROUGH */
1140 default:
1141 return (ENOBUFS);
1142 }
1143
1144 return (0);
1145 }
1146
1147 void
vic_watchdog(struct ifnet * ifp)1148 vic_watchdog(struct ifnet *ifp)
1149 {
1150 #if 0
1151 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
1152
1153 if (sc->sc_txpending && sc->sc_txtimeout > 0) {
1154 if (--sc->sc_txtimeout == 0) {
1155 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1156 ifp->if_flags &= ~IFF_RUNNING;
1157 vic_init(ifp);
1158 ifp->if_oerrors++;
1159 return;
1160 }
1161 }
1162
1163 if (!ifq_empty(&ifp->if_snd))
1164 vic_start(ifp);
1165 #endif
1166 }
1167
1168 int
vic_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)1169 vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1170 {
1171 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
1172 struct ifreq *ifr = (struct ifreq *)data;
1173 int s, error = 0;
1174
1175 s = splnet();
1176
1177 switch (cmd) {
1178 case SIOCSIFADDR:
1179 ifp->if_flags |= IFF_UP;
1180 /* FALLTHROUGH */
1181 case SIOCSIFFLAGS:
1182 if (ifp->if_flags & IFF_UP) {
1183 if (ifp->if_flags & IFF_RUNNING)
1184 error = ENETRESET;
1185 else
1186 vic_init(ifp);
1187 } else {
1188 if (ifp->if_flags & IFF_RUNNING)
1189 vic_stop(ifp);
1190 }
1191 break;
1192
1193 case SIOCGIFMEDIA:
1194 case SIOCSIFMEDIA:
1195 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1196 break;
1197
1198 case SIOCGIFRXR:
1199 error = vic_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data);
1200 break;
1201
1202 default:
1203 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
1204 }
1205
1206 if (error == ENETRESET) {
1207 if (ifp->if_flags & IFF_RUNNING)
1208 vic_iff(sc);
1209 error = 0;
1210 }
1211
1212 splx(s);
1213 return (error);
1214 }
1215
1216 int
vic_rxrinfo(struct vic_softc * sc,struct if_rxrinfo * ifri)1217 vic_rxrinfo(struct vic_softc *sc, struct if_rxrinfo *ifri)
1218 {
1219 struct if_rxring_info ifr[2];
1220
1221 memset(ifr, 0, sizeof(ifr));
1222
1223 ifr[0].ifr_size = MCLBYTES;
1224 ifr[0].ifr_info = sc->sc_rxq[0].ring;
1225
1226 ifr[1].ifr_size = 4096;
1227 ifr[1].ifr_info = sc->sc_rxq[1].ring;
1228
1229 return (if_rxr_info_ioctl(ifri, nitems(ifr), ifr));
1230 }
1231
1232 void
vic_init(struct ifnet * ifp)1233 vic_init(struct ifnet *ifp)
1234 {
1235 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
1236 int q;
1237 int s;
1238
1239 sc->sc_data->vd_tx_curidx = 0;
1240 sc->sc_data->vd_tx_nextidx = 0;
1241 sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0;
1242 sc->sc_data->vd_tx_saved_nextidx = 0;
1243
1244 for (q = 0; q < VIC_NRXRINGS; q++) {
1245 sc->sc_data->vd_rx[q].nextidx = 0;
1246 sc->sc_data->vd_rx_saved_nextidx[q] = 0;
1247 }
1248
1249 if (vic_init_data(sc) != 0)
1250 return;
1251
1252 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
1253 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1254
1255 s = splnet();
1256
1257 vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc));
1258 vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size);
1259
1260 ifp->if_flags |= IFF_RUNNING;
1261 ifq_clr_oactive(&ifp->if_snd);
1262
1263 vic_iff(sc);
1264 vic_write(sc, VIC_CMD, VIC_CMD_INTR_ENABLE);
1265
1266 splx(s);
1267
1268 timeout_add_sec(&sc->sc_tick, 1);
1269 }
1270
1271 void
vic_stop(struct ifnet * ifp)1272 vic_stop(struct ifnet *ifp)
1273 {
1274 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
1275 int s;
1276
1277 s = splnet();
1278
1279 timeout_del(&sc->sc_tick);
1280
1281 ifp->if_flags &= ~IFF_RUNNING;
1282 ifq_clr_oactive(&ifp->if_snd);
1283
1284 bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
1285 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1286
1287 /* XXX wait for tx to complete */
1288 while (sc->sc_txpending > 0) {
1289 splx(s);
1290 delay(1000);
1291 s = splnet();
1292 }
1293
1294 sc->sc_data->vd_tx_stopped = 1;
1295
1296 vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE);
1297
1298 sc->sc_data->vd_iff = 0;
1299 vic_write(sc, VIC_CMD, VIC_CMD_IFF);
1300
1301 vic_write(sc, VIC_DATA_ADDR, 0);
1302
1303 vic_uninit_data(sc);
1304
1305 splx(s);
1306 }
1307
1308 struct mbuf *
vic_alloc_mbuf(struct vic_softc * sc,bus_dmamap_t map,u_int pktlen)1309 vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map, u_int pktlen)
1310 {
1311 struct mbuf *m = NULL;
1312
1313 m = MCLGETL(NULL, M_DONTWAIT, pktlen);
1314 if (!m)
1315 return (NULL);
1316 m->m_data += ETHER_ALIGN;
1317 m->m_len = m->m_pkthdr.len = pktlen - ETHER_ALIGN;
1318
1319 if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
1320 printf("%s: could not load mbuf DMA map\n", DEVNAME(sc));
1321 m_freem(m);
1322 return (NULL);
1323 }
1324
1325 return (m);
1326 }
1327
1328 void
vic_tick(void * arg)1329 vic_tick(void *arg)
1330 {
1331 struct vic_softc *sc = (struct vic_softc *)arg;
1332
1333 vic_link_state(sc);
1334
1335 timeout_add_sec(&sc->sc_tick, 1);
1336 }
1337
1338 u_int32_t
vic_read(struct vic_softc * sc,bus_size_t r)1339 vic_read(struct vic_softc *sc, bus_size_t r)
1340 {
1341 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1342 BUS_SPACE_BARRIER_READ);
1343 return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
1344 }
1345
1346 void
vic_write(struct vic_softc * sc,bus_size_t r,u_int32_t v)1347 vic_write(struct vic_softc *sc, bus_size_t r, u_int32_t v)
1348 {
1349 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1350 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1351 BUS_SPACE_BARRIER_WRITE);
1352 }
1353
1354 u_int32_t
vic_read_cmd(struct vic_softc * sc,u_int32_t cmd)1355 vic_read_cmd(struct vic_softc *sc, u_int32_t cmd)
1356 {
1357 vic_write(sc, VIC_CMD, cmd);
1358 return (vic_read(sc, VIC_CMD));
1359 }
1360
1361 int
vic_alloc_dmamem(struct vic_softc * sc)1362 vic_alloc_dmamem(struct vic_softc *sc)
1363 {
1364 int nsegs;
1365
1366 if (bus_dmamap_create(sc->sc_dmat, sc->sc_dma_size, 1,
1367 sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1368 &sc->sc_dma_map) != 0)
1369 goto err;
1370
1371 if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_dma_size, 16, 0,
1372 &sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
1373 goto destroy;
1374
1375 if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_seg, nsegs,
1376 sc->sc_dma_size, &sc->sc_dma_kva, BUS_DMA_NOWAIT) != 0)
1377 goto free;
1378
1379 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dma_map, sc->sc_dma_kva,
1380 sc->sc_dma_size, NULL, BUS_DMA_NOWAIT) != 0)
1381 goto unmap;
1382
1383 return (0);
1384
1385 unmap:
1386 bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
1387 free:
1388 bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
1389 destroy:
1390 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
1391 err:
1392 return (1);
1393 }
1394
1395 void
vic_free_dmamem(struct vic_softc * sc)1396 vic_free_dmamem(struct vic_softc *sc)
1397 {
1398 bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_map);
1399 bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
1400 bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
1401 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
1402 }
1403