Search
lxdream.org :: lxdream/src/gdrom/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 1075:1a21750d300c
prev1023:264e2fd90be8
next1097:d4807997e450
author nkeynes
date Fri Jul 31 13:45:32 2009 +1000 (11 years ago)
permissions -rw-r--r--
last change Remove or change the level of a bunch of INFO messages that shouldn't really
be INFO level
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@2
     3
 *
nkeynes@31
     4
 * IDE interface implementation
nkeynes@31
     5
 *
nkeynes@152
     6
 *
nkeynes@152
     7
 * Note: All references to read/write are from the host's point of view.
nkeynes@152
     8
 *
nkeynes@152
     9
 * See: INF-8020 
nkeynes@31
    10
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@31
    11
 *
nkeynes@31
    12
 * This program is free software; you can redistribute it and/or modify
nkeynes@31
    13
 * it under the terms of the GNU General Public License as published by
nkeynes@31
    14
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@31
    15
 * (at your option) any later version.
nkeynes@31
    16
 *
nkeynes@31
    17
 * This program is distributed in the hope that it will be useful,
nkeynes@31
    18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@31
    19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@31
    20
 * GNU General Public License for more details.
nkeynes@2
    21
 */
nkeynes@35
    22
nkeynes@35
    23
#define MODULE ide_module
nkeynes@35
    24
nkeynes@138
    25
#include <assert.h>
nkeynes@2
    26
#include <stdlib.h>
nkeynes@35
    27
#include "dream.h"
nkeynes@422
    28
#include "mem.h"
nkeynes@125
    29
#include "asic.h"
nkeynes@39
    30
#include "gdrom/ide.h"
nkeynes@678
    31
#include "gdrom/gddriver.h"
nkeynes@142
    32
#include "gdrom/packet.h"
nkeynes@2
    33
nkeynes@138
    34
#define MAX_WRITE_BUF 4096
nkeynes@138
    35
#define MAX_SECTOR_SIZE 2352 /* Audio sector */
nkeynes@138
    36
#define DEFAULT_DATA_SECTORS 8
nkeynes@2
    37
nkeynes@138
    38
static void ide_init( void );
nkeynes@138
    39
static void ide_reset( void );
nkeynes@342
    40
static uint32_t ide_run_slice( uint32_t nanosecs );
nkeynes@138
    41
static void ide_save_state( FILE *f );
nkeynes@138
    42
static int ide_load_state( FILE *f );
nkeynes@138
    43
static void ide_raise_interrupt( void );
nkeynes@138
    44
static void ide_clear_interrupt( void );
nkeynes@152
    45
static void ide_packet_command( unsigned char *data );
nkeynes@342
    46
static void ide_read_next_sector(void);
nkeynes@15
    47
nkeynes@342
    48
struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, ide_run_slice,
nkeynes@736
    49
        NULL, ide_save_state, ide_load_state };
nkeynes@15
    50
nkeynes@2
    51
struct ide_registers idereg;
nkeynes@342
    52
gdrom_disc_t gdrom_disc = NULL;
nkeynes@342
    53
nkeynes@342
    54
unsigned char data_buffer[MAX_SECTOR_SIZE];
nkeynes@2
    55
nkeynes@152
    56
#define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
nkeynes@152
    57
#define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))
nkeynes@152
    58
nkeynes@493
    59
/* 10 bytes followed by "SE      REV 6.42990316" */
nkeynes@493
    60
unsigned char default_gdrom_mode[GDROM_MODE_LENGTH] = 
nkeynes@736
    61
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00, 0x00, 0x08,
nkeynes@736
    62
        0x53, 0x45, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
nkeynes@736
    63
        0x52, 0x65, 0x76, 0x20, 0x36, 0x2e, 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
nkeynes@736
    64
nkeynes@158
    65
