Improve ATA logging.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2022-07-06 11:02:56 -04:00
parent 9e8bcb7690
commit dfd6ba9a28
+49 -37
View File
@@ -18,13 +18,13 @@
#include "hardware/pic8259.h" #include "hardware/pic8259.h"
#include "klib/spinlock.h" #include "klib/spinlock.h"
#include "process/wait.h" #include "process/wait.h"
#include "system/panic.h"
#include "devices/pci.h" #include "devices/pci.h"
#include "io/port_io.h" #include "io/port_io.h"
#include "sys/errno.h" #include "sys/errno.h"
#include "mem/kheap.h" #include "mem/kheap.h"
#include "io/debug.h" #include "io/debug.h"
#include "string.h" #include "string.h"
#include "assert.h"
#include "fs/vfs.h" #include "fs/vfs.h"
#include "fcntl.h" #include "fcntl.h"
#include "stdio.h" #include "stdio.h"
@@ -286,10 +286,8 @@ typedef struct ata_device_t {
vfs_file_t *fs_root; vfs_file_t *fs_root;
} ata_device_t; } ata_device_t;
/// The sector size. #define ATA_SECTOR_SIZE 512 ///< The sector size.
#define ATA_SECTOR_SIZE 512 #define ATA_DMA_SIZE 512 ///< The size of the DMA area.
/// The size of the DMA area.
#define ATA_DMA_SIZE 512
static spinlock_t ata_lock; static spinlock_t ata_lock;
@@ -400,6 +398,18 @@ static inline const char *ata_get_device_status_str(ata_device_t *dev)
return status_str; return status_str;
} }
static inline const char *ata_get_device_settings_str(ata_device_t *dev)
{
if (dev->io_base == 0x1F0) {
if (dev->slave)
return "Primary Slave";
return "Primary Master";
}
if (dev->slave)
return "Secondary Slave";
return "Secondary Master";
}
static inline const char *ata_get_device_type_str(ata_device_type_t type) static inline const char *ata_get_device_type_str(ata_device_type_t type)
{ {
if (type == ata_dev_type_pata) if (type == ata_dev_type_pata)
@@ -514,6 +524,7 @@ static inline bool_t ata_read_device_identity(ata_device_t *dev, ata_identity_co
/// @param dev the device on which we perform the soft reset. /// @param dev the device on which we perform the soft reset.
static inline void ata_soft_reset(ata_device_t *dev) static inline void ata_soft_reset(ata_device_t *dev)
{ {
pr_debug("[%s] Performing ATA soft reset...\n", ata_get_device_settings_str(dev));
// Do a "software reset" on the bus. // Do a "software reset" on the bus.
outportb(dev->control_base, ata_control_srst); outportb(dev->control_base, ata_control_srst);
// Wait for the soft reset to complete. // Wait for the soft reset to complete.
@@ -524,9 +535,10 @@ static inline void ata_soft_reset(ata_device_t *dev)
static inline void ata_enable_bus_mastering(ata_device_t *dev) static inline void ata_enable_bus_mastering(ata_device_t *dev)
{ {
pr_debug("[%s] Enabling bust mastering...\n", ata_get_device_settings_str(dev));
uint16_t pci_cmd = pci_read_field(ata_pci, PCI_COMMAND, 4); uint16_t pci_cmd = pci_read_field(ata_pci, PCI_COMMAND, 4);
if (bit_check(pci_cmd, pci_command_bus_master)) { if (bit_check(pci_cmd, pci_command_bus_master)) {
pr_warning("Bus mastering already enabled.\n"); pr_warning("[%s] Bus mastering already enabled.\n", ata_get_device_settings_str(dev));
} else { } else {
// Set the bit for bus mastering. // Set the bit for bus mastering.
bit_set_assign(pci_cmd, pci_command_bus_master); bit_set_assign(pci_cmd, pci_command_bus_master);
@@ -535,7 +547,7 @@ static inline void ata_enable_bus_mastering(ata_device_t *dev)
// Check that the bus mastering is enabled. // Check that the bus mastering is enabled.
pci_cmd = pci_read_field(ata_pci, PCI_COMMAND, 4); pci_cmd = pci_read_field(ata_pci, PCI_COMMAND, 4);
if (!bit_check(pci_cmd, pci_command_bus_master)) { if (!bit_check(pci_cmd, pci_command_bus_master)) {
pr_warning("Bus mastering is not correctly set.\n"); pr_warning("[%s] Bus mastering is not correctly set.\n", ata_get_device_settings_str(dev));
} }
} }
} }
@@ -549,11 +561,14 @@ static inline void ata_enable_bus_mastering(ata_device_t *dev)
/// For 32-bit Memory Space BARs, you calculate (BAR[x] & 0xFFFFFFF0). /// For 32-bit Memory Space BARs, you calculate (BAR[x] & 0xFFFFFFF0).
static inline void ata_initialize_bus_mastering_address(ata_device_t *dev) static inline void ata_initialize_bus_mastering_address(ata_device_t *dev)
{ {
pr_debug("[%s] Initializing bust mastering...\n", ata_get_device_settings_str(dev));
unsigned address = pci_read_field(ata_pci, PCI_BASE_ADDRESS_4, 4); unsigned address = pci_read_field(ata_pci, PCI_BASE_ADDRESS_4, 4);
// To distinguish between memory space BARs and I/O space BARs, you can // To distinguish between memory space BARs and I/O space BARs, you can
// check the value of the lowest bit. memory space BARs has always a 0, // check the value of the lowest bit. memory space BARs has always a 0,
// while I/O space BARs has always a 1. // while I/O space BARs has always a 1.
assert(bit_check(address, 0)); if (!bit_check(address, 0)) {
kernel_panic("Failed to initialize BUS Mastering.");
}
/// When you want to retrieve the actual base address of a BAR, be sure to /// When you want to retrieve the actual base address of a BAR, be sure to
/// mask the lower bits, for I/O space BARs you calculate (BAR & 0xFFFFFFFC). /// mask the lower bits, for I/O space BARs you calculate (BAR & 0xFFFFFFFC).
address &= 0xFFFFFFFC; address &= 0xFFFFFFFC;
@@ -572,6 +587,7 @@ static inline void ata_initialize_bus_mastering_address(ata_device_t *dev)
/* on Primary bus: ctrl->base =0x1F0, ctrl->dev_ctl =0x3F6. REG_CYL_LO=4, REG_CYL_HI=5, REG_DEVSEL=6 */ /* on Primary bus: ctrl->base =0x1F0, ctrl->dev_ctl =0x3F6. REG_CYL_LO=4, REG_CYL_HI=5, REG_DEVSEL=6 */
static inline ata_device_type_t ata_detect_device_type(ata_device_t *dev) static inline ata_device_type_t ata_detect_device_type(ata_device_t *dev)
{ {
pr_debug("[%s] Detecting device type...\n", ata_get_device_settings_str(dev));
// Perform a soft reset. // Perform a soft reset.
ata_soft_reset(dev); ata_soft_reset(dev);
// Wait until master drive is ready again. // Wait until master drive is ready again.
@@ -597,39 +613,28 @@ static inline ata_device_type_t ata_detect_device_type(ata_device_t *dev)
return ata_dev_type_unknown; return ata_dev_type_unknown;
} }
static inline int buffer_compare(uint32_t *ptr1, uint32_t *ptr2, size_t size)
{
assert(!(size % 4));
size_t i = 0;
while (i < size) {
if (*ptr1 != *ptr2) {
return 1;
}
ptr1++;
ptr2++;
i += sizeof(uint32_t);
}
return 0;
}
/// @brief Creates the DMA memory area used to write and read on the device. /// @brief Creates the DMA memory area used to write and read on the device.
/// @param size the size of the DMA memory area. /// @param size the size of the DMA memory area.
/// @param physical the physical address of the DMA memory area. /// @param physical the physical address of the DMA memory area.
/// @return the logical address of the DMA memory area. /// @return the logical address of the DMA memory area.
static inline uintptr_t malloc_dma(size_t size, uintptr_t *physical) static inline uintptr_t malloc_dma(size_t size, uintptr_t *physical)
{ {
uint32_t order = find_nearest_order_greater(0, sizeof(prdt_t)); // Get the page order to accomodate the size.
page_t *page = _alloc_pages(GFP_KERNEL, order); uint32_t order = find_nearest_order_greater(0, size);
*physical = get_physical_address_from_page(page); page_t *page = _alloc_pages(GFP_KERNEL, order);
return get_lowmem_address_from_page(page); *physical = get_physical_address_from_page(page);
uintptr_t lowmem_address = get_lowmem_address_from_page(page);
pr_debug("[DMA Malloc] Size requirement is %d, which results in an order %d\n", size, order);
pr_debug("[DMA Malloc] Allocated page is at : 0x%p\n", page);
pr_debug("[DMA Malloc] The physical address is at : 0x%p\n", physical);
pr_debug("[DMA Malloc] The lowmem address is at : 0x%p\n", lowmem_address);
return lowmem_address;
} }
// == ATA DEVICE MANAGEMENT =================================================== // == ATA DEVICE MANAGEMENT ===================================================
static bool_t ata_device_init(ata_device_t *dev) static bool_t ata_device_init(ata_device_t *dev)
{ {
pr_debug("Detected ATA device on bus 0x%3x\n", dev->io_reg.data); pr_debug("[%s] Detected ATA device.\n", ata_get_device_settings_str(dev));
// Select the ATA device. // Select the ATA device.
ata_device_select(dev); ata_device_select(dev);
@@ -754,8 +759,6 @@ static void ata_device_read_sector(ata_device_t *dev, uint32_t lba, uint8_t *buf
static void ata_device_write_sector(ata_device_t *dev, uint32_t lba, uint8_t *buffer) static void ata_device_write_sector(ata_device_t *dev, uint32_t lba, uint8_t *buffer)
{ {
pr_debug("ata_device_write_sector(dev: %p, lba: %d, buff: %p)\n", dev, lba, buffer);
spinlock_lock(&ata_lock); spinlock_lock(&ata_lock);
// Copy the buffer over to the DMA area // Copy the buffer over to the DMA area
@@ -861,8 +864,10 @@ static vfs_file_t *ata_open(const char *path, int flags, mode_t mode)
dev = &ata_secondary_master; dev = &ata_secondary_master;
} else if (strcmp(path, ata_secondary_slave.path) == 0) { } else if (strcmp(path, ata_secondary_slave.path) == 0) {
dev = &ata_secondary_slave; dev = &ata_secondary_slave;
} else {
return NULL;
} }
if (dev && dev->fs_root) { if (dev->fs_root) {
++dev->fs_root->count; ++dev->fs_root->count;
return dev->fs_root; return dev->fs_root;
} }
@@ -875,7 +880,9 @@ static int ata_close(vfs_file_t *file)
// Get the device from the VFS file. // Get the device from the VFS file.
ata_device_t *dev = (ata_device_t *)file->device; ata_device_t *dev = (ata_device_t *)file->device;
// Check the device. // Check the device.
assert(dev && "Device not set."); if (dev == NULL) {
kernel_panic("Device not set.");
}
// //
if ((dev == &ata_primary_master) || (dev == &ata_primary_slave) || if ((dev == &ata_primary_master) || (dev == &ata_primary_slave) ||
(dev == &ata_secondary_master) || (dev == &ata_secondary_slave)) { (dev == &ata_secondary_master) || (dev == &ata_secondary_slave)) {
@@ -886,13 +893,15 @@ static int ata_close(vfs_file_t *file)
static ssize_t ata_read(vfs_file_t *file, char *buffer, off_t offset, size_t size) static ssize_t ata_read(vfs_file_t *file, char *buffer, off_t offset, size_t size)
{ {
pr_debug("ata_read(%p, %p, %d, %d)\n", file, buffer, offset, size); pr_debug("ata_read(file: 0x%p, buffer: 0x%p, offest: %8d, size: %8d)\n", file, buffer, offset, size);
// Prepare a static support buffer. // Prepare a static support buffer.
static char support_buffer[ATA_SECTOR_SIZE]; static char support_buffer[ATA_SECTOR_SIZE];
// Get the device from the VFS file. // Get the device from the VFS file.
ata_device_t *dev = (ata_device_t *)file->device; ata_device_t *dev = (ata_device_t *)file->device;
// Check the device. // Check the device.
assert(dev && "Device not set."); if (dev == NULL) {
kernel_panic("Device not set.");
}
if ((dev->type == ata_dev_type_pata) || (dev->type == ata_dev_type_sata)) { if ((dev->type == ata_dev_type_pata) || (dev->type == ata_dev_type_sata)) {
uint32_t start_block = offset / ATA_SECTOR_SIZE; uint32_t start_block = offset / ATA_SECTOR_SIZE;
@@ -948,7 +957,10 @@ static ssize_t ata_write(vfs_file_t *file, const void *buffer, off_t offset, siz
// Get the device from the VFS file. // Get the device from the VFS file.
ata_device_t *dev = (ata_device_t *)file->device; ata_device_t *dev = (ata_device_t *)file->device;
// Check the device. // Check the device.
assert(dev && "Device not set."); if (dev == NULL) {
kernel_panic("Device not set.");
}
if ((dev->type == ata_dev_type_pata) || (dev->type == ata_dev_type_sata)) { if ((dev->type == ata_dev_type_pata) || (dev->type == ata_dev_type_sata)) {
uint32_t start_block = offset / ATA_SECTOR_SIZE; uint32_t start_block = offset / ATA_SECTOR_SIZE;
uint32_t start_offset = offset % ATA_SECTOR_SIZE; uint32_t start_offset = offset % ATA_SECTOR_SIZE;