Compare commits

..

11 Commits

30 changed files with 658 additions and 675 deletions

View File

@ -69,6 +69,9 @@ SRCFILES += $(call GRABSRC, \
cpu \ cpu \
vmm \ vmm \
pci \ pci \
pci/ata \
pci/qemu_pci_serial \
cjob \
) )
CFILES := $(call GET_CFILES, $(SRCFILES)) CFILES := $(call GET_CFILES, $(SRCFILES))

36
kernel/cjob/cjob.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdint.h>
#include <stddef.h>
#include "spinlock/spinlock.h"
#include "cjob/cjob.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
CJobs CJOBS;
static uint64_t cjobids = 0;
void cjob_init(void) {
spinlock_init(&CJOBS.spinlock);
CJOBS.cjobs = NULL;
}
int32_t cjob_register(CJobFn fn, void *arg) {
CJob *cjob = dlmalloc(sizeof(*cjob));
cjob->fn = fn;
cjob->arg = arg;
int32_t id = cjob->id = cjobids++;
spinlock_acquire(&CJOBS.spinlock);
LL_APPEND(CJOBS.cjobs, cjob);
spinlock_release(&CJOBS.spinlock);
return id;
}
void cjob_runjobs(void) {
CJob *cjob, *cjobtmp;
spinlock_acquire(&CJOBS.spinlock);
LL_FOREACH_SAFE(CJOBS.cjobs, cjob, cjobtmp) {
cjob->fn(cjob->arg);
}
spinlock_release(&CJOBS.spinlock);
}

29
kernel/cjob/cjob.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef CJOB_CJOB_H_
#define CJOB_CJOB_H_
#include <stdint.h>
#include <stddef.h>
#include "spinlock/spinlock.h"
typedef void (*CJobFn)(void *arg);
typedef struct CJob {
struct CJob *next;
CJobFn fn;
void *arg;
int32_t id;
} CJob;
typedef struct {
SpinLock spinlock;
CJob *cjobs;
} CJobs;
extern CJobs CJOBS;
void cjob_init(void);
int32_t cjob_register(CJobFn fn, void *arg);
void cjob_runjobs(void);
#endif // CJOB_CJOB_H_

View File

@ -4,7 +4,6 @@
#include "std/string.h" #include "std/string.h"
#include "dev/dev.h" #include "dev/dev.h"
#include "dev/ps2kbdev.h" #include "dev/ps2kbdev.h"
#include "dev/serialdev.h"
#include "hshtb.h" #include "hshtb.h"
DevTable DEVTABLE; DevTable DEVTABLE;
@ -14,5 +13,4 @@ void dev_init(void) {
spinlock_init(&DEVTABLE.spinlock); spinlock_init(&DEVTABLE.spinlock);
ps2kbdev_init(); ps2kbdev_init();
serialdev_init();
} }

View File

@ -1,81 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include "dev/dev.h"
#include "dev/serialdev.h"
#include "util/util.h"
#include "sysdefs/dev.h"
#include "io/io.h"
#include "errors.h"
#include "hshtb.h"
#include "kprintf.h"
// https://wiki.osdev.org/Serial_Ports
#define PORT 0x3f8
void serial_init(void) {
io_out8(PORT+1, 0x00);
io_out8(PORT+3, 0x80);
io_out8(PORT+0, 0x03);
io_out8(PORT+1, 0x00);
io_out8(PORT+3, 0x03);
io_out8(PORT+2, 0xC7);
io_out8(PORT+4, 0x0B);
io_out8(PORT+4, 0x1E);
io_out8(PORT+0, 0xAE);
if (io_in8(PORT+0) != 0xAE) {
ERR("serial", "serial is faulty!\n");
return;
}
io_out8(PORT+4, 0x0F);
}
int serial_recvready(void) {
return io_in8(PORT+5) & 1;
}
uint8_t serial_recvb(void) {
return io_in8(PORT);
}
int serial_sendready(void) {
return io_in8(PORT+5) & 0x20;
}
void serial_sendb(uint8_t b) {
io_out8(PORT, b);
}
int32_t serialdev_sendb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)len; (void)pid;
serial_sendb(buffer[0]);
return E_OK;
}
int32_t serialdev_sendready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)pid;
return serial_sendready();
}
int32_t serialdev_recvb(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)pid;
return serial_recvb();
}
int32_t serialdev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)pid;
return serial_recvready();
}
void serialdev_init(void) {
Dev *serialdev = NULL;
HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev);
serialdev->fns[DEV_SERIALDEV_SENDB] = &serialdev_sendb;
serialdev->fns[DEV_SERIALDEV_SENDREADY] = &serialdev_sendready;
serialdev->fns[DEV_SERIALDEV_RECVB] = &serialdev_recvb;
serialdev->fns[DEV_SERIALDEV_RECVREADY] = &serialdev_recvready;
spinlock_init(&serialdev->spinlock);
serial_init();
}

View File

@ -1,6 +0,0 @@
#ifndef DEV_SERIALDEV_H_
#define DEV_SERIALDEV_H_
void serialdev_init(void);
#endif // DEV_SERIALDEV_H_

View File

@ -66,7 +66,9 @@
_push_regs _push_regs
cld cld
movq %rsp, %rdi movq %rsp, %rdi
sub $0x8, %rsp
call intr_handleintr call intr_handleintr
add $0x8, %rsp
_pop_regs _pop_regs
add $0x10, %rsp add $0x10, %rsp
iretq iretq

View File

@ -7,15 +7,47 @@
#include "std/string.h" #include "std/string.h"
#include "dlmalloc/malloc.h" #include "dlmalloc/malloc.h"
#include "util/util.h" #include "util/util.h"
#include "cjob/cjob.h"
#include "hshtb.h" #include "hshtb.h"
#include "errors.h" #include "errors.h"
#include "kprintf.h" #include "kprintf.h"
IpcMBuses IPC_MBUSES; IpcMBuses IPC_MBUSES;
void ipc_mbus_gc_cjob(void *arg) {
for (size_t i = 0; i < LEN(IPC_MBUSES.mbuses); i++) {
spinlock_acquire(&IPC_MBUSES.spinlock);
IpcMBus *mbus = &IPC_MBUSES.mbuses[i];
spinlock_release(&IPC_MBUSES.spinlock);
spinlock_acquire(&mbus->spinlock);
if (mbus->_hshtbstate != HSHTB_TAKEN) {
spinlock_release(&mbus->spinlock);
continue;
}
IpcMBusCons *cons, *constmp;
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = NULL;
LL_FINDPROP(PROCS.procs, proc, pid, cons->pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
LL_REMOVE(mbus->consumers, cons);
dlfree(cons->rbuf.buffer);
dlfree(cons);
}
}
spinlock_release(&mbus->spinlock);
}
}
void ipc_mbusinit(void) { void ipc_mbusinit(void) {
memset(&IPC_MBUSES, 0, sizeof(IPC_MBUSES)); memset(&IPC_MBUSES, 0, sizeof(IPC_MBUSES));
spinlock_init(&IPC_MBUSES.spinlock); spinlock_init(&IPC_MBUSES.spinlock);
cjob_register(&ipc_mbus_gc_cjob, NULL);
} }
IpcMBus *ipc_mbusmake(const char *name, size_t objsize, size_t objmax) { IpcMBus *ipc_mbusmake(const char *name, size_t objsize, size_t objmax) {
@ -174,32 +206,3 @@ int32_t ipc_mbusdttch(const char *name, uint64_t pid) {
return E_OK; return E_OK;
} }
void ipc_mbustick(void) {
for (size_t i = 0; i < LEN(IPC_MBUSES.mbuses); i++) {
spinlock_acquire(&IPC_MBUSES.spinlock);
IpcMBus *mbus = &IPC_MBUSES.mbuses[i];
spinlock_release(&IPC_MBUSES.spinlock);
spinlock_acquire(&mbus->spinlock);
if (mbus->_hshtbstate != HSHTB_TAKEN) {
spinlock_release(&mbus->spinlock);
continue;
}
IpcMBusCons *cons, *constmp;
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = NULL;
LL_FINDPROP(PROCS.procs, proc, pid, cons->pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
LL_REMOVE(mbus->consumers, cons);
dlfree(cons->rbuf.buffer);
dlfree(cons);
}
}
spinlock_release(&mbus->spinlock);
}
}