unsigned char gdrom_71[] = { 0x3E, 0x0F, 0x90, 0xBE,  0x1D, 0xD9, 0x89, 0x04,  0x28, 0x3A, 0x8E, 0x26,  0x5C, 0x95, 0x10, 0x5A,
nkeynes@736
    66
        0x0A, 0x99, 0xEE, 0xFB,  0x69, 0xCE, 0xD9, 0x63,  0x00, 0xF5, 0x0A, 0xBC,  0x2C, 0x0D, 0xF8, 0xE2,
nkeynes@736
    67
        0x05, 0x02, 0x00, 0x7C,  0x03, 0x00, 0x3D, 0x08,  0xD8, 0x8D, 0x08, 0x7A,  0x6D, 0x00, 0x35, 0x06,
nkeynes@736
    68
        0xBA, 0x66, 0x10, 0x00,  0x91, 0x08, 0x10, 0x29,  0xD0, 0x45, 0xDA, 0x00,  0x2D, 0x05, 0x69, 0x09,
nkeynes@736
    69
        0x00, 0x5E, 0x0F, 0x70,  0x86, 0x12, 0x6C, 0x77,  0x5A, 0xFB, 0xCD, 0x56,  0xFB, 0xF7, 0xB7, 0x00,
nkeynes@736
    70
        0x5D, 0x07, 0x19, 0x99,  0xF2, 0xAF, 0x00, 0x63,  0x03, 0x00, 0xF0, 0x10,  0xBE, 0xD7, 0xA0, 0x63,
nkeynes@736
    71
        0xFA, 0x84, 0xA7, 0x74,  0x94, 0xEF, 0xAD, 0xC2,  0xAC, 0x00, 0x78, 0x07,  0x9F, 0x57, 0x0B, 0x62,
nkeynes@736
    72
        0x00, 0xFE, 0x08, 0x08,  0x5D, 0x5A, 0x6A, 0x54,  0x00, 0xE2, 0x09, 0x93,  0x7E, 0x62, 0x2A, 0x5E,
nkeynes@736
    73
        0xDA, 0x00, 0x7E, 0x0F,  0xF0, 0x07, 0x01, 0x6D,  0x50, 0x86, 0xDD, 0x4A,  0x15, 0x54, 0xC7, 0xEC,
nkeynes@736
    74
        0x00, 0xF2, 0x0B, 0x07,  0xF8, 0x1A, 0xB0, 0x99,  0x3B, 0xF1, 0x36, 0x00,  0x94, 0x07, 0x34, 0xE3,
nkeynes@736
    75
        0xBC, 0x6E, 0x00, 0x34,  0x0D, 0x6F, 0xDA, 0xBD,  0xEE, 0xF7, 0xCC, 0xCE,  0x39, 0x7E, 0xE3, 0x00,
nkeynes@736
    76
        0x14, 0x08, 0xDC, 0xD2,  0xB9, 0xF9, 0x31, 0x00,  0xB0, 0x0C, 0x10, 0xA3,  0x45, 0x12, 0xC7, 0xCD,
nkeynes@736
    77
        0xBF, 0x05, 0x37, 0x00,  0xC4, 0x0D, 0x5F, 0xE0,  0x59, 0xBB, 0x01, 0x59,  0x03, 0xD6, 0x29, 0x9C,
nkeynes@736
    78
        0x00, 0x01, 0x0A, 0x09,  0xAA, 0xA8, 0xA8, 0x24,  0x0B, 0x66, 0x00, 0x5C,  0x05, 0xA5, 0xCE, 0x00,
nkeynes@736
    79
        0xC1, 0x0B, 0xB7, 0xA0,  0x6F, 0xE9, 0x2B, 0xCC,  0xB5, 0xFC, 0x00, 0x8D,  0x05, 0xF4, 0xAC, 0x00,
nkeynes@736
    80
        0x57, 0x04, 0xB6, 0x00,  0xFC, 0x03, 0x00, 0xC3,  0x10, 0x43, 0x3B, 0xBE,  0xA2, 0x96, 0xC3, 0x65,
nkeynes@736
    81
        0x9F, 0x9A, 0x88, 0xD5,  0x49, 0x68, 0x00, 0xDC,  0x11, 0x56, 0x23, 0x2D,  0xF9, 0xFC, 0xF5, 0x8B,
nkeynes@736
    82
        0x1B, 0xB1, 0xB7, 0x10,  0x21, 0x1C, 0x12, 0x00,  0x0D, 0x0D, 0xEB, 0x86,  0xA2, 0x49, 0x8D, 0x8D,
nkeynes@736
    83
        0xBE, 0xA1, 0x6D, 0x53,  0x00, 0xE1, 0x0A, 0x8E,  0x67, 0xAA, 0x16, 0x79,  0x39, 0x59, 0x00, 0x36,
nkeynes@736
    84
        0x0B, 0x2A, 0x4E, 0xAE,  0x51, 0x4B, 0xD0, 0x66,  0x33, 0x00, 0x8A, 0x07,  0xCD, 0x6F, 0xBA, 0x92,
nkeynes@736
    85
        0x00, 0x1A, 0x0E, 0xDF,  0x4A, 0xB3, 0x77, 0x1F,  0xA5, 0x90, 0x19, 0xFA,  0x59, 0xD7, 0x00, 0x04,
nkeynes@736
    86
        0x0F, 0xAC, 0xCA, 0x9F,  0xA4, 0xFC, 0x6D, 0x90,  0x86, 0x9E, 0x1F, 0x44,  0x40, 0x00, 0x9F, 0x04,
nkeynes@736
    87
        0x56, 0x00, 0x22, 0x03,  0x00, 0xB8, 0x10, 0x2C,  0x7A, 0x53, 0xA4, 0xBF,  0xA3, 0x90, 0x90, 0x14,
nkeynes@736
    88
        0x9D, 0x46, 0x6C, 0x96,  0x00, 0xC6, 0x0B, 0x9B,  0xBB, 0xB0, 0xAE, 0x60,  0x92, 0x8E, 0x0C, 0x00,
nkeynes@736
    89
        0x14, 0x06, 0x4B, 0xAE,  0x7F, 0x00, 0x5C, 0x0B,  0x23, 0xFA, 0xE7, 0x51,  0xDA, 0x61, 0x49, 0x5E,
nkeynes@736
    90
        0x00, 0xD7, 0x0B, 0x01,  0xFC, 0x55, 0x31, 0x84,  0xC5, 0x0C, 0x98, 0x00,  0x97, 0x50, 0x6E, 0xF9,
nkeynes@736
    91
        0xEE, 0x75, 0x92, 0x53,  0xD3, 0x66, 0xA4, 0xAF,  0x3B, 0xFE, 0x7B, 0x27,  0x30, 0xBB, 0xB6, 0xF2,
nkeynes@736
    92
        0x76, 0x22, 0x45, 0x42,  0xCA, 0xF9, 0xF0, 0xDE,  0x9F, 0x45, 0x16, 0x68,  0x22, 0xB9, 0x84, 0x28,
nkeynes@736
    93
        0x8F, 0x2B, 0xB5, 0x5C,  0xD2, 0xF5, 0x45, 0x36,  0x3E, 0x76, 0xC6, 0xBF,  0x32, 0x5C, 0x41, 0xA6,
nkeynes@736
    94
        0x26, 0xC7, 0x82, 0x2F,  0x2E, 0xB5, 0x75, 0xC6,  0xE6, 0x67, 0x9E, 0x77,  0x94, 0xAF, 0x6A, 0x05,
nkeynes@736
    95
        0xC0, 0x05, 0x61, 0x71,  0x89, 0x5A, 0xB1, 0xD0,  0xFC, 0x7E, 0xC0, 0x9B,  0xCB, 0x3B, 0x69, 0xD9,
nkeynes@736
    96
        0x5F, 0xAF, 0xCA, 0xAB,  0x25, 0xD5, 0xBE, 0x8A,  0x6B, 0xB0, 0xFB, 0x61,  0x6C, 0xEB, 0x85, 0x6E,
nkeynes@736
    97
        0x7A, 0x48, 0xFF, 0x97,  0x91, 0x06, 0x3D, 0x4D,  0x68, 0xD3, 0x65, 0x83,  0x90, 0xA0, 0x08, 0x5C,
nkeynes@736
    98
        0xFC, 0xEE, 0x7C, 0x33,  0x43, 0x7F, 0x80, 0x52,  0x8B, 0x19, 0x72, 0xF2,  0xC9, 0xAB, 0x93, 0xAF,
nkeynes@736
    99
        0x16, 0xED, 0x36, 0x48,  0xAB, 0xC9, 0xD1, 0x03,  0xB3, 0xDC, 0x2F, 0xF2,  0x92, 0x3F, 0x0A, 0x19,
nkeynes@736
   100
        0x25, 0xE2, 0xEF, 0x7A,  0x22, 0xDA, 0xDB, 0xCB,  0x32, 0x12, 0x61, 0x49,  0x5B, 0x74, 0x7C, 0x65,
nkeynes@736
   101
        0x20, 0x89, 0x54, 0x9E,  0x0E, 0xC9, 0x52, 0xE3,  0xC9, 0x9A, 0x44, 0xC9,  0x5D, 0xA6, 0x77, 0xC0,
nkeynes@736
   102
        0xE7, 0x60, 0x91, 0x80,  0x50, 0x1F, 0x33, 0xB1,  0xCD, 0xAD, 0xF4, 0x0D,  0xBB, 0x08, 0xB1, 0xD0,
nkeynes@736
   103
        0x13, 0x95, 0xAE, 0xC9,  0xE2, 0x64, 0xA2, 0x65,  0xFB, 0x8F, 0xE9, 0xA2,  0x8A, 0xBC, 0x98, 0x81,
nkeynes@736
   104
        0x45, 0xB4, 0x55, 0x4E,  0xB9, 0x74, 0xB4, 0x50,  0x76, 0xBF, 0xF0, 0x45,  0xE7, 0xEE, 0x41, 0x64,
nkeynes@736
   105
        0x9F, 0xB5, 0xE0, 0xBB,  0x1C, 0xBB, 0x28, 0x66,  0x1B, 0xDD, 0x2B, 0x02,  0x66, 0xBF, 0xFD, 0x7D,
nkeynes@736
   106
        0x37, 0x35, 0x1D, 0x76,  0x21, 0xC3, 0x8F, 0xAF,  0xF6, 0xF9, 0xE9, 0x27,  0x48, 0xE7, 0x3D, 0x95,
nkeynes@736
   107
        0x74, 0x0C, 0x77, 0x88,  0x56, 0xD9, 0x84, 0xC8,  0x7D, 0x20, 0x31, 0x43,  0x53, 0xF1, 0xC1, 0xC7,
nkeynes@736
   108
        0xC9, 0xF7, 0x5C, 0xC0,  0xA6, 0x5A, 0x27, 0x0A,  0x41, 0xD4, 0x44, 0x94,  0x65, 0x4F, 0xE2, 0x53,
nkeynes@736
   109
        0x60, 0x0B, 0xD1, 0x23,  0x6C, 0x0C, 0xBC, 0x70,  0x6C, 0x26, 0x1A, 0x61,  0x1D, 0x35, 0x88, 0xEC,
nkeynes@736
   110
        0xB8, 0x15, 0xE3, 0xB4,  0x82, 0xEE, 0xB3, 0x21,  0xAC, 0x6C, 0xB7, 0x33,  0x6D, 0x78, 0x0C, 0x0D,
nkeynes@736
   111
        0xB4, 0x0B, 0x29, 0xF2,  0xD4, 0x8C, 0x3F, 0xDD,  0x3F, 0x47, 0xDD, 0xF2,  0xD8, 0x39, 0x57, 0x20,
nkeynes@736
   112
        0x28, 0xD8, 0xDD, 0x32,  0xE2, 0x6A, 0x47, 0x53,  0x57, 0xC6, 0xFA, 0x7A,  0x38, 0x30, 0x31, 0x8F,
nkeynes@736
   113
        0xE7, 0xD3, 0x84, 0x2B,  0x5D, 0x4F, 0x95, 0x98,  0xED, 0x0B, 0xD7, 0x50,  0x0C, 0x49, 0xDA, 0x59,
nkeynes@736
   114
        0x15, 0xF1, 0x39, 0xF3,  0x40, 0xDC, 0xDC, 0x25,  0x24, 0x56, 0x6E, 0xA9,  0x2F, 0xF0, 0x00, 0x00 };
