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

Cache object: bfa7a35db84af23c112d82011cc05929


[ 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.