Skip to content

Commit 62a824c

Browse files
author
tthomps
committed
Implement backspace with the GUI Edit control.
Capture enter with the Run Window. Start implementing an IDE driver.
1 parent 4d0c159 commit 62a824c

File tree

13 files changed

+342
-6
lines changed

13 files changed

+342
-6
lines changed

MyOS_1/Drivers/IDE.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#include "IDE.h"
2+
#include "../printf.h"
3+
#include "../System_Specific.h"
4+
// TODO: Support multiple IDE controllers
5+
uint8_t IDE_bus;
6+
uint8_t IDE_slot;
7+
uint8_t IDE_function;
8+
bool IDE_Present;
9+
10+
IDE_CHANNEL_REGISTERS channels[2];
11+
12+
uint8_t ide_buf[2048] = { 0 };
13+
bool ide_irq_invoked = 0;
14+
uint8_t atapi_packet[12] = { 0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
15+
16+
void IDE_Init(uint8_t bus, uint8_t slot, uint8_t function)
17+
{
18+
IDE_bus = bus;
19+
IDE_slot = slot;
20+
IDE_function = function;
21+
22+
kprintf(" Initializing IDE controller driver...");
23+
24+
// Get the operating mode from the programming interface. We only support compatibility mode right now.
25+
// TODO: Support PCI native and/or try writing to progIF to see if device can be put into compatibility mode
26+
uint8_t progIF = PCI_GetProgrammingInterface(bus, slot, function);
27+
if ((progIF & PROG_IF_PRIMARY_CHANNEL_PCI_NATIVE) || (progIF & PROG_IF_SECONDARY_CHANNEL_PCI_NATIVE))
28+
{
29+
kprintf("\n we don't yet support PCI-native IDE controllers; aborting.");
30+
IDE_Present = false;
31+
return;
32+
}
33+
34+
// get the I/O ports - this is how it would be done for PCI-native
35+
/*uint32_t primaryChannelBase = PCI_GetBaseAddress0(bus, slot, function) & ~3;
36+
uint32_t primaryChannelControl = PCI_GetBaseAddress1(bus, slot, function) & ~3;
37+
uint32_t secondaryChannelBase = PCI_GetBaseAddress2(bus, slot, function) & ~3;
38+
uint32_t secondaryChannelControl = PCI_GetBaseAddress3(bus, slot, function) & ~3;*/
39+
40+
// Use the compatibility-mode I/O addresses
41+
channels[0].base = IDE_COMPAT_PRIMARY_COMMAND_IO;
42+
channels[0].ctrl = IDE_COMPAT_PRIMARY_CONTROL_IO;
43+
channels[1].base = IDE_COMPAT_SECONDARY_COMMAND_IO;
44+
channels[1].ctrl = IDE_COMPAT_SECONDARY_CONTROL_IO;
45+
46+
kprintf(" 0x%X 0x%X 0x%X 0x%X", channels[0].base, channels[0].ctrl, channels[1].base, channels[1].ctrl);
47+
48+
// Compatibility mode means we use IRQ's 14 and 15
49+
channels[0].irq = 14;
50+
channels[1].irq = 15;
51+
kprintf(" - IRQs %d&%d\n", channels[0].irq, channels[1].irq);
52+
53+
IDE_Present = true;
54+
55+
kprintf(" IDE controller driver initialized\n");
56+
}
57+
58+
uint8_t ide_polling(uint8_t channel, uint8_t advanced_check)
59+
{
60+
61+
// (I) Delay 400 nanosecond for BSY to be set:
62+
// -------------------------------------------------
63+
for (int i = 0; i < 4; i++)
64+
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times.
65+
66+
// (II) Wait for BSY to be cleared:
67+
// TODO: add timeout
68+
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
69+
; // Wait for BSY to be zero.
70+
71+
if (advanced_check)
72+
{
73+
uint8_t state = ide_read(channel, ATA_REG_STATUS); // Read Status Register.
74+
75+
// (III) Check For Errors:
76+
if (state & ATA_SR_ERR)
77+
return 2; // Error.
78+
79+
// (IV) Check If Device fault:
80+
if (state & ATA_SR_DF)
81+
return 1; // Device Fault.
82+
83+
// (V) Check DRQ:
84+
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
85+
if ((state & ATA_SR_DRQ) == 0)
86+
return 3; // DRQ should be set
87+
}
88+
89+
return 0; // No Error.
90+
}
91+
92+
uint8_t ide_read(uint8_t channel, uint8_t reg)
93+
{
94+
uint8_t result;
95+
96+
// If we're writing to register ATA_REG_SECCOUNT1 or ATA_REG_LBAx (the second device on the channel)
97+
if (reg >= ATA_REG_SECCOUNT1 && reg <= ATA_REG_LBA5)
98+
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].disableInterrupts);
99+
100+
if (reg <= ATA_REG_COMMAND)
101+
result = inb(channels[channel].base + reg - 0x00);
102+
else if (reg <= ATA_REG_LBA5)
103+
result = inb(channels[channel].base + reg - 0x06);
104+
else if (reg <= ATA_REG_DEVADDRESS)
105+
result = inb(channels[channel].ctrl + reg - 0x0A);
106+
else if (reg < 0x16)
107+
result = inb(channels[channel].bmide + reg - 0x0E);
108+
109+
// If we're writing to register ATA_REG_SECCOUNT1 or ATA_REG_LBAx (the second device on the channel)
110+
if (reg >= ATA_REG_SECCOUNT1 && reg <= ATA_REG_LBA5)
111+
ide_write(channel, ATA_REG_CONTROL, channels[channel].disableInterrupts);
112+
113+
return result;
114+
}
115+
116+
void ide_write(uint8_t channel, uint8_t reg, uint8_t data)
117+
{
118+
// If we're writing to register ATA_REG_SECCOUNT1 or ATA_REG_LBAx (the second device on the channel)
119+
if (reg >= ATA_REG_SECCOUNT1 && reg <= ATA_REG_LBA5)
120+
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].disableInterrupts);
121+
122+
if (reg <= ATA_REG_COMMAND)
123+
outb(channels[channel].base + reg - 0x00, data);
124+
else if (reg <= ATA_REG_LBA5)
125+
outb(channels[channel].base + reg - 0x06, data);
126+
else if (reg <= ATA_REG_DEVADDRESS)
127+
outb(channels[channel].ctrl + reg - 0x0A, data);
128+
else if (reg < 0x16)
129+
outb(channels[channel].bmide + reg - 0x0E, data);
130+
131+
// If we're writing to register ATA_REG_SECCOUNT1 or ATA_REG_LBAx (the second device on the channel)
132+
if (reg >= ATA_REG_SECCOUNT1 && reg <= ATA_REG_LBA5)
133+
ide_write(channel, ATA_REG_CONTROL, channels[channel].disableInterrupts);
134+
}

