jankos/serial.c

90 lines
2.3 KiB
C

#include "serial.h"
/*
* SERIAL_LINE_COMMAND_PORT configuration
* Bit: | 7 | 6 | 5 4 3 | 2 | 1 0 |
* Content: | d | b | prty | s | dl |
* d = enable/disable DLAB
* b = enable/disable break control
* prty = # of parity bits to use
* s = # no of stop bits [0 is 1] and [1 is 1.5 or 2]
* dl = length of data
*
*/
void serial_set_baud_rate(const u16 com_port, const u16 divisor) {
// Activate line - ready to send higher 8 bits of data
// send the higher 8 bits first
// send the lower 8 bits next
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(com_port),
SERIAL_LINE_ENABLE);
serialport_write_byte(SERIAL_DATA_PORT(com_port),
(divisor>>8) & 0x00ff);
serialport_write_byte(SERIAL_DATA_PORT(com_port),
divisor & 0x00ff);
}
// Payload described above
void serial_configure_line(const u16 line, const u8 payload) {
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(line), payload);
}
u8 serial_fifo_empty(const u16 com_port) {
// we get back 0x20 if it is empty
return serial_read_byte(SERIAL_LINE_STATUS_PORT(com_port)) &
SERIAL_FIFO_EMPTY_CODE;
}
u64 serial_write(const char* buffer, const u64 size) {
/*
* Writes a given buffer to the com1 serial port for debugging in bochs
*/
serialport_write_byte(SERIAL_DATA_PORT_INT_EN(SERIAL_COM1_BASE),
0x00);
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(SERIAL_COM1_BASE),
SERIAL_LINE_ENABLE);
// quarter speed hopefully the fifo quue wont fill this way
serialport_write_byte(SERIAL_COM1_BASE,
0x01);
serialport_write_byte(SERIAL_DATA_PORT_INT_EN(SERIAL_COM1_BASE),
0x00);
serialport_write_byte(SERIAL_LINE_COMMAND_PORT(SERIAL_COM1_BASE),
SERIAL_DEFAULT_LINE_CFG);
serialport_write_byte(SERIAL_FIFO_COMMAND_PORT(SERIAL_COM1_BASE),
SERIAL_DEFAULT_BUFFER_CFG);
serialport_write_byte(SERIAL_MODEM_COMMAND_PORT(SERIAL_COM1_BASE),
0x0B);
u64 idx;
for(idx =0; idx < size; idx++) {
serialport_write_byte(SERIAL_COM1_BASE, buffer[idx]);
}
return idx;
}
void serial_pic_ack(u32 interrupt) {
// ignore things that are too small and too big
if(interrupt < PIC1_START_INT || interrupt > PIC2_END_INT) {
return;
}
// Send acknoldgement to the pic that we have handled the interrupt
// without this it literally just wait for the ack
if(interrupt < PIC2_START_INT) {
serialport_write_byte(PIC1_PORT, PIC_ACK);
}
else {
serialport_write_byte(PIC2_PORT, PIC_ACK);
}
}