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 static void *isapnp_alloc(long size
);
23 struct pci_bus
*isapnp_cards
;
24 struct pci_dev
*isapnp_devices
;
26 struct isapnp_info_buffer
{
27 char *buffer
; /* pointer to begin of buffer */
28 char *curr
; /* current position in buffer */
29 unsigned long size
; /* current size */
30 unsigned long len
; /* total length of buffer */
31 int stop
; /* stop flag */
32 int error
; /* error code */
35 typedef struct isapnp_info_buffer isapnp_info_buffer_t
;
37 static struct proc_dir_entry
*isapnp_proc_entry
= NULL
;
39 static void isapnp_info_read(isapnp_info_buffer_t
*buffer
);
40 static void isapnp_info_write(isapnp_info_buffer_t
*buffer
);
42 int isapnp_printf(isapnp_info_buffer_t
* buffer
, char *fmt
,...)
48 if (buffer
->stop
|| buffer
->error
)
51 res
= vsprintf(sbuffer
, fmt
, args
);
53 if (buffer
->size
+ res
>= buffer
->len
) {
57 strcpy(buffer
->curr
, sbuffer
);
63 static loff_t
isapnp_info_entry_lseek(struct file
*file
, loff_t offset
, int orig
)
66 case 0: /* SEEK_SET */
69 case 1: /* SEEK_CUR */
70 file
->f_pos
+= offset
;
72 case 2: /* SEEK_END */
79 static ssize_t
isapnp_info_entry_read(struct file
*file
, char *buffer
,
80 size_t count
, loff_t
* offset
)
82 isapnp_info_buffer_t
*buf
;
86 mode
= file
->f_flags
& O_ACCMODE
;
89 buf
= (isapnp_info_buffer_t
*) file
->private_data
;
92 if (file
->f_pos
>= buf
->size
)
94 size
= buf
->size
< count
? buf
->size
: count
;
95 size1
= buf
->size
- file
->f_pos
;
98 if (copy_to_user(buffer
, buf
->buffer
+ file
->f_pos
, size
))
104 static ssize_t
isapnp_info_entry_write(struct file
*file
, const char *buffer
,
105 size_t count
, loff_t
* offset
)
107 isapnp_info_buffer_t
*buf
;
108 long size
= 0, size1
;
111 mode
= file
->f_flags
& O_ACCMODE
;
112 if (mode
!= O_WRONLY
)
114 buf
= (isapnp_info_buffer_t
*) file
->private_data
;
119 if (file
->f_pos
>= buf
->len
)
121 size
= buf
->len
< count
? buf
->len
: count
;
122 size1
= buf
->len
- file
->f_pos
;
125 if (copy_from_user(buf
->buffer
+ file
->f_pos
, buffer
, size
))
127 if (buf
->size
< file
->f_pos
+ size
)
128 buf
->size
= file
->f_pos
+ size
;
133 static int isapnp_info_entry_open(struct inode
*inode
, struct file
*file
)
135 isapnp_info_buffer_t
*buffer
;
138 mode
= file
->f_flags
& O_ACCMODE
;
139 if (mode
!= O_RDONLY
&& mode
!= O_WRONLY
)
141 buffer
= (isapnp_info_buffer_t
*)
142 isapnp_alloc(sizeof(isapnp_info_buffer_t
));
145 buffer
->len
= 4 * PAGE_SIZE
;
146 buffer
->buffer
= vmalloc(buffer
->len
);
147 if (!buffer
->buffer
) {
151 buffer
->curr
= buffer
->buffer
;
152 file
->private_data
= buffer
;
154 if (mode
== O_RDONLY
)
155 isapnp_info_read(buffer
);
159 static int isapnp_info_entry_release(struct inode
*inode
, struct file
*file
)
161 isapnp_info_buffer_t
*buffer
;
164 if ((buffer
= (isapnp_info_buffer_t
*) file
->private_data
) == NULL
)
166 mode
= file
->f_flags
& O_ACCMODE
;
167 if (mode
== O_WRONLY
)
168 isapnp_info_write(buffer
);
169 vfree(buffer
->buffer
);
175 static unsigned int isapnp_info_entry_poll(struct file
*file
, poll_table
* wait
)
177 if (!file
->private_data
)
179 return POLLIN
| POLLRDNORM
;
182 static int isapnp_info_entry_ioctl(struct inode
*inode
, struct file
*file
,
183 unsigned int cmd
, unsigned long arg
)
188 static int isapnp_info_entry_mmap(struct file
*file
, struct vm_area_struct
*vma
)
193 static struct file_operations isapnp_info_entry_operations
=
195 isapnp_info_entry_lseek
, /* lseek */
196 isapnp_info_entry_read
, /* read */
197 isapnp_info_entry_write
, /* write */
199 isapnp_info_entry_poll
, /* poll */
200 isapnp_info_entry_ioctl
, /* ioctl - default */
201 isapnp_info_entry_mmap
, /* mmap */
202 isapnp_info_entry_open
, /* open */
204 isapnp_info_entry_release
, /* release */
205 NULL
, /* can't fsync */
207 NULL
, /* check_media_change */
208 NULL
, /* revalidate */
212 static struct inode_operations isapnp_info_entry_inode_operations
=
214 &isapnp_info_entry_operations
, /* default sound info directory file-ops */
225 NULL
, /* follow_link */
227 NULL
, /* writepage */
230 NULL
/* permission */
233 __initfunc(static int isapnp_proc_init(void))
235 struct proc_dir_entry
*p
;
237 isapnp_proc_entry
= NULL
;
238 p
= create_proc_entry("isapnp", S_IFREG
| S_IRUGO
| S_IWUSR
, &proc_root
);
241 p
->ops
= &isapnp_info_entry_inode_operations
;
242 isapnp_proc_entry
= p
;
247 static int isapnp_proc_done(void)
249 if (isapnp_proc_entry
)
250 proc_unregister(&proc_root
, isapnp_proc_entry
->low_ino
);
259 static void isapnp_print_devid(isapnp_info_buffer_t
*buffer
, unsigned short vendor
, unsigned short device
)
263 sprintf(tmp
, "%c%c%c%x%x%x%x",
264 'A' + ((vendor
>> 2) & 0x3f) - 1,
265 'A' + (((vendor
& 3) << 3) | ((vendor
>> 13) & 7)) - 1,
266 'A' + ((vendor
>> 8) & 0x1f) - 1,
267 (device
>> 4) & 0x0f,
269 (device
>> 12) & 0x0f,
270 (device
>> 8) & 0x0f);
271 isapnp_printf(buffer
, tmp
);
274 static void isapnp_print_compatible(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
278 for (idx
= 0; idx
< DEVICE_COUNT_COMPATIBLE
; idx
++) {
279 if (dev
->vendor_compatible
[idx
] == 0)
281 isapnp_printf(buffer
, " Compatible device ");
282 isapnp_print_devid(buffer
,
283 dev
->vendor_compatible
[idx
],
284 dev
->device_compatible
[idx
]);
285 isapnp_printf(buffer
, "\n");
289 static void isapnp_print_port(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_port
*port
)
291 isapnp_printf(buffer
, "%sPort 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
292 space
, port
->min
, port
->max
, port
->align
? (port
->align
-1) : 0, port
->size
,
293 port
->flags
& ISAPNP_PORT_FLAG_16BITADDR
? 16 : 10);
296 static void isapnp_print_irq(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_irq
*irq
)
300 isapnp_printf(buffer
, "%sIRQ ", space
);
301 for (i
= 0; i
< 16; i
++)
302 if (irq
->map
& (1<<i
)) {
304 isapnp_printf(buffer
, ",");
308 if (i
== 2 || i
== 9)
309 isapnp_printf(buffer
, "2/9");
311 isapnp_printf(buffer
, "%i", i
);
314 isapnp_printf(buffer
, "<none>");
315 if (irq
->flags
& DEVICE_IRQ_FLAG_HIGHEDGE
)
316 isapnp_printf(buffer
, " High-Edge");
317 if (irq
->flags
& DEVICE_IRQ_FLAG_LOWEDGE
)
318 isapnp_printf(buffer
, " Low-Edge");
319 if (irq
->flags
& DEVICE_IRQ_FLAG_HIGHLEVEL
)
320 isapnp_printf(buffer
, " High-Level");
321 if (irq
->flags
& DEVICE_IRQ_FLAG_LOWLEVEL
)
322 isapnp_printf(buffer
, " Low-Level");
323 isapnp_printf(buffer
, "\n");
326 static void isapnp_print_dma(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_dma
*dma
)
331 isapnp_printf(buffer
, "%sDMA ", space
);
332 for (i
= 0; i
< 8; i
++)
333 if (dma
->map
& (1<<i
)) {
335 isapnp_printf(buffer
, ",");
339 isapnp_printf(buffer
, "%i", i
);
342 isapnp_printf(buffer
, "<none>");
344 case DEVICE_DMA_TYPE_8BIT
:
347 case DEVICE_DMA_TYPE_8AND16BIT
:
353 isapnp_printf(buffer
, " %s", s
);
354 if (dma
->flags
& DEVICE_DMA_FLAG_MASTER
)
355 isapnp_printf(buffer
, " master");
356 if (dma
->flags
& DEVICE_DMA_FLAG_BYTE
)
357 isapnp_printf(buffer
, " byte-count");
358 if (dma
->flags
& DEVICE_DMA_FLAG_WORD
)
359 isapnp_printf(buffer
, " word-count");
360 switch (dma
->speed
) {
361 case DEVICE_DMA_SPEED_TYPEA
:
364 case DEVICE_DMA_SPEED_TYPEB
:
367 case DEVICE_DMA_SPEED_TYPEF
:
374 isapnp_printf(buffer
, " %s\n", s
);
377 static void isapnp_print_mem(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_mem
*mem
)
381 isapnp_printf(buffer
, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
382 space
, mem
->min
, mem
->max
, mem
->align
, mem
->size
);
383 if (mem
->flags
& ISAPNP_FLAG_WRITEABLE
)
384 isapnp_printf(buffer
, ", writeable");
385 if (mem
->flags
& ISAPNP_FLAG_CACHEABLE
)
386 isapnp_printf(buffer
, ", cacheable");
387 if (mem
->flags
& ISAPNP_FLAG_RANGELENGTH
)
388 isapnp_printf(buffer
, ", range-length");
389 if (mem
->flags
& ISAPNP_FLAG_SHADOWABLE
)
390 isapnp_printf(buffer
, ", shadowable");
391 if (mem
->flags
& ISAPNP_FLAG_EXPANSIONROM
)
392 isapnp_printf(buffer
, ", expansion ROM");
394 case ISAPNP_TYPE_8BIT
:
397 case ISAPNP_TYPE_8AND16BIT
:
403 isapnp_printf(buffer
, ", %s\n", s
);
406 static void isapnp_print_mem32(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_mem32
*mem32
)
410 isapnp_printf(buffer
, "%s32-bit memory ", space
);
411 for (i
= 0; i
< 17; i
++) {
415 isapnp_printf(buffer
, ":");
417 isapnp_printf(buffer
, "%02x", mem32
->data
[i
]);
421 static void isapnp_print_resources(isapnp_info_buffer_t
*buffer
, char *space
, struct isapnp_resources
*res
)
424 struct isapnp_port
*port
;
425 struct isapnp_irq
*irq
;
426 struct isapnp_dma
*dma
;
427 struct isapnp_mem
*mem
;
428 struct isapnp_mem32
*mem32
;
430 switch (res
->priority
) {
431 case ISAPNP_RES_PRIORITY_PREFERRED
:
434 case ISAPNP_RES_PRIORITY_ACCEPTABLE
:
437 case ISAPNP_RES_PRIORITY_FUNCTIONAL
:
443 isapnp_printf(buffer
, "%sPriority %s\n", space
, s
);
444 for (port
= res
->port
; port
; port
= port
->next
)
445 isapnp_print_port(buffer
, space
, port
);
446 for (irq
= res
->irq
; irq
; irq
= irq
->next
)
447 isapnp_print_irq(buffer
, space
, irq
);
448 for (dma
= res
->dma
; dma
; dma
= dma
->next
)
449 isapnp_print_dma(buffer
, space
, dma
);
450 for (mem
= res
->mem
; mem
; mem
= mem
->next
)
451 isapnp_print_mem(buffer
, space
, mem
);
452 for (mem32
= res
->mem32
; mem32
; mem32
= mem32
->next
)
453 isapnp_print_mem32(buffer
, space
, mem32
);
456 static void isapnp_print_configuration(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
461 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
462 isapnp_printf(buffer
, "%sDevice is %sactive\n",
463 space
, isapnp_read_byte(ISAPNP_CFG_ACTIVATE
)?"":"not ");
464 for (i
= next
= 0; i
< 8; i
++) {
465 tmp
= isapnp_read_word(ISAPNP_CFG_PORT
+ (i
<< 1));
469 isapnp_printf(buffer
, "%sActive port ", space
);
472 isapnp_printf(buffer
, "%s0x%x", i
> 0 ? "," : "", tmp
);
475 isapnp_printf(buffer
, "\n");
476 for (i
= next
= 0; i
< 2; i
++) {
477 tmp
= isapnp_read_word(ISAPNP_CFG_IRQ
+ (i
<< 1));
481 isapnp_printf(buffer
, "%sActive IRQ ", space
);
484 isapnp_printf(buffer
, "%s%i", i
> 0 ? "," : "", tmp
>> 8);
486 isapnp_printf(buffer
, " [0x%x]", tmp
& 0xff);
489 isapnp_printf(buffer
, "\n");
490 for (i
= next
= 0; i
< 2; i
++) {
491 tmp
= isapnp_read_byte(ISAPNP_CFG_DMA
+ i
);
495 isapnp_printf(buffer
, "%sActive DMA ", space
);
498 isapnp_printf(buffer
, "%s%i", i
> 0 ? "," : "", tmp
);
501 isapnp_printf(buffer
, "\n");
502 for (i
= next
= 0; i
< 4; i
++) {
503 tmp
= isapnp_read_dword(ISAPNP_CFG_MEM
+ (i
<< 3));
507 isapnp_printf(buffer
, "%sActive memory ", space
);
510 isapnp_printf(buffer
, "%s0x%x", i
> 0 ? "," : "", tmp
);
513 isapnp_printf(buffer
, "\n");
517 static void isapnp_print_device(isapnp_info_buffer_t
*buffer
, struct pci_dev
*dev
)
521 struct isapnp_resources
*res
, *resa
;
525 isapnp_printf(buffer
, " Logical device %i '", dev
->devfn
);
526 isapnp_print_devid(buffer
, dev
->vendor
, dev
->device
);
527 isapnp_printf(buffer
, ":%s'", dev
->name
[0]?dev
->name
:"Unknown");
528 isapnp_printf(buffer
, "\n");
530 isapnp_cfg_begin(dev
->bus
->number
, dev
->devfn
);
531 for (block
= 0; block
< 128; block
++)
532 if ((block
% 16) == 15)
533 isapnp_printf(buffer
, "%02x\n", isapnp_read_byte(block
));
535 isapnp_printf(buffer
, "%02x:", isapnp_read_byte(block
));
539 isapnp_printf(buffer
, "%sSupported registers 0x%x\n", space
, dev
->regs
);
540 isapnp_print_compatible(buffer
, dev
);
541 isapnp_print_configuration(buffer
, dev
);
542 for (res
= (struct isapnp_resources
*)dev
->sysdata
, block
= 0; res
; res
= res
->next
, block
++) {
543 isapnp_printf(buffer
, "%sResources %i\n", space
, block
);
544 isapnp_print_resources(buffer
, " ", res
);
545 for (resa
= res
->alt
, block1
= 1; resa
; resa
= resa
->alt
, block1
++) {
546 isapnp_printf(buffer
, "%s Alternate resources %i:%i\n", space
, block
, block1
);
547 isapnp_print_resources(buffer
, " ", resa
);
556 static void isapnp_info_read(isapnp_info_buffer_t
*buffer
)
558 struct pci_bus
*card
;
561 for (card
= isapnp_cards
; card
; card
= card
->next
) {
562 isapnp_printf(buffer
, "Card %i '", card
->number
);
563 isapnp_print_devid(buffer
, card
->vendor
, card
->device
);
564 isapnp_printf(buffer
, ":%s'", card
->name
[0]?card
->name
:"Unknown");
566 isapnp_printf(buffer
, " PnP version %x.%x", card
->pnpver
>> 4, card
->pnpver
& 0x0f);
567 if (card
->productver
)
568 isapnp_printf(buffer
, " Product version %x.%x", card
->productver
>> 4, card
->productver
& 0x0f);
569 isapnp_printf(buffer
,"\n");
570 for (dev
= card
->devices
; dev
; dev
= dev
->sibling
)
571 isapnp_print_device(buffer
, dev
);
579 static struct pci_bus
*isapnp_info_card
;
580 static struct pci_dev
*isapnp_info_device
;
582 static char *isapnp_get_str(char *dest
, char *src
, int len
)
586 while (*src
== ' ' || *src
== '\t')
588 if (*src
== '"' || *src
== '\'') {
590 while (--len
> 0 && *src
&& *src
!= c
) {
596 while (--len
> 0 && *src
&& *src
!= ' ' && *src
!= '\t') {
601 while (*src
== ' ' || *src
== '\t')
606 static unsigned char isapnp_get_hex(unsigned char c
)
608 if (c
>= '0' || c
<= '9')
610 if (c
>= 'a' || c
<= 'f')
611 return (c
- 'a') + 10;
612 if (c
>= 'A' || c
<= 'F')
613 return (c
- 'A') + 10;
617 static unsigned int isapnp_parse_id(const char *id
)
619 if (strlen(id
) != 7) {
620 printk("isapnp: wrong PnP ID\n");
623 return (ISAPNP_VENDOR(id
[0], id
[1], id
[2])<<16) |
624 (isapnp_get_hex(id
[3])<<4) |
625 (isapnp_get_hex(id
[4])<<0) |
626 (isapnp_get_hex(id
[5])<<12) |
627 (isapnp_get_hex(id
[6])<<8);
630 static int isapnp_set_card(char *line
)
634 char index
[16], value
[32];
636 isapnp_info_card
= NULL
;
637 line
= isapnp_get_str(index
, line
, sizeof(index
));
638 isapnp_get_str(value
, line
, sizeof(value
));
639 idx
= idx1
= simple_strtoul(index
, NULL
, 0);
640 id
= isapnp_parse_id(value
);
641 isapnp_info_card
= isapnp_find_card(id
>> 16, id
& 0xffff, NULL
);
642 while (isapnp_info_card
&& idx1
-- > 0)
643 isapnp_info_card
= isapnp_find_card(id
>> 16, id
& 0xffff, isapnp_info_card
);
644 if (isapnp_info_card
== NULL
) {
645 printk("isapnp: card '%s' order %i not found\n", value
, idx
);
648 if (isapnp_cfg_begin(isapnp_info_card
->number
, -1)<0) {
649 printk("isapnp: configuration start sequence for device '%s' failed\n", value
);
650 isapnp_info_card
= NULL
;
656 static int isapnp_select_csn(char *line
)
659 char index
[16], value
[32];
661 isapnp_info_device
= NULL
;
662 isapnp_get_str(index
, line
, sizeof(index
));
663 csn
= simple_strtoul(index
, NULL
, 0);
664 for (isapnp_info_card
= isapnp_cards
; isapnp_info_card
; isapnp_info_card
= isapnp_info_card
->next
)
665 if (isapnp_info_card
->number
== csn
)
667 if (isapnp_info_card
== NULL
) {
668 printk("isapnp: cannot find CSN %i\n", csn
);
671 if (isapnp_cfg_begin(isapnp_info_card
->number
, -1)<0) {
672 printk("isapnp: configuration start sequence for device '%s' failed\n", value
);
673 isapnp_info_card
= NULL
;
679 static int isapnp_set_device(char *line
)
683 char index
[16], value
[32];
685 line
= isapnp_get_str(index
, line
, sizeof(index
));
686 isapnp_get_str(value
, line
, sizeof(value
));
687 idx
= idx1
= simple_strtoul(index
, NULL
, 0);
688 id
= isapnp_parse_id(value
);
689 isapnp_info_device
= isapnp_find_dev(isapnp_info_card
, id
>> 16, id
& 0xffff, NULL
);
690 while (isapnp_info_device
&& idx
-- > 0)
691 isapnp_info_device
= isapnp_find_dev(isapnp_info_card
, id
>> 16, id
& 0xffff, isapnp_info_device
);
692 if (isapnp_info_device
== NULL
) {
693 printk("isapnp: device '%s' order %i not found\n", value
, idx
);
696 isapnp_device(isapnp_info_device
->devfn
);
700 static int isapnp_autoconfigure(void)
702 if (isapnp_info_device
== NULL
) {
703 printk("isapnp: device is not set\n");
706 if (isapnp_info_device
->active
)
707 isapnp_info_device
->deactivate(isapnp_info_device
);
708 if (isapnp_info_device
->prepare(isapnp_info_device
) < 0) {
709 printk("isapnp: cannot prepare device for the activation");
712 if (isapnp_info_device
->activate(isapnp_info_device
) < 0) {
713 printk("isapnp: cannot activate device");
719 static int isapnp_set_port(char *line
)
722 char index
[16], value
[32];
724 line
= isapnp_get_str(index
, line
, sizeof(index
));
725 isapnp_get_str(value
, line
, sizeof(value
));
726 idx
= simple_strtoul(index
, NULL
, 0);
727 port
= simple_strtoul(value
, NULL
, 0);
728 if (idx
< 0 || idx
> 7) {
729 printk("isapnp: wrong port index %i\n", idx
);
732 if (port
< 0 || port
> 0xffff) {
733 printk("isapnp: wrong port value 0x%x\n", port
);
736 isapnp_write_word(ISAPNP_CFG_PORT
+ (idx
<< 1), port
);
737 if (isapnp_info_device
->resource
[idx
].start
== ISAPNP_NOTSET
)
739 if (isapnp_info_device
->resource
[idx
].start
== ISAPNP_AUTO
) {
740 isapnp_info_device
->resource
[idx
].start
= port
;
741 isapnp_info_device
->resource
[idx
].end
+= port
- 1;
743 isapnp_info_device
->resource
[idx
].end
-= isapnp_info_device
->resource
[idx
].start
;
744 isapnp_info_device
->resource
[idx
].start
= port
;
745 isapnp_info_device
->resource
[idx
].end
+= port
;
750 static void isapnp_set_irqresource(struct resource
*res
, int irq
)
752 res
->start
= res
->end
= irq
;
753 res
->flags
= IORESOURCE_IRQ
;
756 static int isapnp_set_irq(char *line
)
759 char index
[16], value
[32];
761 line
= isapnp_get_str(index
, line
, sizeof(index
));
762 isapnp_get_str(value
, line
, sizeof(value
));
763 idx
= simple_strtoul(index
, NULL
, 0);
764 irq
= simple_strtoul(value
, NULL
, 0);
765 if (idx
< 0 || idx
> 1) {
766 printk("isapnp: wrong IRQ index %i\n", idx
);
771 if (irq
< 0 || irq
> 15) {
772 printk("isapnp: wrong IRQ value %i\n", irq
);
775 isapnp_write_byte(ISAPNP_CFG_IRQ
+ (idx
<< 1), irq
);
776 isapnp_set_irqresource(isapnp_info_device
->irq_resource
+ idx
, irq
);
780 static void isapnp_set_dmaresource(struct resource
*res
, int dma
)
782 res
->start
= res
->end
= dma
;
783 res
->flags
= IORESOURCE_DMA
;
786 static int isapnp_set_dma(char *line
)
789 char index
[16], value
[32];
791 line
= isapnp_get_str(index
, line
, sizeof(index
));
792 isapnp_get_str(value
, line
, sizeof(value
));
793 idx
= simple_strtoul(index
, NULL
, 0);
794 dma
= simple_strtoul(value
, NULL
, 0);
795 if (idx
< 0 || idx
> 1) {
796 printk("isapnp: wrong DMA index %i\n", idx
);
799 if (dma
< 0 || dma
> 7) {
800 printk("isapnp: wrong DMA value %i\n", dma
);
803 isapnp_write_byte(ISAPNP_CFG_DMA
+ idx
, dma
);
804 isapnp_set_dmaresource(isapnp_info_device
->dma_resource
+ idx
, dma
);
808 static int isapnp_set_mem(char *line
)
812 char index
[16], value
[32];
814 line
= isapnp_get_str(index
, line
, sizeof(index
));
815 isapnp_get_str(value
, line
, sizeof(value
));
816 idx
= simple_strtoul(index
, NULL
, 0);
817 mem
= simple_strtoul(value
, NULL
, 0);
818 if (idx
< 0 || idx
> 3) {
819 printk("isapnp: wrong memory index %i\n", idx
);
823 isapnp_write_word(ISAPNP_CFG_MEM
+ (idx
<<2), mem
& 0xffff);
824 if (isapnp_info_device
->resource
[idx
+ 8].start
== ISAPNP_NOTSET
)
826 if (isapnp_info_device
->resource
[idx
+ 8].start
== ISAPNP_AUTO
) {
827 isapnp_info_device
->resource
[idx
+ 8].start
= mem
& ~0x00ffff00;
828 isapnp_info_device
->resource
[idx
+ 8].end
+= (mem
& ~0x00ffff00) - 1;
830 isapnp_info_device
->resource
[idx
+ 8].end
-= isapnp_info_device
->resource
[idx
+ 8].start
;
831 isapnp_info_device
->resource
[idx
+ 8].start
= mem
& ~0x00ffff00;
832 isapnp_info_device
->resource
[idx
+ 8].end
+= mem
& ~0x00ffff00;
837 static int isapnp_poke(char *line
, int what
)
841 char index
[16], value
[32];
843 line
= isapnp_get_str(index
, line
, sizeof(index
));
844 isapnp_get_str(value
, line
, sizeof(value
));
845 reg
= simple_strtoul(index
, NULL
, 0);
846 val
= simple_strtoul(value
, NULL
, 0);
847 if (reg
< 0 || reg
> 127) {
848 printk("isapnp: wrong register %i\n", reg
);
853 isapnp_write_word(reg
, val
);
856 isapnp_write_dword(reg
, val
);
859 isapnp_write_byte(reg
, val
);
865 static int isapnp_decode_line(char *line
)
869 line
= isapnp_get_str(cmd
, line
, sizeof(cmd
));
870 if (!strcmp(cmd
, "card"))
871 return isapnp_set_card(line
);
872 if (!strcmp(cmd
, "csn"))
873 return isapnp_select_csn(line
);
874 if (!isapnp_info_card
) {
875 printk("isapnp: card is not selected\n");
878 if (!strncmp(cmd
, "dev", 3))
879 return isapnp_set_device(line
);
880 if (!isapnp_info_device
) {
881 printk("isapnp: device is not selected\n");
884 if (!strncmp(cmd
, "auto", 4))
885 return isapnp_autoconfigure();
886 if (!strncmp(cmd
, "act", 3)) {
887 isapnp_activate(isapnp_info_device
->devfn
);
888 isapnp_info_device
->active
= 1;
891 if (!strncmp(cmd
, "deact", 5)) {
892 isapnp_deactivate(isapnp_info_device
->devfn
);
893 isapnp_info_device
->active
= 0;
896 if (!strcmp(cmd
, "port"))
897 return isapnp_set_port(line
);
898 if (!strcmp(cmd
, "irq"))
899 return isapnp_set_irq(line
);
900 if (!strcmp(cmd
, "dma"))
901 return isapnp_set_dma(line
);
902 if (!strncmp(cmd
, "mem", 3))
903 return isapnp_set_mem(line
);
904 if (!strcmp(cmd
, "poke"))
905 return isapnp_poke(line
, 0);
906 if (!strcmp(cmd
, "pokew"))
907 return isapnp_poke(line
, 1);
908 if (!strcmp(cmd
, "poked"))
909 return isapnp_poke(line
, 2);
910 printk("isapnp: wrong command '%s'\n", cmd
);
918 static void isapnp_info_write(isapnp_info_buffer_t
*buffer
)
920 int c
, idx
, idx1
= 0;
923 if (buffer
->size
<= 0)
925 isapnp_info_card
= NULL
;
926 isapnp_info_device
= NULL
;
927 for (idx
= 0; idx
< buffer
->size
; idx
++) {
928 c
= buffer
->buffer
[idx
];
931 if (line
[0] != '#') {
932 if (isapnp_decode_line(line
))
938 if (idx1
>= sizeof(line
)-1) {
939 printk("isapnp: line too long, aborting\n");
945 if (isapnp_info_card
)