View File

@ -34,6 +34,5 @@ int32_t ipc_mbuspublish(const char *name, const uint8_t *const buffer);
int32_t ipc_mbusconsume(const char *name, uint8_t *const buffer, uint64_t pid); int32_t ipc_mbusconsume(const char *name, uint8_t *const buffer, uint64_t pid);
int32_t ipc_mbusattch(const char *name, uint64_t pid); int32_t ipc_mbusattch(const char *name, uint64_t pid);
int32_t ipc_mbusdttch(const char *name, uint64_t pid); int32_t ipc_mbusdttch(const char *name, uint64_t pid);
void ipc_mbustick(void);
#endif // IPC_MBUS_MBUS_H_ #endif // IPC_MBUS_MBUS_H_

View File

@ -19,6 +19,7 @@
#include "cpu/gdt.h" #include "cpu/gdt.h"
#include "ipc/mbus/mbus.h" #include "ipc/mbus/mbus.h"
#include "pci/pci.h" #include "pci/pci.h"
#include "cjob/cjob.h"
void log_bootinfo(void) { void log_bootinfo(void) {
char buf[100]; char buf[100];
@ -50,6 +51,7 @@ void kmain(void) {
vmm_init(); vmm_init();
intr_init(); intr_init();
randcrypto_init(); randcrypto_init();
cjob_init();
ipc_mbusinit(); ipc_mbusinit();
dev_init(); dev_init();
storedev_init(); storedev_init();

54
kernel/pci/ata/ata.c Normal file
View File

@ -0,0 +1,54 @@
#include <stdint.h>
#include <stddef.h>
#include "pci/pci.h"
#include "storedev/storedev.h"
#include "storedev/atasd.h"
#include "kprintf.h"
#define ATA_PROBE(STRING, IOBASE, CTRLBASE, S_OR_M) \
ps = ata_probesize_bytes((IOBASE), (CTRLBASE), (S_OR_M)); \
if (ps > 0) { \
AtaSdInitExtra extra = { \
.devno = (S_OR_M), \
.capacity = ps, \
.iobase = (IOBASE), \
.ctrlbase = (CTRLBASE), \
}; \
storedev_create(STOREDEV_ATASD, (STRING), (void *)&extra); \
}
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x01
#define ATA_PRIM_IO 0x1F0
#define ATA_PRIM_CTRL 0x3F6
#define ATA_SCND_IO 0x170
#define ATA_SCND_CTRL 0x376
void pci_ata_init(void) {
PciDev dev = pci_getdev(0x8086, 0x7010, -1);
uint16_t iobase, ctrlbase;
uint64_t ps;
uint32_t bar0 = pci_read(dev, PCI_BAR0);
uint32_t bar1 = pci_read(dev, PCI_BAR1);
uint32_t bar2 = pci_read(dev, PCI_BAR2);
uint32_t bar3 = pci_read(dev, PCI_BAR3);
LOG("pci", "ATA bar0=0x%x, bar1=0x%x, bar2=0x%x, bar3=0x%x\n", bar0, bar1, bar2, bar3);
iobase = (bar0 & 0xFFFFFFFC) + ATA_PRIM_IO * (!bar0);
ctrlbase = (bar1 & 0xFFFFFFFC) + ATA_PRIM_CTRL * (!bar1);
LOG("pci", "ATA CHANNEL PRIM: iobase=0x%x, ctrlbase=0x%x\n", iobase, ctrlbase);
if (!bar0 || !bar1) LOG("pci", "falling back to ISA\n");
ATA_PROBE("atasd0m", iobase, ctrlbase, ATA_MASTER);
ATA_PROBE("atasd0s", iobase, ctrlbase, ATA_SLAVE);
iobase = (bar2 & 0xFFFFFFFC) + ATA_SCND_IO * (!bar2);
ctrlbase = (bar3 & 0xFFFFFFFC) + ATA_SCND_CTRL * (!bar3);
LOG("pci", "ATA CHANNEL SCND: iobase=0x%x, ctrlbase=0x%x\n", iobase, ctrlbase);
if (!bar2 || !bar3) LOG("pci", "falling back to ISA\n");
ATA_PROBE("atasd1m", iobase, ctrlbase, ATA_MASTER);
ATA_PROBE("atasd2s", iobase, ctrlbase, ATA_SLAVE);
}

6
kernel/pci/ata/ata.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef PCI_ATA_ATA_H_
#define PCI_ATA_ATA_H_
void pci_ata_init(void);
#endif // PCI_ATA__ATA_H_

View File

@ -1,44 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include "pci/pci.h"
#include "pci/ide.h"
#include "storedev/atasd.h"
#include "storedev/storedev.h"
#include "util/util.h"
#include "kprintf.h"
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x01
#define ATA_PROBE(STRING, IOBASE, CTRLBASE, S_OR_M) \
ps = ata_probesize_bytes((IOBASE), (CTRLBASE), (S_OR_M)); \
if (ps > 0) { \
AtaSdInitExtra extra = { \
.devno = (S_OR_M), \
.capacity = ps, \
.iobase = (IOBASE), \
.ctrlbase = (CTRLBASE), \
}; \
storedev_create(STOREDEV_ATASD, (STRING), (void *)&extra); \
}
void pci_ide_init(PciDevInfo *devinfo) {
LOG("pci", "init ATA drive\n");
uint16_t iobase, ctrlbase;
uint64_t ps;
if (!(devinfo->progintf & 0x1)) {
iobase = 0x1F0;
ctrlbase = 0x3F6;
}
ATA_PROBE("atasd0m", iobase, ctrlbase, ATA_MASTER)
ATA_PROBE("atasd0s", iobase, ctrlbase, ATA_SLAVE)
if (!(devinfo->progintf & 0x4)) {
iobase = 0x170;
ctrlbase = 0x376;
}
ATA_PROBE("atasd1m", iobase, ctrlbase, ATA_MASTER)
ATA_PROBE("atasd1s", iobase, ctrlbase, ATA_SLAVE)
}

View File

@ -1,8 +0,0 @@
#ifndef PCI_IDE_H_
#define PCI_IDE_H_
#include "pci/pci.h"
void pci_ide_init(PciDevInfo *devinfo);
#endif // PCI_IDE_H_

View File

@ -1,126 +1,185 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "pci/pci.h" #include "pci/pci.h"
#include "pci/reg.h" #include "pci/ata/ata.h"
#include "pci/qemu_pci_serial/qemu_pci_serial.h"
#include "io/io.h" #include "io/io.h"
#include "std/string.h" #include "std/string.h"
#include "util/util.h" #include "util/util.h"
#include "pci/ide.h"
#include "kprintf.h" #include "kprintf.h"
uint8_t pci_read8(uint32_t id, uint32_t reg) { static PciDev PCI_DEV_ZERO = {0};
uint32_t addr = 0x80000000 | id | (reg & 0xFC); uint32_t PCI_SIZE_MAP[100] = {0};
io_out32(PCI_CONFIG_ADDR, addr);
return io_in8(PCI_CONFIG_DATA + (reg & 0x03));
}
uint16_t pci_read16(uint32_t id, uint32_t reg) { uint32_t pci_read(PciDev dev, uint32_t field) {
uint32_t addr = 0x80000000 | id | (reg & 0xFC); dev.fieldnum = (field & 0xFC) >> 2;
io_out32(PCI_CONFIG_ADDR, addr); dev.enable = 1;
return io_in16(PCI_CONFIG_DATA + (reg & 0x02)); io_out32(PCI_CFG_ADDR, dev.bits);
}
uint32_t pci_read32(uint32_t id, uint32_t reg) { uint32_t size = PCI_SIZE_MAP[field];
uint32_t addr = 0x80000000 | id | (reg & 0xFC); uint8_t u8; uint16_t u16; uint32_t u32;
io_out32(PCI_CONFIG_ADDR, addr); switch (size) {
return io_in32(PCI_CONFIG_DATA + reg); case 1:
} u8 = io_in8(PCI_CFG_DATA + (field & 0x3));
return (uint32_t)u8;
void pci_write8(uint32_t id, uint32_t reg, uint8_t v) { case 2:
uint32_t addr = 0x80000000 | id | (reg & 0xFC); u16 = io_in16(PCI_CFG_DATA + (field & 0x2));
io_out32(PCI_CONFIG_ADDR, addr); return (uint32_t)u16;
io_out8(PCI_CONFIG_DATA + (reg & 0x03), v); case 4:
} u32 = io_in32(PCI_CFG_DATA);
return u32;
void pci_write16(uint32_t id, uint32_t reg, uint16_t v) { default:
uint32_t addr = 0x80000000 | id | (reg & 0xFC); return 0xFFFF;
io_out32(PCI_CONFIG_ADDR, addr);
io_out16(PCI_CONFIG_DATA + (reg & 0x02), v);
}
void pci_write32(uint32_t id, uint32_t reg, uint32_t v) {
uint32_t addr = 0x80000000 | id | (reg & 0xFC);
io_out32(PCI_CONFIG_ADDR, addr);
io_out32(PCI_CONFIG_DATA + reg, v);
}
void pci_readbar(uint32_t id, uint32_t idx, uint32_t *addr, uint32_t *mask) {
uint32_t reg = PCI_BAR0 + idx * sizeof(uint32_t);
*addr = pci_read32(id, reg);
pci_write32(id, reg, 0xffffffff);
*mask = pci_read32(id, reg);
pci_write32(id, reg, *addr);
}
void pci_getbar(PciBar *bar, uint32_t id, uint32_t idx) {
uint32_t addrlo;
uint32_t masklo;
pci_readbar(id, idx, &addrlo, &masklo);
if (addrlo & PCI_BAR_MEM32) {
bar->u.addr = (void *)((uint64_t)(addrlo & ~0x3));
bar->size = ~(masklo & ~0xF) + 1;
bar->flags = addrlo & 0xF;
} else if (addrlo & PCI_BAR_MEM64) {
uint32_t addrhi;
uint32_t maskhi;
pci_readbar(id, idx+1, &addrhi, &maskhi);
bar->u.addr = (void *)(((uint64_t)addrhi << 32) | ((uint64_t)addrlo & ~0xF));
bar->size = ~(((uint64_t)maskhi << 32) | ((uint64_t)masklo & ~0xF)) + 1;
bar->flags = addrlo & 0xF;
} else if (addrlo & PCI_BAR_IO) {
bar->u.port = (uint16_t)(addrlo & ~0x3);
bar->size = (uint16_t)(~(masklo & ~0x3) + 1);
bar->flags = addrlo & 0x3;
} }
} }
static PciMatch PCI_MATCHES[] = { void pci_write(PciDev dev, uint32_t field, uint32_t v) {
{ 0x8086, 0x7010, &pci_ide_init }, dev.fieldnum = (field & 0xFC) >> 2;
dev.enable = 1;
io_out32(PCI_CFG_ADDR, dev.bits);
io_out32(PCI_CFG_DATA, v);
}
uint32_t pci_devtype(PciDev dev) {
uint32_t a = pci_read(dev, PCI_CLASS) << 8;
uint32_t b = pci_read(dev, PCI_SUBCLASS);
return a | b;
}
uint32_t pci_scndrybus(PciDev dev) {
return pci_read(dev, PCI_SCNDRY_BUS);
}
uint32_t pci_isend(PciDev dev) {
return !(pci_read(dev, PCI_HDRTYPE));
}
PciDev pci_scanfn(uint16_t vendorid, uint16_t deviceid, uint32_t bus,
uint32_t device, uint32_t fn, int devtype) {
PciDev dev; memset(&dev, 0, sizeof(dev));
dev.busnum = bus;
dev.devnum = device;
dev.fnnum = fn;
// bridge
if (pci_devtype(dev) == 0x0604) {
pci_scanbus(vendorid, deviceid, pci_scndrybus(dev), devtype);
}
if (devtype == -1 || (uint32_t)devtype == pci_devtype(dev)) {
uint32_t venid = pci_read(dev, PCI_VENDORID);
uint32_t devid = pci_read(dev, PCI_DEVICEID);
if (devid == deviceid && venid == vendorid) {
return dev;
}
}
return PCI_DEV_ZERO;
}
PciDev pci_scanbus(uint16_t vendorid, uint16_t deviceid,
uint32_t bus, int devtype) {
for (uint32_t device = 0; device < PCI_DEV_PER_BUS; device++) {
PciDev d = pci_scandev(vendorid, deviceid, bus, device, devtype);
if (d.bits) {
return d;
}
}
return PCI_DEV_ZERO;
}
PciDev pci_scandev(uint16_t vendorid, uint16_t deviceid,
uint32_t bus, uint32_t device, int devtype) {
PciDev dev; memset(&dev, 0, sizeof(dev));
dev.busnum = bus;
dev.devnum = device;
if (pci_read(dev, PCI_VENDORID) == 0xFFFF) {
return PCI_DEV_ZERO;
}
PciDev d = pci_scanfn(vendorid, deviceid, bus, device, 0, devtype);
if (d.bits) {
return d;
}
if (pci_isend(dev)) {
return PCI_DEV_ZERO;
}
for (uint32_t fn = 1; fn < PCI_FN_PER_DEV; fn++) {
if (pci_read(dev, PCI_VENDORID) != 0xFFFF) {
d = pci_scanfn(vendorid, deviceid, bus, device, fn, devtype);
if (d.bits) {
return d;
}
}
}
return PCI_DEV_ZERO;
}
PciDev pci_getdev(uint16_t vendorid, uint16_t deviceid, int devtype) {
PciDev d = pci_scanbus(vendorid, deviceid, 0, devtype);
if (d.bits) {
return d;
}
if (pci_isend(PCI_DEV_ZERO)) {
ERR("pci", "pci_getdev() failed for 0x%04x/0x%04x,%d\n", vendorid, deviceid, devtype);
return PCI_DEV_ZERO;
}
for (uint32_t fn = 1; fn < PCI_FN_PER_DEV; fn++) {
PciDev d2; memset(&d2, 0, sizeof(d2));
d2.fnnum = fn;
if (pci_read(d2, PCI_VENDORID) == 0xFFFF) {
break;
}
d = pci_scanbus(vendorid, deviceid, fn, devtype);
if (d.bits) {
return d;
}
}
return PCI_DEV_ZERO;
}
void pci_init_size_map(void) {
PCI_SIZE_MAP[PCI_VENDORID] = 2;
PCI_SIZE_MAP[PCI_DEVICEID] = 2;
PCI_SIZE_MAP[PCI_CMD] = 2;
PCI_SIZE_MAP[PCI_STATUS] = 2;
PCI_SIZE_MAP[PCI_SUBCLASS] = 1;
PCI_SIZE_MAP[PCI_CLASS] = 1;
PCI_SIZE_MAP[PCI_CACHELINESZ] = 1;
PCI_SIZE_MAP[PCI_LTNCY_TIMER] = 1;
PCI_SIZE_MAP[PCI_HDRTYPE] = 1;
PCI_SIZE_MAP[PCI_BIST] = 1;
PCI_SIZE_MAP[PCI_BAR0] = 4;
PCI_SIZE_MAP[PCI_BAR1] = 4;
PCI_SIZE_MAP[PCI_BAR2] = 4;
PCI_SIZE_MAP[PCI_BAR3] = 4;
PCI_SIZE_MAP[PCI_BAR4] = 4;
PCI_SIZE_MAP[PCI_BAR5] = 4;
PCI_SIZE_MAP[PCI_INTRLINE] = 1;
PCI_SIZE_MAP[PCI_SCNDRY_BUS] = 1;
}
PciInitFn PCI_INIT_ARRAY[PCI_INIT_ARRAY_MAX] = {
&pci_ata_init,
&pci_qemu_pci_serial_init,
}; };
void pci_visit(uint32_t bus, uint32_t dev, uint32_t fn) { void pci_init_devs(void) {
uint32_t id = PCI_MAKE_ID(bus, dev, fn); for (size_t i = 0; i < LEN(PCI_INIT_ARRAY); i++) {
if (PCI_INIT_ARRAY[i] != NULL)
PciDevInfo devinfo; PCI_INIT_ARRAY[i]();
memset(&devinfo, 0, sizeof(devinfo));
devinfo.vendorid = pci_read16(id, PCI_VENDORID);
if (devinfo.vendorid == 0xffff) {
return;
}
devinfo.deviceid = pci_read16(id, PCI_DEVICEID);
devinfo.progintf = pci_read8(id, PCI_PROGINTF);
devinfo.subclass = pci_read8(id, PCI_SUBCLASS);
devinfo.classcode = pci_read8(id, PCI_CLASSCODE);
devinfo.bus = bus;
devinfo.dev = dev;
devinfo.fn = fn;
LOG("pci", "%02X:%02X:%u 0x%04X/0x%04X: %s\n",
bus, dev, fn, devinfo.vendorid, devinfo.deviceid,
pci_classname(devinfo.classcode, devinfo.subclass, devinfo.progintf));
for (size_t i = 0; i < LEN(PCI_MATCHES); i++) {
if (PCI_MATCHES[i].k1 == devinfo.vendorid && PCI_MATCHES[i].k2 == devinfo.deviceid) {
PCI_MATCHES[i].initfn(&devinfo);
}
} }
} }
void pci_init(void) { void pci_init(void) {
for (uint32_t bus = 0; bus < 0x100; bus++) { pci_init_size_map();
for (uint32_t dev = 0; dev < 32; dev++) { pci_init_devs();
uint32_t baseid = PCI_MAKE_ID(bus, dev, 0);
uint8_t hdrtype = pci_read8(baseid, PCI_HDRTYPE);
uint32_t fncount = hdrtype & PCI_MULTIFN ? 8 : 1;
for (uint32_t fn = 0; fn < fncount; fn++) {
pci_visit(bus, dev, fn);
}
}
}
} }

View File

@ -4,86 +4,68 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define PCI_MAKE_ID(bus, dev, fn) (((bus)<<16) | ((dev)<<11) | ((fn)<<8)) typedef union {
uint32_t bits;
#define PCI_CONFIG_ADDR 0xCF8 struct {
#define PCI_CONFIG_DATA 0xCFC uint32_t alwayszero: 2;
uint32_t fieldnum: 6;
#define PCI_MULTIFN 0x80 uint32_t fnnum: 3;
#define PCI_GENERIC 0x00 uint32_t devnum: 5;
#define PCI_PCI_BRIDGE 0x01 uint32_t busnum: 8;
#define PCI_CARDBUS_BRIDGE 0x02 uint32_t resv: 7;
uint32_t enable: 1;
#define PCI_VENDORID 0x00 };
#define PCI_DEVICEID 0x02
#define PCI_CMD 0x04
#define PCI_STATUS 0x06
#define PCI_REVID 0x08
#define PCI_PROGINTF 0x09
#define PCI_SUBCLASS 0x0A
#define PCI_CLASSCODE 0x0B
#define PCI_CACHELINESZ 0x0C
#define PCI_LATENCY 0x0D
#define PCI_HDRTYPE 0x0E
#define PCI_BIST 0x0F
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_BAR2 0x18
#define PCI_BAR3 0x1C
#define PCI_BAR4 0x20
#define PCI_BAR5 0x24
#define PCI_CARBUS_CIS 0x28
#define PCI_SUBSYS_VENDORID 0x2C
#define PCI_SUBSYS_DEVICEID 0x2E
#define PCI_EXPROM 0x30
#define PCI_CAP 0x34
#define PCI_INTRLINE 0x3C
#define PCI_INTRPIN 0x3D
#define PCI_MIN_GRANT 0x3E
#define PCI_MAX_LATENCY 0x3F
#define PCI_BAR_IO 0x01
#define PCI_BAR_MEM32 0x02
#define PCI_BAR_MEM64 0x04
#define PCI_BAR_PREFETCH 0x08
typedef struct {
union { void *addr; uint16_t port; } u;
uint64_t size;
uint32_t flags;
} PciBar;
typedef struct {
uint16_t vendorid;
uint16_t deviceid;
uint8_t classcode;
uint8_t subclass;
uint8_t progintf;
uint32_t bus, dev, fn;
} PciDevInfo;
typedef struct {
uint16_t k1;
uint16_t k2;
void (*initfn)(PciDevInfo *info);
} PciMatch;
#define PCI_DEV_MAGIC 0xAB0BA
typedef struct {
PciDevInfo devinfo;
} PciDev; } PciDev;
uint8_t pci_read8(uint32_t id, uint32_t reg); #define PCI_CFG_ADDR 0xCF8
uint16_t pci_read16(uint32_t id, uint32_t reg); #define PCI_CFG_DATA 0xCFC
uint32_t pci_read32(uint32_t id, uint32_t reg);
void pci_write8(uint32_t id, uint32_t reg, uint8_t v); #define PCI_VENDORID 0x00
void pci_write16(uint32_t id, uint32_t reg, uint16_t v); #define PCI_DEVICEID 0x02
void pci_write32(uint32_t id, uint32_t reg, uint32_t v); #define PCI_CMD 0x04
void pci_getbar(PciBar *bar, uint32_t id, uint32_t idx); #define PCI_STATUS 0x06
#define PCI_REVID 0x08
#define PCI_PROGIF 0x09
#define PCI_SUBCLASS 0x0A
#define PCI_CLASS 0x0B
#define PCI_CACHELINESZ 0x0C
#define PCI_LTNCY_TIMER 0x0D
#define PCI_HDRTYPE 0x0E
#define PCI_BIST 0x0F
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_BAR2 0x18
#define PCI_BAR3 0x1C
#define PCI_BAR4 0x20
#define PCI_BAR5 0x24
#define PCI_INTRLINE 0x3C
#define PCI_SCNDRY_BUS 0x09
#define PCI_HDR_DEV 0
#define PCI_HDR_BRIDGE 1
#define PCI_HDR_CARDBUS 2
#define PCI_DEV_PER_BUS 32
#define PCI_FN_PER_DEV 32
uint32_t pci_read(PciDev dev, uint32_t field);
void pci_write(PciDev dev, uint32_t field, uint32_t v);
uint32_t pci_devtype(PciDev dev);
uint32_t pci_scndrybus(PciDev dev);
uint32_t pci_isend(PciDev dev);
PciDev pci_scanfn(uint16_t vendorid, uint16_t deviceid, uint32_t bus,
uint32_t device, uint32_t fn, int devtype);
PciDev pci_scanbus(uint16_t vendorid, uint16_t deviceid,
uint32_t bus, int devtype);
PciDev pci_scandev(uint16_t vendorid, uint16_t deviceid,
uint32_t bus, uint32_t device, int devtype);
PciDev pci_getdev(uint16_t vendorid, uint16_t deviceid, int devtype);
void pci_init(void); void pci_init(void);
#define PCI_INIT_ARRAY_MAX 0x100
typedef void (*PciInitFn)(void);
extern PciInitFn PCI_INIT_ARRAY[PCI_INIT_ARRAY_MAX];
#endif // PCI_PCI_H_ #endif // PCI_PCI_H_

View File

@ -0,0 +1,187 @@
#include <stdint.h>
#include <stddef.h>
#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 "cjob/cjob.h"
#include "proc/proc.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;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
_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;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
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;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
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)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
return _serial_recvready(qpsd->iobase);
}
int32_t qemu_pci_serial_dev_lock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate == (int)pid) {
return E_OK;
}
if (qpsd->lockstate == -1) {
qpsd->lockstate = (int)pid;
return E_OK;
}
return E_DEVLOCKED;
}
int32_t qemu_pci_serial_dev_unlock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate == (int)pid) {
qpsd->lockstate = -1;
return E_OK;
}
return E_DEVNOTYOURLOCK;
}
void pci_qemu_pci_serial_gc_cjob(void *arg) {
Dev *dev = arg;
QemuPciSerialDev *qpsd;
spinlock_acquire(&dev->spinlock);
qpsd = dev->extra;
uint64_t pid = qpsd->lockstate;
spinlock_release(&dev->spinlock);
Proc *proc = NULL;
spinlock_acquire(&PROCS.spinlock);
LL_FINDPROP(PROCS.procs, proc, pid, pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
spinlock_acquire(&dev->spinlock);
qpsd = dev->extra;
qpsd->lockstate = -1;
spinlock_release(&dev->spinlock);
}
}
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;
QEMU_PCI_SERIAL_DEV.lockstate = -1;
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;
serialdev->fns[4] = &qemu_pci_serial_dev_lock;
serialdev->fns[5] = &qemu_pci_serial_dev_unlock;
spinlock_init(&serialdev->spinlock);
serialdev->extra = &QEMU_PCI_SERIAL_DEV;
cjob_register(&pci_qemu_pci_serial_gc_cjob, serialdev);
_serial_init(QEMU_PCI_SERIAL_DEV.iobase);
}

