📄 scsibus.cpp
字号:
////////////////////////////////////////////////////////////
//
// Module SCSIBUS.CPP
//
// ASPI class library
// SCSI interface class
//
// Project: A Programmer's Guide to SCSI
//
// Copyright (C) 1997, Brian Sawert
// Portions copyright (C) 1995, Larry Martin
// All rights reserved
//
////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "aspi.h"
#include "list.hpp"
#include "scsidev.hpp"
#include "scsibus.hpp"
ScsiInterface::ScsiInterface()
{
AspiIsOpen = 0;
NumDevices = 0;
NumAdapters = 0;
AdapterList = (AdapterInfo *) malloc(
sizeof(AdapterInfo) * MAX_HOST_ADAPTERS);
// paranoia
assert(AdapterList != NULL);
}
ScsiInterface::ScsiInterface(int build_device_list, int type, int scan_luns)
{
AspiIsOpen = 0;
NumAdapters = 0;
NumDevices = 0;
AdapterList = (AdapterInfo *) malloc(
sizeof(AdapterInfo) * MAX_HOST_ADAPTERS);
// paranoia
assert(AdapterList != NULL);
if (build_device_list)
BuildDeviceList(type,scan_luns);
}
ScsiInterface::~ScsiInterface()
{
ClearDeviceList();
free(AdapterList);
}
ScsiDevice *ScsiInterface::FindDevice(char *name)
{
ScsiDevice *p;
ItemListIterator i;
for ( p=(ScsiDevice *) i.GetFirst(&ScsiDevList); p; p=(ScsiDevice *)i.IterateToNext() )
{
if (strnicmp(name,p->GetName(),strlen(name)) == 0)
return p;
}
return NULL;
}
ScsiDevice *ScsiInterface::FindDevice(unsigned adapter, unsigned unit, unsigned lun)
{
ScsiDevice *p;
ItemListIterator i;
for ( p=(ScsiDevice *)i.GetFirst(&ScsiDevList); p; p=(ScsiDevice *)i.IterateToNext() )
{
if (adapter == (unsigned) p->GetAdapter() &&
unit == (unsigned) p->GetUnit() &&
lun== (unsigned) p->GetLun())
return p;
}
return NULL;
}
ScbError ScsiInterface::OpenAspiLayer()
{
int x;
x = aspi_GetSupportInfo();
if ( ((x >> 8) & 0xFF) != SS_COMP )
return Err_FailedInit;
NumAdapters = x & 0xFF;
AspiIsOpen = 1;
return Err_None;
}
unsigned ScsiInterface::GetNumAdapters()
{
if (!AspiIsOpen)
{
ScbError err;
err = OpenAspiLayer();
if (err)
return 0;
}
return NumAdapters;
}
ScbError ScsiInterface::AttachDevice(unsigned adapter, unsigned unit, unsigned lun, int type)
{
ScbError err;
ScsiCmdBlock scb;
ScsiDevice *dev;
if (!AspiIsOpen)
{
err = OpenAspiLayer();
if (err)
return err;
}
// Make sure we don't already have it attached
if ( (dev=FindDevice(adapter,unit,lun)) != NULL )
{
if ( (type == -1) || (type == dev->GetType()) )
return Err_None;
else
return Err_NoDevice; // Wrong type
}
// See if device really exists by getting its device type
// This should cut down on init time
scb.Init(SC_GET_DEV_TYPE,adapter,unit,lun);
err = scb.Execute(1000L);
if (err)
return err;
if ( (type != -1) && (type != scb.srb.gdt.SRB_DeviceType) )
{
// Wrong type
return Err_NoDevice;
}
dev = new ScsiDevice;
if (!dev)
return Err_OutOfMemory;
err = dev->Init(adapter,unit,lun);
if (err)
{
delete dev;
return err;
}
dev->SetName(dev->GetRealName());
if (!ScsiDevList.AddItem(dev))
{
delete dev;
return Err_OutOfMemory;
}
NumDevices++;
return Err_None;
}
void ScsiInterface::RemoveDevice(unsigned adapter, unsigned unit, unsigned lun)
{
ScsiDevice *dev;
dev = FindDevice(adapter,unit,lun);
if (dev)
{
ScsiDevList.RemoveItem(dev);
delete dev;
NumDevices--;
}
}
void ScsiInterface::ClearDeviceList()
{
ScsiDevice *dev;
// Destroy all allocated devices
while ( (dev=(ScsiDevice *)ScsiDevList.GetFirstItem()) != NULL )
{
ScsiDevList.RemoveItem(dev);
delete dev;
}
NumDevices = 0;
}
int ScsiInterface::BuildDeviceList(int type,int scan_luns)
{
unsigned adapter,unit,lun;
ScbError err;
if (!AspiIsOpen)
{
err = OpenAspiLayer();
if (err)
return 0;
}
// paranoia
assert(NumAdapters <= MAX_HOST_ADAPTERS);
for (adapter=0; adapter<NumAdapters; adapter++)
{
ScsiCmdBlock scb;
scb.Init(SC_HA_INQUIRY,adapter,0,0);
err = scb.Execute(3000);
if (!err)
{
unsigned host_unit = scb.srb.hai.HA_SCSI_ID;
unsigned max_units = scb.srb.hai.HA_Unique[3];
if (max_units == 0) // old ASPI managers?
max_units = 8;
// Save host adapter information
if (AdapterList)
{
char *s;
int i;
AdapterList[adapter].AdapterNum = adapter;
AdapterList[adapter].ScsiId = host_unit;
AdapterList[adapter].MaxUnits = max_units;
AdapterList[adapter].Residual =
scb.srb.hai.HA_Unique[2];
AdapterList[adapter].Align =
((WORD) scb.srb.hai.HA_Unique[0] |
(WORD) scb.srb.hai.HA_Unique[1] << 16);
// Save adapter manager ID
s = AdapterList[adapter].ManagerId;
for (i=0; i<sizeof(scb.srb.hai.HA_ManagerId); i++)
*s++ = scb.srb.hai.HA_ManagerId[i];
*s = '\0';
// Trim trailing spaces
while (--s > AdapterList[adapter].ManagerId)
{
if (isascii(*s) && isspace(*s))
*s = '\0';
else
break;
}
// Save adapter identifier
s = AdapterList[adapter].Identifier;
for (i=0; i<sizeof(scb.srb.hai.HA_Identifier); i++)
*s++ = scb.srb.hai.HA_Identifier[i];
*s = '\0';
// Trim trailing spaces
while (--s > AdapterList[adapter].Identifier)
{
if (isascii(*s) && isspace(*s))
*s = '\0';
else
break;
}
}
for (unit=0; unit<max_units; unit++)
{
if (unit != host_unit)
{
if (scan_luns)
{
for (lun=0; lun<8; lun++)
{
err = AttachDevice(adapter,unit,lun,type);
if (err)
break;
}
}
else
{
lun = 0;
AttachDevice(adapter,unit,lun,type);
}
}
}
}
}
return NumDevices;
}
unsigned ScsiInterface::GetNumDevices()
{
if (!AspiIsOpen)
{
ScbError err;
err = OpenAspiLayer();
if (err)
return 0;
}
return NumDevices;
}
ScsiDevice *ScsiInterface::GetDevice(unsigned n)
{
ItemListIterator i;
unsigned j;
i.GetFirst(&ScsiDevList); // Sets it up
for (j=0; j<n; j++)
{
if (i.IterateToNext() == NULL)
return NULL;
}
return (ScsiDevice *) i.GetCurrent();
}
ScbError ScsiInterface::RescanBus(int type, int scan_luns)
{
ScbError err;
ScsiCmdBlock scb;
unsigned count;
if (!AspiIsOpen)
{
err = OpenAspiLayer();
if (err)
return err;
}
// If we have a device list, clear it
if ( NumDevices > 0 )
{
ClearDeviceList();
}
// Loop through adapters
for (count = 0; count < NumAdapters; count++)
{
// Execute ASPI rescan command
scb.Init(SC_RESCAN_SCSI_BUS,count,0,0);
err = scb.Execute(1000L);
if (err)
return err;
}
// Strange things happen here.
// Under Win95, there is a delay while
// the O/S updates device maps.
// Under NT, this will not detect that
// devices have been removed.
// Rebuild device list
BuildDeviceList(type,scan_luns);
return Err_None;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -