KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches

Driver for Accessing an ATA device on the G1 Bus More...

Topics

 Device Definitions
 ATA device definitions
 

Files

file  g1ata.h
 G1 bus ATA interface.
 

Macros

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

Functions

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

Detailed Description

Driver for Accessing an ATA device on the G1 Bus

Macro Definition Documentation

◆ G1_ATA_LBA_MODE

#define G1_ATA_LBA_MODE   0x40

Select LBA addressing mode.

OR this constant with one of the device constants (G1_ATA_MASTER or G1_ATA_SLAVE) to select LBA addressing mode. The various g1_ata_* functions all do this as appropriate already, so you shouldn't have to worry about this one at all. This bit is irrelevant for packet devices.

◆ G1_ATA_MASTER

#define G1_ATA_MASTER   0x00

ATA master device.

This constant selects the master device on the ATA bus. This is normally the GD-ROM drive.

Note
The GD-ROM really does not like the reserved bits being set in the device select register, hence why this constant doesn't select them. Some hard drives may require them, however. If you find one that does, then you should use the G1_ATA_MASTER_ALT constant to access it if it is the master device on the bus.

◆ G1_ATA_MASTER_ALT

#define G1_ATA_MASTER_ALT   0x90

ATA master device (compatible with old drives).

This constant selects the master device on the ATA bus, with the old reserved bits set to 1. If you have a drive that predates ATA-2, then this will probably be the constant you want to access it as the master device.

Note
Do not use this constant to access the GD-ROM. It will not work. Use G1_ATA_MASTER instead.

◆ G1_ATA_SLAVE

#define G1_ATA_SLAVE   0xB0

ATA slave device.

This constant selects the slave device on the ATA bus. This is where you would find a hard drive, if the user has an adapter installed.

Function Documentation

◆ g1_ata_blockdev_for_device()

int g1_ata_blockdev_for_device ( int dma,
kos_blockdev_t * rv )

Get a block device for the attached ATA device.

This function creates a block device descriptor for the attached ATA device.

Parameters
dmaSet to 1 to use DMA for reads/writes on the device, if available.
rvUsed to return the block device. 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
EFAULT - rv was NULL
ENOMEM - out of memory

◆ g1_ata_blockdev_for_partition()

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.

◆ g1_ata_flush()

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

◆ g1_ata_init()

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

◆ g1_ata_lba_mode()

int g1_ata_lba_mode ( void )

Get LBA mode of the attached disk.

Returns
-1 on error, 0 - CHS, 28 - LBA28, 48 - LBA48
Error Conditions:
ENXIO - ATA support not initialized or no device attached

◆ g1_ata_mutex_lock()

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.

◆ g1_ata_mutex_unlock()

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.

◆ g1_ata_read_chs()

int g1_ata_read_chs ( uint16_t c,
uint8_t h,
uint8_t s,
size_t count,
void * 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

◆ g1_ata_read_lba()

int g1_ata_read_lba ( uint64_t sector,
size_t count,
void * 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

◆ g1_ata_read_lba_dma()

int g1_ata_read_lba_dma ( uint64_t sector,
size_t count,
void * 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

◆ g1_ata_select_device()

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.

◆ g1_ata_shutdown()

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.

◆ g1_ata_write_chs()

int g1_ata_write_chs ( uint16_t c,
uint8_t h,
uint8_t s,
size_t count,
const void * 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

◆ g1_ata_write_lba()

int g1_ata_write_lba ( uint64_t sector,
size_t count,
const void * 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

◆ g1_ata_write_lba_dma()

int g1_ata_write_lba_dma ( uint64_t sector,
size_t count,
const void * 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

◆ g1_dma_in_progress()

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.