Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / netif / awi / if_awi_pccard.c
1 /*
2  * Copyright (c) 2000 Atsushi Onoe <onoe@sm.sony.co.jp>
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, 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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD: src/sys/dev/awi/if_awi_pccard.c,v 1.5.2.1 2000/12/07 04:09:39 imp Exp $
26  */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kernel.h>
31 #include <sys/socket.h>
32
33 #include <sys/module.h>
34 #include <sys/bus.h>
35
36 #include <machine/bus.h>
37 #include <machine/resource.h>
38 #include <sys/rman.h>
39  
40 #include <net/if.h> 
41 #include <net/if_arp.h>
42 #include <net/if_media.h>
43 #include <net/ethernet.h>
44 #include <net/if_ieee80211.h>
45
46 #include <machine/clock.h>
47
48 #include <dev/awi/am79c930reg.h>
49 #include <dev/awi/am79c930var.h>
50 #include <dev/awi/awireg.h>
51 #include <dev/awi/awivar.h>
52
53 struct awi_pccard_softc {
54         struct awi_softc        sc_awi;
55
56         u_int8_t        sc_version[AWI_BANNER_LEN];
57         int             sc_intr_mask;
58         void            *sc_intrhand;
59         struct resource *sc_irq_res;
60         int             sc_irq_rid;
61         struct resource *sc_port_res;
62         int             sc_port_rid;
63         struct resource *sc_mem_res;
64         int             sc_mem_rid;
65 };
66
67 /*
68  * Initialize the device - called from Slot manager.
69  */
70 static int
71 awi_pccard_probe(device_t dev)
72 {
73         struct awi_pccard_softc *psc = device_get_softc(dev);
74         struct awi_softc *sc = &psc->sc_awi;
75         int error = 0;
76
77         psc->sc_port_rid = 0;
78         psc->sc_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
79             &psc->sc_port_rid, 0, ~0, 16, RF_ACTIVE);
80         if (!psc->sc_port_res)
81                 return ENOMEM;
82
83         sc->sc_chip.sc_iot = rman_get_bustag(psc->sc_port_res);
84         sc->sc_chip.sc_ioh = rman_get_bushandle(psc->sc_port_res);
85         am79c930_chip_init(&sc->sc_chip, 0);
86         DELAY(1000); 
87
88         awi_read_bytes(sc, AWI_BANNER, psc->sc_version, AWI_BANNER_LEN);
89         if (memcmp(psc->sc_version, "PCnetMobile:", 12) != 0)  {
90                 device_printf(dev, "awi_pccard_probe: bad banner: %12D\n",
91                     psc->sc_version, " ");
92                 error = ENXIO;
93         } else
94                 device_set_desc(dev, psc->sc_version);
95         bus_release_resource(dev, SYS_RES_IOPORT, psc->sc_port_rid,
96             psc->sc_port_res);
97
98         return error;
99 }
100
101 static int
102 awi_pccard_attach(device_t dev)
103 {
104         struct awi_pccard_softc *psc = device_get_softc(dev);
105         struct awi_softc *sc = &psc->sc_awi;
106         struct ifnet *ifp = &sc->sc_ec.ac_if;
107         int error = 0;
108
109         psc->sc_port_res = 0;
110         psc->sc_irq_res = 0;
111         psc->sc_mem_res = 0;
112         psc->sc_intrhand = 0;
113
114         ifp->if_name = device_get_name(dev);
115         ifp->if_unit = device_get_unit(dev);
116         if (ifp->if_name == NULL) {
117                 printf("awi%d: awi_pccard_attach: cannot get device name\n",
118                     device_get_unit(dev));
119                 goto fail;
120         }
121         snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname),
122             "%s%d", ifp->if_name, ifp->if_unit);
123
124         psc->sc_port_rid = 0;
125         psc->sc_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
126             &psc->sc_port_rid, 0, ~0, 16, RF_ACTIVE);
127         if (!psc->sc_port_res) {
128                 device_printf(dev, "awi_pccard_attach: port alloc failed\n");
129                 goto fail;
130         }
131         sc->sc_chip.sc_iot = rman_get_bustag(psc->sc_port_res);
132         sc->sc_chip.sc_ioh = rman_get_bushandle(psc->sc_port_res);
133
134         psc->sc_irq_rid = 0;
135         psc->sc_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
136             &psc->sc_irq_rid, 0, ~0, 1, RF_ACTIVE);
137         if (!psc->sc_irq_res) {
138                 device_printf(dev, "awi_pccard_attach: irq alloc failed\n");
139                 goto fail;
140         }
141
142         psc->sc_mem_rid = 0;
143 #if 1
144         /*
145          * XXX: awi needs to access memory with 8bit,
146          * but pccardd apparently maps memory with MDF_16BITS flag.
147          * So memory mapped access is disabled and use IO port instead.
148          */
149         psc->sc_mem_res = 0;
150 #else
151         psc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
152             &psc->sc_mem_rid, 0, ~0, 0x8000, RF_ACTIVE);
153 #endif
154         if (psc->sc_mem_res) {
155                 sc->sc_chip.sc_memt = rman_get_bustag(psc->sc_mem_res);
156                 sc->sc_chip.sc_memh = rman_get_bushandle(psc->sc_mem_res);
157                 am79c930_chip_init(&sc->sc_chip, 1);
158         } else
159                 am79c930_chip_init(&sc->sc_chip, 0);
160
161         error = bus_setup_intr(dev, psc->sc_irq_res, INTR_TYPE_NET,
162             (void (*)(void *))awi_intr, sc, &psc->sc_intrhand);
163         if (error) {
164                 device_printf(dev, "awi_pccard_attach: intr setup failed\n");
165                 goto fail;
166         }
167
168         sc->sc_cansleep = 1;
169         sc->sc_enabled = 1;
170         sc->sc_ifp = &sc->sc_ec.ac_if;
171
172         error = awi_attach(sc);
173         sc->sc_enabled = 0;     /*XXX*/
174         if (error == 0)
175                 return 0;
176         device_printf(dev, "awi_pccard_attach: awi_attach failed\n");
177
178   fail:
179         if (psc->sc_intrhand) {
180                 bus_teardown_intr(dev, psc->sc_irq_res, psc->sc_intrhand);
181                 psc->sc_intrhand = 0;
182         }
183         if (psc->sc_port_res) {
184                 bus_release_resource(dev, SYS_RES_IOPORT, psc->sc_port_rid,
185                     psc->sc_port_res);
186                 psc->sc_port_res = 0;
187         }
188         if (psc->sc_irq_res) {
189                 bus_release_resource(dev, SYS_RES_IRQ, psc->sc_irq_rid,
190                     psc->sc_irq_res);
191                 psc->sc_irq_res = 0;
192         }
193         if (psc->sc_mem_res) {
194                 bus_release_resource(dev, SYS_RES_MEMORY, psc->sc_mem_rid,
195                     psc->sc_mem_res);
196                 psc->sc_mem_res = 0;
197         }
198         if (error == 0)
199                 error = ENXIO;
200         return error;
201 }
202
203 static int
204 awi_pccard_detach(device_t dev)
205 {
206         struct awi_pccard_softc *psc = device_get_softc(dev);
207         struct awi_softc *sc = &psc->sc_awi;
208         struct ifnet *ifp = &sc->sc_ec.ac_if;
209
210         ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
211         ifp->if_flags &= ~IFF_RUNNING; 
212         if (psc->sc_intrhand) {
213                 bus_teardown_intr(dev, psc->sc_irq_res, psc->sc_intrhand);
214                 psc->sc_intrhand = 0;
215         }
216         if (psc->sc_port_res) {
217                 bus_release_resource(dev, SYS_RES_IOPORT, psc->sc_port_rid,
218                     psc->sc_port_res);
219                 psc->sc_port_res = 0;
220         }
221         if (psc->sc_irq_res) {
222                 bus_release_resource(dev, SYS_RES_IRQ, psc->sc_irq_rid,
223                     psc->sc_irq_res);
224                 psc->sc_irq_res = 0;
225         }
226         if (psc->sc_mem_res) {
227                 bus_release_resource(dev, SYS_RES_MEMORY, psc->sc_mem_rid,
228                     psc->sc_mem_res);
229                 psc->sc_mem_res = 0;
230         }
231         return 0;
232 }
233
234 static device_method_t awi_pccard_methods[] = {
235         /* Device interface */
236         DEVMETHOD(device_probe,         awi_pccard_probe),
237         DEVMETHOD(device_attach,        awi_pccard_attach),
238         DEVMETHOD(device_detach,        awi_pccard_detach),
239
240         { 0, 0 }
241 };
242
243 static driver_t awi_pccard_driver = {
244         "awi",
245         awi_pccard_methods,
246         sizeof(struct awi_pccard_softc),
247 };
248
249 extern devclass_t awi_devclass;
250
251 DRIVER_MODULE(awi, pccard, awi_pccard_driver, awi_devclass, 0, 0);