MyOS_1/Drivers/IDE.h

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#pragma once
2+
3+
#include "PCI_Bus.h"
4+
5+
// Programming interface bits (from the PCI IDE specification)
6+
// (No idea what "modes" the spec is referring to - it's not a great spec)
7+
#define PROG_IF_PRIMARY_CHANNEL_PCI_NATIVE 0x01
8+
#define PROG_IF_PRIMARY_CHANNEL_BOTH_MODES 0x02
9+
#define PROG_IF_SECONDARY_CHANNEL_PCI_NATIVE 0x04
10+
#define PROG_IF_SECONDARY_CHANNEL_BOTH_MODES 0x08
11+
#define PROG_IF_BUS_MASTER_CAPABLE 0x80
12+
13+
#define IDE_COMPAT_PRIMARY_COMMAND_IO 0x1F0
14+
#define IDE_COMPAT_PRIMARY_CONTROL_IO 0x3F6
15+
#define IDE_COMPAT_SECONDARY_COMMAND_IO 0x170
16+
#define IDE_COMPAT_SECONDARY_CONTROL_IO 0x376
17+
18+
// Some defines from OSdev wiki:
19+
20+
// STATUS
21+
#define ATA_SR_BSY 0x80 // Busy
22+
#define ATA_SR_DRDY 0x40 // Drive ready
23+
#define ATA_SR_DF 0x20 // Drive write fault
24+
#define ATA_SR_DSC 0x10 // Drive seek complete
25+
#define ATA_SR_DRQ 0x08 // Data request ready
26+
#define ATA_SR_CORR 0x04 // Corrected data
27+
#define ATA_SR_IDX 0x02 // Index
28+
#define ATA_SR_ERR 0x01 // Error
29+
30+
// ERRORS
31+
#define ATA_ER_BBK 0x80 // Bad block
32+
#define ATA_ER_UNC 0x40 // Uncorrectable data
33+
#define ATA_ER_MC 0x20 // Media changed
34+
#define ATA_ER_IDNF 0x10 // ID mark not found
35+
#define ATA_ER_MCR 0x08 // Media change request
36+
#define ATA_ER_ABRT 0x04 // Command aborted
37+
#define ATA_ER_TK0NF 0x02 // Track 0 not found
38+
#define ATA_ER_AMNF 0x01 // No address mark
39+
40+
// COMMANDS
41+
#define ATA_CMD_READ_PIO 0x20
42+
#define ATA_CMD_READ_PIO_EXT 0x24
43+
#define ATA_CMD_READ_DMA 0xC8
44+
#define ATA_CMD_READ_DMA_EXT 0x25
45+
#define ATA_CMD_WRITE_PIO 0x30
46+
#define ATA_CMD_WRITE_PIO_EXT 0x34
47+
#define ATA_CMD_WRITE_DMA 0xCA
48+
#define ATA_CMD_WRITE_DMA_EXT 0x35
49+
#define ATA_CMD_CACHE_FLUSH 0xE7
50+
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
51+
#define ATA_CMD_PACKET 0xA0
52+
#define ATA_CMD_IDENTIFY_PACKET 0xA1
53+
#define ATA_CMD_IDENTIFY 0xEC
54+
// ATAPI COMMANDS
55+
#define ATAPI_CMD_READ 0xA8
56+
#define ATAPI_CMD_EJECT 0x1B
57+
58+
// NOT SURE
59+
#define ATA_IDENT_DEVICETYPE 0
60+
#define ATA_IDENT_CYLINDERS 2
61+
#define ATA_IDENT_HEADS 6
62+
#define ATA_IDENT_SECTORS 12
63+
#define ATA_IDENT_SERIAL 20
64+
#define ATA_IDENT_MODEL 54
65+
#define ATA_IDENT_CAPABILITIES 98
66+
#define ATA_IDENT_FIELDVALID 106
67+
#define ATA_IDENT_MAX_LBA 120
68+
#define ATA_IDENT_COMMANDSETS 164
69+
#define ATA_IDENT_MAX_LBA_EXT 200
70+
71+
#define IDE_ATA 0x00
72+
#define IDE_ATAPI 0x01
73+
74+
#define ATA_CHANNEL_DEVICE0 0x00
75+
#define ATA_CHANNEL_DEVICE1 0x01
76+
77+
// ATA-ATAPI "Task-File":
78+
#define ATA_REG_DATA 0x00
79+
#define ATA_REG_ERROR 0x01
80+
#define ATA_REG_FEATURES 0x01
81+
#define ATA_REG_SECCOUNT0 0x02
82+
#define ATA_REG_LBA0 0x03
83+
#define ATA_REG_LBA1 0x04
84+
#define ATA_REG_LBA2 0x05
85+
#define ATA_REG_HDDEVSEL 0x06
86+
#define ATA_REG_COMMAND 0x07
87+
#define ATA_REG_STATUS 0x07
88+
#define ATA_REG_SECCOUNT1 0x08
89+
#define ATA_REG_LBA3 0x09
90+
#define ATA_REG_LBA4 0x0A
91+
#define ATA_REG_LBA5 0x0B
92+
#define ATA_REG_CONTROL 0x0C
93+
#define ATA_REG_ALTSTATUS 0x0C
94+
#define ATA_REG_DEVADDRESS 0x0D
95+
96+
typedef struct IDE_CHANNEL_REGISTERS
97+
{
98+
uint16_t base; // I/O Base.
99+
uint16_t ctrl; // Control Base
100+
uint16_t bmide; // Bus Master IDE
101+
uint8_t disableInterrupts;
102+
uint8_t irq;
103+
} IDE_CHANNEL_REGISTERS;
104+
105+
struct ide_device {
106+
uint8_t Reserved; // 0 (Empty) or 1 (This Drive really exists).
107+
uint8_t Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
108+
uint8_t Drive; // 0 (Master Drive) or 1 (Slave Drive).
109+
uint16_t Type; // 0: ATA, 1:ATAPI.
110+
uint16_t Signature; // Drive Signature
111+
uint16_t Capabilities;// Features.
112+
uint32_t CommandSets; // Command Sets Supported.
113+
uint32_t Size; // Size in Sectors.
114+
char Model[41]; // Model in string.
115+
} ide_devices[4];
116+
117+
118+
119+
// TODO: Support multiple IDE controllers
120+
extern uint8_t IDE_bus;
121+
extern uint8_t IDE_slot;
122+
extern uint8_t IDE_function;
123+
extern bool IDE_Present;
124+
125+
126+
void IDE_Init(uint8_t bus, uint8_t slot, uint8_t function);
127+
128+
uint8_t ide_polling(uint8_t channel, uint8_t advanced_check);
129+
130+
uint8_t ide_read(uint8_t channel, uint8_t reg);
131+
132+
void ide_write(uint8_t channel, uint8_t reg, uint8_t data);

