Skip to content
This repository has been archived by the owner on Jul 12, 2020. It is now read-only.

WIP: Add serial driver #77

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ obj_directories:

# Run bootable ISO
run: dist/panix.iso
$(QEMU) -drive format=raw,file=$< -soundhw pcspk -rtc clock=host -vga std
$(QEMU) -drive format=raw,file=$< -soundhw pcspk -rtc clock=host -vga std -serial mon:stdio

# Install BIN file to local system
install: dist/panix.bin
Expand Down
79 changes: 79 additions & 0 deletions include/drivers/serial/Rs232.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* @file Rs232.hpp
* @author Micah Switzer (mswitzer@cedarville.edu)
* @brief
* @version 0.1
* @date 2019-09-30
*
* @copyright Copyright (c) 2019
*
*/
#ifndef PANIX_RS232_DRIVER
#define PANIX_RS232_DRIVER

#include <types.hpp>
#include <cpu/port/Port.hpp>
#include <cpu/interrupts/InterruptHandler.hpp>
#include <cpu/interrupts/InterruptManager.hpp>
#include <drivers/Driver.hpp>
#include <drivers/DriverManager.hpp>
#include <libc/string.hpp>
#include <libc/kprint.hpp>

#define COM1 0x3F8
#define COM2 0x2F8
#define COM3 0x3E8
#define COM4 0x2E8

#define COM1_IRQ 0x04
#define COM3_IRQ 0x04
#define COM2_IRQ 0x03
#define COM4_IRQ 0x03

#define DATA_REG 0
#define INTERRUPT_ENABLE_REG 1
#define INTERRUPT_IDENTIFICATION_REG 2
#define LINE_CONTROL_REG 3
#define MODEM_CONTROL_REG 4
#define LINE_STATUS_REG 5
#define MODEM_STATUS_REG 6
#define SCRATCH_REG 7

#define BUF_SIZE 75

class Rs232 : public InterruptHandler, public Driver {
private:
char* lineBuffer[BUF_SIZE];
uint8_t lineIndex;
uint16_t portBase;

char readSerial();
int serialReceived();
int isTransmitEmpty();
void writeSerial(char a);

public:
micahswitzer marked this conversation as resolved.
Show resolved Hide resolved
Rs232(uint16_t portNum, InterruptManager* interruptManager);
~Rs232();
void activate();
void deactivate();
void print(char* str);
/**
* @brief
*
* @param esp
* @return uint32_t
*/
uint32_t handleInterrupt(uint32_t esp);
/**
* @brief Returns the short tag type of the driver. Used to identify
* the driver and its purpose. Used by the driver manager to get a
* specific driver type.
*
* @return char* Short driver type tag
*/
char* getDriverTypeTag();
};

#endif /* PANIX_RS232_DRIVER */

1 change: 1 addition & 0 deletions include/kernel/kernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <drivers/speaker/Speaker.hpp>
#include <drivers/timer/Timer.hpp>
#include <drivers/rtc/RTC.hpp>
#include <drivers/serial/Rs232.hpp>
// Graphical Interface
#include <kernel/gui/Desktop.hpp>
#include <kernel/gui/Window.hpp>
Expand Down
79 changes: 79 additions & 0 deletions src/drivers/serial/Rs232.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* @file Rs232.cpp
* @author Micah Switzer (mswitzer@cedarville.edu)
* @brief
* @version 0.1
* @date 2019-09-30
*
* @copyright Copyright (c) 2019
*
*/
#include <drivers/serial/Rs232.hpp>

Rs232::Rs232(uint16_t portNum, InterruptManager* interruptManager) :
InterruptHandler(interruptManager, 0x20 + (portNum == COM1 ? COM1_IRQ : COM2_IRQ)),
portBase(portNum),
lineIndex(0) {
}

Rs232::~Rs232() {
// stubbed
}

char Rs232::readSerial() {
while (serialReceived() == 0);
return readByte(portBase + DATA_REG);
}

int Rs232::serialReceived() {
return readByte(portBase + LINE_STATUS_REG) & 1;
}

int Rs232::isTransmitEmpty() {
return readByte(portBase + LINE_STATUS_REG) & 0x20;
}

void Rs232::writeSerial(char a) {
while (isTransmitEmpty() == 0);
writeByte(portBase + DATA_REG, a);
}

void Rs232::activate() {
// disable interrupts
writeByte(portBase + INTERRUPT_ENABLE_REG, 0x00);
writeByte(portBase + LINE_CONTROL_REG, 0x80);
writeByte(portBase + DATA_REG, 0x03);
writeByte(portBase + INTERRUPT_ENABLE_REG, 0x00);
writeByte(portBase + LINE_CONTROL_REG, 0x03);
writeByte(portBase + INTERRUPT_IDENTIFICATION_REG, 0xC7);
writeByte(portBase + MODEM_CONTROL_REG, 0x0B);
writeByte(portBase + LINE_CONTROL_REG, 0x00);
// re-enable interrupts
writeByte(portBase + INTERRUPT_ENABLE_REG, 0x01);
}

void Rs232::deactivate() {
micahswitzer marked this conversation as resolved.
Show resolved Hide resolved
// stubbed
}

void Rs232::print(char* str) {
int i = 0;
while (str[i] != 0) {
writeSerial(str[i]);
++i;
}
}

uint32_t Rs232::handleInterrupt(uint32_t esp) {
//if (lineIndex == BUF_SIZE)
char str[2] = { readSerial(), '\0' };
if (str[0] == '\r') {
print("\n");
}
print(str);
return esp;
}

char* Rs232::getDriverTypeTag() {
return "RS232";
}
4 changes: 4 additions & 0 deletions src/kernel/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ extern "C" void kernelMain(const void* multiboot_structure, uint32_t multiboot_m
// PCI Interface Driver
PeripheralComponentInterconnectController PCIController;
PCIController.SelectDrivers(&driverManager, &interruptManager);
Rs232 serial = Rs232(COM1, &interruptManager);
driverManager.addDriver(&serial);

// If we put all of the code in startShellAsProcess here then it works.
// But if we make the call to it here then it doesn't.
Expand All @@ -94,6 +96,8 @@ extern "C" void kernelMain(const void* multiboot_structure, uint32_t multiboot_m
kprint("Stage 2 - Activating Drivers...\n");
kprintSetColor(White, Black);
driverManager.activateAll();

serial.print("I think it works?\n");

/*********************************
* STAGE 3 - ACTIVATE INTERRUPTS *
Expand Down