Search
lxdream.org :: lxdream/src/gdrom/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 2:42349f6ea216
next15:5194dd0fdb60
author nkeynes
date Mon Dec 12 10:37:41 2005 +0000 (18 years ago)
permissions -rw-r--r--
last change Use cpu-specific is_valid_page function
view annotate diff log raw
     1 /*
     2  * ide.c    31 Mar 2004  - IDE Interface implementation
     3  *
     4  * Copyright (c) 2004 Nathan Keynes. Distribution and modification permitted
     5  * under the terms of the GNU General Public License version 2 or later. 
     6  */
     7 #include <stdlib.h>
     8 #include "ide.h"
    10 #define MAX_WRITE_BUF 4096;
    12 struct ide_registers idereg;
    14 static char command_buffer[12];
    16 /* "\0\0\0\0\xb4\x19\0\0\x08SE      REV 6.42990316" */
    17 char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
    18                        0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
    19                        0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
    20                        0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
    23 void set_write_buffer( char *buf, int len )
    24 {
    25     idereg.status |= IDE_ST_DATA;
    26     idereg.data = buf;
    27     idereg.datalen = len;
    28     idereg.writeptr = (uint16_t *)buf;
    29     idereg.readptr = NULL;
    30 }
    32 void set_read_buffer( char *buf, int len )
    33 {
    34     idereg.status |= IDE_ST_DATA;
    35     idereg.data = buf;
    36     idereg.datalen = len;
    37     idereg.readptr = (uint16_t *)buf;
    38     idereg.writeptr = NULL;
    39     idereg.lba1 = len&0xFF;
    40     idereg.lba2 = len>>8;
    41 }
    43 void ide_clear_interrupt( void )
    44 {
    45     /* TODO */
    46 }
    48 void ide_reset( void )
    49 {
    50     ide_clear_interrupt();
    51     idereg.error = 0x01;
    52     idereg.count = 0x01;
    53     idereg.lba0 = 0x21;
    54     idereg.lba1 = 0x14;
    55     idereg.lba2 = 0xeb;
    56     idereg.feature = 0; /* Indeterminate really */
    57     idereg.status = 0x00;
    58     idereg.device = 0x00;
    59     idereg.disc = IDE_DISC_GDROM | IDE_DISC_READY;
    60 }
    62 uint16_t ide_read_data_pio( void ) {
    63     if( idereg.readptr == NULL )
    64         return 0xFFFF;
    65     uint16_t rv = *idereg.readptr++;
    66     idereg.datalen-=2;
    67     if( idereg.datalen <=0 ) {
    68         idereg.readptr = NULL;
    69         idereg.status &= ~IDE_ST_DATA;
    70     }
    71     return rv;
    72 }
    74 void ide_write_data_pio( uint16_t val ) {
    75     if( idereg.writeptr == NULL )
    76         return;
    77     *idereg.writeptr++ = val;
    78     idereg.datalen-=2;
    79     if( idereg.datalen <= 0 ) {
    80         idereg.writeptr = NULL;
    81         idereg.status &= ~IDE_ST_DATA;
    82         ide_write_buffer( idereg.data );
    83     }
    84 }
    86 void ide_write_control( uint8_t val ) {
    87     /* TODO: In theory we can cause a soft-reset here, but the DC doesn't
    88      * appear to support it.
    89      */
    90 }
    92 void ide_write_command( uint8_t val ) {
    93     idereg.command = val;
    94     switch( val ) {
    95         case IDE_CMD_RESET_DEVICE:
    96             ide_reset();
    97             break;
    98         case IDE_CMD_PACKET:
    99             set_write_buffer(command_buffer,12);
   100             break;
   101         default:
   102             WARN( "IDE: Unimplemented command: %02X", val );
   103     }
   104     idereg.status |= IDE_ST_READY | IDE_ST_SERV;
   105 }
   107 void ide_write_buffer( char *data ) {
   108     uint16_t length;
   109     switch( idereg.command ) {
   110         case IDE_CMD_PACKET:
   111             /* Okay we have the packet in the command buffer */
   112             WARN( "ATAPI: Received Packet command: %02X", data[0] );
   114             switch( command_buffer[0] ) {
   115                 case PKT_CMD_IDENTIFY:
   116                     /* NB: Bios sets data[4] = 0x08, no idea what this is for;
   117                      * different values here appear to have no effect.
   118                      */
   119                     length = *((uint16_t*)(data+2));
   120                     if( length > sizeof(gdrom_ident) )
   121                         length = sizeof(gdrom_ident);
   122                     set_read_buffer(gdrom_ident, length);
   123                     break;
   124             }
   125             break;
   126     }
   127 }
.