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
17 * 9: destination address
19 * 11: length of data in words (not including 3 word header)
20 * 12: command-specific data
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.
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);
37 ERROR( "Invalid or unmapped buffer passed to maple (0x%08X)", address );
39 unsigned int last = 0;
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;
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 ) {
55 return_buf = mem_get_region(return_addr);
57 recv_addr = GETBYTE(9);
58 send_addr = GETBYTE(10);
60 if( GETBYTE(11) != length ||
61 send_addr != (port<<6) ||
62 recv_addr >> 6 != port ||
63 return_buf == NULL ) {
67 periph_id = recv_addr & 0x3F;
68 if( periph_id != 0x20 ) {
70 if( periph_id == (1<<i) ) {
75 if( periph == 0 ) { /* Bad setting */
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];
83 /* no device attached */
84 *((uint32_t *)return_buf) = -1;
86 int status, func, block;
90 status = MAPLE_RESP_INFO;
91 memcpy( return_buf+4, dev->ident, 112 );
94 case MAPLE_CMD_EXT_INFO:
95 status = MAPLE_RESP_EXT_INFO;
96 memcpy( return_buf+4, dev->ident, 192 );
100 if( dev->reset == NULL )
101 status = MAPLE_RESP_ACK;
102 else status = dev->reset(dev);
104 case MAPLE_CMD_SHUTDOWN:
105 if( dev->shutdown == NULL )
106 status = MAPLE_RESP_ACK;
107 else status = dev->shutdown(dev);
109 case MAPLE_CMD_GET_COND:
111 if( dev->get_condition == NULL )
112 status = MAPLE_ERR_CMD_UNKNOWN;
113 else status = dev->get_condition(dev, func,
117 status = MAPLE_RESP_DATA;
121 case MAPLE_CMD_SET_COND:
123 if( dev->set_condition == NULL )
124 status = MAPLE_ERR_CMD_UNKNOWN;
125 else status = dev->set_condition(dev, func,
129 status = MAPLE_RESP_ACK;
131 case MAPLE_CMD_READ_BLOCK:
134 if( dev->read_block == NULL )
135 status = MAPLE_ERR_CMD_UNKNOWN;
136 else status = dev->read_block(dev, func, block,
140 status = MAPLE_RESP_DATA;
145 case MAPLE_CMD_WRITE_BLOCK:
148 if( dev->write_block == NULL )
149 status = MAPLE_ERR_CMD_UNKNOWN;
151 status = dev->write_block(dev, func, block,
154 status = MAPLE_RESP_ACK;
158 status = MAPLE_ERR_CMD_UNKNOWN;
160 return_buf[0] = status;
161 return_buf[1] = send_addr;
162 return_buf[2] = recv_addr;
164 return_buf[2] |= maple_periph_mask[port];
165 return_buf[3] = out_length;
167 buf += 12 + (length<<2);
169 asic_event( EVENT_MAPLE_DMA );
173 void maple_attach_device( maple_device_t dev, unsigned int port,
174 unsigned int periph ) {
176 assert( periph < 6 );
178 if( maple_devices[port][periph] != NULL ) {
179 /* Detach existing peripheral first */
180 maple_detach_device( port, periph );
183 maple_devices[port][periph] = dev;
185 maple_periph_mask[port] |= (1<<(periph-1));
186 else maple_periph_mask[port] |= 0x20;
187 if( dev->attach != NULL ) {
192 void maple_detach_device( unsigned int port, unsigned int periph ) {
194 assert( periph < 6 );
196 maple_device_t dev = maple_devices[port][periph];
197 if( dev == NULL ) /* already detached */
199 maple_devices[port][periph] = NULL;
200 if( dev->detach != NULL ) {
204 /* If we detach the main peripheral, we also have to detach all the
205 * subperipherals, or the system could get quite confused
208 maple_periph_mask[port] = 0;
209 for( i=1; i<6; i++ ) {
210 maple_detach_device(port,i);
213 maple_periph_mask[port] &= (~(1<<(periph-1)));
.