View File

@ -0,0 +1,17 @@
#ifndef PCI_QEMU_PCI_SERIAL_QEMU_PCI_SERIAL_H_
#define PCI_QEMU_PCI_SERIAL_QEMU_PCI_SERIAL_H_
#include <stdint.h>
#include <stddef.h>
#define QEMU_PCI_SERIAL_MAGIC 0x1234
typedef struct {
uint32_t _magic;
uint16_t iobase;
int lockstate;
} QemuPciSerialDev;
void pci_qemu_pci_serial_init(void);
#endif // PCI_QEMU_PCI_SERIAL_QEMU_PCI_SERIAL_H_

View File

@ -1,113 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include "pci/reg.h"
const char *pci_devname(uint32_t vendorid, uint32_t deviceid) {
return "Unknown Device";
}
const char *pci_classname(uint32_t classcode, uint32_t subclass, uint32_t progintf) {
switch ((classcode << 8) | subclass)
{
case PCI_VGA_COMPATIBLE: return "VGA-Compatible Device";
case PCI_STORAGE_SCSI: return "SCSI Storage Controller";
case PCI_STORAGE_IDE: return "IDE Interface";
case PCI_STORAGE_FLOPPY: return "Floppy Disk Controller";
case PCI_STORAGE_IPI: return "IPI Bus Controller";
case PCI_STORAGE_RAID: return "RAID Bus Controller";
case PCI_STORAGE_ATA: return "ATA Controller";
case PCI_STORAGE_SATA: return "SATA Controller";
case PCI_STORAGE_OTHER: return "Mass Storage Controller";
case PCI_NETWORK_ETHERNET: return "Ethernet Controller";
case PCI_NETWORK_TOKEN_RING: return "Token Ring Controller";
case PCI_NETWORK_FDDI: return "FDDI Controller";
case PCI_NETWORK_ATM: return "ATM Controller";
case PCI_NETWORK_ISDN: return "ISDN Controller";
case PCI_NETWORK_WORLDFIP: return "WorldFip Controller";
case PCI_NETWORK_PICGMG: return "PICMG Controller";
case PCI_NETWORK_OTHER: return "Network Controller";
case PCI_DISPLAY_VGA: return "VGA-Compatible Controller";
case PCI_DISPLAY_XGA: return "XGA-Compatible Controller";
case PCI_DISPLAY_3D: return "3D Controller";
case PCI_DISPLAY_OTHER: return "Display Controller";
case PCI_MULTIMEDIA_VIDEO: return "Multimedia Video Controller";
case PCI_MULTIMEDIA_AUDIO: return "Multimedia Audio Controller";
case PCI_MULTIMEDIA_PHONE: return "Computer Telephony Device";
case PCI_MULTIMEDIA_AUDIO_DEVICE: return "Audio Device";
case PCI_MULTIMEDIA_OTHER: return "Multimedia Controller";
case PCI_MEMORY_RAM: return "RAM Memory";
case PCI_MEMORY_FLASH: return "Flash Memory";
case PCI_MEMORY_OTHER: return "Memory Controller";
case PCI_BRIDGE_HOST: return "Host Bridge";
case PCI_BRIDGE_ISA: return "ISA Bridge";
case PCI_BRIDGE_EISA: return "EISA Bridge";
case PCI_BRIDGE_MCA: return "MicroChannel Bridge";
case PCI_BRIDGE_PCI: return "PCI Bridge";
case PCI_BRIDGE_PCMCIA: return "PCMCIA Bridge";
case PCI_BRIDGE_NUBUS: return "NuBus Bridge";
case PCI_BRIDGE_CARDBUS: return "CardBus Bridge";
case PCI_BRIDGE_RACEWAY: return "RACEway Bridge";
case PCI_BRIDGE_OTHER: return "Bridge Device";
case PCI_COMM_SERIAL: return "Serial Controller";
case PCI_COMM_PARALLEL: return "Parallel Controller";
case PCI_COMM_MULTIPORT: return "Multiport Serial Controller";
case PCI_COMM_MODEM: return "Modem";
case PCI_COMM_OTHER: return "Communication Controller";
case PCI_SYSTEM_PIC: return "PIC";
case PCI_SYSTEM_DMA: return "DMA Controller";
case PCI_SYSTEM_TIMER: return "Timer";
case PCI_SYSTEM_RTC: return "RTC";
case PCI_SYSTEM_PCI_HOTPLUG: return "PCI Hot-Plug Controller";
case PCI_SYSTEM_SD: return "SD Host Controller";
case PCI_SYSTEM_OTHER: return "System Peripheral";
case PCI_INPUT_KEYBOARD: return "Keyboard Controller";
case PCI_INPUT_PEN: return "Pen Controller";
case PCI_INPUT_MOUSE: return "Mouse Controller";
case PCI_INPUT_SCANNER: return "Scanner Controller";
case PCI_INPUT_GAMEPORT: return "Gameport Controller";
case PCI_INPUT_OTHER: return "Input Controller";
case PCI_DOCKING_GENERIC: return "Generic Docking Station";
case PCI_DOCKING_OTHER: return "Docking Station";
case PCI_PROCESSOR_386: return "386";
case PCI_PROCESSOR_486: return "486";
case PCI_PROCESSOR_PENTIUM: return "Pentium";
case PCI_PROCESSOR_ALPHA: return "Alpha";
case PCI_PROCESSOR_MIPS: return "MIPS";
case PCI_PROCESSOR_CO: return "CO-Processor";
case PCI_SERIAL_FIREWIRE: return "FireWire (IEEE 1394)";
case PCI_SERIAL_SSA: return "SSA";
case PCI_SERIAL_USB:
switch (progintf)
{
case PCI_SERIAL_USB_UHCI: return "USB (UHCI)";
case PCI_SERIAL_USB_OHCI: return "USB (OHCI)";
case PCI_SERIAL_USB_EHCI: return "USB2";
case PCI_SERIAL_USB_XHCI: return "USB3";
case PCI_SERIAL_USB_OTHER: return "USB Controller";
default: return "Unknown USB Class";
}
break;
case PCI_SERIAL_FIBER: return "Fiber Channel";
case PCI_SERIAL_SMBUS: return "SMBus";
case PCI_WIRELESS_IRDA: return "iRDA Compatible Controller";
case PCI_WIRLESSS_IR: return "Consumer IR Controller";
case PCI_WIRLESSS_RF: return "RF Controller";
case PCI_WIRLESSS_BLUETOOTH: return "Bluetooth";
case PCI_WIRLESSS_BROADBAND: return "Broadband";
case PCI_WIRLESSS_ETHERNET_A: return "802.1a Controller";
case PCI_WIRLESSS_ETHERNET_B: return "802.1b Controller";
case PCI_WIRELESS_OTHER: return "Wireless Controller";
case PCI_INTELLIGENT_I2O: return "I2O Controller";
case PCI_SATELLITE_TV: return "Satellite TV Controller";
case PCI_SATELLITE_AUDIO: return "Satellite Audio Controller";
case PCI_SATELLITE_VOICE: return "Satellite Voice Controller";
case PCI_SATELLITE_DATA: return "Satellite Data Controller";
case PCI_CRYPT_NETWORK: return "Network and Computing Encryption Device";
case PCI_CRYPT_ENTERTAINMENT: return "Entertainment Encryption Device";
case PCI_CRYPT_OTHER: return "Encryption Device";
case PCI_SP_DPIO: return "DPIO Modules";
case PCI_SP_OTHER: return "Signal Processing Controller";
}
return "Unknown PCI Class";
}

