Add HD support. Seems to work but Mac crashes...

This commit is contained in:
Jeroen Domburg 2017-03-05 16:53:33 +08:00
parent af3b3f98cc
commit cec9a2763d
8 changed files with 350 additions and 13 deletions

View File

@ -1,6 +1,6 @@
TARGET:=tme TARGET:=tme
MUSASHI_GEN_SRC:=musashi/m68kops.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c MUSASHI_GEN_SRC:=musashi/m68kops.c musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) musashi/m68kcpu.o main.o emu.o disp.o iwm.o via.o rtc.o ncr.o OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) musashi/m68kcpu.o main.o emu.o disp.o iwm.o via.o rtc.o ncr.o hd.o
#musashi/m68kdasm.o #musashi/m68kdasm.o
CFLAGS=-Wall -I. -I./musashi -Og -ggdb `sdl2-config --cflags` CFLAGS=-Wall -I. -I./musashi -Og -ggdb `sdl2-config --cflags`
LDFLAGS=`sdl2-config --libs` LDFLAGS=`sdl2-config --libs`

View File

@ -2,7 +2,9 @@
#define TME_ROMSIZE (128*1024) #define TME_ROMSIZE (128*1024)
#define TME_RAMSIZE (512*1024) #define TME_RAMSIZE (4096*1024)
#define TME_SCREENBUF (TME_RAMSIZE-0x5900) #define TME_SCREENBUF (TME_RAMSIZE-0x5900)
#define TME_SCREENBUF_ALT (TME_RAMSIZE-0xd900) #define TME_SCREENBUF_ALT (TME_RAMSIZE-0xD900)

10
emu.c
View File

