move DeclRom from NuBusFPGA to common

This commit is contained in:
Romain Dolbeau
2023-09-23 15:46:31 +02:00
parent b42abbd33a
commit 08bbcc21a1
33 changed files with 5822 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "DeclROM/ns816-declrom"]
path = DeclROM/ns816-declrom
url = https://github.com/jaoswald/ns816-declrom

11
DeclROM/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
vid_decl_rom.bin
vid_decl_rom.dir
vid_decl_rom.l
vid_decl_rom.o
vid_decl_rom.raw
vid_decl_rom.srec
*.bin
VidRom*
NuBusFPGADrvr*.s
NuBusFPGARAMDskDrvr*.s
*.o

56
DeclROM/DepVideo.inc Normal file
View File

@@ -0,0 +1,56 @@
.include "res.inc"
NuBusFPGAID = 0xC0
defMinorBase = 0 /* beginning */
defMinorLength = 0x800000 /* 8192 KiB */
Pages8s = 1
Pages4s = 1
Pages2s = 1
Pages1s = 1
Pages15s = 1
Pages24s = 1
defmBounds_Ls = 0
defmBounds_Ts = 0
defmBounds_Rs = HRES
defmBounds_Bs = VRES
defScrnRow = HRES
/* row bytes */
RB8s = HRES
RB4s = HRES/2
RB2s = HRES/4
RB1s = HRES/8
RB15s = HRES*2
RB24s = HRES*4
DrHwNuBusFPGA = 0xBEEF /* placeholder for GoboFB */
DrHwNuBusFPGADsk = 0xBEEE /* placeholder for RAM Dsk */
DrHwNuBusFPGAAudio = 0xBEED /* placeholder for Audio */
DrHwNuBusFPGASDCard = 0xBEEC /* placeholder for SD Card */
typeDrive = 0x1000 /* placeholder for RAM Dsk*/
typeAudio = 0x1001 /* placeholder for Audio*/
defmBaseOffset = 0 /* beginning, placeholder */
devVersion = 0 /* placeholder */
defmHRes = 0x480000 /* Horizontal Pixels/inch */
defmVRes = 0x480000 /* Vertical pixels/inch */
clutType = 0
directType = 2
defmPlaneBytes = 0 /* Offset from one plane to the next. */
SGammaResID = 0
ChunkyIndexed = 0
ChunkyDirect = 16
defVersion = 0 /* Version = 0 */

89
DeclROM/Makefile Normal file
View File

@@ -0,0 +1,89 @@
AS=/home/dolbeau/Retro68/build/toolchain/bin/m68k-apple-macos-as
CC=/home/dolbeau/Retro68/build/toolchain/bin/m68k-apple-macos-gcc
LD=/home/dolbeau/Retro68/build/toolchain/bin/m68k-apple-macos-ld
STRIP=/home/dolbeau/Retro68/build/toolchain/bin/m68k-apple-macos-strip
OBJCOPY=/home/dolbeau/Retro68/build/toolchain/bin/m68k-apple-macos-objcopy
HOSTCC=gcc
HOSTCFLAGS=-O2
ARCHFLAGS=-march=68020 -mcpu=68020
CFLAGS=-O2 -mpcrel
FEATURES=
TARGET=NUBUSFPGA
ifeq (${TARGET},NUBUSFPGA)
FEATURES+=-DNUBUSFPGA -DENABLE_RAMDSK -DENABLE_SDCARD -DENABLE_HDMIAUDIO
endif
ifeq (${TARGET},IISIFPGA)
FEATURES+=--DIISIFPGA DENABLE_HDMIAUDIO
endif
ifeq (${TARGET},QUADRAFPGA)
FEATURES+=-DQUADRAFPGA -DENABLE_HDMIAUDIO
endif
CFLAGS+=${FEATURES}
NS816DECLROMDIR=./ns816-declrom
NUBUS_CHECKSUM=${NS816DECLROMDIR}/nubus_checksum
PROCESS_ROM=${NS816DECLROMDIR}/process_rom
APPLEINCS=${NS816DECLROMDIR}/atrap.inc ${NS816DECLROMDIR}/declrom.inc ${NS816DECLROMDIR}/globals.inc
HRES=1920
VRES=1080
QEMU=no
ifeq ($(QEMU),yes)
CFLAGS+=-DQEMU
endif
CSRC_VIDEO=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c NuBusFPGAPrimaryInit_Primary.c NuBusFPGAPrimaryInit_RamInit.c NuBusFPGASecondaryInit_Secondary.c
CSRC_RAMDSK=NuBusFPGARAMDskDrvr_OpenClose.c NuBusFPGARAMDskDrvr_Ctrl.c NuBusFPGARAMDskDrvr_Prime.c NuBusFPGARAMDskDrvr_Status.c myrle.c
CSRC_SDCARD=NuBusFPGASDCardDrvr_OpenClose.c NuBusFPGASDCardDrvr_Ctrl.c NuBusFPGASDCardDrvr_Prime.c NuBusFPGASDCardDrvr_Status.c
CSRC=${CSRC_VIDEO} ${CSRC_RAMDSK} ${CSRC_SDCARD}
CSRC_ASM=${CSRC:.c=.s}
GEN_ASM=VidRomDef.s VidRomDir.s VidRomName.s VidRomRes.s VidRomRsrcDir.s
all: vid_decl_rom.bin
gen_mode: gen_mode.c
$(HOSTCC) -Wall ${HOSTCFLAGS} $^ -o $@
${GEN_ASM}: gen_mode
./gen_mode ${HRES} ${VRES}
$(NUBUS_CHECKSUM): ${NS816DECLROMDIR}/nubus_checksum.cc ${NS816DECLROMDIR}/nubus_crc.cc
g++ -std=c++11 $^ -lglog -lgflags -labsl_strings -o $@
vid_decl_rom.o: vid_decl_rom.s NuBusFPGADrvr.s NuBusFPGARAMDskDrvr.s ${APPLEINCS} DepVideo.inc ${GEN_ASM}
rm -f res.inc
echo -e "HRES=${HRES}\nVRES=${VRES}\n" | tee res.inc
${AS} ${ARCHFLAGS} -I${NS816DECLROMDIR} $< -o $@ -a > vid_decl_rom.l
myrle.o: myrle.c
${CC} ${ARCHFLAGS} ${CFLAGS} $< -c -o $@ -DSKIP_MAIN
dump_cpr.s: dump_cpr.c
${CC} ${ARCHFLAGS} ${CFLAGS} $< -S -o $@ -DSKIP_MAIN
sed -i -e 's/^\([^a-zA-Z0-9_]*\.globl.*\)/# --- \1/' $@
sed -i -e 's/\.\(L[0-9][0-9]*\)/.dump_cpr_\1/g' $@
%.o: %.c NuBusFPGADrvr.h
${CC} ${CFLAGS} $< -c -o $@ -DHRES=${HRES} -DVRES=${VRES}
vid_decl_rom.elf: linker.ld vid_decl_rom.o ${CSRC:.c=.o} # linker script must be first
${LD} -o $@ -T $^
vid_decl_rom.raw: vid_decl_rom.elf
${OBJCOPY} $^ $@ --input-target=elf32-m68k --output-target=binary
vid_decl_rom.bin: vid_decl_rom.raw $(NUBUS_CHECKSUM)
${NUBUS_CHECKSUM} --input_file $< --output_file $@ --output_size 32768
dd if=dump.cpr of=vid_decl_rom.bin bs=1 conv=notrunc
clean:
rm -f res.inc ${CSRC_ASM} *.o vid_decl_rom.srec vid_decl_rom.raw vid_decl_rom.dir vid_decl_rom.l VidRom*.s
append_romdir: append_romdir.c
${HOSTCC} $< -o $@

157
DeclROM/NuBusFPGADrvr.h Normal file
View File

@@ -0,0 +1,157 @@
#ifndef __NUBUSFPGADRVR_H__
#define __NUBUSFPGADRVR_H__
#include <Files.h>
#include <Devices.h>
#include <Slots.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Video.h>
#define GOBOFB_BASE 0x00900000
#define GOBOFB_ACCEL 0x00901000
#define GOBOFB_ACCEL_LE 0x00901800
//#define GOBOFB_REG_BASE 0x00900000
//#define GOBOFB_MEM_BASE 0x00000000 /* remapped to 0x8f800000 by HW */
#define GOBOFB_MODE 0x0
#define GOBOFB_VBL_MASK 0x4
#define GOBOFB_VIDEOCTRL 0x8
#define GOBOFB_INTR_CLEAR 0xc
#define GOBOFB_RESET 0x10
#define GOBOFB_LUT_ADDR 0x14
#define GOBOFB_LUT 0x18
#define GOBOFB_DEBUG 0x1c
//#define GOBOFB_CURSOR_LUT 0x20
//#define GOBOFB_CURSOR_XY 0x24
#define GOBOFB_HRES 0x40
#define GOBOFB_VRES 0x44
#define GOBOFB_HRES_START 0x48
#define GOBOFB_VRES_START 0x4C
#define GOBOFB_HRES_END 0x50
#define GOBOFB_VRES_END 0x54
//#define GOBOFB_MASK_BASE 0x80
//#define GOBOFB_BITS_BASE 0x100
#define GOBOFB_INTR_VBL 0x1
// for GOBOFB_MODE
#define GOBOFB_MODE_1BIT 0x0
#define GOBOFB_MODE_2BIT 0x1
#define GOBOFB_MODE_4BIT 0x2
#define GOBOFB_MODE_8BIT 0x3
#define GOBOFB_MODE_24BIT 0x10
#define GOBOFB_MODE_15BIT 0x11
#define u_int32_t volatile unsigned long
struct goblin_accel_regs {
u_int32_t reg_status; // 0
u_int32_t reg_cmd;
u_int32_t reg_r5_cmd;
u_int32_t resv0;
u_int32_t reg_width; // 4
u_int32_t reg_height;
u_int32_t reg_fgcolor;
u_int32_t resv2;
u_int32_t reg_bitblt_src_x; // 8
u_int32_t reg_bitblt_src_y;
u_int32_t reg_bitblt_dst_x;
u_int32_t reg_bitblt_dst_y;
u_int32_t reg_src_stride; // 12
u_int32_t reg_dst_stride;
u_int32_t reg_src_ptr; // 14
u_int32_t reg_dst_ptr;
};
// status
#define WORK_IN_PROGRESS_BIT 0
// cmd
#define DO_BLIT_BIT 0 // hardwired in goblin_accel.py
#define DO_FILL_BIT 1 // hardwired in goblin_accel.py
#define DO_TEST_BIT 3 // hardwired in goblin_accel.py
struct MyGammaTbl {
short gVersion; /*gamma version number*/
short gType; /*gamma data type*/
short gFormulaSize; /*Formula data size*/
short gChanCnt; /*number of channels of data*/
short gDataCnt; /*number of values/channel*/
short gDataWidth; /*bits/corrected value (data packed to next larger byte size)*/
char gFormulaData[3][256]; /*data for formulas followed by gamma values*/
};
#define nativeVidMode ((unsigned char)0x80)
/* alternate resolution in 0x81...0x8f */
#define diskResource ((unsigned char)0x90)
struct NuBusFPGADriverGlobals {
AuxDCEPtr dce; // unused
SlotIntQElement *siqel;
//unsigned char shadowClut[768];
unsigned short hres[16]; /* HW max in 0 */
unsigned short vres[16]; /* HW max in 0 */
unsigned short curPage;
unsigned char maxMode;
unsigned char curMode; /* mode ; this is resolution (which can't be changed in 7.1 except via reboot ?) */
unsigned char curDepth; /* depth */
char gray;
char irqen;
char slot;
struct MyGammaTbl gamma;
};
typedef struct NuBusFPGADriverGlobals NuBusFPGADriverGlobals;
typedef struct NuBusFPGADriverGlobals *NuBusFPGADriverGlobalsPtr;
typedef struct NuBusFPGADriverGlobals **NuBusFPGADriverGlobalsHdl;
typedef struct NuBusFPGAPramRecord { /* slot parameter RAM record, derived from SPRAMRecord */
short boardID; /* Apple-defined card ID */
char vendorUse1; /* reserved for vendor use */ /* DCDMF3 p210 says reserved for system ... */
unsigned char mode; /* vendorUse2 */
unsigned char depth; /* vendorUse3 */
unsigned char page; /* vendorUse4 */
char vendorUse5; /* reserved for vendor use */
char vendorUse6; /* reserved for vendor use */
} NuBusFPGAPramRecord;
typedef struct NuBusFPGAPramRecord *NuBusFPGAPramRecordPtr;
static inline void write_reg(AuxDCEPtr dce, unsigned int reg, unsigned int val) {
*((volatile unsigned int*)(dce->dCtlDevBase+GOBOFB_BASE+reg)) = val;
}
static inline unsigned int read_reg(AuxDCEPtr dce, unsigned int reg) {
return *((volatile unsigned int*)(dce->dCtlDevBase+GOBOFB_BASE+reg));;
}
/* ASM */
extern SlotIntServiceProcPtr interruptRoutine;
/* ctrl */
void linearGamma(NuBusFPGADriverGlobalsPtr dStore) __attribute__ ((section (".text.fbdriver")));
OSErr changeIRQ(AuxDCEPtr dce, char en, OSErr err) __attribute__ ((section (".text.fbdriver")));
OSErr cNuBusFPGACtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.fbdriver")));
OSErr reconfHW(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned short page) __attribute__ ((section (".text.fbdriver")));
OSErr updatePRAM(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned short page) __attribute__ ((section (".text.fbdriver")));
/* status */
OSErr cNuBusFPGAStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.fbdriver")));
/* open close */
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.fbdriver")));
OSErr cNuBusFPGAClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.fbdriver")));
/* primary init */
UInt32 Primary(SEBlock* block) __attribute__ ((section (".text.primary")));
int sdram_init(uint32_t a32) __attribute__ ((section (".text.primary")));
/* secondary init */
UInt32 Secondary(SEBlock* seblock) __attribute__ ((section (".text.secondary")));
#define Check32QDTrap 0xAB03
#if 0
static inline UInt32 revb(UInt32 d) {
return ((d&0xFFul)<<24) | ((d&0xFF00ul)<<8) | ((d&0xFF0000ul)>>8) | ((d&0xFF000000ul)>>24);
}
#else
#define revb(a) __builtin_bswap32(a)
#endif
#endif

23
DeclROM/NuBusFPGADrvr.s Normal file
View File

@@ -0,0 +1,23 @@
NuBusFPGADrvr:
.word 0x4c00 /* 0x4c00: ctl, status, needsLock [Devices.a] */
.word 0
.word 0
.word 0
/* Entry point offset table */
/* we can directly call the C version if it has the right calling convention */
.word cNuBusFPGAOpen-NuBusFPGADrvr /* open routine */
.word NuBusFPGADrvr-NuBusFPGADrvr /* no prime */
.word cNuBusFPGACtl-NuBusFPGADrvr /* control */
.word cNuBusFPGAStatus-NuBusFPGADrvr /* status */
.word cNuBusFPGAClose-NuBusFPGADrvr /* close */
_NuBusFPGATitle:
.byte _NuBusFPGATitle_StringEnd-.-1 /* pascal string length */
.ascii ".NuBusFPGA_Drvr"
_NuBusFPGATitle_StringEnd:
.word 0 /* version number */
/* for entry points: */
/* A0 pointer to driver parameter block */
/* A1 pointer to driver device control entry */
ALIGN 2

View File

@@ -0,0 +1,513 @@
#include "NuBusFPGADrvr.h"
void linearGamma(NuBusFPGADriverGlobalsPtr dStore) {
int i;
dStore->gamma.gVersion = 0;
dStore->gamma.gType = 0;
dStore->gamma.gFormulaSize = 0;
dStore->gamma.gChanCnt = 3;
dStore->gamma.gDataCnt = 256;
dStore->gamma.gDataWidth = 8;
for (i = 0 ; i < 256 ; i++) {
dStore->gamma.gFormulaData[0][i] = i;
dStore->gamma.gFormulaData[1][i] = i;
dStore->gamma.gFormulaData[2][i] = i;
}
}
OSErr changeIRQ(AuxDCEPtr dce, char en, OSErr err) {
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
char busMode = 1;
if (en != dStore->irqen) {
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0005); */
/* write_reg(dce, GOBOFB_DEBUG, en); */
if (en) {
if (SIntInstall(dStore->siqel, dce->dCtlSlot)) {
return err;
}
write_reg(dce, GOBOFB_DEBUG, 0x88888888);
write_reg(dce, GOBOFB_DEBUG, dStore->siqel);
write_reg(dce, GOBOFB_DEBUG, dStore->siqel->sqLink);
} else {
if (SIntRemove(dStore->siqel, dce->dCtlSlot)) {
return err;
}
}
SwapMMUMode ( &busMode );
write_reg(dce, GOBOFB_VBL_MASK, en ? GOBOFB_INTR_VBL : 0);
SwapMMUMode ( &busMode );
dStore->irqen = en;
}
return noErr;
}
/*
7.1.1:
11 Debug: 0x00000003
2 Debug: 0x00000004
1 Debug: 0x00000005
4 Debug: 0x00000006
1 <20>Debug: 0x00000002
7.5.3:
4 Debug: 0x00000002
12 Debug: 0x00000003
3 Debug: 0x00000004
5 Debug: 0x00000005
5 Debug: 0x00000006
5 Debug: 0x00000009
4 Debug: 0x0000000a
5 Debug: 0x00000010
1 <20>Debug: 0x00000002
8.1:
5 Debug: 0x00000002
9 Debug: 0x00000003
1 Debug: 0x00000004
6 Debug: 0x00000005
6 Debug: 0x00000006
4 Debug: 0x00000009
5 Debug: 0x0000000a
4 Debug: 0x00000010
1 <20>Debug: 0x00000002
*/
#pragma parameter __D0 cNuBusFPGACtl(__A0, __A1)
OSErr cNuBusFPGACtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
short ret = -1;
char busMode = 1;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0001); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
switch (pb->csCode)
{
case -1:
asm volatile(".word 0xfe16\n");
break;
case cscReset: /* 0x0 */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
dStore->curMode = nativeVidMode;
dStore->curDepth = kDepthMode1; /* 8-bit */
vPInfo->csMode = nativeVidMode;
vPInfo->csPage = 0;
vPInfo->csBaseAddr = 0;
ret = noErr;
}
break;
case cscKillIO: /* 0x1 */
asm volatile(".word 0xfe16\n");
ret = noErr;
break;
case cscSetMode: /* 0x2 */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
ret = reconfHW(dce, dStore->curMode, vPInfo->csMode, vPInfo->csPage);
if (ret == noErr)
vPInfo->csBaseAddr = (void*)(vPInfo->csPage * 1024 * 1024 * 4);
}
break;
case cscSetEntries: /* 0x3 */
if (1) {
VDSetEntryRecord **vdentry = (VDSetEntryRecord **)(long *)pb->csParam;
int csCount = (*vdentry)->csCount;
int csStart = (*vdentry)->csStart;
int i;
if (csCount <= 0) {
ret = noErr;
goto cscSetMode_done;
}
SwapMMUMode ( &busMode );
if (csStart < 0) {
for (i = 0 ; i <= csCount ; i++) {
unsigned char idx = ((*vdentry)->csTable[i].value & 0x0FF);
/* dStore->shadowClut[idx*3+0] = (*vdentry)->csTable[i].rgb.red; */
/* dStore->shadowClut[idx*3+1] = (*vdentry)->csTable[i].rgb.green; */
/* dStore->shadowClut[idx*3+2] = (*vdentry)->csTable[i].rgb.blue; */
write_reg(dce, GOBOFB_LUT_ADDR, 3 * idx);
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[0][(*vdentry)->csTable[i].rgb.red>>8 & 0xFF]);
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[1][(*vdentry)->csTable[i].rgb.green>>8 & 0xFF]);
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[2][(*vdentry)->csTable[i].rgb.blue>>8 & 0xFF]);
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.red); */
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.green); */
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.blue); */
}
} else {
write_reg(dce, GOBOFB_LUT_ADDR, 3 * (csStart & 0xFF));
for (i = 0 ; i <= csCount ; i++) {
/* dStore->shadowClut[(i+csStart)*3+0] = (*vdentry)->csTable[i].rgb.red; */
/* dStore->shadowClut[(i+csStart)*3+1] = (*vdentry)->csTable[i].rgb.green; */
/* dStore->shadowClut[(i+csStart)*3+2] = (*vdentry)->csTable[i].rgb.blue; */
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[0][(*vdentry)->csTable[i].rgb.red>>8 & 0xFF]);
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[1][(*vdentry)->csTable[i].rgb.green>>8 & 0xFF]);
write_reg(dce, GOBOFB_LUT, dStore->gamma.gFormulaData[2][(*vdentry)->csTable[i].rgb.blue>>8 & 0xFF]);
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.red); */
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.green); */
/* write_reg(dce, GOBOFB_LUT, (*vdentry)->csTable[i].rgb.blue); */
}
}
SwapMMUMode ( &busMode );
ret = noErr;
} else {
ret = noErr;
}
cscSetMode_done:
break;
case cscSetGamma: /* 0x4 */
{
VDGammaRecord *vdgamma = (VDGammaRecord *)*(long *)pb->csParam;
GammaTbl *gammaTbl = (GammaTbl*)vdgamma->csGTable;
int i;
if (gammaTbl == NULL) {
linearGamma(dStore);
} else {
ret = noErr;
if (gammaTbl->gDataWidth != 8)
ret = paramErr;
if (gammaTbl->gDataCnt != 256) // 8-bits
ret = paramErr;
if ((gammaTbl->gChanCnt != 1) && (gammaTbl->gChanCnt != 3))
ret = paramErr;
if ((gammaTbl->gType != 0) && (gammaTbl->gType != 0xFFFFBEEF))
ret = paramErr;
if (gammaTbl->gFormulaSize != 0)
ret = paramErr;
if (ret != noErr)
goto done;
dStore->gamma.gVersion = gammaTbl->gVersion;
dStore->gamma.gType = gammaTbl->gType;
dStore->gamma.gFormulaSize = gammaTbl->gFormulaSize;
dStore->gamma.gChanCnt = gammaTbl->gChanCnt;
dStore->gamma.gDataCnt = gammaTbl->gDataCnt;
dStore->gamma.gDataWidth = gammaTbl->gDataWidth;
int og, ob;
if (gammaTbl->gChanCnt == 1)
og = ob = 0;
else {
og = 256;
ob = 512;
}
for (i = 0 ; i < gammaTbl->gDataCnt ; i++) {
dStore->gamma.gFormulaData[0][i] = ((unsigned char*)gammaTbl->gFormulaData)[i + 0];
dStore->gamma.gFormulaData[1][i] = ((unsigned char*)gammaTbl->gFormulaData)[i + og];
dStore->gamma.gFormulaData[2][i] = ((unsigned char*)gammaTbl->gFormulaData)[i + ob];
}
}
ret = noErr;
}
break;
case cscGrayPage: /* 0x5 == cscGrayScreen */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
const uint8_t idx = dStore->curMode % 4; // checkme
UInt32 a32 = dce->dCtlDevBase;
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
const uint32_t wb = dStore->hres[0] >> idx;
unsigned short j, i;
short npage = (vPInfo->csMode == kDepthMode5) ? 1 : 2;
if (vPInfo->csPage >= npage) {
return paramErr;
goto done;
}
a32 += vPInfo->csPage * 1024 * 1024 * 4; /* fixme */
SwapMMUMode ( &busMode );
#if 0
if ((dStore->curMode != kDepthMode5) && (dStore->curMode != kDepthMode6)) {
/* grey the screen */
a32_l0 = a32;
a32_l1 = a32 + wb;
for (j = 0 ; j < dStore->vres[0] ; j+= 2) {
a32_4p0 = a32_l0;
a32_4p1 = a32_l1;
for (i = 0 ; i < wb ; i += 4) {
*((UInt32*)a32_4p0) = 0xFF00FF00;
*((UInt32*)a32_4p1) = 0x00FF00FF;
a32_4p0 += 4;
a32_4p1 += 4;
}
a32_l0 += 2*wb;
a32_l1 += 2*wb;
}
} else {
/* testing */
a32_l0 = a32;
a32_l1 = a32 + dStore->hres[0]*4;
for (j = 0 ; j < dStore->vres[0] ; j+= 2) {
a32_4p0 = a32_l0;
a32_4p1 = a32_l1;
for (i = 0 ; i < dStore->hres[0] ; i ++ ) {
*((UInt32*)a32_4p0) = (i&0xFF);//(i&0xFF) | (i&0xFF)<<8 | (i&0xff)<<24;
*((UInt32*)a32_4p1) = (i&0xFF)<<16;//(i&0xFF) | (i&0xFF)<<8 | (i&0xff)<<24;
a32_4p0 += 4;
a32_4p1 += 4;
}
a32_l0 += 2*dStore->hres[0]*4;
a32_l1 += 2*dStore->hres[0]*4;
}
}
#else
#define WAIT_FOR_HW_LE(accel_le) \
while (accel_le->reg_status & (1<<WORK_IN_PROGRESS_BIT))
const UInt32 fgcolor = 0; // FIXME: per-depth?
struct goblin_accel_regs* accel_le = (struct goblin_accel_regs*)(dce->dCtlDevBase+GOBOFB_ACCEL_LE);
WAIT_FOR_HW_LE(accel_le);
accel_le->reg_width = dStore->hres[dStore->curMode - nativeVidMode]; // pixels
accel_le->reg_height = dStore->vres[dStore->curMode - nativeVidMode];
accel_le->reg_bitblt_dst_x = 0; // pixels
accel_le->reg_bitblt_dst_y = 0;
accel_le->reg_dst_ptr = 0;
accel_le->reg_fgcolor = fgcolor;
accel_le->reg_cmd = (1<<DO_FILL_BIT);
WAIT_FOR_HW_LE(accel_le);
#undef WAIT_FOR_HW_LE
#endif
SwapMMUMode ( &busMode );
ret = noErr;
}
break;
case cscSetGray: /* 0x6 */
{
VDGrayRecord *vGInfo = (VDGrayRecord *)*(long *)pb->csParam;
dStore->gray = vGInfo->csMode;
ret = noErr;
}
break;
case cscSetInterrupt: /* 0x7 */
{
VDFlagRecord *vdflag = (VDFlagRecord *)*(long *)pb->csParam;
ret = changeIRQ(dce, 1 - vdflag->csMode, controlErr);
}
break;
case cscDirectSetEntries: /* 0x8 */
asm volatile(".word 0xfe16\n");
ret = controlErr;
break;
case cscSetDefaultMode: /* 0x9 */
{
VDDefMode *vddefm = (VDDefMode *)*(long *)pb->csParam;
ret = updatePRAM(dce, vddefm->csID, dStore->curDepth, 0);
}
break;
case cscSwitchMode: /* 0xa */
{
VDSwitchInfoRec *vdswitch = *(VDSwitchInfoRec **)(long *)pb->csParam;
ret = reconfHW(dce, vdswitch->csData, vdswitch->csMode, vdswitch->csPage);
if (ret == noErr)
vdswitch->csBaseAddr = (void*)(vdswitch->csPage * 1024 * 1024 * 4);
}
break;
/* cscSetSync */ /* 0xb */
/* 0xc ... 0xf : undefined */
case cscSavePreferredConfiguration: /* 0x10 */
{
VDSwitchInfoRec *vdswitch = *(VDSwitchInfoRec **)(long *)pb->csParam;
ret = updatePRAM(dce, vdswitch->csData, vdswitch->csMode, 0);
}
break;
/* 0x11 .. 0x15 : undefined */
/* cscSetHardwareCursor */ /* 0x16 */
/* cscDrawHardwareCursor */ /* 0x17 */
/* cscSetConvolution */ /* 0x18 */
/* cscSetPowerState */ /* 0x19 */
/* cscPrivateControlCall */ /* 0x1a */
/* 0x1b : undefined */
/* cscSetMultiConnect */ /* 0x1c */
/* cscSetClutBehavior */ /* 0x1d */
/* 0x1e : undefined */
/* cscSetDetailedTiming */ /* 0x1f */
/* 0x20 : undefined */
/* cscDoCommunication */ /* 0x21 */
/* cscProbeConnection */ /* 0x22 */
default: /* always return controlErr for unknown csCode */
asm volatile(".word 0xfe16\n");
ret = controlErr;
break;
}
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}
OSErr reconfHW(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned short page) {
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
const short npage = (depth == kDepthMode5) ? 1 : 2;
OSErr err = noErr;
char busMode = 1;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0031); */
/* write_reg(dce, GOBOFB_DEBUG, mode); */
/* write_reg(dce, GOBOFB_DEBUG, depth); */
/* write_reg(dce, GOBOFB_DEBUG, page); */
if ((mode == dStore->curMode) &&
(depth == dStore->curDepth) &&
(page == dStore->curPage)) {
return noErr;
}
if (page >= npage)
return paramErr;
if ((mode < nativeVidMode) ||
(mode > dStore->maxMode))
return paramErr;
switch (depth) {
case kDepthMode1:
break;
case kDepthMode2:
break;
case kDepthMode3:
break;
case kDepthMode4:
break;
case kDepthMode5:
break;
case kDepthMode6:
break;
default:
return paramErr;
}
SwapMMUMode ( &busMode );
if (mode != dStore->curMode) {
unsigned short i;
for (i = nativeVidMode ; i <= dStore->maxMode ; i++) {
// disable spurious resources, enable only the right one
SpBlock spb;
spb.spParamData = (i != mode ? 1 : 0); /* disable/enable */
spb.spSlot = dStore->slot;
spb.spID = i;
spb.spExtDev = 0;
SetSRsrcState(&spb);
}
dce->dCtlSlotId = mode; // where is that explained ? cscSwitchMode is not in DCDMF3, and you should'nt do that anymore says PDCD...
UInt8 id = mode - nativeVidMode;
unsigned int ho = ((dStore->hres[0] - dStore->hres[id]) / 2);
unsigned int vo = ((dStore->vres[0] - dStore->vres[id]) / 2);
/* write_reg(dce, GOBOFB_VIDEOCTRL, 0); */
write_reg(dce, GOBOFB_HRES_START, __builtin_bswap32(ho));
write_reg(dce, GOBOFB_VRES_START, __builtin_bswap32(vo));
write_reg(dce, GOBOFB_HRES_END, __builtin_bswap32(ho + dStore->hres[id]));
write_reg(dce, GOBOFB_VRES_END, __builtin_bswap32(vo + dStore->vres[id]));
/* write_reg(dce, GOBOFB_VIDEOCTRL, 1); */
}
if (depth != dStore->curDepth) {
switch (depth) {
case kDepthMode1:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_8BIT);
break;
case kDepthMode2:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_4BIT);
break;
case kDepthMode3:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_2BIT);
break;
case kDepthMode4:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_1BIT);
break;
case kDepthMode5:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_24BIT);
break;
case kDepthMode6:
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_15BIT);
break;
default:
SwapMMUMode ( &busMode );
return paramErr;
}
}
dStore->curMode = mode;
dStore->curDepth = depth;
dStore->curPage = page; /* FIXME: HW */
SwapMMUMode ( &busMode );
return err;
}
OSErr updatePRAM(AuxDCEPtr dce, unsigned char mode, unsigned char depth, unsigned short page) {
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
const short npage = (depth == kDepthMode5) ? 1 : 2;
SpBlock spb;
NuBusFPGAPramRecord pram;
OSErr err;
if (page >= npage)
return paramErr;
if ((mode < nativeVidMode) ||
(mode > dStore->maxMode))
return paramErr;
switch (depth) {
case kDepthMode1:
break;
case kDepthMode2:
break;
case kDepthMode3:
break;
case kDepthMode4:
break;
case kDepthMode5:
break;
case kDepthMode6:
break;
default:
return paramErr;
}
spb.spSlot = dce->dCtlSlot;
spb.spResult = (UInt32)&pram;
err = SReadPRAMRec(&spb);
if (err == noErr) {
pram.mode = mode;
pram.depth = depth;
pram.page = page;
spb.spSlot = dce->dCtlSlot;
spb.spsPointer = &pram;
err = SPutPRAMRec(&spb);
}
return err;
}

