128
src/buslogic.c
128
src/buslogic.c
@@ -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,
|
||||||
|
Reference in New Issue
Block a user