summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/dccons.c
blob: d516fabda288198b66719613fb503a310a3d8e63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*

    dc.c - Sega Dreamcast hardware

    MESS (DC home console) hardware overrides (GD-ROM drive etc)

    c230048 - 5 is written, want 6
    c0d9d9e - where bad happens, from routine @ c0da260

    c0d9d8e - R0 on return is the value to put in

    cfffee0 - stack location when bad happens

    TODO:
    - gdrom_alt_status is identical to normal status except that "but it does not clear DMA status information when it is accessed"

*/

#include "emu.h"
#include "cdrom.h"
#include "debugger.h"
#include "includes/dc.h"
#include "cpu/sh4/sh4.h"
#include "sound/aica.h"
#include "includes/dccons.h"

#define ATAPI_CYCLES_PER_SECTOR (5000)  // TBD for Dreamcast

WRITE_LINE_MEMBER(dc_cons_state::ata_interrupt)
{
	if (state)
		dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM;
	else
		dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_GDROM;

	dc_update_interrupt_status();
}

TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end )
{
	UINT8 sector_buffer[ 4096 ];

	atapi_timer->adjust(attotime::never);

	printf("atapi_xfer_end atapi_xferlen = %d\n", atapi_xferlen );

	//osd_printf_debug("ATAPI: xfer_end.  xferlen = %d\n", atapi_xferlen);

	m_ata->write_dmack(1);

	while (atapi_xferlen > 0 )
	{
		struct sh4_ddt_dma ddtdata;

		// get a sector from the SCSI device
		for (int i = 0; i < 2048/2; i++)
		{
			int d = m_ata->read_dma();
			sector_buffer[ i*2 ] = d & 0xff;
			sector_buffer[ (i*2)+1 ] = d >> 8;
		}

		atapi_xferlen -= 2048;

		// perform the DMA
		ddtdata.destination = atapi_xferbase;   // destination address
		ddtdata.length = 2048/4;
		ddtdata.size = 4;
		ddtdata.buffer = sector_buffer;
		ddtdata.direction=1;    // 0 source to buffer, 1 buffer to destination
		ddtdata.channel= 0;
		ddtdata.mode= -1;       // copy from/to buffer
		printf("ATAPI: DMA one sector to %x, %x remaining\n", atapi_xferbase, atapi_xferlen);
		m_maincpu->sh4_dma_ddt(&ddtdata);

		atapi_xferbase += 2048;
	}

	m_ata->write_dmack(0);

	g1bus_regs[SB_GDST]=0;
	dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM;
	dc_update_interrupt_status();
}

void dc_cons_state::dreamcast_atapi_init()
{
	atapi_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_cons_state::atapi_xfer_end),this));
	atapi_timer->adjust(attotime::never);
	save_item(NAME(atapi_xferlen));
	save_item(NAME(atapi_xferbase));
}

/*

 GDROM regsters:

 5f7018: alternate status/device control
 5f7080: data
 5f7084: error/features
 5f7088: interrupt reason/sector count
 5f708c: sector number
 5f7090: byte control low
 5f7094: byte control high
 5f7098: drive select
 5f709c: status/command

c002910 - ATAPI packet writes
c002796 - aux status read after that
c000776 - DMA triggered to c008000

*/

READ32_MEMBER(dc_cons_state::dc_mess_g1_ctrl_r )
{
	switch(offset)
	{
		case SB_GDSTARD:
			printf("G1CTRL: GDSTARD %08x\n", atapi_xferbase); // Hello Kitty reads here
			debugger_break(machine());
			return atapi_xferbase;
		case SB_GDST:
			break;
		case SB_GDLEND:
			//debugger_break(machine());
			return atapi_xferlen; // TODO: check me
		default:
			printf("G1CTRL:  Unmapped read %08x\n", 0x5f7400+offset*4);
			debugger_break(machine());
	}
	return g1bus_regs[offset];
}

WRITE32_MEMBER(dc_cons_state::dc_mess_g1_ctrl_w )
{
	g1bus_regs[offset] = data; // 5f7400+reg*4=dat
//  osd_printf_verbose("G1CTRL: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x\n", 0x5f7400+reg*4, dat, data, offset, mem_mask);
	switch (offset)
	{
	case SB_GDST:
		if (data & 1 && g1bus_regs[SB_GDEN] == 1) // 0 -> 1
		{
			if (g1bus_regs[SB_GDDIR] == 0)
			{
				printf("G1CTRL: unsupported transfer\n");
				return;
			}

			atapi_xferbase = g1bus_regs[SB_GDSTAR];
			//atapi_timer->adjust(m_maincpu->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048))));
			/* 12x * 75 Hz = 0,00(1) secs per sector */
			/* TODO: make DMA to be single step */
			atapi_timer->adjust(attotime::from_usec(1111*atapi_xferlen/2048));
//          atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
		}
		break;

	case SB_GDLEN:
		atapi_xferlen = data;
		break;

	// The following is required to unlock the GD-ROM. The original Japanese BIOS doesn't need it
	case GD_UNLOCK:
		if (data==0 || data==0x001fffff || data==0x42fe)
		{
//          atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80;
			printf("Unlocking GD-ROM! %x\n", data);
		}
		break;
	}
}