@ -13,6 +13,7 @@
#include "via.h" #include "via.h"
#include "rtc.h" #include "rtc.h"
#include "ncr.h" #include "ncr.h"
#include "hd.h"
unsigned char *macRom; unsigned char *macRom;
unsigned char *macRam; unsigned char *macRam;
@ -30,10 +31,13 @@ unsigned int m68k_read_memory_8(unsigned int address) {
} }
} else if (address >= 0x600000 && address < 0xA00000) { } else if (address >= 0x600000 && address < 0xA00000) {
ret=macRam[(address-0x600000) & (TME_RAMSIZE-1)]; ret=macRam[(address-0x600000) & (TME_RAMSIZE-1)];
} else if (address >= 0x400000 && address<0x41FFFF) { } else if (address >= 0x400000 && address<0x500000) {
int romAdr=address-0x400000; int romAdr=address-0x400000;
if (romAdr>=TME_ROMSIZE) printf("PC %x:Huh? Read from ROM mirror (%x)\n", pc, address); if (romAdr>=TME_ROMSIZE) {
printf("PC %x:Huh? Read from ROM mirror (%x)\n", pc, address);
} else {
ret=macRom[romAdr&(TME_ROMSIZE-1)]; ret=macRom[romAdr&(TME_ROMSIZE-1)];
}
} else if (address >= 0xE80000 && address < 0xf00000) { } else if (address >= 0xE80000 && address < 0xf00000) {
ret=viaRead((address>>9)&0xf); ret=viaRead((address>>9)&0xf);
} else if (address >= 0xc00000 && address < 0xe00000) { } else if (address >= 0xc00000 && address < 0xe00000) {
@ -88,6 +92,8 @@ void tmeStartEmu(void *rom) {
macRam=malloc(TME_RAMSIZE); macRam=malloc(TME_RAMSIZE);
for (int x=0; x<TME_RAMSIZE; x++) macRam[x]=0xaa; for (int x=0; x<TME_RAMSIZE; x++) macRam[x]=0xaa;
rom_remap=1; rom_remap=1;
SCSIDevice *hd=hdCreate("hd.img");
ncrRegisterDevice(6, hd);
viaClear(VIA_PORTA, 0x7F); viaClear(VIA_PORTA, 0x7F);
viaSet(VIA_PORTA, 0x80); viaSet(VIA_PORTA, 0x80);
m68k_init(); m68k_init();

72
hd.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "ncr.h"
#include "hd.h"
typedef struct {
FILE *f;
int size;
} HdPriv;
const uint8_t inq_resp[95]={
0, //HD
0, //0x80 if removable
0x49, //Obsolete SCSI standard 1 all the way
0, //response version etc
31, //extra data
0,0, //reserved
0, //features
'A','P','P','L','E',' ',' ',' ', //vendor id
'2','0','S','C',' ',' ',' ',' ', //prod id
'1','.','0',' ',' ',' ',' ',' ', //prod rev lvl
};
static int hdScsiCmd(SCSITransferData *data, unsigned int cmd, unsigned int len, unsigned int lba, void *arg) {
int ret=0;
HdPriv *hd=(HdPriv*)arg;
for (int x=0; x<32; x++) printf("%02X ", data->cmd[x]);
printf("\n");
if (cmd==0x8 || cmd==0x28) { //read
fseek(hd->f, lba*512, SEEK_SET);
fread(data->data, 512, len, hd->f);
printf("HD: Read %d bytes.\n", len*512);
ret=len*512;
} else if (cmd==0x12) { //inquiry
memcpy(data->data, inq_resp, sizeof(inq_resp));
return 95;
} else if (cmd==0x25) { //read capacity
int lbacnt=hd->size/512;
data->data[0]=(lbacnt>>24);
data->data[1]=(lbacnt>>16);
data->data[2]=(lbacnt>>8);
data->data[3]=(lbacnt>>0);
data->data[4]=0;
data->data[5]=0;
data->data[6]=2; //512
data->data[7]=0;
ret=8;
} else {
printf("********** hdScsiCmd: unrecognized command %x\n", cmd);
}
data->cmd[0]=0; //status
data->msg[0]=0;
return ret;
}
SCSIDevice *hdCreate(char *file) {
SCSIDevice *ret=malloc(sizeof(SCSIDevice));
memset(ret, 0, sizeof(SCSIDevice));
HdPriv *hd=malloc(sizeof(HdPriv));
memset(hd, 0, sizeof(HdPriv));
hd->f=fopen(file, "r+");
if (hd->f<=0) {
perror(file);
exit(0);
}
hd->size=fseek(hd->f, 0, SEEK_END);
ret->arg=hd;
ret->scsiCmd=hdScsiCmd;
return ret;
}

3
hd.h Normal file
View File

@ -0,0 +1,3 @@
#include "ncr.h"
SCSIDevice *hdCreate(char *file);

246
ncr.c
View File

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "ncr.h"
#include "m68k.h"
static const char* const regNamesR[]={ static const char* const regNamesR[]={
"CURSCSIDATA","INITIATORCMD", "MODE", "TARGETCMD", "CURSCSISTATUS", "CURSCSIDATA","INITIATORCMD", "MODE", "TARGETCMD", "CURSCSISTATUS",
@ -13,15 +14,248 @@ static const char* const regNamesW[]={
}; };
unsigned int ncrRead(unsigned int addr, unsigned int dack) { typedef struct {
unsigned int ret=0; SCSIDevice *dev[8];
uint8_t mode;
uint8_t tcr;
uint8_t dout;
uint8_t din;
uint8_t inicmd;
int selected;
int state;
uint8_t tcrforbuf;
SCSITransferData data;
uint8_t *buf;
int bufmax;
int bufpos;
int datalen;
} Ncr;
printf("SCSI: read %s val %x (dack %d)\n", regNamesR[addr], ret, dack); #define INIR_AIP (1<<6)
#define INIR_LA (1<<5)
#define INI_RST (1<<7)
#define INI_ACK (1<<4)
#define INI_BSY (1<<3)
#define INI_SEL (1<<2)
#define INI_ATN (1<<1)
#define INI_DBUS (1<<0)
#define SSR_RST (1<<7)
#define SSR_BSY (1<<6)
#define SSR_REQ (1<<5)
#define SSR_MSG (1<<4)
#define SSR_CD (1<<3)
#define SSR_IO (1<<2)
#define SSR_SEL (1<<1)
#define SSR_DBP (1<<0)
#define TCR_IO (1<<0)
#define TCR_CD (1<<1)
#define TCR_MSG (1<<2)
#define TCR_REQ (1<<3)
#define MODE_ARB (1<<0)
#define MODE_DMA (1<<1)
#define MODE_MONBSY (1<<2)
#define MODE_EIPINTEN (1<<3)
#define MODE_PARINTEN (1<<4)
#define MODE_PARCHK (1<<5)
#define MODE_TARGET (1<<6)
#define MODE_BDMA (1<<7)
#define BSR_ACK (1<<0)
#define BSR_ATN (1<<1)
#define BSR_BUSYERR (1<<2)
#define BSR_PHASEMATCH (1<<3)
#define BSR_IRQACT (1<<4)
#define BSR_PARERR (1<<5)
#define BSR_DMARQ (1<<6)
#define BSR_EODMA (1<<7)
#define ST_IDLE 0
#define ST_ARB 1
#define ST_ARBDONE 2
#define ST_SELECT 3
#define ST_SELDONE 4
#define ST_DATA 5
static const char* const stateNames[]={
"IDLE", "ARB", "ARBDONE", "SELECT", "SELDONE", "DATA"
};
static Ncr ncr;
static SCSIDevice mydev;
static void parseScsiCmd(int isRead) {
uint8_t *buf=ncr.data.cmd;
int cmd=buf[0];
int lba, len, ctrl;
if (cmd<0x20) {
lba=buf[3]|(buf[2]<<8)|((buf[1]&0x1F)<<16);
len=buf[4];
ctrl=buf[5];
} else if (cmd<0x60) {
lba=buf[5]|(buf[4]<<8)|(buf[3]<<16)|(buf[2]<<24);
len=buf[8]|(buf[7]<<8);
ctrl=buf[9];
} else {
printf("SCSI: UNSUPPORTED CMD %x\n", cmd);
return;
}
printf("SCSI: CMD %x LBA %x LEN %x CTRL %x\n", cmd, lba, len, ctrl);
if (ncr.dev[ncr.selected]) {
ncr.datalen=ncr.dev[ncr.selected]->scsiCmd(&ncr.data, cmd, len, lba, ncr.dev[ncr.selected]->arg);
}
}
unsigned int ncrRead(unsigned int addr, unsigned int dack) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
unsigned int ret=0;
if (addr==0) {
if (ncr.mode&MODE_DMA) {
if (ncr.tcr&TCR_IO) {
if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++];
// printf("Send next byte dma %d/%d\n", ncr.bufpos, ncr.datalen);
}
}
ret=ncr.din;
} else if (addr==1) {
// /rst s s /ack /bsy /sel /atn databus
ret=ncr.inicmd;
if (ncr.state==ST_ARB) {
ret|=INIR_AIP;
//We don't have a timer... just set arb to be done right now.
ncr.state=ST_ARBDONE;
}
} else if (addr==2) {
ret=ncr.mode;
} else if (addr==3) {
ret=ncr.tcr;
} else if (addr==4) {
ret=0;
if (ncr.inicmd&INI_RST) ret|=SSR_RST;
if (ncr.inicmd&INI_BSY) ret|=SSR_BSY;
if (ncr.inicmd&INI_SEL) ret|=SSR_SEL;
if (ncr.dev[ncr.selected] && (ncr.state==ST_SELDONE || ncr.state==ST_DATA)) {
// ret|=SSR_REQ;
ret|=SSR_BSY;
}
if (ncr.state==ST_DATA) {
if ((ncr.inicmd&INI_ACK)==0) {
ret|=SSR_REQ;
}
}
} else if (addr==5) {
ret=BSR_PHASEMATCH;
if (ncr.mode&MODE_DMA) {
ret|=BSR_DMARQ;
if (ncr.bufpos<ncr.datalen) {
} else {
printf("End of DMA reached: bufpos %d datalen %d\n", ncr.bufpos, ncr.datalen);
ret|=BSR_EODMA;
}
}
} else if (addr==6) {
ret=ncr.din;
} else if (addr==7) {
printf("!UNIMPLEMENTED!\n");
}
// printf("%08X SCSI: read %d (%s) val %x (dack %d), cur st %s\n", pc, addr, regNamesR[addr], ret, dack, stateNames[ncr.state]);
return ret; return ret;
} }
void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) { void ncrWrite(unsigned int addr, unsigned int dack, unsigned int val) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
printf("SCSI: write %s val %x (dack %d)\n", regNamesW[addr], val, dack); if (addr==0) {
ncr.dout=val;
} else if (addr==1) {
if ((val&INI_SEL) && (val&INI_DBUS) && (val&INI_BSY) && ncr.state==ST_ARBDONE) {
ncr.state=ST_SELECT;
if (ncr.dout==0x81) ncr.selected=0;
if (ncr.dout==0x82) ncr.selected=1;
if (ncr.dout==0x84) ncr.selected=2;
if (ncr.dout==0x88) ncr.selected=3;
if (ncr.dout==0x80) ncr.selected=4;
if (ncr.dout==0x90) ncr.selected=5;
if (ncr.dout==0xC0) ncr.selected=6;
printf("Selected dev: %d (val %x)\n", ncr.selected, ncr.dout);
}
if (((val&INI_BSY)==0) && ncr.state==ST_SELECT) {
ncr.state=ST_SELDONE;
}
if (((val&INI_SEL)==0) && ncr.state==ST_SELDONE) {
if (ncr.dev[ncr.selected]) {
ncr.state=ST_DATA;
} else {
ncr.state=ST_IDLE;
}
}
if (ncr.state==ST_DATA && ((ncr.inicmd&INI_ACK)==0) && (val&INI_ACK)) {
//We have an ack.
if (!(ncr.tcr&TCR_IO)) {
if (ncr.bufpos!=ncr.bufmax) ncr.buf[ncr.bufpos++]=ncr.dout;
}
}
if (ncr.state==ST_DATA && (ncr.inicmd&INI_ACK) && ((val&INI_ACK)==0)) {
//Ack line goes low..
if (ncr.tcr&TCR_IO) {
if (ncr.bufpos!=ncr.bufmax) ncr.din=ncr.buf[ncr.bufpos++];
printf("Send byte non-dma\n");
}
}
if (val&INI_RST) {
ncr.state=ST_IDLE;
}
ncr.inicmd&=~0x9F;
ncr.inicmd|=val&0x9f;
} else if (addr==2) {
ncr.mode=val;
if (val&1) ncr.state=ST_ARB;
} else if (addr==3) {
if (ncr.tcr!=(val&0xf)) {
int oldtcr=(ncr.tcr&7);
int newtcr=(val&7);
if (oldtcr==0 && ncr.bufpos) {
//End of data out phase
parseScsiCmd(1);
} else if ((oldtcr==TCR_CD) && (newtcr==TCR_IO)) {
//Start of data in phase
parseScsiCmd(0);
}
ncr.bufpos=0;
int type=val&(TCR_MSG|TCR_CD);
if (type==0) {
printf("Sel data buf %s.\n", (newtcr&TCR_IO)?"IN":"OUT");
ncr.buf=ncr.data.data;
ncr.bufmax=sizeof(ncr.data.data);
} else if (type==TCR_CD) {
printf("Sel cmd/status buf %s.\n", (newtcr&TCR_IO)?"IN":"OUT");
ncr.buf=ncr.data.cmd;
ncr.bufmax=sizeof(ncr.data.cmd);
ncr.datalen=1;
} else if (type==(TCR_CD|TCR_MSG)) {
printf("Sel msg buf %s.\n", (newtcr&TCR_IO)?"IN":"OUT");
ncr.buf=ncr.data.msg;
ncr.bufmax=sizeof(ncr.data.msg);
ncr.datalen=1;
}
ncr.din=ncr.buf[0];
}
ncr.tcr=val&0xf;
} else if (addr==4) {
printf("!UNIMPLEMENTED! selenable, todo\n");
} else if (addr==5) {
printf("!UNIMPLEMENTED!\n");
} else if (addr==6) {
printf("!UNIMPLEMENTED!\n");
} else if (addr==7) {
//Start DMA. We already do this using the mode bit.
}
// printf("%08X SCSI: write %d (%s) val %x (dack %d), cur state %s\n", pc, addr, regNamesW[addr], val, dack, stateNames[ncr.state]);
}
void ncrRegisterDevice(int id, SCSIDevice* dev){
ncr.dev[id]=dev;
} }

