Search
lxdream.org :: lxdream/src/maple/maple.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/maple.c
changeset 15:5194dd0fdb60
prev2:42349f6ea216
next23:1ec3acd0594d
author nkeynes
date Mon Dec 12 13:11:11 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Add dreamcast_module module structure
view annotate diff log raw
     1 #include <assert.h>
     2 #include "dream.h"
     3 #include "modules.h"
     4 #include "mem.h"
     5 #include "asic.h"
     6 #include "maple.h"
     8 void maple_init( void );
    10 struct dreamcast_module maple_module = { "Maple", maple_init, NULL, NULL, NULL,
    11 					 NULL, NULL };
    13 void maple_init( void )
    14 {
    16 }
    18 /**
    19  * Input data looks like this:
    20  *    0: transfer control word
    21  *      0: length of data in words (not including 3 word header)
    22  *      1: low bit = lightgun mode
    23  *      2: low 2 bits = port # (0..3)
    24  *      3: 0x80 = last packet, 0x00 = normal packet
    25  *    4: output buffer address
    26  *    8: Command word
    27  *      8: command code
    28  *      9: destination address
    29  *     10: source address
    30  *     11: length of data in words (not including 3 word header)
    31  *   12: command-specific data
    32  */
    34 /**
    35  * array is [port][subperipheral], so [0][0] is main peripheral on port A,
    36  * [1][2] is the second subperipheral on port B and so on.
    37  */
    38 maple_device_t maple_devices[4][6];
    39 int maple_periph_mask[4];
    40 #define GETBYTE(n) ((uint32_t)(buf[n]))
    41 #define GETWORD(n) (*((uint32_t *)(buf+(n))))
    42 #define PUTBYTE(n,x) (buf[n] = (char)x)
    43 #define PUTWORD(n,x) (*((uint32_t *)(return_buf+(n))) = (x))
    45 void maple_handle_buffer( uint32_t address ) {
    46     unsigned char *buf = (unsigned char *)mem_get_region(address);
    47     if( buf == NULL ) {
    48         ERROR( "Invalid or unmapped buffer passed to maple (0x%08X)", address );
    49     } else {
    50         unsigned int last = 0;
    51         int i = 0, count;
    52         for( count=0; !last; count++ ) {
    53             unsigned int port, length, gun, periph, periph_id, out_length;
    54             unsigned int cmd, recv_addr, send_addr;
    55             uint32_t return_addr;
    56             unsigned char *return_buf;
    58             last = GETBYTE(3) & 0x80; /* indicates last packet */
    59             port = GETBYTE(2) & 0x03;
    60             gun = GETBYTE(1) & 0x01;
    61             length = GETBYTE(0) & 0xFF;
    62             return_addr = GETWORD(4);
    63             if( return_addr == 0 ) {
    64                 /* ERROR */
    65             }
    66             return_buf = mem_get_region(return_addr);
    67             cmd = GETBYTE(8);
    68             recv_addr = GETBYTE(9);
    69             send_addr = GETBYTE(10);
    70             /* Sanity checks */
    71             if( GETBYTE(11) != length ||
    72                 send_addr != (port<<6) ||
    73                 recv_addr >> 6 != port ||
    74                 return_buf == NULL ) {
    75                 /* ERROR */
    76             }
    77             periph = 0;
    78             periph_id = recv_addr & 0x3F;
    79             if( periph_id != 0x20 ) {
    80                 for( i=0;i<5;i++ ) {
    81                     if( periph_id == (1<<i) ) {
    82                         periph = i+1;
    83                         break;
    84                     }
    85                 }
    86                 if( periph == 0 ) { /* Bad setting */
    87                     /* ERROR */
    88                 }
    89             }
    91             INFO( "Maple packet %d: Cmd %d on port %d device %d", count, cmd, port, periph );
    92             maple_device_t dev = maple_devices[port][periph];
    93             if( dev == NULL ) {
    94                 /* no device attached */
    95                 *((uint32_t *)return_buf) = -1;
    96             } else {
    97                 int status, func, block;
    98                 out_length = 0;
    99                 switch( cmd ) {
   100                     case MAPLE_CMD_INFO:
   101                         status = MAPLE_RESP_INFO;
   102                         memcpy( return_buf+4, dev->ident, 112 );
   103                         out_length = 0x1C;
   104                         break;
   105                     case MAPLE_CMD_EXT_INFO:
   106                         status = MAPLE_RESP_EXT_INFO;
   107                         memcpy( return_buf+4, dev->ident, 192 );
   108                         out_length = 0x30;
   109                         break;
   110                     case MAPLE_CMD_RESET:
   111                         if( dev->reset == NULL )
   112                             status = MAPLE_RESP_ACK;
   113                         else status = dev->reset(dev);
   114                         break;
   115                     case MAPLE_CMD_SHUTDOWN:
   116                         if( dev->shutdown == NULL )
   117                             status = MAPLE_RESP_ACK;
   118                         else status = dev->shutdown(dev);
   119                         break;
   120                     case MAPLE_CMD_GET_COND:
   121                         func = GETWORD(12);
   122                         if( dev->get_condition == NULL )
   123                             status = MAPLE_ERR_CMD_UNKNOWN;
   124                         else status = dev->get_condition(dev, func,
   125                                                          return_buf+8,
   126                                                          &out_length );
   127                         if( status == 0 ) {
   128                             status = MAPLE_RESP_DATA;
   129                             PUTWORD(4,func);
   130                         }
   131                         break;
   132                     case MAPLE_CMD_SET_COND:
   133                         func = GETWORD(12);
   134                         if( dev->set_condition == NULL )
   135                             status = MAPLE_ERR_CMD_UNKNOWN;
   136                         else status = dev->set_condition(dev, func,
   137                                                          buf+16,
   138                                                          length);
   139                         if( status == 0 )
   140                             status = MAPLE_RESP_ACK;
   141                         break;
   142                     case MAPLE_CMD_READ_BLOCK:
   143                         func = GETWORD(12);
   144                         block = GETWORD(16);
   145                         if( dev->read_block == NULL )
   146                             status = MAPLE_ERR_CMD_UNKNOWN;
   147                         else status = dev->read_block(dev, func, block,
   148                                                       return_buf+12,
   149                                                       &out_length );
   150                         if( status == 0 ) {
   151                             status = MAPLE_RESP_DATA;
   152                             PUTWORD(4,func);
   153                             PUTWORD(8,block);
   154                         }
   155                         break;
   156                     case MAPLE_CMD_WRITE_BLOCK:
   157                         func = GETWORD(12);
   158                         block = GETWORD(16);
   159                         if( dev->write_block == NULL )
   160                             status = MAPLE_ERR_CMD_UNKNOWN;
   161                         else {
   162                             status = dev->write_block(dev, func, block, 
   163                                                       buf+20, length);
   164                             if( status == 0 )
   165                                 status = MAPLE_RESP_ACK;
   166                         }
   167                         break;
   168                     default:
   169                         status = MAPLE_ERR_CMD_UNKNOWN;
   170                 }
   171                 return_buf[0] = status;
   172                 return_buf[1] = send_addr;
   173                 return_buf[2] = recv_addr;
   174                 if( periph == 0 )
   175                     return_buf[2] |= maple_periph_mask[port];
   176                 return_buf[3] = out_length;
   177             }
   178             buf += 12 + (length<<2);
   179         }
   180         asic_event( EVENT_MAPLE_DMA );
   181     }
   182 }
   184 void maple_attach_device( maple_device_t dev, unsigned int port,
   185                           unsigned int periph ) {
   186     assert( port < 4 );
   187     assert( periph < 6 );
   189     if( maple_devices[port][periph] != NULL ) {
   190         /* Detach existing peripheral first */
   191         maple_detach_device( port, periph );
   192     }
   194     maple_devices[port][periph] = dev;
   195     if( periph != 0 )
   196         maple_periph_mask[port] |= (1<<(periph-1));
   197     else maple_periph_mask[port] |= 0x20;
   198     if( dev->attach != NULL ) {
   199         dev->attach( dev );
   200     }
   201 }
   203 void maple_detach_device( unsigned int port, unsigned int periph ) {
   204     assert( port < 4 );
   205     assert( periph < 6 );
   207     maple_device_t dev = maple_devices[port][periph];
   208     if( dev == NULL ) /* already detached */
   209         return;
   210     maple_devices[port][periph] = NULL;
   211     if( dev->detach != NULL ) {
   212         dev->detach(dev);
   213     }
   214     if( periph == 0 ) {
   215         /* If we detach the main peripheral, we also have to detach all the
   216          * subperipherals, or the system could get quite confused
   217          */
   218         int i;
   219         maple_periph_mask[port] = 0;
   220         for( i=1; i<6; i++ ) {
   221             maple_detach_device(port,i);
   222         }
   223     } else {
   224         maple_periph_mask[port] &= (~(1<<(periph-1)));
   225     }
   227 }
.