2 * ISA Plug & Play support
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
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.
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.
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.
22 #define __NO_VERSION__
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/proc_fs.h>
28 #include <linux/poll.h>
29 #include <linux/vmalloc.h>
30 #include <asm/uaccess.h>
31 #include <linux/smp_lock.h>
32 #include <linux/isapnp.h>
34 struct isapnp_info_buffer
{
35 char *buffer
; /* pointer to begin of buffer */
36 char *curr
; /* current position in buffer */
37 unsigned long size
; /* current size */
38 unsigned long len
; /* total length of buffer */
39 int stop
; /* stop flag */
40 int error
; /* error code */
43 typedef struct isapnp_info_buffer isapnp_info_buffer_t
;
45 static struct proc_dir_entry
*isapnp_proc_entry
= NULL
;
46 static struct proc_dir_entry
*isapnp_proc_bus_dir
= NULL
;
47 static struct proc_dir_entry
*isapnp_proc_devices_entry
= NULL
;
49 static void isapnp_info_read(isapnp_info_buffer_t
*buffer
);
50 static void isapnp_info_write(isapnp_info_buffer_t
*buffer
);
52 int isapnp_printf(isapnp_info_buffer_t
* buffer
, char *fmt
,...)
58 if (buffer
->stop
|| buffer
->error
)
61 res
= vsprintf(sbuffer
, fmt
, args
);
63 if (buffer
->size
+ res
>= buffer
->len
) {
67 strcpy(buffer
->curr
, sbuffer
);
73 static void isapnp_devid(char *str
, unsigned short vendor
, unsigned short device
)
75 sprintf(str
, "%c%c%c%x%x%x%x",
76 'A' + ((vendor
>> 2) & 0x3f) - 1,
77 'A' + (((vendor
& 3) << 3) | ((vendor
>> 13) & 7)) - 1,
78 'A' + ((vendor
>> 8) & 0x1f) - 1,
81 (device
>> 12) & 0x0f,
82 (device
>> 8) & 0x0f);
85 static loff_t
isapnp_info_entry_lseek(struct file
*file
, loff_t offset
, int orig
)
88 case 0: /* SEEK_SET */
91 case 1: /* SEEK_CUR */
92 file
->f_pos
+= offset
;
94 case 2: /* SEEK_END */
101 static ssize_t
isapnp_info_entry_read(struct file
*file
, char *buffer
,
102 size_t count
, loff_t
* offset
)
104 isapnp_info_buffer_t
*buf
;
105 long size
= 0, size1
;
108 mode
= file
->f_flags
& O_ACCMODE
;
109 if (mode
!= O_RDONLY
)
111 buf
= (isapnp_info_buffer_t
*) file
->private_data
;
114 if (file
->f_pos
>= buf
->size
)
116 size
= buf
->size
< count
? buf
->size
: count
;
117 size1
= buf
->size
- file
->f_pos
;
120 if (copy_to_user(buffer
, buf
->buffer
+ file
->f_pos
, size
))
126 static ssize_t
isapnp_info_entry_write(struct file
*file
, const char *buffer
,
127 size_t count
, loff_t
* offset
)
129 isapnp_info_buffer_t
*buf
;
130 long size
= 0, size1
;
133 mode
= file
->f_flags
& O_ACCMODE
;
134 if (mode
!= O_WRONLY
)
136 buf
= (isapnp_info_buffer_t
*) file
->private_data
;
141 if (file
->f_pos
>= buf
->len
)
143 size
= buf
->len
< count
? buf
->len
: count
;
144 size1
= buf
->len
- file
->f_pos
;
147 if (copy_from_user(buf
->buffer
+ file
->f_pos
, buffer
, size
))
149 if (buf
->size
< file
->f_pos
+ size
)
150 buf
->size
= file
->f_pos
+ size
;
155 static int isapnp_info_entry_open(struct inode
*inode
, struct file
*file
)
157 isapnp_info_buffer_t
*buffer
;
160 mode
= file
->f_flags
& O_ACCMODE
;
161 if (mode
!= O_RDONLY
&& mode
!= O_WRONLY
)
163 buffer
= (isapnp_info_buffer_t
*)
164 isapnp_alloc(sizeof(isapnp_info_buffer_t
));
167 buffer
->len
= 4 * PAGE_SIZE
;
168 buffer
->buffer
= vmalloc(buffer
->len
);
169 if (!buffer
->buffer
) {
174 buffer
->curr
= buffer
->buffer
;
175 file
->private_data
= buffer
;
176 if (mode
== O_RDONLY
)
177 isapnp_info_read(buffer
);
182 static int isapnp_info_entry_release(struct inode
*inode
, struct file
*file
)
184 isapnp_info_buffer_t
*buffer
;
187 if ((buffer
= (isapnp_info_buffer_t
*) file
->private_data
) == NULL
)
189 mode
= file
->f_flags
& O_ACCMODE
;
190 if (mode
== O_WRONLY
)
191 isapnp_info_write(buffer
);
192 vfree(buffer
->buffer
);
197 static unsigned int isapnp_info_entry_poll(struct file
*file
, poll_table
* wait
)
199 if (!file
->private_data
)
201 return POLLIN
| POLLRDNORM
;
204 static struct file_operations isapnp_info_entry_operations
=
206 llseek
: isapnp_info_entry_lseek
,
207 read
: isapnp_info_entry_read
,
208 write
: isapnp_info_entry_write
,
209 poll
: isapnp_info_entry_poll
,
210 open
: isapnp_info_entry_open
,
211 release
: isapnp_info_entry_release
,
214 static loff_t
isapnp_proc_bus_lseek(struct file
*file
, loff_t off
, int whence
)
223 new = file
->f_pos
+ off
;
231 if (new < 0 || new > 256)
233 return (file
->f_pos
= new);
236 static ssize_t
isapnp_proc_bus_read(struct file
*file
, char *buf
, size_t nbytes
, loff_t
*ppos
)
238 struct inode
*ino
= file
->f_dentry
->d_inode
;
239 struct proc_dir_entry
*dp
= ino
->u
.generic_ip
;
240 struct pci_dev
*dev
= dp
->data
;
248 if (pos
+ nbytes
> size
)
252 if (!access_ok(VERIFY_WRITE
, buf
, cnt
))
255 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
256 for ( ; pos
< 256 && cnt
> 0; pos
++, buf
++, cnt
--) {
258 val
= isapnp_read_byte(pos
);
259 __put_user(val
, buf
);
267 static struct file_operations isapnp_proc_bus_file_operations
=
269 llseek
: isapnp_proc_bus_lseek
,
270 read
: isapnp_proc_bus_read
,
273 static int isapnp_proc_attach_device(struct pci_dev
*dev
)
275 struct pci_bus
*bus
= dev
->bus
;
276 struct proc_dir_entry
*de
, *e
;
279 if (!(de
= bus
->procdir
)) {
280 sprintf(name
, "%02x", bus
->number
);
281 de
= bus
->procdir
= proc_mkdir(name
, isapnp_proc_bus_dir
);
285 sprintf(name
, "%02x", dev
->devfn
);
286 e
= dev
->procent
= create_proc_entry(name
, S_IFREG
| S_IRUGO
, de
);
289 e
->proc_fops
= &isapnp_proc_bus_file_operations
;
290 e
->owner
= THIS_MODULE
;
297 static int __exit
isapnp_proc_detach_device(struct pci_dev
*dev
)
299 struct pci_bus
*bus
= dev
->bus
;
300 struct proc_dir_entry
*de
;
303 if (!(de
= bus
->procdir
))
305 sprintf(name
, "%02x", dev
->devfn
);
306 remove_proc_entry(name
, de
);
310 static int __exit
isapnp_proc_detach_bus(struct pci_bus
*bus
)
312 struct proc_dir_entry
*de
;
315 if (!(de
= bus
->procdir
))
317 sprintf(name
, "%02x", bus
->number
);
318 remove_proc_entry(name
, isapnp_proc_bus_dir
);
323 static int isapnp_proc_read_devices(char *buf
, char **start
, off_t pos
, int count
)
330 isapnp_for_each_dev(dev
) {
331 char bus_id
[8], device_id
[8];
333 isapnp_devid(bus_id
, dev
->bus
->vendor
, dev
->bus
->device
);
334 isapnp_devid(device_id
, dev
->vendor
, dev
->device
);
335 len
= sprintf(buf
, "%02x%02x\t%s%s\t",
340 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
341 len
+= sprintf(buf
+len
, "%02x", isapnp_read_byte(ISAPNP_CFG_ACTIVATE
));
342 for (i
= 0; i
< 8; i
++)
343 len
+= sprintf(buf
+len
, "%04x", isapnp_read_word(ISAPNP_CFG_PORT
+ (i
<< 1)));
344 for (i
= 0; i
< 2; i
++)
345 len
+= sprintf(buf
+len
, "%04x", isapnp_read_word(ISAPNP_CFG_IRQ
+ (i
<< 1)));
346 for (i
= 0; i
< 2; i
++)
347 len
+= sprintf(buf
+len
, "%04x", isapnp_read_word(ISAPNP_CFG_DMA
+ i
));
348 for (i
= 0; i
< 4; i
++)
349 len
+= sprintf(buf
+len
, "%08x", isapnp_read_dword(ISAPNP_CFG_MEM
+ (i
<< 3)));
355 *start
= buf
+ (pos
- (at
- len
));
362 return (count
> cnt
) ? cnt
: count
;
365 int __init
isapnp_proc_init(void)
367 struct proc_dir_entry
*p
;
370 isapnp_proc_entry
= NULL
;
371 p
= create_proc_entry("isapnp", S_IFREG
| S_IRUGO
| S_IWUSR
, &proc_root
);
373 p
->proc_fops
= &isapnp_info_entry_operations
;
374 p
->owner
= THIS_MODULE
;
376 isapnp_proc_entry
= p
;
377 isapnp_proc_bus_dir
= proc_mkdir("isapnp", proc_bus
);
378 isapnp_proc_devices_entry
= create_proc_info_entry("devices", 0,
380 isapnp_proc_read_devices
);
381 isapnp_for_each_dev(dev
) {
382 isapnp_proc_attach_device(dev
);
388 int __exit
isapnp_proc_done(void)
391 struct pci_bus
*card
;
393 isapnp_for_each_dev(dev
) {
394 isapnp_proc_detach_device(dev
);
396 isapnp_for_each_card(card
) {
397 isapnp_proc_detach_bus(card
);
399 if (isapnp_proc_devices_entry
)
400 remove_proc_entry("devices", isapnp_proc_devices_entry
);
401 if (isapnp_proc_bus_dir
)
402 remove_proc_entry("isapnp", proc_bus
);
403 if (isapnp_proc_entry
)
404 remove_proc_entry("isapnp", &proc_root
);
413 static void isapnp_print_devid(isapnp_info_buffer_t
*buffer
, unsigned short vendor
, unsigned short device
)
417 isapnp_devid(tmp
, vendor
, device
);
418 isapnp_printf(buffer
, tmp
);
421 static void isapnp_print_compatible(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
425 for (idx
= 0; idx
< DEVICE_COUNT_COMPATIBLE
; idx
++) {
426 if (dev
->vendor_compatible
[idx
] == 0)
428 isapnp_printf(buffer
, " Compatible device ");
429 isapnp_print_devid(buffer
,
430 dev
->vendor_compatible
[idx
],
431 dev
->device_compatible
[idx
]);
432 isapnp_printf(buffer
, "\n");
436 static void isapnp_print_port(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_port
*port
)
438 isapnp_printf(buffer
, "%sPort 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
439 space
, port
->min
, port
->max
, port
->align
? (port
->align
-1) : 0, port
->size
,
440 port
->flags
& ISAPNP_PORT_FLAG_16BITADDR
? 16 : 10);
443 static void isapnp_print_irq(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_irq
*irq
)
447 isapnp_printf(buffer
, "%sIRQ ", space
);
448 for (i
= 0; i
< 16; i
++)
449 if (irq
->map
& (1<<i
)) {
451 isapnp_printf(buffer
, ",");
455 if (i
== 2 || i
== 9)
456 isapnp_printf(buffer
, "2/9");
458 isapnp_printf(buffer
, "%i", i
);
461 isapnp_printf(buffer
, "<none>");
462 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
463 isapnp_printf(buffer
, " High-Edge");
464 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
465 isapnp_printf(buffer
, " Low-Edge");
466 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
467 isapnp_printf(buffer
, " High-Level");
468 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
469 isapnp_printf(buffer
, " Low-Level");
470 isapnp_printf(buffer
, "\n");
473 static void isapnp_print_dma(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_dma
*dma
)
478 isapnp_printf(buffer
, "%sDMA ", space
);
479 for (i
= 0; i
< 8; i
++)
480 if (dma
->map
& (1<<i
)) {
482 isapnp_printf(buffer
, ",");
486 isapnp_printf(buffer
, "%i", i
);
489 isapnp_printf(buffer
, "<none>");
490 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
491 case IORESOURCE_DMA_8BIT
:
494 case IORESOURCE_DMA_8AND16BIT
:
500 isapnp_printf(buffer
, " %s", s
);
501 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
502 isapnp_printf(buffer
, " master");
503 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
504 isapnp_printf(buffer
, " byte-count");
505 if (dma
->flags
& IORESOURCE_DMA_WORD
)
506 isapnp_printf(buffer
, " word-count");
507 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
508 case IORESOURCE_DMA_TYPEA
:
511 case IORESOURCE_DMA_TYPEB
:
514 case IORESOURCE_DMA_TYPEF
:
521 isapnp_printf(buffer
, " %s\n", s
);
524 static void isapnp_print_mem(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_mem
*mem
)
528 isapnp_printf(buffer
, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
529 space
, mem
->min
, mem
->max
, mem
->align
, mem
->size
);
530 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
531 isapnp_printf(buffer
, ", writeable");
532 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
533 isapnp_printf(buffer
, ", cacheable");
534 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
535 isapnp_printf(buffer
, ", range-length");
536 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
537 isapnp_printf(buffer
, ", shadowable");
538 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
539 isapnp_printf(buffer
, ", expansion ROM");
540 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
541 case IORESOURCE_MEM_8BIT
:
544 case IORESOURCE_MEM_8AND16BIT
:
550 isapnp_printf(buffer
, ", %s\n", s
);
553 static void isapnp_print_mem32(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_mem32
*mem32
)
557 isapnp_printf(buffer
, "%s32-bit memory ", space
);
558 for (i
= 0; i
< 17; i
++) {
562 isapnp_printf(buffer
, ":");
564 isapnp_printf(buffer
, "%02x", mem32
->data
[i
]);
568 static void isapnp_print_resources(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_resources
*res
)
571 struct isapnp_port
*port
;
572 struct isapnp_irq
*irq
;
573 struct isapnp_dma
*dma
;
574 struct isapnp_mem
*mem
;
575 struct isapnp_mem32
*mem32
;
577 switch (res
->priority
) {
578 case ISAPNP_RES_PRIORITY_PREFERRED
:
581 case ISAPNP_RES_PRIORITY_ACCEPTABLE
:
584 case ISAPNP_RES_PRIORITY_FUNCTIONAL
:
590 isapnp_printf(buffer
, "%sPriority %s\n", space
, s
);
591 for (port
= res
->port
; port
; port
= port
->next
)
592 isapnp_print_port(buffer
, space
, port
);
593 for (irq
= res
->irq
; irq
; irq
= irq
->next
)
594 isapnp_print_irq(buffer
, space
, irq
);
595 for (dma
= res
->dma
; dma
; dma
= dma
->next
)
596 isapnp_print_dma(buffer
, space
, dma
);
597 for (mem
= res
->mem
; mem
; mem
= mem
->next
)
598 isapnp_print_mem(buffer
, space
, mem
);
599 for (mem32
= res
->mem32
; mem32
; mem32
= mem32
->next
)
600 isapnp_print_mem32(buffer
, space
, mem32
);
603 static void isapnp_print_configuration(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
608 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
609 isapnp_printf(buffer
, "%sDevice is %sactive\n",
610 space
, isapnp_read_byte(ISAPNP_CFG_ACTIVATE
)?"":"not ");
611 for (i
= next
= 0; i
< 8; i
++) {
612 tmp
= isapnp_read_word(ISAPNP_CFG_PORT
+ (i
<< 1));
616 isapnp_printf(buffer
, "%sActive port ", space
);
619 isapnp_printf(buffer
, "%s0x%x", i
> 0 ? "," : "", tmp
);
622 isapnp_printf(buffer
, "\n");
623 for (i
= next
= 0; i
< 2; i
++) {
624 tmp
= isapnp_read_word(ISAPNP_CFG_IRQ
+ (i
<< 1));
628 isapnp_printf(buffer
, "%sActive IRQ ", space
);
631 isapnp_printf(buffer
, "%s%i", i
> 0 ? "," : "", tmp
>> 8);
633 isapnp_printf(buffer
, " [0x%x]", tmp
& 0xff);
636 isapnp_printf(buffer
, "\n");
637 for (i
= next
= 0; i
< 2; i
++) {
638 tmp
= isapnp_read_byte(ISAPNP_CFG_DMA
+ i
);
642 isapnp_printf(buffer
, "%sActive DMA ", space
);
645 isapnp_printf(buffer
, "%s%i", i
> 0 ? "," : "", tmp
);
648 isapnp_printf(buffer
, "\n");
649 for (i
= next
= 0; i
< 4; i
++) {
650 tmp
= isapnp_read_dword(ISAPNP_CFG_MEM
+ (i
<< 3));
654 isapnp_printf(buffer
, "%sActive memory ", space
);
657 isapnp_printf(buffer
, "%s0x%x", i
> 0 ? "," : "", tmp
);
660 isapnp_printf(buffer
, "\n");
664 static void isapnp_print_device(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
668 struct isapnp_resources
*res
, *resa
;
672 isapnp_printf(buffer
, " Logical device %i '", dev
->devfn
);
673 isapnp_print_devid(buffer
, dev
->vendor
, dev
->device
);
674 isapnp_printf(buffer
, ":%s'", dev
->name
[0]?dev
->name
:"Unknown");
675 isapnp_printf(buffer
, "\n");
677 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
678 for (block
= 0; block
< 128; block
++)
679 if ((block
% 16) == 15)
680 isapnp_printf(buffer
, "%02x\n", isapnp_read_byte(block
));
682 isapnp_printf(buffer
, "%02x:", isapnp_read_byte(block
));
686 isapnp_printf(buffer
, "%sSupported registers 0x%x\n", space
, dev
->regs
);
687 isapnp_print_compatible(buffer
, dev
);
688 isapnp_print_configuration(buffer
, dev
);
689 for (res
= (struct isapnp_resources
*)dev
->sysdata
, block
= 0; res
; res
= res
->next
, block
++) {
690 isapnp_printf(buffer
, "%sResources %i\n", space
, block
);
691 isapnp_print_resources(buffer
, " ", res
);
692 for (resa
= res
->alt
, block1
= 1; resa
; resa
= resa
->alt
, block1
++) {
693 isapnp_printf(buffer
, "%s Alternate resources %i:%i\n", space
, block
, block1
);
694 isapnp_print_resources(buffer
, " ", resa
);
703 static void isapnp_info_read(isapnp_info_buffer_t
*buffer
)
705 struct pci_bus
*card
;
707 isapnp_for_each_card(card
) {
708 struct list_head
*dev_list
;
710 isapnp_printf(buffer
, "Card %i '", card
->number
);
711 isapnp_print_devid(buffer
, card
->vendor
, card
->device
);
712 isapnp_printf(buffer
, ":%s'", card
->name
[0]?card
->name
:"Unknown");
714 isapnp_printf(buffer
, " PnP version %x.%x", card
->pnpver
>> 4, card
->pnpver
& 0x0f);
715 if (card
->productver
)
716 isapnp_printf(buffer
, " Product version %x.%x", card
->productver
>> 4, card
->productver
& 0x0f);
717 isapnp_printf(buffer
,"\n");
718 for (dev_list
= card
->devices
.next
; dev_list
!= &card
->devices
; dev_list
= dev_list
->next
)
719 isapnp_print_device(buffer
, pci_dev_b(dev_list
));
727 static struct pci_bus
*isapnp_info_card
;
728 static struct pci_dev
*isapnp_info_device
;
730 static char *isapnp_get_str(char *dest
, char *src
, int len
)
734 while (*src
== ' ' || *src
== '\t')
736 if (*src
== '"' || *src
== '\'') {
738 while (--len
> 0 && *src
&& *src
!= c
) {
744 while (--len
> 0 && *src
&& *src
!= ' ' && *src
!= '\t') {
749 while (*src
== ' ' || *src
== '\t')
754 static unsigned char isapnp_get_hex(unsigned char c
)
756 if (c
>= '0' && c
<= '9')
758 if (c
>= 'a' && c
<= 'f')
759 return (c
- 'a') + 10;
760 if (c
>= 'A' && c
<= 'F')
761 return (c
- 'A') + 10;
765 static unsigned int isapnp_parse_id(const char *id
)
767 if (strlen(id
) != 7) {
768 printk("isapnp: wrong PnP ID\n");
771 return (ISAPNP_VENDOR(id
[0], id
[1], id
[2])<<16) |
772 (isapnp_get_hex(id
[3])<<4) |
773 (isapnp_get_hex(id
[4])<<0) |
774 (isapnp_get_hex(id
[5])<<12) |
775 (isapnp_get_hex(id
[6])<<8);
778 static int isapnp_set_card(char *line
)
782 char index
[16], value
[32];
784 isapnp_info_card
= NULL
;
785 line
= isapnp_get_str(index
, line
, sizeof(index
));
786 isapnp_get_str(value
, line
, sizeof(value
));
787 idx
= idx1
= simple_strtoul(index
, NULL
, 0);
788 id
= isapnp_parse_id(value
);
789 isapnp_info_card
= isapnp_find_card(id
>> 16, id
& 0xffff, NULL
);
790 while (isapnp_info_card
&& idx1
-- > 0)
791 isapnp_info_card
= isapnp_find_card(id
>> 16, id
& 0xffff, isapnp_info_card
);
792 if (isapnp_info_card
== NULL
) {
793 printk("isapnp: card '%s' order %i not found\n", value
, idx
);
796 if (isapnp_cfg_begin(isapnp_info_card
->number
, -1)<0) {
797 printk("isapnp: configuration start sequence for device '%s' failed\n", value
);
798 isapnp_info_card
= NULL
;
804 static int isapnp_select_csn(char *line
)
807 struct list_head
*list
;
808 char index
[16], value
[32];
810 isapnp_info_device
= NULL
;
811 isapnp_get_str(index
, line
, sizeof(index
));
812 csn
= simple_strtoul(index
, NULL
, 0);
814 for (list
= isapnp_cards
.next
; list
!= &isapnp_cards
; list
= list
->next
) {
815 isapnp_info_card
= pci_bus_b(list
);
816 if (isapnp_info_card
->number
== csn
)
819 if (list
== &isapnp_cards
) {
820 printk("isapnp: cannot find CSN %i\n", csn
);
823 if (isapnp_cfg_begin(isapnp_info_card
->number
, -1)<0) {
824 printk("isapnp: configuration start sequence for device '%s' failed\n", value
);
825 isapnp_info_card
= NULL
;
831 static int isapnp_set_device(char *line
)
835 char index
[16], value
[32];
837 line
= isapnp_get_str(index
, line
, sizeof(index
));
838 isapnp_get_str(value
, line
, sizeof(value
));
839 idx
= idx1
= simple_strtoul(index
, NULL
, 0);
840 id
= isapnp_parse_id(value
);
841 isapnp_info_device
= isapnp_find_dev(isapnp_info_card
, id
>> 16, id
& 0xffff, NULL
);
842 while (isapnp_info_device
&& idx
-- > 0)
843 isapnp_info_device
= isapnp_find_dev(isapnp_info_card
, id
>> 16, id
& 0xffff, isapnp_info_device
);
844 if (isapnp_info_device
== NULL
) {
845 printk("isapnp: device '%s' order %i not found\n", value
, idx
);
848 isapnp_device(isapnp_info_device
->devfn
);
852 static int isapnp_autoconfigure(void)
854 if (isapnp_info_device
== NULL
) {
855 printk("isapnp: device is not set\n");
858 if (isapnp_info_device
->active
)
859 isapnp_info_device
->deactivate(isapnp_info_device
);
860 if (isapnp_info_device
->prepare(isapnp_info_device
) < 0) {
861 printk("isapnp: cannot prepare device for the activation");
864 if (isapnp_info_device
->activate(isapnp_info_device
) < 0) {
865 printk("isapnp: cannot activate device");
871 static int isapnp_set_port(char *line
)
874 char index
[16], value
[32];
876 line
= isapnp_get_str(index
, line
, sizeof(index
));
877 isapnp_get_str(value
, line
, sizeof(value
));
878 idx
= simple_strtoul(index
, NULL
, 0);
879 port
= simple_strtoul(value
, NULL
, 0);
880 if (idx
< 0 || idx
> 7) {
881 printk("isapnp: wrong port index %i\n", idx
);
884 if (port
< 0 || port
> 0xffff) {
885 printk("isapnp: wrong port value 0x%x\n", port
);
888 isapnp_write_word(ISAPNP_CFG_PORT
+ (idx
<< 1), port
);
889 if (!isapnp_info_device
->resource
[idx
].flags
)
891 if (isapnp_info_device
->resource
[idx
].flags
& IORESOURCE_AUTO
) {
892 isapnp_info_device
->resource
[idx
].start
= port
;
893 isapnp_info_device
->resource
[idx
].end
+= port
- 1;
894 isapnp_info_device
->resource
[idx
].flags
&= ~IORESOURCE_AUTO
;
896 isapnp_info_device
->resource
[idx
].end
-= isapnp_info_device
->resource
[idx
].start
;
897 isapnp_info_device
->resource
[idx
].start
= port
;
898 isapnp_info_device
->resource
[idx
].end
+= port
;
903 static void isapnp_set_irqresource(struct resource
*res
, int irq
)
905 res
->start
= res
->end
= irq
;
906 res
->flags
= IORESOURCE_IRQ
;
909 static int isapnp_set_irq(char *line
)
912 char index
[16], value
[32];
914 line
= isapnp_get_str(index
, line
, sizeof(index
));
915 isapnp_get_str(value
, line
, sizeof(value
));
916 idx
= simple_strtoul(index
, NULL
, 0);
917 irq
= simple_strtoul(value
, NULL
, 0);
918 if (idx
< 0 || idx
> 1) {
919 printk("isapnp: wrong IRQ index %i\n", idx
);
924 if (irq
< 0 || irq
> 15) {
925 printk("isapnp: wrong IRQ value %i\n", irq
);
928 isapnp_write_byte(ISAPNP_CFG_IRQ
+ (idx
<< 1), irq
);
929 isapnp_set_irqresource(isapnp_info_device
->irq_resource
+ idx
, irq
);
933 static void isapnp_set_dmaresource(struct resource
*res
, int dma
)
935 res
->start
= res
->end
= dma
;
936 res
->flags
= IORESOURCE_DMA
;
939 static int isapnp_set_dma(char *line
)
942 char index
[16], value
[32];
944 line
= isapnp_get_str(index
, line
, sizeof(index
));
945 isapnp_get_str(value
, line
, sizeof(value
));
946 idx
= simple_strtoul(index
, NULL
, 0);
947 dma
= simple_strtoul(value
, NULL
, 0);
948 if (idx
< 0 || idx
> 1) {
949 printk("isapnp: wrong DMA index %i\n", idx
);
952 if (dma
< 0 || dma
> 7) {
953 printk("isapnp: wrong DMA value %i\n", dma
);
956 isapnp_write_byte(ISAPNP_CFG_DMA
+ idx
, dma
);
957 isapnp_set_dmaresource(isapnp_info_device
->dma_resource
+ idx
, dma
);
961 static int isapnp_set_mem(char *line
)
965 char index
[16], value
[32];
967 line
= isapnp_get_str(index
, line
, sizeof(index
));
968 isapnp_get_str(value
, line
, sizeof(value
));
969 idx
= simple_strtoul(index
, NULL
, 0);
970 mem
= simple_strtoul(value
, NULL
, 0);
971 if (idx
< 0 || idx
> 3) {
972 printk("isapnp: wrong memory index %i\n", idx
);
976 isapnp_write_word(ISAPNP_CFG_MEM
+ (idx
<<2), mem
& 0xffff);
977 if (!isapnp_info_device
->resource
[idx
+ 8].flags
)
979 if (isapnp_info_device
->resource
[idx
+ 8].flags
& IORESOURCE_AUTO
) {
980 isapnp_info_device
->resource
[idx
+ 8].start
= mem
& ~0x00ffff00;
981 isapnp_info_device
->resource
[idx
+ 8].end
+= (mem
& ~0x00ffff00) - 1;
982 isapnp_info_device
->resource
[idx
+ 8].flags
&= ~IORESOURCE_AUTO
;
984 isapnp_info_device
->resource
[idx
+ 8].end
-= isapnp_info_device
->resource
[idx
+ 8].start
;
985 isapnp_info_device
->resource
[idx
+ 8].start
= mem
& ~0x00ffff00;
986 isapnp_info_device
->resource
[idx
+ 8].end
+= mem
& ~0x00ffff00;
991 static int isapnp_poke(char *line
, int what
)
995 char index
[16], value
[32];
997 line
= isapnp_get_str(index
, line
, sizeof(index
));
998 isapnp_get_str(value
, line
, sizeof(value
));
999 reg
= simple_strtoul(index
, NULL
, 0);
1000 val
= simple_strtoul(value
, NULL
, 0);
1001 if (reg
< 0 || reg
> 127) {
1002 printk("isapnp: wrong register %i\n", reg
);
1007 isapnp_write_word(reg
, val
);
1010 isapnp_write_dword(reg
, val
);
1013 isapnp_write_byte(reg
, val
);
1019 static int isapnp_decode_line(char *line
)
1023 line
= isapnp_get_str(cmd
, line
, sizeof(cmd
));
1024 if (!strcmp(cmd
, "card"))
1025 return isapnp_set_card(line
);
1026 if (!strcmp(cmd
, "csn"))
1027 return isapnp_select_csn(line
);
1028 if (!isapnp_info_card
) {
1029 printk("isapnp: card is not selected\n");
1032 if (!strncmp(cmd
, "dev", 3))
1033 return isapnp_set_device(line
);
1034 if (!isapnp_info_device
) {
1035 printk("isapnp: device is not selected\n");
1038 if (!strncmp(cmd
, "auto", 4))
1039 return isapnp_autoconfigure();
1040 if (!strncmp(cmd
, "act", 3)) {
1041 isapnp_activate(isapnp_info_device
->devfn
);
1042 isapnp_info_device
->active
= 1;
1045 if (!strncmp(cmd
, "deact", 5)) {
1046 isapnp_deactivate(isapnp_info_device
->devfn
);
1047 isapnp_info_device
->active
= 0;
1050 if (!strcmp(cmd
, "port"))
1051 return isapnp_set_port(line
);
1052 if (!strcmp(cmd
, "irq"))
1053 return isapnp_set_irq(line
);
1054 if (!strcmp(cmd
, "dma"))
1055 return isapnp_set_dma(line
);
1056 if (!strncmp(cmd
, "mem", 3))
1057 return isapnp_set_mem(line
);
1058 if (!strcmp(cmd
, "poke"))
1059 return isapnp_poke(line
, 0);
1060 if (!strcmp(cmd
, "pokew"))
1061 return isapnp_poke(line
, 1);
1062 if (!strcmp(cmd
, "poked"))
1063 return isapnp_poke(line
, 2);
1064 printk("isapnp: wrong command '%s'\n", cmd
);
1069 * Main write routine
1072 static void isapnp_info_write(isapnp_info_buffer_t
*buffer
)
1074 int c
, idx
, idx1
= 0;
1077 if (buffer
->size
<= 0)
1079 isapnp_info_card
= NULL
;
1080 isapnp_info_device
= NULL
;
1081 for (idx
= 0; idx
< buffer
->size
; idx
++) {
1082 c
= buffer
->buffer
[idx
];
1085 if (line
[0] != '#') {
1086 if (isapnp_decode_line(line
))
1092 if (idx1
>= sizeof(line
)-1) {
1093 printk("isapnp: line too long, aborting\n");
1099 if (isapnp_info_card
)