xref: /openbsd-src/sys/dev/pci/if_myx.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: if_myx.c,v 1.10 2008/11/28 02:44:18 brad Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for the Myricom Myri-10G Lanai-Z8E Ethernet chipsets.
21  */
22 
23 #include "bpfilter.h"
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/sockio.h>
28 #include <sys/mbuf.h>
29 #include <sys/kernel.h>
30 #include <sys/socket.h>
31 #include <sys/malloc.h>
32 #include <sys/timeout.h>
33 #include <sys/proc.h>
34 #include <sys/device.h>
35 #include <sys/sensors.h>
36 
37 #include <machine/bus.h>
38 #include <machine/intr.h>
39 
40 #include <net/if.h>
41 #include <net/if_dl.h>
42 #include <net/if_media.h>
43 #include <net/if_types.h>
44 
45 #if NBPFILTER > 0
46 #include <net/bpf.h>
47 #endif
48 
49 #ifdef INET
50 #include <netinet/in.h>
51 #include <netinet/if_ether.h>
52 #endif
53 
54 #include <dev/pci/pcireg.h>
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pcidevs.h>
57 
58 #include <dev/pci/if_myxreg.h>
59 
60 #define MYX_DEBUG
61 #ifdef MYX_DEBUG
62 #define MYXDBG_INIT	(1<<0)	/* chipset initialization */
63 #define MYXDBG_CMD	(2<<0)	/* commands */
64 #define MYXDBG_INTR	(3<<0)	/* interrupts */
65 #define MYXDBG_ALL	0xffff	/* enable all debugging messages */
66 int myx_debug = MYXDBG_ALL;
67 #define DPRINTF(_lvl, _arg...)	do {					\
68 	if (myx_debug & (_lvl))						\
69 		printf(_arg);						\
70 } while (0)
71 #else
72 #define DPRINTF(_lvl, arg...)
73 #endif
74 
75 #define DEVNAME(_s)	((_s)->_s##_dev.dv_xname)
76 
77 struct myx_dmamem {
78 	bus_dmamap_t		 mxm_map;
79 	bus_dma_segment_t	 mxm_seg;
80 	int			 mxm_nsegs;
81 	size_t			 mxm_size;
82 	caddr_t			 mxm_kva;
83 	const char		*mxm_name;
84 };
85 
86 struct myx_buf {
87 	bus_dmamap_t		 mb_dmamap;
88 	struct mbuf		*mb_m;
89 };
90 
91 struct myx_softc {
92 	struct device		 sc_dev;
93 	struct arpcom		 sc_ac;
94 
95 	pci_chipset_tag_t	 sc_pc;
96 	pcitag_t		 sc_tag;
97 	u_int			 sc_function;
98 
99 	bus_dma_tag_t		 sc_dmat;
100 	bus_space_tag_t		 sc_memt;
101 	bus_space_handle_t	 sc_memh;
102 	bus_size_t		 sc_mems;
103 
104 	struct myx_dmamem	 sc_cmddma;
105 	struct myx_dmamem	 sc_paddma;
106 
107 	struct myx_dmamem	 sc_stsdma;
108 	struct myx_status	*sc_sts;
109 
110 	struct myx_dmamem	 sc_rxdma;
111 	struct myx_rxdesc	*sc_rxdesc;
112 	struct myx_rxbufdesc	*sc_rxbufdesc[2];
113 	struct myx_buf		*sc_rxbuf[2];
114 #define  MYX_RXSMALL		 0
115 #define  MYX_RXBIG		 1
116 	int			 sc_rxactive;
117 	int			 sc_rxidx;
118 
119 	void			*sc_irqh;
120 	u_int32_t		 sc_irqcoaloff;
121 	u_int32_t		 sc_irqclaimoff;
122 	u_int32_t		 sc_irqdeassertoff;
123 
124 	u_int8_t		 sc_lladdr[ETHER_ADDR_LEN];
125 	struct ifmedia		 sc_media;
126 
127 	u_int32_t		 sc_rxringsize;
128 	u_int32_t		 sc_rxsmallringoff;
129 	u_int32_t		 sc_rxbigringoff;
130 	int			 sc_rxndesc;
131 	size_t			 sc_rxdescsize;
132 	size_t			 sc_rxbufsize;
133 	size_t			 sc_rxbufdescsize;
134 	u_int32_t		 sc_txringsize;
135 	u_int32_t		 sc_txringoff;
136 	int			 sc_txndesc;
137 
138 	u_int			 sc_phy;	/* PHY type (CX4/SR/LR) */
139 	u_int			 sc_hwflags;
140 #define  MYXFLAG_FLOW_CONTROL	 (1<<0)		/* Rx/Tx pause is enabled */
141 #define  MYXFLAG_PROMISC	 (1<<1)		/* promisc mode is enabled */
142 #define  MYXFLAG_ALLMULTI	 (1<<2)		/* allmulti is set */
143 	u_int8_t		 sc_active;
144 
145 	struct timeout		 sc_tick;
146 };
147 
148 int	 myx_match(struct device *, void *, void *);
149 void	 myx_attach(struct device *, struct device *, void *);
150 int	 myx_query(struct myx_softc *sc);
151 u_int	 myx_ether_aton(char *, u_int8_t *, u_int);
152 int	 myx_loadfirmware(struct myx_softc *, u_int8_t *, size_t,
153 	    u_int32_t, int);
154 void	 myx_attachhook(void *);
155 void	 myx_read(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
156 void	 myx_rawread(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
157 void	 myx_write(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
158 void	 myx_rawwrite(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
159 int	 myx_cmd(struct myx_softc *, u_int32_t, struct myx_cmd *, u_int32_t *);
160 int	 myx_boot(struct myx_softc *, u_int32_t, struct myx_bootcmd *);
161 int	 myx_rdma(struct myx_softc *, u_int);
162 int	 myx_reset(struct myx_softc *);
163 int	 myx_dmamem_alloc(struct myx_softc *, struct myx_dmamem *,
164 	    bus_size_t, u_int align, const char *);
165 void	 myx_dmamem_free(struct myx_softc *, struct myx_dmamem *);
166 int	 myx_media_change(struct ifnet *);
167 void	 myx_media_status(struct ifnet *, struct ifmediareq *);
168 void	 myx_link_state(struct myx_softc *);
169 void	 myx_watchdog(struct ifnet *);
170 void	 myx_tick(void *);
171 int	 myx_ioctl(struct ifnet *, u_long, caddr_t);
172 void	 myx_iff(struct myx_softc *);
173 void	 myx_init(struct ifnet *);
174 void	 myx_start(struct ifnet *);
175 void	 myx_stop(struct ifnet *);
176 int	 myx_setlladdr(struct myx_softc *, u_int8_t *);
177 int	 myx_intr(void *);
178 int	 myx_init_rings(struct myx_softc *);
179 void	 myx_free_rings(struct myx_softc *);
180 struct mbuf *myx_getbuf(struct myx_softc *, bus_dmamap_t, int);
181 
182 struct cfdriver myx_cd = {
183 	0, "myx", DV_IFNET
184 };
185 struct cfattach myx_ca = {
186 	sizeof(struct myx_softc), myx_match, myx_attach
187 };
188 
189 const struct pci_matchid myx_devices[] = {
190 	{ PCI_VENDOR_MYRICOM, PCI_PRODUCT_MYRICOM_Z8E }
191 };
192 
193 int
194 myx_match(struct device *parent, void *match, void *aux)
195 {
196 	return (pci_matchbyid((struct pci_attach_args *)aux,
197 	    myx_devices, sizeof(myx_devices) / sizeof(myx_devices[0])));
198 }
199 
200 void
201 myx_attach(struct device *parent, struct device *self, void *aux)
202 {
203 	struct myx_softc	*sc = (struct myx_softc *)self;
204 	struct pci_attach_args	*pa = aux;
205 	pci_intr_handle_t	 ih;
206 	pcireg_t		 memtype;
207 	const char		*intrstr;
208 	struct ifnet		*ifp;
209 
210 	sc->sc_pc = pa->pa_pc;
211 	sc->sc_tag = pa->pa_tag;
212 	sc->sc_dmat = pa->pa_dmat;
213 	sc->sc_function = pa->pa_function;
214 
215 	/* Map the PCI memory space */
216 	memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0);
217 	if (pci_mapreg_map(pa, MYXBAR0, memtype, 0, &sc->sc_memt,
218 	    &sc->sc_memh, NULL, &sc->sc_mems, 0)) {
219 		printf(": unable to map register memory\n");
220 		return;
221 	}
222 
223 	/* Get the board information and initialize the h/w */
224 	if (myx_query(sc) != 0)
225 		goto unmap;
226 
227 	/*
228 	 * Allocate command DMA memory
229 	 */
230 	if (myx_dmamem_alloc(sc, &sc->sc_cmddma, MYXALIGN_CMD,
231 	    MYXALIGN_CMD, "cmd") != 0) {
232 		printf(": failed to allocate command DMA memory\n");
233 		goto unmap;
234 	}
235 
236 	if (myx_dmamem_alloc(sc, &sc->sc_paddma,
237 	    MYXALIGN_CMD, MYXALIGN_CMD, "pad") != 0) {
238 		printf(": failed to allocate pad DMA memory\n");
239 		goto err2;
240 	}
241 
242 	if (myx_dmamem_alloc(sc, &sc->sc_stsdma,
243 	    sizeof(struct myx_status), MYXALIGN_DATA /* XXX */, "status") != 0) {
244 		printf(": failed to allocate status DMA memory\n");
245 		goto err1;
246 	}
247 	sc->sc_sts = (struct myx_status *)sc->sc_stsdma.mxm_kva;
248 
249 	/*
250 	 * Map and establish the interrupt
251 	 */
252 	if (pci_intr_map(pa, &ih) != 0) {
253 		printf(": unable to map interrupt\n");
254 		goto err;
255 	}
256 	intrstr = pci_intr_string(pa->pa_pc, ih);
257 	sc->sc_irqh = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
258 	    myx_intr, sc, DEVNAME(sc));
259 	if (sc->sc_irqh == NULL) {
260 		printf(": unable to establish interrupt %s\n", intrstr);
261 		goto err;
262 	}
263 	printf(": %s, address %s\n", intrstr,
264 	    ether_sprintf(sc->sc_ac.ac_enaddr));
265 
266 	ifp = &sc->sc_ac.ac_if;
267 	ifp->if_softc = sc;
268 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
269 	ifp->if_ioctl = myx_ioctl;
270 	ifp->if_start = myx_start;
271 	ifp->if_watchdog = myx_watchdog;
272 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
273 	IFQ_SET_MAXLEN(&ifp->if_snd, MYX_NTXDESC_MIN - 1);
274 	IFQ_SET_READY(&ifp->if_snd);
275 
276 	ifp->if_capabilities = IFCAP_VLAN_MTU;
277 #if 0
278 	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
279 	ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
280 		    IFCAP_CSUM_UDPv4;
281 #endif
282 	ifp->if_baudrate = IF_Gbps(10);
283 
284 	ifmedia_init(&sc->sc_media, 0,
285 	    myx_media_change, myx_media_status);
286 	ifmedia_add(&sc->sc_media, IFM_ETHER|sc->sc_phy, 0, NULL);
287 	ifmedia_set(&sc->sc_media, IFM_ETHER|sc->sc_phy);
288 
289 	if_attach(ifp);
290 	ether_ifattach(ifp);
291 
292 	timeout_set(&sc->sc_tick, myx_tick, sc);
293 	timeout_add_sec(&sc->sc_tick, 1);
294 
295 	mountroothook_establish(myx_attachhook, sc);
296 
297 	return;
298 
299  err:
300 	myx_dmamem_free(sc, &sc->sc_stsdma);
301  err1:
302 	myx_dmamem_free(sc, &sc->sc_paddma);
303  err2:
304 	myx_dmamem_free(sc, &sc->sc_cmddma);
305  unmap:
306 	bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
307 	sc->sc_mems = 0;
308 }
309 
310 u_int
311 myx_ether_aton(char *mac, u_int8_t *lladdr, u_int maxlen)
312 {
313 	u_int		i, j;
314 	u_int8_t	digit;
315 
316 	bzero(lladdr, ETHER_ADDR_LEN);
317 	for (i = j = 0; mac[i] != '\0' && i < maxlen; i++) {
318 		if (mac[i] >= '0' && mac[i] <= '9')
319 			digit = mac[i] - '0';
320 		else if (mac[i] >= 'A' && mac[i] <= 'F')
321 			digit = mac[i] - 'A' + 10;
322 		else if (mac[i] >= 'a' && mac[i] <= 'f')
323 			digit = mac[i] - 'a' + 10;
324 		else
325 			continue;
326 		if ((j & 1) == 0)
327 			digit <<= 4;
328 		lladdr[j++/2] |= digit;
329 	}
330 
331 	return (i);
332 }
333 
334 int
335 myx_query(struct myx_softc *sc)
336 {
337 	u_int8_t	eeprom[MYX_EEPROM_SIZE];
338 	u_int		i, maxlen;
339 
340 	myx_read(sc, MYX_EEPROM, eeprom, MYX_EEPROM_SIZE);
341 
342 	for (i = 0; i < MYX_EEPROM_SIZE; i++) {
343 		maxlen = MYX_EEPROM_SIZE - i;
344 		if (eeprom[i] == '\0')
345 			break;
346 		if (maxlen > 4 && bcmp("MAC=", &eeprom[i], 4) == 0) {
347 			i += 4;
348 			i += myx_ether_aton(&eeprom[i],
349 			    sc->sc_ac.ac_enaddr, maxlen);
350 		}
351 		for (; i < MYX_EEPROM_SIZE; i++)
352 			if (eeprom[i] == '\0')
353 				break;
354 	}
355 
356 	return (0);
357 }
358 
359 int
360 myx_loadfirmware(struct myx_softc *sc, u_int8_t *fw, size_t fwlen,
361     u_int32_t fwhdroff, int reload)
362 {
363 	struct myx_firmware_hdr	*fwhdr;
364 	u_int			 i, len, ret = 0;
365 
366 	fwhdr = (struct myx_firmware_hdr *)(fw + fwhdroff);
367 	DPRINTF(MYXDBG_INIT, "%s(%s): "
368 	    "fw hdr off %d, length %d, type 0x%x, version %s\n",
369 	    DEVNAME(sc), __func__,
370 	    fwhdroff, betoh32(fwhdr->fw_hdrlength),
371 	    betoh32(fwhdr->fw_type),
372 	    fwhdr->fw_version);
373 
374 	if (betoh32(fwhdr->fw_type) != MYXFW_TYPE_ETH ||
375 	    bcmp(MYXFW_VER, fwhdr->fw_version, strlen(MYXFW_VER)) != 0) {
376 		if (reload)
377 			printf("%s: invalid firmware type 0x%x version %s\n",
378 			    DEVNAME(sc), betoh32(fwhdr->fw_type),
379 			    fwhdr->fw_version);
380 		ret = 1;
381 		goto done;
382 	}
383 
384 	if (!reload)
385 		goto done;
386 
387 	/* Write the firmware to the card's SRAM */
388 	for (i = 0; i < fwlen; i += 256) {
389 		len = min(256, fwlen - i);
390 		myx_rawwrite(sc, i + MYX_FW, fw + i, min(256, fwlen - i));
391 	}
392 
393  done:
394 	free(fw, M_DEVBUF);
395 	return (ret);
396 }
397 
398 void
399 myx_attachhook(void *arg)
400 {
401 	struct myx_softc	*sc = (struct myx_softc *)arg;
402 	size_t			 fwlen;
403 	u_int8_t		*fw = NULL;
404 	u_int32_t		 fwhdroff;
405 	struct myx_bootcmd	 bc;
406 
407 	/*
408 	 * First try the firmware found in the SRAM
409 	 */
410 	myx_read(sc, MYX_HEADER_POS, (u_int8_t *)&fwhdroff, sizeof(fwhdroff));
411 	fwhdroff = betoh32(fwhdroff);
412 	fwlen = sizeof(struct myx_firmware_hdr);
413 	if ((fwhdroff + fwlen) > MYX_SRAM_SIZE)
414 		goto load;
415 
416 	fw = malloc(fwlen, M_DEVBUF, M_WAIT);
417 	myx_rawread(sc, MYX_HEADER_POS, fw, fwlen);
418 
419 	if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 0) == 0)
420 		goto boot;
421 
422  load:
423 	/*
424 	 * Now try the firmware stored on disk
425 	 */
426 	if (loadfirmware(MYXFW_ALIGNED /* XXX */, &fw, &fwlen) != 0) {
427 		printf("%s: could not load firmware\n", DEVNAME(sc));
428 		return;
429 	}
430 	if (fwlen > MYX_SRAM_SIZE || fwlen < MYXFW_MIN_LEN) {
431 		printf("%s: invalid firmware image size\n", DEVNAME(sc));
432 		goto err;
433 	}
434 
435 	bcopy(fw + MYX_HEADER_POS, &fwhdroff, sizeof(fwhdroff));
436 	fwhdroff = betoh32(fwhdroff);
437 	if ((fwhdroff + sizeof(struct myx_firmware_hdr)) > fwlen) {
438 		printf("%s: invalid firmware image\n", DEVNAME(sc));
439 		goto err;
440 	}
441 
442 	if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 1) != 0) {
443 		fw = NULL;
444 		goto err;
445 	}
446 	fw = NULL;
447 
448  boot:
449 	bzero(&bc, sizeof(bc));
450 	if (myx_boot(sc, fwlen, &bc) != 0) {
451 		printf("%s: failed to bootstrap the device\n", DEVNAME(sc));
452 		goto err;
453 	}
454 	if (myx_reset(sc) != 0)
455 		goto err;
456 
457 	sc->sc_active = 1;
458 	return;
459 
460  err:
461 	if (fw != NULL)
462 		free(fw, M_DEVBUF);
463 }
464 
465 void
466 myx_read(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
467 {
468 	bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
469 	    BUS_SPACE_BARRIER_READ);
470 	bus_space_read_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
471 }
472 
473 void
474 myx_rawread(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
475     bus_size_t len)
476 {
477 	bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
478 	    BUS_SPACE_BARRIER_READ);
479 	bus_space_read_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
480 }
481 
482 void
483 myx_write(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
484 {
485 	bus_space_write_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
486 	bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
487 	    BUS_SPACE_BARRIER_WRITE);
488 }
489 
490 void
491 myx_rawwrite(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
492     bus_size_t len)
493 {
494 	bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
495 	bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
496 	    BUS_SPACE_BARRIER_WRITE);
497 }
498 
499 int
500 myx_dmamem_alloc(struct myx_softc *sc, struct myx_dmamem *mxm,
501     bus_size_t size, u_int align, const char *mname)
502 {
503 	mxm->mxm_size = size;
504 
505 	if (bus_dmamap_create(sc->sc_dmat, mxm->mxm_size, 1,
506 	    mxm->mxm_size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
507 	    &mxm->mxm_map) != 0)
508 		return (1);
509 	if (bus_dmamem_alloc(sc->sc_dmat, mxm->mxm_size,
510 	    align, 0, &mxm->mxm_seg, 1, &mxm->mxm_nsegs,
511 	    BUS_DMA_WAITOK) != 0)
512 		goto destroy;
513 	if (bus_dmamem_map(sc->sc_dmat, &mxm->mxm_seg, mxm->mxm_nsegs,
514 	    mxm->mxm_size, &mxm->mxm_kva, BUS_DMA_WAITOK) != 0)
515 		goto free;
516 	if (bus_dmamap_load(sc->sc_dmat, mxm->mxm_map, mxm->mxm_kva,
517 	    mxm->mxm_size, NULL, BUS_DMA_WAITOK) != 0)
518 		goto unmap;
519 
520 	bzero(mxm->mxm_kva, mxm->mxm_size);
521 	mxm->mxm_name = mname;
522 
523 	return (0);
524  unmap:
525 	bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
526  free:
527 	bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
528  destroy:
529 	bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
530 	return (1);
531 }
532 
533 void
534 myx_dmamem_free(struct myx_softc *sc, struct myx_dmamem *mxm)
535 {
536 	bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map);
537 	bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
538 	bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
539 	bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
540 }
541 
542 int
543 myx_cmd(struct myx_softc *sc, u_int32_t cmd, struct myx_cmd *mc, u_int32_t *r)
544 {
545 	bus_dmamap_t		 map = sc->sc_cmddma.mxm_map;
546 	struct myx_response	*mr;
547 	u_int			 i;
548 	u_int32_t		 result, data;
549 #ifdef MYX_DEBUG
550 	static const char *cmds[MYXCMD_MAX] = {
551 		"CMD_NONE",
552 		"CMD_RESET",
553 		"CMD_GET_VERSION",
554 		"CMD_SET_INTRQDMA",
555 		"CMD_SET_BIGBUFSZ",
556 		"CMD_SET_SMALLBUFSZ",
557 		"CMD_GET_TXRINGOFF",
558 		"CMD_GET_RXSMALLRINGOFF",
559 		"CMD_GET_RXBIGRINGOFF",
560 		"CMD_GET_INTRACKOFF",
561 		"CMD_GET_INTRDEASSERTOFF",
562 		"CMD_GET_TXRINGSZ",
563 		"CMD_GET_RXRINGSZ",
564 		"CMD_SET_INTRQSZ",
565 		"CMD_SET_IFUP",
566 		"CMD_SET_IFDOWN",
567 		"CMD_SET_MTU",
568 		"CMD_GET_INTRCOALDELAYOFF",
569 		"CMD_SET_STATSINTVL",
570 		"CMD_SET_STATSDMA_OLD",
571 		"CMD_SET_PROMISC",
572 		"CMD_UNSET_PROMISC",
573 		"CMD_SET_LLADDR",
574 		"CMD_SET_FC",
575 		"CMD_UNSET_FC",
576 		"CMD_DMA_TEST",
577 		"CMD_SET_ALLMULTI",
578 		"CMD_UNSET_ALLMULTI",
579 		"CMD_SET_MCASTGROUP",
580 		"CMD_UNSET_MCASTGROUP",
581 		"CMD_UNSET_MCAST",
582 		"CMD_SET_STATSDMA",
583 		"CMD_UNALIGNED_DMA_TEST",
584 		"CMD_GET_UNALIGNED_STATUS"
585 	};
586 #endif
587 
588 	mc->mc_cmd = htobe32(cmd);
589 	mc->mc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
590 	mc->mc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
591 
592 	mr = (struct myx_response *)sc->sc_cmddma.mxm_kva;
593 	mr->mr_result = 0xffffffff;
594 
595 	/* Send command */
596 	myx_write(sc, MYX_CMD, (u_int8_t *)mc, sizeof(struct myx_cmd));
597 
598 	for (i = 0; i < 20; i++) {
599 		bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
600 		    BUS_DMASYNC_POSTREAD);
601 		result = betoh32(mr->mr_result);
602 		data = betoh32(mr->mr_data);
603 
604 		if (result != 0xffffffff)
605 			break;
606 		delay(1000);
607 	}
608 
609 	DPRINTF(MYXDBG_CMD, "%s(%s): %s completed, i %d, "
610 	    "result 0x%x, data 0x%x (%u)\n", DEVNAME(sc), __func__,
611 	    cmds[cmd], i, result, data, data);
612 
613 	if (result != 0)
614 		return (-1);
615 
616 	if (r != NULL)
617 		*r = data;
618 	return (0);
619 }
620 
621 int
622 myx_boot(struct myx_softc *sc, u_int32_t length, struct myx_bootcmd *bc)
623 {
624 	bus_dmamap_t		 map = sc->sc_cmddma.mxm_map;
625 	u_int32_t		*status;
626 	u_int			 i;
627 
628 	bc->bc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
629 	bc->bc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
630 	bc->bc_result = 0xffffffff;
631 	bc->bc_offset = htobe32(MYX_FW_BOOT);
632 	bc->bc_length = htobe32(length);
633 	bc->bc_copyto = htobe32(8);
634 	bc->bc_jumpto = htobe32(0);
635 
636 	status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
637 	*status = 0;
638 
639 	/* Send command */
640 	myx_write(sc, MYX_BOOT, (u_int8_t *)bc, sizeof(struct myx_bootcmd));
641 
642 	for (i = 0; i < 200; i++) {
643 		bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
644 		    BUS_DMASYNC_POSTREAD);
645 		if (*status == 0xffffffff)
646 			break;
647 		delay(1000);
648 	}
649 
650 	DPRINTF(MYXDBG_CMD, "%s(%s): boot completed, i %d, result 0x%x\n",
651 	    DEVNAME(sc), __func__, i, betoh32(*status));
652 
653 	if (*status != 0xffffffff)
654 		return (-1);
655 
656 	return (0);
657 }
658 
659 int
660 myx_rdma(struct myx_softc *sc, u_int do_enable)
661 {
662 	struct myx_rdmacmd	 rc;
663 	bus_dmamap_t		 map = sc->sc_cmddma.mxm_map;
664 	bus_dmamap_t		 pad = sc->sc_paddma.mxm_map;
665 	u_int32_t		*status;
666 	u_int			 i;
667 
668 	/*
669 	 * It is required to setup a _dummy_ RDMA address. It also makes
670 	 * some PCI-E chipsets resend dropped messages.
671 	 */
672 	rc.rc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
673 	rc.rc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
674 	rc.rc_result = 0xffffffff;
675 	rc.rc_rdma_high = htobe32(MYX_ADDRHIGH(pad->dm_segs[0].ds_addr));
676 	rc.rc_rdma_low = htobe32(MYX_ADDRLOW(pad->dm_segs[0].ds_addr));
677 	rc.rc_enable = htobe32(do_enable);
678 
679 	status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
680 	*status = 0;
681 
682 	/* Send command */
683 	myx_write(sc, MYX_RDMA, (u_int8_t *)&rc, sizeof(struct myx_rdmacmd));
684 
685 	for (i = 0; i < 20; i++) {
686 		bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
687 		    BUS_DMASYNC_POSTREAD);
688 		if (*status == 0xffffffff)
689 			break;
690 		delay(1000);
691 	}
692 
693 	DPRINTF(MYXDBG_CMD, "%s(%s): dummy RDMA %s, i %d, result 0x%x\n",
694 	    DEVNAME(sc), __func__,
695 	    do_enable ? "enabled" : "disabled", i, betoh32(*status));
696 
697 	if (*status != 0xffffffff)
698 		return (-1);
699 
700 	return (0);
701 }
702 
703 int
704 myx_reset(struct myx_softc *sc)
705 {
706 	struct myx_cmd		 mc;
707 	u_int32_t		 data;
708 	struct ifnet		*ifp = &sc->sc_ac.ac_if;
709 
710 	bzero(&mc, sizeof(mc));
711 	if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) {
712 		printf("%s: failed to reset the device\n", DEVNAME(sc));
713 		return (-1);
714 	}
715 
716 	if (myx_rdma(sc, MYXRDMA_ON) != 0) {
717 		printf("%s: failed to enable dummy RDMA\n", DEVNAME(sc));
718 		return (-1);
719 	}
720 
721 	if (myx_cmd(sc, MYXCMD_GET_INTRCOALDELAYOFF, &mc,
722 	    &sc->sc_irqcoaloff) != 0) {
723 		printf("%s: failed to get IRQ coal offset\n", DEVNAME(sc));
724 		return (-1);
725 	}
726 	data = htobe32(MYX_IRQCOALDELAY);
727 	myx_write(sc, sc->sc_irqcoaloff, (u_int8_t *)&data, sizeof(data));
728 
729 	if (myx_cmd(sc, MYXCMD_GET_INTRACKOFF, &mc,
730 	    &sc->sc_irqclaimoff) != 0) {
731 		printf("%s: failed to get IRQ ack offset\n", DEVNAME(sc));
732 		return (-1);
733 	}
734 
735 	if (myx_cmd(sc, MYXCMD_GET_INTRDEASSERTOFF, &mc,
736 	    &sc->sc_irqdeassertoff) != 0) {
737 		printf("%s: failed to get IRQ deassert offset\n", DEVNAME(sc));
738 		return (-1);
739 	}
740 
741 	if (myx_cmd(sc, MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) {
742 		printf("%s: failed to disable promisc mode\n", DEVNAME(sc));
743 		return (-1);
744 	}
745 
746 	if (myx_cmd(sc, MYXCMD_FC_DEFAULT, &mc, NULL) != 0) {
747 		printf("%s: failed to configure flow control\n", DEVNAME(sc));
748 		return (-1);
749 	}
750 
751 	if (myx_setlladdr(sc, LLADDR(ifp->if_sadl)) != 0)
752 		return (-1);
753 
754 	return (0);
755 }
756 
757 
758 int
759 myx_media_change(struct ifnet *ifp)
760 {
761 	return (EINVAL);
762 }
763 
764 void
765 myx_media_status(struct ifnet *ifp, struct ifmediareq *imr)
766 {
767 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
768 
769 	imr->ifm_active = IFM_ETHER|sc->sc_phy;
770 	imr->ifm_status = IFM_AVALID;
771 	myx_link_state(sc);
772 	if (!LINK_STATE_IS_UP(ifp->if_link_state))
773 		return;
774 	imr->ifm_active |= IFM_FDX;
775 	imr->ifm_status |= IFM_ACTIVE;
776 
777 	/* Flow control */
778 	if (sc->sc_hwflags & MYXFLAG_FLOW_CONTROL)
779 		imr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE;
780 }
781 
782 void
783 myx_link_state(struct myx_softc *sc)
784 {
785 	struct ifnet		*ifp = &sc->sc_ac.ac_if;
786 	int			 link_state = LINK_STATE_DOWN;
787 
788 	if (sc->sc_sts == NULL)
789 		return;
790 	if (sc->sc_sts->ms_linkstate == MYXSTS_LINKUP)
791 		link_state = LINK_STATE_FULL_DUPLEX;
792 	if (ifp->if_link_state != link_state) {
793 		ifp->if_link_state = link_state;
794 		if_link_state_change(ifp);
795 	}
796 }
797 
798 void
799 myx_watchdog(struct ifnet *ifp)
800 {
801 	return;
802 }
803 
804 void
805 myx_tick(void *arg)
806 {
807 	struct myx_softc	*sc = (struct myx_softc *)arg;
808 
809 	if (!sc->sc_active)
810 		return;
811 
812 	myx_link_state(sc);
813 	timeout_add_sec(&sc->sc_tick, 1);
814 }
815 
816 int
817 myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
818 {
819 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
820 	struct ifaddr		*ifa = (struct ifaddr *)data;
821 	struct ifreq		*ifr = (struct ifreq *)data;
822 	int			 s, error = 0;
823 
824 	s = splnet();
825 
826 	switch (cmd) {
827 	case SIOCSIFADDR:
828 		ifp->if_flags |= IFF_UP;
829 #ifdef INET
830 		if (ifa->ifa_addr->sa_family == AF_INET)
831 			arp_ifinit(&sc->sc_ac, ifa);
832 #endif
833 		/* FALLTHROUGH */
834 
835 	case SIOCSIFFLAGS:
836 		if (ifp->if_flags & IFF_UP) {
837 			if (ifp->if_flags & IFF_RUNNING)
838 				myx_iff(sc);
839 			else
840 				myx_init(ifp);
841 		} else {
842 			if (ifp->if_flags & IFF_RUNNING)
843 				myx_stop(ifp);
844 		}
845 		break;
846 
847 	case SIOCGIFMEDIA:
848 	case SIOCSIFMEDIA:
849 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
850 		break;
851 
852 	default:
853 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
854 	}
855 
856 	if (error == ENETRESET) {
857 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
858 		    (IFF_UP | IFF_RUNNING))
859 			myx_iff(sc);
860 		error = 0;
861 	}
862 
863 	splx(s);
864 	return (error);
865 }
866 
867 void
868 myx_iff(struct myx_softc *sc)
869 {
870 	/* XXX set multicast filters etc. */
871 	return;
872 }
873 
874 void
875 myx_init(struct ifnet *ifp)
876 {
877 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
878 	struct myx_cmd		 mc;
879 
880 	if (myx_reset(sc) != 0)
881 		return;
882 
883 	if (myx_init_rings(sc) != 0)
884 		return;
885 
886 	if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) {
887 		printf("%s: failed to start the device\n", DEVNAME(sc));
888 		myx_free_rings(sc);
889 		return;
890 	}
891 
892 	ifp->if_flags |= IFF_RUNNING;
893 	ifp->if_flags &= ~IFF_OACTIVE;
894 }
895 
896 void
897 myx_start(struct ifnet *ifp)
898 {
899 }
900 
901 void
902 myx_stop(struct ifnet *ifp)
903 {
904 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
905 	struct myx_cmd		 mc;
906 
907 	bzero(&mc, sizeof(mc));
908 	(void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL);
909 	myx_free_rings(sc);
910 
911 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
912 }
913 
914 int
915 myx_setlladdr(struct myx_softc *sc, u_int8_t *addr)
916 {
917 	struct myx_cmd		 mc;
918 
919 	bzero(&mc, sizeof(mc));
920 	mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24;
921 	mc.mc_data1 = addr[5] | addr[4] << 8;
922 	if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) {
923 		printf("%s: failed to set the lladdr\n", DEVNAME(sc));
924 		return (-1);
925 	}
926 	return (0);
927 }
928 
929 int
930 myx_intr(void *arg)
931 {
932 	struct myx_softc	*sc = (struct myx_softc *)arg;
933 	u_int32_t		 data, valid;
934 	struct myx_status	*sts = sc->sc_sts;
935 	bus_dmamap_t		 map = sc->sc_stsdma.mxm_map;
936 
937 	if (!sc->sc_active)
938 		return (0);
939 
940 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
941 	    BUS_DMASYNC_POSTWRITE);
942 
943 	/*
944 	 * XXX The 'valid' flags should be set by the NIC, but it doesn't
945 	 * XXX work yet.
946 	 */
947 	valid = sts->ms_isvalid;
948 	if (!valid)
949 		return (0);
950 
951 	data = 0;
952 	myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data));
953 
954 	DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n",
955 	    DEVNAME(sc), __func__, valid);
956 
957 #ifdef MYX_DEBUG
958 #define DPRINT_STATUS(_n)						\
959 	DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\
960 	    #_n, sts->_n, sts->_n)
961 
962 	DPRINT_STATUS(ms_reserved);
963 	DPRINT_STATUS(ms_dropped_pause);
964 	DPRINT_STATUS(ms_dropped_unicast);
965 	DPRINT_STATUS(ms_dropped_crc32err);
966 	DPRINT_STATUS(ms_dropped_phyerr);
967 	DPRINT_STATUS(ms_dropped_mcast);
968 	DPRINT_STATUS(ms_txdonecnt);
969 	DPRINT_STATUS(ms_linkstate);
970 	DPRINT_STATUS(ms_dropped_linkoverflow);
971 	DPRINT_STATUS(ms_dropped_linkerror);
972 	DPRINT_STATUS(ms_dropped_runt);
973 	DPRINT_STATUS(ms_dropped_overrun);
974 	DPRINT_STATUS(ms_dropped_smallbufunderrun);
975 	DPRINT_STATUS(ms_dropped_bigbufunderrun);
976 	DPRINT_STATUS(ms_rdmatags_available);
977 	DPRINT_STATUS(ms_txstopped);
978 	DPRINT_STATUS(ms_linkdowncnt);
979 	DPRINT_STATUS(ms_statusupdated);
980 	DPRINT_STATUS(ms_isvalid);
981 #endif
982 
983 	data = htobe32(3);
984 	if (sts->ms_isvalid)
985 		myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data,
986 		    sizeof(data));
987 	myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t),
988 	    (u_int8_t *)&data, sizeof(data));
989 
990 	return (1);
991 }
992 
993 int
994 myx_init_rings(struct myx_softc *sc)
995 {
996 	struct myx_cmd		 mc;
997 	struct ifnet		*ifp = &sc->sc_ac.ac_if;
998 	bus_dmamap_t		 map;
999 	int			 i;
1000 	struct myx_buf		*mb;
1001 	struct myx_rxbufdesc	*rxb;
1002 	u_int32_t		 data;
1003 
1004 	bzero(&mc, sizeof(mc));
1005 	if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc,
1006 	    &sc->sc_rxringsize) == 0 && sc->sc_rxringsize &&
1007 	    myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc,
1008 	    &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff &&
1009 	    myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc,
1010 	    &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff &&
1011 	    myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc,
1012 	    &sc->sc_txringsize) == 0 && sc->sc_txringsize &&
1013 	    myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc,
1014 	    &sc->sc_txringoff) == 0 && sc->sc_txringoff)) {
1015 		printf("%s: failed to get ring sizes and offsets\n",
1016 		    DEVNAME(sc));
1017 		return (-1);
1018 	}
1019 	sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc);
1020 	sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc);
1021 	sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc);
1022 	sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf);
1023 	sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc);
1024 	IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1);
1025 	IFQ_SET_READY(&ifp->if_snd);
1026 
1027 	DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, "
1028 	    "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__,
1029 	    sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize,
1030 	    sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff);
1031 
1032 	/*
1033 	 * Setup Rx DMA descriptors
1034 	 */
1035 	if (myx_dmamem_alloc(sc, &sc->sc_rxdma,
1036 	    sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) {
1037 		printf(": failed to allocate Rx DMA memory\n");
1038 		return (-1);
1039 	}
1040 	sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva;
1041 
1042 	bzero(&mc, sizeof(mc));
1043 	mc.mc_data0 = htobe32(sc->sc_rxdescsize);
1044 	if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) {
1045 		printf("%s: failed to set Rx DMA size\n", DEVNAME(sc));
1046 		goto err;
1047 	}
1048 
1049 	map = sc->sc_rxdma.mxm_map;
1050 	mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1051 	mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1052 	if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) {
1053 		printf("%s: failed to set Rx DMA address\n", DEVNAME(sc));
1054 		goto err;
1055 	}
1056 
1057 #ifdef notyet
1058 	/*
1059 	 * XXX It fails to set the MTU and it always returns
1060 	 * XXX MYXCMD_ERR_RANGE.
1061 	 */
1062 	bzero(&mc, sizeof(mc));
1063 	mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4;
1064 	if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) {
1065 		printf("%s: failed to set MTU size %d\n",
1066 		    DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4);
1067 		goto err;
1068 	}
1069 #endif
1070 
1071 	/*
1072 	 * Setup Rx buffer descriptors
1073 	 */
1074 	sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *)
1075 	    malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1076 	sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *)
1077 	    malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1078 	sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *)
1079 	    malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1080 	sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *)
1081 	    malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1082 	if (sc->sc_rxbuf[MYX_RXSMALL] == NULL ||
1083 	    sc->sc_rxbufdesc[MYX_RXSMALL] == NULL ||
1084 	    sc->sc_rxbuf[MYX_RXBIG] == NULL ||
1085 	    sc->sc_rxbufdesc[MYX_RXBIG] == NULL) {
1086 		printf("%s: failed to allocate rx buffers\n", DEVNAME(sc));
1087 		goto err;
1088 	}
1089 
1090 	for (i = 0; i < sc->sc_rxndesc; i++) {
1091 		/*
1092 		 * Small Rx buffers and descriptors
1093 		 */
1094 		mb = sc->sc_rxbuf[MYX_RXSMALL] + i;
1095 		rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i;
1096 
1097 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1098 		    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1099 			printf("%s: unable to create dmamap for small rx %d\n",
1100 			    DEVNAME(sc), i);
1101 			goto err;
1102 		}
1103 
1104 		map = mb->mb_dmamap;
1105 		mb->mb_m = myx_getbuf(sc, map, 1);
1106 		if (mb->mb_m == NULL) {
1107 			bus_dmamap_destroy(sc->sc_dmat, map);
1108 			goto err;
1109 		}
1110 
1111 		bus_dmamap_sync(sc->sc_dmat, map, 0,
1112 		    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1113 
1114 		rxb->rb_addr_high =
1115 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1116 		rxb->rb_addr_low =
1117 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1118 
1119 		data = sc->sc_rxsmallringoff + i * sizeof(*rxb);
1120 		myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1121 
1122 		/*
1123 		 * Big Rx buffers and descriptors
1124 		 */
1125 		mb = sc->sc_rxbuf[MYX_RXBIG] + i;
1126 		rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i;
1127 
1128 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1129 		    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1130 			printf("%s: unable to create dmamap for big rx %d\n",
1131 			    DEVNAME(sc), i);
1132 			goto err;
1133 		}
1134 
1135 		map = mb->mb_dmamap;
1136 		mb->mb_m = myx_getbuf(sc, map, 1);
1137 		if (mb->mb_m == NULL) {
1138 			bus_dmamap_destroy(sc->sc_dmat, map);
1139 			goto err;
1140 		}
1141 
1142 		bus_dmamap_sync(sc->sc_dmat, map, 0,
1143 		    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1144 
1145 		rxb->rb_addr_high =
1146 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1147 		rxb->rb_addr_low =
1148 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1149 
1150 		data = sc->sc_rxbigringoff + i * sizeof(*rxb);
1151 		myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1152 	}
1153 
1154 	bzero(&mc, sizeof(mc));
1155 	mc.mc_data0 = MYX_MAX_MTU_SMALL;
1156 	if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) {
1157 		printf("%s: failed to set small buf size\n", DEVNAME(sc));
1158 		goto err;
1159 	}
1160 
1161 	bzero(&mc, sizeof(mc));
1162 	mc.mc_data0 = MCLBYTES;
1163 	if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) {
1164 		printf("%s: failed to set big buf size\n", DEVNAME(sc));
1165 		goto err;
1166 	}
1167 
1168 	/*
1169 	 * Setup status DMA
1170 	 */
1171 	map = sc->sc_stsdma.mxm_map;
1172 
1173 	bzero(&mc, sizeof(mc));
1174 	mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1175 	mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1176 	mc.mc_data2 = sizeof(struct myx_status);
1177 	if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) {
1178 		printf("%s: failed to set status DMA offset\n", DEVNAME(sc));
1179 		goto err;
1180 	}
1181 
1182 	bus_dmamap_sync(sc->sc_dmat, map, 0,
1183 	    map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1184 
1185 	return (0);
1186  err:
1187 	myx_free_rings(sc);
1188 	return (-1);
1189 }
1190 
1191 void
1192 myx_free_rings(struct myx_softc *sc)
1193 {
1194 	if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) {
1195 		free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF);
1196 		sc->sc_rxbuf[MYX_RXSMALL] = NULL;
1197 	}
1198 	if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) {
1199 		free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF);
1200 		sc->sc_rxbufdesc[MYX_RXSMALL] = NULL;
1201 	}
1202 	if (sc->sc_rxbuf[MYX_RXBIG] != NULL) {
1203 		free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF);
1204 		sc->sc_rxbuf[MYX_RXBIG] = NULL;
1205 	}
1206 	if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) {
1207 		free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF);
1208 		sc->sc_rxbufdesc[MYX_RXBIG] = NULL;
1209 	}
1210 	if (sc->sc_rxdesc != NULL) {
1211 		myx_dmamem_free(sc, &sc->sc_rxdma);
1212 		sc->sc_rxdesc = NULL;
1213 	}
1214 	if (sc->sc_sts != NULL) {
1215 		myx_dmamem_free(sc, &sc->sc_stsdma);
1216 		sc->sc_sts = NULL;
1217 	}
1218 	return;
1219 }
1220 
1221 struct mbuf *
1222 myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait)
1223 {
1224 	struct mbuf		*m = NULL;
1225 
1226 	MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA);
1227 	if (m == NULL)
1228 		goto merr;
1229 
1230 	MCLGET(m, wait ? M_WAIT : M_DONTWAIT);
1231 	if ((m->m_flags & M_EXT) == 0)
1232 		goto merr;
1233 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1234 
1235 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
1236 	    wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) {
1237 		printf("%s: could not load mbuf dma map\n", DEVNAME(sc));
1238 		goto err;
1239 	}
1240 
1241 	return (m);
1242  merr:
1243 	printf("%s: unable to allocate mbuf\n", DEVNAME(sc));
1244  err:
1245 	if (m != NULL)
1246 		m_freem(m);
1247 	return (NULL);
1248 }
1249