--- if_skvar.h.orig	2005-11-27 08:37:44.000000000 -0800
+++ if_skvar.h	2005-11-27 08:39:18.000000000 -0800
@@ -87,11 +87,6 @@
 #ifndef _DEV_PCI_IF_SKVAR_H_
 #define _DEV_PCI_IF_SKVAR_H_
 
-struct sk_jslot {
-	caddr_t			sk_buf;
-	int			sk_inuse;
-};
-
 struct sk_jpool_entry {
 	int                             slot;
 	LIST_ENTRY(sk_jpool_entry)	jpool_entries;
@@ -122,6 +117,7 @@
 	struct sk_chain		sk_rx_chain[SK_RX_RING_CNT];
 	struct sk_txmap_entry	*sk_tx_map[SK_TX_RING_CNT];
 	bus_dmamap_t		sk_rx_map[SK_RX_RING_CNT];
+	bus_dmamap_t		sk_rx_jumbo_map;
 	int			sk_tx_prod;
 	int			sk_tx_cons;
 	int			sk_tx_cnt;
@@ -129,7 +125,7 @@
 	int			sk_rx_cons;
 	int			sk_rx_cnt;
 	/* Stick the jumbo mem management stuff here too. */
-	struct sk_jslot		sk_jslots[SK_JSLOTS];
+	caddr_t			sk_jslots[SK_JSLOTS];
 	void			*sk_jumbo_buf;
 
 };
--- if_sk.c.orig	2005-11-27 08:37:44.000000000 -0800
+++ if_sk.c	2005-11-27 08:43:39.000000000 -0800
@@ -191,6 +191,10 @@
 void sk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
 void sk_reset(struct sk_softc *);
 int sk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t);
+int sk_alloc_jumbo_mem(struct sk_if_softc *);
+void sk_free_jumbo_mem(struct sk_if_softc *);
+void *sk_jalloc(struct sk_if_softc *);
+void sk_jfree(struct mbuf *, caddr_t, size_t, void *);
 int sk_init_rx_ring(struct sk_if_softc *);
 int sk_init_tx_ring(struct sk_if_softc *);
 u_int8_t sk_vpd_readbyte(struct sk_softc *, int);
