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