OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pnp/] [isapnp.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  ISA Plug & Play support
3
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4
 *
5
 *
6
 *   This program is free software; you can redistribute it and/or modify
7
 *   it under the terms of the GNU General Public License as published by
8
 *   the Free Software Foundation; either version 2 of the License, or
9
 *   (at your option) any later version.
10
 *
11
 *   This program is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU General Public License for more details.
15
 *
16
 *   You should have received a copy of the GNU General Public License
17
 *   along with this program; if not, write to the Free Software
18
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 *
20
 *  Changelog:
21
 *  2000-01-01  Added quirks handling for buggy hardware
22
 *              Peter Denison <peterd@pnd-pc.demon.co.uk>
23
 *  2000-06-14  Added isapnp_probe_devs() and isapnp_activate_dev()
24
 *              Christoph Hellwig <hch@infradead.org>
25
 *  2001-06-03  Added release_region calls to correspond with
26
 *              request_region calls when a failure occurs.  Also
27
 *              added KERN_* constants to printk() calls.
28
 *  2001-11-07  Added isapnp_{,un}register_driver calls along the lines
29
 *              of the pci driver interface
30
 *              Kai Germaschewski <kai.germaschewski@gmx.de>
31
 *  2002-06-06  Made the use of dma channel 0 configurable
32
 *              Gerald Teschl <gerald.teschl@univie.ac.at>
33
 */
34
 
35
#include <linux/config.h>
36
#include <linux/version.h>
37
#include <linux/module.h>
38
#include <linux/kernel.h>
39
#include <linux/errno.h>
40
#include <linux/ioport.h>
41
#include <linux/string.h>
42
#include <linux/slab.h>
43
#include <linux/delay.h>
44
#include <asm/io.h>
45
#include <asm/dma.h>
46
#include <asm/irq.h>
47
#include <linux/pci.h>
48
#include <linux/init.h>
49
#include <linux/isapnp.h>
50
 
51
LIST_HEAD(isapnp_cards);
52
LIST_HEAD(isapnp_devices);
53
 
54
#if 0
55
#define ISAPNP_REGION_OK
56
#endif
57
#if 0
58
#define ISAPNP_DEBUG
59
#endif
60
 
61
int isapnp_disable;                     /* Disable ISA PnP */
62
int isapnp_rdp;                         /* Read Data Port */
63
int isapnp_reset = 1;                   /* reset all PnP cards (deactivate) */
64
int isapnp_allow_dma0 = -1;             /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */
65
int isapnp_skip_pci_scan;               /* skip PCI resource scanning */
66
int isapnp_verbose = 1;                 /* verbose mode */
67
int isapnp_reserve_irq[16] = { [0 ... 15] = -1 };        /* reserve (don't use) some IRQ */
68
int isapnp_reserve_dma[8] = { [0 ... 7] = -1 };          /* reserve (don't use) some DMA */
69
int isapnp_reserve_io[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
70
int isapnp_reserve_mem[16] = { [0 ... 15] = -1 };        /* reserve (don't use) some memory region */
71
 
72
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
73
MODULE_DESCRIPTION("Generic ISA Plug & Play support");
74
MODULE_PARM(isapnp_disable, "i");
75
MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
76
MODULE_PARM(isapnp_rdp, "i");
77
MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
78
MODULE_PARM(isapnp_reset, "i");
79
MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
80
MODULE_PARM(isapnp_allow_dma0, "i");
81
MODULE_PARM_DESC(isapnp_allow_dma0, "Allow dma value 0 during auto activation");
82
MODULE_PARM(isapnp_skip_pci_scan, "i");
83
MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
84
MODULE_PARM(isapnp_verbose, "i");
85
MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
86
MODULE_PARM(isapnp_reserve_irq, "1-16i");
87
MODULE_PARM_DESC(isapnp_reserve_irq, "ISA Plug & Play - reserve IRQ line(s)");
88
MODULE_PARM(isapnp_reserve_dma, "1-8i");
89
MODULE_PARM_DESC(isapnp_reserve_dma, "ISA Plug & Play - reserve DMA channel(s)");
90
MODULE_PARM(isapnp_reserve_io, "1-16i");
91
MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");
92
MODULE_PARM(isapnp_reserve_mem, "1-16i");
93
MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");
94
MODULE_LICENSE("GPL");
95
 
96
#define _PIDXR          0x279
97
#define _PNPWRP         0xa79
98
 
99
/* short tags */
100
#define _STAG_PNPVERNO          0x01
101
#define _STAG_LOGDEVID          0x02
102
#define _STAG_COMPATDEVID       0x03
103
#define _STAG_IRQ               0x04
104
#define _STAG_DMA               0x05
105
#define _STAG_STARTDEP          0x06
106
#define _STAG_ENDDEP            0x07
107
#define _STAG_IOPORT            0x08
108
#define _STAG_FIXEDIO           0x09
109
#define _STAG_VENDOR            0x0e
110
#define _STAG_END               0x0f
111
/* long tags */
112
#define _LTAG_MEMRANGE          0x81
113
#define _LTAG_ANSISTR           0x82
114
#define _LTAG_UNICODESTR        0x83
115
#define _LTAG_VENDOR            0x84
116
#define _LTAG_MEM32RANGE        0x85
117
#define _LTAG_FIXEDMEM32RANGE   0x86
118
 
119
static unsigned char isapnp_checksum_value;
120
static DECLARE_MUTEX(isapnp_cfg_mutex);
121
static int isapnp_detected;
122
 
123
/* some prototypes */
124
 
125
static int isapnp_config_prepare(struct pci_dev *dev);
126
static int isapnp_config_activate(struct pci_dev *dev);
127
static int isapnp_config_deactivate(struct pci_dev *dev);
128
 
129
static inline void write_data(unsigned char x)
130
{
131
        outb(x, _PNPWRP);
132
}
133
 
134
static inline void write_address(unsigned char x)
135
{
136
        outb(x, _PIDXR);
137
        udelay(20);
138
}
139
 
140
static inline unsigned char read_data(void)
141
{
142
        unsigned char val = inb(isapnp_rdp);
143
        return val;
144
}
145
 
146
unsigned char isapnp_read_byte(unsigned char idx)
147
{
148
        write_address(idx);
149
        return read_data();
150
}
151
 
152
unsigned short isapnp_read_word(unsigned char idx)
153
{
154
        unsigned short val;
155
 
156
        val = isapnp_read_byte(idx);
157
        val = (val << 8) + isapnp_read_byte(idx+1);
158
        return val;
159
}
160
 
161
unsigned int isapnp_read_dword(unsigned char idx)
162
{
163
        unsigned int val;
164
 
165
        val = isapnp_read_byte(idx);
166
        val = (val << 8) + isapnp_read_byte(idx+1);
167
        val = (val << 8) + isapnp_read_byte(idx+2);
168
        val = (val << 8) + isapnp_read_byte(idx+3);
169
        return val;
170
}
171
 
172
void isapnp_write_byte(unsigned char idx, unsigned char val)
173
{
174
        write_address(idx);
175
        write_data(val);
176
}
177
 
178
void isapnp_write_word(unsigned char idx, unsigned short val)
179
{
180
        isapnp_write_byte(idx, val >> 8);
181
        isapnp_write_byte(idx+1, val);
182
}
183
 
184
void isapnp_write_dword(unsigned char idx, unsigned int val)
185
{
186
        isapnp_write_byte(idx, val >> 24);
187
        isapnp_write_byte(idx+1, val >> 16);
188
        isapnp_write_byte(idx+2, val >> 8);
189
        isapnp_write_byte(idx+3, val);
190
}
191
 
192
void *isapnp_alloc(long size)
193
{
194
        void *result;
195
 
196
        result = kmalloc(size, GFP_KERNEL);
197
        if (!result)
198
                return NULL;
199
        memset(result, 0, size);
200
        return result;
201
}
202
 
203
static void isapnp_key(void)
204
{
205
        unsigned char code = 0x6a, msb;
206
        int i;
207
 
208
        mdelay(1);
209
        write_address(0x00);
210
        write_address(0x00);
211
 
212
        write_address(code);
213
 
214
        for (i = 1; i < 32; i++) {
215
                msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
216
                code = (code >> 1) | msb;
217
                write_address(code);
218
        }
219
}
220
 
221
/* place all pnp cards in wait-for-key state */
222
static void isapnp_wait(void)
223
{
224
        isapnp_write_byte(0x02, 0x02);
225
}
226
 
227
void isapnp_wake(unsigned char csn)
228
{
229
        isapnp_write_byte(0x03, csn);
230
}
231
 
232
void isapnp_device(unsigned char logdev)
233
{
234
        isapnp_write_byte(0x07, logdev);
235
}
236
 
237
void isapnp_activate(unsigned char logdev)
238
{
239
        isapnp_device(logdev);
240
        isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
241
        udelay(250);
242
}
243
 
244
void isapnp_deactivate(unsigned char logdev)
245
{
246
        isapnp_device(logdev);
247
        isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
248
        udelay(500);
249
}
250
 
251
static void __init isapnp_peek(unsigned char *data, int bytes)
252
{
253
        int i, j;
254
        unsigned char d=0;
255
 
256
        for (i = 1; i <= bytes; i++) {
257
                for (j = 0; j < 20; j++) {
258
                        d = isapnp_read_byte(0x05);
259
                        if (d & 1)
260
                                break;
261
                        udelay(100);
262
                }
263
                if (!(d & 1)) {
264
                        if (data != NULL)
265
                                *data++ = 0xff;
266
                        continue;
267
                }
268
                d = isapnp_read_byte(0x04);     /* PRESDI */
269
                isapnp_checksum_value += d;
270
                if (data != NULL)
271
                        *data++ = d;
272
        }
273
}
274
 
275
#define RDP_STEP        32      /* minimum is 4 */
276
 
277
static int isapnp_next_rdp(void)
278
{
279
        int rdp = isapnp_rdp;
280
        while (rdp <= 0x3ff) {
281
                /*
282
                 *      We cannot use NE2000 probe spaces for ISAPnP or we
283
                 *      will lock up machines.
284
                 */
285
                if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1))
286
                {
287
                        isapnp_rdp = rdp;
288
                        return 0;
289
                }
290
                rdp += RDP_STEP;
291
        }
292
        return -1;
293
}
294
 
295
/* Set read port address */
296
static inline void isapnp_set_rdp(void)
297
{
298
        isapnp_write_byte(0x00, isapnp_rdp >> 2);
299
        udelay(100);
300
}
301
 
302
/*
303
 *      Perform an isolation. The port selection code now tries to avoid
304
 *      "dangerous to read" ports.
305
 */
306
 
307
static int __init isapnp_isolate_rdp_select(void)
308
{
309
        isapnp_wait();
310
        isapnp_key();
311
 
312
        /* Control: reset CSN and conditionally everything else too */
313
        isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);
314
        mdelay(2);
315
 
316
        isapnp_wait();
