Search
lxdream.org :: lxdream/src/gdrom/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 47:da09bcb7ce69
prev39:3c35cb97b2ff
next125:49bf45f8210a
author nkeynes
date Tue Dec 27 12:41:33 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Log transfer mode set
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@47
     2
 * $Id: ide.c,v 1.7 2005-12-27 12:41:33 nkeynes Exp $
nkeynes@2
     3
 *
nkeynes@31
     4
 * IDE interface implementation
nkeynes@31
     5
 *
nkeynes@31
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@31
     7
 *
nkeynes@31
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@31
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@31
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@31
    11
 * (at your option) any later version.
nkeynes@31
    12
 *
nkeynes@31
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@31
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@31
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@31
    16
 * GNU General Public License for more details.
nkeynes@2
    17
 */
nkeynes@35
    18
nkeynes@35
    19
#define MODULE ide_module
nkeynes@35
    20
nkeynes@2
    21
#include <stdlib.h>
nkeynes@35
    22
#include "dream.h"
nkeynes@39
    23
#include "gdrom/ide.h"
nkeynes@2
    24
nkeynes@2
    25
#define MAX_WRITE_BUF 4096;
nkeynes@2
    26
nkeynes@15
    27
void ide_init( void );
nkeynes@15
    28
void ide_init( void );
nkeynes@15
    29
nkeynes@15
    30
struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, NULL,
nkeynes@23
    31
				       NULL, NULL, NULL };
nkeynes@15
    32
nkeynes@2
    33
struct ide_registers idereg;
nkeynes@2
    34
nkeynes@2
    35
static char command_buffer[12];
nkeynes@2
    36
nkeynes@2
    37
/* "\0\0\0\0\xb4\x19\0\0\x08SE      REV 6.42990316" */
nkeynes@2
    38
char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
nkeynes@2
    39
                       0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
nkeynes@2
    40
                       0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
nkeynes@2
    41
                       0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
nkeynes@2
    42
nkeynes@2
    43
nkeynes@2
    44
void set_write_buffer( char *buf, int len )
nkeynes@2
    45
{
nkeynes@2
    46
    idereg.status |= IDE_ST_DATA;
nkeynes@2
    47
    idereg.data = buf;
nkeynes@2
    48
    idereg.datalen = len;
nkeynes@2
    49
    idereg.writeptr = (uint16_t *)buf;
nkeynes@2
    50
    idereg.readptr = NULL;
nkeynes@2
    51
}
nkeynes@2
    52
nkeynes@2
    53
void set_read_buffer( char *buf, int len )
nkeynes@2
    54
{
nkeynes@2
    55
    idereg.status |= IDE_ST_DATA;
nkeynes@2
    56
    idereg.data = buf;
nkeynes@2
    57
    idereg.datalen = len;
nkeynes@2
    58
    idereg.readptr = (uint16_t *)buf;
nkeynes@2
    59
    idereg.writeptr = NULL;
nkeynes@2
    60
    idereg.lba1 = len&0xFF;
nkeynes@2
    61
    idereg.lba2 = len>>8;
nkeynes@2
    62
}
nkeynes@2
    63
nkeynes@2
    64
void ide_clear_interrupt( void )
nkeynes@2
    65
{
nkeynes@2
    66
    /* TODO */
nkeynes@2
    67
}
nkeynes@2
    68
nkeynes@15
    69
void ide_init( void )
nkeynes@15
    70
{
nkeynes@15
    71
nkeynes@15
    72
}
nkeynes@15
    73
nkeynes@2
    74
void ide_reset( void )
nkeynes@2
    75
{
nkeynes@2
    76
    ide_clear_interrupt();
nkeynes@2
    77
    idereg.error = 0x01;
nkeynes@2
    78
    idereg.count = 0x01;
nkeynes@2
    79
    idereg.lba0 = 0x21;
nkeynes@2
    80
    idereg.lba1 = 0x14;
nkeynes@2
    81
    idereg.lba2 = 0xeb;
nkeynes@2
    82
    idereg.feature = 0; /* Indeterminate really */
nkeynes@2
    83
    idereg.status = 0x00;
nkeynes@2
    84
    idereg.device = 0x00;
nkeynes@2
    85
    idereg.disc = IDE_DISC_GDROM | IDE_DISC_READY;
nkeynes@2
    86
}
nkeynes@2
    87
nkeynes@2
    88
uint16_t ide_read_data_pio( void ) {
nkeynes@2
    89
    if( idereg.readptr == NULL )
nkeynes@2
    90
        return 0xFFFF;
nkeynes@2
    91
    uint16_t rv = *idereg.readptr++;
nkeynes@2
    92
    idereg.datalen-=2;
nkeynes@2
    93
    if( idereg.datalen <=0 ) {
nkeynes@2
    94
        idereg.readptr = NULL;
nkeynes@2
    95
        idereg.status &= ~IDE_ST_DATA;
nkeynes@2
    96
    }
nkeynes@2
    97
    return rv;
nkeynes@2
    98
}
nkeynes@2
    99
