Initial import from FreeBSD RELENG_4:
[games.git] / usr.sbin / pccard / pccardd / cardd.c
1 /*
2  * Copyright (c) 1995 Andrew McRae.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #ifndef lint
28 static const char rcsid[] =
29   "$FreeBSD: src/usr.sbin/pccard/pccardd/cardd.c,v 1.46.2.16 2001/12/10 14:38:19 iwasaki Exp $";
30 #endif /* not lint */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40 #include <regex.h>
41 #include <machine/resource.h>
42 #include <sys/ioctl.h>
43 #include "cardd.h"
44
45 static struct card_config *assign_driver(struct slot *, struct card *);
46 static int               assign_io(struct slot *);
47 static int               setup_slot(struct slot *);
48 static void              card_inserted(struct slot *);
49 static void              card_removed(struct slot *);
50 static void              pr_cmd(struct cmd *);
51 static void              read_ether(struct slot *);
52 static void              read_ether_attr2(struct slot *sp);
53
54 struct slot *slots;
55
56 /*
57  *      Dump configuration file data.
58  */
59 void
60 dump_config_file(void)
61 {
62         struct card *cp;
63         struct card_config *confp;
64
65         for (cp = cards; cp; cp = cp->next) {
66                 printf("Card manuf %s, vers %s\n", cp->manuf, cp->version);
67                 printf("Configuration entries:\n");
68                 for (confp = cp->config; confp; confp = confp->next) {
69                         printf("\tIndex code = ");
70                         switch (confp->index_type) {
71                         case DEFAULT_INDEX:
72                                 printf("default");
73                                 break;
74                         case AUTO_INDEX:
75                                 printf("auto");
76                                 break;
77                         default:
78                                 printf("0x%x", confp->index);
79                                 break;
80                         }
81                         printf(", driver name = %s\n", confp->driver->name);
82                 }
83                 if (cp->insert) {
84                         printf("Insert commands are:\n");
85                         pr_cmd(cp->insert);
86                 }
87                 if (cp->remove) {
88                         printf("Remove commands are:\n");
89                         pr_cmd(cp->remove);
90                 }
91         }
92         fflush(stdout);
93 }
94
95 static void
96 pr_cmd(struct cmd *cp)
97 {
98         while (cp) {
99                 printf("\t%s\n", cp->line);
100                 cp = cp->next;
101         }
102 }
103
104 /*
105  *      readslots - read all the PCMCIA slots, and build
106  *      a list of the slots.
107  */
108 struct slot *
109 readslots(void)
110 {
111         char    name[128];
112         int     i, fd;
113         struct slot *sp;
114
115         slots = NULL;
116         for (i = 0; i < MAXSLOT; i++) {
117                 sprintf(name, CARD_DEVICE, i);
118                 fd = open(name, O_RDWR);
119                 if (fd < 0)
120                         continue;
121                 sp = xmalloc(sizeof(*sp));
122                 sp->fd = fd;
123                 sp->name = newstr(name);
124                 sp->slot = i;
125
126                 /* Check to see if the controller memory has been set up. */
127                 if (slots == 0) {
128                         unsigned long mem = 0;
129
130                         if (ioctl(fd, PIOCRWMEM, &mem))
131                                 logerr("ioctl (PIOCRWMEM)");
132 #ifdef DEBUG
133                         logmsg("mem=0x%x\n", mem);
134 #endif
135                         if (mem == 0) {
136                                 mem = alloc_memory(4 * 1024);
137                                 if (mem == 0)
138                                         die("can't allocate memory for "
139                                             "controller access");
140                                 if (ioctl(fd, PIOCRWMEM, &mem))
141                                         logerr("ioctl (PIOCRWMEM)");
142                         }
143                 }
144                 sp->next = slots;
145                 slots = sp;
146                 slot_change(sp);
147         }
148         return (slots);
149 }
150
151 /*
152  *      slot_change - Card status has changed.
153  *      read new state and process.
154  */
155 void
156 slot_change(struct slot *sp)
157 {
158         struct slotstate state;
159
160         if (ioctl(sp->fd, PIOCGSTATE, &state)) {
161                 logerr("ioctl (PIOCGSTATE)");
162                 return;
163         }
164         switch (state.state) {
165         case empty:
166         case inactive:
167         case noslot:
168                 /* Debounce potentially incorrectly reported removals */
169                 if (state.laststate == filled || state.laststate == suspend)
170                         card_removed(sp);
171                 break;
172         case filled:
173                 /* KLUDGE: if we were suspended, remove card */
174                 if (state.laststate == suspend)
175                         card_removed(sp);
176                 card_inserted(sp);
177                 break;
178         case suspend:
179                 /* ignored */
180                 break;
181         }
182         sp->state = state.state;
183         stat_changed(sp);
184 }
185
186 /*
187  *      card_removed - card has been removed from slot.
188  *      Execute the remove commands, and clear the slot's state.
189  *      Execute the device commands, then the driver commands
190  *      and then the card commands. This is the reverse
191  *      order to the insertion commands
192  */
193 void
194 card_removed(struct slot *sp)
195 {
196         struct card *cp;
197         struct allocblk *sio;
198         int in_use = 0;
199
200         if (sp->config && sp->config->driver && sp->card)
201                 logmsg("%s%d: %s removed.", sp->config->driver->kernel,
202                     sp->config->driver->unit, sp->card->logstr);
203         if (sp->cis)
204                 freecis(sp->cis);
205         if (sp->config) {
206                 if (sp->config->inuse && sp->config->driver->inuse)
207                         in_use = 1;
208                 sp->config->inuse = 0;
209                 sp->config->driver->inuse = 0;
210         }
211         if ((cp = sp->card) != 0 && in_use)
212                 execute(cp->remove, sp);
213         sp->cis = 0;
214         sp->config = 0;
215         /* release io */
216         if (sp->flags & IO_ASSIGNED) 
217             for (sio = &sp->io; sio; sio = sio->next)
218                 if (sio->addr && sio->size)
219                         bit_nset(io_avail, sio->addr, sio->addr + sio->size - 1);
220         /* release irq */
221         if (sp->flags & IRQ_ASSIGNED)
222                 if (sp->irq >= 1 && sp->irq <= 15)
223                         pool_irq[sp->irq] = 1;
224 }
225
226 /* CIS string comparison */
227
228 #define REGCOMP_FLAGS   (REG_EXTENDED | REG_NOSUB)
229 #define REGEXEC_FLAGS   (0)
230
231 static int
232 cis_strcmp(char *db, char *cis)
233 {
234         int     res, err;
235         char    buf[256];
236         regex_t rx;
237         char *  p;
238         size_t  n;
239
240         if (!db || !cis) {
241                 return -1;
242         }
243         n = strlen(db);
244         if (n > 2 && db[0] == '/' && db[n-1] == '/') {
245                 /* matching by regex */
246                 db++;
247         } else {
248                 /* otherwise, matching by strncmp() */
249                 if (n != strlen(cis)) {
250                         return -1;
251                 }
252
253                 return strncmp(db, cis, n);
254         }
255         p = xmalloc(n);
256         strncpy(p + 1, db, n-2);
257         *p = '^';
258         db = p;
259         if ((err = regcomp(&rx, p, REGCOMP_FLAGS))) {
260                 regerror(err, &rx, buf, sizeof buf);
261                 logmsg("Warning: REGEX error for\"%s\" -- %s\n", p, buf);
262                 regfree(&rx);
263                 free(p);
264                 return -1;
265         }
266         res = regexec(&rx, cis, 0, NULL, REGEXEC_FLAGS);
267         regfree(&rx);
268         free(p);
269         return res;
270 }
271
272 /*
273  * card_inserted - Card has been inserted;
274  *      - Read the CIS
275  *      - match the card type.
276  *      - Match the driver and allocate a driver instance.
277  *      - Allocate I/O ports, memory and IRQ.
278  *      - Set up the slot.
279  *      - assign the driver (if failed, then terminate).
280  *      - Run the card commands.
281  *      - Run the driver commands
282  *      - Run the device commands
283  */
284 void
285 card_inserted(struct slot *sp)
286 {
287         struct card *cp;
288         int err;
289
290         usleep(pccard_init_sleep);
291         sp->cis = readcis(sp->fd);
292         if (sp->cis == 0) {
293                 logmsg("Error reading CIS on %s\n", sp->name);
294                 return;
295         }
296 #if 0
297         dumpcis(sp->cis);
298 #endif
299         for (cp = cards; cp; cp = cp->next) {
300                 switch (cp->deftype) {
301                 case DT_VERS:
302                         if (cis_strcmp(cp->manuf, sp->cis->manuf) == 0 &&
303                             cis_strcmp(cp->version, sp->cis->vers) == 0) {
304                                 if (cp->add_info1 != NULL &&
305                                     cis_strcmp(cp->add_info1, sp->cis->add_info1) != 0) {
306                                         break;
307                                 }
308                                 if (cp->add_info2 != NULL &&
309                                     cis_strcmp(cp->add_info2, sp->cis->add_info2) != 0) {
310                                         break;
311                                 }
312
313                                 logmsg("Card \"%s\"(\"%s\") "
314                                         "[%s] [%s] "
315                                         "matched \"%s\" (\"%s\") "
316                                         "[%s] [%s] ",
317                                     sp->cis->manuf, sp->cis->vers,
318                                     sp->cis->add_info1, sp->cis->add_info2,
319                                     cp->manuf, cp->version,
320                                     cp->add_info1, cp->add_info2);
321                                 goto escape;
322                         }
323                         break;
324                 case DT_FUNC:
325                         if (cp->func_id == sp->cis->func_id1) {
326                                 logmsg("Card \"%s\"(\"%s\") "
327                                        "[%s] [%s] "
328                                        "has function ID %d\n",
329                                     sp->cis->manuf, sp->cis->vers,
330                                     sp->cis->add_info1, sp->cis->add_info2,
331                                     cp->func_id);
332                                 goto escape;
333                         }
334                         break;
335                 default:
336                         logmsg("Unknown deftype %d\n", cp->deftype);
337                         die("cardd.c:card_inserted()");
338                 }
339         }
340 escape:
341         sp->card = cp;
342 #if 0
343         reset_slot(sp);
344 #endif
345         if (cp == 0) {
346                 logmsg("No card in database for \"%s\"(\"%s\")",
347                         sp->cis->manuf, sp->cis->vers);
348                 return;
349         }
350         if (sp->cis->lan_nid && sp->cis->lan_nid[0] == sizeof(sp->eaddr)) {
351                 bcopy(sp->cis->lan_nid + 1, sp->eaddr, sizeof(sp->eaddr));
352                 sp->flags |= EADDR_CONFIGED;
353         } else {
354                 bzero(sp->eaddr, sizeof(sp->eaddr));
355         }
356
357         if (cp->ether) {
358                 struct ether *e = 0;
359                 e = cp->ether;
360                 switch (e->type) {
361                 case ETHTYPE_ATTR2:
362                         read_ether_attr2(sp);
363                         break;
364                 default:
365                         read_ether(sp);
366                         break;
367                 }
368         }
369         if ((sp->config = assign_driver(sp, cp)) == NULL) 
370                 return;
371         if ((err = assign_io(sp))) {
372                 char *reason;
373
374                 switch (err) {
375                 case -1:
376                         reason = "specified CIS was not found";
377                         break;
378                 case -2:
379                         reason = "memory block allocation failed";
380                         break;
381                 case -3:
382                         reason = "I/O block allocation failed";
383                         break;
384                 case -4:
385                         reason = "requires more than one memory window";
386                         break;
387                 default:
388                         reason = "Unknown";
389                         break;
390                 }
391                 logmsg("Resource allocation failure for \"%s\"(\"%s\") "
392                        "[%s] [%s]; Reason %s\n",
393                     sp->cis->manuf, sp->cis->vers,
394                     sp->cis->add_info1, sp->cis->add_info2, reason);
395                 return;
396         }
397
398         /*
399          *
400          * Once assigned, set up the I/O & mem contexts, set up the
401          * windows, and then attach the driver.
402          */
403         if (setup_slot(sp))
404                 execute(cp->insert, sp);
405 #if 0
406         else
407                 reset_slot(sp);
408 #endif
409 }
410
411 /*
412  *      read_ether - read ethernet address from card. Offset is
413  *      the offset into the attribute memory of the card.
414  */
415 static void
416 read_ether(struct slot *sp)
417 {
418         unsigned char net_addr[12];
419         int flags = MDF_ATTR;   /* attribute memory */
420
421         ioctl(sp->fd, PIOCRWFLAG, &flags);
422         lseek(sp->fd, (off_t)sp->card->ether->value, SEEK_SET);
423         if (read(sp->fd, net_addr, sizeof(net_addr)) != sizeof(net_addr)) {
424                 logerr("read err on net addr");
425                 return;
426         }
427         sp->eaddr[0] = net_addr[0];
428         sp->eaddr[1] = net_addr[2];
429         sp->eaddr[2] = net_addr[4];
430         sp->eaddr[3] = net_addr[6];
431         sp->eaddr[4] = net_addr[8];
432         sp->eaddr[5] = net_addr[10];
433         logmsg("Ether=%02x:%02x:%02x:%02x:%02x:%02x\n",
434             sp->eaddr[0], sp->eaddr[1], sp->eaddr[2],
435             sp->eaddr[3], sp->eaddr[4], sp->eaddr[5]);
436         sp->flags |= EADDR_CONFIGED;
437 }
438
439 /*
440  *      Megahertz X-Jack Ethernet uses unique way to get/set MAC
441  *      address of the card.
442  */
443 static void
444 read_ether_attr2(struct slot *sp)
445 {
446         int     i;
447         char    *hexaddr;
448
449         hexaddr = sp->cis->add_info2;
450         for (i = 0; i < 6; i++)
451                 sp->eaddr[i] = 0;
452         if (!hexaddr)
453                 return;
454         if (strlen(hexaddr) != 12)
455                 return;
456         for (i = 0; i < 12; i++)
457                 if (!isxdigit(hexaddr[i]))
458                         return;
459         for (i = 0; i < 6; i++) {
460                 u_int   d;
461                 char    s[3];
462                 s[0] = hexaddr[i * 2];
463                 s[1] = hexaddr[i * 2 + 1];
464                 s[2] = '\0';
465                 if (!sscanf(s, "%x", &d)) {
466                         int     j;
467                         for (j = 0; j < 6; j++)
468                                 sp->eaddr[j] = 0;
469                         return;
470                 }
471                 sp->eaddr[i] = (u_char)d;
472         }
473         sp->flags |= EADDR_CONFIGED;
474 }
475
476
477 /*
478  *      assign_driver - Assign driver to card.
479  *      First, see if an existing driver is already setup.
480  */
481 static struct card_config *
482 assign_driver(struct slot *sp, struct card *cp)
483 {
484         struct driver *drvp;
485         struct card_config *conf;
486         struct pccard_resource res;
487         int i;
488         int irqmin, irqmax;
489
490         for (conf = cp->config; conf; conf = conf->next)
491                 if (conf->inuse == 0 && conf->driver->card == cp &&
492                     conf->driver->config == conf &&
493                     conf->driver->inuse == 0) {
494                         if (debug_level > 0) {
495                                 logmsg("Found existing driver (%s) for %s\n",
496                                     conf->driver->name, cp->manuf);
497                         }
498                         conf->driver->inuse = 1;
499                         conf->inuse = 1;
500                         return (conf);
501                 }
502         /*
503          * New driver must be allocated. Find the first configuration
504          * not in use.
505          */
506         for (conf = cp->config; conf; conf = conf->next)
507                 if (conf->inuse == 0 && conf->driver->inuse/*card*/ == 0)
508                         break;
509         if (conf == 0) {
510                 logmsg("No free configuration for card %s", cp->manuf);
511                 return (NULL);
512         }
513         /*
514          * Now we have a free driver and a matching configuration.
515          * Before assigning and allocating everything, check to
516          * see if a device class can be allocated to this.
517          */
518         drvp = conf->driver;
519
520         /* If none available, then we can't use this card. */
521         if (drvp->inuse) {
522                 logmsg("Driver already being used for %s", cp->manuf);
523                 return (NULL);
524         }
525
526         /*
527          * Allocate a free IRQ if none has been specified.  When we're
528          * sharing interrupts (cardbus bridge case), then we'll use what
529          * the kernel tells us to use, reguardless of what the user
530          * configured.  Asking the kernel for IRQ 0 is our way of asking
531          * if we should use a shared interrupt.
532          */
533         res.type = SYS_RES_IRQ;
534         res.size = 1;
535         if (conf->irq == 0) {
536                 irqmin = 1;
537                 irqmax = 15;
538         } else {
539                 irqmin = irqmax = conf->irq;
540                 conf->irq = 0;          /* Make sure we get it. */
541         }
542         res.min = 0;
543         res.max = 0;
544         if (ioctl(sp->fd, PIOCSRESOURCE, &res) < 0)
545                 err(1, "ioctl (PIOCSRESOURCE)");
546         if (res.resource_addr != ~0ul) {
547                 conf->irq = res.resource_addr;
548                 pool_irq[conf->irq] = 0;
549         } else {
550                 for (i = irqmin; i <= irqmax; i++) {
551                         /*
552                          * Skip irqs not in the pool.
553                          */
554                         if (pool_irq[i] == 0)
555                                 continue;
556                         /*
557                          * -I forces us to use the interrupt, so use it.
558                          */
559                         if (!use_kern_irq) {
560                                 conf->irq = i;
561                                 pool_irq[i] = 0;
562                                 break;
563                         }
564                         /*
565                          * Ask the kernel if we have an free irq.
566                          */
567                         res.min = i;
568                         res.max = i;
569                         if (ioctl(sp->fd, PIOCSRESOURCE, &res) < 0)
570                                 err(1, "ioctl (PIOCSRESOURCE)");
571                         if (res.resource_addr == ~0ul)
572                                 continue;
573                         /*
574                          * res.resource_addr might be the kernel's
575                          * better idea than i, so we have to check to
576                          * see if that's in use too.  If not, mark it
577                          * in use and break out of the loop.  I'm not
578                          * sure this can happen when IRQ 0 above fails,
579                          * but the test is cheap enough.
580                          */
581                         if (pool_irq[res.resource_addr] == 0)
582                                 continue;
583                         conf->irq = res.resource_addr;
584                         pool_irq[conf->irq] = 0;
585                         break;
586                 }
587         }
588         if (conf->irq == 0) {
589                 logmsg("Failed to allocate IRQ for %s\n", cp->manuf);
590                 return (NULL);
591         }
592         drvp->card = cp;
593         drvp->config = conf;
594         drvp->inuse = 1;
595         conf->inuse = 1;
596         return (conf);
597 }
598
599 /*
600  *      Auto select config index
601  */
602 static struct cis_config *
603 assign_card_index(struct slot *sp, struct cis * cis)
604 {
605         struct cis_config *cp;
606         struct cis_ioblk *cio;
607         struct pccard_resource res;
608         int i;
609
610         res.type = SYS_RES_IOPORT;
611         for (cp = cis->conf; cp; cp = cp->next) {
612                 if (!cp->iospace || !cp->io)
613                         continue;
614                 for (cio = cp->io; cio; cio = cio->next) {
615                         res.size = cio->size;
616                         res.min = cio->addr;
617                         res.max = res.min + cio->size - 1;
618                         if (ioctl(sp->fd, PIOCSRESOURCE, &res) < 0)
619                                 err(1, "ioctl (PIOCSRESOURCE)");
620                         if (res.resource_addr != cio->addr)
621                                 goto next;
622                         for (i = cio->addr; i < cio->addr + cio->size - 1; i++)
623                                 if (!bit_test(io_avail, i))
624                                         goto next;
625                 }
626                 return cp;      /* found */
627         next:
628         }
629         return cis->def_config;
630 }
631
632 /*
633  *      assign_io - Allocate resources to slot matching the
634  *      configuration index selected.
635  */
636 static int
637 assign_io(struct slot *sp)
638 {
639         struct cis *cis;
640         struct cis_config *cisconf, *defconf;
641
642         cis = sp->cis;
643         defconf = cis->def_config;
644         switch (sp->config->index_type) {
645         case DEFAULT_INDEX:     /* default */
646                 cisconf = defconf;
647                 sp->config->index = cisconf->id;
648                 break;
649         case AUTO_INDEX:        /* auto */
650                 cisconf = assign_card_index(sp, cis);
651                 sp->config->index = cisconf->id;
652                 break;
653         default:                /* normal, use index value */
654                 for (cisconf = cis->conf; cisconf; cisconf = cisconf->next)
655                         if (cisconf->id == sp->config->index)
656                                 break;
657         }
658
659         if (cisconf == 0) {
660                 logmsg("Config id %d not present in this card",
661                     sp->config->index);
662                 return (-1);
663         }
664         sp->card_config = cisconf;
665
666         /*
667          * Found a matching configuration. Now look at the I/O, memory and IRQ
668          * to create the desired parameters. Look at memory first.
669          */
670
671         /* Skip ed cards in PIO mode */
672         if ((strncmp(sp->config->driver->name, "ed", 2) == 0) &&
673             (sp->config->flags & 0x10))
674                 goto memskip;
675
676         if (cisconf->memspace || (defconf && defconf->memspace)) {
677                 struct cis_memblk *mp;
678
679                 mp = cisconf->mem;
680                 /* 
681                  * Currently we do not handle the presence of multiple windows.
682                  * Then again neither does the interface to the kernel!
683                  * See setup_slot() and readcis.c:cis_conf()
684                  */
685                 if (cisconf->memwins > 1) {
686                         logmsg("Card requires %d memory windows.",
687                             cisconf->memwins);
688                         return (-4);
689                 }
690
691                 if (!cisconf->memspace)
692                         mp = defconf->mem;
693                 sp->mem.size = mp->length;
694                 sp->mem.cardaddr = mp->address;
695
696                 /* For now, we allocate our own memory from the pool. */
697                 sp->mem.addr = sp->config->driver->mem;
698                 /*
699                  * Host memory address is required. Allocate one
700                  * from our pool.
701                  */
702                 if (sp->mem.size && sp->mem.addr == 0) {
703                         sp->mem.addr = alloc_memory(mp->length);
704                         if (sp->mem.addr == 0)
705                                 return (-2);
706                         sp->config->driver->mem = sp->mem.addr;
707                 }
708                 /* Driver specific set up */
709                 if (strncmp(sp->config->driver->name, "ed", 2) == 0) {
710                         sp->mem.cardaddr = 0x4000;
711                         sp->mem.flags = MDF_ACTIVE | MDF_16BITS;
712                 } else {
713                         sp->mem.flags = MDF_ACTIVE | MDF_16BITS;
714                 }
715
716                 if (sp->mem.flags & MDF_ACTIVE)
717                         sp->flags |= MEM_ASSIGNED;
718                 if (debug_level > 0) {
719                         logmsg("Using mem addr 0x%x, size %d, card addr 0x%x, flags 0x%x\n",
720                             sp->mem.addr, sp->mem.size, sp->mem.cardaddr,
721                             sp->mem.flags);
722                 }
723         }
724 memskip:
725
726         /* Now look at I/O. */
727         bzero(&sp->io, sizeof(sp->io));
728         if (cisconf->iospace || (defconf && defconf->iospace) 
729             || sp->card->iosize) {
730                 struct cis_config *cp;
731                 struct cis_ioblk *cio;
732                 struct allocblk *sio;
733                 int     x, xmax;
734                 int iosize;
735
736                 cp = cisconf;
737                 if (!cisconf->iospace)
738                         cp = defconf;
739                 iosize = sp->card->iosize;
740
741                 /* iosize auto */
742                 if (iosize < 0) {
743                         if (cp->io)
744                                 iosize = cp->io->size;
745                         else
746                                 iosize = 1 << cp->io_addr;
747                 }
748
749                 /*
750                 * If # of I/O lines decoded == 10, then card does its
751                 * own decoding.
752                 *
753                 * If an I/O block exists, then use it.
754                 * If no address (but a length) is available, allocate
755                 * from the pool.
756                 */
757                 cio = cp->io;
758                 sio = &(sp->io);
759                 xmax = 1;
760                 if (iosize == 0 && cio)
761                         xmax = cisconf->io_blks;
762                 for (x = 0; x < xmax; x++) {
763                         if (iosize) {
764                                 sio->addr = 0;
765                                 sio->size = iosize;
766                         } else if (cio) {
767                                 sio->addr = cio->addr;
768                                 sio->size = cio->size;
769                         } else {
770                                 /*
771                                  * No I/O block, assume the address lines
772                                  * decode gives the size.
773                                  */
774                                 sio->size = 1 << cp->io_addr;
775                         }
776                         if (sio->addr == 0) {
777                                 struct pccard_resource res;
778                                 int i, j;
779
780                                 res.type = SYS_RES_IOPORT;
781                                 res.size = sio->size;
782
783                                 for (i = 0; i < IOPORTS; i++) {
784                                         j = bit_fns(io_avail, IOPORTS, i,
785                                                         sio->size, sio->size);
786                                         if ((j & (sio->size - 1)) != 0)
787                                                 continue;
788                                         res.min = j;
789                                         res.max = j + sio->size - 1;
790                                         if (ioctl(sp->fd, PIOCSRESOURCE, &res) < 0)
791                                                 err(1, "ioctl (PIOCSRESOURCE)");
792                                         if (res.resource_addr == j)
793                                                 break;
794                                 }
795                                 if (j < 0) {
796                                         return (-3);
797                                 } else {
798                                         sio->addr = j;
799                                 }
800                         }
801                         bit_nclear(io_avail, sio->addr,
802                                    sio->addr + sio->size - 1);
803                         sp->flags |= IO_ASSIGNED;
804
805                         /* Set up the size to take into account the decode lines. */
806                         sio->cardaddr = cp->io_addr;
807                         switch (cp->io_bus) {
808                         case 0:
809                                 break;
810                         case 1:
811                                 sio->flags = IODF_WS;
812                                 break;
813                         case 2:
814                                 sio->flags = IODF_WS | IODF_CS16;
815                                 break;
816                         case 3:
817                                 sio->flags = IODF_WS | IODF_CS16 | IODF_16BIT;
818                                 break;
819                         }
820                         if (debug_level > 0) {
821                                 logmsg("Using I/O addr 0x%x, size %d\n",
822                                     sio->addr, sio->size);
823                         }
824                         if (cio && cio->next) {
825                                 sio->next = xmalloc(sizeof(*sio));
826                                 sio = sio->next;
827                                 cio = cio->next;
828                         }
829                 }
830         }
831         sp->irq = sp->config->irq;
832         sp->flags |= IRQ_ASSIGNED;
833         return (0);
834 }
835
836 /*
837  *      setup_slot - Allocate the I/O and memory contexts
838  *      return true if completed OK.
839  */
840 static int
841 setup_slot(struct slot *sp)
842 {
843         struct mem_desc mem;
844         struct io_desc io;
845         struct dev_desc drv;
846         struct driver *drvp = sp->config->driver;
847         struct allocblk *sio;
848         char    *p;
849         char    c;
850         off_t   offs;
851         int     rw_flags;
852         int     iowin;
853
854         memset(&io, 0, sizeof io);
855         memset(&drv, 0, sizeof drv);
856         offs = sp->cis->reg_addr;
857         rw_flags = MDF_ATTR;
858         ioctl(sp->fd, PIOCRWFLAG, &rw_flags);
859 #if RESET_MAY_BE_HARMFUL
860         lseek(sp->fd, offs, SEEK_SET);
861         c = 0x80;
862         write(sp->fd, &c, sizeof(c));
863         usleep(sp->card->reset_time * 1000);
864         lseek(sp->fd, offs, SEEK_SET);
865         c = 0x00;
866         write(sp->fd, &c, sizeof(c));
867         usleep(sp->card->reset_time * 1000);
868 #endif
869         lseek(sp->fd, offs, SEEK_SET);
870         c = sp->config->index;
871         c |= 0x40;
872         write(sp->fd, &c, sizeof(c));
873         if (debug_level > 0) {
874                 logmsg("Setting config reg at offs 0x%lx to 0x%x, "
875                     "Reset time = %d ms\n", (unsigned long)offs, c,
876                     sp->card->reset_time);
877         }
878         usleep(pccard_init_sleep);
879         usleep(sp->card->reset_time * 1000);
880
881         /* If other config registers exist, set them up. */
882         if (sp->cis->ccrs & 2) {
883                 /* CCSR */
884                 c = 0;
885                 if (sp->cis->def_config && sp->cis->def_config->misc_valid &&
886                     (sp->cis->def_config->misc & 0x8))
887                         c |= 0x08;
888                 if (sp->card_config->io_bus == 1)
889                         c |= 0x20;
890                 lseek(sp->fd, offs + 2, SEEK_SET);
891                 write(sp->fd, &c, sizeof(c));
892         }
893         if (sp->flags & MEM_ASSIGNED) {
894                 mem.window = 0;
895                 mem.flags = sp->mem.flags;
896                 mem.start = (caddr_t) sp->mem.addr;
897                 mem.card = sp->mem.cardaddr;
898                 mem.size = sp->mem.size;
899                 if (ioctl(sp->fd, PIOCSMEM, &mem)) {
900                         logerr("ioctl (PIOCSMEM)");
901                         return (0);
902                 }
903         }
904         if (sp->flags & IO_ASSIGNED) {
905             for (iowin = 0, sio = &(sp->io); iowin <= 1; iowin++) {
906                 io.window = iowin;
907                 if (sio->size) {
908                         io.flags = sio->flags;
909                         io.start = sio->addr;
910                         io.size = sio->size;
911                 }
912 #if 0
913                 io.start = sp->io.addr & ~((1 << sp->io.cardaddr) - 1);
914                 io.size = 1 << sp->io.cardaddr;
915                 if (io.start < 0x100) {
916                         io.start = 0x100;
917                         io.size = 0x300;
918                 }
919 #endif
920                 if (debug_level > 0) {
921                         logmsg("Assigning I/O window %d, start 0x%x, "
922                             "size 0x%x flags 0x%x\n", io.window, io.start,
923                             io.size, io.flags);
924                 }
925                 io.flags |= IODF_ACTIVE;
926                 if (ioctl(sp->fd, PIOCSIO, &io)) {
927                         logerr("ioctl (PIOCSIO)");
928                         return (0);
929                 }
930                 if (ioctl(sp->fd, PIOCGIO, &io))
931                 {
932                     logerr("ioctl (PIOCGIO)");
933                     return(0);
934                 }
935                 if (io.start != sio->addr){
936                     logmsg("I/O base address changed from 0x%x to 0x%x\n",
937                            sio->addr, io.start);
938                     sio->addr = io.start;
939                 }
940                 if (sio->next)
941                         sio = sio->next;
942                 else
943                         break;
944             }
945         }
946         strcpy(drv.name, drvp->kernel);
947         drv.unit = drvp->unit;
948         drv.irqmask = 1 << sp->irq;
949         drv.flags = sp->config->flags;
950         if (sp->flags & MEM_ASSIGNED) {
951                 drv.mem = sp->mem.addr;
952                 drv.memsize = sp->mem.size;
953         } else {
954                 drv.mem = 0;
955                 drv.memsize = 0;
956         }
957         if (sp->flags & IO_ASSIGNED)
958                 drv.iobase = sp->io.addr;
959         else
960                 drv.iobase = 0;
961 #ifdef DEV_DESC_HAS_SIZE
962         drv.iosize = sp->io.size;
963 #endif
964         if (debug_level > 0) {
965                 logmsg("Assign %s%d, io 0x%x-0x%x, mem 0x%lx, %d bytes, "
966                     "irq %d, flags %x\n", drv.name, drv.unit, drv.iobase, 
967                     drv.iobase + sp->io.size - 1, drv.mem, drv.memsize, 
968                     sp->irq, drv.flags);
969         }
970         /*
971          * If the driver fails to be connected to the device,
972          * then it may mean that the driver did not recognise it.
973          */
974         memcpy(drv.misc, sp->eaddr, 6);
975         if (ioctl(sp->fd, PIOCSDRV, &drv)) {
976                 logmsg("driver allocation failed for %s(%s): %s",
977                     sp->card->manuf, sp->card->version, strerror(errno));
978                 return (0);
979         }
980         drv.name[sizeof(drv.name) - 1] = '\0';
981         if (strncmp(drv.name, drvp->kernel, sizeof(drv.name))) {
982                 drvp->kernel = newstr(drv.name);
983                 p = drvp->kernel;
984                 while (*p++) 
985                         if (*p >= '0' && *p <= '9') {
986                                 drvp->unit = atoi(p);
987                                 *p = '\0';
988                                 break;
989                         }
990         }
991         logmsg("%s%d: %s inserted.", sp->config->driver->kernel,
992             sp->config->driver->unit, sp->card->logstr);
993         return (1);
994 }