317
        isapnp_key();
318
        isapnp_wake(0x00);
319
 
320
        if (isapnp_next_rdp() < 0) {
321
                isapnp_wait();
322
                return -1;
323
        }
324
 
325
        isapnp_set_rdp();
326
        udelay(1000);
327
        write_address(0x01);
328
        udelay(1000);
329
        return 0;
330
}
331
 
332
/*
333
 *  Isolate (assign uniqued CSN) to all ISA PnP devices.
334
 */
335
 
336
static int __init isapnp_isolate(void)
337
{
338
        unsigned char checksum = 0x6a;
339
        unsigned char chksum = 0x00;
340
        unsigned char bit = 0x00;
341
        int data;
342
        int csn = 0;
343
        int i;
344
        int iteration = 1;
345
 
346
        isapnp_rdp = 0x213;
347
        if (isapnp_isolate_rdp_select() < 0)
348
                return -1;
349
 
350
        while (1) {
351
                for (i = 1; i <= 64; i++) {
352
                        data = read_data() << 8;
353
                        udelay(250);
354
                        data = data | read_data();
355
                        udelay(250);
356
                        if (data == 0x55aa)
357
                                bit = 0x01;
358
                        checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
359
                        bit = 0x00;
360
                }
361
                for (i = 65; i <= 72; i++) {
362
                        data = read_data() << 8;
363
                        udelay(250);
364
                        data = data | read_data();
365
                        udelay(250);
366
                        if (data == 0x55aa)
367
                                chksum |= (1 << (i - 65));
368
                }
369
                if (checksum != 0x00 && checksum == chksum) {
370
                        csn++;
371
 
372
                        isapnp_write_byte(0x06, csn);
373
                        udelay(250);
374
                        iteration++;
375
                        isapnp_wake(0x00);
376
                        isapnp_set_rdp();
377
                        udelay(1000);
378
                        write_address(0x01);
379
                        udelay(1000);
380
                        goto __next;
381
                }
382
                if (iteration == 1) {
383
                        isapnp_rdp += RDP_STEP;
384
                        if (isapnp_isolate_rdp_select() < 0)
385
                                return -1;
386
                } else if (iteration > 1) {
387
                        break;
388
                }
389
              __next:
390
                checksum = 0x6a;
391
                chksum = 0x00;
392
                bit = 0x00;
393
        }
394
        isapnp_wait();
395
        return csn;
396
}
397
 
398
/*
399
 *  Read one tag from stream.
400
 */
401
 
402
static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
403
{
404
        unsigned char tag, tmp[2];
405
 
406
        isapnp_peek(&tag, 1);
407
        if (tag == 0)                            /* invalid tag */
408
                return -1;
409
        if (tag & 0x80) {       /* large item */
410
                *type = tag;
411
                isapnp_peek(tmp, 2);
412
                *size = (tmp[1] << 8) | tmp[0];
413
        } else {
414
                *type = (tag >> 3) & 0x0f;
415
                *size = tag & 0x07;
416
        }
417
#if 0
418
        printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
419
#endif
420
        if (type == 0)                           /* wrong type */
421
                return -1;
422
        if (*type == 0xff && *size == 0xffff)   /* probably invalid data */
423
                return -1;
424
        return 0;
425
}
426
 
427
/*
428
 *  Skip specified number of bytes from stream.
429
 */
430
 
431
static void __init isapnp_skip_bytes(int count)
432
{
433
        isapnp_peek(NULL, count);
434
}
435
 
436
/*
437
 *  Parse logical device tag.
438
 */
439
 
440
static struct pci_dev * __init isapnp_parse_device(struct pci_bus *card, int size, int number)
441
{
442
        unsigned char tmp[6];
443
        struct pci_dev *dev;
444
 
445
        isapnp_peek(tmp, size);
446
        dev = isapnp_alloc(sizeof(struct pci_dev));
447
        if (!dev)
448
                return NULL;
449
        dev->dma_mask = 0x00ffffff;
450
        dev->devfn = number;
451
        dev->vendor = (tmp[1] << 8) | tmp[0];
452
        dev->device = (tmp[3] << 8) | tmp[2];
453
        dev->regs = tmp[4];
454
        dev->bus = card;
455
        if (size > 5)
456
                dev->regs |= tmp[5] << 8;
457
        dev->prepare = isapnp_config_prepare;
458
        dev->activate = isapnp_config_activate;
459
        dev->deactivate = isapnp_config_deactivate;
460
        return dev;
461
}
462
 
463
/*
464
 *  Build new resources structure
465
 */
466
 
467
static struct isapnp_resources * __init isapnp_build_resources(struct pci_dev *dev, int dependent)
468
{
469
        struct isapnp_resources *res, *ptr, *ptra;
470
 
471
        res = isapnp_alloc(sizeof(struct isapnp_resources));
472
        if (!res)
473
                return NULL;
474
        res->dev = dev;
475
        ptr = (struct isapnp_resources *)dev->sysdata;
476
        while (ptr && ptr->next)
477
                ptr = ptr->next;
478
        if (ptr && ptr->dependent && dependent) { /* add to another list */
479
                ptra = ptr->alt;
480
                while (ptra && ptra->alt)
481
                        ptra = ptra->alt;
482
                if (!ptra)
483
                        ptr->alt = res;
484
                else
485
                        ptra->alt = res;
486
        } else {
487
                if (!ptr)
488
                        dev->sysdata = res;
489
                else
490
                        ptr->next = res;
491
        }
492
        if (dependent) {
493
                res->priority = dependent & 0xff;
494
                if (res->priority > ISAPNP_RES_PRIORITY_FUNCTIONAL)
495
                        res->priority = ISAPNP_RES_PRIORITY_INVALID;
496
                res->dependent = 1;
497
        } else {
498
                res->priority = ISAPNP_RES_PRIORITY_PREFERRED;
499
                res->dependent = 0;
500
        }
501
        return res;
502
}
503
 
504
/*
505
 *  Add IRQ resource to resources list.
506
 */
507
 
508
static void __init isapnp_add_irq_resource(struct pci_dev *dev,
509
                                               struct isapnp_resources **res,
510
                                               int dependent, int size)
511
{
512
        unsigned char tmp[3];
513
        struct isapnp_irq *irq, *ptr;
514
 
515
        isapnp_peek(tmp, size);
516
        irq = isapnp_alloc(sizeof(struct isapnp_irq));
517
        if (!irq)
518
                return;
519
        if (*res == NULL) {
520
                *res = isapnp_build_resources(dev, dependent);
521
                if (*res == NULL) {
522
                        kfree(irq);
523
                        return;
524
                }
525
        }
526
        irq->map = (tmp[1] << 8) | tmp[0];
527
        if (size > 2)
528
                irq->flags = tmp[2];
529
        else
530
                irq->flags = IORESOURCE_IRQ_HIGHEDGE;
531
        irq->res = *res;
532
        ptr = (*res)->irq;
533
        while (ptr && ptr->next)
534
                ptr = ptr->next;
535
        if (ptr)
536
                ptr->next = irq;
537
        else
538
                (*res)->irq = irq;
539
#ifdef CONFIG_PCI
540
        {
541
                int i;
542
 
543
                for (i=0; i<16; i++)
544
                        if (irq->map & (1<<i))
545
                                pcibios_penalize_isa_irq(i);
546
        }
547
#endif
548
}
549
 
550
/*
551
 *  Add DMA resource to resources list.
552
 */
553
 
554
static void __init isapnp_add_dma_resource(struct pci_dev *dev,
555
                                               struct isapnp_resources **res,
556
                                               int dependent, int size)
557
{
558
        unsigned char tmp[2];
559
        struct isapnp_dma *dma, *ptr;
560
 
561
        isapnp_peek(tmp, size);
562
        dma = isapnp_alloc(sizeof(struct isapnp_dma));
563
        if (!dma)
564
                return;
565
        if (*res == NULL) {
566
                *res = isapnp_build_resources(dev, dependent);
567
                if (*res == NULL) {
568
                        kfree(dma);
569
                        return;
570
                }
571
        }
572
        dma->map = tmp[0];
573
        dma->flags = tmp[1];
574
        dma->res = *res;
575
        ptr = (*res)->dma;
576
        while (ptr && ptr->next)
577
                ptr = ptr->next;
578
        if (ptr)
579
                ptr->next = dma;
580
        else
581
                (*res)->dma = dma;
582
}
583
 
584
/*
585
 *  Add port resource to resources list.
586
 */
587
 
588
static void __init isapnp_add_port_resource(struct pci_dev *dev,
589
                                                struct isapnp_resources **res,
590
                                                int dependent, int size)
591
{
592
        unsigned char tmp[7];
593
        struct isapnp_port *port, *ptr;
594
 
595
        isapnp_peek(tmp, size);
596
        port = isapnp_alloc(sizeof(struct isapnp_port));
597
        if (!port)
598
                return;
599
        if (*res == NULL) {
600
                *res = isapnp_build_resources(dev, dependent);
601
                if (*res == NULL) {
602
                        kfree(port);
603
                        return;
604
                }
605
        }
606
        port->min = (tmp[2] << 8) | tmp[1];
607
        port->max = (tmp[4] << 8) | tmp[3];
608
        port->align = tmp[5];
609
        port->size = tmp[6];
610
        port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
611
        port->res = *res;
612
        ptr = (*res)->port;
613
        while (ptr && ptr->next)
614
                ptr = ptr->next;
615
        if (ptr)
616
                ptr->next = port;
617
        else
618
                (*res)->port = port;
619
}
620
 
621
/*
622
 *  Add fixed port resource to resources list.
623
 */
624
 
625
static void __init isapnp_add_fixed_port_resource(struct pci_dev *dev,
626
                                                      struct isapnp_resources **res,
627
                                                      int dependent, int size)
628
{
629
        unsigned char tmp[3];
630
        struct isapnp_port *port, *ptr;
631
 
632
        isapnp_peek(tmp, size);
633
        port = isapnp_alloc(sizeof(struct isapnp_port));
634
        if (!port)
635
                return;
636
        if (*res == NULL) {
637
                *res = isapnp_build_resources(dev, dependent);
638
                if (*res == NULL) {
639
                        kfree(port);
640
                        return;
641
                }
642
        }
643
        port->min = port->max = (tmp[1] << 8) | tmp[0];
644
        port->size = tmp[2];
645
        port->align = 0;
646
        port->flags = ISAPNP_PORT_FLAG_FIXED;
647
        port->res = *res;
648
        ptr = (*res)->port;
649
        while (ptr && ptr->next)
650
                ptr = ptr->next;
651
        if (ptr)
652
                ptr->next = port;
653
        else
654
                (*res)->port = port;
655
}
656
 
657
/*
658
 *  Add memory resource to resources list.
659
 */
660
 
661
static void __init isapnp_add_mem_resource(struct pci_dev *dev,
662
                                               struct isapnp_resources **res,
663
                                               int dependent, int size)