nkeynes@158
   115
nkeynes@2
   116
nkeynes@250
   117
char gdrom_status[] = { 
nkeynes@736
   118
        0x00, 0x15, 0x00, 0x64, 0x00, 0x40, 0x00, 0x00, 
nkeynes@736
   119
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   120
        0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   121
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   122
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   123
        0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
nkeynes@736
   124
        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   125
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
nkeynes@736
   126
        0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
nkeynes@736
   127
        0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
nkeynes@736
   128
        0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
nkeynes@736
   129
        0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00,
nkeynes@736
   130
        0x00, 0x40, 0x00, 0x00 };
nkeynes@250
   131
nkeynes@250
   132
nkeynes@138
   133
static void ide_init( void )
nkeynes@138
   134
{
nkeynes@138
   135
    ide_reset();
nkeynes@138
   136
}
nkeynes@138
   137
nkeynes@138
   138
static void ide_reset( void )
nkeynes@138
   139
{
nkeynes@138
   140
    ide_clear_interrupt();
nkeynes@138
   141
    idereg.error = 0x01;
nkeynes@138
   142
    idereg.count = 0x01;
nkeynes@138
   143
    idereg.lba0 = /* 0x21; */ 0x81;
nkeynes@138
   144
    idereg.lba1 = 0x14;
nkeynes@138
   145
    idereg.lba2 = 0xeb;
nkeynes@138
   146
    idereg.feature = 0; /* Indeterminate really */
nkeynes@254
   147
    idereg.status = 0x00;
nkeynes@138
   148
    idereg.device = 0x00;
nkeynes@152
   149
    idereg.state = IDE_STATE_IDLE;
nkeynes@152
   150
    memset( idereg.gdrom_sense, '\0', 10 );
nkeynes@493
   151
    memcpy( idereg.gdrom_mode, default_gdrom_mode, GDROM_MODE_LENGTH );
nkeynes@152
   152
    idereg.data_offset = -1;
nkeynes@152
   153
    idereg.data_length = -1;
nkeynes@245
   154
    idereg.last_read_track = 1;
nkeynes@493
   155
    idereg.current_lba = 150;
nkeynes@493
   156
    idereg.current_mode = 0x28;
nkeynes@342
   157
    idereg.sectors_left = 0;
nkeynes@254
   158
    idereg.was_reset = TRUE;
nkeynes@138
   159
}
nkeynes@138
   160
