Use a globaldata_t instead of a cpuid in the lwkt_token structure. The
[dragonfly.git] / sys / bus / pccard / pccard_nbk.c
1 /*
2  * Copyright (c) 1999, 2001 M. Warner Losh.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: src/sys/pccard/pccard_nbk.c,v 1.15.2.11 2002/09/22 20:26:58 imp Exp $
26  * $DragonFly: src/sys/bus/pccard/Attic/pccard_nbk.c,v 1.4 2004/01/08 10:06:29 joerg Exp $
27  */
28
29 /*
30  * This file contains various kludges to allow the legacy pccard system to
31  * work in the newbus system until the pccard system can be converted
32  * wholesale to newbus.  As that is a while off, I'm providing this glue to
33  * allow newbus drivers to have pccard attachments.
34  *
35  * We do *NOT* implement ISA ivars at all.  We are not an isa bus, and drivers
36  * that abuse isa_{set,get}_* must be fixed in order to work with pccard.
37  * We use ivars for something else anyway, so it becomes fairly awkward
38  * to do so.
39  *
40  * Here's a summary of the glue that we do to make things work.
41  *
42  * First, we have pccard node in the device and driver trees.  The pccard
43  * device lives in the instance tree attached to the nexus.  The pccard
44  * attachments will be attached to that node.  This allows one to pass things
45  * up the tree that terminates at the nexus, like other buses.  The pccard
46  * code will create a device instance for each of the drivers that are to
47  * be attached.
48  *
49  * These compatibility nodes are called pccnbk.  PCCard New Bus Kludge.
50  */
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/module.h>
55 #include <sys/kernel.h>
56 #include <sys/sysctl.h>
57 #include <sys/queue.h>
58 #include <sys/types.h>
59
60 #include <sys/bus.h>
61 #include <machine/bus.h>
62 #include <machine/resource.h>
63
64 /* XXX Shouldn't reach into the MD code here */
65 #ifdef PC98
66 #include <pc98/pc98/pc98.h>
67 #else
68 #include <bus/isa/i386/isa.h>
69 #endif
70
71 #include "cardinfo.h"
72 #include "slot.h"
73
74 #include <bus/pccard/pccardvar.h>
75 #include <net/ethernet.h>
76
77 #include "card_if.h"
78
79 devclass_t      pccard_devclass;
80
81 #define PCCARD_NPORT    2
82 #define PCCARD_NMEM     5
83 #define PCCARD_NIRQ     1
84 #define PCCARD_NDRQ     0
85
86 #define PCCARD_DEVINFO(d) (struct pccard_devinfo *) device_get_ivars(d)
87
88 SYSCTL_NODE(_machdep, OID_AUTO, pccard, CTLFLAG_RW, 0, "pccard");
89
90 #ifdef UNSAFE
91 static u_long mem_start = IOM_BEGIN;
92 static u_long mem_end = IOM_END;
93 #else
94 static u_long mem_start = 0xd0000;
95 static u_long mem_end = 0xeffff;
96 #endif
97
98 SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_start, CTLFLAG_RW,
99     &mem_start, 0, "");
100 SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_end, CTLFLAG_RW,
101     &mem_end, 0, "");
102
103 #if __FreeBSD_version >= 500000
104 /*
105  * glue for NEWCARD/OLDCARD compat layer
106  */
107 static int
108 pccard_compat_do_probe(device_t bus, device_t dev)
109 {
110         return (CARD_COMPAT_PROBE(dev));
111 }
112
113 static int
114 pccard_compat_do_attach(device_t bus, device_t dev)
115 {
116         return (CARD_COMPAT_ATTACH(dev));
117 }
118 #endif
119
120 static int
121 pccard_probe(device_t dev)
122 {
123         device_set_desc(dev, "PC Card 16-bit bus (classic)");
124         return (0);
125 }
126
127 static int
128 pccard_attach(device_t dev)
129 {
130         return (0);
131 }
132
133 static void
134 pccard_print_resources(struct resource_list *rl, const char *name, int type,
135     int count, const char *format)
136 {
137         struct resource_list_entry *rle;
138         int printed;
139         int i;
140
141         printed = 0;
142         for (i = 0; i < count; i++) {
143                 rle = resource_list_find(rl, type, i);
144                 if (rle) {
145                         if (printed == 0)
146                                 printf(" %s ", name);
147                         else if (printed > 0)
148                                 printf(",");
149                         printed++;
150                         printf(format, rle->start);
151                         if (rle->count > 1) {
152                                 printf("-");
153                                 printf(format, rle->start + rle->count - 1);
154                         }
155                 } else if (i > 3) {
156                         /* check the first few regardless */
157                         break;
158                 }
159         }
160 }
161
162 static int
163 pccard_print_child(device_t dev, device_t child)
164 {
165         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
166         struct resource_list *rl = &devi->resources;
167         int     retval = 0;
168         int     flags = device_get_flags(child);
169
170         retval += bus_print_child_header(dev, child);
171         retval += printf(" at");
172
173         if (devi) {
174                 pccard_print_resources(rl, "port", SYS_RES_IOPORT,
175                     PCCARD_NPORT, "%#lx");
176                 pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
177                     PCCARD_NMEM, "%#lx");
178                 pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
179                     "%ld");
180                 pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
181                     "%ld");
182                 if (flags != 0)
183                         retval += printf(" flags 0x%x", flags);
184                 retval += printf(" slot %d", devi->slt->slotnum);
185         }
186
187         retval += bus_print_child_footer(dev, child);
188
189         return (retval);
190 }
191
192 static int
193 pccard_set_resource(device_t dev, device_t child, int type, int rid,
194     u_long start, u_long count)
195 {
196         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
197         struct resource_list *rl = &devi->resources;
198
199         if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
200             && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
201                 return (EINVAL);
202         if (rid < 0)
203                 return (EINVAL);
204         if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
205                 return (EINVAL);
206         if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
207                 return (EINVAL);
208         if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
209                 return (EINVAL);
210         if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
211                 return (EINVAL);
212
213         resource_list_add(rl, type, rid, start, start + count - 1, count);
214
215         return (0);
216 }
217
218 static int
219 pccard_get_resource(device_t dev, device_t child, int type, int rid,
220     u_long *startp, u_long *countp)
221 {
222         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
223         struct resource_list *rl = &devi->resources;
224         struct resource_list_entry *rle;
225
226         rle = resource_list_find(rl, type, rid);
227         if (!rle)
228                 return (ENOENT);
229         
230         if (startp)
231                 *startp = rle->start;
232         if (countp)
233                 *countp = rle->count;
234
235         return (0);
236 }
237
238 static void
239 pccard_delete_resource(device_t dev, device_t child, int type, int rid)
240 {
241         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
242         struct resource_list *rl = &devi->resources;
243         resource_list_delete(rl, type, rid);
244 }
245
246 static struct resource *
247 pccard_alloc_resource(device_t bus, device_t child, int type, int *rid,
248     u_long start, u_long end, u_long count, u_int flags)
249 {
250         /*
251          * Consider adding a resource definition. We allow rid 0 for
252          * irq, 0-4 for memory and 0-1 for ports
253          */
254         int passthrough = (device_get_parent(child) != bus);
255         int isdefault;
256         struct pccard_devinfo *devi = device_get_ivars(child);
257         struct resource_list *rl = &devi->resources;
258         struct resource_list_entry *rle;
259         struct resource *res;
260
261         if (start == 0 && end == ~0 && type == SYS_RES_MEMORY && count != 1) {
262                 start = mem_start;
263                 end = mem_end;
264         }
265         isdefault = (start == 0UL && end == ~0UL);
266         if (!passthrough && !isdefault) {
267                 rle = resource_list_find(rl, type, *rid);
268                 if (!rle) {
269                         if (*rid < 0)
270                                 return (NULL);
271                         switch (type) {
272                         case SYS_RES_IRQ:
273                                 if (*rid >= PCCARD_NIRQ)
274                                         return (NULL);
275                                 break;
276                         case SYS_RES_DRQ:
277                                 if (*rid >= PCCARD_NDRQ)
278                                         return (NULL);
279                                 break;
280                         case SYS_RES_MEMORY:
281                                 if (*rid >= PCCARD_NMEM)
282                                         return (NULL);
283                                 break;
284                         case SYS_RES_IOPORT:
285                                 if (*rid >= PCCARD_NPORT)
286                                         return (NULL);
287                                 break;
288                         default:
289                                 return (NULL);
290                         }
291                         resource_list_add(rl, type, *rid, start, end, count);
292                 }
293         }
294         res = resource_list_alloc(rl, bus, child, type, rid, start, end,
295             count, flags);
296         return (res);
297 }
298
299 static int
300 pccard_release_resource(device_t bus, device_t child, int type, int rid,
301                      struct resource *r)
302 {
303         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
304         struct resource_list *rl = &devi->resources;
305         return (resource_list_release(rl, bus, child, type, rid, r));
306 }
307
308 static int
309 pccard_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
310 {
311         struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
312         
313         switch (which) {
314         case PCCARD_IVAR_ETHADDR:
315                 bcopy(devi->misc, result, ETHER_ADDR_LEN);
316                 return (0);
317         case PCCARD_IVAR_VENDOR:
318                 *(u_int32_t *) result = devi->manufacturer;
319                 return (0);
320         case PCCARD_IVAR_PRODUCT:
321                 *(u_int32_t *) result = devi->product;
322                 return (0);
323         case PCCARD_IVAR_PRODEXT:
324                 *(u_int16_t *) result = devi->prodext;
325                 return (0);
326         }
327         return (ENOENT);
328 }
329
330 static int
331 pccard_set_res_flags(device_t bus, device_t child, int restype, int rid,
332     u_long value)
333 {
334         return (CARD_SET_RES_FLAGS(device_get_parent(bus), child, restype,
335             rid, value));
336 }
337
338 static int
339 pccard_get_res_flags(device_t bus, device_t child, int restype, int rid,
340     u_long *value)
341 {
342         return (CARD_GET_RES_FLAGS(device_get_parent(bus), child, restype,
343             rid, value));
344 }
345
346 static int
347 pccard_set_memory_offset(device_t bus, device_t child, int rid, 
348     u_int32_t offset, u_int32_t *deltap)
349 {
350         return (CARD_SET_MEMORY_OFFSET(device_get_parent(bus), child, rid,
351             offset, deltap));
352 }
353
354 static int
355 pccard_get_memory_offset(device_t bus, device_t child, int rid, 
356     u_int32_t *offset)
357 {
358         return (CARD_GET_MEMORY_OFFSET(device_get_parent(bus), child, rid,
359             offset));
360 }
361
362 #if __FreeBSD_version >= 500000
363 static int
364 pccard_get_function_num(device_t bus, device_t child, int *function)
365 {
366         *function = 0;
367         return (0);
368 }
369
370 static int
371 pccard_activate_function(device_t bus, device_t child)
372 {
373         /* pccardd has alrady activated the function */
374         return (0);
375 }
376
377 static int
378 pccard_deactivate_function(device_t bus, device_t child)
379 {
380         /* pccardd will deactivate the function */
381         return (0);
382 }
383
384 static const struct pccard_product *
385 pccard_do_product_lookup(device_t bus, device_t dev,
386                       const struct pccard_product *tab,
387                       size_t ent_size, pccard_product_match_fn matchfn)
388 {
389         return (NULL);
390 }
391 #endif
392
393 static device_method_t pccard_methods[] = {
394         /* Device interface */
395         DEVMETHOD(device_probe,         pccard_probe),
396         DEVMETHOD(device_attach,        pccard_attach),
397         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
398         DEVMETHOD(device_suspend,       pccard_suspend),
399         DEVMETHOD(device_resume,        pccard_resume),
400
401         /* Bus interface */
402         DEVMETHOD(bus_print_child,      pccard_print_child),
403         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
404         DEVMETHOD(bus_alloc_resource,   pccard_alloc_resource),
405         DEVMETHOD(bus_release_resource, pccard_release_resource),
406         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
407         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
408         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
409         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
410         DEVMETHOD(bus_set_resource,     pccard_set_resource),
411         DEVMETHOD(bus_get_resource,     pccard_get_resource),
412         DEVMETHOD(bus_delete_resource,  pccard_delete_resource),
413         DEVMETHOD(bus_read_ivar,        pccard_read_ivar),
414
415         /* Card interface */
416         DEVMETHOD(card_set_res_flags,   pccard_set_res_flags),
417         DEVMETHOD(card_get_res_flags,   pccard_get_res_flags),
418         DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
419         DEVMETHOD(card_get_memory_offset, pccard_get_memory_offset),
420 #if __FreeBSD_version >= 500000
421         DEVMETHOD(card_get_function,    pccard_get_function_num),
422         DEVMETHOD(card_activate_function, pccard_activate_function),
423         DEVMETHOD(card_deactivate_function, pccard_deactivate_function),
424         DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
425         DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
426         DEVMETHOD(card_do_product_lookup, pccard_do_product_lookup),
427 #endif
428         { 0, 0 }
429 };
430
431 static driver_t pccard_driver = {
432         "pccard",
433         pccard_methods,
434         sizeof(struct slot)
435 };
436
437 DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
438 DRIVER_MODULE(pccard, mecia, pccard_driver, pccard_devclass, 0, 0);
439 MODULE_VERSION(pccard, 1);