View File

@@ -0,0 +1,208 @@
#include "NuBusFPGADrvr.h"
#include "ROMDefs.h"
typedef void(*vblproto)(short);
/* how do I tell it to only modify D0 & A1 ? */
/* the ABI allows to modify D0-D2 & A0-A1 (caller save) */
/* currently this is clobbering A0 yet seems to work ... */
/* 'Devices' p1-37 says of interrupt handler "preserving all registers other than D0 through D3 and A0 through A3"
* but that for NuBus you see SIntInstall which says (2-70)
* "routine must preserve the contents of all registers except A1 and D0"
* yet the interrupt handler for the video card driver example in DCDMF3 p589 clobbers A0
*/
#pragma parameter __D0 fbIrq(__A1)
__attribute__ ((section (".text.fbdriver"))) short fbIrq(const long sqParameter) {
register unsigned long p_D1 asm("d1"), p_D2 asm("d2");
unsigned int irq;
short ret;
asm volatile("" : "+d" (p_D1), "+d" (p_D2));
ret = 0;
irq = (*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)));
if (irq & 1) {
vblproto myVbl = *(vblproto**)0x0d28;
*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)) = 0;
myVbl((sqParameter>>24)&0xf); // cleaner to use dStore->slot ? but require more code...
ret = 1;
}
asm volatile("" : : "d" (p_D1), "d" (p_D2));
return ret;
}
#pragma parameter __D0 cNuBusFPGAOpen(__A0, __A1)
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)dce->dCtlDevBase); */
if (dce->dCtlStorage == nil)
{
int i;
/* set up flags in the device control entry */
/* dce->dCtlFlags |= (dCtlEnableMask | dStatEnableMask | dWritEnableMask |
dReadEnableMask | dNeedLockMask | dRAMBasedMask ); */
/* initialize dCtlStorage */
ReserveMemSys(sizeof(NuBusFPGADriverGlobals));
dce->dCtlStorage = NewHandleSysClear(sizeof(NuBusFPGADriverGlobals));
if (dce->dCtlStorage == nil)
return(openErr);
HLock(dce->dCtlStorage);
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
/* (*dStore)->dce = dce; */
/* for (i = 0 ; i < 256 ; i++) { */
/* dStore->shadowClut[i*3+0] = i; */
/* dStore->shadowClut[i*3+1] = i; */
/* dStore->shadowClut[i*3+2] = i; */
/* } */
dStore->gray = 0;
dStore->irqen = 0;
dStore->slot = dce->dCtlSlot;
/* initialize DRAM controller */
//sdram_init(0xF0000000 | (((unsigned long)dStore->slot) << 24));
/* Get the HW setting for native resolution */
dStore->hres[0] = __builtin_bswap32((unsigned int)read_reg(dce, GOBOFB_HRES)); // fixme: endianness
dStore->vres[0] = __builtin_bswap32((unsigned int)read_reg(dce, GOBOFB_VRES)); // fixme: endianness
SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement));
if (siqel == NULL) {
return openErr;
}
siqel->sqType = sIQType;
siqel->sqPrio = 8;
//siqel->sqAddr = interruptRoutine;
/* not sure how to get the proper result in C... */
/* SlotIntServiceProcPtr sqAddr; */
/* asm("lea %%pc@(interruptRoutine),%0\n" : "=a"(sqAddr)); */
/* siqel->sqAddr = sqAddr; */
/* siqel->sqParm = (long)dce->dCtlDevBase; */
/* not sure how to get the proper result in C... */
/* ... from ~mac68k, you need option "-mpcrel", and it works */
/* SlotIntServiceProcPtr sqAddr; */
/* asm("lea %%pc@(fbIrq),%0\n" : "=a"(sqAddr)); */
siqel->sqAddr = fbIrq;
/* siqel->sqParm = (long)dce; */
siqel->sqParm = (long)dce->dCtlDevBase;
dStore->siqel = siqel;
dStore->curPage = 0;
dStore->curMode = nativeVidMode;
dStore->curDepth = kDepthMode1;
{
OSErr err = noErr;
SpBlock spb;
UInt8 max = nativeVidMode;
spb.spParamData = 1<<fall|1<<foneslot;
spb.spCategory = catDisplay;
spb.spCType = typeVideo;
spb.spDrvrSW = drSwApple;
spb.spDrvrHW = 0xBEEF;
spb.spTBMask = 0; /* match everything above */
spb.spSlot = dce->dCtlSlot;
spb.spID = nativeVidMode;
spb.spExtDev = 0;
err = SGetTypeSRsrc(&spb);
while ((err == noErr) &&
(spb.spSlot == dce->dCtlSlot) &&
(((UInt8)spb.spID) > (UInt8)0x80) &&
(((UInt8)spb.spID) < (UInt8)0x90)) {
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0020); */
/* write_reg(dce, GOBOFB_DEBUG, spb.spID); */
/* write_reg(dce, GOBOFB_DEBUG, err); */
if (((UInt8)spb.spID) == max) // should not happen
err = smNoMoresRsrcs;
if (((UInt8)spb.spID) > max)
max = spb.spID;
err = SGetTypeSRsrc(&spb);
}
dStore->maxMode = max;
}
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000); */
/* write_reg(dce, GOBOFB_DEBUG, dStore->maxMode); */
{
OSErr err = noErr;
SpBlock spb;
/* check for resolution */
UInt8 id;
for (id = nativeVidMode; id <= dStore->maxMode ; id ++) {
/* try every resource, enabled or not */
spb.spParamData = 1<<fall; /* wants disabled */
spb.spCategory = catDisplay;
spb.spCType = typeVideo;
spb.spDrvrSW = drSwApple;
spb.spDrvrHW = 0xBEEF;
spb.spTBMask = 0;
spb.spSlot = dce->dCtlSlot;
spb.spID = id;
spb.spExtDev = 0;
err = SGetSRsrc(&spb);
if (err == noErr) {
spb.spID = kDepthMode1;
err = SFindStruct(&spb); /* that will give us the Parms block ... */
if (err == noErr) {
/* take the Parms pointer, add the offset to the Modes block and then skip the block size at the beginning to get the structure pointer ... */
const unsigned long offset = *(unsigned long*)spb.spsPointer & 0x00FFFFFF;
VPBlockPtr vpblock = (VPBlockPtr)(spb.spsPointer + offset + sizeof(long));
UInt8 idx = id - nativeVidMode;
dStore->hres[idx] = vpblock->vpBounds.right;
dStore->vres[idx] = vpblock->vpBounds.bottom;
}
}
}
}
linearGamma(dStore);
/* now check the content of PRAM */
if (0) {
SpBlock spb;
NuBusFPGAPramRecord pram;
OSErr err;
spb.spSlot = dce->dCtlSlot;
spb.spResult = (UInt32)&pram;
err = SReadPRAMRec(&spb);
if (err == noErr) {
err = reconfHW(dce, pram.mode, pram.depth, pram.page);
}
}
write_reg(dce, GOBOFB_VIDEOCTRL, 1);
ret = changeIRQ(dce, 1, openErr);
}
return noErr;
}
#pragma parameter __D0 cNuBusFPGAClose(__A0, __A1)
OSErr cNuBusFPGAClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0003); */
/* write_reg(dce, GOBOFB_DEBUG, 0x0000DEAD); */
asm(".word 0xfe16\n");
if (dce->dCtlStorage != nil)
{
ret = changeIRQ(dce, 0, openErr);
write_reg(dce, GOBOFB_VIDEOCTRL, 0);
DisposePtr((Ptr)(*(NuBusFPGADriverGlobalsHdl)dce->dCtlStorage)->siqel);
DisposeHandle(dce->dCtlStorage);
dce->dCtlStorage = nil;
}
return ret;
}

View File

@@ -0,0 +1,406 @@
#include "NuBusFPGADrvr.h"
/*
7.1:
2 Debug: 0x00000009
1 <20>Debug: 0x00000009
7.5.3:
6 Debug: 0x00000008
112 Debug: 0x0000000a
32 Debug: 0x0000000c
14 Debug: 0x0000000d
3 Debug: 0x0000000e
4 Debug: 0x00000010
2 Debug: 0x00000011
78 Debug: 0x00000012
1 Debug: 0x00000014
1 <20>Debug: 0x0000000a
8.1:
9 Debug: 0x00000008
273 Debug: 0x0000000a
156 Debug: 0x0000000c
16 Debug: 0x0000000d
3 Debug: 0x00000010
3 Debug: 0x00000011
157 Debug: 0x00000012
1 Debug: 0x00000014
2 Debug: 0x00000018
10 Debug: 0x0000001c
1 <20>Debug: 0x0000000c
*/
#pragma parameter __D0 cNuBusFPGAStatus(__A0, __A1)
OSErr cNuBusFPGAStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
short ret = -1;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0002); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
#if 1
switch (pb->csCode)
{
case -1:
asm volatile(".word 0xfe16\n");
break;
case 0:
ret = statusErr;
break;
/* case 1: */
/* break; */
case cscGetMode: /* 2 */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
vPInfo->csMode = dStore->curDepth; /* checkme: PCI says depth, 7.5+ doesn't call anyway? */
vPInfo->csPage = dStore->curPage;
vPInfo->csBaseAddr = (Ptr)(dStore->curPage * 1024 * 1024 * 4); /* fixme */
ret = noErr;
}
break;
case cscGetEntries: /* 3 */
/* FIXME: TODO */
/* never called in >= 7.1 ? */
asm volatile(".word 0xfe16\n");
ret = noErr;
break;
case cscGetPageCnt: /* 4 == cscGetPages */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
if ((vPInfo->csMode != kDepthMode1) &&
(vPInfo->csMode != kDepthMode2) &&
(vPInfo->csMode != kDepthMode3) &&
(vPInfo->csMode != kDepthMode4) &&
(vPInfo->csMode != kDepthMode5) &&
(vPInfo->csMode != kDepthMode6)) {
ret = paramErr;
goto done;
}
vPInfo->csPage = (vPInfo->csMode == kDepthMode5) ? 1 : 2;
ret = noErr;
}
break;
case cscGetPageBase: /* 5 == cscGetBaseAddr */
{
VDPageInfo *vPInfo = (VDPageInfo *)*(long *)pb->csParam;
if ((vPInfo->csMode != kDepthMode1) &&
(vPInfo->csMode != kDepthMode2) &&
(vPInfo->csMode != kDepthMode3) &&
(vPInfo->csMode != kDepthMode4) &&
(vPInfo->csMode != kDepthMode5) &&
(vPInfo->csMode != kDepthMode6)) {
ret = paramErr;
goto done;
}
short npage = (vPInfo->csMode == kDepthMode5) ? 1 : 2;
if (vPInfo->csPage >= npage) {
ret = paramErr;
goto done;
}
vPInfo->csBaseAddr = (Ptr)(vPInfo->csPage * 1024 * 1024 * 4); /* fixme for > 2 pages ? */
ret = noErr;
}
asm volatile(".word 0xfe16\n");
ret = noErr;
break;
case cscGetGray: /* 6 */
{
VDGrayRecord *vGInfo = (VDGrayRecord *)*(long *)pb->csParam;
vGInfo->csMode = dStore->gray;
ret = noErr;
}
asm volatile(".word 0xfe16\n");
break;
case cscGetInterrupt: /* 7 */
asm volatile(".word 0xfe16\n");
{
VDFlagRecord *vdflag = (VDFlagRecord *)*(long *)pb->csParam;
vdflag->csMode = 1 - dStore->irqen;
ret = noErr;
}
break;
case cscGetGamma: /* 8 */
{
VDGammaRecord *vdgamma = (VDGammaRecord *)*(long *)pb->csParam;
vdgamma->csGTable = (Ptr)&dStore->gamma;
ret = noErr;
}
break;
case cscGetDefaultMode: /* 9 */
{ /* obsolete in PCI, not called >= 7.5 */
VDDefMode *vddefm = (VDDefMode *)*(long *)pb->csParam;
SpBlock spb;
NuBusFPGAPramRecord pram;
OSErr err;
spb.spSlot = dce->dCtlSlot;
spb.spResult = (UInt32)&pram;
ret = SReadPRAMRec(&spb);
if (ret == noErr) {
vddefm->csID = pram.mode;
}
}
break;
case cscGetCurMode: /* 0xa */
{
VDSwitchInfoRec *vdswitch = *(VDSwitchInfoRec **)(long *)pb->csParam;
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0022); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned int)dStore->curDepth); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned int)dStore->curMode); */
vdswitch->csMode = dStore->curDepth;
vdswitch->csData = dStore->curMode;
vdswitch->csPage = dStore->curPage;
vdswitch->csBaseAddr = (Ptr)(dStore->curPage * 1024 * 1024 * 4); /* fixme */
ret = noErr;
}
break;
case cscGetSync: /* 0xb */
asm volatile(".word 0xfe16\n");
ret = statusErr;
break;
case cscGetConnection: /* 0xc */
{
VDDisplayConnectInfoRec *vdconn = *(VDDisplayConnectInfoRec **)(long *)pb->csParam;
vdconn->csDisplayType = kGenericLCD;
vdconn->csConnectTaggedType = 0;
vdconn->csConnectTaggedData = 0;
vdconn->csConnectFlags = (1<<kTaggingInfoNonStandard) | (1<<kAllModesSafe) | (1<<kAllModesValid);
vdconn->csDisplayComponent = 0;
ret = noErr;
}
break;
case cscGetModeTiming: /* 0xd */
{
VDTimingInfoRec *vdtim = *(VDTimingInfoRec **)(long *)pb->csParam;
if (((((UInt8)vdtim->csTimingMode) < nativeVidMode) ||
(((UInt8)vdtim->csTimingMode) > dStore->maxMode)) &&
(vdtim->csTimingMode != kDisplayModeIDFindFirstResolution) &&
(vdtim->csTimingMode != kDisplayModeIDCurrent)) {
ret = paramErr;
goto done;
}
unsigned int mode = vdtim->csTimingMode;
if (mode == kDisplayModeIDFindFirstResolution)
mode = nativeVidMode;
if (mode == kDisplayModeIDCurrent)
mode = dStore->curMode;
switch (mode) {
case nativeVidMode:
vdtim->csTimingFormat = kDeclROMtables;
vdtim->csTimingData = 0;
vdtim->csTimingFlags = 1<<kModeValid | 1<<kModeSafe | 1<<kModeDefault;
break;
default:
vdtim->csTimingFormat = kDeclROMtables;//kDetailedTimingFormat;
vdtim->csTimingData = 0;
vdtim->csTimingFlags = 1<<kModeValid | 1<<kModeSafe;
break;
}
ret = noErr;
}
break;
case cscGetModeBaseAddress: /* 0xe */
/* undocumented ??? */
{
VDBaseAddressInfoRec *vdbase = *(VDBaseAddressInfoRec **)(long *)pb->csParam;
vdbase->csDevBase = 0;
ret = noErr;
}
ret = noErr;
break;
/* cscGetScanProc */ /* 0xf*/ /* undocumented ? could be called according to #mac68k */
case cscGetPreferredConfiguration: /* 0x10 */
{ /* fixme: NVRAM */
VDSwitchInfoRec *vdswitch = *(VDSwitchInfoRec **)(long *)pb->csParam;
vdswitch->csMode = kDepthMode1; //dStore->curDepth; /* fixme: prefered not current / default */
vdswitch->csData = nativeVidMode; //dStore->curMode;
ret = noErr;
SpBlock spb;
NuBusFPGAPramRecord pram;
OSErr err;
spb.spSlot = dce->dCtlSlot;
spb.spResult = (UInt32)&pram;
ret = SReadPRAMRec(&spb);
if (ret == noErr) {
vdswitch->csMode = pram.depth;
vdswitch->csData = pram.mode;
}
}
break;
case cscGetNextResolution: /* 0x11 */
{
VDResolutionInfoRec *vdres = *(VDResolutionInfoRec **)(long *)pb->csParam;
switch (vdres->csPreviousDisplayModeID)
{
default:
if ((((UInt8)vdres->csPreviousDisplayModeID) < nativeVidMode) ||
(((UInt8)vdres->csPreviousDisplayModeID) > dStore->maxMode)) {
ret = paramErr;
goto done;
}
if (((UInt8)vdres->csPreviousDisplayModeID) == dStore->maxMode)
vdres->csDisplayModeID = kDisplayModeIDNoMoreResolutions;
else
vdres->csDisplayModeID = ((UInt8)vdres->csPreviousDisplayModeID) + 1;
vdres->csHorizontalPixels = dStore->hres[((UInt8)vdres->csDisplayModeID) - nativeVidMode];
vdres->csVerticalLines = dStore->vres[((UInt8)vdres->csDisplayModeID) - nativeVidMode];
vdres->csRefreshRate = 60 << 16; /* Fixed(Point) 16+16 */
vdres->csMaxDepthMode = kDepthMode6;
break;
case kDisplayModeIDFindFirstResolution:
vdres->csDisplayModeID = nativeVidMode;
vdres->csHorizontalPixels = dStore->hres[0];
vdres->csVerticalLines = dStore->vres[0];
vdres->csRefreshRate = 60 << 16; /* Fixed(Point) 16+16 */
vdres->csMaxDepthMode = kDepthMode6;
break;
case kDisplayModeIDCurrent:
vdres->csDisplayModeID = dStore->curMode;
vdres->csHorizontalPixels = dStore->hres[dStore->curMode - nativeVidMode];
vdres->csVerticalLines = dStore->vres[dStore->curMode - nativeVidMode];
vdres->csRefreshRate = 60 << 16; /* Fixed(Point) 16+16 */
vdres->csMaxDepthMode = kDepthMode6;
break;
}
ret = noErr;
}
break;
case cscGetVideoParameters: /* 0x12 */
{
VDVideoParametersInfoRec *vdparam = *(VDVideoParametersInfoRec **)(long *)pb->csParam;
if (((((UInt8)vdparam->csDisplayModeID) < nativeVidMode) ||
(((UInt8)vdparam->csDisplayModeID) > dStore->maxMode)) &&
(vdparam->csDisplayModeID != kDisplayModeIDFindFirstResolution) &&
(vdparam->csDisplayModeID != kDisplayModeIDCurrent)) {
ret = paramErr;
goto done;
}
if ((vdparam->csDepthMode != kDepthMode1) &&
(vdparam->csDepthMode != kDepthMode2) &&
(vdparam->csDepthMode != kDepthMode3) &&
(vdparam->csDepthMode != kDepthMode4) &&
(vdparam->csDepthMode != kDepthMode5) &&
(vdparam->csDepthMode != kDepthMode6)) {
ret = paramErr;
goto done;
}
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0022); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned int)vdparam->csDisplayModeID); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned int)vdparam->csDepthMode); */
VPBlock* vpblock = vdparam->csVPBlockPtr;
unsigned char mode = vdparam->csDisplayModeID;
if (mode == kDisplayModeIDFindFirstResolution)
mode = nativeVidMode;
if (mode == kDisplayModeIDCurrent)
mode = dStore->curMode;
/* basically the same as the EBVParms ? */
vdparam->csPageCount = (vdparam->csDepthMode == kDepthMode5) ? 1 : 2;
vpblock->vpBaseOffset = 0;
vpblock->vpBounds.left = 0;
vpblock->vpBounds.top = 0;
vpblock->vpBounds.right = dStore->hres[mode - nativeVidMode];
vpblock->vpBounds.bottom = dStore->vres[mode - nativeVidMode];
vpblock->vpVersion = 0;
vpblock->vpPackType = 0;
vpblock->vpPackSize = 0;
vpblock->vpHRes = 0x480000;
vpblock->vpVRes = 0x480000;
vpblock->vpPixelType = chunky; // checkme?
if (vdparam->csDepthMode == kDepthMode1) {
vpblock->vpRowBytes = vpblock->vpBounds.right;
vdparam->csDeviceType = clutType;
vpblock->vpPixelSize = 8;
vpblock->vpCmpCount = 1;
vpblock->vpCmpSize = 8;
} else if (vdparam->csDepthMode == kDepthMode2) {
vpblock->vpRowBytes = vpblock->vpBounds.right/2;
vdparam->csDeviceType = clutType;
vpblock->vpPixelSize = 4;
vpblock->vpCmpCount = 1;
vpblock->vpCmpSize = 4;
} else if (vdparam->csDepthMode == kDepthMode3) {
vpblock->vpRowBytes = vpblock->vpBounds.right/4;
vdparam->csDeviceType = clutType;
vpblock->vpPixelSize = 2;
vpblock->vpCmpCount = 1;
vpblock->vpCmpSize = 2;
} else if (vdparam->csDepthMode == kDepthMode4) {
vpblock->vpRowBytes = vpblock->vpBounds.right/8;
vdparam->csDeviceType = clutType;
vpblock->vpPixelSize = 1;
vpblock->vpCmpCount = 1;
vpblock->vpCmpSize = 1;
} else if (vdparam->csDepthMode == kDepthMode5) {
vpblock->vpRowBytes = vpblock->vpBounds.right*4;
vdparam->csDeviceType = directType;
vpblock->vpPixelSize = 32;
vpblock->vpCmpCount = 3;
vpblock->vpCmpSize = 8;
} else if (vdparam->csDepthMode == kDepthMode6) {
vpblock->vpRowBytes = vpblock->vpBounds.right*2;
vdparam->csDeviceType = directType;
vpblock->vpPixelSize = 16;
vpblock->vpCmpCount = 3;
vpblock->vpCmpSize = 5;
}
vpblock->vpPlaneBytes = 0;
ret = noErr;
}
break;
/* 0x13 */ /* nothing */
case cscGetGammaInfoList: /* 0x14 */
ret = statusErr;
break;
case cscRetrieveGammaTable: /* 0x15 */
asm volatile(".word 0xfe16\n");
ret = statusErr;
break;
/* cscSupportsHardwareCursor */ /* 0x16 */ /* never called, unfortunately */
/* cscGetHardwareCursorDrawState */ /* 0x17 */ /* never called, unfortunately */
case cscGetConvolution: /* 0x18 */
ret = statusErr;
break;
/* cscGetPowerState */ /* 0x19 */
/* cscPrivateStatusCall */ /* 0x1a */
/* cscGetDDCBlock */ /* 0x1b */
case cscGetMultiConnect: /* 0x1c */
ret = statusErr;
break;
/* cscGetClutBehavior */ /* 0x1d */
/* cscGetTimingRanges */ /* 0x1e */
/* cscGetDetailedTiming */ /* 0x1f */
/* cscGetCommunicationInfo */ /* 0x20 */
default: /* always return statusErr for unknown csCode */
asm volatile(".word 0xfe16\n");
ret = statusErr;
break;
}
#endif
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}

