Merge pull request #60 from carmark/mode_sense
update mode sense command
This commit is contained in:
@@ -43,7 +43,9 @@ script:
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.MandatoryVPDSBC iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.SupportedVPD iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.VersionDescriptors iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.EVPD iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Mandatory iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.ModeSense6 iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.NoMedia iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Prefetch10 iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
- ./test-tool/iscsi-test-cu -d -A --test=ALL.Prefetch16 iscsi://127.0.0.1:3260/${TARGET}/0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016 The GoStor Authors All rights reserved.
|
||||
Copyright 2017 The GoStor Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -148,7 +148,7 @@ type SCSIDataBuffer struct {
|
||||
Buffer *bytes.Buffer
|
||||
Length uint32
|
||||
TransferLength uint32
|
||||
Resid int32
|
||||
Resid uint32
|
||||
}
|
||||
|
||||
type SCSICommandState uint64
|
||||
@@ -364,6 +364,7 @@ type ModePage struct {
|
||||
PageCode uint8
|
||||
// Sub page code
|
||||
SubPageCode uint8
|
||||
Size uint8
|
||||
// Rest of mode page info
|
||||
Data []byte
|
||||
}
|
||||
@@ -378,17 +379,18 @@ type SCSIReservation struct {
|
||||
}
|
||||
|
||||
type SCSILu struct {
|
||||
Address uint64
|
||||
Size uint64
|
||||
UUID uint64
|
||||
Path string
|
||||
BsoFlags int
|
||||
BlockShift uint
|
||||
ReserveID uuid.UUID
|
||||
Attrs SCSILuPhyAttribute
|
||||
ModePages []ModePage
|
||||
Storage BackingStore
|
||||
DeviceProtocol SCSIDeviceProtocol
|
||||
Address uint64
|
||||
Size uint64
|
||||
UUID uint64
|
||||
Path string
|
||||
BsoFlags int
|
||||
BlockShift uint
|
||||
ReserveID uuid.UUID
|
||||
Attrs SCSILuPhyAttribute
|
||||
ModePages []ModePage
|
||||
Storage BackingStore
|
||||
DeviceProtocol SCSIDeviceProtocol
|
||||
ModeBlockDescriptor []byte
|
||||
|
||||
PerformCommand CommandFunc
|
||||
FinishCommand func(*SCSITarget, *SCSICommand)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
)
|
||||
|
||||
@@ -94,6 +95,7 @@ type ISCSICommand struct {
|
||||
TaskTag uint32
|
||||
ExpCmdSN, MaxCmdSN uint32
|
||||
AHSLen int
|
||||
Resid uint32
|
||||
|
||||
// Connection ID.
|
||||
ConnID uint16
|
||||
@@ -185,7 +187,7 @@ func (m *ISCSICommand) String() string {
|
||||
s = append(s, fmt.Sprintf("Next Stage = %v", m.NSG))
|
||||
s = append(s, fmt.Sprintf("Status Class = %d", m.StatusClass))
|
||||
s = append(s, fmt.Sprintf("Status Detail = %d", m.StatusDetail))
|
||||
case OpSCSICmd, OpSCSIOut:
|
||||
case OpSCSICmd, OpSCSIOut, OpSCSIIn:
|
||||
s = append(s, fmt.Sprintf("LUN = %d", m.LUN))
|
||||
s = append(s, fmt.Sprintf("ExpectedDataLen = %d", m.ExpectedDataLen))
|
||||
s = append(s, fmt.Sprintf("CmdSN = %d", m.CmdSN))
|
||||
@@ -278,7 +280,15 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte {
|
||||
// rfc7143 11.4
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte(byte(OpSCSIResp))
|
||||
buf.WriteByte(0x80) // 11.4.1 = wtf
|
||||
var flag byte = 0x80
|
||||
if m.Resid > 0 {
|
||||
if m.Resid > m.ExpectedDataLen {
|
||||
flag |= 0x04
|
||||
} else {
|
||||
flag |= 0x02
|
||||
}
|
||||
}
|
||||
buf.WriteByte(flag)
|
||||
buf.WriteByte(byte(m.SCSIResponse))
|
||||
buf.WriteByte(byte(m.Status))
|
||||
|
||||
@@ -295,9 +305,10 @@ func (m *ISCSICommand) scsiCmdRespBytes() []byte {
|
||||
buf.Write(util.MarshalUint64(uint64(m.StatSN))[4:])
|
||||
buf.Write(util.MarshalUint64(uint64(m.ExpCmdSN))[4:])
|
||||
buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:])
|
||||
for i := 0; i < 3*4; i++ {
|
||||
for i := 0; i < 2*4; i++ {
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
buf.Write(util.MarshalUint64(uint64(m.Resid))[4:])
|
||||
buf.Write(m.RawData)
|
||||
dl := len(m.RawData)
|
||||
for dl%4 > 0 {
|
||||
@@ -312,20 +323,27 @@ func (m *ISCSICommand) dataInBytes() []byte {
|
||||
// rfc7143 11.7
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte(byte(OpSCSIIn))
|
||||
var b byte
|
||||
b = 0x0
|
||||
var flag byte
|
||||
if m.FinalInSeq || m.Final == true {
|
||||
b |= 0x80
|
||||
flag |= 0x80
|
||||
}
|
||||
if m.HasStatus && m.Final == true {
|
||||
b |= 0x01
|
||||
flag |= 0x01
|
||||
}
|
||||
buf.WriteByte(b)
|
||||
log.Debugf("resid: %v, ExpectedDataLen: %v", m.Resid, m.ExpectedDataLen)
|
||||
if m.Resid > 0 {
|
||||
if m.Resid > m.ExpectedDataLen {
|
||||
flag |= 0x04
|
||||
} else {
|
||||
flag |= 0x02
|
||||
}
|
||||
}
|
||||
buf.WriteByte(flag)
|
||||
buf.WriteByte(0x00)
|
||||
if m.HasStatus && m.Final == true {
|
||||
b = byte(m.Status)
|
||||
flag = byte(m.Status)
|
||||
}
|
||||
buf.WriteByte(b)
|
||||
buf.WriteByte(flag)
|
||||
|
||||
buf.WriteByte(0x00) // 4
|
||||
|
||||
@@ -344,9 +362,7 @@ func (m *ISCSICommand) dataInBytes() []byte {
|
||||
buf.Write(util.MarshalUint64(uint64(m.MaxCmdSN))[4:])
|
||||
buf.Write(util.MarshalUint64(uint64(m.DataSN))[4:])
|
||||
buf.Write(util.MarshalUint64(uint64(m.BufferOffset))[4:])
|
||||
for i := 0; i < 4; i++ {
|
||||
buf.WriteByte(0x00)
|
||||
}
|
||||
buf.Write(util.MarshalUint64(uint64(m.Resid))[4:])
|
||||
buf.Write(m.RawData[m.BufferOffset : m.BufferOffset+uint32(m.DataLen)])
|
||||
dl := m.DataLen
|
||||
for dl%4 > 0 {
|
||||
|
||||
@@ -155,10 +155,11 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
|
||||
task = conn.rxTask
|
||||
}
|
||||
resp := &ISCSICommand{
|
||||
StatSN: conn.req.ExpStatSN,
|
||||
TaskTag: conn.req.TaskTag,
|
||||
ExpCmdSN: conn.session.ExpCmdSN,
|
||||
MaxCmdSN: conn.session.ExpCmdSN + conn.session.MaxQueueCommand,
|
||||
StatSN: conn.req.ExpStatSN,
|
||||
TaskTag: conn.req.TaskTag,
|
||||
ExpCmdSN: conn.session.ExpCmdSN,
|
||||
MaxCmdSN: conn.session.ExpCmdSN + conn.session.MaxQueueCommand,
|
||||
ExpectedDataLen: conn.req.ExpectedDataLen,
|
||||
}
|
||||
switch oc {
|
||||
case OpReady:
|
||||
@@ -182,6 +183,7 @@ func (conn *iscsiConnection) buildRespPackage(oc OpCode, task *iscsiTask) error
|
||||
resp.RawData = append(length[2:4], scmd.SenseBuffer.Bytes()...)
|
||||
} else if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite {
|
||||
if scmd.InSDBBuffer.Buffer != nil {
|
||||
resp.Resid = scmd.InSDBBuffer.Resid
|
||||
buf := scmd.InSDBBuffer.Buffer.Bytes()
|
||||
resp.RawData = buf
|
||||
} else {
|
||||
|
||||
@@ -313,8 +313,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
||||
default:
|
||||
iscsiExecReject(conn)
|
||||
}
|
||||
log.Debugf("connection state is %v", conn.state)
|
||||
log.Debugf("%#v", conn.resp.String())
|
||||
log.Debugf("connection state is %v", conn.State())
|
||||
s.handler(DATAOUT, conn)
|
||||
}
|
||||
}
|
||||
@@ -476,9 +475,7 @@ SendRemainingData:
|
||||
switch conn.txIOState {
|
||||
case IOSTATE_TX_BHS:
|
||||
log.Debug("ready to write response")
|
||||
log.Debugf("%s", resp.String())
|
||||
log.Debugf("length of RawData is %d", len(resp.RawData))
|
||||
log.Debugf("length of resp is %d", len(resp.Bytes()))
|
||||
log.Debugf("response is %s", resp.String())
|
||||
if l, err := conn.write(resp.Bytes()); err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
@@ -678,7 +675,7 @@ func (s *ISCSITargetDriver) iscsiTaskQueueHandler(task *iscsiTask) error {
|
||||
return s.iscsiExecTask(task)
|
||||
}
|
||||
cmdsn := cmd.CmdSN
|
||||
log.Debugf("CmdSN of command is %d, ExpCmdSN of session is %d", cmdsn, sess.ExpCmdSN)
|
||||
log.Debugf("CmdSN of command is %d", cmdsn)
|
||||
if cmdsn == sess.ExpCmdSN {
|
||||
retry:
|
||||
cmdsn += 1
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
/*
|
||||
Copyright 2017 The GoStor Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package iscsit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
// log "github.com/Sirupsen/logrus"
|
||||
"github.com/gostor/gotgt/pkg/util"
|
||||
)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package scsi
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
@@ -67,6 +68,8 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||
lu.Attrs.VendorID = SCSIVendorID
|
||||
lu.Attrs.ProductID = SCSIProductID
|
||||
lu.Attrs.ProductRev = version.SCSIVersion
|
||||
lu.Attrs.SCSIID = fmt.Sprintf("gotgt-scsi-%d%d", 0, lu.UUID)
|
||||
lu.Attrs.SCSISN = fmt.Sprintf("gotgt-beaf-%d%d", 0, lu.UUID)
|
||||
|
||||
/*
|
||||
SCSIID for PAGE83 T10 VENDOR IDENTIFICATION field
|
||||
@@ -96,20 +99,25 @@ func (sbc SBCSCSIDeviceProtocol) InitLu(lu *api.SCSILu) error {
|
||||
}
|
||||
pages := []api.ModePage{}
|
||||
// Vendor uniq - However most apps seem to call for mode page 0
|
||||
pages = append(pages, api.ModePage{0, 0, []byte{}})
|
||||
//pages = append(pages, api.ModePage{0, 0, []byte{}})
|
||||
// Disconnect page
|
||||
pages = append(pages, api.ModePage{2, 0, []byte{0x80, 0x80, 0, 0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
pages = append(pages, api.ModePage{2, 0, 14, []byte{0x80, 0x80, 0, 0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
// Caching Page
|
||||
pages = append(pages, api.ModePage{8, 0, []byte{0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}})
|
||||
pages = append(pages, api.ModePage{8, 0, 18, []byte{0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
|
||||
// Control page
|
||||
pages = append(pages, api.ModePage{0x0a, 0, []byte{2, 0x10, 0, 0, 0, 0, 0, 0, 2, 0}})
|
||||
pages = append(pages, api.ModePage{0x0a, 0, 10, []byte{2, 0x10, 0, 0, 0, 0, 0, 0, 2, 0, 0x08, 0, 0, 0, 0, 0, 0, 0}})
|
||||
|
||||
// Control Extensions mode page: TCMOS:1
|
||||
pages = append(pages, api.ModePage{0x0a, 1, []byte{0x04, 0x00, 0x00}})
|
||||
pages = append(pages, api.ModePage{0x0a, 1, 0x1c, []byte{0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
// Informational Exceptions Control page
|
||||
pages = append(pages, api.ModePage{0x1c, 0, []byte{8, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
pages = append(pages, api.ModePage{0x1c, 0, 10, []byte{8, 0, 0, 0, 0, 0, 0, 0, 0, 0}})
|
||||
lu.ModePages = pages
|
||||
mbd := util.MarshalUint32(uint32(0xffffffff))
|
||||
if size := lu.Size >> lu.BlockShift; size>>32 == 0 {
|
||||
mbd = util.MarshalUint32(uint32(size))
|
||||
}
|
||||
lu.ModeBlockDescriptor = append(mbd, util.MarshalUint32(uint32(1<<lu.BlockShift))...)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@ func BuildSenseData(cmd *api.SCSICommand, key byte, asc SCSISubError) {
|
||||
}
|
||||
if ok {
|
||||
if int64(len(senseBuffer.Bytes())) > inBufLen {
|
||||
log.Warnf("sense buffer is bigger than in buffer")
|
||||
senseBuffer.Truncate(int(inBufLen))
|
||||
}
|
||||
} else {
|
||||
|
||||
145
pkg/scsi/spc.go
145
pkg/scsi/spc.go
@@ -86,31 +86,23 @@ func InquiryPage0x00(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
func InquiryPage0x80(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
var (
|
||||
buf = &bytes.Buffer{}
|
||||
descBuf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
pageLength uint16 = 0
|
||||
pageLength uint16 = 36
|
||||
scsisn = make([]byte, pageLength)
|
||||
)
|
||||
|
||||
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
|
||||
//byte 1: PAGE CODE
|
||||
buf.WriteByte(0x80)
|
||||
//PAGE LENGTH
|
||||
binary.Write(buf, binary.BigEndian, pageLength)
|
||||
buf.Write(data)
|
||||
//byte 2-3: PAGE LENGTH
|
||||
buf.WriteByte(uint8(pageLength >> 8))
|
||||
buf.WriteByte(uint8(pageLength & 0xff))
|
||||
copy(scsisn, []byte(fmt.Sprintf("gotgt-%-36v", cmd.Device.UUID)))
|
||||
buf.Write(scsisn)
|
||||
return buf, pageLength
|
||||
}
|
||||
|
||||
@@ -206,7 +198,6 @@ func InquiryPage0x83(host int, cmd *api.SCSICommand) (*bytes.Buffer, uint16) {
|
||||
func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
var (
|
||||
allocationLength uint16
|
||||
pageLength uint16
|
||||
additionLength byte
|
||||
buf = &bytes.Buffer{}
|
||||
data []byte = []byte{}
|
||||
@@ -235,24 +226,28 @@ func SPCInquiry(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
if evpd {
|
||||
switch pcode {
|
||||
case 0x00:
|
||||
buf, pageLength = InquiryPage0x00(host, cmd)
|
||||
buf, _ = InquiryPage0x00(host, cmd)
|
||||
|
||||
case 0x80:
|
||||
buf, pageLength = InquiryPage0x80(host, cmd)
|
||||
buf, _ = InquiryPage0x80(host, cmd)
|
||||
|
||||
case 0x83:
|
||||
buf, pageLength = InquiryPage0x83(host, cmd)
|
||||
buf, _ = InquiryPage0x83(host, cmd)
|
||||
|
||||
default:
|
||||
goto sense
|
||||
}
|
||||
data = buf.Bytes()
|
||||
if allocationLength < pageLength {
|
||||
if int(allocationLength) < len(data) {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:allocationLength])
|
||||
cmd.InSDBBuffer.Resid = uint32(len(data))
|
||||
} else {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data[0:])
|
||||
}
|
||||
} else {
|
||||
if pcode != 0 {
|
||||
goto sense
|
||||
}
|
||||
//byte 5
|
||||
//SCCS(0) AAC(0) TPGS(0) 3PC(0) PROTECT(0)
|
||||
addBuf.WriteByte(INQUIRY_TPGS_IMPLICIT)
|
||||
@@ -354,7 +349,7 @@ func SPCReportLuns(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
|
||||
// LUN list length
|
||||
buf.Write(util.MarshalUint32(availLength))
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||
|
||||
// Skip through to byte 4, Reserved
|
||||
for i := 0; i < 4; i++ {
|
||||
@@ -474,13 +469,17 @@ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
var (
|
||||
scb = cmd.SCB.Bytes()
|
||||
mode6 = (scb[0] == 0x1a)
|
||||
dbd = scb[1] & 0x8 /* Disable Block Descriptors */
|
||||
dbd = scb[1] & 0x8 // Disable Block Descriptors
|
||||
pcode = scb[2] & 0x3f
|
||||
pctrl = (scb[2] & 0xc0) >> 6
|
||||
subpcode = scb[3]
|
||||
blkDesctionLen = 0
|
||||
key = ILLEGAL_REQUEST
|
||||
asc = ASC_INVALID_FIELD_IN_CDB
|
||||
data []byte
|
||||
allocLen uint32
|
||||
remainLen uint32
|
||||
i uint32
|
||||
)
|
||||
if dbd == 0 {
|
||||
blkDesctionLen = 8
|
||||
@@ -489,11 +488,93 @@ func SPCModeSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
asc = ASC_SAVING_PARMS_UNSUP
|
||||
goto sense
|
||||
}
|
||||
_ = dbd
|
||||
_ = pcode
|
||||
_ = subpcode
|
||||
_ = mode6
|
||||
_ = blkDesctionLen
|
||||
if mode6 {
|
||||
allocLen = uint32(scb[4])
|
||||
// set header
|
||||
for i = 0; i < 4 && i < allocLen; i++ {
|
||||
data = append(data, 0x00)
|
||||
}
|
||||
} else {
|
||||
allocLen = uint32(util.GetUnalignedUint16(scb[7:9]))
|
||||
// set header
|
||||
for i = 0; i < 8 && i < allocLen; i++ {
|
||||
data = append(data, 0x00)
|
||||
}
|
||||
}
|
||||
remainLen = allocLen - uint32(len(data))
|
||||
if dbd == 0 && remainLen >= 8 {
|
||||
data = append(data, cmd.Device.ModeBlockDescriptor...)
|
||||
}
|
||||
if pcode == 0x3f {
|
||||
for _, pg := range cmd.Device.ModePages {
|
||||
if pg.SubPageCode == 0 {
|
||||
if remainLen < 2+uint32(pg.Size) {
|
||||
break
|
||||
}
|
||||
data = append(data, pg.PageCode)
|
||||
data = append(data, pg.Size)
|
||||
} else {
|
||||
if remainLen < 4+uint32(pg.Size) {
|
||||
break
|
||||
}
|
||||
data = append(data, pg.PageCode|0x40)
|
||||
data = append(data, pg.SubPageCode)
|
||||
data = append(data, (pg.Size>>8)&0xff)
|
||||
data = append(data, pg.Size&0xff)
|
||||
}
|
||||
if pctrl == 1 {
|
||||
data = append(data, pg.Data[pg.Size:]...)
|
||||
} else {
|
||||
data = append(data, pg.Data[:pg.Size]...)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var pg *api.ModePage
|
||||
for _, p := range cmd.Device.ModePages {
|
||||
if p.PageCode == pcode && p.SubPageCode == subpcode {
|
||||
pg = &p
|
||||
break
|
||||
}
|
||||
}
|
||||
if pg == nil {
|
||||
goto sense
|
||||
}
|
||||
if remainLen >= 2+uint32(pg.Size) {
|
||||
if pg.SubPageCode == 0 {
|
||||
data = append(data, pg.PageCode)
|
||||
data = append(data, pg.Size)
|
||||
if pctrl == 1 {
|
||||
data = append(data, pg.Data[pg.Size:]...)
|
||||
} else {
|
||||
data = append(data, pg.Data[:pg.Size]...)
|
||||
}
|
||||
} else if remainLen >= 4+uint32(pg.Size) {
|
||||
data = append(data, pg.PageCode|0x40)
|
||||
data = append(data, pg.SubPageCode)
|
||||
data = append(data, (pg.Size>>8)&0xff)
|
||||
data = append(data, pg.Size&0xff)
|
||||
if pctrl == 1 {
|
||||
data = append(data, pg.Data[pg.Size:]...)
|
||||
} else {
|
||||
data = append(data, pg.Data[:pg.Size]...)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if mode6 {
|
||||
data[0] = uint8(len(data) - 1)
|
||||
data[3] = uint8(blkDesctionLen)
|
||||
} else {
|
||||
data[0] = uint8((len(data) - 2) >> 8)
|
||||
data[1] = uint8(len(data) - 2)
|
||||
data[6] = uint8(blkDesctionLen >> 8)
|
||||
data[7] = uint8(blkDesctionLen)
|
||||
}
|
||||
if rlen := uint32(len(data)); rlen < allocLen {
|
||||
cmd.InSDBBuffer.Resid = rlen
|
||||
}
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
BuildSenseData(cmd, key, asc)
|
||||
@@ -660,7 +741,7 @@ func SPCPRReadKeys(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
||||
}
|
||||
|
||||
cmd.InSDBBuffer.Resid = int32(additionLength)
|
||||
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
@@ -715,7 +796,7 @@ func SPCPRReadReservation(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
cmd.InSDBBuffer.Buffer = bytes.NewBuffer(data)
|
||||
}
|
||||
|
||||
cmd.InSDBBuffer.Resid = int32(additionLength)
|
||||
cmd.InSDBBuffer.Resid = uint32(additionLength)
|
||||
return api.SAMStatGood
|
||||
|
||||
sense:
|
||||
@@ -760,7 +841,7 @@ func SPCPRReportCapabilities(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
} else {
|
||||
actualLength = availLength
|
||||
}
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||
return api.SAMStatGood
|
||||
sense:
|
||||
cmd.InSDBBuffer.Resid = 0
|
||||
@@ -1257,7 +1338,7 @@ func SPCRequestSense(host int, cmd *api.SCSICommand) api.SAMStat {
|
||||
if cmd.SenseBuffer != nil {
|
||||
data.Write(cmd.SenseBuffer.Bytes()[:actualLength])
|
||||
}
|
||||
cmd.InSDBBuffer.Resid = int32(actualLength)
|
||||
cmd.InSDBBuffer.Resid = uint32(actualLength)
|
||||
cmd.InSDBBuffer.Buffer = data
|
||||
|
||||
// reset sense buffer in cmnd
|
||||
|
||||
Reference in New Issue
Block a user