Ejemplo n.º 1
0
Archivo: lun.go Proyecto: kurin/tgt
func (t *Target) handleVPD(s *Session, m, resp *packet.Message) {
	lun := int(m.LUN)
	alloc := int(packet.ParseUint(m.CDB[3:5]))
	vpd, err := t.LUNs[lun].VitalProductData(m.CDB[2])
	if err != nil {
		resp.Status = 0x02
		resp.SCSIResponse = 0x01
		return
	}
	resp.RawData = vpd
	if len(vpd) >= alloc {
		resp.RawData = resp.RawData[:alloc]
	}
}
Ejemplo n.º 2
0
Archivo: lun.go Proyecto: kurin/tgt
func (t *Target) handleSCSICmd(s *Session, m *packet.Message) (err error) {
	opCode := m.CDB[0]
	lun := int(m.LUN)
	resp := &packet.Message{
		OpCode:   packet.OpSCSIResp,
		Final:    true,
		StatSN:   m.ExpStatSN,
		TaskTag:  m.TaskTag,
		ExpCmdSN: m.CmdSN + 1,
		MaxCmdSN: m.CmdSN + 10,
	}
	defer func() {
		if err == nil {
			err = s.Send(resp)
		}
	}()
	switch opCode {
	case 0x00:
		ready, err := t.LUNs[lun].TestUnitReady()
		if err != nil {
			resp.Status = 0x02
			resp.SCSIResponse = 0x01
		}
		if !ready {
			resp.Status = 0x08
			resp.SCSIResponse = 0x01
		}
		return s.Send(resp)
	case 0x25:
		resp.OpCode = packet.OpSCSIIn
		resp.HasStatus = true
		var data []byte
		pmi := m.CDB[8]&0x01 == 0x01
		lba := uint32(packet.ParseUint(m.CDB[2:6]))
		rlba, blocksize, err := t.LUNs[lun].ReadCapacity10(pmi, lba)
		if err != nil {
			resp.Status = 0x02
			resp.SCSIResponse = 0x01
			break
		}
		data = append(data, packet.MarshalUint64(uint64(rlba))[4:]...)
		data = append(data, packet.MarshalUint64(uint64(blocksize))[4:]...)
		resp.RawData = data
	case 0x9e:
		resp.OpCode = packet.OpSCSIIn
		resp.HasStatus = true
		sa := m.CDB[1] & 0x1f
		switch sa {
		case 0x10:
			pmi := m.CDB[14]&0x01 == 0x01
			lba := packet.ParseUint(m.CDB[2:10])
			capacity, err := t.LUNs[lun].ReadCapacity16(pmi, lba)
			if err != nil {
				resp.Status = 0x02
				resp.SCSIResponse = 0x01
				break
			}
			resp.RawData = capacity.bytes()
		}
	case 0x12:
		resp.OpCode = packet.OpSCSIIn
		resp.HasStatus = true
		alloc := int(packet.ParseUint(m.CDB[3:5]))
		evpd := m.CDB[1]&0x01 == 0x01
		if evpd {
			t.handleVPD(s, m, resp)
			return
		}
		inq, err := t.LUNs[lun].Inquiry()
		if err != nil {
			resp.Status = 0x02
			resp.SCSIResponse = 0x01
			break
		}
		resp.RawData = inq.bytes()[:alloc]
	default:
		setError(resp, ErrUnsupportedCommand)
	}
	return
}