summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/ata.c58
-rw-r--r--kernel/include/comus/drivers/ata.h1
-rw-r--r--kernel/include/comus/procs.h5
-rw-r--r--kernel/include/comus/syscalls.h5
-rw-r--r--kernel/syscall.c99
5 files changed, 141 insertions, 27 deletions
diff --git a/kernel/drivers/ata.c b/kernel/drivers/ata.c
index 6f53d04..2fc059f 100644
--- a/kernel/drivers/ata.c
+++ b/kernel/drivers/ata.c
@@ -252,6 +252,7 @@ static enum ide_error ide_channel_poll(struct ide_channel *channel,
if (advanced_check) {
uint8_t state = ide_channel_read(channel, ATA_REG_STATUS);
+ // check for errors or faults
if (state & ATA_SR_ERROR) {
return IDE_ERROR_POLL_STATUS_REGISTER_ERROR;
}
@@ -260,7 +261,7 @@ static enum ide_error ide_channel_poll(struct ide_channel *channel,
return IDE_ERROR_POLL_DEVICE_FAULT;
}
- // BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
+ // then check if drive is ready
if ((state & ATA_SR_DRIVEREQUESTREADY) == 0) {
return IDE_ERROR_POLL_DRIVE_REQUEST_NOT_READY;
}
@@ -322,7 +323,7 @@ static void ide_error_print(struct ide_device *dev, const enum ide_error err)
static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
uint32_t BAR3, uint32_t BAR4)
{
- // 1- Detect I/O Ports which interface IDE Controller:
+ // calculate which io ports interface with the IDE controller
ide_channels[ATA_PRIMARY] = (struct ide_channel){
.io_base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0),
.control_base = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1),
@@ -334,11 +335,13 @@ static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
.bus_master_ide_base = (BAR4 & 0xFFFFFFFC) + 8,
};
- // 2- Disable IRQs:
+ // disable irqs
ide_channel_write(channel(ATA_PRIMARY), ATA_REG_CONTROL, 2);
ide_channel_write(channel(ATA_SECONDARY), ATA_REG_CONTROL, 2);
- // 3- Detect ATA-ATAPI Devices:
+ // detect disks by writing CMD_IDENTIFY to each one and checking for err.
+ // if device exists, ask for its ID space and copy out info about the
+ // device into the ide_device struct
uint32_t device_count = 0;
for (uint8_t channel_idx = 0; channel_idx < 2; channel_idx++) {
// drive idx is like device_count but it starts at 0 per channel
@@ -362,7 +365,7 @@ static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
kspin_milliseconds(1);
if (ide_channel_read(chan, ATA_REG_STATUS) == 0) {
- continue; // if status == 0, no device.
+ continue; // if status == 0, no device
}
bool ata_err = false;
@@ -383,7 +386,7 @@ static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
}
}
- // probe for ATAPI devices, if needed
+ // probe for ATAPI devices, though they aren't implemented
uint8_t type = IDE_ATA;
if (ata_err) {
uint8_t cl = ide_channel_read(chan, ATA_REG_LBA1);
@@ -396,7 +399,7 @@ static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
WARN("ATAPI device found but ATAPI is not supported");
type = IDE_ATAPI;
} else {
- // unknown type (may not be a device).
+ // unknown type (may not be a device?)
continue;
}
@@ -425,16 +428,16 @@ static void ide_initialize(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2,
// get size (depends on address mode):
if (dev->supported_command_sets & (1 << 26)) {
- // device uses 48-bit addressing:
+ // lba48
dev->size_in_sectors =
*((uint32_t *)(id_space_buf + ATA_IDENT_MAX_LBA_EXT));
} else {
- // device uses CHS or 28-bit dddressing:
+ // lba28
dev->size_in_sectors =
*((uint32_t *)(id_space_buf + ATA_IDENT_MAX_LBA));
}
- // string indicates model of device (Western Digital HDD, SONY DVD-RW...)
+ // string indicates model of device like "Western Digital HDD" etc
for (uint8_t i = 0; i < 40; i += 2) {
dev->model_str[i] = id_space_buf[ATA_IDENT_MODEL + i + 1];
dev->model_str[i + 1] = id_space_buf[ATA_IDENT_MODEL + i];
@@ -460,13 +463,13 @@ enum access_mode {
static uint8_t get_ata_cmd_for_access(enum lba_mode lba_mode,
enum access_mode mode)
{
- // routine that is followed:
- // If ( DMA & LBA48) DO_DMA_EXT;
- // If ( DMA & LBA28) DO_DMA_LBA;
- // If ( DMA & LBA28) DO_DMA_CHS;
- // If (!DMA & LBA48) DO_PIO_EXT;
- // If (!DMA & LBA28) DO_PIO_LBA;
- // If (!DMA & !LBA#) DO_PIO_CHS;
+ // outline of the algorithm:
+ // If ( dma & lba48) DO_DMA_EXT;
+ // If ( dma & lba28) DO_DMA_LBA;
+ // If ( dma & lba28) DO_DMA_CHS;
+ // If (!dma & lba48) DO_PIO_EXT;
+ // If (!dma & lba28) DO_PIO_LBA;
+ // If (!dma & !lba#) DO_PIO_CHS;
if (mode == READ) {
switch (lba_mode) {
@@ -500,7 +503,7 @@ static uint8_t get_ata_cmd_for_access(enum lba_mode lba_mode,
// if (lba_mode == 2 && dma == 1 && direction == 1)
// cmd = ATA_CMD_WRITE_DMA_EXT;
}
- // NOTE: unreachable
+ panic("unreachable");
return -1;
}
@@ -520,7 +523,8 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
ide_channel_write(chan, ATA_REG_CONTROL,
chan->no_interrupt = (ide_irq_invoked = 0x0) + 0x02);
- // select one from LBA28, LBA48 or CHS
+ // select one from lba28, lba48 or CHS, and fill lba_io with the parameters
+ // for the disk access command
if (lba >= 0x10000000 || numsects > UINT8_MAX) {
// drive should support LBA in this case, or you are giving a bad LBA
lba_mode = LBA48;
@@ -561,7 +565,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
if (dev->drive_idx > 1)
panic("unexpected drive_idx");
- // select Drive from the controller
+ // select our drive
if (lba_mode == CHS) {
ide_channel_write(chan, ATA_REG_HDDEVSEL,
0xA0 | (dev->drive_idx << 4) | head);
@@ -572,7 +576,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
ide_channel_write(chan, ATA_REG_HDDEVSEL, 0x40 | (dev->drive_idx << 4));
}
- // write Parameters
+ // actually write the parameters
if (lba_mode == LBA48) {
ide_channel_write(chan, ATA_REG_SECCOUNT1, (numsects >> 8) & 0xff);
ide_channel_write(chan, ATA_REG_LBA3, lba_io[3]);
@@ -589,7 +593,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
// TODO: if (dma) { ... } else {
if (mode == READ) {
- // PIO read
+ // just read all the bytes of the sectors out of the io port
for (size_t i = 0; i < numsects; i++) {
enum ide_error ret = ide_channel_poll(chan, 1);
if (ret)
@@ -599,7 +603,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
rep_inw(chan->io_base, &buf[i * 256], 256);
}
} else {
- // PIO write
+ // just write all the bytes of the sectors into the io port
for (size_t i = 0; i < numsects; i++) {
enum ide_error err = ide_channel_poll(chan, 0);
#if LOG_LEVEL >= LOG_LVL_WARN
@@ -610,13 +614,15 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
#endif
rep_outw(chan->io_base, &buf[i * 256], 256);
}
+
+ // flush the cache to fully complete the write
ide_channel_write(chan, ATA_REG_COMMAND,
(uint8_t[]){ ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH,
ATA_CMD_CACHE_FLUSH_EXT }[lba_mode]);
enum ide_error err = ide_channel_poll(chan, 0);
#if LOG_LEVEL >= LOG_LVL_WARN
if (err) {
- WARN("DRIVE WRITE FAILED:");
+ WARN("DRIVE WRITE FAILED, CACHE FLUSH ERR:");
ide_error_print(dev, err);
}
#endif
@@ -647,7 +653,9 @@ enum ide_error ide_device_read_sectors(ide_device_t dev_identifier,
// for (i = 0; i < numsects; i++)
// err = ide_atapi_read(drive, lba + i, 1, es, edi + (i*2048));
//panic("atapi unimplemented- todo");
- return 1;
+
+ // soft error instead of panic
+ return IDE_ERROR_UNIMPLEMENTED;
}
if (err) {
diff --git a/kernel/include/comus/drivers/ata.h b/kernel/include/comus/drivers/ata.h
index c404d84..c9ef207 100644
--- a/kernel/include/comus/drivers/ata.h
+++ b/kernel/include/comus/drivers/ata.h
@@ -27,6 +27,7 @@ enum ide_error {
IDE_ERROR_POLL_DEVICE_FAULT,
IDE_ERROR_POLL_STATUS_REGISTER_ERROR,
IDE_ERROR_POLL_WRITE_PROTECTED,
+ IDE_ERROR_UNIMPLEMENTED,
};
struct ide_devicelist {
diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h
index 3df31c3..ee723aa 100644
--- a/kernel/include/comus/procs.h
+++ b/kernel/include/comus/procs.h
@@ -75,6 +75,11 @@ struct pcb {
uint64_t syscall;
uint64_t wakeup;
uint8_t exit_status;
+
+ // pipe to check for shared memory
+ void* shared_mem;
+ size_t shared_mem_pages;
+ pid_t shared_mem_source;
};
/// ordering of pcb queues
diff --git a/kernel/include/comus/syscalls.h b/kernel/include/comus/syscalls.h
index 8b671c2..146bce1 100644
--- a/kernel/include/comus/syscalls.h
+++ b/kernel/include/comus/syscalls.h
@@ -31,9 +31,12 @@
#define SYS_drm 18
#define SYS_ticks 19
#define SYS_seek 20
+#define SYS_allocshared 21
+#define SYS_popsharedmem 22
+#define SYS_keypoll 23
// UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED!
-#define N_SYSCALLS 21
+#define N_SYSCALLS 24
// interrupt vector entry for system calls
#define VEC_SYSCALL 0x80
diff --git a/kernel/syscall.c b/kernel/syscall.c
index 44ebfa0..8ed7631 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -3,6 +3,7 @@
#include <comus/user.h>
#include <comus/cpu.h>
#include <comus/syscalls.h>
+#include <comus/input.h>
#include <comus/drivers/acpi.h>
#include <comus/drivers/gpu.h>
#include <comus/drivers/pit.h>
@@ -482,6 +483,99 @@ static int sys_ticks(void)
return 0;
}
+static int sys_popsharedmem(void)
+{
+ RET(void *, res_mem);
+ *res_mem = NULL;
+
+ if (pcb->shared_mem == NULL) {
+ return 1;
+ }
+
+ struct pcb *const sharer = pcb_find_pid(pcb->shared_mem_source);
+ if (sharer == NULL) {
+ // process died or something since sharing
+ pcb->shared_mem = NULL;
+ return 1;
+ }
+
+ void *result =
+ mem_mapaddr(pcb->memctx, mem_get_phys(sharer->memctx, pcb->shared_mem),
+ pcb->shared_mem, pcb->shared_mem_pages * PAGE_SIZE,
+ F_WRITEABLE | F_UNPRIVILEGED);
+
+ // if (!result) {
+ // alert the other process that we cannot get its allocation?
+ // mem_free_pages(pcb->memctx, alloced);
+ // return 1;
+ // }
+
+ *res_mem = result;
+
+ pcb->shared_mem = NULL;
+
+ return 0;
+}
+
+static int sys_allocshared(void)
+{
+ ARG1(size_t, num_pages);
+ ARG2(unsigned short, otherpid); // same as pid_t
+ RET(void *, res_mem);
+ *res_mem = NULL;
+ assert(sizeof(unsigned short) == sizeof(pid_t),
+ "out of date sys_memshare syscall, pid_t changed?");
+
+ if (otherpid == pcb->pid || otherpid == 0) {
+ return 1;
+ }
+
+ struct pcb *const otherpcb = pcb_find_pid(otherpid);
+ if (otherpcb == NULL) {
+ // no such target process exists
+ return 1;
+ }
+ if (otherpcb->shared_mem != NULL) {
+ // it has yet to consume the last allocshared given to it
+ return 1;
+ }
+
+ void *alloced =
+ mem_alloc_pages(pcb->memctx, num_pages, F_WRITEABLE | F_UNPRIVILEGED);
+
+ if (!alloced) {
+ return 1;
+ }
+
+ otherpcb->shared_mem = alloced;
+ otherpcb->shared_mem_source = pcb->pid;
+ otherpcb->shared_mem_pages = num_pages;
+
+ *res_mem = alloced;
+
+ return 0;
+}
+
+// NOTE: observes AND consumes the key event
+static int sys_keypoll(void)
+{
+ ARG1(struct keycode *, keyev);
+ RET(int, waspressed);
+
+ void *ouraddr = kmapuseraddr(pcb->memctx, keyev, sizeof(struct keycode));
+
+ if (keycode_pop(ouraddr)) {
+ kunmapaddr(ouraddr);
+ *waspressed = false;
+ return 0;
+ }
+
+ kunmapaddr(ouraddr);
+
+ *waspressed = true;
+ return 0;
+}
+
static int sys_seek(void)
{
RET(long int, ret);
@@ -498,6 +592,7 @@ static int sys_seek(void)
return 0;
}
+// clang-format off
static int (*syscall_tbl[N_SYSCALLS])(void) = {
[SYS_exit] = sys_exit, [SYS_waitpid] = sys_waitpid,
[SYS_fork] = sys_fork, [SYS_exec] = sys_exec,
@@ -509,8 +604,10 @@ static int (*syscall_tbl[N_SYSCALLS])(void) = {
[SYS_sleep] = sys_sleep, [SYS_brk] = sys_brk,
[SYS_sbrk] = sys_sbrk, [SYS_poweroff] = sys_poweroff,
[SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks,
- [SYS_seek] = sys_seek,
+ [SYS_seek] = sys_seek, [SYS_allocshared] = sys_allocshared,
+ [SYS_popsharedmem] = sys_popsharedmem, [SYS_keypoll] = sys_keypoll,
};
+// clang-format on
void syscall_handler(void)
{