size_t HAL_ATAControllerInfo(int bus, union atainfo *info, size_t buflen)

union atainfo
{
    struct
    {
        uint32_t flags;
        volatile uint8_t *cmd;
        volatile uint8_t *ctrl;
        volatile uint8_t *bus_master_reg;
        int int_device;
        uint32_t available_pio_modes;
        uint32_t available_dma_modes;
        uint32_t available_ultradma_modes;
        uint16_t dma_id;              // see OS_Hardware device spec
        uint32_t dma_location;        //           "
        const char *dma_description;  //           "
        uint32_t dma_logical_channel; // or -1 to obtain at run-time
    } bus;
    struct
    {
        uint32_t buses;
        uint16_t dma_id;
        uint32_t dma_location;
        const char *dma_description;
    } group;
}

flags: bit 0 => interrupt is shared (not supported yet)
       bit 1 => 32-bit PIO supported
       bit 2 => IORDY flow control supported
       bit 3 => 48-bit LBA not supported

size_t HAL_ATAControllerInfo(int bus, struct atainfo *info, size_t len)

Looks up information about the given bus. Up to len bytes of
information are copied into info. It returns the amount of data
that would be returned if not limited by len. It returns 0 if the
bus does not exist.

bool HAL_ATACableID(int bus)

Returns true if CBLID- is currently low; returns false if
CBLID- is currently high, or CBLID- sensing is not available.


void HAL_ATASetModes(int bus, struct atamode *dev0, struct atamode *dev1)

struct atamode
{
    uint32_t flags;
    uint8_t pio_mode;  // (eg 0-4)
    uint8_t dma_mode;  // (eg 0-2) 0xFF if none
    uint8_t udma_mode; // (eg 0-5) 0xFF if none
    uint8_t reserved;  // set to 0xFF
}

flags: bit 0 => FIFOs enabled (ie non-packet device that
                               waits for interrupts)

This call sets the interface timings for PIO and Multiword or
Ultra DMA. The structure is updated to show the actual modes
selected, if the requested modes were not available.

On entry, both DMA and Ultra DMA modes may be requested - the
DMA mode indicates the fallback if Ultra DMA is not available.
On exit, no more than 1 of dma_mode and udma_mode will be
set to valid values.

The call specifies timings for both devices simultaneously, as
it may not be possible to set independent timings, requiring
the highest common mode to be set.

Either pointer on entry may be null, indicating that that
device is not in use.
