nkeynes@31: /** nkeynes@561: * $Id$ nkeynes@2: * nkeynes@31: * This file defines the interface and structures of the dreamcast's IDE nkeynes@31: * port. Note that the register definitions are in asic.h, as the registers nkeynes@31: * fall into the general ASIC ranges (and I don't want to use smaller pages nkeynes@31: * at this stage). The registers here are exactly as per the ATA nkeynes@31: * specifications, which makes things a little easier. nkeynes@2: * nkeynes@31: * Copyright (c) 2005 Nathan Keynes. nkeynes@31: * nkeynes@31: * This program is free software; you can redistribute it and/or modify nkeynes@31: * it under the terms of the GNU General Public License as published by nkeynes@31: * the Free Software Foundation; either version 2 of the License, or nkeynes@31: * (at your option) any later version. nkeynes@31: * nkeynes@31: * This program is distributed in the hope that it will be useful, nkeynes@31: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@31: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@31: * GNU General Public License for more details. nkeynes@2: */ nkeynes@31: nkeynes@736: #ifndef lxdream_ide_H nkeynes@736: #define lxdream_ide_H 1 nkeynes@2: nkeynes@736: #include "lxdream.h" nkeynes@736: nkeynes@736: #ifdef __cplusplus nkeynes@736: extern "C" { nkeynes@736: #endif nkeynes@2: nkeynes@493: #define GDROM_SENSE_LENGTH 10 nkeynes@493: #define GDROM_MODE_LENGTH 32 nkeynes@493: nkeynes@2: struct ide_registers { nkeynes@152: /* IDE interface registers */ nkeynes@2: uint8_t status; /* A05F709C + A05F7018 Read-only */ nkeynes@2: uint8_t control; /* A05F7018 Write-only 01110 */ nkeynes@2: uint8_t error; /* A05F7084 Read-only 10001 */ nkeynes@2: uint8_t feature; /* A05F7084 Write-only 10001 */ nkeynes@2: uint8_t count; /* A05F7088 Read/Write 10010 */ nkeynes@2: uint8_t disc; /* A05F708C Read-only 10011 */ nkeynes@2: uint8_t lba0; /* A05F708C Write-only 10011 (NB: Presumed, TBV */ nkeynes@2: uint8_t lba1; /* A05F7090 Read/Write 10100 */ nkeynes@2: uint8_t lba2; /* A05F7094 Read/Write 10101 */ nkeynes@2: uint8_t device; /* A05F7098 Read/Write 10110 */ nkeynes@2: uint8_t command; /* A05F709C Write-only 10111 */ nkeynes@152: nkeynes@152: /* Internal IDE state */ nkeynes@138: uint8_t intrq_pending; /* Flag to indicate if the INTRQ line is active */ nkeynes@245: gboolean interface_enabled; nkeynes@254: gboolean was_reset; /* Flag indicating that the device has just been reset */ nkeynes@493: uint32_t state; nkeynes@493: uint32_t last_packet_command; /* Identifies the command executing during a r/w cycle */ nkeynes@138: nkeynes@152: /* Sense response for the last executed packet command */ nkeynes@493: unsigned char gdrom_sense[GDROM_SENSE_LENGTH]; nkeynes@493: unsigned char gdrom_mode[GDROM_MODE_LENGTH]; nkeynes@152: nkeynes@152: /* offset in the buffer of the next word to read/write, or -1 nkeynes@152: * if inactive. nkeynes@152: */ nkeynes@493: int32_t data_offset; nkeynes@493: int32_t data_length; nkeynes@152: nkeynes@245: /* Status reporting information */ nkeynes@245: uint8_t last_read_track; nkeynes@493: uint32_t current_lba; nkeynes@493: uint32_t current_mode; nkeynes@342: uint32_t sectors_left; /* sectors left after current read */ nkeynes@2: }; nkeynes@2: nkeynes@152: #define IDE_STATE_IDLE 0 nkeynes@152: #define IDE_STATE_CMD_WRITE 1 nkeynes@152: #define IDE_STATE_PIO_READ 2 nkeynes@152: #define IDE_STATE_PIO_WRITE 3 nkeynes@152: #define IDE_STATE_DMA_READ 4 nkeynes@152: #define IDE_STATE_DMA_WRITE 5 nkeynes@152: #define IDE_STATE_BUSY 6 nkeynes@152: nkeynes@152: /* Flag bits */ nkeynes@152: #define IDE_STATUS_BSY 0x80 /* Busy */ nkeynes@152: #define IDE_STATUS_DRDY 0x40 /* Device ready */ nkeynes@152: #define IDE_STATUS_DMRD 0x20 /* DMA Request */ nkeynes@152: #define IDE_STATUS_SERV 0x10 nkeynes@152: #define IDE_STATUS_DRQ 0x08 nkeynes@152: #define IDE_STATUS_CHK 0x01 /* Check condition (ie error) */ nkeynes@2: nkeynes@149: #define IDE_FEAT_DMA 0x01 nkeynes@149: #define IDE_FEAT_OVL 0x02 nkeynes@149: nkeynes@152: #define IDE_COUNT_CD 0x01 /* Command (1)/Data (0) */ nkeynes@257: #define IDE_COUNT_IO 0x02 /* Input (1)/Output (0) */ nkeynes@152: #define IDE_COUNT_REL 0x04 /* Release device */ nkeynes@149: nkeynes@149: nkeynes@2: #define IDE_CTL_RESET 0x04 nkeynes@2: #define IDE_CTL_IRQEN 0x02 /* IRQ enabled when == 0 */ nkeynes@2: nkeynes@240: #define IDE_CMD_NOP 0x00 nkeynes@2: #define IDE_CMD_RESET_DEVICE 0x08 nkeynes@2: #define IDE_CMD_PACKET 0xA0 nkeynes@2: #define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1 nkeynes@2: #define IDE_CMD_SERVICE 0xA2 nkeynes@2: #define IDE_CMD_SET_FEATURE 0xEF nkeynes@2: nkeynes@47: #define IDE_FEAT_SET_TRANSFER_MODE 0x03 nkeynes@47: #define IDE_XFER_PIO 0x00 nkeynes@47: #define IDE_XFER_PIO_FLOW 0x08 nkeynes@47: #define IDE_XFER_MULTI_DMA 0x20 nkeynes@47: #define IDE_XFER_ULTRA_DMA 0x40 nkeynes@47: nkeynes@2: extern struct ide_registers idereg; nkeynes@2: nkeynes@2: /* Note: control can be written at any time - all other registers are writable nkeynes@2: * only when ide_can_write_regs() is true nkeynes@2: */ nkeynes@254: #define ide_can_write_regs() ((idereg.status&0x80)==0) nkeynes@125: #define IS_IDE_IRQ_ENABLED() ((idereg.control&0x02)==0) nkeynes@2: nkeynes@2: nkeynes@2: uint16_t ide_read_data_pio(void); nkeynes@152: void ide_write_data_pio( uint16_t value ); nkeynes@152: uint32_t ide_read_data_dma( uint32_t addr, uint32_t length ); nkeynes@125: uint8_t ide_read_status(void); nkeynes@342: uint8_t ide_get_drive_status(void); nkeynes@493: void ide_write_buffer( unsigned char *data, uint32_t length ); nkeynes@2: nkeynes@2: void ide_write_command( uint8_t command ); nkeynes@2: void ide_write_control( uint8_t value ); nkeynes@152: nkeynes@152: void ide_dma_read_req( uint32_t addr, uint32_t length ); nkeynes@736: nkeynes@736: #ifdef __cplusplus nkeynes@736: } nkeynes@2: #endif nkeynes@736: nkeynes@736: #endif /* !lxdream_ide_H */