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