Trouble configuring access to serial PCIe card

I run a FreeBSD 13.3-RELEASE-p3 box with a consumer mainboard and an Intel Xeon CPU. I want to access this machine on a console using a USB to TIA-232-F adapter cable which I bought together with a PCIe card for this purpose. (So I can take out the GPU again [which I only put in when I lose SSH and have real trouble with the setup] and still access the box directly). I have been fighting with this for a long time now. Occasionally trying and failing, trying to understand the nitty gritty of manually configuring the COM ports on FreeBSD and trying to troubleshoot this fiendish combination of adapter cards, adapter cables, manual configuration, versioning and as spice on top Xen...(I want to ignore [and turned off for the sake of this argument] the latter for now [I'll suffer with enabling Xen console in the future...]).

I have absolutely no issues in connecting a rollover to my firewall, firing up minicom in WSL or PuTTY on Windows or a Linux laptop and accessing a device this way, so I do have some console experience I suppose. So generally speaking I doubt that I would have to look at how to setup the "terminal" side (cable adapter drivers are installed on the Windows box I want to access from, and the chip is recognized, though I do not own other devices with serial ports to test the cable against).

PCI/PCIe (x1) Dual Port Serial Adapter (Controller Product Page)
Serial Controller: Nanjing Qinheng Microelectronics Co. Ltd. CH352/CH382 PCI/PCIe (rev 10)
Out: 2x TIA-232-F (RS232) 9 Pin DSUB Male
Bought in Germany as "SIENOC" brand, very similar models with same chip usually sold by "StarTech" in the US

USB to RS232 Adapter Cable (Controller Product Page)
Serial Controller: Prolific PL2303GC
USB 2.0 to 9 Pin DSUB Female
Bought in Germany as "DTech" brand

I have read the handbook on this topic again and again, and it's rough to say the least. I'll start with some output. It seems the card is recognized well enough, only minor detail being that the PCIe interface where the card is slotted is mentioned as "none":
pciconf -lBbcevV none1@pci0:3:0:0
Code:
none1@pci0:3:0:0:       class=0x070005 rev=0x10 hdr=0x00 vendor=0x1c00 device=0x3253 subvendor=0x1c00 subdevice=0x3253
    vendor     = 'Nanjing Qinheng Microelectronics Co., Ltd.'
    device     = 'CH352/CH382 PCI/PCIe Dual Port Serial Adapter'
    class      = simple comms
    subclass   = UART
    bar   [10] = type I/O Port, range 32, base 0xd000, size 256, enabled
    bar   [14] = type Prefetchable Memory, range 32, base 0xf0000000, size 32768, enabled
    bar   [18] = type I/O Port, range 32, base 0xd100, size 4, enabled
    cap 01[60] = powerspec 3  supports D0 D3  current D0
    cap 05[68] = MSI supports 32 messages, 64 bit, vector masks
    cap 10[80] = PCI-Express 2 legacy endpoint max data 128(256) NS
                 max read 512
                 link x1(x1) speed 2.5(2.5) ASPM disabled(L0s/L1) ClockPM disabled
    ecap 0001[100] = AER 1 0 fatal 0 non-fatal 0 corrected

lspci -vvv -s 03:00.0
Code:
03:00.0 Serial controller: Nanjing Qinheng Microelectronics Co., Ltd. CH352/CH382 PCI/PCIe Dual Port Serial Adapter (rev 10) (prog-if 05 [16850])
        Subsystem: Nanjing Qinheng Microelectronics Co., Ltd. CH352/CH382 PCI/PCIe Dual Port Serial Adapter
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 16
        Region 0: I/O ports at d000
        Region 1: Memory at f0000000 (32-bit, prefetchable)
        Region 2: I/O ports at d100
        Expansion ROM at f7d00000 [disabled]
        Capabilities: [60] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [68] MSI: Enable- Count=1/32 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [80] Express (v2) Legacy Endpoint, IntMsgNum 0
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <2us, L1 <32us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset- TEE-IO-
                DevCtl: CorrErr- NonFatalErr- FatalErr- UnsupReq-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s unlimited, L1 unlimited
                        ClockPM+ Surprise- LLActRep- BwNot- ASPMOptComp-
                LnkCtl: ASPM Disabled; RCB 64 bytes, LnkDisable- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1
                        TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+ NROPrPrP- LTR-
                         10BitTagComp- 10BitTagReq- OBFF Not Supported, ExtFmt- EETLPPrefix-
                         EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
                         FRS-
                         AtomicOpsCap: 32bit- 64bit- 128bitCAS-
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-
                         AtomicOpsCtl: ReqEn-
                         IDOReq- IDOCompl- LTR- EmergencyPowerReductionReq-
                         10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
                LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete- EqualizationPhase1-
                         EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
                         Retimer- 2Retimers- CrosslinkRes: unsupported
        Capabilities: [100 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+
                AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
                        MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
                HeaderLog: 00000000 00000000 00000000 00000000

To be on the safe side I boot with /boot/loader.conf:
Code:
boot_serial="YES"
boot_multicons="YES"
console="comconsole,vidconsole"
console_speed="9600"
uplcom_load="YES"
uplcom seemingly being the correct driver module to use with the Prolific USB adapter according to uplcom(4)
I have also tried to set bitrate to 115200 in /boot/loader.conf and in /etc/ttys with no difference.

grep uart /var/run/dmesg.boot
Code:
uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
uart0: console (9600,n,8,1)
pgrep -afl ttyu
Code:
2901 /usr/libexec/getty std.9600 ttyu0
stty -a -f /dev/ttyu0
Code:
speed 9600 baud; 0 rows; 0 columns;
lflags: -icanon -isig -iexten -echo -echoe -echok -echoke -echonl
        -echoctl -echoprt -altwerase -noflsh -tostop -flusho -pendin
        -nokerninfo -extproc
iflags: -istrip -icrnl -inlcr -igncr -ixon -ixoff -ixany -imaxbel -ignbrk
        -brkint -inpck -ignpar -parmrk -iutf8
oflags: -opost onlcr -ocrnl tab3 -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
        -dtrflow -mdmbuf rtsdtr
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
        eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
        lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
        status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;

And last but not least:
/etc/ttys
Code:
console none                            unknown off secure
#
ttyv0   "/usr/libexec/getty Pc"         xterm   onifexists secure
# Virtual terminals
ttyv1   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv2   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv3   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv4   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv5   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv6   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv7   "/usr/libexec/getty Pc"         xterm   onifexists secure
ttyv8   "/usr/local/bin/xdm -nodaemon"  xterm   off secure
# Serial terminals
# The 'dialup' keyword identifies dialin lines to login, fingerd etc.
ttyu0   "/usr/libexec/getty std.9600"   xterm   on secure
ttyu1   "/usr/libexec/getty std.9600"   xterm   on secure
ttyu2   "/usr/libexec/getty std.115200" dialup  onifexists secure
ttyu3   "/usr/libexec/getty std.115200" dialup  onifexists secure
# Dumb console
dcons   "/usr/libexec/getty std.9600"   vt100   off secure
# Xen Virtual console
xc0     "/usr/libexec/getty Pc"         xterm   onifexists secure

I ended up setting everything to 9600 bps cause dmesg would always contain uart0: console (9600,n,8,1) no matter what, which kinda weirds me out.
I also find it weird how there's only one ttyu running, even though I have two ports? Is this to be expected? Even with boot_multicons?
Note that as mentioned, I have the driver for the adapter installed, and minicom and PuTTY set up on a Windows client that wants to access this machine but get absolutely no input/output on the connection.

Questions I have:
  1. On consumer devices it seems that COM ports usually get virtually mapped to some sort of USB adapter device/cable, do I expect my two hardware serial ports from this PCIe card to always show up whether a cable is connected or not?
  2. FreeBSD predefines 4 COM ports, 0 through 3. I have 2 serial interfaces but only one COM ttyu shows. Why? If anything I'd at least expect ttyu0 and ttyu1
  3. Does this look more like a driver issue to you, or like it might be misconfiguration (e.g. manually having to mess with device.hints or similar)?
  4. How do I further troubleshoot the connection to hopefully exclude either of the adapter, cable and configuration?
 
Thank you for the detail. Will BSD always try to grab the first COM available if not told otherwise?
Most questions remain, I would hope to get a connection on ttyu0 in that case from my understanding.
 
FreeBSD predefines 4 COM ports, 0 through 3. I have 2 serial interfaces but only one COM ttyu shows. Why? If anything I'd at least expect ttyu0 and ttyu1
usually even consumer boards still have com ports, even if not physically present at the back, there are still some pinheaders. However, some especially stupid vendors even cheap out on those headers yet the chipset still has those ports enabled. Look at the dmesg output at boot (or /var/run/dmesg.boot) to see which ttyus are actually from that card and which are native to the board/chipset.

Also make sure to disable any console redirection (if any) and the need for an actual graphics adapter in the BIOS. Especially the latter is often a problem on consumer boards...
 
Also note there's only one serial console, additional serial ports can be configured for terminal access but they are not console ports. There is a difference. The console will show the kernel starting, system booting, etc. It's also the only port that works in single user mode. Any additional serial terminal ports will only show a login prompt when the system is running multiuser.
 
Thank you everyone for further hints.
About the behavior of console, thanks for clearing up that distinction, good to know, if one day I get this to work.
The bit about uplcom(4) requiring ucom(4) looks right. So I added ucom_load to the loader. Great catch. Sadly didn't change anything neither in behavior nor outputs.

Also a big thanks for hinting at onboard serial ports, I looked into the specs, manual and UEFI and indeed this Gigabyte board does have an onboard serial port with a IT8728 controller. I disabled it in the UEFI and now something interesting is happening. With no changes to the configs from above and ttyu0 and ttyu1 still set to on in /etc/ttys the box can't find any interfaces anymore it seems, even though pciconf and lspci list the PCIe card with all its features. getty can't start. It spams
Code:
mmm   d hh:mm:ss box getty[PID]: open /dev/ttyu0: No such file or directory
mmm   d hh:mm:ss box getty[PID]: open /dev/ttyu1: No such file or directory
mmm   d hh:mm:ss box init[PID]: getty repeating too quickly on port /dev/tty0, sleeping 30s
mmm   d hh:mm:ss box init[PID]: getty repeating too quickly on port /dev/tty1, sleeping 30s
This looks to me as if my box does not actually recognize my card with the two ports yet at all and was maybe referring to that onboard port before? dmesg also makes no mention of uart anymore after rebooting a few times with the disabled onboard port. Is this indeed a missing driver? I have read awful threads on these forums about people hard coding driver support for their add-in cards (ugh...) but I also read that these CH382 chips supposedly are rather well supported by uart.

These serial PCIe cards seem to be a recurring theme on the forums. This thread looks similar and I might even try to load puc and add this patch in manually, see what happens.
I also found this wiki article about adapters earlier which made me have at least some hopes for this adapter cable.

Edit: I did add PMc's patch to /sys/dev/puc/pucdata.c as seen here on forums and adapted slightly to my model, just like thogard did in that same thread, who apparently had the same issue with the same card (exact same devID) but I won't even get the card loaded by uart to begin with. Nothing shows up in dmesg.
 
Ha.
First off, it is not getting clear to me what you are doing. You can have
  1. a serial adapter from an onboard serial (if present). These should work the traditional way over ISA-bridge, same as on the PC-XT, aka COM1 and COM2, on 0x3BC or 0x3f8 and that ilk.
  2. a serial adapter from an USB-dongle, usually Prolific/uplcom. These do NOT work like traditional serials, they appear as /dev/ttyU* instead of /dev/ttyu*
  3. a serial adapter from a puc card like CH38x. These may work very similar to traditional serials; at least they use the same driver and device-node. But the ports are not on the ISA-bridge, they are on PCI/PCIe.
For a serial adapter, you need one of these three options. But You are talking about two of them, and it is unclear why.

Then: I have no idea which of these options may be useable as console, and to what extent. I never tried.
But I might assume the first step, in any case, would be to get the thing properly detected and working, so that, with the system up and running, one can talk over it to some [null]modem.

With the uplcom this is dead simple: just plug it in, load the driver modules, and the device nodes should appear and tty ioctl() should be serviced.

With the WCH chip it is more interesting. At first you need the puc driver to attach - as long as it says "none", the kernel does nothing with it (what you see with pciconf is just what is stored inside the card). This usually means to enter the actual vendor and device numbers into the puc driver code.
The next step is then to make the actual serial driver happy - that can be more or less entertaining, because the actual memory layout may be more or less weird. (That is what I'm doing inside puc_config_wch() by tweaking the PUC_CFG_GET_OFS and similar routines.)

As a result thus far, devinfo should produce something like this:
Code:
        pcib5
          pci5
            puc0
              uart2
              uart3
              ppc1
                ppbus0
                  lpt0
(You probably do not have the ppc/lpt part)

What I did not yet get, is an irq interrupt line for the devices. This is of no major concern of mine, but for decent serial communications you probably need one. Obviousely the irq cannot be simply 3 or 4 (as of old), but has to be somehow obtained from the PCI layer. (Would need some study to figure out how that is generally supposed to work.)

I am currently using that card to drive my (very ancient) line printer - polled, without interrupt. That was also not without difficulty: the card (or the printer?) would frequently hang itself up after half a page, and only after adjusting the delays in the printer driver code to the exact values as from the IEEE specs (which they are by default not), the thing does now work. So, maybe, that WCH chip design is not the very best quality...
 
Possible workaround... since 2009 I've been running FreeBSD on Mac minis and they lack serial ports but they have USB ports. So, I've been using a Lindy branded USB to 4 serial port converter box which provides serial ports to connect to my APC UPSes. This has now worked for the last 15 years without any issues.

Code:
Root mount waiting for: usbus0 usbus1 usbus2
ugen0.3: <FTDI USB HS SERIAL CONVERTER> at usbus0
ugen0.4: <FTDI USB HS SERIAL CONVERTER> at usbus0
ugen0.5: <FTDI USB HS SERIAL CONVERTER> at usbus0
ugen0.6: <FTDI USB HS SERIAL CONVERTER> at usbus0
 
Thanks for offering alternative solutions trev, I might indeed have to rethink this setup if I don't get this card to work.
PMc! Didn't expect you to pop up, thanks for chiming in, appreciate it.

I mentioned all the things involved until now but at a high level I really want a simple thing:
- OOBM on this homelab server, that is: talk to my server from a PuTTY or minicom on another device with a cable when my network goes down.

Really that's all it is. I couldn't care less by what means this happens. I reach my network equipment with a rollover on a RJ45 "console"/"COM" port. Historically this was done with serial connections. Well my server is not really server hardware except the CPU, so I intuitively bought an extension card (CH382) and a cable (nullmodem Prolific). I would prefer to just plug in a USB plug on both ends and serve FreeBSD console output over that. But we can't have nice things (I mean I know it's a completely different protocol, but still). Until yesterday I didn't even know this board had a serial header.

So I'm not concerned about talking to peripheral equipment from my server, but rather about my server being talked to. I might think at this point that the usb to rs232 cable needs the driver at the usb side and if my server has the rs232 card working it should just recognize that cable as serial, not needing additional drivers, would this be correct to assume?

Honestly I'm open to simply buying another card that's known to work well with FreeBSD uart or consider other connection methods, like trev mentioned e.g. (just I find that to be a little bit overkill for my situation, I really would prefer to have a cable and be done). Even though I do find it intriguing to have several COM ports to play around with, but I can't even get one to work at this point...
Today I found vendors that sell cables to connect the onboard serial to a chassis DB9 out like this Delock cable. Still, this would require me to make sure that the onboard header is recognized by FreeBSD, I mentioned earlier that the UEFI reports this as a IT8728 chip.

You are certainly right about the devinfo part, in fact I don't even have any puc interface in devinfo to begin with, even after trying to implement your patch where the only adjustment I made was changing my device ID and the PUC_PORT to 2S instead of 2S1P (like thogard mentioned in that other thread I linked, tried both though). Well, maybe the function name too, but that's really redundant now, is it? (My device only ever mentions CH382 never WCH or 382L or other model identifiers I have seen online).

Code:
        {   0x1c00, 0x3253, 0x1c00, 0x3253,
            "Nanjing Qinheng CH352/CH382 Dual Port Serial"
            DEFAULT_RCLK,
            PUC_PORT_2S, 0x10, 4, 8,
            .config_function = puc_config_ch
        },
I didn't change anything in the actual function (which I suppose possibly might be a no go cause in the end they are different cards) but I'm clearly not informed enough to adjust anything in there. You mentioned in the other thread that these cards only have 4 byte for LPT and that puc can't auto handle this, hence why you wrote the patch. This seems to be in line with my output from above. So even with the device now configured in puc drivers, it still won't show up. I'd rather look elsewhere at this point I guess.

Last thought I'm having for the day (please forgive my ignorance): If I simply swapped the setup and put the card in my workstation, installing the Windows driver that came with the PCIe card and then put the USB side from the prolific cable into my FreeBSD box, and suggesting that uplcom opened a ttyU for me and the Windows machine likes the driver for the card, would I still be able to get a FreeBSD console on the workstation this way? I guess what I'm asking is: Do serial connections work both ways even with all these adapter shenanigans?
 
Thanks for offering alternative solutions trev, I might indeed have to rethink this setup if I don't get this card to work.
PMc! Didn't expect you to pop up, thanks for chiming in, appreciate it.

I mentioned all the things involved until now but at a high level I really want a simple thing:
- OOBM on this homelab server, that is: talk to my server from a PuTTY or minicom on another device with a cable when my network goes down.
Okay, that figures. Let's sort it out:
The downside of this is, if you get a serial console into FreeBSD, it will still not work for BIOS access and the loader. Editing the BIOS setup, choosing the disk to boot, or rebooting after a crash is not in scope of such a solution; it works only while our kernel is actually running. This is why I never looked into it - because I need to go to the physical console anyway for these things.

So I'm not concerned about talking to peripheral equipment from my server, but rather about my server being talked to.
That's not a point - serial usually talks in both directions.

Today I found vendors that sell cables to connect the onboard serial to a chassis DB9 out like this Delock cable.
Yepp. If such a thing isn't in the scrap heap already. Using that onboard serial would be the most straight-forward approach.
Still, this would require me to make sure that the onboard header is recognized by FreeBSD, I mentioned earlier that the UEFI reports this as a IT8728 chip.
So this is not a traditional 16550 serial controller, this is some ASIC that contains (among many other things) a serial controller. But, on the upside, FreeBSD apparently detects and accepts it:
grep uart /var/run/dmesg.boot
Code:
uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
This looks no different than mine on the server board (but mine is a different ASIC)
Somewhere here on the forums somebody wrote a driver to even read the thermal monitors out of that IT8728 chip - there is no mention if the serial works, but I might assume chances are rather high.

You are certainly right about the devinfo part, in fact I don't even have any puc interface in devinfo to begin with, even after trying to implement your patch where the only adjustment I made was changing my device ID and the PUC_PORT to 2S instead of 2S1P (like thogard mentioned in that other thread I linked, tried both though).
It could be helpful to boot in verbose mode - maybe the puc tells us something about what it tried to do.

Well, maybe the function name too, but that's really redundant now, is it? (My device only ever mentions CH382 never WCH or 382L or other model identifiers I have seen online).
It's all the same chinese stuff, where you never know what's actually inside. I have a spec-sheet that says CH382, but actually talks about CH382L, and that is 2ser1par. However, my chip reports in pciconf "CH384 Dual Port Serial and Parallel Port Adapter".
Apparently the 384 is a quad-serial - so why does mine say, "384 dual"?
And WCH is how they tend to call themselves (but that might also be a chinese letter)

I didn't change anything in the actual function (which I suppose possibly might be a no go cause in the end they are different cards) but I'm clearly not informed enough to adjust anything in there.
It is probably something trivial like a port register not at the exact same place, the driver not finding it and then just failing.

Last thought I'm having for the day (please forgive my ignorance): If I simply swapped the setup and put the card in my workstation, installing the Windows driver that came with the PCIe card and then put the USB side from the prolific cable into my FreeBSD box, and suggesting that uplcom opened a ttyU for me and the Windows machine likes the driver for the card, would I still be able to get a FreeBSD console on the workstation this way?
That is a simple question: does the FreeBSD console work on a USB-to-serial? This here seems to have achieved it:

I guess what I'm asking is: Do serial connections work both ways even with all these adapter shenanigans?
It is all logical: a serial is always a serial. The USB-to-serial is actually an adapter/controller on the USB bus that drives a physical serial interface via USB commands - and our uplcom driver steers that controller over USB and makes it appear as a ttyU* serial interface in the system. So you plug that adapter/dongle into an USB port, and onwards you have a (more or less) normal serial wire to connect to any other working serial interface.
I assume that USB-to-serial dongle comes packaged with some device driver useable on Windows (or Windows has it already included) - so that should work also.
 
I want to thank you explicitly for your time and energy in assisting with this topic. I will have to let all of that information sink in for a minute or two, then experiment with some stuff and take some decisions in the process I think. This thread has helped me a lot already thanks to everyone commenting. I would like to react with a little heart, but a handshake will have to do for now!

I realize that this is not proper modern OOBM in any sense, but I thought it'd be a quick (ha!) and dirty approach to have access when I lock myself out because of my own stupidity writing pf rules or similar ;)
In the end I can always pop in a spare GPU, turn on a monitor and all is good. Some people would probably question the time and energy invested vs. actual usefulness at this point, and they'd have a point. (Since I have my network, my SSH and pf pretty much well sorted out) It's a puzzle piece I've always been wanting to solve in this setup.

So as far as puc goes, it doesn't show up in dmesg at all actually. Not a single mention, even with rc_info and rc_debug enabled (and also additionally booting with boot -v). kldstat -v shows that pci/puc, puc/ppc and puc/uart are loaded by the kernel. When I manually add puc_enable to loader.conf then apparently dmesg only informs that puc couldn't be loaded by the kernel since it's already loaded by puc.ko but that's all. I assume puc doesn't recognize the card so it doesn't see the need to load anything?

Again, thanks so far already <3

Edit 10:15pm: I just had a major "we have picture! LOL"-Sorin moment. I figured: Hey guess what, my PCIe add-in serial card uses that exact cabling I linked earlier to connect the serial headers on the card to the chassis, just it's very short. But I don't care about the length at this point, I need to test functionality. I can just pull the cable from the card, and slot it into my mainboard header. Connect the nullmodem and test the setup. And guess what happened...INSTANT console in PuTTY...I'm speechless. I had the very solution on my board hahahahaha. Now this does not at all remedy the situation with the CH382 chip, but it does show that the IT8728 works pretty much out of the box. I'm currently controlling this server from my workstation with a cheap prolific USB to serial adapter and onboard serial headers. I'm baffled.
I would prefer to not mark this as solved, since the actual topic is not solved at all. Marking this as solved is misleading to the issue discussed IMHO.

Screenshot 2024-07-05 003710.png
 
So as far as puc goes, it doesn't show up in dmesg at all actually. Not a single mention, even with rc_info and rc_debug enabled (and also additionally booting with boot -v). kldstat -v shows that pci/puc, puc/ppc and puc/uart are loaded by the kernel.
Very stupid question comes to my mind: you did manage to compile (and install) a new kernel after modifying /usr/src/sys/dev/puc/pucdata.c (or anything else under /usr/src/sys)?
 
Stupidity only lies in my answer: "You have to re-compile the kernel after modifying such driver files in /usr/src/sys?!"
I was under the naive assumption that if I load the kernel module explicitely with puc_enable=YES in /boot/loader.conf and the boot logs show that the driver was loaded by the driver.ko module not by the kernel for some reason I didn't have to do anything else. Do I have to re-compile everytime I touch a kernel module?
I have had a similar situation with WSL2 on Windows where support for the Prolific chip is not compiled into the default kernel and I'm using WSL1 instead,...cause I honestly can't be bothered with compiling a custom kernel for such trivial stuff...
 
Ha. That was my thought: somebody using Windows (I never used that, me switched to unix right from DOS) might not really know about the ways of old. Nowadays people don't want to compile anymore - but there is actually the beauty of it: below /usr/src is the entire OS in sourcecode, and each and every bit of it can be changed, rightaway, just recompile, reinstall (reboot) and run the new changes. (There are not so many OS nowadays where you still can do that in a practical way.)

Stupidity only lies in my answer: "You have to re-compile the kernel after modifying such driver files in /usr/src/sys?!"
;)
Well, below /usr/src is mostly C language code, and that happens to require compilation.

In case of the kernel, i.e. /usr/src/sys the following should do:
Code:
# cd /usr/src
# make buildkernel KERNCONF=GENERIC
# make installkernel KERNCONF=GENERIC
Afterwards the old kernel should have moved into /boot/kernel.old, and can still be booted from the loader menu (in case something went wrong or some comparison is needed).
 
Well to my defense I have had my share of compiling Linux kernels, but the implications this has to the system, and my own sanity, locking in dependencies, next compile right around the corner etc. are not worth the mindf*** it has caused me if it's not for static situations like a kiosk.

Well, below /usr/src is mostly C language code, and that happens to require compilation.
Fair enough. Simple fact. I honestly very conciously tried to ignore this elephant in my room.

I've only been using FreeBSD "on the side" for a few years now in my lab (where everything else evolves around it, and VERY much to my liking so) and from what I've read so far, people like to point out the distinction of how in BSD the kernel is an integrate part of the maintained system, as opposed to Linux. I actually really want to buy a copy of the often praised "The Design and Implementation of the FreeBSD Operating System" (McKusick et al., 2014), I feel like this is a very good moment in time for me personally, but I also read that one of the authors supposedly mentioned this year that there's a third edition in the works. And I really don't wanna buy it twice. It's not cheap.

It might seem slightly off topic, but it does appear relevant to me in regards to the controller I initially wanted to get working:
You're saying that it's very easy to compile the FreeBSD kernel from /usr/src at any point in time with any changes made there. (Thanks for the instructions) That does sound very straight forward indeed.
How does this behave with updates in the kernel? Does the rest of the system and modules just update normally, respecting my changes as long as the source code doesn't change?
That is, if pucdata changed at some point, it would just throw a diff at me? But other than that just happily upgrade to any major future version of FreeBSD?

If the latter was the case, this would be another HUGE plus for BSD in my book and would push my already Fanboy status to new heights.
But it can't be that easy. Right?

Right?
 
. I actually really want to buy a copy of the often praised "The Design and Implementation of the FreeBSD Operating System" (McKusick et al., 2014),
Indeed I did consider to suggest that. You seem to get a point when it is made, so that might really be the adaequate lecture.

You're saying that it's very easy to compile the FreeBSD kernel from /usr/src at any point in time with any changes made there. (Thanks for the instructions) That does sound very straight forward indeed.
How does this behave with updates in the kernel? Does the rest of the system and modules just update normally, respecting my changes as long as the source code doesn't change?
That is, if pucdata changed at some point, it would just throw a diff at me? But other than that just happily upgrade to any major future version of FreeBSD?
Now that depends. Basically, when you start to modify your source (kernel or other parts) to some extent, you will need to somehow keep track of these changes - that doesn't magically happen by itself.

Then, upgrading: if you do a binary upgrade, I think it will just overwrite the modified kernel or the modified module (or the modified /bin/sh or whatever) when it comes to that, and not detect that this has been modified before - but I am not certain here, because I usually upgrade from source.
If you do an upgrade from source (that is, update the soruces below /usr/src, then rebui ld and install the whole OS, kernel and world) and if /usr/src is an active git repo, then git will treat the changes like any local vs. remote changes in a project: it will merge them, and occasionally create a merge conflict.
 
[...] I usually upgrade from source.
NOT the answer I had hoped for hahahaha.

This is one of the reasons people tend to dislike compiling themselves I wager:
Code:
--------------------------------------------------------------
>>> World build completed on Fri Jul 12 19:52:42 CEST 2024
>>> World built in 29584 seconds, ncpu: 8
--------------------------------------------------------------
That's over eight hours. This was an initial run, and follow-ups should apparently be a lot faster, depending on changes, but I would need very good reasons for needed hardware support or such, to make this worth my time hoping that nothing breaks during the compilation (my case here does not warrant any of this IMO [rather buy a card that's got native support], if not for the sake of never giving up on learning new things, which is what my lab is for to begin with). And to speed things up I can't remove /usr/obj now, which takes up over 6GB of disk space (not a big deal, but still, something to consider). To be fair, the kernel compiled a LOT faster. (I think it was about 30m to 1h in my case, I didn't pay too much attention, could've been more). But take this as opposed to a few minutes of running freebsd-update. Much love to everybody involved in maintaining packages for package managers...

