Search
lxdream.org :: lxdream/src/gdrom/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 240:9ae4bd697292
prev166:8aa70cf503a2
next245:a1d0655a88d3
author nkeynes
date Fri Dec 15 10:18:39 2006 +0000 (16 years ago)
permissions -rw-r--r--
last change Initial implementation of the NOP (00h) command
view annotate diff log raw
     1 /**
     2  * $Id: ide.c,v 1.17 2006-12-15 10:18:39 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 }
   139 static void ide_save_state( FILE *f )
   140 {
   141     fwrite( &idereg, sizeof(idereg), 1, f );
   142     fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
   143     fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );
   144 }
   146 static int ide_load_state( FILE *f )
   147 {
   148     uint32_t length;
   149     fread( &idereg, sizeof(idereg), 1, f );
   150     fread( &length, sizeof(uint32_t), 1, f );
   151     if( length > data_buffer_len ) {
   152 	if( data_buffer != NULL )
   153 	    free( data_buffer );
   154 	data_buffer = malloc( MAX_SECTOR_SIZE * length  );
   155 	assert( data_buffer != NULL );
   156 	data_buffer_len = length;
   157     }
   158     fread( data_buffer, MAX_SECTOR_SIZE, length, f );
   159     return 0;
   160 }
   162 /************************ State transitions *************************/
   164 void ide_set_packet_result( uint16_t result )
   165 {
   166     idereg.gdrom_sense[0] = 0xf0;
   167     idereg.gdrom_sense[2] = result & 0xFF;
   168     idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
   169     idereg.error = (result & 0x0F) << 4;
   170     if( result != 0 ) {
   171 	idereg.status = 0x51;
   172 	ide_raise_interrupt();
   173     } else {
   174 	idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
   175     }
   176 }
   178 /**
   179  * Begin command packet write to the device. This is always 12 bytes of PIO data
   180  */
   181 static void ide_start_command_packet_write( )
   182 {
   183     idereg.state = IDE_STATE_CMD_WRITE;
   184     idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
   185     idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
   186     idereg.count = IDE_COUNT_CD;
   187     idereg.data_offset = 0;
   188     idereg.data_length = 12;
   189 }
   191 /**
   192  * Begin PIO read from the device. The data is assumed to already be
   193  * in the buffer at this point.
   194  */
   195 static void ide_start_read( int length, int blocksize, gboolean dma ) 
   196 {
   197     idereg.count = IDE_COUNT_IO;
   198     idereg.data_length = length;
   199     idereg.data_offset = 0;
   200     if( dma ) {
   201 	idereg.state = IDE_STATE_DMA_READ;
   202 	idereg.status = 0xD0;
   203     } else {
   204 	idereg.state = IDE_STATE_PIO_READ;
   205 	idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
   206 	idereg.lba1 = length & 0xFF;
   207 	idereg.lba2 = (length >> 8) & 0xFF;
   208 	//	idereg.lba1 = blocksize & 0xFF;
   209 	//	idereg.lba2 = blocksize >> 8; 
   210 	idereg.block_length = blocksize;
   211 	idereg.block_left = blocksize;
   212 	ide_raise_interrupt( );
   213     }
   214 }
   216 static void ide_start_packet_read( int length, int blocksize )
   217 {
   218     ide_set_packet_result( PKT_ERR_OK );
   219     ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
   220 }
   222 static void ide_raise_interrupt( void )
   223 {
   224     if( idereg.intrq_pending == 0 ) {
   225 	idereg.intrq_pending = 1;
   226 	if( IS_IDE_IRQ_ENABLED() )
   227 	    asic_event( EVENT_IDE );
   228     }
   229 }
   231 static void ide_clear_interrupt( void ) 
   232 {
   233     if( idereg.intrq_pending != 0 ) {
   234 	idereg.intrq_pending = 0;
   235 	if( IS_IDE_IRQ_ENABLED() )
   236 	    asic_clear_event( EVENT_IDE );
   237     }
   238 }
   240 static void ide_set_error( int error_code )
   241 {
   242     idereg.status = 0x51;
   243     idereg.error = error_code;
   244 }
   246 uint8_t ide_read_status( void ) 
   247 {
   248     if( (idereg.status & IDE_STATUS_BSY) == 0 )
   249 	ide_clear_interrupt();
   250     return idereg.status;
   251 }
   253 uint16_t ide_read_data_pio( void ) {
   254     if( idereg.state == IDE_STATE_PIO_READ ) {
   255 	uint16_t rv = READ_BUFFER();
   256 	idereg.data_offset += 2;
   257 	idereg.block_left -= 2;
   258 	if( idereg.data_offset >= idereg.data_length ) {
   259 	    idereg.state = IDE_STATE_IDLE;
   260 	    idereg.status &= ~IDE_STATUS_DRQ;
   261 	    idereg.data_offset = -1;
   262 	    ide_raise_interrupt();
   263 	} else if( idereg.block_left <= 0 ) {
   264 	    idereg.block_left = idereg.block_length;
   265 	    ide_raise_interrupt();
   266 	}
   267 	return rv;
   268     } else {
   269         return 0xFFFF;
   270     }
   271 }
   274 /**
   275  * DMA read request
   276  *
   277  * This method is called from the ASIC side when a DMA read request is
   278  * initiated. If there is a pending DMA transfer already, we copy the
   279  * data immediately, otherwise we record the DMA buffer for use when we
   280  * get to actually doing the transfer.
   281  * @return number of bytes transfered
   282  */
   283 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
   284 {
   285     if( idereg.state == IDE_STATE_DMA_READ ) {
   286 	int xferlen = length;
   287 	int remaining = idereg.data_length - idereg.data_offset;
   288 	if( xferlen > remaining )
   289 	    xferlen = remaining;
   290 	mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
   291 	idereg.data_offset += xferlen;
   292 	if( idereg.data_offset >= idereg.data_length ) {
   293 	    idereg.data_offset = -1;
   294 	    idereg.state = IDE_STATE_IDLE;
   295 	    idereg.status = 0x50;
   296 	    ide_raise_interrupt();
   297 	    asic_event( EVENT_IDE_DMA );
   298 	}
   299 	return xferlen;
   300     }
   301     return 0;
   302 }
   304 void ide_write_data_pio( uint16_t val ) {
   305     if( idereg.state == IDE_STATE_CMD_WRITE ) {
   306 	WRITE_BUFFER(val);
   307 	idereg.data_offset+=2;
   308 	if( idereg.data_offset >= idereg.data_length ) {
   309 	    idereg.state = IDE_STATE_BUSY;
   310 	    idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
   311 	    idereg.data_offset = -1;
   312 	    ide_packet_command(data_buffer);
   313 	}
   314     } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
   315 	WRITE_BUFFER(val);
   316 	if( idereg.data_offset >= idereg.data_length ) {
   317 	    idereg.state = IDE_STATE_BUSY;
   318 	    idereg.data_offset = -1;
   319 	    idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
   320 	    /* ??? - no data writes yet anyway */
   321 	}
   322     }
   323 }
   325 void ide_write_control( uint8_t val ) {
   326     if( IS_IDE_IRQ_ENABLED() ) {
   327 	if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
   328 	    asic_clear_event( EVENT_IDE );
   329     } else {
   330 	if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
   331 	    asic_event( EVENT_IDE );
   332     }
   333     idereg.control = val;
   334 }
   336 void ide_write_command( uint8_t val ) {
   337     ide_clear_interrupt();
   338     idereg.command = val;
   339     switch( val ) {
   340     case IDE_CMD_NOP: /* Effectively an "abort" */
   341 	idereg.state = IDE_STATE_IDLE;
   342 	idereg.status = 0x51;
   343 	idereg.error = 0x04;
   344 	idereg.data_offset = -1;
   345 	ide_raise_interrupt();
   346 	return;
   347     case IDE_CMD_RESET_DEVICE:
   348 	ide_reset();
   349 	break;
   350     case IDE_CMD_PACKET:
   351 	ide_start_command_packet_write();
   352 	break;
   353     case IDE_CMD_SET_FEATURE:
   354 	switch( idereg.feature ) {
   355 	case IDE_FEAT_SET_TRANSFER_MODE:
   356 	    switch( idereg.count & 0xF8 ) {
   357 	    case IDE_XFER_PIO:
   358 		INFO( "Set PIO default mode: %d", idereg.count&0x07 );
   359 		break;
   360 	    case IDE_XFER_PIO_FLOW:
   361 		INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
   362 		break;
   363 	    case IDE_XFER_MULTI_DMA:
   364 		INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
   365 		break;
   366 	    case IDE_XFER_ULTRA_DMA:
   367 		INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
   368 		break;
   369 	    default:
   370 		INFO( "Setting unknown transfer mode: %02X", idereg.count );
   371 		break;
   372 	    }
   373 	    break;
   374 	default:
   375 	    WARN( "IDE: unimplemented feature: %02X", idereg.feature );
   376 	}
   377 	ide_raise_interrupt( );
   378 	break;
   379     default:
   380 	WARN( "IDE: Unimplemented command: %02X", val );
   381     }
   382     idereg.status = (idereg.status | IDE_STATUS_DRDY | IDE_STATUS_SERV) & (~IDE_STATUS_CHK);
   383 }
   385 /**
   386  * Execute a packet command. This particular method is responsible for parsing
   387  * the command buffers (12 bytes), and generating the appropriate responses, 
   388  * although the actual implementation is mostly delegated to gdrom.c
   389  */
   390 void ide_packet_command( unsigned char *cmd )
   391 {
   392     uint32_t length, datalen;
   393     uint32_t lba, status;
   394     int mode;
   395     int blocksize = idereg.lba1 + (idereg.lba2<<8);
   397     /* Okay we have the packet in the command buffer */
   398     INFO( "ATAPI packet: %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X", 
   399 	  cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
   400 	  cmd[8], cmd[9], cmd[10], cmd[11] );
   401     switch( cmd[0] ) {
   402     case PKT_CMD_TEST_READY:
   403 	if( !gdrom_is_mounted() ) {
   404 	    ide_set_packet_result( PKT_ERR_NODISC );
   405 	} else {
   406 	    ide_set_packet_result( 0 );
   407 	    ide_raise_interrupt();
   408 	    idereg.status = 0x50;
   409 	}
   410 	break;
   411     case PKT_CMD_IDENTIFY:
   412 	lba = cmd[2];
   413 	if( lba >= sizeof(gdrom_ident) ) {
   414 	    ide_set_error(PKT_ERR_BADFIELD);
   415 	} else {
   416 	    length = cmd[4];
   417 	    if( lba+length > sizeof(gdrom_ident) )
   418 		length = sizeof(gdrom_ident) - lba;
   419 	    memcpy( data_buffer, gdrom_ident + lba, length );
   420 	    ide_start_packet_read( length, blocksize );
   421 	}
   422 	break;
   423     case PKT_CMD_SENSE:
   424 	length = cmd[4];
   425 	if( length > 10 )
   426 	    length = 10;
   427 	memcpy( data_buffer, idereg.gdrom_sense, length );
   428 	ide_start_packet_read( length, blocksize );
   429 	break;
   430     case PKT_CMD_READ_TOC:
   431 	length = (cmd[3]<<8) | cmd[4];
   432 	if( length > sizeof(struct gdrom_toc) )
   433 	    length = sizeof(struct gdrom_toc);
   435 	status = gdrom_get_toc( data_buffer );
   436 	if( status != PKT_ERR_OK ) {
   437 	    ide_set_packet_result( status );
   438 	} else {
   439 	    ide_start_packet_read( length, blocksize );
   440 	}
   441 	break;
   442     case PKT_CMD_SESSION_INFO:
   443 	length = cmd[4];
   444 	if( length > 6 )
   445 	    length = 6;
   446 	status = gdrom_get_info( data_buffer, cmd[2] );
   447 	if( status != PKT_ERR_OK ) {
   448 	    ide_set_packet_result( status );
   449 	} else {
   450 	    ide_start_packet_read( length, blocksize );
   451 	}
   452 	break;
   453     case PKT_CMD_READ_SECTOR:
   454 	lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
   455 	length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
   456 	switch( cmd[1] ) {
   457 	case 0x20: mode = GDROM_MODE1; break;
   458 	case 0x24: mode = GDROM_GD; break;
   459 	case 0x28: mode = GDROM_MODE1; break; /* ??? */
   460 	case 0x30: mode = GDROM_RAW; break;
   461 	default:
   462 	    ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
   463 	    ide_set_packet_result( PKT_ERR_BADFIELD );
   464 	    return;
   465 	}
   467 	if( length > data_buffer_len ) {
   468 	    do {
   469 		data_buffer_len = data_buffer_len << 1;
   470 	    } while( data_buffer_len < length );
   471 	    data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
   472 	}
   474 	datalen = data_buffer_len;
   475 	status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
   476 	if( status != 0 ) {
   477 	    ide_set_packet_result( status );
   478 	    idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
   479 	    idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
   480 	    idereg.gdrom_sense[7] = lba & 0xFF;
   481 	} else {
   482 	    ide_start_packet_read( datalen, blocksize );
   483 	}
   484 	break;
   485     case PKT_CMD_SPIN_UP:
   486 	/* do nothing? */
   487 	ide_set_packet_result( PKT_ERR_OK );
   488 	ide_raise_interrupt();
   489 	break;
   490     case PKT_CMD_71:
   491 	/* This is a weird one. As far as I can tell it returns random garbage
   492 	 * (and not even the same length each time, never mind the same data).
   493 	 * For sake of something to do, it returns the results from a test dump
   494 	 */
   495 	memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
   496 	ide_start_packet_read( sizeof(gdrom_71), blocksize );
   497 	break;
   498     default:
   499 	ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
   500 	return;
   501     }
   502 }
.