nkeynes@342
   161
static uint32_t ide_run_slice( uint32_t nanosecs )
nkeynes@342
   162
{
nkeynes@342
   163
    if( gdrom_disc != NULL && gdrom_disc->run_time_slice != NULL ) {
nkeynes@736
   164
        gdrom_disc->run_time_slice(gdrom_disc, nanosecs);
nkeynes@342
   165
    }
nkeynes@342
   166
    return nanosecs;
nkeynes@342
   167
}
nkeynes@342
   168
nkeynes@138
   169
static void ide_save_state( FILE *f )
nkeynes@138
   170
{
nkeynes@152
   171
    fwrite( &idereg, sizeof(idereg), 1, f );
nkeynes@342
   172
    fwrite( data_buffer, MAX_SECTOR_SIZE, 1, f );
nkeynes@138
   173
}
nkeynes@138
   174
nkeynes@138
   175
static int ide_load_state( FILE *f )
nkeynes@138
   176
{
nkeynes@1023
   177
    if( fread( &idereg, sizeof(idereg), 1, f ) != 1 ||
nkeynes@1023
   178
        fread( data_buffer, MAX_SECTOR_SIZE, 1, f ) != 1 ) {
nkeynes@1023
   179
        return -1;
nkeynes@1023
   180
    }
nkeynes@138
   181
    return 0;
nkeynes@138
   182
}
nkeynes@125
   183
nkeynes@152
   184
/************************ State transitions *************************/
nkeynes@152
   185
nkeynes@158
   186
void ide_set_packet_result( uint16_t result )
nkeynes@158
   187
{
nkeynes@158
   188
    idereg.gdrom_sense[0] = 0xf0;
nkeynes@158
   189
    idereg.gdrom_sense[2] = result & 0xFF;
nkeynes@158
   190
    idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
nkeynes@158
   191
    idereg.error = (result & 0x0F) << 4;
nkeynes@254
   192
    idereg.count = 3;
nkeynes@158
   193
    if( result != 0 ) {
nkeynes@736
   194
        idereg.status = 0x51;
nkeynes@736
   195
        idereg.state = IDE_STATE_IDLE;
nkeynes@736
   196
        ide_raise_interrupt();
nkeynes@158
   197
    } else {
nkeynes@736
   198
        idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
nkeynes@158
   199
    }
nkeynes@158
   200
}
nkeynes@158
   201
nkeynes@152
   202
/**
nkeynes@152
   203
 * Begin command packet write to the device. This is always 12 bytes of PIO data
nkeynes@152
   204
 */
nkeynes@152
   205
static void ide_start_command_packet_write( )
nkeynes@2
   206
{
nkeynes@152
   207
    idereg.state = IDE_STATE_CMD_WRITE;
nkeynes@254
   208
    idereg.status = 0x58;
nkeynes@152
   209
    idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
nkeynes@152
   210
    idereg.count = IDE_COUNT_CD;
nkeynes@152
   211
    idereg.data_offset = 0;
nkeynes@152
   212
    idereg.data_length = 12;
nkeynes@2
   213
}
nkeynes@2
   214
nkeynes@152
   215
/**
nkeynes@493
   216
 * Begin PIO/DMA read from the device. The data is assumed to already be
nkeynes@152
   217
 * in the buffer at this point.
nkeynes@152
   218
 */
nkeynes@342
   219
static void ide_start_read( int length, gboolean dma ) 
nkeynes@2
   220
{
nkeynes@152
   221
    idereg.count = IDE_COUNT_IO;
nkeynes@152
   222
    idereg.data_length = length;
nkeynes@152
   223
    idereg.data_offset = 0;
nkeynes@152
   224
    if( dma ) {
nkeynes@736
   225
        idereg.state = IDE_STATE_DMA_READ;
nkeynes@736
   226
        idereg.status = 0xD0;
nkeynes@152
   227
    } else {
nkeynes@736
   228
        idereg.state = IDE_STATE_PIO_READ;
nkeynes@736
   229
        idereg.status = 0x58;
nkeynes@736
   230
        idereg.lba1 = length & 0xFF;
nkeynes@736
   231
        idereg.lba2 = length >> 8; 
nkeynes@736
   232
        ide_raise_interrupt( );
nkeynes@152
   233
    }
nkeynes@152
   234
}
nkeynes@152
   235
nkeynes@493
   236
static void ide_start_write( int length, gboolean dma )
nkeynes@493
   237
{
nkeynes@493
   238
    idereg.count = 0;
nkeynes@493
   239
    idereg.data_length = length;
nkeynes@493
   240
    idereg.data_offset = 0;
nkeynes@493
   241
    if( dma ) {
nkeynes@736
   242
        idereg.state = IDE_STATE_DMA_WRITE;
nkeynes@736
   243
        idereg.status = 0xD0;
nkeynes@493
   244
    }  else {
nkeynes@736
   245
        idereg.state = IDE_STATE_PIO_WRITE;
nkeynes@736
   246
        idereg.status = 0x58;
nkeynes@736
   247
        idereg.lba1 = length & 0xFF;
nkeynes@736
   248
        idereg.lba2 = length >> 8;
nkeynes@736
   249
        ide_raise_interrupt( );
nkeynes@493
   250
    }
nkeynes@493
   251
}
nkeynes@493
   252
nkeynes@342
   253
