init commit for spc/sbc
This commit is contained in:
277
pkg/scsi/spc.go
277
pkg/scsi/spc.go
@@ -17,6 +17,14 @@ limitations under the License.
|
||||
// SCSI primary command processing
|
||||
package scsi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
)
|
||||
|
||||
/*
|
||||
* Protocol Identifier Values
|
||||
*
|
||||
@@ -100,78 +108,275 @@ const (
|
||||
DESG_SCSI
|
||||
)
|
||||
|
||||
func SPCIllegalOp(host int, cmd *SCSICommand) error {
|
||||
func SPCIllegalOp(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCLuOffline(lu *SCSILu) error {
|
||||
lu.Attrs.Online = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func SPCInquiry(host int, cmd *SCSICommand) error {
|
||||
func SPCLuOnline(lu *SCSILu) error {
|
||||
if luPreventRemoval(lu) {
|
||||
return fmt.Errorf("lu(%s) prevent removal", lu.Lun)
|
||||
}
|
||||
|
||||
lu.Attrs.Online = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func SPCReportLuns(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCInquiry(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCStartStop(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCReportLuns(host int, cmd *SCSICommand) SAMStat {
|
||||
var (
|
||||
remainLength uint32
|
||||
actualLength uint32 = 8
|
||||
availLength uint32 = 0
|
||||
allocationLength uint32
|
||||
data *bytes.Buffer
|
||||
scb *bytes.Buffer = cmd.SCB
|
||||
)
|
||||
// Get Allocation Length
|
||||
allocationLength = util.GetUnalignedUint32(scb.Bytes()[6:10])
|
||||
if allocationLength < 16 {
|
||||
goto sense
|
||||
}
|
||||
if cmd.InSDBBuffer.Length < allocationLength {
|
||||
goto sense
|
||||
}
|
||||
data = cmd.InSDBBuffer.Buffer
|
||||
remainLength = allocationLength - 8
|
||||
availLength = 8 * uint32(len(cmd.Target.Devices))
|
||||
binary.Write(data, binary.BigEndian, availLength)
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
// Skip through to byte 8, Reserved
|
||||
for i := 0; i < 4; i++ {
|
||||
data.WriteByte(0x00)
|
||||
}
|
||||
|
||||
for _, lu := range cmd.Target.Devices {
|
||||
if remainLength > 0 {
|
||||
lun := lu.Lun
|
||||
if lun > 0xff {
|
||||
lun = 0x1 << 30
|
||||
} else {
|
||||
lun = 0
|
||||
}
|
||||
lun = (0x3fff & lun) << 16
|
||||
lun = uint64(lun << 32)
|
||||
binary.Write(data, binary.BigEndian, lun)
|
||||
remainLength -= 8
|
||||
}
|
||||
}
|
||||
return SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCTestUnit(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCStartStop(host int, cmd *SCSICommand) SAMStat {
|
||||
var (
|
||||
pwrcnd, loej, start byte
|
||||
)
|
||||
if err := deviceReserve(cmd); err != nil {
|
||||
return SAMStatReservationConflict
|
||||
}
|
||||
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
scb := cmd.SCB.Bytes()
|
||||
pwrcnd = scb[4] & 0xf0
|
||||
if pwrcnd != 0 {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
loej = scb[4] & 0x02
|
||||
start = scb[4] & 0x01
|
||||
|
||||
if loej != 0 && start == 0 && cmd.Device.Attrs.Removable {
|
||||
if luPreventRemoval(cmd.Device) {
|
||||
if cmd.Device.Attrs.Online {
|
||||
// online == media is present
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_MEDIUM_REMOVAL_PREVENTED)
|
||||
} else {
|
||||
// !online == media is not present
|
||||
BuildSenseData(cmd, NOT_READY, ASC_MEDIUM_REMOVAL_PREVENTED)
|
||||
}
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
SPCLuOffline(cmd.Device)
|
||||
}
|
||||
if loej != 0 && start != 0 && cmd.Device.Attrs.Removable {
|
||||
SPCLuOnline(cmd.Device)
|
||||
}
|
||||
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPreventAllowMediaRemoval(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCTestUnit(host int, cmd *SCSICommand) SAMStat {
|
||||
if err := deviceReserve(cmd); err != nil {
|
||||
return SAMStatReservationConflict
|
||||
}
|
||||
if cmd.Device.Attrs.Online {
|
||||
return SAMStatGood
|
||||
}
|
||||
if cmd.Device.Attrs.Removable {
|
||||
BuildSenseData(cmd, NOT_READY, ASC_MEDIUM_NOT_PRESENT)
|
||||
} else {
|
||||
BuildSenseData(cmd, NOT_READY, ASC_BECOMING_READY)
|
||||
}
|
||||
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCModeSense(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPreventAllowMediaRemoval(host int, cmd *SCSICommand) SAMStat {
|
||||
if err := deviceReserve(cmd); err != nil {
|
||||
return SAMStatReservationConflict
|
||||
}
|
||||
// PREVENT_MASK = 0x03
|
||||
cmd.ITNexusLuInfo.Prevent = int(cmd.SCB.Bytes()[4] & 0x03)
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCServiceAction(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
// SPCModeSense Implement SCSI op MODE SENSE(6) and MODE SENSE(10)
|
||||
// Reference : SPC4r11
|
||||
// 6.11 - MODE SENSE(6)
|
||||
// 6.12 - MODE SENSE(10)
|
||||
func SPCModeSense(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRReadKeys(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCSendDiagnostics(host int, cmd *SCSICommand) SAMStat {
|
||||
// we only support SELF-TEST==1
|
||||
if cmd.SCB.Bytes()[1]&0x04 == 0 {
|
||||
goto sense
|
||||
}
|
||||
|
||||
return SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCPRReadReservation(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
// This is useful for the various commands using the SERVICE ACTION format.
|
||||
func SPCServiceAction(host int, cmd *SCSICommand) SAMStat {
|
||||
// TODO
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRReportCapabilities(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRReadKeys(host int, cmd *SCSICommand) SAMStat {
|
||||
allocationLength := util.GetUnalignedUint32(cmd.SCB.Bytes()[7:9])
|
||||
if allocationLength < 8 {
|
||||
goto sense
|
||||
}
|
||||
if cmd.InSDBBuffer.Length < allocationLength {
|
||||
goto sense
|
||||
}
|
||||
// TODO
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCPRRegister(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRReadReservation(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRReserve(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRReportCapabilities(host int, cmd *SCSICommand) SAMStat {
|
||||
var (
|
||||
buf []byte = make([]byte, 8)
|
||||
availLength uint32 = 8
|
||||
actualLength uint32 = 0
|
||||
data *bytes.Buffer = cmd.InSDBBuffer.Buffer
|
||||
)
|
||||
allocationLength := util.GetUnalignedUint32(cmd.SCB.Bytes()[7:9])
|
||||
if allocationLength < 8 {
|
||||
goto sense
|
||||
}
|
||||
if cmd.InSDBBuffer.Length < allocationLength {
|
||||
goto sense
|
||||
}
|
||||
binary.BigEndian.PutUint16(buf[0:2], uint16(8))
|
||||
// Persistent Reservation Type Mask format
|
||||
// Type Mask Valid (TMV)
|
||||
buf[3] |= 0x80
|
||||
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
||||
buf[4] |= 0x80
|
||||
// PR_TYPE_EXCLUSIVE_ACCESS_REGONLY
|
||||
buf[4] |= 0x40
|
||||
// PR_TYPE_WRITE_EXCLUSIVE_REGONLY
|
||||
buf[4] |= 0x20
|
||||
// PR_TYPE_EXCLUSIVE_ACCESS
|
||||
buf[4] |= 0x08
|
||||
// PR_TYPE_WRITE_EXCLUSIVE
|
||||
buf[4] |= 0x02
|
||||
// PR_TYPE_EXCLUSIVE_ACCESS_ALLREG
|
||||
buf[5] |= 0x01
|
||||
|
||||
if err := binary.Write(data, binary.BigEndian, buf); err != nil {
|
||||
goto sense
|
||||
} else {
|
||||
actualLength = availLength
|
||||
}
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
return SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
BuildSenseData(cmd, ILLEGAL_REQUEST, ASC_INVALID_FIELD_IN_CDB)
|
||||
return SAMStatCheckCondition
|
||||
}
|
||||
|
||||
func SPCPRRelease(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRRegister(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRClear(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRReserve(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRPreempt(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRRelease(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCPRRegisterAndMove(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRClear(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCRequestSense(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRPreempt(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCSendDiagnostics(host int, cmd *SCSICommand) error {
|
||||
return nil
|
||||
func SPCPRRegisterAndMove(host int, cmd *SCSICommand) SAMStat {
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
func SPCRequestSense(host int, cmd *SCSICommand) SAMStat {
|
||||
var (
|
||||
allocationLength uint32
|
||||
actualLength uint32
|
||||
)
|
||||
|
||||
allocationLength = util.GetUnalignedUint32(cmd.SCB.Bytes()[4:8])
|
||||
if allocationLength > cmd.InSDBBuffer.Length {
|
||||
allocationLength = cmd.InSDBBuffer.Length
|
||||
}
|
||||
BuildSenseData(cmd, NO_SENSE, NO_ADDITIONAL_SENSE)
|
||||
if cmd.SenseLength < allocationLength {
|
||||
actualLength = cmd.SenseLength
|
||||
} else {
|
||||
actualLength = allocationLength
|
||||
}
|
||||
binary.Write(cmd.InSDBBuffer.Buffer, binary.BigEndian, cmd.SenseBuffer.Bytes()[0:actualLength])
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
|
||||
// reset sense buffer in cmnd
|
||||
cmd.SenseBuffer = &bytes.Buffer{}
|
||||
cmd.SenseLength = 0
|
||||
|
||||
return SAMStatGood
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user