nkeynes@2
   100
void ide_write_data_pio( uint16_t val ) {
nkeynes@2
   101
    if( idereg.writeptr == NULL )
nkeynes@2
   102
        return;
nkeynes@2
   103
    *idereg.writeptr++ = val;
nkeynes@2
   104
    idereg.datalen-=2;
nkeynes@2
   105
    if( idereg.datalen <= 0 ) {
nkeynes@2
   106
        idereg.writeptr = NULL;
nkeynes@2
   107
        idereg.status &= ~IDE_ST_DATA;
nkeynes@2
   108
        ide_write_buffer( idereg.data );
nkeynes@2
   109
    }
nkeynes@2
   110
}
nkeynes@2
   111
nkeynes@2
   112
void ide_write_control( uint8_t val ) {
nkeynes@2
   113
    /* TODO: In theory we can cause a soft-reset here, but the DC doesn't
nkeynes@2
   114
     * appear to support it.
nkeynes@2
   115
     */
nkeynes@2
   116
}
nkeynes@2
   117
nkeynes@2
   118
void ide_write_command( uint8_t val ) {
nkeynes@2
   119
    idereg.command = val;
nkeynes@2
   120
    switch( val ) {
nkeynes@39
   121
    case IDE_CMD_RESET_DEVICE:
nkeynes@39
   122
	ide_reset();
nkeynes@39
   123
	break;
nkeynes@39
   124
    case IDE_CMD_PACKET:
nkeynes@39
   125
	set_write_buffer(command_buffer,12);
nkeynes@39
   126
	break;
nkeynes@39
   127
    case IDE_CMD_SET_FEATURE:
nkeynes@39
   128
	switch( idereg.feature ) {
nkeynes@47
   129
	case IDE_FEAT_SET_TRANSFER_MODE:
nkeynes@47
   130
	    switch( idereg.count & 0xF8 ) {
nkeynes@47
   131
	    case IDE_XFER_PIO:
nkeynes@47
   132
		INFO( "Set PIO default mode: %d", idereg.count&0x07 );
nkeynes@47
   133
		break;
nkeynes@47
   134
	    case IDE_XFER_PIO_FLOW:
nkeynes@47
   135
		INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
nkeynes@47
   136
		break;
nkeynes@47
   137
	    case IDE_XFER_MULTI_DMA:
nkeynes@47
   138
		INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
nkeynes@47
   139
		break;
nkeynes@47
   140
	    case IDE_XFER_ULTRA_DMA:
nkeynes@47
   141
		INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
nkeynes@47
   142
		break;
nkeynes@47
   143
	    default:
nkeynes@47
   144
		INFO( "Setting unknown transfer mode: %02X", idereg.count );
nkeynes@47
   145
		break;
nkeynes@47
   146
	    }
nkeynes@47
   147
	    break;
nkeynes@39
   148
	default:
nkeynes@39
   149
	    WARN( "IDE: unimplemented feature: %02X", idereg.feature );
nkeynes@39
   150
	}
nkeynes@39
   151
	break;
nkeynes@39
   152
    default:
nkeynes@39
   153
	WARN( "IDE: Unimplemented command: %02X", val );
nkeynes@2
   154
    }
nkeynes@2
   155
    idereg.status |= IDE_ST_READY | IDE_ST_SERV;
nkeynes@2
   156
}
nkeynes@2
   157
nkeynes@2
   158
void ide_write_buffer( char *data ) {
nkeynes@2
   159
    uint16_t length;
nkeynes@2
   160
    switch( idereg.command ) {
nkeynes@2
   161
        case IDE_CMD_PACKET:
nkeynes@2
   162
            /* Okay we have the packet in the command buffer */
nkeynes@2
   163
            WARN( "ATAPI: Received Packet command: %02X", data[0] );
nkeynes@2
   164
            
nkeynes@2
   165
            switch( command_buffer[0] ) {
nkeynes@2
   166
                case PKT_CMD_IDENTIFY:
nkeynes@2
   167
                    /* NB: Bios sets data[4] = 0x08, no idea what this is for;
nkeynes@2
   168
                     * different values here appear to have no effect.
nkeynes@2
   169
                     */
nkeynes@2
   170
                    length = *((uint16_t*)(data+2));
nkeynes@2
   171
                    if( length > sizeof(gdrom_ident) )
nkeynes@2
   172
                        length = sizeof(gdrom_ident);
nkeynes@2
   173
                    set_read_buffer(gdrom_ident, length);
nkeynes@2
   174
                    break;
nkeynes@2
   175
            }
nkeynes@2
   176
            break;
nkeynes@2
   177
    }
nkeynes@2
   178
}
.