get ide controllers from pci instead of assuming compatibility mode; name pata drives based on order discovered instead of controller
This commit is contained in:
parent
7d90ac7d3d
commit
6d9c3f7794
10 changed files with 251 additions and 199 deletions
|
|
@ -4,4 +4,4 @@ quiet: yes
|
|||
/Calcite
|
||||
protocol: limine
|
||||
path: boot():/calcite/kernel.elf
|
||||
cmdline: root-drive=pata2,root-fs=iso9660
|
||||
cmdline: root-drive=pata0,root-fs=iso9660
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "panic.h"
|
||||
#include "timer.h"
|
||||
#include "heap.h"
|
||||
#include "pata.h"
|
||||
#include "pci.h"
|
||||
#include "ps2.h"
|
||||
#include "fs.h"
|
||||
|
||||
|
|
@ -273,9 +273,9 @@ static const char *cmdline_look_up(const char *key) {
|
|||
register_syscall(SYSCALL_CREATE_THREAD, (void *)&syscall_create_thread);
|
||||
register_syscall(SYSCALL_GET_ENVVAR, (void *)&syscall_get_envvar);
|
||||
|
||||
//probe for drives
|
||||
//probe pci devices
|
||||
|
||||
probe_pata_drives();
|
||||
probe_pci();
|
||||
|
||||
//load root file system
|
||||
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
; Calcite, src/kernel/pata.asm
|
||||
; Copyright 2025 Benji Dial
|
||||
;
|
||||
; This program 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.
|
||||
;
|
||||
; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
bits 64
|
||||
default rel
|
||||
|
||||
section .text
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_set_device
|
||||
pata_set_device:
|
||||
mov dx, 0x01f6
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
mov al, sil
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_set_features
|
||||
pata_set_features:
|
||||
mov dx, 0x01f1
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
mov al, sil
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_set_lba
|
||||
pata_set_lba:
|
||||
|
||||
mov dx, 0x01f3
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
mov eax, esi
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
shr eax, 8
|
||||
out dx, al
|
||||
|
||||
inc dx
|
||||
shr ax, 8
|
||||
out dx, al
|
||||
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_set_command
|
||||
pata_set_command:
|
||||
mov dx, 0x01f7
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
mov al, sil
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_read_status
|
||||
pata_read_status:
|
||||
mov dx, 0x01f7
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_read_error
|
||||
pata_read_error:
|
||||
mov dx, 0x01f1
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_read_lba
|
||||
pata_read_lba:
|
||||
|
||||
mov dx, 0x01f5
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
xor eax, eax
|
||||
in al, dx
|
||||
|
||||
dec dx
|
||||
shl ax, 8
|
||||
in al, dx
|
||||
|
||||
dec dx
|
||||
shl eax, 8
|
||||
in al, dx
|
||||
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_read_data
|
||||
pata_read_data:
|
||||
movzx rcx, dx
|
||||
mov dx, 0x01f0
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
mov rdi, rsi
|
||||
rep insw
|
||||
ret
|
||||
|
||||
;referenced in pata.c
|
||||
global pata_write_data
|
||||
pata_write_data:
|
||||
movzx rcx, dx
|
||||
mov dx, 0x01f0
|
||||
shl dil, 7
|
||||
xor dl, dil
|
||||
rep outsw
|
||||
ret
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
* with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pci.h"
|
||||
#include "utility.h"
|
||||
#include "drives.h"
|
||||
#include "panic.h"
|
||||
|
|
@ -22,41 +23,25 @@
|
|||
#include "pata.h"
|
||||
|
||||
//some relevant sources:
|
||||
// https://www.isdaman.com/alsos/hardware/hdc/pciide.pdf
|
||||
// ANSI: AT Attachment 8 - ATA/ATAPI Command Set
|
||||
// Seagate: SCSI Commands Reference Manual
|
||||
// OSDev Wiki: ATAPI, PCI IDE Controller
|
||||
|
||||
//in any function that takes a "controller", 0 means the primary controller
|
||||
//and 1 means the secondary controller. in any function that takes a "drive",
|
||||
//bit 1 is the controller, and bit 0 is bit 4 of the device register.
|
||||
|
||||
//all defined in pata.asm
|
||||
void pata_set_device(uint8_t controller, uint8_t value);
|
||||
void pata_set_features(uint8_t controller, uint8_t value);
|
||||
void pata_set_lba(uint8_t controller, uint32_t value);
|
||||
void pata_set_command(uint8_t controller, uint8_t value);
|
||||
uint8_t pata_read_status(uint8_t controller);
|
||||
uint8_t pata_read_error(uint8_t controller);
|
||||
uint32_t pata_read_lba(uint8_t controller);
|
||||
void pata_read_data(
|
||||
uint8_t controller, uint16_t *buffer, uint16_t word_count);
|
||||
void pata_write_data(
|
||||
uint8_t controller, const uint16_t *buffer, uint16_t word_count);
|
||||
|
||||
enum pata_result {
|
||||
PR_SUCCESS,
|
||||
PR_NO_CONTROLLER,
|
||||
PR_ABORTED
|
||||
};
|
||||
|
||||
enum pata_result wait_pio(uint8_t controller) {
|
||||
enum pata_result wait_pio(uint16_t command_block_base) {
|
||||
while (1) {
|
||||
uint8_t status = pata_read_status(controller);
|
||||
uint8_t status = inb(command_block_base + 7);
|
||||
//0x00 happens in qemu, 0x7f happens in virtualbox
|
||||
if (status == 0x00 || status == 0x7f)
|
||||
return PR_NO_CONTROLLER;
|
||||
if (status & 0x01) {
|
||||
uint8_t error = pata_read_error(controller);
|
||||
uint8_t error = inb(command_block_base + 1);
|
||||
if (error == 0x04)
|
||||
return PR_ABORTED;
|
||||
panic("TODO")
|
||||
|
|
@ -69,51 +54,50 @@ enum pata_result wait_pio(uint8_t controller) {
|
|||
|
||||
//buffer should have room for 256 words.
|
||||
static enum pata_result
|
||||
pata_identify_packet_device(uint8_t drive, uint16_t *buffer) {
|
||||
pata_identify_packet_device(uint16_t command_block_base, uint8_t device_byte, uint16_t *buffer) {
|
||||
|
||||
uint8_t controller = drive >> 1;
|
||||
outb(command_block_base + 6, device_byte);
|
||||
outb(command_block_base + 7, 0xa1);
|
||||
|
||||
pata_set_device(controller, (drive & 0x01) << 4);
|
||||
pata_set_command(controller, 0xa1);
|
||||
|
||||
enum pata_result result = wait_pio(controller);
|
||||
enum pata_result result = wait_pio(command_block_base);
|
||||
if (result != PR_SUCCESS)
|
||||
return result;
|
||||
|
||||
pata_read_data(controller, buffer, 256);
|
||||
insw(command_block_base, buffer, 256);
|
||||
return PR_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static enum pata_result patapi_read_capacity(
|
||||
uint8_t drive, uint32_t *max_block_out, uint32_t *block_size_out) {
|
||||
uint16_t command_block_base, uint8_t device_byte, uint32_t *max_block_out, uint32_t *block_size_out) {
|
||||
|
||||
uint8_t controller = drive >> 1;
|
||||
outb(command_block_base + 6, device_byte);
|
||||
outb(command_block_base + 1, 0);
|
||||
outb(command_block_base + 3, 0);
|
||||
outb(command_block_base + 4, 8);
|
||||
outb(command_block_base + 5, 0);
|
||||
outb(command_block_base + 7, 0xa0);
|
||||
|
||||
pata_set_device(controller, (drive & 0x01) << 4);
|
||||
pata_set_features(controller, 0);
|
||||
pata_set_lba(controller, 8 << 8);
|
||||
pata_set_command(controller, 0xa0);
|
||||
|
||||
enum pata_result result = wait_pio(controller);
|
||||
enum pata_result result = wait_pio(command_block_base);
|
||||
if (result != PR_SUCCESS)
|
||||
return result;
|
||||
|
||||
uint8_t cmd[12] = {
|
||||
0x25, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0 };
|
||||
pata_write_data(controller, (uint16_t *)cmd, 6);
|
||||
outsw(command_block_base, cmd, 6);
|
||||
|
||||
result = wait_pio(controller);
|
||||
result = wait_pio(command_block_base);
|
||||
if (result != PR_SUCCESS)
|
||||
return result;
|
||||
|
||||
uint32_t actual_response_size = pata_read_lba(controller) >> 8;
|
||||
uint32_t actual_response_size =
|
||||
inb(command_block_base + 4) | (inb(command_block_base + 5) << 8);
|
||||
if (actual_response_size != 8)
|
||||
panic("TODO")
|
||||
|
||||
uint32_t response[2];
|
||||
pata_read_data(controller, (uint16_t *)response, 4);
|
||||
insw(command_block_base, response, 4);
|
||||
|
||||
*max_block_out = end_swap_u32(response[0]);
|
||||
*block_size_out = end_swap_u32(response[1]);
|
||||
|
|
@ -122,16 +106,17 @@ static enum pata_result patapi_read_capacity(
|
|||
}
|
||||
|
||||
static enum pata_result patapi_read(
|
||||
uint8_t drive, uint16_t block_size, uint32_t start_block, uint32_t block_count, void *buffer) {
|
||||
uint16_t command_block_base, uint8_t device_byte, uint16_t block_size,
|
||||
uint32_t start_block, uint32_t block_count, void *buffer) {
|
||||
|
||||
uint8_t controller = drive >> 1;
|
||||
outb(command_block_base + 6, device_byte);
|
||||
outb(command_block_base + 1, 0);
|
||||
outb(command_block_base + 3, 0);
|
||||
outb(command_block_base + 4, block_size & 0xff);
|
||||
outb(command_block_base + 5, block_size >> 8);
|
||||
outb(command_block_base + 7, 0xa0);
|
||||
|
||||
pata_set_device(controller, (drive & 0x01) << 4);
|
||||
pata_set_features(controller, 0);
|
||||
pata_set_lba(controller, (uint32_t)block_size << 8);
|
||||
pata_set_command(controller, 0xa0);
|
||||
|
||||
enum pata_result result = wait_pio(controller);
|
||||
enum pata_result result = wait_pio(command_block_base);
|
||||
if (result != PR_SUCCESS)
|
||||
return result;
|
||||
|
||||
|
|
@ -146,19 +131,21 @@ static enum pata_result patapi_read(
|
|||
(block_count >> 8) & 0xff,
|
||||
block_count & 0xff,
|
||||
0, 0 };
|
||||
pata_write_data(controller, (uint16_t *)cmd, 8);
|
||||
outsw(command_block_base, cmd, 6);
|
||||
|
||||
for (uint32_t i = 0; i < block_count; ++i) {
|
||||
|
||||
result = wait_pio(controller);
|
||||
result = wait_pio(command_block_base);
|
||||
if (result != PR_SUCCESS)
|
||||
return result;
|
||||
|
||||
uint32_t actual_response_size = pata_read_lba(controller) >> 8;
|
||||
uint32_t actual_response_size =
|
||||
inb(command_block_base + 4) | (inb(command_block_base + 5) << 8);
|
||||
|
||||
if (actual_response_size != block_size)
|
||||
panic("TODO")
|
||||
|
||||
pata_read_data(controller, (uint16_t *)(buffer + i * block_size), block_size / 2);
|
||||
insw(command_block_base, buffer + i * block_size, block_size / 2);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +156,8 @@ static enum pata_result patapi_read(
|
|||
static uint16_t ipd_buffer[256];
|
||||
|
||||
struct pata_driver_info {
|
||||
uint8_t drive;
|
||||
uint16_t command_block_base;
|
||||
uint8_t device_byte;
|
||||
};
|
||||
|
||||
static enum drive_access_result read_blocks_patapi(
|
||||
|
|
@ -179,30 +167,36 @@ static enum drive_access_result read_blocks_patapi(
|
|||
if (count >= (1ULL << 32) || start >= (1ULL << 32))
|
||||
panic("TODO")
|
||||
|
||||
uint8_t drive = ((const struct pata_driver_info *)drive_info->driver_info)->drive;
|
||||
const struct pata_driver_info *driver_info = drive_info->driver_info;
|
||||
|
||||
return
|
||||
patapi_read(
|
||||
drive, drive_info->block_size,
|
||||
start, count, buffer) == PR_SUCCESS
|
||||
driver_info->command_block_base, driver_info->device_byte,
|
||||
drive_info->block_size, start, count, buffer) == PR_SUCCESS
|
||||
? DAR_SUCCESS : DAR_HARDWARE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
static void probe_pata_drive(uint8_t drive) {
|
||||
int next_pata_drive_number = 0;
|
||||
|
||||
if (pata_identify_packet_device(drive, ipd_buffer) != PR_SUCCESS)
|
||||
static void probe_pata_drive(uint16_t command_block_base, uint8_t device_byte) {
|
||||
|
||||
if (pata_identify_packet_device(command_block_base, device_byte, ipd_buffer) != PR_SUCCESS)
|
||||
return;
|
||||
|
||||
uint32_t max_block, block_size;
|
||||
if (patapi_read_capacity(drive, &max_block, &block_size) != PR_SUCCESS)
|
||||
if (patapi_read_capacity(
|
||||
command_block_base, device_byte, &max_block, &block_size) != PR_SUCCESS)
|
||||
return;
|
||||
|
||||
if (next_pata_drive_number > 9)
|
||||
panic("TODO")
|
||||
|
||||
struct drive_info *di = add_drive();
|
||||
|
||||
char *name = heap_alloc(6);
|
||||
memcpy(name, "pata", 4);
|
||||
name[4] = '0' + drive;
|
||||
name[4] = '0' + next_pata_drive_number++;
|
||||
name[5] = 0;
|
||||
di->name = name;
|
||||
|
||||
|
|
@ -211,14 +205,38 @@ static void probe_pata_drive(uint8_t drive) {
|
|||
|
||||
struct pata_driver_info *driver_info =
|
||||
heap_alloc(sizeof(struct pata_driver_info));
|
||||
driver_info->drive = drive;
|
||||
driver_info->command_block_base = command_block_base;
|
||||
driver_info->device_byte = device_byte;
|
||||
di->driver_info = driver_info;
|
||||
|
||||
di->read_blocks = &read_blocks_patapi;
|
||||
|
||||
}
|
||||
|
||||
void probe_pata_drives() {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
probe_pata_drive(i);
|
||||
void probe_pata_drives(uint32_t pci_address_base, uint32_t pci_class_etc) {
|
||||
|
||||
if (pci_class_etc & 0x00000100) {
|
||||
uint32_t bar = read_pci_config(pci_address_base + 0x10);
|
||||
if ((bar & 0xffff0003) != 0x00000001)
|
||||
panic("TODO")
|
||||
probe_pata_drive(bar & 0xfffc, 0x00);
|
||||
probe_pata_drive(bar & 0xfffc, 0x10);
|
||||
}
|
||||
else {
|
||||
probe_pata_drive(0x01f0, 0x00);
|
||||
probe_pata_drive(0x01f0, 0x10);
|
||||
}
|
||||
|
||||
if (pci_class_etc & 0x00000400) {
|
||||
uint32_t bar = read_pci_config(pci_address_base + 0x18);
|
||||
if ((bar & 0xffff0003) != 0x00000001)
|
||||
panic("TODO")
|
||||
probe_pata_drive(bar & 0xfffc, 0x00);
|
||||
probe_pata_drive(bar & 0xfffc, 0x10);
|
||||
}
|
||||
else {
|
||||
probe_pata_drive(0x0170, 0x00);
|
||||
probe_pata_drive(0x0170, 0x10);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,5 +19,5 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
//probes for all four pata drives and adds any that exist to drives.h
|
||||
void probe_pata_drives();
|
||||
//probes for pata drives on this "card" and adds any that exist to drives.h
|
||||
void probe_pata_drives(uint32_t pci_address_base, uint32_t pci_class_etc);
|
||||
|
|
|
|||
40
src/kernel/pci.asm
Normal file
40
src/kernel/pci.asm
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
; Calcite, src/kernel/pci.asm
|
||||
; Copyright 2025 Benji Dial
|
||||
;
|
||||
; This program 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.
|
||||
;
|
||||
; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
bits 64
|
||||
default rel
|
||||
|
||||
section .text
|
||||
|
||||
global read_pci_config
|
||||
read_pci_config:
|
||||
mov dx, 0x0cf8
|
||||
mov eax, edi
|
||||
out dx, eax
|
||||
mov dx, 0x0cfc
|
||||
in eax, dx
|
||||
ret
|
||||
|
||||
global write_pci_config
|
||||
write_pci_config:
|
||||
mov dx, 0x0cf8
|
||||
mov eax, edi
|
||||
out dx, eax
|
||||
mov dx, 0x0cfc
|
||||
mov eax, esi
|
||||
out dx, eax
|
||||
ret
|
||||
59
src/kernel/pci.c
Normal file
59
src/kernel/pci.c
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* Calcite, src/kernel/pci.c
|
||||
* Copyright 2025 Benji Dial
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pata.h"
|
||||
#include "pci.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static void probe_bus(uint32_t bus_address_base) {
|
||||
|
||||
for (uint32_t device_address_base = bus_address_base;
|
||||
device_address_base < bus_address_base + 0x00010000;
|
||||
device_address_base += 0x00000800)
|
||||
for (uint32_t function_address_base = device_address_base;
|
||||
function_address_base < device_address_base + 0x00000800;
|
||||
function_address_base += 0x00000100) {
|
||||
|
||||
uint8_t header_type = (read_pci_config(function_address_base | 0x0c) >> 16) & 0xff;
|
||||
if (header_type == 0xff)
|
||||
break;
|
||||
|
||||
if ((header_type & 0x7f) == 0x01)
|
||||
//this is a pci-to-pci bridge
|
||||
probe_bus((read_pci_config(function_address_base | 0x18) >> 8) & 0xff);
|
||||
|
||||
else if ((header_type & 0x7f) == 0x00) {
|
||||
//this is a normal function
|
||||
uint32_t class_etc = read_pci_config(function_address_base | 0x08);
|
||||
switch (class_etc & 0xffff0000) {
|
||||
case 0x01010000:
|
||||
probe_pata_drives(function_address_base, class_etc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(header_type & 0x80))
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void probe_pci() {
|
||||
probe_bus(0x80000000);
|
||||
}
|
||||
32
src/kernel/pci.h
Normal file
32
src/kernel/pci.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* Calcite, src/kernel/pci.h
|
||||
* Copyright 2025 Benji Dial
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//reads one dword from config space.
|
||||
//address is 0x8000000 | (bus << 16) | (device << 11) | (function << 8) | (bytes into that function's space).
|
||||
//bytes into that function's space must be dword-aligned.
|
||||
uint32_t read_pci_config(uint32_t address);
|
||||
|
||||
//writes one dword to config space.
|
||||
//address is 0x8000000 | (bus << 16) | (device << 11) | (function << 8) | (bytes into that function's space).
|
||||
//bytes into that function's space must be dword-aligned.
|
||||
void write_pci_config(uint32_t address, uint32_t value);
|
||||
|
||||
void probe_pci();
|
||||
|
|
@ -32,3 +32,31 @@ memzero:
|
|||
mov rcx, rsi
|
||||
rep stosb
|
||||
ret
|
||||
|
||||
global outb
|
||||
outb:
|
||||
mov dx, di
|
||||
mov al, sil
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
global inb
|
||||
inb:
|
||||
mov dx, di
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
global outsw
|
||||
outsw:
|
||||
mov rcx, rdx
|
||||
mov dx, di
|
||||
rep outsw
|
||||
ret
|
||||
|
||||
global insw
|
||||
insw:
|
||||
mov rcx, rdx
|
||||
mov dx, di
|
||||
mov rdi, rsi
|
||||
rep insw
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -34,3 +34,8 @@ uint32_t end_swap_u32(uint32_t value);
|
|||
//4. zeroes rest of new buffer
|
||||
//5. sets buffer and length to new buffer and twice length
|
||||
void double_buffer_zero(void **buffer, int *length, uint64_t bytes_per_entry);
|
||||
|
||||
void outb(uint16_t port, uint8_t byte);
|
||||
uint8_t inb(uint16_t port);
|
||||
void outsw(uint16_t port, const void *buffer, uint64_t words);
|
||||
void insw(uint16_t port, void *buffer, uint64_t words);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue