root/dev/isa/isapnp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isapnp_init
  2. isapnp_shift_bit
  3. isapnp_findcard
  4. isapnp_free_region
  5. isapnp_alloc_region
  6. isapnp_alloc_irq
  7. isapnp_alloc_drq
  8. isapnp_testconfig
  9. isapnp_config
  10. isapnp_unconfig
  11. isapnp_bestconfig
  12. isapnp_id_to_vendor
  13. isapnp_print_region
  14. isapnp_print_pin
  15. isapnp_print
  16. isapnp_com_submatch
  17. isapnp_submatch
  18. isapnp_find
  19. isapnp_configure
  20. isapnp_isa_attach_hook
  21. isapnp_match
  22. isapnp_attach

    1 /*      $OpenBSD: isapnp.c,v 1.35 2003/04/27 11:22:53 ho Exp $  */
    2 /*      $NetBSD: isapnp.c,v 1.9.4.3 1997/10/29 00:40:43 thorpej Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1996 Christos Zoulas.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Christos Zoulas.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * ISA PnP bus autoconfiguration.
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/device.h>
   40 #include <sys/malloc.h>
   41 
   42 #include <machine/bus.h>
   43 
   44 #include <dev/isa/isapnpreg.h>
   45 
   46 #include <dev/isa/isavar.h>
   47 #include <dev/isa/isadmavar.h>
   48 
   49 #include <dev/isa/pnpdevs.h>
   50 
   51 #include "isadma.h"
   52 
   53 void isapnp_init(struct isapnp_softc *);
   54 static __inline u_char isapnp_shift_bit(struct isapnp_softc *);
   55 int isapnp_findcard(struct isapnp_softc *);
   56 void isapnp_free_region(bus_space_tag_t, struct isapnp_region *);
   57 int isapnp_alloc_region(bus_space_tag_t, struct isapnp_region *);
   58 int isapnp_alloc_irq(isa_chipset_tag_t, struct isapnp_pin *);
   59 int isapnp_alloc_drq(struct device *, struct isapnp_pin *);
   60 int isapnp_testconfig(bus_space_tag_t, bus_space_tag_t,
   61     struct isa_attach_args *, int);
   62 struct isa_attach_args *isapnp_bestconfig(struct device *,
   63     struct isapnp_softc *, struct isa_attach_args **);
   64 void isapnp_print_region(const char *, struct isapnp_region *,
   65     size_t);
   66 void isapnp_configure(struct isapnp_softc *,
   67     const struct isa_attach_args *);
   68 void isapnp_print_pin(const char *, struct isapnp_pin *, size_t);
   69 int isapnp_print(void *, const char *);
   70 int isapnp_submatch(struct device *, void *, void *);
   71 int isapnp_com_submatch(struct device *, void *, void *);
   72 int isapnp_find(struct isapnp_softc *, int);
   73 int isapnp_match(struct device *, void *, void *);
   74 void isapnp_attach(struct device *, struct device *, void *);
   75 
   76 #ifdef DEBUG_ISAPNP
   77 # define DPRINTF(a) printf a
   78 #else
   79 # define DPRINTF(a)
   80 #endif
   81 
   82 struct cfattach isapnp_ca = {
   83         sizeof(struct isapnp_softc), isapnp_match, isapnp_attach
   84 };
   85 
   86 struct cfdriver isapnp_cd = {
   87         NULL, "isapnp", DV_DULL
   88 };
   89 
   90 
   91 /* isapnp_init():
   92  *      Write the PNP initiation key to wake up the cards...
   93  */
   94 void
   95 isapnp_init(sc)
   96         struct isapnp_softc *sc;
   97 {
   98         int i;
   99         u_char v = ISAPNP_LFSR_INIT;
  100 
  101         /* First write 0's twice to enter the Wait for Key state */
  102         ISAPNP_WRITE_ADDR(sc, 0);
  103         ISAPNP_WRITE_ADDR(sc, 0);
  104 
  105         /* Send the 32 byte sequence to awake the logic */
  106         for (i = 0; i < ISAPNP_LFSR_LENGTH; i++) {
  107                 ISAPNP_WRITE_ADDR(sc, v);
  108                 v = ISAPNP_LFSR_NEXT(v);
  109         }
  110 }
  111 
  112 
  113 /* isapnp_shift_bit():
  114  *      Read a bit at a time from the config card.
  115  */
  116 static __inline u_char
  117 isapnp_shift_bit(sc)
  118         struct isapnp_softc *sc;
  119 {
  120         u_char c1, c2;
  121 
  122         DELAY(250);
  123         c1 = ISAPNP_READ_DATA(sc);
  124         DELAY(250);
  125         c2 = ISAPNP_READ_DATA(sc);
  126 
  127         if (c1 == 0x55 && c2 == 0xAA)
  128                 return 0x80;
  129         else
  130                 return 0;
  131 }
  132 
  133 
  134 /* isapnp_findcard():
  135  *      Attempt to read the vendor/serial/checksum for a card
  136  *      If a card is found [the checksum matches], assign the
  137  *      next card number to it and return 1
  138  */
  139 int
  140 isapnp_findcard(sc)
  141         struct isapnp_softc *sc;
  142 {
  143         u_char v = ISAPNP_LFSR_INIT, csum, w;
  144         int i, b;
  145 
  146         if (sc->sc_ncards == ISAPNP_MAX_CARDS) {
  147                 printf("%s: Too many pnp cards\n", sc->sc_dev.dv_xname);
  148                 return 0;
  149         }
  150 
  151         /* Set the read port */
  152         isapnp_write_reg(sc, ISAPNP_WAKE, 0);
  153         isapnp_write_reg(sc, ISAPNP_SET_RD_PORT, sc->sc_read_port >> 2);
  154         sc->sc_read_port |= 3;
  155         DELAY(1000);
  156 
  157         ISAPNP_WRITE_ADDR(sc, ISAPNP_SERIAL_ISOLATION);
  158         DELAY(1000);
  159 
  160         /* Read the 8 bytes of the Vendor ID and Serial Number */
  161         for(i = 0; i < 8; i++) {
  162                 /* Read each bit separately */
  163                 for (w = 0, b = 0; b < 8; b++) {
  164                         u_char neg = isapnp_shift_bit(sc);
  165 
  166                         w >>= 1;
  167                         w |= neg;
  168                         v = ISAPNP_LFSR_NEXT(v) ^ neg;
  169                 }
  170                 sc->sc_id[sc->sc_ncards][i] = w;
  171         }
  172 
  173         /* Read the remaining checksum byte */
  174         for (csum = 0, b = 0; b < 8; b++) {
  175                 u_char neg = isapnp_shift_bit(sc);
  176 
  177                 csum >>= 1;
  178                 csum |= neg;
  179         }
  180         sc->sc_id[sc->sc_ncards][8] = csum;
  181 
  182         if (csum == v) {
  183                 sc->sc_ncards++;
  184                 isapnp_write_reg(sc, ISAPNP_CARD_SELECT_NUM, sc->sc_ncards);
  185                 return 1;
  186         }
  187         return 0;
  188 }
  189 
  190 
  191 /* isapnp_free_region():
  192  *      Free a region
  193  */
  194 void
  195 isapnp_free_region(t, r)
  196         bus_space_tag_t t;
  197         struct isapnp_region *r;
  198 {
  199         if (r->length == 0)
  200                 return;
  201 
  202         bus_space_unmap(t, r->h, r->length);
  203         r->h = NULL;
  204 }
  205 
  206 
  207 /* isapnp_alloc_region():
  208  *      Allocate a single region if possible
  209  */
  210 int
  211 isapnp_alloc_region(t, r)
  212         bus_space_tag_t t;
  213         struct isapnp_region *r;
  214 {
  215         int error = 0;
  216 
  217         if (r->length == 0)
  218                 return 0;
  219 
  220         r->h = NULL;
  221         for (r->base = r->minbase; r->base <= r->maxbase;
  222              r->base += r->align) {
  223                 error = bus_space_map(t, r->base, r->length, 0, &r->h);
  224                 if (error == 0)
  225                         return 0;
  226         }
  227         return error;
  228 }
  229 
  230 
  231 /* isapnp_alloc_irq():
  232  *      Allocate an irq
  233  */
  234 int
  235 isapnp_alloc_irq(ic, i)
  236         isa_chipset_tag_t ic;
  237         struct isapnp_pin *i;
  238 {
  239         int irq;
  240 #define LEVEL_IRQ (ISAPNP_IRQTYPE_LEVEL_PLUS|ISAPNP_IRQTYPE_LEVEL_MINUS)
  241         i->type = (i->flags & LEVEL_IRQ) ? IST_LEVEL : IST_EDGE;
  242 
  243         if (i->bits == 0) {
  244                 i->num = 0;
  245                 return 0;
  246         }
  247 
  248         if (isa_intr_alloc(ic, i->bits, i->type, &irq) == 0) {
  249                 i->num = irq;
  250                 return 0;
  251         }
  252 
  253         return EINVAL;
  254 }
  255 
  256 /* isapnp_alloc_drq():
  257  *      Allocate a drq
  258  */
  259 int
  260 isapnp_alloc_drq(isa, i)
  261         struct device *isa;
  262         struct isapnp_pin *i;
  263 {
  264 #if NISADMA > 0
  265         int b;
  266 
  267         if (i->bits == 0) {
  268                 i->num = 0;
  269                 return 0;
  270         }
  271 
  272         for (b = 0; b < 16; b++)
  273                 if ((i->bits & (1 << b)) && isa_drq_isfree(isa, b)) {
  274                         i->num = b;
  275                         return 0;
  276                 }
  277 #endif
  278 
  279         return EINVAL;
  280 }
  281 
  282 /* isapnp_testconfig():
  283  *      Test/Allocate the regions used
  284  */
  285 int
  286 isapnp_testconfig(iot, memt, ipa, alloc)
  287         bus_space_tag_t iot, memt;
  288         struct isa_attach_args *ipa;
  289         int alloc;
  290 {
  291         int nio = 0, nmem = 0, nmem32 = 0, nirq = 0, ndrq = 0;
  292         int error = 0;
  293 
  294 #ifdef DEBUG_ISAPNP
  295         isapnp_print_attach(ipa);
  296 #endif
  297 
  298         for (; nio < ipa->ipa_nio; nio++) {
  299                 error = isapnp_alloc_region(iot, &ipa->ipa_io[nio]);
  300                 if (error)
  301                         goto bad;
  302         }
  303 
  304         for (; nmem < ipa->ipa_nmem; nmem++) {
  305                 error = isapnp_alloc_region(memt, &ipa->ipa_mem[nmem]);
  306                 if (error)
  307                         goto bad;
  308         }
  309 
  310         for (; nmem32 < ipa->ipa_nmem32; nmem32++) {
  311                 error = isapnp_alloc_region(memt, &ipa->ipa_mem32[nmem32]);
  312                 if (error)
  313                         goto bad;
  314         }
  315 
  316         for (; nirq < ipa->ipa_nirq; nirq++) {
  317                 error = isapnp_alloc_irq(ipa->ia_ic, &ipa->ipa_irq[nirq]);
  318                 if (error)
  319                         goto bad;
  320         }
  321 
  322         for (; ndrq < ipa->ipa_ndrq; ndrq++) {
  323                 error = isapnp_alloc_drq(ipa->ia_isa, &ipa->ipa_drq[ndrq]);
  324                 if (error)
  325                         goto bad;
  326         }
  327 
  328         if (alloc)
  329                 return error;
  330 
  331 bad:
  332 #ifdef notyet
  333         for (ndrq--; ndrq >= 0; ndrq--)
  334                 isapnp_free_pin(&ipa->ipa_drq[ndrq]);
  335 
  336         for (nirq--; nirq >= 0; nirq--)
  337                 isapnp_free_pin(&ipa->ipa_irq[nirq]);
  338 #endif
  339 
  340         for (nmem32--; nmem32 >= 0; nmem32--)
  341                 isapnp_free_region(memt, &ipa->ipa_mem32[nmem32]);
  342 
  343         for (nmem--; nmem >= 0; nmem--)
  344                 isapnp_free_region(memt, &ipa->ipa_mem[nmem]);
  345 
  346         for (nio--; nio >= 0; nio--)
  347                 isapnp_free_region(iot, &ipa->ipa_io[nio]);
  348 
  349         return error;
  350 }
  351 
  352 
  353 /* isapnp_config():
  354  *      Test/Allocate the regions used
  355  */
  356 int
  357 isapnp_config(iot, memt, ipa)
  358         bus_space_tag_t iot, memt;
  359         struct isa_attach_args *ipa;
  360 {
  361         return isapnp_testconfig(iot, memt, ipa, 1);
  362 }
  363 
  364 
  365 /* isapnp_unconfig():
  366  *      Free the regions used
  367  */
  368 void
  369 isapnp_unconfig(iot, memt, ipa)
  370         bus_space_tag_t iot, memt;
  371         struct isa_attach_args *ipa;
  372 {
  373         int i;
  374 
  375 #ifdef notyet
  376         for (i = 0; i < ipa->ipa_ndrq; i++)
  377                 isapnp_free_pin(&ipa->ipa_drq[i]);
  378 
  379         for (i = 0; i < ipa->ipa_nirq; i++)
  380                 isapnp_free_pin(&ipa->ipa_irq[i]);
  381 #endif
  382 
  383         for (i = 0; i < ipa->ipa_nmem32; i++)
  384                 isapnp_free_region(memt, &ipa->ipa_mem32[i]);
  385 
  386         for (i = 0; i < ipa->ipa_nmem; i++)
  387                 isapnp_free_region(memt, &ipa->ipa_mem[i]);
  388 
  389         for (i = 0; i < ipa->ipa_nio; i++)
  390                 isapnp_free_region(iot, &ipa->ipa_io[i]);
  391 }
  392 
  393 
  394 /* isapnp_bestconfig():
  395  *      Return the best configuration for each logical device, remove and
  396  *      free all other configurations.
  397  */
  398 struct isa_attach_args *
  399 isapnp_bestconfig(isa, sc, ipa)
  400         struct device *isa;
  401         struct isapnp_softc *sc;
  402         struct isa_attach_args **ipa;
  403 {
  404         struct isa_attach_args *c, *best, *f = *ipa;
  405         int error;
  406 
  407         for (;;) {
  408                 if (f == NULL)
  409                         return NULL;
  410 
  411 #define SAMEDEV(a, b) (strcmp((a)->ipa_devlogic, (b)->ipa_devlogic) == 0)
  412 
  413                 /* Find the best config */
  414                 for (best = c = f; c != NULL; c = c->ipa_sibling) {
  415                         if (!SAMEDEV(c, f))
  416                                 continue;
  417                         if (c->ipa_pref < best->ipa_pref)
  418                                 best = c;
  419                 }
  420 
  421                 best->ia_isa = isa;
  422                 /* Test the best config */
  423                 error = isapnp_testconfig(sc->sc_iot, sc->sc_memt, best, 0);
  424 
  425                 /* Remove this config from the list */
  426                 if (best == f)
  427                         f = f->ipa_sibling;
  428                 else {
  429                         for (c = f; c->ipa_sibling != best; c = c->ipa_sibling)
  430                                 continue;
  431                         c->ipa_sibling = best->ipa_sibling;
  432                 }
  433 
  434                 if (error) {
  435                         best->ipa_pref = ISAPNP_DEP_CONFLICTING;
  436 
  437                         for (c = f; c != NULL; c = c->ipa_sibling)
  438                                 if (c != best && SAMEDEV(c, best))
  439                                         break;
  440                         /* Last config for this logical device is conflicting */
  441                         if (c == NULL) {
  442                                 *ipa = f;
  443                                 return best;
  444                         }
  445 
  446                         ISAPNP_FREE(best);
  447                         continue;
  448                 }
  449                 else {
  450                         /* Remove all other configs for this device */
  451                         struct isa_attach_args *l = NULL, *n = NULL, *d;
  452 
  453                         for (c = f; c; ) {
  454                                 if (c == best)
  455                                         continue;
  456                                 d = c->ipa_sibling;
  457                                 if (SAMEDEV(c, best))
  458                                         ISAPNP_FREE(c);
  459                                 else {
  460                                         if (n)
  461                                                 n->ipa_sibling = c;
  462 
  463                                         else
  464                                                 l = c;
  465                                         n = c;
  466                                         c->ipa_sibling = NULL;
  467                                 }
  468                                 c = d;
  469                         }
  470                         f = l;
  471                 }
  472                 *ipa = f;
  473                 return best;
  474         }
  475 }
  476 
  477 
  478 /* isapnp_id_to_vendor():
  479  *      Convert a pnp ``compressed ascii'' vendor id to a string
  480  */
  481 char *
  482 isapnp_id_to_vendor(v, id)
  483         char   *v;
  484         const u_char *id;
  485 {
  486         static const char hex[] = "0123456789ABCDEF";
  487         char *p = v;
  488 
  489         *p++ = 'A' + (id[0] >> 2) - 1;
  490         *p++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1;
  491         *p++ = 'A' + (id[1] & 0x1f) - 1;
  492         *p++ = hex[id[2] >> 4];
  493         *p++ = hex[id[2] & 0x0f];
  494         *p++ = hex[id[3] >> 4];
  495         *p++ = hex[id[3] & 0x0f];
  496         *p = '\0';
  497 
  498         return v;
  499 }
  500 
  501 
  502 /* isapnp_print_region():
  503  *      Print a region allocation
  504  */
  505 void
  506 isapnp_print_region(str, r, n)
  507         const char *str;
  508         struct isapnp_region *r;
  509         size_t n;
  510 {
  511         size_t i;
  512 
  513         if (n == 0)
  514                 return;
  515 
  516         printf(" %s ", str);
  517         for (i = 0; i < n; i++, r++) {
  518                 printf("0x%x", r->base);
  519                 if (r->length)
  520                         printf("/%d", r->length);
  521                 if (i != n - 1)
  522                         printf(",");
  523         }
  524 }
  525 
  526 
  527 /* isapnp_print_pin():
  528  *      Print an irq/drq assignment
  529  */
  530 void
  531 isapnp_print_pin(str, p, n)
  532         const char *str;
  533         struct isapnp_pin *p;
  534         size_t n;
  535 {
  536         size_t i;
  537 
  538         if (n == 0)
  539                 return;
  540 
  541         printf(" %s ", str);
  542         for (i = 0; i < n; i++, p++) {
  543                 printf("%d", p->num);
  544                 if (i != n - 1)
  545                         printf(",");
  546         }
  547 }
  548 
  549 /* isapnp_print():
  550  *      Print the configuration line for an ISA PnP card.
  551  */
  552 int
  553 isapnp_print(aux, str)
  554         void *aux;
  555         const char *str;
  556 {
  557         struct isa_attach_args *ipa = aux;
  558 
  559         if (!str)
  560                 printf(" ");
  561         printf("\"%s, %s, %s, %s\"", ipa->ipa_devident,
  562             ipa->ipa_devlogic, ipa->ipa_devcompat, ipa->ipa_devclass);
  563 
  564         if (str)
  565                 printf(" at %s", str);
  566 
  567         isapnp_print_region("port", ipa->ipa_io, ipa->ipa_nio);
  568         isapnp_print_region("mem", ipa->ipa_mem, ipa->ipa_nmem);
  569         isapnp_print_region("mem32", ipa->ipa_mem32, ipa->ipa_nmem32);
  570         isapnp_print_pin("irq", ipa->ipa_irq, ipa->ipa_nirq);
  571         isapnp_print_pin("drq", ipa->ipa_drq, ipa->ipa_ndrq);
  572         return UNCONF;
  573 }
  574 
  575 
  576 /* isapnp_submatch():
  577  * Special case.
  578  * A lot of com/pccom devices do not have the PNPxxx identifiers
  579  * they should have.  If it looks like a modem..... let's try it.
  580  */
  581 int
  582 isapnp_com_submatch(parent, match, aux)
  583         struct device *parent;
  584         void *match, *aux;
  585 {
  586         struct cfdata *cf = match;
  587         struct isa_attach_args *ipa = aux;
  588 
  589         if ((strcmp("com", cf->cf_driver->cd_name) == 0 ||
  590             strcmp("pccom", cf->cf_driver->cd_name) == 0) &&
  591             ipa->ipa_nio == 1 && ipa->ipa_nirq == 1 &&
  592             ipa->ipa_ndrq == 0 && ipa->ipa_nmem == 0 &&
  593             ipa->ipa_io[0].length == 8) {
  594                 if (isapnp_config(ipa->ia_iot, ipa->ia_memt, ipa)) {
  595                         printf("%s: error in region allocation\n",
  596                             cf->cf_driver->cd_name);
  597                         return (0);
  598                 }
  599                 return ((*cf->cf_attach->ca_match)(parent, match, ipa));
  600         }
  601         return (0);
  602 }
  603 
  604 /* isapnp_submatch():
  605  *      Probe the logical device...
  606  */
  607 int
  608 isapnp_submatch(parent, match, aux)
  609         struct device *parent;
  610         void *match, *aux;
  611 {
  612         struct cfdata *cf = match;
  613         struct isa_attach_args *ipa = aux;
  614         const char *dname;
  615         int i;
  616 
  617         for (i = 0; i < sizeof(isapnp_knowndevs)/sizeof(isapnp_knowndevs[0]); i++) {
  618                 dname = NULL;
  619 
  620                 if (strcmp(isapnp_knowndevs[i].pnpid, ipa->ipa_devlogic) == 0)
  621                         dname = isapnp_knowndevs[i].driver;
  622                 else if (strcmp(isapnp_knowndevs[i].pnpid, ipa->ipa_devcompat) == 0)
  623                         dname = isapnp_knowndevs[i].driver;
  624 
  625                 if (dname && strcmp(dname, cf->cf_driver->cd_name) == 0) {
  626                         /*
  627                          * We found a match.  Configure the card and call the
  628                          * ISA probe...
  629                          */
  630                         if (isapnp_config(ipa->ia_iot, ipa->ia_memt, ipa)) {
  631                                 printf("%s: error in region allocation\n",
  632                                     cf->cf_driver->cd_name);
  633                                 return (0);
  634                         }
  635 
  636                         return ((*cf->cf_attach->ca_match)(parent, match, ipa));
  637                 }
  638         }
  639 
  640         return (0);
  641 }
  642 
  643 /* isapnp_find():
  644  *      Probe and add cards
  645  */
  646 int
  647 isapnp_find(sc, all)
  648         struct isapnp_softc *sc;
  649         int all;
  650 {
  651         int p;
  652 
  653         isapnp_init(sc);
  654 
  655         isapnp_write_reg(sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV);
  656         DELAY(2000);
  657 
  658         isapnp_init(sc);
  659         DELAY(2000);
  660 
  661         for (p = ISAPNP_RDDATA_MIN; p <= ISAPNP_RDDATA_MAX; p += 4) {
  662                 sc->sc_read_port = p;
  663                 if (isapnp_map_readport(sc))
  664                         continue;
  665                 DPRINTF(("%s: Trying port %x\n", sc->sc_dev.dv_xname, p));
  666                 if (isapnp_findcard(sc))
  667                         break;
  668                 isapnp_unmap_readport(sc);
  669         }
  670 
  671         if (p > ISAPNP_RDDATA_MAX) {
  672                 sc->sc_read_port = 0;
  673                 return 0;
  674         }
  675 
  676         if (all)
  677                 while (isapnp_findcard(sc))
  678                         continue;
  679 
  680         return 1;
  681 }
  682 
  683 
  684 /* isapnp_configure():
  685  *      Configure a PnP card
  686  *      XXX: The memory configuration code is wrong. We need to check the
  687  *           range/length bit an do appropriate sets.
  688  */
  689 void
  690 isapnp_configure(sc, ipa)
  691         struct isapnp_softc *sc;
  692         const struct isa_attach_args *ipa;
  693 {
  694         int i;
  695         static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC;
  696         static u_char isapnp_io_range[] = ISAPNP_IO_DESC;
  697         static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC;
  698         static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC;
  699         static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC;
  700         const struct isapnp_region *r;
  701         const struct isapnp_pin *p;
  702         struct isapnp_region rz;
  703         struct isapnp_pin pz;
  704 
  705         bzero(&pz, sizeof(pz));
  706         bzero(&rz, sizeof(rz));
  707 
  708 #define B0(a) ((a) & 0xff)
  709 #define B1(a) (((a) >> 8) & 0xff)
  710 #define B2(a) (((a) >> 16) & 0xff)
  711 #define B3(a) (((a) >> 24) & 0xff)
  712 
  713         for (i = 0; i < sizeof(isapnp_io_range); i++) {
  714                 if (i < ipa->ipa_nio)
  715                         r = &ipa->ipa_io[i];
  716                 else
  717                         r = &rz;
  718 
  719                 isapnp_write_reg(sc,
  720                     isapnp_io_range[i] + ISAPNP_IO_BASE_15_8, B1(r->base));
  721                 isapnp_write_reg(sc,
  722                     isapnp_io_range[i] + ISAPNP_IO_BASE_7_0, B0(r->base));
  723         }
  724 
  725         for (i = 0; i < sizeof(isapnp_mem_range); i++) {
  726                 if (i < ipa->ipa_nmem)
  727                         r = &ipa->ipa_mem[i];
  728                 else
  729                         r = &rz;
  730 
  731                 isapnp_write_reg(sc,
  732                     isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16, B2(r->base));
  733                 isapnp_write_reg(sc,
  734                     isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8, B1(r->base));
  735 
  736                 isapnp_write_reg(sc,
  737                     isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16,
  738                     B2(r->length));
  739                 isapnp_write_reg(sc,
  740                     isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8,
  741                     B1(r->length));
  742         }
  743 
  744         for (i = 0; i < sizeof(isapnp_irq_range); i++) {
  745                 u_char v;
  746 
  747                 if (i < ipa->ipa_nirq)
  748                         p = &ipa->ipa_irq[i];
  749                 else
  750                         p = &pz;
  751 
  752                 isapnp_write_reg(sc,
  753                     isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER, p->num);
  754 
  755                 switch (p->flags) {
  756                 case ISAPNP_IRQTYPE_LEVEL_PLUS:
  757                         v = ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH;
  758                         break;
  759 
  760                 case ISAPNP_IRQTYPE_EDGE_PLUS:
  761                         v = ISAPNP_IRQ_HIGH;
  762                         break;
  763 
  764                 case ISAPNP_IRQTYPE_LEVEL_MINUS:
  765                         v = ISAPNP_IRQ_LEVEL;
  766                         break;
  767 
  768                 default:
  769                 case ISAPNP_IRQTYPE_EDGE_MINUS:
  770                         v = 0;
  771                         break;
  772                 }
  773                 isapnp_write_reg(sc,
  774                     isapnp_irq_range[i] + ISAPNP_IRQ_CONTROL, v);
  775         }
  776 
  777         for (i = 0; i < sizeof(isapnp_drq_range); i++) {
  778                 u_char v;
  779 
  780                 if (i < ipa->ipa_ndrq)
  781                         v = ipa->ipa_drq[i].num;
  782                 else
  783                         v = 4;
  784 
  785                 isapnp_write_reg(sc, isapnp_drq_range[i], v);
  786         }
  787 
  788         for (i = 0; i < sizeof(isapnp_mem32_range); i++) {
  789                 if (i < ipa->ipa_nmem32)
  790                         r = &ipa->ipa_mem32[i];
  791                 else
  792                         r = &rz;
  793 
  794                 isapnp_write_reg(sc,
  795                     isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24,
  796                     B3(r->base));
  797                 isapnp_write_reg(sc,
  798                     isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16,
  799                     B2(r->base));
  800                 isapnp_write_reg(sc,
  801                     isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8,
  802                     B1(r->base));
  803                 isapnp_write_reg(sc,
  804                     isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0,
  805                     B0(r->base));
  806 
  807                 isapnp_write_reg(sc,
  808                     isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24,
  809                     B3(r->length));
  810                 isapnp_write_reg(sc,
  811                     isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16,
  812                     B2(r->length));
  813                 isapnp_write_reg(sc,
  814                     isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8,
  815                     B1(r->length));
  816                 isapnp_write_reg(sc,
  817                     isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0,
  818                     B0(r->length));
  819         }
  820 }
  821 
  822 
  823 /*
  824  * Some BIOSes take the liberty of configuring our ISA cards for us.
  825  * This code undoes the PNP card configuration.
  826  */
  827 
  828 void
  829 isapnp_isa_attach_hook(isa_sc)
  830         struct isa_softc *isa_sc;
  831 
  832 {
  833         struct isapnp_softc sc;
  834 
  835         bzero(&sc, sizeof sc);
  836         sc.sc_iot = isa_sc->sc_iot;
  837         sc.sc_ncards = 0;
  838 
  839         if (isapnp_map(&sc))
  840                 return;
  841 
  842         isapnp_init(&sc);
  843 
  844         isapnp_write_reg(&sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV);
  845         DELAY(2000);
  846 
  847         isapnp_unmap(&sc);
  848 }
  849 
  850 /* isapnp_match():
  851  *      Probe routine
  852  */
  853 int
  854 isapnp_match(parent, match, aux)
  855         struct device *parent;
  856         void *match;
  857         void *aux;
  858 {
  859         int rv;
  860         struct isapnp_softc sc;
  861         struct isa_attach_args *ia = aux;
  862 
  863         sc.sc_iot = ia->ia_iot;
  864         sc.sc_ncards = 0;
  865         (void) strlcpy(sc.sc_dev.dv_xname, "(isapnp probe)",
  866              sizeof sc.sc_dev.dv_xname);
  867 
  868         if (isapnp_map(&sc))
  869                 return 0;
  870 
  871         rv = isapnp_find(&sc, 0);
  872         ia->ia_iobase = ISAPNP_ADDR;
  873         ia->ia_iosize = 1;
  874 
  875         isapnp_unmap(&sc);
  876         if (rv)
  877                 isapnp_unmap_readport(&sc);
  878 
  879         return (rv);
  880 }
  881 
  882 
  883 /* isapnp_attach
  884  *      Find and attach PnP cards.
  885  */
  886 void
  887 isapnp_attach(parent, self, aux)
  888         struct device *parent, *self;
  889         void *aux;
  890 {
  891         struct isapnp_softc *sc = (struct isapnp_softc *) self;
  892         struct isa_attach_args *ia = aux;
  893         void *match;
  894         int c, d;
  895 
  896         sc->sc_iot = ia->ia_iot;
  897         sc->sc_memt = ia->ia_memt;
  898 #if NISADMA > 0
  899         sc->sc_dmat = ia->ia_dmat;
  900 #endif
  901         sc->sc_ncards = 0;
  902 
  903         if (isapnp_map(sc))
  904                 panic("%s: bus map failed", sc->sc_dev.dv_xname);
  905 
  906         if (!isapnp_find(sc, 1)) {
  907                 printf(": no cards found\n");
  908                 return;
  909         }
  910 
  911         printf(": read port 0x%x\n", sc->sc_read_port);
  912 
  913         for (c = 0; c < sc->sc_ncards; c++) {
  914                 struct isa_attach_args *ipa, *lpa;
  915 
  916                 /* Good morning card c */
  917                 isapnp_write_reg(sc, ISAPNP_WAKE, c + 1);
  918 
  919                 if ((ipa = isapnp_get_resource(sc, c, ia)) == NULL)
  920                         continue;
  921 
  922                 DPRINTF(("Selecting attachments\n"));
  923                 for (d = 0;
  924                     (lpa = isapnp_bestconfig(parent, sc, &ipa)) != NULL; d++) {
  925                         isapnp_write_reg(sc, ISAPNP_LOGICAL_DEV_NUM, d);
  926                         isapnp_configure(sc, lpa);
  927 #ifdef DEBUG_ISAPNP
  928                         {
  929                                 struct isa_attach_args pa;
  930 
  931                                 isapnp_get_config(sc, &pa);
  932                                 isapnp_print_config(&pa);
  933                         }
  934 #endif
  935 
  936                         DPRINTF(("%s: configuring <%s, %s, %s, %s>\n",
  937                             sc->sc_dev.dv_xname,
  938                             lpa->ipa_devident, lpa->ipa_devlogic,
  939                             lpa->ipa_devcompat, lpa->ipa_devclass));
  940                         if (lpa->ipa_pref == ISAPNP_DEP_CONFLICTING) {
  941                                 isapnp_print(lpa, self->dv_xname);
  942                                 printf(" resource conflict\n");
  943                                 ISAPNP_FREE(lpa);
  944                                 continue;
  945                         }
  946 
  947                         lpa->ia_ic = ia->ia_ic;
  948                         lpa->ia_iot = ia->ia_iot;
  949                         lpa->ia_memt = ia->ia_memt;
  950 #if NISADMA > 0
  951                         lpa->ia_dmat = ia->ia_dmat;
  952 #endif
  953                         lpa->ia_delaybah = ia->ia_delaybah;
  954 
  955                         isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1);
  956 
  957                         if ((match = config_search(isapnp_submatch,
  958                             self, lpa)))
  959                                 config_attach(self, match, lpa, isapnp_print);
  960                         else if ((match = config_search(isapnp_com_submatch,
  961                             self, lpa)))
  962                                 config_attach(self, match, lpa, isapnp_print);
  963                         else {
  964                                 isapnp_print(lpa, self->dv_xname);
  965                                 printf(" not configured\n");
  966                                 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 0);
  967                         }
  968                         ISAPNP_FREE(lpa);
  969                 }
  970                 isapnp_write_reg(sc, ISAPNP_WAKE, 0);    /* Good night cards */
  971         }
  972 }

/* [<][>][^][v][top][bottom][index][help] */