I hereby relicense all my work on Sortix under the ISC license as below. All Sortix contributions by other people are already under this license, are not substantial enough to be copyrightable, or have been removed. All imported code from other projects is compatible with this license. All GPL licensed code from other projects had previously been removed. Copyright 2011-2016 Jonas 'Sortie' Termansen and contributors. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
252 lines
10 KiB
C++
252 lines
10 KiB
C++
/*
|
|
* Copyright (c) 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* disk/ahci/registers.h
|
|
* Driver for the Advanced Host Controller Interface.
|
|
*/
|
|
|
|
#ifndef SORTIX_DISK_AHCI_REGISTERS_H
|
|
#define SORTIX_DISK_AHCI_REGISTERS_H
|
|
|
|
#include <endian.h>
|
|
#include <stdint.h>
|
|
|
|
namespace Sortix {
|
|
namespace AHCI {
|
|
|
|
#define AHCI_COMMAND_HEADER_COUNT 32
|
|
|
|
#if 1 /* ATA STUFF */
|
|
#define ATA_STATUS_ERR (1 << 0) /* Error. */
|
|
#define ATA_STATUS_DRQ (1 << 3) /* Data Request. */
|
|
#define ATA_STATUS_DF (1 << 5) /* Device Fault. */
|
|
#define ATA_STATUS_DRDY (1 << 6) /* Device Ready. */
|
|
#define ATA_STATUS_BSY (1 << 7) /* Busy. */
|
|
|
|
/** ATA Commands. */
|
|
#define ATA_CMD_READ_DMA 0xC8 /**< READ DMA. */
|
|
#define ATA_CMD_READ_DMA_EXT 0x25 /**< READ DMA EXT. */
|
|
#define ATA_CMD_READ_SECTORS 0x20 /**< READ SECTORS. */
|
|
#define ATA_CMD_READ_SECTORS_EXT 0x24 /**< READ SECTORS EXT. */
|
|
#define ATA_CMD_WRITE_DMA 0xCA /**< WRITE DMA. */
|
|
#define ATA_CMD_WRITE_DMA_EXT 0x35 /**< WRITE DMA EXT. */
|
|
#define ATA_CMD_WRITE_SECTORS 0x30 /**< WRITE SECTORS. */
|
|
#define ATA_CMD_WRITE_SECTORS_EXT 0x34 /**< WRITE SECTORS EXT. */
|
|
#define ATA_CMD_PACKET 0xA0 /**< PACKET. */
|
|
#define ATA_CMD_IDENTIFY_PACKET 0xA1 /**< IDENTIFY PACKET DEVICE. */
|
|
#define ATA_CMD_FLUSH_CACHE 0xE7 /**< FLUSH CACHE. */
|
|
#define ATA_CMD_FLUSH_CACHE_EXT 0xEA /**< FLUSH CACHE EXT. */
|
|
#define ATA_CMD_IDENTIFY 0xEC /**< IDENTIFY DEVICE. */
|
|
#endif
|
|
|
|
struct fis
|
|
{
|
|
little_uint8_t dsfis[0x1C]; // DMA Setup FIS.
|
|
little_uint8_t reserved1[0x04];
|
|
little_uint8_t psfis[0x14]; // PIO Setup FIS.
|
|
little_uint8_t reserved2[0x0C];
|
|
little_uint8_t rfis[0x14]; // D2H Register FIS.
|
|
little_uint8_t reserved3[0x04];
|
|
little_uint8_t sdbfis[0x08]; // Set Device Bits FIS.
|
|
little_uint8_t ufis[0x40]; // Unknown FIS.
|
|
little_uint8_t reserved4[0x60];
|
|
};
|
|
|
|
/* TODO: Less blatantly copied from Kiwi: */
|
|
struct command_header
|
|
{
|
|
/** DW0 - Description Information. */
|
|
little_uint16_t dw0l;
|
|
little_uint16_t prdtl;
|
|
/** DW1 - Command Status. */
|
|
little_uint32_t prdbc; /**< Physical Region Descriptor Byte Count. */
|
|
/** DW2 - Command Table Base Address.
|
|
* @note Bits 0-6 are reserved, must be 0. */
|
|
little_uint32_t ctba; /**< Command Table Descriptor Base Address. */
|
|
/** DW3 - Command Table Base Address Upper. */
|
|
little_uint32_t ctbau; /**< Command Table Descriptor Base Address Upper 32-bits. */
|
|
/** DW4-7 - Reserved. */
|
|
little_uint32_t reserved2[4];
|
|
};
|
|
|
|
static const uint32_t COMMAND_HEADER_DW0_WRITE = 1 << 6;
|
|
|
|
/* TODO: Less blatantly copied from Kiwi: */
|
|
struct prd
|
|
{
|
|
/** DW0 - Data Base Address. */
|
|
little_uint32_t dba;
|
|
/** DW1 - Data Base Address Upper. */
|
|
little_uint32_t dbau;
|
|
/** DW2 - Reserved */
|
|
little_uint32_t reserved1;
|
|
/** DW3 - Description Information. */
|
|
/* dw3 bits 0-21: data byte count */
|
|
/* dw3 bits 22-30: reserved */
|
|
/* dw3 bits 31-31: interrupt on completion */
|
|
little_uint32_t dw3;
|
|
};
|
|
|
|
/* TODO: Less blatantly copied from Kiwi: */
|
|
struct command_table
|
|
{
|
|
/** Command FIS - Host to Device. */
|
|
struct
|
|
{
|
|
little_uint8_t type; /**< FIS Type (0x27). */
|
|
/*little_*/uint8_t pm_port : 4; /**< Port Multiplier Port. */
|
|
/*little_*/uint8_t reserved1 : 3; /**< Reserved. */
|
|
/*little_*/uint8_t c_bit : 1; /**< C bit. */
|
|
little_uint8_t command; /**< ATA Command. */
|
|
little_uint8_t features_0_7; /**< Features (bits 0-7). */
|
|
little_uint8_t lba_0_7; /**< LBA (bits 0-7). */
|
|
little_uint8_t lba_8_15; /**< LBA (bits 8-15). */
|
|
little_uint8_t lba_16_23; /**< LBA (bits 16-23). */
|
|
little_uint8_t device; /**< Device (bits 24-27 for LBA28). */
|
|
little_uint8_t lba_24_31; /**< LBA48 (bits 24-31). */
|
|
little_uint8_t lba_32_39; /**< LBA48 (bits 32-39). */
|
|
little_uint8_t lba_40_47; /**< LBA48 (bits 40-47). */
|
|
little_uint8_t features_8_15; /**< Features (bits 8-15). */
|
|
little_uint8_t count_0_7; /**< Sector Count (bits 0-7). */
|
|
little_uint8_t count_8_15; /**< Sector Count (bits 8-15). */
|
|
little_uint8_t icc; /**< Isochronous Command Completion. */
|
|
little_uint8_t control; /**< Device Control. */
|
|
little_uint32_t reserved2; /**< Reserved. */
|
|
little_uint8_t padding[0x2C]; /**< Padding to 64 bytes. */
|
|
} cfis;
|
|
little_uint8_t acmd[0x10]; /**< ATAPI Command (12 or 16 bytes). */
|
|
little_uint8_t reserved[0x30]; /**< Reserved. */
|
|
};
|
|
|
|
struct port_regs
|
|
{
|
|
little_uint32_t pxclb;
|
|
little_uint32_t pxclbu;
|
|
little_uint32_t pxfb;
|
|
little_uint32_t pxfbu;
|
|
little_uint32_t pxis;
|
|
little_uint32_t pxie;
|
|
little_uint32_t pxcmd;
|
|
little_uint32_t reserved0;
|
|
little_uint32_t pxtfd;
|
|
little_uint32_t pxsig;
|
|
little_uint32_t pxssts;
|
|
little_uint32_t pxsctl;
|
|
little_uint32_t pxserr;
|
|
little_uint32_t pxsact;
|
|
little_uint32_t pxci;
|
|
little_uint32_t pxsntf;
|
|
little_uint32_t pxfbs;
|
|
little_uint32_t preserved1[15];
|
|
};
|
|
|
|
/** Bits in the Port x Interrupt Enable register. */
|
|
#define PXIE_DHRE (1 << 0) /**< Device to Host Register Enable. */
|
|
#define PXIE_PSE (1 << 1) /**< PIO Setup FIS Enable. */
|
|
#define PXIE_DSE (1 << 2) /**< DMA Setup FIS Enable. */
|
|
#define PXIE_SDBE (1 << 3) /**< Set Device Bits Enable. */
|
|
#define PXIE_UFE (1 << 4) /**< Unknown FIS Enable. */
|
|
#define PXIE_DPE (1 << 5) /**< Descriptor Processed Enable. */
|
|
#define PXIE_PCE (1 << 6) /**< Port Connect Change Enable. */
|
|
#define PXIE_DMPE (1 << 7) /**< Device Mechanical Presence Enable. */
|
|
#define PXIE_PRCE (1 << 22) /**< PhyRdy Change Enable. */
|
|
#define PXIE_IPME (1 << 23) /**< Incorrect Port Multiplier Enable. */
|
|
#define PXIE_OFE (1 << 24) /**< Overflow Enable. */
|
|
#define PXIE_INFE (1 << 26) /**< Interface Non-Fatal Error Enable. */
|
|
#define PXIE_IFE (1 << 27) /**< Interface Fatal Error Enable. */
|
|
#define PXIE_HBDE (1 << 28) /**< Host Bus Data Error Enable. */
|
|
#define PXIE_HBFE (1 << 29) /**< Host Bus Fatal Error Enable. */
|
|
#define PXIE_TFEE (1 << 30) /**< Task File Error Enable. */
|
|
#define PXIE_CPDE (1 << 31) /**< Cold Port Detect Enable. */
|
|
|
|
#define PORT_INTR_ERROR \
|
|
(PXIE_UFE | PXIE_PCE | PXIE_PRCE | PXIE_IPME | \
|
|
PXIE_OFE | PXIE_INFE | PXIE_IFE | PXIE_HBDE | \
|
|
PXIE_HBFE | PXIE_TFEE)
|
|
|
|
static const uint32_t PXCMD_ST = 1 << 0; /* 0x00000001 */
|
|
static const uint32_t PXCMD_SUD = 1 << 1; /* 0x00000002 */
|
|
static const uint32_t PXCMD_POD = 1 << 2; /* 0x00000004 */
|
|
static const uint32_t PXCMD_CLO = 1 << 3; /* 0x00000008 */
|
|
static const uint32_t PXCMD_FRE = 1 << 4; /* 0x00000010 */
|
|
static inline uint32_t PXCMD_CSS(uint32_t val) { return (val >> 8) % 32; }
|
|
static const uint32_t PXCMD_MPSS = 1 << 13; /* 0x00002000 */
|
|
static const uint32_t PXCMD_FR = 1 << 14; /* 0x00004000 */
|
|
static const uint32_t PXCMD_CR = 1 << 15; /* 0x00008000 */
|
|
static const uint32_t PXCMD_CPS = 1 << 16; /* 0x00010000 */
|
|
static const uint32_t PXCMD_PMA = 1 << 17; /* 0x00020000 */
|
|
static const uint32_t PXCMD_HPCP = 1 << 18; /* 0x00040000 */
|
|
static const uint32_t PXCMD_MPSP = 1 << 19; /* 0x00080000 */
|
|
static const uint32_t PXCMD_CPD = 1 << 20; /* 0x00100000 */
|
|
static const uint32_t PXCMD_ESP = 1 << 21; /* 0x00200000 */
|
|
static const uint32_t PXCMD_FBSCP = 1 << 22; /* 0x00400000 */
|
|
static const uint32_t PXCMD_APSTE = 1 << 23; /* 0x00800000 */
|
|
static const uint32_t PXCMD_ATAPI = 1 << 24; /* 0x01000000 */
|
|
static const uint32_t PXCMD_DLAE = 1 << 25; /* 0x02000000 */
|
|
static const uint32_t PXCMD_ALPE = 1 << 26; /* 0x04000000 */
|
|
static const uint32_t PXCMD_ASP = 1 << 27; /* 0x08000000 */
|
|
static inline uint32_t PXCMD_ICC(uint32_t val) { return (val >> 28) % 16; }
|
|
|
|
struct hba_regs
|
|
{
|
|
little_uint32_t cap;
|
|
little_uint32_t ghc;
|
|
little_uint32_t is;
|
|
little_uint32_t pi;
|
|
little_uint32_t vs;
|
|
little_uint32_t ccc_ctl;
|
|
little_uint32_t ccc_ports;
|
|
little_uint32_t em_loc;
|
|
little_uint32_t em_ctl;
|
|
little_uint32_t cap2;
|
|
little_uint32_t bohc;
|
|
little_uint32_t reserved0[53];
|
|
struct port_regs ports[32];
|
|
};
|
|
|
|
static_assert(sizeof(struct hba_regs) == 0x1100,
|
|
"sizeof(struct hba_regs) == 0x1100");
|
|
|
|
static const uint32_t CAP_S64A = 1U << 31;
|
|
static const uint32_t CAP_SNCQ = 1U << 30;
|
|
static const uint32_t CAP_SSNTF = 1U << 29;
|
|
static const uint32_t CAP_SMPS = 1U << 28;
|
|
static const uint32_t CAP_SSS = 1U << 27;
|
|
static const uint32_t CAP_SALP = 1U << 26;
|
|
static const uint32_t CAP_SAL = 1U << 25;
|
|
static const uint32_t CAP_SCLO = 1U << 24;
|
|
static inline uint32_t CAP_ISS(uint32_t val) { return (val >> 20) % 16; }
|
|
static const uint32_t CAP_SAM = 1U << 18;
|
|
static const uint32_t CAP_SPM = 1U << 17;
|
|
static const uint32_t CAP_FBSS = 1U << 16;
|
|
static const uint32_t CAP_PMD = 1U << 15;
|
|
static const uint32_t CAP_SSC = 1U << 14;
|
|
static const uint32_t CAP_PSC = 1U << 13;
|
|
static inline uint32_t CAP_NCS(uint32_t val) { return (val >> 8) % 32 + 1; }
|
|
static const uint32_t CAP_CCCS = 1U << 7;
|
|
static const uint32_t CAP_EMS = 1U << 6;
|
|
static const uint32_t CAP_SXS = 1U << 5;
|
|
static inline uint32_t CAP_NP(uint32_t val) { return (val >> 0) % 32 + 1; }
|
|
|
|
static const uint32_t GHC_AE = 1U << 31;
|
|
static const uint32_t GHC_MRSM = 1U << 2;
|
|
static const uint32_t GHC_IE = 1U << 1;
|
|
static const uint32_t GHC_HR = 1U << 0;
|
|
|
|
} // namespace AHCI
|
|
} // namespace Sortix
|
|
|
|
#endif
|