xref: /openbsd-src/sys/dev/pci/if_myx.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: if_myx.c,v 1.8 2008/09/10 14:01:22 blambert 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 	if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
826 		splx(s);
827 		return (error);
828 	}
829 
830 	switch (cmd) {
831 	case SIOCSIFADDR:
832 		ifp->if_flags |= IFF_UP;
833 #ifdef INET
834 		if (ifa->ifa_addr->sa_family == AF_INET)
835 			arp_ifinit(&sc->sc_ac, ifa);
836 #endif
837 		/* FALLTHROUGH */
838 	case SIOCSIFFLAGS:
839 		if (ifp->if_flags & IFF_UP) {
840 			if (ifp->if_flags & IFF_RUNNING)
841 				myx_iff(sc);
842 			else
843 				myx_init(ifp);
844 		} else {
845 			if (ifp->if_flags & IFF_RUNNING)
846 				myx_stop(ifp);
847 		}
848 		break;
849 
850 	case SIOCSIFMTU:
851 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
852 			error = EINVAL;
853 		else if (ifp->if_mtu != ifr->ifr_mtu)
854 			ifp->if_mtu = ifr->ifr_mtu;
855 		break;
856 
857 	case SIOCADDMULTI:
858 		error = ether_addmulti(ifr, &sc->sc_ac);
859 		break;
860 
861 	case SIOCDELMULTI:
862 		error = ether_delmulti(ifr, &sc->sc_ac);
863 		break;
864 
865 	case SIOCGIFMEDIA:
866 	case SIOCSIFMEDIA:
867 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
868 		break;
869 
870 	default:
871 		error = ENOTTY;
872 	}
873 
874 	if (error == ENETRESET) {
875 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
876 		    (IFF_UP | IFF_RUNNING))
877 			myx_iff(sc);
878 		error = 0;
879 	}
880 
881 	splx(s);
882 
883 	return (error);
884 }
885 
886 void
887 myx_iff(struct myx_softc *sc)
888 {
889 	/* XXX set multicast filters etc. */
890 	return;
891 }
892 
893 void
894 myx_init(struct ifnet *ifp)
895 {
896 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
897 	struct myx_cmd		 mc;
898 
899 	if (myx_reset(sc) != 0)
900 		return;
901 
902 	if (myx_init_rings(sc) != 0)
903 		return;
904 
905 	if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) {
906 		printf("%s: failed to start the device\n", DEVNAME(sc));
907 		myx_free_rings(sc);
908 		return;
909 	}
910 
911 	ifp->if_flags |= IFF_RUNNING;
912 	ifp->if_flags &= ~IFF_OACTIVE;
913 }
914 
915 void
916 myx_start(struct ifnet *ifp)
917 {
918 }
919 
920 void
921 myx_stop(struct ifnet *ifp)
922 {
923 	struct myx_softc	*sc = (struct myx_softc *)ifp->if_softc;
924 	struct myx_cmd		 mc;
925 
926 	bzero(&mc, sizeof(mc));
927 	(void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL);
928 	myx_free_rings(sc);
929 
930 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
931 }
932 
933 int
934 myx_setlladdr(struct myx_softc *sc, u_int8_t *addr)
935 {
936 	struct myx_cmd		 mc;
937 
938 	bzero(&mc, sizeof(mc));
939 	mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24;
940 	mc.mc_data1 = addr[5] | addr[4] << 8;
941 	if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) {
942 		printf("%s: failed to set the lladdr\n", DEVNAME(sc));
943 		return (-1);
944 	}
945 	return (0);
946 }
947 
948 int
949 myx_intr(void *arg)
950 {
951 	struct myx_softc	*sc = (struct myx_softc *)arg;
952 	u_int32_t		 data, valid;
953 	struct myx_status	*sts = sc->sc_sts;
954 	bus_dmamap_t		 map = sc->sc_stsdma.mxm_map;
955 
956 	if (!sc->sc_active)
957 		return (0);
958 
959 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
960 	    BUS_DMASYNC_POSTWRITE);
961 
962 	/*
963 	 * XXX The 'valid' flags should be set by the NIC, but it doesn't
964 	 * XXX work yet.
965 	 */
966 	valid = sts->ms_isvalid;
967 	if (!valid)
968 		return (0);
969 
970 	data = 0;
971 	myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data));
972 
973 	DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n",
974 	    DEVNAME(sc), __func__, valid);
975 
976 #ifdef MYX_DEBUG
977 #define DPRINT_STATUS(_n)						\
978 	DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\
979 	    #_n, sts->_n, sts->_n)
980 
981 	DPRINT_STATUS(ms_reserved);
982 	DPRINT_STATUS(ms_dropped_pause);
983 	DPRINT_STATUS(ms_dropped_unicast);
984 	DPRINT_STATUS(ms_dropped_crc32err);
985 	DPRINT_STATUS(ms_dropped_phyerr);
986 	DPRINT_STATUS(ms_dropped_mcast);
987 	DPRINT_STATUS(ms_txdonecnt);
988 	DPRINT_STATUS(ms_linkstate);
989 	DPRINT_STATUS(ms_dropped_linkoverflow);
990 	DPRINT_STATUS(ms_dropped_linkerror);
991 	DPRINT_STATUS(ms_dropped_runt);
992 	DPRINT_STATUS(ms_dropped_overrun);
993 	DPRINT_STATUS(ms_dropped_smallbufunderrun);
994 	DPRINT_STATUS(ms_dropped_bigbufunderrun);
995 	DPRINT_STATUS(ms_rdmatags_available);
996 	DPRINT_STATUS(ms_txstopped);
997 	DPRINT_STATUS(ms_linkdowncnt);
998 	DPRINT_STATUS(ms_statusupdated);
999 	DPRINT_STATUS(ms_isvalid);
1000 #endif
1001 
1002 	data = htobe32(3);
1003 	if (sts->ms_isvalid)
1004 		myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data,
1005 		    sizeof(data));
1006 	myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t),
1007 	    (u_int8_t *)&data, sizeof(data));
1008 
1009 	return (1);
1010 }
1011 
1012 int
1013 myx_init_rings(struct myx_softc *sc)
1014 {
1015 	struct myx_cmd		 mc;
1016 	struct ifnet		*ifp = &sc->sc_ac.ac_if;
1017 	bus_dmamap_t		 map;
1018 	int			 i;
1019 	struct myx_buf		*mb;
1020 	struct myx_rxbufdesc	*rxb;
1021 	u_int32_t		 data;
1022 
1023 	bzero(&mc, sizeof(mc));
1024 	if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc,
1025 	    &sc->sc_rxringsize) == 0 && sc->sc_rxringsize &&
1026 	    myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc,
1027 	    &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff &&
1028 	    myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc,
1029 	    &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff &&
1030 	    myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc,
1031 	    &sc->sc_txringsize) == 0 && sc->sc_txringsize &&
1032 	    myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc,
1033 	    &sc->sc_txringoff) == 0 && sc->sc_txringoff)) {
1034 		printf("%s: failed to get ring sizes and offsets\n",
1035 		    DEVNAME(sc));
1036 		return (-1);
1037 	}
1038 	sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc);
1039 	sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc);
1040 	sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc);
1041 	sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf);
1042 	sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc);
1043 	IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1);
1044 	IFQ_SET_READY(&ifp->if_snd);
1045 
1046 	DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, "
1047 	    "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__,
1048 	    sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize,
1049 	    sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff);
1050 
1051 	/*
1052 	 * Setup Rx DMA descriptors
1053 	 */
1054 	if (myx_dmamem_alloc(sc, &sc->sc_rxdma,
1055 	    sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) {
1056 		printf(": failed to allocate Rx DMA memory\n");
1057 		return (-1);
1058 	}
1059 	sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva;
1060 
1061 	bzero(&mc, sizeof(mc));
1062 	mc.mc_data0 = htobe32(sc->sc_rxdescsize);
1063 	if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) {
1064 		printf("%s: failed to set Rx DMA size\n", DEVNAME(sc));
1065 		goto err;
1066 	}
1067 
1068 	map = sc->sc_rxdma.mxm_map;
1069 	mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1070 	mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1071 	if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) {
1072 		printf("%s: failed to set Rx DMA address\n", DEVNAME(sc));
1073 		goto err;
1074 	}
1075 
1076 #ifdef notyet
1077 	/*
1078 	 * XXX It fails to set the MTU and it always returns
1079 	 * XXX MYXCMD_ERR_RANGE.
1080 	 */
1081 	bzero(&mc, sizeof(mc));
1082 	mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4;
1083 	if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) {
1084 		printf("%s: failed to set MTU size %d\n",
1085 		    DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4);
1086 		goto err;
1087 	}
1088 #endif
1089 
1090 	/*
1091 	 * Setup Rx buffer descriptors
1092 	 */
1093 	sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *)
1094 	    malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1095 	sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *)
1096 	    malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1097 	sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *)
1098 	    malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1099 	sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *)
1100 	    malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1101 	if (sc->sc_rxbuf[MYX_RXSMALL] == NULL ||
1102 	    sc->sc_rxbufdesc[MYX_RXSMALL] == NULL ||
1103 	    sc->sc_rxbuf[MYX_RXBIG] == NULL ||
1104 	    sc->sc_rxbufdesc[MYX_RXBIG] == NULL) {
1105 		printf("%s: failed to allocate rx buffers\n", DEVNAME(sc));
1106 		goto err;
1107 	}
1108 
1109 	for (i = 0; i < sc->sc_rxndesc; i++) {
1110 		/*
1111 		 * Small Rx buffers and descriptors
1112 		 */
1113 		mb = sc->sc_rxbuf[MYX_RXSMALL] + i;
1114 		rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i;
1115 
1116 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1117 		    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1118 			printf("%s: unable to create dmamap for small rx %d\n",
1119 			    DEVNAME(sc), i);
1120 			goto err;
1121 		}
1122 
1123 		map = mb->mb_dmamap;
1124 		mb->mb_m = myx_getbuf(sc, map, 1);
1125 		if (mb->mb_m == NULL) {
1126 			bus_dmamap_destroy(sc->sc_dmat, map);
1127 			goto err;
1128 		}
1129 
1130 		bus_dmamap_sync(sc->sc_dmat, map, 0,
1131 		    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1132 
1133 		rxb->rb_addr_high =
1134 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1135 		rxb->rb_addr_low =
1136 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1137 
1138 		data = sc->sc_rxsmallringoff + i * sizeof(*rxb);
1139 		myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1140 
1141 		/*
1142 		 * Big Rx buffers and descriptors
1143 		 */
1144 		mb = sc->sc_rxbuf[MYX_RXBIG] + i;
1145 		rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i;
1146 
1147 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1148 		    MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1149 			printf("%s: unable to create dmamap for big rx %d\n",
1150 			    DEVNAME(sc), i);
1151 			goto err;
1152 		}
1153 
1154 		map = mb->mb_dmamap;
1155 		mb->mb_m = myx_getbuf(sc, map, 1);
1156 		if (mb->mb_m == NULL) {
1157 			bus_dmamap_destroy(sc->sc_dmat, map);
1158 			goto err;
1159 		}
1160 
1161 		bus_dmamap_sync(sc->sc_dmat, map, 0,
1162 		    mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1163 
1164 		rxb->rb_addr_high =
1165 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1166 		rxb->rb_addr_low =
1167 		    htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1168 
1169 		data = sc->sc_rxbigringoff + i * sizeof(*rxb);
1170 		myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1171 	}
1172 
1173 	bzero(&mc, sizeof(mc));
1174 	mc.mc_data0 = MYX_MAX_MTU_SMALL;
1175 	if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) {
1176 		printf("%s: failed to set small buf size\n", DEVNAME(sc));
1177 		goto err;
1178 	}
1179 
1180 	bzero(&mc, sizeof(mc));
1181 	mc.mc_data0 = MCLBYTES;
1182 	if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) {
1183 		printf("%s: failed to set big buf size\n", DEVNAME(sc));
1184 		goto err;
1185 	}
1186 
1187 	/*
1188 	 * Setup status DMA
1189 	 */
1190 	map = sc->sc_stsdma.mxm_map;
1191 
1192 	bzero(&mc, sizeof(mc));
1193 	mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1194 	mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1195 	mc.mc_data2 = sizeof(struct myx_status);
1196 	if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) {
1197 		printf("%s: failed to set status DMA offset\n", DEVNAME(sc));
1198 		goto err;
1199 	}
1200 
1201 	bus_dmamap_sync(sc->sc_dmat, map, 0,
1202 	    map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1203 
1204 	return (0);
1205  err:
1206 	myx_free_rings(sc);
1207 	return (-1);
1208 }
1209 
1210 void
1211 myx_free_rings(struct myx_softc *sc)
1212 {
1213 	if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) {
1214 		free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF);
1215 		sc->sc_rxbuf[MYX_RXSMALL] = NULL;
1216 	}
1217 	if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) {
1218 		free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF);
1219 		sc->sc_rxbufdesc[MYX_RXSMALL] = NULL;
1220 	}
1221 	if (sc->sc_rxbuf[MYX_RXBIG] != NULL) {
1222 		free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF);
1223 		sc->sc_rxbuf[MYX_RXBIG] = NULL;
1224 	}
1225 	if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) {
1226 		free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF);
1227 		sc->sc_rxbufdesc[MYX_RXBIG] = NULL;
1228 	}
1229 	if (sc->sc_rxdesc != NULL) {
1230 		myx_dmamem_free(sc, &sc->sc_rxdma);
1231 		sc->sc_rxdesc = NULL;
1232 	}
1233 	if (sc->sc_sts != NULL) {
1234 		myx_dmamem_free(sc, &sc->sc_stsdma);
1235 		sc->sc_sts = NULL;
1236 	}
1237 	return;
1238 }
1239 
1240 struct mbuf *
1241 myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait)
1242 {
1243 	struct mbuf		*m = NULL;
1244 
1245 	MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA);
1246 	if (m == NULL)
1247 		goto merr;
1248 
1249 	MCLGET(m, wait ? M_WAIT : M_DONTWAIT);
1250 	if ((m->m_flags & M_EXT) == 0)
1251 		goto merr;
1252 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1253 
1254 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
1255 	    wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) {
1256 		printf("%s: could not load mbuf dma map\n", DEVNAME(sc));
1257 		goto err;
1258 	}
1259 
1260 	return (m);
1261  merr:
1262 	printf("%s: unable to allocate mbuf\n", DEVNAME(sc));
1263  err:
1264 	if (m != NULL)
1265 		m_freem(m);
1266 	return (NULL);
1267 }
1268