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