MyOS_1/Drivers/PCI_Bus.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "RTL_8139.h"
66
#include "Bochs_VGA.h"
77
#include "e1000.h"
8+
#include "IDE.h"
89

910
void VirtIO_Net_Init(uint8_t bus, uint8_t slot, uint8_t function);
1011
void VGPU_Init(uint8_t bus, uint8_t slot, uint8_t function);
@@ -509,7 +510,7 @@ void PCI_CheckFunction(uint8_t bus, uint8_t device, uint8_t function, uint16_t v
509510
terminal_newline();
510511

511512
// try to load a driver for the device
512-
PCI_DelegateToDriver(bus, device, function, vendorID, deviceID);
513+
PCI_DelegateToDriver(bus, device, function, vendorID, deviceID, baseClass, subClass);
513514

514515
/*if ((baseClass == 0x06) && (subClass == 0x04))
515516
{
@@ -519,7 +520,7 @@ void PCI_CheckFunction(uint8_t bus, uint8_t device, uint8_t function, uint16_t v
519520
}
520521

521522
// Inelegant hack
522-
void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t vendorID, uint16_t deviceID)
523+
void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t vendorID, uint16_t deviceID, uint8_t baseClass, uint8_t subClass)
523524
{
524525
if (vendorID == PCI_VENDOR_REALTEK)
525526
{
@@ -531,15 +532,19 @@ void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t
531532
if (vendorID == PCI_VENDOR_QEMU)
532533
{
533534
if (deviceID == PCI_DEVICE_BGA)
535+
{
534536
BGA_Init(bus, slot, function);
535-
return;
537+
return;
538+
}
536539
}
537540

538541
if (vendorID == PCI_VENDOR_VBOX)
539542
{
540543
if (deviceID == PCI_DEVICE_VBOX_BGA)
544+
{
541545
BGA_Init(bus, slot, function);
542-
return;
546+
return;
547+
}
543548
}
544549

545550
if (vendorID == PCI_VENDOR_RED_HAT)
@@ -554,7 +559,15 @@ void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t
554559
if (vendorID == PCI_VENDOR_INTEL)
555560
{
556561
if (deviceID == PCI_DEVICE_82540EM)
562+
{
557563
e1000_Net_Init(bus, slot, function);
564+
return;
565+
}
566+
}
567+
568+
if (baseClass == PCI_BASE_CLASS_MASS_STORAGE && subClass == PCI_SUBCLASS_IDE_CONTROLLER)
569+
{
570+
IDE_Init(bus, slot, function);
558571
return;
559572
}
560573
}
@@ -710,6 +723,12 @@ uint8_t PCI_GetInterruptLine(uint8_t bus, uint8_t slot, uint8_t function)
710723
return PCI_ConfigReadWord(bus, slot, function, INTERRUPT_LINE_OFFSET) & 0xFF;
711724
}
712725

726+
uint8_t PCI_GetProgrammingInterface(uint8_t bus, uint8_t slot, uint8_t function)
727+
{
728+
// PROG_IF is upper byte of 16 bits after revision ID
729+
return (uint8_t)(PCI_ConfigReadWord(bus, slot, function, VENDOR_ID_OFFFSET) >> 8);
730+
}
731+
713732
uint16_t PCI_GetVendorID(uint8_t bus, uint8_t slot, uint8_t function)
714733
{
715734
return PCI_ConfigReadWord(bus, slot, function, VENDOR_ID_OFFFSET);

MyOS_1/Drivers/PCI_Bus.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define VENDOR_ID_OFFFSET 0
99
#define DEVICE_ID_OFFSET 0x02
1010
#define COMMAND_OFFSET 0x04
11+
#define REVISION_OFFSET 0x08
1112
#define CLASSES_OFFSET 0x0A
1213
#define HEADER_TYPE_OFFSET 0x0E
1314
#define BAR0_OFFSET 0x10
@@ -42,6 +43,9 @@
4243
#define PCI_VENDOR_INTEL 0x8086
4344
#define PCI_DEVICE_82540EM 0x100E
4445

46+
#define PCI_BASE_CLASS_MASS_STORAGE 0x01
47+
#define PCI_SUBCLASS_IDE_CONTROLLER 0x01
48+
4549
void PCI_CheckAllBuses(void);
4650

4751
void PCI_CheckDevice(uint8_t bus, uint8_t device);
@@ -54,7 +58,7 @@ uint16_t PCI_ConfigReadWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t off
5458

5559
void PCI_ConfigWriteWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset, uint16_t data);
5660

57-
void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t vendorID, uint16_t deviceID);
61+
void PCI_DelegateToDriver(uint8_t bus, uint8_t slot, uint8_t function, uint16_t vendorID, uint16_t deviceID, uint8_t baseClass, uint8_t subClass);
5862

5963
void PCI_EnableBusMastering(uint8_t bus, uint8_t slot, uint8_t function);
6064

@@ -81,6 +85,8 @@ uint8_t PCI_GetHeaderType(uint8_t bus, uint8_t slot, uint8_t function);
8185

8286
uint8_t PCI_GetInterruptLine(uint8_t bus, uint8_t slot, uint8_t function);
8387

88+
uint8_t PCI_GetProgrammingInterface(uint8_t bus, uint8_t slot, uint8_t function);
89+
8490
char *PCI_GetSubclassName(uint8_t baseClass, uint8_t subClass);
8591

8692
uint16_t PCI_GetVendorID(uint8_t bus, uint8_t slot, uint8_t function);

MyOS_1/MyOS_1.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@
280280
<ClCompile Include="Drivers\AdLib.c" />
281281
<ClCompile Include="Drivers\Bochs_VGA.c" />
282282
<ClCompile Include="Drivers\e1000.c" />
283+
<ClCompile Include="Drivers\IDE.c" />
283284
<ClCompile Include="Drivers\ISA_DMA.c" />
284285
<ClCompile Include="Drivers\Keyboard.c" />
285286
<ClCompile Include="Drivers\PCI_Bus.c" />
@@ -332,6 +333,7 @@
332333
<ClInclude Include="Drivers\AdLib.h" />
333334
<ClInclude Include="Drivers\Bochs_VGA.h" />
334335
<ClInclude Include="Drivers\e1000.h" />
336+
<ClInclude Include="Drivers\IDE.h" />
335337
<ClInclude Include="Drivers\ISA_DMA.h" />
336338
<ClInclude Include="Drivers\Keyboard.h" />
337339
<ClInclude Include="Drivers\mouse.h" />

0 commit comments

Comments
 (0)