664
{
665
        unsigned char tmp[9];
666
        struct isapnp_mem *mem, *ptr;
667
 
668
        isapnp_peek(tmp, size);
669
        mem = isapnp_alloc(sizeof(struct isapnp_mem));
670
        if (!mem)
671
                return;
672
        if (*res == NULL) {
673
                *res = isapnp_build_resources(dev, dependent);
674
                if (*res == NULL) {
675
                        kfree(mem);
676
                        return;
677
                }
678
        }
679
        mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
680
        mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
681
        mem->align = (tmp[6] << 8) | tmp[5];
682
        mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
683
        mem->flags = tmp[0];
684
        mem->res = *res;
685
        ptr = (*res)->mem;
686
        while (ptr && ptr->next)
687
                ptr = ptr->next;
688
        if (ptr)
689
                ptr->next = mem;
690
        else
691
                (*res)->mem = mem;
692
}
693
 
694
/*
695
 *  Add 32-bit memory resource to resources list.
696
 */
697
 
698
static void __init isapnp_add_mem32_resource(struct pci_dev *dev,
699
                                                 struct isapnp_resources **res,
700
                                                 int dependent, int size)
701
{
702
        unsigned char tmp[17];
703
        struct isapnp_mem32 *mem32, *ptr;
704
 
705
        isapnp_peek(tmp, size);
706
        mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
707
        if (!mem32)
708
                return;
709
        if (*res == NULL) {
710
                *res = isapnp_build_resources(dev, dependent);
711
                if (*res == NULL) {
712
                        kfree(mem32);
713
                        return;
714
                }
715
        }
716
        memcpy(mem32->data, tmp, 17);
717
        mem32->res = *res;
718
        ptr = (*res)->mem32;
719
        while (ptr && ptr->next)
720
                ptr = ptr->next;
721
        if (ptr)
722
                ptr->next = mem32;
723
        else
724
                (*res)->mem32 = mem32;
725
}
726
 
727
/*
728
 *  Add 32-bit fixed memory resource to resources list.
729
 */
730
 
731
static void __init isapnp_add_fixed_mem32_resource(struct pci_dev *dev,
732
                                                       struct isapnp_resources **res,
733
                                                       int dependent, int size)
734
{
735
        unsigned char tmp[17];
736
        struct isapnp_mem32 *mem32, *ptr;
737
 
738
        isapnp_peek(tmp, size);
739
        mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
740
        if (!mem32)
741
                return;
742
        if (*res == NULL) {
743
                *res = isapnp_build_resources(dev, dependent);
744
                if (*res == NULL) {
745
                        kfree(mem32);
746
                        return;
747
                }
748
        }
749
        memcpy(mem32->data, tmp, 17);
750
        mem32->res = *res;
751
        ptr = (*res)->mem32;
752
        while (ptr && ptr->next)
753
                ptr = ptr->next;
754
        if (ptr)
755
                ptr->next = mem32;
756
        else
757
                (*res)->mem32 = mem32;
758
}
759
 
760
/*
761
 *  Parse card name for ISA PnP device.
762
 */
763
 
764
static void __init
765
isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
766
{
767
        if (name[0] == '\0') {
768
                unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;
769
                isapnp_peek(name, size1);
770
                name[size1] = '\0';
771
                *size -= size1;
772
 
773
                /* clean whitespace from end of string */
774
                while (size1 > 0  &&  name[--size1] == ' ')
775
                        name[size1] = '\0';
776
        }
777
}
778
 
779
/*
780
 *  Parse resource map for logical device.
781
 */
782
 
783
static int __init isapnp_create_device(struct pci_bus *card,
784
                                           unsigned short size)
785
{
786
        int number = 0, skip = 0, dependent = 0, compat = 0;
787
        unsigned char type, tmp[17];
788
        struct pci_dev *dev;
789
        struct isapnp_resources *res = NULL;
790
 
791
        if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
792
                return 1;
793
        list_add(&dev->bus_list, &card->devices);
794
        list_add_tail(&dev->global_list, &isapnp_devices);
795
        while (1) {
796
                if (isapnp_read_tag(&type, &size)<0)
797
                        return 1;
798
                if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
799
                        goto __skip;
800
                switch (type) {
801
                case _STAG_LOGDEVID:
802
                        if (size >= 5 && size <= 6) {
803
                                isapnp_config_prepare(dev);
804
                                if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
805
                                        return 1;
806
                                list_add_tail(&dev->bus_list, &card->devices);
807
                                list_add_tail(&dev->global_list, &isapnp_devices);
808
                                size = 0;
809
                                skip = 0;
810
                        } else {
811
                                skip = 1;
812
                        }
813
                        res = NULL;
814
                        dependent = 0;
815
                        compat = 0;
816
                        break;
817
                case _STAG_COMPATDEVID:
818
                        if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
819
                                isapnp_peek(tmp, 4);
820
                                dev->vendor_compatible[compat] = (tmp[1] << 8) | tmp[0];
821
                                dev->device_compatible[compat] = (tmp[3] << 8) | tmp[2];
822
                                compat++;
823
                                size = 0;
824
                        }
825
                        break;
826
                case _STAG_IRQ:
827
                        if (size < 2 || size > 3)
828
                                goto __skip;
829
                        isapnp_add_irq_resource(dev, &res, dependent, size);
830
                        size = 0;
831
                        break;
832
                case _STAG_DMA:
833
                        if (size != 2)
834
                                goto __skip;
835
                        isapnp_add_dma_resource(dev, &res, dependent, size);
836
                        size = 0;
837
                        break;
838
                case _STAG_STARTDEP:
839
                        if (size > 1)
840
                                goto __skip;
841
                        res = NULL;
842
                        dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
843
                        if (size > 0) {
844
                                isapnp_peek(tmp, size);
845
                                dependent = 0x100 | tmp[0];
846
                                size = 0;
847
                        }
848
                        break;
849
                case _STAG_ENDDEP:
850
                        if (size != 0)
851
                                goto __skip;
852
                        res = NULL;
853
                        dependent = 0;
854
                        break;
855
                case _STAG_IOPORT:
856
                        if (size != 7)
857
                                goto __skip;
858
                        isapnp_add_port_resource(dev, &res, dependent, size);
859
                        size = 0;
860
                        break;
861
                case _STAG_FIXEDIO:
862
                        if (size != 3)
863
                                goto __skip;
864
                        isapnp_add_fixed_port_resource(dev, &res, dependent, size);
865
                        size = 0;
866
                        break;
867
                case _STAG_VENDOR:
868
                        break;
869
                case _LTAG_MEMRANGE:
870
                        if (size != 9)
871
                                goto __skip;
872
                        isapnp_add_mem_resource(dev, &res, dependent, size);
873
                        size = 0;
874
                        break;
875
                case _LTAG_ANSISTR:
876
                        isapnp_parse_name(dev->name, sizeof(dev->name), &size);
877
                        break;
878
                case _LTAG_UNICODESTR:
879
                        /* silently ignore */
880
                        /* who use unicode for hardware identification? */
881
                        break;
882
                case _LTAG_VENDOR:
883
                        break;
884
                case _LTAG_MEM32RANGE:
885
                        if (size != 17)
886
                                goto __skip;
887
                        isapnp_add_mem32_resource(dev, &res, dependent, size);
888
                        size = 0;
889
                        break;
890
                case _LTAG_FIXEDMEM32RANGE:
891
                        if (size != 17)
892
                                goto __skip;
893
                        isapnp_add_fixed_mem32_resource(dev, &res, dependent, size);
894
                        size = 0;
895
                        break;
896
                case _STAG_END:
897
                        if (size > 0)
898
                                isapnp_skip_bytes(size);
899
                        isapnp_config_prepare(dev);
900
                        return 1;
901
                default:
902
                        printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->devfn, card->number);
903
                }
904
              __skip:
905
                if (size > 0)
906
                        isapnp_skip_bytes(size);
907
        }
908
        isapnp_config_prepare(dev);
909
        return 0;
910
}
911
 
912
/*
913
 *  Parse resource map for ISA PnP card.
914
 */
915
 
916
static void __init isapnp_parse_resource_map(struct pci_bus *card)
917
{
918
        unsigned char type, tmp[17];
919
        unsigned short size;
920
 
921
        while (1) {
922
                if (isapnp_read_tag(&type, &size)<0)
923
                        return;
924
                switch (type) {
925
                case _STAG_PNPVERNO:
926
                        if (size != 2)
927
                                goto __skip;
928
                        isapnp_peek(tmp, 2);
929
                        card->pnpver = tmp[0];
930
                        card->productver = tmp[1];
931
                        size = 0;
932
                        break;
933
                case _STAG_LOGDEVID:
934
                        if (size >= 5 && size <= 6) {
935
                                if (isapnp_create_device(card, size)==1)
936
                                        return;
937
                                size = 0;
938
                        }
939
                        break;
940
                case _STAG_VENDOR:
941
                        break;
942
                case _LTAG_ANSISTR:
943
                        isapnp_parse_name(card->name, sizeof(card->name), &size);
944
                        break;
945
                case _LTAG_UNICODESTR:
946
                        /* silently ignore */
947
                        /* who use unicode for hardware identification? */
948
                        break;
949
                case _LTAG_VENDOR:
950
                        break;
951
                case _STAG_END:
952
                        if (size > 0)
953
                                isapnp_skip_bytes(size);
954
                        return;
955
                default:
956
                        printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);
957
                }
958
              __skip:
959
                if (size > 0)
960
                        isapnp_skip_bytes(size);
961
        }
962
}
963
 
964
/*
965
 *  Compute ISA PnP checksum for first eight bytes.
966
 */
967
 
968
static unsigned char __init isapnp_checksum(unsigned char *data)
969
{
970
        int i, j;
971
        unsigned char checksum = 0x6a, bit, b;
972
 
973
        for (i = 0; i < 8; i++) {
974
                b = data[i];
975
                for (j = 0; j < 8; j++) {
976
                        bit = 0;
977
                        if (b & (1 << j))
978
                                bit = 1;
979
                        checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
980
                }
981
        }
982
        return checksum;
983
}
984
 
985
/*
986
 *  Build device list for all present ISA PnP devices.
987
 */
988
 
