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
975f957d
Commit
975f957d
authored
Aug 29, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge HEAD from master.kernel.org:/home/rmk/linux-2.6-serial.git
parents
2321fbd2
661299d9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
380 additions
and
512 deletions
+380
-512
drivers/parport/parport_serial.c
drivers/parport/parport_serial.c
+166
-173
drivers/serial/8250_pci.c
drivers/serial/8250_pci.c
+177
-297
include/linux/8250_pci.h
include/linux/8250_pci.h
+37
-2
include/linux/serialP.h
include/linux/serialP.h
+0
-40
No files found.
drivers/parport/parport_serial.c
View file @
975f957d
...
@@ -23,13 +23,8 @@
...
@@ -23,13 +23,8 @@
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/parport.h>
#include <linux/parport.h>
#include <linux/parport_pc.h>
#include <linux/parport_pc.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/list.h>
#include <linux/8250_pci.h>
#include <linux/8250_pci.h>
#include <asm/serial.h>
enum
parport_pc_pci_cards
{
enum
parport_pc_pci_cards
{
titan_110l
=
0
,
titan_110l
=
0
,
titan_210l
,
titan_210l
,
...
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
...
@@ -168,182 +163,147 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
};
};
MODULE_DEVICE_TABLE
(
pci
,
parport_serial_pci_tbl
);
MODULE_DEVICE_TABLE
(
pci
,
parport_serial_pci_tbl
);
struct
pci_board_no_ids
{
/*
int
flags
;
* This table describes the serial "geometry" of these boards. Any
int
num_ports
;
* quirks for these can be found in drivers/serial/8250_pci.c
int
base_baud
;
*
int
uart_offset
;
* Cards not tested are marked n/t
int
reg_shift
;
* If you have one of these cards and it works for you, please tell me..
int
(
*
init_fn
)(
struct
pci_dev
*
dev
,
struct
pci_board_no_ids
*
board
,
*/
int
enable
);
static
struct
pciserial_board
pci_parport_serial_boards
[]
__devinitdata
=
{
int
first_uart_offset
;
[
titan_110l
]
=
{
};
.
flags
=
FL_BASE1
|
FL_BASE_BARS
,
.
num_ports
=
1
,
static
int
__devinit
siig10x_init_fn
(
struct
pci_dev
*
dev
,
struct
pci_board_no_ids
*
board
,
int
enable
)
.
base_baud
=
921600
,
{
.
uart_offset
=
8
,
return
pci_siig10x_fn
(
dev
,
enable
);
},
}
[
titan_210l
]
=
{
.
flags
=
FL_BASE1
|
FL_BASE_BARS
,
static
int
__devinit
siig20x_init_fn
(
struct
pci_dev
*
dev
,
struct
pci_board_no_ids
*
board
,
int
enable
)
.
num_ports
=
2
,
{
.
base_baud
=
921600
,
return
pci_siig20x_fn
(
dev
,
enable
);
.
uart_offset
=
8
,
}
},
[
netmos_9xx5_combo
]
=
{
static
int
__devinit
netmos_serial_init
(
struct
pci_dev
*
dev
,
struct
pci_board_no_ids
*
board
,
int
enable
)
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
{
.
num_ports
=
1
,
board
->
num_ports
=
dev
->
subsystem_device
&
0xf
;
.
base_baud
=
115200
,
return
0
;
.
uart_offset
=
8
,
}
},
[
netmos_9855
]
=
{
static
struct
pci_board_no_ids
pci_boards
[]
__devinitdata
=
{
.
flags
=
FL_BASE2
|
FL_BASE_BARS
,
/*
.
num_ports
=
1
,
* PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
.
base_baud
=
115200
,
* Offset to get to next UART's registers,
.
uart_offset
=
8
,
* Register shift to use for memory-mapped I/O,
},
* Initialization function, first UART offset
[
avlab_1s1p
]
=
{
/* n/t */
*/
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
1
,
// Cards not tested are marked n/t
.
base_baud
=
115200
,
// If you have one of these cards and it works for you, please tell me..
.
uart_offset
=
8
,
},
/* titan_110l */
{
SPCI_FL_BASE1
|
SPCI_FL_BASE_TABLE
,
1
,
921600
},
[
avlab_1s1p_650
]
=
{
/* nt */
/* titan_210l */
{
SPCI_FL_BASE1
|
SPCI_FL_BASE_TABLE
,
2
,
921600
},
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
/* netmos_9xx5_combo */
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
,
0
,
0
,
netmos_serial_init
},
.
num_ports
=
1
,
/* netmos_9855 */
{
SPCI_FL_BASE2
|
SPCI_FL_BASE_TABLE
,
1
,
115200
,
0
,
0
,
netmos_serial_init
},
.
base_baud
=
115200
,
/* avlab_1s1p (n/t) */
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
.
uart_offset
=
8
,
/* avlab_1s1p_650 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
},
/* avlab_1s1p_850 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
[
avlab_1s1p_850
]
=
{
/* nt */
/* avlab_1s2p (n/t) */
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
/* avlab_1s2p_650 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
.
num_ports
=
1
,
/* avlab_1s2p_850 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
1
,
115200
},
.
base_baud
=
115200
,
/* avlab_2s1p (n/t) */
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
2
,
115200
},
.
uart_offset
=
8
,
/* avlab_2s1p_650 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
2
,
115200
},
},
/* avlab_2s1p_850 (nt)*/
{
SPCI_FL_BASE0
|
SPCI_FL_BASE_TABLE
,
2
,
115200
},
[
avlab_1s2p
]
=
{
/* n/t */
/* siig_1s1p_10x */
{
SPCI_FL_BASE2
,
1
,
460800
,
0
,
0
,
siig10x_init_fn
},
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
/* siig_2s1p_10x */
{
SPCI_FL_BASE2
,
1
,
921600
,
0
,
0
,
siig10x_init_fn
},
.
num_ports
=
1
,
/* siig_2p1s_20x */
{
SPCI_FL_BASE0
,
1
,
921600
,
0
,
0
,
siig20x_init_fn
},
.
base_baud
=
115200
,
/* siig_1s1p_20x */
{
SPCI_FL_BASE0
,
1
,
921600
,
0
,
0
,
siig20x_init_fn
},
.
uart_offset
=
8
,
/* siig_2s1p_20x */
{
SPCI_FL_BASE0
,
1
,
921600
,
0
,
0
,
siig20x_init_fn
},
},
[
avlab_1s2p_650
]
=
{
/* nt */
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
1
,
.
base_baud
=
115200
,
.
uart_offset
=
8
,
},
[
avlab_1s2p_850
]
=
{
/* nt */
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
1
,
.
base_baud
=
115200
,
.
uart_offset
=
8
,
},
[
avlab_2s1p
]
=
{
/* n/t */
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
2
,
.
base_baud
=
115200
,
.
uart_offset
=
8
,
},
[
avlab_2s1p_650
]
=
{
/* nt */
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
2
,
.
base_baud
=
115200
,
.
uart_offset
=
8
,
},
[
avlab_2s1p_850
]
=
{
/* nt */
.
flags
=
FL_BASE0
|
FL_BASE_BARS
,
.
num_ports
=
2
,
.
base_baud
=
115200
,
.
uart_offset
=
8
,
},
[
siig_1s1p_10x
]
=
{
.
flags
=
FL_BASE2
,
.
num_ports
=
1
,
.
base_baud
=
460800
,
.
uart_offset
=
8
,
},
[
siig_2s1p_10x
]
=
{
.
flags
=
FL_BASE2
,
.
num_ports
=
1
,
.
base_baud
=
921600
,
.
uart_offset
=
8
,
},
[
siig_2p1s_20x
]
=
{
.
flags
=
FL_BASE0
,
.
num_ports
=
1
,
.
base_baud
=
921600
,
.
uart_offset
=
8
,
},
[
siig_1s1p_20x
]
=
{
.
flags
=
FL_BASE0
,
.
num_ports
=
1
,
.
base_baud
=
921600
,
.
uart_offset
=
8
,
},
[
siig_2s1p_20x
]
=
{
.
flags
=
FL_BASE0
,
.
num_ports
=
1
,
.
base_baud
=
921600
,
.
uart_offset
=
8
,
},
};
};
struct
parport_serial_private
{
struct
parport_serial_private
{
int
num_ser
;
struct
serial_private
*
serial
;
int
line
[
20
];
struct
pci_board_no_ids
ser
;
int
num_par
;
int
num_par
;
struct
parport
*
port
[
PARPORT_MAX
];
struct
parport
*
port
[
PARPORT_MAX
];
struct
parport_pc_pci
par
;
struct
parport_pc_pci
par
;
};
};
static
int
__devinit
get_pci_port
(
struct
pci_dev
*
dev
,
struct
pci_board_no_ids
*
board
,
struct
serial_struct
*
req
,
int
idx
)
{
unsigned
long
port
;
int
base_idx
;
int
max_port
;
int
offset
;
base_idx
=
SPCI_FL_GET_BASE
(
board
->
flags
);
if
(
board
->
flags
&
SPCI_FL_BASE_TABLE
)
base_idx
+=
idx
;
if
(
board
->
flags
&
SPCI_FL_REGION_SZ_CAP
)
{
max_port
=
pci_resource_len
(
dev
,
base_idx
)
/
8
;
if
(
idx
>=
max_port
)
return
1
;
}
offset
=
board
->
first_uart_offset
;
/* Timedia/SUNIX uses a mixture of BARs and offsets */
/* Ugh, this is ugly as all hell --- TYT */
if
(
dev
->
vendor
==
PCI_VENDOR_ID_TIMEDIA
)
/* 0x1409 */
switch
(
idx
)
{
case
0
:
base_idx
=
0
;
break
;
case
1
:
base_idx
=
0
;
offset
=
8
;
break
;
case
2
:
base_idx
=
1
;
break
;
case
3
:
base_idx
=
1
;
offset
=
8
;
break
;
case
4
:
/* BAR 2*/
case
5
:
/* BAR 3 */
case
6
:
/* BAR 4*/
case
7
:
base_idx
=
idx
-
2
;
/* BAR 5*/
}
port
=
pci_resource_start
(
dev
,
base_idx
)
+
offset
;
if
((
board
->
flags
&
SPCI_FL_BASE_TABLE
)
==
0
)
port
+=
idx
*
(
board
->
uart_offset
?
board
->
uart_offset
:
8
);
if
(
pci_resource_flags
(
dev
,
base_idx
)
&
IORESOURCE_IO
)
{
int
high_bits_offset
=
((
sizeof
(
long
)
-
sizeof
(
int
))
*
8
);
req
->
port
=
port
;
if
(
high_bits_offset
)
req
->
port_high
=
port
>>
high_bits_offset
;
else
req
->
port_high
=
0
;
return
0
;
}
req
->
io_type
=
SERIAL_IO_MEM
;
req
->
iomem_base
=
ioremap
(
port
,
board
->
uart_offset
);
req
->
iomem_reg_shift
=
board
->
reg_shift
;
req
->
port
=
0
;
return
req
->
iomem_base
?
0
:
1
;
}
/* Register the serial port(s) of a PCI card. */
/* Register the serial port(s) of a PCI card. */
static
int
__devinit
serial_register
(
struct
pci_dev
*
dev
,
static
int
__devinit
serial_register
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
const
struct
pci_device_id
*
id
)
{
{
struct
pci_board_no_ids
*
board
;
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
struct
serial_struct
serial_req
;
struct
pciserial_board
*
board
;
int
base_baud
;
struct
serial_private
*
serial
;
int
k
;
int
success
=
0
;
priv
->
ser
=
pci_boards
[
id
->
driver_data
];
board
=
&
priv
->
ser
;
if
(
board
->
init_fn
&&
((
board
->
init_fn
)
(
dev
,
board
,
1
)
!=
0
))
return
1
;
base_baud
=
board
->
base_baud
;
if
(
!
base_baud
)
base_baud
=
BASE_BAUD
;
memset
(
&
serial_req
,
0
,
sizeof
(
serial_req
));
for
(
k
=
0
;
k
<
board
->
num_ports
;
k
++
)
{
int
line
;
if
(
priv
->
num_ser
==
ARRAY_SIZE
(
priv
->
line
))
{
board
=
&
pci_parport_serial_boards
[
id
->
driver_data
];
printk
(
KERN_WARNING
serial
=
pciserial_init_ports
(
dev
,
board
);
"parport_serial: %s: only %u serial lines "
"supported (%d reported)
\n
"
,
pci_name
(
dev
),
ARRAY_SIZE
(
priv
->
line
),
board
->
num_ports
);
break
;
}
serial_req
.
irq
=
dev
->
irq
;
if
(
IS_ERR
(
serial
))
if
(
get_pci_port
(
dev
,
board
,
&
serial_req
,
k
))
return
PTR_ERR
(
serial
);
break
;
serial_req
.
flags
=
ASYNC_SKIP_TEST
|
ASYNC_AUTOPROBE
;
serial_req
.
baud_base
=
base_baud
;
line
=
register_serial
(
&
serial_req
);
if
(
line
<
0
)
{
printk
(
KERN_DEBUG
"parport_serial: register_serial failed
\n
"
);
continue
;
}
priv
->
line
[
priv
->
num_ser
++
]
=
line
;
success
=
1
;
}
return
success
?
0
:
1
;
priv
->
serial
=
serial
;
return
0
;
}
}
/* Register the parallel port(s) of a PCI card. */
/* Register the parallel port(s) of a PCI card. */
...
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
...
@@ -411,7 +371,7 @@ static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
priv
=
kmalloc
(
sizeof
*
priv
,
GFP_KERNEL
);
priv
=
kmalloc
(
sizeof
*
priv
,
GFP_KERNEL
);
if
(
!
priv
)
if
(
!
priv
)
return
-
ENOMEM
;
return
-
ENOMEM
;
priv
->
num_ser
=
priv
->
num_par
=
0
;
memset
(
priv
,
0
,
sizeof
(
struct
parport_serial_private
))
;
pci_set_drvdata
(
dev
,
priv
);
pci_set_drvdata
(
dev
,
priv
);
err
=
pci_enable_device
(
dev
);
err
=
pci_enable_device
(
dev
);
...
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
...
@@ -444,15 +404,12 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
int
i
;
int
i
;
pci_set_drvdata
(
dev
,
NULL
);
// Serial ports
// Serial ports
for
(
i
=
0
;
i
<
priv
->
num_ser
;
i
++
)
{
if
(
priv
->
serial
)
unregister_serial
(
priv
->
line
[
i
]
);
pciserial_remove_ports
(
priv
->
serial
);
if
(
priv
->
ser
.
init_fn
)
(
priv
->
ser
.
init_fn
)
(
dev
,
&
priv
->
ser
,
0
);
}
pci_set_drvdata
(
dev
,
NULL
);
// Parallel ports
// Parallel ports
for
(
i
=
0
;
i
<
priv
->
num_par
;
i
++
)
for
(
i
=
0
;
i
<
priv
->
num_par
;
i
++
)
parport_pc_unregister_port
(
priv
->
port
[
i
]);
parport_pc_unregister_port
(
priv
->
port
[
i
]);
...
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
...
@@ -461,11 +418,47 @@ static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
return
;
return
;
}
}
static
int
parport_serial_pci_suspend
(
struct
pci_dev
*
dev
,
pm_message_t
state
)
{
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
if
(
priv
->
serial
)
pciserial_suspend_ports
(
priv
->
serial
);
/* FIXME: What about parport? */
pci_save_state
(
dev
);
pci_set_power_state
(
dev
,
pci_choose_state
(
dev
,
state
));
return
0
;
}
static
int
parport_serial_pci_resume
(
struct
pci_dev
*
dev
)
{
struct
parport_serial_private
*
priv
=
pci_get_drvdata
(
dev
);
pci_set_power_state
(
dev
,
PCI_D0
);
pci_restore_state
(
dev
);
/*
* The device may have been disabled. Re-enable it.
*/
pci_enable_device
(
dev
);
if
(
priv
->
serial
)
pciserial_resume_ports
(
priv
->
serial
);
/* FIXME: What about parport? */
return
0
;
}
static
struct
pci_driver
parport_serial_pci_driver
=
{
static
struct
pci_driver
parport_serial_pci_driver
=
{
.
name
=
"parport_serial"
,
.
name
=
"parport_serial"
,
.
id_table
=
parport_serial_pci_tbl
,
.
id_table
=
parport_serial_pci_tbl
,
.
probe
=
parport_serial_pci_probe
,
.
probe
=
parport_serial_pci_probe
,
.
remove
=
__devexit_p
(
parport_serial_pci_remove
),
.
remove
=
__devexit_p
(
parport_serial_pci_remove
),
.
suspend
=
parport_serial_pci_suspend
,
.
resume
=
parport_serial_pci_resume
,
};
};
...
...
drivers/serial/8250_pci.c
View file @
975f957d
...
@@ -33,36 +33,6 @@
...
@@ -33,36 +33,6 @@
#undef SERIAL_DEBUG_PCI
#undef SERIAL_DEBUG_PCI
/*
* Definitions for PCI support.
*/
#define FL_BASE_MASK 0x0007
#define FL_BASE0 0x0000
#define FL_BASE1 0x0001
#define FL_BASE2 0x0002
#define FL_BASE3 0x0003
#define FL_BASE4 0x0004
#define FL_GET_BASE(x) (x & FL_BASE_MASK)
/* Use successive BARs (PCI base address registers),
else use offset into some specified BAR */
#define FL_BASE_BARS 0x0008
/* do not assign an irq */
#define FL_NOIRQ 0x0080
/* Use the Base address register size to cap number of ports */
#define FL_REGION_SZ_CAP 0x0100
struct
pci_board
{
unsigned
int
flags
;
unsigned
int
num_ports
;
unsigned
int
base_baud
;
unsigned
int
uart_offset
;
unsigned
int
reg_shift
;
unsigned
int
first_offset
;
};
/*
/*
* init function returns:
* init function returns:
* > 0 - number of ports
* > 0 - number of ports
...
@@ -75,14 +45,15 @@ struct pci_serial_quirk {
...
@@ -75,14 +45,15 @@ struct pci_serial_quirk {
u32
subvendor
;
u32
subvendor
;
u32
subdevice
;
u32
subdevice
;
int
(
*
init
)(
struct
pci_dev
*
dev
);
int
(
*
init
)(
struct
pci_dev
*
dev
);
int
(
*
setup
)(
struct
pci_dev
*
dev
,
struct
pci_board
*
board
,
int
(
*
setup
)(
struct
serial_private
*
,
struct
pciserial_board
*
,
struct
uart_port
*
port
,
int
idx
);
struct
uart_port
*
,
int
);
void
(
*
exit
)(
struct
pci_dev
*
dev
);
void
(
*
exit
)(
struct
pci_dev
*
dev
);
};
};
#define PCI_NUM_BAR_RESOURCES 6
#define PCI_NUM_BAR_RESOURCES 6
struct
serial_private
{
struct
serial_private
{
struct
pci_dev
*
dev
;
unsigned
int
nr
;
unsigned
int
nr
;
void
__iomem
*
remapped_bar
[
PCI_NUM_BAR_RESOURCES
];
void
__iomem
*
remapped_bar
[
PCI_NUM_BAR_RESOURCES
];
struct
pci_serial_quirk
*
quirk
;
struct
pci_serial_quirk
*
quirk
;
...
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev)
...
@@ -101,17 +72,18 @@ static void moan_device(const char *str, struct pci_dev *dev)
}
}
static
int
static
int
setup_port
(
struct
pci_dev
*
de
v
,
struct
uart_port
*
port
,
setup_port
(
struct
serial_private
*
pri
v
,
struct
uart_port
*
port
,
int
bar
,
int
offset
,
int
regshift
)
int
bar
,
int
offset
,
int
regshift
)
{
{
struct
serial_private
*
priv
=
pci_get_drvdata
(
dev
)
;
struct
pci_dev
*
dev
=
priv
->
dev
;
unsigned
long
base
,
len
;
unsigned
long
base
,
len
;
if
(
bar
>=
PCI_NUM_BAR_RESOURCES
)
if
(
bar
>=
PCI_NUM_BAR_RESOURCES
)
return
-
EINVAL
;
return
-
EINVAL
;
base
=
pci_resource_start
(
dev
,
bar
);
if
(
pci_resource_flags
(
dev
,
bar
)
&
IORESOURCE_MEM
)
{
if
(
pci_resource_flags
(
dev
,
bar
)
&
IORESOURCE_MEM
)
{
base
=
pci_resource_start
(
dev
,
bar
);
len
=
pci_resource_len
(
dev
,
bar
);
len
=
pci_resource_len
(
dev
,
bar
);
if
(
!
priv
->
remapped_bar
[
bar
])
if
(
!
priv
->
remapped_bar
[
bar
])
...
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
...
@@ -120,13 +92,16 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
return
-
ENOMEM
;
return
-
ENOMEM
;
port
->
iotype
=
UPIO_MEM
;
port
->
iotype
=
UPIO_MEM
;
port
->
iobase
=
0
;
port
->
mapbase
=
base
+
offset
;
port
->
mapbase
=
base
+
offset
;
port
->
membase
=
priv
->
remapped_bar
[
bar
]
+
offset
;
port
->
membase
=
priv
->
remapped_bar
[
bar
]
+
offset
;
port
->
regshift
=
regshift
;
port
->
regshift
=
regshift
;
}
else
{
}
else
{
base
=
pci_resource_start
(
dev
,
bar
)
+
offset
;
port
->
iotype
=
UPIO_PORT
;
port
->
iotype
=
UPIO_PORT
;
port
->
iobase
=
base
;
port
->
iobase
=
base
+
offset
;
port
->
mapbase
=
0
;
port
->
membase
=
NULL
;
port
->
regshift
=
0
;
}
}
return
0
;
return
0
;
}
}
...
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
...
@@ -136,7 +111,7 @@ setup_port(struct pci_dev *dev, struct uart_port *port,
* Not that ugly ;) -- HW
* Not that ugly ;) -- HW
*/
*/
static
int
static
int
afavlab_setup
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
afavlab_setup
(
struct
serial_private
*
priv
,
struct
pciserial
_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
bar
,
offset
=
board
->
first_offset
;
unsigned
int
bar
,
offset
=
board
->
first_offset
;
...
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -149,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board,
offset
+=
(
idx
-
4
)
*
board
->
uart_offset
;
offset
+=
(
idx
-
4
)
*
board
->
uart_offset
;
}
}
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
/*
/*
...
@@ -189,13 +164,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
...
@@ -189,13 +164,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev)
* some serial ports are supposed to be hidden on certain models.
* some serial ports are supposed to be hidden on certain models.
*/
*/
static
int
static
int
pci_hp_diva_setup
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
pci_hp_diva_setup
(
struct
serial_private
*
priv
,
struct
pciserial
_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
offset
=
board
->
first_offset
;
unsigned
int
offset
=
board
->
first_offset
;
unsigned
int
bar
=
FL_GET_BASE
(
board
->
flags
);
unsigned
int
bar
=
FL_GET_BASE
(
board
->
flags
);
switch
(
dev
->
subsystem_device
)
{
switch
(
priv
->
dev
->
subsystem_device
)
{
case
PCI_DEVICE_ID_HP_DIVA_MAESTRO
:
case
PCI_DEVICE_ID_HP_DIVA_MAESTRO
:
if
(
idx
==
3
)
if
(
idx
==
3
)
idx
++
;
idx
++
;
...
@@ -212,7 +187,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -212,7 +187,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,
offset
+=
idx
*
board
->
uart_offset
;
offset
+=
idx
*
board
->
uart_offset
;
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
/*
/*
...
@@ -307,7 +282,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
...
@@ -307,7 +282,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static
int
static
int
sbs_setup
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
sbs_setup
(
struct
serial_private
*
priv
,
struct
pciserial
_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
bar
,
offset
=
board
->
first_offset
;
unsigned
int
bar
,
offset
=
board
->
first_offset
;
...
@@ -323,7 +298,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -323,7 +298,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board,
}
else
/* we have only 8 ports on PMC-OCTALPRO */
}
else
/* we have only 8 ports on PMC-OCTALPRO */
return
1
;
return
1
;
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
/*
/*
...
@@ -389,6 +364,9 @@ static void __devexit sbs_exit(struct pci_dev *dev)
...
@@ -389,6 +364,9 @@ static void __devexit sbs_exit(struct pci_dev *dev)
* - 10x cards have control registers in IO and/or memory space;
* - 10x cards have control registers in IO and/or memory space;
* - 20x cards have control registers in standard PCI configuration space.
* - 20x cards have control registers in standard PCI configuration space.
*
*
* Note: all 10x cards have PCI device ids 0x10..
* all 20x cards have PCI device ids 0x20..
*
* There are also Quartet Serial cards which use Oxford Semiconductor
* There are also Quartet Serial cards which use Oxford Semiconductor
* 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
* 16954 quad UART PCI chip clocked by 18.432 MHz quartz.
*
*
...
@@ -445,24 +423,18 @@ static int pci_siig20x_init(struct pci_dev *dev)
...
@@ -445,24 +423,18 @@ static int pci_siig20x_init(struct pci_dev *dev)
return
0
;
return
0
;
}
}
int
pci_siig10x_fn
(
struct
pci_dev
*
dev
,
int
enable
)
static
int
pci_siig_init
(
struct
pci_dev
*
dev
)
{
{
int
ret
=
0
;
unsigned
int
type
=
dev
->
device
&
0xff00
;
if
(
enable
)
ret
=
pci_siig10x_init
(
dev
);
return
ret
;
}
int
pci_siig20x_fn
(
struct
pci_dev
*
dev
,
int
enable
)
if
(
type
==
0x1000
)
{
return
pci_siig10x_init
(
dev
);
int
ret
=
0
;
else
if
(
type
==
0x2000
)
if
(
enable
)
return
pci_siig20x_init
(
dev
);
ret
=
pci_siig20x_init
(
dev
);
return
ret
;
}
EXPORT_SYMBOL
(
pci_siig10x_fn
);
moan_device
(
"Unknown SIIG card"
,
dev
);
EXPORT_SYMBOL
(
pci_siig20x_fn
);
return
-
ENODEV
;
}
/*
/*
* Timedia has an explosion of boards, and to avoid the PCI table from
* Timedia has an explosion of boards, and to avoid the PCI table from
...
@@ -523,7 +495,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
...
@@ -523,7 +495,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev)
* Ugh, this is ugly as all hell --- TYT
* Ugh, this is ugly as all hell --- TYT
*/
*/
static
int
static
int
pci_timedia_setup
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
pci_timedia_setup
(
struct
serial_private
*
priv
,
struct
pciserial
_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
bar
=
0
,
offset
=
board
->
first_offset
;
unsigned
int
bar
=
0
,
offset
=
board
->
first_offset
;
...
@@ -549,14 +521,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -549,14 +521,15 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
bar
=
idx
-
2
;
bar
=
idx
-
2
;
}
}
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
/*
/*
* Some Titan cards are also a little weird
* Some Titan cards are also a little weird
*/
*/
static
int
static
int
titan_400l_800l_setup
(
struct
pci_dev
*
dev
,
struct
pci_board
*
board
,
titan_400l_800l_setup
(
struct
serial_private
*
priv
,
struct
pciserial_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
bar
,
offset
=
board
->
first_offset
;
unsigned
int
bar
,
offset
=
board
->
first_offset
;
...
@@ -573,7 +546,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -573,7 +546,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,
offset
=
(
idx
-
2
)
*
board
->
uart_offset
;
offset
=
(
idx
-
2
)
*
board
->
uart_offset
;
}
}
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
static
int
__devinit
pci_xircom_init
(
struct
pci_dev
*
dev
)
static
int
__devinit
pci_xircom_init
(
struct
pci_dev
*
dev
)
...
@@ -593,7 +566,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev)
...
@@ -593,7 +566,7 @@ static int __devinit pci_netmos_init(struct pci_dev *dev)
}
}
static
int
static
int
pci_default_setup
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
pci_default_setup
(
struct
serial_private
*
priv
,
struct
pciserial
_board
*
board
,
struct
uart_port
*
port
,
int
idx
)
struct
uart_port
*
port
,
int
idx
)
{
{
unsigned
int
bar
,
offset
=
board
->
first_offset
,
maxnr
;
unsigned
int
bar
,
offset
=
board
->
first_offset
,
maxnr
;
...
@@ -604,13 +577,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
...
@@ -604,13 +577,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board,
else
else
offset
+=
idx
*
board
->
uart_offset
;
offset
+=
idx
*
board
->
uart_offset
;
maxnr
=
(
pci_resource_len
(
dev
,
bar
)
-
board
->
first_offset
)
/
maxnr
=
(
pci_resource_len
(
priv
->
dev
,
bar
)
-
board
->
first_offset
)
/
(
8
<<
board
->
reg_shift
);
(
8
<<
board
->
reg_shift
);
if
(
board
->
flags
&
FL_REGION_SZ_CAP
&&
idx
>=
maxnr
)
if
(
board
->
flags
&
FL_REGION_SZ_CAP
&&
idx
>=
maxnr
)
return
1
;
return
1
;
return
setup_port
(
de
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
return
setup_port
(
pri
v
,
port
,
bar
,
offset
,
board
->
reg_shift
);
}
}
/* This should be in linux/pci_ids.h */
/* This should be in linux/pci_ids.h */
...
@@ -754,152 +727,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
...
@@ -754,152 +727,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.
setup
=
sbs_setup
,
.
setup
=
sbs_setup
,
.
exit
=
__devexit_p
(
sbs_exit
),
.
exit
=
__devexit_p
(
sbs_exit
),
},
},
/*
/*
* SIIG cards.
* SIIG cards.
* It is not clear whether these could be collapsed.
*/
*/
{
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_10x_550
,
.
device
=
PCI_ANY_ID
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_10x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_10x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_10x_550
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_10x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_10x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_10x_550
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_10x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_10x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig10x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_20x_550
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_20x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_1S_20x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_20x_550
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_20x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_2S_20x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_20x_550
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_20x_650
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig20x_init
,
.
setup
=
pci_default_setup
,
},
{
.
vendor
=
PCI_VENDOR_ID_SIIG
,
.
device
=
PCI_DEVICE_ID_SIIG_4S_20x_850
,
.
subvendor
=
PCI_ANY_ID
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
init
=
pci_siig
20x
_init
,
.
init
=
pci_siig_init
,
.
setup
=
pci_default_setup
,
.
setup
=
pci_default_setup
,
},
},
/*
/*
...
@@ -990,7 +826,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
...
@@ -990,7 +826,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
}
}
static
_INLINE_
int
static
_INLINE_
int
get_pci_irq
(
struct
pci_dev
*
dev
,
struct
pci
_board
*
board
,
int
idx
)
get_pci_irq
(
struct
pci_dev
*
dev
,
struct
pci
serial_board
*
board
)
{
{
if
(
board
->
flags
&
FL_NOIRQ
)
if
(
board
->
flags
&
FL_NOIRQ
)
return
0
;
return
0
;
...
@@ -1115,7 +951,7 @@ enum pci_board_num_t {
...
@@ -1115,7 +951,7 @@ enum pci_board_num_t {
* see first lines of serial_in() and serial_out() in 8250.c
* see first lines of serial_in() and serial_out() in 8250.c
*/
*/
static
struct
pci_board
pci_boards
[]
__devinitdata
=
{
static
struct
pci
serial
_board
pci_boards
[]
__devinitdata
=
{
[
pbn_default
]
=
{
[
pbn_default
]
=
{
.
flags
=
FL_BASE0
,
.
flags
=
FL_BASE0
,
.
num_ports
=
1
,
.
num_ports
=
1
,
...
@@ -1575,7 +1411,7 @@ static struct pci_board pci_boards[] __devinitdata = {
...
@@ -1575,7 +1411,7 @@ static struct pci_board pci_boards[] __devinitdata = {
* serial specs. Returns 0 on success, 1 on failure.
* serial specs. Returns 0 on success, 1 on failure.
*/
*/
static
int
__devinit
static
int
__devinit
serial_pci_guess_board
(
struct
pci_dev
*
dev
,
struct
pci_board
*
board
)
serial_pci_guess_board
(
struct
pci_dev
*
dev
,
struct
pci
serial
_board
*
board
)
{
{
int
num_iomem
,
num_port
,
first_port
=
-
1
,
i
;
int
num_iomem
,
num_port
,
first_port
=
-
1
,
i
;
...
@@ -1640,7 +1476,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
...
@@ -1640,7 +1476,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
}
}
static
inline
int
static
inline
int
serial_pci_matches
(
struct
pci_board
*
board
,
struct
pci_board
*
guessed
)
serial_pci_matches
(
struct
pciserial_board
*
board
,
struct
pciserial_board
*
guessed
)
{
{
return
return
board
->
num_ports
==
guessed
->
num_ports
&&
board
->
num_ports
==
guessed
->
num_ports
&&
...
@@ -1650,58 +1487,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
...
@@ -1650,58 +1487,14 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
board
->
first_offset
==
guessed
->
first_offset
;
board
->
first_offset
==
guessed
->
first_offset
;
}
}
/*
struct
serial_private
*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
pciserial_init_ports
(
struct
pci_dev
*
dev
,
struct
pciserial_board
*
board
)
* to the arrangement of serial ports on a PCI card.
*/
static
int
__devinit
pciserial_init_one
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
{
struct
uart_port
serial_port
;
struct
serial_private
*
priv
;
struct
serial_private
*
priv
;
struct
pci_board
*
board
,
tmp
;
struct
pci_serial_quirk
*
quirk
;
struct
pci_serial_quirk
*
quirk
;
int
rc
,
nr_ports
,
i
;
int
rc
,
nr_ports
,
i
;
if
(
ent
->
driver_data
>=
ARRAY_SIZE
(
pci_boards
))
{
printk
(
KERN_ERR
"pci_init_one: invalid driver_data: %ld
\n
"
,
ent
->
driver_data
);
return
-
EINVAL
;
}
board
=
&
pci_boards
[
ent
->
driver_data
];
rc
=
pci_enable_device
(
dev
);
if
(
rc
)
return
rc
;
if
(
ent
->
driver_data
==
pbn_default
)
{
/*
* Use a copy of the pci_board entry for this;
* avoid changing entries in the table.
*/
memcpy
(
&
tmp
,
board
,
sizeof
(
struct
pci_board
));
board
=
&
tmp
;
/*
* We matched one of our class entries. Try to
* determine the parameters of this board.
*/
rc
=
serial_pci_guess_board
(
dev
,
board
);
if
(
rc
)
goto
disable
;
}
else
{
/*
* We matched an explicit entry. If we are able to
* detect this boards settings with our heuristic,
* then we no longer need this entry.
*/
memcpy
(
&
tmp
,
&
pci_boards
[
pbn_default
],
sizeof
(
struct
pci_board
));
rc
=
serial_pci_guess_board
(
dev
,
&
tmp
);
if
(
rc
==
0
&&
serial_pci_matches
(
board
,
&
tmp
))
moan_device
(
"Redundant entry in serial pci_table."
,
dev
);
}
nr_ports
=
board
->
num_ports
;
nr_ports
=
board
->
num_ports
;
/*
/*
...
@@ -1718,8 +1511,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
...
@@ -1718,8 +1511,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
*/
*/
if
(
quirk
->
init
)
{
if
(
quirk
->
init
)
{
rc
=
quirk
->
init
(
dev
);
rc
=
quirk
->
init
(
dev
);
if
(
rc
<
0
)
if
(
rc
<
0
)
{
goto
disable
;
priv
=
ERR_PTR
(
rc
);
goto
err_out
;
}
if
(
rc
)
if
(
rc
)
nr_ports
=
rc
;
nr_ports
=
rc
;
}
}
...
@@ -1728,27 +1523,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
...
@@ -1728,27 +1523,26 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
sizeof
(
unsigned
int
)
*
nr_ports
,
sizeof
(
unsigned
int
)
*
nr_ports
,
GFP_KERNEL
);
GFP_KERNEL
);
if
(
!
priv
)
{
if
(
!
priv
)
{
rc
=
-
ENOMEM
;
priv
=
ERR_PTR
(
-
ENOMEM
)
;
goto
deinit
;
goto
err_
deinit
;
}
}
memset
(
priv
,
0
,
sizeof
(
struct
serial_private
)
+
memset
(
priv
,
0
,
sizeof
(
struct
serial_private
)
+
sizeof
(
unsigned
int
)
*
nr_ports
);
sizeof
(
unsigned
int
)
*
nr_ports
);
priv
->
dev
=
dev
;
priv
->
quirk
=
quirk
;
priv
->
quirk
=
quirk
;
pci_set_drvdata
(
dev
,
priv
);
memset
(
&
serial_port
,
0
,
sizeof
(
struct
uart_port
));
serial_port
.
flags
=
UPF_SKIP_TEST
|
UPF_BOOT_AUTOCONF
|
UPF_SHARE_IRQ
;
serial_port
.
uartclk
=
board
->
base_baud
*
16
;
serial_port
.
irq
=
get_pci_irq
(
dev
,
board
);
serial_port
.
dev
=
&
dev
->
dev
;
for
(
i
=
0
;
i
<
nr_ports
;
i
++
)
{
for
(
i
=
0
;
i
<
nr_ports
;
i
++
)
{
struct
uart_port
serial_port
;
if
(
quirk
->
setup
(
priv
,
board
,
&
serial_port
,
i
))
memset
(
&
serial_port
,
0
,
sizeof
(
struct
uart_port
));
serial_port
.
flags
=
UPF_SKIP_TEST
|
UPF_BOOT_AUTOCONF
|
UPF_SHARE_IRQ
;
serial_port
.
uartclk
=
board
->
base_baud
*
16
;
serial_port
.
irq
=
get_pci_irq
(
dev
,
board
,
i
);
serial_port
.
dev
=
&
dev
->
dev
;
if
(
quirk
->
setup
(
dev
,
board
,
&
serial_port
,
i
))
break
;
break
;
#ifdef SERIAL_DEBUG_PCI
#ifdef SERIAL_DEBUG_PCI
printk
(
"Setup PCI port: port %x, irq %d, type %d
\n
"
,
printk
(
"Setup PCI port: port %x, irq %d, type %d
\n
"
,
serial_port
.
iobase
,
serial_port
.
irq
,
serial_port
.
iotype
);
serial_port
.
iobase
,
serial_port
.
irq
,
serial_port
.
iotype
);
...
@@ -1763,24 +1557,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
...
@@ -1763,24 +1557,21 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
priv
->
nr
=
i
;
priv
->
nr
=
i
;
return
0
;
return
priv
;
deinit:
err_
deinit:
if
(
quirk
->
exit
)
if
(
quirk
->
exit
)
quirk
->
exit
(
dev
);
quirk
->
exit
(
dev
);
disable:
err_out:
pci_disable_device
(
dev
);
return
priv
;
return
rc
;
}
}
EXPORT_SYMBOL_GPL
(
pciserial_init_ports
);
static
void
__devexit
pciserial_remove_one
(
struct
pci_dev
*
de
v
)
void
pciserial_remove_ports
(
struct
serial_private
*
pri
v
)
{
{
struct
serial_private
*
priv
=
pci_get_drvdata
(
dev
);
struct
pci_serial_quirk
*
quirk
;
struct
pci_serial_quirk
*
quirk
;
int
i
;
int
i
;
pci_set_drvdata
(
dev
,
NULL
);
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
serial8250_unregister_port
(
priv
->
line
[
i
]);
serial8250_unregister_port
(
priv
->
line
[
i
]);
...
@@ -1793,25 +1584,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
...
@@ -1793,25 +1584,123 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
/*
/*
* Find the exit quirks.
* Find the exit quirks.
*/
*/
quirk
=
find_quirk
(
dev
);
quirk
=
find_quirk
(
priv
->
dev
);
if
(
quirk
->
exit
)
if
(
quirk
->
exit
)
quirk
->
exit
(
dev
);
quirk
->
exit
(
priv
->
dev
);
kfree
(
priv
);
}
EXPORT_SYMBOL_GPL
(
pciserial_remove_ports
);
void
pciserial_suspend_ports
(
struct
serial_private
*
priv
)
{
int
i
;
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
if
(
priv
->
line
[
i
]
>=
0
)
serial8250_suspend_port
(
priv
->
line
[
i
]);
}
EXPORT_SYMBOL_GPL
(
pciserial_suspend_ports
);
void
pciserial_resume_ports
(
struct
serial_private
*
priv
)
{
int
i
;
/*
* Ensure that the board is correctly configured.
*/
if
(
priv
->
quirk
->
init
)
priv
->
quirk
->
init
(
priv
->
dev
);
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
if
(
priv
->
line
[
i
]
>=
0
)
serial8250_resume_port
(
priv
->
line
[
i
]);
}
EXPORT_SYMBOL_GPL
(
pciserial_resume_ports
);
/*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
*/
static
int
__devinit
pciserial_init_one
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
struct
serial_private
*
priv
;
struct
pciserial_board
*
board
,
tmp
;
int
rc
;
if
(
ent
->
driver_data
>=
ARRAY_SIZE
(
pci_boards
))
{
printk
(
KERN_ERR
"pci_init_one: invalid driver_data: %ld
\n
"
,
ent
->
driver_data
);
return
-
EINVAL
;
}
board
=
&
pci_boards
[
ent
->
driver_data
];
rc
=
pci_enable_device
(
dev
);
if
(
rc
)
return
rc
;
if
(
ent
->
driver_data
==
pbn_default
)
{
/*
* Use a copy of the pci_board entry for this;
* avoid changing entries in the table.
*/
memcpy
(
&
tmp
,
board
,
sizeof
(
struct
pciserial_board
));
board
=
&
tmp
;
/*
* We matched one of our class entries. Try to
* determine the parameters of this board.
*/
rc
=
serial_pci_guess_board
(
dev
,
board
);
if
(
rc
)
goto
disable
;
}
else
{
/*
* We matched an explicit entry. If we are able to
* detect this boards settings with our heuristic,
* then we no longer need this entry.
*/
memcpy
(
&
tmp
,
&
pci_boards
[
pbn_default
],
sizeof
(
struct
pciserial_board
));
rc
=
serial_pci_guess_board
(
dev
,
&
tmp
);
if
(
rc
==
0
&&
serial_pci_matches
(
board
,
&
tmp
))
moan_device
(
"Redundant entry in serial pci_table."
,
dev
);
}
priv
=
pciserial_init_ports
(
dev
,
board
);
if
(
!
IS_ERR
(
priv
))
{
pci_set_drvdata
(
dev
,
priv
);
return
0
;
}
rc
=
PTR_ERR
(
priv
);
disable:
pci_disable_device
(
dev
);
pci_disable_device
(
dev
);
return
rc
;
}
kfree
(
priv
);
static
void
__devexit
pciserial_remove_one
(
struct
pci_dev
*
dev
)
{
struct
serial_private
*
priv
=
pci_get_drvdata
(
dev
);
pci_set_drvdata
(
dev
,
NULL
);
pciserial_remove_ports
(
priv
);
pci_disable_device
(
dev
);
}
}
static
int
pciserial_suspend_one
(
struct
pci_dev
*
dev
,
pm_message_t
state
)
static
int
pciserial_suspend_one
(
struct
pci_dev
*
dev
,
pm_message_t
state
)
{
{
struct
serial_private
*
priv
=
pci_get_drvdata
(
dev
);
struct
serial_private
*
priv
=
pci_get_drvdata
(
dev
);
if
(
priv
)
{
if
(
priv
)
int
i
;
pciserial_suspend_ports
(
priv
)
;
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
serial8250_suspend_port
(
priv
->
line
[
i
]);
}
pci_save_state
(
dev
);
pci_save_state
(
dev
);
pci_set_power_state
(
dev
,
pci_choose_state
(
dev
,
state
));
pci_set_power_state
(
dev
,
pci_choose_state
(
dev
,
state
));
return
0
;
return
0
;
...
@@ -1825,21 +1714,12 @@ static int pciserial_resume_one(struct pci_dev *dev)
...
@@ -1825,21 +1714,12 @@ static int pciserial_resume_one(struct pci_dev *dev)
pci_restore_state
(
dev
);
pci_restore_state
(
dev
);
if
(
priv
)
{
if
(
priv
)
{
int
i
;
/*
/*
* The device may have been disabled. Re-enable it.
* The device may have been disabled. Re-enable it.
*/
*/
pci_enable_device
(
dev
);
pci_enable_device
(
dev
);
/*
pciserial_resume_ports
(
priv
);
* Ensure that the board is correctly configured.
*/
if
(
priv
->
quirk
->
init
)
priv
->
quirk
->
init
(
dev
);
for
(
i
=
0
;
i
<
priv
->
nr
;
i
++
)
serial8250_resume_port
(
priv
->
line
[
i
]);
}
}
return
0
;
return
0
;
}
}
...
...
include/linux/8250_pci.h
View file @
975f957d
int
pci_siig10x_fn
(
struct
pci_dev
*
dev
,
int
enable
);
/*
int
pci_siig20x_fn
(
struct
pci_dev
*
dev
,
int
enable
);
* Definitions for PCI support.
*/
#define FL_BASE_MASK 0x0007
#define FL_BASE0 0x0000
#define FL_BASE1 0x0001
#define FL_BASE2 0x0002
#define FL_BASE3 0x0003
#define FL_BASE4 0x0004
#define FL_GET_BASE(x) (x & FL_BASE_MASK)
/* Use successive BARs (PCI base address registers),
else use offset into some specified BAR */
#define FL_BASE_BARS 0x0008
/* do not assign an irq */
#define FL_NOIRQ 0x0080
/* Use the Base address register size to cap number of ports */
#define FL_REGION_SZ_CAP 0x0100
struct
pciserial_board
{
unsigned
int
flags
;
unsigned
int
num_ports
;
unsigned
int
base_baud
;
unsigned
int
uart_offset
;
unsigned
int
reg_shift
;
unsigned
int
first_offset
;
};
struct
serial_private
;
struct
serial_private
*
pciserial_init_ports
(
struct
pci_dev
*
dev
,
struct
pciserial_board
*
board
);
void
pciserial_remove_ports
(
struct
serial_private
*
priv
);
void
pciserial_suspend_ports
(
struct
serial_private
*
priv
);
void
pciserial_resume_ports
(
struct
serial_private
*
priv
);
include/linux/serialP.h
View file @
975f957d
...
@@ -140,44 +140,4 @@ struct rs_multiport_struct {
...
@@ -140,44 +140,4 @@ struct rs_multiport_struct {
#define ALPHA_KLUDGE_MCR 0
#define ALPHA_KLUDGE_MCR 0
#endif
#endif
/*
* Definitions for PCI support.
*/
#define SPCI_FL_BASE_MASK 0x0007
#define SPCI_FL_BASE0 0x0000
#define SPCI_FL_BASE1 0x0001
#define SPCI_FL_BASE2 0x0002
#define SPCI_FL_BASE3 0x0003
#define SPCI_FL_BASE4 0x0004
#define SPCI_FL_GET_BASE(x) (x & SPCI_FL_BASE_MASK)
#define SPCI_FL_IRQ_MASK (0x0007 << 4)
#define SPCI_FL_IRQBASE0 (0x0000 << 4)
#define SPCI_FL_IRQBASE1 (0x0001 << 4)
#define SPCI_FL_IRQBASE2 (0x0002 << 4)
#define SPCI_FL_IRQBASE3 (0x0003 << 4)
#define SPCI_FL_IRQBASE4 (0x0004 << 4)
#define SPCI_FL_GET_IRQBASE(x) ((x & SPCI_FL_IRQ_MASK) >> 4)
/* Use successive BARs (PCI base address registers),
else use offset into some specified BAR */
#define SPCI_FL_BASE_TABLE 0x0100
/* Use successive entries in the irq resource table */
#define SPCI_FL_IRQ_TABLE 0x0200
/* Use the irq resource table instead of dev->irq */
#define SPCI_FL_IRQRESOURCE 0x0400
/* Use the Base address register size to cap number of ports */
#define SPCI_FL_REGION_SZ_CAP 0x0800
/* Do not use irq sharing for this device */
#define SPCI_FL_NO_SHIRQ 0x1000
/* This is a PNP device */
#define SPCI_FL_ISPNP 0x2000
#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP)
#endif
/* _LINUX_SERIAL_H */
#endif
/* _LINUX_SERIAL_H */
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