picodrive/Pico/cd/LC89510.c
notaz cc68a136aa initial import
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@2 be3aeb3a-fb24-0410-a615-afba39da0efa
2006-12-19 20:53:21 +00:00

658 lines
15 KiB
C

#if 0
#include <stdio.h>
#include <windows.h>
#include "misc.h"
#include "lc89510.h"
#include "cd_aspi.h"
#include "Star_68k.h"
#include "mem_S68k.h"
#include "pcm.h"
#endif
#include "../PicoInt.h"
#define cdprintf printf
//#define cdprintf(x...)
#define CDC_DMA_SPEED 256
int CDC_Decode_Reg_Read;
static int Status_CDC; // internal status
static void CDD_Reset(void)
{
// Reseting CDD
memset(Pico_mcd->s68k_regs+0x34, 0, 2*2); // CDD.Fader, CDD.Control
Pico_mcd->cdd.Status = 0;
Pico_mcd->cdd.Minute = 0;
Pico_mcd->cdd.Seconde = 0;
Pico_mcd->cdd.Frame = 0;
Pico_mcd->cdd.Ext = 0;
// clear receive status and transfer command
memset(Pico_mcd->s68k_regs+0x38, 0, 20);
Pico_mcd->s68k_regs[0x38+9] = 0xF; // Default checksum
}
static void CDC_Reset(void)
{
// Reseting CDC
memset(Pico_mcd->cdc.Buffer, 0, (16 * 1024 * 2) + 2352);
CDC_Update_Header();
Pico_mcd->cdc.COMIN = 0;
Pico_mcd->cdc.IFSTAT = 0xFF;
Pico_mcd->cdc.DAC.N = 0;
Pico_mcd->cdc.DBC.N = 0;
Pico_mcd->cdc.HEAD.N = 0x01000000;
Pico_mcd->cdc.PT.N = 0;
Pico_mcd->cdc.WA.N = 2352 * 2;
Pico_mcd->cdc.STAT.N = 0x00000080;
Pico_mcd->cdc.SBOUT = 0;
Pico_mcd->cdc.IFCTRL = 0;
Pico_mcd->cdc.CTRL.N = 0;
CDC_Decode_Reg_Read = 0;
Status_CDC = 0;
}
void LC89510_Reset(void)
{
CDD_Reset();
CDC_Reset();
Pico_mcd->cdc.Host_Data = 0;
Pico_mcd->cdc.DMA_Adr = 0;
Pico_mcd->cdc.Stop_Watch = 0;
}
#if 0 // TODO
void Update_CDC_TRansfer(void)
{
unsigned int i, dep, lenght, add_dest;
unsigned char *dest;
if ((Status_CDC & 0x08) == 0) return;
switch(Pico_mcd->s68k_regs[4] & 7)
{
case 0x0200: // MAIN CPU
case 0x0300: // SUB CPU
Pico_mcd->s68k_regs[4] |= 0x40; // Data ready in host port
return;
case 0x0400: // PCM RAM
dest = (unsigned char *) Ram_PCM;
dep = ((Pico_mcd->cdc.DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;
add_dest = 2;
break;
case 0x0500: // PRG RAM
dest = (unsigned char *) Ram_Prg;
dep = (Pico_mcd->cdc.DMA_Adr & 0xFFFF) << 3;
add_dest = 2;
// cdprintf("DMA transfer PRG RAM : adr = %.8X ", dep);
break;
case 0x0700: // WORD RAM
if (Ram_Word_State >= 2)
{
dest = (unsigned char *) Ram_Word_1M;
add_dest = 2;
if (Ram_Word_State & 1) dep = ((Pico_mcd->cdc.DMA_Adr & 0x3FFF) << 3);
else dep = ((Pico_mcd->cdc.DMA_Adr & 0x3FFF) << 3) + 0x20000;
}
else
{
dest = (unsigned char *) Ram_Word_2M;
dep = ((Pico_mcd->cdc.DMA_Adr & 0x7FFF) << 3);
add_dest = 2;
}
break;
default:
return;
}
if (Pico_mcd->cdc.DBC.N <= (CDC_DMA_SPEED * 2))
{
lenght = (Pico_mcd->cdc.DBC.N + 1) >> 1;
Status_CDC &= ~0x08; // Last transfer
Pico_mcd->s68k_regs[4] |= 0x80; // End data transfer
Pico_mcd->s68k_regs[4] &= ~0x40; // no more data ready
Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress
if (Pico_mcd->cdc.IFCTRL & 0x40) // DTEIEN = Data Trasnfer End Interrupt Enable ?
{
Pico_mcd->cdc.IFSTAT &= ~0x40;
if (Int_Mask_S68K & 0x20) sub68k_interrupt(5, -1);
cdprintf("CDC - DTE interrupt\n");
}
}
else lenght = CDC_DMA_SPEED;
// cdprintf("DMA lenght = %.4X\n", lenght);
if ((Pico_mcd->s68k_regs[4] & 7) == 4) // PCM DMA
{
__asm
{
mov ecx, lenght
mov edi, dest
lea esi, Pico_mcd->cdc.Buffer
add edi, dep
add esi, Pico_mcd->cdc.DAC.N
mov ebx, add_dest
Loop_DMA_PCM:
mov ax, [esi]
add esi, 2
mov [edi], ax
add edi, ebx
dec ecx
jnz Loop_DMA_PCM
}
lenght <<= 1;
Pico_mcd->cdc.DMA_Adr += lenght >> 2;
}
else // OTHER DMA
{
__asm
{
mov ecx, lenght
mov edi, dest
lea esi, Pico_mcd->cdc.Buffer
add edi, dep
add esi, Pico_mcd->cdc.DAC.N
mov ebx, add_dest
Loop_DMA:
mov ax, [esi]
add esi, 2
rol ax, 8
mov [edi], ax
add edi, ebx
dec ecx
jnz Loop_DMA
}
lenght <<= 1;
Pico_mcd->cdc.DMA_Adr += lenght >> 3;
}
Pico_mcd->cdc.DAC.N = (Pico_mcd->cdc.DAC.N + lenght) & 0xFFFF;
if (Status_CDC & 0x08) Pico_mcd->cdc.DBC.N -= lenght;
else Pico_mcd->cdc.DBC.N = 0;
}
#endif
unsigned short Read_CDC_Host(int is_sub)
{
int addr;
if (!(Status_CDC & 0x08))
{
// Transfer data disabled
return 0;
}
if ((is_sub && (Pico_mcd->s68k_regs[4] & 7) != 3) ||
(!is_sub && (Pico_mcd->s68k_regs[4] & 7) != 2))
{
// Wrong setting
return 0;
}
Pico_mcd->cdc.DBC.N -= 2;
if (Pico_mcd->cdc.DBC.N <= 0)
{
Pico_mcd->cdc.DBC.N = 0;
Status_CDC &= ~0x08; // Last transfer
Pico_mcd->s68k_regs[4] |= 0x80; // End data transfer
Pico_mcd->s68k_regs[4] &= ~0x40; // no more data ready
Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress
if (Pico_mcd->cdc.IFCTRL & 0x40) // DTEIEN = Data Transfer End Interrupt Enable ?
{
Pico_mcd->cdc.IFSTAT &= ~0x40;
if (Pico_mcd->s68k_regs[0x33]&(1<<5)) {
dprintf("m68k: s68k irq 5");
SekInterruptS68k(5);
}
cdprintf("CDC - DTE interrupt\n");
}
}
addr = Pico_mcd->cdc.DAC.N;
Pico_mcd->cdc.DAC.N += 2;
return (Pico_mcd->cdc.Buffer[addr]<<8) | Pico_mcd->cdc.Buffer[addr+1];
#if 0
__asm
{
mov esi, Pico_mcd->cdc.DAC.N
lea ebx, Pico_mcd->cdc.Buffer
// and esi, 0x3FFF
mov ax, [ebx + esi]
add esi, 2
rol ax, 8
mov Pico_mcd->cdc.DAC.N, esi
mov val, ax
}
#endif
}
void CDC_Update_Header(void)
{
if (Pico_mcd->cdc.CTRL.B.B1 & 0x01) // Sub-Header wanted ?
{
Pico_mcd->cdc.HEAD.B.B0 = 0;
Pico_mcd->cdc.HEAD.B.B1 = 0;
Pico_mcd->cdc.HEAD.B.B2 = 0;
Pico_mcd->cdc.HEAD.B.B3 = 0;
}
else
{
_msf MSF;
LBA_to_MSF(Pico_mcd->scd.Cur_LBA, &MSF);
Pico_mcd->cdc.HEAD.B.B0 = INT_TO_BCDB(MSF.M);
Pico_mcd->cdc.HEAD.B.B1 = INT_TO_BCDB(MSF.S);
Pico_mcd->cdc.HEAD.B.B2 = INT_TO_BCDB(MSF.F);
Pico_mcd->cdc.HEAD.B.B3 = 0x01;
}
}
unsigned char CDC_Read_Reg(void)
{
unsigned char ret;
cdprintf("CDC read reg %.2d = ", Pico_mcd->s68k_regs[5] & 0xF);
switch(Pico_mcd->s68k_regs[5] & 0xF)
{
case 0x0: // COMIN
cdprintf("%.2X\n", Pico_mcd->cdc.COMIN);
Pico_mcd->s68k_regs[5] = 0x1;
return Pico_mcd->cdc.COMIN;
case 0x1: // IFSTAT
cdprintf("%.2X\n", Pico_mcd->cdc.IFSTAT);
CDC_Decode_Reg_Read |= (1 << 1); // Reg 1 (decoding)
Pico_mcd->s68k_regs[5] = 0x2;
return Pico_mcd->cdc.IFSTAT;
case 0x2: // DBCL
cdprintf("%.2X\n", Pico_mcd->cdc.DBC.B.L);
Pico_mcd->s68k_regs[5] = 0x3;
return Pico_mcd->cdc.DBC.B.L;
case 0x3: // DBCH
cdprintf("%.2X\n", Pico_mcd->cdc.DBC.B.H);
Pico_mcd->s68k_regs[5] = 0x4;
return Pico_mcd->cdc.DBC.B.H;
case 0x4: // HEAD0
cdprintf("%.2X\n", Pico_mcd->cdc.HEAD.B.B0);
CDC_Decode_Reg_Read |= (1 << 4); // Reg 4 (decoding)
Pico_mcd->s68k_regs[5] = 0x5;
return Pico_mcd->cdc.HEAD.B.B0;
case 0x5: // HEAD1
cdprintf("%.2X\n", Pico_mcd->cdc.HEAD.B.B1);
CDC_Decode_Reg_Read |= (1 << 5); // Reg 5 (decoding)
Pico_mcd->s68k_regs[5] = 0x6;
return Pico_mcd->cdc.HEAD.B.B1;
case 0x6: // HEAD2
cdprintf("%.2X\n", Pico_mcd->cdc.HEAD.B.B2);
CDC_Decode_Reg_Read |= (1 << 6); // Reg 6 (decoding)
Pico_mcd->s68k_regs[5] = 0x7;
return Pico_mcd->cdc.HEAD.B.B2;
case 0x7: // HEAD3
cdprintf("%.2X\n", Pico_mcd->cdc.HEAD.B.B3);
CDC_Decode_Reg_Read |= (1 << 7); // Reg 7 (decoding)
Pico_mcd->s68k_regs[5] = 0x8;
return Pico_mcd->cdc.HEAD.B.B3;
case 0x8: // PTL
cdprintf("%.2X\n", Pico_mcd->cdc.PT.B.L);
CDC_Decode_Reg_Read |= (1 << 8); // Reg 8 (decoding)
Pico_mcd->s68k_regs[5] = 0x9;
return Pico_mcd->cdc.PT.B.L;
case 0x9: // PTH
cdprintf("%.2X\n", Pico_mcd->cdc.PT.B.H);
CDC_Decode_Reg_Read |= (1 << 9); // Reg 9 (decoding)
Pico_mcd->s68k_regs[5] = 0xA;
return Pico_mcd->cdc.PT.B.H;
case 0xA: // WAL
cdprintf("%.2X\n", Pico_mcd->cdc.WA.B.L);
Pico_mcd->s68k_regs[5] = 0xB;
return Pico_mcd->cdc.WA.B.L;
case 0xB: // WAH
cdprintf("%.2X\n", Pico_mcd->cdc.WA.B.H);
Pico_mcd->s68k_regs[5] = 0xC;
return Pico_mcd->cdc.WA.B.H;
case 0xC: // STAT0
cdprintf("%.2X\n", Pico_mcd->cdc.STAT.B.B0);
CDC_Decode_Reg_Read |= (1 << 12); // Reg 12 (decoding)
Pico_mcd->s68k_regs[5] = 0xD;
return Pico_mcd->cdc.STAT.B.B0;
case 0xD: // STAT1
cdprintf("%.2X\n", Pico_mcd->cdc.STAT.B.B1);
CDC_Decode_Reg_Read |= (1 << 13); // Reg 13 (decoding)
Pico_mcd->s68k_regs[5] = 0xE;
return Pico_mcd->cdc.STAT.B.B1;
case 0xE: // STAT2
cdprintf("%.2X\n", Pico_mcd->cdc.STAT.B.B2);
CDC_Decode_Reg_Read |= (1 << 14); // Reg 14 (decoding)
Pico_mcd->s68k_regs[5] = 0xF;
return Pico_mcd->cdc.STAT.B.B2;
case 0xF: // STAT3
cdprintf("%.2X\n", Pico_mcd->cdc.STAT.B.B3);
ret = Pico_mcd->cdc.STAT.B.B3;
Pico_mcd->cdc.IFSTAT |= 0x20; // decoding interrupt flag cleared
if ((Pico_mcd->cdc.CTRL.B.B0 & 0x80) && (Pico_mcd->cdc.IFCTRL & 0x20))
{
if ((CDC_Decode_Reg_Read & 0x73F2) == 0x73F2)
Pico_mcd->cdc.STAT.B.B3 = 0x80;
}
return ret;
}
return 0;
}
void CDC_Write_Reg(unsigned char Data)
{
cdprintf("CDC write reg%d = %.2X\n", Pico_mcd->s68k_regs[5] & 0xF, Data);
switch (Pico_mcd->s68k_regs[5] & 0xF)
{
case 0x0: // SBOUT
Pico_mcd->s68k_regs[5] = 0x1;
Pico_mcd->cdc.SBOUT = Data;
break;
case 0x1: // IFCTRL
Pico_mcd->s68k_regs[5] = 0x2;
Pico_mcd->cdc.IFCTRL = Data;
if ((Pico_mcd->cdc.IFCTRL & 0x02) == 0) // Stop data transfer
{
Pico_mcd->cdc.DBC.N = 0;
Status_CDC &= ~0x08;
Pico_mcd->cdc.IFSTAT |= 0x08; // No more data transfer in progress
}
break;
case 0x2: // DBCL
Pico_mcd->s68k_regs[5] = 0x3;
Pico_mcd->cdc.DBC.B.L = Data;
break;
case 0x3: // DBCH
Pico_mcd->s68k_regs[5] = 0x4;
Pico_mcd->cdc.DBC.B.H = Data;
break;
case 0x4: // DACL
Pico_mcd->s68k_regs[5] = 0x5;
Pico_mcd->cdc.DAC.B.L = Data;
break;
case 0x5: // DACH
Pico_mcd->s68k_regs[5] = 0x6;
Pico_mcd->cdc.DAC.B.H = Data;
break;
case 0x6: // DTTRG
if (Pico_mcd->cdc.IFCTRL & 0x02) // Data transfer enable ?
{
Pico_mcd->cdc.IFSTAT &= ~0x08; // Data transfer in progress
Status_CDC |= 0x08; // Data transfer in progress
Pico_mcd->s68k_regs[4] &= 0x7F; // A data transfer start
cdprintf("\n************** Starting Data Transfer ***********\n");
cdprintf("RS0 = %.4X DAC = %.4X DBC = %.4X DMA adr = %.4X\n\n", Pico_mcd->s68k_regs[4]<<8,
Pico_mcd->cdc.DAC.N, Pico_mcd->cdc.DBC.N, Pico_mcd->cdc.DMA_Adr);
}
break;
case 0x7: // DTACK
Pico_mcd->cdc.IFSTAT |= 0x40; // end data transfer interrupt flag cleared
break;
case 0x8: // WAL
Pico_mcd->s68k_regs[5] = 0x9;
Pico_mcd->cdc.WA.B.L = Data;
break;
case 0x9: // WAH
Pico_mcd->s68k_regs[5] = 0xA;
Pico_mcd->cdc.WA.B.H = Data;
break;
case 0xA: // CTRL0
Pico_mcd->s68k_regs[5] = 0xB;
Pico_mcd->cdc.CTRL.B.B0 = Data;
break;
case 0xB: // CTRL1
Pico_mcd->s68k_regs[5] = 0xC;
Pico_mcd->cdc.CTRL.B.B1 = Data;
break;
case 0xC: // PTL
Pico_mcd->s68k_regs[5] = 0xD;
Pico_mcd->cdc.PT.B.L = Data;
break;
case 0xD: // PTH
Pico_mcd->s68k_regs[5] = 0xE;
Pico_mcd->cdc.PT.B.H = Data;
break;
case 0xE: // CTRL2
Pico_mcd->cdc.CTRL.B.B2 = Data;
break;
case 0xF: // RESET
CDC_Reset();
break;
}
}
static int bswapwrite(int a, unsigned short d)
{
*(unsigned short *)(Pico_mcd->s68k_regs + a) = (d>>8)|(d<<8);
return d + (d >> 8);
}
void CDD_Export_Status(void)
{
unsigned int csum;
csum = bswapwrite( 0x38+0, Pico_mcd->cdd.Status);
csum += bswapwrite( 0x38+2, Pico_mcd->cdd.Minute);
csum += bswapwrite( 0x38+4, Pico_mcd->cdd.Seconde);
csum += bswapwrite( 0x38+6, Pico_mcd->cdd.Frame);
Pico_mcd->s68k_regs[0x38+8] = Pico_mcd->cdd.Ext;
csum += Pico_mcd->cdd.Ext;
Pico_mcd->s68k_regs[0x38+9] = ~csum & 0xf;
Pico_mcd->s68k_regs[0x36] &= 3; // CDD.Control
if (Pico_mcd->s68k_regs[0x33] & (1<<4))
{
dprintf("cdd export irq 4");
SekInterruptS68k(4);
}
cdprintf("CDD exported status\n");
cdprintf("Status =%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X\n",
(Pico_mcd->s68k_regs[0x38+0] << 8) | Pico_mcd->s68k_regs[0x38+1],
(Pico_mcd->s68k_regs[0x38+2] << 8) | Pico_mcd->s68k_regs[0x38+3],
(Pico_mcd->s68k_regs[0x38+4] << 8) | Pico_mcd->s68k_regs[0x38+5],
(Pico_mcd->s68k_regs[0x38+6] << 8) | Pico_mcd->s68k_regs[0x38+7],
(Pico_mcd->s68k_regs[0x38+8] << 8) | Pico_mcd->s68k_regs[0x38+9]);
}
void CDD_Import_Command(void)
{
cdprintf("CDD importing command\n");
cdprintf("Command=%.4X, Minute=%.4X, Second=%.4X, Frame=%.4X Checksum=%.4X\n",
(Pico_mcd->s68k_regs[0x38+10+0] << 8) | Pico_mcd->s68k_regs[0x38+10+1],
(Pico_mcd->s68k_regs[0x38+10+2] << 8) | Pico_mcd->s68k_regs[0x38+10+3],
(Pico_mcd->s68k_regs[0x38+10+4] << 8) | Pico_mcd->s68k_regs[0x38+10+5],
(Pico_mcd->s68k_regs[0x38+10+6] << 8) | Pico_mcd->s68k_regs[0x38+10+7],
(Pico_mcd->s68k_regs[0x38+10+8] << 8) | Pico_mcd->s68k_regs[0x38+10+9]);
switch (Pico_mcd->s68k_regs[0x38+10+0])
{
case 0x0: // STATUS (?)
Get_Status_CDD_c0();
break;
case 0x1: // STOP ALL (?)
Stop_CDD_c1();
break;
case 0x2: // GET TOC INFORMATIONS
switch(Pico_mcd->s68k_regs[0x38+10+3])
{
case 0x0: // get current position (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00);
Get_Pos_CDD_c20();
break;
case 0x1: // get elapsed time of current track played/scanned (relative MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 1;
Get_Track_Pos_CDD_c21();
break;
case 0x2: // get current track in RS2-RS3
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 2;
Get_Current_Track_CDD_c22();
break;
case 0x3: // get total lenght (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 3;
Get_Total_Lenght_CDD_c23();
break;
case 0x4: // first & last track number
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 4;
Get_First_Last_Track_CDD_c24();
break;
case 0x5: // get track addresse (MSF format)
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 5;
Get_Track_Adr_CDD_c25();
break;
default : // invalid, then we return status
Pico_mcd->cdd.Status = (Pico_mcd->cdd.Status & 0xFF00) | 0xF;
Get_Status_CDD_c0();
break;
}
break;
case 0x3: // READ
Play_CDD_c3();
break;
case 0x4: // SEEK
Seek_CDD_c4();
break;
case 0x6: // PAUSE/STOP
Pause_CDD_c6();
break;
case 0x7: // RESUME
Resume_CDD_c7();
break;
case 0x8: // FAST FOWARD
Fast_Foward_CDD_c8();
break;
case 0x9: // FAST REWIND
Fast_Rewind_CDD_c9();
break;
case 0xA: // RECOVER INITIAL STATE (?)
CDD_cA();
break;
case 0xC: // CLOSE TRAY
Close_Tray_CDD_cC();
break;
case 0xD: // OPEN TRAY
Open_Tray_CDD_cD();
break;
default: // UNKNOWN
CDD_Def();
break;
}
}