Synopsis: <Touchpad emitting keyboard events, unrecognized touchpad> Category: <system kernel> Environment: System: OpenBSD 6.2 Stable Details: OpenBSD laptop.home 6.2 GENERIC.MP#2 amd64 Architecture: OpenBSD.amd64 Machine: amd64 Description: My laptop experienced keyboard events when touching the touchpad. The touchpad was not recognized properly (Linux recognizes it as a Synaptics Touchpad and FreeBSD sees it as a PS/2 mouse since it can default to this behavior) and would not work at all (neither on Stable or Current).
On a previous release though, the touchpad worked without patching but would emit keyboard events (I cannot remember which release sorry). The keyboard events happen both in console and X. The touchpad could sometimes work only for a few seconds after a fresh install but never after its first keyboard events emitting. So I looked for a solution in bugs@ and found two patches. So I applied the patches described here, on Current & Stable : https://marc.info/?l=openbsd-bugs&m=148517909028740&w=2 and here : http://www.stoeckmann.org/patches/ps2apm.patch from this thread: https://marc.info/?l=openbsd-bugs&m=149539198219115&w=2 with a very small correction for it to compile. (further down this mail) It can work on both Current and Stable but I chose to stay on Stable for now. And it works satisfyingly enough. The touchpad is now seen as a PS/2 mouse. It does not work when resuming from suspend and has no advanced features of course. So a big thank you to the guys who made the patches. I could also try to apply only the second patch to see if keyboard events happen if that's of any use to the devs. So I send the dmesg and other info as recommended: dmesg: OpenBSD 6.2-stable (GENERIC.MP) #2: Wed Nov 29 17:55:25 CET 2017 [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP real mem = 4196806656 (4002MB) avail mem = 4062593024 (3874MB) mpath0 at root scsibus0 at mpath0: 256 targets mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.8 @ 0xec200 (39 entries) bios0: vendor American Megatrends Inc. version "5.6.5" date 02/10/2015 bios0: Notebook W54_55_94_95_97AU,AUQ acpi0 at bios0: rev 2 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP APIC FPDT FIDT MCFG HPET SSDT UEFI SSDT SSDT ASF! SSDT SSDT TPM2 SSDT SSDT DMAR acpi0: wakeup devices PEGP(S4) PEG0(S4) PEGP(S4) PEG1(S4) PEGP(S4) PEG2(S4) PXSX(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4) RP03(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) [...] acpitimer0 at acpi0: 3579545 Hz, 24 bits acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Celeron(R) 3205U @ 1.50GHz, 1496.77 MHz cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,ERMS,INVPCID,RDSEED,PT,SENSOR,ARAT cpu0: 256KB 64b/line 8-way L2 cache cpu0: TSC frequency 1496770360 Hz cpu0: smt 0, core 0, package 0 mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges cpu0: apic clock running at 99MHz cpu0: mwait min=64, max=64, C-substates=0.2.1.2.4.1.1.1, IBE cpu1 at mainbus0: apid 2 (application processor) cpu1: Intel(R) Celeron(R) 3205U @ 1.50GHz, 1496.54 MHz cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,ERMS,INVPCID,RDSEED,PT,SENSOR,ARAT cpu1: 256KB 64b/line 8-way L2 cache cpu1: smt 0, core 1, package 0 ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 40 pins acpimcfg0 at acpi0 addr 0xf8000000, bus 0-63 acpihpet0 at acpi0: 14318179 Hz acpiprt0 at acpi0: bus 0 (PCI0) acpiprt1 at acpi0: bus -1 (PEG0) acpiprt2 at acpi0: bus -1 (PEG1) acpiprt3 at acpi0: bus -1 (PEG2) acpiprt4 at acpi0: bus 1 (RP01) acpiprt5 at acpi0: bus -1 (RP02) acpiprt6 at acpi0: bus 2 (RP03) acpiprt7 at acpi0: bus 3 (RP04) acpiprt8 at acpi0: bus -1 (RP05) acpiprt9 at acpi0: bus -1 (RP06) acpiprt10 at acpi0: bus -1 (RP07) acpiprt11 at acpi0: bus -1 (RP08) acpiec0 at acpi0 acpicpu0 at acpi0: C3(200@506 mwait.1@0x60), C2(200@117 mwait.1@0x32), C1(1000@1 mwait.1), PSS acpicpu1 at acpi0: C3(200@506 mwait.1@0x60), C2(200@117 mwait.1@0x32), C1(1000@1 mwait.1), PSS acpipwrres0 at acpi0: PG00, resource for PEG0 acpipwrres1 at acpi0: PG01, resource for PEG1 acpipwrres2 at acpi0: PG02, resource for PEG2 acpitz0 at acpi0: critical temperature is 120 degC acpipwrres3 at acpi0: FN00, resource for FAN0 acpipwrres4 at acpi0: FN01, resource for FAN1 acpipwrres5 at acpi0: FN02, resource for FAN2 acpipwrres6 at acpi0: FN03, resource for FAN3 acpipwrres7 at acpi0: FN04, resource for FAN4 acpitz1 at acpi0: critical temperature is 105 degC acpitz2 at acpi0: critical temperature is 105 degC "MSFT0001" at acpi0 not configured "SYN1212" at acpi0 not configured "INT3F0D" at acpi0 not configured "MSFT0101" at acpi0 not configured "PNPC000" at acpi0 not configured acpibtn0 at acpi0: PWRB acpibtn1 at acpi0: SLPB acpibtn2 at acpi0: LID0 acpiac0 at acpi0: AC unit online acpibat0 at acpi0: BAT0 model "BAT" serial 0001 type LION oem "Notebook" "PNP0C14" at acpi0 not configured "INT340E" at acpi0 not configured "PNP0C0B" at acpi0 not configured "PNP0C0B" at acpi0 not configured "PNP0C0B" at acpi0 not configured "PNP0C0B" at acpi0 not configured "PNP0C0B" at acpi0 not configured acpivideo0 at acpi0: GFX0 acpivout0 at acpivideo0: DD1F cpu0: Enhanced SpeedStep 1496 MHz: speeds: 1501, 1500, 1400, 1300, 1200, 1100, 1000, 900, 800, 700, 600, 500 MHz pci0 at mainbus0 bus 0 pchb0 at pci0 dev 0 function 0 "Intel Core 5G Host" rev 0x08 inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics" rev 0x08 drm0 at inteldrm0 inteldrm0: msi inteldrm0: 1366x768, 32bpp wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation) wsdisplay0: screen 1-5 added (std, vt100 emulation) azalia0 at pci0 dev 3 function 0 "Intel Core 5G HD Audio" rev 0x08: msi xhci0 at pci0 dev 20 function 0 "Intel 9 Series xHCI" rev 0x03: msi usb0 at xhci0: USB revision 3.0 uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00 addr 1 "Intel 9 Series MEI" rev 0x03 at pci0 dev 22 function 0 not configured azalia1 at pci0 dev 27 function 0 "Intel 9 Series HD Audio" rev 0x03: msi azalia1: codecs: Realtek ALC269 audio0 at azalia1 ppb0 at pci0 dev 28 function 0 "Intel 9 Series PCIE" rev 0xe3: msi pci1 at ppb0 bus 1 ppb1 at pci0 dev 28 function 2 "Intel 9 Series PCIE" rev 0xe3: msi pci2 at ppb1 bus 2 iwm0 at pci2 dev 0 function 0 "Intel Dual Band Wireless AC 7260" rev 0xc3, msi ppb2 at pci0 dev 28 function 3 "Intel 9 Series PCIE" rev 0xe3: msi pci3 at ppb2 bus 3 rtsx0 at pci3 dev 0 function 0 "Realtek RTL8411B Card Reader" rev 0x01: msi sdmmc0 at rtsx0: 4-bit re0 at pci3 dev 0 function 1 "Realtek 8168" rev 0x12: RTL8411B (0x5c80), msi, address 80:fa:5b:13:a4:89 rgephy0 at re0 phy 7: RTL8251 PHY, rev. 0 ehci0 at pci0 dev 29 function 0 "Intel 9 Series USB" rev 0x03: apic 2 int 23 usb1 at ehci0: USB revision 2.0 uhub1 at usb1 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1 pcib0 at pci0 dev 31 function 0 "Intel 9 Series LPC" rev 0x03 ahci0 at pci0 dev 31 function 2 "Intel 9 Series AHCI" rev 0x03: msi, AHCI 1.3 ahci0: port 0: 6.0Gb/s ahci0: port 1: 1.5Gb/s scsibus1 at ahci0: 32 targets sd0 at scsibus1 targ 0 lun 0: <ATA, CT120BX100SSD1, MU01> SCSI3 0/direct fixed naa.500a0751f0030605 sd0: 114473MB, 512 bytes/sector, 234441648 sectors, thin cd0 at scsibus1 targ 1 lun 0: <MATSHITA, DVD-RAM UJ8E2, 1.00> ATAPI 5/cdrom removable ichiic0 at pci0 dev 31 function 3 "Intel 9 Series SMBus" rev 0x03: apic 2 int 18 iic0 at ichiic0 spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-12800 SO-DIMM isa0 at pcib0 isadma0 at isa0 pckbc0 at isa0 port 0x60/5 irq 1 irq 12 irq 12 irq 12 irq 12 pckbd0 at pckbc0 (kbd slot) wskbd0 at pckbd0: console keyboard, using wsdisplay0 pckbc0: Active PS/2 Multiplexing, version 1.1 pms0 at pckbc0 (aux slot #1) wsmouse0 at pms0 mux 0 pcppi0 at isa0 port 0x61 spkr0 at pcppi0 vmm0 at mainbus0: VMX/EPT Unclaimed register detected before reading register 0x23a0 ugen0 at uhub0 port 5 "Intel product 0x07dc" rev 2.00/0.01 addr 2 uvideo0 at uhub0 port 6 configuration 1 interface 0 "Acer BisonCam, NB Pro" rev 2.00/6.08 addr 3 video0 at uvideo0 uhub2 at uhub1 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.03 addr 2 sdmmc0: can't enable card vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets root on sd0a (51efcee656494d34.a) swap on sd0b dump on sd0b iwm0: hw rev 0x140, fw ver 16.242414.0, address 48:51:b7:d6:8d:ff usbdevs: addr 1: xHCI root hub, Intel addr 2: product 0x07dc, Intel addr 3: BisonCam, NB Pro, Acer addr 1: EHCI root hub, Intel addr 2: Rate Matching Hub, Intel pcidump: Domain /dev/pci0: 0:0:0: Intel Core 5G Host 0:2:0: Intel HD Graphics 0:3:0: Intel Core 5G HD Audio 0:20:0: Intel 9 Series xHCI 0:22:0: Intel 9 Series MEI 0:27:0: Intel 9 Series HD Audio 0:28:0: Intel 9 Series PCIE 0:28:2: Intel 9 Series PCIE 0:28:3: Intel 9 Series PCIE 0:29:0: Intel 9 Series USB 0:31:0: Intel 9 Series LPC 0:31:2: Intel 9 Series AHCI 0:31:3: Intel 9 Series SMBus 2:0:0: Intel Dual Band Wireless AC 7260 3:0:0: Realtek RTL8411B Card Reader 3:0:1: Realtek 8168 Now comes the patch I used, which is simply the combination of the two previously cited patches with a small correction for it to compile when building /usr/src. (Correction is a macro added near lines 765,839 of sys/dev/ic/pckbc.c) Best regards, Alex C. Index: sys/arch/hppa/gsc/gsckbc.c =================================================================== RCS file: /cvs/src/sys/arch/hppa/gsc/gsckbc.c,v retrieving revision 1.19 diff -u -p -r1.19 gsckbc.c --- sys/arch/hppa/gsc/gsckbc.c 24 May 2015 10:57:47 -0000 1.19 +++ sys/arch/hppa/gsc/gsckbc.c 30 Nov 2017 16:03:11 -0000 @@ -459,7 +459,7 @@ pckbc_poll_data1(iot, ioh, ioh_c, slot, bus_space_tag_t iot; bus_space_handle_t ioh, ioh_c; pckbc_slot_t slot; - int checkaux; /* ignored on hppa */ + struct pckbc_internal *t; /* ignored on hppa */ { int i; u_char stat; @@ -558,7 +558,7 @@ pckbc_flush(self, slot) { struct pckbc_internal *t = self; - pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_d, slot, 0); + pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_d, slot, t); } int @@ -570,7 +570,7 @@ pckbc_poll_data(self, slot) struct pckbc_slotdata *q = t->t_slotdata[slot]; int c; - c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_d, slot, 0); + c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_d, slot, t); if (c != -1 && q && CMD_IN_QUEUE(q)) { /* we jumped into a running command - try to deliver the response */ @@ -645,7 +645,7 @@ pckbc_poll_cmd1(t, slot, cmd) return; } for (i = 10; i; i--) { /* 1s ??? */ - c = pckbc_poll_data1(iot, ioh, ioh, slot, 0); + c = pckbc_poll_data1(iot, ioh, ioh, slot, t); if (c != -1) break; } @@ -686,7 +686,7 @@ pckbc_poll_cmd1(t, slot, cmd) else i = 10; /* 1s ??? */ while (i--) { - c = pckbc_poll_data1(iot, ioh, ioh, slot, 0); + c = pckbc_poll_data1(iot, ioh, ioh, slot, t); if (c != -1) break; } Index: sys/dev/ic/i8042reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/i8042reg.h,v retrieving revision 1.9 diff -u -p -r1.9 i8042reg.h --- sys/dev/ic/i8042reg.h 5 May 2015 16:27:20 -0000 1.9 +++ sys/dev/ic/i8042reg.h 30 Nov 2017 16:06:19 -0000 @@ -49,3 +49,18 @@ #define KCID_KBD1 0xAB #define KCID_KBD2 0x83 #define KCID_MOUSE 0x00 + +/* + * Defines for Active PS/2 Multiplexing + */ + +#define KBC_APM_ENB1 0xf0 +#define KBC_APM_ENB2 0x56 +#define KBC_APM_ENB3 0xa4 + +#define KBC_APM_DIS1 0xf0 +#define KBC_APM_DIS2 0x56 +#define KBC_APM_DIS3 0xa5 + +#define KBC_APM_PREFIX(p) (0x90 | (p)) + Index: sys/dev/ic/pckbc.c =================================================================== RCS file: /cvs/src/sys/dev/ic/pckbc.c,v retrieving revision 1.50 diff -u -p -r1.50 pckbc.c --- sys/dev/ic/pckbc.c 11 Mar 2017 11:55:03 -0000 1.50 +++ sys/dev/ic/pckbc.c 30 Nov 2017 16:06:33 -0000 @@ -104,8 +104,20 @@ void pckbc_poll(void *); int pckbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char); void pckbc_start(struct pckbc_internal *, pckbc_slot_t); int pckbcintr_internal(struct pckbc_internal *, struct pckbc_softc *); +int pckbc_enable_apm(struct pckbc_internal *); +int pckbc_disable_apm(struct pckbc_internal *); -const char *pckbc_slot_names[] = { "kbd", "aux" }; +const char *pckbc_slot_names[] = { + "kbd slot", +#ifdef PCKBC_APM + "aux slot #0", + "aux slot #1", + "aux slot #2", + "aux slot #3", +#else + "aux slot" +#endif +}; #define KBC_DEVCMD_ACK 0xfa #define KBC_DEVCMD_RESEND 0xfe @@ -136,32 +148,58 @@ pckbc_send_cmd(bus_space_tag_t iot, bus_ return (1); } +/* + * NOTE: Active PS/2 Multiplexing behaviour is only checked if t != NULL. + * This behaviour is intentional. + */ int pckbc_poll_data1(bus_space_tag_t iot, bus_space_handle_t ioh_d, - bus_space_handle_t ioh_c, pckbc_slot_t slot, int checkaux) + bus_space_handle_t ioh_c, pckbc_slot_t slot, struct pckbc_internal *t) { int i; + int active; u_char stat; /* polls for ~100ms */ for (i = 100; i; i--, delay(1000)) { stat = bus_space_read_1(iot, ioh_c, 0); + /* XXX no error bit handling */ if (stat & KBS_DIB) { register u_char c; KBD_DELAY; CPU_BUSY_CYCLE(); c = bus_space_read_1(iot, ioh_d, 0); - if (checkaux && (stat & KBS_AUXDATA)) { - if (slot != PCKBC_AUX_SLOT) { - DPRINTF("lost aux 0x%x\n", c); - continue; - } - } else { - if (slot == PCKBC_AUX_SLOT) { - DPRINTF("lost kbd 0x%x\n", c); +#ifdef PCKBC_APM + if (t && t->t_apmver >= 0) { + if (stat & KBS_AUXDATA) + active = PCKBC_AUX_SLOT + (stat >> 6); + else + active = PCKBC_KBD_SLOT; + } else +#endif + active = stat & KBS_AUXDATA ? + PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; + +#ifdef PCKBC_APM + if (active != PCKBC_KBD_SLOT && + t && t->t_apmver >= 0 && (stat & KBS_WARM)) { + if (c >= 0xfd) { + /* genuine error */ + /* XXX handle hot removal? */ continue; } + DPRINTF("pckbc apm mode reverted?\n"); + /* XXX schedule a switch as soon as possible */ +} +#endif + if (slot != active) { + if ((t && t->t_haveaux) || + slot != PCKBC_KBD_SLOT || + active == PCKBC_KBD_SLOT) + DPRINTF("lost data on slot%d 0x%x\n", + active, c); + continue; } return (c); } @@ -182,8 +220,7 @@ pckbc_get8042cmd(struct pckbc_internal * if (!pckbc_send_cmd(iot, ioh_c, K_RDCMDBYTE)) return (0); - data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, - t->t_haveaux); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, t); if (data == -1) return (0); t->t_cmdbyte = data; @@ -215,7 +252,15 @@ pckbc_send_devcmd(struct pckbc_internal bus_space_handle_t ioh_d = t->t_ioh_d; bus_space_handle_t ioh_c = t->t_ioh_c; - if (slot == PCKBC_AUX_SLOT) { + if (slot >= PCKBC_AUX_SLOT) { +#ifdef PCKBC_APM + /* send specific routing prefix if multiplexing */ + if (t->t_apmver >= 0) { + if (pckbc_send_cmd(iot, ioh_c, + KBC_APM_PREFIX(slot - PCKBC_AUX_SLOT)) == 0) + return (0); + } else +#endif if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) return (0); } @@ -311,7 +356,7 @@ pckbc_attach(struct pckbc_softc *sc, int } /* flush */ - (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); /* set initial cmd byte */ if (!pckbc_put8042cmd(t)) { @@ -335,7 +380,7 @@ pckbc_attach(struct pckbc_softc *sc, int */ if (!pckbc_send_cmd(iot, ioh_c, KBC_KBDTEST)) return; - res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); /* * Normally, we should get a "0" here. @@ -375,7 +420,11 @@ pckbc_attach(struct pckbc_softc *sc, int goto nomouse; } bus_space_write_1(iot, ioh_d, 0, 0x5a); /* a random value */ - res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, 1); + res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + +#if defined(__amd64__) + t->t_flags |= PCKBC_NEED_AUXWRITE; +#endif if (ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) { /* @@ -391,7 +440,7 @@ pckbc_attach(struct pckbc_softc *sc, int goto nomouse; bus_space_write_1(iot, ioh_d, 0, 0x5a); res = pckbc_poll_data1(iot, ioh_d, ioh_c, - PCKBC_AUX_SLOT, 1); + PCKBC_AUX_SLOT, NULL); DPRINTF("kbc: aux echo: %x\n", res); } } @@ -406,8 +455,21 @@ pckbc_attach(struct pckbc_softc *sc, int */ DPRINTF("kbc: aux echo: %x\n", res); t->t_haveaux = 1; - if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT, 0)) + +#ifdef PCKBC_APM + t->t_apmver = -1; + t->t_apmver = pckbc_enable_apm(t); + if (t->t_apmver >= 0) { + printf("%s: Active PS/2 Multiplexing, version %d.%d\n", + sc->sc_dv.dv_xname, t->t_apmver >> 4, + t->t_apmver & 0x0f); cmdbits |= KC8_MENABLE; + for (res = PCKBC_AUX_SLOT; res < PCKBC_NSLOTS; res++) + pckbc_attach_slot(sc, res, 0); + } else +#endif + if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT, 0)) + cmdbits |= KC8_MENABLE; } #ifdef PCKBCDEBUG else @@ -438,7 +500,7 @@ pckbcprint(void *aux, const char *pnp) struct pckbc_attach_args *pa = aux; if (!pnp) - printf(" (%s slot)", pckbc_slot_names[pa->pa_slot]); + printf(" (%s)", pckbc_slot_names[pa->pa_slot]); return (QUIET); } @@ -484,8 +546,7 @@ pckbc_flush(pckbc_tag_t self, pckbc_slot { struct pckbc_internal *t = self; - (void) pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, - slot, t->t_haveaux); + (void) pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, slot, t); } int @@ -495,8 +556,7 @@ pckbc_poll_data(pckbc_tag_t self, pckbc_ struct pckbc_slotdata *q = t->t_slotdata[slot]; int c; - c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, - slot, t->t_haveaux); + c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, slot, t); if (c != -1 && q && CMD_IN_QUEUE(q)) { /* we jumped into a running command - try to deliver the response */ @@ -545,13 +605,28 @@ void pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on) { struct pckbc_internal *t = (struct pckbc_internal *)self; - struct pckbc_portcmd *cmd; + const struct pckbc_portcmd *cmd; + int rc; +#ifdef PCKBC_APM + cmd = &pckbc_portcmd[slot >= PCKBC_AUX_SLOT ? PCKBC_AUX_SLOT : slot]; +#else cmd = &pckbc_portcmd[slot]; +#endif - if (!pckbc_send_cmd(t->t_iot, t->t_ioh_c, - on ? cmd->cmd_en : cmd->cmd_dis)) - printf("pckbc_slot_enable(%d) failed\n", on); +#ifdef PCKBC_APM + /* send specific routing prefix if multiplexing */ + if (t->t_apmver >= 0 && slot >= PCKBC_AUX_SLOT) { + rc = pckbc_send_cmd(t->t_iot, t->t_ioh_c, + KBC_APM_PREFIX(slot - PCKBC_AUX_SLOT)); + } else +#endif + rc = 1; + if (rc != 0) + rc = pckbc_send_cmd(t->t_iot, t->t_ioh_c, + on ? cmd->cmd_en : cmd->cmd_dis); + if (rc == 0) + printf("pckbc_slot_enable(%d,%d) failed\n", slot, on); if (slot == PCKBC_KBD_SLOT) { if (on) @@ -605,8 +680,7 @@ pckbc_poll_cmd1(struct pckbc_internal *t return; } for (i = 10; i; i--) { /* 1s ??? */ - c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, - t->t_haveaux); + c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, t); if (c != -1) break; } @@ -645,8 +719,7 @@ pckbc_poll_cmd1(struct pckbc_internal *t else i = 10; /* 1s ??? */ while (i--) { - c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, - t->t_haveaux); + c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, t); if (c != -1) break; } @@ -709,10 +782,11 @@ pckbc_cleanqueue(struct pckbc_slotdata * void pckbc_cleanqueues(struct pckbc_internal *t) { - if (t->t_slotdata[PCKBC_KBD_SLOT]) - pckbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]); - if (t->t_slotdata[PCKBC_AUX_SLOT]) - pckbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]); + uint slot; + + for (slot = 0; slot < PCKBC_NSLOTS; slot++) + if (t->t_slotdata[slot]) + pckbc_cleanqueue(t->t_slotdata[slot]); } /* @@ -765,11 +839,15 @@ pckbc_reset(struct pckbc_softc *sc) bus_space_tag_t iot = t->t_iot; bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c; - pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); /* KBC selftest */ if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0) return; - pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); +#ifdef PCKBC_APM + if (t->t_apmver >= 0) + pckbc_enable_apm(t); +#endif (void)pckbc_put8042cmd(t); pckbcintr_internal(t->t_sc->id, t->t_sc); } @@ -995,8 +1073,16 @@ pckbcintr_internal(struct pckbc_internal served = 1; - slot = (t->t_haveaux && (stat & KBS_AUXDATA)) ? - PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; +#ifdef PCKBC_APM + if (t->t_apmver >= 0) { /* implies t->t_haveaux != 0 */ + if (stat & KBS_AUXDATA) + slot = PCKBC_AUX_SLOT + (stat >> 6); + else + slot = PCKBC_KBD_SLOT; + } else +#endif + slot = (t->t_haveaux && (stat & KBS_AUXDATA)) ? + PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; q = t->t_slotdata[slot]; if (!q) { @@ -1033,6 +1119,89 @@ pckbcintr_internal(struct pckbc_internal return (served); } +#ifdef PCKBC_APM + +/* + * Disable Active PS/2 Multiplexing. + * Returns nonzero if error. + */ +int +pckbc_disable_apm(struct pckbc_internal *t) +{ + bus_space_tag_t iot = t->t_iot; + bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c; + int data; + + /* + * Send the three bytes of the disable sequence + */ + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_DIS1); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data != KBC_APM_DIS1) + return -1; + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_DIS2); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data != KBC_APM_DIS2) + return -1; + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_DIS3); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data != t->t_apmver) + return -1; + + return 0; +} + +/* + * Enable Active PS/2 Multiplexing. + * Returns -1 if unavailable or version supported by the controller. + */ +int +pckbc_enable_apm(struct pckbc_internal *t) +{ + bus_space_tag_t iot = t->t_iot; + bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c; + int data; + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_ENB1); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data != KBC_APM_ENB1) + return -1; + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_ENB2); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data != KBC_APM_ENB2) + return -1; + + if (pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO) == 0 || + pckbc_wait_output(iot, ioh_c) == 0) + return -1; + bus_space_write_1(iot, ioh_d, 0, KBC_APM_ENB3); + data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, NULL); + if (data < 0 || data == KBC_APM_ENB3) + return -1; + + return data; +} +#endif + int pckbc_cnattach(bus_space_tag_t iot, bus_addr_t addr, bus_size_t cmd_offset, int flags) @@ -1056,7 +1225,7 @@ pckbc_cnattach(bus_space_tag_t iot, bus_ timeout_set(&pckbc_consdata.t_poll, pckbc_poll, &pckbc_consdata); /* flush */ - (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); /* selftest? */ Index: sys/dev/ic/pckbcvar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/pckbcvar.h,v retrieving revision 1.16 diff -u -p -r1.16 pckbcvar.h --- sys/dev/ic/pckbcvar.h 11 Mar 2017 11:55:03 -0000 1.16 +++ sys/dev/ic/pckbcvar.h 30 Nov 2017 16:06:33 -0000 @@ -32,6 +32,14 @@ #include <sys/timeout.h> +/* + * Only compile Active PS/2 Multiplexing support on systems where it might + * be found. + */ +#if (defined(__i386__) || defined(__amd64__)) && !defined(SMALL_KERNEL) +#define PCKBC_APM +#endif + #define PCKBCCF_SLOT 0 #define PCKBCCF_SLOT_DEFAULT -1 @@ -39,7 +47,11 @@ typedef void *pckbc_tag_t; typedef int pckbc_slot_t; #define PCKBC_KBD_SLOT 0 #define PCKBC_AUX_SLOT 1 +#ifdef PCKBC_APM +#define PCKBC_NSLOTS 5 /* 1 KBD + 4 AUX */ +#else #define PCKBC_NSLOTS 2 +#endif /* * external representation (pckbc_tag_t), @@ -55,6 +67,9 @@ struct pckbc_internal { #define PCKBC_CANT_TRANSLATE 0x0001 /* can't translate to XT scancodes */ #define PCKBC_NEED_AUXWRITE 0x0002 /* need auxwrite command to find aux */ int t_haveaux; /* controller has an aux port */ +#ifdef PCKBC_APM + int t_apmver; /* Active PS/2 Multiplexing version */ +#endif struct pckbc_slotdata *t_slotdata[PCKBC_NSLOTS]; @@ -97,8 +112,8 @@ int pckbc_enqueue_cmd(pckbc_tag_t, pckbc int, int, u_char *); int pckbc_send_cmd(bus_space_tag_t, bus_space_handle_t, u_char); int pckbc_poll_data(pckbc_tag_t, pckbc_slot_t); -int pckbc_poll_data1(bus_space_tag_t, bus_space_handle_t, - bus_space_handle_t, pckbc_slot_t, int); +int pckbc_poll_data1(bus_space_tag_t, bus_space_handle_t, bus_space_handle_t, + pckbc_slot_t, struct pckbc_internal *); void pckbc_set_poll(pckbc_tag_t, pckbc_slot_t, int); int pckbc_xt_translation(pckbc_tag_t); void pckbc_slot_enable(pckbc_tag_t, pckbc_slot_t, int); Index: sys/dev/isa/pckbc_isa.c =================================================================== RCS file: /cvs/src/sys/dev/isa/pckbc_isa.c,v retrieving revision 1.19 diff -u -p -r1.19 pckbc_isa.c --- sys/dev/isa/pckbc_isa.c 18 Aug 2015 06:54:00 -0000 1.19 +++ sys/dev/isa/pckbc_isa.c 30 Nov 2017 16:07:01 -0000 @@ -55,6 +55,9 @@ pckbc_isa_match(struct device *parent, v bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh_d, ioh_c; int res; +#ifdef PCKBC_APM + uint slot; +#endif /* If values are hardwired to something that they can't be, punt. */ if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_KBD) || @@ -70,12 +73,12 @@ pckbc_isa_match(struct device *parent, v goto fail; /* flush KBC */ - (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); /* KBC selftest */ if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0) goto fail2; - res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); + res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, NULL); if (res != 0x55) { printf("kbc selftest: %x\n", res); goto fail2; @@ -89,7 +92,12 @@ pckbc_isa_match(struct device *parent, v ia->ia_msize = 0x0; ia->ipa_nirq = PCKBC_NSLOTS; ia->ipa_irq[PCKBC_KBD_SLOT].num = 1; +#ifdef PCKBC_APM + for (slot = PCKBC_AUX_SLOT; slot < PCKBC_NSLOTS; slot++) + ia->ipa_irq[slot].num = 12; +#else ia->ipa_irq[PCKBC_AUX_SLOT].num = 12; +#endif return (1); Index: sys/dev/pckbc/pms.c =================================================================== RCS file: /cvs/src/sys/dev/pckbc/pms.c,v retrieving revision 1.80 diff -u -p -r1.80 pms.c --- sys/dev/pckbc/pms.c 26 Aug 2017 18:34:04 -0000 1.80 +++ sys/dev/pckbc/pms.c 30 Nov 2017 16:12:01 -0000 @@ -150,6 +150,7 @@ struct pms_softc { /* driver status inf struct device sc_dev; pckbc_tag_t sc_kbctag; + int sc_slot; int sc_state; #define PMS_STATE_DISABLED 0 @@ -414,10 +415,10 @@ int pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen) { if (sc->poll) { - return pckbc_poll_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT, + return pckbc_poll_cmd(sc->sc_kbctag, sc->sc_slot, cmd, len, resplen, resp, 1); } else { - return pckbc_enqueue_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT, + return pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_slot, cmd, len, resplen, 1, resp); } } @@ -638,7 +639,7 @@ pmsprobe(struct device *parent, void *ma u_char cmd[1], resp[2]; int res; - if (pa->pa_slot != PCKBC_AUX_SLOT) + if (pa->pa_slot < PCKBC_AUX_SLOT) return (0); /* Flush any garbage. */ @@ -666,8 +667,9 @@ pmsattach(struct device *parent, struct struct wsmousedev_attach_args a; sc->sc_kbctag = pa->pa_tag; + sc->sc_slot = pa->pa_slot; - pckbc_set_inputhandler(sc->sc_kbctag, PCKBC_AUX_SLOT, + pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_slot, pmsinput, sc, DEVNAME(sc)); printf("\n"); @@ -744,10 +746,10 @@ pms_change_state(struct pms_softc *sc, i case PMS_STATE_ENABLED: sc->inputstate = 0; - pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 1); + pckbc_slot_enable(sc->sc_kbctag, sc->sc_slot, 1); if (sc->poll) - pckbc_flush(sc->sc_kbctag, PCKBC_AUX_SLOT); + pckbc_flush(sc->sc_kbctag, sc->sc_slot); pms_reset(sc); if (sc->protocol->enable != NULL && @@ -763,7 +765,7 @@ pms_change_state(struct pms_softc *sc, i if (sc->protocol->disable) sc->protocol->disable(sc); - pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 0); + pckbc_slot_enable(sc->sc_kbctag, sc->sc_slot, 0); break; }
