KallistiOS  ##version##
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
Macros | Functions
g1ata.h File Reference

G1 bus ATA interface. More...

#include <sys/cdefs.h>
#include <stdint.h>
#include <kos/blockdev.h>

Go to the source code of this file.

Macros

#define G1_ATA_MASTER   0x00
 ATA master device. More...
 
#define G1_ATA_MASTER_ALT   0x90
 ATA master device (compatible with old drives). More...
 
#define G1_ATA_SLAVE   0xB0
 ATA slave device. More...
 
#define G1_ATA_LBA_MODE   0x40
 Select LBA addressing mode. More...
 

Functions

int g1_dma_in_progress (void)
 Is there a G1 DMA in progress currently? More...
 
int g1_ata_mutex_lock (void)
 Lock the G1 ATA mutex. More...
 
int g1_ata_mutex_unlock (void)
 Unlock the G1 ATA mutex. More...
 
uint8_t g1_ata_select_device (uint8_t dev)
 Set the active ATA device. More...
 
int g1_ata_read_chs (uint16_t c, uint8_t h, uint8_t s, size_t count, uint16_t *buf)
 Read one or more disk sectors with Cylinder-Head-Sector addressing. More...
 
int g1_ata_write_chs (uint16_t c, uint8_t h, uint8_t s, size_t count, const uint16_t *buf)
 Write one or more disk sectors with Cylinder-Head-Sector addressing. More...
 
int g1_ata_read_lba (uint64_t sector, size_t count, uint16_t *buf)
 Read one or more disk sectors with Linear Block Addressing (LBA). More...
 
int g1_ata_read_lba_dma (uint64_t sector, size_t count, uint16_t *buf, int block)
 DMA read disk sectors with Linear Block Addressing (LBA). More...
 
int g1_ata_write_lba (uint64_t sector, size_t count, const uint16_t *buf)
 Write one or more disk sectors with Linear Block Addressing (LBA). More...
 
int g1_ata_write_lba_dma (uint64_t sector, size_t count, const uint16_t *buf, int block)
 DMA Write disk sectors with Linear Block Addressing (LBA). More...
 
int g1_ata_flush (void)
 Flush the write cache on the attached disk. More...
 
int g1_ata_blockdev_for_partition (int partition, int dma, kos_blockdev_t *rv, uint8_t *partition_type)
 Get a block device for a given partition on the slave ATA device. More...
 
int g1_ata_init (void)
 Initialize G1 ATA support. More...
 
void g1_ata_shutdown (void)
 Shut down G1 ATA support. More...
 

Detailed Description

G1 bus ATA interface.

This file provides support for accessing an ATA device on the G1 bus in the Dreamcast. The G1 bus usually contains a few useful pieces of the system, including the flashrom and the GD-ROM drive. The interesting piece here is that the GD-ROM drive itself is actually an ATA device.

Luckily, Sega left everything in place to access both a master and slave device on this ATA port. The GD-ROM drive should always be the master device on the chain, but you can hook up a hard drive or some other device as a slave. The functions herein are for accessing just such a slave device.

Note
The functions herein do not provide for direct access to the GD-ROM drive. There is not really any sort of compelling reason to access the GD-ROM drive directly instead of using the system calls, so you should continue to use the normal cdrom_* functions for accessing the GD-ROM drive. Also, currently there is no locking done to prevent you from doing "bad things" with concurrent access on the bus, so be careful. ;)
Author
Lawrence Sebald

Function Documentation

int g1_ata_blockdev_for_partition ( int  partition,
int  dma,
kos_blockdev_t rv,
uint8_t *  partition_type 
)

Get a block device for a given partition on the slave ATA device.

This function creates a block device descriptor for the given partition on the attached ATA device. This block device is used to interface with various filesystems on the device.

Parameters
partitionThe partition number (0-3) to use.
dmaSet to 1 to use DMA for reads/writes on the device, if available.
rvUsed to return the block device. Must be non-NULL.
partition_typeUsed to return the partition type. Must be non-NULL.
Return values
0On success.
-1On error, errno will be set as appropriate.
Error Conditions:
ENXIO - ATA support not initialized or no device attached
EIO - an I/O error occurred in reading data
EINVAL - invalid partition number was given
EFAULT - rv or partition_type was NULL
ENOENT - no MBR found
ENOENT - no partition at the specified position
ENOMEM - out of memory
Note
This interface currently only supports MBR-formatted disks. There is currently no support for GPT partition tables.
int g1_ata_flush ( void  )

