nkeynes@31 | 1 | /**
|
nkeynes@258 | 2 | * $Id: ide.c,v 1.22 2006-12-29 00:23:13 nkeynes Exp $
|
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@125 | 28 | #include "asic.h"
|
nkeynes@39 | 29 | #include "gdrom/ide.h"
|
nkeynes@125 | 30 | #include "gdrom/gdrom.h"
|
nkeynes@142 | 31 | #include "gdrom/packet.h"
|
nkeynes@2 | 32 |
|
nkeynes@138 | 33 | #define MAX_WRITE_BUF 4096
|
nkeynes@138 | 34 | #define MAX_SECTOR_SIZE 2352 /* Audio sector */
|
nkeynes@138 | 35 | #define DEFAULT_DATA_SECTORS 8
|
nkeynes@2 | 36 |
|
nkeynes@138 | 37 | static void ide_init( void );
|
nkeynes@138 | 38 | static void ide_reset( void );
|
nkeynes@138 | 39 | static void ide_save_state( FILE *f );
|
nkeynes@138 | 40 | static int ide_load_state( FILE *f );
|
nkeynes@138 | 41 | static void ide_raise_interrupt( void );
|
nkeynes@138 | 42 | static void ide_clear_interrupt( void );
|
nkeynes@152 | 43 | static void ide_packet_command( unsigned char *data );
|
nkeynes@15 | 44 |
|
nkeynes@15 | 45 | struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, NULL,
|
nkeynes@138 | 46 | NULL, ide_save_state, ide_load_state };
|
nkeynes@15 | 47 |
|
nkeynes@2 | 48 | struct ide_registers idereg;
|
nkeynes@138 | 49 | unsigned char *data_buffer = NULL;
|
nkeynes@138 | 50 | uint32_t data_buffer_len = 0;
|
nkeynes@2 | 51 |
|
nkeynes@152 | 52 | #define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
|
nkeynes@152 | 53 | #define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))
|
nkeynes@152 | 54 |
|
nkeynes@2 | 55 | /* "\0\0\0\0\xb4\x19\0\0\x08SE REV 6.42990316" */
|
nkeynes@125 | 56 | unsigned char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
|
nkeynes@2 | 57 | 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
|
nkeynes@2 | 58 | 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
|
nkeynes@2 | 59 | 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
|
nkeynes@2 | 60 |
|
nkeynes@158 | 61 | unsigned char gdrom_71[] = { 0x3E, 0x0F, 0x90, 0xBE, 0x1D, 0xD9, 0x89, 0x04, 0x28, 0x3A, 0x8E, 0x26, 0x5C, 0x95, 0x10, 0x5A,
|
nkeynes@158 | 62 | 0x0A, 0x99, 0xEE, 0xFB, 0x69, 0xCE, 0xD9, 0x63, 0x00, 0xF5, 0x0A, 0xBC, 0x2C, 0x0D, 0xF8, 0xE2,
|
nkeynes@158 | 63 | 0x05, 0x02, 0x00, 0x7C, 0x03, 0x00, 0x3D, 0x08, 0xD8, 0x8D, 0x08, 0x7A, 0x6D, 0x00, 0x35, 0x06,
|
nkeynes@158 | 64 | 0xBA, 0x66, 0x10, 0x00, 0x91, 0x08, 0x10, 0x29, 0xD0, 0x45, 0xDA, 0x00, 0x2D, 0x05, 0x69, 0x09,
|
nkeynes@158 | 65 | 0x00, 0x5E, 0x0F, 0x70, 0x86, 0x12, 0x6C, 0x77, 0x5A, 0xFB, 0xCD, 0x56, 0xFB, 0xF7, 0xB7, 0x00,
|
nkeynes@158 | 66 | 0x5D, 0x07, 0x19, 0x99, 0xF2, 0xAF, 0x00, 0x63, 0x03, 0x00, 0xF0, 0x10, 0xBE, 0xD7, 0xA0, 0x63,
|
nkeynes@158 | 67 | 0xFA, 0x84, 0xA7, 0x74, 0x94, 0xEF, 0xAD, 0xC2, 0xAC, 0x00, 0x78, 0x07, 0x9F, 0x57, 0x0B, 0x62,
|
nkeynes@158 | 68 | 0x00, 0xFE, 0x08, 0x08, 0x5D, 0x5A, 0x6A, 0x54, 0x00, 0xE2, 0x09, 0x93, 0x7E, 0x62, 0x2A, 0x5E,
|
nkeynes@158 | 69 | 0xDA, 0x00, 0x7E, 0x0F, 0xF0, 0x07, 0x01, 0x6D, 0x50, 0x86, 0xDD, 0x4A, 0x15, 0x54, 0xC7, 0xEC,
|
nkeynes@158 | 70 | 0x00, 0xF2, 0x0B, 0x07, 0xF8, 0x1A, 0xB0, 0x99, 0x3B, 0xF1, 0x36, 0x00, 0x94, 0x07, 0x34, 0xE3,
|
nkeynes@158 | 71 | 0xBC, 0x6E, 0x00, 0x34, 0x0D, 0x6F, 0xDA, 0xBD, 0xEE, 0xF7, 0xCC, 0xCE, 0x39, 0x7E, 0xE3, 0x00,
|
nkeynes@158 | 72 | 0x14, 0x08, 0xDC, 0xD2, 0xB9, 0xF9, 0x31, 0x00, 0xB0, 0x0C, 0x10, 0xA3, 0x45, 0x12, 0xC7, 0xCD,
|
nkeynes@158 | 73 | 0xBF, 0x05, 0x37, 0x00, 0xC4, 0x0D, 0x5F, 0xE0, 0x59, 0xBB, 0x01, 0x59, 0x03, 0xD6, 0x29, 0x9C,
|
nkeynes@158 | 74 | 0x00, 0x01, 0x0A, 0x09, 0xAA, 0xA8, 0xA8, 0x24, 0x0B, 0x66, 0x00, 0x5C, 0x05, 0xA5, 0xCE, 0x00,
|
nkeynes@158 | 75 | 0xC1, 0x0B, 0xB7, 0xA0, 0x6F, 0xE9, 0x2B, 0xCC, 0xB5, 0xFC, 0x00, 0x8D, 0x05, 0xF4, 0xAC, 0x00,
|
nkeynes@158 | 76 | 0x57, 0x04, 0xB6, 0x00, 0xFC, 0x03, 0x00, 0xC3, 0x10, 0x43, 0x3B, 0xBE, 0xA2, 0x96, 0xC3, 0x65,
|
nkeynes@158 | 77 | 0x9F, 0x9A, 0x88, 0xD5, 0x49, 0x68, 0x00, 0xDC, 0x11, 0x56, 0x23, 0x2D, 0xF9, 0xFC, 0xF5, 0x8B,
|
nkeynes@158 | 78 | 0x1B, 0xB1, 0xB7, 0x10, 0x21, 0x1C, 0x12, 0x00, 0x0D, 0x0D, 0xEB, 0x86, 0xA2, 0x49, 0x8D, 0x8D,
|
nkeynes@158 | 79 | 0xBE, 0xA1, 0x6D, 0x53, 0x00, 0xE1, 0x0A, 0x8E, 0x67, 0xAA, 0x16, 0x79, 0x39, 0x59, 0x00, 0x36,
|
nkeynes@158 | 80 | 0x0B, 0x2A, 0x4E, 0xAE, 0x51, 0x4B, 0xD0, 0x66, 0x33, 0x00, 0x8A, 0x07, 0xCD, 0x6F, 0xBA, 0x92,
|
nkeynes@158 | 81 | 0x00, 0x1A, 0x0E, 0xDF, 0x4A, 0xB3, 0x77, 0x1F, 0xA5, 0x90, 0x19, 0xFA, 0x59, 0xD7, 0x00, 0x04,
|
nkeynes@158 | 82 | 0x0F, 0xAC, 0xCA, 0x9F, 0xA4, 0xFC, 0x6D, 0x90, 0x86, 0x9E, 0x1F, 0x44, 0x40, 0x00, 0x9F, 0x04,
|
nkeynes@158 | 83 | 0x56, 0x00, 0x22, 0x03, 0x00, 0xB8, 0x10, 0x2C, 0x7A, 0x53, 0xA4, 0xBF, 0xA3, 0x90, 0x90, 0x14,
|
nkeynes@158 | 84 | 0x9D, 0x46, 0x6C, 0x96, 0x00, 0xC6, 0x0B, 0x9B, 0xBB, 0xB0, 0xAE, 0x60, 0x92, 0x8E, 0x0C, 0x00,
|
nkeynes@158 | 85 | 0x14, 0x06, 0x4B, 0xAE, 0x7F, 0x00, 0x5C, 0x0B, 0x23, 0xFA, 0xE7, 0x51, 0xDA, 0x61, 0x49, 0x5E,
|
nkeynes@158 | 86 | 0x00, 0xD7, 0x0B, 0x01, 0xFC, 0x55, 0x31, 0x84, 0xC5, 0x0C, 0x98, 0x00, 0x97, 0x50, 0x6E, 0xF9,
|
nkeynes@158 | 87 | 0xEE, 0x75, 0x92, 0x53, 0xD3, 0x66, 0xA4, 0xAF, 0x3B, 0xFE, 0x7B, 0x27, 0x30, 0xBB, 0xB6, 0xF2,
|
nkeynes@158 | 88 | 0x76, 0x22, 0x45, 0x42, 0xCA, 0xF9, 0xF0, 0xDE, 0x9F, 0x45, 0x16, 0x68, 0x22, 0xB9, 0x84, 0x28,
|
nkeynes@158 | 89 | 0x8F, 0x2B, 0xB5, 0x5C, 0xD2, 0xF5, 0x45, 0x36, 0x3E, 0x76, 0xC6, 0xBF, 0x32, 0x5C, 0x41, 0xA6,
|
nkeynes@158 | 90 | 0x26, 0xC7, 0x82, 0x2F, 0x2E, 0xB5, 0x75, 0xC6, 0xE6, 0x67, 0x9E, 0x77, 0x94, 0xAF, 0x6A, 0x05,
|
nkeynes@158 | 91 | 0xC0, 0x05, 0x61, 0x71, 0x89, 0x5A, 0xB1, 0xD0, 0xFC, 0x7E, 0xC0, 0x9B, 0xCB, 0x3B, 0x69, 0xD9,
|
nkeynes@158 | 92 | 0x5F, 0xAF, 0xCA, 0xAB, 0x25, 0xD5, 0xBE, 0x8A, 0x6B, 0xB0, 0xFB, 0x61, 0x6C, 0xEB, 0x85, 0x6E,
|
nkeynes@158 | 93 | 0x7A, 0x48, 0xFF, 0x97, 0x91, 0x06, 0x3D, 0x4D, 0x68, 0xD3, 0x65, 0x83, 0x90, 0xA0, 0x08, 0x5C,
|
nkeynes@158 | 94 | 0xFC, 0xEE, 0x7C, 0x33, 0x43, 0x7F, 0x80, 0x52, 0x8B, 0x19, 0x72, 0xF2, 0xC9, 0xAB, 0x93, 0xAF,
|
nkeynes@158 | 95 | 0x16, 0xED, 0x36, 0x48, 0xAB, 0xC9, 0xD1, 0x03, 0xB3, 0xDC, 0x2F, 0xF2, 0x92, 0x3F, 0x0A, 0x19,
|
nkeynes@158 | 96 | 0x25, 0xE2, 0xEF, 0x7A, 0x22, 0xDA, 0xDB, 0xCB, 0x32, 0x12, 0x61, 0x49, 0x5B, 0x74, 0x7C, 0x65,
|
nkeynes@158 | 97 | 0x20, 0x89, 0x54, 0x9E, 0x0E, 0xC9, 0x52, 0xE3, 0xC9, 0x9A, 0x44, 0xC9, 0x5D, 0xA6, 0x77, 0xC0,
|
nkeynes@158 | 98 | 0xE7, 0x60, 0x91, 0x80, 0x50, 0x1F, 0x33, 0xB1, 0xCD, 0xAD, 0xF4, 0x0D, 0xBB, 0x08, 0xB1, 0xD0,
|
nkeynes@158 | 99 | 0x13, 0x95, 0xAE, 0xC9, 0xE2, 0x64, 0xA2, 0x65, 0xFB, 0x8F, 0xE9, 0xA2, 0x8A, 0xBC, 0x98, 0x81,
|
nkeynes@158 | 100 | 0x45, 0xB4, 0x55, 0x4E, 0xB9, 0x74, 0xB4, 0x50, 0x76, 0xBF, 0xF0, 0x45, 0xE7, 0xEE, 0x41, 0x64,
|
nkeynes@158 | 101 | 0x9F, 0xB5, 0xE0, 0xBB, 0x1C, 0xBB, 0x28, 0x66, 0x1B, 0xDD, 0x2B, 0x02, 0x66, 0xBF, 0xFD, 0x7D,
|
nkeynes@158 | 102 | 0x37, 0x35, 0x1D, 0x76, 0x21, 0xC3, 0x8F, 0xAF, 0xF6, 0xF9, 0xE9, 0x27, 0x48, 0xE7, 0x3D, 0x95,
|
nkeynes@158 | 103 | 0x74, 0x0C, 0x77, 0x88, 0x56, 0xD9, 0x84, 0xC8, 0x7D, 0x20, 0x31, 0x43, 0x53, 0xF1, 0xC1, 0xC7,
|
nkeynes@158 | 104 | 0xC9, 0xF7, 0x5C, 0xC0, 0xA6, 0x5A, 0x27, 0x0A, 0x41, 0xD4, 0x44, 0x94, 0x65, 0x4F, 0xE2, 0x53,
|
nkeynes@158 | 105 | 0x60, 0x0B, 0xD1, 0x23, 0x6C, 0x0C, 0xBC, 0x70, 0x6C, 0x26, 0x1A, 0x61, 0x1D, 0x35, 0x88, 0xEC,
|
nkeynes@158 | 106 | 0xB8, 0x15, 0xE3, 0xB4, 0x82, 0xEE, 0xB3, 0x21, 0xAC, 0x6C, 0xB7, 0x33, 0x6D, 0x78, 0x0C, 0x0D,
|
nkeynes@158 | 107 | 0xB4, 0x0B, 0x29, 0xF2, 0xD4, 0x8C, 0x3F, 0xDD, 0x3F, 0x47, 0xDD, 0xF2, 0xD8, 0x39, 0x57, 0x20,
|
nkeynes@158 | 108 | 0x28, 0xD8, 0xDD, 0x32, 0xE2, 0x6A, 0x47, 0x53, 0x57, 0xC6, 0xFA, 0x7A, 0x38, 0x30, 0x31, 0x8F,
|
nkeynes@158 | 109 | 0xE7, 0xD3, 0x84, 0x2B, 0x5D, 0x4F, 0x95, 0x98, 0xED, 0x0B, 0xD7, 0x50, 0x0C, 0x49, 0xDA, 0x59,
|
nkeynes@158 | 110 | 0x15, 0xF1, 0x39, 0xF3, 0x40, 0xDC, 0xDC, 0x25, 0x24, 0x56, 0x6E, 0xA9, 0x2F, 0xF0, 0x00, 0x00 };
|
nkeynes@158 | 111 |
|
nkeynes@2 | 112 |
|
nkeynes@250 | 113 | char gdrom_status[] = {
|
nkeynes@250 | 114 | 0x00, 0x15, 0x00, 0x64, 0x00, 0x40, 0x00, 0x00,
|
nkeynes@250 | 115 | 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 116 | 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 117 | 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 118 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
|
nkeynes@250 | 120 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
nkeynes@250 | 122 | 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
|
nkeynes@250 | 123 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
|
nkeynes@250 | 124 | 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
|
nkeynes@250 | 125 | 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00,
|
nkeynes@250 | 126 | 0x00, 0x40, 0x00, 0x00 };
|
nkeynes@250 | 127 |
|
nkeynes@250 | 128 |
|
nkeynes@138 | 129 | static void ide_init( void )
|
nkeynes@138 | 130 | {
|
nkeynes@138 | 131 | ide_reset();
|
nkeynes@138 | 132 | data_buffer_len = DEFAULT_DATA_SECTORS;
|
nkeynes@138 | 133 | data_buffer = malloc( MAX_SECTOR_SIZE * data_buffer_len );
|
nkeynes@138 | 134 | assert( data_buffer != NULL );
|
nkeynes@138 | 135 | }
|
nkeynes@138 | 136 |
|
nkeynes@138 | 137 | static void ide_reset( void )
|
nkeynes@138 | 138 | {
|
nkeynes@138 | 139 | ide_clear_interrupt();
|
nkeynes@138 | 140 | idereg.error = 0x01;
|
nkeynes@138 | 141 | idereg.count = 0x01;
|
nkeynes@138 | 142 | idereg.lba0 = /* 0x21; */ 0x81;
|
nkeynes@138 | 143 | idereg.lba1 = 0x14;
|
nkeynes@138 | 144 | idereg.lba2 = 0xeb;
|
nkeynes@138 | 145 | idereg.feature = 0; /* Indeterminate really */
|
nkeynes@254 | 146 | idereg.status = 0x00;
|
nkeynes@138 | 147 | idereg.device = 0x00;
|
nkeynes@143 | 148 | idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;
|
nkeynes@152 | 149 | idereg.state = IDE_STATE_IDLE;
|
nkeynes@152 | 150 | memset( idereg.gdrom_sense, '\0', 10 );
|
nkeynes@152 | 151 | idereg.data_offset = -1;
|
nkeynes@152 | 152 | idereg.data_length = -1;
|
nkeynes@245 | 153 | idereg.last_read_track = 1;
|
nkeynes@245 | 154 | idereg.last_read_lba = 150;
|
nkeynes@254 | 155 | idereg.was_reset = TRUE;
|
nkeynes@138 | 156 | }
|
nkeynes@138 | 157 |
|
nkeynes@138 | 158 | static void ide_save_state( FILE *f )
|
nkeynes@138 | 159 | {
|
nkeynes@152 | 160 | fwrite( &idereg, sizeof(idereg), 1, f );
|
nkeynes@152 | 161 | fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
|
nkeynes@158 | 162 | fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );
|
nkeynes@138 | 163 | }
|
nkeynes@138 | 164 |
|
nkeynes@138 | 165 | static int ide_load_state( FILE *f )
|
nkeynes@138 | 166 | {
|
nkeynes@152 | 167 | uint32_t length;
|
nkeynes@152 | 168 | fread( &idereg, sizeof(idereg), 1, f );
|
nkeynes@152 | 169 | fread( &length, sizeof(uint32_t), 1, f );
|
nkeynes@152 | 170 | if( length > data_buffer_len ) {
|
nkeynes@152 | 171 | if( data_buffer != NULL )
|
nkeynes@152 | 172 | free( data_buffer );
|
nkeynes@158 | 173 | data_buffer = malloc( MAX_SECTOR_SIZE * length );
|
nkeynes@152 | 174 | assert( data_buffer != NULL );
|
nkeynes@152 | 175 | data_buffer_len = length;
|
nkeynes@152 | 176 | }
|
nkeynes@158 | 177 | fread( data_buffer, MAX_SECTOR_SIZE, length, f );
|
nkeynes@138 | 178 | return 0;
|
nkeynes@138 | 179 | }
|
nkeynes@125 | 180 |
|
nkeynes@152 | 181 | /************************ State transitions *************************/
|
nkeynes@152 | 182 |
|
nkeynes@158 | 183 | void ide_set_packet_result( uint16_t result )
|
nkeynes@158 | 184 | {
|
nkeynes@158 | 185 | idereg.gdrom_sense[0] = 0xf0;
|
nkeynes@158 | 186 | idereg.gdrom_sense[2] = result & 0xFF;
|
nkeynes@158 | 187 | idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
|
nkeynes@158 | 188 | idereg.error = (result & 0x0F) << 4;
|
nkeynes@254 | 189 | idereg.count = 3;
|
nkeynes@158 | 190 | if( result != 0 ) {
|
nkeynes@158 | 191 | idereg.status = 0x51;
|
nkeynes@158 | 192 | ide_raise_interrupt();
|
nkeynes@158 | 193 | } else {
|
nkeynes@158 | 194 | idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
|
nkeynes@158 | 195 | }
|
nkeynes@158 | 196 | }
|
nkeynes@158 | 197 |
|
nkeynes@152 | 198 | /**
|
nkeynes@152 | 199 | * Begin command packet write to the device. This is always 12 bytes of PIO data
|
nkeynes@152 | 200 | */
|
nkeynes@152 | 201 | static void ide_start_command_packet_write( )
|
nkeynes@2 | 202 | {
|
nkeynes@152 | 203 | idereg.state = IDE_STATE_CMD_WRITE;
|
nkeynes@254 | 204 | idereg.status = 0x58;
|
nkeynes@152 | 205 | idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
|
nkeynes@152 | 206 | idereg.count = IDE_COUNT_CD;
|
nkeynes@152 | 207 | idereg.data_offset = 0;
|
nkeynes@152 | 208 | idereg.data_length = 12;
|
nkeynes@2 | 209 | }
|
nkeynes@2 | 210 |
|
nkeynes@152 | 211 | /**
|
nkeynes@152 | 212 | * Begin PIO read from the device. The data is assumed to already be
|
nkeynes@152 | 213 | * in the buffer at this point.
|
nkeynes@152 | 214 | */
|
nkeynes@152 | 215 | static void ide_start_read( int length, int blocksize, gboolean dma )
|
nkeynes@2 | 216 | {
|
nkeynes@152 | 217 | idereg.count = IDE_COUNT_IO;
|
nkeynes@152 | 218 | idereg.data_length = length;
|
nkeynes@152 | 219 | idereg.data_offset = 0;
|
nkeynes@152 | 220 | if( dma ) {
|
nkeynes@152 | 221 | idereg.state = IDE_STATE_DMA_READ;
|
nkeynes@158 | 222 | idereg.status = 0xD0;
|
nkeynes@152 | 223 | } else {
|
nkeynes@152 | 224 | idereg.state = IDE_STATE_PIO_READ;
|
nkeynes@254 | 225 | idereg.status = 0x58;
|
nkeynes@258 | 226 | idereg.lba1 = blocksize & 0xFF;
|
nkeynes@258 | 227 | idereg.lba2 = blocksize >> 8;
|
nkeynes@152 | 228 | idereg.block_length = blocksize;
|
nkeynes@152 | 229 | idereg.block_left = blocksize;
|
nkeynes@158 | 230 | ide_raise_interrupt( );
|
nkeynes@152 | 231 | }
|
nkeynes@152 | 232 | }
|
nkeynes@152 | 233 |
|
nkeynes@152 | 234 | static void ide_start_packet_read( int length, int blocksize )
|
nkeynes@152 | 235 | {
|
nkeynes@158 | 236 | ide_set_packet_result( PKT_ERR_OK );
|
nkeynes@158 | 237 | ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
|
nkeynes@2 | 238 | }
|
nkeynes@2 | 239 |
|
nkeynes@125 | 240 | static void ide_raise_interrupt( void )
|
nkeynes@2 | 241 | {
|
nkeynes@125 | 242 | if( idereg.intrq_pending == 0 ) {
|
nkeynes@125 | 243 | idereg.intrq_pending = 1;
|
nkeynes@125 | 244 | if( IS_IDE_IRQ_ENABLED() )
|
nkeynes@125 | 245 | asic_event( EVENT_IDE );
|
nkeynes@125 | 246 | }
|
nkeynes@125 | 247 | }
|
nkeynes@125 | 248 |
|
nkeynes@125 | 249 | static void ide_clear_interrupt( void )
|
nkeynes@125 | 250 | {
|
nkeynes@125 | 251 | if( idereg.intrq_pending != 0 ) {
|
nkeynes@125 | 252 | idereg.intrq_pending = 0;
|
nkeynes@125 | 253 | if( IS_IDE_IRQ_ENABLED() )
|
nkeynes@125 | 254 | asic_clear_event( EVENT_IDE );
|
nkeynes@125 | 255 | }
|
nkeynes@125 | 256 | }
|
nkeynes@125 | 257 |
|
nkeynes@125 | 258 | static void ide_set_error( int error_code )
|
nkeynes@125 | 259 | {
|
nkeynes@125 | 260 | idereg.status = 0x51;
|
nkeynes@125 | 261 | idereg.error = error_code;
|
nkeynes@2 | 262 | }
|
nkeynes@2 | 263 |
|
nkeynes@125 | 264 | uint8_t ide_read_status( void )
|
nkeynes@125 | 265 | {
|
nkeynes@152 | 266 | if( (idereg.status & IDE_STATUS_BSY) == 0 )
|
nkeynes@125 | 267 | ide_clear_interrupt();
|
nkeynes@125 | 268 | return idereg.status;
|
nkeynes@2 | 269 | }
|
nkeynes@2 | 270 |
|
nkeynes@2 | 271 | uint16_t ide_read_data_pio( void ) {
|
nkeynes@152 | 272 | if( idereg.state == IDE_STATE_PIO_READ ) {
|
nkeynes@152 | 273 | uint16_t rv = READ_BUFFER();
|
nkeynes@152 | 274 | idereg.data_offset += 2;
|
nkeynes@152 | 275 | idereg.block_left -= 2;
|
nkeynes@152 | 276 | if( idereg.data_offset >= idereg.data_length ) {
|
nkeynes@152 | 277 | idereg.state = IDE_STATE_IDLE;
|
nkeynes@152 | 278 | idereg.status &= ~IDE_STATUS_DRQ;
|
nkeynes@152 | 279 | idereg.data_offset = -1;
|
nkeynes@254 | 280 | idereg.count = 3; /* complete */
|
nkeynes@152 | 281 | ide_raise_interrupt();
|
nkeynes@152 | 282 | } else if( idereg.block_left <= 0 ) {
|
nkeynes@152 | 283 | idereg.block_left = idereg.block_length;
|
nkeynes@152 | 284 | ide_raise_interrupt();
|
nkeynes@152 | 285 | }
|
nkeynes@152 | 286 | return rv;
|
nkeynes@152 | 287 | } else {
|
nkeynes@2 | 288 | return 0xFFFF;
|
nkeynes@2 | 289 | }
|
nkeynes@2 | 290 | }
|
nkeynes@2 | 291 |
|
nkeynes@152 | 292 |
|
nkeynes@152 | 293 | /**
|
nkeynes@152 | 294 | * DMA read request
|
nkeynes@152 | 295 | *
|
nkeynes@152 | 296 | * This method is called from the ASIC side when a DMA read request is
|
nkeynes@152 | 297 | * initiated. If there is a pending DMA transfer already, we copy the
|
nkeynes@152 | 298 | * data immediately, otherwise we record the DMA buffer for use when we
|
nkeynes@152 | 299 | * get to actually doing the transfer.
|
nkeynes@152 | 300 | * @return number of bytes transfered
|
nkeynes@152 | 301 | */
|
nkeynes@152 | 302 | uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
|
nkeynes@152 | 303 | {
|
nkeynes@152 | 304 | if( idereg.state == IDE_STATE_DMA_READ ) {
|
nkeynes@152 | 305 | int xferlen = length;
|
nkeynes@152 | 306 | int remaining = idereg.data_length - idereg.data_offset;
|
nkeynes@152 | 307 | if( xferlen > remaining )
|
nkeynes@152 | 308 | xferlen = remaining;
|
nkeynes@152 | 309 | mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
|
nkeynes@152 | 310 | idereg.data_offset += xferlen;
|
nkeynes@152 | 311 | if( idereg.data_offset >= idereg.data_length ) {
|
nkeynes@152 | 312 | idereg.data_offset = -1;
|
nkeynes@152 | 313 | idereg.state = IDE_STATE_IDLE;
|
nkeynes@158 | 314 | idereg.status = 0x50;
|
nkeynes@254 | 315 | idereg.count = 0x03;
|
nkeynes@152 | 316 | ide_raise_interrupt();
|
nkeynes@158 | 317 | asic_event( EVENT_IDE_DMA );
|
nkeynes@152 | 318 | }
|
nkeynes@152 | 319 | return xferlen;
|
nkeynes@152 | 320 | }
|
nkeynes@152 | 321 | return 0;
|
nkeynes@152 | 322 | }
|
nkeynes@152 | 323 |
|
nkeynes@2 | 324 | void ide_write_data_pio( uint16_t val ) {
|
nkeynes@152 | 325 | if( idereg.state == IDE_STATE_CMD_WRITE ) {
|
nkeynes@152 | 326 | WRITE_BUFFER(val);
|
nkeynes@152 | 327 | idereg.data_offset+=2;
|
nkeynes@152 | 328 | if( idereg.data_offset >= idereg.data_length ) {
|
nkeynes@152 | 329 | idereg.state = IDE_STATE_BUSY;
|
nkeynes@152 | 330 | idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
|
nkeynes@152 | 331 | idereg.data_offset = -1;
|
nkeynes@152 | 332 | ide_packet_command(data_buffer);
|
nkeynes@152 | 333 | }
|
nkeynes@152 | 334 | } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
|
nkeynes@152 | 335 | WRITE_BUFFER(val);
|
nkeynes@152 | 336 | if( idereg.data_offset >= idereg.data_length ) {
|
nkeynes@152 | 337 | idereg.state = IDE_STATE_BUSY;
|
nkeynes@152 | 338 | idereg.data_offset = -1;
|
nkeynes@152 | 339 | idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
|
nkeynes@152 | 340 | /* ??? - no data writes yet anyway */
|
nkeynes@152 | 341 | }
|
nkeynes@2 | 342 | }
|
nkeynes@2 | 343 | }
|
nkeynes@2 | 344 |
|
nkeynes@2 | 345 | void ide_write_control( uint8_t val ) {
|
nkeynes@125 | 346 | if( IS_IDE_IRQ_ENABLED() ) {
|
nkeynes@125 | 347 | if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
|
nkeynes@125 | 348 | asic_clear_event( EVENT_IDE );
|
nkeynes@125 | 349 | } else {
|
nkeynes@125 | 350 | if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
|
nkeynes@125 | 351 | asic_event( EVENT_IDE );
|
nkeynes@125 | 352 | }
|
nkeynes@125 | 353 | idereg.control = val;
|
nkeynes@2 | 354 | }
|
nkeynes@2 | 355 |
|
nkeynes@2 | 356 | void ide_write_command( uint8_t val ) {
|
nkeynes@125 | 357 | ide_clear_interrupt();
|
nkeynes@2 | 358 | idereg.command = val;
|
nkeynes@2 | 359 | switch( val ) {
|
nkeynes@240 | 360 | case IDE_CMD_NOP: /* Effectively an "abort" */
|
nkeynes@240 | 361 | idereg.state = IDE_STATE_IDLE;
|
nkeynes@240 | 362 | idereg.status = 0x51;
|
nkeynes@240 | 363 | idereg.error = 0x04;
|
nkeynes@240 | 364 | idereg.data_offset = -1;
|
nkeynes@240 | 365 | ide_raise_interrupt();
|
nkeynes@240 | 366 | return;
|
nkeynes@39 | 367 | case IDE_CMD_RESET_DEVICE:
|
nkeynes@39 | 368 | ide_reset();
|
nkeynes@39 | 369 | break;
|
nkeynes@39 | 370 | case IDE_CMD_PACKET:
|
nkeynes@152 | 371 | ide_start_command_packet_write();
|
nkeynes@39 | 372 | break;
|
nkeynes@39 | 373 | case IDE_CMD_SET_FEATURE:
|
nkeynes@39 | 374 | switch( idereg.feature ) {
|
nkeynes@47 | 375 | case IDE_FEAT_SET_TRANSFER_MODE:
|
nkeynes@47 | 376 | switch( idereg.count & 0xF8 ) {
|
nkeynes@47 | 377 | case IDE_XFER_PIO:
|
nkeynes@47 | 378 | INFO( "Set PIO default mode: %d", idereg.count&0x07 );
|
nkeynes@47 | 379 | break;
|
nkeynes@47 | 380 | case IDE_XFER_PIO_FLOW:
|
nkeynes@47 | 381 | INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
|
nkeynes@47 | 382 | break;
|
nkeynes@47 | 383 | case IDE_XFER_MULTI_DMA:
|
nkeynes@47 | 384 | INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
|
nkeynes@47 | 385 | break;
|
nkeynes@47 | 386 | case IDE_XFER_ULTRA_DMA:
|
nkeynes@47 | 387 | INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
|
nkeynes@47 | 388 | break;
|
nkeynes@47 | 389 | default:
|
nkeynes@47 | 390 | INFO( "Setting unknown transfer mode: %02X", idereg.count );
|
nkeynes@47 | 391 | break;
|
nkeynes@47 | 392 | }
|
nkeynes@47 | 393 | break;
|
nkeynes@39 | 394 | default:
|
nkeynes@39 | 395 | WARN( "IDE: unimplemented feature: %02X", idereg.feature );
|
nkeynes@39 | 396 | }
|
nkeynes@254 | 397 | idereg.status = 0x50;
|
nkeynes@254 | 398 | idereg.error = 0x00;
|
nkeynes@254 | 399 | idereg.lba1 = 0x00;
|
nkeynes@254 | 400 | idereg.lba2 = 0x00;
|
nkeynes@256 | 401 | ide_raise_interrupt();
|
nkeynes@39 | 402 | break;
|
nkeynes@39 | 403 | default:
|
nkeynes@39 | 404 | WARN( "IDE: Unimplemented command: %02X", val );
|
nkeynes@2 | 405 | }
|
nkeynes@2 | 406 | }
|
nkeynes@2 | 407 |
|
nkeynes@142 | 408 | /**
|
nkeynes@142 | 409 | * Execute a packet command. This particular method is responsible for parsing
|
nkeynes@142 | 410 | * the command buffers (12 bytes), and generating the appropriate responses,
|
nkeynes@142 | 411 | * although the actual implementation is mostly delegated to gdrom.c
|
nkeynes@142 | 412 | */
|
nkeynes@125 | 413 | void ide_packet_command( unsigned char *cmd )
|
nkeynes@125 | 414 | {
|
nkeynes@138 | 415 | uint32_t length, datalen;
|
nkeynes@143 | 416 | uint32_t lba, status;
|
nkeynes@143 | 417 | int mode;
|
nkeynes@125 | 418 | int blocksize = idereg.lba1 + (idereg.lba2<<8);
|
nkeynes@125 | 419 |
|
nkeynes@125 | 420 | /* Okay we have the packet in the command buffer */
|
nkeynes@166 | 421 | INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
|
nkeynes@166 | 422 | cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
|
nkeynes@166 | 423 | cmd[8], cmd[9], cmd[10], cmd[11] );
|
nkeynes@254 | 424 |
|
nkeynes@254 | 425 | if( cmd[0] != PKT_CMD_SENSE && idereg.was_reset ) {
|
nkeynes@254 | 426 | ide_set_packet_result( PKT_ERR_RESET );
|
nkeynes@254 | 427 | idereg.was_reset = FALSE;
|
nkeynes@254 | 428 | return;
|
nkeynes@254 | 429 | }
|
nkeynes@254 | 430 |
|
nkeynes@125 | 431 | switch( cmd[0] ) {
|
nkeynes@142 | 432 | case PKT_CMD_TEST_READY:
|
nkeynes@142 | 433 | if( !gdrom_is_mounted() ) {
|
nkeynes@152 | 434 | ide_set_packet_result( PKT_ERR_NODISC );
|
nkeynes@158 | 435 | } else {
|
nkeynes@158 | 436 | ide_set_packet_result( 0 );
|
nkeynes@158 | 437 | ide_raise_interrupt();
|
nkeynes@158 | 438 | idereg.status = 0x50;
|
nkeynes@142 | 439 | }
|
nkeynes@142 | 440 | break;
|
nkeynes@125 | 441 | case PKT_CMD_IDENTIFY:
|
nkeynes@140 | 442 | lba = cmd[2];
|
nkeynes@140 | 443 | if( lba >= sizeof(gdrom_ident) ) {
|
nkeynes@142 | 444 | ide_set_error(PKT_ERR_BADFIELD);
|
nkeynes@158 | 445 | } else {
|
nkeynes@158 | 446 | length = cmd[4];
|
nkeynes@158 | 447 | if( lba+length > sizeof(gdrom_ident) )
|
nkeynes@158 | 448 | length = sizeof(gdrom_ident) - lba;
|
nkeynes@158 | 449 | memcpy( data_buffer, gdrom_ident + lba, length );
|
nkeynes@258 | 450 | ide_start_packet_read( length, length );
|
nkeynes@140 | 451 | }
|
nkeynes@125 | 452 | break;
|
nkeynes@142 | 453 | case PKT_CMD_SENSE:
|
nkeynes@142 | 454 | length = cmd[4];
|
nkeynes@142 | 455 | if( length > 10 )
|
nkeynes@142 | 456 | length = 10;
|
nkeynes@152 | 457 | memcpy( data_buffer, idereg.gdrom_sense, length );
|
nkeynes@258 | 458 | ide_start_packet_read( length, length );
|
nkeynes@142 | 459 | break;
|
nkeynes@125 | 460 | case PKT_CMD_READ_TOC:
|
nkeynes@142 | 461 | length = (cmd[3]<<8) | cmd[4];
|
nkeynes@142 | 462 | if( length > sizeof(struct gdrom_toc) )
|
nkeynes@142 | 463 | length = sizeof(struct gdrom_toc);
|
nkeynes@152 | 464 |
|
nkeynes@152 | 465 | status = gdrom_get_toc( data_buffer );
|
nkeynes@152 | 466 | if( status != PKT_ERR_OK ) {
|
nkeynes@152 | 467 | ide_set_packet_result( status );
|
nkeynes@158 | 468 | } else {
|
nkeynes@258 | 469 | ide_start_packet_read( length, length );
|
nkeynes@152 | 470 | }
|
nkeynes@125 | 471 | break;
|
nkeynes@158 | 472 | case PKT_CMD_SESSION_INFO:
|
nkeynes@149 | 473 | length = cmd[4];
|
nkeynes@149 | 474 | if( length > 6 )
|
nkeynes@149 | 475 | length = 6;
|
nkeynes@152 | 476 | status = gdrom_get_info( data_buffer, cmd[2] );
|
nkeynes@152 | 477 | if( status != PKT_ERR_OK ) {
|
nkeynes@152 | 478 | ide_set_packet_result( status );
|
nkeynes@158 | 479 | } else {
|
nkeynes@258 | 480 | ide_start_packet_read( length, length );
|
nkeynes@152 | 481 | }
|
nkeynes@149 | 482 | break;
|
nkeynes@250 | 483 | case PKT_CMD_PLAY_CD:
|
nkeynes@250 | 484 | ide_set_packet_result( 0 );
|
nkeynes@250 | 485 | ide_raise_interrupt();
|
nkeynes@250 | 486 | idereg.status = 0x50;
|
nkeynes@250 | 487 | break;
|
nkeynes@125 | 488 | case PKT_CMD_READ_SECTOR:
|
nkeynes@125 | 489 | lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
|
nkeynes@125 | 490 | length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
|
nkeynes@143 | 491 | switch( cmd[1] ) {
|
nkeynes@245 | 492 | case 0x20: mode = GDROM_MODE1; break; /* TODO - might be unchecked? */
|
nkeynes@143 | 493 | case 0x24: mode = GDROM_GD; break;
|
nkeynes@245 | 494 | case 0x28: mode = GDROM_MODE2_XA1; break; /* ??? */
|
nkeynes@143 | 495 | case 0x30: mode = GDROM_RAW; break;
|
nkeynes@143 | 496 | default:
|
nkeynes@143 | 497 | ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
|
nkeynes@152 | 498 | ide_set_packet_result( PKT_ERR_BADFIELD );
|
nkeynes@142 | 499 | return;
|
nkeynes@142 | 500 | }
|
nkeynes@158 | 501 |
|
nkeynes@158 | 502 | if( length > data_buffer_len ) {
|
nkeynes@158 | 503 | do {
|
nkeynes@158 | 504 | data_buffer_len = data_buffer_len << 1;
|
nkeynes@158 | 505 | } while( data_buffer_len < length );
|
nkeynes@158 | 506 | data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
|
nkeynes@158 | 507 | }
|
nkeynes@158 | 508 |
|
nkeynes@152 | 509 | datalen = data_buffer_len;
|
nkeynes@152 | 510 | status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
|
nkeynes@143 | 511 | if( status != 0 ) {
|
nkeynes@152 | 512 | ide_set_packet_result( status );
|
nkeynes@152 | 513 | idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
|
nkeynes@152 | 514 | idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
|
nkeynes@152 | 515 | idereg.gdrom_sense[7] = lba & 0xFF;
|
nkeynes@258 | 516 | WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );
|
nkeynes@158 | 517 | } else {
|
nkeynes@245 | 518 | idereg.last_read_lba = lba + length;
|
nkeynes@245 | 519 | idereg.last_read_track = gdrom_get_track_no_by_lba( idereg.last_read_lba );
|
nkeynes@258 | 520 | ide_start_packet_read( datalen, 0x0800 );
|
nkeynes@125 | 521 | }
|
nkeynes@125 | 522 | break;
|
nkeynes@149 | 523 | case PKT_CMD_SPIN_UP:
|
nkeynes@149 | 524 | /* do nothing? */
|
nkeynes@158 | 525 | ide_set_packet_result( PKT_ERR_OK );
|
nkeynes@158 | 526 | ide_raise_interrupt();
|
nkeynes@158 | 527 | break;
|
nkeynes@245 | 528 | case PKT_CMD_STATUS:
|
nkeynes@245 | 529 | length = cmd[4];
|
nkeynes@245 | 530 | if( !gdrom_is_mounted() ) {
|
nkeynes@245 | 531 | ide_set_packet_result( PKT_ERR_NODISC );
|
nkeynes@245 | 532 | } else {
|
nkeynes@245 | 533 | switch( cmd[1] ) {
|
nkeynes@245 | 534 | case 0:
|
nkeynes@250 | 535 | if( length > sizeof(gdrom_status) ) {
|
nkeynes@250 | 536 | length = sizeof(gdrom_status);
|
nkeynes@250 | 537 | }
|
nkeynes@250 | 538 | memcpy( data_buffer, gdrom_status, length );
|
nkeynes@258 | 539 | ide_start_packet_read( length, length );
|
nkeynes@245 | 540 | break;
|
nkeynes@245 | 541 | case 1:
|
nkeynes@254 | 542 | if( length > 14 ) {
|
nkeynes@254 | 543 | length = 14;
|
nkeynes@245 | 544 | }
|
nkeynes@254 | 545 | gdrom_track_t track = gdrom_get_track(idereg.last_read_track);
|
nkeynes@254 | 546 | int offset = idereg.last_read_lba - track->lba;
|
nkeynes@245 | 547 | data_buffer[0] = 0x00;
|
nkeynes@245 | 548 | data_buffer[1] = 0x15; /* ??? */
|
nkeynes@245 | 549 | data_buffer[2] = 0x00;
|
nkeynes@245 | 550 | data_buffer[3] = 0x0E;
|
nkeynes@254 | 551 | data_buffer[4] = track->flags;
|
nkeynes@245 | 552 | data_buffer[5] = idereg.last_read_track;
|
nkeynes@245 | 553 | data_buffer[6] = 0x01; /* ?? */
|
nkeynes@254 | 554 | data_buffer[7] = (offset >> 16) & 0xFF;
|
nkeynes@254 | 555 | data_buffer[8] = (offset >> 8) & 0xFF;
|
nkeynes@254 | 556 | data_buffer[9] = offset & 0xFF;
|
nkeynes@245 | 557 | data_buffer[10] = (idereg.last_read_lba >> 24) & 0xFF;
|
nkeynes@245 | 558 | data_buffer[11] = (idereg.last_read_lba >> 16) & 0xFF;
|
nkeynes@245 | 559 | data_buffer[12] = (idereg.last_read_lba >> 8) & 0xFF;
|
nkeynes@245 | 560 | data_buffer[13] = idereg.last_read_lba & 0xFF;
|
nkeynes@258 | 561 | ide_start_packet_read( length, length );
|
nkeynes@245 | 562 | break;
|
nkeynes@245 | 563 | }
|
nkeynes@245 | 564 | }
|
nkeynes@245 | 565 | break;
|
nkeynes@158 | 566 | case PKT_CMD_71:
|
nkeynes@158 | 567 | /* This is a weird one. As far as I can tell it returns random garbage
|
nkeynes@158 | 568 | * (and not even the same length each time, never mind the same data).
|
nkeynes@158 | 569 | * For sake of something to do, it returns the results from a test dump
|
nkeynes@158 | 570 | */
|
nkeynes@158 | 571 | memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
|
nkeynes@258 | 572 | ide_start_packet_read( sizeof(gdrom_71), sizeof(gdrom_71) );
|
nkeynes@149 | 573 | break;
|
nkeynes@142 | 574 | default:
|
nkeynes@152 | 575 | ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
|
nkeynes@142 | 576 | return;
|
nkeynes@125 | 577 | }
|
nkeynes@125 | 578 | }
|