989
static int __init isapnp_build_device_list(void)
990
{
991
        int csn;
992
        unsigned char header[9], checksum;
993
        struct pci_bus *card;
994
        struct pci_dev *dev;
995
 
996
        isapnp_wait();
997
        isapnp_key();
998
        for (csn = 1; csn <= 10; csn++) {
999
                isapnp_wake(csn);
1000
                isapnp_peek(header, 9);
1001
                checksum = isapnp_checksum(header);
1002
#if 0
1003
                printk(KERN_DEBUG "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
1004
                        header[0], header[1], header[2], header[3],
1005
                        header[4], header[5], header[6], header[7], header[8]);
1006
                printk(KERN_DEBUG "checksum = 0x%x\n", checksum);
1007
#endif
1008
                /* Don't be strict on the checksum, here !
1009
                   e.g. 'SCM SwapBox Plug and Play' has header[8]==0 (should be: b7)*/
1010
                if (header[8] == 0)
1011
                        ;
1012
                else if (checksum == 0x00 || checksum != header[8])     /* not valid CSN */
1013
                        continue;
1014
                if ((card = isapnp_alloc(sizeof(struct pci_bus))) == NULL)
1015
                        continue;
1016
 
1017
                card->number = csn;
1018
                card->vendor = (header[1] << 8) | header[0];
1019
                card->device = (header[3] << 8) | header[2];
1020
                card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
1021
                isapnp_checksum_value = 0x00;
1022
                INIT_LIST_HEAD(&card->children);
1023
                INIT_LIST_HEAD(&card->devices);
1024
                isapnp_parse_resource_map(card);
1025
                if (isapnp_checksum_value != 0x00)
1026
                        printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
1027
                card->checksum = isapnp_checksum_value;
1028
 
1029
                list_add_tail(&card->node, &isapnp_cards);
1030
        }
1031
        isapnp_for_each_dev(dev) {
1032
                isapnp_fixup_device(dev);
1033
        }
1034
        return 0;
1035
}
1036
 
1037
/*
1038
 *  Basic configuration routines.
1039
 */
1040
 
1041
int isapnp_present(void)
1042
{
1043
        return !list_empty(&isapnp_devices);
1044
}
1045
 
1046
int isapnp_cfg_begin(int csn, int logdev)
1047
{
1048
        if (csn < 1 || csn > 10 || logdev > 10)
1049
                return -EINVAL;
1050
        MOD_INC_USE_COUNT;
1051
        down(&isapnp_cfg_mutex);
1052
        isapnp_wait();
1053
        isapnp_key();
1054
        isapnp_wake(csn);
1055
#if 1   /* to avoid malfunction when the isapnptools package is used */
1056
        isapnp_set_rdp();
1057
        udelay(1000);   /* delay 1000us */
1058
        write_address(0x01);
1059
        udelay(1000);   /* delay 1000us */
1060
#endif
1061
        if (logdev >= 0)
1062
                isapnp_device(logdev);
1063
        return 0;
1064
}
1065
 
1066
int isapnp_cfg_end(void)
1067
{
1068
        isapnp_wait();
1069
        up(&isapnp_cfg_mutex);
1070
        MOD_DEC_USE_COUNT;
1071
        return 0;
1072
}
1073
 
1074
/*
1075
 *  Resource manager.
1076
 */
1077
 
1078
static struct isapnp_port *isapnp_find_port(struct pci_dev *dev, int index)
1079
{
1080
        struct isapnp_resources *res;
1081
        struct isapnp_port *port;
1082
 
1083
        if (!dev || index < 0 || index > 7)
1084
                return NULL;
1085
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1086
                for (port = res->port; port; port = port->next) {
1087
                        if (!index)
1088
                                return port;
1089
                        index--;
1090
                }
1091
        }
1092
        return NULL;
1093
}
1094
 
1095
struct isapnp_irq *isapnp_find_irq(struct pci_dev *dev, int index)
1096
{
1097
        struct isapnp_resources *res, *resa;
1098
        struct isapnp_irq *irq;
1099
        int index1, index2, index3;
1100
 
1101
        if (!dev || index < 0 || index > 7)
1102
                return NULL;
1103
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1104
                index3 = 0;
1105
                for (resa = res; resa; resa = resa->alt) {
1106
                        index1 = index;
1107
                        index2 = 0;
1108
                        for (irq = resa->irq; irq; irq = irq->next) {
1109
                                if (!index1)
1110
                                        return irq;
1111
                                index1--;
1112
                                index2++;
1113
                        }
1114
                        if (index3 < index2)
1115
                                index3 = index2;
1116
                }
1117
                index -= index3;
1118
        }
1119
        return NULL;
1120
}
1121
 
1122
struct isapnp_dma *isapnp_find_dma(struct pci_dev *dev, int index)
1123
{
1124
        struct isapnp_resources *res;
1125
        struct isapnp_dma *dma;
1126
 
1127
        if (!dev || index < 0 || index > 7)
1128
                return NULL;
1129
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1130
                for (dma = res->dma; dma; dma = dma->next) {
1131
                        if (!index)
1132
                                return dma;
1133
                        index--;
1134
                }
1135
        }
1136
        return NULL;
1137
}
1138
 
1139
struct isapnp_mem *isapnp_find_mem(struct pci_dev *dev, int index)
1140
{
1141
        struct isapnp_resources *res;
1142
        struct isapnp_mem *mem;
1143
 
1144
        if (!dev || index < 0 || index > 7)
1145
                return NULL;
1146
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1147
                for (mem = res->mem; mem; mem = mem->next) {
1148
                        if (!index)
1149
                                return mem;
1150
                        index--;
1151
                }
1152
        }
1153
        return NULL;
1154
}
1155
 
1156
struct isapnp_mem32 *isapnp_find_mem32(struct pci_dev *dev, int index)
1157
{
1158
        struct isapnp_resources *res;
1159
        struct isapnp_mem32 *mem32;
1160
 
1161
        if (!dev || index < 0 || index > 7)
1162
                return NULL;
1163
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1164
                for (mem32 = res->mem32; mem32; mem32 = mem32->next) {
1165
                        if (!index)
1166
                                return mem32;
1167
                        index--;
1168
                }
1169
        }
1170
        return NULL;
1171
}
1172
 
1173
/*
1174
 *  Device manager.
1175
 */
1176
 
1177
struct pci_bus *isapnp_find_card(unsigned short vendor,
1178
                                 unsigned short device,
1179
                                 struct pci_bus *from)
1180
{
1181
        struct list_head *list;
1182
 
1183
        list = isapnp_cards.next;
1184
        if (from)
1185
                list = from->node.next;
1186
 
1187
        while (list != &isapnp_cards) {
1188
                struct pci_bus *card = pci_bus_b(list);
1189
                if (card->vendor == vendor && card->device == device)
1190
                        return card;
1191
                list = list->next;
1192
        }
1193
        return NULL;
1194
}
1195
 
1196
struct pci_dev *isapnp_find_dev(struct pci_bus *card,
1197
                                unsigned short vendor,
1198
                                unsigned short function,
1199
                                struct pci_dev *from)
1200
{
1201
        if (card == NULL) {     /* look for a logical device from all cards */
1202
                struct list_head *list;
1203
 
1204
                list = isapnp_devices.next;
1205
                if (from)
1206
                        list = from->global_list.next;
1207
 
1208
                while (list != &isapnp_devices) {
1209
                        int idx;
1210
                        struct pci_dev *dev = pci_dev_g(list);
1211
 
1212
                        if (dev->vendor == vendor && dev->device == function)
1213
                                return dev;
1214
                        for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
1215
                                if (dev->vendor_compatible[idx] == vendor &&
1216
                                    dev->device_compatible[idx] == function)
1217
                                        return dev;
1218
                        list = list->next;
1219
                }
1220
        } else {
1221
                struct list_head *list;
1222
 
1223
                list = card->devices.next;
1224
                if (from) {
1225
                        list = from->bus_list.next;
1226
                        if (from->bus != card)  /* something is wrong */
1227
                                return NULL;
1228
                }
1229
                while (list != &card->devices) {
1230
                        int idx;
1231
                        struct pci_dev *dev = pci_dev_b(list);
1232
 
1233
                        if (dev->vendor == vendor && dev->device == function)
1234
                                return dev;
1235
                        for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
1236
                                if (dev->vendor_compatible[idx] == vendor &&
1237
                                    dev->device_compatible[idx] == function)
1238
                                        return dev;
1239
                        list = list->next;
1240
                }
1241
        }
1242
        return NULL;
1243
}
1244
 
1245
static const struct isapnp_card_id *
1246
isapnp_match_card(const struct isapnp_card_id *ids, struct pci_bus *card)
1247
{
1248
        int idx;
1249
 
1250
        while (ids->card_vendor || ids->card_device) {
1251
                if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == card->vendor) &&
1252
                    (ids->card_device == ISAPNP_ANY_ID || ids->card_device == card->device)) {
1253
                        for (idx = 0; idx < ISAPNP_CARD_DEVS; idx++) {
1254
                                if (ids->devs[idx].vendor == 0 &&
1255
                                    ids->devs[idx].function == 0)
1256
                                        return ids;
1257
                                if (isapnp_find_dev(card,
1258
                                                    ids->devs[idx].vendor,
1259
                                                    ids->devs[idx].function,
1260
                                                    NULL) == NULL)
1261
                                        goto __next;
1262
                        }
1263
                        return ids;
1264
                }
1265
              __next:
1266
                ids++;
1267
        }
1268
        return NULL;
1269
}
1270
 
1271
int isapnp_probe_cards(const struct isapnp_card_id *ids,
1272
                       int (*probe)(struct pci_bus *_card,
1273
                                    const struct isapnp_card_id *_id))
1274
{
1275
        struct pci_bus *card;
1276
        const struct isapnp_card_id *id;
1277
        int count = 0;
1278
 
1279
        if (ids == NULL || probe == NULL)
1280
                return -EINVAL;
1281
        isapnp_for_each_card(card) {
1282
                id = isapnp_match_card(ids, card);
1283
                if (id != NULL && probe(card, id) >= 0)
1284
                        count++;
1285
        }
1286
        return count;
1287
}
1288
 
1289
static const struct isapnp_device_id *
1290
isapnp_match_dev(const struct isapnp_device_id *ids, struct pci_dev *dev)
1291
{
1292
        while (ids->card_vendor || ids->card_device) {
1293
                if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == dev->bus->vendor) &&
1294
                    (ids->card_device == ISAPNP_ANY_ID || ids->card_device == dev->bus->device) &&
1295
                    (ids->vendor == ISAPNP_ANY_ID || ids->vendor == dev->vendor) &&
1296
                    (ids->function == ISAPNP_ANY_ID || ids->function == dev->device))
1297
                        return ids;
1298
                ids++;
1299
        }
1300
        return NULL;
1301
}
1302
 
1303
int isapnp_probe_devs(const struct isapnp_device_id *ids,
1304
                      int (*probe)(struct pci_dev *dev,
1305
                                   const struct isapnp_device_id *id))
1306
{
1307
 
1308
        struct pci_dev *dev;
1309
        const struct isapnp_device_id *id;
1310
        int count = 0;
1311
 
1312
        if (ids == NULL || probe == NULL)
1313
                return -EINVAL;
1314
        isapnp_for_each_dev(dev) {
1315
                id = isapnp_match_dev(ids, dev);
1316
                if (id != NULL && probe(dev, id) >= 0)
1317
                        count++;
1318
        }
1319
        return count;
1320
}
1321
 
