cros_ec_python.ioports.freebsdportio

This file provides a way to interact with the /dev/io device file on FreeBSD.

  1"""
  2This file provides a way to interact with the `/dev/io` device file on
  3FreeBSD.
  4"""
  5
  6from typing import Final, IO
  7from fcntl import ioctl
  8import struct
  9
 10from .baseportio import PortIOClass
 11
 12IODEV_PIO_READ: Final = 0
 13IODEV_PIO_WRITE: Final = 1
 14
 15
 16def _IOC(inout: int, group: str, num: int, length: int):
 17    """
 18    Create an ioctl command number.
 19    Based on the FreeBSD kernels sys/sys/ioccom.h.
 20    """
 21    IOCPARM_SHIFT: Final = 13  # number of bits for ioctl size
 22    IOCPARM_MASK: Final = ((1 << IOCPARM_SHIFT) - 1)  # parameter length mask
 23
 24    return (((inout) | (((length) & IOCPARM_MASK) << 16) | (ord(group) << 8) | (num)))
 25
 26
 27def _IOWR(group: str, num: int, length: int):
 28    """
 29    Create an ioctl command number for read/write commands.
 30    Based on the FreeBSD kernels sys/sys/ioccom.h.
 31    """
 32    IOC_VOID: Final = 0x20000000  # no parameters
 33    IOC_OUT: Final = 0x40000000  # copy out parameters
 34    IOC_IN: Final = 0x80000000  # copy in parameters
 35    IOC_INOUT: Final = (IOC_IN|IOC_OUT)  # copy parameters in and out
 36    IOC_DIRMASK: Final = (IOC_VOID|IOC_OUT|IOC_IN)  # mask for IN/OUT/VOID
 37    return _IOC(IOC_INOUT, group, num, length)
 38
 39
 40def IODEV_PIO():
 41    """
 42    Create an ioctl command number for the `/dev/io` device file.
 43    """
 44
 45    # struct iodev_pio_req {
 46    # 	u_int access;
 47    # 	u_int port;
 48    # 	u_int width;
 49    # 	u_int val;
 50    # };
 51
 52    length = struct.calcsize("IIII")
 53    return _IOWR("I", 0, length)
 54
 55
 56class FreeBsdPortIO(PortIOClass):
 57    """
 58    A class to interact with the `/dev/io` device file on FreeBSD.
 59    """
 60
 61    _dev_io: IO | None = None
 62
 63    def __init__(self):
 64        """
 65        Initialize the `/dev/port` device file.
 66        """
 67        self._dev_io = open("/dev/io", "wb", buffering=0)
 68
 69    def __del__(self):
 70        """
 71        Close the `/dev/port` device file.
 72        """
 73        if self._dev_io:
 74            self._dev_io.close()
 75
 76    def out_bytes(self, data: bytes, port: int) -> None:
 77        """
 78        Write data to the specified port.
 79        :param data: Data to write.
 80        :param port: Port to write to.
 81        """
 82        iodev_pio_req = struct.pack(
 83            "IIII", IODEV_PIO_WRITE, port, len(data), int.from_bytes(data, "little")
 84        )
 85        ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)
 86
 87    def outb(self, data: int, port: int) -> None:
 88        """
 89        Write a byte (8 bit) to the specified port.
 90        :param data: Byte to write.
 91        :param port: Port to write to.
 92        """
 93        self.out_bytes(data.to_bytes(1, "little"), port)
 94
 95    def outw(self, data: int, port: int) -> None:
 96        """
 97        Write a word (16 bit) to the specified port.
 98        :param data: Word to write.
 99        :param port: Port to write to.
100        """
101        self.out_bytes(data.to_bytes(2, "little"), port)
102
103    def outl(self, data: int, port: int) -> None:
104        """
105        Write a long (32 bit) to the specified port.
106        :param data: Long to write.
107        :param port: Port to write to.
108        """
109        self.out_bytes(data.to_bytes(4, "little"), port)
110
111    def in_bytes(self, port: int, num: int) -> bytes:
112        """
113        Read data from the specified port.
114        :param port: Port to read from.
115        :param num: Number of bytes to read (1 - 4).
116        :return: Data read.
117        """
118        iodev_pio_req = struct.pack("IIII", IODEV_PIO_READ, port, num, 0)
119        return ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)[struct.calcsize("III") :]
120
121    def inb(self, port: int) -> int:
122        """
123        Read a byte (8 bit) from the specified port.
124        :param port: Port to read from.
125        :return: Byte read.
126        """
127        return int.from_bytes(self.in_bytes(port, 1), "little")
128
129    def inw(self, port: int) -> int:
130        """
131        Read a word (16 bit) from the specified port.
132        :param port: Port to read from.
133        :return: Word read.
134        """
135        return int.from_bytes(self.in_bytes(port, 2), "little")
136
137    def inl(self, port: int) -> int:
138        """
139        Read a long (32 bit) from the specified port.
140        :param port: Port to read from.
141        :return: Long read.
142        """
143        return int.from_bytes(self.in_bytes(port, 4), "little")
144
145    def ioperm(self, port: int, num: int, turn_on: bool) -> None:
146        """
147        `ioperm` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
148        """
149        pass
150
151    def iopl(self, level: int) -> None:
152        """
153        `iopl` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
154        """
155        pass
IODEV_PIO_READ: Final = 0
IODEV_PIO_WRITE: Final = 1
def IODEV_PIO():
41def IODEV_PIO():
42    """
43    Create an ioctl command number for the `/dev/io` device file.
44    """
45
46    # struct iodev_pio_req {
47    # 	u_int access;
48    # 	u_int port;
49    # 	u_int width;
50    # 	u_int val;
51    # };
52
53    length = struct.calcsize("IIII")
54    return _IOWR("I", 0, length)

