1139749Simp/*- 266550Snyan * Copyright (c) 1995, David Greenman 366550Snyan * All rights reserved. 466550Snyan * 566550Snyan * Redistribution and use in source and binary forms, with or without 666550Snyan * modification, are permitted provided that the following conditions 766550Snyan * are met: 866550Snyan * 1. Redistributions of source code must retain the above copyright 966550Snyan * notice unmodified, this list of conditions, and the following 1066550Snyan * disclaimer. 1166550Snyan * 2. Redistributions in binary form must reproduce the above copyright 1266550Snyan * notice, this list of conditions and the following disclaimer in the 1366550Snyan * documentation and/or other materials provided with the distribution. 1466550Snyan * 1566550Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1666550Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1766550Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1866550Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1966550Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2066550Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2166550Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2266550Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2366550Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2466550Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2566550Snyan * SUCH DAMAGE. 2666550Snyan * 2766550Snyan */ 2866550Snyan 29119419Sobrien#include <sys/cdefs.h> 30119419Sobrien__FBSDID("$FreeBSD$"); 31119419Sobrien 3266550Snyan/* 3366550Snyan * National Semiconductor DP8393X SONIC Driver 3466550Snyan * 3566550Snyan * This is the bus independent attachment on FreeBSD 4.x 3666550Snyan * written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp> 3766550Snyan */ 3866550Snyan 3966550Snyan#include <sys/param.h> 4066550Snyan#include <sys/socket.h> 4166550Snyan 4266550Snyan#include <sys/bus.h> 4366550Snyan#include <machine/bus.h> 4466550Snyan#include <sys/rman.h> 4566550Snyan#include <machine/resource.h> 4666550Snyan 4766550Snyan#include <net/ethernet.h> 4866550Snyan#include <net/if.h> 4966550Snyan#include <net/if_arp.h> 5066550Snyan#include <net/if_media.h> 5166550Snyan 5266550Snyan#include <dev/snc/dp83932reg.h> 5366550Snyan#include <dev/snc/dp83932var.h> 5466550Snyan#include <dev/snc/dp83932subr.h> 5566550Snyan#include <dev/snc/if_sncreg.h> 5666550Snyan#include <dev/snc/if_sncvar.h> 5766550Snyan 5866550Snyan/* devclass for "snc" */ 5966550Snyandevclass_t snc_devclass; 6066550Snyan 6166550Snyan/**************************************************************** 6266550Snyan Resource management functions 6366550Snyan ****************************************************************/ 6466550Snyan 6566550Snyan/* 6666550Snyan * Allocate a port resource with the given resource id. 6766550Snyan */ 6866550Snyanint 69242871Snyansnc_alloc_port(device_t dev, int rid) 7066550Snyan{ 7166550Snyan struct snc_softc *sc = device_get_softc(dev); 7266550Snyan struct resource *res; 7366550Snyan 7466550Snyan res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 7566550Snyan 0ul, ~0ul, SNEC_NREGS, RF_ACTIVE); 7666550Snyan if (res) { 7766550Snyan sc->ioport = res; 7866550Snyan sc->ioport_rid = rid; 7966550Snyan sc->sc_iot = rman_get_bustag(res); 8066550Snyan sc->sc_ioh = rman_get_bushandle(res); 8166550Snyan return (0); 8266550Snyan } else { 8366581Snyan device_printf(dev, "can't assign port\n"); 8466550Snyan return (ENOENT); 8566550Snyan } 8666550Snyan} 8766550Snyan 8866550Snyan/* 8966550Snyan * Allocate a memory resource with the given resource id. 9066550Snyan */ 9166550Snyanint 92242871Snyansnc_alloc_memory(device_t dev, int rid) 9366550Snyan{ 9466550Snyan struct snc_softc *sc = device_get_softc(dev); 9566550Snyan struct resource *res; 9666550Snyan 9766550Snyan res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 9866550Snyan 0ul, ~0ul, SNEC_NMEMS, RF_ACTIVE); 9966550Snyan if (res) { 10066550Snyan sc->iomem = res; 10166550Snyan sc->iomem_rid = rid; 10266550Snyan sc->sc_memt = rman_get_bustag(res); 10366550Snyan sc->sc_memh = rman_get_bushandle(res); 10466550Snyan return (0); 10566550Snyan } else { 10666581Snyan device_printf(dev, "can't assign memory\n"); 10766550Snyan return (ENOENT); 10866550Snyan } 10966550Snyan} 11066550Snyan 11166550Snyan/* 11266550Snyan * Allocate an irq resource with the given resource id. 11366550Snyan */ 11466550Snyanint 115242871Snyansnc_alloc_irq(device_t dev, int rid, int flags) 11666550Snyan{ 11766550Snyan struct snc_softc *sc = device_get_softc(dev); 11866550Snyan struct resource *res; 11966550Snyan 120127135Snjl res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | flags); 12166550Snyan if (res) { 12266550Snyan sc->irq = res; 12366550Snyan sc->irq_rid = rid; 12466550Snyan return (0); 12566550Snyan } else { 12666581Snyan device_printf(dev, "can't assign irq\n"); 12766550Snyan return (ENOENT); 12866550Snyan } 12966550Snyan} 13066550Snyan 13166550Snyan/* 13266550Snyan * Release all resources 13366550Snyan */ 13466550Snyanvoid 135242871Snyansnc_release_resources(device_t dev) 13666550Snyan{ 13766550Snyan struct snc_softc *sc = device_get_softc(dev); 13866550Snyan 13966550Snyan if (sc->ioport) { 14066550Snyan bus_release_resource(dev, SYS_RES_IOPORT, 14166550Snyan sc->ioport_rid, sc->ioport); 14266550Snyan sc->ioport = 0; 14366550Snyan } 14466550Snyan if (sc->iomem) { 14566550Snyan bus_release_resource(dev, SYS_RES_MEMORY, 14666550Snyan sc->iomem_rid, sc->iomem); 14766550Snyan sc->iomem = 0; 14866550Snyan } 14966550Snyan if (sc->irq) { 15066550Snyan bus_release_resource(dev, SYS_RES_IRQ, 15166550Snyan sc->irq_rid, sc->irq); 15266550Snyan sc->irq = 0; 15366550Snyan } 154181298Sjhb if (sc->sc_ifp) { 155181298Sjhb if_free(sc->sc_ifp); 156181298Sjhb sc->sc_ifp = 0; 157181298Sjhb } 15866550Snyan} 15966550Snyan 16066550Snyan/**************************************************************** 16166550Snyan Probe routine 16266550Snyan ****************************************************************/ 16366550Snyan 16466550Snyanint 165242871Snyansnc_probe(device_t dev, int type) 16666550Snyan{ 16766550Snyan struct snc_softc *sc = device_get_softc(dev); 16866550Snyan 16966550Snyan return snc_nec16_detectsubr(sc->sc_iot, sc->sc_ioh, 17066550Snyan sc->sc_memt, sc->sc_memh, 17166550Snyan rman_get_start(sc->irq), 17266550Snyan rman_get_start(sc->iomem), 17366550Snyan type); 17466550Snyan} 17566550Snyan 17666550Snyan/**************************************************************** 17766550Snyan Attach routine 17866550Snyan ****************************************************************/ 17966550Snyan 18066550Snyanint 181242871Snyansnc_attach(device_t dev) 18266550Snyan{ 18366550Snyan struct snc_softc *sc = device_get_softc(dev); 18466550Snyan u_int8_t myea[ETHER_ADDR_LEN]; 185181298Sjhb int error; 18666550Snyan 18766550Snyan if (snc_nec16_register_irq(sc, rman_get_start(sc->irq)) == 0 || 18866550Snyan snc_nec16_register_mem(sc, rman_get_start(sc->iomem)) == 0) { 18966550Snyan snc_release_resources(dev); 19066550Snyan return(ENOENT); 19166550Snyan } 19266550Snyan 19366550Snyan snc_nec16_get_enaddr(sc->sc_iot, sc->sc_ioh, myea); 19466550Snyan device_printf(dev, "%s Ethernet\n", snc_nec16_detect_type(myea)); 19566550Snyan 19666550Snyan sc->sc_dev = dev; 19766550Snyan 19866550Snyan sc->sncr_dcr = DCR_SYNC | DCR_WAIT0 | 19966550Snyan DCR_DMABLOCK | DCR_RFT16 | DCR_TFT28; 20066550Snyan sc->sncr_dcr2 = 0; /* XXX */ 20166550Snyan sc->bitmode = 0; /* 16 bit card */ 20266550Snyan 20366550Snyan sc->sc_nic_put = snc_nec16_nic_put; 20466550Snyan sc->sc_nic_get = snc_nec16_nic_get; 20566550Snyan sc->sc_writetodesc = snc_nec16_writetodesc; 20666550Snyan sc->sc_readfromdesc = snc_nec16_readfromdesc; 20766550Snyan sc->sc_copytobuf = snc_nec16_copytobuf; 20866550Snyan sc->sc_copyfrombuf = snc_nec16_copyfrombuf; 20966550Snyan sc->sc_zerobuf = snc_nec16_zerobuf; 21066550Snyan 21166550Snyan /* sncsetup returns 1 if something fails */ 21266550Snyan if (sncsetup(sc, myea)) { 21366550Snyan snc_release_resources(dev); 21466550Snyan return(ENOENT); 21566550Snyan } 21666550Snyan 217181298Sjhb mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, 218181298Sjhb MTX_DEF); 219181298Sjhb callout_init_mtx(&sc->sc_timer, &sc->sc_lock, 0); 220181298Sjhb error = sncconfig(sc, NULL, 0, 0, myea); 221181298Sjhb if (error) { 222181298Sjhb snc_release_resources(dev); 223181298Sjhb mtx_destroy(&sc->sc_lock); 224181298Sjhb return (error); 225181298Sjhb } 22666550Snyan 227181298Sjhb error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, 228181298Sjhb NULL, sncintr, sc, &sc->irq_handle); 229181298Sjhb if (error) { 230181298Sjhb printf("snc_isa_attach: bus_setup_intr() failed\n"); 231181298Sjhb ether_ifdetach(sc->sc_ifp); 232181298Sjhb snc_release_resources(dev); 233181298Sjhb mtx_destroy(&sc->sc_lock); 234181298Sjhb return (error); 235181298Sjhb } 236181298Sjhb 23766550Snyan return 0; 23866550Snyan} 23966550Snyan 24066550Snyan/**************************************************************** 24166550Snyan Shutdown routine 24266550Snyan ****************************************************************/ 24366550Snyan 244194023Savgint 245242871Snyansnc_shutdown(device_t dev) 24666550Snyan{ 247181298Sjhb struct snc_softc *sc = device_get_softc(dev); 248181298Sjhb 249181298Sjhb SNC_LOCK(sc); 250181298Sjhb sncshutdown(sc); 251181298Sjhb SNC_UNLOCK(sc); 252194023Savg 253194023Savg return (0); 25466550Snyan} 255