1322
int isapnp_activate_dev(struct pci_dev *dev, const char *name)
1323
{
1324
        int err;
1325
 
1326
        /* Device already active? Let's use it and inform the caller */
1327
        if (dev->active)
1328
                return -EBUSY;
1329
 
1330
        if ((err = dev->activate(dev)) < 0) {
1331
                printk(KERN_ERR "isapnp: config of %s failed (out of resources?)[%d]\n", name, err);
1332
                dev->deactivate(dev);
1333
                return err;
1334
        }
1335
 
1336
        return 0;
1337
}
1338
 
1339
static unsigned int isapnp_dma_resource_flags(struct isapnp_dma *dma)
1340
{
1341
        return dma->flags | IORESOURCE_DMA | IORESOURCE_AUTO;
1342
}
1343
 
1344
static unsigned int isapnp_mem_resource_flags(struct isapnp_mem *mem)
1345
{
1346
        unsigned int result;
1347
 
1348
        result = mem->flags | IORESOURCE_MEM | IORESOURCE_AUTO;
1349
        if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
1350
                result |= IORESOURCE_READONLY;
1351
        if (mem->flags & IORESOURCE_MEM_CACHEABLE)
1352
                result |= IORESOURCE_CACHEABLE;
1353
        if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
1354
                result |= IORESOURCE_RANGELENGTH;
1355
        if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
1356
                result |= IORESOURCE_SHADOWABLE;
1357
        return result;
1358
}
1359
 
1360
static unsigned int isapnp_irq_resource_flags(struct isapnp_irq *irq)
1361
{
1362
        return irq->flags | IORESOURCE_IRQ | IORESOURCE_AUTO;
1363
}
1364
 
1365
static unsigned int isapnp_port_resource_flags(struct isapnp_port *port)
1366
{
1367
        return port->flags | IORESOURCE_IO | IORESOURCE_AUTO;
1368
}
1369
 
1370
static int isapnp_config_prepare(struct pci_dev *dev)
1371
{
1372
        struct isapnp_resources *res, *resa;
1373
        struct isapnp_port *port;
1374
        struct isapnp_irq *irq;
1375
        struct isapnp_dma *dma;
1376
        struct isapnp_mem *mem;
1377
        int port_count, port_count1;
1378
        int irq_count, irq_count1;
1379
        int dma_count, dma_count1;
1380
        int mem_count, mem_count1;
1381
        int idx;
1382
 
1383
        if (dev == NULL)
1384
                return -EINVAL;
1385
        if (dev->active || dev->ro)
1386
                return -EBUSY;
1387
        for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
1388
                dev->irq_resource[idx].name = NULL;
1389
                dev->irq_resource[idx].start = 0;
1390
                dev->irq_resource[idx].end = 0;
1391
                dev->irq_resource[idx].flags = 0;
1392
        }
1393
        for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
1394
                dev->dma_resource[idx].name = NULL;
1395
                dev->dma_resource[idx].start = 0;
1396
                dev->dma_resource[idx].end = 0;
1397
                dev->dma_resource[idx].flags = 0;
1398
        }
1399
        for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
1400
                dev->resource[idx].name = NULL;
1401
                dev->resource[idx].start = 0;
1402
                dev->resource[idx].end = 0;
1403
                dev->resource[idx].flags = 0;
1404
        }
1405
        port_count = irq_count = dma_count = mem_count = 0;
1406
        for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1407
                port_count1 = irq_count1 = dma_count1 = mem_count1 = 0;
1408
                for (resa = res; resa; resa = resa->alt) {
1409
                        for (port = resa->port, idx = 0; port; port = port->next, idx++) {
1410
                                if (dev->resource[port_count + idx].flags == 0) {
1411
                                        dev->resource[port_count + idx].flags = isapnp_port_resource_flags(port);
1412
                                        dev->resource[port_count + idx].end = port->size;
1413
                                }
1414
                        }
1415
                        if (port_count1 < idx)
1416
                                port_count1 = idx;
1417
                        for (irq = resa->irq, idx = 0; irq; irq = irq->next, idx++) {
1418
                                int count = irq_count + idx;
1419
                                if (count < DEVICE_COUNT_IRQ) {
1420
                                        if (dev->irq_resource[count].flags == 0) {
1421
                                                dev->irq_resource[count].flags = isapnp_irq_resource_flags(irq);
1422
                                        }
1423
                                }
1424
 
1425
                        }
1426
                        if (irq_count1 < idx)
1427
                                irq_count1 = idx;
1428
                        for (dma = resa->dma, idx = 0; dma; dma = dma->next, idx++)
1429
                                if (dev->dma_resource[idx].flags == 0) {
1430
                                        dev->dma_resource[idx].flags = isapnp_dma_resource_flags(dma);
1431
                                }
1432
                        if (dma_count1 < idx)
1433
                                dma_count1 = idx;
1434
                        for (mem = resa->mem, idx = 0; mem; mem = mem->next, idx++)
1435
                                if (dev->resource[mem_count + idx + 8].flags == 0) {
1436
                                        dev->resource[mem_count + idx + 8].flags = isapnp_mem_resource_flags(mem);
1437
                                }
1438
                        if (mem_count1 < idx)
1439
                                mem_count1 = idx;
1440
                }
1441
                port_count += port_count1;
1442
                irq_count += irq_count1;
1443
                dma_count += dma_count1;
1444
                mem_count += mem_count1;
1445
        }
1446
        return 0;
1447
}
1448
 
1449
struct isapnp_cfgtmp {
1450
        struct isapnp_port *port[8];
1451
        struct isapnp_irq *irq[2];
1452
        struct isapnp_dma *dma[2];
1453
        struct isapnp_mem *mem[4];
1454
        struct pci_dev *request;
1455
        struct pci_dev result;
1456
};
1457
 
1458
static int isapnp_alternative_switch(struct isapnp_cfgtmp *cfg,
1459
                                     struct isapnp_resources *from,
1460
                                     struct isapnp_resources *to)
1461
{
1462
        int tmp, tmp1;
1463
        struct isapnp_port *port;
1464
        struct isapnp_irq *irq;
1465
        struct isapnp_dma *dma;
1466
        struct isapnp_mem *mem;
1467
 
1468
        if (!cfg)
1469
                return -EINVAL;
1470
        /* process port settings */
1471
        for (tmp = 0; tmp < 8; tmp++) {
1472
                if (!(cfg->request->resource[tmp].flags & IORESOURCE_AUTO))
1473
                        continue;               /* don't touch */
1474
                port = cfg->port[tmp];
1475
                if (!port) {
1476
                        cfg->port[tmp] = port = isapnp_find_port(cfg->request, tmp);
1477
                        if (!port)
1478
                                return -EINVAL;
1479
                }
1480
                if (from && port->res == from) {
1481
                        while (port->res != to) {
1482
                                if (!port->res->alt)
1483
                                        return -EINVAL;
1484
                                port = port->res->alt->port;
1485
                                for (tmp1 = tmp; tmp1 > 0 && port; tmp1--)
1486
                                        port = port->next;
1487
                                cfg->port[tmp] = port;
1488
                                if (!port)
1489
                                        return -ENOENT;
1490
                                cfg->result.resource[tmp].flags = isapnp_port_resource_flags(port);
1491
                        }
1492
                }
1493
        }
1494
        /* process irq settings */
1495
        for (tmp = 0; tmp < 2; tmp++) {
1496
                if (!(cfg->request->irq_resource[tmp].flags & IORESOURCE_AUTO))
1497
                        continue;               /* don't touch */
1498
                irq = cfg->irq[tmp];
1499
                if (!irq) {
1500
                        cfg->irq[tmp] = irq = isapnp_find_irq(cfg->request, tmp);
1501
                        if (!irq)
1502
                                return -EINVAL;
1503
                }
1504
                if (from && irq->res == from) {
1505
                        while (irq->res != to) {
1506
                                if (!irq->res->alt)
1507
                                        return -EINVAL;
1508
                                irq = irq->res->alt->irq;
1509
                                for (tmp1 = tmp; tmp1 > 0 && irq; tmp1--)
1510
                                        irq = irq->next;
1511
                                cfg->irq[tmp] = irq;
1512
                                if (!irq)
1513
                                        return -ENOENT;
1514
                                cfg->result.irq_resource[tmp].flags = isapnp_irq_resource_flags(irq);
1515
                        }
1516
                }
1517
        }
1518
        /* process dma settings */
1519
        for (tmp = 0; tmp < 2; tmp++) {
1520
                if (!(cfg->request->dma_resource[tmp].flags & IORESOURCE_AUTO))
1521
                        continue;               /* don't touch */
1522
                dma = cfg->dma[tmp];
1523
                if (!dma) {
1524
                        cfg->dma[tmp] = dma = isapnp_find_dma(cfg->request, tmp);
1525
                        if (!dma)
1526
                                return -EINVAL;
1527
                }
1528
                if (from && dma->res == from) {
1529
                        while (dma->res != to) {
1530
                                if (!dma->res->alt)
1531
                                        return -EINVAL;
1532
                                dma = dma->res->alt->dma;
1533
                                for (tmp1 = tmp; tmp1 > 0 && dma; tmp1--)
1534
                                        dma = dma->next;
1535
                                cfg->dma[tmp] = dma;
1536
                                if (!dma)
1537
                                        return -ENOENT;
1538
                                cfg->result.dma_resource[tmp].flags = isapnp_dma_resource_flags(dma);
1539
                        }
1540
                }
1541
        }
1542
        /* process memory settings */
1543
        for (tmp = 0; tmp < 4; tmp++) {
1544
                if (!(cfg->request->resource[tmp + 8].flags & IORESOURCE_AUTO))
1545
                        continue;               /* don't touch */
1546
                mem = cfg->mem[tmp];
1547
                if (!mem) {
1548
                        cfg->mem[tmp] = mem = isapnp_find_mem(cfg->request, tmp);
1549
                        if (!mem)
1550
                                return -EINVAL;
1551
                }
1552
                if (from && mem->res == from) {
1553
                        while (mem->res != to) {
1554
                                if (!mem->res->alt)
1555
                                        return -EINVAL;
1556
                                mem = mem->res->alt->mem;
1557
                                for (tmp1 = tmp; tmp1 > 0 && mem; tmp1--)
1558
                                        mem = mem->next;
1559
                                cfg->mem[tmp] = mem;
1560
                                if (!mem)
1561
                                        return -ENOENT;
1562
                                cfg->result.resource[tmp + 8].flags = isapnp_mem_resource_flags(mem);
1563
                        }
1564
                }
1565
        }
1566
        return 0;
1567
}
1568
 
