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/pcic.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  *  Intel PCIC or compatible Controller driver
    3  *  May be built using LKM to make a loadable module.
    4  *-------------------------------------------------------------------------
    5  *
    6  * Copyright (c) 1995 Andrew McRae.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * pcic98 : PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L.
   33  * by Noriyuki Hosobuchi <yj8n-hsbc@asahi-net.or.jp>
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/select.h>
   40 
   41 #include <machine/clock.h>
   42 
   43 #include <i386/isa/icu.h>
   44 #include <i386/isa/isa_device.h>
   45 
   46 #include <pccard/i82365.h>
   47 #ifdef  PC98
   48 #include <pccard/pcic98reg.h>
   49 #endif
   50 
   51 #include <pccard/cardinfo.h>
   52 #include <pccard/driver.h>
   53 #include <pccard/slot.h>
   54 
   55 /*
   56  *      Prototypes for interrupt handler.
   57  */
   58 static void             pcicintr        __P((int unit));
   59 static int              pcic_ioctl __P((struct slot *, int, caddr_t));
   60 static int              pcic_power __P((struct slot *));
   61 static timeout_t        pcic_reset;
   62 static void             pcic_resume(struct slot *);
   63 static void             pcic_disable __P((struct slot *));
   64 static void             pcic_mapirq __P((struct slot *, int));
   65 static timeout_t        pcictimeout;
   66 #ifdef LKM
   67 static int              pcic_handle __P((struct lkm_table *lkmtp, int cmd));
   68 #endif
   69 static int              pcic_memory(struct slot *, int);
   70 static int              pcic_io(struct slot *, int);
   71 static u_int            build_freelist(u_int);
   72 
   73 /*
   74  *      Per-slot data table.
   75  */
   76 static struct pcic_slot {
   77         int slotnum;                    /* My slot number */
   78         int index;                      /* Index register */
   79         int data;                       /* Data register */
   80         int offset;                     /* Offset value for index */
   81         char controller;                /* Device type */
   82         char revision;                  /* Device Revision */
   83         struct slot *slt;               /* Back ptr to slot */
   84         u_char (*getb)(struct pcic_slot *, int);
   85         void   (*putb)(struct pcic_slot *, int, u_char);
   86         u_char  *regs;                  /* Pointer to regs in mem */
   87 } pcic_slots[PCIC_MAX_SLOTS];
   88 
   89 static int              pcic_irq;
   90 static unsigned         pcic_imask;
   91 static struct slot_ctrl cinfo;
   92 
   93 
   94 /*
   95  *      Internal inline functions for accessing the PCIC.
   96  */
   97 /*
   98  * Read a register from the PCIC.
   99  */
  100 static __inline unsigned char
  101 getb1(struct pcic_slot *sp, int reg)
  102 {
  103         outb(sp->index, sp->offset + reg);
  104         return inb(sp->data);
  105 }
  106 
  107 static __inline unsigned char
  108 getb2(struct pcic_slot *sp, int reg)
  109 {
  110         return (sp->regs[reg]);
  111 }
  112 
  113 /*
  114  * Write a register on the PCIC
  115  */
  116 static __inline void
  117 putb1(struct pcic_slot *sp, int reg, unsigned char val)
  118 {
  119         outb(sp->index, sp->offset + reg);
  120         outb(sp->data, val);
  121 }
  122 
  123 static __inline void
  124 putb2(struct pcic_slot *sp, int reg, unsigned char val)
  125 {
  126         sp->regs[reg] = val;
  127 }
  128 
  129 /*
  130  * Clear bit(s) of a register.
  131  */
  132 static __inline void
  133 clrb(struct pcic_slot *sp, int reg, unsigned char mask)
  134 {
  135         sp->putb(sp, reg, sp->getb(sp, reg) & ~mask);
  136 }
  137 
  138 /*
  139  * Set bit(s) of a register
  140  */
  141 static __inline void
  142 setb(struct pcic_slot *sp, int reg, unsigned char mask)
  143 {
  144         sp->putb(sp, reg, sp->getb(sp, reg) | mask);
  145 }
  146 
  147 /*
  148  * Write a 16 bit value to 2 adjacent PCIC registers
  149  */
  150 static __inline void
  151 putw(struct pcic_slot *sp, int reg, unsigned short word)
  152 {
  153         sp->putb(sp, reg, word & 0xFF);
  154         sp->putb(sp, reg + 1, (word >> 8) & 0xff);
  155 }
  156 
  157 
  158 /*
  159  *      Loadable kernel module interface.
  160  */
  161 #ifdef  LKM
  162 /*
  163  *      This defines the lkm_misc module use by modload
  164  *      to define the module name.
  165  */
  166 MOD_MISC(pcic);
  167 
  168 /*
  169  *      Module handler that processes loads and unloads.
  170  *      Once the module is loaded, the probe routine
  171  *      is called to install the slots (if any).
  172  */
  173 static int
  174 pcic_handle(struct lkm_table *lkmtp, int cmd)
  175 {
  176         int err = 0;    /* default = success*/
  177 
  178         switch(cmd) {
  179         case LKM_E_LOAD:
  180 
  181                 /*
  182                  * Don't load twice! (lkmexists() is exported by kern_lkm.c)
  183                  */
  184                 if (lkmexists(lkmtp))
  185                         return(EEXIST);
  186                 /*
  187                  *      Call the probe routine to find the slots. If
  188                  *      no slots exist, then don't bother loading the module.
  189                  */
  190                 if (pcic_probe() == 0)
  191                         return(ENODEV);
  192                 break;          /* Success*/
  193         /*
  194          *      Attempt to unload the slot driver.
  195          */
  196         case LKM_E_UNLOAD:
  197                 printf("Unloading PCIC driver\n");
  198                 err = pcic_unload(lkmtp, cmd);
  199                 break;          /* Success*/
  200 
  201         default:        /* we only understand load/unload*/
  202                 err = EINVAL;
  203                 break;
  204         }
  205 
  206         return(err);
  207 }
  208 
  209 /*
  210  * External entry point; should generally match name of .o file.  The
  211  * arguments are always the same for all loaded modules.  The "load",
  212  * "unload", and "stat" functions in "DISPATCH" will be called under
  213  * their respective circumstances unless their value is "lkm_nullcmd".
  214  * If called, they are called with the same arguments (cmd is included to
  215  * allow the use of a single function, ver is included for version
  216  * matching between modules and the kernel loader for the modules).
  217  *
  218  * Since we expect to link in the kernel and add external symbols to
  219  * the kernel symbol name space in a future version, generally all
  220  * functions used in the implementation of a particular module should
  221  * be static unless they are expected to be seen in other modules or
  222  * to resolve unresolved symbols alread existing in the kernel (the
  223  * second case is not likely to ever occur).
  224  *
  225  * The entry point should return 0 unless it is refusing load (in which
  226  * case it should return an errno from errno.h).
  227  */
  228 int
  229 pcic_mod(struct lkm_table *lkmtp, int cmd, int ver)
  230 {
  231         MOD_DISPATCH(pcic, lkmtp, cmd, ver,
  232                 pcic_handle, pcic_handle, lkm_nullcmd);
  233 }
  234 
  235 /*
  236  *      pcic_unload - Called when unloading a LKM.
  237  *      Disables interrupts and resets PCIC.
  238  */
  239 static int
  240 pcic_unload(struct lkm_table *lkmtp, int cmd)
  241 {
  242         int     slot;
  243         struct pcic_slot *sp = pcic_slots;
  244 
  245         untimeout(pcictimeout, 0);
  246         if (pcic_irq) {
  247                 for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++) {
  248                         if (sp->slt)
  249                                 sp->putb(sp, PCIC_STAT_INT, 0);
  250                 }
  251                 unregister_intr(pcic_irq, pcicintr);
  252         }
  253         pccard_remove_controller(&cinfo);
  254         return(0);
  255 }
  256 
  257 #endif /* LKM */
  258 
  259 #if 0
  260 static void
  261 pcic_dump_attributes(unsigned char *scratch, int maxlen)
  262 {
  263         int i,j,k;
  264 
  265         i = 0;
  266         while (scratch[i] != 0xff && i < maxlen) {
  267                 unsigned char link = scratch[i+2];
  268 
  269                 /*
  270                  *      Dump attribute memory
  271                  */
  272                 if (scratch[i]) {
  273                         printf("[%02x] ", i);
  274                         for (j = 0; j < 2 * link + 4 && j < 128; j += 2)
  275                                 printf("%02x ", scratch[j + i]);
  276                         printf("\n");
  277                 }
  278                 i += 4 + 2 * link;
  279         }
  280 }
  281 #endif
  282 
  283 static void
  284 nullfunc(int unit)
  285 {
  286         /* empty */
  287 }
  288 
  289 static u_int
  290 build_freelist(u_int pcic_mask)
  291 { 
  292         int irq;
  293         u_int mask, freemask; 
  294  
  295         /* No free IRQs (yet). */ 
  296         freemask = 0; 
  297  
  298         /* Walk through all of the IRQ's and find any that aren't allocated. */ 
  299         for (irq = 1; irq < ICU_LEN; irq++) { 
  300                 /* 
  301                  * If the PCIC controller can't generate it, don't
  302                  * bother checking to see if it it's free. 
  303                  */ 
  304                 mask = 1 << irq; 
  305                 if (!(mask & pcic_mask)) continue; 
  306  
  307                 /* See if the IRQ is free. */
  308                 if (register_intr(irq, 0, 0, nullfunc, NULL, irq) == 0) {
  309                         /* Give it back, but add it to the mask */ 
  310                         INTRMASK(freemask, mask); 
  311                         unregister_intr(irq, nullfunc); 
  312                 }
  313         } 
  314 #ifdef PCIC_DEBUG
  315         printf("Freelist of IRQ's <0x%x>\n", freemask);
  316 #endif
  317         return freemask; 
  318 }
  319 
  320 /*
  321  *      entry point from main code to map/unmap memory context.
  322  */
  323 static int
  324 pcic_memory(struct slot *slt, int win)
  325 {
  326         struct pcic_slot *sp = slt->cdata;
  327         struct mem_desc *mp = &slt->mem[win];
  328         int reg = mp->window * PCIC_MEMSIZE + PCIC_MEMBASE;
  329 
  330 #ifdef  PC98
  331         if (sp->controller == PCIC_PC98) {
  332             if (mp->flags & MDF_ACTIVE) {
  333                 /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */
  334                 unsigned char x;
  335                 
  336                 if ((unsigned long)mp->start != 0xda000) {
  337                     printf("sys_addr must be 0xda000. requested address = 0x%x\n",
  338                            mp->start);
  339                     return(EINVAL);
  340                 }
  341                 
  342                 /* omajinai ??? */
  343                 outb(PCIC98_REG0, 0);
  344                 x = inb(PCIC98_REG1);
  345                 x &= 0xfc;
  346                 x |= 0x02;
  347                 outb(PCIC98_REG1, x);
  348                 
  349                 outw(PCIC98_REG_PAGOFS, 0);
  350                 
  351                 if (mp->flags & MDF_ATTR) {
  352                     outb(PCIC98_REG6, inb(PCIC98_REG6) | PCIC98_ATTRMEM);
  353                 }else{
  354                     outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_ATTRMEM));
  355                 }
  356                 
  357                 outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN);
  358                 
  359 #if 0
  360                 if (mp->flags & MDF_16BITS == 1) {      /* 16bit */
  361                     outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_8BIT));
  362                 }else{                                  /* 8bit */
  363                     outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT);
  364                 }
  365 #endif
  366             }else{
  367                 outb(PCIC98_REG_WINSEL, PCIC98_UNMAPWIN);
  368             }
  369             return 0;
  370         }
  371 #endif  /* PC98 */
  372 
  373         if (mp->flags & MDF_ACTIVE) {
  374                 unsigned long sys_addr = (unsigned long)mp->start >> 12;
  375                 /*
  376                  * Write the addresses, card offsets and length.
  377                  * The values are all stored as the upper 12 bits of the
  378                  * 24 bit address i.e everything is allocated as 4 Kb chunks.
  379                  */
  380                 putw(sp, reg, sys_addr & 0xFFF);
  381                 putw(sp, reg+2, (sys_addr + (mp->size >> 12) - 1) & 0xFFF);
  382                 putw(sp, reg+4, ((mp->card >> 12) - sys_addr) & 0x3FFF);
  383 #if 0
  384                 printf("card offs = card_adr = 0x%x 0x%x, sys_addr = 0x%x\n", 
  385                         mp->card, ((mp->card >> 12) - sys_addr) & 0x3FFF,
  386                         sys_addr);
  387 #endif
  388                 /*
  389                  *      Each 16 bit register has some flags in the upper bits.
  390                  */
  391                 if (mp->flags & MDF_16BITS)
  392                         setb(sp, reg+1, PCIC_DATA16);
  393                 if (mp->flags & MDF_ZEROWS)
  394                         setb(sp, reg+1, PCIC_ZEROWS);
  395                 if (mp->flags & MDF_WS0)
  396                         setb(sp, reg+3, PCIC_MW0);
  397                 if (mp->flags & MDF_WS1)
  398                         setb(sp, reg+3, PCIC_MW1);
  399                 if (mp->flags & MDF_ATTR)
  400                         setb(sp, reg+5, PCIC_REG);
  401                 if (mp->flags & MDF_WP)
  402                         setb(sp, reg+5, PCIC_WP);
  403 #if 0
  404         printf("Slot number %d, reg 0x%x, offs 0x%x\n",
  405                 sp->slotnum, reg, sp->offset);
  406         printf("Map window to sys addr 0x%x for %d bytes, card 0x%x\n",
  407                 mp->start, mp->size, mp->card);
  408         printf("regs are: 0x%02x%02x 0x%02x%02x 0x%02x%02x flags 0x%x\n",
  409                 sp->getb(sp, reg), sp->getb(sp, reg+1),
  410                 sp->getb(sp, reg+2), sp->getb(sp, reg+3),
  411                 sp->getb(sp, reg+4), sp->getb(sp, reg+5),
  412                 mp->flags);
  413 #endif
  414                 /*
  415                  * Enable the memory window. By experiment, we need a delay.
  416                  */
  417                 setb(sp, PCIC_ADDRWINE, (1<<win) | PCIC_MEMCS16);
  418                 DELAY(50);
  419         } else {
  420 #if 0
  421                 printf("Unmapping window %d\n", win);
  422 #endif
  423                 clrb(sp, PCIC_ADDRWINE, 1<<win);
  424                 putw(sp, reg, 0);
  425                 putw(sp, reg+2, 0);
  426                 putw(sp, reg+4, 0);
  427         }
  428         return(0);
  429 }
  430 
  431 /*
  432  *      pcic_io - map or unmap I/O context
  433  */
  434 static int
  435 pcic_io(struct slot *slt, int win)
  436 {
  437         int     mask, reg;
  438         struct pcic_slot *sp = slt->cdata;
  439         struct io_desc *ip = &slt->io[win];
  440 #ifdef  PC98
  441         if (sp->controller == PCIC_PC98) {
  442             unsigned char x;
  443 
  444 #if 0
  445             if (win =! 0) {
  446                 printf("pcic98:Illegal PCIC I/O window request(%d)!", win);
  447                 return(EINVAL);
  448             }
  449 #endif
  450 
  451             if (ip->flags & IODF_ACTIVE) {
  452                 unsigned short base;
  453 
  454                 x = inb(PCIC98_REG2) & 0x0f;
  455                 if (! (ip->flags & IODF_16BIT))
  456                     x |= PCIC98_8BIT;
  457 
  458                 if (ip->size > 16)      /* 128bytes mapping */
  459                     x |= PCIC98_MAP128;
  460 
  461                 x |= PCIC98_IOMEMORY;
  462                 outb(PCIC98_REG2, x);
  463     
  464                 base = 0x80d0;
  465                 outw(PCIC98_REG4, base);                /* 98side IO base */
  466                 outw(PCIC98_REG5, ip->start);   /* card side IO base */
  467 
  468 #ifdef  PCIC_DEBUG
  469                 printf("pcic98: IO mapped 0x%04x(98) -> 0x%04x(Card) and width %d bytes\n",
  470                        base, ip->start, ip->size);
  471 #endif
  472                 ip->start = base;
  473 
  474             }else{
  475                 outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_IOMEMORY));
  476             }
  477             return 0;
  478         }
  479 #endif
  480         switch (win) {
  481         case 0:
  482                 mask = PCIC_IO0_EN;
  483                 reg = PCIC_IO0;
  484                 break;
  485         case 1:
  486                 mask = PCIC_IO1_EN;
  487                 reg = PCIC_IO1;
  488                 break;
  489         default:
  490                 panic("Illegal PCIC I/O window request!");
  491         }
  492         if (ip->flags & IODF_ACTIVE) {
  493                 unsigned char x, ioctlv;
  494 
  495 #ifdef  PCIC_DEBUG
  496 printf("Map I/O 0x%x (size 0x%x) on Window %d\n", ip->start, ip->size, win);
  497 #endif  /* PCIC_DEBUG */
  498                 putw(sp, reg, ip->start);
  499                 putw(sp, reg+2, ip->start+ip->size-1);
  500                 x = 0;
  501                 if (ip->flags & IODF_ZEROWS)
  502                         x |= PCIC_IO_0WS;
  503                 if (ip->flags & IODF_WS)
  504                         x |= PCIC_IO_WS;
  505                 if (ip->flags & IODF_CS16)
  506                         x |= PCIC_IO_CS16;
  507                 if (ip->flags & IODF_16BIT)
  508                         x |= PCIC_IO_16BIT;
  509                 /*
  510                  * Extract the current flags and merge with new flags.
  511                  * Flags for window 0 in lower nybble, and in upper nybble
  512                  * for window 1.
  513                  */
  514                 ioctlv = sp->getb(sp, PCIC_IOCTL);
  515                 DELAY(100);
  516                 switch (win) {
  517                 case 0:
  518                         sp->putb(sp, PCIC_IOCTL, x | (ioctlv & 0xf0));
  519                         break;
  520                 case 1:
  521                         sp->putb(sp, PCIC_IOCTL, (x << 4) | (ioctlv & 0xf));
  522                         break;
  523                 }
  524                 DELAY(100);
  525                 setb(sp, PCIC_ADDRWINE, mask);
  526                 DELAY(100);
  527         } else {
  528                 clrb(sp, PCIC_ADDRWINE, mask);
  529                 DELAY(100);
  530                 putw(sp, reg, 0);
  531                 putw(sp, reg + 2, 0);
  532         }
  533         return(0);
  534 }
  535 
  536 /*
  537  *      Look for an Intel PCIC (or compatible).
  538  *      For each available slot, allocate a PC-CARD slot.
  539  */
  540 
  541 /*
  542  *      VLSI 82C146 has incompatibilities about the I/O address 
  543  *      of slot 1.  Assume it's the only PCIC whose vendor ID is 0x84,
  544  *      contact Nate Williams <nate@FreeBSD.org> if incorrect.
  545  */
  546 int
  547 pcic_probe(void)
  548 {
  549         int slotnum, i, validslots = 0;
  550         u_int free_irqs;
  551         struct slot *slt;
  552         struct pcic_slot *sp;
  553         unsigned char c;
  554         static int maybe_vlsi = 0;
  555 
  556         /* Determine the list of free interrupts */
  557         free_irqs = build_freelist(PCIC_INT_MASK_ALLOWED);
  558         
  559         /*
  560          *      Initialise controller information structure.
  561          */
  562         cinfo.mapmem = pcic_memory;
  563         cinfo.mapio = pcic_io;
  564         cinfo.ioctl = pcic_ioctl;
  565         cinfo.power = pcic_power;
  566         cinfo.mapirq = pcic_mapirq;
  567         cinfo.reset = pcic_reset;
  568         cinfo.disable = pcic_disable;
  569         cinfo.resume = pcic_resume;
  570         cinfo.maxmem = PCIC_MEM_WIN;
  571         cinfo.maxio = PCIC_IO_WIN;
  572         cinfo.irqs = free_irqs;
  573         cinfo.imask = &pcic_imask;
  574 
  575 #ifdef  LKM
  576         bzero(pcic_slots, sizeof(pcic_slots));
  577 #endif
  578         sp = pcic_slots;
  579         for (slotnum = 0; slotnum < PCIC_MAX_SLOTS; slotnum++, sp++) {
  580                 /*
  581                  *      Initialise the PCIC slot table.
  582                  */
  583                 sp->getb = getb1;
  584                 sp->putb = putb1;
  585                 if (slotnum < 4) {
  586                         sp->index = PCIC_INDEX_0;
  587                         sp->data = PCIC_DATA_0;
  588                         sp->offset = slotnum * PCIC_SLOT_SIZE;
  589                 } else {
  590                         sp->index = PCIC_INDEX_1;
  591                         sp->data = PCIC_DATA_1;
  592                         sp->offset = (slotnum - 4) * PCIC_SLOT_SIZE;
  593                 }
  594                 /* 
  595                  * XXX - Screwed up slot 1 on the VLSI chips.  According to
  596                  * the Linux PCMCIA code from David Hinds, working chipsets
  597                  * return 0x84 from their (correct) ID ports, while the broken
  598                  * ones would need to be probed at the new offset we set after
  599                  * we assume it's broken.
  600                  */
  601                 if (slotnum == 1 && maybe_vlsi && sp->getb(sp, PCIC_ID_REV) != 0x84) {
  602                         sp->index += 4;
  603                         sp->data += 4;
  604                         sp->offset = PCIC_SLOT_SIZE << 1;
  605                 }
  606                 /*
  607                  * see if there's a PCMCIA controller here
  608                  * Intel PCMCIA controllers use 0x82 and 0x83
  609                  * IBM clone chips use 0x88 and 0x89, apparently
  610                  */
  611                 c = sp->getb(sp, PCIC_ID_REV);
  612                 sp->revision = -1;
  613                 switch(c) {
  614                 /*
  615                  *      82365 or clones.
  616                  */
  617                 case 0x82:
  618                 case 0x83:
  619                         sp->controller = PCIC_I82365;
  620                         sp->revision = c & 1;
  621                         /*
  622                          *      Now check for VADEM chips.
  623                          */
  624                         outb(sp->index, 0x0E);
  625                         outb(sp->index, 0x37);
  626                         setb(sp, 0x3A, 0x40);
  627                         c = sp->getb(sp, PCIC_ID_REV);
  628                         if (c & 0x08) {
  629                                 sp->controller = ((sp->revision = c & 7) == 4) ?        
  630                                         PCIC_VG469 : PCIC_VG468 ;
  631                                 clrb(sp, 0x3A, 0x40);
  632                         }
  633 
  634                         /*
  635                          * Check for RICOH RF5C396 PCMCIA Controller
  636                          */
  637                         c = sp->getb(sp, 0x3a);
  638                         if (c == 0xb2) {
  639                                 sp->controller = PCIC_RF5C396;
  640                         }
  641 
  642                         break;
  643                 /*
  644                  *      VLSI chips.
  645                  */
  646                 case 0x84:
  647                         sp->controller = PCIC_VLSI;
  648                         maybe_vlsi = 1;
  649                         break;
  650                 case 0x88:
  651                 case 0x89:
  652                         sp->controller = PCIC_IBM;
  653                         sp->revision = c & 1;
  654                         break;
  655                 case 0x8a:
  656                         sp->controller = PCIC_IBM_KING;
  657                         sp->revision = c & 1;
  658                         break;
  659                 default:
  660                         continue;
  661                 }
  662                 /*
  663                  *      Check for Cirrus logic chips.
  664                  */
  665                 sp->putb(sp, 0x1F, 0);
  666                 c = sp->getb(sp, 0x1F);
  667                 if ((c & 0xC0) == 0xC0) {
  668                         c = sp->getb(sp, 0x1F);
  669                         if ((c & 0xC0) == 0) {
  670                                 if (c & 0x20)
  671                                         sp->controller = PCIC_PD672X;
  672                                 else
  673                                         sp->controller = PCIC_PD6710;
  674                                 sp->revision = 8 - ((c & 0x1F) >> 2);
  675                         }
  676                 }
  677                 switch(sp->controller) {
  678                 case PCIC_I82365:
  679                         cinfo.name = "Intel 82365";
  680                         break;
  681                 case PCIC_IBM:
  682                         cinfo.name = "IBM PCIC";
  683                         break;
  684                 case PCIC_IBM_KING:
  685                         cinfo.name = "IBM KING PCMCIA Controller";
  686                         break;
  687                 case PCIC_PD672X:
  688                         cinfo.name = "Cirrus Logic PD672X";
  689                         break;
  690                 case PCIC_PD6710:
  691                         cinfo.name = "Cirrus Logic PD6710";
  692                         break;
  693                 case PCIC_VG468:
  694                         cinfo.name = "Vadem 468";
  695                         break;
  696                 case PCIC_VG469:
  697                         cinfo.name = "Vadem 469";
  698                         break;
  699                 case PCIC_RF5C396:
  700                         cinfo.name = "Ricoh RF5C396";
  701                         break;
  702                 case PCIC_VLSI:
  703                         cinfo.name = "VLSI 82C146";
  704                         break;
  705                 default:
  706                         cinfo.name = "Unknown!";
  707                         break;
  708                 }
  709                 /*
  710                  *      OK it seems we have a PCIC or lookalike.
  711                  *      Allocate a slot and initialise the data structures.
  712                  */
  713                 validslots++;
  714                 sp->slotnum = slotnum;
  715                 slt = pccard_alloc_slot(&cinfo);
  716                 if (slt == 0)
  717                         continue;
  718                 slt->cdata = sp;
  719                 sp->slt = slt;
  720                 /*
  721                  *      If we haven't allocated an interrupt for the controller,
  722                  *      then attempt to get one.
  723                  */
  724                 if (pcic_irq == 0) {
  725                         pcic_imask = SWI_MASK;
  726                         pcic_irq = pccard_alloc_intr(free_irqs,
  727                                 pcicintr, 0, &pcic_imask, NULL);
  728                         if (pcic_irq < 0)
  729                                 printf("pcic: failed to allocate IRQ\n");
  730                         else
  731                                 printf("pcic: controller irq %d\n", pcic_irq);
  732                 }
  733                 /*
  734                  * Modem cards send the speaker audio (dialing noises)
  735                  * to the host's speaker.  Cirrus Logic PCIC chips must
  736                  * enable this.  There is also a Low Power Dynamic Mode bit
  737                  * that claims to reduce power consumption by 30%, so
  738                  * enable it and hope for the best.
  739                  */
  740                 if (sp->controller == PCIC_PD672X) {
  741                         setb(sp, PCIC_MISC1, PCIC_SPKR_EN);
  742                         setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
  743                 }
  744                 /*
  745                  *      Check for a card in this slot.
  746                  */
  747                 setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST);
  748                 if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {
  749                         slt->laststate = slt->state = empty;
  750                 } else {
  751                         slt->laststate = slt->state = filled;
  752                         pccard_event(sp->slt, card_inserted);
  753                 }
  754                 /*
  755                  *      Assign IRQ for slot changes
  756                  */
  757                 if (pcic_irq > 0)
  758                         sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
  759         }
  760 #ifdef  PC98
  761         if (validslots == 0) {
  762             sp = pcic_slots;
  763             slotnum = 0;
  764             if (inb(PCIC98_REG0) != 0xff) {
  765                 sp->controller = PCIC_PC98;
  766                 sp->revision = 0;
  767                 cinfo.name = "PC98 Original";
  768                 cinfo.maxmem = 1;
  769                 cinfo.maxio = 1;
  770 /*              cinfo.irqs = PCIC_INT_MASK_ALLOWED;*/
  771                 cinfo.irqs = 0x1468;
  772                 validslots++;
  773                 sp->slotnum = slotnum;
  774 
  775                 slt = pccard_alloc_slot(&cinfo);
  776                 if (slt == 0) {
  777                     printf("pcic98: slt == NULL\n");
  778                     goto pcic98_probe_end;
  779                 }
  780                 slt->cdata = sp;
  781                 sp->slt = slt;
  782 
  783                 /* Check for a card in this slot */
  784                 if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) {
  785                     /* PCMCIA card exist */
  786                     slt->laststate = slt->state = filled;
  787                     pccard_event(sp->slt, card_inserted);
  788                 } else {
  789                     slt->laststate = slt->state = empty;
  790                 }
  791             }
  792         pcic98_probe_end:
  793         }
  794 #endif  /* PC98 */
  795         if (validslots)
  796                 timeout(pcictimeout, 0, hz/2);
  797         return(validslots);
  798 }
  799 
  800 /*
  801  *      ioctl calls - Controller specific ioctls
  802  */
  803 static int
  804 pcic_ioctl(struct slot *slt, int cmd, caddr_t data)
  805 {
  806         struct pcic_slot *sp = slt->cdata;
  807 
  808         switch(cmd) {
  809         default:
  810                 return(EINVAL);
  811         /*
  812          * Get/set PCIC registers
  813          */
  814         case PIOCGREG:
  815                 ((struct pcic_reg *)data)->value =
  816                         sp->getb(sp, ((struct pcic_reg *)data)->reg);
  817                 break;
  818         case PIOCSREG:
  819                 sp->putb(sp, ((struct pcic_reg *)data)->reg,
  820                         ((struct pcic_reg *)data)->value);
  821                 break;
  822         }
  823         return(0);
  824 }
  825 
  826 /*
  827  *      pcic_power - Enable the power of the slot according to
  828  *      the parameters in the power structure(s).
  829  */
  830 static int
  831 pcic_power(struct slot *slt)
  832 {
  833         unsigned char reg = PCIC_DISRST|PCIC_PCPWRE;
  834         struct pcic_slot *sp = slt->cdata;
  835 
  836         switch(sp->controller) {
  837 #ifdef  PC98
  838         case PCIC_PC98:
  839             reg = inb(PCIC98_REG6) & (~PCIC98_VPP12V);
  840             switch(slt->pwr.vpp) {
  841             default:
  842                 return(EINVAL);
  843             case 50:
  844                 break;
  845             case 120:
  846                 reg |= PCIC98_VPP12V;
  847                 break;
  848             }
  849             outb(PCIC98_REG6, reg);
  850             DELAY(100*1000);
  851 
  852             reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V);
  853             switch(slt->pwr.vcc) {
  854             default:
  855                 return(EINVAL);
  856             case 33:
  857                 reg |= PCIC98_VCC3P3V;
  858                 break;
  859             case 50:
  860                 break;
  861             }
  862             outb(PCIC98_REG2, reg);
  863             DELAY(100*1000);
  864             return (0);
  865 #endif
  866         case PCIC_PD672X:
  867         case PCIC_PD6710:
  868         case PCIC_VG468:
  869         case PCIC_VG469:
  870         case PCIC_RF5C396:
  871         case PCIC_VLSI:
  872         case PCIC_IBM_KING:
  873                 switch(slt->pwr.vpp) {
  874                 default:
  875                         return(EINVAL);
  876                 case 0:
  877                         break;
  878                 case 50:
  879                 case 33:
  880                         reg |= PCIC_VPP_5V;
  881                         break;
  882                 case 120:
  883                         reg |= PCIC_VPP_12V;
  884                         break;
  885                 }
  886                 switch(slt->pwr.vcc) {
  887                 default:
  888                         return(EINVAL);
  889                 case 0:
  890                         break;
  891                 case 33:
  892                         if (sp->controller == PCIC_IBM_KING) {
  893                                 reg |= PCIC_VCC_5V_KING;
  894                                 break;
  895                         }
  896                         reg |= PCIC_VCC_3V;
  897                         if ((sp->controller == PCIC_VG468)||
  898                                 (sp->controller == PCIC_VG469))
  899                                 setb(sp, 0x2f, 0x03) ;
  900                         else
  901                                 setb(sp, 0x16, 0x02);
  902                         break;
  903                 case 50:
  904                         if (sp->controller == PCIC_IBM_KING) {
  905                                 reg |= PCIC_VCC_5V_KING;
  906                                 break;
  907                         }
  908                         reg |= PCIC_VCC_5V;
  909                         if ((sp->controller == PCIC_VG468)||
  910                                 (sp->controller == PCIC_VG469))
  911                                 clrb(sp, 0x2f, 0x03) ;
  912                         else
  913                                 clrb(sp, 0x16, 0x02);
  914                         break;
  915                 }
  916                 break;
  917         }
  918         sp->putb(sp, PCIC_POWER, reg);
  919         DELAY(300*1000);
  920         if (slt->pwr.vcc) {
  921                 reg |= PCIC_OUTENA;
  922                 sp->putb(sp, PCIC_POWER, reg);
  923                 DELAY(100*1000);
  924         }
  925         /* Some chips are smarter than us it seems, so if we weren't
  926          * allowed to use 5V, try 3.3 instead
  927          */
  928         if (!(sp->getb(sp, PCIC_STATUS) &  0x40) && slt->pwr.vcc == 50) {
  929                 slt->pwr.vcc = 33;
  930                 slt->pwr.vpp = 0;
  931                 return (pcic_power(slt));
  932         }
  933         return(0);
  934 }
  935 
  936 /*
  937  * tell the PCIC which irq we want to use.  only the following are legal:
  938  * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15
  939  */
  940 static void
  941 pcic_mapirq(struct slot *slt, int irq)
  942 {
  943         struct pcic_slot *sp = slt->cdata;
  944 #ifdef  PC98
  945         if (sp->controller == PCIC_PC98) {
  946             unsigned char x;
  947             switch (irq) {
  948             case 3:
  949                 x = PCIC98_INT0; break;
  950             case 5:
  951                 x = PCIC98_INT1; break;
  952             case 6:
  953                 x = PCIC98_INT2; break;
  954             case 10:
  955                 x = PCIC98_INT4; break;
  956             case 12:
  957                 x = PCIC98_INT5; break;
  958             case 0:             /* disable */
  959                 x = PCIC98_INTDISABLE;
  960                 break;
  961             default:
  962                 printf("pcic98: illegal irq %d\n", irq);
  963                 return;
  964             }
  965 #ifdef  PCIC_DEBUG
  966             printf("pcic98: irq=%d mapped.\n", irq);
  967 #endif
  968             outb(PCIC98_REG3, x);
  969 
  970             return;
  971         }       
  972 #endif
  973         if (irq == 0)
  974                 clrb(sp, PCIC_INT_GEN, 0xF);
  975         else
  976                 sp->putb(sp, PCIC_INT_GEN, 
  977                     (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq);
  978 }
  979 
  980 /*
  981  *      pcic_reset - Reset the card and enable initial power.
  982  */
  983 static void
  984 pcic_reset(void *chan)
  985 {
  986         struct slot *slt = chan;
  987         struct pcic_slot *sp = slt->cdata;
  988 
  989 #ifdef  PC98
  990         if (sp->controller == PCIC_PC98) {
  991             outb(PCIC98_REG0, 0);
  992             outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_IOMEMORY));
  993             outb(PCIC98_REG3, PCIC98_INTDISABLE);
  994             outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V));
  995             outb(PCIC98_REG6, inb(PCIC98_REG6) & (~PCIC98_VPP12V));
  996             outb(PCIC98_REG1, 0);
  997 
  998             selwakeup(&slt->selp);
  999             return;
 1000         }
 1001 #endif
 1002         switch (slt->insert_seq) {
 1003             case 0: /* Something funny happended on the way to the pub... */
 1004                 return;
 1005             case 1: /* Assert reset */
 1006                 clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET);
 1007                 slt->insert_seq = 2;
 1008                 timeout(pcic_reset, (void *)slt, hz/4);
 1009                 return;
 1010             case 2: /* Deassert it again */
 1011                 setb(sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD);
 1012                 slt->insert_seq = 3;
 1013                 timeout(pcic_reset, (void *)slt, hz/4);
 1014                 return;
 1015             case 3: /* Wait if card needs more time */
 1016                 if (!sp->getb(sp, PCIC_STATUS) & PCIC_READY) {
 1017                         timeout(pcic_reset, (void *)slt, hz/10);
 1018                         return;
 1019                 }
 1020         }
 1021         slt->insert_seq = 0;
 1022         if (sp->controller == PCIC_PD672X || sp->controller == PCIC_PD6710) {
 1023                 sp->putb(sp, PCIC_TIME_SETUP0, 0x1);
 1024                 sp->putb(sp, PCIC_TIME_CMD0, 0x6);
 1025                 sp->putb(sp, PCIC_TIME_RECOV0, 0x0);
 1026                 sp->putb(sp, PCIC_TIME_SETUP1, 1);
 1027                 sp->putb(sp, PCIC_TIME_CMD1, 0xf);
 1028                 sp->putb(sp, PCIC_TIME_RECOV1, 0);
 1029         }
 1030         selwakeup(&slt->selp);
 1031 }
 1032 
 1033 /*
 1034  *      pcic_disable - Disable the slot.
 1035  */
 1036 static void
 1037 pcic_disable(struct slot *slt)
 1038 {
 1039         struct pcic_slot *sp = slt->cdata;
 1040 
 1041 #ifdef  PC98
 1042         if (sp->controller == PCIC_PC98) {
 1043             return;
 1044         }
 1045 #endif
 1046         sp->putb(sp, PCIC_INT_GEN, 0);
 1047         sp->putb(sp, PCIC_POWER, 0);
 1048 }
 1049 
 1050 /*
 1051  *      PCIC timer, it seems that we lose interrupts sometimes
 1052  *      so poll just in case...
 1053  */
 1054 static void
 1055 pcictimeout(void *chan)
 1056 {
 1057         pcicintr(0);
 1058         timeout(pcictimeout, 0, hz/2);
 1059 }
 1060 
 1061 /*
 1062  *      PCIC Interrupt handler.
 1063  *      Check each slot in turn, and read the card status change
 1064  *      register. If this is non-zero, then a change has occurred
 1065  *      on this card, so send an event to the main code.
 1066  */
 1067 static void
 1068 pcicintr(int unit)
 1069 {
 1070         int     slot, s;
 1071         unsigned char chg;
 1072         struct pcic_slot *sp = pcic_slots;
 1073 
 1074 #ifdef  PC98
 1075         if (sp->controller == PCIC_PC98) {
 1076             slot = 0;
 1077             s = splhigh();
 1078             /* Check for a card in this slot */
 1079             if (inb(PCIC98_REG1) & PCIC98_CARDEXIST) {
 1080                 if (sp->slt->laststate != filled) {
 1081                     pccard_event(sp->slt, card_inserted);
 1082                 }
 1083             } else {
 1084                 if (sp->slt->laststate != empty) {
 1085                     pccard_event(sp->slt, card_removed);
 1086                 }
 1087             }
 1088             splx(s);
 1089             return;
 1090         }
 1091 #endif  /* PC98 */
 1092         s = splhigh();
 1093         for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++)
 1094                 if (sp->slt && (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0)
 1095                         if (chg & PCIC_CDTCH) {
 1096                                 if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) ==
 1097                                                 PCIC_CD) {
 1098                                         pccard_event(sp->slt, card_inserted);
 1099                                 } else {
 1100                                         pccard_event(sp->slt, card_removed);
 1101                                 }
 1102                         }
 1103         splx(s);
 1104 }
 1105 
 1106 /*
 1107  *      pcic_resume - Suspend/resume support for PCIC
 1108  */
 1109 static void
 1110 pcic_resume(struct slot *slt)
 1111 {
 1112         struct pcic_slot *sp = slt->cdata;
 1113         if (pcic_irq > 0)
 1114                 sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
 1115         if (sp->controller == PCIC_PD672X) {
 1116                 setb(sp, PCIC_MISC1, PCIC_SPKR_EN);
 1117                 setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
 1118         }
 1119 }

Cache object: cddb5d4e98a1c1dc2297bea09472d01c


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