inquiry page00h page80h page83h
This commit is contained in:
@@ -47,6 +47,7 @@ func NewSCSILu(device_uuid uint64, path string, online bool) (*api.SCSILu, error
|
||||
DeviceProtocol: sbc,
|
||||
Storage: backing,
|
||||
BlockShift: api.DefaultBlockShift,
|
||||
UUID: device_uuid,
|
||||
}
|
||||
|
||||
err = backing.Open(lu, backendPath)
|
||||
@@ -69,6 +70,7 @@ func NewLUN0() *api.SCSILu {
|
||||
DeviceProtocol: sbc,
|
||||
Storage: backing,
|
||||
BlockShift: api.DefaultBlockShift,
|
||||
UUID: 0,
|
||||
}
|
||||
|
||||
lu.Size = backing.Size(lu)
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/golang/glog"
|
||||
"github.com/gostor/gotgt/pkg/api"
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
"github.com/gostor/gotgt/pkg/version"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -53,8 +54,9 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||
lu.Attrs.Readonly = false
|
||||
lu.Attrs.SWP = false
|
||||
lu.Attrs.SenseFormat = false
|
||||
lu.Attrs.VendorID = "GOSTOR"
|
||||
lu.Attrs.ProductID = "VIRTUAL-DISK"
|
||||
lu.Attrs.VendorID = SCSI_VendorID
|
||||
lu.Attrs.ProductID = SCSI_ProductID
|
||||
lu.Attrs.ProductRev = version.SCSI_VERSION
|
||||
|
||||
/*
|
||||
SCSIID for PAGE83 T10 VENDOR IDENTIFICATION field
|
||||
@@ -73,10 +75,11 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||
*/
|
||||
lu.Attrs.SCSISN = " "
|
||||
|
||||
lu.Attrs.VersionDesction = []uint16{
|
||||
0x04C0, // SBC-3 no version claimed
|
||||
0x0960, // iSCSI
|
||||
0x0300, // SPC-3
|
||||
lu.Attrs.VersionDesction = [8]uint16{
|
||||
0x0320, // SBC-2 no version claimed
|
||||
0x0960, // iSCSI no version claimed
|
||||
0x0300, // SPC-3 no version claimed
|
||||
0x0060, // SAM-3 no version claimed
|
||||
}
|
||||
if lu.BlockShift == 0 {
|
||||
lu.BlockShift = api.DefaultBlockShift
|
||||
|
||||
348
pkg/scsi/spc.go
348
pkg/scsi/spc.go
@@ -42,15 +42,17 @@ import (
|
||||
*/
|
||||
|
||||
const (
|
||||
PIV_FCP = iota
|
||||
PIV_SPI
|
||||
PIV_S3P
|
||||
PIV_SBP
|
||||
PIV_SRP
|
||||
PIV_ISCSI
|
||||
PIV_SAS
|
||||
PIV_ADT
|
||||
PIV_ATA
|
||||
PIV_FCP = byte(0x00)
|
||||
PIV_SPI = byte(0x01)
|
||||
PIV_S3P = byte(0x02)
|
||||
PIV_SBP = byte(0x03)
|
||||
PIV_SRP = byte(0x04)
|
||||
PIV_ISCSI = byte(0x05)
|
||||
PIV_SAS = byte(0x06)
|
||||
PIV_ADT = byte(0x07)
|
||||
PIV_ATA = byte(0x08)
|
||||
PIV_USB = byte(0x09)
|
||||
PIV_SOP = byte(0x0A)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,12 +69,11 @@ const (
|
||||
* 2 - Designator field contains ASCII printable chars
|
||||
* 3 - Designaotor field contains UTF-8
|
||||
*/
|
||||
type CodeSet byte
|
||||
|
||||
var (
|
||||
INQ_CODE_BIN CodeSet = 1
|
||||
INQ_CODE_ASCII CodeSet = 2
|
||||
INQ_CODE_UTF8 CodeSet = 3
|
||||
const (
|
||||
INQ_CODE_BIN = byte(1)
|
||||
INQ_CODE_ASCII = byte(2)
|
||||
INQ_CODE_UTF8 = byte(3)
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -83,12 +84,11 @@ var (
|
||||
* 10b - Associated with SCSI Target device
|
||||
* 11b - Reserved
|
||||
*/
|
||||
type AssociationField byte
|
||||
|
||||
var (
|
||||
ASS_LU AssociationField = 0
|
||||
ASS_TGT_PORT AssociationField = 0x10
|
||||
ASS_TGT_DEV AssociationField = 0x20
|
||||
const (
|
||||
ASS_LU = byte(0x00)
|
||||
ASS_TGT_PORT = byte(0x01)
|
||||
ASS_TGT_DEV = byte(0x02)
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -112,10 +112,10 @@ var (
|
||||
*/
|
||||
|
||||
const (
|
||||
PQ_DEVICE_CONNECTED = byte(0x00)
|
||||
PQ_DEVICE_NOT_CONNECT = byte(0x01)
|
||||
PQ_RESERVED = byte(0x02)
|
||||
PQ_NOT_SUPPORT = byte(0x03)
|
||||
PQ_DEVICE_CONNECTED = byte(0x00 << 5)
|
||||
PQ_DEVICE_NOT_CONNECT = byte(0x01 << 5)
|
||||
PQ_RESERVED = byte(0x02 << 5)
|
||||
PQ_NOT_SUPPORT = byte(0x03 << 5)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -132,6 +132,19 @@ const (
|
||||
INQUIRY_NORM_ACA = byte(0x20)
|
||||
INQUIRY_HISUP = byte(0x10)
|
||||
INQUIRY_STANDARD_FORMAT = byte(0x02)
|
||||
|
||||
INQUIRY_ENCSERV = byte(0x40)
|
||||
INQUIRY_VS0 = byte(0x20)
|
||||
INQUIRY_MULTIP = byte(0x10)
|
||||
INQUIRY_ADDR16 = byte(0x01)
|
||||
|
||||
INQUIRY_WBUS16 = byte(0x20)
|
||||
INQUIRY_SYNC = byte(0x10)
|
||||
INQUIRY_CMDQUE = byte(0x02)
|
||||
INQUIRY_VS1 = byte(0x01)
|
||||
|
||||
INQUIRY_QAS = byte(0x02)
|
||||
INQUIRY_IUS = byte(0x01)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -167,6 +180,18 @@ const (
|
||||
DESG_SCSI
|
||||
)
|
||||
|
||||
const (
|
||||
NAA_IEEE_EXTD = byte(0x2)
|
||||
NAA_LOCAL = byte(0x3)
|
||||
NAA_IEEE_REGD = byte(0x5)
|
||||
NAA_IEEE_REGD_EXTD = byte(0x6)
|
||||
)
|
||||
|
||||
const (
|
||||
SCSI_VendorID = "GOSTOR"
|
||||
SCSI_ProductID = "GOTGT-VDISK"
|
||||
)
|
||||
|
||||
func SPCIllegalOp(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
return api.SAMStatGood
|
||||
}
|
||||
@@ -185,90 +210,251 @@ func SPCLuOnline(lu *api.SCSILu) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func InquiryPage0x00(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
descBuf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
pageLength uint16 = 0
|
||||
)
|
||||
|
||||
descBuf.WriteByte(0x00)
|
||||
descBuf.WriteByte(0x80)
|
||||
descBuf.WriteByte(0x83)
|
||||
/*
|
||||
TODO:
|
||||
descBuf.WriteByte(0x86)
|
||||
descBuf.WriteByte(0xB0)
|
||||
descBuf.WriteByte(0xB2)
|
||||
*/
|
||||
|
||||
data = descBuf.Bytes()
|
||||
pageLength = uint16(len(data))
|
||||
|
||||
//byte 0
|
||||
if cmd.Device.Attrs.Online {
|
||||
buf.WriteByte(PQ_DEVICE_CONNECTED | byte(cmd.Device.Attrs.DeviceType))
|
||||
} else {
|
||||
buf.WriteByte(PQ_DEVICE_NOT_CONNECT | byte(cmd.Device.Attrs.DeviceType))
|
||||
}
|
||||
//byte 1
|
||||
//PAGE CODE
|
||||
buf.WriteByte(0x00)
|
||||
//PAGE LENGTH
|
||||
binary.Write(buf, binary.BigEndian, pageLength)
|
||||
buf.Write(data)
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
func InquiryPage0x80(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
descBuf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
pageLength uint16 = 0
|
||||
)
|
||||
|
||||
descBuf.WriteByte(0x20)
|
||||
descBuf.WriteByte(0x20)
|
||||
descBuf.WriteByte(0x20)
|
||||
descBuf.WriteByte(0x20)
|
||||
|
||||
data = descBuf.Bytes()
|
||||
pageLength = uint16(len(data))
|
||||
|
||||
//byte 0
|
||||
if cmd.Device.Attrs.Online {
|
||||
buf.WriteByte(PQ_DEVICE_CONNECTED | byte(cmd.Device.Attrs.DeviceType))
|
||||
} else {
|
||||
buf.WriteByte(PQ_DEVICE_NOT_CONNECT | byte(cmd.Device.Attrs.DeviceType))
|
||||
}
|
||||
//byte 1
|
||||
//PAGE CODE
|
||||
buf.WriteByte(0x80)
|
||||
//PAGE LENGTH
|
||||
binary.Write(buf, binary.BigEndian, pageLength)
|
||||
buf.Write(data)
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
descBuf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
pageLength uint16 = 0
|
||||
)
|
||||
|
||||
//DESCRIPTOR 1 TARGET NAME
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_ASCII)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_VENDOR)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(byte(len([]byte(cmd.Target.Name))))
|
||||
//target name
|
||||
descBuf.Write([]byte(cmd.Target.Name))
|
||||
|
||||
//DESCRIPTOR 2 NNA Locally
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_NAA)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
//NNA
|
||||
binary.Write(descBuf, binary.BigEndian, (cmd.Device.UUID | (uint64(NAA_LOCAL) << 60)))
|
||||
|
||||
//TODO: Target Port Group(0x05), Relative Target port identifier(0x04)
|
||||
|
||||
/*
|
||||
//DESCRIPTOR 3 TPG
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_REL_TGT_PORT)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
//TPG
|
||||
binary.Write(descBuf, binary.BigEndian,)
|
||||
|
||||
//DESCRIPTOR 4 RTPI
|
||||
descBuf.WriteByte((PIV_ISCSI << 4) | INQ_CODE_BIN)
|
||||
descBuf.WriteByte(0x80 | ASS_TGT_PORT | DESG_NAA)
|
||||
descBuf.WriteByte(0x00)
|
||||
//length
|
||||
descBuf.WriteByte(0x08)
|
||||
//RTPGI
|
||||
binary.Write(descBuf, binary.BigEndian,)
|
||||
*/
|
||||
|
||||
data = descBuf.Bytes()
|
||||
pageLength = uint16(len(data))
|
||||
|
||||
//byte 0
|
||||
if cmd.Device.Attrs.Online {
|
||||
buf.WriteByte(PQ_DEVICE_CONNECTED | byte(cmd.Device.Attrs.DeviceType))
|
||||
} else {
|
||||
buf.WriteByte(PQ_DEVICE_NOT_CONNECT | byte(cmd.Device.Attrs.DeviceType))
|
||||
}
|
||||
//byte 1
|
||||
//PAGE CODE
|
||||
buf.WriteByte(0x83)
|
||||
//PAGE LENGTH
|
||||
binary.Write(buf, binary.BigEndian, pageLength)
|
||||
buf.Write(data)
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
b byte = 0x75
|
||||
allocationLength uint16
|
||||
pageLength uint16
|
||||
additionLength byte
|
||||
buf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
addBuf = &bytes.Buffer{}
|
||||
addBufData []byte = []byte{}
|
||||
//b byte = 0x75
|
||||
scb []byte = cmd.SCB.Bytes()
|
||||
pcode byte = scb[2]
|
||||
evpd bool = false
|
||||
|
||||
vendorID = make([]byte, 8)
|
||||
productID = make([]byte, 16)
|
||||
productRev = make([]byte, 4)
|
||||
)
|
||||
|
||||
allocationLength = util.GetUnalignedUint16(scb[3:5])
|
||||
|
||||
if scb[1]&0x01 > 0 {
|
||||
evpd = true
|
||||
}
|
||||
|
||||
if cmd.Device == nil {
|
||||
b = (uint8(0) & 0x7) << 5
|
||||
b |= uint8(0) & 0x1f
|
||||
goto sense
|
||||
}
|
||||
|
||||
if cmd.Device.Attrs.Online {
|
||||
b = (byte(PQ_DEVICE_CONNECTED) << 5) | byte(cmd.Device.Attrs.DeviceType)
|
||||
} else {
|
||||
b = (byte(PQ_DEVICE_NOT_CONNECT) << 5) | byte(cmd.Device.Attrs.DeviceType)
|
||||
}
|
||||
|
||||
if evpd {
|
||||
if pcode == 0x0 {
|
||||
buf.WriteByte(b)
|
||||
b = 0
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(b)
|
||||
} else if pcode == 0xb0 {
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(0xb0)
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x3c)
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x80)
|
||||
switch pcode {
|
||||
case 0x00:
|
||||
buf, pageLength = InquiryPage0x00(host, cmd)
|
||||
|
||||
for i := 0; i < 58; i++ {
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
case 0x80:
|
||||
buf, pageLength = InquiryPage0x80(host, cmd)
|
||||
|
||||
case 0x83:
|
||||
buf, pageLength = InquiryPage0x83(host, cmd)
|
||||
|
||||
default:
|
||||
goto sense
|
||||
}
|
||||
data = buf.Bytes()
|
||||
if allocationLength < pageLength {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
||||
} else {
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(0xb0)
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x00)
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:])
|
||||
}
|
||||
} else {
|
||||
buf.WriteByte(b)
|
||||
//byte 5
|
||||
//SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
|
||||
addBuf.WriteByte(0x00)
|
||||
//byte 6
|
||||
//ENCSERV(0) VS(0) MULTIP(0) ADDR16(0)
|
||||
addBuf.WriteByte(0x00)
|
||||
//byte 7
|
||||
//WBUS16(0) SYNC(0) CMDQUE(1) VS1(0)
|
||||
addBuf.WriteByte(INQUIRY_CMDQUE)
|
||||
|
||||
copy(vendorID, []byte(cmd.Device.Attrs.VendorID))
|
||||
addBuf.Write(vendorID)
|
||||
|
||||
copy(productID, []byte(cmd.Device.Attrs.ProductID))
|
||||
addBuf.Write(productID)
|
||||
|
||||
copy(productRev, []byte(cmd.Device.Attrs.ProductRev))
|
||||
addBuf.Write(productRev)
|
||||
//Vendor specific(20 bytes)
|
||||
for i := 0; i < 20; i++ {
|
||||
addBuf.WriteByte(0x00)
|
||||
}
|
||||
//byte 56
|
||||
addBuf.WriteByte(0x00)
|
||||
//byte 57
|
||||
addBuf.WriteByte(0x00)
|
||||
//VERSION DESCRIPTOR 1 ~ 8
|
||||
binary.Write(addBuf, binary.BigEndian, cmd.Device.Attrs.VersionDesction)
|
||||
|
||||
addBufData = addBuf.Bytes()
|
||||
additionLength = byte(len(addBufData))
|
||||
|
||||
//Write header
|
||||
//byte 0
|
||||
//PERIPHERAL QUALIFIER, PERIPHERAL DEVICE TYPE
|
||||
if cmd.Device.Attrs.Online {
|
||||
buf.WriteByte(PQ_DEVICE_CONNECTED | byte(cmd.Device.Attrs.DeviceType))
|
||||
} else {
|
||||
buf.WriteByte(PQ_DEVICE_NOT_CONNECT | byte(cmd.Device.Attrs.DeviceType))
|
||||
}
|
||||
// byte 1
|
||||
// RMB(0) LU_CONG(0)
|
||||
buf.WriteByte(0x00)
|
||||
// version byte
|
||||
// byte 2
|
||||
// VERSION
|
||||
buf.WriteByte(VERSION_WITHDRAW_SPC3)
|
||||
|
||||
// byte 3
|
||||
// Reserved, Reserved, NORMACA, HISUP, RESPONSE DATA FORMAT
|
||||
buf.WriteByte(INQUIRY_HISUP | INQUIRY_STANDARD_FORMAT)
|
||||
// byte 4
|
||||
// ADDITIONAL LENGTH
|
||||
buf.WriteByte(0x00)
|
||||
// byte 5
|
||||
/*
|
||||
* SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
|
||||
*/
|
||||
buf.WriteByte(0x00)
|
||||
// byte 6
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x02)
|
||||
buf.Write([]byte{'1', '1', 'c', 'a', 'n', 's'})
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(0x00)
|
||||
buf.Write([]byte{'c', 'o', 'f', 'f', 'e', 'e'})
|
||||
for i := 0; i < 10; i++ {
|
||||
buf.WriteByte(0x00)
|
||||
buf.WriteByte(additionLength)
|
||||
|
||||
buf.Write(addBufData)
|
||||
data = buf.Bytes()
|
||||
if allocationLength < uint16(additionLength) {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
||||
} else {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:])
|
||||
}
|
||||
buf.Write([]byte{'1', '.', '0'})
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
data = buf.Bytes()
|
||||
data[4] = byte(len(data) - 4)
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
||||
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
@@ -302,7 +488,7 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
buf.Write(util.MarshalUint32(availLength))
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
|
||||
// Skip through to byte 8, Reserved
|
||||
// Skip through to byte 4, Reserved
|
||||
for i := 0; i < 4; i++ {
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user