Hello,
I have CH382-based PCI Express UART card and trying to use this port as
serial console. But specifing I/O port by "machine comaddr 0xd0c0"
at bootloader, kernel crashes with protection fault.
Here is the log.
--------
pci3 at ppb2 bus 3
puc0 at pci3 dev 0 function 0 "Nanjing QinHeng Electronics CH382" rev 0x10:
ports: 2 com
puc0: couldn't map BAR at offset 0x10
puc0: com port uses unmapped BAR (0x10)
puc0: com port uses unmapped BAR (0x10)
(snip)
vscsi0 at root
scsibus3 at vscsi0: 256 targets
softraid0 at root
scsibus4 at softraid0: 256 targets
root on sd1a (693a5e2a4cd28136.a) swap on sd1b dump on sd1b
radeondrm0: 1440x900
wsdisplay0 at radeondrm0 mux 1: console (std, vt100 emulation), using wskbd0
wsdisplay0: screen 1-5 added (std, vt100 emulation)
kernel: protection fault trap, code=0
Stopped at comwrite+0x16: movq mptramp_gdt32_desc+0x36(%rax),%rdi
ddb{2}> ps
TID PPID PGRP UID S FLAGS WAIT COMMAND
*62499 1 1 0 7 0 init
40202 0 0 0 3 0x14200 bored ttm_swap
16400 0 0 0 3 0x14200 pgzero zerothread
63444 0 0 0 3 0x14200 aiodoned aiodoned
19864 0 0 0 3 0x14200 syncer update
33777 0 0 0 3 0x14200 cleaner cleaner
29173 0 0 0 3 0x14200 reaper reaper
19502 0 0 0 3 0x14200 pgdaemon pagedaemon
30664 0 0 0 3 0x14200 bored crynlk
14562 0 0 0 3 0x14200 bored crypto
90437 0 0 0 3 0x14200 pftm pfpurge
83523 0 0 0 3 0x14200 bored sensors
66506 0 0 0 3 0x14200 usbtsk usbtask
59687 0 0 0 3 0x14200 usbatsk usbatsk
26939 0 0 0 3 0x40014200 acpi0 acpi0
52265 0 0 0 7 0x40014200 idle3
7097 0 0 0 3 0x40014200 idle2
7435 0 0 0 7 0x40014200 idle1
91364 0 0 0 3 0x14200 bored softnet
20307 0 0 0 3 0x14200 bored systqmp
26585 0 0 0 3 0x14200 bored systq
754 0 0 0 7 0x40014200 idle0
71396 0 0 0 3 0x14200 bored sbar
1 0 1 0 3 0x82 wait init
0 -1 0 0 3 0x10200 scheduler swapper
ddb{2}> trace
comwrite() at comwrite+0x16
dosendsyslog() at dosendsyslog+0x1ce
sys_sendsyslog() at sys_sendsyslog+0xbe
syscall() at syscall+0x27b
--- syscall (number 112) ---
end of kernel
end trace frame: 0x25f8573e0a2, count: -4
0x25f85635b5a:
ddb{2}> boot poweroff
--------
Here is the PCI configuration register of my CH382.
--------
3:0:0: Nanjing QinHeng Electronics CH382
0x0000: Vendor ID: 1c00 Product ID: 3253
0x0004: Command: 0007 Status: 0010
0x0008: Class: 07 Subclass: 00 Interface: 05 Revision: 10
0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 10
0x0010: BAR io addr: 0x0000d000/0x0100
0x0014: BAR mem prefetchable 32bit addr: 0xd0100000/0x00008000
0x0018: BAR io addr: 0x0000d100/0x0004
0x001c: BAR empty (00000000)
0x0020: BAR empty (00000000)
0x0024: BAR empty (00000000)
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 1c00 Product ID: 3253
0x0030: Expansion ROM Base Address: fe900000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: 0b Min Gnt: 00 Max Lat: 00
0x0060: Capability 0x01: Power Management
State: D0
0x0068: Capability 0x05: Message Signaled Interrupts (MSI)
0x0080: Capability 0x10: PCI Express
Link Speed: 2.5 / 2.5 GT/s Link Width: x1 / x1
--------
puc_pci_attach() in sys/dev/pci/puc.c requires BAR == UART's address
(specified with machine comaddr argument).
CH382's UART lies on BAR + 0xc0, so 0xd0c0 is real address.
To solve this problem, I am testing this patch. It seems to be working,
but can I use _bus_space_map() in puc.c?
--------
Index: puc.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/puc.c,v
retrieving revision 1.24
diff -u -p -r1.24 puc.c
--- puc.c 14 Mar 2015 03:38:49 -0000 1.24
+++ puc.c 23 Aug 2016 13:30:50 -0000
@@ -151,6 +151,7 @@ puc_pci_attach(struct device *parent, st
for (i = 0; i < PUC_NBARS; i++) {
pcireg_t type;
int bar;
+ bus_size_t size;
sc->sc_bar_mappings[i].mapped = 0;
bar = PCI_MAPREG_START + 4 * i;
@@ -174,12 +175,14 @@ puc_pci_attach(struct device *parent, st
* work.
*/
if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, type,
- &sc->sc_bar_mappings[i].a, NULL, NULL) == 0 &&
+ &sc->sc_bar_mappings[i].a, &size, NULL) == 0 &&
pa->pa_iot == comconsiot &&
- sc->sc_bar_mappings[i].a == comconsaddr) {
+ (sc->sc_bar_mappings[i].a <= comconsaddr &&
+ (sc->sc_bar_mappings[i].a + size) > comconsaddr) &&
+ _bus_space_map(comconsiot, sc->sc_bar_mappings[i].a,
+ size, 0, &sc->sc_bar_mappings[i].h) == 0) {
sc->sc_bar_mappings[i].t = comconsiot;
- sc->sc_bar_mappings[i].h = comconsioh;
- sc->sc_bar_mappings[i].s = COM_NPORTS;
+ sc->sc_bar_mappings[i].s = size;
sc->sc_bar_mappings[i].mapped = 1;
continue;
}
Regards,
--
SASANO Takayoshi <[email protected]>