The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pccard/pccard_nbk.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 9988465ca7b8cb59218c1b924da358e8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.