Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / netif / snc / if_snc.c
1 /*
2  * Copyright (c) 1995, David Greenman
3  * 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 unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/snc/if_snc.c,v 1.2.2.1 2000/10/21 03:30:03 nyan Exp $
28  */
29
30 /*
31  *      National Semiconductor  DP8393X SONIC Driver
32  *
33  *      This is the bus independent attachment on FreeBSD 4.x
34  *              written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp>
35  */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/sockio.h>
40 #include <sys/mbuf.h>
41 #include <sys/socket.h>
42 #include <sys/syslog.h>
43
44 #include <sys/module.h>
45 #include <sys/bus.h>
46 #include <machine/bus.h>
47 #include <sys/rman.h>
48 #include <machine/resource.h>
49
50 #include <net/ethernet.h>
51 #include <net/if.h>
52 #include <net/if_arp.h>
53 #include <net/if_media.h>
54 #include <net/if_dl.h>
55 #include <net/if_mib.h>
56
57 #include <net/bpf.h>
58 #include "opt_bdg.h"
59 #ifdef BRIDGE
60 #include <net/bridge.h>
61 #endif
62
63 #include <dev/snc/dp83932reg.h>
64 #include <dev/snc/dp83932var.h>
65 #include <dev/snc/dp83932subr.h>
66 #include <dev/snc/if_sncreg.h>
67 #include <dev/snc/if_sncvar.h>
68
69 /* devclass for "snc" */
70 devclass_t snc_devclass;
71
72 /****************************************************************
73   Resource management functions
74  ****************************************************************/
75
76 /*
77  * Allocate a port resource with the given resource id.
78  */
79 int
80 snc_alloc_port(dev, rid)
81         device_t dev;
82         int rid;
83 {
84         struct snc_softc *sc = device_get_softc(dev);
85         struct resource *res;
86
87         res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
88                                  0ul, ~0ul, SNEC_NREGS, RF_ACTIVE);
89         if (res) {
90                 sc->ioport = res;
91                 sc->ioport_rid = rid;
92                 sc->sc_iot = rman_get_bustag(res);
93                 sc->sc_ioh = rman_get_bushandle(res);
94                 return (0);
95         } else {
96                 device_printf(dev, "can't assign port\n");
97                 return (ENOENT);
98         }
99 }
100
101 /*
102  * Allocate a memory resource with the given resource id.
103  */
104 int
105 snc_alloc_memory(dev, rid)
106         device_t dev;
107         int rid;
108 {
109         struct snc_softc *sc = device_get_softc(dev);
110         struct resource *res;
111
112         res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
113                                  0ul, ~0ul, SNEC_NMEMS, RF_ACTIVE);
114         if (res) {
115                 sc->iomem = res;
116                 sc->iomem_rid = rid;
117                 sc->sc_memt = rman_get_bustag(res);
118                 sc->sc_memh = rman_get_bushandle(res);
119                 return (0);
120         } else {
121                 device_printf(dev, "can't assign memory\n");
122                 return (ENOENT);
123         }
124 }
125
126 /*
127  * Allocate an irq resource with the given resource id.
128  */
129 int
130 snc_alloc_irq(dev, rid, flags)
131         device_t dev;
132         int rid;
133         int flags;
134 {
135         struct snc_softc *sc = device_get_softc(dev);
136         struct resource *res;
137
138         res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
139                                  0ul, ~0ul, 1, (RF_ACTIVE | flags));
140         if (res) {
141                 sc->irq = res;
142                 sc->irq_rid = rid;
143                 return (0);
144         } else {
145                 device_printf(dev, "can't assign irq\n");
146                 return (ENOENT);
147         }
148 }
149
150 /*
151  * Release all resources
152  */
153 void
154 snc_release_resources(dev)
155         device_t dev;
156 {
157         struct snc_softc *sc = device_get_softc(dev);
158
159         if (sc->ioport) {
160                 bus_release_resource(dev, SYS_RES_IOPORT,
161                                      sc->ioport_rid, sc->ioport);
162                 sc->ioport = 0;
163         }
164         if (sc->iomem) {
165                 bus_release_resource(dev, SYS_RES_MEMORY,
166                                      sc->iomem_rid, sc->iomem);
167                 sc->iomem = 0;
168         }
169         if (sc->irq) {
170                 bus_release_resource(dev, SYS_RES_IRQ,
171                                      sc->irq_rid, sc->irq);
172                 sc->irq = 0;
173         }
174 }
175
176 /****************************************************************
177   Probe routine
178  ****************************************************************/
179
180 int
181 snc_probe(dev, type)
182      device_t dev;
183      int type;
184 {
185         struct snc_softc *sc = device_get_softc(dev);
186
187         return snc_nec16_detectsubr(sc->sc_iot, sc->sc_ioh,
188                                     sc->sc_memt, sc->sc_memh,
189                                     rman_get_start(sc->irq),
190                                     rman_get_start(sc->iomem),
191                                     type);
192 }
193
194 /****************************************************************
195   Attach routine
196  ****************************************************************/
197
198 int
199 snc_attach(dev)
200         device_t dev;
201 {
202         struct snc_softc *sc = device_get_softc(dev);
203         u_int8_t myea[ETHER_ADDR_LEN];
204
205         if (snc_nec16_register_irq(sc, rman_get_start(sc->irq)) == 0 || 
206             snc_nec16_register_mem(sc, rman_get_start(sc->iomem)) == 0) {
207                 snc_release_resources(dev);
208                 return(ENOENT);
209         }
210
211         snc_nec16_get_enaddr(sc->sc_iot, sc->sc_ioh, myea);
212         device_printf(dev, "%s Ethernet\n", snc_nec16_detect_type(myea));
213
214         sc->sc_dev = dev;
215
216         sc->sncr_dcr = DCR_SYNC | DCR_WAIT0 |
217             DCR_DMABLOCK | DCR_RFT16 | DCR_TFT28;
218         sc->sncr_dcr2 = 0;      /* XXX */
219         sc->bitmode = 0;        /* 16 bit card */
220
221         sc->sc_nic_put = snc_nec16_nic_put;
222         sc->sc_nic_get = snc_nec16_nic_get;
223         sc->sc_writetodesc = snc_nec16_writetodesc;
224         sc->sc_readfromdesc = snc_nec16_readfromdesc;
225         sc->sc_copytobuf = snc_nec16_copytobuf;
226         sc->sc_copyfrombuf = snc_nec16_copyfrombuf;
227         sc->sc_zerobuf = snc_nec16_zerobuf;
228
229         /* sncsetup returns 1 if something fails */
230         if (sncsetup(sc, myea)) {
231                 snc_release_resources(dev);
232                 return(ENOENT);
233         }
234
235         sncconfig(sc, NULL, 0, 0, myea);
236
237         return 0;
238 }
239
240 /****************************************************************
241   Shutdown routine
242  ****************************************************************/
243
244 void
245 snc_shutdown(dev)
246         device_t dev;
247 {
248         sncshutdown(device_get_softc(dev));
249 }