Flush the write cache on the attached disk.

This function flushes the write cache on the disk attached as the slave device on the G1 ATA bus. This ensures that all writes that have previously completed are fully persisted to the disk. You should do this before unmounting any disks or exiting your program if you have called any of the write functions in here.

Returns
0 on success. <0 on error, setting errno as appropriate.
Error Conditions:
ENXIO - ATA support not initialized or no device attached
int g1_ata_init ( void  )

Initialize G1 ATA support.

This function initializes the rest of this subsystem and completes a scan of the G1 ATA bus for devices. This function may take a while to complete with some devices. Currently only the slave device is scanned, as the master device should always be the GD-ROM drive.

Returns
0 on success, <0 on error or if no device is present
int g1_ata_mutex_lock ( void  )

Lock the G1 ATA mutex.

This function locks the mutex that arbitrates access to the ATA bus. You should never have to do this on your own unless you're accessing devices manually yourself.

Returns
0 on success, -1 on failure.
Note
Failure conditions are exactly the same as the mutex_lock() function.
int g1_ata_mutex_unlock ( void  )

Unlock the G1 ATA mutex.

This function unlocks the mutex that arbitrates access to the ATA bus. You should never have to do this on your own unless you're accessing devices manually yourself.

Returns
0 on success, -1 on failure.
Note
Failure conditions are exactly the same as the mutex_unlock() function.
int g1_ata_read_chs ( uint16_t  c,
uint8_t  h,
uint8_t  s,
size_t  count,
uint16_t *  buf 
)

Read one or more disk sectors with Cylinder-Head-Sector addressing.

This function reads one or more 512-byte disk blocks from the slave device on the G1 ATA bus using Cylinder-Head-Sector addressing. This function uses PIO and blocks until the data is read in.

Parameters
cThe cylinder to start reading from.
hThe head to start reading from.
sThe sector to start reading from.
countThe number of disk sectors to read.
bufStorage for the read-in disk sectors. This should be at least (count * 512) bytes in length, and must be at least 16-bit aligned.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
Unless you're accessing a really old hard drive, you probably do not want to use this function to access the disk. Use the g1_ata_read_lba() function instead of this one, unless you get an error from that function indicating that LBA addressing is not supported.
Error Conditions:
EIO - an I/O error occurred in reading data
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
int g1_ata_read_lba ( uint64_t  sector,
size_t  count,
uint16_t *  buf 
)

Read one or more disk sectors with Linear Block Addressing (LBA).

This function reads one or more 512-byte disk blocks from the slave device on the G1 ATA bus using LBA mode (either 28 or 48 bits, as appropriate). This function uses PIO and blocks until the data is read.

Parameters
sectorThe sector to start reading from.
countThe number of disk sectors to read.
bufStorage for the read-in disk sectors. This should be at least (count * 512) bytes in length, and must be at least 16-bit aligned.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
If errno is set to ENOTSUP after calling this function, you must use the g1_ata_read_chs() function instead.
Error Conditions:
EIO - an I/O error occurred in reading data
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
ENOTSUP - LBA mode not supported by the device
int g1_ata_read_lba_dma ( uint64_t  sector,
size_t  count,
uint16_t *  buf,
int  block 
)

DMA read disk sectors with Linear Block Addressing (LBA).

This function reads one or more 512-byte disk blocks from the slave device on the G1 ATA bus using LBA mode (either 28 or 48 bits, as appropriate). This function uses DMA and optionally blocks until the data is read.

