Merge pull request #59 from TC1995/master

Buslogic fixes
This commit is contained in:
OBattler
2016-12-26 03:47:24 +01:00
committed by GitHub

View File

@@ -513,18 +513,17 @@ typedef struct Buslogic_t
int DmaChannel; int DmaChannel;
int IrqEnabled; int IrqEnabled;
int Mbx24bit; int Mbx24bit;
int CommandCallback;
} Buslogic_t; } Buslogic_t;
int scsi_base = 0x330; int scsi_base = 0x330;
int scsi_dma = 6; int scsi_dma = 6;
int scsi_irq = 11; int scsi_irq = 11;
int aha154x_do_log = 0; int buslogic_do_log = 0;
void BuslogicLog(const char *format, ...) void BuslogicLog(const char *format, ...)
{ {
if (aha154x_do_log) if (buslogic_do_log)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
@@ -536,7 +535,7 @@ void BuslogicLog(const char *format, ...)
static void BuslogicClearInterrupt(Buslogic_t *Buslogic) static void BuslogicClearInterrupt(Buslogic_t *Buslogic)
{ {
BuslogicLog("Buslogic: Clearing Interrupt 0x%02X\n", Buslogic->Interrupt); pclog("Buslogic: Clearing Interrupt 0x%02X\n", Buslogic->Interrupt);
Buslogic->Interrupt = 0; Buslogic->Interrupt = 0;
picintc(1 << Buslogic->Irq); picintc(1 << Buslogic->Irq);
} }
@@ -567,7 +566,7 @@ static void BuslogicLocalRam(Buslogic_t *Buslogic)
static void BuslogicReset(Buslogic_t *Buslogic) static void BuslogicReset(Buslogic_t *Buslogic)
{ {
Buslogic->Status = STAT_IDLE | STAT_INIT; Buslogic->Status = STAT_IDLE | STAT_INIT;
Buslogic->Geometry = 0x80; Buslogic->Geometry |= 0x80;
Buslogic->Command = 0xFF; Buslogic->Command = 0xFF;
Buslogic->CmdParam = 0; Buslogic->CmdParam = 0;
Buslogic->CmdParamLeft = 0; Buslogic->CmdParamLeft = 0;
@@ -585,9 +584,9 @@ static void BuslogicReset(Buslogic_t *Buslogic)
static void BuslogicResetControl(Buslogic_t *Buslogic, uint8_t Reset) static void BuslogicResetControl(Buslogic_t *Buslogic, uint8_t Reset)
{ {
BuslogicReset(Buslogic); BuslogicReset(Buslogic);
if (Reset & CTRL_HRST) if (Reset)
{ {
Buslogic->Status = STAT_STST; Buslogic->Status |= STAT_STST;
Buslogic->Status &= ~STAT_IDLE; Buslogic->Status &= ~STAT_IDLE;
} }
} }
@@ -881,7 +880,7 @@ uint8_t BuslogicRead(uint16_t Port, void *p)
break; break;
} }
BuslogicLog("Buslogic: Read Port 0x%02X, Returned Value %02X\n", Port, Temp); pclog("Buslogic: Read Port 0x%02X, Returned Value %02X\n", Port, Temp);
return Temp; return Temp;
} }
@@ -889,7 +888,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
{ {
Buslogic_t *Buslogic = (Buslogic_t *)p; Buslogic_t *Buslogic = (Buslogic_t *)p;
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
BuslogicLog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); pclog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val);
switch (Port & 3) switch (Port & 3)
{ {
@@ -902,7 +901,9 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
} }
if (Val & CTRL_IRST) if (Val & CTRL_IRST)
{
BuslogicClearInterrupt(Buslogic); BuslogicClearInterrupt(Buslogic);
}
break; break;
case 1: case 1:
@@ -927,12 +928,13 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 0x0B: case 0x0B:
case 0x84: case 0x84:
case 0x85: case 0x85:
case 0x86:
case 0x95:
case 0x22: case 0x22:
Buslogic->CmdParamLeft = 0; Buslogic->CmdParamLeft = 0;
break; break;
case 0x0A: case 0x0A:
//case 0x8D: //For Aha-154x
Buslogic->CmdParamLeft = 0; Buslogic->CmdParamLeft = 0;
break; break;
@@ -942,12 +944,15 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 0x0D: case 0x0D:
case 0x1F: case 0x1F:
case 0x21: case 0x21:
case 0x8B: //For Buslogic
case 0x8D: //For Buslogic
case 0x24: case 0x24:
case 0x25: case 0x25:
Buslogic->CmdParamLeft = 1;
break;
case 0x8B:
case 0x8D:
case 0x8F: case 0x8F:
case 0x96: //For Buslogic case 0x96:
Buslogic->CmdParamLeft = 1; Buslogic->CmdParamLeft = 1;
break; break;
@@ -973,11 +978,8 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
break; break;
case 0x28: case 0x28:
Buslogic->CmdParamLeft = 0;
break;
case 0x29: case 0x29:
Buslogic->CmdParamLeft = 2; Buslogic->CmdParamLeft = 0;
break; break;
} }
} }
@@ -1081,18 +1083,13 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
break; break;
case 0x0A: case 0x0A:
{ if (SCSIDevices[scsi_cdrom_id].LunType == SCSI_CDROM)
int i; Buslogic->DataBuf[scsi_cdrom_id] = 1;
memset(Buslogic->DataBuf, 0, 8); else
for (i=0;i<7;++i) Buslogic->DataBuf[scsi_cdrom_id] = 0;
{
if (SCSIDevices[i].LunType == SCSI_CDROM)
Buslogic->DataBuf[i] = 1;
}
Buslogic->DataBuf[7] = 0; Buslogic->DataBuf[7] = 0;
Buslogic->DataReplyLeft = 8; Buslogic->DataReplyLeft = 8;
}
break; break;
case 0x0B: case 0x0B:
@@ -1112,19 +1109,18 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Reply->fParityCheckingEnabled = 1; Reply->fParityCheckingEnabled = 1;
Reply->cMailbox = Buslogic->MailboxCount; Reply->cMailbox = Buslogic->MailboxCount;
U32_TO_ADDR(Reply->MailboxAddress, Buslogic->MailboxOutAddr); U32_TO_ADDR(Reply->MailboxAddress, Buslogic->MailboxOutAddr);
#if 1
Reply->uSignature = 'B'; Reply->uSignature = 'B';
/* The 'D' signature prevents Buslogic's OS/2 drivers from getting too /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too
* friendly with BusLogic hardware and upsetting the HBA state. * friendly with Adaptec hardware and upsetting the HBA state.
*/ */
Reply->uCharacterD = 'D'; /* BusLogic model. */ Reply->uCharacterD = 'D'; /* BusLogic model. */
Reply->uHostBusType = 'A'; /* ISA bus. */ Reply->uHostBusType = 'A'; /* ISA bus. */
#endif
pclog("Return Setup Information: %d\n", Buslogic->CmdBuf[0]); pclog("Return Setup Information: %d\n", Buslogic->CmdBuf[0]);
} }
break; break;
#if 1
case 0x8B: case 0x8B:
{ {
int i; int i;
@@ -1132,7 +1128,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
/* The reply length is set by the guest and is found in the first byte of the command buffer. */ /* The reply length is set by the guest and is found in the first byte of the command buffer. */
Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; Buslogic->DataReplyLeft = Buslogic->CmdBuf[0];
memset(Buslogic->DataBuf, 0, Buslogic->DataReplyLeft); memset(Buslogic->DataBuf, 0, Buslogic->DataReplyLeft);
const char aModelName[] = "540B "; /* Trailing \0 is fine, that's the filler anyway. */ const char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */
int cCharsToTransfer = Buslogic->DataReplyLeft <= sizeof(aModelName) int cCharsToTransfer = Buslogic->DataReplyLeft <= sizeof(aModelName)
? Buslogic->DataReplyLeft ? Buslogic->DataReplyLeft
: sizeof(aModelName); : sizeof(aModelName);
@@ -1141,9 +1137,8 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->DataBuf[i] = aModelName[i]; Buslogic->DataBuf[i] = aModelName[i];
} }
break; break;
#endif
case 0x8D: case 0x8D:
#if 1
{ {
Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; Buslogic->DataReplyLeft = Buslogic->CmdBuf[0];
ReplyInquireExtendedSetupInformation *Reply = (ReplyInquireExtendedSetupInformation *)Buslogic->DataBuf; ReplyInquireExtendedSetupInformation *Reply = (ReplyInquireExtendedSetupInformation *)Buslogic->DataBuf;
@@ -1155,11 +1150,6 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision)); memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision));
pclog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]); pclog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]);
} }
#endif
#if 0
Buslogic->DataReplyLeft = 0;
Buslogic->Status |= STAT_INVCMD;
#endif
break; break;
case 0x1C: case 0x1C:
@@ -1245,11 +1235,6 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
} }
break; break;
case 0x22:
Buslogic->DataReplyLeft = 0;
Buslogic->Status |= STAT_INVCMD;
break;
case 0x96: case 0x96:
if (Buslogic->CmdBuf[0] == 0) if (Buslogic->CmdBuf[0] == 0)
Buslogic->ExtendedLUNCCBFormat = 0; Buslogic->ExtendedLUNCCBFormat = 0;
@@ -1259,12 +1244,13 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
break; break;
case 0x28: case 0x22: //undocumented
Buslogic->DataReplyLeft = 2; case 0x28: //only for the Adaptec 154xC series
break; case 0x29: //only for the Adaptec 154xC series
case 0x86: //PCI only
case 0x29: case 0x95: //PCI only
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
Buslogic->Status |= STAT_INVCMD;
break; break;
} }
} }
@@ -1276,7 +1262,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
break; break;
case 2: case 2:
Buslogic->Irq = Val; //For Buslogic Buslogic->Interrupt = Val; //For Buslogic
break; break;
case 3: case 3:
@@ -1432,12 +1418,12 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
{ {
if (BuslogicRequests->Is24bit) if (BuslogicRequests->Is24bit)
{ {
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[Id].InitLength); U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].buffer_size);
pclog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); pclog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
} }
else else
{ {
BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[Id].InitLength; BuslogicRequests->CmdBlock.new.DataLength = SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].buffer_size;
pclog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); pclog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
} }
} }
@@ -1455,23 +1441,40 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
if (BuslogicRequests->RequestSenseBuffer) if (BuslogicRequests->RequestSenseBuffer)
BuslogicSenseBufferFree(BuslogicRequests, 1); BuslogicSenseBufferFree(BuslogicRequests, 1);
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK,
MBI_ERROR); MBI_ERROR);
} }
} }
else else
{ {
pclog("ID equal or higher than 7 not supported at the moment\n");
BuslogicDataBufferFree(BuslogicRequests); BuslogicDataBufferFree(BuslogicRequests);
if (BuslogicRequests->RequestSenseBuffer) if (BuslogicRequests->RequestSenseBuffer)
BuslogicSenseBufferFree(BuslogicRequests, 1); BuslogicSenseBufferFree(BuslogicRequests, 1);
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_INVALID_CCB, SCSI_STATUS_OK, BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK,
MBI_ERROR); MBI_ERROR);
} }
}
static void BuslogicSCSIRequestAbort(Buslogic_t *Buslogic, uint32_t CCBPointer)
{
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
CCBU CmdBlock;
uint8_t Id;
//Fetch data from the Command Control Block.
DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32));
BuslogicRequests->TargetID = Buslogic->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id;
Id = BuslogicRequests->TargetID;
//Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon.
if (Id < ELEMENTS(SCSIDevices))
{
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
}
} }
static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32) static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32)
@@ -1512,15 +1515,20 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic)
Buslogic->MailboxOutPosCur = (Buslogic->MailboxOutPosCur + 1) % Buslogic->MailboxCount; Buslogic->MailboxOutPosCur = (Buslogic->MailboxOutPosCur + 1) % Buslogic->MailboxCount;
} while (Mailbox32.u.out.ActionCode == MBO_FREE && MailboxOutCur != Buslogic->MailboxOutPosCur); } while (Mailbox32.u.out.ActionCode == MBO_FREE && MailboxOutCur != Buslogic->MailboxOutPosCur);
Buslogic->MailboxOutPosCur = MailboxOutCur;
uint8_t CmdStatus = MBO_FREE; uint8_t CmdStatus = MBO_FREE;
uint32_t CodeOffset = Buslogic->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode); uint32_t CodeOffset = Buslogic->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode);
DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus)); DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus));
if (Mailbox32.u.out.ActionCode == MBO_START) if (Mailbox32.u.out.ActionCode == MBO_START)
{
pclog("Start Mailbox Command\n");
BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer); BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer);
} if (Mailbox32.u.out.ActionCode == MBO_ABORT)
{
pclog("Abort Mailbox Command\n");
BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer);
}
} }
void BuslogicCommandCallback(void *p) void BuslogicCommandCallback(void *p)
@@ -1562,7 +1570,7 @@ void BuslogicClose(void *p)
device_t BuslogicDevice = device_t BuslogicDevice =
{ {
"Buslogic BT-540B", "Buslogic BT-542B",
0, 0,
BuslogicInit, BuslogicInit,
BuslogicClose, BuslogicClose,