aboutsummaryrefslogtreecommitdiff
path: root/mubios
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-09 01:57:05 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-09 01:57:05 +0800
commit9b380041e6ad178f96942fd3b2521c1aba21a068 (patch)
tree87d682c1940341b4968fb1452a474795f2b96525 /mubios
parent3ef6001ab0e719c18cfd369ecd0df108a9520991 (diff)
downloadrcc-project-9b380041e6ad178f96942fd3b2521c1aba21a068.tar.gz
rcc-project-9b380041e6ad178f96942fd3b2521c1aba21a068.tar.xz
[mubios] Add EDD parameters and normalize PS/2 input
Diffstat (limited to 'mubios')
-rw-r--r--mubios/arch/irq.S20
-rw-r--r--mubios/drivers/ata.c40
-rw-r--r--mubios/include/bios.h2
-rw-r--r--mubios/services/int13.c57
-rw-r--r--mubios/services/int16.c14
5 files changed, 129 insertions, 4 deletions
diff --git a/mubios/arch/irq.S b/mubios/arch/irq.S
index 0c192ff..99eb9b3 100644
--- a/mubios/arch/irq.S
+++ b/mubios/arch/irq.S
@@ -25,6 +25,7 @@
.equ BDA_BASE, 0x0400
.equ BDA_KBD_BUFFER_START, 0x001E
.equ BDA_KBD_BUFFER_END, 0x003E
+ .equ BDA_KBD_BREAK_PREFIX, 0x0497
.equ TIMER_TICKS_PER_DAY_LOW, 0x00B0
.equ TIMER_TICKS_PER_DAY_HIGH, 0x0018
@@ -83,12 +84,25 @@ irq1_entry:
in al, 0x60
mov dl, al
- test dl, 0x80
- jnz irq1_send_eoi
-
xor ax, ax
mov ds, ax
+ # Ignore a PS/2 set-2 break prefix and its following release code.
+ cmp dl, 0xF0
+ jne irq1_check_break_prefix
+ mov byte ptr [BDA_KBD_BREAK_PREFIX], 1
+ jmp irq1_send_eoi
+
+irq1_check_break_prefix:
+ cmp byte ptr [BDA_KBD_BREAK_PREFIX], 0
+ je irq1_check_set1_break
+ mov byte ptr [BDA_KBD_BREAK_PREFIX], 0
+ jmp irq1_send_eoi
+
+irq1_check_set1_break:
+ test dl, 0x80
+ jnz irq1_send_eoi
+
mov bx, word ptr [0x041C]
mov ax, bx
add ax, 2
diff --git a/mubios/drivers/ata.c b/mubios/drivers/ata.c
index 928a7d1..a7c6d8d 100644
--- a/mubios/drivers/ata.c
+++ b/mubios/drivers/ata.c
@@ -36,6 +36,7 @@
#define ATA_STATUS_BSY 0x80u
#define ATA_CMD_READ_SECTORS 0x20u
+#define ATA_CMD_IDENTIFY 0xECu
static u8
ata_wait_not_busy (void)
@@ -111,3 +112,42 @@ ata_read_sectors28 (u32 lba, u16 *buffer, u16 count)
return 0;
}
+
+u8
+ata_identify (u16 *cylinders, u16 *heads, u16 *sectors_per_track,
+ u32 *total_sectors_low, u32 *total_sectors_high)
+{
+ u16 identify_data[256];
+ u8 status;
+ u16 index;
+
+ status = ata_wait_not_busy ();
+ if ((status & ATA_STATUS_ERR) != 0)
+ return 1;
+
+ io_out8 (ATA_DRIVE, 0xE0u);
+ ata_delay_400ns ();
+
+ io_out8 (ATA_SECTOR_COUNT, 0);
+ io_out8 (ATA_LBA_LOW, 0);
+ io_out8 (ATA_LBA_MID, 0);
+ io_out8 (ATA_LBA_HIGH, 0);
+ io_out8 (ATA_COMMAND, ATA_CMD_IDENTIFY);
+
+ status = ata_wait_not_busy ();
+ if ((status & ATA_STATUS_ERR) != 0 || (status & ATA_STATUS_DRQ) == 0)
+ return 1;
+
+ for (index = 0; index < 256; ++index)
+ identify_data[index] = io_in16 (ATA_DATA);
+
+ *cylinders = identify_data[1];
+ *heads = identify_data[3];
+ *sectors_per_track = identify_data[6];
+ *total_sectors_low
+ = (u32)identify_data[60] | ((u32)identify_data[61] << 16);
+ *total_sectors_high
+ = (u32)identify_data[100] | ((u32)identify_data[101] << 16);
+
+ return 0;
+}
diff --git a/mubios/include/bios.h b/mubios/include/bios.h
index 456d212..7ec2198 100644
--- a/mubios/include/bios.h
+++ b/mubios/include/bios.h
@@ -51,6 +51,8 @@ void ioapic_init (void);
void ivt_init (void);
u8 ata_read_sectors28 (u32 lba, u16 *buffer, u16 count);
+u8 ata_identify (u16 *cylinders, u16 *heads, u16 *sectors_per_track,
+ u32 *total_sectors_low, u32 *total_sectors_high);
struct bios_regs;
diff --git a/mubios/services/int13.c b/mubios/services/int13.c
index 2c12261..73d553b 100644
--- a/mubios/services/int13.c
+++ b/mubios/services/int13.c
@@ -35,6 +35,19 @@ struct edd_packet
u32 lba_high;
} __attribute__ ((packed));
+struct edd_parameters
+{
+ u16 size;
+ u16 flags;
+ u32 cylinders_low;
+ u32 cylinders_high;
+ u32 heads;
+ u32 sectors_per_track;
+ u32 total_sectors_low;
+ u32 total_sectors_high;
+ u16 bytes_per_sector;
+} __attribute__ ((packed));
+
static void
int13_fail (struct bios_regs *regs)
{
@@ -51,6 +64,15 @@ get_edd_packet (struct bios_regs *regs)
return (struct edd_packet *)address;
}
+static struct edd_parameters *
+get_edd_parameters (struct bios_regs *regs)
+{
+ u32 address;
+
+ address = ((u32)regs->ds << 4) + (u16)regs->esi;
+ return (struct edd_parameters *)address;
+}
+
void
int13_service (struct bios_regs *regs)
{
@@ -103,5 +125,40 @@ int13_service (struct bios_regs *regs)
return;
}
+ if (function == 0x48u)
+ {
+ struct edd_parameters *parameters;
+ u16 cylinders;
+ u16 heads;
+ u16 sectors_per_track;
+ u32 total_sectors_low;
+ u32 total_sectors_high;
+
+ parameters = get_edd_parameters (regs);
+
+ if (parameters->size < 0x001Eu
+ || ata_identify (&cylinders, &heads, &sectors_per_track,
+ &total_sectors_low, &total_sectors_high)
+ != 0)
+ {
+ int13_fail (regs);
+ return;
+ }
+
+ parameters->size = 0x001Eu;
+ parameters->flags = 0;
+ parameters->cylinders_low = cylinders;
+ parameters->cylinders_high = 0;
+ parameters->heads = heads;
+ parameters->sectors_per_track = sectors_per_track;
+ parameters->total_sectors_low = total_sectors_low;
+ parameters->total_sectors_high = total_sectors_high;
+ parameters->bytes_per_sector = 512;
+
+ regs->eax = 0;
+ regs->flags &= (u16)~BIOS_CF;
+ return;
+ }
+
int13_fail (regs);
}
diff --git a/mubios/services/int16.c b/mubios/services/int16.c
index 4a04828..5872fb1 100644
--- a/mubios/services/int16.c
+++ b/mubios/services/int16.c
@@ -27,6 +27,18 @@
#define BDA_KBD_BUFFER_END 0x003Eu
static u8
+normalize_scancode (u8 scancode)
+{
+ switch (scancode)
+ {
+ case 0x5Au:
+ return 0x1Cu;
+ default:
+ return scancode;
+ }
+}
+
+static u8
scancode_to_ascii (u8 scancode)
{
switch (scancode)
@@ -126,7 +138,7 @@ int16_service (struct bios_regs *regs)
position = *head;
value = buffer[(position - BDA_KBD_BUFFER_START) >> 1];
- scancode = (u8)(value >> 8);
+ scancode = normalize_scancode ((u8)(value >> 8));
ascii = scancode_to_ascii (scancode);
regs->eax = ((u32)scancode << 8) | ascii;