From a1bf1cd7b4c2be33202566869a4a39e882c53205 Mon Sep 17 00:00:00 2001 From: quackerd Date: Mon, 11 Nov 2024 05:14:06 -0500 Subject: [PATCH] ide --- sys/arm64/machine.c | 11 +- sys/dev/ata.h | 256 +++++++++++++++++++++-- sys/dev/ide.c | 466 ++++++++++++++++++++++-------------------- sys/include/kassert.h | 4 +- sys/include/sysctl.h | 3 +- sys/kern/bufcache.c | 4 +- sys/kern/vfs.c | 4 +- 7 files changed, 493 insertions(+), 255 deletions(-) diff --git a/sys/arm64/machine.c b/sys/arm64/machine.c index f04e5f4..c576071 100644 --- a/sys/arm64/machine.c +++ b/sys/arm64/machine.c @@ -110,10 +110,8 @@ void Machine_Init() // XXX: disable interrupts here to avoid the timer interrupt firing before KTimer is initialized // alternatively, break the dependency or use an "initialized" flag in KTimer_Process - disable_interrupts(); PTimer_Init(); KTimer_Init(); - enable_interrupts(); Thread_Init(); @@ -132,19 +130,20 @@ void Machine_Init() PCI_Init(); // PCI BUS BufCache_Init(); - while(1){ - hlt(); - } /* * Open the primary disk and mount the root file system */ Disk *root = Disk_GetByID(0, 0); if (!root) - Panic("No boot disk!"); + Panic("No boot disk!"); VFS_MountRoot(root); Critical_Exit(); + while(1){ + hlt(); + } + /* * Create the idle thread */ diff --git a/sys/dev/ata.h b/sys/dev/ata.h index 33fab27..91f4409 100644 --- a/sys/dev/ata.h +++ b/sys/dev/ata.h @@ -5,30 +5,242 @@ #ifndef __ATA_H__ #define __ATA_H__ -typedef struct ATAIdentifyDevice +#include + +#define LITTLE_ENDIAN +/* + * Drive parameter structure for ATA/ATAPI. + * Bit fields: WDC_* : common to ATA/ATAPI + * ATA_* : ATA only + * ATAPI_* : ATAPI only. + */ +typedef struct { - uint16_t _rsvd0[10]; // 0-9 - uint8_t serial[20]; // 10-19 - Serial - uint16_t _rsvd1[3]; // 20-22 - uint8_t firmware[8]; // 23-26 - Firmware - uint8_t model[40]; // 27-46 - Model - uint16_t _rsvd2[16]; // 47-62 X - uint16_t dmaMode; // 63 - DMA Mode - uint16_t _rsvd3[11]; // 64-74 X - uint16_t queueDepth; // 75 - Queue Depth - uint16_t sataCap; // 76 - SATA Capabilities - uint16_t ncqCap; // 77 - NCQ Capabilities - uint16_t _rsvd4[8]; // 78-85 - uint16_t deviceFlags; // 86 - Device Flags (48-bit Addressing) - uint16_t deviceFlags2; // 87 - Device Flags 2 (SMART) - uint16_t udmaMode; // 88 - Ultra DMA Mode - uint16_t _rsvd5[11]; // 89-99 - uint64_t lbaSectors; // 100-103 - User Addressable Logical Sectors - uint16_t _rsvd6[2]; // 104-105 - uint16_t sectorSize; // 106 - Physical Sector Size - uint16_t _rsvd7[148]; // 107-254 - uint16_t chksum; // 255 - Checksum + /* drive info */ + uint16_t atap_config; /* 0: general configuration */ +#define WDC_CFG_ATAPI_MASK 0xc000 +#define WDC_CFG_ATAPI 0x8000 +#define ATA_CFG_REMOVABLE 0x0080 +#define ATA_CFG_FIXED 0x0040 +#define ATAPI_CFG_TYPE_MASK 0x1f00 +#define ATAPI_CFG_TYPE(x) (((x) & ATAPI_CFG_TYPE_MASK) >> 8) +#define ATAPI_CFG_TYPE_DIRECT 0x00 +#define ATAPI_CFG_TYPE_SEQUENTIAL 0x01 +#define ATAPI_CFG_TYPE_CDROM 0x05 +#define ATAPI_CFG_TYPE_OPTICAL 0x07 +#define ATAPI_CFG_TYPE_NODEVICE 0x1F +#define ATAPI_CFG_REMOV 0x0080 +#define ATAPI_CFG_DRQ_MASK 0x0060 +#define ATAPI_CFG_STD_DRQ 0x0000 +#define ATAPI_CFG_IRQ_DRQ 0x0020 +#define ATAPI_CFG_ACCEL_DRQ 0x0040 +#define ATAPI_CFG_CMD_MASK 0x0003 +#define ATAPI_CFG_CMD_12 0x0000 +#define ATAPI_CFG_CMD_16 0x0001 +/* words 1-9 are ATA only */ + uint16_t atap_cylinders; /* 1: # of non-removable cylinders */ + uint16_t __reserved1; + uint16_t atap_heads; /* 3: # of heads */ + uint16_t __retired1[2]; /* 4-5: # of unform. bytes/track */ + uint16_t atap_sectors; /* 6: # of sectors */ + uint16_t __retired2[3]; + + uint8_t atap_serial[20]; /* 10-19: serial number */ + uint16_t __retired3[2]; + uint16_t __obsolete1; + uint8_t atap_revision[8]; /* 23-26: firmware revision */ + uint8_t atap_model[40]; /* 27-46: model number */ + uint16_t atap_multi; /* 47: maximum sectors per irq (ATA) */ + uint16_t __reserved2; + uint8_t atap_vendor; /* 49: vendor */ + uint8_t atap_capabilities1; /* 49: capability flags */ +#define WDC_CAP_IORDY 0x0800 +#define WDC_CAP_IORDY_DSBL 0x0400 +#define WDC_CAP_LBA 0x0200 +#define WDC_CAP_DMA 0x0100 +#define ATA_CAP_STBY 0x2000 +#define ATAPI_CAP_INTERL_DMA 0x8000 +#define ATAPI_CAP_CMD_QUEUE 0x4000 +#define ATAPI_CAP_OVERLP 0x2000 +#define ATAPI_CAP_ATA_RST 0x1000 + uint16_t atap_capabilities2; /* 50: capability flags (ATA) */ +#ifdef LITTLE_ENDIAN + uint8_t __junk2; + uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */ + uint8_t __junk3; + uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */ +#else + uint8_t atap_oldpiotiming; /* 51: old PIO timing mode */ + uint8_t __junk2; + uint8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */ + uint8_t __junk3; +#endif + uint16_t atap_extensions; /* 53: extensions supported */ +#define WDC_EXT_UDMA_MODES 0x0004 +#define WDC_EXT_MODES 0x0002 +#define WDC_EXT_GEOM 0x0001 +/* words 54-62 are ATA only */ + uint16_t atap_curcylinders; /* 54: current logical cylinders */ + uint16_t atap_curheads; /* 55: current logical heads */ + uint16_t atap_cursectors; /* 56: current logical sectors/tracks */ + uint16_t atap_curcapacity[2]; /* 57-58: current capacity */ + uint8_t atap_curmulti; /* 59: current multi-sector setting */ + uint8_t atap_curmulti_valid; /* 59: current multi-sector setting */ +#define WDC_MULTI_VALID 0x0100 +#define WDC_MULTI_MASK 0x00ff + uint32_t atap_capacity; /* 60-61: total capacity (LBA only) */ + uint16_t __retired4; +#ifdef LITTLE_ENDIAN + uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */ + uint8_t atap_dmamode_act; /* multiword DMA mode active */ + uint8_t atap_piomode_supp; /* 64: PIO mode supported */ + uint8_t __junk4; +#else + uint8_t atap_dmamode_act; /* multiword DMA mode active */ + uint8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */ + uint8_t __junk4; + uint8_t atap_piomode_supp; /* 64: PIO mode supported */ +#endif + uint16_t atap_dmatiming_mimi; /* 65: minimum DMA cycle time */ + uint16_t atap_dmatiming_recom; /* 66: recommended DMA cycle time */ + uint16_t atap_piotiming; /* 67: mini PIO cycle time without FC */ + uint16_t atap_piotiming_iordy; /* 68: mini PIO cycle time with IORDY FC */ + uint16_t __reserved3[2]; +/* words 71-72 are ATAPI only */ + uint16_t atap_pkt_br; /* 71: time (ns) to bus release */ + uint16_t atap_pkt_bsyclr; /* 72: tme to clear BSY after service */ + uint16_t __reserved4[2]; + uint16_t atap_queuedepth; /* 75: */ +#define WDC_QUEUE_DEPTH_MASK 0x1f + uint16_t atap_sata_caps; /* 76: SATA capabilities */ +#define SATA_SIGNAL_GEN1 0x0002 /* SATA Gen-1 signaling speed */ +#define SATA_SIGNAL_GEN2 0x0004 /* SATA Gen-2 signaling speed */ +#define SATA_NATIVE_CMDQ 0x0100 /* native command queuing */ +#define SATA_HOST_PWR_MGMT 0x0200 /* power management (host) */ + uint16_t atap_sata_reserved; /* 77: reserved */ + uint16_t atap_sata_features_supp;/* 78: SATA features supported */ +#define SATA_NONZERO_OFFSETS 0x0002 /* non-zero buffer offsets */ +#define SATA_DMA_SETUP_AUTO 0x0004 /* DMA setup auto-activate */ +#define SATA_DRIVE_PWR_MGMT 0x0008 /* power management (device) */ + uint16_t atap_sata_features_en; /* 79: SATA features enabled */ + uint16_t atap_ata_major; /* 80: Major version number */ +#define WDC_VER_ATA1 0x0002 +#define WDC_VER_ATA2 0x0004 +#define WDC_VER_ATA3 0x0008 +#define WDC_VER_ATA4 0x0010 +#define WDC_VER_ATA5 0x0020 +#define WDC_VER_ATA6 0x0040 +#define WDC_VER_ATA7 0x0080 +#define WDC_VER_ATA8 0x0100 +#define WDC_VER_ATA9 0x0200 +#define WDC_VER_ATA10 0x0400 +#define WDC_VER_ATA11 0x0800 +#define WDC_VER_ATA12 0x1000 +#define WDC_VER_ATA13 0x2000 +#define WDC_VER_ATA14 0x4000 + uint16_t atap_ata_minor; /* 81: Minor version number */ + uint16_t atap_cmd_set1; /* 82: command set supported */ +#define WDC_CMD1_NOP 0x4000 +#define WDC_CMD1_RB 0x2000 +#define WDC_CMD1_WB 0x1000 +#define WDC_CMD1_HPA 0x0400 +#define WDC_CMD1_DVRST 0x0200 +#define WDC_CMD1_SRV 0x0100 +#define WDC_CMD1_RLSE 0x0080 +#define WDC_CMD1_AHEAD 0x0040 +#define WDC_CMD1_CACHE 0x0020 +#define WDC_CMD1_PKT 0x0010 +#define WDC_CMD1_PM 0x0008 +#define WDC_CMD1_REMOV 0x0004 +#define WDC_CMD1_SEC 0x0002 +#define WDC_CMD1_SMART 0x0001 + uint16_t atap_cmd_set2; /* 83: command set supported */ +#define ATAPI_CMD2_FCE 0x2000 /* Flush Cache Ext supported */ +#define ATAPI_CMD2_FC 0x1000 /* Flush Cache supported */ +#define ATAPI_CMD2_DCO 0x0800 /* Device Configuration Overlay supported */ +#define ATAPI_CMD2_48AD 0x0400 /* 48bit address supported */ +#define ATAPI_CMD2_AAM 0x0200 /* Automatic Acoustic Management supported */ +#define ATAPI_CMD2_SM 0x0100 /* Set Max security extension supported */ +#define ATAPI_CMD2_SF 0x0040 /* Set Features subcommand required */ +#define ATAPI_CMD2_PUIS 0x0020 /* Power up in standby supported */ +#define WDC_CMD2_RMSN 0x0010 +#define ATA_CMD2_APM 0x0008 +#define ATA_CMD2_CFA 0x0004 +#define ATA_CMD2_RWQ 0x0002 +#define WDC_CMD2_DM 0x0001 /* Download Microcode supported */ + uint16_t atap_cmd_ext; /* 84: command/features supp. ext. */ +#define ATAPI_CMDE_MSER 0x0004 /* Media serial number supported */ +#define ATAPI_CMDE_TEST 0x0002 /* SMART self-test supported */ +#define ATAPI_CMDE_SLOG 0x0001 /* SMART error logging supported */ + uint16_t atap_cmd1_en; /* 85: cmd/features enabled */ +/* bits are the same as atap_cmd_set1 */ + uint16_t atap_cmd2_en; /* 86: cmd/features enabled */ +/* bits are the same as atap_cmd_set2 */ + uint16_t atap_cmd_def; /* 87: cmd/features default */ +/* bits are NOT the same as atap_cmd_ext */ +#ifdef LITTLE_ENDIAN + uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */ + uint8_t atap_udmamode_act; /* Ultra-DMA mode active */ +#else + uint8_t atap_udmamode_act; /* Ultra-DMA mode active */ + uint8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */ +#endif +/* 89-92 are ATA-only */ + uint16_t atap_seu_time; /* 89: Sec. Erase Unit compl. time */ + uint16_t atap_eseu_time; /* 90: Enhanced SEU compl. time */ + uint16_t atap_apm_val; /* 91: current APM value */ + uint16_t atap_mpasswd_rev; /* 92: Master Password revision */ + uint16_t atap_hwreset_res; /* 93: Hardware reset value */ +#define ATA_HWRES_CBLID 0x2000 /* CBLID above Vih */ +#define ATA_HWRES_D1_PDIAG 0x0800 /* Device 1 PDIAG detect OK */ +#define ATA_HWRES_D1_CSEL 0x0400 /* Device 1 used CSEL for address */ +#define ATA_HWRES_D1_JUMP 0x0200 /* Device 1 jumpered to address */ +#define ATA_HWRES_D0_SEL 0x0040 /* Device 0 responds when Dev 1 selected */ +#define ATA_HWRES_D0_DASP 0x0020 /* Device 0 DASP detect OK */ +#define ATA_HWRES_D0_PDIAG 0x0010 /* Device 0 PDIAG detect OK */ +#define ATA_HWRES_D0_DIAG 0x0008 /* Device 0 diag OK */ +#define ATA_HWRES_D0_CSEL 0x0004 /* Device 0 used CSEL for address */ +#define ATA_HWRES_D0_JUMP 0x0002 /* Device 0 jumpered to address */ +#ifdef LITTLE_ENDIAN + uint8_t atap_acoustic_val; /* 94: Current acoustic level */ + uint8_t atap_acoustic_def; /* recommended level */ +#else + uint8_t atap_acoustic_def; /* recommended level */ + uint8_t atap_acoustic_val; /* 94: Current acoustic level */ +#endif + uint16_t __reserved6[5]; /* 95-99: reserved */ + uint16_t atap_max_lba[4]; /* 100-103: Max. user LBA add */ + uint16_t __reserved7[23]; /* 104-126: reserved */ + uint16_t atap_rmsn_supp; /* 127: remov. media status notif. */ +#define WDC_RMSN_SUPP_MASK 0x0003 +#define WDC_RMSN_SUPP 0x0001 + uint16_t atap_sec_st; /* 128: security status */ +#define WDC_SEC_LEV_MAX 0x0100 +#define WDC_SEC_ESE_SUPP 0x0020 +#define WDC_SEC_EXP 0x0010 +#define WDC_SEC_FROZEN 0x0008 +#define WDC_SEC_LOCKED 0x0004 +#define WDC_SEC_EN 0x0002 +#define WDC_SEC_SUPP 0x0001 + uint16_t __reserved8[31]; /* 129-159: vendor specific */ + uint16_t atap_cfa_power; /* 160: CFA powermode */ +#define ATAPI_CFA_MAX_MASK 0x0FFF +#define ATAPI_CFA_MODE1_DIS 0x1000 /* CFA Mode 1 Disabled */ +#define ATAPI_CFA_MODE1_REQ 0x2000 /* CFA Mode 1 Required */ +#define ATAPI_CFA_WORD160 0x8000 /* Word 160 supported */ + uint16_t __reserved9[15]; /* 161-175: reserved for CFA */ + uint8_t atap_media_serial[60]; /* 176-205: media serial number */ + uint16_t __reserved10[49]; /* 206-254: reserved */ +#ifdef LITTLE_ENDIAN + uint8_t atap_signature; /* 255: Signature */ + uint8_t atap_checksum; /* Checksum */ +#else + uint8_t atap_checksum; /* Checksum */ + uint8_t atap_signature; /* 255: Signature */ +#endif } ATAIdentifyDevice; + +#undef ATA_BYTE_ORDER _Static_assert(sizeof(ATAIdentifyDevice) == 512); diff --git a/sys/dev/ide.c b/sys/dev/ide.c index e0f7be6..1352ab6 100644 --- a/sys/dev/ide.c +++ b/sys/dev/ide.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "ata.h" @@ -25,15 +26,23 @@ // #define IDE_SECONDARY_IRQ 15 // Port Offsets -#define IDE_REG_DATAPORT 0 -#define IDE_REG_FEATURES 1 -#define IDE_REG_SECTORCOUNT 2 -#define IDE_REG_LBALOW 3 -#define IDE_REG_LBAMID 4 -#define IDE_REG_LBAHIGH 5 -#define IDE_REG_DRIVE 6 -#define IDE_REG_COMMAND 7 /* Write */ -#define IDE_REG_STATUS 7 /* Read */ +#define IDE_REG_DATAPORT 0x00 +#define IDE_REG_ERROR 0x01 +#define IDE_REG_FEATURES 0x01 +#define IDE_REG_SECCOUNT0 0x02 +#define IDE_REG_LBA0 0x03 +#define IDE_REG_LBA1 0x04 +#define IDE_REG_LBA2 0x05 +#define IDE_REG_HDDEVSEL 0x06 +#define IDE_REG_COMMAND 0x07 +#define IDE_REG_STATUS 0x07 +#define IDE_REG_SECCOUNT1 0x08 +#define IDE_REG_LBA3 0x09 +#define IDE_REG_LBA4 0x0A +#define IDE_REG_LBA5 0x0B +#define IDE_REG_CONTROL 0x0C +#define IDE_REG_ALTSTATUS 0x0C +#define IDE_REG_DEVADDRESS 0x0D #define IDE_CTRLREG_OFFSET 2 @@ -104,21 +113,31 @@ ide_write_reg8(const IDE * ide, UNUSED unsigned int channel, unsigned int offset } static inline void -ide_read_buf32(const IDE * ide, UNUSED unsigned int channel, void * buffer, size_t times) +ide_read_buf16(const IDE * ide, UNUSED unsigned int channel, void * buffer, size_t times) { for(unsigned int i = 0; i < times ; i++) { - volatile uint32_t * read = ide->primary_base + IDE_REG_DATAPORT; - uint32_t data = * read; - memcpy(buffer, &data, sizeof(uint32_t)); + volatile uint16_t * read = ide->primary_base + IDE_REG_DATAPORT; + uint16_t data = * read; + memcpy(buffer, &data, sizeof(uint16_t)); + buffer = buffer + sizeof(uint16_t); } } -// static inline uint8_t -// ide_read_ctrl(const IDE * ide, UNUSED unsigned int channel) -// { -// volatile uint8_t * read = ide->primary_ctl + IDE_CTRLREG_OFFSET; -// return *read; -// } +static inline void +ide_write_buf16(const IDE * ide, UNUSED unsigned int channel, void * buffer, size_t times) +{ + for(unsigned int i = 0; i < times ; i++) { + volatile uint16_t * read = ide->primary_base + IDE_REG_DATAPORT; + *read = *(uint16_t *)(buffer + i * sizeof(uint16_t)); + } +} + +UNUSED static inline uint8_t +ide_read_ctrl(const IDE * ide, UNUSED unsigned int channel) +{ + volatile uint8_t * read = ide->primary_ctl + IDE_CTRLREG_OFFSET; + return *read; +} static inline void ide_write_ctrl(const IDE * ide, UNUSED unsigned int channel, uint8_t data) @@ -142,7 +161,7 @@ IDE_Init(PCIDevice * dev) Panic("IDE controller does not support memory mapped IO.\n"); } - kprintf("Initializing: IDE controller, progif = 0x%x, bar0 = 0x%x, bar1 = 0x%x\n", dev->progif, dev->bars[0].base, dev->bars[1].base); + Log(ide, "Progif = 0x%x, BAR0 = 0x%x, BAR1 = 0x%x\n", dev->progif, dev->bars[0].base, dev->bars[1].base); // ide primary base primary.primary_base = (void *)DEVPA2VA(dev->bar_mappings[0]); primary.primary_ctl = (void *)DEVPA2VA(dev->bar_mappings[1]); @@ -150,7 +169,7 @@ IDE_Init(PCIDevice * dev) SPINLOCK_TYPE_NORMAL); if (!IDE_HasController(&primary)) { - kprintf("IDE: No controller detected\n"); + Warning(ide, "IDE: No controller detected\n"); return; } @@ -181,12 +200,12 @@ IDEWaitForBusy(IDE *ide) bool IDE_HasController(IDE *ide) { - ide_write_reg8(ide, 0, IDE_REG_LBALOW, 0x41); - ide_write_reg8(ide, 0, IDE_REG_LBAMID, 0x4D); + ide_write_reg8(ide, 0, IDE_REG_LBA0, 0x41); + ide_write_reg8(ide, 0, IDE_REG_LBA1, 0x4D); - if (ide_read_reg8(ide, 0, IDE_REG_LBALOW) != 0x41) + if (ide_read_reg8(ide, 0, IDE_REG_LBA0) != 0x41) return false; - if (ide_read_reg8(ide, 0, IDE_REG_LBAMID) != 0x4D) + if (ide_read_reg8(ide, 0, IDE_REG_LBA1) != 0x4D) return false; return true; @@ -207,7 +226,7 @@ IDE_Reset(IDE *ide) } } -void +UNUSED static void IDE_SwapAndTruncateString(char *str, int len) { int i; @@ -243,7 +262,7 @@ IDE_Identify(IDE *ide, int drive) else driveCode = 0xB0; - ide_write_reg8(ide, 0, IDE_REG_DRIVE, driveCode); + ide_write_reg8(ide, 0, IDE_REG_HDDEVSEL, driveCode); status = IDEWaitForBusy(ide); if ((status & IDE_STATUS_ERR) != 0) { @@ -277,28 +296,32 @@ IDE_Identify(IDE *ide, int drive) break; } - ide_read_buf32(ide, 0, &ident, sizeof(struct ATAIdentifyDevice) / sizeof(uint32_t)); + ide_read_buf16(ide, 0, &ident, sizeof(ATAIdentifyDevice) / sizeof(uint16_t)); // Cleanup model and serial for printing char model[41]; char serial[21]; - memcpy(&model[0], &ident.model[0], 40); + memcpy(&model[0], &ident.atap_model[0], 40); model[40] = '\0'; - IDE_SwapAndTruncateString(&model[0], 40); + //IDE_SwapAndTruncateString(&model[0], 40); - memcpy(&serial[0], &ident.serial[0], 20); + memcpy(&serial[0], &ident.atap_serial[0], 20); serial[20] = '\0'; - IDE_SwapAndTruncateString(&serial[0], 20); + //IDE_SwapAndTruncateString(&serial[0], 20); - kprintf("Drive %d Model: %s Serial: %s\n", drive, model, serial); - kprintf("Drive %d %lu Sectors (%llu MBs)\n", - drive, ident.lbaSectors, ident.lbaSectors / 2048ULL); + Log(ide, "Drive %d Model: \"%s\" Capabilities: 0x%x\n", drive, model, ident.atap_capabilities1); + // XXX: check capabilities + Log(ide, "Drive %d: %u Sectors (%lu Bytes, %lu KiB, %lu MiB)\n", + drive, ident.atap_capacity, + (uint64_t)ident.atap_capacity * IDE_SECTOR_SIZE, + (uint64_t)ident.atap_capacity * IDE_SECTOR_SIZE / 1024, + (uint64_t)ident.atap_capacity * IDE_SECTOR_SIZE / 1024 / 1024); primaryDrives[drive].ide = &primary; primaryDrives[drive].drive = drive; - primaryDrives[drive].lba48 = (ident.lbaSectors > (1 << 24)); - primaryDrives[drive].size = ident.lbaSectors; + primaryDrives[drive].lba48 = (ident.atap_capacity > (1 << 24)); + primaryDrives[drive].size = ident.atap_capacity; // Register Disk Disk *disk = PAlloc_AllocPage(); @@ -310,231 +333,232 @@ IDE_Identify(IDE *ide, int drive) disk->ctrlNo = 0; disk->diskNo = drive; disk->sectorSize = IDE_SECTOR_SIZE; - disk->sectorCount = ident.lbaSectors; - disk->diskSize = IDE_SECTOR_SIZE * ident.lbaSectors; - // disk->read = IDE_Read; - // disk->write = IDE_Write; - // disk->flush = IDE_Flush; + disk->sectorCount = ident.atap_capacity; + disk->diskSize = IDE_SECTOR_SIZE * ident.atap_capacity; + disk->read = IDE_Read; + disk->write = IDE_Write; + disk->flush = IDE_Flush; - // Disk_AddDisk(disk); + Disk_AddDisk(disk); } -// int -// IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) -// { -// int i; -// int status; -// IDEDrive *idedrive; +int +IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) +{ + unsigned int i; + int status; + IDEDrive *idedrive; -// idedrive = disk->handle; + idedrive = disk->handle; -// for (i = 0; i < sga->len; i++) { -// status = IDE_ReadOne(idedrive, -// buf, -// sga->entries[i].offset / 512, -// sga->entries[i].length / 512); -// buf += sga->entries[i].length; -// if (status < 0) -// return status; -// } + for (i = 0; i < sga->len; i++) { + status = IDE_ReadOne(idedrive, + buf, + sga->entries[i].offset / 512, + sga->entries[i].length / 512); + buf += sga->entries[i].length; + if (status < 0) + return status; + } -// return 0; -// } + return 0; +} -// int -// IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) -// { -// int i; -// int status; -// IDEDrive *idedrive; +int +IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) +{ + unsigned int i; + int status; + IDEDrive *idedrive; -// idedrive = disk->handle; + idedrive = disk->handle; -// for (i = 0; i < sga->len; i++) { -// status = IDE_WriteOne(idedrive, -// buf, -// sga->entries[i].offset / 512, -// sga->entries[i].length / 512); -// buf += sga->entries[i].length; -// if (status < 0) -// return status; -// } + for (i = 0; i < sga->len; i++) { + status = IDE_WriteOne(idedrive, + buf, + sga->entries[i].offset / 512, + sga->entries[i].length / 512); + buf += sga->entries[i].length; + if (status < 0) + return status; + } -// return 0; -// } + return 0; +} -// int -// IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) -// { -// uint8_t driveCode; -// IDE *ide; -// IDEDrive *idedrive; +int +IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg) +{ + uint8_t driveCode; + IDE *ide; + IDEDrive *idedrive; -// idedrive = disk->handle; -// ide = idedrive->ide; + idedrive = disk->handle; + ide = idedrive->ide; -// if (idedrive->drive == 0) -// driveCode = 0xA0; -// else -// driveCode = 0xB0; + if (idedrive->drive == 0) + driveCode = 0xA0; + else + driveCode = 0xB0; -// Spinlock_Lock(&ide->lock); -// outb(ide->base + IDE_DRIVE, driveCode); -// outb(ide->base + IDE_COMMAND, IDE_CMD_FLUSH); + Spinlock_Lock(&ide->lock); + ide_write_reg8(ide, 0, IDE_REG_HDDEVSEL, driveCode); + ide_write_reg8(ide, 0, IDE_REG_COMMAND, IDE_CMD_FLUSH); -// IDEWaitForBusy(ide, false); -// Spinlock_Unlock(&ide->lock); + IDEWaitForBusy(ide); + Spinlock_Unlock(&ide->lock); -// return 0; -// } + return 0; +} -// int -// IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) -// { -// bool lba48 = false; -// uint8_t driveCode; -// uint8_t status; -// IDE *ide = drive->ide; +int +IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) +{ + bool lba48 = false; + uint8_t driveCode; + uint8_t status; + IDE *ide = drive->ide; -// DLOG(ide, "read %llx %llx\n", off, len); + DLOG(ide, "read offset = 0x%lx, len = 0x%lx.\n", off, len); -// ASSERT(drive->drive == 0 || drive->drive == 1); + ASSERT(drive->drive == 0 || drive->drive == 1); -// if (drive->drive == 0) -// driveCode = lba48 ? 0x40 : 0xE0; -// else -// driveCode = lba48 ? 0x50 : 0xF0; + if (drive->drive == 0) + driveCode = lba48 ? 0x40 : 0xE0; + else + driveCode = lba48 ? 0x50 : 0xF0; -// ASSERT(len < 0x10000); + ASSERT(len < 0x10000); -// Spinlock_Lock(&ide->lock); -// if (driveCode != ide->lastDriveCode) { -// outb(ide->base + IDE_DRIVE, driveCode); + Spinlock_Lock(&ide->lock); + if (driveCode != ide->lastDriveCode) { + ide_write_reg8(ide, 0, IDE_REG_HDDEVSEL, driveCode); -// // Need to wait for select to complete -// status = IDEWaitForBusy(ide, true); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error selecting drive %d\n", drive->drive); -// return -1; -// } -// ide->lastDriveCode = driveCode; -// } + // Need to wait for select to complete + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error selecting drive %d\n", drive->drive); + return EIO; + } + ide->lastDriveCode = driveCode; + } -// if (lba48) { -// outb(ide->base + IDE_SECTORCOUNT, len >> 8); -// outb(ide->base + IDE_LBALOW, off >> 24); -// outb(ide->base + IDE_LBAMID, off >> 32); -// outb(ide->base + IDE_LBAHIGH, off >> 40); -// } -// outb(ide->base + IDE_SECTORCOUNT, len); -// outb(ide->base + IDE_LBALOW, off & 0xff); -// outb(ide->base + IDE_LBAMID, (off >> 8) & 0xff); -// outb(ide->base + IDE_LBAHIGH, (off >> 16) & 0xff); + if (lba48) { + ide_write_reg8(ide, 0, IDE_REG_SECCOUNT1, len >> 8); + ide_write_reg8(ide, 0, IDE_REG_LBA3, off >> 24); + ide_write_reg8(ide, 0, IDE_REG_LBA4, off >> 32); + ide_write_reg8(ide, 0, IDE_REG_LBA5, off >> 40); + } -// if (lba48) -// outb(ide->base + IDE_COMMAND, IDE_CMD_READ_EXT); -// else -// outb(ide->base + IDE_COMMAND, IDE_CMD_READ); + ide_write_reg8(ide, 0, IDE_REG_SECCOUNT0, len); + ide_write_reg8(ide, 0, IDE_REG_LBA0, off & 0xff); + ide_write_reg8(ide, 0, IDE_REG_LBA1, (off >> 8) & 0xff); + ide_write_reg8(ide, 0, IDE_REG_LBA2, (off >> 16) & 0xff); -// status = IDEWaitForBusy(ide, false); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error trying read from drive %d\n", drive->drive); -// return -1; -// } + if (lba48) + ide_write_reg8(ide, 0, IDE_REG_COMMAND, IDE_CMD_READ_EXT); + else + ide_write_reg8(ide, 0, IDE_REG_COMMAND, IDE_CMD_READ); -// int sectors; -// for (sectors = 0; sectors < len; sectors++) -// { -// uint8_t *b = buf + sectors * IDE_SECTOR_SIZE; -// insw(ide->base + IDE_DATAPORT, b, 256); + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error trying read from drive %d\n", drive->drive); + return EIO; + } -// status = IDEWaitForBusy(ide, true); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error reading from drive %d\n", drive->drive); -// return -1; -// } -// } -// Spinlock_Unlock(&ide->lock); + unsigned int sectors; + for (sectors = 0; sectors < len; sectors++) + { + uint8_t *b = buf + sectors * IDE_SECTOR_SIZE; + ide_read_buf16(ide, 0, b, IDE_SECTOR_SIZE / sizeof(uint16_t)); -// return 0; -// } + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error reading from drive %d\n", drive->drive); + return EIO; + } + } + Spinlock_Unlock(&ide->lock); -// int -// IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) -// { -// bool lba48 = false; -// uint8_t driveCode; -// uint8_t status; -// IDE *ide = drive->ide; + return 0; +} -// DLOG(ide, "read %llx %llx\n", off, len); +int +IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len) +{ + bool lba48 = false; + uint8_t driveCode; + uint8_t status; + IDE *ide = drive->ide; -// ASSERT(drive->drive == 0 || drive->drive == 1); + DLOG(ide, "write offset = 0x%lx, len = 0x%lx.\n", off, len); -// if (drive->drive == 0) -// driveCode = lba48 ? 0x40 : 0xE0; -// else -// driveCode = lba48 ? 0x50 : 0xF0; + ASSERT(drive->drive == 0 || drive->drive == 1); -// ASSERT(len < 0x10000); + if (drive->drive == 0) + driveCode = lba48 ? 0x40 : 0xE0; + else + driveCode = lba48 ? 0x50 : 0xF0; -// Spinlock_Lock(&ide->lock); -// if (driveCode != ide->lastDriveCode) { -// outb(ide->base + IDE_DRIVE, driveCode); + ASSERT(len < 0x10000); -// // Need to wait for select to complete -// status = IDEWaitForBusy(ide, true); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error selecting drive %d\n", drive->drive); -// return -1; -// } -// ide->lastDriveCode = driveCode; -// } + Spinlock_Lock(&ide->lock); + if (driveCode != ide->lastDriveCode) { + ide_write_reg8(ide, 0, IDE_REG_HDDEVSEL, driveCode); -// if (lba48) { -// outb(ide->base + IDE_SECTORCOUNT, len >> 8); -// outb(ide->base + IDE_LBALOW, off >> 24); -// outb(ide->base + IDE_LBAMID, off >> 32); -// outb(ide->base + IDE_LBAHIGH, off >> 40); -// } -// outb(ide->base + IDE_SECTORCOUNT, len); -// outb(ide->base + IDE_LBALOW, off & 0xff); -// outb(ide->base + IDE_LBAMID, (off >> 8) & 0xff); -// outb(ide->base + IDE_LBAHIGH, (off >> 16) & 0xff); + // Need to wait for select to complete + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error selecting drive %d\n", drive->drive); + return EIO; + } + ide->lastDriveCode = driveCode; + } -// if (lba48) -// outb(ide->base + IDE_COMMAND, IDE_CMD_WRITE_EXT); -// else -// outb(ide->base + IDE_COMMAND, IDE_CMD_WRITE); + if (lba48) { + ide_write_reg8(ide, 0, IDE_REG_SECCOUNT1, len >> 8); + ide_write_reg8(ide, 0, IDE_REG_LBA3, off >> 24); + ide_write_reg8(ide, 0, IDE_REG_LBA4, off >> 32); + ide_write_reg8(ide, 0, IDE_REG_LBA5, off >> 40); + } + ide_write_reg8(ide, 0, IDE_REG_SECCOUNT0, len); + ide_write_reg8(ide, 0, IDE_REG_LBA0, off & 0xff); + ide_write_reg8(ide, 0, IDE_REG_LBA1, (off >> 8) & 0xff); + ide_write_reg8(ide, 0, IDE_REG_LBA2, (off >> 16) & 0xff); -// status = IDEWaitForBusy(ide, false); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error trying read from drive %d\n", drive->drive); -// return -1; -// } + if (lba48) + ide_write_reg8(ide, 0, IDE_REG_COMMAND, IDE_CMD_WRITE_EXT); + else + ide_write_reg8(ide, 0, IDE_REG_COMMAND, IDE_CMD_WRITE); -// int sectors; -// for (sectors = 0; sectors < len; sectors++) -// { -// uint8_t *b = buf + sectors * IDE_SECTOR_SIZE; -// outsw(ide->base + IDE_DATAPORT, b, 256); + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error trying read from drive %d\n", drive->drive); + return EIO; + } -// status = IDEWaitForBusy(ide, true); -// if ((status & IDE_STATUS_ERR) != 0) { -// Spinlock_Unlock(&ide->lock); -// Log(ide, "Error reading from drive %d\n", drive->drive); -// return -1; -// } -// } -// Spinlock_Unlock(&ide->lock); + unsigned int sectors; + for (sectors = 0; sectors < len; sectors++) + { + uint8_t *b = buf + sectors * IDE_SECTOR_SIZE; + ide_write_buf16(ide, 0, b, IDE_SECTOR_SIZE / sizeof(uint16_t)); -// // XXX: Flush cache ... + status = IDEWaitForBusy(ide); + if ((status & IDE_STATUS_ERR) != 0) { + Spinlock_Unlock(&ide->lock); + Log(ide, "Error reading from drive %d\n", drive->drive); + return EIO; + } + } + Spinlock_Unlock(&ide->lock); -// return 0; -// } + // XXX: Flush cache ... + + return 0; +} diff --git a/sys/include/kassert.h b/sys/include/kassert.h index 1170565..5dcdf9b 100644 --- a/sys/include/kassert.h +++ b/sys/include/kassert.h @@ -42,12 +42,12 @@ NO_RETURN void Debug_Assert(const char *fmt, ...); #define Warning(_module, _format, ...) kprintf(#_module ": " _format, ##__VA_ARGS__) // Normal Logging #define Log(_module, _format, ...) \ - if (SYSCTL_GETINT(log_##_module) >= 1) { \ + if (SYSCTL_GETINT(log_##_module) >= 1 || 1) { \ kprintf(#_module ": " _format, ##__VA_ARGS__); \ } // Debug Logging #define DLOG(_module, _format, ...) \ - if (SYSCTL_GETINT(log_##_module) >= 5) { \ + if (SYSCTL_GETINT(log_##_module) >= 5 || 1) { \ kprintf(#_module ": " _format, ##__VA_ARGS__); \ } // Verbose Logging diff --git a/sys/include/sysctl.h b/sys/include/sysctl.h index 6fe88d5..d5c8785 100644 --- a/sys/include/sysctl.h +++ b/sys/include/sysctl.h @@ -29,7 +29,8 @@ SYSCTL_INT(log_loader, SYSCTL_FLAG_RW, "Loader log level", 0) \ SYSCTL_INT(log_o2fs, SYSCTL_FLAG_RW, "O2FS log level", 0) \ SYSCTL_INT(log_syscall, SYSCTL_FLAG_RW, "Syscall log level", 0) \ - SYSCTL_INT(log_vfs, SYSCTL_FLAG_RW, "VFS log level", 0) + SYSCTL_INT(log_vfs, SYSCTL_FLAG_RW, "VFS log level", 0) \ + SYSCTL_INT(log_bufcache, SYSCTL_FLAG_RW, "Buffer cache log level", 0) #define SYSCTL_STR_MAXLENGTH 128 diff --git a/sys/kern/bufcache.c b/sys/kern/bufcache.c index 205a774..fcfefa7 100644 --- a/sys/kern/bufcache.c +++ b/sys/kern/bufcache.c @@ -40,7 +40,7 @@ void BufCache_Init() { int i; - + Log(bufcache, "Initializing ...\n"); Spinlock_Init(&cacheLock, "BufCache Lock", SPINLOCK_TYPE_NORMAL); diskBuf = XMem_New(); @@ -78,6 +78,8 @@ BufCache_Init() cacheHit = 0; cacheMiss = 0; cacheAlloc = 0; + + Log(bufcache, "Initialized!\n"); } /** diff --git a/sys/kern/vfs.c b/sys/kern/vfs.c index a1c77e2..b35475b 100644 --- a/sys/kern/vfs.c +++ b/sys/kern/vfs.c @@ -36,7 +36,7 @@ int VFS_MountRoot(Disk *rootDisk) { int status; - + Log(vfs, "Mounting root...\n"); Spinlock_Init(&vfsLock, "VFS Lock", SPINLOCK_TYPE_NORMAL); Slab_Init(&vfsSlab, "VFS Slab", sizeof(VFS), 16); @@ -49,7 +49,7 @@ VFS_MountRoot(Disk *rootDisk) status = rootFS->op->getroot(rootFS, &rootNode); if (status < 0) Panic("Failed to get root VNode\n"); - + Log(vfs, "Root mounted!\n"); return 0; }