1 1.66 riastrad /* $NetBSD: if_ste.c,v 1.66 2024/06/29 12:11:12 riastradh Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /*- 4 1.1 thorpej * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.1 thorpej * by Jason R. Thorpe. 9 1.1 thorpej * 10 1.1 thorpej * Redistribution and use in source and binary forms, with or without 11 1.1 thorpej * modification, are permitted provided that the following conditions 12 1.1 thorpej * are met: 13 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.1 thorpej * notice, this list of conditions and the following disclaimer. 15 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.1 thorpej * documentation and/or other materials provided with the distribution. 18 1.1 thorpej * 19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.1 thorpej /* 33 1.1 thorpej * Device driver for the Sundance Tech. ST-201 10/100 34 1.1 thorpej * Ethernet controller. 35 1.1 thorpej */ 36 1.7 lukem 37 1.7 lukem #include <sys/cdefs.h> 38 1.66 riastrad __KERNEL_RCSID(0, "$NetBSD: if_ste.c,v 1.66 2024/06/29 12:11:12 riastradh Exp $"); 39 1.1 thorpej 40 1.1 thorpej 41 1.1 thorpej #include <sys/param.h> 42 1.1 thorpej #include <sys/systm.h> 43 1.1 thorpej #include <sys/callout.h> 44 1.1 thorpej #include <sys/mbuf.h> 45 1.1 thorpej #include <sys/kernel.h> 46 1.1 thorpej #include <sys/socket.h> 47 1.1 thorpej #include <sys/ioctl.h> 48 1.1 thorpej #include <sys/errno.h> 49 1.1 thorpej #include <sys/device.h> 50 1.1 thorpej #include <sys/queue.h> 51 1.1 thorpej 52 1.1 thorpej #include <net/if.h> 53 1.1 thorpej #include <net/if_dl.h> 54 1.1 thorpej #include <net/if_media.h> 55 1.1 thorpej #include <net/if_ether.h> 56 1.1 thorpej 57 1.1 thorpej #include <net/bpf.h> 58 1.1 thorpej 59 1.31 ad #include <sys/bus.h> 60 1.31 ad #include <sys/intr.h> 61 1.1 thorpej 62 1.1 thorpej #include <dev/mii/mii.h> 63 1.1 thorpej #include <dev/mii/miivar.h> 64 1.1 thorpej #include <dev/mii/mii_bitbang.h> 65 1.1 thorpej 66 1.1 thorpej #include <dev/pci/pcireg.h> 67 1.1 thorpej #include <dev/pci/pcivar.h> 68 1.1 thorpej #include <dev/pci/pcidevs.h> 69 1.1 thorpej 70 1.1 thorpej #include <dev/pci/if_stereg.h> 71 1.1 thorpej 72 1.1 thorpej /* 73 1.1 thorpej * Transmit descriptor list size. 74 1.1 thorpej */ 75 1.1 thorpej #define STE_NTXDESC 256 76 1.1 thorpej #define STE_NTXDESC_MASK (STE_NTXDESC - 1) 77 1.1 thorpej #define STE_NEXTTX(x) (((x) + 1) & STE_NTXDESC_MASK) 78 1.1 thorpej 79 1.1 thorpej /* 80 1.1 thorpej * Receive descriptor list size. 81 1.1 thorpej */ 82 1.1 thorpej #define STE_NRXDESC 128 83 1.1 thorpej #define STE_NRXDESC_MASK (STE_NRXDESC - 1) 84 1.1 thorpej #define STE_NEXTRX(x) (((x) + 1) & STE_NRXDESC_MASK) 85 1.1 thorpej 86 1.1 thorpej /* 87 1.1 thorpej * Control structures are DMA'd to the ST-201 chip. We allocate them in 88 1.1 thorpej * a single clump that maps to a single DMA segment to make several things 89 1.1 thorpej * easier. 90 1.1 thorpej */ 91 1.1 thorpej struct ste_control_data { 92 1.1 thorpej /* 93 1.1 thorpej * The transmit descriptors. 94 1.1 thorpej */ 95 1.1 thorpej struct ste_tfd scd_txdescs[STE_NTXDESC]; 96 1.1 thorpej 97 1.1 thorpej /* 98 1.1 thorpej * The receive descriptors. 99 1.1 thorpej */ 100 1.1 thorpej struct ste_rfd scd_rxdescs[STE_NRXDESC]; 101 1.1 thorpej }; 102 1.1 thorpej 103 1.1 thorpej #define STE_CDOFF(x) offsetof(struct ste_control_data, x) 104 1.1 thorpej #define STE_CDTXOFF(x) STE_CDOFF(scd_txdescs[(x)]) 105 1.1 thorpej #define STE_CDRXOFF(x) STE_CDOFF(scd_rxdescs[(x)]) 106 1.1 thorpej 107 1.1 thorpej /* 108 1.1 thorpej * Software state for transmit and receive jobs. 109 1.1 thorpej */ 110 1.1 thorpej struct ste_descsoft { 111 1.1 thorpej struct mbuf *ds_mbuf; /* head of our mbuf chain */ 112 1.1 thorpej bus_dmamap_t ds_dmamap; /* our DMA map */ 113 1.1 thorpej }; 114 1.1 thorpej 115 1.1 thorpej /* 116 1.1 thorpej * Software state per device. 117 1.1 thorpej */ 118 1.1 thorpej struct ste_softc { 119 1.44 chs device_t sc_dev; /* generic device information */ 120 1.1 thorpej bus_space_tag_t sc_st; /* bus space tag */ 121 1.1 thorpej bus_space_handle_t sc_sh; /* bus space handle */ 122 1.1 thorpej bus_dma_tag_t sc_dmat; /* bus DMA tag */ 123 1.1 thorpej struct ethercom sc_ethercom; /* ethernet common data */ 124 1.1 thorpej 125 1.1 thorpej void *sc_ih; /* interrupt cookie */ 126 1.1 thorpej 127 1.1 thorpej struct mii_data sc_mii; /* MII/media information */ 128 1.1 thorpej 129 1.28 ad callout_t sc_tick_ch; /* tick callout */ 130 1.1 thorpej 131 1.1 thorpej bus_dmamap_t sc_cddmamap; /* control data DMA map */ 132 1.1 thorpej #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr 133 1.1 thorpej 134 1.1 thorpej /* 135 1.1 thorpej * Software state for transmit and receive descriptors. 136 1.1 thorpej */ 137 1.1 thorpej struct ste_descsoft sc_txsoft[STE_NTXDESC]; 138 1.1 thorpej struct ste_descsoft sc_rxsoft[STE_NRXDESC]; 139 1.1 thorpej 140 1.1 thorpej /* 141 1.1 thorpej * Control data structures. 142 1.1 thorpej */ 143 1.1 thorpej struct ste_control_data *sc_control_data; 144 1.1 thorpej #define sc_txdescs sc_control_data->scd_txdescs 145 1.1 thorpej #define sc_rxdescs sc_control_data->scd_rxdescs 146 1.1 thorpej 147 1.1 thorpej int sc_txpending; /* number of Tx requests pending */ 148 1.1 thorpej int sc_txdirty; /* first dirty Tx descriptor */ 149 1.1 thorpej int sc_txlast; /* last used Tx descriptor */ 150 1.1 thorpej 151 1.1 thorpej int sc_rxptr; /* next ready Rx descriptor/descsoft */ 152 1.1 thorpej 153 1.1 thorpej int sc_txthresh; /* Tx threshold */ 154 1.1 thorpej uint32_t sc_DMACtrl; /* prototype DMACtrl register */ 155 1.1 thorpej uint16_t sc_IntEnable; /* prototype IntEnable register */ 156 1.1 thorpej uint16_t sc_MacCtrl0; /* prototype MacCtrl0 register */ 157 1.1 thorpej uint8_t sc_ReceiveMode; /* prototype ReceiveMode register */ 158 1.61 thorpej 159 1.61 thorpej bool sc_enable_phy0; /* access to phy #0 allowed */ 160 1.1 thorpej }; 161 1.1 thorpej 162 1.1 thorpej #define STE_CDTXADDR(sc, x) ((sc)->sc_cddma + STE_CDTXOFF((x))) 163 1.1 thorpej #define STE_CDRXADDR(sc, x) ((sc)->sc_cddma + STE_CDRXOFF((x))) 164 1.1 thorpej 165 1.1 thorpej #define STE_CDTXSYNC(sc, x, ops) \ 166 1.1 thorpej bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 167 1.1 thorpej STE_CDTXOFF((x)), sizeof(struct ste_tfd), (ops)) 168 1.1 thorpej 169 1.1 thorpej #define STE_CDRXSYNC(sc, x, ops) \ 170 1.1 thorpej bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ 171 1.1 thorpej STE_CDRXOFF((x)), sizeof(struct ste_rfd), (ops)) 172 1.1 thorpej 173 1.1 thorpej #define STE_INIT_RXDESC(sc, x) \ 174 1.1 thorpej do { \ 175 1.1 thorpej struct ste_descsoft *__ds = &(sc)->sc_rxsoft[(x)]; \ 176 1.1 thorpej struct ste_rfd *__rfd = &(sc)->sc_rxdescs[(x)]; \ 177 1.1 thorpej struct mbuf *__m = __ds->ds_mbuf; \ 178 1.1 thorpej \ 179 1.1 thorpej /* \ 180 1.1 thorpej * Note: We scoot the packet forward 2 bytes in the buffer \ 181 1.1 thorpej * so that the payload after the Ethernet header is aligned \ 182 1.1 thorpej * to a 4-byte boundary. \ 183 1.1 thorpej */ \ 184 1.1 thorpej __m->m_data = __m->m_ext.ext_buf + 2; \ 185 1.1 thorpej __rfd->rfd_frag.frag_addr = \ 186 1.1 thorpej htole32(__ds->ds_dmamap->dm_segs[0].ds_addr + 2); \ 187 1.1 thorpej __rfd->rfd_frag.frag_len = htole32((MCLBYTES - 2) | FRAG_LAST); \ 188 1.1 thorpej __rfd->rfd_next = htole32(STE_CDRXADDR((sc), STE_NEXTRX((x)))); \ 189 1.1 thorpej __rfd->rfd_status = 0; \ 190 1.54 msaitoh STE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \ 191 1.1 thorpej } while (/*CONSTCOND*/0) 192 1.1 thorpej 193 1.1 thorpej #define STE_TIMEOUT 1000 194 1.1 thorpej 195 1.19 thorpej static void ste_start(struct ifnet *); 196 1.19 thorpej static void ste_watchdog(struct ifnet *); 197 1.27 christos static int ste_ioctl(struct ifnet *, u_long, void *); 198 1.19 thorpej static int ste_init(struct ifnet *); 199 1.19 thorpej static void ste_stop(struct ifnet *, int); 200 1.19 thorpej 201 1.38 tsutsui static bool ste_shutdown(device_t, int); 202 1.19 thorpej 203 1.54 msaitoh static void ste_reset(struct ste_softc *, uint32_t); 204 1.19 thorpej static void ste_setthresh(struct ste_softc *); 205 1.54 msaitoh static void ste_txrestart(struct ste_softc *, uint8_t); 206 1.19 thorpej static void ste_rxdrain(struct ste_softc *); 207 1.19 thorpej static int ste_add_rxbuf(struct ste_softc *, int); 208 1.19 thorpej static void ste_read_eeprom(struct ste_softc *, int, uint16_t *); 209 1.19 thorpej static void ste_tick(void *); 210 1.19 thorpej 211 1.19 thorpej static void ste_stats_update(struct ste_softc *); 212 1.19 thorpej 213 1.19 thorpej static void ste_set_filter(struct ste_softc *); 214 1.19 thorpej 215 1.19 thorpej static int ste_intr(void *); 216 1.19 thorpej static void ste_txintr(struct ste_softc *); 217 1.19 thorpej static void ste_rxintr(struct ste_softc *); 218 1.19 thorpej 219 1.53 msaitoh static int ste_mii_readreg(device_t, int, int, uint16_t *); 220 1.53 msaitoh static int ste_mii_writereg(device_t, int, int, uint16_t); 221 1.43 matt static void ste_mii_statchg(struct ifnet *); 222 1.1 thorpej 223 1.37 cegger static int ste_match(device_t, cfdata_t, void *); 224 1.34 dyoung static void ste_attach(device_t, device_t, void *); 225 1.1 thorpej 226 1.1 thorpej int ste_copy_small = 0; 227 1.1 thorpej 228 1.44 chs CFATTACH_DECL_NEW(ste, sizeof(struct ste_softc), 229 1.14 thorpej ste_match, ste_attach, NULL, NULL); 230 1.1 thorpej 231 1.34 dyoung static uint32_t ste_mii_bitbang_read(device_t); 232 1.34 dyoung static void ste_mii_bitbang_write(device_t, uint32_t); 233 1.1 thorpej 234 1.19 thorpej static const struct mii_bitbang_ops ste_mii_bitbang_ops = { 235 1.1 thorpej ste_mii_bitbang_read, 236 1.1 thorpej ste_mii_bitbang_write, 237 1.1 thorpej { 238 1.1 thorpej PC_MgmtData, /* MII_BIT_MDO */ 239 1.1 thorpej PC_MgmtData, /* MII_BIT_MDI */ 240 1.1 thorpej PC_MgmtClk, /* MII_BIT_MDC */ 241 1.1 thorpej PC_MgmtDir, /* MII_BIT_DIR_HOST_PHY */ 242 1.1 thorpej 0, /* MII_BIT_DIR_PHY_HOST */ 243 1.1 thorpej } 244 1.1 thorpej }; 245 1.1 thorpej 246 1.1 thorpej /* 247 1.1 thorpej * Devices supported by this driver. 248 1.1 thorpej */ 249 1.61 thorpej struct ste_product { 250 1.1 thorpej pci_vendor_id_t ste_vendor; 251 1.1 thorpej pci_product_id_t ste_product; 252 1.1 thorpej const char *ste_name; 253 1.61 thorpej const struct ste_product *ste_subs; 254 1.61 thorpej }; 255 1.61 thorpej 256 1.61 thorpej static const struct ste_product ste_dlink_products[] = { 257 1.61 thorpej { PCI_VENDOR_DLINK, 0x1002, 258 1.61 thorpej "D-Link DFE-550TX 10/100 Ethernet", 259 1.61 thorpej NULL }, 260 1.61 thorpej 261 1.61 thorpej { PCI_VENDOR_DLINK, 0x1003, 262 1.61 thorpej "D-Link DFE-550FX Ethernet", 263 1.61 thorpej NULL }, 264 1.61 thorpej 265 1.61 thorpej { PCI_VENDOR_DLINK, 0x1012, 266 1.61 thorpej "D-Link DFE-580TX 4-port 10/100 Ethernet", 267 1.61 thorpej NULL }, 268 1.61 thorpej 269 1.61 thorpej { PCI_VENDOR_DLINK, 0x1040, 270 1.61 thorpej "D-Link DFE-530TXS 10/100 Ethernet", 271 1.61 thorpej NULL }, 272 1.61 thorpej 273 1.61 thorpej { 0, 0, 274 1.61 thorpej NULL, 275 1.61 thorpej NULL }, 276 1.61 thorpej }; 277 1.61 thorpej 278 1.61 thorpej static const struct ste_product ste_products[] = { 279 1.55 msaitoh { PCI_VENDOR_SUNDANCETI, PCI_PRODUCT_SUNDANCETI_IP100A, 280 1.61 thorpej "IC Plus Corp. IP00A 10/100 Fast Ethernet Adapter", 281 1.61 thorpej NULL }, 282 1.30 xtraeme 283 1.1 thorpej { PCI_VENDOR_SUNDANCETI, PCI_PRODUCT_SUNDANCETI_ST201, 284 1.61 thorpej "Sundance ST-201 10/100 Ethernet", 285 1.61 thorpej NULL }, 286 1.1 thorpej 287 1.3 thorpej { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DL1002, 288 1.61 thorpej "D-Link DL-1002 10/100 Ethernet", 289 1.61 thorpej ste_dlink_products }, 290 1.1 thorpej 291 1.1 thorpej { 0, 0, 292 1.61 thorpej NULL, 293 1.1 thorpej NULL }, 294 1.1 thorpej }; 295 1.1 thorpej 296 1.1 thorpej static const struct ste_product * 297 1.61 thorpej ste_lookup_table(pcireg_t pci_id, const struct ste_product * const products) 298 1.1 thorpej { 299 1.1 thorpej const struct ste_product *sp; 300 1.1 thorpej 301 1.61 thorpej for (sp = products; sp->ste_name != NULL; sp++) { 302 1.61 thorpej if (PCI_VENDOR(pci_id) == sp->ste_vendor && 303 1.61 thorpej PCI_PRODUCT(pci_id) == sp->ste_product) 304 1.1 thorpej return (sp); 305 1.1 thorpej } 306 1.1 thorpej return (NULL); 307 1.1 thorpej } 308 1.1 thorpej 309 1.61 thorpej static const struct ste_product * 310 1.61 thorpej ste_lookup(const struct pci_attach_args *pa) 311 1.61 thorpej { 312 1.61 thorpej const struct ste_product *sp; 313 1.61 thorpej 314 1.61 thorpej sp = ste_lookup_table(pa->pa_id, ste_products); 315 1.61 thorpej if (sp && sp->ste_subs) { 316 1.61 thorpej const pcireg_t subsys = 317 1.61 thorpej pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 318 1.61 thorpej const struct ste_product *ssp = 319 1.61 thorpej ste_lookup_table(subsys, sp->ste_subs); 320 1.61 thorpej if (ssp) 321 1.61 thorpej sp = ssp; 322 1.61 thorpej } 323 1.61 thorpej return (sp); 324 1.61 thorpej } 325 1.61 thorpej 326 1.19 thorpej static int 327 1.37 cegger ste_match(device_t parent, cfdata_t cf, void *aux) 328 1.1 thorpej { 329 1.1 thorpej struct pci_attach_args *pa = aux; 330 1.1 thorpej 331 1.1 thorpej if (ste_lookup(pa) != NULL) 332 1.1 thorpej return (1); 333 1.1 thorpej 334 1.1 thorpej return (0); 335 1.1 thorpej } 336 1.1 thorpej 337 1.19 thorpej static void 338 1.34 dyoung ste_attach(device_t parent, device_t self, void *aux) 339 1.1 thorpej { 340 1.34 dyoung struct ste_softc *sc = device_private(self); 341 1.1 thorpej struct pci_attach_args *pa = aux; 342 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 343 1.54 msaitoh struct mii_data * const mii = &sc->sc_mii; 344 1.1 thorpej pci_chipset_tag_t pc = pa->pa_pc; 345 1.1 thorpej pci_intr_handle_t ih; 346 1.1 thorpej const char *intrstr = NULL; 347 1.1 thorpej bus_space_tag_t iot, memt; 348 1.1 thorpej bus_space_handle_t ioh, memh; 349 1.1 thorpej bus_dma_segment_t seg; 350 1.1 thorpej int ioh_valid, memh_valid; 351 1.1 thorpej int i, rseg, error; 352 1.1 thorpej const struct ste_product *sp; 353 1.1 thorpej uint8_t enaddr[ETHER_ADDR_LEN]; 354 1.1 thorpej uint16_t myea[ETHER_ADDR_LEN / 2]; 355 1.45 christos char intrbuf[PCI_INTRSTR_LEN]; 356 1.1 thorpej 357 1.44 chs sc->sc_dev = self; 358 1.44 chs 359 1.28 ad callout_init(&sc->sc_tick_ch, 0); 360 1.60 thorpej callout_setfunc(&sc->sc_tick_ch, ste_tick, sc); 361 1.1 thorpej 362 1.1 thorpej sp = ste_lookup(pa); 363 1.1 thorpej if (sp == NULL) { 364 1.1 thorpej printf("\n"); 365 1.1 thorpej panic("ste_attach: impossible"); 366 1.1 thorpej } 367 1.1 thorpej 368 1.1 thorpej printf(": %s\n", sp->ste_name); 369 1.1 thorpej 370 1.1 thorpej /* 371 1.1 thorpej * Map the device. 372 1.1 thorpej */ 373 1.1 thorpej ioh_valid = (pci_mapreg_map(pa, STE_PCI_IOBA, 374 1.1 thorpej PCI_MAPREG_TYPE_IO, 0, 375 1.1 thorpej &iot, &ioh, NULL, NULL) == 0); 376 1.1 thorpej memh_valid = (pci_mapreg_map(pa, STE_PCI_MMBA, 377 1.54 msaitoh PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, 378 1.1 thorpej &memt, &memh, NULL, NULL) == 0); 379 1.1 thorpej 380 1.1 thorpej if (memh_valid) { 381 1.1 thorpej sc->sc_st = memt; 382 1.1 thorpej sc->sc_sh = memh; 383 1.1 thorpej } else if (ioh_valid) { 384 1.1 thorpej sc->sc_st = iot; 385 1.1 thorpej sc->sc_sh = ioh; 386 1.1 thorpej } else { 387 1.44 chs aprint_error_dev(self, "unable to map device registers\n"); 388 1.1 thorpej return; 389 1.1 thorpej } 390 1.1 thorpej 391 1.1 thorpej sc->sc_dmat = pa->pa_dmat; 392 1.1 thorpej 393 1.1 thorpej /* Enable bus mastering. */ 394 1.1 thorpej pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 395 1.1 thorpej pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | 396 1.1 thorpej PCI_COMMAND_MASTER_ENABLE); 397 1.1 thorpej 398 1.23 christos /* power up chip */ 399 1.34 dyoung if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, 400 1.23 christos NULL)) && error != EOPNOTSUPP) { 401 1.48 msaitoh aprint_error_dev(sc->sc_dev, "cannot activate %d\n", error); 402 1.23 christos return; 403 1.1 thorpej } 404 1.1 thorpej 405 1.1 thorpej /* 406 1.1 thorpej * Map and establish our interrupt. 407 1.1 thorpej */ 408 1.1 thorpej if (pci_intr_map(pa, &ih)) { 409 1.44 chs aprint_error_dev(sc->sc_dev, "unable to map interrupt\n"); 410 1.1 thorpej return; 411 1.1 thorpej } 412 1.45 christos intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 413 1.52 jdolecek sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_NET, ste_intr, sc, 414 1.52 jdolecek device_xname(self)); 415 1.1 thorpej if (sc->sc_ih == NULL) { 416 1.44 chs aprint_error_dev(sc->sc_dev, "unable to establish interrupt"); 417 1.1 thorpej if (intrstr != NULL) 418 1.39 njoly aprint_error(" at %s", intrstr); 419 1.39 njoly aprint_error("\n"); 420 1.1 thorpej return; 421 1.1 thorpej } 422 1.44 chs aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); 423 1.1 thorpej 424 1.1 thorpej /* 425 1.1 thorpej * Allocate the control data structures, and create and load the 426 1.1 thorpej * DMA map for it. 427 1.1 thorpej */ 428 1.1 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat, 429 1.1 thorpej sizeof(struct ste_control_data), PAGE_SIZE, 0, &seg, 1, &rseg, 430 1.1 thorpej 0)) != 0) { 431 1.48 msaitoh aprint_error_dev(sc->sc_dev, 432 1.48 msaitoh "unable to allocate control data, error = %d\n", error); 433 1.1 thorpej goto fail_0; 434 1.1 thorpej } 435 1.1 thorpej 436 1.1 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 437 1.27 christos sizeof(struct ste_control_data), (void **)&sc->sc_control_data, 438 1.1 thorpej BUS_DMA_COHERENT)) != 0) { 439 1.48 msaitoh aprint_error_dev(sc->sc_dev, 440 1.48 msaitoh "unable to map control data, error = %d\n", error); 441 1.1 thorpej goto fail_1; 442 1.1 thorpej } 443 1.1 thorpej 444 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, 445 1.1 thorpej sizeof(struct ste_control_data), 1, 446 1.1 thorpej sizeof(struct ste_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { 447 1.48 msaitoh aprint_error_dev(sc->sc_dev, 448 1.48 msaitoh "unable to create control data DMA map, error = %d\n", 449 1.48 msaitoh error); 450 1.1 thorpej goto fail_2; 451 1.1 thorpej } 452 1.1 thorpej 453 1.1 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, 454 1.1 thorpej sc->sc_control_data, sizeof(struct ste_control_data), NULL, 455 1.1 thorpej 0)) != 0) { 456 1.48 msaitoh aprint_error_dev(sc->sc_dev, 457 1.48 msaitoh "unable to load control data DMA map, error = %d\n", 458 1.35 cegger error); 459 1.1 thorpej goto fail_3; 460 1.1 thorpej } 461 1.1 thorpej 462 1.1 thorpej /* 463 1.1 thorpej * Create the transmit buffer DMA maps. 464 1.1 thorpej */ 465 1.1 thorpej for (i = 0; i < STE_NTXDESC; i++) { 466 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 467 1.1 thorpej STE_NTXFRAGS, MCLBYTES, 0, 0, 468 1.1 thorpej &sc->sc_txsoft[i].ds_dmamap)) != 0) { 469 1.48 msaitoh aprint_error_dev(sc->sc_dev, 470 1.48 msaitoh "unable to create tx DMA map %d, error = %d\n", i, 471 1.48 msaitoh error); 472 1.1 thorpej goto fail_4; 473 1.1 thorpej } 474 1.1 thorpej } 475 1.1 thorpej 476 1.1 thorpej /* 477 1.1 thorpej * Create the receive buffer DMA maps. 478 1.1 thorpej */ 479 1.1 thorpej for (i = 0; i < STE_NRXDESC; i++) { 480 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 481 1.1 thorpej MCLBYTES, 0, 0, &sc->sc_rxsoft[i].ds_dmamap)) != 0) { 482 1.48 msaitoh aprint_error_dev(sc->sc_dev, 483 1.48 msaitoh "unable to create rx DMA map %d, error = %d\n", i, 484 1.48 msaitoh error); 485 1.1 thorpej goto fail_5; 486 1.1 thorpej } 487 1.1 thorpej sc->sc_rxsoft[i].ds_mbuf = NULL; 488 1.1 thorpej } 489 1.1 thorpej 490 1.1 thorpej /* 491 1.1 thorpej * Reset the chip to a known state. 492 1.1 thorpej */ 493 1.10 bouyer ste_reset(sc, AC_GlobalReset | AC_RxReset | AC_TxReset | AC_DMA | 494 1.10 bouyer AC_FIFO | AC_Network | AC_Host | AC_AutoInit | AC_RstOut); 495 1.1 thorpej 496 1.1 thorpej /* 497 1.1 thorpej * Read the Ethernet address from the EEPROM. 498 1.1 thorpej */ 499 1.1 thorpej for (i = 0; i < 3; i++) { 500 1.1 thorpej ste_read_eeprom(sc, STE_EEPROM_StationAddress0 + i, &myea[i]); 501 1.1 thorpej myea[i] = le16toh(myea[i]); 502 1.1 thorpej } 503 1.1 thorpej memcpy(enaddr, myea, sizeof(enaddr)); 504 1.1 thorpej 505 1.44 chs printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), 506 1.1 thorpej ether_sprintf(enaddr)); 507 1.1 thorpej 508 1.1 thorpej /* 509 1.1 thorpej * Initialize our media structures and probe the MII. 510 1.1 thorpej */ 511 1.54 msaitoh mii->mii_ifp = ifp; 512 1.54 msaitoh mii->mii_readreg = ste_mii_readreg; 513 1.54 msaitoh mii->mii_writereg = ste_mii_writereg; 514 1.54 msaitoh mii->mii_statchg = ste_mii_statchg; 515 1.54 msaitoh sc->sc_ethercom.ec_mii = mii; 516 1.54 msaitoh ifmedia_init(&mii->mii_media, IFM_IMASK, ether_mediachange, 517 1.32 dyoung ether_mediastatus); 518 1.54 msaitoh mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, 519 1.1 thorpej MII_OFFSET_ANY, 0); 520 1.54 msaitoh if (LIST_FIRST(&mii->mii_phys) == NULL) { 521 1.61 thorpej /* 522 1.61 thorpej * It seems that some variants of this chip "ghost" the 523 1.61 thorpej * single PHY at #0 and #1. We will try probing the MII 524 1.61 thorpej * first while ignoring #0 access. If we find the PHY, 525 1.61 thorpej * great! If not, un-ignore #0 and try probing *just* 526 1.61 thorpej * #0 to see if we can find it. 527 1.61 thorpej */ 528 1.61 thorpej sc->sc_enable_phy0 = true; 529 1.61 thorpej mii_attach(sc->sc_dev, mii, 0xffffffff, 0, 530 1.61 thorpej MII_OFFSET_ANY, 0); 531 1.61 thorpej } 532 1.61 thorpej if (LIST_FIRST(&mii->mii_phys) == NULL) { 533 1.54 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 534 1.54 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 535 1.1 thorpej } else 536 1.54 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 537 1.1 thorpej 538 1.1 thorpej ifp = &sc->sc_ethercom.ec_if; 539 1.44 chs strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 540 1.1 thorpej ifp->if_softc = sc; 541 1.1 thorpej ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 542 1.1 thorpej ifp->if_ioctl = ste_ioctl; 543 1.1 thorpej ifp->if_start = ste_start; 544 1.1 thorpej ifp->if_watchdog = ste_watchdog; 545 1.1 thorpej ifp->if_init = ste_init; 546 1.1 thorpej ifp->if_stop = ste_stop; 547 1.1 thorpej IFQ_SET_READY(&ifp->if_snd); 548 1.1 thorpej 549 1.1 thorpej /* 550 1.10 bouyer * Default the transmit threshold to 128 bytes. 551 1.1 thorpej */ 552 1.10 bouyer sc->sc_txthresh = 128; 553 1.1 thorpej 554 1.1 thorpej /* 555 1.1 thorpej * Disable MWI if the PCI layer tells us to. 556 1.1 thorpej */ 557 1.1 thorpej sc->sc_DMACtrl = 0; 558 1.1 thorpej if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0) 559 1.1 thorpej sc->sc_DMACtrl |= DC_MWIDisable; 560 1.1 thorpej 561 1.1 thorpej /* 562 1.1 thorpej * We can support 802.1Q VLAN-sized frames. 563 1.1 thorpej */ 564 1.1 thorpej sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 565 1.1 thorpej 566 1.1 thorpej /* 567 1.1 thorpej * Attach the interface. 568 1.1 thorpej */ 569 1.1 thorpej if_attach(ifp); 570 1.49 ozaki if_deferred_start_init(ifp, NULL); 571 1.1 thorpej ether_ifattach(ifp, enaddr); 572 1.1 thorpej 573 1.1 thorpej /* 574 1.1 thorpej * Make sure the interface is shutdown during reboot. 575 1.1 thorpej */ 576 1.38 tsutsui if (pmf_device_register1(self, NULL, NULL, ste_shutdown)) 577 1.38 tsutsui pmf_class_network_register(self, ifp); 578 1.38 tsutsui else 579 1.38 tsutsui aprint_error_dev(self, "couldn't establish power handler\n"); 580 1.38 tsutsui 581 1.1 thorpej return; 582 1.1 thorpej 583 1.1 thorpej /* 584 1.1 thorpej * Free any resources we've allocated during the failed attach 585 1.1 thorpej * attempt. Do this in reverse order and fall through. 586 1.1 thorpej */ 587 1.1 thorpej fail_5: 588 1.1 thorpej for (i = 0; i < STE_NRXDESC; i++) { 589 1.1 thorpej if (sc->sc_rxsoft[i].ds_dmamap != NULL) 590 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, 591 1.1 thorpej sc->sc_rxsoft[i].ds_dmamap); 592 1.1 thorpej } 593 1.1 thorpej fail_4: 594 1.1 thorpej for (i = 0; i < STE_NTXDESC; i++) { 595 1.1 thorpej if (sc->sc_txsoft[i].ds_dmamap != NULL) 596 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, 597 1.1 thorpej sc->sc_txsoft[i].ds_dmamap); 598 1.1 thorpej } 599 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); 600 1.1 thorpej fail_3: 601 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); 602 1.1 thorpej fail_2: 603 1.27 christos bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, 604 1.1 thorpej sizeof(struct ste_control_data)); 605 1.1 thorpej fail_1: 606 1.1 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg); 607 1.1 thorpej fail_0: 608 1.1 thorpej return; 609 1.1 thorpej } 610 1.1 thorpej 611 1.1 thorpej /* 612 1.1 thorpej * ste_shutdown: 613 1.1 thorpej * 614 1.1 thorpej * Make sure the interface is stopped at reboot time. 615 1.1 thorpej */ 616 1.38 tsutsui static bool 617 1.38 tsutsui ste_shutdown(device_t self, int howto) 618 1.1 thorpej { 619 1.38 tsutsui struct ste_softc *sc; 620 1.1 thorpej 621 1.38 tsutsui sc = device_private(self); 622 1.1 thorpej ste_stop(&sc->sc_ethercom.ec_if, 1); 623 1.38 tsutsui 624 1.38 tsutsui return true; 625 1.1 thorpej } 626 1.1 thorpej 627 1.1 thorpej static void 628 1.1 thorpej ste_dmahalt_wait(struct ste_softc *sc) 629 1.1 thorpej { 630 1.1 thorpej int i; 631 1.1 thorpej 632 1.1 thorpej for (i = 0; i < STE_TIMEOUT; i++) { 633 1.1 thorpej delay(2); 634 1.1 thorpej if ((bus_space_read_4(sc->sc_st, sc->sc_sh, STE_DMACtrl) & 635 1.1 thorpej DC_DMAHaltBusy) == 0) 636 1.1 thorpej break; 637 1.1 thorpej } 638 1.1 thorpej 639 1.1 thorpej if (i == STE_TIMEOUT) 640 1.44 chs printf("%s: DMA halt timed out\n", device_xname(sc->sc_dev)); 641 1.1 thorpej } 642 1.1 thorpej 643 1.1 thorpej /* 644 1.1 thorpej * ste_start: [ifnet interface function] 645 1.1 thorpej * 646 1.1 thorpej * Start packet transmission on the interface. 647 1.1 thorpej */ 648 1.19 thorpej static void 649 1.1 thorpej ste_start(struct ifnet *ifp) 650 1.1 thorpej { 651 1.1 thorpej struct ste_softc *sc = ifp->if_softc; 652 1.1 thorpej struct mbuf *m0, *m; 653 1.1 thorpej struct ste_descsoft *ds; 654 1.1 thorpej struct ste_tfd *tfd; 655 1.1 thorpej bus_dmamap_t dmamap; 656 1.1 thorpej int error, olasttx, nexttx, opending, seg, totlen; 657 1.1 thorpej 658 1.62 thorpej if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) 659 1.1 thorpej return; 660 1.1 thorpej 661 1.1 thorpej /* 662 1.1 thorpej * Remember the previous number of pending transmissions 663 1.1 thorpej * and the current last descriptor in the list. 664 1.1 thorpej */ 665 1.1 thorpej opending = sc->sc_txpending; 666 1.1 thorpej olasttx = sc->sc_txlast; 667 1.1 thorpej 668 1.1 thorpej /* 669 1.1 thorpej * Loop through the send queue, setting up transmit descriptors 670 1.1 thorpej * until we drain the queue, or use up all available transmit 671 1.1 thorpej * descriptors. 672 1.1 thorpej */ 673 1.1 thorpej while (sc->sc_txpending < STE_NTXDESC) { 674 1.1 thorpej /* 675 1.1 thorpej * Grab a packet off the queue. 676 1.1 thorpej */ 677 1.1 thorpej IFQ_POLL(&ifp->if_snd, m0); 678 1.1 thorpej if (m0 == NULL) 679 1.1 thorpej break; 680 1.1 thorpej m = NULL; 681 1.1 thorpej 682 1.1 thorpej /* 683 1.1 thorpej * Get the last and next available transmit descriptor. 684 1.1 thorpej */ 685 1.1 thorpej nexttx = STE_NEXTTX(sc->sc_txlast); 686 1.1 thorpej tfd = &sc->sc_txdescs[nexttx]; 687 1.1 thorpej ds = &sc->sc_txsoft[nexttx]; 688 1.1 thorpej 689 1.1 thorpej dmamap = ds->ds_dmamap; 690 1.1 thorpej 691 1.1 thorpej /* 692 1.1 thorpej * Load the DMA map. If this fails, the packet either 693 1.65 andvar * didn't fit in the allotted number of segments, or we 694 1.1 thorpej * were short on resources. In this case, we'll copy 695 1.1 thorpej * and try again. 696 1.1 thorpej */ 697 1.1 thorpej if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, 698 1.54 msaitoh BUS_DMA_WRITE | BUS_DMA_NOWAIT) != 0) { 699 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 700 1.1 thorpej if (m == NULL) { 701 1.1 thorpej printf("%s: unable to allocate Tx mbuf\n", 702 1.44 chs device_xname(sc->sc_dev)); 703 1.1 thorpej break; 704 1.1 thorpej } 705 1.61 thorpej MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); 706 1.1 thorpej if (m0->m_pkthdr.len > MHLEN) { 707 1.1 thorpej MCLGET(m, M_DONTWAIT); 708 1.1 thorpej if ((m->m_flags & M_EXT) == 0) { 709 1.1 thorpej printf("%s: unable to allocate Tx " 710 1.48 msaitoh "cluster\n", 711 1.48 msaitoh device_xname(sc->sc_dev)); 712 1.1 thorpej m_freem(m); 713 1.1 thorpej break; 714 1.1 thorpej } 715 1.1 thorpej } 716 1.27 christos m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); 717 1.1 thorpej m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; 718 1.1 thorpej error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, 719 1.54 msaitoh m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); 720 1.1 thorpej if (error) { 721 1.1 thorpej printf("%s: unable to load Tx buffer, " 722 1.48 msaitoh "error = %d\n", device_xname(sc->sc_dev), 723 1.48 msaitoh error); 724 1.63 thorpej m_freem(m); 725 1.1 thorpej break; 726 1.1 thorpej } 727 1.1 thorpej } 728 1.1 thorpej 729 1.1 thorpej IFQ_DEQUEUE(&ifp->if_snd, m0); 730 1.1 thorpej if (m != NULL) { 731 1.1 thorpej m_freem(m0); 732 1.1 thorpej m0 = m; 733 1.1 thorpej } 734 1.1 thorpej 735 1.1 thorpej /* 736 1.1 thorpej * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. 737 1.1 thorpej */ 738 1.1 thorpej 739 1.1 thorpej /* Sync the DMA map. */ 740 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, 741 1.1 thorpej BUS_DMASYNC_PREWRITE); 742 1.1 thorpej 743 1.1 thorpej /* Initialize the fragment list. */ 744 1.1 thorpej for (totlen = 0, seg = 0; seg < dmamap->dm_nsegs; seg++) { 745 1.1 thorpej tfd->tfd_frags[seg].frag_addr = 746 1.1 thorpej htole32(dmamap->dm_segs[seg].ds_addr); 747 1.1 thorpej tfd->tfd_frags[seg].frag_len = 748 1.1 thorpej htole32(dmamap->dm_segs[seg].ds_len); 749 1.1 thorpej totlen += dmamap->dm_segs[seg].ds_len; 750 1.1 thorpej } 751 1.1 thorpej tfd->tfd_frags[seg - 1].frag_len |= htole32(FRAG_LAST); 752 1.1 thorpej 753 1.1 thorpej /* Initialize the descriptor. */ 754 1.1 thorpej tfd->tfd_next = htole32(STE_CDTXADDR(sc, nexttx)); 755 1.1 thorpej tfd->tfd_control = htole32(TFD_FrameId(nexttx) | (totlen & 3)); 756 1.1 thorpej 757 1.1 thorpej /* Sync the descriptor. */ 758 1.1 thorpej STE_CDTXSYNC(sc, nexttx, 759 1.54 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 760 1.1 thorpej 761 1.1 thorpej /* 762 1.1 thorpej * Store a pointer to the packet so we can free it later, 763 1.1 thorpej * and remember what txdirty will be once the packet is 764 1.1 thorpej * done. 765 1.1 thorpej */ 766 1.1 thorpej ds->ds_mbuf = m0; 767 1.1 thorpej 768 1.1 thorpej /* Advance the tx pointer. */ 769 1.1 thorpej sc->sc_txpending++; 770 1.1 thorpej sc->sc_txlast = nexttx; 771 1.1 thorpej 772 1.1 thorpej /* 773 1.1 thorpej * Pass the packet to any BPF listeners. 774 1.1 thorpej */ 775 1.51 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 776 1.1 thorpej } 777 1.1 thorpej 778 1.1 thorpej if (sc->sc_txpending != opending) { 779 1.1 thorpej /* 780 1.1 thorpej * We enqueued packets. If the transmitter was idle, 781 1.1 thorpej * reset the txdirty pointer. 782 1.1 thorpej */ 783 1.1 thorpej if (opending == 0) 784 1.1 thorpej sc->sc_txdirty = STE_NEXTTX(olasttx); 785 1.1 thorpej 786 1.1 thorpej /* 787 1.1 thorpej * Cause a descriptor interrupt to happen on the 788 1.1 thorpej * last packet we enqueued, and also cause the 789 1.1 thorpej * DMA engine to wait after is has finished processing 790 1.1 thorpej * it. 791 1.1 thorpej */ 792 1.1 thorpej sc->sc_txdescs[sc->sc_txlast].tfd_next = 0; 793 1.1 thorpej sc->sc_txdescs[sc->sc_txlast].tfd_control |= 794 1.1 thorpej htole32(TFD_TxDMAIndicate); 795 1.1 thorpej STE_CDTXSYNC(sc, sc->sc_txlast, 796 1.54 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 797 1.1 thorpej 798 1.1 thorpej /* 799 1.1 thorpej * Link up the new chain of descriptors to the 800 1.1 thorpej * last. 801 1.1 thorpej */ 802 1.1 thorpej sc->sc_txdescs[olasttx].tfd_next = 803 1.17 tsutsui htole32(STE_CDTXADDR(sc, STE_NEXTTX(olasttx))); 804 1.1 thorpej STE_CDTXSYNC(sc, olasttx, 805 1.54 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 806 1.1 thorpej 807 1.1 thorpej /* 808 1.1 thorpej * Kick the transmit DMA logic. Note that since we're 809 1.1 thorpej * using auto-polling, reading the Tx desc pointer will 810 1.1 thorpej * give it the nudge it needs to get going. 811 1.1 thorpej */ 812 1.1 thorpej if (bus_space_read_4(sc->sc_st, sc->sc_sh, 813 1.1 thorpej STE_TxDMAListPtr) == 0) { 814 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, 815 1.1 thorpej STE_DMACtrl, DC_TxDMAHalt); 816 1.1 thorpej ste_dmahalt_wait(sc); 817 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, 818 1.1 thorpej STE_TxDMAListPtr, 819 1.1 thorpej STE_CDTXADDR(sc, STE_NEXTTX(olasttx))); 820 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, 821 1.1 thorpej STE_DMACtrl, DC_TxDMAResume); 822 1.1 thorpej } 823 1.1 thorpej 824 1.1 thorpej /* Set a watchdog timer in case the chip flakes out. */ 825 1.1 thorpej ifp->if_timer = 5; 826 1.1 thorpej } 827 1.1 thorpej } 828 1.1 thorpej 829 1.1 thorpej /* 830 1.1 thorpej * ste_watchdog: [ifnet interface function] 831 1.1 thorpej * 832 1.1 thorpej * Watchdog timer handler. 833 1.1 thorpej */ 834 1.19 thorpej static void 835 1.1 thorpej ste_watchdog(struct ifnet *ifp) 836 1.1 thorpej { 837 1.1 thorpej struct ste_softc *sc = ifp->if_softc; 838 1.1 thorpej 839 1.44 chs printf("%s: device timeout\n", device_xname(sc->sc_dev)); 840 1.59 thorpej if_statinc(ifp, if_oerrors); 841 1.1 thorpej 842 1.26 mlelstv ste_txintr(sc); 843 1.26 mlelstv ste_rxintr(sc); 844 1.1 thorpej (void) ste_init(ifp); 845 1.1 thorpej 846 1.1 thorpej /* Try to get more packets going. */ 847 1.1 thorpej ste_start(ifp); 848 1.1 thorpej } 849 1.1 thorpej 850 1.1 thorpej /* 851 1.1 thorpej * ste_ioctl: [ifnet interface function] 852 1.1 thorpej * 853 1.1 thorpej * Handle control requests from the operator. 854 1.1 thorpej */ 855 1.19 thorpej static int 856 1.27 christos ste_ioctl(struct ifnet *ifp, u_long cmd, void *data) 857 1.1 thorpej { 858 1.1 thorpej struct ste_softc *sc = ifp->if_softc; 859 1.1 thorpej int s, error; 860 1.1 thorpej 861 1.1 thorpej s = splnet(); 862 1.1 thorpej 863 1.32 dyoung error = ether_ioctl(ifp, cmd, data); 864 1.32 dyoung if (error == ENETRESET) { 865 1.32 dyoung /* 866 1.32 dyoung * Multicast list has changed; set the hardware filter 867 1.32 dyoung * accordingly. 868 1.32 dyoung */ 869 1.32 dyoung if (ifp->if_flags & IFF_RUNNING) 870 1.32 dyoung ste_set_filter(sc); 871 1.32 dyoung error = 0; 872 1.1 thorpej } 873 1.1 thorpej 874 1.1 thorpej /* Try to get more packets going. */ 875 1.1 thorpej ste_start(ifp); 876 1.1 thorpej 877 1.1 thorpej splx(s); 878 1.1 thorpej return (error); 879 1.1 thorpej } 880 1.1 thorpej 881 1.1 thorpej /* 882 1.1 thorpej * ste_intr: 883 1.1 thorpej * 884 1.1 thorpej * Interrupt service routine. 885 1.1 thorpej */ 886 1.19 thorpej static int 887 1.1 thorpej ste_intr(void *arg) 888 1.1 thorpej { 889 1.1 thorpej struct ste_softc *sc = arg; 890 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 891 1.1 thorpej uint16_t isr; 892 1.1 thorpej uint8_t txstat; 893 1.1 thorpej int wantinit; 894 1.1 thorpej 895 1.1 thorpej if ((bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatus) & 896 1.1 thorpej IS_InterruptStatus) == 0) 897 1.1 thorpej return (0); 898 1.1 thorpej 899 1.1 thorpej for (wantinit = 0; wantinit == 0;) { 900 1.1 thorpej isr = bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatusAck); 901 1.1 thorpej if ((isr & sc->sc_IntEnable) == 0) 902 1.1 thorpej break; 903 1.21 perry 904 1.1 thorpej /* Receive interrupts. */ 905 1.1 thorpej if (isr & IE_RxDMAComplete) 906 1.1 thorpej ste_rxintr(sc); 907 1.1 thorpej 908 1.1 thorpej /* Transmit interrupts. */ 909 1.54 msaitoh if (isr & (IE_TxDMAComplete | IE_TxComplete)) 910 1.1 thorpej ste_txintr(sc); 911 1.1 thorpej 912 1.1 thorpej /* Statistics overflow. */ 913 1.1 thorpej if (isr & IE_UpdateStats) 914 1.1 thorpej ste_stats_update(sc); 915 1.1 thorpej 916 1.1 thorpej /* Transmission errors. */ 917 1.1 thorpej if (isr & IE_TxComplete) { 918 1.1 thorpej for (;;) { 919 1.1 thorpej txstat = bus_space_read_1(sc->sc_st, sc->sc_sh, 920 1.1 thorpej STE_TxStatus); 921 1.1 thorpej if ((txstat & TS_TxComplete) == 0) 922 1.1 thorpej break; 923 1.1 thorpej if (txstat & TS_TxUnderrun) { 924 1.1 thorpej sc->sc_txthresh += 32; 925 1.1 thorpej if (sc->sc_txthresh > 0x1ffc) 926 1.1 thorpej sc->sc_txthresh = 0x1ffc; 927 1.1 thorpej printf("%s: transmit underrun, new " 928 1.1 thorpej "threshold: %d bytes\n", 929 1.44 chs device_xname(sc->sc_dev), 930 1.1 thorpej sc->sc_txthresh); 931 1.10 bouyer ste_reset(sc, AC_TxReset | AC_DMA | 932 1.10 bouyer AC_FIFO | AC_Network); 933 1.10 bouyer ste_setthresh(sc); 934 1.10 bouyer bus_space_write_1(sc->sc_st, sc->sc_sh, 935 1.10 bouyer STE_TxDMAPollPeriod, 127); 936 1.10 bouyer ste_txrestart(sc, 937 1.10 bouyer bus_space_read_1(sc->sc_st, 938 1.10 bouyer sc->sc_sh, STE_TxFrameId)); 939 1.1 thorpej } 940 1.10 bouyer if (txstat & TS_TxReleaseError) { 941 1.1 thorpej printf("%s: Tx FIFO release error\n", 942 1.44 chs device_xname(sc->sc_dev)); 943 1.10 bouyer wantinit = 1; 944 1.10 bouyer } 945 1.10 bouyer if (txstat & TS_MaxCollisions) { 946 1.1 thorpej printf("%s: excessive collisions\n", 947 1.44 chs device_xname(sc->sc_dev)); 948 1.10 bouyer wantinit = 1; 949 1.10 bouyer } 950 1.10 bouyer if (txstat & TS_TxStatusOverflow) { 951 1.10 bouyer printf("%s: status overflow\n", 952 1.44 chs device_xname(sc->sc_dev)); 953 1.10 bouyer wantinit = 1; 954 1.10 bouyer } 955 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, 956 1.1 thorpej STE_TxStatus, 0); 957 1.1 thorpej } 958 1.1 thorpej } 959 1.1 thorpej 960 1.1 thorpej /* Host interface errors. */ 961 1.1 thorpej if (isr & IE_HostError) { 962 1.1 thorpej printf("%s: Host interface error\n", 963 1.44 chs device_xname(sc->sc_dev)); 964 1.1 thorpej wantinit = 1; 965 1.1 thorpej } 966 1.1 thorpej } 967 1.1 thorpej 968 1.1 thorpej if (wantinit) 969 1.1 thorpej ste_init(ifp); 970 1.1 thorpej 971 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_IntEnable, 972 1.1 thorpej sc->sc_IntEnable); 973 1.1 thorpej 974 1.1 thorpej /* Try to get more packets going. */ 975 1.49 ozaki if_schedule_deferred_start(ifp); 976 1.1 thorpej 977 1.1 thorpej return (1); 978 1.1 thorpej } 979 1.1 thorpej 980 1.1 thorpej /* 981 1.1 thorpej * ste_txintr: 982 1.1 thorpej * 983 1.1 thorpej * Helper; handle transmit interrupts. 984 1.1 thorpej */ 985 1.19 thorpej static void 986 1.1 thorpej ste_txintr(struct ste_softc *sc) 987 1.1 thorpej { 988 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 989 1.1 thorpej struct ste_descsoft *ds; 990 1.1 thorpej uint32_t control; 991 1.1 thorpej int i; 992 1.1 thorpej 993 1.1 thorpej /* 994 1.1 thorpej * Go through our Tx list and free mbufs for those 995 1.1 thorpej * frames which have been transmitted. 996 1.1 thorpej */ 997 1.1 thorpej for (i = sc->sc_txdirty; sc->sc_txpending != 0; 998 1.1 thorpej i = STE_NEXTTX(i), sc->sc_txpending--) { 999 1.1 thorpej ds = &sc->sc_txsoft[i]; 1000 1.1 thorpej 1001 1.1 thorpej STE_CDTXSYNC(sc, i, 1002 1.54 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1003 1.1 thorpej 1004 1.1 thorpej control = le32toh(sc->sc_txdescs[i].tfd_control); 1005 1.1 thorpej if ((control & TFD_TxDMAComplete) == 0) 1006 1.1 thorpej break; 1007 1.1 thorpej 1008 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 1009 1.1 thorpej 0, ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 1010 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1011 1.1 thorpej m_freem(ds->ds_mbuf); 1012 1.1 thorpej ds->ds_mbuf = NULL; 1013 1.1 thorpej } 1014 1.1 thorpej 1015 1.1 thorpej /* Update the dirty transmit buffer pointer. */ 1016 1.1 thorpej sc->sc_txdirty = i; 1017 1.1 thorpej 1018 1.1 thorpej /* 1019 1.1 thorpej * If there are no more pending transmissions, cancel the watchdog 1020 1.1 thorpej * timer. 1021 1.1 thorpej */ 1022 1.1 thorpej if (sc->sc_txpending == 0) 1023 1.1 thorpej ifp->if_timer = 0; 1024 1.1 thorpej } 1025 1.1 thorpej 1026 1.1 thorpej /* 1027 1.1 thorpej * ste_rxintr: 1028 1.1 thorpej * 1029 1.1 thorpej * Helper; handle receive interrupts. 1030 1.1 thorpej */ 1031 1.19 thorpej static void 1032 1.1 thorpej ste_rxintr(struct ste_softc *sc) 1033 1.1 thorpej { 1034 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1035 1.1 thorpej struct ste_descsoft *ds; 1036 1.1 thorpej struct mbuf *m; 1037 1.1 thorpej uint32_t status; 1038 1.1 thorpej int i, len; 1039 1.1 thorpej 1040 1.1 thorpej for (i = sc->sc_rxptr;; i = STE_NEXTRX(i)) { 1041 1.1 thorpej ds = &sc->sc_rxsoft[i]; 1042 1.1 thorpej 1043 1.54 msaitoh STE_CDRXSYNC(sc, i, 1044 1.54 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1045 1.1 thorpej 1046 1.1 thorpej status = le32toh(sc->sc_rxdescs[i].rfd_status); 1047 1.1 thorpej 1048 1.1 thorpej if ((status & RFD_RxDMAComplete) == 0) 1049 1.1 thorpej break; 1050 1.1 thorpej 1051 1.1 thorpej /* 1052 1.1 thorpej * If the packet had an error, simply recycle the 1053 1.1 thorpej * buffer. Note, we count the error later in the 1054 1.1 thorpej * periodic stats update. 1055 1.1 thorpej */ 1056 1.1 thorpej if (status & RFD_RxFrameError) { 1057 1.1 thorpej STE_INIT_RXDESC(sc, i); 1058 1.1 thorpej continue; 1059 1.1 thorpej } 1060 1.1 thorpej 1061 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 1062 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 1063 1.1 thorpej 1064 1.1 thorpej /* 1065 1.1 thorpej * No errors; receive the packet. Note, we have 1066 1.1 thorpej * configured the chip to not include the CRC at 1067 1.1 thorpej * the end of the packet. 1068 1.1 thorpej */ 1069 1.1 thorpej len = RFD_RxDMAFrameLen(status); 1070 1.1 thorpej 1071 1.1 thorpej /* 1072 1.1 thorpej * If the packet is small enough to fit in a 1073 1.1 thorpej * single header mbuf, allocate one and copy 1074 1.1 thorpej * the data into it. This greatly reduces 1075 1.1 thorpej * memory consumption when we receive lots 1076 1.1 thorpej * of small packets. 1077 1.1 thorpej * 1078 1.1 thorpej * Otherwise, we add a new buffer to the receive 1079 1.1 thorpej * chain. If this fails, we drop the packet and 1080 1.1 thorpej * recycle the old buffer. 1081 1.1 thorpej */ 1082 1.2 thorpej if (ste_copy_small != 0 && len <= (MHLEN - 2)) { 1083 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 1084 1.1 thorpej if (m == NULL) 1085 1.1 thorpej goto dropit; 1086 1.61 thorpej MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 1087 1.2 thorpej m->m_data += 2; 1088 1.27 christos memcpy(mtod(m, void *), 1089 1.27 christos mtod(ds->ds_mbuf, void *), len); 1090 1.1 thorpej STE_INIT_RXDESC(sc, i); 1091 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 1092 1.1 thorpej ds->ds_dmamap->dm_mapsize, 1093 1.1 thorpej BUS_DMASYNC_PREREAD); 1094 1.1 thorpej } else { 1095 1.1 thorpej m = ds->ds_mbuf; 1096 1.1 thorpej if (ste_add_rxbuf(sc, i) != 0) { 1097 1.1 thorpej dropit: 1098 1.59 thorpej if_statinc(ifp, if_ierrors); 1099 1.1 thorpej STE_INIT_RXDESC(sc, i); 1100 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, 1101 1.1 thorpej ds->ds_dmamap, 0, 1102 1.1 thorpej ds->ds_dmamap->dm_mapsize, 1103 1.1 thorpej BUS_DMASYNC_PREREAD); 1104 1.1 thorpej continue; 1105 1.1 thorpej } 1106 1.1 thorpej } 1107 1.1 thorpej 1108 1.47 ozaki m_set_rcvif(m, ifp); 1109 1.1 thorpej m->m_pkthdr.len = m->m_len = len; 1110 1.1 thorpej 1111 1.1 thorpej /* Pass it on. */ 1112 1.46 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1113 1.1 thorpej } 1114 1.1 thorpej 1115 1.1 thorpej /* Update the receive pointer. */ 1116 1.1 thorpej sc->sc_rxptr = i; 1117 1.1 thorpej } 1118 1.1 thorpej 1119 1.1 thorpej /* 1120 1.1 thorpej * ste_tick: 1121 1.1 thorpej * 1122 1.1 thorpej * One second timer, used to tick the MII. 1123 1.1 thorpej */ 1124 1.19 thorpej static void 1125 1.1 thorpej ste_tick(void *arg) 1126 1.1 thorpej { 1127 1.1 thorpej struct ste_softc *sc = arg; 1128 1.1 thorpej int s; 1129 1.1 thorpej 1130 1.1 thorpej s = splnet(); 1131 1.1 thorpej mii_tick(&sc->sc_mii); 1132 1.1 thorpej ste_stats_update(sc); 1133 1.1 thorpej splx(s); 1134 1.1 thorpej 1135 1.60 thorpej callout_schedule(&sc->sc_tick_ch, hz); 1136 1.1 thorpej } 1137 1.1 thorpej 1138 1.1 thorpej /* 1139 1.1 thorpej * ste_stats_update: 1140 1.1 thorpej * 1141 1.1 thorpej * Read the ST-201 statistics counters. 1142 1.1 thorpej */ 1143 1.19 thorpej static void 1144 1.1 thorpej ste_stats_update(struct ste_softc *sc) 1145 1.1 thorpej { 1146 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1147 1.1 thorpej bus_space_tag_t st = sc->sc_st; 1148 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 1149 1.1 thorpej 1150 1.1 thorpej (void) bus_space_read_2(st, sh, STE_OctetsReceivedOk0); 1151 1.1 thorpej (void) bus_space_read_2(st, sh, STE_OctetsReceivedOk1); 1152 1.1 thorpej 1153 1.1 thorpej (void) bus_space_read_2(st, sh, STE_OctetsTransmittedOk0); 1154 1.1 thorpej (void) bus_space_read_2(st, sh, STE_OctetsTransmittedOk1); 1155 1.1 thorpej 1156 1.59 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 1157 1.59 thorpej 1158 1.66 riastrad if_statadd_ref(ifp, nsr, if_opackets, 1159 1.59 thorpej (u_int) bus_space_read_2(st, sh, STE_FramesTransmittedOK)); 1160 1.57 msaitoh 1161 1.58 tnn (void) bus_space_read_2(st, sh, STE_FramesReceivedOK); 1162 1.1 thorpej 1163 1.66 riastrad if_statadd_ref(ifp, nsr, if_collisions, 1164 1.1 thorpej (u_int) bus_space_read_1(st, sh, STE_LateCollisions) + 1165 1.1 thorpej (u_int) bus_space_read_1(st, sh, STE_MultipleColFrames) + 1166 1.59 thorpej (u_int) bus_space_read_1(st, sh, STE_SingleColFrames)); 1167 1.1 thorpej 1168 1.1 thorpej (void) bus_space_read_1(st, sh, STE_FramesWDeferredXmt); 1169 1.1 thorpej 1170 1.66 riastrad if_statadd_ref(ifp, nsr, if_ierrors, 1171 1.59 thorpej (u_int) bus_space_read_1(st, sh, STE_FramesLostRxErrors)); 1172 1.1 thorpej 1173 1.66 riastrad if_statadd_ref(ifp, nsr, if_oerrors, 1174 1.1 thorpej (u_int) bus_space_read_1(st, sh, STE_FramesWExDeferral) + 1175 1.11 bouyer (u_int) bus_space_read_1(st, sh, STE_FramesXbortXSColls) + 1176 1.59 thorpej bus_space_read_1(st, sh, STE_CarrierSenseErrors)); 1177 1.59 thorpej 1178 1.59 thorpej IF_STAT_PUTREF(ifp); 1179 1.1 thorpej 1180 1.1 thorpej (void) bus_space_read_1(st, sh, STE_BcstFramesXmtdOk); 1181 1.1 thorpej (void) bus_space_read_1(st, sh, STE_BcstFramesRcvdOk); 1182 1.1 thorpej (void) bus_space_read_1(st, sh, STE_McstFramesXmtdOk); 1183 1.1 thorpej (void) bus_space_read_1(st, sh, STE_McstFramesRcvdOk); 1184 1.1 thorpej } 1185 1.1 thorpej 1186 1.1 thorpej /* 1187 1.1 thorpej * ste_reset: 1188 1.1 thorpej * 1189 1.1 thorpej * Perform a soft reset on the ST-201. 1190 1.1 thorpej */ 1191 1.19 thorpej static void 1192 1.54 msaitoh ste_reset(struct ste_softc *sc, uint32_t rstbits) 1193 1.1 thorpej { 1194 1.1 thorpej uint32_t ac; 1195 1.1 thorpej int i; 1196 1.1 thorpej 1197 1.1 thorpej ac = bus_space_read_4(sc->sc_st, sc->sc_sh, STE_AsicCtrl); 1198 1.1 thorpej 1199 1.10 bouyer bus_space_write_4(sc->sc_st, sc->sc_sh, STE_AsicCtrl, ac | rstbits); 1200 1.1 thorpej 1201 1.1 thorpej delay(50000); 1202 1.1 thorpej 1203 1.1 thorpej for (i = 0; i < STE_TIMEOUT; i++) { 1204 1.5 thorpej delay(1000); 1205 1.1 thorpej if ((bus_space_read_4(sc->sc_st, sc->sc_sh, STE_AsicCtrl) & 1206 1.1 thorpej AC_ResetBusy) == 0) 1207 1.1 thorpej break; 1208 1.1 thorpej } 1209 1.1 thorpej 1210 1.1 thorpej if (i == STE_TIMEOUT) 1211 1.48 msaitoh printf("%s: reset failed to complete\n", 1212 1.48 msaitoh device_xname(sc->sc_dev)); 1213 1.1 thorpej 1214 1.1 thorpej delay(1000); 1215 1.1 thorpej } 1216 1.1 thorpej 1217 1.1 thorpej /* 1218 1.10 bouyer * ste_setthresh: 1219 1.10 bouyer * 1220 1.10 bouyer * set the various transmit threshold registers 1221 1.10 bouyer */ 1222 1.19 thorpej static void 1223 1.10 bouyer ste_setthresh(struct ste_softc *sc) 1224 1.10 bouyer { 1225 1.10 bouyer /* set the TX threhold */ 1226 1.10 bouyer bus_space_write_2(sc->sc_st, sc->sc_sh, 1227 1.10 bouyer STE_TxStartThresh, sc->sc_txthresh); 1228 1.10 bouyer /* Urgent threshold: set to sc_txthresh / 2 */ 1229 1.61 thorpej bus_space_write_1(sc->sc_st, sc->sc_sh, STE_TxDMAUrgentThresh, 1230 1.10 bouyer sc->sc_txthresh >> 6); 1231 1.10 bouyer /* Burst threshold: use default value (256 bytes) */ 1232 1.10 bouyer } 1233 1.10 bouyer 1234 1.10 bouyer /* 1235 1.10 bouyer * restart TX at the given frame ID in the transmitter ring 1236 1.10 bouyer */ 1237 1.19 thorpej static void 1238 1.54 msaitoh ste_txrestart(struct ste_softc *sc, uint8_t id) 1239 1.10 bouyer { 1240 1.54 msaitoh uint32_t control; 1241 1.10 bouyer 1242 1.54 msaitoh STE_CDTXSYNC(sc, id, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1243 1.10 bouyer control = le32toh(sc->sc_txdescs[id].tfd_control); 1244 1.10 bouyer control &= ~TFD_TxDMAComplete; 1245 1.10 bouyer sc->sc_txdescs[id].tfd_control = htole32(control); 1246 1.54 msaitoh STE_CDTXSYNC(sc, id, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1247 1.10 bouyer 1248 1.10 bouyer bus_space_write_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr, 0); 1249 1.10 bouyer bus_space_write_2(sc->sc_st, sc->sc_sh, STE_MacCtrl1, MC1_TxEnable); 1250 1.10 bouyer bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, DC_TxDMAHalt); 1251 1.10 bouyer ste_dmahalt_wait(sc); 1252 1.10 bouyer bus_space_write_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr, 1253 1.10 bouyer STE_CDTXADDR(sc, id)); 1254 1.10 bouyer bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, DC_TxDMAResume); 1255 1.10 bouyer } 1256 1.10 bouyer 1257 1.10 bouyer /* 1258 1.1 thorpej * ste_init: [ ifnet interface function ] 1259 1.1 thorpej * 1260 1.1 thorpej * Initialize the interface. Must be called at splnet(). 1261 1.1 thorpej */ 1262 1.19 thorpej static int 1263 1.1 thorpej ste_init(struct ifnet *ifp) 1264 1.1 thorpej { 1265 1.1 thorpej struct ste_softc *sc = ifp->if_softc; 1266 1.1 thorpej bus_space_tag_t st = sc->sc_st; 1267 1.1 thorpej bus_space_handle_t sh = sc->sc_sh; 1268 1.1 thorpej struct ste_descsoft *ds; 1269 1.1 thorpej int i, error = 0; 1270 1.1 thorpej 1271 1.1 thorpej /* 1272 1.1 thorpej * Cancel any pending I/O. 1273 1.1 thorpej */ 1274 1.1 thorpej ste_stop(ifp, 0); 1275 1.1 thorpej 1276 1.1 thorpej /* 1277 1.1 thorpej * Reset the chip to a known state. 1278 1.1 thorpej */ 1279 1.10 bouyer ste_reset(sc, AC_GlobalReset | AC_RxReset | AC_TxReset | AC_DMA | 1280 1.10 bouyer AC_FIFO | AC_Network | AC_Host | AC_AutoInit | AC_RstOut); 1281 1.1 thorpej 1282 1.1 thorpej /* 1283 1.1 thorpej * Initialize the transmit descriptor ring. 1284 1.1 thorpej */ 1285 1.1 thorpej memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs)); 1286 1.1 thorpej sc->sc_txpending = 0; 1287 1.1 thorpej sc->sc_txdirty = 0; 1288 1.1 thorpej sc->sc_txlast = STE_NTXDESC - 1; 1289 1.1 thorpej 1290 1.1 thorpej /* 1291 1.1 thorpej * Initialize the receive descriptor and receive job 1292 1.1 thorpej * descriptor rings. 1293 1.1 thorpej */ 1294 1.1 thorpej for (i = 0; i < STE_NRXDESC; i++) { 1295 1.1 thorpej ds = &sc->sc_rxsoft[i]; 1296 1.1 thorpej if (ds->ds_mbuf == NULL) { 1297 1.1 thorpej if ((error = ste_add_rxbuf(sc, i)) != 0) { 1298 1.1 thorpej printf("%s: unable to allocate or map rx " 1299 1.1 thorpej "buffer %d, error = %d\n", 1300 1.44 chs device_xname(sc->sc_dev), i, error); 1301 1.1 thorpej /* 1302 1.1 thorpej * XXX Should attempt to run with fewer receive 1303 1.1 thorpej * XXX buffers instead of just failing. 1304 1.1 thorpej */ 1305 1.1 thorpej ste_rxdrain(sc); 1306 1.1 thorpej goto out; 1307 1.1 thorpej } 1308 1.6 thorpej } else 1309 1.6 thorpej STE_INIT_RXDESC(sc, i); 1310 1.1 thorpej } 1311 1.1 thorpej sc->sc_rxptr = 0; 1312 1.1 thorpej 1313 1.1 thorpej /* Set the station address. */ 1314 1.1 thorpej for (i = 0; i < ETHER_ADDR_LEN; i++) 1315 1.1 thorpej bus_space_write_1(st, sh, STE_StationAddress0 + 1, 1316 1.29 dyoung CLLADDR(ifp->if_sadl)[i]); 1317 1.1 thorpej 1318 1.1 thorpej /* Set up the receive filter. */ 1319 1.1 thorpej ste_set_filter(sc); 1320 1.1 thorpej 1321 1.1 thorpej /* 1322 1.1 thorpej * Give the receive ring to the chip. 1323 1.1 thorpej */ 1324 1.1 thorpej bus_space_write_4(st, sh, STE_RxDMAListPtr, 1325 1.1 thorpej STE_CDRXADDR(sc, sc->sc_rxptr)); 1326 1.1 thorpej 1327 1.1 thorpej /* 1328 1.1 thorpej * We defer giving the transmit ring to the chip until we 1329 1.1 thorpej * transmit the first packet. 1330 1.1 thorpej */ 1331 1.1 thorpej 1332 1.1 thorpej /* 1333 1.1 thorpej * Initialize the Tx auto-poll period. It's OK to make this number 1334 1.1 thorpej * large (127 is the max) -- we explicitly kick the transmit engine 1335 1.1 thorpej * when there's actually a packet. We are using auto-polling only 1336 1.1 thorpej * to make the interface to the transmit engine not suck. 1337 1.1 thorpej */ 1338 1.1 thorpej bus_space_write_1(sc->sc_st, sc->sc_sh, STE_TxDMAPollPeriod, 127); 1339 1.1 thorpej 1340 1.1 thorpej /* ..and the Rx auto-poll period. */ 1341 1.1 thorpej bus_space_write_1(st, sh, STE_RxDMAPollPeriod, 64); 1342 1.1 thorpej 1343 1.1 thorpej /* Initialize the Tx start threshold. */ 1344 1.10 bouyer ste_setthresh(sc); 1345 1.1 thorpej 1346 1.1 thorpej /* Set the FIFO release threshold to 512 bytes. */ 1347 1.1 thorpej bus_space_write_1(st, sh, STE_TxReleaseThresh, 512 >> 4); 1348 1.1 thorpej 1349 1.18 mycroft /* Set maximum packet size for VLAN. */ 1350 1.18 mycroft if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) 1351 1.18 mycroft bus_space_write_2(st, sh, STE_MaxFrameSize, ETHER_MAX_LEN + 4); 1352 1.18 mycroft else 1353 1.18 mycroft bus_space_write_2(st, sh, STE_MaxFrameSize, ETHER_MAX_LEN); 1354 1.18 mycroft 1355 1.1 thorpej /* 1356 1.1 thorpej * Initialize the interrupt mask. 1357 1.1 thorpej */ 1358 1.1 thorpej sc->sc_IntEnable = IE_HostError | IE_TxComplete | IE_UpdateStats | 1359 1.1 thorpej IE_TxDMAComplete | IE_RxDMAComplete; 1360 1.11 bouyer 1361 1.1 thorpej bus_space_write_2(st, sh, STE_IntStatus, 0xffff); 1362 1.1 thorpej bus_space_write_2(st, sh, STE_IntEnable, sc->sc_IntEnable); 1363 1.1 thorpej 1364 1.1 thorpej /* 1365 1.1 thorpej * Start the receive DMA engine. 1366 1.1 thorpej */ 1367 1.1 thorpej bus_space_write_4(st, sh, STE_DMACtrl, sc->sc_DMACtrl | DC_RxDMAResume); 1368 1.1 thorpej 1369 1.1 thorpej /* 1370 1.1 thorpej * Initialize MacCtrl0 -- do it before setting the media, 1371 1.1 thorpej * as setting the media will actually program the register. 1372 1.1 thorpej */ 1373 1.1 thorpej sc->sc_MacCtrl0 = MC0_IFSSelect(0); 1374 1.1 thorpej if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) 1375 1.1 thorpej sc->sc_MacCtrl0 |= MC0_RcvLargeFrames; 1376 1.1 thorpej 1377 1.1 thorpej /* 1378 1.1 thorpej * Set the current media. 1379 1.1 thorpej */ 1380 1.32 dyoung if ((error = ether_mediachange(ifp)) != 0) 1381 1.32 dyoung goto out; 1382 1.1 thorpej 1383 1.1 thorpej /* 1384 1.1 thorpej * Start the MAC. 1385 1.1 thorpej */ 1386 1.1 thorpej bus_space_write_2(st, sh, STE_MacCtrl1, 1387 1.1 thorpej MC1_StatisticsEnable | MC1_TxEnable | MC1_RxEnable); 1388 1.1 thorpej 1389 1.1 thorpej /* 1390 1.1 thorpej * Start the one second MII clock. 1391 1.1 thorpej */ 1392 1.60 thorpej callout_schedule(&sc->sc_tick_ch, hz); 1393 1.1 thorpej 1394 1.1 thorpej /* 1395 1.1 thorpej * ...all done! 1396 1.1 thorpej */ 1397 1.1 thorpej ifp->if_flags |= IFF_RUNNING; 1398 1.1 thorpej 1399 1.1 thorpej out: 1400 1.1 thorpej if (error) 1401 1.44 chs printf("%s: interface not running\n", device_xname(sc->sc_dev)); 1402 1.1 thorpej return (error); 1403 1.1 thorpej } 1404 1.1 thorpej 1405 1.1 thorpej /* 1406 1.1 thorpej * ste_drain: 1407 1.1 thorpej * 1408 1.1 thorpej * Drain the receive queue. 1409 1.1 thorpej */ 1410 1.19 thorpej static void 1411 1.1 thorpej ste_rxdrain(struct ste_softc *sc) 1412 1.1 thorpej { 1413 1.1 thorpej struct ste_descsoft *ds; 1414 1.1 thorpej int i; 1415 1.1 thorpej 1416 1.1 thorpej for (i = 0; i < STE_NRXDESC; i++) { 1417 1.1 thorpej ds = &sc->sc_rxsoft[i]; 1418 1.1 thorpej if (ds->ds_mbuf != NULL) { 1419 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1420 1.1 thorpej m_freem(ds->ds_mbuf); 1421 1.1 thorpej ds->ds_mbuf = NULL; 1422 1.1 thorpej } 1423 1.1 thorpej } 1424 1.1 thorpej } 1425 1.1 thorpej 1426 1.1 thorpej /* 1427 1.1 thorpej * ste_stop: [ ifnet interface function ] 1428 1.1 thorpej * 1429 1.1 thorpej * Stop transmission on the interface. 1430 1.1 thorpej */ 1431 1.19 thorpej static void 1432 1.1 thorpej ste_stop(struct ifnet *ifp, int disable) 1433 1.1 thorpej { 1434 1.1 thorpej struct ste_softc *sc = ifp->if_softc; 1435 1.1 thorpej struct ste_descsoft *ds; 1436 1.1 thorpej int i; 1437 1.1 thorpej 1438 1.1 thorpej /* 1439 1.1 thorpej * Stop the one second clock. 1440 1.1 thorpej */ 1441 1.1 thorpej callout_stop(&sc->sc_tick_ch); 1442 1.1 thorpej 1443 1.1 thorpej /* Down the MII. */ 1444 1.1 thorpej mii_down(&sc->sc_mii); 1445 1.1 thorpej 1446 1.1 thorpej /* 1447 1.1 thorpej * Disable interrupts. 1448 1.1 thorpej */ 1449 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_IntEnable, 0); 1450 1.1 thorpej 1451 1.1 thorpej /* 1452 1.1 thorpej * Stop receiver, transmitter, and stats update. 1453 1.1 thorpej */ 1454 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_MacCtrl1, 1455 1.1 thorpej MC1_StatisticsDisable | MC1_TxDisable | MC1_RxDisable); 1456 1.1 thorpej 1457 1.1 thorpej /* 1458 1.1 thorpej * Stop the transmit and receive DMA. 1459 1.1 thorpej */ 1460 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, 1461 1.1 thorpej DC_RxDMAHalt | DC_TxDMAHalt); 1462 1.1 thorpej ste_dmahalt_wait(sc); 1463 1.1 thorpej 1464 1.1 thorpej /* 1465 1.1 thorpej * Release any queued transmit buffers. 1466 1.1 thorpej */ 1467 1.1 thorpej for (i = 0; i < STE_NTXDESC; i++) { 1468 1.1 thorpej ds = &sc->sc_txsoft[i]; 1469 1.1 thorpej if (ds->ds_mbuf != NULL) { 1470 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1471 1.1 thorpej m_freem(ds->ds_mbuf); 1472 1.1 thorpej ds->ds_mbuf = NULL; 1473 1.1 thorpej } 1474 1.1 thorpej } 1475 1.1 thorpej 1476 1.1 thorpej /* 1477 1.1 thorpej * Mark the interface down and cancel the watchdog timer. 1478 1.1 thorpej */ 1479 1.62 thorpej ifp->if_flags &= ~IFF_RUNNING; 1480 1.1 thorpej ifp->if_timer = 0; 1481 1.33 dyoung 1482 1.33 dyoung if (disable) 1483 1.33 dyoung ste_rxdrain(sc); 1484 1.1 thorpej } 1485 1.1 thorpej 1486 1.1 thorpej static int 1487 1.1 thorpej ste_eeprom_wait(struct ste_softc *sc) 1488 1.1 thorpej { 1489 1.1 thorpej int i; 1490 1.1 thorpej 1491 1.1 thorpej for (i = 0; i < STE_TIMEOUT; i++) { 1492 1.5 thorpej delay(1000); 1493 1.1 thorpej if ((bus_space_read_2(sc->sc_st, sc->sc_sh, STE_EepromCtrl) & 1494 1.1 thorpej EC_EepromBusy) == 0) 1495 1.1 thorpej return (0); 1496 1.1 thorpej } 1497 1.1 thorpej return (1); 1498 1.1 thorpej } 1499 1.1 thorpej 1500 1.1 thorpej /* 1501 1.1 thorpej * ste_read_eeprom: 1502 1.1 thorpej * 1503 1.1 thorpej * Read data from the serial EEPROM. 1504 1.1 thorpej */ 1505 1.19 thorpej static void 1506 1.1 thorpej ste_read_eeprom(struct ste_softc *sc, int offset, uint16_t *data) 1507 1.1 thorpej { 1508 1.1 thorpej 1509 1.1 thorpej if (ste_eeprom_wait(sc)) 1510 1.1 thorpej printf("%s: EEPROM failed to come ready\n", 1511 1.44 chs device_xname(sc->sc_dev)); 1512 1.1 thorpej 1513 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_EepromCtrl, 1514 1.1 thorpej EC_EepromAddress(offset) | EC_EepromOpcode(EC_OP_R)); 1515 1.1 thorpej if (ste_eeprom_wait(sc)) 1516 1.1 thorpej printf("%s: EEPROM read timed out\n", 1517 1.44 chs device_xname(sc->sc_dev)); 1518 1.1 thorpej *data = bus_space_read_2(sc->sc_st, sc->sc_sh, STE_EepromData); 1519 1.1 thorpej } 1520 1.1 thorpej 1521 1.1 thorpej /* 1522 1.1 thorpej * ste_add_rxbuf: 1523 1.1 thorpej * 1524 1.1 thorpej * Add a receive buffer to the indicated descriptor. 1525 1.1 thorpej */ 1526 1.19 thorpej static int 1527 1.1 thorpej ste_add_rxbuf(struct ste_softc *sc, int idx) 1528 1.1 thorpej { 1529 1.1 thorpej struct ste_descsoft *ds = &sc->sc_rxsoft[idx]; 1530 1.1 thorpej struct mbuf *m; 1531 1.1 thorpej int error; 1532 1.1 thorpej 1533 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA); 1534 1.21 perry if (m == NULL) 1535 1.1 thorpej return (ENOBUFS); 1536 1.1 thorpej 1537 1.61 thorpej MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); 1538 1.1 thorpej MCLGET(m, M_DONTWAIT); 1539 1.1 thorpej if ((m->m_flags & M_EXT) == 0) { 1540 1.1 thorpej m_freem(m); 1541 1.1 thorpej return (ENOBUFS); 1542 1.1 thorpej } 1543 1.1 thorpej 1544 1.1 thorpej if (ds->ds_mbuf != NULL) 1545 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap); 1546 1.1 thorpej 1547 1.1 thorpej ds->ds_mbuf = m; 1548 1.1 thorpej 1549 1.1 thorpej error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap, 1550 1.4 thorpej m->m_ext.ext_buf, m->m_ext.ext_size, NULL, 1551 1.54 msaitoh BUS_DMA_READ | BUS_DMA_NOWAIT); 1552 1.1 thorpej if (error) { 1553 1.1 thorpej printf("%s: can't load rx DMA map %d, error = %d\n", 1554 1.44 chs device_xname(sc->sc_dev), idx, error); 1555 1.1 thorpej panic("ste_add_rxbuf"); /* XXX */ 1556 1.1 thorpej } 1557 1.1 thorpej 1558 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, 1559 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1560 1.1 thorpej 1561 1.1 thorpej STE_INIT_RXDESC(sc, idx); 1562 1.1 thorpej 1563 1.1 thorpej return (0); 1564 1.1 thorpej } 1565 1.1 thorpej 1566 1.1 thorpej /* 1567 1.1 thorpej * ste_set_filter: 1568 1.1 thorpej * 1569 1.1 thorpej * Set up the receive filter. 1570 1.1 thorpej */ 1571 1.19 thorpej static void 1572 1.1 thorpej ste_set_filter(struct ste_softc *sc) 1573 1.1 thorpej { 1574 1.1 thorpej struct ethercom *ec = &sc->sc_ethercom; 1575 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1576 1.1 thorpej struct ether_multi *enm; 1577 1.1 thorpej struct ether_multistep step; 1578 1.1 thorpej uint32_t crc; 1579 1.1 thorpej uint16_t mchash[4]; 1580 1.1 thorpej 1581 1.1 thorpej sc->sc_ReceiveMode = RM_ReceiveUnicast; 1582 1.1 thorpej if (ifp->if_flags & IFF_BROADCAST) 1583 1.1 thorpej sc->sc_ReceiveMode |= RM_ReceiveBroadcast; 1584 1.1 thorpej 1585 1.1 thorpej if (ifp->if_flags & IFF_PROMISC) { 1586 1.1 thorpej sc->sc_ReceiveMode |= RM_ReceiveAllFrames; 1587 1.1 thorpej goto allmulti; 1588 1.1 thorpej } 1589 1.1 thorpej 1590 1.1 thorpej /* 1591 1.1 thorpej * Set up the multicast address filter by passing all multicast 1592 1.1 thorpej * addresses through a CRC generator, and then using the low-order 1593 1.1 thorpej * 6 bits as an index into the 64 bit multicast hash table. The 1594 1.1 thorpej * high order bits select the register, while the rest of the bits 1595 1.1 thorpej * select the bit within the register. 1596 1.1 thorpej */ 1597 1.1 thorpej 1598 1.1 thorpej memset(mchash, 0, sizeof(mchash)); 1599 1.1 thorpej 1600 1.56 msaitoh ETHER_LOCK(ec); 1601 1.1 thorpej ETHER_FIRST_MULTI(step, ec, enm); 1602 1.56 msaitoh if (enm == NULL) { 1603 1.56 msaitoh ETHER_UNLOCK(ec); 1604 1.1 thorpej goto done; 1605 1.56 msaitoh } 1606 1.1 thorpej 1607 1.1 thorpej while (enm != NULL) { 1608 1.1 thorpej if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 1609 1.1 thorpej /* 1610 1.1 thorpej * We must listen to a range of multicast addresses. 1611 1.1 thorpej * For now, just accept all multicasts, rather than 1612 1.1 thorpej * trying to set only those filter bits needed to match 1613 1.1 thorpej * the range. (At this time, the only use of address 1614 1.1 thorpej * ranges is for IP multicast routing, for which the 1615 1.1 thorpej * range is big enough to require all bits set.) 1616 1.1 thorpej */ 1617 1.56 msaitoh ETHER_UNLOCK(ec); 1618 1.1 thorpej goto allmulti; 1619 1.1 thorpej } 1620 1.1 thorpej 1621 1.1 thorpej crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); 1622 1.1 thorpej 1623 1.1 thorpej /* Just want the 6 least significant bits. */ 1624 1.1 thorpej crc &= 0x3f; 1625 1.1 thorpej 1626 1.1 thorpej /* Set the corresponding bit in the hash table. */ 1627 1.1 thorpej mchash[crc >> 4] |= 1 << (crc & 0xf); 1628 1.1 thorpej 1629 1.1 thorpej ETHER_NEXT_MULTI(step, enm); 1630 1.1 thorpej } 1631 1.56 msaitoh ETHER_UNLOCK(ec); 1632 1.1 thorpej 1633 1.1 thorpej sc->sc_ReceiveMode |= RM_ReceiveMulticastHash; 1634 1.1 thorpej 1635 1.1 thorpej ifp->if_flags &= ~IFF_ALLMULTI; 1636 1.1 thorpej goto done; 1637 1.1 thorpej 1638 1.1 thorpej allmulti: 1639 1.1 thorpej ifp->if_flags |= IFF_ALLMULTI; 1640 1.1 thorpej sc->sc_ReceiveMode |= RM_ReceiveMulticast; 1641 1.1 thorpej 1642 1.1 thorpej done: 1643 1.1 thorpej if ((ifp->if_flags & IFF_ALLMULTI) == 0) { 1644 1.1 thorpej /* 1645 1.1 thorpej * Program the multicast hash table. 1646 1.1 thorpej */ 1647 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_HashTable0, 1648 1.1 thorpej mchash[0]); 1649 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_HashTable1, 1650 1.1 thorpej mchash[1]); 1651 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_HashTable2, 1652 1.1 thorpej mchash[2]); 1653 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_HashTable3, 1654 1.1 thorpej mchash[3]); 1655 1.1 thorpej } 1656 1.1 thorpej 1657 1.1 thorpej bus_space_write_1(sc->sc_st, sc->sc_sh, STE_ReceiveMode, 1658 1.1 thorpej sc->sc_ReceiveMode); 1659 1.1 thorpej } 1660 1.1 thorpej 1661 1.1 thorpej /* 1662 1.1 thorpej * ste_mii_readreg: [mii interface function] 1663 1.1 thorpej * 1664 1.1 thorpej * Read a PHY register on the MII of the ST-201. 1665 1.1 thorpej */ 1666 1.19 thorpej static int 1667 1.53 msaitoh ste_mii_readreg(device_t self, int phy, int reg, uint16_t *val) 1668 1.1 thorpej { 1669 1.61 thorpej struct ste_softc *sc = device_private(self); 1670 1.61 thorpej 1671 1.61 thorpej if (phy == 0 && !sc->sc_enable_phy0) 1672 1.61 thorpej return EIO; 1673 1.1 thorpej 1674 1.53 msaitoh return mii_bitbang_readreg(self, &ste_mii_bitbang_ops, phy, reg, val); 1675 1.1 thorpej } 1676 1.1 thorpej 1677 1.1 thorpej /* 1678 1.1 thorpej * ste_mii_writereg: [mii interface function] 1679 1.1 thorpej * 1680 1.1 thorpej * Write a PHY register on the MII of the ST-201. 1681 1.1 thorpej */ 1682 1.53 msaitoh static int 1683 1.53 msaitoh ste_mii_writereg(device_t self, int phy, int reg, uint16_t val) 1684 1.1 thorpej { 1685 1.61 thorpej struct ste_softc *sc = device_private(self); 1686 1.61 thorpej 1687 1.61 thorpej if (phy == 0 && !sc->sc_enable_phy0) 1688 1.61 thorpej return EIO; 1689 1.1 thorpej 1690 1.53 msaitoh return mii_bitbang_writereg(self, &ste_mii_bitbang_ops, phy, reg, val); 1691 1.1 thorpej } 1692 1.1 thorpej 1693 1.1 thorpej /* 1694 1.1 thorpej * ste_mii_statchg: [mii interface function] 1695 1.1 thorpej * 1696 1.1 thorpej * Callback from MII layer when media changes. 1697 1.1 thorpej */ 1698 1.19 thorpej static void 1699 1.43 matt ste_mii_statchg(struct ifnet *ifp) 1700 1.1 thorpej { 1701 1.43 matt struct ste_softc *sc = ifp->if_softc; 1702 1.1 thorpej 1703 1.1 thorpej if (sc->sc_mii.mii_media_active & IFM_FDX) 1704 1.1 thorpej sc->sc_MacCtrl0 |= MC0_FullDuplexEnable; 1705 1.1 thorpej else 1706 1.1 thorpej sc->sc_MacCtrl0 &= ~MC0_FullDuplexEnable; 1707 1.1 thorpej 1708 1.1 thorpej /* XXX 802.1x flow-control? */ 1709 1.1 thorpej 1710 1.1 thorpej bus_space_write_2(sc->sc_st, sc->sc_sh, STE_MacCtrl0, sc->sc_MacCtrl0); 1711 1.1 thorpej } 1712 1.1 thorpej 1713 1.1 thorpej /* 1714 1.1 thorpej * ste_mii_bitbang_read: [mii bit-bang interface function] 1715 1.1 thorpej * 1716 1.1 thorpej * Read the MII serial port for the MII bit-bang module. 1717 1.1 thorpej */ 1718 1.19 thorpej static uint32_t 1719 1.34 dyoung ste_mii_bitbang_read(device_t self) 1720 1.1 thorpej { 1721 1.34 dyoung struct ste_softc *sc = device_private(self); 1722 1.1 thorpej 1723 1.1 thorpej return (bus_space_read_1(sc->sc_st, sc->sc_sh, STE_PhyCtrl)); 1724 1.1 thorpej } 1725 1.1 thorpej 1726 1.1 thorpej /* 1727 1.1 thorpej * ste_mii_bitbang_write: [mii big-bang interface function] 1728 1.1 thorpej * 1729 1.1 thorpej * Write the MII serial port for the MII bit-bang module. 1730 1.1 thorpej */ 1731 1.19 thorpej static void 1732 1.34 dyoung ste_mii_bitbang_write(device_t self, uint32_t val) 1733 1.1 thorpej { 1734 1.34 dyoung struct ste_softc *sc = device_private(self); 1735 1.1 thorpej 1736 1.1 thorpej bus_space_write_1(sc->sc_st, sc->sc_sh, STE_PhyCtrl, val); 1737 1.1 thorpej } 1738