1569
static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int idx)
1570
{
1571
        int i, tmp, rport, rsize;
1572
        struct isapnp_port *xport;
1573
        struct pci_dev *dev;
1574
 
1575
        if (check_region(port, size))
1576
                return 1;
1577
        for (i = 0; i < 8; i++) {
1578
                rport = isapnp_reserve_io[i << 1];
1579
                rsize = isapnp_reserve_io[(i << 1) + 1];
1580
                if (port >= rport && port < rport + rsize)
1581
                        return 1;
1582
                if (port + size > rport && port + size < (rport + rsize) - 1)
1583
                        return 1;
1584
        }
1585
 
1586
        isapnp_for_each_dev(dev) {
1587
                if (dev->active) {
1588
                        for (tmp = 0; tmp < 8; tmp++) {
1589
                                if (dev->resource[tmp].flags) {
1590
                                        rport = dev->resource[tmp].start;
1591
                                        rsize = (dev->resource[tmp].end - rport) + 1;
1592
                                        if (port >= rport && port < rport + rsize)
1593
                                                return 1;
1594
                                        if (port + size > rport && port + size < (rport + rsize) - 1)
1595
                                                return 1;
1596
                                }
1597
                        }
1598
                }
1599
        }
1600
        for (i = 0; i < 8; i++) {
1601
                unsigned int flags;
1602
                if (i == idx)
1603
                        continue;
1604
                flags = cfg->request->resource[i].flags;
1605
                if (!flags)
1606
                        continue;
1607
                tmp = cfg->request->resource[i].start;
1608
                if (flags & IORESOURCE_AUTO) {          /* auto */
1609
                        xport = cfg->port[i];
1610
                        if (!xport)
1611
                                return 1;
1612
                        if (cfg->result.resource[i].flags & IORESOURCE_AUTO)
1613
                                continue;
1614
                        tmp = cfg->result.resource[i].start;
1615
                        if (tmp + xport->size >= port && tmp <= port + xport->size)
1616
                                return 1;
1617
                        continue;
1618
                }
1619
                if (port == tmp)
1620
                        return 1;
1621
                xport = isapnp_find_port(cfg->request, i);
1622
                if (!xport)
1623
                        return 1;
1624
                if (tmp + xport->size >= port && tmp <= port + xport->size)
1625
                        return 1;
1626
        }
1627
        return 0;
1628
}
1629
 
1630
static int isapnp_valid_port(struct isapnp_cfgtmp *cfg, int idx)
1631
{
1632
        int err;
1633
        unsigned long *value1, *value2;
1634
        struct isapnp_port *port;
1635
 
1636
        if (!cfg || idx < 0 || idx > 7)
1637
                return -EINVAL;
1638
        if (!(cfg->result.resource[idx].flags & IORESOURCE_AUTO)) /* don't touch */
1639
                return 0;
1640
      __again:
1641
        port = cfg->port[idx];
1642
        if (!port)
1643
                return -EINVAL;
1644
        value1 = &cfg->result.resource[idx].start;
1645
        value2 = &cfg->result.resource[idx].end;
1646
        if (cfg->result.resource[idx].flags & IORESOURCE_AUTO) {
1647
                cfg->result.resource[idx].flags &= ~IORESOURCE_AUTO;
1648
                *value1 = port->min;
1649
                *value2 = port->min + port->size - 1;
1650
                if (!isapnp_check_port(cfg, *value1, port->size, idx))
1651
                        return 0;
1652
        }
1653
        do {
1654
                *value1 += port->align;
1655
                *value2 = *value1 + port->size - 1;
1656
                if (*value1 > port->max || !port->align) {
1657
                        if (port->res && port->res->alt) {
1658
                                if ((err = isapnp_alternative_switch(cfg, port->res, port->res->alt))<0)
1659
                                        return err;
1660
                                goto __again;
1661
                        }
1662
                        return -ENOENT;
1663
                }
1664
        } while (isapnp_check_port(cfg, *value1, port->size, idx));
1665
        return 0;
1666
}
1667
 
1668
static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
1669
{
1670
}
1671
 
1672
static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
1673
{
1674
        int i;
1675
        struct pci_dev *dev;
1676
 
1677
        if (irq < 0 || irq > 15)
1678
                return 1;
1679
        for (i = 0; i < 16; i++) {
1680
                if (isapnp_reserve_irq[i] == irq)
1681
                        return 1;
1682
        }
1683
        isapnp_for_each_dev(dev) {
1684
                if (dev->active) {
1685
                        if ((dev->irq_resource[0].flags && dev->irq_resource[0].start == irq) ||
1686
                            (dev->irq_resource[1].flags && dev->irq_resource[1].start == irq))
1687
                                return 1;
1688
                }
1689
        }
1690
#ifdef CONFIG_PCI
1691
        if (!isapnp_skip_pci_scan) {
1692
                pci_for_each_dev(dev) {
1693
                        if (dev->irq == irq)
1694
                                return 1;
1695
                }
1696
        }
1697
#endif
1698
        if (request_irq(irq, isapnp_test_handler, SA_INTERRUPT, "isapnp", NULL))
1699
                return 1;
1700
        free_irq(irq, NULL);
1701
        for (i = 0; i < DEVICE_COUNT_IRQ; i++) {
1702
                if (i == idx)
1703
                        continue;
1704
                if (!cfg->result.irq_resource[i].flags)
1705
                        continue;
1706
                if (cfg->result.irq_resource[i].flags & IORESOURCE_AUTO)
1707
                        continue;
1708
                if (cfg->result.irq_resource[i].start == irq)
1709
                        return 1;
1710
        }
1711
        return 0;
1712
}
1713
 
1714
static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
1715
{
1716
        /* IRQ priority: this table is good for i386 */
1717
        static unsigned short xtab[16] = {
1718
                5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
1719
        };
1720
        int err, i;
1721
        unsigned long *value1, *value2;
1722
        struct isapnp_irq *irq;
1723
 
1724
        if (!cfg || idx < 0 || idx > 1)
1725
                return -EINVAL;
1726
        if (!(cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO))
1727
                return 0;
1728
      __again:
1729
        irq = cfg->irq[idx];
1730
        if (!irq)
1731
                return -EINVAL;
1732
        value1 = &cfg->result.irq_resource[idx].start;
1733
        value2 = &cfg->result.irq_resource[idx].end;
1734
        if (cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO) {
1735
                for (i = 0; i < 16 && !(irq->map & (1<<xtab[i])); i++);
1736
                if (i >= 16)
1737
                        return -ENOENT;
1738
                cfg->result.irq_resource[idx].flags &= ~IORESOURCE_AUTO;
1739
                if (!isapnp_check_interrupt(cfg, *value1 = *value2 = xtab[i], idx))
1740
                        return 0;
1741
        }
1742
        do {
1743
                for (i = 0; i < 16 && xtab[i] != *value1; i++);
1744
                for (i++; i < 16 && !(irq->map & (1<<xtab[i])); i++);
1745
                if (i >= 16) {
1746
                        if (irq->res && irq->res->alt) {
1747
                                if ((err = isapnp_alternative_switch(cfg, irq->res, irq->res->alt))<0)
1748
                                        return err;
1749
                                goto __again;
1750
                        }
1751
                        return -ENOENT;
1752
                } else {
1753
                        *value1 = *value2 = xtab[i];
1754
                }
1755
        } while (isapnp_check_interrupt(cfg, *value1, idx));
1756
        return 0;
1757
}
1758
 
1759
static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
1760
{
1761
        int i, mindma =1;
1762
        struct pci_dev *dev;
1763
 
1764
        /* Some machines allow DMA 0, but others don't. In fact on some
1765
           boxes DMA 0 is the memory refresh. Play safe */
1766
        if (isapnp_allow_dma0 == 1)
1767
                mindma = 0;
1768
        if (dma < mindma || dma == 4 || dma > 7)
1769
                return 1;
1770
        for (i = 0; i < 8; i++) {
1771
                if (isapnp_reserve_dma[i] == dma)
1772
                        return 1;
1773
        }
1774
        isapnp_for_each_dev(dev) {
1775
                if (dev->active) {
1776
                        if ((dev->dma_resource[0].flags && dev->dma_resource[0].start == dma) ||
1777
                            (dev->dma_resource[1].flags && dev->dma_resource[1].start == dma))
1778
                                return 1;
1779
                }
1780
        }
1781
        if (request_dma(dma, "isapnp"))
1782
                return 1;
1783
        free_dma(dma);
1784
        for (i = 0; i < 2; i++) {
1785
                if (i == idx)
1786
                        continue;
1787
                if (!cfg->result.dma_resource[i].flags ||
1788
                    (cfg->result.dma_resource[i].flags & IORESOURCE_AUTO))
1789
                        continue;
1790
                if (cfg->result.dma_resource[i].start == dma)
1791
                        return 1;
1792
        }
1793
        return 0;
1794
}
1795
 
1796
static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx)
1797
{
1798
        /* DMA priority: this table is good for i386 */
1799
        static unsigned short xtab[16] = {
1800
                1, 3, 5, 6, 7, 0, 2, 4
1801
        };
1802
        int err, i;
1803
        unsigned long *value1, *value2;
1804
        struct isapnp_dma *dma;
1805
 
1806
        if (!cfg || idx < 0 || idx > 1)
1807
                return -EINVAL;
1808
        if (!(cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO))   /* don't touch */
1809
                return 0;
1810
      __again:
1811
        dma = cfg->dma[idx];
1812
        if (!dma)
1813
                return -EINVAL;
1814
        value1 = &cfg->result.dma_resource[idx].start;
1815
        value2 = &cfg->result.dma_resource[idx].end;
1816
        if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) {
1817
                for (i = 0; i < 8 && !(dma->map & (1<<xtab[i])); i++);
1818
                if (i >= 8)
1819
                        return -ENOENT;
1820
                cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO;
1821
                if (!isapnp_check_dma(cfg, *value1 = *value2 = xtab[i], idx))
1822
                        return 0;
1823
        }
1824
        do {
1825
                for (i = 0; i < 8 && xtab[i] != *value1; i++);
1826
                for (i++; i < 8 && !(dma->map & (1<<xtab[i])); i++);
1827
                if (i >= 8) {
1828
                        if (dma->res && dma->res->alt) {
1829
                                if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)
1830
                                        return err;
1831
                                goto __again;
1832
                        }
1833
                        return -ENOENT;
1834
                } else {
1835
                        *value1 = *value2 = xtab[i];
1836
                }
1837
        } while (isapnp_check_dma(cfg, *value1, idx));
1838
        return 0;
1839
}
1840
 
1841
static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx)
1842
{
1843
        int i, tmp;
1844
        unsigned int raddr, rsize;
1845
        struct isapnp_mem *xmem;
1846
        struct pci_dev *dev;
1847
 
1848
        for (i = 0; i < 8; i++) {
1849
                raddr = (unsigned int)isapnp_reserve_mem[i << 1];
1850
                rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1];
1851
                if (addr >= raddr && addr < raddr + rsize)
1852
                        return 1;
1853
                if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
1854
                        return 1;
1855
                if (__check_region(&iomem_resource, addr, size))
1856
                        return 1;
1857
        }
