1/* 2 * Copyright (c) 2003 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
| 1/* 2 * Copyright (c) 2003 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
|
34__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 123537 2003-12-14 22:47:01Z wpaul $");
| 34__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis.c 123620 2003-12-18 03:51:21Z wpaul $");
|
35 36#include "opt_bdg.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/sockio.h> 41#include <sys/mbuf.h> 42#include <sys/malloc.h> 43#include <sys/kernel.h> 44#include <sys/socket.h> 45#include <sys/queue.h> 46#include <sys/sysctl.h> 47 48#include <net/if.h> 49#include <net/if_arp.h> 50#include <net/ethernet.h> 51#include <net/if_dl.h> 52#include <net/if_media.h> 53 54#include <net/bpf.h> 55 56#include <vm/vm.h> /* for vtophys */ 57#include <vm/pmap.h> /* for vtophys */ 58#include <machine/bus_memio.h> 59#include <machine/bus_pio.h> 60#include <machine/bus.h> 61#include <machine/resource.h> 62#include <sys/bus.h> 63#include <sys/rman.h> 64 65#include <dev/pci/pcireg.h> 66#include <dev/pci/pcivar.h> 67 68#include <compat/ndis/pe_var.h> 69#include <compat/ndis/resource_var.h> 70#include <compat/ndis/ndis_var.h> 71#include <compat/ndis/cfg_var.h> 72#include <dev/if_ndis/if_ndisvar.h> 73 74#include "ndis_driver_data.h" 75 76MODULE_DEPEND(ndis, pci, 1, 1, 1); 77MODULE_DEPEND(ndis, ether, 1, 1, 1); 78MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); 79 80/* 81 * Various supported device vendors/types and their names. 82 * These are defined in the ndis_driver_data.h file. 83 */ 84static struct ndis_type ndis_devs[] = { 85#ifdef NDIS_DEV_TABLE 86 NDIS_DEV_TABLE 87#endif
| 35 36#include "opt_bdg.h" 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/sockio.h> 41#include <sys/mbuf.h> 42#include <sys/malloc.h> 43#include <sys/kernel.h> 44#include <sys/socket.h> 45#include <sys/queue.h> 46#include <sys/sysctl.h> 47 48#include <net/if.h> 49#include <net/if_arp.h> 50#include <net/ethernet.h> 51#include <net/if_dl.h> 52#include <net/if_media.h> 53 54#include <net/bpf.h> 55 56#include <vm/vm.h> /* for vtophys */ 57#include <vm/pmap.h> /* for vtophys */ 58#include <machine/bus_memio.h> 59#include <machine/bus_pio.h> 60#include <machine/bus.h> 61#include <machine/resource.h> 62#include <sys/bus.h> 63#include <sys/rman.h> 64 65#include <dev/pci/pcireg.h> 66#include <dev/pci/pcivar.h> 67 68#include <compat/ndis/pe_var.h> 69#include <compat/ndis/resource_var.h> 70#include <compat/ndis/ndis_var.h> 71#include <compat/ndis/cfg_var.h> 72#include <dev/if_ndis/if_ndisvar.h> 73 74#include "ndis_driver_data.h" 75 76MODULE_DEPEND(ndis, pci, 1, 1, 1); 77MODULE_DEPEND(ndis, ether, 1, 1, 1); 78MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); 79 80/* 81 * Various supported device vendors/types and their names. 82 * These are defined in the ndis_driver_data.h file. 83 */ 84static struct ndis_type ndis_devs[] = { 85#ifdef NDIS_DEV_TABLE 86 NDIS_DEV_TABLE 87#endif
|
88 { 0, 0, NULL }
| 88 { 0, 0, 0, NULL }
|
89}; 90 91#define __stdcall __attribute__((__stdcall__)) 92 93static int ndis_probe (device_t); 94static int ndis_attach (device_t); 95static int ndis_detach (device_t); 96 97static __stdcall void ndis_txeof (ndis_handle, 98 ndis_packet *, ndis_status); 99static __stdcall void ndis_rxeof (ndis_handle, 100 ndis_packet **, uint32_t); 101static void ndis_intr (void *); 102static void ndis_tick (void *); 103static void ndis_start (struct ifnet *); 104static int ndis_ioctl (struct ifnet *, u_long, caddr_t); 105static void ndis_init (void *); 106static void ndis_stop (struct ndis_softc *); 107static void ndis_watchdog (struct ifnet *); 108static void ndis_shutdown (device_t); 109static int ndis_ifmedia_upd (struct ifnet *); 110static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); 111 112static void ndis_reset (struct ndis_softc *); 113static void ndis_setmulti (struct ndis_softc *); 114static void ndis_map_sclist (void *, bus_dma_segment_t *, 115 int, bus_size_t, int); 116 117#ifdef NDIS_USEIOSPACE 118#define NDIS_RES SYS_RES_IOPORT 119#define NDIS_RID NDIS_PCI_LOIO 120#else 121#define NDIS_RES SYS_RES_MEMORY 122#define NDIS_RID NDIS_PCI_LOMEM 123#endif 124 125static device_method_t ndis_methods[] = { 126 /* Device interface */ 127 DEVMETHOD(device_probe, ndis_probe), 128 DEVMETHOD(device_attach, ndis_attach), 129 DEVMETHOD(device_detach, ndis_detach), 130 DEVMETHOD(device_shutdown, ndis_shutdown), 131 132 { 0, 0 } 133}; 134 135static driver_t ndis_driver = { 136 "ndis", 137 ndis_methods, 138 sizeof(struct ndis_softc) 139}; 140 141static devclass_t ndis_devclass; 142 143DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); 144 145/* 146 * Program the 64-bit multicast hash filter. 147 */ 148static void 149ndis_setmulti(sc) 150 struct ndis_softc *sc; 151{ 152#ifdef notyet 153 uint32_t ndis_filter; 154 int len; 155#endif 156 return; 157} 158 159static void 160ndis_reset(sc) 161 struct ndis_softc *sc; 162{ 163 ndis_reset_nic(sc); 164 return; 165} 166 167/* 168 * Probe for an NDIS device. Check the PCI vendor and device 169 * IDs against our list and return a device name if we find a match. 170 */ 171static int 172ndis_probe(dev) 173 device_t dev; 174{ 175 struct ndis_type *t; 176 177 t = ndis_devs; 178 179 while(t->ndis_name != NULL) { 180 if ((pci_get_vendor(dev) == t->ndis_vid) &&
| 89}; 90 91#define __stdcall __attribute__((__stdcall__)) 92 93static int ndis_probe (device_t); 94static int ndis_attach (device_t); 95static int ndis_detach (device_t); 96 97static __stdcall void ndis_txeof (ndis_handle, 98 ndis_packet *, ndis_status); 99static __stdcall void ndis_rxeof (ndis_handle, 100 ndis_packet **, uint32_t); 101static void ndis_intr (void *); 102static void ndis_tick (void *); 103static void ndis_start (struct ifnet *); 104static int ndis_ioctl (struct ifnet *, u_long, caddr_t); 105static void ndis_init (void *); 106static void ndis_stop (struct ndis_softc *); 107static void ndis_watchdog (struct ifnet *); 108static void ndis_shutdown (device_t); 109static int ndis_ifmedia_upd (struct ifnet *); 110static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); 111 112static void ndis_reset (struct ndis_softc *); 113static void ndis_setmulti (struct ndis_softc *); 114static void ndis_map_sclist (void *, bus_dma_segment_t *, 115 int, bus_size_t, int); 116 117#ifdef NDIS_USEIOSPACE 118#define NDIS_RES SYS_RES_IOPORT 119#define NDIS_RID NDIS_PCI_LOIO 120#else 121#define NDIS_RES SYS_RES_MEMORY 122#define NDIS_RID NDIS_PCI_LOMEM 123#endif 124 125static device_method_t ndis_methods[] = { 126 /* Device interface */ 127 DEVMETHOD(device_probe, ndis_probe), 128 DEVMETHOD(device_attach, ndis_attach), 129 DEVMETHOD(device_detach, ndis_detach), 130 DEVMETHOD(device_shutdown, ndis_shutdown), 131 132 { 0, 0 } 133}; 134 135static driver_t ndis_driver = { 136 "ndis", 137 ndis_methods, 138 sizeof(struct ndis_softc) 139}; 140 141static devclass_t ndis_devclass; 142 143DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); 144 145/* 146 * Program the 64-bit multicast hash filter. 147 */ 148static void 149ndis_setmulti(sc) 150 struct ndis_softc *sc; 151{ 152#ifdef notyet 153 uint32_t ndis_filter; 154 int len; 155#endif 156 return; 157} 158 159static void 160ndis_reset(sc) 161 struct ndis_softc *sc; 162{ 163 ndis_reset_nic(sc); 164 return; 165} 166 167/* 168 * Probe for an NDIS device. Check the PCI vendor and device 169 * IDs against our list and return a device name if we find a match. 170 */ 171static int 172ndis_probe(dev) 173 device_t dev; 174{ 175 struct ndis_type *t; 176 177 t = ndis_devs; 178 179 while(t->ndis_name != NULL) { 180 if ((pci_get_vendor(dev) == t->ndis_vid) &&
|
181 (pci_get_device(dev) == t->ndis_did)) {
| 181 (pci_get_device(dev) == t->ndis_did) && 182 (pci_read_config(dev, PCIR_SUBVEND_0, 4) == 183 t->ndis_subsys)) {
|
182 device_set_desc(dev, t->ndis_name); 183 return(0); 184 } 185 t++; 186 } 187 188 return(ENXIO); 189} 190 191/* 192 * Attach the interface. Allocate softc structures, do ifmedia 193 * setup and ethernet/BPF attach. 194 */ 195static int 196ndis_attach(dev) 197 device_t dev; 198{ 199 u_char eaddr[ETHER_ADDR_LEN]; 200 struct ndis_softc *sc; 201 struct ifnet *ifp; 202 int unit, error = 0, rid, len; 203 void *img;
| 184 device_set_desc(dev, t->ndis_name); 185 return(0); 186 } 187 t++; 188 } 189 190 return(ENXIO); 191} 192 193/* 194 * Attach the interface. Allocate softc structures, do ifmedia 195 * setup and ethernet/BPF attach. 196 */ 197static int 198ndis_attach(dev) 199 device_t dev; 200{ 201 u_char eaddr[ETHER_ADDR_LEN]; 202 struct ndis_softc *sc; 203 struct ifnet *ifp; 204 int unit, error = 0, rid, len; 205 void *img;
|
| 206 struct ndis_type *t; 207 int devidx = 0, defidx = 0;
|
204
| 208
|
| 209
|
205 sc = device_get_softc(dev); 206 unit = device_get_unit(dev); 207 208 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 209 MTX_DEF | MTX_RECURSE); 210 211 /* 212 * Map control/status registers. 213 */ 214 pci_enable_busmaster(dev); 215 216 /* Try to map iospace */ 217 218 sc->ndis_io_rid = NDIS_PCI_LOIO; 219 sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, 220 &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); 221 222 /* 223 * Sometimes the iospace and memspace BARs are swapped. 224 * Make one more try to map I/O space using a different 225 * RID. 226 */ 227 if (sc->ndis_res_io == NULL) { 228 sc->ndis_io_rid = NDIS_PCI_LOMEM; 229 sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, 230 &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); 231 } 232 233 if (sc->ndis_res_io != NULL) 234 sc->ndis_rescnt++; 235 236 /* Now try to mem memory space */ 237 sc->ndis_mem_rid = NDIS_PCI_LOMEM; 238 sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, 239 &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); 240 241 /* 242 * If the first attempt fails, try again with another 243 * BAR. 244 */ 245 if (sc->ndis_res_mem == NULL) { 246 sc->ndis_mem_rid = NDIS_PCI_LOIO; 247 sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, 248 &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); 249 } 250 251 if (sc->ndis_res_mem != NULL) 252 sc->ndis_rescnt++; 253 254 if (!sc->ndis_rescnt) { 255 printf("ndis%d: couldn't map ports/memory\n", unit); 256 error = ENXIO; 257 goto fail; 258 } 259#ifdef notdef 260 sc->ndis_btag = rman_get_bustag(sc->ndis_res); 261 sc->ndis_bhandle = rman_get_bushandle(sc->ndis_res); 262#endif 263 264 /* Allocate interrupt */ 265 rid = 0; 266 sc->ndis_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 267 RF_SHAREABLE | RF_ACTIVE); 268 269 if (sc->ndis_irq == NULL) { 270 printf("ndis%d: couldn't map interrupt\n", unit); 271 error = ENXIO; 272 goto fail; 273 } 274 275 sc->ndis_rescnt++; 276 277 /* 278 * Allocate the parent bus DMA tag appropriate for PCI. 279 */ 280#define NDIS_NSEG_NEW 32 281 error = bus_dma_tag_create(NULL, /* parent */ 282 1, 0, /* alignment, boundary */ 283 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 284 BUS_SPACE_MAXADDR, /* highaddr */ 285 NULL, NULL, /* filter, filterarg */ 286 MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ 287 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 288 BUS_DMA_ALLOCNOW, /* flags */ 289 NULL, NULL, /* lockfunc, lockarg */ 290 &sc->ndis_parent_tag); 291 292 if (error) 293 goto fail; 294 295 img = drv_data; 296 sc->ndis_dev = dev; 297 sc->ndis_regvals = ndis_regvals; 298 sc->ndis_iftype = PCIBus; 299
| 210 sc = device_get_softc(dev); 211 unit = device_get_unit(dev); 212 213 mtx_init(&sc->ndis_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 214 MTX_DEF | MTX_RECURSE); 215 216 /* 217 * Map control/status registers. 218 */ 219 pci_enable_busmaster(dev); 220 221 /* Try to map iospace */ 222 223 sc->ndis_io_rid = NDIS_PCI_LOIO; 224 sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, 225 &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); 226 227 /* 228 * Sometimes the iospace and memspace BARs are swapped. 229 * Make one more try to map I/O space using a different 230 * RID. 231 */ 232 if (sc->ndis_res_io == NULL) { 233 sc->ndis_io_rid = NDIS_PCI_LOMEM; 234 sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, 235 &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); 236 } 237 238 if (sc->ndis_res_io != NULL) 239 sc->ndis_rescnt++; 240 241 /* Now try to mem memory space */ 242 sc->ndis_mem_rid = NDIS_PCI_LOMEM; 243 sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, 244 &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); 245 246 /* 247 * If the first attempt fails, try again with another 248 * BAR. 249 */ 250 if (sc->ndis_res_mem == NULL) { 251 sc->ndis_mem_rid = NDIS_PCI_LOIO; 252 sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, 253 &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); 254 } 255 256 if (sc->ndis_res_mem != NULL) 257 sc->ndis_rescnt++; 258 259 if (!sc->ndis_rescnt) { 260 printf("ndis%d: couldn't map ports/memory\n", unit); 261 error = ENXIO; 262 goto fail; 263 } 264#ifdef notdef 265 sc->ndis_btag = rman_get_bustag(sc->ndis_res); 266 sc->ndis_bhandle = rman_get_bushandle(sc->ndis_res); 267#endif 268 269 /* Allocate interrupt */ 270 rid = 0; 271 sc->ndis_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 272 RF_SHAREABLE | RF_ACTIVE); 273 274 if (sc->ndis_irq == NULL) { 275 printf("ndis%d: couldn't map interrupt\n", unit); 276 error = ENXIO; 277 goto fail; 278 } 279 280 sc->ndis_rescnt++; 281 282 /* 283 * Allocate the parent bus DMA tag appropriate for PCI. 284 */ 285#define NDIS_NSEG_NEW 32 286 error = bus_dma_tag_create(NULL, /* parent */ 287 1, 0, /* alignment, boundary */ 288 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 289 BUS_SPACE_MAXADDR, /* highaddr */ 290 NULL, NULL, /* filter, filterarg */ 291 MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ 292 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 293 BUS_DMA_ALLOCNOW, /* flags */ 294 NULL, NULL, /* lockfunc, lockarg */ 295 &sc->ndis_parent_tag); 296 297 if (error) 298 goto fail; 299 300 img = drv_data; 301 sc->ndis_dev = dev; 302 sc->ndis_regvals = ndis_regvals; 303 sc->ndis_iftype = PCIBus; 304
|
| 305 /* Figure out exactly which device we matched. */ 306 307 t = ndis_devs; 308 309 while(t->ndis_name != NULL) { 310 if ((pci_get_vendor(dev) == t->ndis_vid) && 311 (pci_get_device(dev) == t->ndis_did)) { 312 if (t->ndis_subsys == 0) 313 defidx = devidx; 314 else { 315 if (t->ndis_subsys == 316 pci_read_config(dev, PCIR_SUBVEND_0, 4)) 317 break; 318 } 319 } 320 t++; 321 devidx++; 322 } 323 324 if (ndis_devs[devidx].ndis_name == NULL) 325 sc->ndis_devidx = defidx; 326 else 327 sc->ndis_devidx = devidx; 328
|
300 sysctl_ctx_init(&sc->ndis_ctx); 301 302 /* Create sysctl registry nodes */ 303 ndis_create_sysctls(sc); 304 305 /* Set up driver image in memory. */ 306 ndis_load_driver((vm_offset_t)img, sc); 307 308 /* Do resource conversion. */ 309 ndis_convert_res(sc); 310 311 /* Install our RX and TX interrupt handlers. */ 312 sc->ndis_block.nmb_senddone_func = ndis_txeof; 313 sc->ndis_block.nmb_pktind_func = ndis_rxeof; 314 315 /* Call driver's init routine. */ 316 if (ndis_init_nic(sc)) { 317 printf ("ndis%d: init handler failed\n", sc->ndis_unit); 318 error = ENXIO; 319 goto fail; 320 } 321 322 /* Reset the adapter. */ 323 ndis_reset(sc); 324 325 /* 326 * Get station address from the driver. 327 */ 328 len = sizeof(eaddr); 329 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); 330 331 /* 332 * An NDIS device was detected. Inform the world. 333 */ 334 printf("ndis%d: Ethernet address: %6D\n", unit, eaddr, ":"); 335 336 sc->ndis_unit = unit; 337 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 338 339 /* 340 * Figure out of we're allowed to use multipacket sends 341 * with this driver, and if so, how many. 342 */ 343 344 if (sc->ndis_chars.nmc_sendsingle_func) 345 sc->ndis_maxpkts = 1; 346 else { 347 len = sizeof(sc->ndis_maxpkts); 348 ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, 349 &sc->ndis_maxpkts, &len); 350 sc->ndis_txarray = malloc(sizeof(ndis_packet *) * 351 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT); 352 bzero((char *)sc->ndis_txarray, sizeof(ndis_packet *) * 353 sc->ndis_maxpkts); 354 } 355 356 sc->ndis_txpending = sc->ndis_maxpkts; 357 358 sc->ndis_oidcnt = 0; 359 /* Get supported oid list. */ 360 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); 361 362 /* If the NDIS module requested scatter/gather, init maps. */ 363 if (sc->ndis_sc) 364 ndis_init_dma(sc); 365 366 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, 367 ndis_ifmedia_sts); 368 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 369 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 370 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); 371 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 372 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 373 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); 374 375 ifp = &sc->arpcom.ac_if; 376 ifp->if_softc = sc; 377 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 378 ifp->if_mtu = ETHERMTU; 379 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 380 ifp->if_ioctl = ndis_ioctl; 381 ifp->if_output = ether_output; 382 ifp->if_start = ndis_start; 383 ifp->if_watchdog = ndis_watchdog; 384 ifp->if_init = ndis_init; 385 ifp->if_baudrate = 10000000; 386 ifp->if_snd.ifq_maxlen = 50; 387 388 /* 389 * Call MI attach routine. 390 */ 391 ether_ifattach(ifp, eaddr); 392 393 /* Hook interrupt last to avoid having to lock softc */ 394 error = bus_setup_intr(dev, sc->ndis_irq, INTR_TYPE_NET, 395 ndis_intr, sc, &sc->ndis_intrhand); 396 397 if (error) { 398 printf("ndis%d: couldn't set up irq\n", unit); 399 ether_ifdetach(ifp); 400 goto fail; 401 } 402 403fail: 404 if (error) 405 ndis_detach(dev); 406 407 return(error); 408} 409 410/* 411 * Shutdown hardware and free up resources. This can be called any 412 * time after the mutex has been initialized. It is called in both 413 * the error case in attach and the normal detach case so it needs 414 * to be careful about only freeing resources that have actually been 415 * allocated. 416 */ 417static int 418ndis_detach(dev) 419 device_t dev; 420{ 421 struct ndis_softc *sc; 422 struct ifnet *ifp; 423 424 sc = device_get_softc(dev); 425 KASSERT(mtx_initialized(&sc->ndis_mtx), ("ndis mutex not initialized")); 426 NDIS_LOCK(sc); 427 ifp = &sc->arpcom.ac_if; 428 429 if (device_is_attached(dev)) { 430 NDIS_UNLOCK(sc); 431 ndis_stop(sc); 432 ether_ifdetach(ifp); 433 NDIS_LOCK(sc); 434 } 435 436 bus_generic_detach(dev); 437 438 if (sc->ndis_intrhand) 439 bus_teardown_intr(dev, sc->ndis_irq, sc->ndis_intrhand); 440 if (sc->ndis_irq) 441 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); 442 if (sc->ndis_res_io) 443 bus_release_resource(dev, SYS_RES_IOPORT, 444 sc->ndis_io_rid, sc->ndis_res_io); 445 if (sc->ndis_res_mem) 446 bus_release_resource(dev, SYS_RES_MEMORY, 447 sc->ndis_mem_rid, sc->ndis_res_mem); 448 449 if (sc->ndis_sc) 450 ndis_destroy_dma(sc); 451 452 ndis_unload_driver((void *)ifp); 453 454 bus_dma_tag_destroy(sc->ndis_parent_tag); 455 456 sysctl_ctx_free(&sc->ndis_ctx); 457 458 NDIS_UNLOCK(sc); 459 mtx_destroy(&sc->ndis_mtx); 460 461 return(0); 462} 463 464/* 465 * A frame has been uploaded: pass the resulting mbuf chain up to 466 * the higher level protocols. 467 */ 468__stdcall static void 469ndis_rxeof(adapter, packets, pktcnt) 470 ndis_handle adapter; 471 ndis_packet **packets; 472 uint32_t pktcnt; 473{ 474 struct ndis_softc *sc; 475 ndis_miniport_block *block; 476 ndis_packet *p; 477 struct ifnet *ifp; 478 struct mbuf *m0; 479 int i; 480 481 block = (ndis_miniport_block *)adapter; 482 sc = (struct ndis_softc *)(block->nmb_ifp); 483 ifp = block->nmb_ifp; 484 485 for (i = 0; i < pktcnt; i++) { 486 p = packets[i]; 487 /* Stash the softc here so ptom can use it. */ 488 p->np_rsvd[0] = (uint32_t *)sc; 489 if (ndis_ptom(&m0, p)) { 490 printf ("ndis%d: ptom failed\n", sc->ndis_unit); 491 ndis_return_packet(sc, p); 492 } else { 493 m0->m_pkthdr.rcvif = ifp; 494 ifp->if_ipackets++; 495 (*ifp->if_input)(ifp, m0); 496 } 497 } 498 499 return; 500} 501 502/* 503 * A frame was downloaded to the chip. It's safe for us to clean up 504 * the list buffers. 505 */ 506__stdcall static void 507ndis_txeof(adapter, packet, status) 508 ndis_handle adapter; 509 ndis_packet *packet; 510 ndis_status status; 511 512{ 513 struct ndis_softc *sc; 514 ndis_miniport_block *block; 515 struct ifnet *ifp; 516 int idx; 517 struct mbuf *m; 518 519 block = (ndis_miniport_block *)adapter; 520 sc = (struct ndis_softc *)block->nmb_ifp; 521 ifp = block->nmb_ifp; 522 523 if (packet->np_rsvd[1] == NULL) 524 panic("NDIS driver corrupted reserved packet fields"); 525 526 NDIS_LOCK(sc); 527 528 m = (struct mbuf *)packet->np_rsvd[1]; 529 idx = (int)packet->np_rsvd[0]; 530 ifp->if_opackets++; 531 m_freem(m); 532 if (sc->ndis_sc) 533 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); 534 535 ndis_free_packet(packet); 536 sc->ndis_txarray[idx] = NULL; 537 sc->ndis_txpending++; 538 539 ifp->if_timer = 0; 540 ifp->if_flags &= ~IFF_OACTIVE; 541 542 NDIS_UNLOCK(sc); 543 544 if (ifp->if_snd.ifq_head != NULL) 545 ndis_start(ifp); 546 547 return; 548} 549 550static void 551ndis_intr(arg) 552 void *arg; 553{ 554 struct ndis_softc *sc; 555 struct ifnet *ifp; 556 int is_our_intr = 0; 557 int call_isr = 0; 558 559 sc = arg; 560 /*NDIS_LOCK(sc);*/ 561 ifp = &sc->arpcom.ac_if; 562 563/* 564 if (!(ifp->if_flags & IFF_UP)) { 565 NDIS_UNLOCK(sc); 566 return; 567 } 568*/ 569 ndis_isr(sc, &is_our_intr, &call_isr); 570 571 if (is_our_intr || call_isr) 572 ndis_intrhand(sc); 573 574 if (ifp->if_snd.ifq_head != NULL) 575 ndis_start(ifp); 576 577 /*NDIS_UNLOCK(sc);*/ 578 579 return; 580} 581 582static void 583ndis_tick(xsc) 584 void *xsc; 585{ 586 struct ndis_softc *sc; 587 __stdcall ndis_checkforhang_handler hangfunc; 588 uint8_t rval; 589 590 sc = xsc; 591 NDIS_LOCK(sc); 592 593 hangfunc = sc->ndis_chars.nmc_checkhang_func; 594 595 if (hangfunc != NULL) { 596 rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx); 597 if (rval == TRUE) 598 ndis_reset_nic(sc); 599 } 600 601 sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * 602 sc->ndis_block.nmb_checkforhangsecs); 603 604 NDIS_UNLOCK(sc); 605 606 return; 607} 608 609static void 610ndis_map_sclist(arg, segs, nseg, mapsize, error) 611 void *arg; 612 bus_dma_segment_t *segs; 613 int nseg; 614 bus_size_t mapsize; 615 int error; 616 617{ 618 struct ndis_sc_list *sclist; 619 int i; 620 621 if (error || arg == NULL) 622 return; 623 624 sclist = arg; 625 626 sclist->nsl_frags = nseg; 627 628 for (i = 0; i < nseg; i++) { 629 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; 630 sclist->nsl_elements[i].nse_len = segs[i].ds_len; 631 } 632 633 return; 634} 635 636/* 637 * Main transmit routine. To make NDIS drivers happy, we need to 638 * transform mbuf chains into NDIS packets and feed them to the 639 * send packet routines. Most drivers allow you to send several 640 * packets at once (up to the maxpkts limit). Unfortunately, rather 641 * that accepting them in the form of a linked list, they expect 642 * a contiguous array of pointers to packets. 643 * 644 * For those drivers which use the NDIS scatter/gather DMA mechanism, 645 * we need to perform busdma work here. Those that use map registers 646 * will do the mapping themselves on a buffer by buffer basis. 647 */ 648 649static void 650ndis_start(ifp) 651 struct ifnet *ifp; 652{ 653 struct ndis_softc *sc; 654 struct mbuf *m = NULL; 655 ndis_packet **p0 = NULL, *p = NULL; 656 int pcnt = 0; 657 658 sc = ifp->if_softc; 659 660 NDIS_LOCK(sc); 661 662 p0 = &sc->ndis_txarray[sc->ndis_txidx]; 663 664 while(sc->ndis_txpending) { 665 IF_DEQUEUE(&ifp->if_snd, m); 666 if (m == NULL) 667 break; 668 669 sc->ndis_txarray[sc->ndis_txidx] = NULL; 670 671 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { 672 NDIS_UNLOCK(sc); 673 IF_PREPEND(&ifp->if_snd, m); 674 return; 675 } 676 677 /* 678 * Save pointer to original mbuf 679 * so we can free it later. 680 */ 681 682 (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[0] = 683 (uint32_t *)sc->ndis_txidx; 684 (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[1] = (uint32_t *)m; 685 686 /* 687 * Do scatter/gather processing, if driver requested it. 688 */ 689 if (sc->ndis_sc) { 690 p = sc->ndis_txarray[sc->ndis_txidx]; 691 bus_dmamap_load_mbuf(sc->ndis_ttag, 692 sc->ndis_tmaps[sc->ndis_txidx], m, 693 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); 694 bus_dmamap_sync(sc->ndis_ttag, 695 sc->ndis_tmaps[sc->ndis_txidx], 696 BUS_DMASYNC_PREREAD); 697 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; 698 } 699 700 NDIS_INC(sc); 701 sc->ndis_txpending--; 702 703 pcnt++; 704 705 /* 706 * If there's a BPF listener, bounce a copy of this frame 707 * to him. 708 */ 709 710 BPF_MTAP(ifp, m); 711 712 /* 713 * The array that p0 points to must appear contiguous, 714 * so we must not wrap past the end of sc->ndis_txarray[]. 715 * If it looks like we're about to wrap, break out here 716 * so the this batch of packets can be transmitted, then 717 * wait for txeof to ask us to send the rest. 718 */ 719 720 if (sc->ndis_txidx == 0) 721 break; 722 } 723 724 if (sc->ndis_txpending == 0) 725 ifp->if_flags |= IFF_OACTIVE; 726 727 /* 728 * Set a timeout in case the chip goes out to lunch. 729 */ 730 ifp->if_timer = 5; 731 732 NDIS_UNLOCK(sc); 733 734 ndis_send_packets(sc, p0, pcnt); 735 736 return; 737} 738 739static void 740ndis_init(xsc) 741 void *xsc; 742{ 743 struct ndis_softc *sc = xsc; 744 struct ifnet *ifp = &sc->arpcom.ac_if; 745 int i, error; 746 uint32_t ndis_filter = 0; 747 748 /*NDIS_LOCK(sc);*/ 749 750 /* 751 * Cancel pending I/O and free all RX/TX buffers. 752 */ 753 ndis_reset(sc); 754 ndis_stop(sc); 755 ndis_init_nic(sc); 756 757 /* Init our MAC address */ 758#ifdef notdef 759 /* 760 * Program the multicast filter, if necessary. 761 */ 762 ndis_setmulti(sc); 763#endif 764 765 /* Program the packet filter */ 766 767 ndis_filter = NDIS_PACKET_TYPE_DIRECTED; 768 769 if (ifp->if_flags & IFF_BROADCAST) 770 ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; 771 772 if (ifp->if_flags & IFF_PROMISC) 773 ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; 774 775 if (ifp->if_flags & IFF_MULTICAST) 776 ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; 777 778 i = sizeof(ndis_filter); 779 780 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 781 &ndis_filter, &i); 782 783 if (error) 784 printf ("set filter failed: %d\n", error); 785 786 sc->ndis_txidx = 0; 787 sc->ndis_txpending = sc->ndis_maxpkts; 788 789 ifp->if_flags |= IFF_RUNNING; 790 ifp->if_flags &= ~IFF_OACTIVE; 791 792 if (sc->ndis_chars.nmc_checkhang_func != NULL) 793 sc->ndis_stat_ch = timeout(ndis_tick, sc, 794 hz * sc->ndis_block.nmb_checkforhangsecs); 795 796 /*NDIS_UNLOCK(sc);*/ 797 798 return; 799} 800 801/* 802 * Set media options. 803 */ 804static int 805ndis_ifmedia_upd(ifp) 806 struct ifnet *ifp; 807{ 808 struct ndis_softc *sc; 809 810 sc = ifp->if_softc; 811 812 if (ifp->if_flags & IFF_UP) 813 ndis_init(sc); 814 815 return(0); 816} 817 818/* 819 * Report current media status. 820 */ 821static void 822ndis_ifmedia_sts(ifp, ifmr) 823 struct ifnet *ifp; 824 struct ifmediareq *ifmr; 825{ 826 struct ndis_softc *sc; 827 uint32_t media_info; 828 ndis_media_state linkstate; 829 int error, len; 830 831 sc = ifp->if_softc; 832 833 len = sizeof(linkstate); 834 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, 835 (void *)&linkstate, &len); 836 837 len = sizeof(media_info); 838 error = ndis_get_info(sc, OID_GEN_LINK_SPEED, 839 (void *)&media_info, &len); 840 841 ifmr->ifm_status = IFM_AVALID; 842 ifmr->ifm_active = IFM_ETHER; 843 844 if (linkstate == nmc_connected) 845 ifmr->ifm_status |= IFM_ACTIVE; 846 847 switch(media_info) { 848 case 100000: 849 ifmr->ifm_active |= IFM_10_T; 850 break; 851 case 1000000: 852 ifmr->ifm_active |= IFM_100_TX; 853 break; 854 case 10000000: 855 ifmr->ifm_active |= IFM_1000_T; 856 break; 857 default: 858 printf("ndis%d: unknown speed: %d\n", 859 sc->ndis_unit, media_info); 860 break; 861 } 862 863 return; 864} 865 866static int 867ndis_ioctl(ifp, command, data) 868 struct ifnet *ifp; 869 u_long command; 870 caddr_t data; 871{ 872 struct ndis_softc *sc = ifp->if_softc; 873 struct ifreq *ifr = (struct ifreq *) data; 874 int error = 0; 875 876 /*NDIS_LOCK(sc);*/ 877 878 switch(command) { 879 case SIOCSIFFLAGS: 880 if (ifp->if_flags & IFF_UP) { 881 ndis_init(sc); 882 } else { 883 if (ifp->if_flags & IFF_RUNNING) 884 ndis_stop(sc); 885 } 886 error = 0; 887 break; 888 case SIOCADDMULTI: 889 case SIOCDELMULTI: 890 ndis_setmulti(sc); 891 error = 0; 892 break; 893 case SIOCGIFMEDIA: 894 case SIOCSIFMEDIA: 895 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); 896 break; 897 default: 898 error = ether_ioctl(ifp, command, data); 899 break; 900 } 901 902 /*NDIS_UNLOCK(sc);*/ 903 904 return(error); 905} 906 907static void 908ndis_watchdog(ifp) 909 struct ifnet *ifp; 910{ 911 struct ndis_softc *sc; 912 913 sc = ifp->if_softc; 914 915 NDIS_LOCK(sc); 916 ifp->if_oerrors++; 917 printf("ndis%d: watchdog timeout\n", sc->ndis_unit); 918 919 ndis_reset(sc); 920 921 if (ifp->if_snd.ifq_head != NULL) 922 ndis_start(ifp); 923 NDIS_UNLOCK(sc); 924 925 return; 926} 927 928/* 929 * Stop the adapter and free any mbufs allocated to the 930 * RX and TX lists. 931 */ 932static void 933ndis_stop(sc) 934 struct ndis_softc *sc; 935{ 936 struct ifnet *ifp; 937 938/* NDIS_LOCK(sc);*/ 939 ifp = &sc->arpcom.ac_if; 940 ifp->if_timer = 0; 941 942 untimeout(ndis_tick, sc, sc->ndis_stat_ch); 943 944 ndis_halt_nic(sc); 945 946 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 947 /*NDIS_UNLOCK(sc);*/ 948 949 return; 950} 951 952/* 953 * Stop all chip I/O so that the kernel's probe routines don't 954 * get confused by errant DMAs when rebooting. 955 */ 956static void 957ndis_shutdown(dev) 958 device_t dev; 959{ 960 struct ndis_softc *sc; 961 962 sc = device_get_softc(dev); 963 ndis_shutdown_nic(sc); 964 965 return; 966}
| 329 sysctl_ctx_init(&sc->ndis_ctx); 330 331 /* Create sysctl registry nodes */ 332 ndis_create_sysctls(sc); 333 334 /* Set up driver image in memory. */ 335 ndis_load_driver((vm_offset_t)img, sc); 336 337 /* Do resource conversion. */ 338 ndis_convert_res(sc); 339 340 /* Install our RX and TX interrupt handlers. */ 341 sc->ndis_block.nmb_senddone_func = ndis_txeof; 342 sc->ndis_block.nmb_pktind_func = ndis_rxeof; 343 344 /* Call driver's init routine. */ 345 if (ndis_init_nic(sc)) { 346 printf ("ndis%d: init handler failed\n", sc->ndis_unit); 347 error = ENXIO; 348 goto fail; 349 } 350 351 /* Reset the adapter. */ 352 ndis_reset(sc); 353 354 /* 355 * Get station address from the driver. 356 */ 357 len = sizeof(eaddr); 358 ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); 359 360 /* 361 * An NDIS device was detected. Inform the world. 362 */ 363 printf("ndis%d: Ethernet address: %6D\n", unit, eaddr, ":"); 364 365 sc->ndis_unit = unit; 366 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 367 368 /* 369 * Figure out of we're allowed to use multipacket sends 370 * with this driver, and if so, how many. 371 */ 372 373 if (sc->ndis_chars.nmc_sendsingle_func) 374 sc->ndis_maxpkts = 1; 375 else { 376 len = sizeof(sc->ndis_maxpkts); 377 ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, 378 &sc->ndis_maxpkts, &len); 379 sc->ndis_txarray = malloc(sizeof(ndis_packet *) * 380 sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT); 381 bzero((char *)sc->ndis_txarray, sizeof(ndis_packet *) * 382 sc->ndis_maxpkts); 383 } 384 385 sc->ndis_txpending = sc->ndis_maxpkts; 386 387 sc->ndis_oidcnt = 0; 388 /* Get supported oid list. */ 389 ndis_get_supported_oids(sc, &sc->ndis_oids, &sc->ndis_oidcnt); 390 391 /* If the NDIS module requested scatter/gather, init maps. */ 392 if (sc->ndis_sc) 393 ndis_init_dma(sc); 394 395 ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, 396 ndis_ifmedia_sts); 397 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 398 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 399 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); 400 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 401 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 402 ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); 403 404 ifp = &sc->arpcom.ac_if; 405 ifp->if_softc = sc; 406 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 407 ifp->if_mtu = ETHERMTU; 408 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 409 ifp->if_ioctl = ndis_ioctl; 410 ifp->if_output = ether_output; 411 ifp->if_start = ndis_start; 412 ifp->if_watchdog = ndis_watchdog; 413 ifp->if_init = ndis_init; 414 ifp->if_baudrate = 10000000; 415 ifp->if_snd.ifq_maxlen = 50; 416 417 /* 418 * Call MI attach routine. 419 */ 420 ether_ifattach(ifp, eaddr); 421 422 /* Hook interrupt last to avoid having to lock softc */ 423 error = bus_setup_intr(dev, sc->ndis_irq, INTR_TYPE_NET, 424 ndis_intr, sc, &sc->ndis_intrhand); 425 426 if (error) { 427 printf("ndis%d: couldn't set up irq\n", unit); 428 ether_ifdetach(ifp); 429 goto fail; 430 } 431 432fail: 433 if (error) 434 ndis_detach(dev); 435 436 return(error); 437} 438 439/* 440 * Shutdown hardware and free up resources. This can be called any 441 * time after the mutex has been initialized. It is called in both 442 * the error case in attach and the normal detach case so it needs 443 * to be careful about only freeing resources that have actually been 444 * allocated. 445 */ 446static int 447ndis_detach(dev) 448 device_t dev; 449{ 450 struct ndis_softc *sc; 451 struct ifnet *ifp; 452 453 sc = device_get_softc(dev); 454 KASSERT(mtx_initialized(&sc->ndis_mtx), ("ndis mutex not initialized")); 455 NDIS_LOCK(sc); 456 ifp = &sc->arpcom.ac_if; 457 458 if (device_is_attached(dev)) { 459 NDIS_UNLOCK(sc); 460 ndis_stop(sc); 461 ether_ifdetach(ifp); 462 NDIS_LOCK(sc); 463 } 464 465 bus_generic_detach(dev); 466 467 if (sc->ndis_intrhand) 468 bus_teardown_intr(dev, sc->ndis_irq, sc->ndis_intrhand); 469 if (sc->ndis_irq) 470 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ndis_irq); 471 if (sc->ndis_res_io) 472 bus_release_resource(dev, SYS_RES_IOPORT, 473 sc->ndis_io_rid, sc->ndis_res_io); 474 if (sc->ndis_res_mem) 475 bus_release_resource(dev, SYS_RES_MEMORY, 476 sc->ndis_mem_rid, sc->ndis_res_mem); 477 478 if (sc->ndis_sc) 479 ndis_destroy_dma(sc); 480 481 ndis_unload_driver((void *)ifp); 482 483 bus_dma_tag_destroy(sc->ndis_parent_tag); 484 485 sysctl_ctx_free(&sc->ndis_ctx); 486 487 NDIS_UNLOCK(sc); 488 mtx_destroy(&sc->ndis_mtx); 489 490 return(0); 491} 492 493/* 494 * A frame has been uploaded: pass the resulting mbuf chain up to 495 * the higher level protocols. 496 */ 497__stdcall static void 498ndis_rxeof(adapter, packets, pktcnt) 499 ndis_handle adapter; 500 ndis_packet **packets; 501 uint32_t pktcnt; 502{ 503 struct ndis_softc *sc; 504 ndis_miniport_block *block; 505 ndis_packet *p; 506 struct ifnet *ifp; 507 struct mbuf *m0; 508 int i; 509 510 block = (ndis_miniport_block *)adapter; 511 sc = (struct ndis_softc *)(block->nmb_ifp); 512 ifp = block->nmb_ifp; 513 514 for (i = 0; i < pktcnt; i++) { 515 p = packets[i]; 516 /* Stash the softc here so ptom can use it. */ 517 p->np_rsvd[0] = (uint32_t *)sc; 518 if (ndis_ptom(&m0, p)) { 519 printf ("ndis%d: ptom failed\n", sc->ndis_unit); 520 ndis_return_packet(sc, p); 521 } else { 522 m0->m_pkthdr.rcvif = ifp; 523 ifp->if_ipackets++; 524 (*ifp->if_input)(ifp, m0); 525 } 526 } 527 528 return; 529} 530 531/* 532 * A frame was downloaded to the chip. It's safe for us to clean up 533 * the list buffers. 534 */ 535__stdcall static void 536ndis_txeof(adapter, packet, status) 537 ndis_handle adapter; 538 ndis_packet *packet; 539 ndis_status status; 540 541{ 542 struct ndis_softc *sc; 543 ndis_miniport_block *block; 544 struct ifnet *ifp; 545 int idx; 546 struct mbuf *m; 547 548 block = (ndis_miniport_block *)adapter; 549 sc = (struct ndis_softc *)block->nmb_ifp; 550 ifp = block->nmb_ifp; 551 552 if (packet->np_rsvd[1] == NULL) 553 panic("NDIS driver corrupted reserved packet fields"); 554 555 NDIS_LOCK(sc); 556 557 m = (struct mbuf *)packet->np_rsvd[1]; 558 idx = (int)packet->np_rsvd[0]; 559 ifp->if_opackets++; 560 m_freem(m); 561 if (sc->ndis_sc) 562 bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]); 563 564 ndis_free_packet(packet); 565 sc->ndis_txarray[idx] = NULL; 566 sc->ndis_txpending++; 567 568 ifp->if_timer = 0; 569 ifp->if_flags &= ~IFF_OACTIVE; 570 571 NDIS_UNLOCK(sc); 572 573 if (ifp->if_snd.ifq_head != NULL) 574 ndis_start(ifp); 575 576 return; 577} 578 579static void 580ndis_intr(arg) 581 void *arg; 582{ 583 struct ndis_softc *sc; 584 struct ifnet *ifp; 585 int is_our_intr = 0; 586 int call_isr = 0; 587 588 sc = arg; 589 /*NDIS_LOCK(sc);*/ 590 ifp = &sc->arpcom.ac_if; 591 592/* 593 if (!(ifp->if_flags & IFF_UP)) { 594 NDIS_UNLOCK(sc); 595 return; 596 } 597*/ 598 ndis_isr(sc, &is_our_intr, &call_isr); 599 600 if (is_our_intr || call_isr) 601 ndis_intrhand(sc); 602 603 if (ifp->if_snd.ifq_head != NULL) 604 ndis_start(ifp); 605 606 /*NDIS_UNLOCK(sc);*/ 607 608 return; 609} 610 611static void 612ndis_tick(xsc) 613 void *xsc; 614{ 615 struct ndis_softc *sc; 616 __stdcall ndis_checkforhang_handler hangfunc; 617 uint8_t rval; 618 619 sc = xsc; 620 NDIS_LOCK(sc); 621 622 hangfunc = sc->ndis_chars.nmc_checkhang_func; 623 624 if (hangfunc != NULL) { 625 rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx); 626 if (rval == TRUE) 627 ndis_reset_nic(sc); 628 } 629 630 sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * 631 sc->ndis_block.nmb_checkforhangsecs); 632 633 NDIS_UNLOCK(sc); 634 635 return; 636} 637 638static void 639ndis_map_sclist(arg, segs, nseg, mapsize, error) 640 void *arg; 641 bus_dma_segment_t *segs; 642 int nseg; 643 bus_size_t mapsize; 644 int error; 645 646{ 647 struct ndis_sc_list *sclist; 648 int i; 649 650 if (error || arg == NULL) 651 return; 652 653 sclist = arg; 654 655 sclist->nsl_frags = nseg; 656 657 for (i = 0; i < nseg; i++) { 658 sclist->nsl_elements[i].nse_addr.np_quad = segs[i].ds_addr; 659 sclist->nsl_elements[i].nse_len = segs[i].ds_len; 660 } 661 662 return; 663} 664 665/* 666 * Main transmit routine. To make NDIS drivers happy, we need to 667 * transform mbuf chains into NDIS packets and feed them to the 668 * send packet routines. Most drivers allow you to send several 669 * packets at once (up to the maxpkts limit). Unfortunately, rather 670 * that accepting them in the form of a linked list, they expect 671 * a contiguous array of pointers to packets. 672 * 673 * For those drivers which use the NDIS scatter/gather DMA mechanism, 674 * we need to perform busdma work here. Those that use map registers 675 * will do the mapping themselves on a buffer by buffer basis. 676 */ 677 678static void 679ndis_start(ifp) 680 struct ifnet *ifp; 681{ 682 struct ndis_softc *sc; 683 struct mbuf *m = NULL; 684 ndis_packet **p0 = NULL, *p = NULL; 685 int pcnt = 0; 686 687 sc = ifp->if_softc; 688 689 NDIS_LOCK(sc); 690 691 p0 = &sc->ndis_txarray[sc->ndis_txidx]; 692 693 while(sc->ndis_txpending) { 694 IF_DEQUEUE(&ifp->if_snd, m); 695 if (m == NULL) 696 break; 697 698 sc->ndis_txarray[sc->ndis_txidx] = NULL; 699 700 if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { 701 NDIS_UNLOCK(sc); 702 IF_PREPEND(&ifp->if_snd, m); 703 return; 704 } 705 706 /* 707 * Save pointer to original mbuf 708 * so we can free it later. 709 */ 710 711 (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[0] = 712 (uint32_t *)sc->ndis_txidx; 713 (sc->ndis_txarray[sc->ndis_txidx])->np_rsvd[1] = (uint32_t *)m; 714 715 /* 716 * Do scatter/gather processing, if driver requested it. 717 */ 718 if (sc->ndis_sc) { 719 p = sc->ndis_txarray[sc->ndis_txidx]; 720 bus_dmamap_load_mbuf(sc->ndis_ttag, 721 sc->ndis_tmaps[sc->ndis_txidx], m, 722 ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); 723 bus_dmamap_sync(sc->ndis_ttag, 724 sc->ndis_tmaps[sc->ndis_txidx], 725 BUS_DMASYNC_PREREAD); 726 p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; 727 } 728 729 NDIS_INC(sc); 730 sc->ndis_txpending--; 731 732 pcnt++; 733 734 /* 735 * If there's a BPF listener, bounce a copy of this frame 736 * to him. 737 */ 738 739 BPF_MTAP(ifp, m); 740 741 /* 742 * The array that p0 points to must appear contiguous, 743 * so we must not wrap past the end of sc->ndis_txarray[]. 744 * If it looks like we're about to wrap, break out here 745 * so the this batch of packets can be transmitted, then 746 * wait for txeof to ask us to send the rest. 747 */ 748 749 if (sc->ndis_txidx == 0) 750 break; 751 } 752 753 if (sc->ndis_txpending == 0) 754 ifp->if_flags |= IFF_OACTIVE; 755 756 /* 757 * Set a timeout in case the chip goes out to lunch. 758 */ 759 ifp->if_timer = 5; 760 761 NDIS_UNLOCK(sc); 762 763 ndis_send_packets(sc, p0, pcnt); 764 765 return; 766} 767 768static void 769ndis_init(xsc) 770 void *xsc; 771{ 772 struct ndis_softc *sc = xsc; 773 struct ifnet *ifp = &sc->arpcom.ac_if; 774 int i, error; 775 uint32_t ndis_filter = 0; 776 777 /*NDIS_LOCK(sc);*/ 778 779 /* 780 * Cancel pending I/O and free all RX/TX buffers. 781 */ 782 ndis_reset(sc); 783 ndis_stop(sc); 784 ndis_init_nic(sc); 785 786 /* Init our MAC address */ 787#ifdef notdef 788 /* 789 * Program the multicast filter, if necessary. 790 */ 791 ndis_setmulti(sc); 792#endif 793 794 /* Program the packet filter */ 795 796 ndis_filter = NDIS_PACKET_TYPE_DIRECTED; 797 798 if (ifp->if_flags & IFF_BROADCAST) 799 ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; 800 801 if (ifp->if_flags & IFF_PROMISC) 802 ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; 803 804 if (ifp->if_flags & IFF_MULTICAST) 805 ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; 806 807 i = sizeof(ndis_filter); 808 809 error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, 810 &ndis_filter, &i); 811 812 if (error) 813 printf ("set filter failed: %d\n", error); 814 815 sc->ndis_txidx = 0; 816 sc->ndis_txpending = sc->ndis_maxpkts; 817 818 ifp->if_flags |= IFF_RUNNING; 819 ifp->if_flags &= ~IFF_OACTIVE; 820 821 if (sc->ndis_chars.nmc_checkhang_func != NULL) 822 sc->ndis_stat_ch = timeout(ndis_tick, sc, 823 hz * sc->ndis_block.nmb_checkforhangsecs); 824 825 /*NDIS_UNLOCK(sc);*/ 826 827 return; 828} 829 830/* 831 * Set media options. 832 */ 833static int 834ndis_ifmedia_upd(ifp) 835 struct ifnet *ifp; 836{ 837 struct ndis_softc *sc; 838 839 sc = ifp->if_softc; 840 841 if (ifp->if_flags & IFF_UP) 842 ndis_init(sc); 843 844 return(0); 845} 846 847/* 848 * Report current media status. 849 */ 850static void 851ndis_ifmedia_sts(ifp, ifmr) 852 struct ifnet *ifp; 853 struct ifmediareq *ifmr; 854{ 855 struct ndis_softc *sc; 856 uint32_t media_info; 857 ndis_media_state linkstate; 858 int error, len; 859 860 sc = ifp->if_softc; 861 862 len = sizeof(linkstate); 863 error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS, 864 (void *)&linkstate, &len); 865 866 len = sizeof(media_info); 867 error = ndis_get_info(sc, OID_GEN_LINK_SPEED, 868 (void *)&media_info, &len); 869 870 ifmr->ifm_status = IFM_AVALID; 871 ifmr->ifm_active = IFM_ETHER; 872 873 if (linkstate == nmc_connected) 874 ifmr->ifm_status |= IFM_ACTIVE; 875 876 switch(media_info) { 877 case 100000: 878 ifmr->ifm_active |= IFM_10_T; 879 break; 880 case 1000000: 881 ifmr->ifm_active |= IFM_100_TX; 882 break; 883 case 10000000: 884 ifmr->ifm_active |= IFM_1000_T; 885 break; 886 default: 887 printf("ndis%d: unknown speed: %d\n", 888 sc->ndis_unit, media_info); 889 break; 890 } 891 892 return; 893} 894 895static int 896ndis_ioctl(ifp, command, data) 897 struct ifnet *ifp; 898 u_long command; 899 caddr_t data; 900{ 901 struct ndis_softc *sc = ifp->if_softc; 902 struct ifreq *ifr = (struct ifreq *) data; 903 int error = 0; 904 905 /*NDIS_LOCK(sc);*/ 906 907 switch(command) { 908 case SIOCSIFFLAGS: 909 if (ifp->if_flags & IFF_UP) { 910 ndis_init(sc); 911 } else { 912 if (ifp->if_flags & IFF_RUNNING) 913 ndis_stop(sc); 914 } 915 error = 0; 916 break; 917 case SIOCADDMULTI: 918 case SIOCDELMULTI: 919 ndis_setmulti(sc); 920 error = 0; 921 break; 922 case SIOCGIFMEDIA: 923 case SIOCSIFMEDIA: 924 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); 925 break; 926 default: 927 error = ether_ioctl(ifp, command, data); 928 break; 929 } 930 931 /*NDIS_UNLOCK(sc);*/ 932 933 return(error); 934} 935 936static void 937ndis_watchdog(ifp) 938 struct ifnet *ifp; 939{ 940 struct ndis_softc *sc; 941 942 sc = ifp->if_softc; 943 944 NDIS_LOCK(sc); 945 ifp->if_oerrors++; 946 printf("ndis%d: watchdog timeout\n", sc->ndis_unit); 947 948 ndis_reset(sc); 949 950 if (ifp->if_snd.ifq_head != NULL) 951 ndis_start(ifp); 952 NDIS_UNLOCK(sc); 953 954 return; 955} 956 957/* 958 * Stop the adapter and free any mbufs allocated to the 959 * RX and TX lists. 960 */ 961static void 962ndis_stop(sc) 963 struct ndis_softc *sc; 964{ 965 struct ifnet *ifp; 966 967/* NDIS_LOCK(sc);*/ 968 ifp = &sc->arpcom.ac_if; 969 ifp->if_timer = 0; 970 971 untimeout(ndis_tick, sc, sc->ndis_stat_ch); 972 973 ndis_halt_nic(sc); 974 975 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 976 /*NDIS_UNLOCK(sc);*/ 977 978 return; 979} 980 981/* 982 * Stop all chip I/O so that the kernel's probe routines don't 983 * get confused by errant DMAs when rebooting. 984 */ 985static void 986ndis_shutdown(dev) 987 device_t dev; 988{ 989 struct ndis_softc *sc; 990 991 sc = device_get_softc(dev); 992 ndis_shutdown_nic(sc); 993 994 return; 995}
|