summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/phy/rt8139.c54
-rw-r--r--sys/dev/usb/xhci.c43
-rw-r--r--sys/fs/initramfs.c108
-rw-r--r--sys/include/dev/phy/rt8139.h13
-rw-r--r--sys/include/dev/usb/xhcivar.h5
-rw-r--r--sys/include/net/if.h35
-rw-r--r--sys/include/net/if_ether.h74
7 files changed, 267 insertions, 65 deletions
diff --git a/sys/dev/phy/rt8139.c b/sys/dev/phy/rt8139.c
index e2f87e1..ab8a6c0 100644
--- a/sys/dev/phy/rt8139.c
+++ b/sys/dev/phy/rt8139.c
@@ -31,10 +31,12 @@
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/driver.h>
+#include <sys/device.h>
#include <dev/pci/pci.h>
#include <dev/phy/rt8139.h>
#include <dev/timer.h>
#include <dev/pci/pciregs.h>
+#include <net/if_ether.h>
#include <vm/physmem.h>
#include <vm/vm.h>
#include <machine/pio.h>
@@ -65,6 +67,7 @@
static struct pci_device *dev;
static struct timer tmr;
+static struct etherdev wire;
static uint16_t ioport;
static paddr_t rxbuf, txbuf;
@@ -218,6 +221,10 @@ rt_init_pci(void)
static int
rt_init_mac(void)
{
+ uint8_t conf;
+ uint32_t tmp;
+ int error;
+
/*
* First step is ensuring the MAC is in known
* and consistent state by resetting it. God
@@ -226,7 +233,52 @@ rt_init_mac(void)
ioport = dev->bar[0] & ~1;
pr_trace("resetting MAC...\n");
rt_write(RT_CHIPCMD, 1, RT_RST);
- rt_poll(RT_CHIPCMD, 1, RT_RST, 0);
+ error = rt_poll(RT_CHIPCMD, 1, RT_RST, 0);
+ if (error < 0) {
+ pr_error("RTL8139 reset timeout\n");
+ return error;
+ }
+
+ /*
+ * Tell the RTL8139 to load config data from
+ * the 93C46. This is done by clearing EEM1
+ * and setting EEM0. This whole process should
+ * take roughly 2 milliseconds.
+ *
+ * XXX: EEPROM autoloads *should* happen during a hardware
+ * reset but some cards might not follow spec so force
+ * it.
+ */
+ conf = rt_read(RT_CFG9346, 1);
+ conf &= ~RT_EEM1;
+ conf |= RT_EEM0;
+ rt_write(RT_CFG9346, 1, conf);
+
+ /* MAC address dword 0 */
+ tmp = rt_read(RT_IDR0, 4);
+ wire.mac_addr[0] = tmp & 0xFF;
+ wire.mac_addr[1] = (tmp >> 8) & 0xFF;
+ wire.mac_addr[2] = (tmp >> 16) & 0xFF;
+ wire.mac_addr[3] = (tmp >> 24) & 0xFF;
+
+ /* MAC address word 1 */
+ tmp = rt_read(RT_IDR2, 4);
+ wire.mac_addr[4] = (tmp >> 16) & 0xFF;
+ wire.mac_addr[5] = (tmp >> 24) & 0xFF;
+
+ pr_trace("MAC address: %x:%x:%x:%x:%x:%x\n",
+ (uint64_t)wire.mac_addr[0], (uint64_t)wire.mac_addr[1],
+ (uint64_t)wire.mac_addr[2], (uint64_t)wire.mac_addr[3],
+ (uint64_t)wire.mac_addr[4], (uint64_t)wire.mac_addr[5]);
+
+ /*
+ * Alright, now we don't want those EEM bits
+ * sticking lopsided so lets put the RTL8139
+ * back into normal operation...
+ */
+ conf = rt_read(RT_CFG9346, 1);
+ conf &= ~(RT_EEM1 | RT_EEM0);
+ rt_write(RT_CFG9346, 1, conf);
rxbuf = vm_alloc_frame(RX_BUF_SIZE);
txbuf = vm_alloc_frame(RX_BUF_SIZE);
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 67a1e4e..d68f98e 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -37,6 +37,7 @@
#include <dev/usb/xhciregs.h>
#include <dev/usb/xhcivar.h>
#include <dev/pci/pci.h>
+#include <dev/acpi/acpi.h>
#include <vm/physmem.h>
#include <vm/dynalloc.h>
#include <assert.h>
@@ -145,15 +146,17 @@ xhci_parse_ecp(struct xhci_hc *hc)
break;
case XHCI_ECAP_USBLEGSUP:
/* Begin xHC BIOS handoff to us */
- pr_trace("establishing xHC ownership...\n");
- val |= XHCI_OS_SEM;
- mmio_write32(p, val);
-
- /* Ensure the xHC responded correctly */
- if (xhci_poll32(p, XHCI_OS_SEM, 1) < 0)
- return -EIO;
- if (xhci_poll32(p, XHCI_BIOS_SEM, 0) < 0)
- return -EIO;
+ if (!ISSET(hc->quirks, XHCI_QUIRK_HANDOFF)) {
+ pr_trace("establishing xHC ownership...\n");
+ val |= XHCI_OS_SEM;
+ mmio_write32(p, val);
+
+ /* Ensure the xHC responded correctly */
+ if (xhci_poll32(p, XHCI_OS_SEM, 1) < 0)
+ return -EIO;
+ if (xhci_poll32(p, XHCI_BIOS_SEM, 0) < 0)
+ return -EIO;
+ }
break;
}
@@ -414,6 +417,28 @@ xhci_init_hc(struct xhci_hc *hc)
uintptr_t dcbaap, cmdring;
struct xhci_caps *caps;
struct xhci_opregs *opregs;
+ const char *vendor;
+
+ /*
+ * The firmware on some Dell machines handle the
+ * xHCI BIOS/OS handoff very poorly. Updating the
+ * the OS semaphore in the USBLEGSUP register will
+ * result in the chipset firing off an SMI which is
+ * supposed to perform the actual handoff.
+ *
+ * However, Dell is stupid as always and the machine
+ * can get stuck in SMM which results in the machine
+ * locking up in a *very* bad way. In other words, the
+ * OS execution is literally halted and further SMIs like
+ * thermal, power, and fan events are deferred forever
+ * (no bueno!!). The best thing to do is to not perform
+ * a handoff if the host board is by Dell (bad Dell!!).
+ */
+ vendor = acpi_oemid();
+ if (memcmp(vendor, "DELL", 4) == 0) {
+ pr_trace("detected xhc handoff quirk\n");
+ hc->quirks |= XHCI_QUIRK_HANDOFF;
+ }
caps = (struct xhci_caps *)hc->base;
caplength = mmio_read8(&caps->caplength);
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index fd746ef..b12a64b 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -33,12 +33,16 @@
#include <sys/errno.h>
#include <sys/limine.h>
#include <sys/panic.h>
+#include <sys/param.h>
#include <sys/vnode.h>
#include <fs/initramfs.h>
#include <vm/dynalloc.h>
#include <string.h>
-#define CPIO_TRAILER "TRAILER!!!"
+#define OMAR_EOF "RAMO"
+#define OMAR_REG 0
+#define OMAR_DIR 1
+#define BLOCK_SIZE 512
/*
* File or directory.
@@ -51,20 +55,18 @@ struct initramfs_node {
};
/*
- * ODC CPIO header
+ * The OMAR file header, describes the basics
+ * of a file.
+ *
+ * @magic: Header magic ("OMAR")
+ * @len: Length of the file
+ * @namelen: Length of the filename
*/
-struct cpio_hdr {
- char c_magic[6];
- char c_dev[6];
- char c_ino[6];
- char c_mode[6];
- char c_uid[6];
- char c_gid[6];
- char c_nlink[6];
- char c_rdev[6];
- char c_mtime[11];
- char c_namesize[6];
- char c_filesize[11];
+struct __packed omar_hdr {
+ char magic[4];
+ uint8_t type;
+ uint8_t namelen;
+ uint32_t len;
};
static volatile struct limine_module_request mod_req = {
@@ -92,21 +94,6 @@ get_module(const char *path, uint64_t *size) {
}
/*
- * Convert octal to base 10
- */
-static uint32_t
-oct2dec(const char *in, size_t sz)
-{
- size_t val = 0;
-
- for (size_t i = 0; i < sz; ++i) {
- val = val * 8 + (in[i] - '0');
- }
-
- return val;
-}
-
-/*
* Get a file from initramfs
*
* @path: Path of file to get.
@@ -115,41 +102,54 @@ oct2dec(const char *in, size_t sz)
static int
initramfs_get_file(const char *path, struct initramfs_node *res)
{
- const struct cpio_hdr *hdr;
struct initramfs_node node;
- uintptr_t addr;
- size_t namesize, filesize;
- mode_t mode;
+ const struct omar_hdr *hdr;
+ const char *p, *name;
+ char namebuf[256];
+ off_t off;
- addr = (uintptr_t)initramfs;
+ p = initramfs;
for (;;) {
- hdr = (void *)addr;
- namesize = oct2dec(hdr->c_namesize, sizeof(hdr->c_namesize));
- filesize = oct2dec(hdr->c_filesize, sizeof(hdr->c_filesize));
- mode = oct2dec(hdr->c_mode, sizeof(hdr->c_mode));
+ hdr = (struct omar_hdr *)p;
+ if (strncmp(hdr->magic, OMAR_EOF, sizeof(OMAR_EOF)) == 0) {
+ break;
+ }
- /* Make sure the magic is correct */
- if (strncmp(hdr->c_magic, "070707", 6) != 0) {
+ /* Ensure the file is valid */
+ if (strncmp(hdr->magic, "OMAR", 4) != 0) {
+ /* Bad magic */
+ return -EINVAL;
+ }
+ if (hdr->namelen > sizeof(namebuf) - 1) {
return -EINVAL;
}
- addr += sizeof(struct cpio_hdr);
- node.path = (const char *)addr;
+ name = (char *)p + sizeof(struct omar_hdr);
+ memcpy(namebuf, name, hdr->namelen);
+ namebuf[hdr->namelen] = '\0';
- /* Is this the requested file? */
- if (strcmp(node.path, path) == 0) {
- node.data = (void *)(addr + namesize);
- node.size = filesize;
- node.mode = mode;
+ /* Compute offset to next block */
+ if (hdr->type == OMAR_DIR) {
+ off = 512;
+ } else {
+ off = ALIGN_UP(sizeof(*hdr) + hdr->namelen + hdr->len, BLOCK_SIZE);
+ }
+
+ /* Skip header and name, right to the data */
+ p = (char *)hdr + sizeof(struct omar_hdr);
+ p += hdr->namelen;
+
+ if (strcmp(namebuf, path) == 0) {
+ node.mode = 0700;
+ node.size = hdr->len;
+ node.data = (void *)p;
*res = node;
return 0;
}
- /* Get next header and see if we are at the end */
- addr += (namesize + filesize);
- if (strcmp(node.path, CPIO_TRAILER) == 0) {
- break;
- }
+ hdr = (struct omar_hdr *)((char *)hdr + off);
+ p = (char *)hdr;
+ memset(namebuf, 0, sizeof(namebuf));
}
return -ENOENT;
@@ -256,9 +256,9 @@ initramfs_init(struct fs_info *fip)
struct mount *mp;
int status;
- initramfs = get_module("/boot/ramfs.cpio", &initramfs_size);
+ initramfs = get_module("/boot/ramfs.omar", &initramfs_size);
if (initramfs == NULL) {
- panic("failed to open initramfs cpio image\n");
+ panic("failed to open initramfs OMAR image\n");
}
status = vfs_alloc_vnode(&g_root_vnode, VDIR);
diff --git a/sys/include/dev/phy/rt8139.h b/sys/include/dev/phy/rt8139.h
index ef7b127..21c7d54 100644
--- a/sys/include/dev/phy/rt8139.h
+++ b/sys/include/dev/phy/rt8139.h
@@ -33,7 +33,14 @@
#include <sys/types.h>
#include <sys/param.h>
-#define RT_IDR0 0x00 /* MAC address */
+/* MAC address */
+#define RT_IDR0 0x00
+#define RT_IDR1 0x00
+#define RT_IDR2 0x02
+#define RT_IDR3 0x03
+#define RT_IDR4 0x04
+#define RT_IDR5 0x05
+
#define RT_MAR0 0x08 /* Multicast filter */
#define RT_TXSTATUS0 0x10 /* Transmit status (4 32bit regs) */
#define RT_TXADDR0 0x20 /* Tx descriptors (also 4 32bit) */
@@ -70,6 +77,10 @@
#define RT_RE BIT(3) /* Receiver enable */
#define RT_RST BIT(4) /* Reset */
+/* 93C46 EEPROM mode bits */
+#define RT_EEM0 BIT(6)
+#define RT_EEM1 BIT(7)
+
/* Receive register bits */
#define RT_AAP BIT(0) /* Accept all packets */
#define RT_APM BIT(1) /* Accept physical match packets */
diff --git a/sys/include/dev/usb/xhcivar.h b/sys/include/dev/usb/xhcivar.h
index 0488ad8..a9a8fc1 100644
--- a/sys/include/dev/usb/xhcivar.h
+++ b/sys/include/dev/usb/xhcivar.h
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/types.h>
+#include <sys/param.h>
#include <dev/usb/xhciregs.h>
#define XHCI_TIMEOUT 500 /* In ms */
@@ -41,6 +42,9 @@
#define XHCI_MAX_PROTOS 4
#define XHCI_IMOD_DEFAULT 0
+/* Quirks */
+#define XHCI_QUIRK_HANDOFF BIT(0)
+
/*
* USB proto (USB 2.0 or 3.0)
*/
@@ -108,6 +112,7 @@ struct xhci_hc {
uint32_t *evring;
uint8_t maxslots;
uint8_t cr_cycle : 1;
+ uint16_t quirks;
size_t maxports;
size_t protocnt;
struct xhci_caps *caps;
diff --git a/sys/include/net/if.h b/sys/include/net/if.h
new file mode 100644
index 0000000..bd57509
--- /dev/null
+++ b/sys/include/net/if.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_IF_H_
+#define _NET_IF_H_
+
+#define IFNAMESIZ 16
+
+#endif /* !_NET_IF_H_ */
diff --git a/sys/include/net/if_ether.h b/sys/include/net/if_ether.h
new file mode 100644
index 0000000..a8fcfa5
--- /dev/null
+++ b/sys/include/net/if_ether.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IF_ETHER_H_
+#define _IF_ETHER_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <net/if.h>
+
+#define MACADDR_LEN 6
+
+struct __packed ether_frame {
+ uint8_t sync[7]; /* Preamble (sync stuff) */
+ uint8_t spd; /* Start frame delimiter */
+ uint8_t macd[6]; /* MAC destination */
+ uint8_t macs[6]; /* MAC source */
+ uint16_t type; /* Protocol type */
+ char payload[1]; /* sized @ 1+n */
+};
+
+/*
+ * Used by the driver to buffer packets.
+ */
+struct etherbuf {
+ struct ether_frame *frp;
+ off_t head;
+ off_t tail;
+ size_t cap; /* In entries */
+};
+
+/*
+ * Ethernet device
+ *
+ * if_ether: E
+ * driver: D
+ *
+ * @if_name: Interface name.
+ * @tx: Transmit packets (D->E)
+ */
+struct etherdev {
+ char if_name[IFNAMESIZ];
+ struct etherbuf *buf;
+ ssize_t(*tx)(struct etherdev *ep, const void *buf, size_t len);
+ char mac_addr[MACADDR_LEN];
+};
+
+#endif /* !_IF_ETHER_H_ */