21
ncr.h
View File

@ -1,4 +1,25 @@
#ifndef NCR_H
#define NCR_H
#include <stdint.h>
typedef struct {
uint8_t cmd[128];
uint8_t data[1024*1024];
uint8_t msg[2];
int cmdlen;
int datalen;
int msglen;
} SCSITransferData;
typedef struct {
int (*scsiCmd)(SCSITransferData *data, unsigned int cmd, unsigned int len, unsigned int lba, void *arg);
void *arg;
} SCSIDevice;
void ncrInit();
void ncrRegisterDevice(int id, SCSIDevice* dev);
unsigned int ncrRead(unsigned int addr, unsigned int dack); unsigned int ncrRead(unsigned int addr, unsigned int dack);
void ncrWrite(unsigned int addr,unsigned int dack, unsigned int val); void ncrWrite(unsigned int addr,unsigned int dack, unsigned int val);
#endif

1
rtc.c
View File

@ -39,7 +39,6 @@ int rtcCom(int en, int dat, int clk) {
printf("RTC/PRAM CMD %x\n", rtc.cmd); printf("RTC/PRAM CMD %x\n", rtc.cmd);
} }
rtc.pos++; rtc.pos++;
printf("RTC/PRAM pos %d CMD %x\n", rtc.pos, rtc.cmd);
} }
} }
rtc.lastClkVal=clk; rtc.lastClkVal=clk;