1858
        isapnp_for_each_dev(dev) {
1859
                if (dev->active) {
1860
                        for (tmp = 0; tmp < 4; tmp++) {
1861
                                if (dev->resource[tmp].flags) {
1862
                                        raddr = dev->resource[tmp + 8].start;
1863
                                        rsize = (dev->resource[tmp + 8].end - raddr) + 1;
1864
                                        if (addr >= raddr && addr < raddr + rsize)
1865
                                                return 1;
1866
                                        if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
1867
                                                return 1;
1868
                                }
1869
                        }
1870
                }
1871
        }
1872
        for (i = 0; i < 4; i++) {
1873
                unsigned int flags = cfg->request->resource[i + 8].flags;
1874
                if (i == idx)
1875
                        continue;
1876
                if (!flags)
1877
                        continue;
1878
                tmp = cfg->result.resource[i + 8].start;
1879
                if (flags & IORESOURCE_AUTO) {          /* auto */
1880
                        xmem = cfg->mem[i];
1881
                        if (!xmem)
1882
                                return 1;
1883
                        if (cfg->result.resource[i + 8].flags & IORESOURCE_AUTO)
1884
                                continue;
1885
                        if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
1886
                                return 1;
1887
                        continue;
1888
                }
1889
                if (addr == tmp)
1890
                        return 1;
1891
                xmem = isapnp_find_mem(cfg->request, i);
1892
                if (!xmem)
1893
                        return 1;
1894
                if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
1895
                        return 1;
1896
        }
1897
        return 0;
1898
}
1899
 
1900
static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx)
1901
{
1902
        int err;
1903
        unsigned long *value1, *value2;
1904
        struct isapnp_mem *mem;
1905
 
1906
        if (!cfg || idx < 0 || idx > 3)
1907
                return -EINVAL;
1908
        if (!(cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO)) /* don't touch */
1909
                return 0;
1910
      __again:
1911
        mem = cfg->mem[idx];
1912
        if (!mem)
1913
                return -EINVAL;
1914
        value1 = &cfg->result.resource[idx + 8].start;
1915
        value2 = &cfg->result.resource[idx + 8].end;
1916
        if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) {
1917
                cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO;
1918
                *value1 = mem->min;
1919
                *value2 = mem->min + mem->size - 1;
1920
                if (!isapnp_check_mem(cfg, *value1, mem->size, idx))
1921
                        return 0;
1922
        }
1923
        do {
1924
                *value1 += mem->align;
1925
                *value2 = *value1 + mem->size - 1;
1926
                if (*value1 > mem->max || !mem->align) {
1927
                        if (mem->res && mem->res->alt) {
1928
                                if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)
1929
                                        return err;
1930
                                goto __again;
1931
                        }
1932
                        return -ENOENT;
1933
                }
1934
        } while (isapnp_check_mem(cfg, *value1, mem->size, idx));
1935
        return 0;
1936
}
1937
 
1938
static int isapnp_check_valid(struct isapnp_cfgtmp *cfg)
1939
{
1940
        int tmp;
1941
 
1942
        for (tmp = 0; tmp < 8; tmp++)
1943
                if (cfg->result.resource[tmp].flags & IORESOURCE_AUTO)
1944
                        return -EAGAIN;
1945
        for (tmp = 0; tmp < 2; tmp++)
1946
                if (cfg->result.irq_resource[tmp].flags & IORESOURCE_AUTO)
1947
                        return -EAGAIN;
1948
        for (tmp = 0; tmp < 2; tmp++)
1949
                if (cfg->result.dma_resource[tmp].flags & IORESOURCE_AUTO)
1950
                        return -EAGAIN;
1951
        for (tmp = 0; tmp < 4; tmp++)
1952
                if (cfg->result.resource[tmp + 8].flags & IORESOURCE_AUTO)
1953
                        return -EAGAIN;
1954
        return 0;
1955
}
1956
 
1957
static int isapnp_config_activate(struct pci_dev *dev)
1958
{
1959
        struct isapnp_cfgtmp cfg;
1960
        int tmp, fauto, err;
1961
 
1962
        if (!dev)
1963
                return -EINVAL;
1964
        if (dev->active)
1965
                return -EBUSY;
1966
        memset(&cfg, 0, sizeof(cfg));
1967
        cfg.request = dev;
1968
        memcpy(&cfg.result, dev, sizeof(struct pci_dev));
1969
        /* check if all values are set, otherwise try auto-configuration */
1970
        for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) {
1971
                if (dev->resource[tmp].flags & IORESOURCE_AUTO)
1972
                        fauto++;
1973
        }
1974
        for (tmp = 0; !fauto && tmp < 2; tmp++) {
1975
                if (dev->irq_resource[tmp].flags & IORESOURCE_AUTO)
1976
                        fauto++;
1977
        }
1978
        for (tmp = 0; !fauto && tmp < 2; tmp++) {
1979
                if (dev->dma_resource[tmp].flags & IORESOURCE_AUTO)
1980
                        fauto++;
1981
        }
1982
        for (tmp = 0; !fauto && tmp < 4; tmp++) {
1983
                if (dev->resource[tmp + 8].flags & IORESOURCE_AUTO)
1984
                        fauto++;
1985
        }
1986
        if (!fauto)
1987
                goto __skip_auto;
1988
        /* set variables to initial values */
1989
        if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0)
1990
                return err;
1991
        /* find first valid configuration */
1992
        fauto = 0;
1993
        do {
1994
                for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].flags; tmp++)
1995
                        if ((err = isapnp_valid_port(&cfg, tmp))<0)
1996
                                return err;
1997
                for (tmp = 0; tmp < 2 && cfg.result.irq_resource[tmp].flags; tmp++)
1998
                        if ((err = isapnp_valid_irq(&cfg, tmp))<0)
1999
                                return err;
2000
                for (tmp = 0; tmp < 2 && cfg.result.dma_resource[tmp].flags; tmp++)
2001
                        if ((err = isapnp_valid_dma(&cfg, tmp))<0)
2002
                                return err;
2003
                for (tmp = 0; tmp < 4 && cfg.result.resource[tmp + 8].flags; tmp++)
2004
                        if ((err = isapnp_valid_mem(&cfg, tmp))<0)
2005
                                return err;
2006
        } while (isapnp_check_valid(&cfg)<0 && fauto++ < 20);
2007
        if (fauto >= 20)
2008
                return -EAGAIN;
2009
      __skip_auto:
2010
        /* we have valid configuration, try configure hardware */
2011
        isapnp_cfg_begin(dev->bus->number, dev->devfn);
2012
        dev->active = 1;
2013
        dev->irq_resource[0] = cfg.result.irq_resource[0];
2014
        dev->irq_resource[1] = cfg.result.irq_resource[1];
2015
        dev->dma_resource[0] = cfg.result.dma_resource[0];
2016
        dev->dma_resource[1] = cfg.result.dma_resource[1];
2017
        for (tmp = 0; tmp < 12; tmp++) {
2018
                dev->resource[tmp] = cfg.result.resource[tmp];
2019
        }
2020
        for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++)
2021
                isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);
2022
        for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) {
2023
                int irq = dev->irq_resource[tmp].start;
2024
                if (irq == 2)
2025
                        irq = 9;
2026
                isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
2027
        }
2028
        for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++)
2029
                isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start);
2030
        for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++)
2031
                isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);
2032
        isapnp_activate(dev->devfn);
2033
        isapnp_cfg_end();
2034
        return 0;
2035
}
2036
 
2037
static int isapnp_config_deactivate(struct pci_dev *dev)
2038
{
2039
        if (!dev || !dev->active)
2040
                return -EINVAL;
2041
        isapnp_cfg_begin(dev->bus->number, dev->devfn);
2042
        isapnp_deactivate(dev->devfn);
2043
        dev->active = 0;
2044
        isapnp_cfg_end();
2045
        return 0;
2046
}
2047
 
2048
void isapnp_resource_change(struct resource *resource,
2049
                            unsigned long start,
2050
                            unsigned long size)
2051
{
2052
        if (resource == NULL)
2053
                return;
2054
        resource->flags &= ~IORESOURCE_AUTO;
2055
        resource->start = start;
2056
        resource->end = start + size - 1;
2057
}
2058
 
2059
/*
2060
 *  Inititialization.
2061
 */
2062
 
2063
#ifdef MODULE
2064
 
2065
static void isapnp_free_port(struct isapnp_port *port)
2066
{
2067
        struct isapnp_port *next;
2068
 
2069
        while (port) {
2070
                next = port->next;
2071
                kfree(port);
2072
                port = next;
2073
        }
2074
}
2075
 
2076
static void isapnp_free_irq(struct isapnp_irq *irq)
2077
{
2078
        struct isapnp_irq *next;
2079
 
2080
        while (irq) {
2081
                next = irq->next;
2082
                kfree(irq);
2083
                irq = next;
2084
        }
2085
}
2086
 
2087
static void isapnp_free_dma(struct isapnp_dma *dma)
2088
{
2089
        struct isapnp_dma *next;
2090
 
2091
        while (dma) {
2092
                next = dma->next;
2093
                kfree(dma);
2094
                dma = next;
2095
        }
2096
}
2097
 
2098
static void isapnp_free_mem(struct isapnp_mem *mem)
2099
{
2100
        struct isapnp_mem *next;
2101
 
2102
        while (mem) {
2103
                next = mem->next;
2104
                kfree(mem);
2105
                mem = next;
2106
        }
2107
}
2108
 
2109
static void isapnp_free_mem32(struct isapnp_mem32 *mem32)
2110
{
2111
        struct isapnp_mem32 *next;
2112
 
2113
        while (mem32) {
2114
                next = mem32->next;
2115
                kfree(mem32);
2116
                mem32 = next;
2117
        }
2118
}
2119
 
2120
static void isapnp_free_resources(struct isapnp_resources *resources, int alt)
2121
{
2122
        struct isapnp_resources *next;
2123
 
2124
        while (resources) {
2125
                next = alt ? resources->alt : resources->next;
2126
                isapnp_free_port(resources->port);
2127
                isapnp_free_irq(resources->irq);
2128
                isapnp_free_dma(resources->dma);
2129
                isapnp_free_mem(resources->mem);
2130
                isapnp_free_mem32(resources->mem32);
2131
                if (!alt && resources->alt)
2132
                        isapnp_free_resources(resources->alt, 1);
2133
                kfree(resources);
2134
                resources = next;
2135
        }
2136
}
2137
 
2138
static void isapnp_free_card(struct pci_bus *card)
2139
{
2140
        while (!list_empty(&card->devices)) {
2141
                struct list_head *list = card->devices.next;
2142
                struct pci_dev *dev = pci_dev_b(list);
2143
                list_del(list);
2144
                isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);
2145
                kfree(dev);
2146
        }
2147
        kfree(card);
2148
}
2149
 