View File

@@ -0,0 +1,157 @@
#include "NuBusFPGADrvr.h"
#include "NuBusFPGARAMDskDrvr.h"
#include <Traps.h>
#include <ROMDefs.h>
#define PRIM_WRITEREG(reg, val) \
*((volatile UInt32*)(a32+GOBOFB_BASE+reg)) = (UInt32)val
#define PRIM_READREG(reg) \
(*((volatile UInt32*)(a32+GOBOFB_BASE+reg)))
#pragma parameter __D0 Primary(__A0)
UInt32 Primary(SEBlock* seblock) {
UInt32 a32 = 0xF0000000 | ((UInt32)seblock->seSlot << 24);
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
SpBlock spblock;
/* UInt8 pram[8]; */
OSErr err;
UInt16 i,j, hres, vres;
char busMode;
UniversalProcPtr qd32ptr, unimpptr;
busMode = 1;
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
PRIM_WRITEREG(GOBOFB_VBL_MASK, 0);// disable interrupts on FB
PRIM_WRITEREG(DMA_IRQ_CTL, revb(0x2));// disable/clear interrupts on DSK
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0x87654321);// trace */
/* PRIM_WRITEREG(GOBOFB_DEBUG, busMode);// trace */
hres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_HRES)); // fixme: endianness
vres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_VRES)); // fixme: endianness
/* initialize DRAM controller */
#ifndef QEMU
sdram_init(a32);
#endif
/* grey the screen */
/* should switch to HW ? */
a32_l0 = a32;
a32_l1 = a32 + hres;
for (j = 0 ; j < vres ; j+= 2) {
a32_4p0 = a32_l0;
a32_4p1 = a32_l1;
for (i = 0 ; i < hres ; i += 4) {
*((UInt32*)a32_4p0) = 0xAAAAAAAA;
*((UInt32*)a32_4p1) = 0x55555555;
a32_4p0 += 4;
a32_4p1 += 4;
}
a32_l0 += 2*hres;
a32_l1 += 2*hres;
}
SwapMMUMode ( &busMode ); // restore
{ // disable non-default entries
SpBlock spb;
err = noErr;
do {
spb.spParamData = 1<<foneslot|1<<fnext;
spb.spCategory = catDisplay;
spb.spCType = typeVideo;
spb.spDrvrSW = drSwApple;
spb.spDrvrHW = 0xBEEF;
spb.spTBMask = 0; /* match everything above */
spb.spSlot = seblock->seSlot;
spb.spID = nativeVidMode; /* skip over the 'good' one; we can reset as SNextTypeSRsrc skips disabled */
spb.spExtDev = 0;
err = SNextTypeSRsrc(&spb);
if ((err == noErr) &&
(spb.spSlot == seblock->seSlot) &&
(((UInt8)spb.spID) > (UInt8)nativeVidMode) &&
(((UInt8)spb.spID) < (UInt8)diskResource)) {
spb.spParamData = 1; /* disable */
spb.spSlot = seblock->seSlot;
spb.spExtDev = 0;
SetSRsrcState(&spb);
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xBEEF000F); */
/* PRIM_WRITEREG(GOBOFB_DEBUG, spb.spID); */
}
} while (err == noErr);
}
#if 0
/* call SVersion to figure out if we have a recent SlotManager */
//spblock.spSlot = seblock->seSlot;
//spblock.spExtDev = 0;
err = SVersion(&spblock);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* DCDMF3 p178: if error, old slot manager*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* DCDMF3 p178: new slot manager */
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, spblock.spResult);*/
}
SwapMMUMode ( &busMode ); // restore
/* check for 32-bits QuickDraw */
qd32ptr = GetTrapAddress(Check32QDTrap);
unimpptr = GetTrapAddress(_Unimplemented);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (qd32ptr == unimpptr) {
/* no 32QD */
PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);
PRIM_WRITEREG(GOBOFB_DEBUG, unimpptr);
} else {
/* yes 32QD */
PRIM_WRITEREG(GOBOFB_DEBUG, 0x00C0FFEE);
}
SwapMMUMode ( &busMode ); // restore
/* check the content of the PRAM */
spblock.spSlot = seblock->seSlot;
spblock.spResult = (UInt32)pram;
err = SReadPRAMRec(&spblock);
#if 0
PRIM_WRITEREG(GOBOFB_DEBUG, 0x88888888);
for (j = 0 ; j < 8 ; j++)
PRIM_WRITEREG(GOBOFB_DEBUG, (uint32_t)pram[j]);
PRIM_WRITEREG(GOBOFB_DEBUG, 0x88888888);
#endif
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xC0FFEE00);*/
/* for (i = 0 ; i < 8 ; i++) */
/* PRIM_WRITEREG(GOBOFB_DEBUG, pram[i]);*/
}
SwapMMUMode ( &busMode ); // restore
#endif
seblock->seStatus = 1;
return 0;
}
/* SDRAM INIT */

View File

@@ -0,0 +1,660 @@
#include "NuBusFPGADrvr.h"
#define CONFIG_CSR_DATA_WIDTH 32
#if defined(NUBUSFPGA)
#include "../nubusfpga_csr_ddrphy.h"
#include "../nubusfpga_csr_sdram.h"
#elif defined(IISIFPGA)
#include "../IIsifpga_csr_ddrphy.h"
#include "../IIsifpga_csr_sdram.h"
#elif defined(QUADRAFPGA)
#include "../quadrafpga_csr_ddrphy.h"
#include "../quadrafpga_csr_sdram.h"
#else
#error "no board defined"
#endif
/* auto-generated sdram_phy.h + sc */
#define DFII_CONTROL_SEL 0x01
#define DFII_CONTROL_CKE 0x02
#define DFII_CONTROL_ODT 0x04
#define DFII_CONTROL_RESET_N 0x08
#define DFII_COMMAND_CS 0x01
#define DFII_COMMAND_WE 0x02
#define DFII_COMMAND_CAS 0x04
#define DFII_COMMAND_RAS 0x08
#define DFII_COMMAND_WRDATA 0x10
#define DFII_COMMAND_RDDATA 0x20
#define SDRAM_PHY_A7DDRPHY
#define SDRAM_PHY_XDR 2
#define SDRAM_PHY_DATABITS 16
#define SDRAM_PHY_PHASES 4
#define SDRAM_PHY_CL 6
#define SDRAM_PHY_CWL 5
#define SDRAM_PHY_CMD_LATENCY 0
#define SDRAM_PHY_RDPHASE 2
#define SDRAM_PHY_WRPHASE 3
#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
#define SDRAM_PHY_READ_LEVELING_CAPABLE
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
#define SDRAM_PHY_DELAYS 32
#define SDRAM_PHY_BITSLIPS 8
__attribute__ ((section (".text.primary"))) static void cdelay(int i);
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_rst_delay (uint32_t a32, int module);
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_inc_delay (uint32_t a32, int module);
__attribute__ ((section (".text.primary"))) static inline void command_p0(uint32_t a32, int cmd)
{
sdram_dfii_pi0_command_write(a32, cmd);
sdram_dfii_pi0_command_issue_write(a32, 1);
}
__attribute__ ((section (".text.primary"))) static inline void command_p1(uint32_t a32, int cmd)
{
sdram_dfii_pi1_command_write(a32, cmd);
sdram_dfii_pi1_command_issue_write(a32, 1);
}
__attribute__ ((section (".text.primary"))) static inline void command_p2(uint32_t a32, int cmd)
{
sdram_dfii_pi2_command_write(a32, cmd);
sdram_dfii_pi2_command_issue_write(a32, 1);
}
__attribute__ ((section (".text.primary"))) static inline void command_p3(uint32_t a32, int cmd)
{
sdram_dfii_pi3_command_write(a32, cmd);
sdram_dfii_pi3_command_issue_write(a32, 1);
}
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
__attribute__ ((section (".text.primary"))) static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase)
{
switch (phase) {
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_WRDATA_ADDR;
default: return 0;
}
}
__attribute__ ((section (".text.primary"))) static inline unsigned long sdram_dfii_pix_rddata_addr(int phase)
{
switch (phase) {
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR;
default: return 0;
}
}
#define DDRX_MR_WRLVL_ADDRESS 1
#define DDRX_MR_WRLVL_RESET 6
#define DDRX_MR_WRLVL_BIT 7
__attribute__ ((section (".text.primary"))) static inline void init_sequence(uint32_t a32)
{
/* Release reset */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 0);
sdram_dfii_control_write(a32, DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
cdelay(50000);
/* Bring CKE high */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 0);
sdram_dfii_control_write(a32, DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
cdelay(10000);
/* Load Mode Register 2, CWL=5 */
sdram_dfii_pi0_address_write(a32, 0x200);
sdram_dfii_pi0_baddress_write(a32, 2);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Mode Register 3 */
sdram_dfii_pi0_address_write(a32, 0x0);
sdram_dfii_pi0_baddress_write(a32, 3);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Mode Register 1 */
sdram_dfii_pi0_address_write(a32, 0x6);
sdram_dfii_pi0_baddress_write(a32, 1);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
/* Load Mode Register 0, CL=6, BL=8 */
sdram_dfii_pi0_address_write(a32, 0x920);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
cdelay(200);
/* ZQ Calibration */
sdram_dfii_pi0_address_write(a32, 0x400);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, DFII_COMMAND_WE|DFII_COMMAND_CS);
cdelay(200);
}
#include "nubusfpga_csr_common.h"
/* sdram.c from liblitedram, preprocessed for our case, + sc */
__attribute__ ((section (".text.primary"))) static inline unsigned long
lfsr (unsigned long bits, unsigned long prev)
{
/*static*/ const unsigned long long lfsr_taps[] = {
0x0L,
0x0L,
0x3L,
0x6L,
0xcL,
0x14L,
0x30L,
0x60L,
0xb8L,
0x110L,
0x240L,
0x500L,
0x829L,
0x100dL,
0x2015L,
0x6000L,
0xd008L,
0x12000L,
0x20400L,
0x40023L,
0x90000L,
0x140000L,
0x300000L,
0x420000L,
0xe10000L,
0x1200000L,
0x2000023L,
0x4000013L,
0x9000000L,
0x14000000L,
0x20000029L,
0x48000000L,
0x80200003L,
0x100080000L,
0x204000003L,
0x500000000L,
0x801000000L,
0x100000001fL,
0x2000000031L,
0x4400000000L,
0xa000140000L,
0x12000000000L,
0x300000c0000L,
0x63000000000L,
0xc0000030000L,
0x1b0000000000L,
0x300003000000L,
0x420000000000L,
0xc00000180000L,
0x1008000000000L,
0x3000000c00000L,
0x6000c00000000L,
0x9000000000000L,
0x18003000000000L,
0x30000000030000L,
0x40000040000000L,
0xc0000600000000L,
0x102000000000000L,
0x200004000000000L,
0x600003000000000L,
0xc00000000000000L,
0x1800300000000000L,
0x3000000000000030L,
0x6000000000000000L,
0x800000000000000dL
};
unsigned long lsb = prev & 1;
prev >>= 1;
prev ^= (-lsb) & lfsr_taps[bits];
return prev;
}
__attribute__ ((section (".text.primary")))
static void cdelay (int i)
{
//i >>= 2;
while (i > 0) {
__asm__ volatile ("");
i--;
}
}
__attribute__ ((section (".text.primary"))) static unsigned char
sdram_dfii_get_rdphase(uint32_t a32)
{
return ddrphy_rdphase_read(a32);
}
__attribute__ ((section (".text.primary"))) static unsigned char
sdram_dfii_get_wrphase(uint32_t a32)
{
return ddrphy_wrphase_read(a32);
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_pix_address_write(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
case 3:
sdram_dfii_pi3_address_write(a32, value);
break;
case 2:
sdram_dfii_pi2_address_write(a32, value);
break;
case 1:
sdram_dfii_pi1_address_write(a32, value);
break;
default:
sdram_dfii_pi0_address_write(a32, value);
}
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_pird_address_write(uint32_t a32, unsigned int value)
{
unsigned char rdphase = sdram_dfii_get_rdphase(a32);
sdram_dfii_pix_address_write(a32, rdphase, value);
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_piwr_address_write(uint32_t a32, unsigned int value)
{
unsigned char wrphase = sdram_dfii_get_wrphase(a32);
sdram_dfii_pix_address_write(a32, wrphase, value);
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_pix_baddress_write(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
case 3:
sdram_dfii_pi3_baddress_write(a32, value);
break;
case 2:
sdram_dfii_pi2_baddress_write(a32, value);
break;
case 1:
sdram_dfii_pi1_baddress_write(a32, value);
break;
default:
sdram_dfii_pi0_baddress_write(a32, value);
}
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_pird_baddress_write(uint32_t a32, unsigned int value)
{
unsigned char rdphase = sdram_dfii_get_rdphase(a32);
sdram_dfii_pix_baddress_write(a32, rdphase, value);
}
__attribute__ ((section (".text.primary"))) static void
sdram_dfii_piwr_baddress_write(uint32_t a32, unsigned int value)
{
unsigned char wrphase = sdram_dfii_get_wrphase(a32);
sdram_dfii_pix_baddress_write(a32, wrphase, value);
}
__attribute__ ((section (".text.primary"))) static void
command_px(uint32_t a32, unsigned char phase, unsigned int value)
{
switch (phase) {
case 3:
command_p3(a32, value);
break;
case 2:
command_p2(a32, value);
break;
case 1:
command_p1(a32, value);
break;
default:
command_p0(a32, value);
}
}
__attribute__ ((section (".text.primary"))) static void
command_prd(uint32_t a32, unsigned int value)
{
unsigned char rdphase = sdram_dfii_get_rdphase(a32);
command_px(a32, rdphase, value);
}
__attribute__ ((section (".text.primary"))) static void
command_pwr (uint32_t a32, unsigned int value)
{
unsigned char wrphase = sdram_dfii_get_wrphase(a32);
command_px(a32, wrphase, value);
}
__attribute__ ((section (".text.primary"))) static void
sdram_software_control_on(uint32_t a32)
{
unsigned int previous;
previous = sdram_dfii_control_read(a32);
if (previous != (0x02 | 0x04 | 0x08)) {
sdram_dfii_control_write(a32, (0x02 | 0x04 | 0x08));
}
}
__attribute__ ((section (".text.primary"))) static void
sdram_software_control_off(uint32_t a32)
{
unsigned int previous;
previous = sdram_dfii_control_read(a32);
if (previous != (0x01)) {
sdram_dfii_control_write(a32, (0x01));
}
}
__attribute__ ((section (".text.primary"))) static void
sdram_mode_register_write(uint32_t a32, char reg, int value)
{
sdram_dfii_pi0_address_write(a32, value);
sdram_dfii_pi0_baddress_write(a32, reg);
command_p0(a32, 0x08 | 0x04 | 0x02 | 0x01);
}
//typedef void (*delay_callback) (uint32_t a32, int module);
__attribute__ ((section (".text.primary"))) static void
sdram_activate_test_row(uint32_t a32)
{
sdram_dfii_pi0_address_write(a32, 0);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, 0x08 | 0x01);
cdelay (15);
}
__attribute__ ((section (".text.primary"))) static void
sdram_precharge_test_row(uint32_t a32)
{
sdram_dfii_pi0_address_write(a32, 0);
sdram_dfii_pi0_baddress_write(a32, 0);
command_p0(a32, 0x08 | 0x02 | 0x01);
cdelay (15);
}
__attribute__ ((section (".text.primary"))) static unsigned int
popcount (unsigned int x)
{
x -= ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0F0F0F0F;
x += (x >> 8);
x += (x >> 16);
return x & 0x0000003F;
}
__attribute__ ((section (".text.primary"))) static unsigned int
sdram_write_read_check_test_pattern (uint32_t a32, int module, unsigned int seed)
{
int p, i;
unsigned int errors;
unsigned int prv;
unsigned char tst[1 * 32 / 8];
unsigned char prs[4][1 * 32 / 8];
prv = seed;
for (p = 0; p < 4; p++) {
for (i = 0; i < 1 * 32 / 8; i++) {
prv = lfsr (32, prv);
prs[p][i] = prv;
}
}
sdram_activate_test_row(a32);
for (p = 0; p < 4; p++)
csr_wr_buf_uint8(a32, (sdram_dfii_pix_wrdata_addr (p)/* - CSR_SDRAM_BASE*/), prs[p], 1 * 32 / 8); /* cleanme */
sdram_dfii_piwr_address_write(a32, 0);
sdram_dfii_piwr_baddress_write(a32, 0);
command_pwr(a32, 0x04 | 0x02 | 0x01 | 0x10);
cdelay (15);
sdram_dfii_pird_address_write(a32, 0);
sdram_dfii_pird_baddress_write(a32, 0);
command_prd(a32, 0x04 | 0x01 | 0x20);
cdelay (15);
sdram_precharge_test_row(a32);
errors = 0;
for (p = 0; p < 4; p++) {
csr_rd_buf_uint8(a32, (sdram_dfii_pix_rddata_addr (p)/* - CSR_SDRAM_BASE*/), tst, 1 * 32 / 8); /* cleanme */
errors +=
popcount (prs[p][16 / 8 - 1 - module] ^ tst[16 / 8 - 1 - module]);
errors +=
popcount (prs[p][2 * 16 / 8 - 1 - module] ^
tst[2 * 16 / 8 - 1 - module]);
}
return errors;
}
__attribute__ ((section (".text.primary"))) static void
sdram_leveling_center_module (uint32_t a32, int module, int show_short, int show_long)
/* ,
delay_callback rst_delay,
delay_callback inc_delay) */
{
int i;
int show;
int working;
unsigned int errors;
int delay, delay_mid, delay_range;
int delay_min = -1, delay_max = -1;
delay = 0;
//rst_delay(a32, module);
sdram_read_leveling_rst_delay(a32, module);
while (1) {
errors = sdram_write_read_check_test_pattern(a32, module, 42);
errors += sdram_write_read_check_test_pattern(a32, module, 84);
working = errors == 0;
show = show_long;
if (working && delay_min < 0) {
delay_min = delay;
break;
}
delay++;
if (delay >= 32)
break;
//inc_delay(a32, module);
sdram_read_leveling_inc_delay(a32, module);
}
delay++;
//inc_delay(a32, module);
sdram_read_leveling_inc_delay(a32, module);
while (1) {
errors = sdram_write_read_check_test_pattern(a32, module, 42);
errors += sdram_write_read_check_test_pattern(a32, module, 84);
working = errors == 0;
show = show_long;
if (!working && delay_max < 0) {
delay_max = delay;
}
delay++;
if (delay >= 32)
break;
//inc_delay(a32, module);
sdram_read_leveling_inc_delay(a32, module);
}
if (delay_max < 0) {
delay_max = delay;
}
delay_mid = (delay_min + delay_max) / 2 % 32;
delay_range = (delay_max - delay_min) / 2;
//delay_mid = 25;
//rst_delay(a32, module);
sdram_read_leveling_rst_delay(a32, module);
cdelay (100);
for (i = 0; i < delay_mid; i++) {
//inc_delay(a32, module);
sdram_read_leveling_inc_delay(a32, module);
cdelay (100);
}
}
//__attribute__ ((section (".data.primary"))) int _sdram_write_leveling_bitslips[16];
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_rst_delay (uint32_t a32, int module)
{
ddrphy_dly_sel_write(a32, 1 << module);
ddrphy_rdly_dq_rst_write(a32, 1);
ddrphy_dly_sel_write(a32, 0);
}
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_inc_delay (uint32_t a32, int module)
{
ddrphy_dly_sel_write(a32, 1 << module);
ddrphy_rdly_dq_inc_write(a32, 1);
ddrphy_dly_sel_write(a32, 0);
}
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_rst_bitslip (uint32_t a32, char m)
{
ddrphy_dly_sel_write(a32, 1 << m);
ddrphy_rdly_dq_bitslip_rst_write(a32, 1);
ddrphy_dly_sel_write(a32, 0);
}
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling_inc_bitslip (uint32_t a32, char m)
{
ddrphy_dly_sel_write(a32, 1 << m);
ddrphy_rdly_dq_bitslip_write(a32, 1);
ddrphy_dly_sel_write(a32, 0);
}
__attribute__ ((section (".text.primary"))) static unsigned int
sdram_read_leveling_scan_module (uint32_t a32, int module, int bitslip, int show)
{
const unsigned int max_errors = 2 * (4 * 2 * 32);
int i;
unsigned int score;
unsigned int errors;
score = 0;
sdram_read_leveling_rst_delay(a32, module);
for (i = 0; i < 32; i++) {
int working;
int _show = show;
errors = sdram_write_read_check_test_pattern(a32, module, 42);
errors += sdram_write_read_check_test_pattern(a32, module, 84);
working = (errors == 0) ? 1 : 0;
score += (working * max_errors * 32) + (max_errors - errors);
sdram_read_leveling_inc_delay(a32, module);
}
return score;
}
__attribute__ ((section (".text.primary"))) static void
sdram_read_leveling(uint32_t a32)
{
int module;
int bitslip;
unsigned int score;
unsigned int best_score;
int best_bitslip;
for (module = 0; module < 16 / 8; module++) {
best_score = 0;
best_bitslip = 0;
sdram_read_leveling_rst_bitslip(a32, module);
for (bitslip = 0; bitslip < 8; bitslip++) {
score = sdram_read_leveling_scan_module(a32, module, bitslip, 1);
sdram_leveling_center_module(a32, module, 1, 0);
/*,
sdram_read_leveling_rst_delay,
sdram_read_leveling_inc_delay);*/
if (score > best_score) {
best_bitslip = bitslip;
best_score = score;
}
if (bitslip == 8 - 1)
break;
sdram_read_leveling_inc_bitslip(a32, module);
}
//best_bitslip = 1;
sdram_read_leveling_rst_bitslip(a32, module);
for (bitslip = 0; bitslip < best_bitslip; bitslip++)
sdram_read_leveling_inc_bitslip(a32, module);
sdram_leveling_center_module(a32, module, 1, 0);
/*,
sdram_read_leveling_rst_delay,
sdram_read_leveling_inc_delay);*/
}
}
__attribute__ ((section (".text.primary"))) static void
sdram_write_latency_calibration(uint32_t a32)
{
int i;
int module;
int bitslip;
unsigned int score;
unsigned int subscore;
unsigned int best_score;
int best_bitslip;
int _sdram_write_leveling_bitslips[16] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
for (module = 0; module < 16 / 8; module++) {
best_score = 0;
best_bitslip = -1;
for (bitslip = 0; bitslip < 8; bitslip += 2) {
score = 0;
ddrphy_dly_sel_write(a32, 1 << module);
ddrphy_wdly_dq_bitslip_rst_write(a32, 1);
for (i = 0; i < bitslip; i++) {
ddrphy_wdly_dq_bitslip_write(a32, 1);
}
ddrphy_dly_sel_write(a32, 0);
score = 0;
sdram_read_leveling_rst_bitslip(a32, module);
for (i = 0; i < 8; i++) {
subscore = sdram_read_leveling_scan_module(a32, module, i, 0);
score = subscore > score ? subscore : score;
sdram_read_leveling_inc_bitslip(a32, module);
}
if (score > best_score) {
best_bitslip = bitslip;
best_score = score;
}
}
if (_sdram_write_leveling_bitslips[module] < 0)
bitslip = best_bitslip;
else
bitslip = _sdram_write_leveling_bitslips[module];
//bitslip = 0;
ddrphy_dly_sel_write(a32, 1 << module);
ddrphy_wdly_dq_bitslip_rst_write(a32, 1);
for (i = 0; i < bitslip; i++) {
ddrphy_wdly_dq_bitslip_write(a32, 1);
}
ddrphy_dly_sel_write(a32, 0);
}
}
__attribute__ ((section (".text.primary"))) static int
sdram_leveling(uint32_t a32)
{
int module;
sdram_software_control_on(a32);
for (module = 0; module < 16 / 8; module++) {
sdram_read_leveling_rst_delay(a32, module);
sdram_read_leveling_rst_bitslip(a32, module);
}
sdram_write_latency_calibration(a32);
sdram_read_leveling(a32);
sdram_software_control_off(a32);
return 1;
}
int
sdram_init(uint32_t a32) // // attribute in header file
{
ddrphy_rdphase_write(a32, 2);
ddrphy_wrphase_write(a32, 3);
sdram_software_control_on(a32);
ddrphy_rst_write(a32, 1);
cdelay (1000);
ddrphy_rst_write(a32, 0);
cdelay (1000);
init_sequence(a32);
sdram_leveling(a32);
sdram_software_control_off(a32);
return 1;
}

View File

@@ -0,0 +1,74 @@
#ifndef __NUBUSFPGARAMDSKDRVR_H__
#define __NUBUSFPGARAMDSKDRVR_H__
#include <Files.h>
#include <Devices.h>
#include <Slots.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Disks.h>
// noy yest supported on PDS variants
#if defined(NUBUSFPGA)
// #define ENABLE_DMA 1
#endif
#include "NuBusFPGADrvr.h"
typedef struct {
unsigned long blk_todo;
unsigned long blk_done;
unsigned long blk_offset;
unsigned long blk_doing;
void *ioBuffer;
int write;
} ram_dsk_op;
struct RAMDrvContext {
DrvSts2 drvsts;
ram_dsk_op op;
char slot;
#ifdef ENABLE_DMA
char irqen;
unsigned int dma_blk_size;
unsigned int dma_blk_size_mask;
unsigned int dma_blk_size_shift;
unsigned long dma_blk_base;
unsigned long dma_mem_size;
SlotIntQElement *siqel;
#endif
};
#define DRIVE_SIZE_BYTES ((256ul-8ul)*1024ul*1024ul) // FIXME: mem size minus fb size
/* FIXME; should be auto-generated for CSR addresses... */
/* WARNING: 0x00100800 is the offset to GOBOFB_BASE !! */
#define DMA_BLK_SIZE (0x00100800 | 0x00)
#define DMA_BLK_BASE (0x00100800 | 0x04)
#define DMA_MEM_SIZE (0x00100800 | 0x08)
#define DMA_IRQ_CTL (0x00100800 | 0x0c)
#define DMA_BLK_ADDR (0x00100800 | 0x10)
#define DMA_DMA_ADDR (0x00100800 | 0x14)
#define DMA_BLK_CNT (0x00100800 | 0x18)
#define DMA_STATUS (0x00100800 | 0x2c)
#define DMA_STATUS_CHECK_BITS (0x01F)
#define DMA_IRQSTATUS (0x00100800 | 0x34)
/* ctrl */
OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) __attribute__ ((section (".text.dskdriver")));
OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
/* open, close */
OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
OSErr cNuBusFPGARAMDskClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
/* prime */
short dskIrq(const long sqParameter) __attribute__ ((section (".text.dskdriver")));
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
/* status */
OSErr cNuBusFPGARAMDskStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
uint32_t rledec(uint32_t* out, const uint32_t* in, const uint32_t len) __attribute__ ((section (".text.dskdriver")));;
#endif

View File

@@ -0,0 +1,23 @@
NuBusFPGARAMDskDrvr:
.word 0x4f00 /* 0x4f00: ctl, status, read, write, needsLock [Devices.a] */
.word 0
.word 0
.word 0
/* Entry point offset table */
/* we can directly call the C version if it has the right calling convention */
.word cNuBusFPGARAMDskOpen - NuBusFPGARAMDskDrvr /* open routine */
.word cNuBusFPGARAMDskPrime - NuBusFPGARAMDskDrvr /* prime */
.word cNuBusFPGARAMDskCtl - NuBusFPGARAMDskDrvr /* control */
.word cNuBusFPGARAMDskStatus- NuBusFPGARAMDskDrvr /* status */
.word cNuBusFPGARAMDskClose - NuBusFPGARAMDskDrvr /* close */
_NuBusFPGARAMDskTitle:
.byte _NuBusFPGARAMDskTitle_StringEnd-.-1 /* pascal string length */
.ascii ".NuBusFPGARAMDsk_Drvr"
_NuBusFPGARAMDskTitle_StringEnd:
.word 0 /* version number */
/* for entry points: */
/* A0 pointer to driver parameter block */
/* A1 pointer to driver device control entry */
ALIGN 2

View File

@@ -0,0 +1,59 @@
#include "NuBusFPGARAMDskDrvr.h"
#ifdef ENABLE_DMA
OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) {
struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
if (en != ctx->irqen) {
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0005); */
/* write_reg(dce, GOBOFB_DEBUG, en); */
if (en) {
if (SIntInstall(ctx->siqel, dce->dCtlSlot)) {
return err;
}
} else {
if (SIntRemove(ctx->siqel, dce->dCtlSlot)) {
return err;
}
}
write_reg(dce, DMA_IRQ_CTL, en ? revb(0x3) : revb(0x2)); // 0x2: always clear pending interrupt
ctx->irqen = en;
}
return noErr;
}
#endif
#pragma parameter __D0 cNuBusFPGARAMDskCtl(__A0, __A1)
OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct RAMDrvContext *ctx;
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0002); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
if (ctx) {
switch (pb->csCode)
{
case kFormat:
ret = noErr;
break;
default:
ret = controlErr;
break;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
goto done;
}
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}

View File

@@ -0,0 +1,185 @@
#include "NuBusFPGARAMDskDrvr.h"
#include <Disks.h>
/* FYI, missing in library with Retro68 */
/* void AddDrive(short drvrRefNum, short drvNum, DrvQElPtr qEl); */
/* re-implement with Retro68 features */
/* drVNum to high-order bits of num, drvrRefNum in low-order */
/* not sure how to do "parameter" without output ? */
#pragma parameter __D0 AddDrive(__D0, __A0)
__attribute__ ((section (".text.dskdriver"))) static inline int dupAddDrive(unsigned long num, DrvQElPtr qEl) {
asm volatile(".word 0xA04E" : : "d" (num), "a" (qEl));
return num; // should cost nothing, num is already in D0
}
#include <ROMDefs.h>
#pragma parameter __D0 cNuBusFPGARAMDskOpen(__A0, __A1)
OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
DrvSts2 *dsptr; // pointer to the DrvSts2 in our context
int drvnum = 1;
struct RAMDrvContext *ctx;
OSErr ret = noErr;
char busMode;
char slot;
busMode = 1;
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
if (dce->dCtlDevBase == 0) { // for some unknown reason, we get an empty dCtlDevBase...
if ((dce->dCtlSlot > 0xE) || (dce->dCtlSlot < 0x9)) { // safety net
SpBlock mySpBlock;
SInfoRecord mySInfoRecord;
mySpBlock.spResult = (long)&mySInfoRecord;
mySpBlock.spSlot = 0x9; // start at first
mySpBlock.spID = 0;
mySpBlock.spExtDev = 0;
mySpBlock.spCategory = catProto;
mySpBlock.spCType = 0x1000; // typeDrive;
mySpBlock.spDrvrSW = drSwApple;
mySpBlock.spDrvrHW = 0xbeee; // DrHwNuBusFPGADsk
mySpBlock.spTBMask = 0;
ret = SNextTypeSRsrc(&mySpBlock);
if (ret)
goto done;
slot = mySpBlock.spSlot;
} else {
slot = dce->dCtlSlot;
}
dce->dCtlDevBase = 0xF0000000ul | ((unsigned long)slot << 24);
}
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0000); */
/* write_reg(dce, GOBOFB_DEBUG, dce->dCtlSlot); */
if (dce->dCtlStorage == nil) {
DrvQElPtr dq;
for(dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvnum)
drvnum = dq->dQDrive+1;
}
ReserveMemSys(sizeof(struct RAMDrvContext));
dce->dCtlStorage = NewHandleSysClear(sizeof(struct RAMDrvContext));
if (dce->dCtlStorage == nil) {
ret = openErr;
goto done;
}
HLock(dce->dCtlStorage);
ctx = *(struct RAMDrvContext **)dce->dCtlStorage;
ctx->slot = slot;
// disable IRQ for now
write_reg(dce, DMA_IRQ_CTL, revb(0x2)); // 0x1 would enable irq, 0x2 is auto-clear so we make sure there's no spurious IRQ pending ; should be already done by Pirmary
dsptr = &ctx->drvsts;
// dsptr->track /* current track */
dsptr->writeProt = 0; /* bit 7 = 1 if volume is locked */
dsptr->diskInPlace = 8; /* disk in drive */
// dsptr->installed /* drive installed */
// dsptr->sides /* -1 for 2-sided, 0 for 1-sided */
// dsptr->QLink /* next queue entry */
dsptr->qType = 1; /* 1 for HD20 */ /* Files 2-85 (p173) : 1 to enable S1 */
dsptr->dQDrive = drvnum; /* drive number */
dsptr->dQRefNum = dce->dCtlRefNum; /* driver reference number */
// dsptr->dQFSID /* file system ID */
dsptr->driveSize = ((DRIVE_SIZE_BYTES/512ul) & 0x0000FFFFul); /* (no comments in Disks.h) */
dsptr->driveS1 = ((DRIVE_SIZE_BYTES/512ul) & 0xFFFF0000ul) >> 16; /* */
// dsptr->driveType
// dsptr->driveManf
// dsptr->driveChar
// dsptr->driveMisc
// MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
// write_reg(dce, GOBOFB_DEBUG, 0x0000DEAD);
// initialize to our empty volume
{
unsigned long *superslot = (unsigned long*)(((unsigned long)ctx->slot) << 28ul);
unsigned long *compressed = (unsigned long*)(dce->dCtlDevBase + 0x00FF8000ul);
unsigned long res;
res = rledec(superslot, compressed, 730); // FIXME: 730 = 2920/4 (compressed size in words)
}
// add the drive
//MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
dupAddDrive((dsptr->dQRefNum & 0xFFFF) | (drvnum << 16), (DrvQElPtr)&dsptr->qLink);
#ifdef ENABLE_DMA
ctx->dma_blk_size = revb( read_reg(dce, DMA_BLK_SIZE) );
ctx->dma_blk_size_mask = ctx->dma_blk_size - 1; // size is Po2
ctx->dma_blk_size_shift = 0;
while ((1 << ctx->dma_blk_size_shift) < ctx->dma_blk_size) // fixme
ctx->dma_blk_size_shift++;
ctx->dma_blk_base = revb( read_reg(dce, DMA_BLK_BASE) );
ctx->dma_mem_size = revb( read_reg(dce, DMA_MEM_SIZE) );
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580002); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_mask); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_shift); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_base); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_mem_size); */
{
SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement));
if (siqel == NULL) {
return openErr;
}
siqel->sqType = sIQType;
siqel->sqPrio = 7;
siqel->sqAddr = dskIrq;
siqel->sqParm = (long)dce;
ctx->siqel = siqel;
ctx->irqen = 0;
ctx->op.blk_todo = 0;
ctx->op.blk_done = 0;
ctx->op.blk_offset = 0;
ctx->op.blk_doing = 0;
ctx->op.ioBuffer = 0;
ctx->op.write = 0;
}
#endif
// auto-mount
{
ParamBlockRec pbr;
pbr.volumeParam.ioVRefNum = dsptr->dQDrive;
ret = PBMountVol(&pbr);
}
}
SwapMMUMode ( &busMode );
done:
return ret;
}
#pragma parameter __D0 cNuBusFPGARAMDskClose(__A0, __A1)
OSErr cNuBusFPGARAMDskClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
/* dce->dCtlDevBase = 0xfc000000; */
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0001); */
if (dce->dCtlStorage) {
//DisposePtr((Ptr)ctx->siqel);
/* HUnlock(dce->dCtlStorage); */ /* not needed before DisposeHandle */
DisposeHandle(dce->dCtlStorage);
dce->dCtlStorage = NULL;
}
return ret;
}

View File

@@ -0,0 +1,350 @@
#include "NuBusFPGARAMDskDrvr.h"
/* #include <DriverServices.h> */
__attribute__ ((section (".text.dskdriver"))) static inline void waitSome(unsigned long bound) {
unsigned long i;
for (i = 0 ; i < bound ; i++) {
asm volatile("nop");
}
}
// CLEANME: use the proper CSR accessor from nubusfpga_csr_exchange_with_mem.h
#ifdef ENABLE_DMA
__attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
if (ctx->op.blk_todo > 0) {
ctx->op.blk_doing = ctx->op.blk_todo;
if (ctx->op.blk_doing > 65535) { // fixme: read HW max
ctx->op.blk_doing = 32768; // nice Po2
}
write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + ctx->op.blk_offset));
write_reg(dce, DMA_DMA_ADDR, revb((uint32_t)(ctx->op.ioBuffer + (ctx->op.blk_done << ctx->dma_blk_size_shift))));
ctx->op.blk_done += ctx->op.blk_doing;
ctx->op.blk_todo -= ctx->op.blk_doing;
ctx->op.blk_offset += ctx->op.blk_doing;
write_reg(dce, DMA_BLK_CNT, revb((ctx->op.write ? 0x80000000ul : 0x00000000ul) | ctx->op.blk_doing));
}
}
#endif
#ifdef ENABLE_DMA
__attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
unsigned long count, max_count, delay;
unsigned long blk_cnt, status;
OSErr ret = noErr;
max_count = 32 * ctx->op.blk_doing;
delay = (ctx->op.blk_doing >> 4);
if (delay > 65536)
delay = 65536;
waitSome(delay);
count = 0;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
while (((blk_cnt != 0) ||
(status != 0)) &&
(count < max_count)) {
count ++;
waitSome(delay);
if (blk_cnt) blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
if (status) status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
}
if (blk_cnt || status) {
ret = ctx->op.write ? writErr : readErr;
}
return ret;
}
#endif
#ifdef ENABLE_DMA
/* see the comment for the FB irq */
#pragma parameter __D0 dskIrq(__A1)
__attribute__ ((section (".text.dskdriver"))) short dskIrq(const long sqParameter) {
register unsigned long p_D1 asm("d1"), p_D2 asm("d2");
AuxDCEPtr dce;
struct RAMDrvContext *ctx;
unsigned int irq;
short ret;
asm volatile("" : "+d" (p_D1), "+d" (p_D2));
dce = (AuxDCEPtr)sqParameter;
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
ret = 0;
irq = revb(read_reg(dce, DMA_IRQSTATUS));
if (irq & 1) {
unsigned int irqctrl = revb(read_reg(dce, DMA_IRQ_CTL));
irqctrl |= 0x2; // irq clear
write_reg(dce, DMA_IRQ_CTL, revb(irqctrl));
if (ctx->op.blk_todo > 0) {
startOneOp(ctx, dce);
} else {
if (ctx->op.blk_doing > 0) {
ctx->op.blk_doing = 0; // reset just in case
IODone((DCtlPtr)dce, noErr);
}
}
ret = 1;
}
asm volatile("" : : "d" (p_D1), "d" (p_D2));
return ret;
}
#endif
#ifdef ENABLE_DMA
__attribute__ ((section (".text.dskdriver"))) static OSErr doAsync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct RAMDrvContext *ctx) {
OSErr ret = noErr;
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
unsigned long abs_offset = 0;
/* IOParamPtr: Devices 1-53 (p73) */
/* **** WHERE **** */
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
case fsAtMark:
abs_offset = dce->dCtlPosition;
break;
case fsFromStart:
abs_offset = pb->ioPosOffset;
break;
case fsFromMark:
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
break;
default:
break;
}
/* **** WHAT **** */
/* Devices 1-33 (p53) */
if ((pb->ioTrap & 0x00FF) == aRdCmd) {
if(!(pb->ioPosMode & 0x40)) { // rdVerify, let's ignore it for now
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
if ((blk_cnt == 0) && (status == 0)) {
ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift;
ctx->op.blk_done = 0;
ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift;
ctx->op.ioBuffer = pb->ioBuffer;
ctx->op.write = 0;
/* should we do it now ? */
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
if (ctx->op.blk_todo > 0) {
startOneOp(ctx, dce);
goto done;
}
}
if (blk_cnt || status) {
ret = readErr;
goto done;
}
}
} else if ((pb->ioTrap & 0x00FF) == aWrCmd) {
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
if ((blk_cnt == 0) && (status == 0)) {
ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift;
ctx->op.blk_done = 0;
ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift;
ctx->op.ioBuffer = pb->ioBuffer;
ctx->op.write = 1;
/* should we do it now ? */
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
if (ctx->op.blk_todo > 0) {
startOneOp(ctx, dce);
goto done;
}
}
if (blk_cnt || status) {
ret = writErr;
goto done;
}
} else {
ret = paramErr;
goto done;
}
done:
return ret;
}
#endif // ENABLE_DMA
__attribute__ ((section (".text.dskdriver"))) static OSErr doSync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct RAMDrvContext *ctx) {
OSErr ret = noErr;
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
unsigned long abs_offset = 0;
/* IOParamPtr: Devices 1-53 (p73) */
/* **** WHERE **** */
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
case fsAtMark:
abs_offset = dce->dCtlPosition;
break;
case fsFromStart:
abs_offset = pb->ioPosOffset;
break;
case fsFromMark:
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
break;
default:
break;
}
/* **** WHAT **** */
/* Devices 1-33 (p53) */
if ((pb->ioTrap & 0x00FF) == aRdCmd) {
if(!(pb->ioPosMode & 0x40)) { // rdVerify, let's ignore it for now
#ifdef ENABLE_DMA
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580000); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)pb->ioBuffer); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
if ((((unsigned long)pb->ioBuffer & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)pb->ioReqCount & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)abs_offset & ctx->dma_blk_size_mask) == 0)) {
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
if ((blk_cnt == 0) && (status == 0)) {
ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift;
ctx->op.blk_done = 0;
ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift;
ctx->op.ioBuffer = pb->ioBuffer;
ctx->op.write = 0;
while (ctx->op.blk_todo > 0) {
startOneOp(ctx, dce);
ret = waitForHW(ctx, dce);
if (ret != noErr)
goto done;
}
}
if (blk_cnt || status) {
ret = readErr;
goto done;
}
} else
#endif
{
BlockMoveData((superslot + abs_offset), pb->ioBuffer, pb->ioReqCount);
}
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else if ((pb->ioTrap & 0x00FF) == aWrCmd) {
#ifdef ENABLE_DMA
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580001); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)pb->ioBuffer); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
if ((((unsigned long)pb->ioBuffer & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)pb->ioReqCount & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)abs_offset & ctx->dma_blk_size_mask) == 0)) {
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
if ((blk_cnt == 0) && (status == 0)) {
ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift;
ctx->op.blk_done = 0;
ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift;
ctx->op.ioBuffer = pb->ioBuffer;
ctx->op.write = 1;
while (ctx->op.blk_todo > 0) {
startOneOp(ctx, dce);
ret = waitForHW(ctx, dce);
if (ret != noErr)
goto done;
}
}
if (blk_cnt || status) {
ret = writErr;
goto done;
}
} else
#endif
{
BlockMoveData(pb->ioBuffer, (superslot + abs_offset), pb->ioReqCount);
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else {
ret = paramErr;
goto done;
}
done:
ctx->op.blk_doing = 0;
return ret;
}
/* Devices 1-34 (p54) */
#pragma parameter __D0 cNuBusFPGARAMDskPrime(__A0, __A1)
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct RAMDrvContext *ctx;
unsigned long abs_offset = 0;
/* IOParamPtr: Devices 1-53 (p73) */
/* **** WHERE **** */
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
case fsAtMark:
abs_offset = dce->dCtlPosition;
break;
case fsFromStart:
abs_offset = pb->ioPosOffset;
break;
case fsFromMark:
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
break;
default:
break;
}
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0003); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioTrap); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosMode); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosOffset); */
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
if (ctx) {
#ifdef ENABLE_DMA
if ((((unsigned long)pb->ioBuffer & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)pb->ioReqCount & ctx->dma_blk_size_mask) == 0) &&
(((unsigned long)abs_offset & ctx->dma_blk_size_mask) == 0) &&
(!(pb->ioTrap & (1<<noQueueBit)))) {
ret = changeRAMDskIRQ(dce, 1, (pb->ioTrap & 0x00FF) == aWrCmd ? writErr : readErr);
if (ret != noErr) {
IODone((DCtlPtr)dce, ret);
goto done;
}
// DMA-ifiable & queuable, go async
ret = doAsync(pb, dce, ctx);
// no IODone if ongoing, done at interrupt time
if (ret != noErr)
IODone((DCtlPtr)dce, ret);
goto done;
} else
#endif
{
#ifdef ENABLE_DMA
ret = changeRAMDskIRQ(dce, 0, (pb->ioTrap & 0x00FF) == aWrCmd ? writErr : readErr);
#endif
if (ret)
goto done;
ret = doSync(pb, dce, ctx);
if (!(pb->ioTrap & (1<<noQueueBit))) {
IODone((DCtlPtr)dce, ret);
}
goto done;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
goto done;
}
done:
return ret;
}

View File

@@ -0,0 +1,30 @@
#include "NuBusFPGARAMDskDrvr.h"
#pragma parameter __D0 cNuBusFPGARAMDskStatus(__A0, __A1)
OSErr cNuBusFPGARAMDskStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct RAMDrvContext *ctx;
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0004); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
if (ctx) {
switch (pb->csCode)
{
default:
ret = statusErr;
break;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
goto done;
}
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}

View File

@@ -0,0 +1,137 @@
#ifndef __NUBUSFPGARAMDSKDRVR_H__
#define __NUBUSFPGARAMDSKDRVR_H__
#include <Files.h>
#include <Devices.h>
#include <Slots.h>
#include <MacErrors.h>
#include <MacMemory.h>
#include <Disks.h>
#include "NuBusFPGADrvr.h"
struct SDCardContext {
DrvSts2 drvsts;
unsigned int dma_blk_size;
unsigned int dma_blk_size_mask;
unsigned int dma_blk_size_shift;
unsigned int dma_blk_per_sdblk;
unsigned int dma_blk_per_sdblk_lshift;
char slot;
char toto;
unsigned int max_rd_blk_len;
SlotIntQElement *siqel;
};
#include "nubusfpga_csr_common.h"
#if defined(NUBUSFPGA)
#include "../nubusfpga_csr_sdblock2mem.h"
#include "../nubusfpga_csr_sdcore.h"
//#include "../nubusfpga_csr_sdirq.h"
#include "../nubusfpga_csr_sdmem2block.h"
#include "../nubusfpga_csr_sdphy.h"
#include "../nubusfpga_csr_exchange_with_sd.h"
#elif defined(IISIFPGA)
#include "../IIsifpga_csr_sdblock2mem.h"
#include "../IIsifpga_csr_sdcore.h"
//#include "../IIsifpga_csr_sdirq.h"
#include "../IIsifpga_csr_sdmem2block.h"
#include "../IIsifpga_csr_sdphy.h"
#include "../IIsifpga_csr_exchange_with_sd.h"
#elif defined(QUADRAFPGA)
#include "../quadrafpga_csr_sdblock2mem.h"
#include "../quadrafpga_csr_sdcore.h"
//#include "../quadrafpga_csr_sdirq.h"
#include "../quadrafpga_csr_sdmem2block.h"
#include "../quadrafpga_csr_sdphy.h"
#include "../quadrafpga_csr_exchange_with_sd.h"
#else
#error "no board defined"
#endif
/* basically Litex BIOS code */
#ifndef CONFIG_CLOCK_FREQUENCY
#define CONFIG_CLOCK_FREQUENCY 100000000
#endif
#define CLKGEN_STATUS_BUSY 0x1
#define CLKGEN_STATUS_PROGDONE 0x2
#define CLKGEN_STATUS_LOCKED 0x4
#define SD_CMD_RESPONSE_SIZE 16
#define SD_OK 0
#define SD_CRCERROR 1
#define SD_TIMEOUT 2
#define SD_WRITEERROR 3
#define SD_SWITCH_CHECK 0
#define SD_SWITCH_SWITCH 1
#define SD_SPEED_SDR12 0
#define SD_SPEED_SDR25 1
#define SD_SPEED_SDR50 2
#define SD_SPEED_SDR104 3
#define SD_SPEED_DDR50 4
#define SD_DRIVER_STRENGTH_B 0
#define SD_DRIVER_STRENGTH_A 1
#define SD_DRIVER_STRENGTH_C 2
#define SD_DRIVER_STRENGTH_D 3
#define SD_GROUP_ACCESSMODE 0
#define SD_GROUP_COMMANDSYSTEM 1
#define SD_GROUP_DRIVERSTRENGTH 2
#define SD_GROUP_POWERLIMIT 3
#define SDCARD_STREAM_STATUS_OK 0b000
#define SDCARD_STREAM_STATUS_TIMEOUT 0b001
#define SDCARD_STREAM_STATUS_DATAACCEPTED 0b010
#define SDCARD_STREAM_STATUS_CRCERROR 0b101
#define SDCARD_STREAM_STATUS_WRITEERROR 0b110
#define SDCARD_CTRL_DATA_TRANSFER_NONE 0
#define SDCARD_CTRL_DATA_TRANSFER_READ 1
#define SDCARD_CTRL_DATA_TRANSFER_WRITE 2
#define SDCARD_CTRL_RESPONSE_NONE 0
#define SDCARD_CTRL_RESPONSE_SHORT 1
#define SDCARD_CTRL_RESPONSE_LONG 2
#define SDCARD_CTRL_RESPONSE_SHORT_BUSY 3
//#define SDCARD_DEBUG
#define SDCARD_CMD23_SUPPORT /* SET_BLOCK_COUNT */
#define SDCARD_CMD18_SUPPORT /* READ_MULTIPLE_BLOCK */
#define SDCARD_CMD25_SUPPORT /* WRITE_MULTIPLE_BLOCK */
#ifndef SDCARD_CLK_FREQ_INIT
#define SDCARD_CLK_FREQ_INIT 400000
#endif
#ifndef SDCARD_CLK_FREQ
#define SDCARD_CLK_FREQ 25000000
//#define SDCARD_CLK_FREQ 12500000
#endif
/* ctrl */
OSErr cNuBusFPGASDCardCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver")));
/* open, close */
OSErr cNuBusFPGASDCardOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver")));
OSErr cNuBusFPGASDCardClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver")));
void busy_wait(int d) __attribute__ ((section (".text.sddriver")));
void delay(int d) __attribute__ ((section (".text.sddriver")));
int sdcard_read(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) __attribute__ ((section (".text.sddriver")));
int sdcard_write(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) __attribute__ ((section (".text.sddriver")));
/* prime */
OSErr cNuBusFPGASDCardPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver")));
void waitSome(unsigned long bound) __attribute__ ((section (".text.sddriver")));
/* status */
OSErr cNuBusFPGASDCardStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver")));
uint32_t rledec(uint32_t* out, const uint32_t* in, const uint32_t len) __attribute__ ((section (".text.sddriver")));
#endif

View File

@@ -0,0 +1,23 @@
NuBusFPGASDCardDrvr:
.word 0x4f00 /* 0x4f00: ctl, status, read, write, needsLock [Devices.a] */
.word 0
.word 0
.word 0
/* Entry point offset table */
/* we can directly call the C version if it has the right calling convention */
.word cNuBusFPGASDCardOpen - NuBusFPGASDCardDrvr /* open routine */
.word cNuBusFPGASDCardPrime - NuBusFPGASDCardDrvr /* prime */
.word cNuBusFPGASDCardCtl - NuBusFPGASDCardDrvr /* control */
.word cNuBusFPGASDCardStatus- NuBusFPGASDCardDrvr /* status */
.word cNuBusFPGASDCardClose - NuBusFPGASDCardDrvr /* close */
_NuBusFPGASDCardTitle:
.byte _NuBusFPGASDCardTitle_StringEnd-.-1 /* pascal string length */
.ascii ".NuBusFPGASDCard_Drvr"
_NuBusFPGASDCardTitle_StringEnd:
.word 0 /* version number */
/* for entry points: */
/* A0 pointer to driver parameter block */
/* A1 pointer to driver device control entry */
ALIGN 2

