Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d3899e3c
Commit
d3899e3c
authored
Jun 18, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-pnp.bkbits.net/pnp-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
77518190
8397ceac
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
783 additions
and
1362 deletions
+783
-1362
drivers/pnp/base.h
drivers/pnp/base.h
+1
-19
drivers/pnp/core.c
drivers/pnp/core.c
+3
-3
drivers/pnp/interface.c
drivers/pnp/interface.c
+54
-152
drivers/pnp/isapnp/core.c
drivers/pnp/isapnp/core.c
+89
-114
drivers/pnp/manager.c
drivers/pnp/manager.c
+319
-529
drivers/pnp/pnpbios/core.c
drivers/pnp/pnpbios/core.c
+4
-0
drivers/pnp/quirks.c
drivers/pnp/quirks.c
+9
-9
drivers/pnp/resource.c
drivers/pnp/resource.c
+150
-360
drivers/pnp/support.c
drivers/pnp/support.c
+73
-68
drivers/serial/8250_pnp.c
drivers/serial/8250_pnp.c
+28
-34
include/linux/pnp.h
include/linux/pnp.h
+53
-74
No files found.
drivers/pnp/base.h
View file @
d3899e3c
...
...
@@ -4,29 +4,11 @@ void *pnp_alloc(long size);
int
pnp_interface_attach_device
(
struct
pnp_dev
*
dev
);
void
pnp_name_device
(
struct
pnp_dev
*
dev
);
void
pnp_fixup_device
(
struct
pnp_dev
*
dev
);
void
pnp_free_
resources
(
struct
pnp_resources
*
resources
);
void
pnp_free_
option
(
struct
pnp_option
*
option
);
int
__pnp_add_device
(
struct
pnp_dev
*
dev
);
void
__pnp_remove_device
(
struct
pnp_dev
*
dev
);
/* resource conflict types */
#define CONFLICT_TYPE_NONE 0x0000
/* there are no conflicts, other than those in the link */
#define CONFLICT_TYPE_RESERVED 0x0001
/* the resource requested was reserved */
#define CONFLICT_TYPE_IN_USE 0x0002
/* there is a conflict because the resource is in use */
#define CONFLICT_TYPE_PCI 0x0004
/* there is a conflict with a pci device */
#define CONFLICT_TYPE_INVALID 0x0008
/* the resource requested is invalid */
#define CONFLICT_TYPE_INTERNAL 0x0010
/* resources within the device conflict with each ohter */
#define CONFLICT_TYPE_PNP_WARM 0x0020
/* there is a conflict with a pnp device that is active */
#define CONFLICT_TYPE_PNP_COLD 0x0040
/* there is a conflict with a pnp device that is disabled */
/* conflict search modes */
#define SEARCH_WARM 1
/* check for conflicts with active devices */
#define SEARCH_COLD 0
/* check for conflicts with disabled devices */
struct
pnp_dev
*
pnp_check_port_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
);
int
pnp_check_port
(
struct
pnp_dev
*
dev
,
int
idx
);
struct
pnp_dev
*
pnp_check_mem_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
);
int
pnp_check_mem
(
struct
pnp_dev
*
dev
,
int
idx
);
struct
pnp_dev
*
pnp_check_irq_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
);
int
pnp_check_irq
(
struct
pnp_dev
*
dev
,
int
idx
);
struct
pnp_dev
*
pnp_check_dma_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
);
int
pnp_check_dma
(
struct
pnp_dev
*
dev
,
int
idx
);
drivers/pnp/core.c
View file @
d3899e3c
...
...
@@ -104,8 +104,8 @@ static void pnp_free_ids(struct pnp_dev *dev)
static
void
pnp_release_device
(
struct
device
*
dmdev
)
{
struct
pnp_dev
*
dev
=
to_pnp_dev
(
dmdev
);
if
(
dev
->
possible
)
pnp_free_resources
(
dev
->
possible
);
pnp_free_option
(
dev
->
independent
);
pnp_free_option
(
dev
->
dependent
);
pnp_free_ids
(
dev
);
kfree
(
dev
);
}
...
...
@@ -122,7 +122,7 @@ int __pnp_add_device(struct pnp_dev *dev)
list_add_tail
(
&
dev
->
global_list
,
&
pnp_global
);
list_add_tail
(
&
dev
->
protocol_list
,
&
dev
->
protocol
->
devices
);
spin_unlock
(
&
pnp_lock
);
pnp_auto_config_dev
(
dev
);
ret
=
device_register
(
&
dev
->
dev
);
if
(
ret
==
0
)
pnp_interface_attach_device
(
dev
);
...
...
drivers/pnp/interface.c
View file @
d3899e3c
...
...
@@ -168,7 +168,8 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem
pnp_printf
(
buffer
,
", %s
\n
"
,
s
);
}
static
void
pnp_print_resources
(
pnp_info_buffer_t
*
buffer
,
char
*
space
,
struct
pnp_resources
*
res
,
int
dep
)
static
void
pnp_print_option
(
pnp_info_buffer_t
*
buffer
,
char
*
space
,
struct
pnp_option
*
option
,
int
dep
)
{
char
*
s
;
struct
pnp_port
*
port
;
...
...
@@ -176,7 +177,8 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
struct
pnp_dma
*
dma
;
struct
pnp_mem
*
mem
;
switch
(
res
->
priority
)
{
if
(
dep
)
{
switch
(
option
->
priority
)
{
case
PNP_RES_PRIORITY_PREFERRED
:
s
=
"preferred"
;
break
;
...
...
@@ -189,36 +191,41 @@ static void pnp_print_resources(pnp_info_buffer_t *buffer, char *space, struct p
default:
s
=
"invalid"
;
}
if
(
dep
>
0
)
pnp_printf
(
buffer
,
"Dependent: %02i - Priority %s
\n
"
,
dep
,
s
);
for
(
port
=
res
->
port
;
port
;
port
=
port
->
next
)
}
for
(
port
=
option
->
port
;
port
;
port
=
port
->
next
)
pnp_print_port
(
buffer
,
space
,
port
);
for
(
irq
=
res
->
irq
;
irq
;
irq
=
irq
->
next
)
for
(
irq
=
option
->
irq
;
irq
;
irq
=
irq
->
next
)
pnp_print_irq
(
buffer
,
space
,
irq
);
for
(
dma
=
res
->
dma
;
dma
;
dma
=
dma
->
next
)
for
(
dma
=
option
->
dma
;
dma
;
dma
=
dma
->
next
)
pnp_print_dma
(
buffer
,
space
,
dma
);
for
(
mem
=
res
->
mem
;
mem
;
mem
=
mem
->
next
)
for
(
mem
=
option
->
mem
;
mem
;
mem
=
mem
->
next
)
pnp_print_mem
(
buffer
,
space
,
mem
);
}
static
ssize_t
pnp_show_possible_resources
(
struct
device
*
dmdev
,
char
*
buf
)
static
ssize_t
pnp_show_options
(
struct
device
*
dmdev
,
char
*
buf
)
{
struct
pnp_dev
*
dev
=
to_pnp_dev
(
dmdev
);
struct
pnp_resources
*
res
=
dev
->
possible
;
int
ret
,
dep
=
0
;
struct
pnp_option
*
independent
=
dev
->
independent
;
struct
pnp_option
*
dependent
=
dev
->
dependent
;
int
ret
,
dep
=
1
;
pnp_info_buffer_t
*
buffer
=
(
pnp_info_buffer_t
*
)
pnp_alloc
(
sizeof
(
pnp_info_buffer_t
));
if
(
!
buffer
)
return
-
ENOMEM
;
buffer
->
len
=
PAGE_SIZE
;
buffer
->
buffer
=
buf
;
buffer
->
curr
=
buffer
->
buffer
;
while
(
res
){
if
(
dep
==
0
)
pnp_print_resources
(
buffer
,
""
,
res
,
dep
);
else
pnp_print_resources
(
buffer
,
" "
,
res
,
dep
);
res
=
res
->
dep
;
if
(
independent
)
pnp_print_option
(
buffer
,
""
,
independent
,
0
);
while
(
dependent
){
pnp_print_option
(
buffer
,
" "
,
dependent
,
dep
);
dependent
=
dependent
->
next
;
dep
++
;
}
ret
=
(
buffer
->
curr
-
buf
);
...
...
@@ -226,97 +233,8 @@ static ssize_t pnp_show_possible_resources(struct device *dmdev, char *buf)
return
ret
;
}
static
DEVICE_ATTR
(
possible
,
S_IRUGO
,
pnp_show_possible_resources
,
NULL
);
static
void
pnp_print_conflict_node
(
pnp_info_buffer_t
*
buffer
,
struct
pnp_dev
*
dev
)
{
if
(
!
dev
)
return
;
pnp_printf
(
buffer
,
"'%s'.
\n
"
,
dev
->
dev
.
bus_id
);
}
static
void
pnp_print_conflict_desc
(
pnp_info_buffer_t
*
buffer
,
int
conflict
)
{
if
(
!
conflict
)
return
;
pnp_printf
(
buffer
,
" Conflict Detected: %2x - "
,
conflict
);
switch
(
conflict
)
{
case
CONFLICT_TYPE_RESERVED
:
pnp_printf
(
buffer
,
"manually reserved.
\n
"
);
break
;
case
CONFLICT_TYPE_IN_USE
:
pnp_printf
(
buffer
,
"currently in use.
\n
"
);
break
;
case
CONFLICT_TYPE_PCI
:
pnp_printf
(
buffer
,
"PCI device.
\n
"
);
break
;
case
CONFLICT_TYPE_INVALID
:
pnp_printf
(
buffer
,
"invalid.
\n
"
);
break
;
case
CONFLICT_TYPE_INTERNAL
:
pnp_printf
(
buffer
,
"another resource on this device.
\n
"
);
break
;
static
DEVICE_ATTR
(
options
,
S_IRUGO
,
pnp_show_options
,
NULL
);
case
CONFLICT_TYPE_PNP_WARM
:
pnp_printf
(
buffer
,
"active PnP device "
);
break
;
case
CONFLICT_TYPE_PNP_COLD
:
pnp_printf
(
buffer
,
"disabled PnP device "
);
break
;
default:
pnp_printf
(
buffer
,
"Unknown conflict.
\n
"
);
break
;
}
}
static
void
pnp_print_conflict
(
pnp_info_buffer_t
*
buffer
,
struct
pnp_dev
*
dev
,
int
idx
,
int
type
)
{
struct
pnp_dev
*
cdev
,
*
wdev
=
NULL
;
int
conflict
;
switch
(
type
)
{
case
IORESOURCE_IO
:
conflict
=
pnp_check_port
(
dev
,
idx
);
if
(
conflict
==
CONFLICT_TYPE_PNP_WARM
)
wdev
=
pnp_check_port_conflicts
(
dev
,
idx
,
SEARCH_WARM
);
cdev
=
pnp_check_port_conflicts
(
dev
,
idx
,
SEARCH_COLD
);
break
;
case
IORESOURCE_MEM
:
conflict
=
pnp_check_mem
(
dev
,
idx
);
if
(
conflict
==
CONFLICT_TYPE_PNP_WARM
)
wdev
=
pnp_check_mem_conflicts
(
dev
,
idx
,
SEARCH_WARM
);
cdev
=
pnp_check_mem_conflicts
(
dev
,
idx
,
SEARCH_COLD
);
break
;
case
IORESOURCE_IRQ
:
conflict
=
pnp_check_irq
(
dev
,
idx
);
if
(
conflict
==
CONFLICT_TYPE_PNP_WARM
)
wdev
=
pnp_check_irq_conflicts
(
dev
,
idx
,
SEARCH_WARM
);
cdev
=
pnp_check_irq_conflicts
(
dev
,
idx
,
SEARCH_COLD
);
break
;
case
IORESOURCE_DMA
:
conflict
=
pnp_check_dma
(
dev
,
idx
);
if
(
conflict
==
CONFLICT_TYPE_PNP_WARM
)
wdev
=
pnp_check_dma_conflicts
(
dev
,
idx
,
SEARCH_WARM
);
cdev
=
pnp_check_dma_conflicts
(
dev
,
idx
,
SEARCH_COLD
);
break
;
default:
return
;
}
pnp_print_conflict_desc
(
buffer
,
conflict
);
if
(
wdev
)
pnp_print_conflict_node
(
buffer
,
wdev
);
if
(
cdev
)
{
pnp_print_conflict_desc
(
buffer
,
CONFLICT_TYPE_PNP_COLD
);
pnp_print_conflict_node
(
buffer
,
cdev
);
}
}
static
ssize_t
pnp_show_current_resources
(
struct
device
*
dmdev
,
char
*
buf
)
{
...
...
@@ -332,12 +250,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
buffer
->
buffer
=
buf
;
buffer
->
curr
=
buffer
->
buffer
;
pnp_printf
(
buffer
,
"mode = "
);
if
(
dev
->
config_mode
&
PNP_CONFIG_MANUAL
)
pnp_printf
(
buffer
,
"manual
\n
"
);
else
pnp_printf
(
buffer
,
"auto
\n
"
);
pnp_printf
(
buffer
,
"state = "
);
if
(
dev
->
active
)
pnp_printf
(
buffer
,
"active
\n
"
);
...
...
@@ -350,7 +262,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
pnp_printf
(
buffer
,
" 0x%lx-0x%lx
\n
"
,
pnp_port_start
(
dev
,
i
),
pnp_port_end
(
dev
,
i
));
pnp_print_conflict
(
buffer
,
dev
,
i
,
IORESOURCE_IO
);
}
}
for
(
i
=
0
;
i
<
PNP_MAX_MEM
;
i
++
)
{
...
...
@@ -359,21 +270,18 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
pnp_printf
(
buffer
,
" 0x%lx-0x%lx
\n
"
,
pnp_mem_start
(
dev
,
i
),
pnp_mem_end
(
dev
,
i
));
pnp_print_conflict
(
buffer
,
dev
,
i
,
IORESOURCE_MEM
);
}
}
for
(
i
=
0
;
i
<
PNP_MAX_IRQ
;
i
++
)
{
if
(
pnp_irq_valid
(
dev
,
i
))
{
pnp_printf
(
buffer
,
"irq"
);
pnp_printf
(
buffer
,
" %ld
\n
"
,
pnp_irq
(
dev
,
i
));
pnp_print_conflict
(
buffer
,
dev
,
i
,
IORESOURCE_IRQ
);
}
}
for
(
i
=
0
;
i
<
PNP_MAX_DMA
;
i
++
)
{
if
(
pnp_dma_valid
(
dev
,
i
))
{
pnp_printf
(
buffer
,
"dma"
);
pnp_printf
(
buffer
,
" %ld
\n
"
,
pnp_dma
(
dev
,
i
));
pnp_print_conflict
(
buffer
,
dev
,
i
,
IORESOURCE_DMA
);
}
}
ret
=
(
buffer
->
curr
-
buf
);
...
...
@@ -381,7 +289,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
return
ret
;
}
extern
int
pnp_resolve_conflicts
(
struct
pnp_dev
*
dev
)
;
extern
struct
semaphore
pnp_res_mutex
;
static
ssize_t
pnp_set_current_resources
(
struct
device
*
dmdev
,
const
char
*
ubuf
,
size_t
count
)
...
...
@@ -390,6 +298,12 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
char
*
buf
=
(
void
*
)
ubuf
;
int
retval
=
0
;
if
(
dev
->
status
&
PNP_ATTACHED
)
{
retval
=
-
EBUSY
;
pnp_info
(
"Device %s cannot be configured because it is in use."
,
dev
->
dev
.
bus_id
);
goto
done
;
}
while
(
isspace
(
*
buf
))
++
buf
;
if
(
!
strnicmp
(
buf
,
"disable"
,
7
))
{
...
...
@@ -400,41 +314,30 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
retval
=
pnp_activate_dev
(
dev
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"reset"
,
5
))
{
if
(
!
dev
->
active
)
goto
done
;
retval
=
pnp_disable_dev
(
dev
);
if
(
retval
)
if
(
!
strnicmp
(
buf
,
"fill"
,
4
))
{
if
(
dev
->
active
)
goto
done
;
retval
=
pnp_a
ctivate
_dev
(
dev
);
retval
=
pnp_a
uto_config
_dev
(
dev
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"auto"
,
4
))
{
if
(
dev
->
active
)
goto
done
;
pnp_init_resources
(
&
dev
->
res
);
retval
=
pnp_auto_config_dev
(
dev
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"clear"
,
5
))
{
if
(
dev
->
active
)
goto
done
;
spin_lock
(
&
pnp_lock
);
dev
->
config_mode
=
PNP_CONFIG_MANUAL
;
pnp_init_resource_table
(
&
dev
->
res
);
if
(
dev
->
rule
)
dev
->
rule
->
depnum
=
0
;
spin_unlock
(
&
pnp_lock
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"resolve"
,
7
))
{
retval
=
pnp_resolve_conflicts
(
dev
);
pnp_init_resources
(
&
dev
->
res
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"get"
,
3
))
{
spin_lock
(
&
pnp_lock
);
down
(
&
pnp_res_mutex
);
if
(
pnp_can_read
(
dev
))
dev
->
protocol
->
get
(
dev
,
&
dev
->
res
);
spin_unlock
(
&
pnp_lock
);
up
(
&
pnp_res_mutex
);
goto
done
;
}
if
(
!
strnicmp
(
buf
,
"set"
,
3
))
{
...
...
@@ -442,9 +345,8 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
if
(
dev
->
active
)
goto
done
;
buf
+=
3
;
spin_lock
(
&
pnp_lock
);
dev
->
config_mode
=
PNP_CONFIG_MANUAL
;
pnp_init_resource_table
(
&
dev
->
res
);
pnp_init_resources
(
&
dev
->
res
);
down
(
&
pnp_res_mutex
);
while
(
1
)
{
while
(
isspace
(
*
buf
))
++
buf
;
...
...
@@ -514,7 +416,7 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
}
break
;
}
spin_unlock
(
&
pnp_lock
);
up
(
&
pnp_res_mutex
);
goto
done
;
}
done:
...
...
@@ -543,7 +445,7 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL);
int
pnp_interface_attach_device
(
struct
pnp_dev
*
dev
)
{
device_create_file
(
&
dev
->
dev
,
&
dev_attr_
possible
);
device_create_file
(
&
dev
->
dev
,
&
dev_attr_
options
);
device_create_file
(
&
dev
->
dev
,
&
dev_attr_resources
);
device_create_file
(
&
dev
->
dev
,
&
dev_attr_id
);
return
0
;
...
...
drivers/pnp/isapnp/core.c
View file @
d3899e3c
...
...
@@ -31,6 +31,7 @@
* 2002-06-06 Made the use of dma channel 0 configurable
* Gerald Teschl <gerald.teschl@univie.ac.at>
* 2002-10-06 Ported to PnP Layer - Adam Belay <ambx1@neo.rr.com>
* 2003-08-11 Resource Management Updates - Adam Belay <ambx1@neo.rr.com>
*/
#include <linux/config.h>
...
...
@@ -54,7 +55,6 @@
int
isapnp_disable
;
/* Disable ISA PnP */
int
isapnp_rdp
;
/* Read Data Port */
int
isapnp_reset
=
1
;
/* reset all PnP cards (deactivate) */
int
isapnp_skip_pci_scan
;
/* skip PCI resource scanning */
int
isapnp_verbose
=
1
;
/* verbose mode */
MODULE_AUTHOR
(
"Jaroslav Kysela <perex@suse.cz>"
);
...
...
@@ -66,8 +66,6 @@ MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
MODULE_PARM
(
isapnp_reset
,
"i"
);
MODULE_PARM_DESC
(
isapnp_reset
,
"ISA Plug & Play reset all cards"
);
MODULE_PARM
(
isapnp_allow_dma0
,
"i"
);
MODULE_PARM
(
isapnp_skip_pci_scan
,
"i"
);
MODULE_PARM_DESC
(
isapnp_skip_pci_scan
,
"ISA Plug & Play skip PCI resource scanning"
);
MODULE_PARM
(
isapnp_verbose
,
"i"
);
MODULE_PARM_DESC
(
isapnp_verbose
,
"ISA Plug & Play verbose mode"
);
MODULE_LICENSE
(
"GPL"
);
...
...
@@ -460,6 +458,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
dev
->
capabilities
|=
PNP_READ
;
dev
->
capabilities
|=
PNP_WRITE
;
dev
->
capabilities
|=
PNP_DISABLE
;
pnp_init_resources
(
&
dev
->
res
);
return
dev
;
}
...
...
@@ -468,8 +467,8 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si
* Add IRQ resource to resources list.
*/
static
void
__init
isapnp_
add_irq_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_irq_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
3
];
struct
pnp_irq
*
irq
;
...
...
@@ -483,7 +482,7 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev,
irq
->
flags
=
tmp
[
2
];
else
irq
->
flags
=
IORESOURCE_IRQ_HIGHEDGE
;
pnp_
add_irq_resource
(
dev
,
depnum
,
irq
);
pnp_
register_irq_resource
(
option
,
irq
);
return
;
}
...
...
@@ -491,8 +490,8 @@ static void __init isapnp_add_irq_resource(struct pnp_dev *dev,
* Add DMA resource to resources list.
*/
static
void
__init
isapnp_
add_dma_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_dma_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
2
];
struct
pnp_dma
*
dma
;
...
...
@@ -503,7 +502,7 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev,
return
;
dma
->
map
=
tmp
[
0
];
dma
->
flags
=
tmp
[
1
];
pnp_
add_dma_resource
(
dev
,
depnum
,
dma
);
pnp_
register_dma_resource
(
option
,
dma
);
return
;
}
...
...
@@ -511,8 +510,8 @@ static void __init isapnp_add_dma_resource(struct pnp_dev *dev,
* Add port resource to resources list.
*/
static
void
__init
isapnp_
add_port_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_port_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
7
];
struct
pnp_port
*
port
;
...
...
@@ -526,7 +525,7 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev,
port
->
align
=
tmp
[
5
];
port
->
size
=
tmp
[
6
];
port
->
flags
=
tmp
[
0
]
?
PNP_PORT_FLAG_16BITADDR
:
0
;
pnp_
add_port_resource
(
dev
,
depnum
,
port
);
pnp_
register_port_resource
(
option
,
port
);
return
;
}
...
...
@@ -534,8 +533,8 @@ static void __init isapnp_add_port_resource(struct pnp_dev *dev,
* Add fixed port resource to resources list.
*/
static
void
__init
isapnp_
add_fixed_port_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_fixed_port_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
3
];
struct
pnp_port
*
port
;
...
...
@@ -548,7 +547,7 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
port
->
size
=
tmp
[
2
];
port
->
align
=
0
;
port
->
flags
=
PNP_PORT_FLAG_FIXED
;
pnp_
add_port_resource
(
dev
,
depnum
,
port
);
pnp_
register_port_resource
(
option
,
port
);
return
;
}
...
...
@@ -556,8 +555,8 @@ static void __init isapnp_add_fixed_port_resource(struct pnp_dev *dev,
* Add memory resource to resources list.
*/
static
void
__init
isapnp_
add_mem_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_mem_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
9
];
struct
pnp_mem
*
mem
;
...
...
@@ -571,7 +570,7 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev,
mem
->
align
=
(
tmp
[
6
]
<<
8
)
|
tmp
[
5
];
mem
->
size
=
((
tmp
[
8
]
<<
8
)
|
tmp
[
7
])
<<
8
;
mem
->
flags
=
tmp
[
0
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
pnp_
register_mem_resource
(
option
,
mem
);
return
;
}
...
...
@@ -579,8 +578,8 @@ static void __init isapnp_add_mem_resource(struct pnp_dev *dev,
* Add 32-bit memory resource to resources list.
*/
static
void
__init
isapnp_
add_mem32_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_mem32_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
17
];
struct
pnp_mem
*
mem
;
...
...
@@ -594,15 +593,15 @@ static void __init isapnp_add_mem32_resource(struct pnp_dev *dev,
mem
->
align
=
(
tmp
[
12
]
<<
24
)
|
(
tmp
[
11
]
<<
16
)
|
(
tmp
[
10
]
<<
8
)
|
tmp
[
9
];
mem
->
size
=
(
tmp
[
16
]
<<
24
)
|
(
tmp
[
15
]
<<
16
)
|
(
tmp
[
14
]
<<
8
)
|
tmp
[
13
];
mem
->
flags
=
tmp
[
0
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
pnp_
register_mem_resource
(
option
,
mem
);
}
/*
* Add 32-bit fixed memory resource to resources list.
*/
static
void
__init
isapnp_
add_fixed_mem32_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
int
size
)
static
void
__init
isapnp_
parse_fixed_mem32_resource
(
struct
pnp_option
*
option
,
int
size
)
{
unsigned
char
tmp
[
9
];
struct
pnp_mem
*
mem
;
...
...
@@ -615,7 +614,7 @@ static void __init isapnp_add_fixed_mem32_resource(struct pnp_dev *dev,
mem
->
size
=
(
tmp
[
8
]
<<
24
)
|
(
tmp
[
7
]
<<
16
)
|
(
tmp
[
6
]
<<
8
)
|
tmp
[
5
];
mem
->
align
=
0
;
mem
->
flags
=
tmp
[
0
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
pnp_
register_mem_resource
(
option
,
mem
);
}
/*
...
...
@@ -644,14 +643,17 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
static
int
__init
isapnp_create_device
(
struct
pnp_card
*
card
,
unsigned
short
size
)
{
int
number
=
0
,
skip
=
0
,
depnum
=
0
,
dependent
=
0
,
compat
=
0
;
int
number
=
0
,
skip
=
0
,
priority
=
0
,
compat
=
0
;
unsigned
char
type
,
tmp
[
17
];
struct
pnp_option
*
option
;
struct
pnp_dev
*
dev
;
if
((
dev
=
isapnp_parse_device
(
card
,
size
,
number
++
))
==
NULL
)
return
1
;
if
(
pnp_build_resource
(
dev
,
0
)
==
NULL
)
option
=
pnp_register_independent_option
(
dev
);
if
(
!
option
)
return
1
;
pnp_add_card_device
(
card
,
dev
);
while
(
1
)
{
if
(
isapnp_read_tag
(
&
type
,
&
size
)
<
0
)
return
1
;
...
...
@@ -662,15 +664,16 @@ static int __init isapnp_create_device(struct pnp_card *card,
if
(
size
>=
5
&&
size
<=
6
)
{
if
((
dev
=
isapnp_parse_device
(
card
,
size
,
number
++
))
==
NULL
)
return
1
;
pnp_build_resource
(
dev
,
0
);
pnp_add_card_device
(
card
,
dev
);
size
=
0
;
skip
=
0
;
option
=
pnp_register_independent_option
(
dev
);
if
(
!
option
)
return
1
;
pnp_add_card_device
(
card
,
dev
);
}
else
{
skip
=
1
;
}
dependent
=
0
;
depnum
=
0
;
priority
=
0
;
compat
=
0
;
break
;
case
_STAG_COMPATDEVID
:
...
...
@@ -684,43 +687,43 @@ static int __init isapnp_create_device(struct pnp_card *card,
case
_STAG_IRQ
:
if
(
size
<
2
||
size
>
3
)
goto
__skip
;
isapnp_
add_irq_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_irq_resource
(
option
,
size
);
size
=
0
;
break
;
case
_STAG_DMA
:
if
(
size
!=
2
)
goto
__skip
;
isapnp_
add_dma_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_dma_resource
(
option
,
size
);
size
=
0
;
break
;
case
_STAG_STARTDEP
:
if
(
size
>
1
)
goto
__skip
;
dependent
=
0x100
|
PNP_RES_PRIORITY_ACCEPTABLE
;
priority
=
0x100
|
PNP_RES_PRIORITY_ACCEPTABLE
;
if
(
size
>
0
)
{
isapnp_peek
(
tmp
,
size
);
dependent
=
0x100
|
tmp
[
0
];
priority
=
0x100
|
tmp
[
0
];
size
=
0
;
}
pnp_build_resource
(
dev
,
dependent
);
depnum
=
pnp_get_max_depnum
(
dev
);
option
=
pnp_register_dependent_option
(
dev
,
priority
);
if
(
!
option
)
return
1
;
break
;
case
_STAG_ENDDEP
:
if
(
size
!=
0
)
goto
__skip
;
dependent
=
0
;
depnum
=
0
;
priority
=
0
;
break
;
case
_STAG_IOPORT
:
if
(
size
!=
7
)
goto
__skip
;
isapnp_
add_port_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_port_resource
(
option
,
size
);
size
=
0
;
break
;
case
_STAG_FIXEDIO
:
if
(
size
!=
3
)
goto
__skip
;
isapnp_
add_fixed_port_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_fixed_port_resource
(
option
,
size
);
size
=
0
;
break
;
case
_STAG_VENDOR
:
...
...
@@ -728,7 +731,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
case
_LTAG_MEMRANGE
:
if
(
size
!=
9
)
goto
__skip
;
isapnp_
add_mem_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_mem_resource
(
option
,
size
);
size
=
0
;
break
;
case
_LTAG_ANSISTR
:
...
...
@@ -743,13 +746,13 @@ static int __init isapnp_create_device(struct pnp_card *card,
case
_LTAG_MEM32RANGE
:
if
(
size
!=
17
)
goto
__skip
;
isapnp_
add_mem32_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_mem32_resource
(
option
,
size
);
size
=
0
;
break
;
case
_LTAG_FIXEDMEM32RANGE
:
if
(
size
!=
9
)
goto
__skip
;
isapnp_
add_fixed_mem32_resource
(
dev
,
depnum
,
size
);
isapnp_
parse_fixed_mem32_resource
(
option
,
size
);
size
=
0
;
break
;
case
_STAG_END
:
...
...
@@ -859,63 +862,6 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor,
pnp_add_card_id
(
id
,
card
);
}
static
int
isapnp_parse_current_resources
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
)
{
int
tmp
,
ret
;
struct
pnp_rule_table
rule
;
if
(
dev
->
rule
)
rule
=
*
dev
->
rule
;
else
{
if
(
!
pnp_generate_rule
(
dev
,
1
,
&
rule
))
return
-
EINVAL
;
}
dev
->
active
=
isapnp_read_byte
(
ISAPNP_CFG_ACTIVATE
);
if
(
dev
->
active
)
{
for
(
tmp
=
0
;
tmp
<
PNP_MAX_PORT
;
tmp
++
)
{
ret
=
isapnp_read_word
(
ISAPNP_CFG_PORT
+
(
tmp
<<
1
));
if
(
!
ret
)
continue
;
res
->
port_resource
[
tmp
].
start
=
ret
;
if
(
rule
.
port
[
tmp
])
res
->
port_resource
[
tmp
].
end
=
ret
+
rule
.
port
[
tmp
]
->
size
-
1
;
else
res
->
port_resource
[
tmp
].
end
=
ret
+
1
;
/* all we can do is assume 1 :-( */
res
->
port_resource
[
tmp
].
flags
=
IORESOURCE_IO
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_MEM
;
tmp
++
)
{
ret
=
isapnp_read_dword
(
ISAPNP_CFG_MEM
+
(
tmp
<<
3
));
if
(
!
ret
)
continue
;
res
->
mem_resource
[
tmp
].
start
=
ret
;
if
(
rule
.
mem
[
tmp
])
res
->
mem_resource
[
tmp
].
end
=
ret
+
rule
.
mem
[
tmp
]
->
size
-
1
;
else
res
->
mem_resource
[
tmp
].
end
=
ret
+
1
;
/* all we can do is assume 1 :-( */
res
->
mem_resource
[
tmp
].
flags
=
IORESOURCE_MEM
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_IRQ
;
tmp
++
)
{
ret
=
(
isapnp_read_word
(
ISAPNP_CFG_IRQ
+
(
tmp
<<
1
))
>>
8
);
if
(
!
ret
)
continue
;
res
->
irq_resource
[
tmp
].
start
=
res
->
irq_resource
[
tmp
].
end
=
ret
;
res
->
irq_resource
[
tmp
].
flags
=
IORESOURCE_IRQ
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_DMA
;
tmp
++
)
{
ret
=
isapnp_read_byte
(
ISAPNP_CFG_DMA
+
tmp
);
if
(
ret
==
4
)
continue
;
if
(
rule
.
dma
[
tmp
])
{
/* some isapnp systems forget to set this to 4 so we have to check */
res
->
dma_resource
[
tmp
].
start
=
res
->
dma_resource
[
tmp
].
end
=
ret
;
res
->
dma_resource
[
tmp
].
flags
=
IORESOURCE_DMA
;
}
}
}
return
0
;
}
/*
* Build device list for all present ISA PnP devices.
*/
...
...
@@ -925,7 +871,6 @@ static int __init isapnp_build_device_list(void)
int
csn
;
unsigned
char
header
[
9
],
checksum
;
struct
pnp_card
*
card
;
struct
pnp_dev
*
dev
;
isapnp_wait
();
isapnp_key
();
...
...
@@ -959,13 +904,6 @@ static int __init isapnp_build_device_list(void)
card
->
checksum
=
isapnp_checksum_value
;
card
->
protocol
=
&
isapnp_protocol
;
/* read the current resource data */
card_for_each_dev
(
card
,
dev
)
{
isapnp_device
(
dev
->
number
);
pnp_init_resource_table
(
&
dev
->
res
);
isapnp_parse_current_resources
(
dev
,
&
dev
->
res
);
}
pnp_add_card
(
card
);
}
isapnp_wait
();
...
...
@@ -1041,12 +979,50 @@ EXPORT_SYMBOL(isapnp_write_dword);
EXPORT_SYMBOL
(
isapnp_wake
);
EXPORT_SYMBOL
(
isapnp_device
);
static
int
isapnp_read_resources
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
)
{
int
tmp
,
ret
;
dev
->
active
=
isapnp_read_byte
(
ISAPNP_CFG_ACTIVATE
);
if
(
dev
->
active
)
{
for
(
tmp
=
0
;
tmp
<
PNP_MAX_PORT
;
tmp
++
)
{
ret
=
isapnp_read_word
(
ISAPNP_CFG_PORT
+
(
tmp
<<
1
));
if
(
!
ret
)
continue
;
res
->
port_resource
[
tmp
].
start
=
ret
;
res
->
port_resource
[
tmp
].
flags
=
IORESOURCE_IO
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_MEM
;
tmp
++
)
{
ret
=
isapnp_read_dword
(
ISAPNP_CFG_MEM
+
(
tmp
<<
3
));
if
(
!
ret
)
continue
;
res
->
mem_resource
[
tmp
].
start
=
ret
;
res
->
mem_resource
[
tmp
].
flags
=
IORESOURCE_MEM
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_IRQ
;
tmp
++
)
{
ret
=
(
isapnp_read_word
(
ISAPNP_CFG_IRQ
+
(
tmp
<<
1
))
>>
8
);
if
(
!
ret
)
continue
;
res
->
irq_resource
[
tmp
].
start
=
res
->
irq_resource
[
tmp
].
end
=
ret
;
res
->
irq_resource
[
tmp
].
flags
=
IORESOURCE_IRQ
;
}
for
(
tmp
=
0
;
tmp
<
PNP_MAX_DMA
;
tmp
++
)
{
ret
=
isapnp_read_byte
(
ISAPNP_CFG_DMA
+
tmp
);
if
(
ret
==
4
)
continue
;
res
->
dma_resource
[
tmp
].
start
=
res
->
dma_resource
[
tmp
].
end
=
ret
;
res
->
dma_resource
[
tmp
].
flags
=
IORESOURCE_DMA
;
}
}
return
0
;
}
static
int
isapnp_get_resources
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
)
{
int
ret
;
pnp_init_resource
_table
(
res
);
pnp_init_resource
s
(
res
);
isapnp_cfg_begin
(
dev
->
card
->
number
,
dev
->
number
);
ret
=
isapnp_
parse_current
_resources
(
dev
,
res
);
ret
=
isapnp_
read
_resources
(
dev
,
res
);
isapnp_cfg_end
();
return
ret
;
}
...
...
@@ -1196,7 +1172,6 @@ static int __init isapnp_setup_isapnp(char *str)
{
(
void
)((
get_option
(
&
str
,
&
isapnp_rdp
)
==
2
)
&&
(
get_option
(
&
str
,
&
isapnp_reset
)
==
2
)
&&
(
get_option
(
&
str
,
&
isapnp_skip_pci_scan
)
==
2
)
&&
(
get_option
(
&
str
,
&
isapnp_verbose
)
==
2
));
return
1
;
}
...
...
drivers/pnp/manager.c
View file @
d3899e3c
/*
* manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
*
* based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
* Copyright 2003 Adam Belay <ambx1@neo.rr.com>
*
*/
...
...
@@ -20,551 +21,341 @@
#include <linux/pnp.h>
#include "base.h"
DECLARE_MUTEX
(
pnp_res_mutex
);
int
pnp_max_moves
=
4
;
static
int
pnp_next_port
(
struct
pnp_dev
*
dev
,
int
idx
)
static
int
pnp_assign_port
(
struct
pnp_dev
*
dev
,
struct
pnp_port
*
rule
,
int
idx
)
{
struct
pnp_port
*
port
;
unsigned
long
*
start
,
*
end
,
*
flags
;
if
(
!
dev
||
idx
<
0
||
idx
>=
PNP_MAX_PORT
)
return
0
;
port
=
dev
->
rule
->
port
[
idx
];
if
(
!
port
)
if
(
!
dev
||
!
rule
)
return
-
EINVAL
;
if
(
idx
>=
PNP_MAX_PORT
)
{
pnp_err
(
"More than 4 ports is incompatible with pnp specifications."
);
/* pretend we were successful so at least the manager won't try again */
return
1
;
}
/* check if this resource has been manually set, if so skip */
if
(
!
(
dev
->
res
.
port_resource
[
idx
].
flags
&
IORESOURCE_AUTO
))
return
1
;
start
=
&
dev
->
res
.
port_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
port_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
port_resource
[
idx
].
flags
;
/* set the initial values if this is the first time */
if
(
*
start
==
0
)
{
*
start
=
port
->
min
;
*
end
=
*
start
+
port
->
size
-
1
;
*
flags
=
port
->
flags
|
IORESOURCE_IO
;
if
(
!
pnp_check_port
(
dev
,
idx
))
return
1
;
}
/* set the initial values */
*
start
=
rule
->
min
;
*
end
=
*
start
+
rule
->
size
-
1
;
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_IO
;
/* run through until pnp_check_port is happy */
do
{
*
start
+=
port
->
align
;
*
end
=
*
start
+
port
->
size
-
1
;
if
(
*
start
>
port
->
max
||
!
port
->
align
)
while
(
!
pnp_check_port
(
dev
,
idx
))
{
*
start
+=
rule
->
align
;
*
end
=
*
start
+
rule
->
size
-
1
;
if
(
*
start
>
rule
->
max
||
!
rule
->
align
)
return
0
;
}
while
(
pnp_check_port
(
dev
,
idx
));
}
return
1
;
}
static
int
pnp_
next_mem
(
struct
pnp_dev
*
dev
,
int
idx
)
static
int
pnp_
assign_mem
(
struct
pnp_dev
*
dev
,
struct
pnp_mem
*
rule
,
int
idx
)
{
struct
pnp_mem
*
mem
;
unsigned
long
*
start
,
*
end
,
*
flags
;
if
(
!
dev
||
idx
<
0
||
idx
>=
PNP_MAX_MEM
)
return
0
;
mem
=
dev
->
rule
->
mem
[
idx
];
if
(
!
mem
)
if
(
!
dev
||
!
rule
)
return
-
EINVAL
;
if
(
idx
>=
PNP_MAX_MEM
)
{
pnp_err
(
"More than 8 mems is incompatible with pnp specifications."
);
/* pretend we were successful so at least the manager won't try again */
return
1
;
}
/* check if this resource has been manually set, if so skip */
if
(
!
(
dev
->
res
.
mem_resource
[
idx
].
flags
&
IORESOURCE_AUTO
))
return
1
;
start
=
&
dev
->
res
.
mem_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
mem_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
mem_resource
[
idx
].
flags
;
/* set the initial values if this is the first time */
if
(
*
start
==
0
)
{
*
start
=
mem
->
min
;
*
end
=
*
start
+
mem
->
size
-
1
;
*
flags
=
mem
->
flags
|
IORESOURCE_MEM
;
if
(
!
(
mem
->
flags
&
IORESOURCE_MEM_WRITEABLE
))
/* set the initial values */
*
start
=
rule
->
min
;
*
end
=
*
start
+
rule
->
size
-
1
;
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_MEM
;
/* convert pnp flags to standard Linux flags */
if
(
!
(
rule
->
flags
&
IORESOURCE_MEM_WRITEABLE
))
*
flags
|=
IORESOURCE_READONLY
;
if
(
mem
->
flags
&
IORESOURCE_MEM_CACHEABLE
)
if
(
rule
->
flags
&
IORESOURCE_MEM_CACHEABLE
)
*
flags
|=
IORESOURCE_CACHEABLE
;
if
(
mem
->
flags
&
IORESOURCE_MEM_RANGELENGTH
)
if
(
rule
->
flags
&
IORESOURCE_MEM_RANGELENGTH
)
*
flags
|=
IORESOURCE_RANGELENGTH
;
if
(
mem
->
flags
&
IORESOURCE_MEM_SHADOWABLE
)
if
(
rule
->
flags
&
IORESOURCE_MEM_SHADOWABLE
)
*
flags
|=
IORESOURCE_SHADOWABLE
;
if
(
!
pnp_check_mem
(
dev
,
idx
))
return
1
;
}
/* run through until pnp_check_mem is happy */
do
{
*
start
+=
mem
->
align
;
*
end
=
*
start
+
mem
->
size
-
1
;
if
(
*
start
>
mem
->
max
||
!
mem
->
align
)
while
(
!
pnp_check_mem
(
dev
,
idx
))
{
*
start
+=
rule
->
align
;
*
end
=
*
start
+
rule
->
size
-
1
;
if
(
*
start
>
rule
->
max
||
!
rule
->
align
)
return
0
;
}
while
(
pnp_check_mem
(
dev
,
idx
));
}
return
1
;
}
static
int
pnp_
next_irq
(
struct
pnp_dev
*
dev
,
int
idx
)
static
int
pnp_
assign_irq
(
struct
pnp_dev
*
dev
,
struct
pnp_irq
*
rule
,
int
idx
)
{
struct
pnp_irq
*
irq
;
unsigned
long
*
start
,
*
end
,
*
flags
;
int
i
,
mask
;
if
(
!
dev
||
idx
<
0
||
idx
>=
PNP_MAX_IRQ
)
return
0
;
irq
=
dev
->
rule
->
irq
[
idx
];
if
(
!
irq
)
return
1
;
int
i
;
start
=
&
dev
->
res
.
irq_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
irq_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
irq_resource
[
idx
].
flags
;
/* IRQ priority: this table is good for i386 */
static
unsigned
short
xtab
[
16
]
=
{
5
,
10
,
11
,
12
,
9
,
14
,
15
,
7
,
3
,
4
,
13
,
0
,
1
,
6
,
8
,
2
};
/* set the initial values if this is the first time */
if
(
*
start
==
-
1
)
{
*
start
=
*
end
=
0
;
*
flags
=
irq
->
flags
|
IORESOURCE_IRQ
;
if
(
!
pnp_check_irq
(
dev
,
idx
))
return
1
;
}
mask
=
irq
->
map
;
for
(
i
=
*
start
+
1
;
i
<
16
;
i
++
)
{
if
(
mask
>>
i
&
0x01
)
{
*
start
=
*
end
=
i
;
if
(
!
pnp_check_irq
(
dev
,
idx
))
return
1
;
}
}
return
0
;
}
static
int
pnp_next_dma
(
struct
pnp_dev
*
dev
,
int
idx
)
{
struct
pnp_dma
*
dma
;
unsigned
long
*
start
,
*
end
,
*
flags
;
int
i
,
mask
;
if
(
!
dev
||
idx
<
0
||
idx
>=
PNP_MAX_DMA
)
if
(
!
dev
||
!
rule
)
return
-
EINVAL
;
dma
=
dev
->
rule
->
dma
[
idx
];
if
(
!
dma
)
return
1
;
start
=
&
dev
->
res
.
dma_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
dma_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
dma_resource
[
idx
].
flags
;
/* set the initial values if this is the first time */
if
(
*
start
==
-
1
)
{
*
start
=
*
end
=
0
;
*
flags
=
dma
->
flags
|
IORESOURCE_DMA
;
if
(
!
pnp_check_dma
(
dev
,
idx
))
if
(
idx
>=
PNP_MAX_IRQ
)
{
pnp_err
(
"More than 2 irqs is incompatible with pnp specifications."
);
/* pretend we were successful so at least the manager won't try again */
return
1
;
}
mask
=
dma
->
map
;
for
(
i
=
*
start
+
1
;
i
<
8
;
i
++
)
{
if
(
mask
>>
i
&
0x01
)
{
*
start
=
*
end
=
i
;
if
(
!
pnp_check_dma
(
dev
,
idx
))
/* check if this resource has been manually set, if so skip */
if
(
!
(
dev
->
res
.
irq_resource
[
idx
].
flags
&
IORESOURCE_AUTO
))
return
1
;
}
}
return
0
;
}
static
int
pnp_next_rule
(
struct
pnp_dev
*
dev
)
{
int
depnum
=
dev
->
rule
->
depnum
;
int
max
=
pnp_get_max_depnum
(
dev
);
int
priority
=
PNP_RES_PRIORITY_PREFERRED
;
if
(
depnum
<
0
)
return
0
;
if
(
max
==
0
)
{
if
(
pnp_generate_rule
(
dev
,
0
,
dev
->
rule
))
{
dev
->
rule
->
depnum
=
-
1
;
return
1
;
}
}
start
=
&
dev
->
res
.
irq_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
irq_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
irq_resource
[
idx
].
flags
;
if
(
depnum
>
0
)
{
struct
pnp_resources
*
res
=
pnp_find_resources
(
dev
,
depnum
);
priority
=
res
->
priority
;
}
/* set the initial values */
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_IRQ
;
for
(;
priority
<=
PNP_RES_PRIORITY_FUNCTIONAL
;
priority
++
,
depnum
=
0
)
{
depnum
+=
1
;
for
(;
depnum
<=
max
;
depnum
++
)
{
struct
pnp_resources
*
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
res
->
priority
==
priority
)
{
if
(
pnp_generate_rule
(
dev
,
depnum
,
dev
->
rule
))
{
dev
->
rule
->
depnum
=
depnum
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
(
rule
->
map
&
(
1
<<
xtab
[
i
]))
{
*
start
=
*
end
=
xtab
[
i
];
if
(
pnp_check_irq
(
dev
,
idx
))
return
1
;
}
}
}
}
return
0
;
}
struct
pnp_change
{
struct
list_head
change_list
;
struct
list_head
changes
;
struct
pnp_resource_table
res_bak
;
struct
pnp_rule_table
rule_bak
;
struct
pnp_dev
*
dev
;
};
static
void
pnp_free_changes
(
struct
pnp_change
*
parent
)
{
struct
list_head
*
pos
,
*
temp
;
list_for_each_safe
(
pos
,
temp
,
&
parent
->
changes
)
{
struct
pnp_change
*
change
=
list_entry
(
pos
,
struct
pnp_change
,
change_list
);
list_del
(
&
change
->
change_list
);
kfree
(
change
);
}
}
static
void
pnp_undo_changes
(
struct
pnp_change
*
parent
)
{
struct
list_head
*
pos
,
*
temp
;
list_for_each_safe
(
pos
,
temp
,
&
parent
->
changes
)
{
struct
pnp_change
*
change
=
list_entry
(
pos
,
struct
pnp_change
,
change_list
);
*
change
->
dev
->
rule
=
change
->
rule_bak
;
change
->
dev
->
res
=
change
->
res_bak
;
list_del
(
&
change
->
change_list
);
kfree
(
change
);
}
}
static
struct
pnp_change
*
pnp_add_change
(
struct
pnp_change
*
parent
,
struct
pnp_dev
*
dev
)
{
struct
pnp_change
*
change
=
pnp_alloc
(
sizeof
(
struct
pnp_change
));
if
(
!
change
)
return
NULL
;
change
->
res_bak
=
dev
->
res
;
change
->
rule_bak
=
*
dev
->
rule
;
change
->
dev
=
dev
;
INIT_LIST_HEAD
(
&
change
->
changes
);
if
(
parent
)
list_add
(
&
change
->
change_list
,
&
parent
->
changes
);
return
change
;
}
static
void
pnp_commit_changes
(
struct
pnp_change
*
parent
,
struct
pnp_change
*
change
)
{
/* check if it's the root change */
if
(
!
parent
)
return
;
if
(
!
list_empty
(
&
change
->
changes
))
list_splice_init
(
&
change
->
changes
,
&
parent
->
changes
);
}
static
int
pnp_next_config
(
struct
pnp_dev
*
dev
,
int
move
,
struct
pnp_change
*
parent
);
static
int
pnp_next_request
(
struct
pnp_dev
*
dev
,
int
move
,
struct
pnp_change
*
parent
,
struct
pnp_change
*
change
)
static
int
pnp_assign_dma
(
struct
pnp_dev
*
dev
,
struct
pnp_dma
*
rule
,
int
idx
)
{
unsigned
long
*
start
,
*
end
,
*
flags
;
int
i
;
struct
pnp_dev
*
cdev
;
for
(
i
=
0
;
i
<
PNP_MAX_PORT
;
i
++
)
{
if
(
dev
->
res
.
port_resource
[
i
].
start
==
0
||
pnp_check_port_conflicts
(
dev
,
i
,
SEARCH_WARM
))
{
if
(
!
pnp_next_port
(
dev
,
i
))
return
0
;
}
do
{
cdev
=
pnp_check_port_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
&&
(
!
move
||
!
pnp_next_config
(
cdev
,
move
,
change
)))
{
pnp_undo_changes
(
change
);
if
(
!
pnp_next_port
(
dev
,
i
))
return
0
;
}
}
while
(
cdev
);
pnp_commit_changes
(
parent
,
change
);
}
for
(
i
=
0
;
i
<
PNP_MAX_MEM
;
i
++
)
{
if
(
dev
->
res
.
mem_resource
[
i
].
start
==
0
||
pnp_check_mem_conflicts
(
dev
,
i
,
SEARCH_WARM
))
{
if
(
!
pnp_next_mem
(
dev
,
i
))
return
0
;
}
do
{
cdev
=
pnp_check_mem_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
&&
(
!
move
||
!
pnp_next_config
(
cdev
,
move
,
change
)))
{
pnp_undo_changes
(
change
);
if
(
!
pnp_next_mem
(
dev
,
i
))
return
0
;
}
}
while
(
cdev
);
pnp_commit_changes
(
parent
,
change
);
}
for
(
i
=
0
;
i
<
PNP_MAX_IRQ
;
i
++
)
{
if
(
dev
->
res
.
irq_resource
[
i
].
start
==
-
1
||
pnp_check_irq_conflicts
(
dev
,
i
,
SEARCH_WARM
))
{
if
(
!
pnp_next_irq
(
dev
,
i
))
return
0
;
}
do
{
cdev
=
pnp_check_irq_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
&&
(
!
move
||
!
pnp_next_config
(
cdev
,
move
,
change
)))
{
pnp_undo_changes
(
change
);
if
(
!
pnp_next_irq
(
dev
,
i
))
return
0
;
}
}
while
(
cdev
);
pnp_commit_changes
(
parent
,
change
);
}
for
(
i
=
0
;
i
<
PNP_MAX_DMA
;
i
++
)
{
if
(
dev
->
res
.
dma_resource
[
i
].
start
==
-
1
||
pnp_check_dma_conflicts
(
dev
,
i
,
SEARCH_WARM
))
{
if
(
!
pnp_next_dma
(
dev
,
i
))
return
0
;
}
do
{
cdev
=
pnp_check_dma_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
&&
(
!
move
||
!
pnp_next_config
(
cdev
,
move
,
change
)))
{
pnp_undo_changes
(
change
);
if
(
!
pnp_next_dma
(
dev
,
i
))
return
0
;
}
}
while
(
cdev
);
pnp_commit_changes
(
parent
,
change
);
}
return
1
;
}
/* DMA priority: this table is good for i386 */
static
unsigned
short
xtab
[
8
]
=
{
1
,
3
,
5
,
6
,
7
,
0
,
2
,
4
};
static
int
pnp_next_config
(
struct
pnp_dev
*
dev
,
int
move
,
struct
pnp_change
*
parent
)
{
struct
pnp_change
*
change
;
move
--
;
if
(
!
dev
->
rule
)
return
0
;
change
=
pnp_add_change
(
parent
,
dev
);
if
(
!
change
)
return
0
;
if
(
!
pnp_can_configure
(
dev
))
goto
fail
;
if
(
!
dev
->
rule
->
depnum
)
{
if
(
!
pnp_next_rule
(
dev
))
goto
fail
;
}
while
(
!
pnp_next_request
(
dev
,
move
,
parent
,
change
))
{
if
(
!
pnp_next_rule
(
dev
))
goto
fail
;
pnp_init_resource_table
(
&
dev
->
res
);
}
if
(
!
parent
)
{
pnp_free_changes
(
change
);
kfree
(
change
);
}
return
1
;
fail:
if
(
!
parent
)
kfree
(
change
);
return
0
;
}
if
(
!
dev
||
!
rule
)
return
-
EINVAL
;
/* this advanced algorithm will shuffle other configs to make room and ensure that the most possible devices have configs */
static
int
pnp_advanced_config
(
struct
pnp_dev
*
dev
)
{
int
move
;
/* if the device cannot be configured skip it */
if
(
!
pnp_can_configure
(
dev
))
if
(
idx
>=
PNP_MAX_DMA
)
{
pnp_err
(
"More than 2 dmas is incompatible with pnp specifications."
);
/* pretend we were successful so at least the manager won't try again */
return
1
;
if
(
!
dev
->
rule
)
{
dev
->
rule
=
pnp_alloc
(
sizeof
(
struct
pnp_rule_table
));
if
(
!
dev
->
rule
)
return
-
ENOMEM
;
}
spin_lock
(
&
pnp_lock
);
for
(
move
=
1
;
move
<=
pnp_max_moves
;
move
++
)
{
dev
->
rule
->
depnum
=
0
;
pnp_init_resource_table
(
&
dev
->
res
);
if
(
pnp_next_config
(
dev
,
move
,
NULL
))
{
spin_unlock
(
&
pnp_lock
);
/* check if this resource has been manually set, if so skip */
if
(
!
(
dev
->
res
.
dma_resource
[
idx
].
flags
&
IORESOURCE_AUTO
))
return
1
;
}
}
pnp_init_resource_table
(
&
dev
->
res
);
dev
->
rule
->
depnum
=
0
;
spin_unlock
(
&
pnp_lock
);
pnp_err
(
"res: Unable to resolve resource conflicts for the device '%s', some devices may not be usable."
,
dev
->
dev
.
bus_id
);
return
0
;
}
start
=
&
dev
->
res
.
dma_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
dma_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
dma_resource
[
idx
].
flags
;
int
pnp_resolve_conflicts
(
struct
pnp_dev
*
dev
)
{
int
i
;
struct
pnp_dev
*
cdev
;
/* set the initial values */
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_DMA
;
for
(
i
=
0
;
i
<
PNP_MAX_PORT
;
i
++
)
{
do
{
cdev
=
pnp_check_port_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
)
pnp_advanced_config
(
cdev
);
}
while
(
cdev
);
}
for
(
i
=
0
;
i
<
PNP_MAX_MEM
;
i
++
)
{
do
{
cdev
=
pnp_check_mem_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
)
pnp_advanced_config
(
cdev
);
}
while
(
cdev
);
}
for
(
i
=
0
;
i
<
PNP_MAX_IRQ
;
i
++
)
{
do
{
cdev
=
pnp_check_irq_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
)
pnp_advanced_config
(
cdev
);
}
while
(
cdev
);
}
for
(
i
=
0
;
i
<
PNP_MAX_DMA
;
i
++
)
{
do
{
cdev
=
pnp_check_dma_conflicts
(
dev
,
i
,
SEARCH_COLD
);
if
(
cdev
)
pnp_advanced_config
(
cdev
);
}
while
(
cdev
);
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
rule
->
map
&
(
1
<<
xtab
[
i
]))
{
*
start
=
*
end
=
xtab
[
i
];
if
(
pnp_check_dma
(
dev
,
idx
))
return
1
;
}
/* this is a much faster algorithm but it may not leave resources for other devices to use */
static
int
pnp_simple_config
(
struct
pnp_dev
*
dev
)
{
int
i
;
spin_lock
(
&
pnp_lock
);
if
(
dev
->
active
)
{
spin_unlock
(
&
pnp_lock
);
return
1
;
}
if
(
!
dev
->
rule
)
{
dev
->
rule
=
pnp_alloc
(
sizeof
(
struct
pnp_rule_table
));
if
(
!
dev
->
rule
)
{
spin_unlock
(
&
pnp_lock
);
return
-
ENOMEM
;
}
}
dev
->
rule
->
depnum
=
0
;
pnp_init_resource_table
(
&
dev
->
res
);
while
(
pnp_next_rule
(
dev
))
{
for
(
i
=
0
;
i
<
PNP_MAX_PORT
;
i
++
)
{
if
(
!
pnp_next_port
(
dev
,
i
))
continue
;
}
for
(
i
=
0
;
i
<
PNP_MAX_MEM
;
i
++
)
{
if
(
!
pnp_next_mem
(
dev
,
i
))
continue
;
}
for
(
i
=
0
;
i
<
PNP_MAX_IRQ
;
i
++
)
{
if
(
!
pnp_next_irq
(
dev
,
i
))
continue
;
}
for
(
i
=
0
;
i
<
PNP_MAX_DMA
;
i
++
)
{
if
(
!
pnp_next_dma
(
dev
,
i
))
continue
;
}
goto
done
;
}
pnp_init_resource_table
(
&
dev
->
res
);
dev
->
rule
->
depnum
=
0
;
spin_unlock
(
&
pnp_lock
);
return
0
;
done:
pnp_resolve_conflicts
(
dev
);
/* this is required or we will break the advanced configs */
return
1
;
}
static
int
pnp_compare_resources
(
struct
pnp_resource_table
*
resa
,
struct
pnp_resource_table
*
resb
)
/**
* pnp_init_resources - Resets a resource table to default values.
* @table: pointer to the desired resource table
*
*/
void
pnp_init_resources
(
struct
pnp_resource_table
*
table
)
{
int
idx
;
down
(
&
pnp_res_mutex
);
for
(
idx
=
0
;
idx
<
PNP_MAX_IRQ
;
idx
++
)
{
if
(
resa
->
irq_resource
[
idx
].
start
!=
resb
->
irq_resource
[
idx
].
start
)
return
1
;
table
->
irq_resource
[
idx
].
name
=
NULL
;
table
->
irq_resource
[
idx
].
start
=
-
1
;
table
->
irq_resource
[
idx
].
end
=
-
1
;
table
->
irq_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_DMA
;
idx
++
)
{
if
(
resa
->
dma_resource
[
idx
].
start
!=
resb
->
dma_resource
[
idx
].
start
)
return
1
;
table
->
dma_resource
[
idx
].
name
=
NULL
;
table
->
dma_resource
[
idx
].
start
=
-
1
;
table
->
dma_resource
[
idx
].
end
=
-
1
;
table
->
dma_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_PORT
;
idx
++
)
{
if
(
resa
->
port_resource
[
idx
].
start
!=
resb
->
port_resource
[
idx
].
start
)
return
1
;
if
(
resa
->
port_resource
[
idx
].
end
!=
resb
->
port_resource
[
idx
].
end
)
return
1
;
table
->
port_resource
[
idx
].
name
=
NULL
;
table
->
port_resource
[
idx
].
start
=
0
;
table
->
port_resource
[
idx
].
end
=
0
;
table
->
port_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_MEM
;
idx
++
)
{
if
(
resa
->
mem_resource
[
idx
].
start
!=
resb
->
mem_resource
[
idx
].
start
)
return
1
;
if
(
resa
->
mem_resource
[
idx
].
end
!=
resb
->
mem_resource
[
idx
].
end
)
return
1
;
table
->
mem_resource
[
idx
].
name
=
NULL
;
table
->
mem_resource
[
idx
].
start
=
0
;
table
->
mem_resource
[
idx
].
end
=
0
;
table
->
mem_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
return
0
;
up
(
&
pnp_res_mutex
)
;
}
/*
* PnP Device Resource Management
*/
/**
* pnp_
auto_config_dev - determines the best possible resource configuration based on available information
* @
dev: pointer to the desired device
* pnp_
clean_resources - clears resources that were not manually set
* @
res - the resources to clean
*
*/
int
pnp_auto_config_dev
(
struct
pnp_dev
*
dev
)
{
int
error
;
if
(
!
dev
)
return
-
EINVAL
;
dev
->
config_mode
=
PNP_CONFIG_AUTO
;
if
(
dev
->
active
)
error
=
pnp_resolve_conflicts
(
dev
);
else
error
=
pnp_advanced_config
(
dev
);
return
error
;
}
static
void
pnp_process_manual_resources
(
struct
pnp_resource_table
*
ctab
,
struct
pnp_resource_table
*
ntab
)
static
void
pnp_clean_resources
(
struct
pnp_resource_table
*
res
)
{
int
idx
;
for
(
idx
=
0
;
idx
<
PNP_MAX_IRQ
;
idx
++
)
{
if
(
ntab
->
irq_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
if
(
!
(
res
->
irq_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
)
continue
;
ctab
->
irq_resource
[
idx
].
start
=
ntab
->
irq_resource
[
idx
].
start
;
ctab
->
irq_resource
[
idx
].
end
=
ntab
->
irq_resource
[
idx
].
end
;
ctab
->
irq_resource
[
idx
].
flags
=
ntab
->
irq_resource
[
idx
].
flags
;
res
->
irq_resource
[
idx
].
start
=
-
1
;
res
->
irq_resource
[
idx
].
end
=
-
1
;
res
->
irq_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_DMA
;
idx
++
)
{
if
(
ntab
->
dma_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
if
(
!
(
res
->
dma_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
)
continue
;
ctab
->
dma_resource
[
idx
].
start
=
ntab
->
dma_resource
[
idx
].
start
;
ctab
->
dma_resource
[
idx
].
end
=
ntab
->
dma_resource
[
idx
].
end
;
ctab
->
dma_resource
[
idx
].
flags
=
ntab
->
dma_resource
[
idx
].
flags
;
res
->
dma_resource
[
idx
].
start
=
-
1
;
res
->
dma_resource
[
idx
].
end
=
-
1
;
res
->
dma_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_PORT
;
idx
++
)
{
if
(
ntab
->
port_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
if
(
!
(
res
->
port_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
)
continue
;
ctab
->
port_resource
[
idx
].
start
=
ntab
->
port_resource
[
idx
].
start
;
ctab
->
port_resource
[
idx
].
end
=
ntab
->
port_resource
[
idx
].
end
;
ctab
->
port_resource
[
idx
].
flags
=
ntab
->
port_resource
[
idx
].
flags
;
res
->
port_resource
[
idx
].
start
=
0
;
res
->
port_resource
[
idx
].
end
=
0
;
res
->
port_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_MEM
;
idx
++
)
{
if
(
ntab
->
irq_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
if
(
!
(
res
->
mem_resource
[
idx
].
flags
&
IORESOURCE_AUTO
)
)
continue
;
ctab
->
irq_resource
[
idx
].
start
=
ntab
->
mem_resource
[
idx
].
start
;
ctab
->
irq_resource
[
idx
].
end
=
ntab
->
mem_resource
[
idx
].
end
;
ctab
->
irq_resource
[
idx
].
flags
=
ntab
->
mem_resource
[
idx
].
flags
;
res
->
mem_resource
[
idx
].
start
=
0
;
res
->
mem_resource
[
idx
].
end
=
0
;
res
->
mem_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
}
/**
* pnp_assign_resources - assigns resources to the device based on the specified dependent number
* @dev: pointer to the desired device
* @depnum: the dependent function number
*
* Only set depnum to 0 if the device does not have dependent options.
*/
int
pnp_assign_resources
(
struct
pnp_dev
*
dev
,
int
depnum
)
{
struct
pnp_port
*
port
;
struct
pnp_mem
*
mem
;
struct
pnp_irq
*
irq
;
struct
pnp_dma
*
dma
;
int
nport
=
0
,
nmem
=
0
,
nirq
=
0
,
ndma
=
0
;
if
(
!
pnp_can_configure
(
dev
))
return
-
ENODEV
;
down
(
&
pnp_res_mutex
);
pnp_clean_resources
(
&
dev
->
res
);
/* start with a fresh slate */
if
(
dev
->
independent
)
{
port
=
dev
->
independent
->
port
;
mem
=
dev
->
independent
->
mem
;
irq
=
dev
->
independent
->
irq
;
dma
=
dev
->
independent
->
dma
;
while
(
port
)
{
if
(
!
pnp_assign_port
(
dev
,
port
,
nport
))
goto
fail
;
nport
++
;
port
=
port
->
next
;
}
while
(
mem
)
{
if
(
!
pnp_assign_mem
(
dev
,
mem
,
nmem
))
goto
fail
;
nmem
++
;
mem
=
mem
->
next
;
}
while
(
irq
)
{
if
(
!
pnp_assign_irq
(
dev
,
irq
,
nirq
))
goto
fail
;
nirq
++
;
irq
=
irq
->
next
;
}
while
(
dma
)
{
if
(
!
pnp_assign_dma
(
dev
,
dma
,
ndma
))
goto
fail
;
ndma
++
;
dma
=
dma
->
next
;
}
}
if
(
depnum
)
{
struct
pnp_option
*
dep
;
int
i
;
for
(
i
=
1
,
dep
=
dev
->
dependent
;
i
<
depnum
;
i
++
,
dep
=
dep
->
next
)
if
(
!
dep
)
goto
fail
;
port
=
dep
->
port
;
mem
=
dep
->
mem
;
irq
=
dep
->
irq
;
dma
=
dep
->
dma
;
while
(
port
)
{
if
(
!
pnp_assign_port
(
dev
,
port
,
nport
))
goto
fail
;
nport
++
;
port
=
port
->
next
;
}
while
(
mem
)
{
if
(
!
pnp_assign_mem
(
dev
,
mem
,
nmem
))
goto
fail
;
nmem
++
;
mem
=
mem
->
next
;
}
while
(
irq
)
{
if
(
!
pnp_assign_irq
(
dev
,
irq
,
nirq
))
goto
fail
;
nirq
++
;
irq
=
irq
->
next
;
}
while
(
dma
)
{
if
(
!
pnp_assign_dma
(
dev
,
dma
,
ndma
))
goto
fail
;
ndma
++
;
dma
=
dma
->
next
;
}
}
else
if
(
dev
->
dependent
)
goto
fail
;
up
(
&
pnp_res_mutex
);
return
1
;
fail:
pnp_clean_resources
(
&
dev
->
res
);
up
(
&
pnp_res_mutex
);
return
0
;
}
/**
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @dev: pointer to the desired device
...
...
@@ -572,22 +363,21 @@ static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struc
*
* This function can be used by drivers that want to manually set thier resources.
*/
int
pnp_manual_config_dev
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
,
int
mode
)
{
int
i
;
struct
pnp_resource_table
*
bak
;
if
(
!
dev
||
!
res
)
return
-
EINVAL
;
if
(
dev
->
active
)
return
-
E
BUSY
;
if
(
!
pnp_can_configure
(
dev
)
)
return
-
E
NODEV
;
bak
=
pnp_alloc
(
sizeof
(
struct
pnp_resource_table
));
if
(
!
bak
)
return
-
ENOMEM
;
*
bak
=
dev
->
res
;
spin_lock
(
&
pnp_lock
);
pnp_process_manual_resources
(
&
dev
->
res
,
res
)
;
down
(
&
pnp_res_mutex
);
dev
->
res
=
*
res
;
if
(
!
(
mode
&
PNP_CONFIG_FORCE
))
{
for
(
i
=
0
;
i
<
PNP_MAX_PORT
;
i
++
)
{
if
(
pnp_check_port
(
dev
,
i
))
...
...
@@ -606,27 +396,64 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res,
goto
fail
;
}
}
dev
->
config_mode
=
PNP_CONFIG_MANUAL
;
spin_unlock
(
&
pnp_lock
);
up
(
&
pnp_res_mutex
);
pnp_
resolve_conflicts
(
dev
);
pnp_
auto_config_dev
(
dev
);
kfree
(
bak
);
return
0
;
fail:
dev
->
res
=
*
bak
;
spin_unlock
(
&
pnp_lock
);
up
(
&
pnp_res_mutex
);
kfree
(
bak
);
return
-
EINVAL
;
}
/**
* pnp_a
ctivate_dev - activates a PnP device for us
e
* pnp_a
uto_config_dev - automatically assigns resources to a devic
e
* @dev: pointer to the desired device
*
* finds the best resource configuration and then informs the correct pnp protocol
*/
int
pnp_auto_config_dev
(
struct
pnp_dev
*
dev
)
{
struct
pnp_option
*
dep
;
int
i
=
1
;
if
(
!
dev
)
return
-
EINVAL
;
if
(
!
pnp_can_configure
(
dev
))
{
pnp_info
(
"Device %s does not support resource configuration."
,
dev
->
dev
.
bus_id
);
return
-
ENODEV
;
}
if
(
!
dev
->
dependent
)
{
if
(
pnp_assign_resources
(
dev
,
0
))
return
1
;
else
return
0
;
}
dep
=
dev
->
dependent
;
do
{
if
(
pnp_assign_resources
(
dev
,
i
))
return
1
;
/* if this dependent resource failed, try the next one */
dep
=
dep
->
next
;
i
++
;
}
while
(
dep
);
pnp_err
(
"Unable to assign resources to device %s."
,
dev
->
dev
.
bus_id
);
return
0
;
}
/**
* pnp_activate_dev - activates a PnP device for use
* @dev: pointer to the desired device
*
* does not validate or set resources so be careful.
*/
int
pnp_activate_dev
(
struct
pnp_dev
*
dev
)
{
if
(
!
dev
)
...
...
@@ -634,55 +461,25 @@ int pnp_activate_dev(struct pnp_dev *dev)
if
(
dev
->
active
)
{
return
0
;
/* the device is already active */
}
/* If this condition is true, advanced configuration failed, we need to get this device up and running
* so we use the simple config engine which ignores cold conflicts, this of course may lead to new failures */
if
(
!
pnp_is_active
(
dev
))
{
if
(
!
pnp_simple_config
(
dev
))
{
pnp_err
(
"res: Unable to resolve resource conflicts for the device '%s'."
,
dev
->
dev
.
bus_id
);
goto
fail
;
}
}
spin_lock
(
&
pnp_lock
);
/* we lock just in case the device is being configured during this call
*/
dev
->
active
=
1
;
spin_unlock
(
&
pnp_lock
);
/* once the device is claimed active we know it won't be configured so we can unlock */
/* ensure resources are allocated
*/
if
(
!
pnp_auto_config_dev
(
dev
))
return
-
EBUSY
;
if
(
dev
->
config_mode
&
PNP_CONFIG_INVALID
)
{
pnp_info
(
"res: Unable to activate the PnP device '%s' because its resource configuration is invalid."
,
dev
->
dev
.
bus_id
);
goto
fail
;
}
if
(
dev
->
status
!=
PNP_READY
&&
dev
->
status
!=
PNP_ATTACHED
){
pnp_err
(
"res: Activation failed because the PnP device '%s' is busy."
,
dev
->
dev
.
bus_id
);
goto
fail
;
}
if
(
!
pnp_can_write
(
dev
))
{
pnp_info
(
"
res: Unable to activate the PnP device '%s' because this feature is not supported
."
,
dev
->
dev
.
bus_id
);
goto
fail
;
pnp_info
(
"
Device %s does not supported activation
."
,
dev
->
dev
.
bus_id
);
return
-
EINVAL
;
}
if
(
dev
->
protocol
->
set
(
dev
,
&
dev
->
res
)
<
0
)
{
pnp_err
(
"res: The protocol '%s' reports that activating the PnP device '%s' has failed."
,
dev
->
protocol
->
name
,
dev
->
dev
.
bus_id
);
goto
fail
;
}
if
(
pnp_can_read
(
dev
))
{
struct
pnp_resource_table
*
res
=
pnp_alloc
(
sizeof
(
struct
pnp_resource_table
));
if
(
!
res
)
goto
fail
;
dev
->
protocol
->
get
(
dev
,
res
);
if
(
pnp_compare_resources
(
&
dev
->
res
,
res
))
/* if this happens we may be in big trouble but it's best just to continue */
pnp_err
(
"res: The resources requested do not match those set for the PnP device '%s'."
,
dev
->
dev
.
bus_id
);
kfree
(
res
);
}
else
dev
->
active
=
pnp_is_active
(
dev
);
pnp_dbg
(
"res: the device '%s' has been activated."
,
dev
->
dev
.
bus_id
);
if
(
dev
->
rule
)
{
kfree
(
dev
->
rule
);
dev
->
rule
=
NULL
;
pnp_err
(
"Failed to activate device %s."
,
dev
->
dev
.
bus_id
);
return
-
EIO
;
}
return
0
;
fail:
dev
->
active
=
0
;
/* fixes incorrect active state */
return
-
EINVAL
;
dev
->
active
=
1
;
pnp_info
(
"Device %s activated."
,
dev
->
dev
.
bus_id
);
return
1
;
}
/**
...
...
@@ -691,7 +488,6 @@ int pnp_activate_dev(struct pnp_dev *dev)
*
* inform the correct pnp protocol so that resources can be used by other devices
*/
int
pnp_disable_dev
(
struct
pnp_dev
*
dev
)
{
if
(
!
dev
)
...
...
@@ -699,21 +495,25 @@ int pnp_disable_dev(struct pnp_dev *dev)
if
(
!
dev
->
active
)
{
return
0
;
/* the device is already disabled */
}
if
(
dev
->
status
!=
PNP_READY
){
pnp_info
(
"res: Disable failed becuase the PnP device '%s' is busy."
,
dev
->
dev
.
bus_id
);
return
-
EINVAL
;
}
if
(
!
pnp_can_disable
(
dev
))
{
pnp_info
(
"
res: Unable to disable the PnP device '%s' because this feature is not supported
."
,
dev
->
dev
.
bus_id
);
pnp_info
(
"
Device %s does not supported disabling
."
,
dev
->
dev
.
bus_id
);
return
-
EINVAL
;
}
if
(
dev
->
protocol
->
disable
(
dev
)
<
0
)
{
pnp_err
(
"
res: The protocol '%s' reports that disabling the PnP device '%s' has failed."
,
dev
->
protocol
->
name
,
dev
->
dev
.
bus_id
);
return
-
1
;
pnp_err
(
"
Failed to disable device %s."
,
dev
->
dev
.
bus_id
);
return
-
EIO
;
}
dev
->
active
=
0
;
/* just in case the protocol doesn't do this */
pnp_dbg
(
"res: the device '%s' has been disabled."
,
dev
->
dev
.
bus_id
);
return
0
;
dev
->
active
=
0
;
pnp_info
(
"Device %s disabled."
,
dev
->
dev
.
bus_id
);
/* release the resources so that other devices can use them */
down
(
&
pnp_res_mutex
);
pnp_clean_resources
(
&
dev
->
res
);
up
(
&
pnp_res_mutex
);
return
1
;
}
/**
...
...
@@ -723,7 +523,6 @@ int pnp_disable_dev(struct pnp_dev *dev)
* @size: size of region
*
*/
void
pnp_resource_change
(
struct
resource
*
resource
,
unsigned
long
start
,
unsigned
long
size
)
{
if
(
resource
==
NULL
)
...
...
@@ -734,19 +533,10 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne
}
EXPORT_SYMBOL
(
pnp_a
uto_config_dev
);
EXPORT_SYMBOL
(
pnp_a
ssign_resources
);
EXPORT_SYMBOL
(
pnp_manual_config_dev
);
EXPORT_SYMBOL
(
pnp_auto_config_dev
);
EXPORT_SYMBOL
(
pnp_activate_dev
);
EXPORT_SYMBOL
(
pnp_disable_dev
);
EXPORT_SYMBOL
(
pnp_resource_change
);
/* format is: pnp_max_moves=num */
static
int
__init
pnp_setup_max_moves
(
char
*
str
)
{
get_option
(
&
str
,
&
pnp_max_moves
);
return
1
;
}
__setup
(
"pnp_max_moves="
,
pnp_setup_max_moves
);
EXPORT_SYMBOL
(
pnp_init_resources
);
drivers/pnp/pnpbios/core.c
View file @
d3899e3c
...
...
@@ -935,6 +935,10 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node)
dev
->
capabilities
|=
PNP_REMOVABLE
;
dev
->
protocol
=
&
pnpbios_protocol
;
/* clear out the damaged flags */
if
(
!
dev
->
active
)
pnp_init_resources
(
&
dev
->
res
);
pnp_add_device
(
dev
);
pnpbios_interface_attach_device
(
node
);
...
...
drivers/pnp/quirks.c
View file @
d3899e3c
...
...
@@ -30,7 +30,7 @@
static
void
quirk_awe32_resources
(
struct
pnp_dev
*
dev
)
{
struct
pnp_port
*
port
,
*
port2
,
*
port3
;
struct
pnp_
resources
*
res
=
dev
->
possible
->
dep
;
struct
pnp_
option
*
res
=
dev
->
dependent
;
/*
* Unfortunately the isapnp_add_port_resource is too tightly bound
...
...
@@ -38,7 +38,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
* two extra ports (at offset 0x400 and 0x800 from the one given) by
* hand.
*/
for
(
;
res
;
res
=
res
->
dep
)
{
for
(
;
res
;
res
=
res
->
next
)
{
port2
=
pnp_alloc
(
sizeof
(
struct
pnp_port
));
if
(
!
port2
)
return
;
...
...
@@ -62,9 +62,9 @@ static void quirk_awe32_resources(struct pnp_dev *dev)
static
void
quirk_cmi8330_resources
(
struct
pnp_dev
*
dev
)
{
struct
pnp_
resources
*
res
=
dev
->
possible
->
dep
;
struct
pnp_
option
*
res
=
dev
->
dependent
;
for
(
;
res
;
res
=
res
->
dep
)
{
for
(
;
res
;
res
=
res
->
next
)
{
struct
pnp_irq
*
irq
;
struct
pnp_dma
*
dma
;
...
...
@@ -82,7 +82,7 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev)
static
void
quirk_sb16audio_resources
(
struct
pnp_dev
*
dev
)
{
struct
pnp_port
*
port
;
struct
pnp_
resources
*
res
=
dev
->
possible
->
dep
;
struct
pnp_
option
*
res
=
dev
->
dependent
;
int
changed
=
0
;
/*
...
...
@@ -91,7 +91,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
* auto-configured.
*/
for
(
;
res
;
res
=
res
->
dep
)
{
for
(
;
res
;
res
=
res
->
next
)
{
port
=
res
->
port
;
if
(
!
port
)
continue
;
...
...
@@ -118,11 +118,11 @@ static void quirk_opl3sax_resources(struct pnp_dev *dev)
* doesn't allow a DMA channel of 0, afflicted card is an
* OPL3Sax where x=4.
*/
struct
pnp_
resources
*
res
;
struct
pnp_
option
*
res
;
int
max
;
res
=
dev
->
possible
;
res
=
dev
->
dependent
;
max
=
0
;
for
(
res
=
res
->
dep
;
res
;
res
=
res
->
dep
)
{
for
(
;
res
;
res
=
res
->
next
)
{
if
(
res
->
dma
->
map
>
max
)
max
=
res
->
dma
->
map
;
}
...
...
drivers/pnp/resource.c
View file @
d3899e3c
...
...
@@ -10,18 +10,19 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pnp.h>
#include "base.h"
int
pnp_allow_dma0
=
-
1
;
/* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */
int
pnp_allow_dma0
=
-
1
;
/* allow dma 0 during auto activation:
* -1=off (:default), 0=off (set by user), 1=on */
int
pnp_skip_pci_scan
;
/* skip PCI resource scanning */
int
pnp_reserve_irq
[
16
]
=
{
[
0
...
15
]
=
-
1
};
/* reserve (don't use) some IRQ */
int
pnp_reserve_dma
[
8
]
=
{
[
0
...
7
]
=
-
1
};
/* reserve (don't use) some DMA */
...
...
@@ -30,88 +31,75 @@ int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memor
/*
*
possible resource
registration
*
option
registration
*/
st
ruct
pnp_resources
*
pnp_build_resource
(
struct
pnp_dev
*
dev
,
int
dependent
)
st
atic
struct
pnp_option
*
pnp_build_option
(
int
priority
)
{
struct
pnp_
resources
*
res
,
*
ptr
,
*
ptra
;
struct
pnp_
option
*
option
=
pnp_alloc
(
sizeof
(
struct
pnp_option
))
;
res
=
pnp_alloc
(
sizeof
(
struct
pnp_resources
));
if
(
!
res
)
/* check if pnp_alloc ran out of memory */
if
(
!
option
)
return
NULL
;
ptr
=
dev
->
possible
;
if
(
ptr
)
{
/* add to another list */
ptra
=
ptr
->
dep
;
while
(
ptra
&&
ptra
->
dep
)
ptra
=
ptra
->
dep
;
if
(
!
ptra
)
ptr
->
dep
=
res
;
else
ptra
->
dep
=
res
;
}
else
dev
->
possible
=
res
;
if
(
dependent
)
{
res
->
priority
=
dependent
&
0xff
;
if
(
res
->
priority
>
PNP_RES_PRIORITY_FUNCTIONAL
)
res
->
priority
=
PNP_RES_PRIORITY_INVALID
;
}
else
res
->
priority
=
PNP_RES_PRIORITY_PREFERRED
;
return
res
;
option
->
priority
=
priority
&
0xff
;
/* make sure the priority is valid */
if
(
option
->
priority
>
PNP_RES_PRIORITY_FUNCTIONAL
)
option
->
priority
=
PNP_RES_PRIORITY_INVALID
;
return
option
;
}
struct
pnp_
resources
*
pnp_find_resources
(
struct
pnp_dev
*
dev
,
int
depnum
)
struct
pnp_
option
*
pnp_register_independent_option
(
struct
pnp_dev
*
dev
)
{
int
i
;
struct
pnp_resources
*
res
;
struct
pnp_option
*
option
;
if
(
!
dev
)
return
NULL
;
res
=
dev
->
possible
;
if
(
!
res
)
return
NULL
;
for
(
i
=
0
;
i
<
depnum
;
i
++
)
{
if
(
res
->
dep
)
res
=
res
->
dep
;
else
return
NULL
;
}
return
res
;
option
=
pnp_build_option
(
PNP_RES_PRIORITY_PREFERRED
);
/* this should never happen but if it does we'll try to continue */
if
(
dev
->
independent
)
pnp_err
(
"independent resource already registered"
);
dev
->
independent
=
option
;
return
option
;
}
int
pnp_get_max_depnum
(
struct
pnp_dev
*
dev
)
struct
pnp_option
*
pnp_register_dependent_option
(
struct
pnp_dev
*
dev
,
int
priority
)
{
int
num
=
0
;
struct
pnp_resources
*
res
;
struct
pnp_option
*
option
;
if
(
!
dev
)
return
-
EINVAL
;
res
=
dev
->
possible
;
if
(
!
res
)
return
-
EINVAL
;
while
(
res
->
dep
){
res
=
res
->
dep
;
num
++
;
}
return
num
;
return
NULL
;
option
=
pnp_build_option
(
priority
);
if
(
dev
->
dependent
)
{
struct
pnp_option
*
parent
=
dev
->
dependent
;
while
(
parent
->
next
)
parent
=
parent
->
next
;
parent
->
next
=
option
;
}
else
dev
->
dependent
=
option
;
return
option
;
}
int
pnp_
add_irq_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
)
int
pnp_
register_irq_resource
(
struct
pnp_option
*
option
,
struct
pnp_irq
*
data
)
{
int
i
;
struct
pnp_resources
*
res
;
struct
pnp_irq
*
ptr
;
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
!
res
)
if
(
!
option
)
return
-
EINVAL
;
if
(
!
data
)
return
-
EINVAL
;
ptr
=
res
->
irq
;
ptr
=
option
->
irq
;
while
(
ptr
&&
ptr
->
next
)
ptr
=
ptr
->
next
;
if
(
ptr
)
ptr
->
next
=
data
;
else
res
->
irq
=
data
;
option
->
irq
=
data
;
#ifdef CONFIG_PCI
for
(
i
=
0
;
i
<
16
;
i
++
)
if
(
data
->
map
&
(
1
<<
i
))
...
...
@@ -120,60 +108,59 @@ int pnp_add_irq_resource(struct pnp_dev *dev, int depnum, struct pnp_irq *data)
return
0
;
}
int
pnp_
add_dma_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_dma
*
data
)
int
pnp_
register_dma_resource
(
struct
pnp_option
*
option
,
struct
pnp_dma
*
data
)
{
struct
pnp_resources
*
res
;
struct
pnp_dma
*
ptr
;
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
!
res
)
if
(
!
option
)
return
-
EINVAL
;
if
(
!
data
)
return
-
EINVAL
;
ptr
=
res
->
dma
;
ptr
=
option
->
dma
;
while
(
ptr
&&
ptr
->
next
)
ptr
=
ptr
->
next
;
if
(
ptr
)
ptr
->
next
=
data
;
else
res
->
dma
=
data
;
option
->
dma
=
data
;
return
0
;
}
int
pnp_
add_port_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_port
*
data
)
int
pnp_
register_port_resource
(
struct
pnp_option
*
option
,
struct
pnp_port
*
data
)
{
struct
pnp_resources
*
res
;
struct
pnp_port
*
ptr
;
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
!
res
)
if
(
!
option
)
return
-
EINVAL
;
if
(
!
data
)
return
-
EINVAL
;
ptr
=
res
->
port
;
ptr
=
option
->
port
;
while
(
ptr
&&
ptr
->
next
)
ptr
=
ptr
->
next
;
if
(
ptr
)
ptr
->
next
=
data
;
else
res
->
port
=
data
;
option
->
port
=
data
;
return
0
;
}
int
pnp_
add_mem_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_mem
*
data
)
int
pnp_
register_mem_resource
(
struct
pnp_option
*
option
,
struct
pnp_mem
*
data
)
{
struct
pnp_resources
*
res
;
struct
pnp_mem
*
ptr
;
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
!
res
)
if
(
!
option
)
return
-
EINVAL
;
if
(
!
data
)
return
-
EINVAL
;
ptr
=
res
->
mem
;
ptr
=
option
->
mem
;
while
(
ptr
&&
ptr
->
next
)
ptr
=
ptr
->
next
;
if
(
ptr
)
ptr
->
next
=
data
;
else
res
->
mem
=
data
;
option
->
mem
=
data
;
return
0
;
}
...
...
@@ -221,18 +208,18 @@ static void pnp_free_mem(struct pnp_mem *mem)
}
}
void
pnp_free_
resources
(
struct
pnp_resources
*
resources
)
void
pnp_free_
option
(
struct
pnp_option
*
option
)
{
struct
pnp_
resources
*
next
;
struct
pnp_
option
*
next
;
while
(
resources
)
{
next
=
resources
->
dep
;
pnp_free_port
(
resources
->
port
);
pnp_free_irq
(
resources
->
irq
);
pnp_free_dma
(
resources
->
dma
);
pnp_free_mem
(
resources
->
mem
);
kfree
(
resources
);
resources
=
next
;
while
(
option
)
{
next
=
option
->
next
;
pnp_free_port
(
option
->
port
);
pnp_free_irq
(
option
->
irq
);
pnp_free_dma
(
option
->
dma
);
pnp_free_mem
(
option
->
mem
);
kfree
(
option
);
option
=
next
;
}
}
...
...
@@ -253,50 +240,23 @@ void pnp_free_resources(struct pnp_resources *resources)
(*(enda) >= *(startb) && *(enda) <= *(endb)) || \
(*(starta) < *(startb) && *(enda) > *(endb)))
struct
pnp_dev
*
pnp_check_port_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
)
{
int
tmp
;
unsigned
long
*
port
,
*
end
,
*
tport
,
*
tend
;
struct
pnp_dev
*
tdev
;
port
=
&
dev
->
res
.
port_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
port_resource
[
idx
].
end
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
port_resource
[
idx
].
start
==
0
)
return
NULL
;
/* check for cold conflicts */
pnp_for_each_dev
(
tdev
)
{
/* Is the device configurable? */
if
(
tdev
==
dev
||
(
mode
?
!
tdev
->
active
:
tdev
->
active
))
continue
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_PORT
;
tmp
++
)
{
if
(
tdev
->
res
.
port_resource
[
tmp
].
flags
&
IORESOURCE_IO
)
{
tport
=
&
tdev
->
res
.
port_resource
[
tmp
].
start
;
tend
=
&
tdev
->
res
.
port_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
port
,
end
,
tport
,
tend
))
return
tdev
;
}
}
}
return
NULL
;
}
int
pnp_check_port
(
struct
pnp_dev
*
dev
,
int
idx
)
{
int
tmp
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
port
,
*
end
,
*
tport
,
*
tend
;
port
=
&
dev
->
res
.
port_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
port_resource
[
idx
].
end
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
port_resource
[
idx
].
start
==
0
)
return
0
;
return
1
;
/* check if the resource is already in use, skip if the device is active because it itself may be in use */
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if
(
!
dev
->
active
)
{
if
(
check_region
(
*
port
,
length
(
port
,
end
)))
return
CONFLICT_TYPE_IN_USE
;
if
(
__check_region
(
&
ioport_resource
,
*
port
,
length
(
port
,
end
)))
return
0
;
}
/* check if the resource is reserved */
...
...
@@ -304,7 +264,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
int
rport
=
pnp_reserve_io
[
tmp
<<
1
];
int
rend
=
pnp_reserve_io
[(
tmp
<<
1
)
+
1
]
+
rport
-
1
;
if
(
ranged_conflict
(
port
,
end
,
&
rport
,
&
rend
))
return
CONFLICT_TYPE_RESERVED
;
return
0
;
}
/* check for internal conflicts */
...
...
@@ -313,61 +273,44 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
tport
=
&
dev
->
res
.
port_resource
[
tmp
].
start
;
tend
=
&
dev
->
res
.
port_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
port
,
end
,
tport
,
tend
))
return
CONFLICT_TYPE_INTERNAL
;
return
0
;
}
}
/* check for warm conflicts */
if
(
pnp_check_port_conflicts
(
dev
,
idx
,
SEARCH_WARM
))
return
CONFLICT_TYPE_PNP_WARM
;
return
0
;
}
struct
pnp_dev
*
pnp_check_mem_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
)
{
int
tmp
;
unsigned
long
*
addr
,
*
end
,
*
taddr
,
*
tend
;
struct
pnp_dev
*
tdev
;
addr
=
&
dev
->
res
.
mem_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
mem_resource
[
idx
].
end
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
mem_resource
[
idx
].
start
==
0
)
return
NULL
;
/* check for cold conflicts */
/* check for conflicts with other pnp devices */
pnp_for_each_dev
(
tdev
)
{
/* Is the device configurable? */
if
(
tdev
==
dev
||
(
mode
?
!
tdev
->
active
:
tdev
->
active
))
if
(
tdev
==
dev
)
continue
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_
MEM
;
tmp
++
)
{
if
(
tdev
->
res
.
mem_resource
[
tmp
].
flags
&
IORESOURCE_MEM
)
{
t
addr
=
&
tdev
->
res
.
mem
_resource
[
tmp
].
start
;
tend
=
&
tdev
->
res
.
mem
_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
addr
,
end
,
taddr
,
tend
))
return
tdev
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_
PORT
;
tmp
++
)
{
if
(
tdev
->
res
.
port_resource
[
tmp
].
flags
&
IORESOURCE_IO
)
{
t
port
=
&
tdev
->
res
.
port
_resource
[
tmp
].
start
;
tend
=
&
tdev
->
res
.
port
_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
port
,
end
,
tport
,
tend
))
return
0
;
}
}
}
return
NULL
;
return
1
;
}
int
pnp_check_mem
(
struct
pnp_dev
*
dev
,
int
idx
)
{
int
tmp
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
addr
,
*
end
,
*
taddr
,
*
tend
;
addr
=
&
dev
->
res
.
mem_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
mem_resource
[
idx
].
end
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
mem_resource
[
idx
].
start
==
0
)
return
0
;
return
1
;
/* check if the resource is already in use, skip if the device is active because it itself may be in use */
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if
(
!
dev
->
active
)
{
if
(
__check_region
(
&
iomem_resource
,
*
addr
,
length
(
addr
,
end
)))
return
CONFLICT_TYPE_IN_USE
;
if
(
check_mem_region
(
*
addr
,
length
(
addr
,
end
)))
return
0
;
}
/* check if the resource is reserved */
...
...
@@ -375,7 +318,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
int
raddr
=
pnp_reserve_mem
[
tmp
<<
1
];
int
rend
=
pnp_reserve_mem
[(
tmp
<<
1
)
+
1
]
+
raddr
-
1
;
if
(
ranged_conflict
(
addr
,
end
,
&
raddr
,
&
rend
))
return
CONFLICT_TYPE_RESERVED
;
return
0
;
}
/* check for internal conflicts */
...
...
@@ -384,40 +327,25 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
taddr
=
&
dev
->
res
.
mem_resource
[
tmp
].
start
;
tend
=
&
dev
->
res
.
mem_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
addr
,
end
,
taddr
,
tend
))
return
CONFLICT_TYPE_INTERNAL
;
return
0
;
}
}
/* check for warm conflicts */
if
(
pnp_check_mem_conflicts
(
dev
,
idx
,
SEARCH_WARM
))
return
CONFLICT_TYPE_PNP_WARM
;
return
0
;
}
struct
pnp_dev
*
pnp_check_irq_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
)
{
int
tmp
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
irq
=
&
dev
->
res
.
irq_resource
[
idx
].
start
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
irq_resource
[
idx
].
start
==
-
1
)
return
NULL
;
/* check for cold conflicts */
/* check for conflicts with other pnp devices */
pnp_for_each_dev
(
tdev
)
{
/* Is the device configurable? */
if
(
tdev
==
dev
||
(
mode
?
!
tdev
->
active
:
tdev
->
active
))
if
(
tdev
==
dev
)
continue
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_IRQ
;
tmp
++
)
{
if
(
tdev
->
res
.
irq_resource
[
tmp
].
flags
&
IORESOURCE_IRQ
)
{
if
((
tdev
->
res
.
irq_resource
[
tmp
].
start
==
*
irq
))
return
tdev
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_MEM
;
tmp
++
)
{
if
(
tdev
->
res
.
mem_resource
[
tmp
].
flags
&
IORESOURCE_MEM
)
{
taddr
=
&
tdev
->
res
.
mem_resource
[
tmp
].
start
;
tend
=
&
tdev
->
res
.
mem_resource
[
tmp
].
end
;
if
(
ranged_conflict
(
addr
,
end
,
taddr
,
tend
))
return
0
;
}
}
}
return
NULL
;
return
1
;
}
static
irqreturn_t
pnp_test_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
...
...
@@ -428,27 +356,28 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
int
pnp_check_irq
(
struct
pnp_dev
*
dev
,
int
idx
)
{
int
tmp
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
irq
=
&
dev
->
res
.
irq_resource
[
idx
].
start
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
irq_resource
[
idx
].
start
==
-
1
)
return
0
;
return
1
;
/* check if the resource is valid */
if
(
*
irq
<
0
||
*
irq
>
15
)
return
CONFLICT_TYPE_INVALID
;
return
0
;
/* check if the resource is reserved */
for
(
tmp
=
0
;
tmp
<
16
;
tmp
++
)
{
if
(
pnp_reserve_irq
[
tmp
]
==
*
irq
)
return
CONFLICT_TYPE_RESERVED
;
return
0
;
}
/* check for internal conflicts */
for
(
tmp
=
0
;
tmp
<
PNP_MAX_IRQ
&&
tmp
!=
idx
;
tmp
++
)
{
if
(
dev
->
res
.
irq_resource
[
tmp
].
flags
&
IORESOURCE_IRQ
)
{
if
(
dev
->
res
.
irq_resource
[
tmp
].
start
==
*
irq
)
return
CONFLICT_TYPE_INTERNAL
;
return
0
;
}
}
...
...
@@ -458,233 +387,94 @@ int pnp_check_irq(struct pnp_dev * dev, int idx)
struct
pci_dev
*
pci
=
NULL
;
while
((
pci
=
pci_find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
pci
))
!=
NULL
)
{
if
(
pci
->
irq
==
*
irq
)
return
CONFLICT_TYPE_PCI
;
return
0
;
}
}
#endif
/* check if the resource is already in use, skip if the device is active because it itself may be in use */
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if
(
!
dev
->
active
)
{
if
(
request_irq
(
*
irq
,
pnp_test_handler
,
SA_INTERRUPT
,
"pnp"
,
NULL
))
return
CONFLICT_TYPE_IN_USE
;
return
0
;
free_irq
(
*
irq
,
NULL
);
}
/* check for warm conflicts */
if
(
pnp_check_irq_conflicts
(
dev
,
idx
,
SEARCH_WARM
))
return
CONFLICT_TYPE_PNP_WARM
;
return
0
;
}
struct
pnp_dev
*
pnp_check_dma_conflicts
(
struct
pnp_dev
*
dev
,
int
idx
,
int
mode
)
{
int
tmp
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
dma
=
&
dev
->
res
.
dma_resource
[
idx
].
start
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
dma_resource
[
idx
].
start
==
-
1
)
return
NULL
;
/* check for cold conflicts */
/* check for conflicts with other pnp devices */
pnp_for_each_dev
(
tdev
)
{
/* Is the device configurable? */
if
(
tdev
==
dev
||
(
mode
?
!
tdev
->
active
:
tdev
->
active
))
if
(
tdev
==
dev
)
continue
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_
DMA
;
tmp
++
)
{
if
(
tdev
->
res
.
dma_resource
[
tmp
].
flags
&
IORESOURCE_DMA
)
{
if
((
tdev
->
res
.
dma_resource
[
tmp
].
start
==
*
dma
))
return
tdev
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_
IRQ
;
tmp
++
)
{
if
(
tdev
->
res
.
irq_resource
[
tmp
].
flags
&
IORESOURCE_IRQ
)
{
if
((
tdev
->
res
.
irq_resource
[
tmp
].
start
==
*
irq
))
return
0
;
}
}
}
return
NULL
;
return
1
;
}
int
pnp_check_dma
(
struct
pnp_dev
*
dev
,
int
idx
)
{
int
tmp
,
mindma
=
1
;
struct
pnp_dev
*
tdev
;
unsigned
long
*
dma
=
&
dev
->
res
.
dma_resource
[
idx
].
start
;
/* if the resource doesn't exist, don't complain about it */
if
(
dev
->
res
.
dma_resource
[
idx
].
start
==
-
1
)
return
0
;
return
1
;
/* check if the resource is valid */
if
(
pnp_allow_dma0
==
1
)
mindma
=
0
;
if
(
*
dma
<
mindma
||
*
dma
==
4
||
*
dma
>
7
)
return
CONFLICT_TYPE_INVALID
;
return
0
;
/* check if the resource is reserved */
for
(
tmp
=
0
;
tmp
<
8
;
tmp
++
)
{
if
(
pnp_reserve_dma
[
tmp
]
==
*
dma
)
return
CONFLICT_TYPE_RESERVED
;
return
0
;
}
/* check for internal conflicts */
for
(
tmp
=
0
;
tmp
<
PNP_MAX_DMA
&&
tmp
!=
idx
;
tmp
++
)
{
if
(
dev
->
res
.
dma_resource
[
tmp
].
flags
&
IORESOURCE_DMA
)
{
if
(
dev
->
res
.
dma_resource
[
tmp
].
start
==
*
dma
)
return
CONFLICT_TYPE_INTERNAL
;
return
0
;
}
}
/* check if the resource is already in use, skip if the device is active because it itself may be in use */
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */
if
(
!
dev
->
active
)
{
if
(
request_dma
(
*
dma
,
"pnp"
))
return
CONFLICT_TYPE_IN_USE
;
return
0
;
free_dma
(
*
dma
);
}
/* check for warm conflicts */
if
(
pnp_check_dma_conflicts
(
dev
,
idx
,
SEARCH_WARM
))
return
CONFLICT_TYPE_PNP_WARM
;
/* check for conflicts with other pnp devices */
pnp_for_each_dev
(
tdev
)
{
if
(
tdev
==
dev
)
continue
;
for
(
tmp
=
0
;
tmp
<
PNP_MAX_DMA
;
tmp
++
)
{
if
(
tdev
->
res
.
dma_resource
[
tmp
].
flags
&
IORESOURCE_DMA
)
{
if
((
tdev
->
res
.
dma_resource
[
tmp
].
start
==
*
dma
))
return
0
;
}
/**
* pnp_init_resource_table - Resets a resource table to default values.
* @table: pointer to the desired resource table
*
*/
void
pnp_init_resource_table
(
struct
pnp_resource_table
*
table
)
{
int
idx
;
for
(
idx
=
0
;
idx
<
PNP_MAX_IRQ
;
idx
++
)
{
table
->
irq_resource
[
idx
].
name
=
NULL
;
table
->
irq_resource
[
idx
].
start
=
-
1
;
table
->
irq_resource
[
idx
].
end
=
-
1
;
table
->
irq_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_DMA
;
idx
++
)
{
table
->
dma_resource
[
idx
].
name
=
NULL
;
table
->
dma_resource
[
idx
].
start
=
-
1
;
table
->
dma_resource
[
idx
].
end
=
-
1
;
table
->
dma_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_PORT
;
idx
++
)
{
table
->
port_resource
[
idx
].
name
=
NULL
;
table
->
port_resource
[
idx
].
start
=
0
;
table
->
port_resource
[
idx
].
end
=
0
;
table
->
port_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
for
(
idx
=
0
;
idx
<
PNP_MAX_MEM
;
idx
++
)
{
table
->
mem_resource
[
idx
].
name
=
NULL
;
table
->
mem_resource
[
idx
].
start
=
0
;
table
->
mem_resource
[
idx
].
end
=
0
;
table
->
mem_resource
[
idx
].
flags
=
IORESOURCE_AUTO
;
}
}
/**
* pnp_generate_rule - Creates a rule table structure based on depnum and device.
* @dev: pointer to the desired device
* @depnum: dependent function, if not valid will return an error
* @rule: pointer to a rule structure to record data to
*
*/
int
pnp_generate_rule
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_rule_table
*
rule
)
{
int
nport
=
0
,
nirq
=
0
,
ndma
=
0
,
nmem
=
0
;
struct
pnp_resources
*
res
;
struct
pnp_port
*
port
;
struct
pnp_mem
*
mem
;
struct
pnp_irq
*
irq
;
struct
pnp_dma
*
dma
;
if
(
depnum
<
0
||
!
rule
)
return
-
EINVAL
;
}
}
/* independent */
res
=
pnp_find_resources
(
dev
,
0
);
if
(
!
res
)
return
-
ENODEV
;
port
=
res
->
port
;
mem
=
res
->
mem
;
irq
=
res
->
irq
;
dma
=
res
->
dma
;
while
(
port
){
rule
->
port
[
nport
]
=
port
;
nport
++
;
port
=
port
->
next
;
}
while
(
mem
){
rule
->
mem
[
nmem
]
=
mem
;
nmem
++
;
mem
=
mem
->
next
;
}
while
(
irq
){
rule
->
irq
[
nirq
]
=
irq
;
nirq
++
;
irq
=
irq
->
next
;
}
while
(
dma
){
rule
->
dma
[
ndma
]
=
dma
;
ndma
++
;
dma
=
dma
->
next
;
}
/* dependent */
if
(
depnum
==
0
)
return
1
;
res
=
pnp_find_resources
(
dev
,
depnum
);
if
(
!
res
)
return
-
ENODEV
;
port
=
res
->
port
;
mem
=
res
->
mem
;
irq
=
res
->
irq
;
dma
=
res
->
dma
;
while
(
port
){
rule
->
port
[
nport
]
=
port
;
nport
++
;
port
=
port
->
next
;
}
while
(
mem
){
rule
->
mem
[
nmem
]
=
mem
;
nmem
++
;
mem
=
mem
->
next
;
}
while
(
irq
){
rule
->
irq
[
nirq
]
=
irq
;
nirq
++
;
irq
=
irq
->
next
;
}
while
(
dma
){
rule
->
dma
[
ndma
]
=
dma
;
ndma
++
;
dma
=
dma
->
next
;
}
/* clear the remaining values */
for
(;
nport
<
PNP_MAX_PORT
;
nport
++
)
rule
->
port
[
nport
]
=
NULL
;
for
(;
nmem
<
PNP_MAX_MEM
;
nmem
++
)
rule
->
mem
[
nmem
]
=
NULL
;
for
(;
nirq
<
PNP_MAX_IRQ
;
nirq
++
)
rule
->
irq
[
nirq
]
=
NULL
;
for
(;
ndma
<
PNP_MAX_DMA
;
ndma
++
)
rule
->
dma
[
ndma
]
=
NULL
;
return
1
;
}
EXPORT_SYMBOL
(
pnp_build_resource
);
EXPORT_SYMBOL
(
pnp_find_resources
);
EXPORT_SYMBOL
(
pnp_get_max_depnum
);
EXPORT_SYMBOL
(
pnp_add_irq_resource
);
EXPORT_SYMBOL
(
pnp_add_dma_resource
);
EXPORT_SYMBOL
(
pnp_add_port_resource
);
EXPORT_SYMBOL
(
pnp_add_mem_resource
);
EXPORT_SYMBOL
(
pnp_init_resource_table
);
EXPORT_SYMBOL
(
pnp_generate_rule
);
EXPORT_SYMBOL
(
pnp_register_dependent_option
);
EXPORT_SYMBOL
(
pnp_register_independent_option
);
EXPORT_SYMBOL
(
pnp_register_irq_resource
);
EXPORT_SYMBOL
(
pnp_register_dma_resource
);
EXPORT_SYMBOL
(
pnp_register_port_resource
);
EXPORT_SYMBOL
(
pnp_register_mem_resource
);
/* format is: allowdma0 */
...
...
drivers/pnp/support.c
View file @
d3899e3c
/*
* support.c - provides standard pnp functions for the use of pnp protocol drivers,
*
* Copyright 200
2
Adam Belay <ambx1@neo.rr.com>
* Copyright 200
3
Adam Belay <ambx1@neo.rr.com>
*
* Resource parsing functions are based on those in the linux pnpbios driver.
* Copyright Christian Schmidt, Tom Lees, David Hinds, Alan Cox, Thomas Hood,
...
...
@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ctype.h>
#ifdef CONFIG_PNP_DEBUG
#define DEBUG
...
...
@@ -122,7 +123,7 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e
return
NULL
;
/* Blank the resource table values */
pnp_init_resource
_table
(
res
);
pnp_init_resource
s
(
res
);
while
((
char
*
)
p
<
(
char
*
)
end
)
{
...
...
@@ -250,51 +251,51 @@ unsigned char * pnp_parse_current_resources(unsigned char * p, unsigned char * e
* Possible resource reading functions *
*/
static
void
possible_mem
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_mem
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_mem
*
mem
;
mem
=
pnp_alloc
(
sizeof
(
struct
pnp_mem
));
if
(
!
mem
)
return
;
mem
->
min
=
((
p
[
3
]
<<
8
)
|
p
[
2
])
<<
8
;
mem
->
max
=
((
p
[
5
]
<<
8
)
|
p
[
4
])
<<
8
;
mem
->
align
=
(
p
[
7
]
<<
8
)
|
p
[
6
];
mem
->
size
=
((
p
[
9
]
<<
8
)
|
p
[
8
])
<<
8
;
mem
->
flags
=
p
[
1
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
mem
->
min
=
((
p
[
5
]
<<
8
)
|
p
[
4
])
<<
8
;
mem
->
max
=
((
p
[
7
]
<<
8
)
|
p
[
6
])
<<
8
;
mem
->
align
=
(
p
[
9
]
<<
8
)
|
p
[
8
];
mem
->
size
=
((
p
[
11
]
<<
8
)
|
p
[
10
])
<<
8
;
mem
->
flags
=
p
[
3
];
pnp_
register_mem_resource
(
option
,
mem
);
return
;
}
static
void
possible_mem32
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_mem32
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_mem
*
mem
;
mem
=
pnp_alloc
(
sizeof
(
struct
pnp_mem
));
if
(
!
mem
)
return
;
mem
->
min
=
(
p
[
5
]
<<
24
)
|
(
p
[
4
]
<<
16
)
|
(
p
[
3
]
<<
8
)
|
p
[
2
];
mem
->
max
=
(
p
[
9
]
<<
24
)
|
(
p
[
8
]
<<
16
)
|
(
p
[
7
]
<<
8
)
|
p
[
6
];
mem
->
align
=
(
p
[
1
3
]
<<
24
)
|
(
p
[
12
]
<<
16
)
|
(
p
[
11
]
<<
8
)
|
p
[
10
];
mem
->
size
=
(
p
[
1
7
]
<<
24
)
|
(
p
[
16
]
<<
16
)
|
(
p
[
15
]
<<
8
)
|
p
[
14
];
mem
->
flags
=
p
[
1
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
mem
->
min
=
(
p
[
7
]
<<
24
)
|
(
p
[
6
]
<<
16
)
|
(
p
[
5
]
<<
8
)
|
p
[
4
];
mem
->
max
=
(
p
[
11
]
<<
24
)
|
(
p
[
10
]
<<
16
)
|
(
p
[
9
]
<<
8
)
|
p
[
8
];
mem
->
align
=
(
p
[
1
5
]
<<
24
)
|
(
p
[
14
]
<<
16
)
|
(
p
[
13
]
<<
8
)
|
p
[
12
];
mem
->
size
=
(
p
[
1
9
]
<<
24
)
|
(
p
[
18
]
<<
16
)
|
(
p
[
17
]
<<
8
)
|
p
[
16
];
mem
->
flags
=
p
[
3
];
pnp_
register_mem_resource
(
option
,
mem
);
return
;
}
static
void
possible_fixed_mem32
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_fixed_mem32
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_mem
*
mem
;
mem
=
pnp_alloc
(
sizeof
(
struct
pnp_mem
));
if
(
!
mem
)
return
;
mem
->
min
=
mem
->
max
=
(
p
[
5
]
<<
24
)
|
(
p
[
4
]
<<
16
)
|
(
p
[
3
]
<<
8
)
|
p
[
2
];
mem
->
size
=
(
p
[
9
]
<<
24
)
|
(
p
[
8
]
<<
16
)
|
(
p
[
7
]
<<
8
)
|
p
[
6
];
mem
->
min
=
mem
->
max
=
(
p
[
7
]
<<
24
)
|
(
p
[
6
]
<<
16
)
|
(
p
[
5
]
<<
8
)
|
p
[
4
];
mem
->
size
=
(
p
[
11
]
<<
24
)
|
(
p
[
10
]
<<
16
)
|
(
p
[
9
]
<<
8
)
|
p
[
8
];
mem
->
align
=
0
;
mem
->
flags
=
p
[
1
];
pnp_
add_mem_resource
(
dev
,
depnum
,
mem
);
mem
->
flags
=
p
[
3
];
pnp_
register_mem_resource
(
option
,
mem
);
return
;
}
static
void
possible_irq
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_irq
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_irq
*
irq
;
irq
=
pnp_alloc
(
sizeof
(
struct
pnp_irq
));
...
...
@@ -303,11 +304,13 @@ static void possible_irq(unsigned char *p, int size, int depnum, struct pnp_dev
irq
->
map
=
(
p
[
2
]
<<
8
)
|
p
[
1
];
if
(
size
>
2
)
irq
->
flags
=
p
[
3
];
pnp_add_irq_resource
(
dev
,
depnum
,
irq
);
else
irq
->
flags
=
IORESOURCE_IRQ_HIGHEDGE
;
pnp_register_irq_resource
(
option
,
irq
);
return
;
}
static
void
possible_dma
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_dma
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_dma
*
dma
;
dma
=
pnp_alloc
(
sizeof
(
struct
pnp_dma
));
...
...
@@ -315,11 +318,11 @@ static void possible_dma(unsigned char *p, int size, int depnum, struct pnp_dev
return
;
dma
->
map
=
p
[
1
];
dma
->
flags
=
p
[
2
];
pnp_
add_dma_resource
(
dev
,
depnum
,
dma
);
pnp_
register_dma_resource
(
option
,
dma
);
return
;
}
static
void
possible_port
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_port
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_port
*
port
;
port
=
pnp_alloc
(
sizeof
(
struct
pnp_port
));
...
...
@@ -330,11 +333,11 @@ static void possible_port(unsigned char *p, int size, int depnum, struct pnp_dev
port
->
align
=
p
[
6
];
port
->
size
=
p
[
7
];
port
->
flags
=
p
[
1
]
?
PNP_PORT_FLAG_16BITADDR
:
0
;
pnp_
add_port_resource
(
dev
,
depnum
,
port
);
pnp_
register_port_resource
(
option
,
port
);
return
;
}
static
void
possible_fixed_port
(
unsigned
char
*
p
,
int
size
,
int
depnum
,
struct
pnp_dev
*
dev
)
static
void
possible_fixed_port
(
unsigned
char
*
p
,
int
size
,
struct
pnp_option
*
option
)
{
struct
pnp_port
*
port
;
port
=
pnp_alloc
(
sizeof
(
struct
pnp_port
));
...
...
@@ -344,7 +347,7 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p
port
->
size
=
p
[
3
];
port
->
align
=
0
;
port
->
flags
=
PNP_PORT_FLAG_FIXED
;
pnp_
add_port_resource
(
dev
,
depnum
,
port
);
pnp_
register_port_resource
(
option
,
port
);
return
;
}
...
...
@@ -358,12 +361,14 @@ static void possible_fixed_port(unsigned char *p, int size, int depnum, struct p
unsigned
char
*
pnp_parse_possible_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_dev
*
dev
)
{
int
len
,
depnum
=
0
,
dependent
=
0
;
int
len
,
priority
=
0
;
struct
pnp_option
*
option
;
if
(
!
p
)
return
NULL
;
if
(
pnp_build_resource
(
dev
,
0
)
==
NULL
)
option
=
pnp_register_independent_option
(
dev
);
if
(
!
option
)
return
NULL
;
while
((
char
*
)
p
<
(
char
*
)
end
)
{
...
...
@@ -375,21 +380,21 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char *
{
if
(
len
!=
9
)
goto
lrg_err
;
possible_mem
(
p
,
len
,
depnum
,
dev
);
possible_mem
(
p
,
len
,
option
);
break
;
}
case
LARGE_TAG_MEM32
:
{
if
(
len
!=
17
)
goto
lrg_err
;
possible_mem32
(
p
,
len
,
depnum
,
dev
);
possible_mem32
(
p
,
len
,
option
);
break
;
}
case
LARGE_TAG_FIXEDMEM32
:
{
if
(
len
!=
9
)
goto
lrg_err
;
possible_fixed_mem32
(
p
,
len
,
depnum
,
dev
);
possible_fixed_mem32
(
p
,
len
,
option
);
break
;
}
default:
/* an unkown tag */
...
...
@@ -410,46 +415,46 @@ unsigned char * pnp_parse_possible_resources(unsigned char * p, unsigned char *
{
if
(
len
<
2
||
len
>
3
)
goto
sm_err
;
possible_irq
(
p
,
len
,
depnum
,
dev
);
possible_irq
(
p
,
len
,
option
);
break
;
}
case
SMALL_TAG_DMA
:
{
if
(
len
!=
2
)
goto
sm_err
;
possible_dma
(
p
,
len
,
depnum
,
dev
);
possible_dma
(
p
,
len
,
option
);
break
;
}
case
SMALL_TAG_STARTDEP
:
{
if
(
len
>
1
)
goto
sm_err
;
dependent
=
0x100
|
PNP_RES_PRIORITY_ACCEPTABLE
;
priority
=
0x100
|
PNP_RES_PRIORITY_ACCEPTABLE
;
if
(
len
>
0
)
dependent
=
0x100
|
p
[
1
];
pnp_build_resource
(
dev
,
dependent
);
depnum
=
pnp_get_max_depnum
(
dev
);
priority
=
0x100
|
p
[
1
];
option
=
pnp_register_dependent_option
(
dev
,
priority
);
if
(
!
option
)
return
NULL
;
break
;
}
case
SMALL_TAG_ENDDEP
:
{
if
(
len
!=
0
)
goto
sm_err
;
depnum
=
0
;
break
;
}
case
SMALL_TAG_PORT
:
{
if
(
len
!=
7
)
goto
sm_err
;
possible_port
(
p
,
len
,
depnum
,
dev
);
possible_port
(
p
,
len
,
option
);
break
;
}
case
SMALL_TAG_FIXEDPORT
:
{
if
(
len
!=
3
)
goto
sm_err
;
possible_fixed_port
(
p
,
len
,
depnum
,
dev
);
possible_fixed_port
(
p
,
len
,
option
);
break
;
}
case
SMALL_TAG_END
:
...
...
@@ -481,12 +486,12 @@ static void write_mem(unsigned char *p, struct resource * res)
{
unsigned
long
base
=
res
->
start
;
unsigned
long
len
=
res
->
end
-
res
->
start
+
1
;
p
[
2
]
=
(
base
>>
8
)
&
0xff
;
p
[
3
]
=
((
base
>>
8
)
>>
8
)
&
0xff
;
p
[
4
]
=
(
base
>>
8
)
&
0xff
;
p
[
5
]
=
((
base
>>
8
)
>>
8
)
&
0xff
;
p
[
8
]
=
(
len
>>
8
)
&
0xff
;
p
[
9
]
=
((
len
>>
8
)
>>
8
)
&
0xff
;
p
[
6
]
=
(
base
>>
8
)
&
0xff
;
p
[
7
]
=
((
base
>>
8
)
>>
8
)
&
0xff
;
p
[
10
]
=
(
len
>>
8
)
&
0xff
;
p
[
11
]
=
((
len
>>
8
)
>>
8
)
&
0xff
;
return
;
}
...
...
@@ -494,32 +499,32 @@ static void write_mem32(unsigned char *p, struct resource * res)
{
unsigned
long
base
=
res
->
start
;
unsigned
long
len
=
res
->
end
-
res
->
start
+
1
;
p
[
2
]
=
base
&
0xff
;
p
[
3
]
=
(
base
>>
8
)
&
0xff
;
p
[
4
]
=
(
base
>>
16
)
&
0xff
;
p
[
5
]
=
(
base
>>
24
)
&
0xff
;
p
[
6
]
=
base
&
0xff
;
p
[
7
]
=
(
base
>>
8
)
&
0xff
;
p
[
8
]
=
(
base
>>
16
)
&
0xff
;
p
[
9
]
=
(
base
>>
24
)
&
0xff
;
p
[
1
4
]
=
len
&
0xff
;
p
[
1
5
]
=
(
len
>>
8
)
&
0xff
;
p
[
1
6
]
=
(
len
>>
16
)
&
0xff
;
p
[
1
7
]
=
(
len
>>
24
)
&
0xff
;
p
[
4
]
=
base
&
0xff
;
p
[
5
]
=
(
base
>>
8
)
&
0xff
;
p
[
6
]
=
(
base
>>
16
)
&
0xff
;
p
[
7
]
=
(
base
>>
24
)
&
0xff
;
p
[
8
]
=
base
&
0xff
;
p
[
9
]
=
(
base
>>
8
)
&
0xff
;
p
[
10
]
=
(
base
>>
16
)
&
0xff
;
p
[
11
]
=
(
base
>>
24
)
&
0xff
;
p
[
1
6
]
=
len
&
0xff
;
p
[
1
7
]
=
(
len
>>
8
)
&
0xff
;
p
[
1
8
]
=
(
len
>>
16
)
&
0xff
;
p
[
1
9
]
=
(
len
>>
24
)
&
0xff
;
return
;
}
static
void
write_fixed_mem32
(
unsigned
char
*
p
,
struct
resource
*
res
)
{
unsigned
long
base
=
res
->
start
;
unsigned
long
len
=
res
->
end
-
res
->
start
+
1
;
p
[
2
]
=
base
&
0xff
;
p
[
3
]
=
(
base
>>
8
)
&
0xff
;
p
[
4
]
=
(
base
>>
16
)
&
0xff
;
p
[
5
]
=
(
base
>>
24
)
&
0xff
;
p
[
6
]
=
len
&
0xff
;
p
[
7
]
=
(
len
>>
8
)
&
0xff
;
p
[
8
]
=
(
len
>>
16
)
&
0xff
;
p
[
9
]
=
(
len
>>
24
)
&
0xff
;
p
[
4
]
=
base
&
0xff
;
p
[
5
]
=
(
base
>>
8
)
&
0xff
;
p
[
6
]
=
(
base
>>
16
)
&
0xff
;
p
[
7
]
=
(
base
>>
24
)
&
0xff
;
p
[
8
]
=
len
&
0xff
;
p
[
9
]
=
(
len
>>
8
)
&
0xff
;
p
[
10
]
=
(
len
>>
16
)
&
0xff
;
p
[
11
]
=
(
len
>>
24
)
&
0xff
;
return
;
}
...
...
@@ -630,7 +635,7 @@ unsigned char * pnp_write_resources(unsigned char * p, unsigned char * end, stru
{
if
(
len
!=
2
)
goto
sm_err
;
write_dma
(
p
,
&
res
->
dma_resource
[
irq
]);
write_dma
(
p
,
&
res
->
dma_resource
[
dma
]);
dma
++
;
break
;
}
...
...
drivers/serial/8250_pnp.c
View file @
d3899e3c
...
...
@@ -315,19 +315,6 @@ static const struct pnp_device_id pnp_dev_table[] = {
MODULE_DEVICE_TABLE
(
pnp
,
pnp_dev_table
);
static
inline
void
avoid_irq_share
(
struct
pnp_dev
*
dev
)
{
unsigned
int
map
=
0x1FF8
;
struct
pnp_irq
*
irq
;
struct
pnp_resources
*
res
=
dev
->
possible
;
serial8250_get_irq_map
(
&
map
);
for
(
;
res
;
res
=
res
->
dep
)
for
(
irq
=
res
->
irq
;
irq
;
irq
=
irq
->
next
)
irq
->
map
=
map
;
}
static
char
*
modem_names
[]
__devinitdata
=
{
"MODEM"
,
"Modem"
,
"modem"
,
"FAX"
,
"Fax"
,
"fax"
,
"56K"
,
"56k"
,
"K56"
,
"33.6"
,
"28.8"
,
"14.4"
,
...
...
@@ -346,6 +333,29 @@ static int __devinit check_name(char *name)
return
0
;
}
static
int
__devinit
check_resources
(
struct
pnp_option
*
option
)
{
struct
pnp_option
*
tmp
;
if
(
!
option
)
return
0
;
for
(
tmp
=
option
;
tmp
;
tmp
=
tmp
->
next
)
{
struct
pnp_port
*
port
;
for
(
port
=
tmp
->
port
;
port
;
port
=
port
->
next
)
if
((
port
->
size
==
8
)
&&
((
port
->
min
==
0x2f8
)
||
(
port
->
min
==
0x3f8
)
||
(
port
->
min
==
0x2e8
)
||
#ifdef CONFIG_X86_PC9800
(
port
->
min
==
0x8b0
)
||
#endif
(
port
->
min
==
0x3e8
)))
return
1
;
}
return
0
;
}
/*
* Given a complete unknown PnP device, try to use some heuristics to
* detect modems. Currently use such heuristic set:
...
...
@@ -357,30 +367,16 @@ static int __devinit check_name(char *name)
* PnP modems, alternatively we must hardcode all modems in pnp_devices[]
* table.
*/
static
int
serial_pnp_guess_board
(
struct
pnp_dev
*
dev
,
int
*
flags
)
static
int
__devinit
serial_pnp_guess_board
(
struct
pnp_dev
*
dev
,
int
*
flags
)
{
struct
pnp_resources
*
res
=
dev
->
possible
;
struct
pnp_resources
*
resa
;
if
(
!
(
check_name
(
dev
->
dev
.
name
)
||
(
dev
->
card
&&
check_name
(
dev
->
card
->
dev
.
name
))))
return
-
ENODEV
;
if
(
!
res
)
return
-
ENODEV
;
if
(
check_resources
(
dev
->
independent
)
)
return
0
;
for
(
resa
=
res
->
dep
;
resa
;
resa
=
resa
->
dep
)
{
struct
pnp_port
*
port
;
for
(
port
=
res
->
port
;
port
;
port
=
port
->
next
)
if
((
port
->
size
==
8
)
&&
((
port
->
min
==
0x2f8
)
||
(
port
->
min
==
0x3f8
)
||
(
port
->
min
==
0x2e8
)
||
#ifdef CONFIG_X86_PC9800
(
port
->
min
==
0x8b0
)
||
#endif
(
port
->
min
==
0x3e8
)))
if
(
check_resources
(
dev
->
dependent
))
return
0
;
}
return
-
ENODEV
;
}
...
...
@@ -395,8 +391,6 @@ serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
if
(
ret
<
0
)
return
ret
;
}
if
(
flags
&
SPCI_FL_NO_SHIRQ
)
avoid_irq_share
(
dev
);
memset
(
&
serial_req
,
0
,
sizeof
(
serial_req
));
serial_req
.
irq
=
pnp_irq
(
dev
,
0
);
serial_req
.
port
=
pnp_port_start
(
dev
,
0
);
...
...
include/linux/pnp.h
View file @
d3899e3c
...
...
@@ -102,22 +102,13 @@ struct pnp_mem {
#define PNP_RES_PRIORITY_FUNCTIONAL 2
#define PNP_RES_PRIORITY_INVALID 65535
struct
pnp_
resources
{
struct
pnp_
option
{
unsigned
short
priority
;
/* priority */
struct
pnp_port
*
port
;
/* first port */
struct
pnp_irq
*
irq
;
/* first IRQ */
struct
pnp_dma
*
dma
;
/* first DMA */
struct
pnp_mem
*
mem
;
/* first memory resource */
struct
pnp_dev
*
dev
;
/* parent */
struct
pnp_resources
*
dep
;
/* dependent resources */
};
struct
pnp_rule_table
{
int
depnum
;
struct
pnp_port
*
port
[
PNP_MAX_PORT
];
struct
pnp_irq
*
irq
[
PNP_MAX_IRQ
];
struct
pnp_dma
*
dma
[
PNP_MAX_DMA
];
struct
pnp_mem
*
mem
[
PNP_MAX_MEM
];
struct
pnp_option
*
next
;
/* used to chain dependent resources */
};
struct
pnp_resource_table
{
...
...
@@ -187,8 +178,6 @@ static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data
struct
pnp_dev
{
struct
device
dev
;
/* Driver Model device interface */
unsigned
char
number
;
/* used as an index, must be unique */
int
active
;
int
capabilities
;
int
status
;
struct
list_head
global_list
;
/* node in global list of devices */
...
...
@@ -202,10 +191,12 @@ struct pnp_dev {
struct
pnp_card_link
*
card_link
;
struct
pnp_id
*
id
;
/* supported EISA IDs*/
struct
pnp_resource_table
res
;
/* contains the currently chosen resources */
struct
pnp_resources
*
possible
;
/* a list of possible resources */
struct
pnp_rule_table
*
rule
;
/* the current possible resource set */
int
config_mode
;
/* flags that determine how the device's resources should be configured */
int
active
;
int
capabilities
;
struct
pnp_option
*
independent
;
struct
pnp_option
*
dependent
;
struct
pnp_resource_table
res
;
void
*
protocol_data
;
/* Used to store protocol specific data */
unsigned
short
regs
;
/* ISAPnP: supported registers */
...
...
@@ -252,11 +243,9 @@ struct pnp_fixup {
void
(
*
quirk_function
)(
struct
pnp_dev
*
dev
);
/* fixup function */
};
/* config modes */
#define PNP_CONFIG_AUTO 0x0001
/* Use the Resource Configuration Engine to determine resource settings */
#define PNP_CONFIG_MANUAL 0x0002
/* the config has been manually specified */
#define PNP_CONFIG_FORCE 0x0004
/* disables validity checking */
#define PNP_CONFIG_INVALID 0x0008
/* If this flag is set, the pnp layer will refuse to activate the device */
/* config parameters */
#define PNP_CONFIG_NORMAL 0x0001
#define PNP_CONFIG_FORCE 0x0002
/* disables validity checking */
/* capabilities */
#define PNP_READ 0x0001
...
...
@@ -271,7 +260,7 @@ struct pnp_fixup {
((dev)->capabilities & PNP_WRITE))
#define pnp_can_disable(dev) (((dev)->protocol) && ((dev)->protocol->disable) && \
((dev)->capabilities & PNP_DISABLE))
#define pnp_can_configure(dev) ((!(dev)->active) &&
((dev)->config_mode & PNP_CONFIG_AUTO) &&
\
#define pnp_can_configure(dev) ((!(dev)->active) && \
((dev)->capabilities & PNP_CONFIGURABLE))
#ifdef CONFIG_ISAPNP
...
...
@@ -383,7 +372,7 @@ struct pnp_protocol {
#if defined(CONFIG_PNP)
/*
core
*/
/*
device management
*/
int
pnp_register_protocol
(
struct
pnp_protocol
*
protocol
);
void
pnp_unregister_protocol
(
struct
pnp_protocol
*
protocol
);
int
pnp_add_device
(
struct
pnp_dev
*
dev
);
...
...
@@ -392,7 +381,7 @@ int pnp_device_attach(struct pnp_dev *pnp_dev);
void
pnp_device_detach
(
struct
pnp_dev
*
pnp_dev
);
extern
struct
list_head
pnp_global
;
/*
card
*/
/*
multidevice card support
*/
int
pnp_add_card
(
struct
pnp_card
*
card
);
void
pnp_remove_card
(
struct
pnp_card
*
card
);
int
pnp_add_card_device
(
struct
pnp_card
*
card
,
struct
pnp_dev
*
dev
);
...
...
@@ -404,41 +393,35 @@ int pnp_register_card_driver(struct pnp_card_driver * drv);
void
pnp_unregister_card_driver
(
struct
pnp_card_driver
*
drv
);
extern
struct
list_head
pnp_cards
;
/* resource */
struct
pnp_
resources
*
pnp_build_resource
(
struct
pnp_dev
*
dev
,
int
dependent
);
struct
pnp_
resources
*
pnp_find_resources
(
struct
pnp_dev
*
dev
,
int
depnum
);
int
pnp_
get_max_depnum
(
struct
pnp_dev
*
dev
);
int
pnp_
add_irq_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
);
int
pnp_
add_dma_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_dma
*
data
);
int
pnp_
add_port_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_port
*
data
);
int
pnp_add_mem_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_mem
*
data
);
void
pnp_init_resource_table
(
struct
pnp_resource_table
*
table
);
int
pnp_
generate_rule
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_rule_table
*
rul
e
);
/* manager */
/* resource
management
*/
struct
pnp_
option
*
pnp_register_independent_option
(
struct
pnp_dev
*
dev
);
struct
pnp_
option
*
pnp_register_dependent_option
(
struct
pnp_dev
*
dev
,
int
priority
);
int
pnp_
register_irq_resource
(
struct
pnp_option
*
option
,
struct
pnp_irq
*
data
);
int
pnp_
register_dma_resource
(
struct
pnp_option
*
option
,
struct
pnp_dma
*
data
);
int
pnp_
register_port_resource
(
struct
pnp_option
*
option
,
struct
pnp_port
*
data
);
int
pnp_
register_mem_resource
(
struct
pnp_option
*
option
,
struct
pnp_mem
*
data
);
void
pnp_init_resources
(
struct
pnp_resource_table
*
table
);
int
pnp_assign_resources
(
struct
pnp_dev
*
dev
,
int
depnum
);
int
pnp_
manual_config_dev
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
,
int
mod
e
);
int
pnp_auto_config_dev
(
struct
pnp_dev
*
dev
);
int
pnp_validate_config
(
struct
pnp_dev
*
dev
);
int
pnp_activate_dev
(
struct
pnp_dev
*
dev
);
int
pnp_disable_dev
(
struct
pnp_dev
*
dev
);
void
pnp_resource_change
(
struct
resource
*
resource
,
unsigned
long
start
,
unsigned
long
size
);
int
pnp_manual_config_dev
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
,
int
mode
);
int
pnp_auto_config_dev
(
struct
pnp_dev
*
dev
);
/* driver */
int
compare_pnp_id
(
struct
pnp_id
*
pos
,
const
char
*
id
);
int
pnp_add_id
(
struct
pnp_id
*
id
,
struct
pnp_dev
*
dev
);
int
pnp_register_driver
(
struct
pnp_driver
*
drv
);
void
pnp_unregister_driver
(
struct
pnp_driver
*
drv
);
/*
support
*/
/*
protocol helpers
*/
int
pnp_is_active
(
struct
pnp_dev
*
dev
);
unsigned
char
*
pnp_parse_current_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_resource_table
*
res
);
unsigned
char
*
pnp_parse_possible_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_dev
*
dev
);
unsigned
char
*
pnp_write_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_resource_table
*
res
);
int
compare_pnp_id
(
struct
pnp_id
*
pos
,
const
char
*
id
);
int
pnp_add_id
(
struct
pnp_id
*
id
,
struct
pnp_dev
*
dev
);
int
pnp_register_driver
(
struct
pnp_driver
*
drv
);
void
pnp_unregister_driver
(
struct
pnp_driver
*
drv
);
#else
/* just in case anyone decides to call these without PnP Support Enabled */
/* core */
/* device management */
static
inline
int
pnp_register_protocol
(
struct
pnp_protocol
*
protocol
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_unregister_protocol
(
struct
pnp_protocol
*
protocol
)
{
}
static
inline
int
pnp_init_device
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
...
...
@@ -447,7 +430,7 @@ static inline void pnp_remove_device(struct pnp_dev *dev) { }
static
inline
int
pnp_device_attach
(
struct
pnp_dev
*
pnp_dev
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_device_detach
(
struct
pnp_dev
*
pnp_dev
)
{
;
}
/*
card
*/
/*
multidevice card support
*/
static
inline
int
pnp_add_card
(
struct
pnp_card
*
card
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_remove_card
(
struct
pnp_card
*
card
)
{
;
}
static
inline
int
pnp_add_card_device
(
struct
pnp_card
*
card
,
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
...
...
@@ -458,35 +441,31 @@ static inline void pnp_release_card_device(struct pnp_dev * dev) { ; }
static
inline
int
pnp_register_card_driver
(
struct
pnp_card_driver
*
drv
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_unregister_card_driver
(
struct
pnp_card_driver
*
drv
)
{
;
}
/* resource */
static
inline
struct
pnp_resources
*
pnp_build_resource
(
struct
pnp_dev
*
dev
,
int
dependent
)
{
return
NULL
;
}
static
inline
struct
pnp_resources
*
pnp_find_resources
(
struct
pnp_dev
*
dev
,
int
depnum
)
{
return
NULL
;
}
static
inline
int
pnp_get_max_depnum
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_irq_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_dma_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_port_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_mem_resource
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_irq
*
data
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_init_resource_table
(
struct
pnp_resource_table
*
table
)
{
;
}
static
inline
int
pnp_generate_rule
(
struct
pnp_dev
*
dev
,
int
depnum
,
struct
pnp_rule_table
*
rule
)
{
return
-
ENODEV
;
}
/* manager */
static
inline
int
pnp_activate_dev
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_disable_dev
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_resource_change
(
struct
resource
*
resource
,
unsigned
long
start
,
unsigned
long
size
)
{
;
}
/* resource management */
static
inline
struct
pnp_option
*
pnp_register_independent_option
(
struct
pnp_dev
*
dev
)
{
return
NULL
;
}
static
inline
struct
pnp_option
*
pnp_register_dependent_option
(
struct
pnp_dev
*
dev
,
int
priority
)
{
return
NULL
;
}
static
inline
int
pnp_register_irq_resource
(
struct
pnp_option
*
option
,
struct
pnp_irq
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_register_dma_resource
(
struct
pnp_option
*
option
,
struct
pnp_dma
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_register_port_resource
(
struct
pnp_option
*
option
,
struct
pnp_port
*
data
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_register_mem_resource
(
struct
pnp_option
*
option
,
struct
pnp_mem
*
data
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_init_resources
(
struct
pnp_resource_table
*
table
)
{
}
static
inline
int
pnp_assign_resources
(
struct
pnp_dev
*
dev
,
int
depnum
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_manual_config_dev
(
struct
pnp_dev
*
dev
,
struct
pnp_resource_table
*
res
,
int
mode
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_auto_config_dev
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_validate_config
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_activate_dev
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_disable_dev
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_resource_change
(
struct
resource
*
resource
,
unsigned
long
start
,
unsigned
long
size
)
{
}
/* driver */
static
inline
int
compare_pnp_id
(
struct
list_head
*
id_list
,
const
char
*
id
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_id
(
struct
pnp_id
*
id
,
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_register_driver
(
struct
pnp_driver
*
drv
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_unregister_driver
(
struct
pnp_driver
*
drv
)
{
;
}
/* support */
static
inline
int
pnp_is_active
(
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
/* protocol helpers */
static
inline
int
pnp_is_active
(
struct
pnp_dev
*
dev
)
{
return
0
;
}
static
inline
unsigned
char
*
pnp_parse_current_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_resource_table
*
res
)
{
return
NULL
;
}
static
inline
unsigned
char
*
pnp_parse_possible_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_dev
*
dev
)
{
return
NULL
;
}
static
inline
unsigned
char
*
pnp_write_resources
(
unsigned
char
*
p
,
unsigned
char
*
end
,
struct
pnp_resource_table
*
res
)
{
return
NULL
;
}
static
inline
int
compare_pnp_id
(
struct
pnp_id
*
pos
,
const
char
*
id
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_add_id
(
struct
pnp_id
*
id
,
struct
pnp_dev
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
pnp_register_driver
(
struct
pnp_driver
*
drv
)
{
return
-
ENODEV
;
}
static
inline
void
pnp_unregister_driver
(
struct
pnp_driver
*
drv
)
{
;
}
#endif
/* CONFIG_PNP */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment