Added support for v4.2 boards

Renamed "pbook" firmware to "v4". Original "green" boards now under "v3".
Add external LED support for v4 firmware.
Added --reset to scsi2sd-config
bootloaderhost can now reset the board.
This commit is contained in:
Michael McMaster 2014-07-12 23:55:57 +10:00
parent 186938a03f
commit 5e0f1e3360
527 changed files with 3428 additions and 2152 deletions

View File

@ -1,7 +1,12 @@
201404xx 3.5
20140713 3.5
- Fixed several performance issues. Transfer rates up to 2.5MB/s are now
possible.
- Implemented the READ BUFFER scsi command for performance testing purposes.
- Added support for the new "yellow" v4.2 revision boards.
- Improved firmware uploading. bootloaderhost can now reset the board back
to the bootloader.
- Display firmware version in scsi2sd-config
- Add "--reset" parameter to scsi2sd-config
20140418 3.4
- Critical fix for writes when using non-standard block sizes.

View File

@ -62,19 +62,34 @@ Tested with a 16GB class 10 SD card, via the commands:
Compatibility
Tested with Linux (current), Apple Macintosh System 7.5.3 on LC-III, and LC-475 hardware.
Users have reported success on these systems:
Desktop systems
Mac LC-III and LC-475
Mac II running System 6.0.8
Mac SE/30
Apple IIgs using Apple II High Speed SCSI controller card (from v3.3)
Symbolics Lisp Machine XL1200, using 1280 byte sectors (from v3.4)
PDP-11/73 running RSX11M+ V4.6
Amiga 500+ with GVP A530
Atari TT030 System V
Samplers
Roland JS-30 Sampler
Akai S1000, S3200, S3000XL, MPC 2000XL, DPS 12
SCSI cable reversed on S3200
There are compatibility problems with the Akai MPC3000. It works (slowly) with the alternate Vailixi OS with multi-sector transfers disabled.
EMU Emulator E4X with EOS 3.00b and E6400 (classic) with Eos 4.01
Ensoniq ASR-X, ASR-10 (from v3.4, 2GB size limit)
ASR-20 Requires TERMPWR jumper.
Kurzweil K2000R
See kurzweil.com for size limits which a dependant on the OS version. Older OS versions have a 1GB limit.
SCSI cable reversed
Casio FZ-20M
Requires TERMPWR jumper. The manual shows the pin25 of the DB25 connector is "not connected".
May require scsi2sd-config --apple flag
Other
HP 16601A logic analyzer
Apple IIgs using Apple II High Speed SCSI controller card (from v3.3)
Symbolics List Machine XL1200, using 1280 byte sectors (from v3.4)
Fluke 9100 series
PDP-11/73 running RSX11M+ V4.6
Amiga 500+ with GVP A530
Fluke 9100 series

View File

@ -1 +0,0 @@
../../SCSI2SD.cydsn/OddParityGen/

View File

@ -1 +0,0 @@
../../SCSI2SD.cydsn/scsiTarget/

View File

@ -28,6 +28,7 @@
// CYDEV_EEPROM_ROW_SIZE == 16.
static const char magic[CYDEV_EEPROM_ROW_SIZE] = "codesrc_00000002";
static const uint16_t FIRMWARE_VERSION = 0x0350;
// Config shadow RAM (copy of EEPROM)
static Config shadow =
@ -48,6 +49,7 @@ enum USB_ENDPOINTS
{
USB_EP_OUT = 1,
USB_EP_IN = 2,
USB_EP_COMMAND = 3,
USB_EP_DEBUG = 4
};
enum USB_STATE
@ -172,6 +174,7 @@ void configPoll()
if (reset)
{
USBFS_EnableOutEP(USB_EP_OUT);
USBFS_EnableOutEP(USB_EP_COMMAND);
usbInEpState = usbDebugEpState = USB_IDLE;
}
@ -238,14 +241,31 @@ void configPoll()
}
}
#ifdef MM_DEBUG
void debugPoll()
{
if (!usbReady)
{
return;
}
if(USBFS_GetEPState(USB_EP_COMMAND) == USBFS_OUT_BUFFER_FULL)
{
// The host sent us some data!
int byteCount = USBFS_GetEPCount(USB_EP_COMMAND);
USBFS_ReadOutEP(USB_EP_COMMAND, (uint8 *)&debugBuffer, byteCount);
if (byteCount >= 1 &&
debugBuffer[0] == 0x01)
{
// Reboot command.
Bootloadable_1_Load();
}
// Allow the host to send us another command.
// (assuming we didn't reboot outselves)
USBFS_EnableOutEP(USB_EP_COMMAND);
}
switch (usbDebugEpState)
{
case USB_IDLE:
@ -265,6 +285,14 @@ void debugPoll()
debugBuffer[24] = scsiDev.cmdCount;
debugBuffer[25] = scsiDev.watchdogTick;
debugBuffer[58] = sdDev.capacity >> 24;
debugBuffer[59] = sdDev.capacity >> 16;
debugBuffer[60] = sdDev.capacity >> 8;
debugBuffer[61] = sdDev.capacity;
debugBuffer[62] = FIRMWARE_VERSION >> 8;
debugBuffer[63] = FIRMWARE_VERSION;
USBFS_LoadInEP(USB_EP_DEBUG, (uint8 *)&debugBuffer, sizeof(debugBuffer));
usbDebugEpState = USB_DATA_SENT;
break;
@ -287,18 +315,11 @@ CY_ISR(debugTimerISR)
debugPoll();
CyExitCriticalSection(savedIntrStatus);
}
#endif
void debugInit()
{
#ifdef MM_DEBUG
Debug_Timer_Interrupt_StartEx(debugTimerISR);
Debug_Timer_Start();
#else
Debug_Timer_Interrupt_Stop();
Debug_Timer_Stop();
#endif
}
// Public method for storing MODE SELECT results.

View File

@ -180,7 +180,6 @@ static void doWrite(uint32 lba, uint32 blocks)
// multi-block write is minimal.
transfer.multiBlock = 1;
if (blocks > 1) scsiDev.needReconnect = 1;
sdWriteMultiSectorPrep();
}
}
@ -216,7 +215,6 @@ static void doRead(uint32 lba, uint32 blocks)
else
{
transfer.multiBlock = 1;
scsiDev.needReconnect = 1;
sdReadMultiSectorPrep();
}
}
@ -612,7 +610,10 @@ void scsiDiskInit()
}
#endif
if (SD_CD_Read() == 1)
// The Card-detect switches of micro-sd sockets are not standard. Don't make
// use of SD_CD so we can use sockets from other manufacturers.
// Detect presence of the card by testing whether it responds to commands.
// if (SD_CD_Read() == 1)
{
int retry;
blockDev.state = blockDev.state | DISK_PRESENT;

77
software/SCSI2SD/src/led.c Executable file
View File

@ -0,0 +1,77 @@
// Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
//
// This file is part of SCSI2SD.
//
// SCSI2SD is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SCSI2SD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
#include "led.h"
// External LED support only exists on the 3.5" v4 board.
// The powerbook v4 board ties the pin to ground.
// The v3 boards do not have any such pin.
#ifdef EXTLED_CTL
#define HAVE_EXTLED 1
#endif
#ifdef HAVE_EXTLED
static int enable_EXTLED = 0;
#endif
void ledInit()
{
#ifdef HAVE_EXTLED
EXTLED_SetDriveMode(EXTLED_DM_DIG_HIZ | EXTLED_DM_RES_UP);
int val = EXTLED_Read();
if (val)
{
// Pin is not tied to ground, so it's safe to use.
enable_EXTLED = 1;
EXTLED_SetDriveMode(LED1_DM_STRONG);
}
else
{
// Pin is tied to ground. Using it would damage hardware
// This is the case for the powerbook boards.
enable_EXTLED = 0;
EXTLED_SetDriveMode(EXTLED_DM_DIG_HIZ);
}
#endif
ledOff();
}
void ledOn()
{
LED1_Write(0);
#ifdef HAVE_EXTLED
if (enable_EXTLED)
{
EXTLED_Write(1);
}
#endif
}
void ledOff()
{
LED1_Write(1);
#ifdef HAVE_EXTLED
if (enable_EXTLED)
{
EXTLED_Write(0);
}
#endif
}

View File

@ -19,7 +19,8 @@
#include "device.h"
#define ledOn() LED1_Write(0)
#define ledOff() LED1_Write(1)
void ledInit(void);
void ledOn(void);
void ledOff(void);
#endif

View File

@ -26,7 +26,7 @@ const char* Notice = "Copyright (C) 2014 Michael McMaster <michael@codesrc.com>"
int main()
{
ledOff();
ledInit();
// Enable global interrupts.
// Needed for RST and ATN interrupt handlers.
@ -41,17 +41,10 @@ int main()
scsiInit();
scsiDiskInit();
if (!(blockDev.state & DISK_INITIALISED))
{
while (1) { ledOn();CyDelay(200); ledOff();CyDelay(200); }
}
while (1)
{
#ifdef MM_DEBUG
scsiDev.watchdogTick++;
#endif
scsiPoll();
scsiDiskPoll();
configPoll();

View File

@ -111,93 +111,12 @@ static void enter_Status(uint8 status)
scsiDev.status = status;
scsiDev.phase = STATUS;
#ifdef MM_DEBUG
scsiDev.lastStatus = scsiDev.status;
scsiDev.lastSense = scsiDev.sense.code;
#endif
}
static void doReselectTest()
{
scsiDev.needReconnect = 0;
scsiEnterPhase(MESSAGE_IN);
scsiWriteByte(0x02); // save data pointer
// TODO check if this message was rejected.
scsiWriteByte(0x04); // disconnect msg.
enter_BusFree();
CyDelay(100);
while (1)
{
int sel = SCSI_ReadPin(SCSI_In_SEL);
int bsy = SCSI_ReadPin(SCSI_In_BSY);
if (!sel && !bsy)
{
// TODO wait bus settle delay
CyDelayUs(1); // TODO bus free delay 800ns
// Arbitrate.
ledOn();
SCSI_Out_Bits_Write(scsiDev.scsiIdMask);
SCSI_Out_Ctl_Write(1); // Write bits manually.
SCSI_SetPin(SCSI_Out_BSY);
CyDelayUs(3); // arbitrate delay. 2.4us.
uint8_t dbx = scsiReadDBxPins();
sel = SCSI_ReadPin(SCSI_In_SEL);
if (sel || ((dbx ^ scsiDev.scsiIdMask) > scsiDev.scsiIdMask))
{
// Lost arbitration.
SCSI_Out_Ctl_Write(0);
SCSI_ClearPin(SCSI_Out_BSY);
ledOff();
}
else
{
// Won arbitration
SCSI_SetPin(SCSI_Out_SEL);
CyDelayUs(1); // Bus clear + Bus settle.
// Reselection phase
scsiEnterPhase(__scsiphase_io); // TODO get rid of delay
SCSI_Out_Bits_Write(scsiDev.scsiIdMask | (1 << scsiDev.initiatorId));
CyDelayCycles(4); // 2 deskew delays
SCSI_ClearPin(SCSI_Out_BSY);
CyDelayUs(1); // Bus Settle Delay
bsy = SCSI_ReadPin(SCSI_In_BSY);
while (!bsy) { bsy = SCSI_ReadPin(SCSI_In_BSY); } // Wait for initiator.
SCSI_SetPin(SCSI_Out_BSY);
// Prepare for the initial IDENTIFY message.
scsiEnterPhase(MESSAGE_IN);
SCSI_Out_Ctl_Write(0);
SCSI_ClearPin(SCSI_Out_SEL);
// Send identify command
scsiWriteByte(0x80);
break;
}
}
}
// Continue with status.
}
static void process_Status()
{
if (scsiDev.status == GOOD && scsiDev.needReconnect && scsiDev.allowDisconnect)
{
// doReselectTest();
}
scsiEnterPhase(STATUS);
uint8 message;
@ -222,10 +141,8 @@ static void process_Status()
}
scsiWriteByte(scsiDev.status);
#ifdef MM_DEBUG
scsiDev.lastStatus = scsiDev.status;
scsiDev.lastSense = scsiDev.sense.code;
#endif
// Command Complete occurs AFTER a valid status has been
// sent. then we go bus-free.
@ -325,17 +242,13 @@ static void process_Command()
lun = scsiDev.cdb[1] >> 5;
control = scsiDev.cdb[scsiDev.cdbLen - 1];
#ifdef MM_DEBUG
scsiDev.cmdCount++;
#endif
if (scsiDev.resetFlag)
{
#ifdef MM_DEBUG
// Don't log bogus commands
scsiDev.cmdCount--;
memset(scsiDev.cdb, 0xff, sizeof(scsiDev.cdb));
#endif
return;
}
else if (scsiDev.parityError)
@ -501,9 +414,7 @@ static void doReserveRelease()
static void scsiReset()
{
#ifdef MM_DEBUG
scsiDev.rstCount++;
#endif
ledOff();
scsiPhyReset();
@ -513,7 +424,6 @@ static void scsiReset()
scsiDev.phase = BUS_FREE;
scsiDev.atnFlag = 0;
scsiDev.resetFlag = 0;
scsiDev.needReconnect = 0;
if (scsiDev.unitAttention != POWER_ON_RESET)
{
@ -548,8 +458,6 @@ static void enter_SelectionPhase()
scsiDev.dataLen = 0;
scsiDev.status = GOOD;
scsiDev.phase = SELECTION;
scsiDev.needReconnect = 0;
scsiDev.allowDisconnect = 0;
transfer.blocks = 0;
transfer.currentBlock = 0;
@ -593,9 +501,7 @@ static void process_SelectionPhase()
SCSI_SetPin(SCSI_Out_BSY);
ledOn();
#ifdef MM_DEBUG
scsiDev.selCount++;
#endif
// Wait until the end of the selection phase.
while (!scsiDev.resetFlag)
@ -643,9 +549,7 @@ static void process_MessageOut()
scsiDev.atnFlag = 0;
scsiDev.parityError = 0;
scsiDev.msgOut = scsiReadByte();
#ifdef MM_DEBUG
scsiDev.msgCount++;
#endif
if (scsiDev.parityError)
{
@ -731,7 +635,7 @@ static void process_MessageOut()
//enter_Status(CHECK_CONDITION);
messageReject();
}
scsiDev.allowDisconnect = scsiDev.msgOut & 0x40;
//scsiDev.allowDisconnect = scsiDev.msgOut & 0x40;
}
else if (scsiDev.msgOut >= 0x20 && scsiDev.msgOut <= 0x2F)
{

View File

@ -17,12 +17,6 @@
#ifndef SCSI_H
#define SCSI_H
// Set this to true to log SCSI commands and status information via
// USB HID packets. The can be captured and viewed in wireshark.
// For windows users, capture using USBPcap http://desowin.org/usbpcap/
//#define MM_DEBUG 1
#undef MM_DEBUG
#include "geometry.h"
#include "sense.h"
@ -110,7 +104,6 @@ typedef struct
void (*postDataOutHook)(void);
#ifdef MM_DEBUG
uint8 cmdCount;
uint8 selCount;
uint8 rstCount;
@ -118,10 +111,6 @@ typedef struct
uint8 watchdogTick;
uint8 lastStatus;
uint8 lastSense;
#endif
uint8 allowDisconnect;
uint8 needReconnect;
} ScsiDevice;
extern ScsiDevice scsiDev;

Some files were not shown because too many files have changed in this diff Show More