View File

@ -1,169 +0,0 @@
#ifndef PCI_REG_H_
#define PCI_REG_H_
#include <stdint.h>
#include <stddef.h>
// PCI Vendors
#define PCI_VENDOR_INTEL 0x8086
// PCI Classes
#define PCI_CLASS_LEGACY 0x00
#define PCI_CLASS_STORAGE 0x01
#define PCI_CLASS_NETWORK 0x02
#define PCI_CLASS_DISPLAY 0x03
#define PCI_CLASS_MULTIMEDIA 0x04
#define PCI_CLASS_MEMORY 0x05
#define PCI_CLASS_BRIDGE_DEVICE 0x06
#define PCI_CLASS_COMMUNICATION 0x07
#define PCI_CLASS_PERIHPERALS 0x08
#define PCI_CLASS_INPUT_DEVICES 0x09
#define PCI_CLASS_DOCKING_STATION 0x0a
#define PCI_CLASS_PROCESSOR 0x0b
#define PCI_CLASS_SERIAL_BUS 0x0c
#define PCI_CLASS_WIRELESS 0x0d
#define PCI_CLASS_INTELLIGENT_IO 0x0e
#define PCI_CLASS_SATELLITE 0x0f
#define PCI_CLASS_CRYPT 0x10
#define PCI_CLASS_SIGNAL_PROCESSING 0x11
#define PCI_CLASS_UNDEFINED 0xff
// Undefined Class
#define PCI_UNCLASSIFIED 0x0000
#define PCI_VGA_COMPATIBLE 0x0001
// Mass Storage Controller
#define PCI_STORAGE_SCSI 0x0100
#define PCI_STORAGE_IDE 0x0101
#define PCI_STORAGE_FLOPPY 0x0102
#define PCI_STORAGE_IPI 0x0103
#define PCI_STORAGE_RAID 0x0104
#define PCI_STORAGE_ATA 0x0105
#define PCI_STORAGE_SATA 0x0106
#define PCI_STORAGE_OTHER 0x0180
// Network Controller
#define PCI_NETWORK_ETHERNET 0x0200
#define PCI_NETWORK_TOKEN_RING 0x0201
#define PCI_NETWORK_FDDI 0x0202
#define PCI_NETWORK_ATM 0x0203
#define PCI_NETWORK_ISDN 0x0204
#define PCI_NETWORK_WORLDFIP 0x0205
#define PCI_NETWORK_PICGMG 0x0206
#define PCI_NETWORK_OTHER 0x0280
// Display Controller
#define PCI_DISPLAY_VGA 0x0300
#define PCI_DISPLAY_XGA 0x0301
#define PCI_DISPLAY_3D 0x0302
#define PCI_DISPLAY_OTHER 0x0380
// Multimedia Controller
#define PCI_MULTIMEDIA_VIDEO 0x0400
#define PCI_MULTIMEDIA_AUDIO 0x0401
#define PCI_MULTIMEDIA_PHONE 0x0402
#define PCI_MULTIMEDIA_AUDIO_DEVICE 0x0403
#define PCI_MULTIMEDIA_OTHER 0x0480
// Memory Controller
#define PCI_MEMORY_RAM 0x0500
#define PCI_MEMORY_FLASH 0x0501
#define PCI_MEMORY_OTHER 0x0580
// Bridge Device
#define PCI_BRIDGE_HOST 0x0600
#define PCI_BRIDGE_ISA 0x0601
#define PCI_BRIDGE_EISA 0x0602
#define PCI_BRIDGE_MCA 0x0603
#define PCI_BRIDGE_PCI 0x0604
#define PCI_BRIDGE_PCMCIA 0x0605
#define PCI_BRIDGE_NUBUS 0x0606
#define PCI_BRIDGE_CARDBUS 0x0607
#define PCI_BRIDGE_RACEWAY 0x0608
#define PCI_BRIDGE_OTHER 0x0680
// Simple Communication Controller
#define PCI_COMM_SERIAL 0x0700
#define PCI_COMM_PARALLEL 0x0701
#define PCI_COMM_MULTIPORT 0x0702
#define PCI_COMM_MODEM 0x0703
#define PCI_COMM_GPIB 0x0704
#define PCI_COMM_SMARTCARD 0x0705
#define PCI_COMM_OTHER 0x0780
// Base System Peripherals
#define PCI_SYSTEM_PIC 0x0800
#define PCI_SYSTEM_DMA 0x0801
#define PCI_SYSTEM_TIMER 0x0802
#define PCI_SYSTEM_RTC 0x0803
#define PCI_SYSTEM_PCI_HOTPLUG 0x0804
#define PCI_SYSTEM_SD 0x0805
#define PCI_SYSTEM_OTHER 0x0880
// Input Devices
#define PCI_INPUT_KEYBOARD 0x0900
#define PCI_INPUT_PEN 0x0901
#define PCI_INPUT_MOUSE 0x0902
#define PCI_INPUT_SCANNER 0x0903
#define PCI_INPUT_GAMEPORT 0x0904
#define PCI_INPUT_OTHER 0x0980
// Docking Stations
#define PCI_DOCKING_GENERIC 0x0a00
#define PCI_DOCKING_OTHER 0x0a80
// Processors
#define PCI_PROCESSOR_386 0x0b00
#define PCI_PROCESSOR_486 0x0b01
#define PCI_PROCESSOR_PENTIUM 0x0b02
#define PCI_PROCESSOR_ALPHA 0x0b10
#define PCI_PROCESSOR_POWERPC 0x0b20
#define PCI_PROCESSOR_MIPS 0x0b30
#define PCI_PROCESSOR_CO 0x0b40
// Serial Bus Controllers
#define PCI_SERIAL_FIREWIRE 0x0c00
#define PCI_SERIAL_ACCESS 0x0c01
#define PCI_SERIAL_SSA 0x0c02
#define PCI_SERIAL_USB 0x0c03
#define PCI_SERIAL_FIBER 0x0c04
#define PCI_SERIAL_SMBUS 0x0c05
#define PCI_SERIAL_USB_UHCI 0x00
#define PCI_SERIAL_USB_OHCI 0x10
#define PCI_SERIAL_USB_EHCI 0x20
#define PCI_SERIAL_USB_XHCI 0x30
#define PCI_SERIAL_USB_OTHER 0x80
// Wireless Controllers
#define PCI_WIRELESS_IRDA 0x0d00
#define PCI_WIRLESSS_IR 0x0d01
#define PCI_WIRLESSS_RF 0x0d10
#define PCI_WIRLESSS_BLUETOOTH 0x0d11
#define PCI_WIRLESSS_BROADBAND 0x0d12
#define PCI_WIRLESSS_ETHERNET_A 0x0d20
#define PCI_WIRLESSS_ETHERNET_B 0x0d21
#define PCI_WIRELESS_OTHER 0x0d80
// Intelligent I/O Controllers
#define PCI_INTELLIGENT_I2O 0x0e00
// Satellite Communication Controllers
#define PCI_SATELLITE_TV 0x0f00
#define PCI_SATELLITE_AUDIO 0x0f01
#define PCI_SATELLITE_VOICE 0x0f03
#define PCI_SATELLITE_DATA 0x0f04
// Encryption/Decryption Controllers
#define PCI_CRYPT_NETWORK 0x1000
#define PCI_CRYPT_ENTERTAINMENT 0x1001
#define PCI_CRYPT_OTHER 0x1080
// Data Acquisition and Signal Processing Controllers
#define PCI_SP_DPIO 0x1100
#define PCI_SP_OTHER 0x1180
const char *pci_devname(uint32_t vendorid, uint32_t deviceid);
const char *pci_classname(uint32_t classcode, uint32_t subclass, uint32_t progintf);
#endif // PCI_REG_H_