Parameters
sectorThe sector to start reading from.
countThe number of disk sectors to read.
bufStorage for the read-in disk sectors. This should be at least (count * 512) bytes in length, and must be at least 32-byte aligned.
blockNon-zero to block until the transfer completes.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
If errno is set to ENOTSUP after calling this function, you must use a CHS addressed transfer function instead, like g1_ata_read_chs().
If errno is set to EPERM after calling this function, DMA mode is not supported. You should use a PIO transfer function like g1_ata_read_lba() instead.
Error Conditions:
EIO - an I/O error occurred in reading data
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
ENOTSUP - LBA mode not supported by the device
EPERM - device does not support DMA
uint8_t g1_ata_select_device ( uint8_t  dev)

Set the active ATA device.

This function sets the device that any further ATA commands will go to. You shouldn't have to ever call this yourself, as it should be done for you by any of the access functions. This must be called with the ATA lock held.

Parameters
devThe device to access (generally either G1_ATA_MASTER or G1_ATA_SLAVE).
Returns
The previous active device (or 0x0F if the function would block in an IRQ handler).
Note
This function may block if there is a transfer ongoing. If called in an IRQ handler and the call would otherwise block, 0x0F is returned.
void g1_ata_shutdown ( void  )

Shut down G1 ATA support.

This function shuts down the rest of this subsystem, and attempts to flush the write cache of any attached slave devices. Accessing any ATA devices using this subsystem after this function is called may produce undefined results.

int g1_ata_write_chs ( uint16_t  c,
uint8_t  h,
uint8_t  s,
size_t  count,
const uint16_t *  buf 
)

Write one or more disk sectors with Cylinder-Head-Sector addressing.

This function writes one or more 512-byte disk blocks to the slave device on the G1 ATA bus using Cylinder-Head-Sector addressing. This function uses PIO and blocks until the data is written.

Parameters
cThe cylinder to start writing to.
hThe head to start writing to.
sThe sector to start writing to.
countThe number of disk sectors to write.
bufThe data to write to the disk. This should be (count * 512) bytes in length and must be at least 16-bit aligned.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
Unless you're accessing a really old hard drive, you probably do not want to use this function to access the disk. Use the g1_ata_write_lba() function instead of this one, unless you get an error from that function indicating that LBA addressing is not supported.
Error Conditions:
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
int g1_ata_write_lba ( uint64_t  sector,
size_t  count,
const uint16_t *  buf 
)

Write one or more disk sectors with Linear Block Addressing (LBA).

This function writes one or more 512-byte disk blocks to the slave device on the G1 ATA bus using LBA mode (either 28 or 48 bits, as appropriate). This function uses PIO and blocks until the data is written.

Parameters
sectorThe sector to start writing to.
countThe number of disk sectors to write.
bufThe data to write to the disk. This should be (count * 512) bytes in length and must be at least 16-bit aligned.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
If errno is set to ENOTSUP after calling this function, you must use the g1_ata_write_chs() function instead.
Error Conditions:
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
ENOTSUP - LBA mode not supported by the device
int g1_ata_write_lba_dma ( uint64_t  sector,
size_t  count,
const uint16_t *  buf,
int  block 
)

DMA Write disk sectors with Linear Block Addressing (LBA).

This function writes one or more 512-byte disk blocks to the slave device on the G1 ATA bus using LBA mode (either 28 or 48 bits, as appropriate). This function uses DMA and optionally blocks until the data is written.

Parameters
sectorThe sector to start writing to.
countThe number of disk sectors to write.
bufThe data to write to the disk. This should be (count * 512) bytes in length and must be at least 32-byte aligned.
blockNon-zero to block until the transfer completes.
Returns
0 on success. < 0 on failure, setting errno as appropriate.
Note
If errno is set to ENOTSUP after calling this function, you must use the g1_ata_write_chs() function instead.
If errno is set to EPERM after calling this function, DMA mode is not supported. You should use a PIO transfer function like g1_ata_write_lba() instead.
Error Conditions:
ENXIO - ATA support not initialized or no device attached
EOVERFLOW - one or more of the requested sectors is out of the range of the disk
ENOTSUP - LBA mode not supported by the device
EPERM - device does not support DMA
int g1_dma_in_progress ( void  )

Is there a G1 DMA in progress currently?

This function returns non-zero if a DMA is in progress. This can be used to check on the completion of DMA transfers when non-blocking mode was selected at transfer time.

Returns
0 if no DMA is in progress, nonzero otherwise.