August 5, 2004

### NAME

pckbport, pckbport_attach, pckbport_attach_slot, pckbport_cnattach, pckbportintr, pckbport_set_inputhandler, pckbport_flush, pckbport_poll_cmd, pckbport_enqueue_cmd, pckbport_poll_data, pckbport_set_poll, pckbport_xt_translation, pckbport_slot_enable - PC keyboard port interface

### SYNOPSIS

```pckbport_tag_t` pckbport_attach(```void *``, struct pckbport_accessops const *`)
```struct device *` pckbport_attach_slot(```struct device *``, pckbport_tag_t``, pckbport_slot_t`)
```int` pckbport_cnattach(```void *``, struct pckbport_accessops const *``, pckbport_slot_t`)
```void` pckbportintr(```pckbport_tag_t``, pckbport_slot_t``, int`)
```void` pckbport_set_inputhandler(```pckbport_tag_t``, pckbport_slot_t``, pckbport_inputfcn``, void *``, char *`)
```void` pckbport_flush(```pckbport_tag_t``, pckbport_slot_t`)
```int` pckbport_poll_cmd(```pckbport_tag_t``, pckbport_slot_t``, u_char *``, int``, int``, u_char *``, int`)
```int` pckbport_enqueue_cmd(```pckbport_tag_t``, pckbport_slot_t``, u_char *``, int``, int``, int``, u_char *`)
```int` pckbport_poll_data(```pckbport_tag_t``, pckbport_slot_t`)
```void` pckbport_set_poll(```pckbport_tag_t``, pckbport_slot_t``, int`)
```int` pckbport_xt_translation(```pckbport_tag_t``, pckbport_slot_t``, int`)
```void` pckbport_slot_enable(```pckbport_tag_t``, pckbport_slot_t``, int`)

### DESCRIPTION

The machine-independent pckbport subsystem provides an interface layer corresponding to the serial keyboard and mouse interface used on the IBM PS/2 and many other machines. It interfaces a controller driver such as pckbc(4) to device drivers such as pckbd(4) and pms(4).

A single controller can have up to two ports (known as ``slots''), and these are identified by values of type ```pckbport_slot_t`. The values ```PCKBPORT_KBD_SLOT` and ```PCKBPORT_AUX_SLOT` should be used for keyboard and mouse ports respectively. Each controller is identified by an opaque value of type ```pckbport_tag_t`.

#### Controller interface

A PC keyboard controller registers itself by calling pckbport_attach(```cookie``, ops`), with ```ops` being a pointer to a ```struct` `pckbport_accessops` containing pointers to functions for driving the controller, which will all be called with ```cookie` as their first argument. pckbport_attach(``) returns the ```pckbport_tag_t` assigned to the controller. The controller is then expected to call pckbport_attach_slot(``) for each slot with which it is equipped, passing the ```struct device *` corresponding to the controller. This function returns a pointer to the child device attached to the slot, or ```NULL` if no such device was attached.

The elements of ```struct pckbport_accessops` each take as their first two arguments the ```cookie` passed to pckbport_attach(``) and the slot in question. The elements are:

```int`(*t_xt_translation)(```, void *cookie``, pckbport_slot_t slot``, int on`)
  If ```on` is non-zero, enable, otherwise disable, AT-to-XT keycode translation on the slot specified. Returns 1 on success, 0 on failure (or if the controller does not support such translation).

```int`(*t_send_devcmd)(```, void *cookie``, pckbport_slot_t slot``, u_char byte`)
  Send a single ```byte` to the device without waiting for completion. Returns 1 on success, 0 on failure.

```int`(*t_poll_data1)(```, void *cookie``, pckbport_slot_t slot`)
  Wait for and return one byte of data from the device, without using interrupts. This function will only be called after (*t_set_poll)(``) has been used to put the slot in polling mode. If no data are forthcoming from the device after about 100ms, return -1.

```void`(*t_slot_enable)(```, void *cookie``, pckbport_slot_t slot``, int on`)
  If ```on` is non-zero, enable, otherwise disable, the slot. If a slot is disabled, it can be powered down, and is not expected to generate any interrupts. When first attached, ports should be disabled.

```void`(*t_intr_establish)(```, void *cookie``, pckbport_slot_t slot`)
  Set up an interrupt handler for the slot. Called when a device gets attached to it.