2150
static void isapnp_free_all_resources(void)
2151
{
2152
#ifdef ISAPNP_REGION_OK
2153
        release_region(_PIDXR, 1);
2154
#endif
2155
        release_region(_PNPWRP, 1);
2156
        release_region(isapnp_rdp, 1);
2157
#ifdef CONFIG_PROC_FS
2158
        isapnp_proc_done();
2159
#endif
2160
        while (!list_empty(&isapnp_cards)) {
2161
                struct list_head *list = isapnp_cards.next;
2162
                list_del(list);
2163
                isapnp_free_card(pci_bus_b(list));
2164
        }
2165
}
2166
 
2167
#endif /* MODULE */
2168
 
2169
static int isapnp_announce_device(struct isapnp_driver *drv,
2170
                                  struct pci_dev *dev)
2171
{
2172
        const struct isapnp_device_id *id;
2173
        int ret = 0;
2174
 
2175
        if (drv->id_table) {
2176
                id = isapnp_match_dev(drv->id_table, dev);
2177
                if (!id) {
2178
                        ret = 0;
2179
                        goto out;
2180
                }
2181
        } else
2182
                id = NULL;
2183
 
2184
        if (drv->probe(dev, id) >= 0) {
2185
                dev->driver = (struct pci_driver *) drv;
2186
                ret = 1;
2187
        }
2188
out:
2189
        return ret;
2190
}
2191
 
2192
/**
2193
 * isapnp_dev_driver - get the isapnp_driver of a device
2194
 * @dev: the device to query
2195
 *
2196
 * Returns the appropriate isapnp_driver structure or %NULL if there is no
2197
 * registered driver for the device.
2198
 */
2199
static struct isapnp_driver *isapnp_dev_driver(const struct pci_dev *dev)
2200
{
2201
        return (struct isapnp_driver *) dev->driver;
2202
}
2203
 
2204
static LIST_HEAD(isapnp_drivers);
2205
 
2206
/**
2207
 * isapnp_register_driver - register a new ISAPnP driver
2208
 * @drv: the driver structure to register
2209
 *
2210
 * Adds the driver structure to the list of registered ISAPnP drivers
2211
 * Returns the number of isapnp devices which were claimed by the driver
2212
 * during registration.  The driver remains registered even if the
2213
 * return value is zero.
2214
 */
2215
int isapnp_register_driver(struct isapnp_driver *drv)
2216
{
2217
        struct pci_dev *dev;
2218
        int count = 0;
2219
 
2220
        list_add_tail(&drv->node, &isapnp_drivers);
2221
 
2222
        isapnp_for_each_dev(dev) {
2223
                if (!isapnp_dev_driver(dev))
2224
                        count += isapnp_announce_device(drv, dev);
2225
        }
2226
        return count;
2227
}
2228
 
2229
/**
2230
 * isapnp_unregister_driver - unregister an isapnp driver
2231
 * @drv: the driver structure to unregister
2232
 *
2233
 * Deletes the driver structure from the list of registered ISAPnP drivers,
2234
 * gives it a chance to clean up by calling its remove() function for
2235
 * each device it was responsible for, and marks those devices as
2236
 * driverless.
2237
 */
2238
void isapnp_unregister_driver(struct isapnp_driver *drv)
2239
{
2240
        struct pci_dev *dev;
2241
 
2242
        list_del(&drv->node);
2243
        isapnp_for_each_dev(dev) {
2244
                if (dev->driver == (struct pci_driver *) drv) {
2245
                        if (drv->remove)
2246
                                drv->remove(dev);
2247
                        dev->driver = NULL;
2248
                }
2249
        }
2250
}
2251
 
2252
EXPORT_SYMBOL(isapnp_cards);
2253
EXPORT_SYMBOL(isapnp_devices);
2254
EXPORT_SYMBOL(isapnp_present);
2255
EXPORT_SYMBOL(isapnp_cfg_begin);
2256
EXPORT_SYMBOL(isapnp_cfg_end);
2257
EXPORT_SYMBOL(isapnp_read_byte);
2258
EXPORT_SYMBOL(isapnp_read_word);
2259
EXPORT_SYMBOL(isapnp_read_dword);
2260
EXPORT_SYMBOL(isapnp_write_byte);
2261
EXPORT_SYMBOL(isapnp_write_word);
2262
EXPORT_SYMBOL(isapnp_write_dword);
2263
EXPORT_SYMBOL(isapnp_wake);
2264
EXPORT_SYMBOL(isapnp_device);
2265
EXPORT_SYMBOL(isapnp_activate);
2266
EXPORT_SYMBOL(isapnp_deactivate);
2267
EXPORT_SYMBOL(isapnp_find_card);
2268
EXPORT_SYMBOL(isapnp_find_dev);
2269
EXPORT_SYMBOL(isapnp_probe_cards);
2270
EXPORT_SYMBOL(isapnp_probe_devs);
2271
EXPORT_SYMBOL(isapnp_activate_dev);
2272
EXPORT_SYMBOL(isapnp_resource_change);
2273
EXPORT_SYMBOL(isapnp_register_driver);
2274
EXPORT_SYMBOL(isapnp_unregister_driver);
2275
 
2276
int __init isapnp_init(void)
2277
{
2278
        int cards;
2279
        struct pci_bus *card;
2280
 
2281
        if (isapnp_disable) {
2282
                isapnp_detected = 0;
2283
                printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
2284
                return 0;
2285
        }
2286
#ifdef ISAPNP_REGION_OK
2287
        if (!request_region(_PIDXR, 1, "isapnp index")) {
2288
                printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);
2289
                return -EBUSY;
2290
        }
2291
#endif
2292
        if (!request_region(_PNPWRP, 1, "isapnp write")) {
2293
                printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
2294
#ifdef ISAPNP_REGION_OK
2295
                release_region(_PIDXR, 1);
2296
#endif
2297
                return -EBUSY;
2298
        }
2299
 
2300
        /*
2301
         *      Print a message. The existing ISAPnP code is hanging machines
2302
         *      so let the user know where.
2303
         */
2304
 
2305
        printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");
2306
        if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
2307
                isapnp_rdp |= 3;
2308
                if (!request_region(isapnp_rdp, 1, "isapnp read")) {
2309
                        printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
2310
#ifdef ISAPNP_REGION_OK
2311
                        release_region(_PIDXR, 1);
2312
#endif
2313
                        release_region(_PNPWRP, 1);
2314
                        return -EBUSY;
2315
                }
2316
                isapnp_set_rdp();
2317
        }
2318
        isapnp_detected = 1;
2319
        if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
2320
                cards = isapnp_isolate();
2321
                if (cards < 0 ||
2322
                    (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
2323
#ifdef ISAPNP_REGION_OK
2324
                        release_region(_PIDXR, 1);
2325
#endif
2326
                        release_region(_PNPWRP, 1);
2327
                        isapnp_detected = 0;
2328
                        printk(KERN_INFO "isapnp: No Plug & Play device found\n");
2329
                        return 0;
2330
                }
2331
                request_region(isapnp_rdp, 1, "isapnp read");
2332
        }
2333
        isapnp_build_device_list();
2334
        cards = 0;
2335
 
2336
        isapnp_for_each_card(card) {
2337
                cards++;
2338
                if (isapnp_verbose) {
2339
                        struct list_head *devlist;
2340
                        printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
2341
                        if (isapnp_verbose < 2)
2342
                                continue;
2343
                        for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
2344
                                struct pci_dev *dev = pci_dev_b(devlist);
2345
                                printk(KERN_INFO "isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
2346
                        }
2347
                }
2348
        }
2349
        if (cards) {
2350
                printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");
2351
        } else {
2352
                printk(KERN_INFO "isapnp: No Plug & Play card found\n");
2353
        }
2354
#ifdef CONFIG_PROC_FS
2355
        isapnp_proc_init();
2356
#endif
2357
        return 0;
2358
}
2359
 
2360
#ifdef MODULE
2361
 
2362
int init_module(void)
2363
{
2364
        return isapnp_init();
2365
}
2366
 
2367
void cleanup_module(void)
2368
{
2369
        if (isapnp_detected)
2370
                isapnp_free_all_resources();
2371
}
2372
 
2373
#else
2374
 
2375
/* format is: noisapnp */
2376
 
2377
static int __init isapnp_setup_disable(char *str)
2378
{
2379
        isapnp_disable = 1;
2380
        return 1;
2381
}
2382
 
2383
__setup("noisapnp", isapnp_setup_disable);
2384
 
2385
/* format is: isapnp=rdp,reset,skip_pci_scan,verbose */
2386
 
2387
static int __init isapnp_setup_isapnp(char *str)
2388
{
2389
        (void)((get_option(&str,&isapnp_rdp) == 2) &&
2390
               (get_option(&str,&isapnp_reset) == 2) &&
2391
               (get_option(&str,&isapnp_skip_pci_scan) == 2) &&
2392
               (get_option(&str,&isapnp_verbose) == 2));
2393
        return 1;
2394
}
2395
 
2396
__setup("isapnp=", isapnp_setup_isapnp);
2397
 
2398
/* format is: isapnp_reserve_irq=irq1[,irq2] .... */
2399
 
2400
static int __init isapnp_setup_reserve_irq(char *str)
2401
{
2402
        int i;
2403
 
2404
        for (i = 0; i < 16; i++)
2405
                if (get_option(&str,&isapnp_reserve_irq[i]) != 2)
2406
                        break;
2407
        return 1;
2408
}
2409
 
2410
__setup("isapnp_reserve_irq=", isapnp_setup_reserve_irq);
2411
 
2412
/* format is: isapnp_reserve_dma=dma1[,dma2] .... */
2413
 
2414
static int __init isapnp_setup_reserve_dma(char *str)
2415
{
2416
        int i;
2417
 
2418
        for (i = 0; i < 8; i++)
2419
                if (get_option(&str,&isapnp_reserve_dma[i]) != 2)
2420
                        break;
2421
        return 1;
2422
}
2423
 
2424
__setup("isapnp_reserve_dma=", isapnp_setup_reserve_dma);
2425
 
2426
/* format is: isapnp_reserve_io=io1,size1[,io2,size2] .... */
2427
 
2428
static int __init isapnp_setup_reserve_io(char *str)
2429
{
2430
        int i;
2431
 
2432
        for (i = 0; i < 16; i++)
2433
                if (get_option(&str,&isapnp_reserve_io[i]) != 2)
2434
                        break;
2435
        return 1;
2436
}
2437
 
2438
__setup("isapnp_reserve_io=", isapnp_setup_reserve_io);
2439
 
2440
/* format is: isapnp_reserve_mem=mem1,size1[,mem2,size2] .... */
2441
 
2442
static int __init isapnp_setup_reserve_mem(char *str)
2443
{
2444
        int i;
2445
 
2446
        for (i = 0; i < 16; i++)
2447
                if (get_option(&str,&isapnp_reserve_mem[i]) != 2)
2448
                        break;
2449
        return 1;
2450
}
2451
 
2452
__setup("isapnp_reserve_mem=", isapnp_setup_reserve_mem);
2453
 
2454
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.