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/pc/devpccard.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      cardbus and pcmcia (grmph) support.
    3 */
    4 #include "u.h"
    5 #include "../port/lib.h"
    6 #include "mem.h"
    7 #include "dat.h"
    8 #include "fns.h"
    9 #include "../port/error.h"
   10 #include "io.h"
   11 
   12 #define DEBUG   0
   13 
   14 #pragma varargck        type    "T"     int
   15 
   16 #define MAP(x,o)        (Rmap + (x)*0x8 + o)
   17 
   18 enum {
   19         TI_vid = 0x104c,
   20         TI_1131_did = 0xAC15,
   21         TI_1250_did = 0xAC16,
   22         TI_1450_did = 0xAC1B,
   23         TI_1251A_did = 0xAC1D,
   24         TI_1420_did = 0xAC51,
   25 
   26         Ricoh_vid = 0x1180,
   27         Ricoh_475_did = 0x0475,
   28         Ricoh_476_did = 0x0476,
   29         Ricoh_478_did = 0x0478,
   30 
   31         O2_vid = 0x1217,
   32         O2_OZ711M3_did = 0x7134,
   33 
   34         Nslots = 4,             /* Maximum number of CardBus slots to use */
   35 
   36         K = 1024,
   37         M = K * K,
   38 
   39         LegacyAddr = 0x3e0,
   40         NUMEVENTS = 10,
   41 
   42         TI1131xSC = 0x80,               /* system control */
   43                 TI122X_SC_INTRTIE = 1 << 29,
   44         TI12xxIM = 0x8c,                /*  */
   45         TI1131xCC = 0x91,               /* card control */
   46                 TI113X_CC_RIENB = 1 << 7,
   47                 TI113X_CC_ZVENABLE = 1 << 6,
   48                 TI113X_CC_PCI_IRQ_ENA = 1 << 5,
   49                 TI113X_CC_PCI_IREQ = 1 << 4,
   50                 TI113X_CC_PCI_CSC = 1 << 3,
   51                 TI113X_CC_SPKROUTEN = 1 << 1,
   52                 TI113X_CC_IFG = 1 << 0,
   53         TI1131xDC = 0x92,               /* device control */
   54 };
   55 
   56 typedef struct Variant Variant;
   57 struct Variant {
   58         ushort  vid;
   59         ushort  did;
   60         char    *name;
   61 };
   62 
   63 static Variant variant[] = {
   64 {       Ricoh_vid,      Ricoh_475_did,  "Ricoh 475 PCI/Cardbus bridge", },
   65 {       Ricoh_vid,      Ricoh_476_did,  "Ricoh 476 PCI/Cardbus bridge", },
   66 {       Ricoh_vid,      Ricoh_478_did,  "Ricoh 478 PCI/Cardbus bridge", },
   67 {       TI_vid,         TI_1131_did,    "TI PCI-1131 Cardbus Controller", },
   68 {       TI_vid,         TI_1250_did,    "TI PCI-1250 Cardbus Controller", },
   69 {       TI_vid,         TI_1450_did,    "TI PCI-1450 Cardbus Controller", },
   70 {       TI_vid,         TI_1251A_did,   "TI PCI-1251A Cardbus Controller", },
   71 {       TI_vid,         TI_1420_did,    "TI PCI-1420 Cardbus Controller", },
   72 {       O2_vid,         O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
   73 };
   74 
   75 /* Cardbus registers */
   76 enum {
   77         SocketEvent = 0,
   78                 SE_CCD = 3 << 1,
   79                 SE_POWER = 1 << 3,
   80         SocketMask = 1,
   81         SocketState = 2,
   82                 SS_CCD = 3 << 1,
   83                 SS_POWER = 1 << 3,
   84                 SS_PC16 = 1 << 4,
   85                 SS_CBC = 1 << 5,
   86                 SS_NOTCARD = 1 << 7,
   87                 SS_BADVCC = 1 << 9,
   88                 SS_5V = 1 << 10,
   89                 SS_3V = 1 << 11,
   90         SocketForce = 3,
   91         SocketControl = 4,
   92                 SC_5V = 0x22,
   93                 SC_3V = 0x33,
   94 };
   95 
   96 enum {
   97         PciPCR_IO = 1 << 0,
   98         PciPCR_MEM = 1 << 1,
   99         PciPCR_Master = 1 << 2,
  100 
  101         PciPMC = 0xa4,
  102 
  103         Nbars = 6,
  104         Ncmd = 10,
  105         CBIRQ = 9,
  106 
  107         PC16,
  108         PC32,
  109 };
  110 
  111 enum {
  112         Ti82365,
  113         Tpd6710,
  114         Tpd6720,
  115         Tvg46x,
  116 };
  117 
  118 /*
  119  *  Intel 82365SL PCIC controller for the PCMCIA or
  120  *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
  121  */
  122 enum
  123 {
  124         /*
  125          *  registers indices
  126          */
  127         Rid=            0x0,            /* identification and revision */
  128         Ris=            0x1,            /* interface status */
  129         Rpc=            0x2,            /* power control */
  130          Foutena=        (1<<7),        /*  output enable */
  131          Fautopower=     (1<<5),        /*  automatic power switching */
  132          Fcardena=       (1<<4),        /*  PC card enable */
  133         Rigc=           0x3,            /* interrupt and general control */
  134          Fiocard=        (1<<5),        /*  I/O card (vs memory) */
  135          Fnotreset=      (1<<6),        /*  reset if not set */
  136          FSMIena=        (1<<4),        /*  enable change interrupt on SMI */
  137         Rcsc=           0x4,            /* card status change */
  138         Rcscic=         0x5,            /* card status change interrupt config */
  139          Fchangeena=     (1<<3),        /*  card changed */
  140          Fbwarnena=      (1<<1),        /*  card battery warning */
  141          Fbdeadena=      (1<<0),        /*  card battery dead */
  142         Rwe=            0x6,            /* address window enable */
  143          Fmem16=         (1<<5),        /*  use A23-A12 to decode address */
  144         Rio=            0x7,            /* I/O control */
  145          Fwidth16=       (1<<0),        /*  16 bit data width */
  146          Fiocs16=        (1<<1),        /*  IOCS16 determines data width */
  147          Fzerows=        (1<<2),        /*  zero wait state */
  148          Ftiming=        (1<<3),        /*  timing register to use */
  149         Riobtm0lo=      0x8,            /* I/O address 0 start low byte */
  150         Riobtm0hi=      0x9,            /* I/O address 0 start high byte */
  151         Riotop0lo=      0xa,            /* I/O address 0 stop low byte */
  152         Riotop0hi=      0xb,            /* I/O address 0 stop high byte */
  153         Riobtm1lo=      0xc,            /* I/O address 1 start low byte */
  154         Riobtm1hi=      0xd,            /* I/O address 1 start high byte */
  155         Riotop1lo=      0xe,            /* I/O address 1 stop low byte */
  156         Riotop1hi=      0xf,            /* I/O address 1 stop high byte */
  157         Rmap=           0x10,           /* map 0 */
  158 
  159         /*
  160          *  CL-PD67xx extension registers
  161          */
  162         Rmisc1=         0x16,           /* misc control 1 */
  163          F5Vdetect=      (1<<0),
  164          Fvcc3V=         (1<<1),
  165          Fpmint=         (1<<2),
  166          Fpsirq=         (1<<3),
  167          Fspeaker=       (1<<4),
  168          Finpack=        (1<<7),
  169         Rfifo=          0x17,           /* fifo control */
  170          Fflush=         (1<<7),        /*  flush fifo */
  171         Rmisc2=         0x1E,           /* misc control 2 */
  172          Flowpow=        (1<<1),        /*  low power mode */
  173         Rchipinfo=      0x1F,           /* chip information */
  174         Ratactl=        0x26,           /* ATA control */
  175 
  176         /*
  177          *  offsets into the system memory address maps
  178          */
  179         Mbtmlo=         0x0,            /* System mem addr mapping start low byte */
  180         Mbtmhi=         0x1,            /* System mem addr mapping start high byte */
  181          F16bit=         (1<<7),        /*  16-bit wide data path */
  182         Mtoplo=         0x2,            /* System mem addr mapping stop low byte */
  183         Mtophi=         0x3,            /* System mem addr mapping stop high byte */
  184          Ftimer1=        (1<<6),        /*  timer set 1 */
  185         Mofflo=         0x4,            /* Card memory offset address low byte */
  186         Moffhi=         0x5,            /* Card memory offset address high byte */
  187          Fregactive=     (1<<6),        /*  attribute memory */
  188 
  189         /*
  190          *  configuration registers - they start at an offset in attribute
  191          *  memory found in the CIS.
  192          */
  193         Rconfig=        0,
  194          Creset=         (1<<7),        /*  reset device */
  195          Clevel=         (1<<6),        /*  level sensitive interrupt line */
  196 };
  197 
  198 /*
  199  *  read and crack the card information structure enough to set
  200  *  important parameters like power
  201  */
  202 /* cis memory walking */
  203 typedef struct Cisdat Cisdat;
  204 struct Cisdat {
  205         uchar           *cisbase;
  206         int             cispos;
  207         int             cisskip;
  208         int             cislen;
  209 };
  210 
  211 typedef struct Pcminfo Pcminfo;
  212 struct Pcminfo {
  213         char            verstr[512];            /* Version string */
  214         PCMmap          mmap[4];                /* maps, last is always for the kernel */
  215         ulong           conf_addr;              /* Config address */
  216         uchar           conf_present;           /* Config register present */
  217         int             nctab;                  /* In use configuration tables */
  218         PCMconftab      ctab[8];                /* Configuration tables */
  219         PCMconftab      *defctab;               /* Default conftab */
  220 
  221         int             port;                   /* Actual port usage */
  222         int             irq;                    /* Actual IRQ usage */
  223 };
  224 
  225 typedef struct Cardbus Cardbus;
  226 struct Cardbus {
  227         Lock;
  228         Variant         *variant;               /* Which CardBus chipset */
  229         Pcidev          *pci;                   /* The bridge itself */
  230         ulong           *regs;                  /* Cardbus registers */
  231         int             ltype;                  /* Legacy type */
  232         int             lindex;                 /* Legacy port index address */
  233         int             ldata;                  /* Legacy port data address */
  234         int             lbase;                  /* Base register for this socket */
  235 
  236         int             state;                  /* Current state of card */
  237         int             type;                   /* Type of card */
  238         Pcminfo         linfo;                  /* PCMCIA slot info */
  239 
  240         int             special;                /* card is allocated to a driver */
  241 
  242         int             refs;                   /* Number of refs to slot */
  243         Lock            refslock;               /* inc/dev ref lock */
  244 };
  245 
  246 static int managerstarted;
  247 
  248 enum {
  249         Mshift= 12,
  250         Mgran=  (1<<Mshift),    /* granularity of maps */
  251         Mmask=  ~(Mgran-1),     /* mask for address bits important to the chip */
  252 };
  253 
  254 static Cardbus cbslots[Nslots];
  255 static int nslots;
  256 
  257 static ulong exponent[8] = {
  258         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
  259 };
  260 
  261 static ulong vmant[16] = {
  262         10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
  263 };
  264 
  265 static ulong mantissa[16] = {
  266         0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
  267 };
  268 
  269 static char Enocard[] = "No card in slot";
  270 
  271 enum
  272 {
  273         CMdown,
  274         CMpower,
  275 };
  276 
  277 static Cmdtab pccardctlmsg[] =
  278 {
  279         CMdown,         "down", 2,
  280         CMpower,        "power",        1,
  281 };
  282 
  283 static int powerup(Cardbus *);
  284 static void configure(Cardbus *);
  285 static void powerdown(Cardbus *cb);
  286 static void unconfigure(Cardbus *cb);
  287 
  288 static void i82365probe(Cardbus *cb, int lindex, int ldata);
  289 static void i82365configure(Cardbus *cb);
  290 static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
  291 static void isaunmap(PCMmap* m);
  292 static uchar rdreg(Cardbus *cb, int index);
  293 static void wrreg(Cardbus *cb, int index, uchar val);
  294 static int readc(Cisdat *cis, uchar *x);
  295 static void tvers1(Cardbus *cb, Cisdat *cis, int );
  296 static void tcfig(Cardbus *cb, Cisdat *cis, int );
  297 static void tentry(Cardbus *cb, Cisdat *cis, int );
  298 static int vcode(int volt);
  299 static int pccard_pcmspecial(char *idstr, ISAConf *isa);
  300 static void pccard_pcmspecialclose(int slotno);
  301 
  302 enum {
  303         CardDetected,
  304         CardPowered,
  305         CardEjected,
  306         CardConfigured,
  307 };
  308 
  309 static char *messages[] = {
  310 [CardDetected]          "CardDetected",
  311 [CardPowered]           "CardPowered",
  312 [CardEjected]           "CardEjected",
  313 [CardConfigured]        "CardConfigured",
  314 };
  315 
  316 enum {
  317         SlotEmpty,
  318         SlotFull,
  319         SlotPowered,
  320         SlotConfigured,
  321 };
  322 
  323 static char *states[] = {
  324 [SlotEmpty]             "SlotEmpty",
  325 [SlotFull]              "SlotFull",
  326 [SlotPowered]           "SlotPowered",
  327 [SlotConfigured]        "SlotConfigured",
  328 };
  329 
  330 static void
  331 engine(Cardbus *cb, int message)
  332 {
  333         if(DEBUG)
  334                 print("engine(%ld): %s(%s)\n", cb - cbslots,
  335                         states[cb->state], messages[message]);
  336         switch (cb->state) {
  337         case SlotEmpty:
  338 
  339                 switch (message) {
  340                 case CardDetected:
  341                         cb->state = SlotFull;
  342                         powerup(cb);
  343                         break;
  344                 case CardEjected:
  345                         break;
  346                 default:
  347                         if(DEBUG)
  348                                 print("#Y%ld: Invalid message %s in SlotEmpty state\n",
  349                                         cb - cbslots, messages[message]);
  350                         break;
  351                 }
  352                 break;
  353 
  354         case SlotFull:
  355 
  356                 switch (message) {
  357                 case CardPowered:
  358                         cb->state = SlotPowered;
  359                         configure(cb);
  360                         break;
  361                 case CardEjected:
  362                         cb->state = SlotEmpty;
  363                         powerdown(cb);
  364                         break;
  365                 default:
  366                         if(DEBUG)
  367                                 print("#Y%ld: Invalid message %s in SlotFull state\n",
  368                                         cb - cbslots, messages[message]);
  369                         break;
  370                 }
  371                 break;
  372 
  373         case SlotPowered:
  374 
  375                 switch (message) {
  376                 case CardConfigured:
  377                         cb->state = SlotConfigured;
  378                         break;
  379                 case CardEjected:
  380                         cb->state = SlotEmpty;
  381                         unconfigure(cb);
  382                         powerdown(cb);
  383                         break;
  384                 default:
  385                         print("#Y%ld: Invalid message %s in SlotPowered state\n",
  386                                 cb - cbslots, messages[message]);
  387                         break;
  388                 }
  389                 break;
  390 
  391         case SlotConfigured:
  392 
  393                 switch (message) {
  394                 case CardEjected:
  395                         cb->state = SlotEmpty;
  396                         unconfigure(cb);
  397                         powerdown(cb);
  398                         break;
  399                 default:
  400                         if(DEBUG)
  401                                 print("#Y%ld: Invalid message %s in SlotConfigured state\n",
  402                                         cb - cbslots, messages[message]);
  403                         break;
  404                 }
  405                 break;
  406         }
  407 }
  408 
  409 static void
  410 qengine(Cardbus *cb, int message)
  411 {
  412         lock(cb);
  413         engine(cb, message);
  414         unlock(cb);
  415 }
  416 
  417 typedef struct Events Events;
  418 struct Events {
  419         Cardbus *cb;
  420         int     message;
  421 };
  422 
  423 static Lock levents;
  424 static Events events[NUMEVENTS];
  425 static Rendez revents;
  426 static int nevents;
  427 
  428 static void
  429 iengine(Cardbus *cb, int message)
  430 {
  431         if (nevents >= NUMEVENTS) {
  432                 print("#Y: Too many events queued, discarding request\n");
  433                 return;
  434         }
  435         ilock(&levents);
  436         events[nevents].cb = cb;
  437         events[nevents].message = message;
  438         nevents++;
  439         iunlock(&levents);
  440         wakeup(&revents);
  441 }
  442 
  443 static int
  444 eventoccured(void)
  445 {
  446         return nevents > 0;
  447 }
  448 
  449 static void
  450 processevents(void *)
  451 {
  452         while (1) {
  453                 int message;
  454                 Cardbus *cb;
  455 
  456                 sleep(&revents, (int (*)(void *))eventoccured, nil);
  457 
  458                 cb = nil;
  459                 message = 0;
  460                 ilock(&levents);
  461                 if (nevents > 0) {
  462                         cb = events[0].cb;
  463                         message = events[0].message;
  464                         nevents--;
  465                         if (nevents > 0)
  466                                 memmove(events, &events[1], nevents * sizeof(Events));
  467                 }
  468                 iunlock(&levents);
  469 
  470                 if (cb)
  471                         qengine(cb, message);
  472         }
  473 }
  474 
  475 static void
  476 cbinterrupt(Ureg *, void *)
  477 {
  478         int i;
  479 
  480         for (i = 0; i != nslots; i++) {
  481                 Cardbus *cb = &cbslots[i];
  482                 ulong event, state;
  483 
  484                 event = cb->regs[SocketEvent];
  485                 if(!(event & (SE_POWER|SE_CCD)))
  486                         continue;
  487                 state = cb->regs[SocketState];
  488                 rdreg(cb, Rcsc);        /* Ack the interrupt */
  489 
  490                 if(DEBUG)
  491                         print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n",
  492                                 cb - cbslots, event, state, states[cb->state]);
  493 
  494                 if (event & SE_CCD) {
  495                         cb->regs[SocketEvent] |= SE_CCD;        /* Ack interrupt */
  496                         if (state & SE_CCD) {
  497                                 if (cb->state != SlotEmpty) {
  498                                         print("#Y: take cardejected interrupt\n");
  499                                         iengine(cb, CardEjected);
  500                                 }
  501                         }
  502                         else
  503                                 iengine(cb, CardDetected);
  504                 }
  505 
  506                 if (event & SE_POWER) {
  507                         cb->regs[SocketEvent] |= SE_POWER;      /* Ack interrupt */
  508                         iengine(cb, CardPowered);
  509                 }
  510         }
  511 }
  512 
  513 void
  514 devpccardlink(void)
  515 {
  516         static int initialized;
  517         Pcidev *pci;
  518         int i;
  519         uchar intl;
  520         char *p;
  521         void *baddrva;
  522 
  523         if (initialized)
  524                 return;
  525         initialized = 1;
  526 
  527         if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
  528                 return;
  529 
  530         if(_pcmspecial)
  531                 return;
  532 
  533         /* Allocate legacy space */
  534         if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
  535                 print("#Y: WARNING: Cannot allocate legacy ports\n");
  536 
  537         /* Find all CardBus controllers */
  538         pci = nil;
  539         intl = 0xff;
  540         while ((pci = pcimatch(pci, 0, 0)) != nil) {
  541                 ulong baddr;
  542                 Cardbus *cb;
  543                 int slot;
  544                 uchar pin;
  545 
  546                 if(pci->ccrb != 6 || pci->ccru != 7)
  547                         continue;
  548                 for (i = 0; i != nelem(variant); i++)
  549                         if (pci->vid == variant[i].vid && pci->did == variant[i].did)
  550                                 break;
  551                 if (i == nelem(variant))
  552                         continue;
  553 
  554                 /* initialize this slot */
  555                 slot = nslots++;
  556                 cb = &cbslots[slot];
  557 
  558                 cb->pci = pci;
  559                 cb->variant = &variant[i];
  560 
  561                 if (pci->vid != TI_vid) {
  562                         /*
  563                          * Gross hack, needs a fix.  Inherit the mappings from
  564                          * 9load for the TIs (pb)
  565                          */
  566                         pcicfgw32(pci, PciCBMBR0, 0xffffffff);
  567                         pcicfgw32(pci, PciCBMLR0, 0);
  568                         pcicfgw32(pci, PciCBMBR1, 0xffffffff);
  569                         pcicfgw32(pci, PciCBMLR1, 0);
  570                         pcicfgw32(pci, PciCBIBR0, 0xffffffff);
  571                         pcicfgw32(pci, PciCBILR0, 0);
  572                         pcicfgw32(pci, PciCBIBR1, 0xffffffff);
  573                         pcicfgw32(pci, PciCBILR1, 0);
  574                 }
  575 
  576                 /* Set up PCI bus numbers if needed. */
  577                 if (pcicfgr8(pci, PciSBN) == 0) {
  578                         static int busbase = 0x20;
  579 
  580                         pcicfgw8(pci, PciSBN, busbase);
  581                         pcicfgw8(pci, PciUBN, busbase + 2);
  582                         busbase += 3;
  583                 }
  584 
  585                 /* Patch up intl if needed. */
  586                 if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
  587                     (pci->intl == 0xff || pci->intl == 0)) {
  588                         pci->intl = pciipin(nil, pin);
  589                         pcicfgw8(pci, PciINTL, pci->intl);
  590 
  591                         if (pci->intl == 0xff || pci->intl == 0)
  592                                 print("#Y%ld: No interrupt?\n", cb - cbslots);
  593                 }
  594 
  595                 /* Don't you love standards! */
  596                 if (pci->vid == TI_vid) {
  597                         if (pci->did <= TI_1131_did) {
  598                                 uchar cc;
  599 
  600                                 cc = pcicfgr8(pci, TI1131xCC);
  601                                 cc &= ~(TI113X_CC_PCI_IRQ_ENA |
  602                                         TI113X_CC_PCI_IREQ |
  603                                         TI113X_CC_PCI_CSC |
  604                                         TI113X_CC_ZVENABLE);
  605                                 cc |= TI113X_CC_PCI_IRQ_ENA |
  606                                         TI113X_CC_PCI_IREQ |
  607                                         TI113X_CC_SPKROUTEN;
  608                                 pcicfgw8(pci, TI1131xCC, cc);
  609 
  610                                 /* PCI interrupts only */
  611                                 pcicfgw8(pci, TI1131xDC,
  612                                         pcicfgr8(pci, TI1131xDC) & ~6);
  613 
  614                                 /* CSC ints to PCI bus. */
  615                                 wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
  616                         }
  617                         else if (pci->did == TI_1250_did) {
  618                                 print("No support yet for the TI_1250_did, prod pb\n");
  619                         }
  620                         else if (pci->did == TI_1420_did) {
  621                                 /* Disable Vcc protection */
  622                                 pcicfgw32(cb->pci, 0x80,
  623                                         pcicfgr32(cb->pci, 0x80) | (1 << 21));
  624                         }
  625 
  626                         pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
  627                 }
  628                 if (pci->vid == O2_vid) {
  629                         if(DEBUG)
  630                                 print("writing O2 config\n");
  631                         pcicfgw8(cb->pci, 0x94, 0xCA);
  632                         pcicfgw8(cb->pci, 0xD4, 0xCA);
  633                 }
  634 
  635                 if (intl != 0xff && intl != pci->intl)
  636                         intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
  637                 intl = pci->intl;
  638 
  639                 if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
  640                         int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
  641 
  642                         baddr = upaalloc(size, size);
  643                         baddrva = vmap(baddr, size);
  644                         pcicfgw32(cb->pci, PciBAR0, baddr);
  645                         cb->regs = (ulong *)baddrva;
  646                 }
  647                 else
  648                         cb->regs = (ulong *)vmap(baddr, 4096);
  649                 cb->state = SlotEmpty;
  650 
  651                 /* Don't really know what to do with this... */
  652                 i82365probe(cb, LegacyAddr, LegacyAddr + 1);
  653 
  654                 print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
  655                          variant[i].name, baddr, pci->intl);
  656         }
  657 
  658         if (nslots == 0){
  659                 iofree(LegacyAddr);
  660                 return;
  661         }
  662 
  663         _pcmspecial = pccard_pcmspecial;
  664         _pcmspecialclose = pccard_pcmspecialclose;
  665 
  666         for (i = 0; i != nslots; i++) {
  667                 Cardbus *cb = &cbslots[i];
  668 
  669                 if ((cb->regs[SocketState] & SE_CCD) == 0)
  670                         engine(cb, CardDetected);
  671         }
  672 
  673         delay(500);                     /* Allow time for power up */
  674 
  675         for (i = 0; i != nslots; i++) {
  676                 Cardbus *cb = &cbslots[i];
  677 
  678                 if (cb->regs[SocketState] & SE_POWER)
  679                         engine(cb, CardPowered);
  680 
  681                 /* Ack and enable interrupts on all events */
  682                 // cb->regs[SocketEvent] = cb->regs[SocketEvent];
  683                 cb->regs[SocketMask] |= 0xF;
  684                 wrreg(cb, Rcscic, 0xC);
  685         }
  686 }
  687 
  688 static int
  689 powerup(Cardbus *cb)
  690 {
  691         ulong state;
  692         ushort bcr;
  693 
  694         state = cb->regs[SocketState];
  695         if (state & SS_PC16) {
  696                 if(DEBUG)
  697                         print("#Y%ld: Probed a PC16 card, powering up card\n",
  698                                 cb - cbslots);
  699                 cb->type = PC16;
  700                 memset(&cb->linfo, 0, sizeof(Pcminfo));
  701 
  702                 /* power up and unreset, wait's are empirical (???) */
  703                 wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
  704                 delay(300);
  705                 wrreg(cb, Rigc, 0);
  706                 delay(100);
  707                 wrreg(cb, Rigc, Fnotreset);
  708                 delay(500);
  709 
  710 //              return 1;
  711         }
  712 
  713         if (state & SS_CCD)
  714                 return 0;
  715 
  716         if (state & SS_NOTCARD) {
  717                 print("#Y%ld: No card inserted\n", cb - cbslots);
  718                 return 0;
  719         }
  720 
  721         if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
  722                 print("#Y%ld: Unsupported voltage, powering down card!\n",
  723                         cb - cbslots);
  724                 cb->regs[SocketControl] = 0;
  725                 return 0;
  726         }
  727 
  728         if(DEBUG)
  729                 print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
  730                         (state & SS_POWER)? "": "not ",
  731                         (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
  732 
  733         /* Power up the card
  734          * and make sure the secondary bus is not in reset.
  735          */
  736         cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
  737         delay(50);
  738         bcr = pcicfgr16(cb->pci, PciBCR);
  739         bcr &= ~0x40;
  740         pcicfgw16(cb->pci, PciBCR, bcr);
  741         delay(100);
  742 
  743         if (state & SS_PC16)
  744                 cb->type = PC16;
  745         else
  746                 cb->type = PC32;
  747 
  748         return 1;
  749 }
  750 
  751 static void
  752 powerdown(Cardbus *cb)
  753 {
  754         ushort bcr;
  755 
  756         if (cb->type == PC16) {
  757 
  758                 wrreg(cb, Rpc, 0);      /* turn off card power */
  759                 wrreg(cb, Rwe, 0);      /* no windows */
  760 
  761                 cb->type = -1;
  762                 return;
  763         }
  764 
  765         bcr = pcicfgr16(cb->pci, PciBCR);
  766         bcr |= 0x40;
  767         pcicfgw16(cb->pci, PciBCR, bcr);
  768         cb->regs[SocketControl] = 0;
  769         cb->type = -1;
  770 }
  771 
  772 static void
  773 configure(Cardbus *cb)
  774 {
  775         int i, r;
  776         ulong size, bar;
  777         Pcidev *pci;
  778         ulong membase, iobase, memlen, iolen, rombase, romlen;
  779 
  780         if(DEBUG)
  781                 print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);
  782         if (cb->state == SlotConfigured)
  783                 return;
  784         engine(cb, CardConfigured);
  785 
  786         delay(50);                                      /* Emperically established */
  787 
  788         if (cb->type == PC16) {
  789                 i82365configure(cb);
  790                 return;
  791         }
  792 
  793         /* Scan the CardBus for new PCI devices */
  794         pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
  795 
  796         /*
  797          * size the devices on the bus, reserve a minimum for devices arriving later,
  798          * allow for ROM space, allocate space, and set the cardbus mapping registers
  799          */
  800         pcibussize(cb->pci->bridge, &memlen, &iolen);   /* TO DO: need initial alignments */
  801 
  802         romlen = 0;
  803         for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
  804                 size = pcibarsize(pci, PciEBAR0);
  805                 if(size > 0){
  806                         pci->rom.bar = -1;
  807                         pci->rom.size = size;
  808                         romlen += size;
  809                 }
  810         }
  811 
  812         if(iolen < 512)
  813                 iolen = 512;
  814         iobase = ioreserve(~0, iolen, 0, "cardbus");
  815         pcicfgw32(cb->pci, PciCBIBR0, iobase);
  816         pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
  817         pcicfgw32(cb->pci, PciCBIBR1, 0);
  818         pcicfgw32(cb->pci, PciCBILR1, 0);
  819 
  820         rombase = memlen;
  821         memlen += romlen;
  822         if(memlen < 1*1024*1024)
  823                 memlen = 1*1024*1024;
  824         membase = upaalloc(memlen, 4*1024*1024);        /* TO DO: better alignment */
  825         pcicfgw32(cb->pci, PciCBMBR0, membase);
  826         pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1);
  827         pcicfgw32(cb->pci, PciCBMBR1, 0);
  828         pcicfgw32(cb->pci, PciCBMLR1, 0);
  829 
  830 //      pcibussize(cb->pci->bridge, &membase, &iobase); /* now assign them */
  831         rombase += membase;
  832 
  833         for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
  834                 r = pcicfgr16(pci, PciPCR);
  835                 r &= ~(PciPCR_IO|PciPCR_MEM);
  836                 pcicfgw16(pci, PciPCR, r);
  837 
  838                 /*
  839                  * Treat the found device as an ordinary PCI card.
  840                  * It seems that the CIS is not always present in
  841                  * CardBus cards.
  842                  * XXX, need to support multifunction cards
  843                  */
  844                 for(i = 0; i < Nbars; i++) {
  845                         if(pci->mem[i].size == 0)
  846                                 continue;
  847                         bar = pci->mem[i].bar;
  848                         if(bar & 1)
  849                                 bar += iobase;
  850                         else
  851                                 bar += membase;
  852                         pci->mem[i].bar = bar;
  853                         pcicfgw32(pci, PciBAR0 + 4*i, bar);
  854                         if((bar & 1) == 0){
  855                                 print("%T mem[%d] %8.8lux %d\n", pci->tbdf, i, bar, pci->mem[i].size);
  856                                 if(bar & 0x80){ /* TO DO: enable prefetch */
  857                                         ;
  858                                 }
  859                         }
  860                 }
  861                 if((size = pcibarsize(pci, PciEBAR0)) > 0) {    /* TO DO: can this be done by pci.c? */
  862                         pci->rom.bar = rombase;
  863                         pci->rom.size = size;
  864                         rombase += size;
  865                         pcicfgw32(pci, PciEBAR0, pci->rom.bar);
  866                 }
  867 
  868                 /* Set the basic PCI registers for the device */
  869                 pci->pcr = pcicfgr16(pci, PciPCR);
  870                 pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
  871                 pci->cls = 8;
  872                 pci->ltr = 64;
  873                 pcicfgw16(pci, PciPCR, pci->pcr);
  874                 pcicfgw8(pci, PciCLS, pci->cls);
  875                 pcicfgw8(pci, PciLTR, pci->ltr);
  876 
  877                 if (pcicfgr8(pci, PciINTP)) {
  878                         pci->intl = pcicfgr8(cb->pci, PciINTL);
  879                         pcicfgw8(pci, PciINTL, pci->intl);
  880 
  881                         /* Route interrupts to INTA#/B# */
  882                         pcicfgw16(cb->pci, PciBCR,
  883                                           pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
  884                 }
  885         }
  886 }
  887 
  888 static void
  889 unconfigure(Cardbus *cb)
  890 {
  891         Pcidev *pci;
  892         int i, ioindex, memindex, r;
  893 
  894         if (cb->type == PC16) {
  895                 print("#Y%d: Don't know how to unconfigure a PC16 card\n",
  896                          (int)(cb - cbslots));
  897 
  898                 memset(&cb->linfo, 0, sizeof(Pcminfo));
  899                 return;
  900         }
  901 
  902         pci = cb->pci->bridge;
  903         if (pci == nil)
  904                 return;         /* Not configured */
  905         cb->pci->bridge = nil;
  906 
  907         memindex = ioindex = 0;
  908         while (pci) {
  909                 Pcidev *_pci;
  910 
  911                 for (i = 0; i != Nbars; i++) {
  912                         if (pci->mem[i].size == 0)
  913                                 continue;
  914                         if (pci->mem[i].bar & 1) {
  915                                 iofree(pci->mem[i].bar & ~1);
  916                                 pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
  917                                                  (ushort)-1);
  918                                 pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
  919                                 ioindex++;
  920                                 continue;
  921                         }
  922 
  923                         upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
  924                         pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
  925                         pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
  926                         r = pcicfgr16(cb->pci, PciBCR);
  927                         r &= ~(1 << (8 + memindex));
  928                         pcicfgw16(cb->pci, PciBCR, r);
  929                         memindex++;
  930                 }
  931 
  932                 if (pci->rom.bar && memindex < 2) {
  933                         upafree(pci->rom.bar & ~0xF, pci->rom.size);
  934                         pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
  935                         pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
  936                         memindex++;
  937                 }
  938 
  939                 _pci = pci->list;
  940                 free(_pci);
  941                 pci = _pci;
  942         }
  943 }
  944 
  945 static void
  946 i82365configure(Cardbus *cb)
  947 {
  948         int this;
  949         Cisdat cis;
  950         PCMmap *m;
  951         uchar type, link;
  952 
  953         /*
  954          * Read all tuples in attribute space.
  955          */
  956         m = isamap(cb, 0, 0, 1);
  957         if(m == 0)
  958                 return;
  959 
  960         cis.cisbase = KADDR(m->isa);
  961         cis.cispos = 0;
  962         cis.cisskip = 2;
  963         cis.cislen = m->len;
  964 
  965         /* loop through all the tuples */
  966         for(;;){
  967                 this = cis.cispos;
  968                 if(readc(&cis, &type) != 1)
  969                         break;
  970                 if(type == 0xFF)
  971                         break;
  972                 if(readc(&cis, &link) != 1)
  973                         break;
  974 
  975                 switch(type){
  976                 default:
  977                         break;
  978                 case 0x15:
  979                         tvers1(cb, &cis, type);
  980                         break;
  981                 case 0x1A:
  982                         tcfig(cb, &cis, type);
  983                         break;
  984                 case 0x1B:
  985                         tentry(cb, &cis, type);
  986                         break;
  987                 }
  988 
  989                 if(link == 0xFF)
  990                         break;
  991                 cis.cispos = this + (2+link);
  992         }
  993         isaunmap(m);
  994 }
  995 
  996 /*
  997  *  look for a card whose version contains 'idstr'
  998  */
  999 static int
 1000 pccard_pcmspecial(char *idstr, ISAConf *isa)
 1001 {
 1002         int i, irq;
 1003         PCMconftab *ct, *et;
 1004         Pcminfo *pi;
 1005         Cardbus *cb;
 1006         uchar x, we, *p;
 1007 
 1008         cb = nil;
 1009         for (i = 0; i != nslots; i++) {
 1010                 cb = &cbslots[i];
 1011 
 1012                 lock(cb);
 1013                 if (cb->state == SlotConfigured &&
 1014                     cb->type == PC16 &&
 1015                     !cb->special &&
 1016                     strstr(cb->linfo.verstr, idstr))
 1017                         break;
 1018                 unlock(cb);
 1019         }
 1020 
 1021         if (i == nslots) {
 1022                 if(0 && DEBUG)
 1023                         print("#Y: %s not found\n", idstr);
 1024                 return -1;
 1025         }
 1026 
 1027         pi = &cb->linfo;
 1028 
 1029         /*
 1030           *  configure the PCMslot for IO.  We assume very heavily that we can read
 1031           *  configuration info from the CIS.  If not, we won't set up correctly.
 1032           */
 1033         irq = isa->irq;
 1034         if(irq == 2)
 1035                 irq = 9;
 1036 
 1037         et = &pi->ctab[pi->nctab];
 1038         ct = nil;
 1039         for(i = 0; i < isa->nopt; i++){
 1040                 int index;
 1041                 char *cp;
 1042 
 1043                 if(strncmp(isa->opt[i], "index=", 6))
 1044                         continue;
 1045                 index = strtol(&isa->opt[i][6], &cp, 0);
 1046                 if(cp == &isa->opt[i][6] || index >= pi->nctab) {
 1047                         unlock(cb);
 1048                         print("#Y%d: Cannot find index %d in conf table\n",
 1049                                  (int)(cb - cbslots), index);
 1050                         return -1;
 1051                 }
 1052                 ct = &pi->ctab[index];
 1053         }
 1054 
 1055         if(ct == nil){
 1056                 PCMconftab *t;
 1057 
 1058                 /* assume default is right */
 1059                 if(pi->defctab)
 1060                         ct = pi->defctab;
 1061                 else
 1062                         ct = pi->ctab;
 1063 
 1064                 /* try for best match */
 1065                 if(ct->nio == 0
 1066                 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
 1067                         for(t = pi->ctab; t < et; t++)
 1068                                 if(t->nio
 1069                                 && t->io[0].start == isa->port
 1070                                 && ((1<<irq) & t->irqs)){
 1071                                         ct = t;
 1072                                         break;
 1073                                 }
 1074                 }
 1075                 if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
 1076                         for(t = pi->ctab; t < et; t++)
 1077                                 if(t->nio && ((1<<irq) & t->irqs)){
 1078                                         ct = t;
 1079                                         break;
 1080                                 }
 1081                 }
 1082                 if(ct->nio == 0){
 1083                         for(t = pi->ctab; t < et; t++)
 1084                                 if(t->nio){
 1085                                         ct = t;
 1086                                         break;
 1087                                 }
 1088                 }
 1089         }
 1090 
 1091         if(ct == et || ct->nio == 0) {
 1092                 unlock(cb);
 1093                 print("#Y%d: No configuration?\n", (int)(cb - cbslots));
 1094                 return -1;
 1095         }
 1096         if(isa->port == 0 && ct->io[0].start == 0) {
 1097                 unlock(cb);
 1098                 print("#Y%d: No part or start address\n", (int)(cb - cbslots));
 1099                 return -1;
 1100         }
 1101 
 1102         cb->special = 1;        /* taken */
 1103 
 1104         /* route interrupts */
 1105         isa->irq = irq;
 1106         wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
 1107 
 1108         /* set power and enable device */
 1109         x = vcode(ct->vpp1);
 1110         wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
 1111 
 1112         /* 16-bit data path */
 1113         if(ct->bit16)
 1114                 x = Ftiming|Fiocs16|Fwidth16;
 1115         else
 1116                 x = Ftiming;
 1117         if(ct->nio == 2 && ct->io[1].start)
 1118                 x |= x<<4;
 1119         wrreg(cb, Rio, x);
 1120 
 1121         /*
 1122          * enable io port map 0
 1123          * the 'top' register value includes the last valid address
 1124          */
 1125         if(isa->port == 0)
 1126                 isa->port = ct->io[0].start;
 1127         we = rdreg(cb, Rwe);
 1128         wrreg(cb, Riobtm0lo, isa->port);
 1129         wrreg(cb, Riobtm0hi, isa->port>>8);
 1130         i = isa->port+ct->io[0].len-1;
 1131         wrreg(cb, Riotop0lo, i);
 1132         wrreg(cb, Riotop0hi, i>>8);
 1133         we |= 1<<6;
 1134         if(ct->nio == 2 && ct->io[1].start){
 1135                 wrreg(cb, Riobtm1lo, ct->io[1].start);
 1136                 wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
 1137                 i = ct->io[1].start+ct->io[1].len-1;
 1138                 wrreg(cb, Riotop1lo, i);
 1139                 wrreg(cb, Riotop1hi, i>>8);
 1140                 we |= 1<<7;
 1141         }
 1142         wrreg(cb, Rwe, we);
 1143 
 1144         /* only touch Rconfig if it is present */
 1145         if(pi->conf_present & (1<<Rconfig)){
 1146                 PCMmap *m;
 1147 
 1148                 /*  Reset adapter */
 1149                 m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
 1150                 p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
 1151 
 1152                 /* set configuration and interrupt type */
 1153                 x = ct->index;
 1154                 if(ct->irqtype & 0x20)
 1155                         x |= Clevel;
 1156                 *p = x;
 1157                 delay(5);
 1158 
 1159                 isaunmap(m);
 1160         }
 1161 
 1162         pi->port = isa->port;
 1163         pi->irq = isa->irq;
 1164         unlock(cb);
 1165 
 1166         print("#Y%ld: %s irq %d, port %lX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);
 1167         return (int)(cb - cbslots);
 1168 }
 1169 
 1170 static void
 1171 pccard_pcmspecialclose(int slotno)
 1172 {
 1173         Cardbus *cb = &cbslots[slotno];
 1174 
 1175         wrreg(cb, Rwe, 0);      /* no windows */
 1176         cb->special = 0;
 1177 }
 1178 
 1179 static Chan*
 1180 pccardattach(char *spec)
 1181 {
 1182         if (!managerstarted) {
 1183                 managerstarted = 1;
 1184                 kproc("cardbus", processevents, nil);
 1185         }
 1186         return devattach('Y', spec);
 1187 }
 1188 
 1189 enum
 1190 {
 1191         Qdir,
 1192         Qctl,
 1193 
 1194         Nents = 1,
 1195 };
 1196 
 1197 #define SLOTNO(c)       ((ulong)((c->qid.path>>8)&0xff))
 1198 #define TYPE(c) ((ulong)(c->qid.path&0xff))
 1199 #define QID(s,t)        (((s)<<8)|(t))
 1200 
 1201 static int
 1202 pccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
 1203 {
 1204         int slotno;
 1205         Qid qid;
 1206         long len;
 1207         int entry;
 1208 
 1209         if(i == DEVDOTDOT){
 1210                 mkqid(&qid, Qdir, 0, QTDIR);
 1211                 devdir(c, qid, "#Y", 0, eve, 0555, dp);
 1212                 return 1;
 1213         }
 1214 
 1215         len = 0;
 1216         if(i >= Nents * nslots) return -1;
 1217         slotno = i / Nents;
 1218         entry = i % Nents;
 1219         if (entry == 0) {
 1220                 qid.path = QID(slotno, Qctl);
 1221                 snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno);
 1222         }
 1223         else {
 1224                 /* Entries for memory regions.  I'll implement them when
 1225                      needed. (pb) */
 1226         }
 1227         qid.vers = 0;
 1228         qid.type = QTFILE;
 1229         devdir(c, qid, up->genbuf, len, eve, 0660, dp);
 1230         return 1;
 1231 }
 1232 
 1233 static Walkqid*
 1234 pccardwalk(Chan *c, Chan *nc, char **name, int nname)
 1235 {
 1236         return devwalk(c, nc, name, nname, 0, 0, pccardgen);
 1237 }
 1238 
 1239 static int
 1240 pccardstat(Chan *c, uchar *db, int n)
 1241 {
 1242         return devstat(c, db, n, 0, 0, pccardgen);
 1243 }
 1244 
 1245 static void
 1246 increfp(Cardbus *cb)
 1247 {
 1248         lock(&cb->refslock);
 1249         cb->refs++;
 1250         unlock(&cb->refslock);
 1251 }
 1252 
 1253 static void
 1254 decrefp(Cardbus *cb)
 1255 {
 1256         lock(&cb->refslock);
 1257         cb->refs--;
 1258         unlock(&cb->refslock);
 1259 }
 1260 
 1261 static Chan*
 1262 pccardopen(Chan *c, int omode)
 1263 {
 1264         if (c->qid.type & QTDIR){
 1265                 if(omode != OREAD)
 1266                         error(Eperm);
 1267         } else
 1268                 increfp(&cbslots[SLOTNO(c)]);
 1269         c->mode = openmode(omode);
 1270         c->flag |= COPEN;
 1271         c->offset = 0;
 1272         return c;
 1273 }
 1274 
 1275 static void
 1276 pccardclose(Chan *c)
 1277 {
 1278         if(c->flag & COPEN)
 1279                 if((c->qid.type & QTDIR) == 0)
 1280                         decrefp(&cbslots[SLOTNO(c)]);
 1281 }
 1282 
 1283 static long
 1284 pccardread(Chan *c, void *a, long n, vlong offset)
 1285 {
 1286         Cardbus *cb;
 1287         char *buf, *p, *e;
 1288         int i;
 1289 
 1290         switch(TYPE(c)){
 1291         case Qdir:
 1292                 return devdirread(c, a, n, 0, 0, pccardgen);
 1293 
 1294         case Qctl:
 1295                 buf = p = malloc(READSTR);
 1296                 buf[0] = 0;
 1297                 e = p + READSTR;
 1298 
 1299                 cb = &cbslots[SLOTNO(c)];
 1300                 lock(cb);
 1301                 p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]);
 1302 
 1303                 switch (cb->type) {
 1304                 case -1:
 1305                         seprint(p, e, "\n");
 1306                         break;
 1307 
 1308                 case PC32:
 1309                         if (cb->pci->bridge) {
 1310                                 Pcidev *pci = cb->pci->bridge;
 1311                                 int i;
 1312 
 1313                                 while (pci) {
 1314                                         p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
 1315                                                           pci->vid, pci->did, pci->intl);
 1316                                         for (i = 0; i != Nbars; i++)
 1317                                                 if (pci->mem[i].size)
 1318                                                         p = seprint(p, e,
 1319                                                                           "\tmem[%d] %.8ulX (%.8uX)\n",
 1320                                                                           i, pci->mem[i].bar,
 1321                                                                           pci->mem[i].size);
 1322                                         if (pci->rom.size)
 1323                                                 p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n",
 1324                                                                   pci->rom.bar, pci->rom.size);
 1325                                         pci = pci->list;
 1326                                 }
 1327                         }
 1328                         break;
 1329 
 1330                 case PC16:
 1331                         if (cb->state == SlotConfigured) {
 1332                                 Pcminfo *pi = &cb->linfo;
 1333 
 1334                                 p = seprint(p, e, "%s port %X; irq %d;\n",
 1335                                                   pi->verstr, pi->port,
 1336                                                   pi->irq);
 1337                                 for (i = 0; i != pi->nctab; i++) {
 1338                                         PCMconftab *ct;
 1339                                         int j;
 1340 
 1341                                         ct = &pi->ctab[i];
 1342                                         p = seprint(p, e,
 1343                                                 "\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n",
 1344                                                           i, ct->irqs, ct->vpp1, ct->vpp2,
 1345                                                           (ct == pi->defctab)? "(default);": "");
 1346                                         for (j = 0; j != ct->nio; j++)
 1347                                                 if (ct->io[j].len > 0)
 1348                                                         p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n",
 1349                                                                           j, ct->io[j].start, ct->io[j].len);
 1350                                 }
 1351                         }
 1352                         break;
 1353                 }
 1354                 unlock(cb);
 1355 
 1356                 n = readstr(offset, a, n, buf);
 1357                 free(buf);
 1358                 return n;
 1359         }
 1360         return 0;
 1361 }
 1362 
 1363 static long
 1364 pccardwrite(Chan *c, void *v, long n, vlong)
 1365 {
 1366         Rune r;
 1367         ulong n0;
 1368         char *device;
 1369         Cmdbuf *cbf;
 1370         Cmdtab *ct;
 1371         Cardbus *cb;
 1372 
 1373         n0 = n;
 1374         switch(TYPE(c)){
 1375         case Qctl:
 1376                 cb = &cbslots[SLOTNO(c)];
 1377 
 1378                 cbf = parsecmd(v, n);
 1379                 if(waserror()){
 1380                         free(cbf);
 1381                         nexterror();
 1382                 }
 1383                 ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg));
 1384                 switch(ct->index){
 1385                 case CMdown:
 1386                         device = cbf->f[1];
 1387                         device += chartorune(&r, device);
 1388                         if ((n = devno(r, 1)) >= 0 && devtab[n]->config)
 1389                                 devtab[n]->config(0, device, nil);
 1390                         qengine(cb, CardEjected);
 1391                         break;
 1392                 case CMpower:
 1393                         if ((cb->regs[SocketState] & SS_CCD) == 0)
 1394                                 qengine(cb, CardDetected);
 1395                         break;
 1396                 }
 1397                 poperror();
 1398                 free(cbf);
 1399                 break;
 1400         }
 1401         return n0 - n;
 1402 }
 1403 
 1404 Dev pccarddevtab = {
 1405         'Y',
 1406         "cardbus",
 1407 
 1408         devreset,
 1409         devinit,
 1410         devshutdown,
 1411         pccardattach,
 1412         pccardwalk,
 1413         pccardstat,
 1414         pccardopen,
 1415         devcreate,
 1416         pccardclose,
 1417         pccardread,
 1418         devbread,
 1419         pccardwrite,
 1420         devbwrite,
 1421         devremove,
 1422         devwstat,
 1423 };
 1424 
 1425 static PCMmap *
 1426 isamap(Cardbus *cb, ulong offset, int len, int attr)
 1427 {
 1428         uchar we, bit;
 1429         PCMmap *m, *nm;
 1430         Pcminfo *pi;
 1431         int i;
 1432         ulong e;
 1433 
 1434         pi = &cb->linfo;
 1435 
 1436         /* convert offset to granularity */
 1437         if(len <= 0)
 1438                 len = 1;
 1439         e = ROUND(offset+len, Mgran);
 1440         offset &= Mmask;
 1441         len = e - offset;
 1442 
 1443         /* look for a map that covers the right area */
 1444         we = rdreg(cb, Rwe);
 1445         bit = 1;
 1446         nm = 0;
 1447         for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
 1448                 if((we & bit))
 1449                 if(m->attr == attr)
 1450                 if(offset >= m->ca && e <= m->cea){
 1451 
 1452                         m->ref++;
 1453                         return m;
 1454                 }
 1455                 bit <<= 1;
 1456                 if(nm == 0 && m->ref == 0)
 1457                         nm = m;
 1458         }
 1459         m = nm;
 1460         if(m == 0)
 1461                 return 0;
 1462 
 1463         /* if isa space isn't big enough, free it and get more */
 1464         if(m->len < len){
 1465                 if(m->isa){
 1466                         umbfree(m->isa, m->len);
 1467                         m->len = 0;
 1468                 }
 1469                 m->isa = PADDR(umbmalloc(0, len, Mgran));
 1470                 if(m->isa == 0){
 1471                         print("isamap: out of isa space\n");
 1472                         return 0;
 1473                 }
 1474                 m->len = len;
 1475         }
 1476 
 1477         /* set up new map */
 1478         m->ca = offset;
 1479         m->cea = m->ca + m->len;
 1480         m->attr = attr;
 1481         i = m - pi->mmap;
 1482         bit = 1<<i;
 1483         wrreg(cb, Rwe, we & ~bit);              /* disable map before changing it */
 1484         wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
 1485         wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
 1486         wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
 1487         wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
 1488         offset -= m->isa;
 1489         offset &= (1<<25)-1;
 1490         offset >>= Mshift;
 1491         wrreg(cb, MAP(i, Mofflo), offset);
 1492         wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
 1493         wrreg(cb, Rwe, we | bit);               /* enable map */
 1494         m->ref = 1;
 1495 
 1496         return m;
 1497 }
 1498 
 1499 static void
 1500 isaunmap(PCMmap* m)
 1501 {
 1502         m->ref--;
 1503 }
 1504 
 1505 /*
 1506  *  reading and writing card registers
 1507  */
 1508 static uchar
 1509 rdreg(Cardbus *cb, int index)
 1510 {
 1511         outb(cb->lindex, cb->lbase + index);
 1512         return inb(cb->ldata);
 1513 }
 1514 
 1515 static void
 1516 wrreg(Cardbus *cb, int index, uchar val)
 1517 {
 1518         outb(cb->lindex, cb->lbase + index);
 1519         outb(cb->ldata, val);
 1520 }
 1521 
 1522 static int
 1523 readc(Cisdat *cis, uchar *x)
 1524 {
 1525         if(cis->cispos >= cis->cislen)
 1526                 return 0;
 1527         *x = cis->cisbase[cis->cisskip*cis->cispos];
 1528         cis->cispos++;
 1529         return 1;
 1530 }
 1531 
 1532 static ulong
 1533 getlong(Cisdat *cis, int size)
 1534 {
 1535         uchar c;
 1536         int i;
 1537         ulong x;
 1538 
 1539         x = 0;
 1540         for(i = 0; i < size; i++){
 1541                 if(readc(cis, &c) != 1)
 1542                         break;
 1543                 x |= c<<(i*8);
 1544         }
 1545         return x;
 1546 }
 1547 
 1548 static void
 1549 tcfig(Cardbus *cb, Cisdat *cis, int )
 1550 {
 1551         uchar size, rasize, rmsize;
 1552         uchar last;
 1553         Pcminfo *pi;
 1554 
 1555         if(readc(cis, &size) != 1)
 1556                 return;
 1557         rasize = (size&0x3) + 1;
 1558         rmsize = ((size>>2)&0xf) + 1;
 1559         if(readc(cis, &last) != 1)
 1560                 return;
 1561 
 1562         pi = &cb->linfo;
 1563         pi->conf_addr = getlong(cis, rasize);
 1564         pi->conf_present = getlong(cis, rmsize);
 1565 }
 1566 
 1567 static void
 1568 tvers1(Cardbus *cb, Cisdat *cis, int )
 1569 {
 1570         uchar c, major, minor, last;
 1571         int  i;
 1572         Pcminfo *pi;
 1573 
 1574         pi = &cb->linfo;
 1575         if(readc(cis, &major) != 1)
 1576                 return;
 1577         if(readc(cis, &minor) != 1)
 1578                 return;
 1579         last = 0;
 1580         for(i = 0; i < sizeof(pi->verstr) - 1; i++){
 1581                 if(readc(cis, &c) != 1)
 1582                         return;
 1583                 if(c == 0)
 1584                         c = ';';
 1585                 if(c == '\n')
 1586                         c = ';';
 1587                 if(c == 0xff)
 1588                         break;
 1589                 if(c == ';' && last == ';')
 1590                         continue;
 1591                 pi->verstr[i] = c;
 1592                 last = c;
 1593         }
 1594         pi->verstr[i] = 0;
 1595 }
 1596 
 1597 static ulong
 1598 microvolt(Cisdat *cis)
 1599 {
 1600         uchar c;
 1601         ulong microvolts;
 1602         ulong exp;
 1603 
 1604         if(readc(cis, &c) != 1)
 1605                 return 0;
 1606         exp = exponent[c&0x7];
 1607         microvolts = vmant[(c>>3)&0xf]*exp;
 1608         while(c & 0x80){
 1609                 if(readc(cis, &c) != 1)
 1610                         return 0;
 1611                 switch(c){
 1612                 case 0x7d:
 1613                         break;          /* high impedence when sleeping */
 1614                 case 0x7e:
 1615                 case 0x7f:
 1616                         microvolts = 0; /* no connection */
 1617                         break;
 1618                 default:
 1619                         exp /= 10;
 1620                         microvolts += exp*(c&0x7f);
 1621                 }
 1622         }
 1623         return microvolts;
 1624 }
 1625 
 1626 static ulong
 1627 nanoamps(Cisdat *cis)
 1628 {
 1629         uchar c;
 1630         ulong nanoamps;
 1631 
 1632         if(readc(cis, &c) != 1)
 1633                 return 0;
 1634         nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
 1635         while(c & 0x80){
 1636                 if(readc(cis, &c) != 1)
 1637                         return 0;
 1638                 if(c == 0x7d || c == 0x7e || c == 0x7f)
 1639                         nanoamps = 0;
 1640         }
 1641         return nanoamps;
 1642 }
 1643 
 1644 /*
 1645  * only nominal voltage (feature 1) is important for config,
 1646  * other features must read card to stay in sync.
 1647  */
 1648 static ulong
 1649 power(Cisdat *cis)
 1650 {
 1651         uchar feature;
 1652         ulong mv;
 1653 
 1654         mv = 0;
 1655         if(readc(cis, &feature) != 1)
 1656                 return 0;
 1657         if(feature & 1)
 1658                 mv = microvolt(cis);
 1659         if(feature & 2)
 1660                 microvolt(cis);
 1661         if(feature & 4)
 1662                 microvolt(cis);
 1663         if(feature & 8)
 1664                 nanoamps(cis);
 1665         if(feature & 0x10)
 1666                 nanoamps(cis);
 1667         if(feature & 0x20)
 1668                 nanoamps(cis);
 1669         if(feature & 0x40)
 1670                 nanoamps(cis);
 1671         return mv/1000000;
 1672 }
 1673 
 1674 static ulong
 1675 ttiming(Cisdat *cis, int scale)
 1676 {
 1677         uchar unscaled;
 1678         ulong nanosecs;
 1679 
 1680         if(readc(cis, &unscaled) != 1)
 1681                 return 0;
 1682         nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
 1683         nanosecs = nanosecs * exponent[scale];
 1684         return nanosecs;
 1685 }
 1686 
 1687 static void
 1688 timing(Cisdat *cis, PCMconftab *ct)
 1689 {
 1690         uchar c, i;
 1691 
 1692         if(readc(cis, &c) != 1)
 1693                 return;
 1694         i = c&0x3;
 1695         if(i != 3)
 1696                 ct->maxwait = ttiming(cis, i);          /* max wait */
 1697         i = (c>>2)&0x7;
 1698         if(i != 7)
 1699                 ct->readywait = ttiming(cis, i);        /* max ready/busy wait */
 1700         i = (c>>5)&0x7;
 1701         if(i != 7)
 1702                 ct->otherwait = ttiming(cis, i);        /* reserved wait */
 1703 }
 1704 
 1705 static void
 1706 iospaces(Cisdat *cis, PCMconftab *ct)
 1707 {
 1708         uchar c;
 1709         int i, nio;
 1710 
 1711         ct->nio = 0;
 1712         if(readc(cis, &c) != 1)
 1713                 return;
 1714 
 1715         ct->bit16 = ((c>>5)&3) >= 2;
 1716         if(!(c & 0x80)){
 1717                 ct->io[0].start = 0;
 1718                 ct->io[0].len = 1<<(c&0x1f);
 1719                 ct->nio = 1;
 1720                 return;
 1721         }
 1722 
 1723         if(readc(cis, &c) != 1)
 1724                 return;
 1725 
 1726         /*
 1727          * For each of the range descriptions read the
 1728          * start address and the length (value is length-1).
 1729          */
 1730         nio = (c&0xf)+1;
 1731         for(i = 0; i < nio; i++){
 1732                 ct->io[i].start = getlong(cis, (c>>4)&0x3);
 1733                 ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
 1734         }
 1735         ct->nio = nio;
 1736 }
 1737 
 1738 static void
 1739 irq(Cisdat *cis, PCMconftab *ct)
 1740 {
 1741         uchar c;
 1742 
 1743         if(readc(cis, &c) != 1)
 1744                 return;
 1745         ct->irqtype = c & 0xe0;
 1746         if(c & 0x10)
 1747                 ct->irqs = getlong(cis, 2);
 1748         else
 1749                 ct->irqs = 1<<(c&0xf);
 1750         ct->irqs &= 0xDEB8;             /* levels available to card */
 1751 }
 1752 
 1753 static void
 1754 memspace(Cisdat *cis, int asize, int lsize, int host)
 1755 {
 1756         ulong haddress, address, len;
 1757 
 1758         len = getlong(cis, lsize)*256;
 1759         address = getlong(cis, asize)*256;
 1760         USED(len, address);
 1761         if(host){
 1762                 haddress = getlong(cis, asize)*256;
 1763                 USED(haddress);
 1764         }
 1765 }
 1766 
 1767 static void
 1768 tentry(Cardbus *cb, Cisdat *cis, int )
 1769 {
 1770         uchar c, i, feature;
 1771         PCMconftab *ct;
 1772         Pcminfo *pi;
 1773 
 1774         pi = &cb->linfo;
 1775         if(pi->nctab >= nelem(pi->ctab))
 1776                 return;
 1777         if(readc(cis, &c) != 1)
 1778                 return;
 1779         ct = &pi->ctab[pi->nctab++];
 1780 
 1781         /* copy from last default config */
 1782         if(pi->defctab)
 1783                 *ct = *pi->defctab;
 1784 
 1785         ct->index = c & 0x3f;
 1786 
 1787         /* is this the new default? */
 1788         if(c & 0x40)
 1789                 pi->defctab = ct;
 1790 
 1791         /* memory wait specified? */
 1792         if(c & 0x80){
 1793                 if(readc(cis, &i) != 1)
 1794                         return;
 1795                 if(i&0x80)
 1796                         ct->memwait = 1;
 1797         }
 1798 
 1799         if(readc(cis, &feature) != 1)
 1800                 return;
 1801         switch(feature&0x3){
 1802         case 1:
 1803                 ct->vpp1 = ct->vpp2 = power(cis);
 1804                 break;
 1805         case 2:
 1806                 power(cis);
 1807                 ct->vpp1 = ct->vpp2 = power(cis);
 1808                 break;
 1809         case 3:
 1810                 power(cis);
 1811                 ct->vpp1 = power(cis);
 1812                 ct->vpp2 = power(cis);
 1813                 break;
 1814         default:
 1815                 break;
 1816         }
 1817         if(feature&0x4)
 1818                 timing(cis, ct);
 1819         if(feature&0x8)
 1820                 iospaces(cis, ct);
 1821         if(feature&0x10)
 1822                 irq(cis, ct);
 1823         switch((feature>>5)&0x3){
 1824         case 1:
 1825                 memspace(cis, 0, 2, 0);
 1826                 break;
 1827         case 2:
 1828                 memspace(cis, 2, 2, 0);
 1829                 break;
 1830         case 3:
 1831                 if(readc(cis, &c) != 1)
 1832                         return;
 1833                 for(i = 0; i <= (c&0x7); i++)
 1834                         memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
 1835                 break;
 1836         }
 1837 }
 1838 
 1839 static void
 1840 i82365probe(Cardbus *cb, int lindex, int ldata)
 1841 {
 1842         uchar c, id;
 1843         int dev = 0;    /* According to the Ricoh spec 00->3F _and_ 80->BF seem
 1844                                      to be the same socket A (ditto for B). */
 1845 
 1846         outb(lindex, Rid + (dev<<7));
 1847         id = inb(ldata);
 1848         if((id & 0xf0) != 0x80)
 1849                 return;         /* not a memory & I/O card */
 1850         if((id & 0x0f) == 0x00)
 1851                 return;         /* no revision number, not possible */
 1852 
 1853         cb->lindex = lindex;
 1854         cb->ldata = ldata;
 1855         cb->ltype = Ti82365;
 1856         cb->lbase = (int)(cb - cbslots) * 0x40;
 1857 
 1858         switch(id){
 1859         case 0x82:
 1860         case 0x83:
 1861         case 0x84:
 1862                 /* could be a cirrus */
 1863                 outb(cb->lindex, Rchipinfo + (dev<<7));
 1864                 outb(cb->ldata, 0);
 1865                 c = inb(cb->ldata);
 1866                 if((c & 0xc0) != 0xc0)
 1867                         break;
 1868                 c = inb(cb->ldata);
 1869                 if((c & 0xc0) != 0x00)
 1870                         break;
 1871                 if(c & 0x20){
 1872                         cb->ltype = Tpd6720;
 1873                 } else {
 1874                         cb->ltype = Tpd6710;
 1875                 }
 1876 
 1877                 /* low power mode */
 1878                 outb(cb->lindex, Rmisc2 + (dev<<7));
 1879                 c = inb(cb->ldata);
 1880                 outb(cb->ldata, c & ~Flowpow);
 1881                 break;
 1882                 break;
 1883         }
 1884 
 1885         /* if it's not a Cirrus, it could be a Vadem... */
 1886         if(cb->ltype == Ti82365){
 1887                 /* unlock the Vadem extended regs */
 1888                 outb(cb->lindex, 0x0E + (dev<<7));
 1889                 outb(cb->lindex, 0x37 + (dev<<7));
 1890 
 1891                 /* make the id register show the Vadem id */
 1892                 outb(cb->lindex, 0x3A + (dev<<7));
 1893                 c = inb(cb->ldata);
 1894                 outb(cb->ldata, c|0xC0);
 1895                 outb(cb->lindex, Rid + (dev<<7));
 1896                 c = inb(cb->ldata);
 1897                 if(c & 0x08)
 1898                         cb->ltype = Tvg46x;
 1899 
 1900                 /* go back to Intel compatible id */
 1901                 outb(cb->lindex, 0x3A + (dev<<7));
 1902                 c = inb(cb->ldata);
 1903                 outb(cb->ldata, c & ~0xC0);
 1904         }
 1905 }
 1906 
 1907 static int
 1908 vcode(int volt)
 1909 {
 1910         switch(volt){
 1911         case 5:
 1912                 return 1;
 1913         case 12:
 1914                 return 2;
 1915         default:
 1916                 return 0;
 1917         }
 1918 }

Cache object: 10d0bb69a78ec3dcbca2de157d8867d7


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