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
Kirill Smelkov
linux
Commits
a7035a19
Commit
a7035a19
authored
Jun 18, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://are.twiddle.net/axp-2.5/
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
a58d5360
d3899e3c
Changes
11
Hide 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 @
a7035a19
...
...
@@ -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 @
a7035a19
...
...
@@ -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 @
a7035a19
...
...
@@ -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,49 +177,55 @@ 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
)
{
case
PNP_RES_PRIORITY_PREFERRED
:
s
=
"preferred"
;
break
;
case
PNP_RES_PRIORITY_ACCEPTABLE
:
s
=
"acceptable"
;
break
;
case
PNP_RES_PRIORITY_FUNCTIONAL
:
s
=
"functional"
;
break
;
default:
s
=
"invalid"
;
}
if
(
dep
>
0
)
if
(
dep
)
{
switch
(
option
->
priority
)
{
case
PNP_RES_PRIORITY_PREFERRED
:
s
=
"preferred"
;
break
;
case
PNP_RES_PRIORITY_ACCEPTABLE
:
s
=
"acceptable"
;
break
;
case
PNP_RES_PRIORITY_FUNCTIONAL
:
s
=
"functional"
;
break
;
default:
s
=
"invalid"
;
}
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
;
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
);
static
DEVICE_ATTR
(
options
,
S_IRUGO
,
pnp_show_options
,
NULL
);
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 @
a7035a19
...
...
@@ -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,14 +614,14 @@ 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
);
}
/*
* Parse card name for ISA PnP device.
*/
static
void
__init
static
void
__init
isapnp_parse_name
(
char
*
name
,
unsigned
int
name_max
,
unsigned
short
*
size
)
{
if
(
name
[
0
]
==
'\0'
)
{
...
...
@@ -634,7 +633,7 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
/* clean whitespace from end of string */
while
(
size1
>
0
&&
name
[
--
size1
]
==
' '
)
name
[
size1
]
=
'\0'
;
}
}
}
/*
...
...
@@ -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 @
a7035a19
/*
* 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
))
*
flags
|=
IORESOURCE_READONLY
;
if
(
mem
->
flags
&
IORESOURCE_MEM_CACHEABLE
)
*
flags
|=
IORESOURCE_CACHEABLE
;
if
(
mem
->
flags
&
IORESOURCE_MEM_RANGELENGTH
)
*
flags
|=
IORESOURCE_RANGELENGTH
;
if
(
mem
->
flags
&
IORESOURCE_MEM_SHADOWABLE
)
*
flags
|=
IORESOURCE_SHADOWABLE
;
if
(
!
pnp_check_mem
(
dev
,
idx
))
return
1
;
}
/* 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
(
rule
->
flags
&
IORESOURCE_MEM_CACHEABLE
)
*
flags
|=
IORESOURCE_CACHEABLE
;
if
(
rule
->
flags
&
IORESOURCE_MEM_RANGELENGTH
)
*
flags
|=
IORESOURCE_RANGELENGTH
;
if
(
rule
->
flags
&
IORESOURCE_MEM_SHADOWABLE
)
*
flags
|=
IORESOURCE_SHADOWABLE
;
/* 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
;
}
if
(
!
dev
||
!
rule
)
return
-
EINVAL
;
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
;
}
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
;
}
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
)
return
-
EINVAL
;
dma
=
dev
->
rule
->
dma
[
idx
];
if
(
!
dma
)
/* check if this resource has been manually set, if so skip */
if
(
!
(
dev
->
res
.
irq_resource
[
idx
].
flags
&
IORESOURCE_AUTO
))
return
1
;
start
=
&
dev
->
res
.
dma
_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
dma
_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
dma
_resource
[
idx
].
flags
;
start
=
&
dev
->
res
.
irq
_resource
[
idx
].
start
;
end
=
&
dev
->
res
.
irq
_resource
[
idx
].
end
;
flags
=
&
dev
->
res
.
irq
_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
))
return
1
;
}
/* set the initial values */
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_IRQ
;
mask
=
dma
->
map
;
for
(
i
=
*
start
+
1
;
i
<
8
;
i
++
)
{
if
(
mask
>>
i
&
0x01
)
{
*
start
=
*
end
=
i
;
if
(
!
pnp_check_dma
(
dev
,
idx
))
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
;
}
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
;
}
}
if
(
depnum
>
0
)
{
struct
pnp_resources
*
res
=
pnp_find_resources
(
dev
,
depnum
);
priority
=
res
->
priority
;
}
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
;
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
;
}
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
;
/* DMA priority: this table is good for i386 */
static
unsigned
short
xtab
[
8
]
=
{
1
,
3
,
5
,
6
,
7
,
0
,
2
,
4
};
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
);
return
1
;
}
}
/* 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
;
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
);
}
return
1
;
}
/* set the initial values */
*
flags
=
*
flags
|
rule
->
flags
|
IORESOURCE_DMA
;
/* 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
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
rule
->
map
&
(
1
<<
xtab
[
i
]))
{
*
start
=
*
end
=
xtab
[
i
];
if
(
pnp_check_dma
(
dev
,
idx
))
return
1
;
}
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
;
pnp_err
(
"
Failed to activate device %s."
,
dev
->
dev
.
bus_id
);
return
-
EIO
;
}
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
;
}
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 @
a7035a19
...
...
@@ -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 @
a7035a19
...
...
@@ -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 @
a7035a19
...
...
@@ -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
;
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
;
struct
pnp_
option
*
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
;
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
;
/* 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
;
}
}
}
/* 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 @
a7035a19
/*
* 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 @
a7035a19
...
...
@@ -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
)))
return
0
;
}
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 @
a7035a19
...
...
@@ -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 */
...
...
@@ -201,11 +190,13 @@ struct pnp_dev {
struct
pnp_driver
*
driver
;
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 */
struct
pnp_id
*
id
;
/* supported EISA IDs*/
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