Search
lxdream.org :: lxdream/src/maple/maple.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/maple/maple.c
changeset 2:42349f6ea216
prev1:eea311cfd33e
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
file annotate diff log raw
1.1 --- a/src/maple/maple.c Sat Mar 13 00:03:32 2004 +0000
1.2 +++ b/src/maple/maple.c Mon Dec 12 10:37:41 2005 +0000
1.3 @@ -4,24 +4,213 @@
1.4 #include "asic.h"
1.5 #include "maple.h"
1.6
1.7 +/**
1.8 + * Input data looks like this:
1.9 + * 0: transfer control word
1.10 + * 0: length of data in words (not including 3 word header)
1.11 + * 1: low bit = lightgun mode
1.12 + * 2: low 2 bits = port # (0..3)
1.13 + * 3: 0x80 = last packet, 0x00 = normal packet
1.14 + * 4: output buffer address
1.15 + * 8: Command word
1.16 + * 8: command code
1.17 + * 9: destination address
1.18 + * 10: source address
1.19 + * 11: length of data in words (not including 3 word header)
1.20 + * 12: command-specific data
1.21 + */
1.22 +
1.23 +/**
1.24 + * array is [port][subperipheral], so [0][0] is main peripheral on port A,
1.25 + * [1][2] is the second subperipheral on port B and so on.
1.26 + */
1.27 +maple_device_t maple_devices[4][6];
1.28 +int maple_periph_mask[4];
1.29 +#define GETBYTE(n) ((uint32_t)(buf[n]))
1.30 +#define GETWORD(n) (*((uint32_t *)(buf+(n))))
1.31 +#define PUTBYTE(n,x) (buf[n] = (char)x)
1.32 +#define PUTWORD(n,x) (*((uint32_t *)(return_buf+(n))) = (x))
1.33 +
1.34 void maple_handle_buffer( uint32_t address ) {
1.35 - uint32_t *buf = (uint32_t *)mem_get_region(address);
1.36 + unsigned char *buf = (unsigned char *)mem_get_region(address);
1.37 if( buf == NULL ) {
1.38 ERROR( "Invalid or unmapped buffer passed to maple (0x%08X)", address );
1.39 } else {
1.40 - int last, port, length, cmd, recv_addr, send_addr, add_length;
1.41 - int i = 0;
1.42 - do {
1.43 - last = buf[i]>>31; /* indicates last packet */
1.44 - port = (buf[i]>>16)&0x03;
1.45 - length = buf[i]&0x0F;
1.46 - uint32_t return_address = buf[i+1];
1.47 - cmd = buf[i+2]&0xFF;
1.48 - recv_addr = (buf[i+2]>>8)&0xFF;
1.49 - send_addr = (buf[i+2]>>16)&0xFF;
1.50 - add_length = (buf[i+2]>>24)&0xFF;
1.51 - char *return_buf = mem_get_region(return_address);
1.52 + unsigned int last = 0;
1.53 + int i = 0, count;
1.54 + for( count=0; !last; count++ ) {
1.55 + unsigned int port, length, gun, periph, periph_id, out_length;
1.56 + unsigned int cmd, recv_addr, send_addr;
1.57 + uint32_t return_addr;
1.58 + unsigned char *return_buf;
1.59
1.60 - } while( !last );
1.61 + last = GETBYTE(3) & 0x80; /* indicates last packet */
1.62 + port = GETBYTE(2) & 0x03;
1.63 + gun = GETBYTE(1) & 0x01;
1.64 + length = GETBYTE(0) & 0xFF;
1.65 + return_addr = GETWORD(4);
1.66 + if( return_addr == 0 ) {
1.67 + /* ERROR */
1.68 + }
1.69 + return_buf = mem_get_region(return_addr);
1.70 + cmd = GETBYTE(8);
1.71 + recv_addr = GETBYTE(9);
1.72 + send_addr = GETBYTE(10);
1.73 + /* Sanity checks */
1.74 + if( GETBYTE(11) != length ||
1.75 + send_addr != (port<<6) ||
1.76 + recv_addr >> 6 != port ||
1.77 + return_buf == NULL ) {
1.78 + /* ERROR */
1.79 + }
1.80 + periph = 0;
1.81 + periph_id = recv_addr & 0x3F;
1.82 + if( periph_id != 0x20 ) {
1.83 + for( i=0;i<5;i++ ) {
1.84 + if( periph_id == (1<<i) ) {
1.85 + periph = i+1;
1.86 + break;
1.87 + }
1.88 + }
1.89 + if( periph == 0 ) { /* Bad setting */
1.90 + /* ERROR */
1.91 + }
1.92 + }
1.93 +
1.94 + INFO( "Maple packet %d: Cmd %d on port %d device %d", count, cmd, port, periph );
1.95 + maple_device_t dev = maple_devices[port][periph];
1.96 + if( dev == NULL ) {
1.97 + /* no device attached */
1.98 + *((uint32_t *)return_buf) = -1;
1.99 + } else {
1.100 + int status, func, block;
1.101 + out_length = 0;
1.102 + switch( cmd ) {
1.103 + case MAPLE_CMD_INFO:
1.104 + status = MAPLE_RESP_INFO;
1.105 + memcpy( return_buf+4, dev->ident, 112 );
1.106 + out_length = 0x1C;
1.107 + break;
1.108 + case MAPLE_CMD_EXT_INFO:
1.109 + status = MAPLE_RESP_EXT_INFO;
1.110 + memcpy( return_buf+4, dev->ident, 192 );
1.111 + out_length = 0x30;
1.112 + break;
1.113 + case MAPLE_CMD_RESET:
1.114 + if( dev->reset == NULL )
1.115 + status = MAPLE_RESP_ACK;
1.116 + else status = dev->reset(dev);
1.117 + break;
1.118 + case MAPLE_CMD_SHUTDOWN:
1.119 + if( dev->shutdown == NULL )
1.120 + status = MAPLE_RESP_ACK;
1.121 + else status = dev->shutdown(dev);
1.122 + break;
1.123 + case MAPLE_CMD_GET_COND:
1.124 + func = GETWORD(12);
1.125 + if( dev->get_condition == NULL )
1.126 + status = MAPLE_ERR_CMD_UNKNOWN;
1.127 + else status = dev->get_condition(dev, func,
1.128 + return_buf+8,
1.129 + &out_length );
1.130 + if( status == 0 ) {
1.131 + status = MAPLE_RESP_DATA;
1.132 + PUTWORD(4,func);
1.133 + }
1.134 + break;
1.135 + case MAPLE_CMD_SET_COND:
1.136 + func = GETWORD(12);
1.137 + if( dev->set_condition == NULL )
1.138 + status = MAPLE_ERR_CMD_UNKNOWN;
1.139 + else status = dev->set_condition(dev, func,
1.140 + buf+16,
1.141 + length);
1.142 + if( status == 0 )
1.143 + status = MAPLE_RESP_ACK;
1.144 + break;
1.145 + case MAPLE_CMD_READ_BLOCK:
1.146 + func = GETWORD(12);
1.147 + block = GETWORD(16);
1.148 + if( dev->read_block == NULL )
1.149 + status = MAPLE_ERR_CMD_UNKNOWN;
1.150 + else status = dev->read_block(dev, func, block,
1.151 + return_buf+12,
1.152 + &out_length );
1.153 + if( status == 0 ) {
1.154 + status = MAPLE_RESP_DATA;
1.155 + PUTWORD(4,func);
1.156 + PUTWORD(8,block);
1.157 + }
1.158 + break;
1.159 + case MAPLE_CMD_WRITE_BLOCK:
1.160 + func = GETWORD(12);
1.161 + block = GETWORD(16);
1.162 + if( dev->write_block == NULL )
1.163 + status = MAPLE_ERR_CMD_UNKNOWN;
1.164 + else {
1.165 + status = dev->write_block(dev, func, block,
1.166 + buf+20, length);
1.167 + if( status == 0 )
1.168 + status = MAPLE_RESP_ACK;
1.169 + }
1.170 + break;
1.171 + default:
1.172 + status = MAPLE_ERR_CMD_UNKNOWN;
1.173 + }
1.174 + return_buf[0] = status;
1.175 + return_buf[1] = send_addr;
1.176 + return_buf[2] = recv_addr;
1.177 + if( periph == 0 )
1.178 + return_buf[2] |= maple_periph_mask[port];
1.179 + return_buf[3] = out_length;
1.180 + }
1.181 + buf += 12 + (length<<2);
1.182 + }
1.183 + asic_event( EVENT_MAPLE_DMA );
1.184 }
1.185 }
1.186 +
1.187 +void maple_attach_device( maple_device_t dev, unsigned int port,
1.188 + unsigned int periph ) {
1.189 + assert( port < 4 );
1.190 + assert( periph < 6 );
1.191 +
1.192 + if( maple_devices[port][periph] != NULL ) {
1.193 + /* Detach existing peripheral first */
1.194 + maple_detach_device( port, periph );
1.195 + }
1.196 +
1.197 + maple_devices[port][periph] = dev;
1.198 + if( periph != 0 )
1.199 + maple_periph_mask[port] |= (1<<(periph-1));
1.200 + else maple_periph_mask[port] |= 0x20;
1.201 + if( dev->attach != NULL ) {
1.202 + dev->attach( dev );
1.203 + }
1.204 +}
1.205 +
1.206 +void maple_detach_device( unsigned int port, unsigned int periph ) {
1.207 + assert( port < 4 );
1.208 + assert( periph < 6 );
1.209 +
1.210 + maple_device_t dev = maple_devices[port][periph];
1.211 + if( dev == NULL ) /* already detached */
1.212 + return;
1.213 + maple_devices[port][periph] = NULL;
1.214 + if( dev->detach != NULL ) {
1.215 + dev->detach(dev);
1.216 + }
1.217 + if( periph == 0 ) {
1.218 + /* If we detach the main peripheral, we also have to detach all the
1.219 + * subperipherals, or the system could get quite confused
1.220 + */
1.221 + int i;
1.222 + maple_periph_mask[port] = 0;
1.223 + for( i=1; i<6; i++ ) {
1.224 + maple_detach_device(port,i);
1.225 + }
1.226 + } else {
1.227 + maple_periph_mask[port] &= (~(1<<(periph-1)));
1.228 + }
1.229 +
1.230 +}
.