But on topic though:
After compiling world and kernel according to the handbook (to make sure I have a clean system after messing with it), the discussed card (Nanjing Qinheng Microelectronics Co., Ltd. CH352/CH382 PCI/PCIe Dual Port Serial Adapter (rev 10)) is now (to some degree at least) recognized by both uart(4) and puc(4), as can be seen in dmesg:
Code:
# dmesg | grep -i uart
uart4: <16x50 with 256 byte FIFO> at port 1 on puc0
uart4: fast interrupt
uart4: PPS capture mode: DCD
uart5: <16x50 with 256 byte FIFO> at port 2 on puc0
uart5: fast interrupt
uart5: PPS capture mode: DCD
ns8250: UART FCR is broken
ns8250: UART FCR is broken
uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
ns8250: UART FCR is broken
uart0: console (115200,n,8,1)
uart0: fast interrupt
uart0: PPS capture mode: DCD
uart: uart0 already exists; skipping it
pcib0: allocated type 4 (0x2f8-0x2f8) for rid 0 of uart1
uart1 failed to probe at port 0x2f8 irq 3 on isa0
pcib0: allocated type 4 (0x3e8-0x3e8) for rid 0 of uart2
uart2 failed to probe at port 0x3e8 irq 5 on isa0
pcib0: allocated type 4 (0x2e8-0x2e8) for rid 0 of uart3
uart3 failed to probe at port 0x2e8 irq 9 on isa0
and pciconf (which finally shows the card under puc0 instead of none [I switched PCIe slots since thread start]):
Code:
# pciconf -lBbcevV puc0@pci0:2:0:0
puc0@pci0:2:0:0:        class=0x070005 rev=0x10 hdr=0x00 vendor=0x1c00 device=0x3253 subvendor=0x1c00 subdevice=0x3253
    vendor     = 'Nanjing Qinheng Microelectronics Co., Ltd.'
    device     = 'CH352/CH382 PCI/PCIe Dual Port Serial Adapter'
    class      = simple comms
    subclass   = UART
    bar   [10] = type I/O Port, range 32, base 0xe000, size 256, enabled
    bar   [14] = type Prefetchable Memory, range 32, base 0xf7b00000, size 32768, enabled
    bar   [18] = type I/O Port, range 32, base 0xe100, size 4, enabled
    cap 01[60] = powerspec 3  supports D0 D3  current D0
    cap 05[68] = MSI supports 32 messages, 64 bit, vector masks enabled with 1 message
    cap 10[80] = PCI-Express 2 legacy endpoint max data 128(256) NS
                 max read 512
                 link x1(x1) speed 2.5(2.5) ASPM disabled(L0s/L1) ClockPM disabled
    ecap 0001[100] = AER 1 0 fatal 0 non-fatal 0 corrected