static void ide_start_packet_read( int length, int sector_count )
nkeynes@152
   254
{
nkeynes@342
   255
    idereg.sectors_left = sector_count;
nkeynes@158
   256
    ide_set_packet_result( PKT_ERR_OK );
nkeynes@342
   257
    ide_start_read( length, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
nkeynes@2
   258
}
nkeynes@2
   259
nkeynes@493
   260
static void ide_start_packet_write( int length, int sector_count )
nkeynes@493
   261
{
nkeynes@493
   262
    idereg.sectors_left = sector_count;
nkeynes@493
   263
    ide_set_packet_result( PKT_ERR_OK );
nkeynes@493
   264
    ide_start_write( length, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
nkeynes@493
   265
}
nkeynes@493
   266
nkeynes@125
   267
static void ide_raise_interrupt( void )
nkeynes@2
   268
{
nkeynes@125
   269
    if( idereg.intrq_pending == 0 ) {
nkeynes@736
   270
        idereg.intrq_pending = 1;
nkeynes@736
   271
        if( IS_IDE_IRQ_ENABLED() )
nkeynes@736
   272
            asic_event( EVENT_IDE );
nkeynes@125
   273
    }
nkeynes@125
   274
}
nkeynes@125
   275
nkeynes@125
   276
static void ide_clear_interrupt( void ) 
nkeynes@125
   277
{
nkeynes@125
   278
    if( idereg.intrq_pending != 0 ) {
nkeynes@736
   279
        idereg.intrq_pending = 0;
nkeynes@736
   280
        if( IS_IDE_IRQ_ENABLED() )
nkeynes@736
   281
            asic_clear_event( EVENT_IDE );
nkeynes@125
   282
    }
nkeynes@125
   283
}
nkeynes@125
   284
nkeynes@125
   285
static void ide_set_error( int error_code )
nkeynes@125
   286
{
nkeynes@125
   287
    idereg.status = 0x51;
nkeynes@125
   288
    idereg.error = error_code;
nkeynes@2
   289
}
nkeynes@2
   290
nkeynes@125
   291
uint8_t ide_read_status( void ) 
nkeynes@125
   292
{
nkeynes@152
   293
    if( (idereg.status & IDE_STATUS_BSY) == 0 )
nkeynes@736
   294
        ide_clear_interrupt();
nkeynes@125
   295
    return idereg.status;
nkeynes@2
   296
}
nkeynes@2
   297
nkeynes@2
   298
uint16_t ide_read_data_pio( void ) {
nkeynes@152
   299
    if( idereg.state == IDE_STATE_PIO_READ ) {
nkeynes@736
   300
        uint16_t rv = READ_BUFFER();
nkeynes@736
   301
        idereg.data_offset += 2;
nkeynes@736
   302
        if( idereg.data_offset >= idereg.data_length ) {
nkeynes@736
   303
            idereg.state = IDE_STATE_IDLE;
nkeynes@736
   304
            idereg.status &= ~IDE_STATUS_DRQ;
nkeynes@736
   305
            idereg.data_offset = -1;
nkeynes@736
   306
            idereg.count = 3; /* complete */
nkeynes@736
   307
            ide_raise_interrupt();
nkeynes@736
   308
            if( idereg.sectors_left > 0 ) {
nkeynes@736
   309
                ide_read_next_sector();
nkeynes@736
   310
            }
nkeynes@736
   311
        }
nkeynes@736
   312
        return rv;
nkeynes@152
   313
    } else {
nkeynes@2
   314
        return 0xFFFF;
nkeynes@2
   315
    }
nkeynes@2
   316
}
nkeynes@2
   317
nkeynes@152
   318
nkeynes@152
   319
/**
nkeynes@152
   320
 * DMA read request
nkeynes@152
   321
 *
nkeynes@152
   322
 * This method is called from the ASIC side when a DMA read request is
nkeynes@152
   323
 * initiated. If there is a pending DMA transfer already, we copy the
nkeynes@152
   324
 * data immediately, otherwise we record the DMA buffer for use when we
nkeynes@152
   325
 * get to actually doing the transfer.
nkeynes@152
   326
 * @return number of bytes transfered
nkeynes@152
   327
 */
nkeynes@152
   328
uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
nkeynes@152
   329
{
nkeynes@342
   330
    uint32_t xfercount = 0;
nkeynes@629
   331
    while( xfercount < length && idereg.state == IDE_STATE_DMA_READ ) {
nkeynes@736
   332
        int xferlen = length - xfercount;
nkeynes@736
   333
        int remaining = idereg.data_length - idereg.data_offset;
nkeynes@736
   334
        if( xferlen > remaining ) {
nkeynes@736
   335
            xferlen = remaining;
nkeynes@736
   336
        }
nkeynes@736
   337
        mem_copy_to_sh4( addr, (data_buffer + idereg.data_offset), xferlen );
nkeynes@736
   338
        xfercount += xferlen;
nkeynes@736
   339
        addr += xferlen;
nkeynes@736
   340
        idereg.data_offset += xferlen;
nkeynes@736
   341
        if( idereg.data_offset >= idereg.data_length ) {
nkeynes@736
   342
            if( idereg.sectors_left > 0 ) {
nkeynes@736
   343
                ide_read_next_sector();
nkeynes@736
   344
            } else {
nkeynes@736
   345
                idereg.data_offset = -1;
nkeynes@736
   346
                idereg.state = IDE_STATE_IDLE;
nkeynes@736
   347
                idereg.status = 0x50;
nkeynes@736
   348
                idereg.count = 0x03;
nkeynes@736
   349
                ide_raise_interrupt();
nkeynes@736
   350
                break;
nkeynes@736
   351
            }
nkeynes@736
   352
        }
nkeynes@152
   353
    }
nkeynes@342
   354
    return xfercount;
nkeynes@152
   355
}
nkeynes@152
   356
nkeynes@2
   357
void ide_write_data_pio( uint16_t val ) {
nkeynes@152
   358
    if( idereg.state == IDE_STATE_CMD_WRITE ) {
nkeynes@736
   359
        WRITE_BUFFER(val);
nkeynes@736
   360
        idereg.data_offset+=2;
nkeynes@736
   361
        if( idereg.data_offset >= idereg.data_length ) {
nkeynes@736
   362
            idereg.state = IDE_STATE_BUSY;
nkeynes@736
   363
            idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
nkeynes@736
   364
            idereg.data_offset = -1;
nkeynes@736
   365
            ide_packet_command(data_buffer);
nkeynes@736
   366
        }
nkeynes@152
   367
    } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
nkeynes@736
   368
        WRITE_BUFFER(val);
nkeynes@736
   369
        idereg.data_offset +=2;
nkeynes@736
   370
        if( idereg.data_offset >= idereg.data_length ) {
nkeynes@736
   371
            idereg.state = IDE_STATE_IDLE;
nkeynes@736
   372
            idereg.status &= ~IDE_STATUS_DRQ;
nkeynes@736
   373
            idereg.data_offset = -1;
nkeynes@736
   374
            idereg.count = 3; /* complete */
nkeynes@736
   375
            ide_raise_interrupt();
nkeynes@736
   376
            ide_write_buffer( data_buffer, idereg.data_length );
nkeynes@736
   377
        }
nkeynes@2
   378
    }
nkeynes@2
   379
}
nkeynes@2
   380
nkeynes@2
   381
void ide_write_control( uint8_t val ) {
nkeynes@125
   382
    if( IS_IDE_IRQ_ENABLED() ) {
nkeynes@736
   383
        if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
nkeynes@736
   384
            asic_clear_event( EVENT_IDE );
nkeynes@125
   385
    } else {
nkeynes@736
   386
        if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
nkeynes@736
   387
            asic_event( EVENT_IDE );
nkeynes@125
   388
    }
nkeynes@125
   389
    idereg.control = val;
nkeynes@2
   390
}
nkeynes@2
   391
nkeynes@2
   392
void ide_write_command( uint8_t val ) {
nkeynes@125
   393
    ide_clear_interrupt();
nkeynes@2
   394
    idereg.command = val;
nkeynes@2
   395
    switch( val ) {
nkeynes@240
   396
    case IDE_CMD_NOP: /* Effectively an "abort" */
nkeynes@736
   397
        idereg.state = IDE_STATE_IDLE;
nkeynes@736
   398
        idereg.status = 0x51;
nkeynes@736
   399
        idereg.error = 0x04;
nkeynes@736
   400
        idereg.data_offset = -1;
nkeynes@736
   401
        ide_raise_interrupt();
nkeynes@736
   402
        return;
nkeynes@39
   403
    case IDE_CMD_RESET_DEVICE:
nkeynes@736
   404
        ide_reset();
nkeynes@736
   405
        break;
nkeynes@39
   406
    case IDE_CMD_PACKET:
nkeynes@736
   407
        ide_start_command_packet_write();
nkeynes@736
   408
        break;
nkeynes@39
   409
    case IDE_CMD_SET_FEATURE:
nkeynes@736
   410
        switch( idereg.feature ) {
nkeynes@736
   411
        case IDE_FEAT_SET_TRANSFER_MODE:
nkeynes@736
   412
            switch( idereg.count & 0xF8 ) {
nkeynes@736
   413
            case IDE_XFER_PIO:
nkeynes@1075
   414
                DEBUG( "Set PIO default mode: %d", idereg.count&0x07 );
nkeynes@736
   415
                break;
nkeynes@736
   416
            case IDE_XFER_PIO_FLOW:
nkeynes@1075
   417
                DEBUG( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
nkeynes@736
   418
                break;
nkeynes@736
   419
            case IDE_XFER_MULTI_DMA:
nkeynes@1075
   420
                DEBUG( "Set Multiword DMA mode: %d", idereg.count&0x07 );
nkeynes@736
   421
                break;
nkeynes@736
   422
            case IDE_XFER_ULTRA_DMA:
nkeynes@1075
   423
                DEBUG( "Set Ultra DMA mode: %d", idereg.count&0x07 );
nkeynes@736
   424
                break;
nkeynes@736
   425
            default:
nkeynes@1075
   426
                DEBUG( "Setting unknown transfer mode: %02X", idereg.count );
nkeynes@736
   427
                break;
nkeynes@736
   428
            }
nkeynes@736
   429
            break;
nkeynes@736
   430
            default:
nkeynes@1075
   431
                DEBUG( "IDE: unimplemented feature: %02X", idereg.feature );
nkeynes@736
   432
        }
nkeynes@736
   433
        idereg.status = 0x50;
nkeynes@736
   434
        idereg.error = 0x00;
nkeynes@736
   435
        idereg.lba1 = 0x00;
nkeynes@736
   436
        idereg.lba2 = 0x00;
nkeynes@736
   437
        ide_raise_interrupt();
nkeynes@736
   438
        break;
nkeynes@736
   439
        default:
nkeynes@1075
   440
            DEBUG( "IDE: Unimplemented command: %02X", val );
nkeynes@2
   441
    }
nkeynes@2
   442
}
nkeynes@2
   443
nkeynes@342
   444
uint8_t ide_get_drive_status( void )
nkeynes@342
   445
{
nkeynes@1023
   446
    return gdrom_disc_get_drive_status(gdrom_disc);
nkeynes@342
   447
}
nkeynes@342
   448
nkeynes@1023
   449
#define REQUIRE_DISC() if( gdrom_disc == NULL || gdrom_disc->disc_type == IDE_DISC_NONE  ) { ide_set_packet_result( PKT_ERR_NODISC ); return; }
nkeynes@342
   450
nkeynes@342
   451
/**
nkeynes@342
   452
 * Read the next sector from the active read, if any
nkeynes@342
   453
 */
nkeynes@342
   454
static void ide_read_next_sector( void )
nkeynes@342
   455
{
nkeynes@422
   456
    uint32_t sector_size;
nkeynes@342
   457
    REQUIRE_DISC();
nkeynes@342
   458
    gdrom_error_t status = 
nkeynes@736
   459
        gdrom_disc->read_sector( gdrom_disc, idereg.current_lba, idereg.current_mode, 
nkeynes@736
   460
                data_buffer, &sector_size );
nkeynes@342
   461
    if( status != PKT_ERR_OK ) {
nkeynes@736
   462
        ide_set_packet_result( status );
nkeynes@736
   463
        idereg.gdrom_sense[5] = (idereg.current_lba >> 16) & 0xFF;
nkeynes@736
   464
        idereg.gdrom_sense[6] = (idereg.current_lba >> 8) & 0xFF;
nkeynes@736
   465
        idereg.gdrom_sense[7] = idereg.current_lba & 0xFF;
nkeynes@736
   466
        WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );
nkeynes@342
   467
    } else {
nkeynes@736
   468
        idereg.current_lba++;
nkeynes@736
   469
        idereg.sectors_left--;
nkeynes@736
   470
        ide_start_read( sector_size, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
nkeynes@342
   471
    }
nkeynes@342
   472
}
nkeynes@342
   473
nkeynes@142
   474
/**
nkeynes@142
   475
 * Execute a packet command. This particular method is responsible for parsing
nkeynes@142
   476
 * the command buffers (12 bytes), and generating the appropriate responses, 
nkeynes@142
   477
 * although the actual implementation is mostly delegated to gdrom.c
nkeynes@142
   478
 */
nkeynes@125
   479
void ide_packet_command( unsigned char *cmd )
nkeynes@125
   480
{
nkeynes@422
   481
    uint32_t length;
nkeynes@143
   482
    uint32_t lba, status;
nkeynes@125
   483
nkeynes@125
   484
    /* Okay we have the packet in the command buffer */
nkeynes@1075
   485
    DEBUG( "ATAPI packet: %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X", 
nkeynes@736
   486
          cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
nkeynes@736
   487
          cmd[8], cmd[9], cmd[10], cmd[11] );
nkeynes@254
   488
nkeynes@254
   489
    if( cmd[0] != PKT_CMD_SENSE && idereg.was_reset ) {
nkeynes@736
   490
        ide_set_packet_result( PKT_ERR_RESET );
nkeynes@736
   491
        idereg.was_reset = FALSE;
nkeynes@736
   492
        return;
nkeynes@254
   493
    }
nkeynes@254
   494
nkeynes@125
   495
    switch( cmd[0] ) {
nkeynes@142
   496
    case PKT_CMD_TEST_READY:
nkeynes@736
   497
        REQUIRE_DISC();
nkeynes@736
   498
        ide_set_packet_result( 0 );
nkeynes@736
   499
        ide_raise_interrupt();
nkeynes@736
   500
        idereg.status = 0x50;
nkeynes@736
   501
        break;
nkeynes@858
   502
    case PKT_CMD_DRIVE_STATUS:
nkeynes@858
   503
        lba = cmd[2];
nkeynes@858
   504
        if( lba >= GDROM_DRIVE_STATUS_LENGTH ) {
nkeynes@858
   505
            ide_set_error(PKT_ERR_BADFIELD);
nkeynes@858
   506
        } else {
nkeynes@858
   507
            uint8_t status = ide_get_drive_status();
nkeynes@858
   508
            /* FIXME: Refactor read_position to avoid this kind of crud */
nkeynes@888
   509
            unsigned char tmp[16];
nkeynes@1023
   510
            gdrom_disc_get_short_status( gdrom_disc, idereg.current_lba, tmp );
nkeynes@858
   511
            
nkeynes@858
   512
            length = cmd[4];
nkeynes@858
   513
            if( lba+length > GDROM_DRIVE_STATUS_LENGTH )
nkeynes@858
   514
                length = GDROM_DRIVE_STATUS_LENGTH - lba;
nkeynes@858
   515
            char data[10];
nkeynes@858
   516
            data[0] = status & 0x0F;
nkeynes@858
   517
            data[1] = status & 0xF0;
nkeynes@858
   518
            data[2] = tmp[4];
nkeynes@858
   519
            data[3] = tmp[5];
nkeynes@858
   520
            data[4] = tmp[6];
nkeynes@858
   521
            data[5] = tmp[11];
nkeynes@858
   522
            data[6] = tmp[12];
nkeynes@858
   523
            data[7] = tmp[13];
nkeynes@858
   524
            data[8] = 0;
nkeynes@858
   525
            data[9] = 0;
nkeynes@858
   526
            memcpy( data_buffer, data + lba, length );
nkeynes@858
   527
            ide_start_packet_read( length, 0 );
nkeynes@858
   528
        }
nkeynes@858
   529
        break;
nkeynes@493
   530
    case PKT_CMD_MODE_SENSE:
nkeynes@736
   531
        lba = cmd[2];
nkeynes@736
   532
        if( lba >= GDROM_MODE_LENGTH ) {
nkeynes@736
   533
            ide_set_error(PKT_ERR_BADFIELD);
nkeynes@736
   534
        } else {
nkeynes@736
   535
            length = cmd[4];
nkeynes@736
   536
            if( lba+length > GDROM_MODE_LENGTH )
nkeynes@736
   537
                length = GDROM_MODE_LENGTH - lba;
nkeynes@736
   538
            memcpy( data_buffer, idereg.gdrom_mode + lba, length );
nkeynes@736
   539
            ide_start_packet_read( length, 0 );
nkeynes@736
   540
        }
nkeynes@736
   541
        break;
nkeynes@493
   542
    case PKT_CMD_MODE_SELECT:
nkeynes@736
   543
        lba = cmd[2];
nkeynes@736
   544
        if( lba >= GDROM_MODE_LENGTH ) {
nkeynes@736
   545
            ide_set_error(PKT_ERR_BADFIELD);
nkeynes@736
   546
        } else {
nkeynes@736
   547
            length = cmd[4];
nkeynes@736
   548
            if( lba+length > GDROM_MODE_LENGTH )
nkeynes@736
   549
                length = GDROM_MODE_LENGTH - lba;
nkeynes@736
   550
            idereg.current_lba = lba;
nkeynes@736
   551
            ide_start_packet_write( length, 0 );
nkeynes@736
   552
        }
nkeynes@736
   553
        break;
nkeynes@142
   554
    case PKT_CMD_SENSE:
nkeynes@736
   555
        length = cmd[4];
nkeynes@736
   556
        if( length > 10 )
nkeynes@736
   557
            length = 10;
nkeynes@736
   558
        memcpy( data_buffer, idereg.gdrom_sense, length );
nkeynes@736
   559
        ide_start_packet_read( length, 0 );
nkeynes@736
   560
        break;
nkeynes@125
   561
    case PKT_CMD_READ_TOC:
nkeynes@736
   562
        REQUIRE_DISC();
nkeynes@736
   563
        length = (cmd[3]<<8) | cmd[4];
nkeynes@1023
   564
        if( length > GDROM_TOC_SIZE )
nkeynes@1023
   565
            length = GDROM_TOC_SIZE;
nkeynes@152
   566
nkeynes@1023
   567
        status = gdrom_disc_get_toc( gdrom_disc, data_buffer );
nkeynes@736
   568
        if( status != PKT_ERR_OK ) {
nkeynes@736
   569
            ide_set_packet_result( status );
nkeynes@736
   570
        } else {
nkeynes@736
   571
            ide_start_packet_read( length, 0 );
nkeynes@736
   572
        }
nkeynes@736
   573
        break;
nkeynes@158
   574
    case PKT_CMD_SESSION_INFO:
nkeynes@736
   575
        REQUIRE_DISC();
nkeynes@736
   576
        length = cmd[4];
nkeynes@736
   577
        if( length > 6 )
nkeynes@736
   578
            length = 6;
nkeynes@1023
   579
        status = gdrom_disc_get_session_info( gdrom_disc, cmd[2], data_buffer );
nkeynes@736
   580
        if( status != PKT_ERR_OK ) {
nkeynes@736
   581
            ide_set_packet_result( status );
nkeynes@736
   582
        } else {
nkeynes@736
   583
            ide_start_packet_read( length, 0 );
nkeynes@736
   584
        }
nkeynes@736
   585
        break;
nkeynes@342
   586
    case PKT_CMD_PLAY_AUDIO:
nkeynes@736
   587
        REQUIRE_DISC();
nkeynes@736
   588
        ide_set_packet_result( 0 );
nkeynes@736
   589
        ide_raise_interrupt();
nkeynes@736
   590
        idereg.status = 0x50;
nkeynes@736
   591
        break;
nkeynes@125
   592
    case PKT_CMD_READ_SECTOR:
nkeynes@736
   593
        REQUIRE_DISC();
nkeynes@736
   594
        idereg.current_lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
nkeynes@736
   595
        idereg.sectors_left = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
nkeynes@736
   596
        idereg.current_mode = cmd[1];
nkeynes@736
   597
        ide_read_next_sector();
nkeynes@736
   598
        break;
nkeynes@149
   599
    case PKT_CMD_SPIN_UP:
nkeynes@736
   600
        REQUIRE_DISC();
nkeynes@736
   601
        /* do nothing? */
nkeynes@736
   602
        ide_set_packet_result( PKT_ERR_OK );
nkeynes@736
   603
        ide_raise_interrupt();
nkeynes@736
   604
        break;
nkeynes@245
   605
    case PKT_CMD_STATUS:
nkeynes@736
   606
        REQUIRE_DISC();
nkeynes@736
   607
        length = cmd[4];
nkeynes@736
   608
        switch( cmd[1] ) {
nkeynes@736
   609
        case 0:
nkeynes@736
   610
            if( length > sizeof(gdrom_status) ) {
nkeynes@736
   611
                length = sizeof(gdrom_status);
nkeynes@736
   612
            }
nkeynes@736
   613
            memcpy( data_buffer, gdrom_status, length );
nkeynes@736
   614
            ide_start_packet_read( length, 0 );
nkeynes@736
   615
            break;
nkeynes@736
   616
        case 1:
nkeynes@736
   617
            if( length > 14 ) {
nkeynes@736
   618
                length = 14;
nkeynes@736
   619
            }
nkeynes@1023
   620
            gdrom_disc_get_short_status( gdrom_disc, idereg.current_lba, data_buffer );
nkeynes@736
   621
            ide_start_packet_read( length, 0 );
nkeynes@736
   622
            break;
nkeynes@736
   623
        }
nkeynes@736
   624
        break;
nkeynes@736
   625
        case PKT_CMD_71:
nkeynes@736
   626
            /* This is a weird one. As far as I can tell it returns random garbage
nkeynes@736
   627
             * (and not even the same length each time, never mind the same data).
nkeynes@736
   628
             * For sake of something to do, it returns the results from a test dump
nkeynes@736
   629
             */
nkeynes@736
   630
            REQUIRE_DISC();
nkeynes@736
   631
            memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
nkeynes@736
   632
            ide_start_packet_read( sizeof(gdrom_71), 0 );
nkeynes@736
   633
            break;
nkeynes@736
   634
        default:
nkeynes@736
   635
            ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
nkeynes@736
   636
            return;
nkeynes@125
   637
    }
nkeynes@493
   638
    idereg.last_packet_command = cmd[0];
nkeynes@125
   639
}
nkeynes@493
   640
nkeynes@493
   641
void ide_write_buffer( unsigned char *data, uint32_t length )
nkeynes@493
   642
{
nkeynes@493
   643
    switch( idereg.last_packet_command ) {
nkeynes@493
   644
    case PKT_CMD_MODE_SELECT:
nkeynes@736
   645
        if( idereg.current_lba < 10 ) {
nkeynes@736
   646
            if( idereg.current_lba + length > 10 ) {
nkeynes@736
   647
                length = 10 - idereg.current_lba;
nkeynes@736
   648
            }
nkeynes@736
   649
            memcpy( idereg.gdrom_mode + idereg.current_lba, data, length );
nkeynes@736
   650
        }
nkeynes@736
   651
        break;
nkeynes@493
   652
    default:
nkeynes@736
   653
        WARN( "Don't know what to do with received data buffer for command %02X", idereg.last_packet_command );
nkeynes@493
   654
    }
nkeynes@493
   655
}
.