mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Relocate kernel IO port functions to <sortix/kernel/ioport.h>.
This commit is contained in:
parent
7b3e2fa229
commit
25b4125840
14 changed files with 265 additions and 212 deletions
|
@ -33,6 +33,7 @@
|
||||||
#include <sortix/kernel/inode.h>
|
#include <sortix/kernel/inode.h>
|
||||||
#include <sortix/kernel/interlock.h>
|
#include <sortix/kernel/interlock.h>
|
||||||
#include <sortix/kernel/ioctx.h>
|
#include <sortix/kernel/ioctx.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/refcount.h>
|
#include <sortix/kernel/refcount.h>
|
||||||
|
@ -195,7 +196,7 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
|
||||||
|
|
||||||
ATABus* CreateBus(uint16_t portoffset, uint16_t altport)
|
ATABus* CreateBus(uint16_t portoffset, uint16_t altport)
|
||||||
{
|
{
|
||||||
unsigned status = CPU::InPortB(portoffset + STATUS);
|
unsigned status = inport8(portoffset + STATUS);
|
||||||
// Detect if there is no such bus.
|
// Detect if there is no such bus.
|
||||||
if ( status == 0xFF )
|
if ( status == 0xFF )
|
||||||
{
|
{
|
||||||
|
@ -210,7 +211,7 @@ ATABus* CreateBus(uint16_t portoffset, uint16_t altport)
|
||||||
void Wait400NSecs(uint16_t iobase)
|
void Wait400NSecs(uint16_t iobase)
|
||||||
{
|
{
|
||||||
// Now wait 400 ns for the drive to be ready.
|
// Now wait 400 ns for the drive to be ready.
|
||||||
for ( unsigned i = 0; i < 4; i++ ) { CPU::InPortB(iobase + STATUS); }
|
for ( unsigned i = 0; i < 4; i++ ) { inport8(iobase + STATUS); }
|
||||||
}
|
}
|
||||||
|
|
||||||
ATABus::ATABus(uint16_t portoffset, uint16_t altport)
|
ATABus::ATABus(uint16_t portoffset, uint16_t altport)
|
||||||
|
@ -231,30 +232,30 @@ ATADrive* ATABus::Instatiate(unsigned driveid)
|
||||||
curdriveid = 0;
|
curdriveid = 0;
|
||||||
|
|
||||||
uint8_t drivemagic = 0xA0 | (driveid << 4);
|
uint8_t drivemagic = 0xA0 | (driveid << 4);
|
||||||
CPU::OutPortB(iobase + DRIVE_SELECT, drivemagic);
|
outport8(iobase + DRIVE_SELECT, drivemagic);
|
||||||
CPU::OutPortB(iobase + SECTOR_COUNT, 0);
|
outport8(iobase + SECTOR_COUNT, 0);
|
||||||
CPU::OutPortB(iobase + LBA_LOW, 0);
|
outport8(iobase + LBA_LOW, 0);
|
||||||
CPU::OutPortB(iobase + LBA_MID, 0);
|
outport8(iobase + LBA_MID, 0);
|
||||||
CPU::OutPortB(iobase + LBA_HIGH, 0);
|
outport8(iobase + LBA_HIGH, 0);
|
||||||
CPU::OutPortB(iobase + COMMAND, CMD_IDENTIFY);
|
outport8(iobase + COMMAND, CMD_IDENTIFY);
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
status = CPU::InPortB(iobase + STATUS);
|
status = inport8(iobase + STATUS);
|
||||||
if ( !status || status == 0xFF )
|
if ( !status || status == 0xFF )
|
||||||
return errno = ENODEV, (ATADrive*) NULL;
|
return errno = ENODEV, (ATADrive*) NULL;
|
||||||
if ( !(status & STATUS_BUSY) )
|
if ( !(status & STATUS_BUSY) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Check for ATAPI device not following spec.
|
// Check for ATAPI device not following spec.
|
||||||
if ( CPU::InPortB(iobase + LBA_MID) || CPU::InPortB(iobase + LBA_MID) )
|
if ( inport8(iobase + LBA_MID) || inport8(iobase + LBA_MID) )
|
||||||
return errno = ENODEV, (ATADrive*) NULL;
|
return errno = ENODEV, (ATADrive*) NULL;
|
||||||
while ( (status & STATUS_BUSY) || (!(status & STATUS_DATAREADY) && !(status & STATUS_ERROR)) )
|
while ( (status & STATUS_BUSY) || (!(status & STATUS_DATAREADY) && !(status & STATUS_ERROR)) )
|
||||||
status = CPU::InPortB(iobase + STATUS);
|
status = inport8(iobase + STATUS);
|
||||||
if ( status & STATUS_ERROR )
|
if ( status & STATUS_ERROR )
|
||||||
{
|
{
|
||||||
unsigned mid = CPU::InPortB(iobase + LBA_MID);
|
unsigned mid = inport8(iobase + LBA_MID);
|
||||||
unsigned high = CPU::InPortB(iobase + LBA_HIGH);
|
unsigned high = inport8(iobase + LBA_HIGH);
|
||||||
if ( mid == 0x14 && high == 0xEB )
|
if ( mid == 0x14 && high == 0xEB )
|
||||||
{
|
{
|
||||||
//Log::PrintF("Found ATAPI device instead of ATA\n");
|
//Log::PrintF("Found ATAPI device instead of ATA\n");
|
||||||
|
@ -283,7 +284,7 @@ bool ATABus::SelectDrive(unsigned driveid)
|
||||||
if ( 1 < driveid ) { errno = EINVAL; return false; }
|
if ( 1 < driveid ) { errno = EINVAL; return false; }
|
||||||
|
|
||||||
uint8_t drivemagic = 0xA0 | (driveid << 4);
|
uint8_t drivemagic = 0xA0 | (driveid << 4);
|
||||||
CPU::OutPortB(iobase + DRIVE_SELECT, drivemagic);
|
outport8(iobase + DRIVE_SELECT, drivemagic);
|
||||||
Wait400NSecs(iobase);
|
Wait400NSecs(iobase);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +302,7 @@ ATADrive::ATADrive(ATABus* bus, unsigned driveid, uint16_t portoffset, uint16_t
|
||||||
this->iobase = portoffset;
|
this->iobase = portoffset;
|
||||||
this->altport = altport;
|
this->altport = altport;
|
||||||
for ( size_t i = 0; i < 256; i++ )
|
for ( size_t i = 0; i < 256; i++ )
|
||||||
meta[i] = CPU::InPortW(iobase + DATA);
|
meta[i] = inport16(iobase + DATA);
|
||||||
lba48 = meta[META_FLAGS] & FLAG_LBA48;
|
lba48 = meta[META_FLAGS] & FLAG_LBA48;
|
||||||
numsectors = 0;
|
numsectors = 0;
|
||||||
if ( lba48 )
|
if ( lba48 )
|
||||||
|
@ -346,27 +347,27 @@ bool ATADrive::PrepareIO(bool write, off_t sector)
|
||||||
uint8_t mode = (lba48) ? 0x40 : 0xE0;
|
uint8_t mode = (lba48) ? 0x40 : 0xE0;
|
||||||
mode |= driveid << 4;
|
mode |= driveid << 4;
|
||||||
mode |= (lba48) ? 0 : (sector >> 24) & 0x0F;
|
mode |= (lba48) ? 0 : (sector >> 24) & 0x0F;
|
||||||
CPU::OutPortB(iobase + DRIVE_SELECT, mode);
|
outport8(iobase + DRIVE_SELECT, mode);
|
||||||
uint16_t sectorcount = 1;
|
uint16_t sectorcount = 1;
|
||||||
uint8_t sectorcountlow = sectorcount & 0xFF;
|
uint8_t sectorcountlow = sectorcount & 0xFF;
|
||||||
uint8_t sectorcounthigh = (sectorcount >> 8) & 0xFF;
|
uint8_t sectorcounthigh = (sectorcount >> 8) & 0xFF;
|
||||||
if ( lba48 )
|
if ( lba48 )
|
||||||
{
|
{
|
||||||
CPU::OutPortB(iobase + SECTOR_COUNT, sectorcounthigh);
|
outport8(iobase + SECTOR_COUNT, sectorcounthigh);
|
||||||
CPU::OutPortB(iobase + LBA_LOW, (sector >> 24) & 0xFF);
|
outport8(iobase + LBA_LOW, (sector >> 24) & 0xFF);
|
||||||
CPU::OutPortB(iobase + LBA_MID, (sector >> 32) & 0xFF);
|
outport8(iobase + LBA_MID, (sector >> 32) & 0xFF);
|
||||||
CPU::OutPortB(iobase + LBA_HIGH, (sector >> 40) & 0xFF);
|
outport8(iobase + LBA_HIGH, (sector >> 40) & 0xFF);
|
||||||
}
|
}
|
||||||
CPU::OutPortB(iobase + SECTOR_COUNT, sectorcountlow);
|
outport8(iobase + SECTOR_COUNT, sectorcountlow);
|
||||||
CPU::OutPortB(iobase + LBA_LOW, sector & 0xFF);
|
outport8(iobase + LBA_LOW, sector & 0xFF);
|
||||||
CPU::OutPortB(iobase + LBA_MID, (sector >> 8) & 0xFF);
|
outport8(iobase + LBA_MID, (sector >> 8) & 0xFF);
|
||||||
CPU::OutPortB(iobase + LBA_HIGH, (sector >> 16) & 0xFF);
|
outport8(iobase + LBA_HIGH, (sector >> 16) & 0xFF);
|
||||||
uint8_t command = (write) ? CMD_WRITE : CMD_READ;
|
uint8_t command = (write) ? CMD_WRITE : CMD_READ;
|
||||||
if ( lba48 ) { command = (write) ? CMD_WRITE_EXT : CMD_READ_EXT; }
|
if ( lba48 ) { command = (write) ? CMD_WRITE_EXT : CMD_READ_EXT; }
|
||||||
CPU::OutPortB(iobase + COMMAND, command);
|
outport8(iobase + COMMAND, command);
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
uint8_t status = CPU::InPortB(iobase + STATUS);
|
uint8_t status = inport8(iobase + STATUS);
|
||||||
if ( status & STATUS_BUSY ) { continue; }
|
if ( status & STATUS_BUSY ) { continue; }
|
||||||
if ( status & STATUS_DATAREADY ) { break; }
|
if ( status & STATUS_DATAREADY ) { break; }
|
||||||
if ( status & STATUS_ERROR ) { errno = EIO; return false; }
|
if ( status & STATUS_ERROR ) { errno = EIO; return false; }
|
||||||
|
@ -382,10 +383,10 @@ bool ATADrive::ReadSector(off_t sector, uint8_t* dest)
|
||||||
uint16_t* destword = (uint16_t*) dest;
|
uint16_t* destword = (uint16_t*) dest;
|
||||||
for ( size_t i = 0; i < sectorsize/2; i++ )
|
for ( size_t i = 0; i < sectorsize/2; i++ )
|
||||||
{
|
{
|
||||||
destword[i] = CPU::InPortW(iobase + DATA);
|
destword[i] = inport16(iobase + DATA);
|
||||||
}
|
}
|
||||||
Wait400NSecs(iobase);
|
Wait400NSecs(iobase);
|
||||||
CPU::InPortB(iobase + STATUS);
|
inport8(iobase + STATUS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,13 +397,13 @@ bool ATADrive::WriteSector(off_t sector, const uint8_t* src)
|
||||||
const uint16_t* srcword = (const uint16_t*) src;
|
const uint16_t* srcword = (const uint16_t*) src;
|
||||||
for ( size_t i = 0; i < sectorsize/2; i++ )
|
for ( size_t i = 0; i < sectorsize/2; i++ )
|
||||||
{
|
{
|
||||||
CPU::OutPortW(iobase + DATA, srcword[i]);
|
outport16(iobase + DATA, srcword[i]);
|
||||||
}
|
}
|
||||||
Wait400NSecs(iobase);
|
Wait400NSecs(iobase);
|
||||||
CPU::OutPortB(iobase + COMMAND, CMD_FLUSH_CACHE);
|
outport8(iobase + COMMAND, CMD_FLUSH_CACHE);
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
uint8_t status = CPU::InPortB(iobase + STATUS);
|
uint8_t status = inport8(iobase + STATUS);
|
||||||
if ( status & STATUS_ERROR ) { errno = EIO; return false; }
|
if ( status & STATUS_ERROR ) { errno = EIO; return false; }
|
||||||
if ( status & STATUS_DRIVEFAULT ) { errno = EIO; return false; }
|
if ( status & STATUS_DRIVEFAULT ) { errno = EIO; return false; }
|
||||||
if ( !(status & STATUS_BUSY) ) { break; }
|
if ( !(status & STATUS_BUSY) ) { break; }
|
||||||
|
@ -470,7 +471,7 @@ size_t ATADrive::Write(off_t byteoffset, const uint8_t* src, size_t numbytes)
|
||||||
void ATADrive::Initialize()
|
void ATADrive::Initialize()
|
||||||
{
|
{
|
||||||
bus->SelectDrive(driveid);
|
bus->SelectDrive(driveid);
|
||||||
CPU::OutPortB(iobase + COMMAND, CTL_NO_INTERRUPT);
|
outport8(iobase + COMMAND, CTL_NO_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <sortix/kernel/addralloc.h>
|
#include <sortix/kernel/addralloc.h>
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/memorymanagement.h>
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
|
@ -127,14 +128,14 @@ addr_t bgaframebuffer;
|
||||||
|
|
||||||
void WriteRegister(uint16_t index, uint16_t value)
|
void WriteRegister(uint16_t index, uint16_t value)
|
||||||
{
|
{
|
||||||
CPU::OutPortW(VBE_DISPI_IOPORT_INDEX, index);
|
outport16(VBE_DISPI_IOPORT_INDEX, index);
|
||||||
CPU::OutPortW(VBE_DISPI_IOPORT_DATA, value);
|
outport16(VBE_DISPI_IOPORT_DATA, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ReadRegister(uint16_t index)
|
uint16_t ReadRegister(uint16_t index)
|
||||||
{
|
{
|
||||||
CPU::OutPortW(VBE_DISPI_IOPORT_INDEX, index);
|
outport16(VBE_DISPI_IOPORT_INDEX, index);
|
||||||
return CPU::InPortW(VBE_DISPI_IOPORT_DATA);
|
return inport16(VBE_DISPI_IOPORT_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t GetCapability(uint16_t index)
|
uint16_t GetCapability(uint16_t index)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <sortix/kernel/interlock.h>
|
#include <sortix/kernel/interlock.h>
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
#include <sortix/kernel/ioctx.h>
|
#include <sortix/kernel/ioctx.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/process.h>
|
#include <sortix/kernel/process.h>
|
||||||
|
@ -130,8 +131,8 @@ unsigned hwversion[1+NUMCOMPORTS];
|
||||||
static unsigned HardwareProbe(uint16_t port)
|
static unsigned HardwareProbe(uint16_t port)
|
||||||
{
|
{
|
||||||
// Set the value "0xE7" to the FCR to test the status of the FIFO flags.
|
// Set the value "0xE7" to the FCR to test the status of the FIFO flags.
|
||||||
CPU::OutPortB(port + FCR, 0xE7);
|
outport8(port + FCR, 0xE7);
|
||||||
uint8_t iir = CPU::InPortB(port + IIR);
|
uint8_t iir = inport8(port + IIR);
|
||||||
if ( iir & (1U<<6U) )
|
if ( iir & (1U<<6U) )
|
||||||
{
|
{
|
||||||
if ( iir & (1<<7U) )
|
if ( iir & (1<<7U) )
|
||||||
|
@ -145,40 +146,40 @@ static unsigned HardwareProbe(uint16_t port)
|
||||||
// doesn't do it. This is technically undefined behavior, but it is useful
|
// doesn't do it. This is technically undefined behavior, but it is useful
|
||||||
// to detect hardware versions.
|
// to detect hardware versions.
|
||||||
uint16_t anyvalue = 0x2A;
|
uint16_t anyvalue = 0x2A;
|
||||||
CPU::OutPortB(port + SCR, anyvalue);
|
outport8(port + SCR, anyvalue);
|
||||||
return CPU::InPortB(port + SCR) == anyvalue ? UART16450 : UART8250;
|
return inport8(port + SCR) == anyvalue ? UART16450 : UART8250;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void WaitForEmptyBuffers(uint16_t port)
|
static inline void WaitForEmptyBuffers(uint16_t port)
|
||||||
{
|
{
|
||||||
while ( (CPU::InPortB(port + LSR) & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY ) { }
|
while ( (inport8(port + LSR) & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY ) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsLineReady(uint16_t port)
|
static inline bool IsLineReady(uint16_t port)
|
||||||
{
|
{
|
||||||
return CPU::InPortB(port + LSR) & LSR_READY;
|
return inport8(port + LSR) & LSR_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool CanWriteByte(uint16_t port)
|
static inline bool CanWriteByte(uint16_t port)
|
||||||
{
|
{
|
||||||
return CPU::InPortB(port + LSR) & LSR_THRE;
|
return inport8(port + LSR) & LSR_THRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ReadBlocking(uint16_t port, void* buf, size_t size)
|
ssize_t ReadBlocking(uint16_t port, void* buf, size_t size)
|
||||||
{
|
{
|
||||||
if ( SSIZE_MAX < size ) { size = SSIZE_MAX; }
|
if ( SSIZE_MAX < size ) { size = SSIZE_MAX; }
|
||||||
uint8_t* buffer = (uint8_t*) buf;
|
uint8_t* buffer = (uint8_t*) buf;
|
||||||
uint8_t interruptsenabled = CPU::InPortB(port + IER);
|
uint8_t interruptsenabled = inport8(port + IER);
|
||||||
CPU::OutPortB(port + IER, 0);
|
outport8(port + IER, 0);
|
||||||
|
|
||||||
for ( size_t i = 0; i < size; i++ )
|
for ( size_t i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
while ( !IsLineReady(port) ) { }
|
while ( !IsLineReady(port) ) { }
|
||||||
buffer[i] = CPU::InPortB(port + RXR);
|
buffer[i] = inport8(port + RXR);
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForEmptyBuffers(port);
|
WaitForEmptyBuffers(port);
|
||||||
CPU::OutPortB(port + IER, interruptsenabled);
|
outport8(port + IER, interruptsenabled);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,17 +187,17 @@ ssize_t WriteBlocking(uint16_t port, const void* buf, size_t size)
|
||||||
{
|
{
|
||||||
if ( SSIZE_MAX < size ) { size = SSIZE_MAX; }
|
if ( SSIZE_MAX < size ) { size = SSIZE_MAX; }
|
||||||
const uint8_t* buffer = (const uint8_t*) buf;
|
const uint8_t* buffer = (const uint8_t*) buf;
|
||||||
uint8_t interruptsenabled = CPU::InPortB(port + IER);
|
uint8_t interruptsenabled = inport8(port + IER);
|
||||||
CPU::OutPortB(port + IER, 0);
|
outport8(port + IER, 0);
|
||||||
|
|
||||||
for ( size_t i = 0; i < size; i++ )
|
for ( size_t i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
while ( !CanWriteByte(port) ) { }
|
while ( !CanWriteByte(port) ) { }
|
||||||
CPU::OutPortB(port + TXR, buffer[i]);
|
outport8(port + TXR, buffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForEmptyBuffers(port);
|
WaitForEmptyBuffers(port);
|
||||||
CPU::OutPortB(port + IER, interruptsenabled);
|
outport8(port + IER, interruptsenabled);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +211,7 @@ void EarlyInit()
|
||||||
comports[i] = bioscomports[i-1];
|
comports[i] = bioscomports[i-1];
|
||||||
if ( !comports[i] ) { continue; }
|
if ( !comports[i] ) { continue; }
|
||||||
hwversion[i] = HardwareProbe(comports[i]);
|
hwversion[i] = HardwareProbe(comports[i]);
|
||||||
CPU::OutPortB(comports[i] + IER, 0x0);
|
outport8(comports[i] + IER, 0x0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +278,7 @@ ssize_t DevCOMPort::read(ioctx_t* ctx, uint8_t* dest, size_t count)
|
||||||
return errno = EINTR, -1;
|
return errno = EINTR, -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t val = CPU::InPortB(port + RXR);
|
uint8_t val = inport8(port + RXR);
|
||||||
if ( !ctx->copy_to_dest(dest + i, &val, sizeof(val)) )
|
if ( !ctx->copy_to_dest(dest + i, &val, sizeof(val)) )
|
||||||
{
|
{
|
||||||
// TODO: The byte is lost in this case!
|
// TODO: The byte is lost in this case!
|
||||||
|
@ -310,7 +311,7 @@ ssize_t DevCOMPort::write(ioctx_t* ctx, const uint8_t* src, size_t count)
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
if ( !ctx->copy_from_src(&val, src + i, sizeof(val)) )
|
if ( !ctx->copy_from_src(&val, src + i, sizeof(val)) )
|
||||||
return i ? (ssize_t) i : -1;
|
return i ? (ssize_t) i : -1;
|
||||||
CPU::OutPortB(port + TXR, val);
|
outport8(port + TXR, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t) count;
|
return (ssize_t) count;
|
||||||
|
@ -327,7 +328,7 @@ ssize_t DevCOMPort::Read(byte* dest, size_t count)
|
||||||
#if POLL_BLOCKING
|
#if POLL_BLOCKING
|
||||||
return ReadBlocking(port, dest, 1);
|
return ReadBlocking(port, dest, 1);
|
||||||
#endif
|
#endif
|
||||||
uint8_t lsr = CPU::InPortB(port + LSR);
|
uint8_t lsr = inport8(port + LSR);
|
||||||
if ( !(lsr & LSR_READY) )
|
if ( !(lsr & LSR_READY) )
|
||||||
{
|
{
|
||||||
Panic("Can't wait for com data receive event");
|
Panic("Can't wait for com data receive event");
|
||||||
|
@ -339,8 +340,8 @@ ssize_t DevCOMPort::Read(byte* dest, size_t count)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ( count <= sofar ) { break; }
|
if ( count <= sofar ) { break; }
|
||||||
dest[sofar++] = CPU::InPortB(port + RXR);
|
dest[sofar++] = inport8(port + RXR);
|
||||||
} while ( CPU::InPortB(port + LSR) & LSR_READY);
|
} while ( inport8(port + LSR) & LSR_READY);
|
||||||
|
|
||||||
return sofar;
|
return sofar;
|
||||||
}
|
}
|
||||||
|
@ -352,7 +353,7 @@ ssize_t DevCOMPort::Write(const uint8_t* src, size_t count)
|
||||||
#if POLL_BLOCKING
|
#if POLL_BLOCKING
|
||||||
return WriteBlocking(port, src, 1);
|
return WriteBlocking(port, src, 1);
|
||||||
#endif
|
#endif
|
||||||
uint8_t lsr = CPU::InPortB(port + LSR);
|
uint8_t lsr = inport8(port + LSR);
|
||||||
if ( !(lsr & LSR_THRE) )
|
if ( !(lsr & LSR_THRE) )
|
||||||
{
|
{
|
||||||
Panic("Can't wait for com data sent event");
|
Panic("Can't wait for com data sent event");
|
||||||
|
@ -364,8 +365,8 @@ ssize_t DevCOMPort::Write(const uint8_t* src, size_t count)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ( count <= sofar ) { break; }
|
if ( count <= sofar ) { break; }
|
||||||
CPU::OutPortB(port + TXR, src[sofar++]);
|
outport8(port + TXR, src[sofar++]);
|
||||||
} while ( CPU::InPortB(port + LSR) & LSR_THRE );
|
} while ( inport8(port + LSR) & LSR_THRE );
|
||||||
|
|
||||||
return sofar;
|
return sofar;
|
||||||
}
|
}
|
||||||
|
@ -378,27 +379,27 @@ void DevCOMPort::OnInterrupt()
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t iir = CPU::InPortB(port + IIR);
|
uint8_t iir = inport8(port + IIR);
|
||||||
if ( iir & IIR_NO_INTERRUPT ) { return; }
|
if ( iir & IIR_NO_INTERRUPT ) { return; }
|
||||||
uint8_t intrtype = iir & IIR_INTERRUPT_TYPE;
|
uint8_t intrtype = iir & IIR_INTERRUPT_TYPE;
|
||||||
switch ( intrtype )
|
switch ( intrtype )
|
||||||
{
|
{
|
||||||
case IIR_TIMEOUT:
|
case IIR_TIMEOUT:
|
||||||
CPU::InPortB(port + RXR);
|
inport8(port + RXR);
|
||||||
break;
|
break;
|
||||||
case IIR_RECV_LINE_STATUS:
|
case IIR_RECV_LINE_STATUS:
|
||||||
// TODO: Proper error handling!
|
// TODO: Proper error handling!
|
||||||
CPU::InPortB(port + LSR);
|
inport8(port + LSR);
|
||||||
break;
|
break;
|
||||||
case IIR_RECV_DATA:
|
case IIR_RECV_DATA:
|
||||||
Panic("Can't wait for com data sent event");
|
Panic("Can't wait for com data sent event");
|
||||||
break;
|
break;
|
||||||
case IIR_SENT_DATA:
|
case IIR_SENT_DATA:
|
||||||
Panic("Can't wait for com data sent event");
|
Panic("Can't wait for com data sent event");
|
||||||
CPU::InPortB(port + IIR);
|
inport8(port + IIR);
|
||||||
break;
|
break;
|
||||||
case IIR_MODEM_STATUS:
|
case IIR_MODEM_STATUS:
|
||||||
CPU::InPortB(port + MSR);
|
inport8(port + MSR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,13 +450,13 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
|
||||||
| IER_LINE_STATUS
|
| IER_LINE_STATUS
|
||||||
| IER_MODEM_STATUS;
|
| IER_MODEM_STATUS;
|
||||||
#endif
|
#endif
|
||||||
CPU::OutPortB(port + FCR, 0);
|
outport8(port + FCR, 0);
|
||||||
CPU::OutPortB(port + LCR, 0x80);
|
outport8(port + LCR, 0x80);
|
||||||
CPU::OutPortB(port + DLL, 0xC);
|
outport8(port + DLL, 0xC);
|
||||||
CPU::OutPortB(port + DLM, 0x0);
|
outport8(port + DLM, 0x0);
|
||||||
CPU::OutPortB(port + LCR, 0x3); // 8n1
|
outport8(port + LCR, 0x3); // 8n1
|
||||||
CPU::OutPortB(port + MCR, 0x3); // DTR + RTS
|
outport8(port + MCR, 0x3); // DTR + RTS
|
||||||
CPU::OutPortB(port + IER, interrupts);
|
outport8(port + IER, interrupts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
#include <sortix/kernel/debugger.h>
|
#include <sortix/kernel/debugger.h>
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/keyboard.h>
|
#include <sortix/kernel/keyboard.h>
|
||||||
#include <sortix/kernel/memorymanagement.h>
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
|
@ -65,18 +66,18 @@ void SetCursor(int x, int y)
|
||||||
// CRT Control Register of the VGA controller. These
|
// CRT Control Register of the VGA controller. These
|
||||||
// are the high and low bytes of the index that show
|
// are the high and low bytes of the index that show
|
||||||
// where the hardware cursor is to be 'blinking'.
|
// where the hardware cursor is to be 'blinking'.
|
||||||
CPU::OutPortB(0x3D4, 14);
|
outport8(0x3D4, 14);
|
||||||
CPU::OutPortB(0x3D5, (value >> 8) & 0xFF);
|
outport8(0x3D5, (value >> 8) & 0xFF);
|
||||||
CPU::OutPortB(0x3D4, 15);
|
outport8(0x3D4, 15);
|
||||||
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
outport8(0x3D5, (value >> 0) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCursor(int* x, int* y)
|
void GetCursor(int* x, int* y)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(0x3D4, 14);
|
outport8(0x3D4, 14);
|
||||||
uint8_t high = CPU::InPortB(0x3D5);
|
uint8_t high = inport8(0x3D5);
|
||||||
CPU::OutPortB(0x3D4, 15);
|
outport8(0x3D4, 15);
|
||||||
uint8_t low = CPU::InPortB(0x3D5);
|
uint8_t low = inport8(0x3D5);
|
||||||
unsigned value = high << 8 | low;
|
unsigned value = high << 8 | low;
|
||||||
*x = value % 80;
|
*x = value % 80;
|
||||||
*y = value / 80;
|
*y = value / 80;
|
||||||
|
@ -241,8 +242,8 @@ void ReadCommand(char* buffer, size_t buffer_length)
|
||||||
const uint16_t DATA = 0x0;
|
const uint16_t DATA = 0x0;
|
||||||
//const uint16_t COMMAND = 0x0;
|
//const uint16_t COMMAND = 0x0;
|
||||||
const uint16_t STATUS = 0x4;
|
const uint16_t STATUS = 0x4;
|
||||||
while ( (CPU::InPortB(iobase + STATUS) & (1<<0)) == 0 );
|
while ( (inport8(iobase + STATUS) & (1<<0)) == 0 );
|
||||||
uint8_t scancode = CPU::InPortB(iobase + DATA);
|
uint8_t scancode = inport8(iobase + DATA);
|
||||||
|
|
||||||
// Handle escaped scancodes.
|
// Handle escaped scancodes.
|
||||||
const uint8_t SCANCODE_ESCAPE = 0xE0;
|
const uint8_t SCANCODE_ESCAPE = 0xE0;
|
||||||
|
|
|
@ -35,12 +35,6 @@ namespace Sortix {
|
||||||
// Functions for 32-bit and 64-bit x86.
|
// Functions for 32-bit and 64-bit x86.
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
void OutPortB(uint16_t Port, uint8_t Value);
|
|
||||||
void OutPortW(uint16_t Port, uint16_t Value);
|
|
||||||
void OutPortL(uint16_t Port, uint32_t Value);
|
|
||||||
uint8_t InPortB(uint16_t Port);
|
|
||||||
uint16_t InPortW(uint16_t Port);
|
|
||||||
uint32_t InPortL(uint16_t Port);
|
|
||||||
void Reboot();
|
void Reboot();
|
||||||
void ShutDown();
|
void ShutDown();
|
||||||
} // namespace CPU
|
} // namespace CPU
|
||||||
|
|
83
kernel/include/sortix/kernel/ioport.h
Normal file
83
kernel/include/sortix/kernel/ioport.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2014.
|
||||||
|
|
||||||
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
Sortix is free software: you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
sortix/kernel/ioport.h
|
||||||
|
IO ports.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_SORTIX_KERNEL_IOPORT_H
|
||||||
|
#define INCLUDE_SORTIX_KERNEL_IOPORT_H
|
||||||
|
|
||||||
|
#if !(defined(__i386__) || defined(__x86_64__))
|
||||||
|
#error "This hardware platform doesn't have IO ports"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint8_t outport8(uint16_t port, uint8_t value)
|
||||||
|
{
|
||||||
|
asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint16_t outport16(uint16_t port, uint16_t value)
|
||||||
|
{
|
||||||
|
asm volatile ("outw %1, %0" : : "dN" (port), "a" (value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint32_t outport32(uint16_t port, uint32_t value)
|
||||||
|
{
|
||||||
|
asm volatile ("outl %1, %0" : : "dN" (port), "a" (value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint8_t inport8(uint16_t port)
|
||||||
|
{
|
||||||
|
uint8_t result;
|
||||||
|
asm volatile("inb %1, %0" : "=a" (result) : "dN" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint16_t inport16(uint16_t port)
|
||||||
|
{
|
||||||
|
uint16_t result;
|
||||||
|
asm volatile("inw %1, %0" : "=a" (result) : "dN" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline uint32_t inport32(uint16_t port)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
asm volatile("inl %1, %0" : "=a" (result) : "dN" (port));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Sortix
|
||||||
|
|
||||||
|
#endif
|
|
@ -36,6 +36,7 @@
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
#include <sortix/kernel/debugger.h>
|
#include <sortix/kernel/debugger.h>
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/keyboard.h>
|
#include <sortix/kernel/keyboard.h>
|
||||||
#include <sortix/kernel/thread.h>
|
#include <sortix/kernel/thread.h>
|
||||||
|
@ -184,15 +185,15 @@ int PS2Keyboard::DecodeScancode(uint8_t scancode)
|
||||||
|
|
||||||
uint8_t PS2Keyboard::PopScancode()
|
uint8_t PS2Keyboard::PopScancode()
|
||||||
{
|
{
|
||||||
return CPU::InPortB(iobase + DATA);
|
return inport8(iobase + DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2Keyboard::UpdateLEDs(int ledval)
|
void PS2Keyboard::UpdateLEDs(int ledval)
|
||||||
{
|
{
|
||||||
while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) );
|
while ( (inport8(iobase + STATUS) & (1<<1)) );
|
||||||
CPU::OutPortB(iobase + COMMAND, CMD_SETLED);
|
outport8(iobase + COMMAND, CMD_SETLED);
|
||||||
while ( (CPU::InPortB(iobase + STATUS) & (1<<1)) );
|
while ( (inport8(iobase + STATUS) & (1<<1)) );
|
||||||
CPU::OutPortB(iobase + COMMAND, ledval);
|
outport8(iobase + COMMAND, ledval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2Keyboard::SetOwner(KeyboardOwner* owner, void* user)
|
void PS2Keyboard::SetOwner(KeyboardOwner* owner, void* user)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
|
@ -55,14 +56,14 @@ void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */)
|
||||||
|
|
||||||
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off)
|
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off)
|
||||||
{
|
{
|
||||||
CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
|
outport32(CONFIG_ADDRESS, devaddr + off);
|
||||||
return CPU::InPortL(CONFIG_DATA);
|
return inport32(CONFIG_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val)
|
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val)
|
||||||
{
|
{
|
||||||
CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
|
outport32(CONFIG_ADDRESS, devaddr + off);
|
||||||
CPU::OutPortL(CONFIG_DATA, val);
|
outport32(CONFIG_DATA, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Read32(uint32_t devaddr, uint8_t off)
|
uint32_t Read32(uint32_t devaddr, uint8_t off)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
|
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
@ -67,11 +68,11 @@ const unsigned BOTH_EMPTY = LSR_TEMT | LSR_THRE;
|
||||||
|
|
||||||
unsigned ProbeBaud(unsigned port)
|
unsigned ProbeBaud(unsigned port)
|
||||||
{
|
{
|
||||||
uint8_t lcr = CPU::InPortB(port + LCR);
|
uint8_t lcr = inport8(port + LCR);
|
||||||
CPU::OutPortB(port + LCR, lcr | LCR_DLAB);
|
outport8(port + LCR, lcr | LCR_DLAB);
|
||||||
uint8_t dll = CPU::InPortB(port + DLL);
|
uint8_t dll = inport8(port + DLL);
|
||||||
uint8_t dlm = CPU::InPortB(port + DLM);
|
uint8_t dlm = inport8(port + DLM);
|
||||||
CPU::OutPortB(port + LCR, lcr);
|
outport8(port + LCR, lcr);
|
||||||
unsigned quot = dlm << 8 | dll;
|
unsigned quot = dlm << 8 | dll;
|
||||||
|
|
||||||
return BASE_BAUD / quot;
|
return BASE_BAUD / quot;
|
||||||
|
@ -79,7 +80,7 @@ unsigned ProbeBaud(unsigned port)
|
||||||
|
|
||||||
void WaitForEmptyBuffers(unsigned port)
|
void WaitForEmptyBuffers(unsigned port)
|
||||||
{
|
{
|
||||||
while ( (CPU::InPortB(port + LSR) & BOTH_EMPTY) != BOTH_EMPTY );
|
while ( (inport8(port + LSR) & BOTH_EMPTY) != BOTH_EMPTY );
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned PORT = 0x3F8;
|
const unsigned PORT = 0x3F8;
|
||||||
|
@ -88,34 +89,34 @@ void Init()
|
||||||
{
|
{
|
||||||
unsigned baud = ProbeBaud(PORT);
|
unsigned baud = ProbeBaud(PORT);
|
||||||
|
|
||||||
CPU::OutPortB(PORT + LCR, 0x3); // 8n1
|
outport8(PORT + LCR, 0x3); // 8n1
|
||||||
CPU::OutPortB(PORT + IER, 0); // No interrupt
|
outport8(PORT + IER, 0); // No interrupt
|
||||||
CPU::OutPortB(PORT + FCR, 0); // No FIFO
|
outport8(PORT + FCR, 0); // No FIFO
|
||||||
CPU::OutPortB(PORT + MCR, 0x3); // DTR + RTS
|
outport8(PORT + MCR, 0x3); // DTR + RTS
|
||||||
|
|
||||||
unsigned divisor = 115200 / baud;
|
unsigned divisor = 115200 / baud;
|
||||||
uint8_t c = CPU::InPortB(PORT + LCR);
|
uint8_t c = inport8(PORT + LCR);
|
||||||
CPU::OutPortB(PORT + LCR, c | LCR_DLAB);
|
outport8(PORT + LCR, c | LCR_DLAB);
|
||||||
CPU::OutPortB(PORT + DLL, divisor >> 0 & 0xFF);
|
outport8(PORT + DLL, divisor >> 0 & 0xFF);
|
||||||
CPU::OutPortB(PORT + DLM, divisor >> 8 & 0xFF);
|
outport8(PORT + DLM, divisor >> 8 & 0xFF);
|
||||||
CPU::OutPortB(PORT + LCR, c & ~LCR_DLAB);
|
outport8(PORT + LCR, c & ~LCR_DLAB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read(uint8_t* buffer, size_t size)
|
void Read(uint8_t* buffer, size_t size)
|
||||||
{
|
{
|
||||||
// Save the IER and disable interrupts.
|
// Save the IER and disable interrupts.
|
||||||
unsigned ier = CPU::InPortB(PORT + IER);
|
unsigned ier = inport8(PORT + IER);
|
||||||
CPU::OutPortB(PORT + IER, 0);
|
outport8(PORT + IER, 0);
|
||||||
|
|
||||||
for ( size_t i = 0; i < size; i++ )
|
for ( size_t i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
while ( !(CPU::InPortB(PORT + LSR) & LSR_READY) );
|
while ( !(inport8(PORT + LSR) & LSR_READY) );
|
||||||
buffer[i] = CPU::InPortB(PORT);
|
buffer[i] = inport8(PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for transmitter to become empty and restore the IER.
|
// Wait for transmitter to become empty and restore the IER.
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
CPU::OutPortB(PORT + IER, ier);
|
outport8(PORT + IER, ier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(const void* b, size_t size)
|
void Write(const void* b, size_t size)
|
||||||
|
@ -123,49 +124,49 @@ void Write(const void* b, size_t size)
|
||||||
const uint8_t* buffer = (const uint8_t*) b;
|
const uint8_t* buffer = (const uint8_t*) b;
|
||||||
|
|
||||||
// Save the IER and disable interrupts.
|
// Save the IER and disable interrupts.
|
||||||
unsigned ier = CPU::InPortB(PORT + IER);
|
unsigned ier = inport8(PORT + IER);
|
||||||
CPU::OutPortB(PORT + IER, 0);
|
outport8(PORT + IER, 0);
|
||||||
|
|
||||||
for ( size_t i = 0; i < size; i++ )
|
for ( size_t i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
CPU::OutPortB(PORT, buffer[i]);
|
outport8(PORT, buffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for transmitter to become empty and restore the IER.
|
// Wait for transmitter to become empty and restore the IER.
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
CPU::OutPortB(PORT + IER, ier);
|
outport8(PORT + IER, ier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteChar(char c)
|
void WriteChar(char c)
|
||||||
{
|
{
|
||||||
// Save the IER and disable interrupts.
|
// Save the IER and disable interrupts.
|
||||||
unsigned ier = CPU::InPortB(PORT + IER);
|
unsigned ier = inport8(PORT + IER);
|
||||||
CPU::OutPortB(PORT + IER, 0);
|
outport8(PORT + IER, 0);
|
||||||
|
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
|
|
||||||
CPU::OutPortB(PORT, c);
|
outport8(PORT, c);
|
||||||
|
|
||||||
// Wait for transmitter to become empty and restore the IER.
|
// Wait for transmitter to become empty and restore the IER.
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
CPU::OutPortB(PORT + IER, ier);
|
outport8(PORT + IER, ier);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TryPopChar()
|
int TryPopChar()
|
||||||
{
|
{
|
||||||
// Save the IER and disable interrupts.
|
// Save the IER and disable interrupts.
|
||||||
unsigned ier = CPU::InPortB(PORT + IER);
|
unsigned ier = inport8(PORT + IER);
|
||||||
CPU::OutPortB(PORT + IER, 0);
|
outport8(PORT + IER, 0);
|
||||||
|
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
if ( CPU::InPortB(PORT + LSR) & LSR_READY )
|
if ( inport8(PORT + LSR) & LSR_READY )
|
||||||
result = CPU::InPortB(PORT);
|
result = inport8(PORT);
|
||||||
|
|
||||||
// Wait for transmitter to become empty and restore the IER.
|
// Wait for transmitter to become empty and restore the IER.
|
||||||
WaitForEmptyBuffers(PORT);
|
WaitForEmptyBuffers(PORT);
|
||||||
CPU::OutPortB(PORT + IER, ier);
|
outport8(PORT + IER, ier);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,14 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <sortix/kernel/descriptor.h>
|
#include <sortix/kernel/descriptor.h>
|
||||||
#include <sortix/kernel/inode.h>
|
#include <sortix/kernel/inode.h>
|
||||||
#include <sortix/kernel/interlock.h>
|
#include <sortix/kernel/interlock.h>
|
||||||
#include <sortix/kernel/ioctx.h>
|
#include <sortix/kernel/ioctx.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/process.h>
|
#include <sortix/kernel/process.h>
|
||||||
|
@ -33,9 +37,6 @@
|
||||||
#include <sortix/kernel/scheduler.h>
|
#include <sortix/kernel/scheduler.h>
|
||||||
#include <sortix/kernel/syscall.h>
|
#include <sortix/kernel/syscall.h>
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "fs/util.h"
|
#include "fs/util.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
|
||||||
|
@ -53,14 +54,14 @@ uint8_t* vgafont;
|
||||||
|
|
||||||
static void WriteIndex(uint16_t port, uint8_t index, uint8_t value)
|
static void WriteIndex(uint16_t port, uint8_t index, uint8_t value)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(port, index);
|
outport8(port, index);
|
||||||
CPU::OutPortB(port+1, value);
|
outport8(port+1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ReadIndex(uint16_t port, uint8_t index)
|
static uint8_t ReadIndex(uint16_t port, uint8_t index)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(port, index);
|
outport8(port, index);
|
||||||
return CPU::InPortB(port+1);
|
return inport8(port+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ReplaceIndex(uint16_t port, uint8_t index, uint8_t value)
|
static uint8_t ReplaceIndex(uint16_t port, uint8_t index, uint8_t value)
|
||||||
|
@ -165,10 +166,10 @@ void SetCursor(unsigned x, unsigned y)
|
||||||
// CRT Control Register of the VGA controller. These
|
// CRT Control Register of the VGA controller. These
|
||||||
// are the high and low bytes of the index that show
|
// are the high and low bytes of the index that show
|
||||||
// where the hardware cursor is to be 'blinking'.
|
// where the hardware cursor is to be 'blinking'.
|
||||||
CPU::OutPortB(0x3D4, 14);
|
outport8(0x3D4, 14);
|
||||||
CPU::OutPortB(0x3D5, (value >> 8) & 0xFF);
|
outport8(0x3D5, (value >> 8) & 0xFF);
|
||||||
CPU::OutPortB(0x3D4, 15);
|
outport8(0x3D4, 15);
|
||||||
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
outport8(0x3D5, (value >> 0) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VGA
|
} // namespace VGA
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <sortix/kernel/clock.h>
|
#include <sortix/kernel/clock.h>
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/time.h>
|
#include <sortix/kernel/time.h>
|
||||||
|
|
||||||
|
@ -43,8 +44,8 @@ const uint16_t CMOS_DATA_REG = 0x71;
|
||||||
|
|
||||||
uint8_t ReadRTC(uint8_t reg)
|
uint8_t ReadRTC(uint8_t reg)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(CMOS_ADDRESS_REG, reg);
|
outport8(CMOS_ADDRESS_REG, reg);
|
||||||
return CPU::InPortB(CMOS_DATA_REG);
|
return inport8(CMOS_DATA_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRTCUpdateInProgress()
|
bool IsRTCUpdateInProgress()
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
|
#include <sortix/kernel/kernel.h>
|
||||||
|
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
|
|
||||||
|
@ -53,10 +54,10 @@ const uint8_t PIC_READ_ISR = 0x0B;
|
||||||
|
|
||||||
static uint16_t ReadRegister(uint8_t ocw3)
|
static uint16_t ReadRegister(uint8_t ocw3)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, ocw3);
|
outport8(PIC_MASTER + PIC_COMMAND, ocw3);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, ocw3);
|
outport8(PIC_SLAVE + PIC_COMMAND, ocw3);
|
||||||
return CPU::InPortB(PIC_MASTER + PIC_COMMAND) << 0 |
|
return inport8(PIC_MASTER + PIC_COMMAND) << 0 |
|
||||||
CPU::InPortB(PIC_SLAVE + PIC_COMMAND) << 8;
|
inport8(PIC_SLAVE + PIC_COMMAND) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ReadIRR()
|
uint16_t ReadIRR()
|
||||||
|
@ -73,42 +74,42 @@ extern "C" void ReprogramPIC()
|
||||||
{
|
{
|
||||||
uint8_t master_mask = 0;
|
uint8_t master_mask = 0;
|
||||||
uint8_t slave_mask = 0;
|
uint8_t slave_mask = 0;
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
outport8(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
outport8(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, Interrupt::IRQ0);
|
outport8(PIC_MASTER + PIC_DATA, Interrupt::IRQ0);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, Interrupt::IRQ8);
|
outport8(PIC_SLAVE + PIC_DATA, Interrupt::IRQ8);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
outport8(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
outport8(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
outport8(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
outport8(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
outport8(PIC_MASTER + PIC_DATA, master_mask);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
outport8(PIC_SLAVE + PIC_DATA, slave_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void DeprogramPIC()
|
extern "C" void DeprogramPIC()
|
||||||
{
|
{
|
||||||
uint8_t master_mask = 0;
|
uint8_t master_mask = 0;
|
||||||
uint8_t slave_mask = 0;
|
uint8_t slave_mask = 0;
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
outport8(PIC_MASTER + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
outport8(PIC_SLAVE + PIC_COMMAND, PIC_CMD_INIT | PIC_ICW1_ICW4);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x08);
|
outport8(PIC_MASTER + PIC_DATA, 0x08);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x70);
|
outport8(PIC_SLAVE + PIC_DATA, 0x70);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
outport8(PIC_MASTER + PIC_DATA, 0x04); // Slave PIC at IRQ2
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
outport8(PIC_SLAVE + PIC_DATA, 0x02); // Cascade Identity
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
outport8(PIC_MASTER + PIC_DATA, PIC_MODE_8086);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
outport8(PIC_SLAVE + PIC_DATA, PIC_MODE_8086);
|
||||||
CPU::OutPortB(PIC_MASTER + PIC_DATA, master_mask);
|
outport8(PIC_MASTER + PIC_DATA, master_mask);
|
||||||
CPU::OutPortB(PIC_SLAVE + PIC_DATA, slave_mask);
|
outport8(PIC_SLAVE + PIC_DATA, slave_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendMasterEOI()
|
void SendMasterEOI()
|
||||||
{
|
{
|
||||||
CPU::OutPortB(PIC_MASTER, PIC_CMD_ENDINTR);
|
outport8(PIC_MASTER, PIC_CMD_ENDINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSlaveEOI()
|
void SendSlaveEOI()
|
||||||
{
|
{
|
||||||
CPU::OutPortB(PIC_SLAVE, PIC_CMD_ENDINTR);
|
outport8(PIC_SLAVE, PIC_CMD_ENDINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendEOI(unsigned int irq)
|
void SendEOI(unsigned int irq)
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <sortix/kernel/clock.h>
|
#include <sortix/kernel/clock.h>
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
#include <sortix/kernel/interrupt.h>
|
#include <sortix/kernel/interrupt.h>
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/process.h>
|
#include <sortix/kernel/process.h>
|
||||||
#include <sortix/kernel/scheduler.h>
|
#include <sortix/kernel/scheduler.h>
|
||||||
|
@ -65,9 +66,9 @@ static struct timespec PeriodOfFrequency(long frequency)
|
||||||
|
|
||||||
static void RequestIRQ0(uint16_t divisor)
|
static void RequestIRQ0(uint16_t divisor)
|
||||||
{
|
{
|
||||||
CPU::OutPortB(0x43, 0x36);
|
outport8(0x43, 0x36);
|
||||||
CPU::OutPortB(0x40, divisor >> 0 & 0xFF);
|
outport8(0x40, divisor >> 0 & 0xFF);
|
||||||
CPU::OutPortB(0x40, divisor >> 8 & 0xFF);
|
outport8(0x40, divisor >> 8 & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Clock* realtime_clock;
|
extern Clock* realtime_clock;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <msr.h>
|
#include <msr.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/syscall.h>
|
#include <sortix/kernel/syscall.h>
|
||||||
|
|
||||||
|
@ -34,42 +35,6 @@
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
|
|
||||||
void OutPortB(uint16_t port, uint8_t value)
|
|
||||||
{
|
|
||||||
asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutPortW(uint16_t port, uint16_t value)
|
|
||||||
{
|
|
||||||
asm volatile ("outw %1, %0" : : "dN" (port), "a" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutPortL(uint16_t port, uint32_t value)
|
|
||||||
{
|
|
||||||
asm volatile ("outl %1, %0" : : "dN" (port), "a" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t InPortB(uint16_t port)
|
|
||||||
{
|
|
||||||
uint8_t result;
|
|
||||||
asm volatile("inb %1, %0" : "=a" (result) : "dN" (port));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t InPortW(uint16_t port)
|
|
||||||
{
|
|
||||||
uint16_t result;
|
|
||||||
asm volatile("inw %1, %0" : "=a" (result) : "dN" (port));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t InPortL(uint16_t port)
|
|
||||||
{
|
|
||||||
uint32_t result;
|
|
||||||
asm volatile("inl %1, %0" : "=a" (result) : "dN" (port));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reboot()
|
void Reboot()
|
||||||
{
|
{
|
||||||
// Keyboard interface IO port: data and control.
|
// Keyboard interface IO port: data and control.
|
||||||
|
@ -91,16 +56,16 @@ void Reboot()
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
byte = InPortB(KEYBOARD_INTERFACE);
|
byte = inport8(KEYBOARD_INTERFACE);
|
||||||
if ( byte & KEYBOARD_DATA )
|
if ( byte & KEYBOARD_DATA )
|
||||||
InPortB(KEYBOARD_IO);
|
inport8(KEYBOARD_IO);
|
||||||
} while ( byte & USER_DATA );
|
} while ( byte & USER_DATA );
|
||||||
|
|
||||||
// CPU reset command.
|
// CPU reset command.
|
||||||
uint8_t KEYBOARD_RESET_CPU = 0xFE;
|
uint8_t KEYBOARD_RESET_CPU = 0xFE;
|
||||||
|
|
||||||
// Now pulse the CPU reset line and reset.
|
// Now pulse the CPU reset line and reset.
|
||||||
OutPortB(KEYBOARD_INTERFACE, KEYBOARD_RESET_CPU);
|
outport8(KEYBOARD_INTERFACE, KEYBOARD_RESET_CPU);
|
||||||
|
|
||||||
// If that didn't work, just halt.
|
// If that didn't work, just halt.
|
||||||
asm volatile("hlt");
|
asm volatile("hlt");
|
||||||
|
|
Loading…
Add table
Reference in a new issue