/[gxemul]/upstream/0.4.6/src/devices/dev_dreamcast_gdrom.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.6/src/devices/dev_dreamcast_gdrom.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 8187 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: dev_dreamcast_gdrom.c,v 1.5 2007/06/15 19:11:15 debug Exp $
29 *
30 * COMMENT: Dreamcast GD-ROM
31 *
32 * TODO: This is just a dummy so far.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "cpu.h"
40 #include "device.h"
41 #include "diskimage.h"
42 #include "machine.h"
43 #include "memory.h"
44 #include "misc.h"
45
46 #include "dreamcast_sysasicvar.h"
47
48
49 /* #define debug fatal */
50
51 struct dreamcast_gdrom_data {
52 uint8_t busy; /* Busy status */
53 uint8_t stat; /* Status */
54 int cnt; /* Data length */
55 uint8_t cond;
56
57 int cmd_count;
58 uint8_t cmd[12];
59
60 uint8_t *data;
61 int data_len;
62 int cur_data_offset;
63 int cur_cnt;
64 };
65
66 /* Register offsets: */
67 #define GDROM_BUSY 0x18
68 #define GDROM_DATA 0x80
69 #define GDROM_REGX 0x84
70 #define GDROM_STAT 0x8c
71 #define GDROM_CNTLO 0x90
72 #define GDROM_CNTHI 0x94
73 #define GDROM_COND 0x9c
74
75 #define COND_DATA_AVAIL 0x08
76
77
78 static void alloc_data(struct dreamcast_gdrom_data *d)
79 {
80 d->data_len = d->cnt;
81
82 CHECK_ALLOCATION(d->data = malloc(d->data_len));
83 memset(d->data, 0, d->data_len);
84 }
85
86
87 static void handle_command(struct cpu *cpu, struct dreamcast_gdrom_data *d)
88 {
89 int64_t sector_nr, sector_count;
90 int i, res;
91
92 debug("[ GDROM cmd: ");
93 for (i=0; i<12; i++)
94 debug("%02x ", d->cmd[i]);
95 debug("(cnt=%i) ]\n", d->cnt);
96
97 if (d->data != NULL)
98 free(d->data);
99 d->data = NULL;
100 d->cur_data_offset = 0;
101 d->cur_cnt = 0;
102
103 switch (d->cmd[0]) {
104
105 case 0x14:
106 /* Read Table-Of-Contents: */
107 if (d->cnt != 408) {
108 fatal("GDROM Read TOC not 408 bytes?\n");
109 exit(1);
110 }
111 alloc_data(d);
112
113 /* TODO: Fill TOC in a better way */
114 d->data[99*4] = 1; /* First track */
115 d->data[100*4] = 2; /* Last track */
116
117 d->data[0*4] = 0x10; /* Track 1 */
118 d->data[1*4] = 0x10; /* Track 2 */
119 break;
120
121 case 0x30:
122 /* Read sectors: */
123 if (d->cmd[1] != 0x20) {
124 fatal("GDROM unimplemented data format 0x%02x\n",
125 d->cmd[1]);
126 exit(1);
127 }
128 sector_nr = d->cmd[2] * 65536 + d->cmd[3] * 256 + d->cmd[4];
129 sector_count = d->cmd[8] * 65536 + d->cmd[9] * 256 + d->cmd[10];
130 if (d->cnt == 0)
131 d->cnt = 65536;
132 alloc_data(d);
133 if (sector_count * 2048 != d->data_len) {
134 fatal("Huh? GDROM data_len=0x%x, but sector_count"
135 "=0x%x\n", (int)d->data_len, (int)sector_count);
136 exit(1);
137 }
138
139 {
140 if (sector_nr >= 1376810)
141 sector_nr -= 1376810;
142 sector_nr -= 150;
143 if (sector_nr > 1048576)
144 sector_nr -= 1048576;
145 /* printf("sector nr = %i\n", (int)sector_nr); */
146
147 if (sector_nr < 1000)
148 sector_nr += (diskimage_get_baseoffset(cpu->machine, 0, DISKIMAGE_IDE)
149 / 2048);
150 }
151
152 res = diskimage_access(cpu->machine, 0, DISKIMAGE_IDE,
153 0, sector_nr * 2048, d->data, d->data_len);
154 if (!res) {
155 fatal("GDROM: diskimage_access failed? TODO\n");
156 // exit(1);
157 }
158 break;
159
160 case 0x70:
161 /* Mount: (?) */
162 break;
163
164 default:fatal("GDROM handle_command: unimplemented command 0x%02x"
165 "\n", d->cmd[0]);
166 exit(1);
167 }
168
169 if (d->data != NULL)
170 d->cond |= COND_DATA_AVAIL;
171
172 if (d->cnt == 65536)
173 d->cnt = 32768;
174
175 SYSASIC_TRIGGER_EVENT(SYSASIC_EVENT_GDROM);
176 }
177
178
179 DEVICE_ACCESS(dreamcast_gdrom)
180 {
181 struct dreamcast_gdrom_data *d = (struct dreamcast_gdrom_data *) extra;
182 uint64_t idata = 0, odata = 0;
183
184 if (writeflag == MEM_WRITE)
185 idata = memory_readmax64(cpu, data, len);
186
187 switch (relative_addr) {
188
189 case GDROM_BUSY:
190 if (writeflag == MEM_READ) {
191 odata = d->busy;
192 } else {
193 fatal("Write to GDROM_BUSY?\n");
194 exit(1);
195 }
196 break;
197
198 case GDROM_DATA:
199 if (len != sizeof(uint16_t)) {
200 fatal("Non-16bit GDROM data access? TODO\n");
201 exit(1);
202 }
203
204 if (writeflag == MEM_READ) {
205 if (!(d->cond & COND_DATA_AVAIL)) {
206 fatal("Read from GDROM_DATA when no data"
207 " is available? TODO\n");
208 exit(1);
209 }
210 if (d->cur_data_offset < d->data_len) {
211 odata = d->data[d->cur_data_offset ++];
212 odata |= (d->data[d->cur_data_offset ++] << 8);
213 d->cur_cnt += 2;
214 if (d->cur_cnt >= d->cnt) {
215 if (d->cur_data_offset >= d->data_len) {
216 d->cond &= ~COND_DATA_AVAIL;
217 } else {
218 d->cnt = d->data_len -
219 d->cur_data_offset;
220 d->cur_cnt = 0;
221 }
222 SYSASIC_TRIGGER_EVENT(
223 SYSASIC_EVENT_GDROM);
224 }
225 } else {
226 fatal("Read too much from GDROM_DATA\n");
227 exit(1);
228 }
229 } else {
230 if (d->busy & 0x08) {
231 if (d->cmd_count >= 12) {
232 fatal("Too much GDROM_DATA?\n");
233 exit(1);
234 }
235 /* Add data to cmd: */
236 d->cmd[d->cmd_count++] = idata;
237 d->cmd[d->cmd_count++] = idata >> 8;
238 if (d->cmd_count == 12) {
239 d->busy &= ~0x08;
240 handle_command(cpu, d);
241 }
242 } else {
243 fatal("Write to GDROM_DATA, but not waiting"
244 " for data?\n");
245 exit(1);
246 }
247 }
248 break;
249
250 case GDROM_REGX:
251 if (writeflag == MEM_READ) {
252 fatal("Read from GDROM_REGX?\n");
253 exit(1);
254 } else {
255 /* NetBSD/dreamcast writes 0 here. */
256 if (idata != 0) {
257 fatal("Write to GDROM_REGX?\n");
258 exit(1);
259 }
260 }
261 break;
262
263 case GDROM_STAT:
264 if (writeflag == MEM_READ) {
265 odata = d->stat;
266 } else {
267 fatal("Write to GDROM_STAT?\n");
268 exit(1);
269 }
270 break;
271
272 case GDROM_CNTLO:
273 if (writeflag == MEM_READ) {
274 odata = d->cnt & 0xff;
275 } else {
276 d->cnt = (d->cnt & 0xff00) | (idata & 0xff);
277 }
278 break;
279
280 case GDROM_CNTHI:
281 if (writeflag == MEM_READ) {
282 odata = (d->cnt >> 8) & 0xff;
283 } else {
284 d->cnt = (d->cnt & 0x00ff) | ((idata & 0xff) << 8);
285 }
286 break;
287
288 case GDROM_COND:
289 if (writeflag == MEM_READ) {
290 odata = d->cond;
291 } else {
292 d->cond = idata;
293
294 /*
295 * NetBSD/dreamcast writes 0xa0 to GDROM_COND to
296 * start a command. It expects (BUSY & 0x88) to
297 * be 0x08 after writing to GDROM_COND, and STAT
298 * to be not equal to 6. NetBSD then sends 6
299 * 16-bit data words to GDROM_DATA.
300 */
301 if (idata == 0xa0) {
302 d->stat = 0; /* TODO */
303 d->busy |= 0x08;
304 d->cmd_count = 0;
305 } else {
306 fatal("dreamcast_gdrom: unimplemented "
307 "GDROM_COND = 0x%02x\n", (int)idata);
308 exit(1);
309 }
310 }
311 break;
312
313 default:if (writeflag == MEM_READ) {
314 fatal("[ dreamcast_gdrom: read from addr 0x%x ]\n",
315 (int)relative_addr);
316 } else {
317 fatal("[ dreamcast_gdrom: write to addr 0x%x: 0x%x ]\n",
318 (int)relative_addr, (int)idata);
319 }
320 exit(1);
321 }
322
323 if (writeflag == MEM_READ)
324 memory_writemax64(cpu, data, len, odata);
325
326 return 1;
327 }
328
329
330 DEVINIT(dreamcast_gdrom)
331 {
332 struct dreamcast_gdrom_data *d;
333
334 CHECK_ALLOCATION(d = malloc(sizeof(struct dreamcast_gdrom_data)));
335 memset(d, 0, sizeof(struct dreamcast_gdrom_data));
336
337 memory_device_register(devinit->machine->memory, devinit->name,
338 0x005f7000, 0x100, dev_dreamcast_gdrom_access, d,
339 DM_DEFAULT, NULL);
340
341 return 1;
342 }
343

  ViewVC Help
Powered by ViewVC 1.1.26