@@ -726,7 +730,8 @@
 	}
 
 	for (i = 0; i < SK_RX_RING_CNT; i++) {
-		if (sk_newbuf(sc_if, i, NULL, NULL) == ENOBUFS) {
+		if (sk_newbuf(sc_if, i, NULL, 
+		    sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) {
 			printf("%s: failed alloc of %dth mbuf\n",
 			    sc_if->sk_dev.dv_xname, i);
 			return(ENOBUFS);
@@ -773,26 +778,13 @@
 sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m,
 	  bus_dmamap_t dmamap)
 {
-	struct sk_softc		*sc = sc_if->sk_softc;
 	struct mbuf		*m_new = NULL;
 	struct sk_chain		*c;
 	struct sk_rx_desc	*r;
 
-	if (dmamap == NULL) {
-		/* if (m) panic() */
-
-		if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1, MCLBYTES,
-				      0, BUS_DMA_NOWAIT, &dmamap)) {
-			printf("%s: can't create recv map\n",
-			       sc_if->sk_dev.dv_xname);
-			return(ENOMEM);
-		}
-	} else if (m == NULL)
-		bus_dmamap_unload(sc->sc_dmatag, dmamap);
-
-	sc_if->sk_cdata.sk_rx_map[i] = dmamap;
-
 	if (m == NULL) {
+		caddr_t buf = NULL;
+
 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
 		if (m_new == NULL) {
 			printf("%s: no memory for rx list -- "
@@ -801,19 +793,18 @@
 		}
 
 		/* Allocate the jumbo buffer */
-		MCLGET(m_new, M_DONTWAIT);
-		if (!(m_new->m_flags & M_EXT)) {
+		buf = sk_jalloc(sc_if);
+		if (buf == NULL) {
 			m_freem(m_new);
-			return (ENOBUFS);
+			DPRINTFN(1, ("%s jumbo allocation failed -- packet "
+			    "dropped!\n", sc_if->sk_ethercom.ec_if.if_xname));
+			return(ENOBUFS);
 		}
 
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-
-		m_adj(m_new, ETHER_ALIGN);
+		/* Attach the buffer to the mbuf */
+		m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
+		MEXTADD(m_new, buf, SK_JLEN, 0, sk_jfree, sc_if);
 
-		if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m_new,
-					 BUS_DMA_NOWAIT))
-			return(ENOBUFS);
 	} else {
 		/*
 	 	 * We're re-using a previously allocated mbuf;
@@ -821,16 +812,18 @@
 		 * default values.
 		 */
 		m_new = m;
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-		m_adj(m_new, ETHER_ALIGN);
+		m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
 		m_new->m_data = m_new->m_ext.ext_buf;
 	}
+	m_adj(m_new, ETHER_ALIGN);
 
 	c = &sc_if->sk_cdata.sk_rx_chain[i];
 	r = c->sk_desc;
 	c->sk_mbuf = m_new;
-	r->sk_data_lo = dmamap->dm_segs[0].ds_addr;
-	r->sk_ctl = dmamap->dm_segs[0].ds_len | SK_RXSTAT;
+	r->sk_data_lo = dmamap->dm_segs[0].ds_addr +
+	    (((vaddr_t)m_new->m_data
+		- (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf));
+	r->sk_ctl = SK_JLEN | SK_RXSTAT;
 
 	SK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
 
@@ -838,6 +831,161 @@
 }
 
 /*
+ * Memory management for jumbo frames.
+ */
+
+int
+sk_alloc_jumbo_mem(struct sk_if_softc *sc_if)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	caddr_t			ptr, kva;
+	bus_dma_segment_t	seg;
+	int		i, rseg, state, error;
+	struct sk_jpool_entry   *entry;
+
+	state = error = 0;
+
+	/* Grab a big chunk o' storage. */
+	if (bus_dmamem_alloc(sc->sc_dmatag, SK_JMEM, PAGE_SIZE, 0,
+			     &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
+		printf("%s: can't alloc rx buffers\n", sc->sk_dev.dv_xname);
+		return (ENOBUFS);
+	}
+
+	state = 1;
+	if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, SK_JMEM, &kva,
+			   BUS_DMA_NOWAIT)) {
+		printf("%s: can't map dma buffers (%d bytes)\n",
+		    sc->sk_dev.dv_xname, SK_JMEM);
+		error = ENOBUFS;
+		goto out;
+	}
+
+	state = 2;
+	if (bus_dmamap_create(sc->sc_dmatag, SK_JMEM, 1, SK_JMEM, 0,
+	    BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) {
+		printf("%s: can't create dma map\n", sc->sk_dev.dv_xname);
+		error = ENOBUFS;
+		goto out;
+	}
+
+	state = 3;
+	if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map,
+			    kva, SK_JMEM, NULL, BUS_DMA_NOWAIT)) {
+		printf("%s: can't load dma map\n", sc->sk_dev.dv_xname);
+		error = ENOBUFS;
+		goto out;
+	}
+
+	state = 4;
+	sc_if->sk_cdata.sk_jumbo_buf = (caddr_t)kva;
+	DPRINTFN(1,("sk_jumbo_buf = 0x%08X\n", sc_if->sk_cdata.sk_jumbo_buf));
+
+	LIST_INIT(&sc_if->sk_jfree_listhead);
+	LIST_INIT(&sc_if->sk_jinuse_listhead);
+
+	/*
+	 * Now divide it up into 9K pieces and save the addresses
+	 * in an array.
+	 */
+	ptr = sc_if->sk_cdata.sk_jumbo_buf;
+	for (i = 0; i < SK_JSLOTS; i++) {
+		sc_if->sk_cdata.sk_jslots[i] = ptr;
+		ptr += SK_JLEN;
+		entry = malloc(sizeof(struct sk_jpool_entry),
+		    M_DEVBUF, M_NOWAIT);
+		if (entry == NULL) {
+			printf("%s: no memory for jumbo buffer queue!\n",
+			    sc->sk_dev.dv_xname);
+			error = ENOBUFS;
+			goto out;
+		}
+		entry->slot = i;
+		if (i)
+		LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead,
+				 entry, jpool_entries);
+		else
+		LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead,
+				 entry, jpool_entries);
+	}
+out:
+	if (error != 0) {
+		switch (state) {
+		case 4:
+			bus_dmamap_unload(sc->sc_dmatag,
+			    sc_if->sk_cdata.sk_rx_jumbo_map);
+		case 3:
+			bus_dmamap_destroy(sc->sc_dmatag,
+			    sc_if->sk_cdata.sk_rx_jumbo_map);
+		case 2:
+			bus_dmamem_unmap(sc->sc_dmatag, kva, SK_JMEM);
+		case 1:
+			bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return (error);
+}
+
+/*
+ * Allocate a jumbo buffer.
+ */
+void *
+sk_jalloc(struct sk_if_softc *sc_if)
+{
+	struct sk_jpool_entry   *entry;
+
+	entry = LIST_FIRST(&sc_if->sk_jfree_listhead);
+
+	if (entry == NULL)
+		return (NULL);
+
+	LIST_REMOVE(entry, jpool_entries);
+	LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
+	return (sc_if->sk_cdata.sk_jslots[entry->slot]);
+}
+
+/*
+ * Release a jumbo buffer.
+ */
+void
+sk_jfree(struct mbuf *m, caddr_t buf, size_t size, void	*arg)
+{
+	struct sk_jpool_entry *entry;
+	struct sk_if_softc *sc;
+	int i, s;
+
+	/* Extract the softc struct pointer. */
+	sc = (struct sk_if_softc *)arg;
+
+	if (sc == NULL)
+		panic("sk_jfree: can't find softc pointer!");
+
+	/* calculate the slot this buffer belongs to */
+
+	i = ((vaddr_t)buf
+	     - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN;
+
+	if ((i < 0) || (i >= SK_JSLOTS))
+		panic("sk_jfree: asked to free buffer that we don't manage!");
+
+	s = splvm();
+	entry = LIST_FIRST(&sc->sk_jinuse_listhead);
+	if (entry == NULL)
+		panic("sk_jfree: buffer not in use!");
+	entry->slot = i;
+	LIST_REMOVE(entry, jpool_entries);
+	LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries);
+
+	if (__predict_true(m != NULL))
+		pool_cache_put(&mbpool_cache, m);
+	splx(s);
+}
+
+/*
  * Set media options.
  */
 int
@@ -1120,7 +1268,7 @@
 	 * amount of SRAM on it, somewhere between 512K and 2MB. We
 	 * need to divide this up a) between the transmitter and
  	 * receiver and b) between the two XMACs, if this is a