Create an ioctl command number for the /dev/io device file.

class FreeBsdPortIO(cros_ec_python.ioports.baseportio.PortIOClass):
 57class FreeBsdPortIO(PortIOClass):
 58    """
 59    A class to interact with the `/dev/io` device file on FreeBSD.
 60    """
 61
 62    _dev_io: IO | None = None
 63
 64    def __init__(self):
 65        """
 66        Initialize the `/dev/port` device file.
 67        """
 68        self._dev_io = open("/dev/io", "wb", buffering=0)
 69
 70    def __del__(self):
 71        """
 72        Close the `/dev/port` device file.
 73        """
 74        if self._dev_io:
 75            self._dev_io.close()
 76
 77    def out_bytes(self, data: bytes, port: int) -> None:
 78        """
 79        Write data to the specified port.
 80        :param data: Data to write.
 81        :param port: Port to write to.
 82        """
 83        iodev_pio_req = struct.pack(
 84            "IIII", IODEV_PIO_WRITE, port, len(data), int.from_bytes(data, "little")
 85        )
 86        ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)
 87
 88    def outb(self, data: int, port: int) -> None:
 89        """
 90        Write a byte (8 bit) to the specified port.
 91        :param data: Byte to write.
 92        :param port: Port to write to.
 93        """
 94        self.out_bytes(data.to_bytes(1, "little"), port)
 95
 96    def outw(self, data: int, port: int) -> None:
 97        """
 98        Write a word (16 bit) to the specified port.
 99        :param data: Word to write.
100        :param port: Port to write to.
101        """
102        self.out_bytes(data.to_bytes(2, "little"), port)
103
104    def outl(self, data: int, port: int) -> None:
105        """
106        Write a long (32 bit) to the specified port.
107        :param data: Long to write.
108        :param port: Port to write to.
109        """
110        self.out_bytes(data.to_bytes(4, "little"), port)
111
112    def in_bytes(self, port: int, num: int) -> bytes:
113        """
114        Read data from the specified port.
115        :param port: Port to read from.
116        :param num: Number of bytes to read (1 - 4).
117        :return: Data read.
118        """
119        iodev_pio_req = struct.pack("IIII", IODEV_PIO_READ, port, num, 0)
120        return ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)[struct.calcsize("III") :]
121
122    def inb(self, port: int) -> int:
123        """
124        Read a byte (8 bit) from the specified port.
125        :param port: Port to read from.
126        :return: Byte read.
127        """
128        return int.from_bytes(self.in_bytes(port, 1), "little")
129
130    def inw(self, port: int) -> int:
131        """
132        Read a word (16 bit) from the specified port.
133        :param port: Port to read from.
134        :return: Word read.
135        """
136        return int.from_bytes(self.in_bytes(port, 2), "little")
137
138    def inl(self, port: int) -> int:
139        """
140        Read a long (32 bit) from the specified port.
141        :param port: Port to read from.
142        :return: Long read.
143        """
144        return int.from_bytes(self.in_bytes(port, 4), "little")
145
146    def ioperm(self, port: int, num: int, turn_on: bool) -> None:
147        """
148        `ioperm` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
149        """
150        pass
151
152    def iopl(self, level: int) -> None:
153        """
154        `iopl` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
155        """
156        pass