View File

@ -19,6 +19,7 @@
#include "intr/pic.h" #include "intr/pic.h"
#include "vmm/vmm.h" #include "vmm/vmm.h"
#include "proc/switch.h" #include "proc/switch.h"
#include "cjob/cjob.h"
#include "elf.h" #include "elf.h"
#include "errors.h" #include "errors.h"
#include "kprintf.h" #include "kprintf.h"
@ -174,7 +175,33 @@ Proc *proc_nextready(void) {
} }
} }
void proc_reaper(void) { void proc_sched(void *cpustate) {
intr_disable();
memcpy(&PROCS.current->platformdata.trapframe, cpustate, sizeof(IntrStackFrame));
PROCS.current = proc_nextready();
cjob_runjobs();
tss.rsp0 = (uint64_t)VIRT(PROCS.current->platformdata.kstack);
proc_switch(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
}
void proc_kill(Proc *proc) {
spinlock_acquire(&PROCS.spinlock);
proc->state = PROC_ZOMBIE;
spinlock_release(&PROCS.spinlock);
}
void proc_killself(void) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
proc_kill(proc);
}
void proc_gc_cjob(void *arg) {
spinlock_acquire(&PROCS.spinlock); spinlock_acquire(&PROCS.spinlock);
Proc *head, *tmp; Proc *head, *tmp;
LL_FOREACH_SAFE(PROCS.procs, head, tmp) { LL_FOREACH_SAFE(PROCS.procs, head, tmp) {
@ -222,41 +249,12 @@ void proc_reaper(void) {
spinlock_release(&PROCS.spinlock); spinlock_release(&PROCS.spinlock);
} }
void proc_tick(void) {
proc_reaper();
ipc_mbustick();
}
void proc_sched(void *cpustate) {
intr_disable();
memcpy(&PROCS.current->platformdata.trapframe, cpustate, sizeof(IntrStackFrame));
PROCS.current = proc_nextready();
proc_tick();
tss.rsp0 = (uint64_t)VIRT(PROCS.current->platformdata.kstack);
proc_switch(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3);
}
void proc_kill(Proc *proc) {
spinlock_acquire(&PROCS.spinlock);
proc->state = PROC_ZOMBIE;
spinlock_release(&PROCS.spinlock);
}
void proc_killself(void) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock);
proc_kill(proc);
}
void proc_init(void) { void proc_init(void) {
spinlock_init(&PROCS.spinlock); spinlock_init(&PROCS.spinlock);
PROCS.procs = NULL; PROCS.procs = NULL;
cjob_register(&proc_gc_cjob, NULL);
Proc *init = proc_spawnuser("base", "/bin/init"); Proc *init = proc_spawnuser("base", "/bin/init");
PROCS.current = init; PROCS.current = init;
proc_register(init); proc_register(init);

View File

@ -2,10 +2,7 @@
.global proc_switch .global proc_switch
proc_switch: proc_switch:
testq %rsi, %rsi
je 1f
movq %rsi, %cr3 movq %rsi, %cr3
1:
mov %rdi, %rsp mov %rdi, %rsp
_pop_regs _pop_regs
add $0x10, %rsp add $0x10, %rsp

View File

@ -6,8 +6,8 @@
#define SPINLOCK_HINT() asm volatile("pause") #define SPINLOCK_HINT() asm volatile("pause")
struct { static struct {
uint64_t irq_flags; volatile uint64_t irq_flags;
atomic_int irq_nest; atomic_int irq_nest;
} IRQ_CTX = {0}; } IRQ_CTX = {0};

View File

@ -6,6 +6,6 @@ qemu-system-x86_64 \
-machine pc \ -machine pc \
-m 4G \ -m 4G \
-boot d \ -boot d \
-serial stdio \ -hda disk.hdd \
-drive file=disk.hdd,format=raw,if=ide \ -device pci-serial,chardev=char0 -chardev stdio,id=char0 \
$@ $@

View File

@ -17,6 +17,8 @@
#define E_SPAWNERROR -13 #define E_SPAWNERROR -13
#define E_NOTYET -14 #define E_NOTYET -14
#define E_MOUNTERR -15 #define E_MOUNTERR -15
#define E_DEVLOCKED -16
#define E_DEVNOTYOURLOCK -17
#if !defined(__ASSEMBLER__) #if !defined(__ASSEMBLER__)
@ -38,6 +40,8 @@ static const char *_ERROR_STRINGS[] = {
"Process spawn error", "Process spawn error",
"Data isn't ready yet", "Data isn't ready yet",
"File system mount error", "File system mount error",
"This device is locked",
"Device is hasn't been locked by this process",
}; };
#define ERRSTRING_INDEX(ioh) ((size_t)((ioh) < 0 ? (ioh) * (-1) : (ioh))) #define ERRSTRING_INDEX(ioh) ((size_t)((ioh) < 0 ? (ioh) * (-1) : (ioh)))

View File

@ -4,11 +4,6 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define DEV_SERIALDEV_SENDB 0
#define DEV_SERIALDEV_SENDREADY 1
#define DEV_SERIALDEV_RECVB 2
#define DEV_SERIALDEV_RECVREADY 3
#define DEV_STOREDEV_READ 0 #define DEV_STOREDEV_READ 0
#define DEV_STOREDEV_WRITE 1 #define DEV_STOREDEV_WRITE 1
#define DEV_STOREDEV_SECCOUNT 2 #define DEV_STOREDEV_SECCOUNT 2

View File

@ -9,8 +9,8 @@
#include <umalloc/umalloc.h> #include <umalloc/umalloc.h>
extern void main(void); extern void main(void);
extern uint8_t _bss_start[]; extern volatile uint8_t _bss_start[];
extern uint8_t _bss_end[]; extern volatile uint8_t _bss_end[];
void clearbss(void) { void clearbss(void) {
uint8_t *p = _bss_start; uint8_t *p = _bss_start;
@ -20,7 +20,7 @@ void clearbss(void) {
} }
#define MAX_ARGS 25 #define MAX_ARGS 25
static char *_args[MAX_ARGS]; static volatile char *_args[MAX_ARGS];
size_t _argslen; size_t _argslen;
@ -40,7 +40,7 @@ void _premain(void) {
_args[i] = umalloc(PROC_ARG_MAX); _args[i] = umalloc(PROC_ARG_MAX);
} }
proc_argv(-1, &_argslen, _args, MAX_ARGS); proc_argv(-1, &_argslen, (char **)_args, MAX_ARGS);
main(); main();
proc_kill(proc_getpid()); proc_kill(proc_getpid());

View File

@ -4,4 +4,9 @@
.global _start .global _start
_start: _start:
xor %rbp, %rbp
mov %rsp, %rbp
and $-0x10, %rsp
sub $0x8, %rsp
call _premain call _premain

View File

@ -2,7 +2,7 @@
#define CMDS(X) \ #define CMDS(X) \
X(block) X(openf) \ X(block) X(openf) \
X(serialprint) X(srpr) X(srpr2) \
void main(void) { void main(void) {
if (argslen() == 0) { if (argslen() == 0) {

View File

@ -2,7 +2,14 @@
#include <stddef.h> #include <stddef.h>
#include <ulib.h> #include <ulib.h>
void diagdummy_serialprint(void) { #define SENDB 0
#define SENDREADY 1
#define RECVB 2
#define RECVREADY 3
#define LOCK 4
#define UNLOCK 5
void diagdummy_srpr(void) {
char *str = "Hello world\n"; char *str = "Hello world\n";
if (argslen() >= 2) { if (argslen() >= 2) {
@ -14,8 +21,29 @@ void diagdummy_serialprint(void) {
char *s = str; char *s = str;
while (*s) { while (*s) {
while(!dev_cmd(&serialdev, DEV_SERIALDEV_SENDREADY, NULL, 0)); while(!dev_cmd(&serialdev, SENDREADY, NULL, 0));
dev_cmd(&serialdev, DEV_SERIALDEV_SENDB, s, 1); dev_cmd(&serialdev, SENDB, s, 1);
s++; s++;
} }
} }
void diagdummy_srpr2(void) {
if (argslen() < 2) {
return;
}
char *str = args()[1];
Dev_t serialdev;
dev_gethandle(&serialdev, "serialdev");
while(dev_cmd(&serialdev, LOCK, NULL, 0) != E_OK);
for (;;) {
while (!dev_cmd(&serialdev, SENDREADY, NULL, 0));
dev_cmd(&serialdev, SENDB, str, 1);
schedsleep(500);
}
dev_cmd(&serialdev, UNLOCK, NULL, 0);
}