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/pc98/pc98/canbus.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) 2000 KIYOHARA Takashi <kiyohara@kk.iij4u.ne.jp>
    3  * Copyright (c) 2000 Takanori Watanabe <takawata@jp.FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following 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: releng/6.4/sys/pc98/pc98/canbus.c 143866 2005-03-20 05:22:57Z nyan $
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #include <sys/module.h>
   36 #include <sys/sysctl.h>
   37 
   38 #include <machine/clock.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/resource.h>
   42 #include <sys/rman.h>
   43 
   44 #include <pc98/pc98/canbus.h>
   45 #include <pc98/pc98/canbusvars.h>
   46 #include "canbus_if.h"
   47 
   48 
   49 #define CANBE_IO_DELAY_TIME 5000
   50 
   51 
   52 static MALLOC_DEFINE(M_CANBUSDEV, "canbusdev", "CanBe device");
   53 struct canbus_device {
   54         struct resource_list cbdev_resources;
   55 };
   56 
   57 /* canbus softc */
   58 struct canbus_softc {
   59         int io_delay_time;                      /* CanBe I/O delay time */
   60 
   61         struct sysctl_ctx_list canbus_sysctl_ctx;
   62                                                 /* dynamic sysctl tree */
   63 
   64         /* index register */
   65         int index_id;                           /* index ID */
   66         struct resource *index_res;             /* index resouce */
   67         bus_space_tag_t index_tag;              /* index tag */
   68         bus_space_handle_t index_handle;        /* index handle */
   69 
   70         /* data register */
   71         int data_id;                            /* data ID */
   72         struct resource *data_res;              /* data resouce */
   73         bus_space_tag_t data_tag;               /* data tag */
   74         bus_space_handle_t data_handle;         /* data handle */
   75 };
   76 
   77 
   78 /* Device interface methods */
   79 static void     canbus_identify(driver_t *, device_t);
   80 static int      canbus_probe(device_t);
   81 static int      canbus_attach(device_t);
   82 static int      canbus_detach(device_t);
   83 
   84 /* Bus interface methods */
   85 static int      canbus_print_child(device_t, device_t);
   86 static device_t canbus_add_child(device_t, int, const char *, int);
   87 static struct resource *        canbus_alloc_resource(
   88     device_t, device_t, int, int *, u_long, u_long, u_long, u_int);
   89 static int      canbus_activate_resource(
   90     device_t, device_t, int, int, struct resource *);
   91 static int      canbus_deactivate_resource(
   92     device_t, device_t, int, int, struct resource *);
   93 static int      canbus_release_resource(
   94     device_t, device_t, int, int, struct resource *);
   95 static int      canbus_set_resource (
   96     device_t, device_t, int, int, u_long, u_long);
   97 static void     canbus_delete_resource(device_t, device_t, int, int);
   98 
   99 /* canbus local function */
  100 static void     set_ioresource(device_t dev);
  101 static void     delete_ioresource(device_t dev);
  102 static int      alloc_ioresource(device_t);
  103 static void     release_ioresource(device_t);
  104 static int      print_all_resources(device_t);
  105 
  106 static device_method_t canbus_methods[] = { 
  107         /* Device interface */
  108         DEVMETHOD(device_identify,      canbus_identify),
  109         DEVMETHOD(device_probe,         canbus_probe),
  110         DEVMETHOD(device_attach,        canbus_attach),
  111         DEVMETHOD(device_detach,        canbus_detach),
  112 
  113         /* Bus interface */
  114         DEVMETHOD(bus_print_child,      canbus_print_child),
  115         DEVMETHOD(bus_add_child,        canbus_add_child),
  116         DEVMETHOD(bus_alloc_resource,   canbus_alloc_resource),
  117         DEVMETHOD(bus_activate_resource,        canbus_activate_resource),
  118         DEVMETHOD(bus_deactivate_resource,      canbus_deactivate_resource),
  119         DEVMETHOD(bus_release_resource, canbus_release_resource),
  120         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  121         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  122         DEVMETHOD(bus_set_resource,     canbus_set_resource),
  123         DEVMETHOD(bus_delete_resource,  canbus_delete_resource),
  124 
  125         /* CanBe interface */
  126         DEVMETHOD(canbus_read,          canbus_read),
  127         DEVMETHOD(canbus_write,         canbus_write),
  128         DEVMETHOD(canbus_write_multi,   canbus_write_multi),
  129 
  130         {0, 0}
  131 };
  132 
  133 static driver_t canbus_driver = {
  134         "canbus",
  135         canbus_methods,
  136         sizeof(struct canbus_softc),
  137 };
  138 
  139 devclass_t canbus_devclass;
  140 DRIVER_MODULE(canbus, nexus, canbus_driver, canbus_devclass, 0, 0);
  141 MODULE_VERSION(canbus, 1);
  142 
  143 
  144 static void
  145 canbus_identify(driver_t *drv, device_t parent)
  146 {
  147         if (device_find_child(parent, "canbus", 0) == NULL) {
  148                 if (BUS_ADD_CHILD(parent, 33, "canbus", 0) == NULL)
  149                         device_printf(parent, "canbus cannot attach\n");
  150         }
  151 }
  152 
  153 
  154 static int
  155 canbus_probe(device_t dev)
  156 {
  157         u_int8_t flag;
  158 
  159         set_ioresource(dev);
  160         if(alloc_ioresource(dev))
  161                 return (ENXIO);
  162         flag = canbus_read(dev, NULL, CANBE_SOUND_INTR_ADDR);
  163         release_ioresource(dev);
  164 
  165         if (bootverbose)
  166                 device_printf(dev, "probe flag = 0x%x\n", flag);
  167 
  168         if (flag != CANBE_SOUND_INTR_VAL0 && flag != CANBE_SOUND_INTR_VAL1 &&
  169             flag != CANBE_SOUND_INTR_VAL2 && flag != CANBE_SOUND_INTR_VAL3) {
  170                 device_printf(dev, "Device Not Found\n");
  171                 return (ENXIO);
  172         }
  173         device_set_desc(dev, "CanBe I/O Bus");
  174 
  175         return (0);     
  176 }
  177 
  178 static int
  179 canbus_attach(device_t dev)
  180 {
  181         struct canbus_softc *sc = device_get_softc(dev);
  182         struct sysctl_oid *canbus_sysctl_tree;
  183 
  184         sc->io_delay_time = CANBE_IO_DELAY_TIME;
  185 
  186         /* I/O resource setup */
  187         if(alloc_ioresource(dev))
  188                 return (ENXIO);
  189 
  190         /* Dynamic sysctl tree setup */
  191         sysctl_ctx_init(&sc->canbus_sysctl_ctx);
  192         canbus_sysctl_tree = SYSCTL_ADD_NODE(&sc->canbus_sysctl_ctx,
  193             SYSCTL_STATIC_CHILDREN(/* tree top */), OID_AUTO,
  194             "canbus", CTLFLAG_RD, 0, "CanBe I/O Bus");
  195         SYSCTL_ADD_INT(&sc->canbus_sysctl_ctx,
  196             SYSCTL_CHILDREN(canbus_sysctl_tree), OID_AUTO, "io_delay_time",
  197             CTLFLAG_RW, &sc->io_delay_time, 0, "CanBe Bus I/O delay time");
  198 
  199         bus_generic_probe(dev);
  200         bus_generic_attach(dev);
  201 
  202         return (0);
  203 }
  204 
  205 
  206 static int
  207 canbus_detach(device_t dev)
  208 {
  209         struct canbus_softc *sc = device_get_softc(dev);
  210 
  211         /* I/O resource free */
  212         release_ioresource(dev);
  213         delete_ioresource(dev);
  214 
  215         /* Dynamic sysctl tree destroy */
  216         if (sysctl_ctx_free(&sc->canbus_sysctl_ctx)) {
  217                 device_printf(dev,
  218                     "can't free this context - other oids depend on it\n");
  219                 return (ENOTEMPTY);
  220         }
  221 
  222         return (0);
  223 }
  224 
  225 
  226 static int
  227 canbus_print_child(device_t dev, device_t child)
  228 {
  229         int     retval = 0;
  230 
  231         retval += bus_print_child_header(dev, child);
  232         retval += print_all_resources(child);
  233         retval += bus_print_child_footer(dev, child);
  234 
  235         return (retval);
  236 }
  237 
  238 static device_t
  239 canbus_add_child(device_t bus, int order, const char *name, int unit)
  240 {
  241         device_t child;
  242         struct canbus_device *cbdev;
  243 
  244         child = device_add_child_ordered(bus, order, name, unit);
  245 
  246         cbdev = malloc(
  247             sizeof(struct canbus_device), M_CANBUSDEV, M_NOWAIT | M_ZERO);
  248         if (!cbdev)
  249                 return (0);
  250 
  251         resource_list_init(&cbdev->cbdev_resources);
  252         device_set_ivars(child, cbdev);
  253 
  254         return (child);
  255 }
  256 
  257 static struct resource *
  258 canbus_alloc_resource(device_t dev, device_t child, int type,
  259     int *rid, u_long start, u_long end, u_long count, u_int flags)
  260 {
  261         return (BUS_ALLOC_RESOURCE(device_get_parent(dev),
  262             child, type, rid, start, end, count, flags));
  263 }
  264 
  265 static int
  266 canbus_activate_resource(
  267     device_t dev, device_t child, int type, int rid, struct resource *res)
  268 {
  269         return (BUS_ACTIVATE_RESOURCE(
  270             device_get_parent(dev), child, type, rid, res));
  271 }
  272 
  273 static int
  274 canbus_deactivate_resource(
  275     device_t dev, device_t child, int type, int rid, struct resource *res)
  276 {
  277         return (BUS_DEACTIVATE_RESOURCE(
  278             device_get_parent(dev), child, type, rid, res));
  279 }
  280 
  281 static int
  282 canbus_release_resource(
  283     device_t dev, device_t child, int type, int rid, struct resource *res)
  284 {
  285         return (BUS_RELEASE_RESOURCE(
  286             device_get_parent(dev), child, type, rid, res));
  287 }
  288 
  289 static int
  290 canbus_set_resource (
  291     device_t dev, device_t child, int type, int rid, u_long start, u_long count)
  292 {
  293         struct  canbus_device *cbdev =
  294             (struct canbus_device *)device_get_ivars(child);
  295         struct resource_list *rl = &cbdev->cbdev_resources;
  296 
  297         resource_list_add(rl, type, rid, start, (start + count - 1), count);
  298 
  299         return (0);
  300 }
  301 
  302 static void
  303 canbus_delete_resource(device_t dev, device_t child, int type, int rid)
  304 {
  305         struct  canbus_device *cbdev =
  306             (struct canbus_device *)device_get_ivars(child);
  307         struct resource_list *rl = &cbdev->cbdev_resources;
  308 
  309         resource_list_delete(rl, type, rid);
  310 }
  311 
  312 
  313 u_int8_t
  314 canbus_read(device_t dev, device_t child, int reg)
  315 {
  316         struct canbus_softc *sc = device_get_softc(dev);
  317 
  318         bus_space_write_1(sc->index_tag, sc->index_handle, 0, reg);
  319         return (bus_space_read_1(sc->data_tag, sc->data_handle, 0));
  320 }
  321 
  322 void
  323 canbus_write(device_t dev, device_t child, int reg, u_int8_t val)
  324 {
  325         struct canbus_softc *sc = device_get_softc(dev);
  326 
  327         bus_space_write_1(sc->index_tag, sc->index_handle, 0, reg);
  328         bus_space_write_1(sc->data_tag, sc->data_handle, 0, val);
  329 }
  330 
  331 void
  332 canbus_write_multi(device_t dev,
  333     device_t child, int reg, const int count, const u_int8_t *vals)
  334 {
  335         struct canbus_softc *sc = device_get_softc(dev);
  336         int i;
  337 
  338         bus_space_write_1(sc->index_tag, sc->index_handle, 0, reg);
  339 
  340         for (i = 0; i < count; i ++) {
  341                 bus_space_write_1(sc->data_tag, sc->data_handle, 0, vals[i]);
  342                 DELAY(sc->io_delay_time);
  343         }
  344 }
  345 
  346 void
  347 canbus_delay(device_t dev, device_t child)
  348 {
  349         struct canbus_softc *sc = device_get_softc(dev);
  350 
  351         DELAY(sc->io_delay_time);
  352 }
  353 
  354 
  355 /*
  356  * canbus local function.
  357  */
  358 
  359 /*
  360  * CanBe I/O resource set function
  361  */
  362 static void
  363 set_ioresource(device_t dev)
  364 {
  365         struct canbus_softc *sc = device_get_softc(dev);
  366 
  367         sc->index_id = 0;
  368         sc->data_id = 1;
  369 
  370         bus_set_resource(
  371             dev, SYS_RES_IOPORT, sc->index_id, CANBE_IOPORT_INDEX, 1);
  372         bus_set_resource(
  373             dev, SYS_RES_IOPORT, sc->data_id, CANBE_IOPORT_DATA, 1);
  374 }
  375 
  376 /*
  377  * CanBe I/O resource delete function
  378  */
  379 static void
  380 delete_ioresource(device_t dev)
  381 {
  382         struct canbus_softc *sc = device_get_softc(dev);
  383 
  384         bus_delete_resource(dev, SYS_RES_IOPORT, sc->index_id);
  385         bus_delete_resource(dev, SYS_RES_IOPORT, sc->data_id);
  386 }
  387 
  388 /*
  389  * CanBe I/O resource alloc function
  390  */
  391 static int
  392 alloc_ioresource(device_t dev)
  393 {
  394         struct canbus_softc *sc = device_get_softc(dev);
  395 
  396         sc->index_res = bus_alloc_resource_any(
  397             dev, SYS_RES_IOPORT, &sc->index_id, RF_ACTIVE);
  398         sc->data_res = bus_alloc_resource_any(
  399             dev, SYS_RES_IOPORT, &sc->data_id, RF_ACTIVE);
  400         if (sc->index_res == NULL || sc->data_res == NULL) {
  401                 device_printf(dev, "could not map I/O\n");
  402                 return (ENXIO);
  403         }
  404 
  405         sc->index_tag = rman_get_bustag(sc->index_res);
  406         sc->index_handle = rman_get_bushandle(sc->index_res);
  407         sc->data_tag = rman_get_bustag(sc->data_res);
  408         sc->data_handle = rman_get_bushandle(sc->data_res);
  409 
  410         return (0);
  411 }
  412 
  413 /*
  414  * CanBe I/O resource release function
  415  */
  416 static void
  417 release_ioresource(device_t dev)
  418 {
  419         struct canbus_softc *sc = device_get_softc(dev);
  420 
  421         bus_release_resource(dev, SYS_RES_IOPORT, sc->index_id, sc->index_res);
  422         bus_release_resource(dev, SYS_RES_IOPORT, sc->data_id, sc->data_res);
  423 }
  424 
  425 
  426 static int
  427 print_all_resources(device_t dev)
  428 {
  429         struct  canbus_device *cbdev =
  430             (struct canbus_device *)device_get_ivars(dev);
  431         struct resource_list *rl = &cbdev->cbdev_resources;
  432         int retval = 0;
  433 
  434         if (STAILQ_FIRST(rl))
  435                 retval += printf(" at");
  436 
  437         retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
  438         retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
  439         retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
  440 
  441         return retval;
  442 }

Cache object: 462284e384378c0c672dcf6b28045a2f


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