init commit for spc/sbc

This commit is contained in:
Lei Xue
2015-12-27 20:44:54 +08:00
parent e7366b4ed1
commit d770eb33ac
11 changed files with 788 additions and 124 deletions

View File

@@ -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
}