Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a Red Hat Enterprise 6.2 machine with two on-board serial ports and a PCIe card with 8 additional serial ports (16C950 UARTs, 16C550 compliant). I've added the kernel option 8250.nr_uarts=10 so that all devices show up under /dev.

The two on-board devices show up as ttyS0 and ttyS1, as expected, but the serial ports on the PCIe card aren't being ordered by their I/O port as I would expect them to. Otherwise the devices work fine, it's just that it's not very elegant that the tty order doesn't match the order on the breakout cable for the board. Any ideas on how to change the order?

Output form setserial:

# setserial -g /dev/ttyS*
/dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
/dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
/dev/ttyS2, UART: 16650, Port: 0xdf30, IRQ: 30
/dev/ttyS3, UART: 16650, Port: 0xdf38, IRQ: 30
/dev/ttyS4, UART: 16650, Port: 0xdf00, IRQ: 30      <-- Why is this one not ttyS2?
/dev/ttyS5, UART: 16650, Port: 0xdf08, IRQ: 30
/dev/ttyS6, UART: 16650, Port: 0xdf10, IRQ: 30
/dev/ttyS7, UART: 16650, Port: 0xdf18, IRQ: 30
/dev/ttyS8, UART: 16650, Port: 0xdf20, IRQ: 30
/dev/ttyS9, UART: 16650, Port: 0xdf28, IRQ: 30

Looking in dmesg, it's finding them in the right order, but starting the lowest I/O port out at ttyS4:

# dmesg | grep ttyS
serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
00:06: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
00:07: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
0000:05:00.0: ttyS4 at I/O 0xdf00 (irq = 30) is a ST16650
0000:05:00.0: ttyS5 at I/O 0xdf08 (irq = 30) is a ST16650
0000:05:00.0: ttyS6 at I/O 0xdf10 (irq = 30) is a ST16650
0000:05:00.0: ttyS7 at I/O 0xdf18 (irq = 30) is a ST16650
0000:05:00.0: ttyS8 at I/O 0xdf20 (irq = 30) is a ST16650
0000:05:00.0: ttyS9 at I/O 0xdf28 (irq = 30) is a ST16650
0000:05:00.0: ttyS2 at I/O 0xdf30 (irq = 30) is a ST16650
0000:05:00.0: ttyS3 at I/O 0xdf38 (irq = 30) is a ST16650

Trying to use setserial to change the port doesn't seem to work, it always reports that the device is busy (this is from a fresh reboot, nothing has accessed the device).

# setserial /dev/ttyS2 port 0xdf00
Cannot set serial info: Device or resource busy

Edit: Thanks to info provided by Gilles, I have it mostly working now using a udev that writes an ordered NAME by matching on the KERNEL name. The output from udevadm info shows that is the only parameter that can be used to uniquely identify the individual devices (ttyS[2-9] all report the same information, except for the KERNEL parameter).

# udevadm info -a -n /dev/ttyS2
  looking at device '/devices/pci0000:00/0000:00:07.0/0000:05:00.0/tty/ttyS2':
    KERNEL=="ttyS2"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:07.0/0000:05:00.0':
    KERNELS=="0000:05:00.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="serial"
    ATTRS{vendor}=="0x494f"
    ATTRS{device}=="0x10a9"
    ATTRS{subsystem_vendor}=="0x0000"
    ATTRS{subsystem_device}=="0x0000"
    ATTRS{class}=="0x070002"
    ATTRS{irq}=="30"
    ATTRS{local_cpus}=="0000ff"
    ATTRS{local_cpulist}=="0-7"

My new udev rules:

SUBSYSTEM=="tty", DRIVERS=="serial", ATTRS{vendor}=="0x494f", KERNEL=="ttyS4", NAME="ttyS2"
# [snipped 7 more rules for each device]
share|improve this question
add comment

1 Answer 1

up vote 1 down vote accepted

You should be able to change the device names with a udev rule. Run udevadm info -a -n /dev/ttyS2 to obtain characteristics of your device. Find attributes that uniquely identify the multiport card, and one attribute that identifies the port. Then write udev rules for each port. The rules might look like this:

SUBSYSTEM=="tty", DRIVERS=="serial", ATTRS{vendor}=="Yoyodyne", ATTRS{port}=="0xdf00", NAME="ttyS2"
SUBSYSTEM=="tty", DRIVERS=="serial", ATTRS{vendor}=="Yoyodyne", ATTRS{port}=="0xdf80", NAME="ttyS3"
…

Run udevadm trigger (with the right --attr-match-… option) to reapply the rules to already-connected devices.

share|improve this answer
    
Using udevadm, interestingly, it appears that there are no unique attributes on the devices on the multiport serial card. I created a udev rule that matches using KERNEL for the kernel name for the device and then provides a NAME with the corrected ordered name for the device. I'm not sure if that is optimal, but it appears to be working well right now. –  Linville Jun 18 '13 at 20:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.