To my surprise the card did not take up the default ports, but instead created new ones (uart4 & uart5), and I'm personally unable to configure a working session on either (for lack of knowledge and stamina with this issue at this point to be honest). I would probably need to add additional /boot/device.hints (no idea what ports and irq's to assign [0x3D8 and 0x2D8 for ports??]) and add more ttyu's in /etc/ttys. Doing only the latter spawns getty processes but shows "-" for TT which "indicates a process which never had a controlling terminal" according to ps(1).

So personally I think it's pretty safe to say that these CH382 controllers are not supported out-of-the-box in FreeBSD 14.2-RELEASE-p2 and earlier, but manually patching /usr/src/sys/dev/puc/pucdata.c with the patch provided by PMc found here and recompiling the kernel, can possibly provide support to some extend.
 
This is one of the reasons people tend to dislike compiling themselves I wager:
Code:
--------------------------------------------------------------
>>> World build completed on Fri Jul 12 19:52:42 CEST 2024
>>> World built in 29584 seconds, ncpu: 8
--------------------------------------------------------------
That's over eight hours.
Something is wrong with this. You might try make -j8 buildworld to use all available vCore.
My initial 13.3 build (on a 10-year old Haswell-EP):
Code:
--------------------------------------------------------------
>>> World build completed on Sun Feb  4 10:29:33 CET 2024
>>> World built in 4195 seconds, ncpu: 10, make -j10
--------------------------------------------------------------

To my surprise the card did not take up the default ports, but instead created new ones (uart4 & uart5),
That's okay.
and I'm personally unable to configure a working session on either (for lack of knowledge and stamina with this issue at this point to be honest). I would probably need to add additional /boot/device.hints (no idea what ports and irq's to assign [0x3D8 and 0x2D8 for ports??])
No, these are ISA ports, PCI does not use them. (One reason PCI was dieveloped is to get rid of these ports that need manual configuration, and have real Plug-n-Play instead - so in PCI the ports are automatically arranged between card and machine).

As I mentioned, at this point I got as far as to successfully read the AT&V report from a modem. So basically the serial does transfer data in both directions. But then one would need to get the interrupt working, and have it run something faster than 2400 or 9600 baud.
 
Back
Top