#include #include #include "pci/pci.h" #include "pci/qemu_pci_serial/qemu_pci_serial.h" #include "io/io.h" #include "sysdefs/dev.h" #include "util/util.h" #include "dev/dev.h" #include "errors.h" #include "hshtb.h" #include "kprintf.h" static QemuPciSerialDev QEMU_PCI_SERIAL_DEV; // https://wiki.osdev.org/Serial_Ports void _serial_init(uint16_t iobase) { io_out8(iobase+1, 0x00); io_out8(iobase+3, 0x80); io_out8(iobase+0, 0x03); io_out8(iobase+1, 0x00); io_out8(iobase+3, 0x03); io_out8(iobase+2, 0xC7); io_out8(iobase+4, 0x0B); io_out8(iobase+4, 0x1E); io_out8(iobase+0, 0xAE); if (io_in8(iobase+0) != 0xAE) { ERR("pci", "QEMU_PCI_SERIAL serial is faulty!\n"); return; } io_out8(iobase+4, 0x0F); } int _serial_recvready(uint16_t iobase) { return io_in8(iobase+5) & 1; } uint8_t _serial_recvb(uint16_t iobase) { return io_in8(iobase); } int _serial_sendready(uint16_t iobase) { return io_in8(iobase+5) & 0x20; } void _serial_sendb(uint16_t iobase, uint8_t b) { io_out8(iobase, b); } int32_t qemu_pci_serial_dev_sendb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; _serial_sendb(qpsd->iobase, buffer[0]); return E_OK; } int32_t qemu_pci_serial_dev_sendready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; return _serial_sendready(qpsd->iobase); } int32_t qemu_pci_serial_dev_recvb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; return _serial_recvb(qpsd->iobase); } int32_t qemu_pci_serial_dev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { (void)dev; (void)buffer; (void)len; (void)pid; QemuPciSerialDev *qpsd = dev->extra; return _serial_recvready(qpsd->iobase); } void pci_qemu_pci_serial_init(void) { PciDev dev = pci_getdev(0x1B36, 0x0002, -1); if (!dev.bits) { return; } uint32_t bar0 = pci_read(dev, PCI_BAR0); LOG("pci", "QEMU_PCI_SERIAL bar0=0x%x\n", bar0); uint16_t iobase = bar0 & 0xFFFFFFFC; LOG("pci", "QEMU_PCI_SERIAL iobase=0x%x\n", iobase); QEMU_PCI_SERIAL_DEV._magic = QEMU_PCI_SERIAL_MAGIC; QEMU_PCI_SERIAL_DEV.iobase = iobase; Dev *serialdev = NULL; HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev); serialdev->fns[0] = &qemu_pci_serial_dev_sendb; serialdev->fns[1] = &qemu_pci_serial_dev_sendready; serialdev->fns[2] = &qemu_pci_serial_dev_recvb; serialdev->fns[3] = &qemu_pci_serial_dev_recvready; spinlock_init(&serialdev->spinlock); serialdev->extra = &QEMU_PCI_SERIAL_DEV; _serial_init(QEMU_PCI_SERIAL_DEV.iobase); }