```void`(*t_set_poll)(```, void *cookie``, pckbport_slot_t slot``, int on`)
  If ```on` is non-zero, enable, otherwise disable, polling mode on the slot. In polling mode, data received from the device are provided to (*t_poll_data1)(``) and not passed to pckbportintr(``), whether or not interrupts are enabled. In non-polling mode, data from the device are expected to cause interrupts. The controller interrupt handler should call pckbportintr(```tag``, slot``, byte`) once for each byte received from the device. When first attached, a port should be in non-polling mode.

#### Device interface

Devices that attach to pckbport controllers do so using the normal autoconf(9) mechanism. Their (*ca_match)(``) and (*ca_attach)(``) functions get passed a ```struct pckbport_attach_args` which contains the controller and slot number where the device was found. Device drivers can use the following functions to communicate with the controller. Each takes ```tag` and ```slot` arguments to specify the slot to be acted on.

pckbport_set_inputhandler(```tag``, slot``, fn``, arg``, name`)
  Arrange for ```fn` to be called with argument ```arg` whenever an unsolicited byte is received from the slot. The function will be called at spltty(``).

pckbport_flush(```tag``, slot`)
  Ensure that there is no pending input from the slot.

pckbport_poll_cmd(```tag``, slot``, cmd``, len``, responselen``, respbuf``, slow`)
  Issue a complete device command, ```cmd`, ```len` bytes long, expecting a response ```responselen` bytes long, which will be placed in ```respbuf`. If ```slow` is true, the command is expected to take over a second to execute. pckbport_poll_cmd(``) handles getting an acknowledgement from the device and retrying the command if necessary. Returns 0 on success, and an error value on failure. This function should only be called during autoconfiguration or when the slot has been placed into polling mode by pckbport_set_poll(``).

pckbport_enqueue_cmd(```tag``, slot``, cmd``, len``, responselen``, sync``, respbuf`)
  Issue a complete device command, ```cmd`, ```len` bytes long, expecting a response ```responselen` bytes long, which will be places in ```respbuf`. If ```sync` is true, pckbport_enqueue_cmd(``) waits for the command to complete before returning, otherwise it returns immediately. It is not safe to set ```sync` when calling from an interrupt context. The pckbport layer handles getting an acknowledgement from the device and retrying the command if necessary. Returns 0 on success, and an error value on failure.

pckbport_poll_data(```tag``, slot`)
  Low-level command to poll for a single byte of data from the device, but ignoring bytes that are part of the response to a command issued through pckbport_enqueue_command(``).

pckbport_set_poll(```tag``, slot``, on`)
  If ```on` is true, enable polling on the slot, otherwise disable it. In polling mode, pckbport_poll_cmd(``) can be used to issue commands and pckbport_poll_data(``) to read unsolicited data, without enabling interrupts. In non-polling mode, commands should be issued using pckbport_enqueue_cmd(``), unsolicited data are handled by the input function, and disabling interrupts will suspend pckbport operation.

pckbport_xt_translation(```tag``, slot``, on`)
  Passthrough of (*t_xt_translation)(``) (see above).

pckbport_slot(```enable``, tag``, slot``, on`)
  Passthrough of (*t_slot_enable)(``) (see above).

#### Console interface

On systems that can attach consoles through , the controller's console attachment function (called very early in autoconfiguration) calls pckbport_cnattach(```cookie``, ops``, slot`). The first two arguments are the same as for pckbport_attach(``), while the third indicates which slot the console keyboard is attached to. pckbport_cnattach(``) either calls pckbd_cnattach(``), if it is available, or pckbport_machdep_cnattach(``). The latter allows machine-dependent keyboard drivers to attach themselves, but it is only called if a device with the `pckbport_machdep_cnattach' attribute is configured into the system. pckbport_cnattach(``) returns 0 on success and an error value on failure. pckbport_machdep_cnattach(``) is expected to do the same.

### CODE REFERENCES

The pckbport code, and the pckbd(4) and pms(4) device drivers are in ```sys/dev/pckbport`.

### SEE ALSO

pckbc(4), pckbd(4), pms(4), autoconf(9), spl(9)

### HISTORY

The pckbport system appeared in NetBSD2.0. Before that, pckbd(4) and pms(4) attached directly to pckbc(4) without any sensible way of using a different controller.