diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_sk.c | 107 | ||||
-rw-r--r-- | sys/dev/pci/if_skreg.h | 34 |
2 files changed, 97 insertions, 44 deletions
diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index a156f6567a0..95312f335a1 100644 --- a/sys/dev/pci/if_sk.c +++ b/sys/dev/pci/if_sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sk.c,v 1.72 2005/07/14 01:47:58 brad Exp $ */ +/* $OpenBSD: if_sk.c,v 1.73 2005/07/21 15:23:27 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -759,6 +759,9 @@ sk_init_tx_ring(struct sk_if_softc *sc_if) sc_if->sk_cdata.sk_tx_cons = 0; sc_if->sk_cdata.sk_tx_cnt = 0; + SK_CDTXSYNC(sc_if, 0, SK_TX_RING_CNT, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + return (0); } @@ -809,6 +812,8 @@ sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m, - (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); + return(0); } @@ -1402,17 +1407,13 @@ skc_attach(struct device *parent, struct device *self, void *aux) pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; - bus_addr_t iobase; - bus_size_t iosize; - int s; + bus_size_t size; u_int8_t skrs; u_int32_t command; char *revstr = NULL; DPRINTFN(2, ("begin skc_attach\n")); - s = splimp(); - /* * Handle power management nonsense. */ @@ -1446,41 +1447,19 @@ skc_attach(struct device *parent, struct device *self, void *aux) /* * Map control/status registers. */ - command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); #ifdef SK_USEIOSPACE - if (!(command & PCI_COMMAND_IO_ENABLE)) { - printf(": failed to enable I/O ports!\n"); - goto fail; - } - /* - * Map control/status registers. - */ - if (pci_io_find(pc, pa->pa_tag, SK_PCI_LOIO, &iobase, &iosize)) { - printf(": can't find i/o space\n"); - goto fail; - } - if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &sc->sk_bhandle)) { + if (pci_mapreg_map(pa, SK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, + &sc->sk_btag, &sc->sk_bhandle, NULL, &size, 0)) { printf(": can't map i/o space\n"); goto fail; - } - sc->sk_btag = pa->pa_iot; + } #else - if (!(command & PCI_COMMAND_MEM_ENABLE)) { - printf(": failed to enable memory mapping!\n"); - goto fail; - } - if (pci_mem_find(pc, pa->pa_tag, SK_PCI_LOMEM, &iobase, &iosize, NULL)){ - printf(": can't find mem space\n"); + if (pci_mapreg_map(pa, SK_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, + &sc->sk_btag, &sc->sk_bhandle, NULL, &size, 0)) { + printf(": can't map mem space\n"); goto fail; - } - if (bus_space_map(pa->pa_memt, iobase, iosize, 0, &sc->sk_bhandle)) { - printf(": can't map mem space\n"); - goto fail; - } - sc->sk_btag = pa->pa_memt; - - DPRINTFN(2, ("skc_attach: iobase=%#x, iosize=%#x\n", iobase, iosize)); + } #endif sc->sc_dmatag = pa->pa_dmat; @@ -1490,6 +1469,7 @@ skc_attach(struct device *parent, struct device *self, void *aux) /* bail out here if chip is not recognized */ if (sc->sk_type != SK_GENESIS && ! SK_YUKON_FAMILY(sc->sk_type)) { printf("%s: unknown chip type\n",sc->sk_dev.dv_xname); + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); goto fail; } DPRINTFN(2, ("skc_attach: allocate interrupt\n")); @@ -1497,6 +1477,7 @@ skc_attach(struct device *parent, struct device *self, void *aux) /* Allocate interrupt */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); goto fail; } @@ -1507,6 +1488,7 @@ skc_attach(struct device *parent, struct device *self, void *aux) printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); goto fail; } printf(": %s\n", intrstr); @@ -1540,7 +1522,8 @@ skc_attach(struct device *parent, struct device *self, void *aux) default: printf("%s: unknown ram size: %d\n", sc->sk_dev.dv_xname, skrs); - goto fail; + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); + goto fail_1; break; } } else { @@ -1572,7 +1555,8 @@ skc_attach(struct device *parent, struct device *self, void *aux) default: printf("%s: unknown media type: 0x%x\n", sc->sk_dev.dv_xname, sk_win_read_1(sc, SK_PMDTYPE)); - goto fail; + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); + goto fail_1; } switch (sc->sk_type) { @@ -1655,7 +1639,10 @@ skc_attach(struct device *parent, struct device *self, void *aux) CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); fail: - splx(s); + return; + +fail_1: + pci_intr_disestablish(pc, sc->sk_intrhand); } int @@ -1697,6 +1684,10 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx) DPRINTFN(2, ("sk_encap: dm_nsegs=%d\n", txmap->dm_nsegs)); + /* Sync the DMA map. */ + bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, + BUS_DMASYNC_PREWRITE); + for (i = 0; i < txmap->dm_nsegs; i++) { if ((SK_TX_RING_CNT - (sc_if->sk_cdata.sk_tx_cnt + cnt)) < 2) { DPRINTFN(2, ("sk_encap: too few descriptors free\n")); @@ -1717,10 +1708,20 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx) sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head; SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link); + sc_if->sk_cdata.sk_tx_map[cur] = entry; sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= SK_TXCTL_LASTFRAG|SK_TXCTL_EOF_INTR; + + /* Sync descriptors before handing to chip */ + SK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + sc_if->sk_rdata->sk_tx_ring[*txidx].sk_ctl |= SK_TXCTL_OWN; + + /* Sync first descriptor to hand it off */ + SK_CDTXSYNC(sc_if, *txidx, 1, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + sc_if->sk_cdata.sk_tx_cnt += cnt; #ifdef SK_DEBUG @@ -1837,18 +1838,32 @@ sk_rxeof(struct sk_if_softc *sc_if) i = sc_if->sk_cdata.sk_rx_prod; - while(!(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl & SK_RXCTL_OWN)) { + for (;;) { cur = i; + + /* Sync the descriptor */ + SK_CDRXSYNC(sc_if, cur, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + + if (sc_if->sk_rdata->sk_rx_ring[i].sk_ctl & SK_RXCTL_OWN) { + /* Invalidate the descriptor -- it's not ready yet */ + SK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_PREREAD); + sc_if->sk_cdata.sk_rx_prod = i; + break; + } + 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_jumbo_map; + + bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, + dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); rxstat = cur_desc->sk_xmac_rxstat; m = cur_rx->sk_mbuf; cur_rx->sk_mbuf = NULL; total_len = SK_RXBYTES(cur_desc->sk_ctl); - dmamap = sc_if->sk_cdata.sk_rx_jumbo_map; - csum1 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum1; csum2 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum2; @@ -2004,20 +2019,26 @@ sk_txeof(struct sk_if_softc *sc_if) */ idx = sc_if->sk_cdata.sk_tx_cons; while(idx != sc_if->sk_cdata.sk_tx_prod) { + SK_CDTXSYNC(sc_if, idx, 1, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx]; #ifdef SK_DEBUG if (skdebug >= 2) sk_dump_txdesc(cur_tx, idx); #endif - if (cur_tx->sk_ctl & SK_TXCTL_OWN) + if (cur_tx->sk_ctl & SK_TXCTL_OWN) { + SK_CDTXSYNC(sc_if, idx, 1, BUS_DMASYNC_PREREAD); break; + } if (cur_tx->sk_ctl & SK_TXCTL_LASTFRAG) ifp->if_opackets++; if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) { + entry = sc_if->sk_cdata.sk_tx_map[idx]; + m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf); sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL; - entry = sc_if->sk_cdata.sk_tx_map[idx]; bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0, entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); diff --git a/sys/dev/pci/if_skreg.h b/sys/dev/pci/if_skreg.h index 6bca79b48ff..009b8b77902 100644 --- a/sys/dev/pci/if_skreg.h +++ b/sys/dev/pci/if_skreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_skreg.h,v 1.16 2005/03/14 01:15:14 brad Exp $ */ +/* $OpenBSD: if_skreg.h,v 1.17 2005/07/21 15:23:27 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -1322,6 +1322,38 @@ struct sk_tx_desc { #define SK_TX_RING_CNT 512 #define SK_RX_RING_CNT 256 +#define SK_CDOFF(x) offsetof(struct sk_ring_data, x) +#define SK_CDTXOFF(x) SK_CDOFF(sk_tx_ring[(x)]) +#define SK_CDRXOFF(x) SK_CDOFF(sk_rx_ring[(x)]) + +#define SK_CDTXSYNC(sc, x, n, ops) \ +do { \ + int __x, __n; \ + \ + __x = (x); \ + __n = (n); \ + \ + /* If it will wrap around, sync to the end of the ring. */ \ + if ((__x + __n) > SK_TX_RING_CNT) { \ + bus_dmamap_sync((sc)->sk_softc->sc_dmatag, \ + (sc)->sk_ring_map, SK_CDTXOFF(__x), \ + sizeof(struct sk_tx_desc) * (SK_TX_RING_CNT - __x),\ + (ops)); \ + __n -= (SK_TX_RING_CNT - __x); \ + __x = 0; \ + } \ + \ + /* Now sync whatever is left. */ \ + bus_dmamap_sync((sc)->sk_softc->sc_dmatag, (sc)->sk_ring_map, \ + SK_CDTXOFF((__x)), sizeof(struct sk_tx_desc) * __n, (ops)); \ +} while (/*CONSTCOND*/0) + +#define SK_CDRXSYNC(sc, x, ops) \ +do { \ + bus_dmamap_sync((sc)->sk_softc->sc_dmatag, (sc)->sk_ring_map, \ + SK_CDRXOFF((x)), sizeof(struct sk_rx_desc), (ops)); \ +} while (/*CONSTCOND*/0) + /* * Jumbo buffer stuff. Note that we must allocate more jumbo * buffers than there are descriptors in the receive ring. This |