1 /* $NetBSD: if_admswvar.h,v 1.5 2012/10/27 17:18:01 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or 8 * without modification, are permitted provided that the following 9 * conditions are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 3. The names of the authors may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 */ 33 #ifndef _IF_ADMSWVAR_H_ 34 #define _IF_ADMSWVAR_H_ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: if_admswvar.h,v 1.5 2012/10/27 17:18:01 chs Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/callout.h> 42 #include <sys/device.h> 43 #include <sys/endian.h> 44 #include <sys/errno.h> 45 #include <sys/intr.h> 46 #include <sys/ioctl.h> 47 #include <sys/kernel.h> 48 #include <sys/malloc.h> 49 #include <sys/mbuf.h> 50 #include <sys/socket.h> 51 #include <sys/systm.h> 52 #include <sys/wdog.h> 53 54 #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ 55 56 #include <net/if.h> 57 #include <net/if_dl.h> 58 #include <net/if_media.h> 59 #include <net/if_ether.h> 60 61 #include <dev/mii/mii.h> 62 #include <dev/mii/miivar.h> 63 64 #include <dev/sysmon/sysmonvar.h> 65 66 #include <mips/adm5120/include/adm5120reg.h> 67 #include <mips/adm5120/include/adm5120var.h> 68 #include <mips/adm5120/include/adm5120_obiovar.h> 69 70 #include <mips/adm5120/dev/if_admswreg.h> 71 72 #define ADMSW_EVENT_COUNTERS 73 74 #define MAC_BUFLEN 0x07ff 75 76 #define ADMSW_NTXHDESC 4 77 #define ADMSW_NRXHDESC 32 78 #define ADMSW_NTXLDESC 32 79 #define ADMSW_NRXLDESC 32 80 81 #define ADMSW_NTXHDESC_MASK (ADMSW_NTXHDESC - 1) 82 #define ADMSW_NRXHDESC_MASK (ADMSW_NRXHDESC - 1) 83 #define ADMSW_NTXLDESC_MASK (ADMSW_NTXLDESC - 1) 84 #define ADMSW_NRXLDESC_MASK (ADMSW_NRXLDESC - 1) 85 86 #define ADMSW_NEXTTXH(x) (((x) + 1) & ADMSW_NTXHDESC_MASK) 87 #define ADMSW_NEXTRXH(x) (((x) + 1) & ADMSW_NRXHDESC_MASK) 88 #define ADMSW_NEXTTXL(x) (((x) + 1) & ADMSW_NTXLDESC_MASK) 89 #define ADMSW_NEXTRXL(x) (((x) + 1) & ADMSW_NRXLDESC_MASK) 90 91 struct admsw_control_data { 92 /* The transmit descriptors. */ 93 struct admsw_desc acd_txhdescs[ADMSW_NTXHDESC]; 94 95 /* The receive descriptors. */ 96 struct admsw_desc acd_rxhdescs[ADMSW_NRXHDESC]; 97 98 /* The transmit descriptors. */ 99 struct admsw_desc acd_txldescs[ADMSW_NTXLDESC]; 100 101 /* The receive descriptors. */ 102 struct admsw_desc acd_rxldescs[ADMSW_NRXLDESC]; 103 }; 104 105 #define ADMSW_CDOFF(x) offsetof(struct admsw_control_data, x) 106 #define ADMSW_CDTXHOFF(x) ADMSW_CDOFF(acd_txhdescs[(x)]) 107 #define ADMSW_CDTXLOFF(x) ADMSW_CDOFF(acd_txldescs[(x)]) 108 #define ADMSW_CDRXHOFF(x) ADMSW_CDOFF(acd_rxhdescs[(x)]) 109 #define ADMSW_CDRXLOFF(x) ADMSW_CDOFF(acd_rxldescs[(x)]) 110 111 struct admsw_descsoft { 112 struct mbuf *ds_mbuf; 113 bus_dmamap_t ds_dmamap; 114 }; 115 116 /* 117 * Software state per device. 118 */ 119 struct admsw_softc { 120 device_t sc_dev; /* generic device information */ 121 uint8_t sc_enaddr[ETHER_ADDR_LEN]; 122 bus_dma_tag_t sc_dmat; /* bus DMA tag */ 123 bus_space_tag_t sc_st; /* bus space tag */ 124 bus_space_handle_t sc_ioh; /* MAC space handle */ 125 struct sysmon_wdog sc_smw; 126 struct ifmedia sc_ifmedia[SW_DEVS]; 127 int ndevs; /* number of IFF_RUNNING interfaces */ 128 struct ethercom sc_ethercom[SW_DEVS]; /* Ethernet common data */ 129 void *sc_sdhook; /* shutdown hook */ 130 void *sc_ih; /* interrupt cookie */ 131 struct admsw_descsoft sc_txhsoft[ADMSW_NTXHDESC]; 132 struct admsw_descsoft sc_rxhsoft[ADMSW_NRXHDESC]; 133 struct admsw_descsoft sc_txlsoft[ADMSW_NTXLDESC]; 134 struct admsw_descsoft sc_rxlsoft[ADMSW_NRXLDESC]; 135 bus_dmamap_t sc_cddmamap; /* control data DMA map */ 136 #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr 137 struct admsw_control_data *sc_control_data; 138 #define sc_txhdescs sc_control_data->acd_txhdescs 139 #define sc_rxhdescs sc_control_data->acd_rxhdescs 140 #define sc_txldescs sc_control_data->acd_txldescs 141 #define sc_rxldescs sc_control_data->acd_rxldescs 142 143 int sc_txfree; /* number of free Tx descriptors */ 144 int sc_txnext; /* next Tx descriptor to use */ 145 int sc_txdirty; /* first dirty Tx descriptor */ 146 147 int sc_rxptr; /* next ready Rx descriptor */ 148 149 #ifdef ADMSW_EVENT_COUNTERS 150 struct evcnt sc_ev_txstall; /* Tx stalled */ 151 struct evcnt sc_ev_rxstall; /* Rx stalled */ 152 struct evcnt sc_ev_txintr; /* Tx interrupts */ 153 struct evcnt sc_ev_rxintr; /* Rx interrupts */ 154 #if 1 155 struct evcnt sc_ev_rxsync; /* Rx syncs */ 156 #endif 157 #endif 158 159 }; 160 161 #define ADMSW_CDTXHADDR(sc, x) ((sc)->sc_cddma + ADMSW_CDTXHOFF((x))) 162 #define ADMSW_CDTXLADDR(sc, x) ((sc)->sc_cddma + ADMSW_CDTXLOFF((x))) 163 #define ADMSW_CDRXHADDR(sc, x) ((sc)->sc_cddma + ADMSW_CDRXHOFF((x))) 164 #define ADMSW_CDRXLADDR(sc, x) ((sc)->sc_cddma + ADMSW_CDRXLOFF((x))) 165 166 #define ADMSW_CDTXHSYNC(sc, x, ops) \ 167 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 168 ADMSW_CDTXHOFF((x)), sizeof(struct admsw_desc), (ops)) 169 170 #define ADMSW_CDTXLSYNC(sc, x, ops) \ 171 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 172 ADMSW_CDTXLOFF((x)), sizeof(struct admsw_desc), (ops)) 173 174 #define ADMSW_CDRXHSYNC(sc, x, ops) \ 175 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 176 ADMSW_CDRXHOFF((x)), sizeof(struct admsw_desc), (ops)) 177 178 #define ADMSW_CDRXLSYNC(sc, x, ops) \ 179 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 180 ADMSW_CDRXLOFF((x)), sizeof(struct admsw_desc), (ops)) 181 182 #define ADMSW_INIT_RXHDESC(sc, x) \ 183 do { \ 184 struct admsw_descsoft *__ds = &(sc)->sc_rxhsoft[(x)]; \ 185 struct admsw_desc *__desc = &(sc)->sc_rxhdescs[(x)]; \ 186 struct mbuf *__m = __ds->ds_mbuf; \ 187 \ 188 __m->m_data = __m->m_ext.ext_buf + 2; \ 189 __desc->data = __ds->ds_dmamap->dm_segs[0].ds_addr + 2; \ 190 __desc->cntl = 0; \ 191 __desc->len = min(MCLBYTES - 2, MAC_BUFLEN - 2); \ 192 __desc->status = 0; \ 193 if ((x) == ADMSW_NRXHDESC - 1) \ 194 __desc->data |= ADM5120_DMA_RINGEND; \ 195 __desc->data |= ADM5120_DMA_OWN; \ 196 ADMSW_CDRXHSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ 197 } while (0) 198 199 #define ADMSW_INIT_RXLDESC(sc, x) \ 200 do { \ 201 struct admsw_descsoft *__ds = &(sc)->sc_rxlsoft[(x)]; \ 202 struct admsw_desc *__desc = &(sc)->sc_rxldescs[(x)]; \ 203 struct mbuf *__m = __ds->ds_mbuf; \ 204 \ 205 __m->m_data = __m->m_ext.ext_buf + 2; \ 206 __desc->data = __ds->ds_dmamap->dm_segs[0].ds_addr + 2; \ 207 __desc->cntl = 0; \ 208 __desc->len = min(MCLBYTES - 2, MAC_BUFLEN - 2); \ 209 __desc->status = 0; \ 210 if ((x) == ADMSW_NRXLDESC - 1) \ 211 __desc->data |= ADM5120_DMA_RINGEND; \ 212 __desc->data |= ADM5120_DMA_OWN; \ 213 ADMSW_CDRXLSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ 214 } while (0) 215 216 void admwdog_attach(struct admsw_softc *); 217 218 #endif /* _IF_ADMSWVAR_H_ */ 219