View File

@@ -0,0 +1,59 @@
#include "NuBusFPGASDCardDrvr.h"
#if 0
OSErr changeSDCardIRQ(AuxDCEPtr dce, char en, OSErr err) {
struct SDCardContext *ctx = *(struct SDCardContext**)dce->dCtlStorage;
if (en != ctx->irqen) {
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0005); */
/* write_reg(dce, GOBOFB_DEBUG, en); */
if (en) {
if (SIntInstall(ctx->siqel, dce->dCtlSlot)) {
return err;
}
} else {
if (SIntRemove(ctx->siqel, dce->dCtlSlot)) {
return err;
}
}
write_reg(dce, DMA_IRQ_CTL, en ? revb(0x3) : revb(0x2)); // 0x2: always clear pending interrupt
ctx->irqen = en;
}
return noErr;
}
#endif
#pragma parameter __D0 cNuBusFPGASDCardCtl(__A0, __A1)
OSErr cNuBusFPGASDCardCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct SDCardContext *ctx;
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0002); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
ctx = *(struct SDCardContext**)dce->dCtlStorage;
if (ctx) {
switch (pb->csCode)
{
case kFormat:
ret = noErr;
break;
default:
ret = controlErr;
break;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
goto done;
}
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}

View File

@@ -0,0 +1,878 @@
#include "NuBusFPGASDCardDrvr.h"
#include <Disks.h>
/* FYI, missing in library with Retro68 */
/* void AddDrive(short drvrRefNum, short drvNum, DrvQElPtr qEl); */
/* re-implement with Retro68 features */
/* drVNum to high-order bits of num, drvrRefNum in low-order */
/* not sure how to do "parameter" without output ? */
#pragma parameter __D0 AddDrive(__D0, __A0)
__attribute__ ((section (".text.sddriver"))) static inline int dupAddDrive(unsigned long num, DrvQElPtr qEl) {
asm volatile(".word 0xA04E" : : "d" (num), "a" (qEl));
return num; // should cost nothing, num is already in D0
}
static int sdcard_init(struct SDCardContext* sdcc, uint32_t sc) __attribute__ ((section (".text.sddriver")));
#include <ROMDefs.h>
#pragma parameter __D0 cNuBusFPGASDCardOpen(__A0, __A1)
OSErr cNuBusFPGASDCardOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
DrvSts2 *dsptr; // pointer to the DrvSts2 in our context
int drvnum = 1;
struct SDCardContext *ctx;
OSErr ret = noErr;
char busMode;
char slot;
busMode = 1;
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
if (dce->dCtlDevBase == 0) { // for some unknown reason, we get an empty dCtlDevBase...
if ((dce->dCtlSlot > 0xE) || (dce->dCtlSlot < 0x9)) { // safety net
SpBlock mySpBlock;
SInfoRecord mySInfoRecord;
mySpBlock.spResult = (long)&mySInfoRecord;
mySpBlock.spSlot = 0x9; // start at first
mySpBlock.spID = 0;
mySpBlock.spExtDev = 0;
mySpBlock.spCategory = catProto;
mySpBlock.spCType = 0x1000; // typeDrive;
mySpBlock.spDrvrSW = drSwApple;
mySpBlock.spDrvrHW = 0xbeec; // DrHwNuBusFPGADsk
mySpBlock.spTBMask = 0;
ret = SNextTypeSRsrc(&mySpBlock);
if (ret)
goto done;
slot = mySpBlock.spSlot;
} else {
slot = dce->dCtlSlot;
}
dce->dCtlDevBase = 0xF0000000ul | ((unsigned long)slot << 24);
}
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0000); */
/* write_reg(dce, GOBOFB_DEBUG, dce->dCtlSlot); */
if (dce->dCtlStorage == nil) {
DrvQElPtr dq;
for(dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvnum)
drvnum = dq->dQDrive+1;
}
ReserveMemSys(sizeof(struct SDCardContext));
dce->dCtlStorage = NewHandleSysClear(sizeof(struct SDCardContext));
if (dce->dCtlStorage == nil) {
ret = openErr;
goto done;
}
HLock(dce->dCtlStorage);
ctx = *(struct SDCardContext **)dce->dCtlStorage;
ctx->slot = slot;
ctx->toto = 0; // removeme
/* init the SDCard, this will also fill out dsptr->driveSize & dsptr->driveS1 */
if (!sdcard_init(ctx, dce->dCtlDevBase)) {
ret = openErr;
HUnlock(dce->dCtlStorage);
DisposeHandle(dce->dCtlStorage);
dce->dCtlStorage = NULL;
goto done;
}
#if 0
ctx->dma_blk_size = exchange_with_sd_blk_size_read(dce->dCtlDevBase);
ctx->dma_blk_size_mask = ctx->dma_blk_size - 1; // size is Po2
ctx->dma_blk_size_shift = 0;
while ((1 << ctx->dma_blk_size_shift) < ctx->dma_blk_size) // fixme
ctx->dma_blk_size_shift++;
ctx->dma_blk_per_sdblk_lshift = 9 - ctx->dma_blk_size_shift;
ctx->dma_blk_per_sdblk = 1 << ctx->dma_blk_per_sdblk_lshift; // 512 / ctx->dma_blk_size
#endif
dsptr = &ctx->drvsts;
// dsptr->track /* current track */
dsptr->writeProt = 0; /* bit 7 = 1 if volume is locked */
dsptr->diskInPlace = 8; /* disk in drive */
// dsptr->installed /* drive installed */
// dsptr->sides /* -1 for 2-sided, 0 for 1-sided */
// dsptr->QLink /* next queue entry */
dsptr->qType = 1; /* 1 for HD20 */ /* Files 2-85 (p173) : 1 to enable S1 */
dsptr->dQDrive = drvnum; /* drive number */
dsptr->dQRefNum = dce->dCtlRefNum; /* driver reference number */
// dsptr->dQFSID /* file system ID */
/* driveSize & driveS1 filled by sdcard_init */
//dsptr->driveSize = ((DRIVE_SIZE_BYTES/512ul) & 0x0000FFFFul); /* (no comments in Disks.h) */
//dsptr->driveS1 = ((DRIVE_SIZE_BYTES/512ul) & 0xFFFF0000ul) >> 16; /* */
// dsptr->driveType
// dsptr->driveManf
// dsptr->driveChar
// dsptr->driveMisc
// MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
// write_reg(dce, GOBOFB_DEBUG, 0x0000DEAD);
// add the drive
//MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
dupAddDrive((dsptr->dQRefNum & 0xFFFF) | (drvnum << 16), (DrvQElPtr)&dsptr->qLink);
#if 0
ctx->dma_blk_size = revb( read_reg(dce, DMA_BLK_SIZE) );
ctx->dma_blk_size_mask = ctx->dma_blk_size - 1; // size is Po2
ctx->dma_blk_size_shift = 0;
while ((1 << ctx->dma_blk_size_shift) < ctx->dma_blk_size) // fixme
ctx->dma_blk_size_shift++;
ctx->dma_blk_base = revb( read_reg(dce, DMA_BLK_BASE) );
ctx->dma_mem_size = revb( read_reg(dce, DMA_MEM_SIZE) );
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580002); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_mask); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_shift); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_base); */
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_mem_size); */
{
SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement));
if (siqel == NULL) {
return openErr;
}
siqel->sqType = sIQType;
siqel->sqPrio = 7;
siqel->sqAddr = dskIrq;
siqel->sqParm = (long)dce;
ctx->siqel = siqel;
ctx->irqen = 0;
ctx->op.blk_todo = 0;
ctx->op.blk_done = 0;
ctx->op.blk_offset = 0;
ctx->op.blk_doing = 0;
ctx->op.ioBuffer = 0;
ctx->op.write = 0;
}
#endif
// auto-mount
if (0) {
ParamBlockRec pbr;
pbr.volumeParam.ioVRefNum = dsptr->dQDrive;
ret = PBMountVol(&pbr);
}
}
SwapMMUMode ( &busMode );
done:
return ret;
}
#pragma parameter __D0 cNuBusFPGASDCardClose(__A0, __A1)
OSErr cNuBusFPGASDCardClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct SDCardContext *ctx = *(struct SDCardContext**)dce->dCtlStorage;
/* dce->dCtlDevBase = 0xfc000000; */
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0001); */
if (dce->dCtlStorage) {
//DisposePtr((Ptr)ctx->siqel);
/* HUnlock(dce->dCtlStorage); */ /* not needed before DisposeHandle */
DisposeHandle(dce->dCtlStorage);
dce->dCtlStorage = NULL;
}
return ret;
}
/*-----------------------------------------------------------------------*/
/* Helpers */
/*-----------------------------------------------------------------------*/
#define max(x, y) (((x) > (y)) ? (x) : (y))
#define min(x, y) (((x) < (y)) ? (x) : (y))
/* In MacOS
Delay(unsigned long numTicks, unsigned long * finalTicks)
has ticks in 1/60th of a second or 16.6666 ms
*/
/* in NetBSD/sparc busy_wait is 1ms * d */
void busy_wait(int d) {
waitSome(d * 20000); // improveme
return;
}
/* in NetBSD/sparc delay is 1us * d */
void delay(int d) {
waitSome(d * 20); // improveme
return;
}
/*-----------------------------------------------------------------------*/
/* SDCard command helpers */
/*-----------------------------------------------------------------------*/
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_wait_cmd_done(uint32_t sc) {
unsigned int event;
#ifdef SDCARD_DEBUG
uint32_t r[SD_CMD_RESPONSE_SIZE/4];
#endif
for (;;) {
event = sdcore_cmd_event_read(sc);
#ifdef SDCARD_DEBUG
printf("cmdevt: %08x\n", event);
#endif
delay(10);
if (event & 0x1)
break;
}
#ifdef SDCARD_DEBUG
csr_rd_buf_uint32(sc, sc->sc_bhregs_sdcore + (CSR_SDCORE_CMD_RESPONSE_ADDR - CSR_SDCORE_BASE), r, SD_CMD_RESPONSE_SIZE/4);
printf("%08x %08x %08x %08x\n", r[0], r[1], r[2], r[3]);
#endif
if (event & 0x4)
return SD_TIMEOUT;
if (event & 0x8)
return SD_CRCERROR;
return SD_OK;
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_wait_data_done(uint32_t sc) {
unsigned int event;
for (;;) {
event = sdcore_data_event_read(sc);
#ifdef SDCARD_DEBUG
printf("dataevt: %08x\n", event);
#endif
if (event & 0x1)
break;
delay(10);
}
if (event & 0x4)
return SD_TIMEOUT;
else if (event & 0x8)
return SD_CRCERROR;
return SD_OK;
}
/*-----------------------------------------------------------------------*/
/* SDCard clocker functions */
/*-----------------------------------------------------------------------*/
/* round up to closest power-of-two */
__attribute__ ((section (".text.sddriver"))) static inline uint32_t pow2_round_up(uint32_t r) {
r--;
r |= r >> 1;
r |= r >> 2;
r |= r >> 4;
r |= r >> 8;
r |= r >> 16;
r++;
return r;
}
__attribute__ ((section (".text.sddriver"))) static inline void sdcard_set_clk_freq(uint32_t sc, uint32_t clk_freq, int show) {
uint32_t divider;
divider = clk_freq ? CONFIG_CLOCK_FREQUENCY/clk_freq : 256;
divider = pow2_round_up(divider);
divider = min(max(divider, 2), 256);
#ifdef SDCARD_DEBUG
show = 1;
#endif
if (show) {
/* this is the *effective* new clk_freq */
clk_freq = CONFIG_CLOCK_FREQUENCY/divider;
/*
printf("Setting SDCard clk freq to ");
if (clk_freq > 1000000)
printf("%d MHz\n", clk_freq/1000000);
else
printf("%d KHz\n", clk_freq/1000);
*/
}
sdphy_clocker_divider_write(sc, divider);
}
/*-----------------------------------------------------------------------*/
/* SDCard commands functions */
/*-----------------------------------------------------------------------*/
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_command(uint32_t sc, uint32_t arg, uint8_t cmd, uint8_t rsp) {
sdcore_cmd_argument_write(sc, arg);
sdcore_cmd_command_write(sc, (cmd << 8) | rsp);
sdcore_cmd_send_write(sc, 1);
return sdcard_wait_cmd_done(sc);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_go_idle(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("CMD0: GO_IDLE\n");
#endif
return sdcard_send_command(sc, 0, 0, SDCARD_CTRL_RESPONSE_NONE);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_ext_csd(uint32_t sc) {
uint32_t arg = 0x000001aa;
#ifdef SDCARD_DEBUG
printf("CMD8: SEND_EXT_CSD, arg: 0x%08x\n", arg);
#endif
return sdcard_send_command(sc, arg, 8, SDCARD_CTRL_RESPONSE_SHORT);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_cmd(uint32_t sc, uint16_t rca) {
#ifdef SDCARD_DEBUG
printf("CMD55: APP_CMD\n");
#endif
return sdcard_send_command(sc, rca << 16, 55, SDCARD_CTRL_RESPONSE_SHORT);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_send_op_cond(uint32_t sc, int hcs) {
uint32_t arg = 0x10ff8000;
if (hcs)
arg |= 0x60000000;
#ifdef SDCARD_DEBUG
printf("ACMD41: APP_SEND_OP_COND, arg: %08x\n", arg);
#endif
return sdcard_send_command(sc, arg, 41, SDCARD_CTRL_RESPONSE_SHORT_BUSY);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_all_send_cid(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("CMD2: ALL_SEND_CID\n");
#endif
return sdcard_send_command(sc, 0, 2, SDCARD_CTRL_RESPONSE_LONG);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_set_relative_address(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("CMD3: SET_RELATIVE_ADDRESS\n");
#endif
return sdcard_send_command(sc, 0, 3, SDCARD_CTRL_RESPONSE_SHORT);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_cid(uint32_t sc, uint16_t rca) {
#ifdef SDCARD_DEBUG
printf("CMD10: SEND_CID\n");
#endif
return sdcard_send_command(sc, rca << 16, 10, SDCARD_CTRL_RESPONSE_LONG);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_csd(uint32_t sc, uint16_t rca) {
#ifdef SDCARD_DEBUG
printf("CMD9: SEND_CSD\n");
#endif
return sdcard_send_command(sc, rca << 16, 9, SDCARD_CTRL_RESPONSE_LONG);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_select_card(uint32_t sc, uint16_t rca) {
#ifdef SDCARD_DEBUG
printf("CMD7: SELECT_CARD\n");
#endif
return sdcard_send_command(sc, rca << 16, 7, SDCARD_CTRL_RESPONSE_SHORT_BUSY);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_set_bus_width(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("ACMD6: SET_BUS_WIDTH\n");
#endif
return sdcard_send_command(sc, 2, 6, SDCARD_CTRL_RESPONSE_SHORT);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_switch(uint32_t sc, unsigned int mode, unsigned int group, unsigned int value) {
unsigned int arg;
arg = (mode << 31) | 0xffffff;
arg &= ~(0xf << (group * 4));
arg |= value << (group * 4);
//device_printf(sc->dk.sc_dev, "switch arg is 0x%08x\n", arg);
#ifdef SDCARD_DEBUG
printf("CMD6: SWITCH_FUNC\n");
#endif
sdcore_block_length_write(sc, 64);
sdcore_block_count_write(sc, 1);
while (sdcard_send_command(sc, arg, 6,
(SDCARD_CTRL_DATA_TRANSFER_READ << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return sdcard_wait_data_done(sc);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_send_scr(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("CMD51: APP_SEND_SCR\n");
#endif
sdcore_block_length_write(sc, 8);
sdcore_block_count_write(sc, 1);
while (sdcard_send_command(sc, 0, 51,
(SDCARD_CTRL_DATA_TRANSFER_READ << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return sdcard_wait_data_done(sc);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_set_blocklen(uint32_t sc, unsigned int blocklen) {
#ifdef SDCARD_DEBUG
printf("CMD16: SET_BLOCKLEN\n");
#endif
return sdcard_send_command(sc, blocklen, 16, SDCARD_CTRL_RESPONSE_SHORT);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_write_single_block(uint32_t sc, unsigned int blockaddr) {
#ifdef SDCARD_DEBUG
printf("CMD24: WRITE_SINGLE_BLOCK\n");
#endif
sdcore_block_length_write(sc, 512);
sdcore_block_count_write(sc, 1);
while (sdcard_send_command(sc, blockaddr, 24,
(SDCARD_CTRL_DATA_TRANSFER_WRITE << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return SD_OK;
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_write_multiple_block(uint32_t sc, unsigned int blockaddr, unsigned int blockcnt) {
#ifdef SDCARD_DEBUG
printf("CMD25: WRITE_MULTIPLE_BLOCK\n");
#endif
sdcore_block_length_write(sc, 512);
sdcore_block_count_write(sc, blockcnt);
while (sdcard_send_command(sc, blockaddr, 25,
(SDCARD_CTRL_DATA_TRANSFER_WRITE << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return SD_OK;
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_read_single_block(uint32_t sc, unsigned int blockaddr) {
#ifdef SDCARD_DEBUG
printf("CMD17: READ_SINGLE_BLOCK\n");
#endif
sdcore_block_length_write(sc, 512);
sdcore_block_count_write(sc, 1);
while (sdcard_send_command(sc, blockaddr, 17,
(SDCARD_CTRL_DATA_TRANSFER_READ << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return sdcard_wait_data_done(sc);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_read_multiple_block(uint32_t sc, unsigned int blockaddr, unsigned int blockcnt) {
#ifdef SDCARD_DEBUG
printf("CMD18: READ_MULTIPLE_BLOCK\n");
#endif
sdcore_block_length_write(sc, 512);
sdcore_block_count_write(sc, blockcnt);
while (sdcard_send_command(sc, blockaddr, 18,
(SDCARD_CTRL_DATA_TRANSFER_READ << 5) |
SDCARD_CTRL_RESPONSE_SHORT) != SD_OK);
return sdcard_wait_data_done(sc);
}
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_stop_transmission(uint32_t sc) {
#ifdef SDCARD_DEBUG
printf("CMD12: STOP_TRANSMISSION\n");
#endif
return sdcard_send_command(sc, 0, 12, SDCARD_CTRL_RESPONSE_SHORT_BUSY);
}
#if 0
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_status(uint32_t sc, uint16_t rca) {
#ifdef SDCARD_DEBUG
printf("CMD13: SEND_STATUS\n");
#endif
return sdcard_send_command(sc, rca << 16, 13, SDCARD_CTRL_RESPONSE_SHORT);
}
#endif
#if 1
__attribute__ ((section (".text.sddriver"))) static inline int sdcard_set_block_count(uint32_t sc, unsigned int blockcnt) {
#ifdef SDCARD_DEBUG
printf("CMD23: SET_BLOCK_COUNT\n");
#endif
return sdcard_send_command(sc, blockcnt, 23, SDCARD_CTRL_RESPONSE_SHORT);
}
#endif
__attribute__ ((section (".text.sddriver"))) static inline uint16_t sdcard_decode_rca(uint32_t sc) {
uint32_t r[SD_CMD_RESPONSE_SIZE/4];
csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4);
return (r[3] >> 16) & 0xffff;
}
__attribute__ ((section (".text.sddriver"))) static inline void sdcard_decode_cid(uint32_t sc) {
uint32_t r[SD_CMD_RESPONSE_SIZE/4];
csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4);
/* aprint_normal_dev(sc->dk.sc_dev, */
/* "CID Register: 0x%08x%08x%08x%08x " */
/* "Manufacturer ID: 0x%x " */
/* "Application ID 0x%x " */
/* "Product name: %c%c%c%c%c " */
/* "CRC: %02x " */
/* "Production date(m/yy): %d/%d " */
/* "PSN: %08x " */
/* "OID: %c%c\n", */
/* r[0], r[1], r[2], r[3], */
/* (r[0] >> 16) & 0xffff, */
/* r[0] & 0xffff, */
/* (r[1] >> 24) & 0xff, (r[1] >> 16) & 0xff, */
/* (r[1] >> 8) & 0xff, (r[1] >> 0) & 0xff, (r[2] >> 24) & 0xff, */
/* r[3] & 0xff, */
/* (r[3] >> 8) & 0x0f, (r[3] >> 12) & 0xff, */
/* (r[3] >> 24) | (r[2] << 8), */
/* (r[0] >> 16) & 0xff, (r[0] >> 8) & 0xff */
/* ); */
}
__attribute__ ((section (".text.sddriver"))) static inline void sdcard_decode_csd(struct SDCardContext* sdcc, uint32_t sc) {
uint32_t r[SD_CMD_RESPONSE_SIZE/4];
csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4);
/* FIXME: only support CSR structure version 2.0 */
//sc->max_rd_blk_len = (1 << ((r[1] >> 16) & 0xf));
//sc->max_size_in_blk = ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 * 2;
uint32_t max_size_in_blk = ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 * 2; // weird spec in 512KiB unit
if (max_size_in_blk >= 4194304) // 2 GiB
max_size_in_blk = 4194303; // 2 GiB - 512 B
#define MAX_DSK_SIZE_MB 80
if (max_size_in_blk >= (MAX_DSK_SIZE_MB*(1048576/512))) // TEMPORARY FOR TESTING
max_size_in_blk = (MAX_DSK_SIZE_MB*(1048576/512)); // TEMPORARY FOR TESTING
sdcc->drvsts.driveSize = max_size_in_blk & 0x0000FFFF;
sdcc->drvsts.driveS1 = (max_size_in_blk & 0xFFFF0000) >> 16;
sdcc->max_rd_blk_len = (1 << ((r[1] >> 16) & 0xf)); // READ_BL_LEN ? should always be 9 ?
/* aprint_normal_dev(sc->dk.sc_dev, */
/* "CSD Register: 0x%08x%08x%08x%08x " */
/* "Max data transfer rate: %d MB/s " */
/* "Max read block length: %d bytes " */
/* "Device size: %d GiB (%d blocks)\n", */
/* r[0], r[1], r[2], r[3], */
/* (r[0] >> 24) & 0xff, */
/* sc->max_rd_blk_len, */
/* ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 / (1024 * 1024), */
/* sc->max_size_in_blk */
/* ); */
}
/*-----------------------------------------------------------------------*/
/* SDCard user functions */
/*-----------------------------------------------------------------------*/
static int sdcard_init(struct SDCardContext* sdcc, uint32_t sc) {
uint16_t rca, timeout;
int res;
/* Set SD clk freq to Initialization frequency */
sdcard_set_clk_freq(sc, SDCARD_CLK_FREQ_INIT, 0);
busy_wait(1);
for (timeout=1000; timeout>0; timeout--) {
/* Set SDCard in SPI Mode (generate 80 dummy clocks) */
sdphy_init_initialize_write(sc, 1);
busy_wait(1);
/* Set SDCard in Idle state */
if (sdcard_go_idle(sc) == SD_OK)
break;
busy_wait(1);
}
if (timeout == 0) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard timeout (1)\n");
return 0;
}
/* Set SDCard voltages, only supported by ver2.00+ SDCards */
if ((res = sdcard_send_ext_csd(sc)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_send_ext_csd failed\n");
return 0;
}
/* Set SD clk freq to Operational frequency */
sdcard_set_clk_freq(sc, SDCARD_CLK_FREQ, 0);
busy_wait(1);
/* Set SDCard in Operational state */
for (timeout=1000; timeout>0; timeout--) {
sdcard_app_cmd(sc, 0);
if ((res = sdcard_app_send_op_cond(sc, 1)) != SD_OK)
break;
busy_wait(1);
}
if (timeout == 0) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard timeout (2)\n");
return 0;
}
/* Send identification */
if ((res = sdcard_all_send_cid(sc)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_all_send_cid failed (%d)\n", res);
return 0;
}
sdcard_decode_cid(sc);
/* Set Relative Card Address (RCA) */
if ((res = sdcard_set_relative_address(sc)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_set_relative_address failed (%d)\n", res);
return 0;
}
rca = sdcard_decode_rca(sc);
//device_printf(sc->dk.sc_dev, "rca is 0x%08x\n", rca);
/* Set CID */
if ((res = sdcard_send_cid(sc, rca)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_send_cid failed (%d)\n", res);
return 0;
}
#ifdef SDCARD_DEBUG
/* FIXME: add cid decoding (optional) */
#endif
/* Set CSD */
if ((res = sdcard_send_csd(sc, rca)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_send_csd failed (%d)\n", res);
return 0;
}
sdcard_decode_csd(sdcc, sc);
/* Select card */
if ((res = sdcard_select_card(sc, rca)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_select_card failed (%d)\n", res);
return 0;
}
/* Set bus width */
if ((res = sdcard_app_cmd(sc, rca)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_app_cmd failed (%d)\n", res);
return 0;
}
if((res = sdcard_app_set_bus_width(sc)) != SD_OK){
//aprint_error_dev(sc->dk.sc_dev, "sdcard_app_set_bus_width failed (%d)\n", res);
return 0;
}
/* Switch speed */
if ((res = sdcard_switch(sc, SD_SWITCH_SWITCH, SD_GROUP_ACCESSMODE, SD_SPEED_SDR25)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_switch failed (%d)\n", res);
return 0;
}
/* Send SCR */
/* FIXME: add scr decoding (optional) */
if ((res = sdcard_app_cmd(sc, rca)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_app_cmd failed (%d)\n", res);
return 0;
}
if ((res = sdcard_app_send_scr(sc)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_app_send_scr failed (%d)\n", res);
return 0;
}
/* Set block length */
if ((res = sdcard_app_set_blocklen(sc, 512)) != SD_OK) {
//aprint_error_dev(sc->dk.sc_dev, "sdcard_app_set_blocklen failed (%d)\n", res);
return 0;
}
return 1;
}
#if 1
__attribute__ ((section (".text.sddriver"))) static inline void do_copy_rev(uint32_t *src, uint32_t *dst, uint32_t size) {
uint32_t i;
for (i = 0 ; i < size/4 ; i++) {
dst[i] = revb(src[i]);
}
}
#endif
__attribute__ ((section (".text.sddriver"))) static inline OSErr start_dma_read(uint32_t sc, struct SDCardContext *ctx, uint32_t count, uint8_t* buf) {
unsigned int dma_blk_cnt = count << ctx->dma_blk_per_sdblk_lshift;
exchange_with_sd_blk_addr_write(sc, 0);
exchange_with_sd_dma_addr_write(sc, buf);
exchange_with_sd_blk_cnt_write(sc, dma_blk_cnt | 0x80000000); // MSb==1, read
return noErr;
}
__attribute__ ((section (".text.sddriver"))) static inline OSErr start_dma_write(uint32_t sc, struct SDCardContext *ctx, uint32_t count, uint8_t* buf) {
unsigned int dma_blk_cnt = count << ctx->dma_blk_per_sdblk_lshift;
exchange_with_sd_blk_addr_write(sc, 0);
exchange_with_sd_dma_addr_write(sc, buf);
exchange_with_sd_blk_cnt_write(sc, dma_blk_cnt); // MSb==0, write
return noErr;
}
#if 0
#define DMA_STATUS_CHECK_BITS (0x01F)
__attribute__ ((section (".text.sddriver"))) static inline OSErr wait_dma(uint32_t sc, uint32_t blk_count, OSErr err) {
unsigned long count, max_count, delay;
unsigned long blk_cnt, status;
OSErr ret = noErr;
max_count = 32 * blk_count;
delay = blk_count >> 2;
if (delay > 65536)
delay = 65536;
waitSome(delay);
count = 0;
blk_cnt = exchange_with_sd_blk_cnt_blk_cnt_read(sc);
status = exchange_with_sd_dma_status_read(sc) & DMA_STATUS_CHECK_BITS;
while (((blk_cnt != 0) ||
(status != 0)) &&
(count < max_count)) {
count ++;
waitSome(delay);
if (blk_cnt) blk_cnt = exchange_with_sd_blk_cnt_blk_cnt_read(sc);
if (status) status = exchange_with_sd_dma_status_read(sc) & DMA_STATUS_CHECK_BITS;
}
if (blk_cnt || status) {
ret = err;
}
return ret;
}
#endif
int sdcard_read(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) {
while (count) {
uint32_t nblocks;
//uint64_t buf_hw_addr = ((uint64_t)((uint32_t)buf));// << 32;
uint32_t buf_hw_addr = (uint32_t)buf; // TEMPORARY FOR TESTING // VIRTUAL NEEDS TO GO THROUGH MemoryManager
uint32_t stage_addr_dma = 0x80000000; // DDR // TEMPORARY FOR TESTING
uint32_t stage_addr_cpu = sc << 4; // superslot // TEMPORARY FOR TESTING
#ifdef SDCARD_CMD18_SUPPORT
nblocks = count;
if (nblocks > 16)
nblocks = 16;
#else
nblocks = 1;
#endif
#if 1
/* Initialize DMA Writer */
sdblock2mem_dma_enable_write(sc, 0);
/* sdblock2mem_dma_base_write takes an uint64_t */
////sdblock2mem_dma_base_write(sc, buf_hw_addr);
sdblock2mem_dma_base_write(sc, stage_addr_dma);
sdblock2mem_dma_length_write(sc, 512*nblocks);
sdblock2mem_dma_enable_write(sc, 1);
#else
start_dma_write(sc, ctx, nblocks, buf_hw_addr); // read from sdcard, write to memory
#endif
/* Read Block(s) from SDCard */
#ifdef SDCARD_CMD23_SUPPORT
sdcard_set_block_count(sc, nblocks);
#endif
if (nblocks > 1)
sdcard_read_multiple_block(sc, block, nblocks);
else
sdcard_read_single_block(sc, block);
#if 1
//int timeout = 64 * nblocks;
int timeout = 1024 * nblocks;
/* Wait for DMA Writer to complete */
while (((sdblock2mem_dma_done_read(sc) & 0x1) == 0) && timeout) {
//delay(2);
delay(20);
timeout --;
}
if ((sdblock2mem_dma_done_read(sc) & 0x1) == 0) {
/* device_printf(sc->dk.sc_dev, "%s: SD card timeout\n", __PRETTY_FUNCTION__); */
return 1;
}
#else
if (wait_dma(sc, nblocks, readErr) != noErr)
return 1;
#endif
/* Stop transmission (Only for multiple block reads) */
if (nblocks > 1)
sdcard_stop_transmission(sc);
BlockMoveData((void*)stage_addr_cpu, (void*)buf_hw_addr, 512*nblocks);
//do_copy_rev((void*)stage_addr_cpu, (void*)buf_hw_addr, 512*nblocks);
/* Update Block/Buffer/Count */
block += nblocks;
buf += 512*nblocks;
count -= nblocks;
}
return 0;
}
int sdcard_write(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) {
while (count) {
uint32_t nblocks;
//uint64_t buf_hw_addr = ((uint64_t)((uint32_t)buf));// << 32;
uint32_t buf_hw_addr = (uint32_t)buf; // TEMPORARY FOR TESTING
uint32_t stage_addr_dma = 0x80000000; // DDR // TEMPORARY FOR TESTING
uint32_t stage_addr_cpu = sc << 4; // superslot // TEMPORARY FOR TESTING
#ifdef SDCARD_CMD25_SUPPORT
nblocks = count;
if (nblocks > 16)
nblocks = 16;
#else
nblocks = 1;
#endif
BlockMoveData((void*)buf_hw_addr, (void*)stage_addr_cpu, 512*nblocks);
//do_copy_rev((void*)buf_hw_addr, (void*)stage_addr_cpu, 512*nblocks);
#if 1
/* Initialize DMA Reader */
sdmem2block_dma_enable_write(sc, 0);
/* sdblock2mem_dma_base_write takes an uint64_t */
////sdmem2block_dma_base_write(sc, buf_hw_addr);
sdmem2block_dma_base_write(sc, stage_addr_dma);
sdmem2block_dma_length_write(sc, 512*nblocks);
sdmem2block_dma_enable_write(sc, 1);
#else
start_dma_read(sc, ctx, nblocks, buf_hw_addr); // write to sdcard, read from memory
#endif
/* Write Block(s) to SDCard */
#ifdef SDCARD_CMD23_SUPPORT
sdcard_set_block_count(sc, nblocks);
#endif
if (nblocks > 1)
sdcard_write_multiple_block(sc, block, nblocks);
else
sdcard_write_single_block(sc, block);
/* Stop transmission (Only for multiple block writes) */
//if (nblocks > 1)
// sdcard_stop_transmission(sc);
#if 1
/* Wait for DMA Reader to complete */
//int timeout = 64 * nblocks;
int timeout = 1024 * nblocks;
while (((sdmem2block_dma_done_read(sc) & 0x1) == 0) && timeout) {
//delay(2);
delay(20);
timeout --;
}
if ((sdmem2block_dma_done_read(sc) & 0x1) == 0) {
/* device_printf(sc->dk.sc_dev, "%s: SD card timeout\n", __PRETTY_FUNCTION__); */
return 1;
}
#else
if (wait_dma(sc, nblocks, writErr) != noErr)
return 1;
#endif
if (nblocks > 1)
sdcard_stop_transmission(sc);
/* Update Block/Buffer/Count */
block += nblocks;
buf += 512*nblocks;
count -= nblocks;
}
return 0;
}

View File

@@ -0,0 +1,111 @@
#include "NuBusFPGASDCardDrvr.h"
/* #include <DriverServices.h> */
inline void waitSome(unsigned long bound) {
unsigned long i;
for (i = 0 ; i < bound ; i++) {
asm volatile("nop");
}
}
__attribute__ ((section (".text.sddriver"))) static OSErr doSync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct SDCardContext *ctx) {
OSErr ret = noErr;
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
unsigned long abs_offset = 0;
/* IOParamPtr: Devices 1-53 (p73) */
/* **** WHERE **** */
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
case fsAtMark:
abs_offset = dce->dCtlPosition;
break;
case fsFromStart:
abs_offset = pb->ioPosOffset;
break;
case fsFromMark:
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
break;
default:
break;
}
/* **** WHAT **** */
/* Devices 1-33 (p53) */
if ((pb->ioTrap & 0x00FF) == aRdCmd) {
if(!(pb->ioPosMode & 0x40)) { // rdVerify, let's ignore it for now
if (abs_offset & 0x01FF) {
ret = paramErr;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount;
goto done;
}
if (pb->ioReqCount & 0x01FF) {
ret = paramErr;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount;
goto done;
}
if (sdcard_read(dce->dCtlDevBase, ctx, abs_offset >> 9, pb->ioReqCount >> 9, pb->ioBuffer)) {
ret = readErr;
goto done;
}
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else if ((pb->ioTrap & 0x00FF) == aWrCmd) {
if (abs_offset & 0x01FF) {
ret = paramErr;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount;
goto done;
}
if (pb->ioReqCount & 0x01FF) {
ret = paramErr;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset;
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount;
goto done;
}
if (sdcard_write(dce->dCtlDevBase, ctx, abs_offset >> 9, pb->ioReqCount >> 9, pb->ioBuffer)) {
ret = writErr;
goto done;
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else {
ret = paramErr;
goto done;
}
done:
if (ret != noErr)
*(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x800) = ret | (((pb->ioTrap & 0x00FF) == aRdCmd) ? 0x11000000 : 0x22000000);
return ret;
}
/* Devices 1-34 (p54) */
#pragma parameter __D0 cNuBusFPGASDCardPrime(__A0, __A1)
OSErr cNuBusFPGASDCardPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) {
OSErr ret = noErr;
struct SDCardContext *ctx;
unsigned long abs_offset = 0;
ctx = *(struct SDCardContext**)dce->dCtlStorage;
if (ctx) {
ret = doSync(pb, dce, ctx);
if (!(pb->ioTrap & (1<<noQueueBit))) {
IODone((DCtlPtr)dce, ret);
}
goto done;
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
goto done;
}
done:
return ret;
}

View File

@@ -0,0 +1,30 @@
#include "NuBusFPGASDCardDrvr.h"
#pragma parameter __D0 cNuBusFPGASDCardStatus(__A0, __A1)
OSErr cNuBusFPGASDCardStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct SDCardContext *ctx;
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0004); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
ctx = *(struct SDCardContext**)dce->dCtlStorage;
if (ctx) {
switch (pb->csCode)
{
default:
ret = statusErr;
break;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
goto done;
}
done:
if (!(pb->ioTrap & (1<<noQueueBit)))
IODone((DCtlPtr)dce, ret);
return ret;
}

View File

@@ -0,0 +1,93 @@
#include "NuBusFPGADrvr.h"
#include <Traps.h>
#define SECO_WRITEREG(reg, val) \
*((volatile UInt32*)(a32+GOBOFB_BASE+reg)) = (UInt32)val;
#pragma parameter __D0 Primary(__A0)
UInt32 Secondary(SEBlock* seblock) {
UInt32 a32 = 0xF0000000 | ((UInt32)seblock->seSlot << 24);
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
SpBlock spblock;
/* UInt8 pram[8]; */
OSErr err;
UInt16 i,j;
char busMode;
UniversalProcPtr qd32ptr, unimpptr;
busMode = 1;
/* call SVersion to figure out if we have a recent SlotManager */
#if 0
//spblock.spSlot = seblock->seSlot;
//spblock.spExtDev = 0;
err = SVersion(&spblock);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* DCDMF3 p178: if error, old slot manager*/
/* SECO_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* SECO_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* DCDMF3 p178: new slot manager */
/* SECO_WRITEREG(GOBOFB_DEBUG, 0);*/
/* SECO_WRITEREG(GOBOFB_DEBUG, spblock.spResult);*/
}
SwapMMUMode ( &busMode ); // restore
#endif
#if 1
/* check for 32-bits QuickDraw */
qd32ptr = GetTrapAddress(Check32QDTrap);
unimpptr = GetTrapAddress(_Unimplemented);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (qd32ptr == unimpptr) {
/* no 32QD */
SECO_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);
SECO_WRITEREG(GOBOFB_DEBUG, unimpptr);
} else {
/* yes 32QD */
SECO_WRITEREG(GOBOFB_DEBUG, 0x00C0FFEE);
}
SwapMMUMode ( &busMode ); // restore
#endif
#if 0
/* check the content of the PRAM */
spblock.spSlot = seblock->seSlot;
spblock.spResult = (UInt32)pram;
err = SReadPRAMRec(&spblock);
#if 0
SECO_WRITEREG(GOBOFB_DEBUG, 0x88888888);
for (j = 0 ; j < 8 ; j++)
SECO_WRITEREG(GOBOFB_DEBUG, (uint32_t)pram[j]);
SECO_WRITEREG(GOBOFB_DEBUG, 0x88888888);
#endif
#endif
#if 0
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* SECO_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* SECO_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* SECO_WRITEREG(GOBOFB_DEBUG, 0xC0FFEE00);*/
/* for (i = 0 ; i < 8 ; i++) */
/* SECO_WRITEREG(GOBOFB_DEBUG, pram[i]);*/
}
SwapMMUMode ( &busMode ); // restore
#endif
seblock->seStatus = 1;
return 0;
}

197
DeclROM/ROMDefs.inc Normal file
View File

@@ -0,0 +1,197 @@
appleFormat = 1
romRevision = 1
romRevRange = 9
testPattern = 1519594439L
sCodeRev = 2
sExec2 = 2
sCPU68000 = 1
sCPU68020 = 2
sCPU68030 = 3
sCPU68040 = 4
sMacOS68000 = 1
sMacOS68020 = 2
sMacOS68030 = 3
sMacOS68040 = 4
board = 0
displayVideoAppleTFB = 16843009L
displayVideoAppleGM = 16843010L
networkEtherNetApple3Com = 33620225L
testSimpleAppleAny = -2147417856L
endOfList = 255
defaultTO = 100
fOpenAtStart = 1
f32BitMode = 2
sRsrcType = 1
sRsrcName = 2
sRsrcIcon = 3
sRsrcDrvrDir = 4
sRsrcLoadDir = 5
sRsrcBootRec = 6
sRsrcFlags = 7
sRsrcHWDevId = 8
minorBaseOS = 10
majorBaseOS = 12
majorLength = 13
sRsrcTest = 14
sRsrccicn = 15
sRsrcicl8 = 16
sRsrcicl4 = 17
sDRVRDir = 16
sGammaDir = 64
sRsrcVidNames = 65
sRsrcDock = 80
sDiagRec = 85
sVidAuxParams = 123
sDebugger = 124
sVidAttributes = 125
fLCDScreen = 0
fBuiltInDisplay = 1
fDefaultColor = 2
fActiveBlack = 3
fDimMinAt1 = 4
fBuiltInDetach = 4
sVidParmDir = 126
sBkltParmDir = 140
sSuperDir = 254
/* = */
/* = */
catBoard = 0x0001
catTest = 0x0002
catDisplay = 0x0003
catNetwork = 0x0004
catScanner = 0x0008
catCPU = 0x000A
catIntBus = 0x000C
catProto = 0x0011
catDock = 0x0020
typeBoard = 0x0000
typeApple = 0x0001
typeVideo = 0x0001
typeEtherNet = 0x0001
typeStation = 0x0001
typeDesk = 0x0002
typeTravel = 0x0003
typeDSP = 0x0004
typeXPT = 0x000B
typeSIM = 0x000C
typeDebugger = 0x0100
type68000 = 0x0002
type68020 = 0x0003
type68030 = 0x0004
type68040 = 0x0005
type601 = 0x0025
type603 = 0x002E
typeAppleII = 0x0015
drSwMacCPU = 0
drSwAppleIIe = 0x0001
drSwApple = 1
drSwMacsBug = 0x0104
drSwDepewEngineering = 0x0101
drHwTFB = 1
drHw3Com = 1
drHwBSC = 3
drHwGemini = 1
drHwDeskBar = 1
drHwATT3210 = 0x0001
drHwBootBug = 0x0100
drHwMicroDock = 0x0100
drHwSTB3 = 0x0002
drHwSTB = drHwSTB3
drHwRBV = 0x0018
drHwElsie = 0x001A
drHwTim = 0x001B
drHwDAFB = 0x001C
drHwGSC = 0x001E
drHwDAFBPDS = 0x001F
drHWVSC = 0x0020
drHwApollo = 0x0021
drHwSonora = 0x0022
drHwReserved2 = 0x0023
drHwColumbia = 0x0024
drHwCivic = 0x0025
drHwBrazil = 0x0026
drHWPBLCD = 0x0027
drHWCSC = 0x0028
drHwJET = 0x0029
drHWMEMCjr = 0x002A
drHwHPV = 0x002C
drHwPlanaria = 0x002D
drHwValkyrie = 0x002E
drHwKeystone = 0x002F
drHWATI = 0x0055
drHwGammaFormula = 0x0056
drHwSonic = 0x0110
drHwMace = 0x0114
drHwDblExp = 0x0001
MIIBoardId = 0x0010
ciVidBoardID = 0x001F
CX16VidBoardID = 0x0020
MIIxBoardId = 0x0021
SE30BoardID = 0x0022
MIIcxBoardId = 0x0023
MIIfxBoardId = 0x0024
EricksonBoardID = 0x0028
ElsieBoardID = 0x0029
TIMBoardID = 0x002A
EclipseBoardID = 0x002B
SpikeBoardID = 0x0033
DBLiteBoardID = 0x0035
ZydecoBrdID = 0x0036
ApolloBoardID = 0x0038
PDMBrdID = 0x0039
VailBoardID = 0x003A
WombatBrdID = 0x003B
ColumbiaBrdID = 0x003C
CycloneBrdID = 0x003D
CompanionBrdID = 0x003E
DartanianBoardID = 0x0040
DartExtVidBoardID = 0x0046
HookBoardID = 0x0047
EscherBoardID = 0x004A
POBoardID = 0x004D
TempestBrdID = 0x0050
BlackBirdBdID = 0x0058
BBExtVidBdID = 0x0059
YeagerBoardID = 0x005A
BBEtherNetBdID = 0x005E
TELLBoardID = 0x0065
MalcolmBoardID = 0x065E
AJBoardID = 0x065F
M2BoardID = 0x0660
OmegaBoardID = 0x0661
TNTBoardID = 0x0670
HooperBoardID = 0x06CD
BoardIDDblExp = 0x002F
DAFBPDSBoardID = 0x0037
MonetBoardID = 0x0048
SacSONIC16BoardID = 0x004E
SacSONIC32BoardID = 0x004F
drHWMacII = 0x0001
drHwMacIIx = 0x0002
drHWSE30 = 0x0003
drHwMacIIcx = 0x0004
drHWMacIIfx = 0x0005
drHWF19 = 0x0005
sBlockTransferInfo = 20
sMaxLockedTransferCount = 21
boardId = 32
pRAMInitData = 33
primaryInit = 34
timeOutConst = 35
vendorInfo = 36
boardFlags = 37
secondaryInit = 38
MajRAMSp = 129
MinROMSp = 130
vendorId = 1
serialNum = 2
revLevel = 3
partNum = 4
date = 5
testByte = 32
testWord = 33
testLong = 34
testString = 35
mBlockTransferInfo = 5
mMaxLockedTransferCount = 6

358
DeclROM/Video.inc Normal file
View File

@@ -0,0 +1,358 @@
mBaseOffset = 1 /*IdofmBaseOffset.*/
mRowBytes = 2 /*VideosResourceparameterId's*/
mBounds = 3 /*VideosResourceparameterId's*/
mVersion = 4 /*VideosResourceparameterId's*/
mHRes = 5 /*VideosResourceparameterId's*/
mVRes = 6 /*VideosResourceparameterId's*/
mPixelType = 7 /*VideosResourceparameterId's*/
mPixelSize = 8 /*VideosResourceparameterId's*/
mCmpCount = 9 /*VideosResourceparameterId's*/
mCmpSize = 10 /*VideosResourceparameterId's*/
mPlaneBytes = 11 /*VideosResourceparameterId's*/
mVertRefRate = 14 /*VideosResourceparameterId's*/
mVidParams = 1 /*Videoparameterblockid.*/
mTable = 2 /*Offsettothetable.*/
mPageCnt = 3 /*Numberofpages*/
mDevType = 4 /*DeviceType*/
oneBitMode = 128 /*IdofOneBitModeParameterlist.*/
twoBitMode = 129 /*IdofTwoBitModeParameterlist.*/
fourBitMode = 130 /*IdofFourBitModeParameterlist.*/
eightBitMode = 131/*IdofEightBitModeParameterlist.*/
sixteenBitMode = 132 /*IdofSixteenBitModeParameterlist.*/
thirtyTwoBitMode = 133 /*IdofThirtyTwoBitModeParameterlist.*/
firstVidMode = 128 /*Thenew,betterwaytodotheabove.*/
secondVidMode = 129 /*QuickDrawonlysupportssixvideo*/
thirdVidMode = 130 /*atthistime.*/
fourthVidMode = 131
fifthVidMode = 132
sixthVidMode = 133
spGammaDir = 64
spVidNamesDir = 65
/* kDeclROMtables = FOUR_CHAR_CODE('decl') */
/* kDetailedTimingFormat = FOUR_CHAR_CODE('arba') */ /*Timingisadetailedtiming*/
kDDCBlockSize = 128
kDDCBlockTypeEDID = 0/*EDIDblocktype.*/
kDDCForceReadBit = 0 /*ForceanewreadoftheEDID.*/
kDDCForceReadMask = (1<<kDDCForceReadBit)/*MaskforkddcForceReadBit.*/
timingInvalid_SM_T24 = 8 /*WorkaroundbuginSMThunder24card.*/
timingApple_FixedRateLCD = 42 /*Lumpallfixed-rateLCDsintoonecategory.*/
timingApple_512x384_60hz = 130 /*512x384(60Hz)Rubiktiming.*/
timingApple_560x384_60hz = 135 /*560x384(60Hz)Rubik-560timing.*/
timingApple_640x480_67hz = 140 /*640x480(67Hz)HRtiming.*/
timingApple_640x400_67hz = 145 /*640x400(67Hz)HR-400timing.*/
timingVESA_640x480_60hz = 150 /*640x480(60Hz)VGAtiming.*/
timingVESA_640x480_72hz = 152 /*640x480(72Hz)VGAtiming.*/
timingVESA_640x480_75hz = 154 /*640x480(75Hz)VGAtiming.*/
timingVESA_640x480_85hz = 158 /*640x480(85Hz)VGAtiming.*/
timingGTF_640x480_120hz = 159 /*640x480(120Hz)VESAGeneralizedTimingFormula*/
timingApple_640x870_75hz = 160 /*640x870(75Hz)FPDtiming.*/
timingApple_640x818_75hz = 165 /*640x818(75Hz)FPD-818timing.*/
timingApple_832x624_75hz = 170 /*832x624(75Hz)GoldFishtiming.*/
timingVESA_800x600_56hz = 180 /*800x600(56Hz)SVGAtiming.*/
timingVESA_800x600_60hz = 182 /*800x600(60Hz)SVGAtiming.*/
timingVESA_800x600_72hz = 184 /*800x600(72Hz)SVGAtiming.*/
timingVESA_800x600_75hz = 186 /*800x600(75Hz)SVGAtiming.*/
timingVESA_800x600_85hz = 188 /*800x600(85Hz)SVGAtiming.*/
timingVESA_1024x768_60hz = 190 /*1024x768(60Hz)VESA1K-60Hztiming.*/
timingVESA_1024x768_70hz = 200 /*1024x768(70Hz)VESA1K-70Hztiming.*/
timingVESA_1024x768_75hz = 204 /*1024x768(75Hz)VESA1K-75Hztiming(verysimilarto
timingVESA_1024x768_85hz = 208 /*1024x768(85Hz)VESAtiming.*/
timingApple_1024x768_75hz = 210 /*1024x768(75Hz)Apple19"RGB.*/
timingApple_1152x870_75hz = 220 /*1152x870(75Hz)Apple21"RGB.*/
timingAppleNTSC_ST = 230 /*512x384(60Hz,interlaced,non-convolved).*/
timingAppleNTSC_FF = 232 /*640x480(60Hz,interlaced,non-convolved).*/
timingAppleNTSC_STconv = 234 /*512x384(60Hz,interlaced,convolved).*/
timingAppleNTSC_FFconv = 236 /*640x480(60Hz,interlaced,convolved).*/
timingApplePAL_ST = 238 /*640x480(50Hz,interlaced,non-convolved).*/
timingApplePAL_FF = 240 /*768x576(50Hz,interlaced,non-convolved).*/
timingApplePAL_STconv = 242 /*640x480(50Hz,interlaced,convolved).*/
timingApplePAL_FFconv = 244 /*768x576(50Hz,interlaced,convolved).*/
timingVESA_1280x960_75hz = 250 /*1280x960(75Hz)*/
timingVESA_1280x960_60hz = 252 /*1280x960(60Hz)*/
timingVESA_1280x960_85hz = 254 /*1280x960(85Hz)*/
timingVESA_1280x1024_60hz = 260 /*1280x1024(60Hz)*/
timingVESA_1280x1024_75hz = 262 /*1280x1024(75Hz)*/
timingVESA_1280x1024_85hz = 268 /*1280x1024(85Hz)*/
timingVESA_1600x1200_60hz = 280 /*1600x1200(60Hz)VESAtiming.*/
timingVESA_1600x1200_65hz = 282 /*1600x1200(65Hz)VESAtiming.*/
timingVESA_1600x1200_70hz = 284 /*1600x1200(70Hz)VESAtiming.*/
timingVESA_1600x1200_75hz = 286 /*1600x1200(75Hz)VESAtiming(pixelclockis189.2
timingVESA_1600x1200_80hz = 288 /*1600x1200(80Hz)VESAtiming(pixelclockis216>?
timingVESA_1600x1200_85hz = 289 /*1600x1200(85Hz)VESAtiming(pixelclockis229.5
timingVESA_1792x1344_60hz = 296 /*1792x1344(60Hz)VESAtiming(204.75Mhzdotclock).
timingVESA_1792x1344_75hz = 298 /*1792x1344(75Hz)VESAtiming(261.75Mhzdotclock).
timingVESA_1856x1392_60hz = 300 /*1856x1392(60Hz)VESAtiming(218.25Mhzdotclock).
timingVESA_1856x1392_75hz = 302 /*1856x1392(75Hz)VESAtiming(288Mhzdotclock).
timingVESA_1920x1440_60hz = 304 /*1920x1440(60Hz)VESAtiming(234Mhzdotclock).
timingVESA_1920x1440_75hz = 306 /*1920x1440(75Hz)VESAtiming(297Mhzdotclock).
timingSMPTE240M_60hz = 400 /*60HzV,33.75KHzH,interlacedtiming,16:9aspect,typical
timingFilmRate_48hz = 410 /*48HzV,25.20KHzH,non-interlacedtiming,typicalresolutionof
timingSony_1600x1024_76hz = 500 /*1600x1024(76Hz)Sonytiming(pixelclockis170.447
timingSony_1920x1080_60hz = 510 /*1920x1080(60Hz)Sonytiming(pixelclockis159.84
timingSony_1920x1080_72hz = 520 /*1920x1080(72Hz)Sonytiming(pixelclockis216.023
timingSony_1920x1200_76hz = 540 /*1900x1200(76Hz)Sonytiming(pixelclockis243.20
timingApple_0x0_0hz_Offline = 550/*Indicatesthatthistimingwilltakethedisplayoff-line
timingApple12 = timingApple_512x384_60hz
timingApple12x = timingApple_560x384_60hz
timingApple13 = timingApple_640x480_67hz
timingApple13x = timingApple_640x400_67hz
timingAppleVGA = timingVESA_640x480_60hz
timingApple15 = timingApple_640x870_75hz
timingApple15x = timingApple_640x818_75hz
timingApple16 = timingApple_832x624_75hz
timingAppleSVGA = timingVESA_800x600_56hz
timingApple1Ka = timingVESA_1024x768_60hz
timingApple1Kb = timingVESA_1024x768_70hz
timingApple19 = timingApple_1024x768_75hz
timingApple21 = timingApple_1152x870_75hz
timingSony_1900x1200_74hz = 530 /*1900x1200(74Hz)Sonytiming(pixelclockis236.25
timingSony_1900x1200_76hz = timingSony_1920x1200_76hz/*1900x1200(76Hz)Sonytiming(pixelclockis245.48
kAllModesValid = 0 /*Allmodesnottrimmedbyprimaryinitaregood
kAllModesSafe = 1 /*Allmodesnottrimmedbyprimaryinitareknow
kReportsTagging = 2 /*Candetecttaggeddisplays(toidentifysmartmonitors)*/
kHasDirectConnection = 3 /*Trueimpliesthatdrivercantalkdirectlytodevice
kUncertainConnection = 5 /*Theremaynotbeadisplay(nosenselines?).
kTaggingInfoNonStandard = 6 /*SetwhencsConnectTaggedType/csConnectTaggedDataarenon-standard(i.e.,nottheApple
kReportsDDCConnection = 7 /*Cardcandoddc(setkHasDirectConnect&&kHasDDCConnectif
kHasDDCConnection = 8 /*Cardhasddcconnectnow.*/
kConnectionInactive = 9 /*SetwhentheconnectionisNOTcurrentlyactive(generally
kDependentConnection = 10 /*SetwhensomeascpectofTHISconnectiondependson
kBuiltInConnection = 11 /*SetwhenconnectionisKNOWNtobebuilt-in(this
kOverrideConnection = 12 /*Setwhenthereportedconnectionisnotthetrue
kFastCheckForDDC = 13 /*Setwhenall3aretrue:1)sensecodes
kReportsHotPlugging = 14/*Detectsandreportshotplugggingonconnector(viaVSL
kPanelConnect = 2 /*Forusewithfixed-in-placeLCDpanels.*/
kPanelTFTConnect = 2 /*AliasforkPanelConnect*/
kFixedModeCRTConnect = 3 /*Forusewithfixed-mode(i.e.,verylimitedrange)displays.
kMultiModeCRT1Connect = 4 /*320x200maybe,12"maybe,13"(default),16"certain,19"
kMultiModeCRT2Connect = 5 /*320x200maybe,12"maybe,13"certain,16"(default),19"
kMultiModeCRT3Connect = 6 /*320x200maybe,12"maybe,13"certain,16"certain,19"
kMultiModeCRT4Connect = 7 /*Expansiontolargemultimode(notyetused)*/
kModelessConnect = 8 /*Expansiontomodelessmodel(notyetused)*/
kFullPageConnect = 9 /*640x818(toget8bppin512Kcase)and640x870
kVGAConnect = 10 /*640x480VGAdefault--questioneverythingelse*/
kNTSCConnect = 11 /*NTSCST(default),FF,STconv,FFconv*/
kPALConnect = 12 /*PALST(default),FF,STconv,FFconv*/
kHRConnect = 13 /*Straight-6connect--640x480and640x400(toget8bpp
kMonoTwoPageConnect = 15 /*1152x870Applecolortwo-pagedisplay*/
kColorTwoPageConnect = 16 /*1152x870AppleB&Wtwo-pagedisplay*/
kColor16Connect = 17 /*832x624AppleB&Wtwo-pagedisplay*/
kColor19Connect = 18 /*1024x768AppleB&Wtwo-pagedisplay*/
kGenericCRT = 19 /*IndicatesnothingexceptthatconnectionisCRTinnature.
kGenericLCD = 20 /*IndicatesnothingexceptthatconnectionisLCDinnature.
kDDCConnect = 21 /*DDCconnection,alwayssetkHasDDCConnection*/
kNoConnect = 22/*Nodisplayisconnected-loadsensingorsimilar
kModeValid = 0 /*SaysthatthismodeshouldNOTbetrimmed.*/
kModeSafe = 1 /*Thismodedoesnotneedconfirmation*/
kModeDefault = 2 /*Thisisthedefaultmodeforthistypeof
kModeShowNow = 3 /*Thismodeshouldalwaysbeshown(eventhoughit
kModeNotResize = 4 /*Thismodeshouldnotbeusedtoresizethe
kModeRequiresPan = 5 /*Thismodehasmorepixelsthanareactuallydisplayed
kModeInterlaced = 6 /*Thismodeisinterlaced(singlepixellineslookbad).
kModeShowNever = 7 /*Thismodeshouldnotbeshownintheuser
kModeSimulscan = 8 /*Indicatesthatmorethanonedisplayconnectioncanbe
kModeNotPreset = 9 /*Indicatesthatthetimingisnotafactorypreset
kModeBuiltIn = 10 /*Indicatesthatthedisplaymodeisforthebuilt-in
kModeStretched = 11/*Indicatesthatthedisplaymodewillbestretched/distortedto
kDepthDependent = 0/*Saysthatthisdepthmodemaycausedependentchanges
kResolutionHasMultipleDepthSizes = 0/*SaysthatthismodehasdifferentcsHorizontalPixels csVerticalLinesat
kAVPowerOff = 0 /*Powerfullyoff*/
kAVPowerStandby = 1
kAVPowerSuspend = 2
kAVPowerOn = 3
kHardwareSleep = 128
kHardwareWake = 129
kHardwareWakeFromSuspend = 130
kHardwareWakeToDoze = 131
kHardwareWakeToDozeFromSuspend = 132
cscReset = 0
cscKillIO = 1
cscSetMode = 2
cscSetEntries = 3
cscSetGamma = 4
cscGrayPage = 5
cscGrayScreen = 5
cscSetGray = 6
cscSetInterrupt = 7
cscDirectSetEntries = 8
cscSetDefaultMode = 9
cscSwitchMode = 10 /*TakesaVDSwitchInfoPtr*/
cscSetSync = 11 /*TakesaVDSyncInfoPtr*/
cscSavePreferredConfiguration = 16 /*TakesaVDSwitchInfoPtr*/
cscSetHardwareCursor = 22 /*TakesaVDSetHardwareCursorPtr*/
cscDrawHardwareCursor = 23 /*TakesaVDDrawHardwareCursorPtr*/
cscSetConvolution = 24 /*TakesaVDConvolutionInfoPtr*/
cscSetPowerState = 25 /*TakesaVDPowerStatePtr*/
cscPrivateControlCall = 26 /*TakesaVDPrivateSelectorDataPtr*/
cscSetMultiConnect = 28 /*TakesaVDMultiConnectInfoPtr*/
cscSetClutBehavior = 29 /*TakesaVDClutBehavior*/
cscSetDetailedTiming = 31 /*TakesaVDDetailedTimingPtr*/
cscDoCommunication = 33 /*TakesaVDCommunicationPtr*/
cscProbeConnection = 34 /*Takesnilpointer(maygenerateakFBConnectInterruptServiceTypeserviceinterrupt)*/
cscUnusedCall = 127/*Thiscallusedtoexpendthescrnresource.Its
cscGetMode = 2
cscGetEntries = 3
cscGetPageCnt = 4
cscGetPages = 4 /*ThisiswhatC&D2callsit.*/
cscGetPageBase = 5
cscGetBaseAddr = 5 /*ThisiswhatC&D2callsit.*/
cscGetGray = 6
cscGetInterrupt = 7
cscGetGamma = 8
cscGetDefaultMode = 9
cscGetCurMode = 10 /*TakesaVDSwitchInfoPtr*/
cscGetSync = 11 /*TakesaVDSyncInfoPtr*/
cscGetConnection = 12 /*Returninformationabouttheconnectiontothedisplay*/
cscGetModeTiming = 13 /*Returntiminginfoforamode*/
cscGetModeBaseAddress = 14 /*Returnbaseaddressinformationaboutaparticularmode*/
cscGetScanProc = 15 /*QuickTimescanchasingroutine*/
cscGetPreferredConfiguration = 16 /*TakesaVDSwitchInfoPtr*/
cscGetNextResolution = 17 /*TakesaVDResolutionInfoPtr*/
cscGetVideoParameters = 18 /*TakesaVDVideoParametersInfoPtr*/
cscGetGammaInfoList = 20 /*TakesaVDGetGammaListPtr*/
cscRetrieveGammaTable = 21 /*TakesaVDRetrieveGammaPtr*/
cscSupportsHardwareCursor = 22 /*TakesaVDSupportsHardwareCursorPtr*/
cscGetHardwareCursorDrawState = 23 /*TakesaVDHardwareCursorDrawStatePtr*/
cscGetConvolution = 24 /*TakesaVDConvolutionInfoPtr*/
cscGetPowerState = 25 /*TakesaVDPowerStatePtr*/
cscPrivateStatusCall = 26 /*TakesaVDPrivateSelectorDataPtr*/
cscGetDDCBlock = 27 /*TakesaVDDDCBlockPtr*/
cscGetMultiConnect = 28 /*TakesaVDMultiConnectInfoPtr*/
cscGetClutBehavior = 29 /*TakesaVDClutBehaviorPtr*/
cscGetTimingRanges = 30 /*TakesaVDDisplayTimingRangePtr*/
cscGetDetailedTiming = 31 /*TakesaVDDetailedTimingPtr*/
cscGetCommunicationInfo = 32/*TakesaVDCommunicationInfoPtr*/
kDisableHorizontalSyncBit = 0
kDisableVerticalSyncBit = 1
kDisableCompositeSyncBit = 2
kEnableSyncOnBlue = 3
kEnableSyncOnGreen = 4
kEnableSyncOnRed = 5
kNoSeparateSyncControlBit = 6
kTriStateSyncBit = 7
kHorizontalSyncMask = 0x01
kVerticalSyncMask = 0x02
kCompositeSyncMask = 0x04
kDPMSSyncMask = 0x07
kTriStateSyncMask = 0x80
kSyncOnBlueMask = 0x08
kSyncOnGreenMask = 0x10
kSyncOnRedMask = 0x20
kSyncOnMask = 0x38
kDPMSSyncOn = 0
kDPMSSyncStandby = 1
kDPMSSyncSuspend = 2
kDPMSSyncOff = 7
kConvolved = 0
kLiveVideoPassThru = 1
kConvolvedMask = 0x01
kLiveVideoPassThruMask = 0x02
kRSCZero = 0
kRSCOne = 1
kRSCTwo = 2
kRSCThree = 3
kRSCFour = 4
kRSCFive = 5
kRSCSix = 6
kRSCSeven = 7
kESCZero21Inch = 0x00 /*21"RGB*/
kESCOnePortraitMono = 0x14 /*PortraitMonochrome*/
kESCTwo12Inch = 0x21 /*12"RGB*/
kESCThree21InchRadius = 0x31 /*21"RGB(Radius)*/
kESCThree21InchMonoRadius = 0x34 /*21"Monochrome(Radius)*/
kESCThree21InchMono = 0x35 /*21"Monochrome*/
kESCFourNTSC = 0x0A /*NTSC*/
kESCFivePortrait = 0x1E /*PortraitRGB*/
kESCSixMSB1 = 0x03 /*MultiScanBand-1(12"thru1Six")*/
kESCSixMSB2 = 0x0B /*MultiScanBand-2(13"thru19")*/
kESCSixMSB3 = 0x23 /*MultiScanBand-3(13"thru21")*/
kESCSixStandard = 0x2B /*13"/14"RGBor12"Monochrome*/
kESCSevenPAL = 0x00 /*PAL*/
kESCSevenNTSC = 0x14 /*NTSC*/
kESCSevenVGA = 0x17 /*VGA*/
kESCSeven16Inch = 0x2D /*16"RGB(GoldFish)*/
kESCSevenPALAlternate = 0x30 /*PAL(Alternate)*/
kESCSevenDDC = 0x3E /*DDCdisplay*/
kESCSevenNoDisplay = 0x3F/*Nodisplayconnected*/
kDepthMode1 = 128
kDepthMode2 = 129
kDepthMode3 = 130
kDepthMode4 = 131
kDepthMode5 = 132
kDepthMode6 = 133
kFirstDepthMode = 128 /*Theseconstantsareobsolete,andjustincluded*/
kSecondDepthMode = 129 /*forclientsthathaveconvertedtotheabove*/
kThirdDepthMode = 130 /*kDepthModeXXXconstants.*/
kFourthDepthMode = 131
kFifthDepthMode = 132
kSixthDepthMode = 133
kDisplayModeIDCurrent = 0x00 /*ReferencetheCurrentDisplayModeID*/
kDisplayModeIDInvalid = 0xFFFFFFFF /*AbogusDisplayModeIDinallcases*/
kDisplayModeIDFindFirstResolution = 0xFFFFFFFE /*UsedincscGetNextResolutiontoresetiterator*/
kDisplayModeIDNoMoreResolutions = 0xFFFFFFFD /*UsedincscGetNextResolutiontoindicateEndOfList*/
kDisplayModeIDFindFirstProgrammable = 0xFFFFFFFC /*UsedincscGetNextResolutiontofindunusedprogrammabletiming*/
kDisplayModeIDBootProgrammable = 0xFFFFFFFB /*ThisistheIDgivenatboottimeby
kDisplayModeIDReservedBase = 0x80000000/*Lowest(unsigned)DisplayModeIDreservedbyApple*/
kGammaTableIDFindFirst = 0xFFFFFFFE /*GetthefirstgammatableID*/
kGammaTableIDNoMoreTables = 0xFFFFFFFD /*Usedtoindicateendoflist*/
kGammaTableIDSpecific = 0x00/*Returntheinfoforthegiventableid*/
kActivateConnection = (0<<kConnectionInactive) /*Usedforactivatingaconnection(csConnectFlagsvalue).*/
kDeactivateConnection = (1<<kConnectionInactive)/*Usedfordeactivatingaconnection(csConnectFlagsvalue.)*/
kVideoDefaultBus = 0
kVideoBusTypeInvalid = 0
kVideoBusTypeI2C = 1
kVideoNoTransactionType = 0 /*Notransaction*/
kVideoSimpleI2CType = 1 /*SimpleI2Cmessage*/
kVideoDDCciReplyType = 2/*DDC/cimessage(withimbeddedlength)*/
kVideoReplyMicroSecDelayMask = (1<<0)/*Ifset thedrivershoulddelaycsMinReplyDelay
kSyncInterlaceMask = (1<<7)
kSyncAnalogCompositeMask = 0
kSyncAnalogCompositeSerrateMask = (1<<2)
kSyncAnalogCompositeRGBSyncMask = (1<<1)
kSyncAnalogBipolarMask = (1<<3)
kSyncAnalogBipolarSerrateMask = (1<<2)
kSyncAnalogBipolarSRGBSyncMask = (1<<1)
kSyncDigitalCompositeMask = (1<<4)
kSyncDigitalCompositeSerrateMask = (1<<2)
kSyncDigitalCompositeMatchHSyncMask = (1<<2)
kSyncDigitalSeperateMask = (1<<4)+(1<<3)
kSyncDigitalVSyncPositiveMask = (1<<2)
kSyncDigitalHSyncPositiveMask = (1<<1)
kDMSModeReady = 0 /*DisplayModeIDisconfiguredandready*/
kDMSModeNotReady = 1 /*DisplayModeIDisisbeingprogrammed*/
kDMSModeFree = 2/*DisplayModeIDisnotassociatedwithatiming*/
kTimingChangeRestrictedErr = -10930
kVideoI2CReplyPendingErr = -10931
kVideoI2CTransactionErr = -10932
kVideoI2CBusyErr = -10933
kVideoI2CTransactionTypeErr = -10934
kVideoBufferSizeErr = -10935
kRangeSupportsSignal_0700_0300_Bit = 0
kRangeSupportsSignal_0714_0286_Bit = 1
kRangeSupportsSignal_1000_0400_Bit = 2
kRangeSupportsSignal_0700_0000_Bit = 3
kRangeSupportsSignal_0700_0300_Mask = (1<<kRangeSupportsSignal_0700_0300_Bit)
kRangeSupportsSignal_0714_0286_Mask = (1<<kRangeSupportsSignal_0714_0286_Bit)
kRangeSupportsSignal_1000_0400_Mask = (1<<kRangeSupportsSignal_1000_0400_Bit)
kRangeSupportsSignal_0700_0000_Mask = (1<<kRangeSupportsSignal_0700_0000_Bit)
kDigitalSignalBit = 0 /*Donotset.MacOSdoesnotcurrentlysupport
kAnalogSetupExpectedBit = 1 /*Analogdisplays-displayexpectsablank-to-blacksetupor
kDigitalSignalMask = (1<<kDigitalSignalBit)
kAnalogSetupExpectedMask = (1<<kAnalogSetupExpectedBit)
kAnalogSignalLevel_0700_0300 = 0
kAnalogSignalLevel_0714_0286 = 1
kAnalogSignalLevel_1000_0400 = 2
kAnalogSignalLevel_0700_0000 = 3
kRangeSupportsSeperateSyncsBit = 0
kRangeSupportsSyncOnGreenBit = 1
kRangeSupportsCompositeSyncBit = 2
kRangeSupportsVSyncSerrationBit = 3
kRangeSupportsSeperateSyncsMask = (1<<kRangeSupportsSeperateSyncsBit)
kRangeSupportsSyncOnGreenMask = (1<<kRangeSupportsSyncOnGreenBit)
kRangeSupportsCompositeSyncMask = (1<<kRangeSupportsCompositeSyncBit)
kRangeSupportsVSyncSerrationMask = (1<<kRangeSupportsVSyncSerrationBit)
kSyncPositivePolarityBit = 0 /*Digitalseparatesyncpolarityforanaloginterfaces(0=>
kSyncPositivePolarityMask = (1<<kSyncPositivePolarityBit)
kSetClutAtSetEntries = 0 /*SetEntriesbehavioristoupdateclutduringSetEntriescall*/
kSetClutAtVBL = 1/*SetEntriesbehavioristoupateclutatnextvbl*/

BIN
DeclROM/dump.cpr Executable file

Binary file not shown.

288
DeclROM/gen_mode.c Normal file
View File

@@ -0,0 +1,288 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
struct one_res {
const unsigned short hres;
const unsigned short vres;
const unsigned char native_only;
};
#define NUM_RES 16
#if 1
static struct one_res res_db[NUM_RES] = {
{ 1920, 1080, 0 },
{ 1680, 1050, 0 }, // should be unsuitable
{ 1600, 900, 1 }, // freaks out my monitor on 1920x1080, it thinks it's 1680x1050...
{ 1440, 900, 0 },
{ 1280, 1024, 0 },
{ 1280, 960, 0 },
{ 1280, 800, 0 },
{ 1152, 870, 0 },
{ 1152, 864, 0 },
{ 1024, 768, 0 },
{ 832, 624, 0 },
{ 800, 600, 0 },
{ 768, 576, 0 },
{ 640, 480, 0 },
{ 512, 384, 0 },
{ 0, 0, 0 }
};
#else
static struct one_res res_db[NUM_RES] = {
{ 1920, 1080, 0 },
{ 1600, 900, 1 },
/* { 640, 480, 0 }, */
{ 0, 0, 0}
};
#endif
int main(int argc, char **argv) {
unsigned short maxhres = 1920, maxvres = 1080;
const int depthdb[6] = { 8, 4, 2, 1, 32, 16 };
int enabled[NUM_RES];
int i, j;
unsigned char id;
for (i = 0 ; i < NUM_RES ; i++) {
enabled[i] = 0;
}
if (argc == 3) {
maxhres = atoi(argv[1]);
maxvres = atoi(argv[2]);
}
fprintf(stderr, "Resolution: %hu x %hu\n", maxhres, maxvres);
id = 0x80;
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) && (id < 0x90); i++) { // 0x90 is the ram disk
char filename[512];
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
FILE *fd;
if ((hres * vres) % 128) // unsuitable, safety net
continue;
if (res_db[i].native_only && ((hres != maxhres) || (vres != maxvres)))
continue;
if ((hres > maxhres) || (vres > maxvres))
continue;
snprintf(filename, 512, "VidRomRes_%hux%hu.s", hres, vres);
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
enabled[i] = 1;
id ++;
for (j = 0 ; j < 6 ; j++) {
char modename[128];
const unsigned short depth = depthdb[j];
const unsigned short rowBytes = (hres * depth) / 8;
snprintf(modename, 128, "R%hux%huD%d", hres, vres, depth);
fprintf(fd, "\tALIGN 2\n");
fprintf(fd, "_%sModes: /* id 0x%02x */\n", modename, id-1);
fprintf(fd, "\tOSLstEntry\tmVidParams,_%sParms\t/* offset to vid parameters */\n", modename);
fprintf(fd, "\tDatLstEntry\tmPageCnt,%d\t/* number of video pages */\n", (depth == 32) ? 1 : 2);
fprintf(fd, "\tDatLstEntry\tmDevType,%s\t/* device type */\n", depth <= 8 ? "clutType" : "directType");
fprintf(fd, "\t.long\tEndOfList\t/* end of list */\n");
fprintf(fd, "_%sParms:\n", modename);
fprintf(fd, "\t.long\t_End%sParms-_%sParms\t/* physical block size */\n", modename, modename);
fprintf(fd, "\t.long\t0\t/* QuickDraw base offset ; vpBaseOffset */\n"); // defmBaseOffset
fprintf(fd, "\t.word\t%hu\t/* physRowBytes ; vpRowBytes */\n", rowBytes);
fprintf(fd, "\t.word\t0,0,%hu,%hu\t/* vpBounds */\n", vres, hres);
fprintf(fd, "\t.word\tdefVersion\t/* bmVersion ; vpVersion */\n");
fprintf(fd, "\t.word\t0\t/* packType not used ; vpPackType */\n");
fprintf(fd, "\t.long\t0\t/* packSize not used ; vpPackSize */\n");
fprintf(fd, "\t.long\tdefmHRes\t/* bmHRes */\n");
fprintf(fd, "\t.long\tdefmVRes\t/* bmVRes */\n");
fprintf(fd, "\t.word\t%s\t/* bmPixelType */\n", depth <= 8 ? "ChunkyIndexed" : "ChunkyDirect");
fprintf(fd, "\t.word\t%d\t/* bmPixelSize */\n", depth);
fprintf(fd, "\t.word\t%d\t/* bmCmpCount */\n", depth <= 8 ? 1 : 3);
fprintf(fd, "\t.word\t%d\t/* bmCmpSize */\n", depth <= 8 ? depth : (depth == 32 ? 8 : 5));
fprintf(fd, "\t.long\t0\t/* bmPlaneBytes */\n"); // defmPlaneBytes
fprintf(fd, "_End%sParms:\n\n",modename);
}
fclose(fd);
}
{
char filename[512];
FILE *fd;
id = 0x80;
snprintf(filename, 512, "VidRomRes.s");
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
fprintf(fd, ".include \"VidRomRes_%hux%hu.s\"\n", hres, vres);
}
}
fclose(fd);
}
{
char filename[512];
FILE *fd;
snprintf(filename, 512, "VidRomName.s");
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
fprintf(fd, "\tALIGN 2\n");
fprintf(fd, "_VModeName:\n");
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
fprintf(fd, "\tOSLstEntry\tsRsrc_GoboFB_R%hux%hu,_ScreenNameGoboFB_R%hux%hu\n", hres, vres, hres, vres);
}
}
fprintf(fd, "\tDatLstEntry endOfList, 0\n");
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
int native = (hres == maxhres) && (vres == maxvres);
fprintf(fd, "\tALIGN 2\n");
fprintf(fd, "_ScreenNameGoboFB_R%hux%hu:\n", hres, vres);
fprintf(fd, "\t.long\t_ScreenNameGoboFB_R%hux%huEnd - _ScreenNameGoboFB_R%hux%hu\n", hres, vres, hres, vres);
fprintf(fd, "\t.word\t0\n");
fprintf(fd, "\t.string\t\"GoblinFB %hux%hu%s\\0\"\n", hres, vres, native ? " (N)": "");
fprintf(fd, "_ScreenNameGoboFB_R%hux%huEnd:\n", hres, vres);
}
}
fclose(fd);
}
{
char filename[512];
FILE *fd;
snprintf(filename, 512, "VidRomDir_%hux%hu.s", maxhres, maxvres);
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
int native = (hres == maxhres) && (vres == maxvres);
fprintf(fd, "\tALIGN 2\n");
fprintf(fd, "_sRsrc_GoboFB_R%hux%hu:\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tsRsrcType,_GoboFBType\t/* video type descriptor */\n");
fprintf(fd, "\tOSLstEntry\tsRsrcName,_GoboFBName\t/* offset to driver name string */\n");
fprintf(fd, "\tOSLstEntry\tsRsrcDrvrDir,_GoboFBDrvrDir /* offset to driver directory */\n");
fprintf(fd, "\tDatLstEntry\tsRsrcFlags,%d\t/* force 32 bits mode & open (native) - or not (others)*/\n", native ? 6 : 0);
fprintf(fd, "\tDatLstEntry\tsRsrcHWDevId,1\t/* hardware device ID */\n");
fprintf(fd, "\tOSLstEntry\tMinorBaseOS,_MinorBase\t/* offset to frame buffer array */\n");
fprintf(fd, "\tOSLstEntry\tMinorLength,_MinorLength\t/* offset to frame buffer length */\n");
fprintf(fd, "\t/* OSLstEntry\tsGammaDir,_GammaDirS\t/* directory for 640x480 monitor */\n");
fprintf(fd, "/* Parameters */\n");
fprintf(fd, "\tOSLstEntry\tfirstVidMode,_R%hux%huD8Modes\t/* offset to 8 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tsecondVidMode,_R%hux%huD4Modes\t/* offset to 4 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tthirdVidMode,_R%hux%huD2Modes\t/* offset to 2 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tfourthVidMode,_R%hux%huD1Modes\t/* offset to 1 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tfifthVidMode,_R%hux%huD32Modes\t/* offset to 24/32 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\tOSLstEntry\tsixthVidMode,_R%hux%huD16Modes\t/* offset to 15/16 Bit Mode parms */\n", hres, vres);
fprintf(fd, "\t.long EndOfList\t/* end of list */\n\n");
}
}
fclose(fd);
}
{
char filename[512];
FILE *fd;
unsigned char id = 0x80;
snprintf(filename, 512, "VidRomDir.s");
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
fprintf(fd, "\t.include \"VidRomDir_%hux%hu.s\"\n", maxhres, maxvres);
fclose(fd);
}
{
char filename[512];
FILE *fd;
unsigned char id = 0x80;
snprintf(filename, 512, "VidRomDef.s");
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
fprintf(fd, "sRsrc_GoboFB_R%hux%hu = 0x%02hhx\n", hres, vres, id++);
}
}
fclose(fd);
}
{
char filename[512];
FILE *fd;
snprintf(filename, 512, "VidRomRsrcDir.s");
fd = fopen(filename, "w");
if (fd == NULL) {
fprintf(stderr, "Generating '%s' failed.\n", filename);
return -1;
}
fprintf(fd, "_sRsrcDir:\n");
fprintf(fd, "\tOSLstEntry\tsRsrc_Board,_sRsrc_Board\t/* board sRsrc List */\n");
for (i = 0 ; (res_db[i].hres != 0) && (res_db[i].vres != 0) ; i++) {
const unsigned short hres = res_db[i].hres;
const unsigned short vres = res_db[i].vres;
if (enabled[i]) {
fprintf(fd, "\tOSLstEntry\tsRsrc_GoboFB_R%hux%hu,_sRsrc_GoboFB_R%hux%hu/* video sRsrc List */\n", hres, vres, hres, vres);
}
}
#ifdef ENABLE_RAMDSK
fprintf(fd, "\tOSLstEntry\tsRsrc_RAMDsk,_sRsrc_RAMDsk\n");
#endif
#ifdef ENABLE_SDCARD
fprintf(fd, "\tOSLstEntry\tsRsrc_SDCard,_sRsrc_SDCard\n");
#endif
#ifdef ENABLE_HDMIAUDIO
fprintf(fd, "\tOSLstEntry\tsRsrc_HDMIAudio,_sRsrc_HDMIAudio\n");
#endif
fprintf(fd, "\tDatLstEntry endOfList, 0\n");
fclose(fd);
}
return 0;
}

50
DeclROM/linker.ld Normal file
View File

@@ -0,0 +1,50 @@
OUTPUT_FORMAT("elf32-m68k");
ENTRY(DeclROMDir);
SECTIONS {
.text : {
/* first the resource dir & related */
*(.text.begin)
*(.text .sdata .sdata.* .data .data.* .rodata .rodata.*)
/* then various sections for the various bits of codes */
PROVIDE(_sPInitRec = .);
PROVIDE(entry_sPInitRec = (0x22000000 | ((_sPInitRec - _sRsrc_Board - 12) & 0xFFFFFF))); /* fixme; offset 12 hardwired */
*(.text.primary_init)
*(.text.primary)
PROVIDE(_EndsPInitRec = .);
PROVIDE(size_sPInitRec = _EndsPInitRec - _sPInitRec);
PROVIDE(_sSInitRec = .);
PROVIDE(entry_sSInitRec = (0x24000000 | ((_sSInitRec - _sRsrc_Board - 20) & 0xFFFFFF))); /* fixme; offset 20 hardwired */
*(.text.secondary_init)
*(.text.secondary)
PROVIDE(_EndsSInitRec = .);
PROVIDE(size_sSInitRec = _EndsSInitRec - _sSInitRec);
PROVIDE(_GoboFBDrvrMacOS68020 = .);
PROVIDE(entry_GoboFBDrvrMacOS68020 = (0x02000000 | ((_GoboFBDrvrMacOS68020 - _GoboFBDrvrDir) & 0xFFFFFF)));
*(.text.fbdriver_init)
*(.text.fbdriver)
PROVIDE(_GoboFBEnd020Drvr = .);
PROVIDE(_RAMDskDrvrMacOS68020 = .);
PROVIDE(entry_RAMDskDrvrMacOS68020 = (0x02000000 | ((_RAMDskDrvrMacOS68020 - _RAMDskDrvrDir) & 0xFFFFFF)));
*(.text.dskdriver_init)
*(.text.dskdriver)
PROVIDE(_RAMDskEnd020Drvr = .);
PROVIDE(_SDCardDrvrMacOS68020 = .);
PROVIDE(entry_SDCardDrvrMacOS68020 = (0x02000000 | ((_SDCardDrvrMacOS68020 - _SDCardDrvrDir) & 0xFFFFFF)));
*(.text.sddriver_init)
*(.text.sddriver)
PROVIDE(_SDCardEnd020Drvr = .);
/* and at the end the ROM block, missing only the CRC */
. = ALIGN(4);
*(.romblock)
PROVIDE(ROMSize = .);
PROVIDE(RsrcDirOffset = ((0-.)+20) & 0xFFFFFF);
}
/DISCARD/ : { *(*) }
}

151
DeclROM/myrle.c Normal file
View File

@@ -0,0 +1,151 @@
#include <stdint.h>
//#include <stdio.h>
#include "NuBusFPGARAMDskDrvr.h"
#ifndef SKIP_MAIN
uint32_t rleenc(uint32_t* out, const uint32_t* in, const uint32_t len) {
uint32_t i = 0, j = 0, p = 0, ib, k;
int32_t c = 0;
p = in[0];
for (i = 1 ; i < len ; i++) {
if (c == 0) { // just started
if (in[i] == p) { // repeat
c++;
} else { // non-repeat
p = in[i];
c--;
ib = i - 1;
}
} else if (c > 0) { // in-repeat
if (in[i] == p) { // keep repeating
c++;
} else { // exit repeat
out[j++] = __builtin_bswap32(c); // write result
out[j++] = p;
p = in[i]; // restart
c = 0;
}
} else { // c < 0
if (in[i] == p) { // exit non-repeat
out[j++] = __builtin_bswap32(c+1); // write result, removing previous
for (k = 0 ; k < (-c) ; k++)
out[j++] = in[ib+k];
p = in[i]; // restart
c = 1; // this and previous
} else { // non-repeat
p = in[i];
c--;
}
}
}
out[j++] = __builtin_bswap32(c);
out[j++] = p;
return j;
}
#endif
uint32_t rledec(uint32_t* out, const uint32_t* in, const uint32_t len) {
uint32_t i = 0, j = 0, k = 0, chk = 0, ib;
for (i = 0 ; i < len ; ) {
#ifndef __m68k__
int32_t c = (int32_t)__builtin_bswap32(in[i]);
#else
int32_t c = (int32_t)(in[i]);
#endif
if (c >= 0) {
chk += (1 + c);
if (c < 300000) { // !!!!!!!!!!!!!!!!!!!!!!!!!!
for (k = 0 ; k < (c + 1) ; k++)
out[j++] = in[i+1];
} else { // do a small subset at the beginning and end instead of the full range and assume this is padding otherwise
for (k = 0 ; k < 4 ; k++)
out[j+k] = in[i+1];
for (k = c-3 ; k < (c + 1) ; k++)
out[j+k] = in[i+1];
j += c+1;
}
i += 2;
} else {
chk += (1 + -c);
for (k = 0 ; k < (1 + -c) ; k++)
out[j++] = in[i+1+k];
i += 2 + -c;
}
//fprintf(stderr, "%u: %u <> %u (%d, 0x%08x)\n", i, j, chk, c, in[i+1]);
}
return j;
}
#ifndef SKIP_MAIN
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
int main(int argc, char** argv) {
int fd;
uint32_t len, k;
uint32_t *bufa, *bufb;
FILE* f;
bufa = calloc(sizeof(uint32_t), 256*1024*1024/sizeof(uint32_t));
bufb = calloc(sizeof(uint32_t), 256*1024*1024/sizeof(uint32_t));
fd = open("dump.raw", O_RDONLY);
len = read(fd, bufa, 248*1024*1024ull) / 4;
close(fd);
printf("File : %d bytes\n", len*4);
len = rleenc(bufb, bufa, len);
printf("Compressed : %d bytes\n", len*4);
/* for (k = 0 ; k < len ; k++) */
/* bufb[k] = __builtin_bswap32(bufb[k]); */
fd = open("dump.cpr", O_WRONLY | O_CREAT, S_IRWXU);
/* len = */write (fd, bufb, len*4);
close(fd);
/* for (k = 0 ; k < len ; k++) */
/* bufb[k] = __builtin_bswap32(bufb[k]); */
f = fopen("dump_cpr.c", "w");
/* fprintf(f, "unsigned char* compressed[%d] = {\n", len*4); */
/* for (k = 0 ; k < len*4 ; k++) { */
/* fprintf(f, "0x%02x%s", ((unsigned char*)bufb)[k], */
/* k == (len*4-1) ? "};" : (k%16 == 15 ? ",\n" : ",") */
/* ); */
/* } */
fprintf(f, "unsigned long* compressed[%d] = {\n", len);
for (k = 0 ; k < len ; k++) {
fprintf(f, "0x%08x%s", bufb[k],
k == (len-1) ? "};" : (k%8 == 7 ? ",\n" : ",")
);
}
fclose(f);
len = rledec(bufa, bufb, len);
printf("Uncompressed : %d bytes\n", len*4);
fd = open("dump.ucp", O_WRONLY | O_CREAT, S_IRWXU);
len = write (fd, bufa, len*4);
close(fd);
return 0;
}
#endif

1
DeclROM/ns816-declrom Submodule

Submodule DeclROM/ns816-declrom added at 618242763e

View File

@@ -0,0 +1,214 @@
#ifndef __NUBUSFPGA_CSR_COMMON_H__
#define __NUBUSFPGA_CSR_COMMON_H__
/* from hw/common.h, +a32 */
#define CONFIG_CSR_DATA_WIDTH 32
/* CSR data width (subreg. width) in bytes, for direct comparson to sizeof() */
#define CSR_DW_BYTES (CONFIG_CSR_DATA_WIDTH/8)
#define CSR_OFFSET_BYTES 4
/* Number of subregs required for various total byte sizes, by subreg width:
* NOTE: 1, 2, 4, and 8 bytes represent uint[8|16|32|64]_t C types; However,
* CSRs of intermediate byte sizes (24, 40, 48, and 56) are NOT padded
* (with extra unallocated subregisters) to the next valid C type!
* +-----+-----------------+
* | csr | bytes |
* | _dw | 1 2 3 4 5 6 7 8 |
* | |-----=---=-=-=---|
* | 1 | 1 2 3 4 5 6 7 8 |
* | 2 | 1 1 2 2 3 3 4 4 |
* | 4 | 1 1 1 1 2 2 2 2 |
* | 8 | 1 1 1 1 1 1 1 1 |
* +-----+-----------------+ */
static inline int num_subregs(int csr_bytes)
{
return (csr_bytes - 1) / CSR_DW_BYTES + 1;
}
/* Read a CSR of size 'csr_bytes' located at address 'a'. */
static inline uint64_t _csr_rd(uint32_t a32, unsigned long a, int csr_bytes)
{
uint64_t r = __builtin_bswap32(*((uint32_t*)(a32 + a)));
for (int i = 1; i < num_subregs(csr_bytes); i++) {
r <<= CONFIG_CSR_DATA_WIDTH;
a += CSR_OFFSET_BYTES;
r |= __builtin_bswap32(*((uint32_t*)(a32 + a)));
}
return r;
}
/* Write value 'v' to a CSR of size 'csr_bytes' located at address 'a'. */
static inline void _csr_wr(uint32_t a32, unsigned long a, uint64_t v, int csr_bytes)
{
int ns = num_subregs(csr_bytes);
for (int i = 0; i < ns; i++) {
*((uint32_t*)(a32 + a)) = __builtin_bswap32(v >> (CONFIG_CSR_DATA_WIDTH * (ns - 1 - i)));
a += CSR_OFFSET_BYTES;
}
}
// FIXME: - should we provide 24, 40, 48, and 56 bit csr_[rd|wr] methods?
static inline uint8_t csr_rd_uint8(uint32_t a32, unsigned long a)
{
return _csr_rd(a32, a, sizeof(uint8_t));
}
static inline void csr_wr_uint8(uint32_t a32, uint8_t v, unsigned long a)
{
_csr_wr(a32, a, v, sizeof(uint8_t));
}
static inline uint16_t csr_rd_uint16(uint32_t a32, unsigned long a)
{
return _csr_rd(a32, a, sizeof(uint16_t));
}
static inline void csr_wr_uint16(uint32_t a32, uint16_t v, unsigned long a)
{
_csr_wr(a32, a, v, sizeof(uint16_t));
}
static inline uint32_t csr_rd_uint32(uint32_t a32, unsigned long a)
{
return _csr_rd(a32, a, sizeof(uint32_t));
}
static inline void csr_wr_uint32(uint32_t a32, uint32_t v, unsigned long a)
{
_csr_wr(a32, a, v, sizeof(uint32_t));
}
static inline uint64_t csr_rd_uint64(uint32_t a32, unsigned long a)
{
return _csr_rd(a32, a, sizeof(uint64_t));
}
static inline void csr_wr_uint64(uint32_t a32, uint64_t v, unsigned long a)
{
_csr_wr(a32, a, v, sizeof(uint64_t));
}
/* Read a CSR located at address 'a' into an array 'buf' of 'cnt' elements.
*
* NOTE: Since CSR_DW_BYTES is a constant here, we might be tempted to further
* optimize things by leaving out one or the other of the if() branches below,
* depending on each unsigned type width;
* However, this code is also meant to serve as a reference for how CSRs are
* to be manipulated by other programs (e.g., an OS kernel), which may benefit
* from dynamically handling multiple possible CSR subregister data widths
* (e.g., by passing a value in through the Device Tree).
* Ultimately, if CSR_DW_BYTES is indeed a constant, the compiler should be
* able to determine on its own whether it can automatically optimize away one
* of the if() branches! */
#define _csr_rd_buf(a32, a, buf, cnt) \
{ \
int i, j, nsubs, n_sub_elem; \
uint64_t r; \
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
/* one or more subregisters per element */ \
for (i = 0; i < cnt; i++) { \
buf[i] = _csr_rd(a32, a, sizeof(buf[0])); \
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
} \
} else { \
/* multiple elements per subregister (2, 4, or 8) */ \
nsubs = num_subregs(sizeof(buf[0]) * cnt); \
n_sub_elem = CSR_DW_BYTES / sizeof(buf[0]); \
for (i = 0; i < nsubs; i++) { \
r = __builtin_bswap32(*(uint32_t*)(a32 + a)); \
for (j = n_sub_elem - 1; j >= 0; j--) { \
if (i * n_sub_elem + j < cnt) \
buf[i * n_sub_elem + j] = r; \
r >>= sizeof(buf[0]) * 8; \
} \
a += CSR_OFFSET_BYTES; \
} \
} \
}
/* Write an array 'buf' of 'cnt' elements to a CSR located at address 'a'.
*
* NOTE: The same optimization considerations apply here as with _csr_rd_buf()
* above.
*/
#define _csr_wr_buf(a32, a, buf, cnt) \
{ \
int i, j, nsubs, n_sub_elem; \
uint64_t v; \
if (sizeof(buf[0]) >= CSR_DW_BYTES) { \
/* one or more subregisters per element */ \
for (i = 0; i < cnt; i++) { \
_csr_wr(a32, a, buf[i], sizeof(buf[0])); \
a += CSR_OFFSET_BYTES * num_subregs(sizeof(buf[0])); \
} \
} else { \
/* multiple elements per subregister (2, 4, or 8) */ \
nsubs = num_subregs(sizeof(buf[0]) * cnt); \
n_sub_elem = CSR_DW_BYTES / sizeof(buf[0]); \
for (i = 0; i < nsubs; i++) { \
v = buf[i * n_sub_elem + 0]; \
for (j = 1; j < n_sub_elem; j++) { \
if (i * n_sub_elem + j == cnt) \
break; \
v <<= sizeof(buf[0]) * 8; \
v |= buf[i * n_sub_elem + j]; \
} \
*((uint32_t*)(a32 + a)) = __builtin_bswap32(v); \
a += CSR_OFFSET_BYTES; \
} \
} \
}
static inline void csr_rd_buf_uint8(uint32_t a32, unsigned long a, uint8_t *buf, int cnt)
{
_csr_rd_buf(a32, a, buf, cnt);
}
static inline void csr_wr_buf_uint8(uint32_t a32, unsigned long a,
const uint8_t *buf, int cnt)
{
_csr_wr_buf(a32, a, buf, cnt);
}
static inline void csr_rd_buf_uint16(uint32_t a32, unsigned long a, uint16_t *buf, int cnt)
{
_csr_rd_buf(a32, a, buf, cnt);
}
static inline void csr_wr_buf_uint16(uint32_t a32, unsigned long a,
const uint16_t *buf, int cnt)
{
_csr_wr_buf(a32, a, buf, cnt);
}
static inline void csr_rd_buf_uint32(uint32_t a32, unsigned long a, uint32_t *buf, int cnt)
{
_csr_rd_buf(a32, a, buf, cnt);
}
static inline void csr_wr_buf_uint32(uint32_t a32, unsigned long a,
const uint32_t *buf, int cnt)
{
_csr_wr_buf(a32, a, buf, cnt);
}
/* NOTE: the macros' "else" branch is unreachable, no need to be warned
* about a >= 64bit left shift! */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
static inline void csr_rd_buf_uint64(uint32_t a32, unsigned long a, uint64_t *buf, int cnt)
{
_csr_rd_buf(a32, a, buf, cnt);
}
static inline void csr_wr_buf_uint64(uint32_t a32, unsigned long a,
const uint64_t *buf, int cnt)
{
_csr_wr_buf(a32, a, buf, cnt);
}
#pragma GCC diagnostic pop
#endif // __NUBUSFPGA_CSR_COMMON_H__

228
DeclROM/vid_decl_rom.s Normal file
View File

@@ -0,0 +1,228 @@
.include "atrap.inc"
.include "globals.inc"
.include "declrom.inc"
.include "ROMDefs.inc"
.include "Video.inc"
.include "DepVideo.inc"
sRsrc_Board = 1 /* board sResource (>0 & <128) */
.include "VidRomDef.s"
sRsrc_RAMDsk = 0x90 /* functional sResources */
sRsrc_SDCard = 0x91 /* functional sResources */
sRsrc_HDMIAudio = 0xA0 /* functional sResources */
.global DeclROMDir
.section .text.begin
.include "VidRomRsrcDir.s"
.global _sRsrc_Board
_sRsrc_Board:
OSLstEntry sRsrcType,_BoardType /* offset to board descriptor */
OSLstEntry sRsrcName,_BoardName /* offset to name of board */
DatLstEntry boardId,NuBusFPGAID /* board ID # (assigned by DTS) */
/* OSLstEntry primaryInit,_sPInitRec */ /* offset to PrimaryInit exec blk */
.long entry_sPInitRec
OSLstEntry vendorInfo,_VendorInfo /* offset to vendor info record */
/* OSLstEntry secondaryInit,_sSInitRec */ /* offset to SecondaryInit block */
.long entry_sSInitRec
OSLstEntry sRsrcVidNames, _VModeName /* video name directory */
.long EndOfList
_BoardType:
.short catBoard /* board sResource */
.short typeBoard
.short 0
.short 0
_BoardName:
.string "NuBusFPGA GoboFB\0" /* name of board */
ALIGN 2
/* _VidICON ; optional icon, not needed */
/* _sVidNameDir ; optional name(s), not needed */
.section .text.primary_init
/* _sPInitRec: */
/* .long _EndsPInitRec-_sPInitRec */ /* physical block size */
.long size_sPInitRec
.byte sExec2 /* Code revision (Primary init) */
.byte sCPU68020 /* CPU type is 68020 */
.short 0 /* Reserved */
.long Primary-. /* Offset to C code. */
ALIGN 2
/* _EndsPInitRec: */
.section .text.secondary_init
/* _sSInitRec: */
/* .long _EndsSInitRec-_sSInitRec */ /* physical block size */
.long size_sSInitRec
.byte sExec2 /* Code revision (Primary init) */
.byte sCPU68020 /* CPU type is 68020 */
.short 0 /* Reserved */
.long Secondary-. /* Offset to C code. */
ALIGN 2
/* _EndsSInitRec: */
.section .text.begin
ALIGN 2
_VendorInfo:
OSLstEntry vendorId,_VendorId /* offset to vendor ID */
OSLstEntry serialNum,_SerialNum /* offset to revision */
OSLstEntry revLevel,_RevLevel /* offset to revision */
OSLstEntry partNum,_PartNum /* offset to part number record */
OSLstEntry date,_Date /* offset to ROM build date */
.long EndOfList
_VendorId:
.string "Romain Dolbeau\0" /* vendor ID */
_SerialNum:
.string "0000000001\0" /* serial number */
_RevLevel:
.string "NuBusFPGA V1.0\0" /* revision level */
_PartNum:
.string "Part Number\0" /* part number */
_Date:
.string "&SysDate" /* date */
.include "VidRomName.s" /* contains _VidName */
.include "VidRomDir.s"
ALIGN 2
_GoboFBType:
.short catDisplay /* <Category> */
.short typeVideo /* <Type> */
.short drSwApple /* <DrvrSw> */
.short DrHwNuBusFPGA /* <DrvrHw> */
_GoboFBName:
.string "GoboFB_NuBusFPGA" /* video driver name */
_MinorBase:
.long defMinorBase /* frame buffer offset */
_MinorLength:
.long defMinorLength /* frame buffer length */
ALIGN 2
.section .text.begin
.global _GoboFBDrvrDir
_GoboFBDrvrDir:
/* OSLstEntry sMacOS68020,_GoboFBDrvrMacOS68020 */ /* driver directory for Mac OS */
.long entry_GoboFBDrvrMacOS68020
.long EndOfList
ALIGN 2
.section .text.fbdriver_init
/* _GoboFBDrvrMacOS68020: */ /* supplied by linker script */
.long _GoboFBEnd020Drvr-. /* physical block size */
.include "NuBusFPGADrvr.s" /* driver code */
/* _GoboFBEnd020Drvr: */ /* supplied by linker script */
.section .text.begin
.include "VidRomRes.s"
/* ////////////////////////////////////////////// RAM DISK */
.section .text.begin
ALIGN 2
_sRsrc_RAMDsk:
OSLstEntry sRsrcType,_RAMDskType /* video type descriptor */
OSLstEntry sRsrcName,_RAMDskName /* offset to driver name string */
OSLstEntry sRsrcDrvrDir,_RAMDskDrvrDir /* offset to driver directory */
DatLstEntry sRsrcFlags,6 /* force 32 bits mode & open */
DatLstEntry sRsrcHWDevId,2 /* hardware device ID */
.long EndOfList /* end of list */
ALIGN 2
_RAMDskType:
.short catProto /* <Category> */
.short typeDrive /* custom */ /* <Type> */
.short drSwApple /* <DrvrSw> */
.short DrHwNuBusFPGADsk /* <DrvrHw> */
_RAMDskName:
.string "RAMDsk_NuBusFPGA" /* video driver name */
ALIGN 2
.section .text.begin
.global _RAMDskDrvrDir
_RAMDskDrvrDir:
/* OSLstEntry sMacOS68020,_RAMDskDrvrMacOS68020 */ /* driver directory for Mac OS */
.long entry_RAMDskDrvrMacOS68020
.long EndOfList
ALIGN 2
.section .text.dskdriver_init
/* _RAMDskDrvrMacOS68020: */ /* supplied by linker script */
.long _RAMDskEnd020Drvr-. /* physical block size */
.include "NuBusFPGARAMDskDrvr.s" /* driver code */
/* _RAMDskEnd020Drvr: */ /* supplied by linker script */
/* ////////////////////////////////////////////// SDCARD */
.section .text.begin
ALIGN 2
_sRsrc_SDCard:
OSLstEntry sRsrcType,_SDCardType /* video type descriptor */
OSLstEntry sRsrcName,_SDCardName /* offset to driver name string */
OSLstEntry sRsrcDrvrDir,_SDCardDrvrDir /* offset to driver directory */
DatLstEntry sRsrcFlags,6 /* force 32 bits mode & open */
DatLstEntry sRsrcHWDevId,2 /* hardware device ID */
.long EndOfList /* end of list */
ALIGN 2
_SDCardType:
.short catProto /* <Category> */
.short typeDrive /* custom */ /* <Type> */
.short drSwApple /* <DrvrSw> */
.short DrHwNuBusFPGASDCard /* <DrvrHw> */
_SDCardName:
.string "SDCard_NuBusFPGA" /* video driver name */
ALIGN 2
.section .text.begin
.global _SDCardDrvrDir
_SDCardDrvrDir:
/* OSLstEntry sMacOS68020,_SDCardDrvrMacOS68020 */ /* driver directory for Mac OS */
.long entry_SDCardDrvrMacOS68020
.long EndOfList
ALIGN 2
.section .text.sddriver_init
/* _SDCardDrvrMacOS68020: */ /* supplied by linker script */
.long _SDCardEnd020Drvr-. /* physical block size */
.include "NuBusFPGASDCardDrvr.s" /* driver code */
/* _SDCardEnd020Drvr: */ /* supplied by linker script */
/* ////////////////////////////////////////////// HDMI AUDIO */
.section .text.begin
ALIGN 2
_sRsrc_HDMIAudio:
OSLstEntry sRsrcType,_HDMIAudioType /* video type descriptor */
.long EndOfList /* end of list */
ALIGN 2
_HDMIAudioType:
.short catProto /* <Category> */
.short typeAudio /* custom */ /* <Type> */
.short drSwApple /* <DrvrSw> */
.short DrHwNuBusFPGAAudio /* <DrvrHw> */
/* Declaration ROM directory at end */
.section .romblock
ALIGN 2
DeclROMDir:
.long RsrcDirOffset /* supplied by linker script, replace OSLstEntry 0, _sRsrcDir */
DeclROMCRC:
.long ROMSize /* supplied by linker script */
.long 0 /* crc TBComputed after the fact */
.byte 1 /* Revision Level */
.byte appleFormat /* Apple Format */
.long testPattern /* magic TestPattern */
.byte 0 /* reserved */
.byte 0x0F /* byte lane marker */
DeclRomEnd:
.end