-	 * dual port NIC. Our algotithm is to divide up the memory
+	 * dual port NIC. Our algorithm is to divide up the memory
 	 * evenly so that everyone gets a fair share.
 	 */
 	if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) {
@@ -1214,8 +1362,8 @@
 	for (i = 0; i < SK_TX_RING_CNT; i++) {
 		sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL;
 
-		if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, SK_NTXSEG,
-		    MCLBYTES, 0, BUS_DMA_NOWAIT, &dmamap)) {
+		if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, SK_NTXSEG,
+		    SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap)) {
 			aprint_error("%s: Can't create TX dmamap\n",
 				sc_if->sk_dev.dv_xname);
 			bus_dmamap_unload(sc->sc_dmatag, sc_if->sk_ring_map);
@@ -1245,12 +1393,15 @@
         sc_if->sk_rdata = (struct sk_ring_data *)kva;
 	bzero(sc_if->sk_rdata, sizeof(struct sk_ring_data));
 
-	/* XXX TLS It's not clear what's wrong with the Jumbo MTU
-	   XXX TLS support in this driver, so we don't enable it. */
-
-	sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU;
-
 	ifp = &sc_if->sk_ethercom.ec_if;
+	/* Try to allocate memory for jumbo buffers. */
+	if (sk_alloc_jumbo_mem(sc_if)) {
+		printf("%s: jumbo buffer allocation failed\n", ifp->if_xname);
+		goto fail;
+	}
+	sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU 
+		| ETHERCAP_JUMBO_MTU;
+
 	ifp->if_softc = sc_if;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = sk_ioctl;
@@ -1889,7 +2040,7 @@
 
 		cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur];
 		cur_desc = &sc_if->sk_rdata->sk_rx_ring[cur];
-		dmamap = sc_if->sk_cdata.sk_rx_map[cur];
+		dmamap = sc_if->sk_cdata.sk_rx_jumbo_map;
 
 		bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0,
 		    dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
@@ -2482,7 +2633,8 @@
 	/* serial mode register */
 	DPRINTFN(6, ("sk_init_yukon: 9\n"));
 	SK_YU_WRITE_2(sc_if, YUKON_SMR, YU_SMR_DATA_BLIND(0x1c) |
-		      YU_SMR_MFL_VLAN | YU_SMR_IPG_DATA(0x1e));
+		      YU_SMR_MFL_VLAN | YU_SMR_MFL_JUMBO |
+		      YU_SMR_IPG_DATA(0x1e));
 
 	DPRINTFN(6, ("sk_init_yukon: 10\n"));
 	/* Setup Yukon's address */