A class to interact with the /dev/io device file on FreeBSD.

FreeBsdPortIO()
64    def __init__(self):
65        """
66        Initialize the `/dev/port` device file.
67        """
68        self._dev_io = open("/dev/io", "wb", buffering=0)

Initialize the /dev/port device file.

def out_bytes(self, data: bytes, port: int) -> None:
77    def out_bytes(self, data: bytes, port: int) -> None:
78        """
79        Write data to the specified port.
80        :param data: Data to write.
81        :param port: Port to write to.
82        """
83        iodev_pio_req = struct.pack(
84            "IIII", IODEV_PIO_WRITE, port, len(data), int.from_bytes(data, "little")
85        )
86        ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)

Write data to the specified port.

Parameters
  • data: Data to write.
  • port: Port to write to.
def outb(self, data: int, port: int) -> None:
88    def outb(self, data: int, port: int) -> None:
89        """
90        Write a byte (8 bit) to the specified port.
91        :param data: Byte to write.
92        :param port: Port to write to.
93        """
94        self.out_bytes(data.to_bytes(1, "little"), port)

Write a byte (8 bit) to the specified port.

Parameters
  • data: Byte to write.
  • port: Port to write to.
def outw(self, data: int, port: int) -> None:
 96    def outw(self, data: int, port: int) -> None:
 97        """
 98        Write a word (16 bit) to the specified port.
 99        :param data: Word to write.
100        :param port: Port to write to.
101        """
102        self.out_bytes(data.to_bytes(2, "little"), port)

Write a word (16 bit) to the specified port.

Parameters
  • data: Word to write.
  • port: Port to write to.
def outl(self, data: int, port: int) -> None:
104    def outl(self, data: int, port: int) -> None:
105        """
106        Write a long (32 bit) to the specified port.
107        :param data: Long to write.
108        :param port: Port to write to.
109        """
110        self.out_bytes(data.to_bytes(4, "little"), port)

Write a long (32 bit) to the specified port.

Parameters
  • data: Long to write.
  • port: Port to write to.
def in_bytes(self, port: int, num: int) -> bytes:
112    def in_bytes(self, port: int, num: int) -> bytes:
113        """
114        Read data from the specified port.
115        :param port: Port to read from.
116        :param num: Number of bytes to read (1 - 4).
117        :return: Data read.
118        """
119        iodev_pio_req = struct.pack("IIII", IODEV_PIO_READ, port, num, 0)
120        return ioctl(self._dev_io, IODEV_PIO(), iodev_pio_req)[struct.calcsize("III") :]

Read data from the specified port.

Parameters
  • port: Port to read from.
  • num: Number of bytes to read (1 - 4).
Returns

Data read.

def inb(self, port: int) -> int:
122    def inb(self, port: int) -> int:
123        """
124        Read a byte (8 bit) from the specified port.
125        :param port: Port to read from.
126        :return: Byte read.
127        """
128        return int.from_bytes(self.in_bytes(port, 1), "little")

Read a byte (8 bit) from the specified port.

Parameters
  • port: Port to read from.
Returns

Byte read.

def inw(self, port: int) -> int:
130    def inw(self, port: int) -> int:
131        """
132        Read a word (16 bit) from the specified port.
133        :param port: Port to read from.
134        :return: Word read.
135        """
136        return int.from_bytes(self.in_bytes(port, 2), "little")

Read a word (16 bit) from the specified port.

Parameters
  • port: Port to read from.
Returns

Word read.

def inl(self, port: int) -> int:
138    def inl(self, port: int) -> int:
139        """
140        Read a long (32 bit) from the specified port.
141        :param port: Port to read from.
142        :return: Long read.
143        """
144        return int.from_bytes(self.in_bytes(port, 4), "little")

Read a long (32 bit) from the specified port.

Parameters
  • port: Port to read from.
Returns

Long read.

def ioperm(self, port: int, num: int, turn_on: bool) -> None:
146    def ioperm(self, port: int, num: int, turn_on: bool) -> None:
147        """
148        `ioperm` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
149        """
150        pass

ioperm stub function. The iopl will already be raised from opening /dev/io and is not required.

def iopl(self, level: int) -> None:
152    def iopl(self, level: int) -> None:
153        """
154        `iopl` stub function. The iopl will already be raised from opening `/dev/io` and is not required.
155        """
156        pass

iopl stub function. The iopl will already be raised from opening /dev/io and is not required.