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/mecia.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  *  NEC MECIA controller.
    3  *-------------------------------------------------------------------------
    4  *
    5  * Copyright (c) 2001 M. Warner Losh.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  * $FreeBSD: releng/5.2/sys/pccard/mecia.c 122352 2003-11-09 09:17:26Z tanimura $
   28  *
   29  * Based heavily on the FreeBSD pcic driver's pcic98 support, derived
   30  * from PAO3 tree.  This copyright notice likely needs modification for
   31  * such a linage.  The only authorship I could find was:
   32  *
   33  * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L.
   34  * by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp>
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/bus.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 
   43 #include <pccard/meciareg.h>
   44 #include <pccard/cardinfo.h>
   45 #include <pccard/slot.h>
   46 #ifndef MECIA_IOBASE
   47 #define MECIA_IOBASE   0x80d0
   48 #endif
   49 
   50 /* Get pnp IDs */
   51 #include <isa/isavar.h>
   52 
   53 #include <dev/pccard/pccardvar.h>
   54 #include "card_if.h"
   55 
   56 #define MECIA_DEVICE2SOFTC(dev) ((struct mecia_slot *) device_get_softc(dev))
   57 
   58 /*
   59  *      Prototypes for interrupt handler.
   60  */
   61 static driver_intr_t    meciaintr;
   62 static int              mecia_ioctl(struct slot *, int, caddr_t);
   63 static int              mecia_power(struct slot *);
   64 static void             mecia_mapirq(struct slot *, int);
   65 static timeout_t        mecia_reset;
   66 static void             mecia_resume(struct slot *);
   67 static void             mecia_disable(struct slot *);
   68 static timeout_t        meciatimeout;
   69 static struct callout_handle meciatimeout_ch
   70     = CALLOUT_HANDLE_INITIALIZER(&meciatimeout_ch);
   71 static int              mecia_memory(struct slot *, int);
   72 static int              mecia_io(struct slot *, int);
   73 
   74 /*
   75  *      Per-slot data table.
   76  */
   77 struct mecia_slot {
   78         int             unit;           /* Unit number */
   79         int             slotnum;        /* My slot number */
   80         struct slot     *slt;           /* Back ptr to slot */
   81         device_t        dev;            /* My device */
   82         u_char          last_reg1;      /* Last value of change reg */
   83 };
   84 
   85 static struct slot_ctrl mecia_cinfo = {
   86         mecia_mapirq,
   87         mecia_memory,
   88         mecia_io,
   89         mecia_reset,
   90         mecia_disable,
   91         mecia_power,
   92         mecia_ioctl,
   93         mecia_resume,
   94         1,
   95 #if 0
   96         1
   97 #else
   98         2               /* Fake for UE2212 LAN card */
   99 #endif
  100 };
  101 
  102 static int validunits = 0;
  103 
  104 /*
  105  *      Look for an NEC MECIA.
  106  *      For each available slot, allocate a PC-CARD slot.
  107  */
  108 
  109 static int
  110 mecia_probe(device_t dev)
  111 {
  112         int             validslots = 0;
  113 
  114         /* Check isapnp ids */
  115         if (isa_get_logicalid(dev))             /* skip PnP probes */
  116                 return (ENXIO);
  117 
  118         if (inb(MECIA_REG0) != 0xff) {
  119                 validslots++;
  120                 /* XXX need to allocated the port resources */
  121                 device_set_desc(dev, "MECIA PC98 Original PCMCIA Controller");
  122         }
  123         return (validslots ? 0 : ENXIO);
  124 }
  125 
  126 static int
  127 mecia_attach(device_t dev)
  128 {
  129         int             error;
  130         int             irq;
  131         void            *ih;
  132         device_t        kid;
  133         struct resource *r;
  134         int             rid;
  135         struct slot     *slt;
  136         struct mecia_slot *sp;
  137         
  138         sp = MECIA_DEVICE2SOFTC(dev);
  139         sp->unit = validunits++;
  140         kid = device_add_child(dev, NULL, -1);
  141         if (kid == NULL) {
  142                 device_printf(dev, "Can't add pccard bus slot 0\n");
  143                 return (ENXIO);
  144         }
  145         device_probe_and_attach(kid);
  146         slt = pccard_init_slot(kid, &mecia_cinfo);
  147         if (slt == 0) {
  148                 device_printf(dev, "Can't get pccard info slot 0\n");
  149                 return (ENXIO);
  150         }
  151         slt->cdata = sp;
  152         sp->slt = slt;
  153         validunits++;
  154 
  155         rid = 0;
  156         r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
  157         if (!r)
  158                 return (ENXIO);
  159 
  160         irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
  161         if (irq == 0) {
  162                 /* See if the user has requested a specific IRQ */
  163                 if (!getenv_int("machdep.pccard.mecia_irq", &irq))
  164                         irq = 0;
  165         }
  166         rid = 0;
  167         r = 0;
  168         if (irq > 0) {
  169                 r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq,
  170                     irq, 1, RF_ACTIVE);
  171         }
  172         if (r && ((1 << (rman_get_start(r))) & MECIA_INT_MASK_ALLOWED) == 0) {
  173                 device_printf(dev,
  174                     "Hardware does not support irq %d, trying polling.\n",
  175                     irq);
  176                 bus_release_resource(dev, SYS_RES_IRQ, rid, r);
  177                 r = 0;
  178                 irq = 0;
  179         }
  180         if (r) {
  181                 error = bus_setup_intr(dev, r, INTR_TYPE_MISC,
  182                     meciaintr, (void *) sp, &ih);
  183                 if (error) {
  184                         bus_release_resource(dev, SYS_RES_IRQ, rid, r);
  185                         return (error);
  186                 }
  187                 irq = rman_get_start(r);
  188                 device_printf(dev, "management irq %d\n", irq);
  189         } else {
  190                 irq = 0;
  191         }
  192         if (irq == 0) {
  193                 meciatimeout_ch = timeout(meciatimeout, (void *) sp, hz/2);
  194                 device_printf(dev, "Polling mode\n");
  195         }
  196 
  197         sp->last_reg1 = inb(MECIA_REG1);
  198         if (sp->last_reg1 & MECIA_CARDEXIST) {
  199                 /* PCMCIA card exist */
  200                 sp->slt->laststate = sp->slt->state = filled;
  201                 pccard_event(sp->slt, card_inserted);
  202         } else {
  203                 sp->slt->laststate = sp->slt->state = empty;
  204         }
  205         sp->slt->irq = irq;
  206 
  207         return (bus_generic_attach(dev));
  208 }
  209 
  210 static int
  211 mecia_sresource(struct slot *slt, caddr_t data)
  212 {
  213         struct pccard_resource *pr;
  214         struct resource *r;
  215         int flags;
  216         int rid = 0;
  217         device_t pccarddev = slt->dev;
  218 
  219         pr = (struct pccard_resource *)data;
  220         pr->resource_addr = ~0ul;
  221         switch(pr->type) {
  222         default:
  223                 return (EINVAL);
  224         case SYS_RES_MEMORY:
  225         case SYS_RES_IRQ:
  226         case SYS_RES_IOPORT:
  227                 break;
  228         }
  229         flags = rman_make_alignment_flags(pr->size);
  230         r = bus_alloc_resource(pccarddev, pr->type, &rid, pr->min, pr->max,
  231            pr->size, flags);
  232         if (r != NULL) {
  233                 pr->resource_addr = (u_long)rman_get_start(r);
  234                 bus_release_resource(bridgedev, pr->type, rid, r);
  235         }
  236         return (0);
  237 }
  238 
  239 /*
  240  *      ioctl calls - Controller specific ioctls
  241  */
  242 static int
  243 mecia_ioctl(struct slot *slt, int cmd, caddr_t data)
  244 {
  245         switch(cmd) {
  246         default:
  247                 return (ENOTTY);
  248         case PIOCSRESOURCE:             /* Can I use this resource? */
  249                 mecia_sresource(slt, data);
  250                 break;
  251         }
  252         return (0);
  253 }
  254 
  255 /*
  256  *      MECIA timer.  If the controller doesn't have a free IRQ to use
  257  *      or if interrupt steering doesn't work, poll the controller for
  258  *      insertion/removal events.
  259  */
  260 static void
  261 meciatimeout(void *chan)
  262 {
  263         meciaintr(chan);
  264         meciatimeout_ch = timeout(meciatimeout, chan, hz/2);
  265 }
  266 
  267 /*
  268  *      MECIA Interrupt handler.
  269  *      Check the slot and report any changes.
  270  */
  271 static void
  272 meciaintr(void *arg)
  273 {
  274         u_char  reg1;
  275         int     s;
  276         struct mecia_slot *sp = (struct mecia_slot *) arg;
  277 
  278         s = splhigh();
  279         /* Check for a card in this slot */
  280         reg1 = inb(MECIA_REG1);
  281         if ((sp->last_reg1 ^ reg1) & MECIA_CARDEXIST) {
  282                 sp->last_reg1 = reg1;
  283                 if (reg1 & MECIA_CARDEXIST)
  284                         pccard_event(sp->slt, card_inserted);
  285                 else
  286                         pccard_event(sp->slt, card_removed);
  287         }
  288         splx(s);
  289 }
  290 
  291 /*
  292  * local functions for PC-98 Original PC-Card controller
  293  */
  294 #define MECIA_ALWAYS_128MAPPING 1       /* trick for using UE2212  */
  295 
  296 int mecia_mode = 0;     /* almost the same as the value in MECIA_REG2 */
  297 
  298 static unsigned char reg_winsel = MECIA_UNMAPWIN;
  299 static unsigned short reg_pagofs = 0;
  300 
  301 static int
  302 mecia_memory(struct slot *slt, int win)
  303 {
  304         struct mem_desc *mp = &slt->mem[win];
  305         unsigned char x;
  306 
  307         if (mp->flags & MDF_ACTIVE) {
  308                 /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */
  309                 if ((unsigned long)mp->start != 0xda000) {
  310                         printf(
  311                         "sys_addr must be 0xda000. requested address = %p\n",
  312                         mp->start);
  313                         return (EINVAL);
  314                 }
  315 
  316                 /* omajinai ??? */
  317                 outb(MECIA_REG0, 0);
  318                 x = inb(MECIA_REG1);
  319                 x &= 0xfc;
  320                 x |= 0x02;
  321                 outb(MECIA_REG1, x);
  322                 reg_winsel = inb(MECIA_REG_WINSEL);
  323                 reg_pagofs = inw(MECIA_REG_PAGOFS);
  324                 outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
  325                 outw(MECIA_REG_PAGOFS, (mp->card >> 13)); /* 8KB */
  326 
  327                 if (mp->flags & MDF_ATTR)
  328                         outb(MECIA_REG7, inb(MECIA_REG7) | MECIA_ATTRMEM);
  329                 else
  330                         outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_ATTRMEM));
  331 
  332                 outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
  333 #if 0
  334                 if ((mp->flags & MDF_16BITS) == 1)      /* 16bit */
  335                         outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_8BIT));
  336                 else                                    /* 8bit */
  337                         outb(MECIA_REG2, inb(MECIA_REG2) | MECIA_8BIT);
  338 #endif
  339         } else {  /* !(mp->flags & MDF_ACTIVE) */
  340                 outb(MECIA_REG0, 0);
  341                 x = inb(MECIA_REG1);
  342                 x &= 0xfc;
  343                 x |= 0x02;
  344                 outb(MECIA_REG1, x);
  345 #if 0
  346                 outb(MECIA_REG_WINSEL, MECIA_UNMAPWIN);
  347                 outw(MECIA_REG_PAGOFS, 0);
  348 #else
  349                 outb(MECIA_REG_WINSEL, reg_winsel);
  350                 outw(MECIA_REG_PAGOFS, reg_pagofs);
  351 #endif
  352         }
  353         return (0);
  354 }
  355 
  356 static int
  357 mecia_io(struct slot *slt, int win)
  358 {
  359         struct io_desc *ip = &slt->io[win];
  360         unsigned char x;
  361         unsigned short cardbase;
  362         u_short ofst;
  363 
  364         if (win != 0) {
  365                 /* ignore for UE2212 */
  366                 printf(
  367                 "mecia:Illegal MECIA I/O window(%d) request! Ignored.\n", win);
  368 /*              return (EINVAL);*/
  369                 return (0);
  370         }
  371 
  372         if (ip->flags & IODF_ACTIVE) {
  373                 x = inb(MECIA_REG2) & 0x0f;
  374 #if 0
  375                 if (! (ip->flags & IODF_CS16))
  376                         x |= MECIA_8BIT;
  377 #else
  378                 if (! (ip->flags & IODF_16BIT)) {
  379                         x |= MECIA_8BIT;
  380                         mecia_mode |= MECIA_8BIT;
  381                 }
  382 #endif
  383 
  384                 ofst = ip->start & 0xf;
  385                 cardbase = ip->start & ~0xf;
  386 #ifndef MECIA_ALWAYS_128MAPPING
  387                 if (ip->size + ofst > 16)
  388 #endif
  389                 {       /* 128bytes mapping */
  390                         x |= MECIA_MAP128;
  391                         mecia_mode |= MECIA_MAP128;
  392                         ofst |= ((cardbase & 0x70) << 4);
  393                         cardbase &= ~0x70;
  394                 }
  395 
  396                 x |= MECIA_MAPIO;
  397                 outb(MECIA_REG2, x);
  398     
  399                 outw(MECIA_REG4, MECIA_IOBASE); /* 98side I/O base */
  400                 outw(MECIA_REG5, cardbase);     /* card side I/O base */
  401 
  402                 if (bootverbose) {
  403                         printf("mecia: I/O mapped 0x%04x(98) -> "
  404                                "0x%04x(Card) and width %d bytes\n",
  405                                 MECIA_IOBASE+ofst, ip->start, ip->size);
  406                         printf("mecia: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n",
  407                                 inb(MECIA_REG2), inb(MECIA_REG3),
  408                                 inb(MECIA_REG7));
  409                         printf("mecia: mode=%d\n", mecia_mode);
  410                 }
  411 
  412                 ip->start = MECIA_IOBASE + ofst;
  413         } else {
  414                 outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
  415                 mecia_mode = 0;
  416         }
  417         return (0);
  418 }
  419 
  420 static int
  421 mecia_power(struct slot *slt)
  422 {
  423         unsigned char reg;
  424 
  425         reg = inb(MECIA_REG7) & (~MECIA_VPP12V);
  426         switch(slt->pwr.vpp) {
  427         default:
  428                 return (EINVAL);
  429         case 50:
  430                 break;
  431         case 120:
  432                 reg |= MECIA_VPP12V;
  433                 break;
  434         }
  435         outb(MECIA_REG7, reg);
  436         DELAY(100*1000);
  437 
  438         reg = inb(MECIA_REG2) & (~MECIA_VCC3P3V);
  439         switch(slt->pwr.vcc) {
  440         default:
  441                 return (EINVAL);
  442         case 33:
  443                 reg |= MECIA_VCC3P3V;
  444                 break;
  445         case 50:
  446                 break;
  447         }
  448         outb(MECIA_REG2, reg);
  449         DELAY(100*1000);
  450         return (0);
  451 }
  452 
  453 static void
  454 mecia_mapirq(struct slot *slt, int irq)
  455 {
  456         u_char x;
  457 
  458         switch (irq) {
  459         case 3:
  460                 x = MECIA_INT0;
  461                 break;
  462         case 5:
  463                 x = MECIA_INT1;
  464                 break;
  465         case 6:
  466                 x = MECIA_INT2;
  467                 break;
  468         case 10:
  469                 x = MECIA_INT4;
  470                 break;
  471         case 12:
  472                 x = MECIA_INT5;
  473                 break;
  474         case 0:         /* disable */
  475                 x = MECIA_INTDISABLE;
  476                 break;
  477         default:
  478                 printf("mecia: illegal irq %d\n", irq);
  479                 return;
  480         }
  481 #ifdef  MECIA_DEBUG
  482         printf("mecia: irq=%d mapped.\n", irq);
  483 #endif
  484         outb(MECIA_REG3, x);
  485 }
  486 
  487 static void
  488 mecia_reset(void *chan)
  489 {
  490         struct slot *slt = chan;
  491 
  492         outb(MECIA_REG0, 0);
  493         outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
  494         outb(MECIA_REG3, MECIA_INTDISABLE);
  495 #if 0
  496 /* mecia_reset() is called after mecia_power() */
  497         outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_VCC3P3V));
  498         outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_VPP12V));
  499 #endif
  500         outb(MECIA_REG1, 0);
  501 
  502         selwakeuppri(&slt->selp, PZERO);
  503 }
  504 
  505 static void
  506 mecia_disable(struct slot *slt)
  507 {
  508         /* null function */
  509 }
  510 
  511 static void
  512 mecia_resume(struct slot *slt)
  513 {
  514         /* XXX MECIA How ? */
  515 }
  516 
  517 static int
  518 mecia_activate_resource(device_t dev, device_t child, int type, int rid,
  519     struct resource *r)
  520 {
  521         struct pccard_devinfo *devi = device_get_ivars(child);
  522         int err;
  523 
  524         if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
  525                 return (bus_generic_activate_resource(dev, child, type,
  526                     rid, r));
  527 
  528         switch (type) {
  529         case SYS_RES_IOPORT: {
  530                 struct io_desc *ip;
  531                 ip = &devi->slt->io[rid];
  532                 if (ip->flags == 0) {
  533                         if (rid == 0)
  534                                 ip->flags = IODF_WS | IODF_16BIT | IODF_CS16;
  535                         else
  536                                 ip->flags = devi->slt->io[0].flags;
  537                 }
  538                 ip->flags |= IODF_ACTIVE;
  539                 ip->start = rman_get_start(r);
  540                 ip->size = rman_get_end(r) - rman_get_start(r) + 1;
  541                 err = mecia_cinfo.mapio(devi->slt, rid);
  542                 if (err)
  543                         return (err);
  544                 break;
  545         }
  546         case SYS_RES_IRQ:
  547                 /*
  548                  * We actually defer the activation of the IRQ resource
  549                  * until the interrupt is registered to avoid stray
  550                  * interrupt messages.
  551                  */
  552                 break;
  553         case SYS_RES_MEMORY: {
  554                 struct mem_desc *mp;
  555                 if (rid >= NUM_MEM_WINDOWS)
  556                         return (EINVAL);
  557                 mp = &devi->slt->mem[rid];
  558                 mp->flags |= MDF_ACTIVE;
  559                 mp->start = (caddr_t) rman_get_start(r);
  560                 mp->size = rman_get_end(r) - rman_get_start(r) + 1;
  561                 err = mecia_cinfo.mapmem(devi->slt, rid);
  562                 if (err)
  563                         return (err);
  564                 break;
  565         }
  566         default:
  567                 break;
  568         }
  569         err = bus_generic_activate_resource(dev, child, type, rid, r);
  570         return (err);
  571 }
  572 
  573 static int
  574 mecia_deactivate_resource(device_t dev, device_t child, int type, int rid,
  575     struct resource *r)
  576 {
  577         struct pccard_devinfo *devi = device_get_ivars(child);
  578         int err;
  579 
  580         if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
  581                 return (bus_generic_deactivate_resource(dev, child, type,
  582                     rid, r));
  583 
  584         switch (type) {
  585         case SYS_RES_IOPORT: {
  586                 struct io_desc *ip = &devi->slt->io[rid];
  587                 ip->flags &= ~IODF_ACTIVE;
  588                 err = mecia_cinfo.mapio(devi->slt, rid);
  589                 if (err)
  590                         return (err);
  591                 break;
  592         }
  593         case SYS_RES_IRQ:
  594                 break;
  595         case SYS_RES_MEMORY: {
  596                 struct mem_desc *mp = &devi->slt->mem[rid];
  597                 mp->flags &= ~(MDF_ACTIVE | MDF_ATTR);
  598                 err = mecia_cinfo.mapmem(devi->slt, rid);
  599                 if (err)
  600                         return (err);
  601                 break;
  602         }
  603         default:
  604                 break;
  605         }
  606         err = bus_generic_deactivate_resource(dev, child, type, rid, r);
  607         return (err);
  608 }
  609 
  610 static int
  611 mecia_setup_intr(device_t dev, device_t child, struct resource *irq,
  612     int flags, driver_intr_t *intr, void *arg, void **cookiep)
  613 {
  614         struct pccard_devinfo *devi = device_get_ivars(child);
  615         int err;
  616 
  617         if (((1 << rman_get_start(irq)) & MECIA_INT_MASK_ALLOWED) == 0) {
  618                 device_printf(dev, "Hardware does not support irq %ld.\n",
  619                     rman_get_start(irq));
  620                 return (EINVAL);
  621         }
  622 
  623         err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg,
  624             cookiep);
  625         if (err == 0)
  626                 mecia_cinfo.mapirq(devi->slt, rman_get_start(irq));
  627         else
  628                 device_printf(dev, "Error %d irq %ld\n", err,
  629                     rman_get_start(irq));
  630         return (err);
  631 }
  632 
  633 static int
  634 mecia_teardown_intr(device_t dev, device_t child, struct resource *irq,
  635     void *cookie)
  636 {
  637         struct pccard_devinfo *devi = device_get_ivars(child);
  638 
  639         mecia_cinfo.mapirq(devi->slt, 0);
  640         return (bus_generic_teardown_intr(dev, child, irq, cookie));
  641 }
  642 
  643 static int
  644 mecia_set_res_flags(device_t bus, device_t child, int restype, int rid,
  645     u_long value)
  646 {
  647         struct pccard_devinfo *devi = device_get_ivars(child);
  648         int err = 0;
  649 
  650         switch (restype) {
  651         case SYS_RES_MEMORY: {
  652                 struct mem_desc *mp = &devi->slt->mem[rid];
  653                 switch (value) {
  654                 case PCCARD_A_MEM_COM:
  655                         mp->flags &= ~MDF_ATTR;
  656                         break;
  657                 case PCCARD_A_MEM_ATTR:
  658                         mp->flags |= MDF_ATTR;
  659                         break;
  660                 case PCCARD_A_MEM_8BIT:
  661                         mp->flags &= ~MDF_16BITS;
  662                         break;
  663                 case PCCARD_A_MEM_16BIT:
  664                         mp->flags |= MDF_16BITS;
  665                         break;
  666                 }
  667                 err = mecia_cinfo.mapmem(devi->slt, rid);
  668                 break;
  669         }
  670         default:
  671                 err = EOPNOTSUPP;
  672         }
  673         return (err);
  674 }
  675 
  676 static int
  677 mecia_get_res_flags(device_t bus, device_t child, int restype, int rid,
  678     u_long *value)
  679 {
  680         struct pccard_devinfo *devi = device_get_ivars(child);
  681         int err = 0;
  682 
  683         if (value == 0)
  684                 return (ENOMEM);
  685 
  686         switch (restype) {
  687         case SYS_RES_IOPORT: {
  688                 struct io_desc *ip = &devi->slt->io[rid];
  689                 *value = ip->flags;
  690                 break;
  691         }
  692         case SYS_RES_MEMORY: {
  693                 struct mem_desc *mp = &devi->slt->mem[rid];
  694                 *value = mp->flags;
  695                 break;
  696         }
  697         default:
  698                 err = EOPNOTSUPP;
  699         }
  700         return (err);
  701 }
  702 
  703 static int
  704 mecia_set_memory_offset(device_t bus, device_t child, int rid,
  705     u_int32_t offset, u_int32_t *deltap)
  706 {
  707         struct pccard_devinfo *devi = device_get_ivars(child);
  708         struct mem_desc *mp = &devi->slt->mem[rid];
  709 
  710         mp->card = offset;
  711         if (deltap)
  712                 *deltap = 0;                    /* XXX BAD XXX */
  713         return (mecia_cinfo.mapmem(devi->slt, rid));
  714 }
  715 
  716 static int
  717 mecia_get_memory_offset(device_t bus, device_t child, int rid,
  718     u_int32_t *offset)
  719 {
  720         struct pccard_devinfo *devi = device_get_ivars(child);
  721         struct mem_desc *mp = &devi->slt->mem[rid];
  722 
  723         if (offset == 0)
  724                 return (ENOMEM);
  725 
  726         *offset = mp->card;
  727 
  728         return (0);
  729 }
  730 
  731 static device_method_t mecia_methods[] = {
  732         /* Device interface */
  733         DEVMETHOD(device_probe,         mecia_probe),
  734         DEVMETHOD(device_attach,        mecia_attach),
  735         DEVMETHOD(device_detach,        bus_generic_detach),
  736         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  737         DEVMETHOD(device_suspend,       bus_generic_suspend),
  738         DEVMETHOD(device_resume,        bus_generic_resume),
  739 
  740         /* Bus interface */
  741         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  742         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
  743         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  744         DEVMETHOD(bus_activate_resource, mecia_activate_resource),
  745         DEVMETHOD(bus_deactivate_resource, mecia_deactivate_resource),
  746         DEVMETHOD(bus_setup_intr,       mecia_setup_intr),
  747         DEVMETHOD(bus_teardown_intr,    mecia_teardown_intr),
  748 
  749         /* Card interface */
  750         DEVMETHOD(card_set_res_flags,   mecia_set_res_flags),
  751         DEVMETHOD(card_get_res_flags,   mecia_get_res_flags),
  752         DEVMETHOD(card_set_memory_offset, mecia_set_memory_offset),
  753         DEVMETHOD(card_get_memory_offset, mecia_get_memory_offset),
  754 
  755         { 0, 0 }
  756 };
  757 
  758 devclass_t      mecia_devclass;
  759 
  760 static driver_t mecia_driver = {
  761         "mecia",
  762         mecia_methods,
  763         sizeof(struct mecia_slot)
  764 };
  765 
  766 DRIVER_MODULE(mecia, isa, mecia_driver, mecia_devclass, 0, 0);

Cache object: 1b64b32e4129a893c0cf7a869ae2ebc1


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