def handle_register_HTD(self, register_packet): """ Handle a Register HTD Always returns None """ sata_header = register_packet.sata_header # Check if C bit is set to 0 -- see 11.2 Dl1 Note 1 -- no FIS is sent # I think we can ignore if C bit is set to 0 and go back to IDLE state # software reset could still happen -- not sure which bit is the SRST bit in the control register? if sata_header['C'] == 0: logger.debug( "Got HTD Register Packet but C bit is set to 0. Ignoring.") return None # check if this is an NCQ command if sata_header[ 'command'] == NCQCommandType.ReadFPDMAQueued or sata_header[ 'command'] == NCQCommandType.WriteFPDMAQueued: cmd = "READ" direction = G.SATA_OP.DIRECTION.READ if sata_header['command'] == NCQCommandType.WriteFPDMAQueued: cmd = "WRITE" direction = G.SATA_OP.DIRECTION.WRITE # NCQ uses features field for sector count logger.debug( "Got HTD Register Packet for NCQ %s -- TAG %d expecting %d bytes." % (cmd, sata_header['tag'], sata_header['features'] * self.sector_size)) # if len(self.ncq_register_stack) > 0: # logger.error("Our NCQ register stack will be greater than 1, so we have at least one outstanding NCQ register packet with NO Register ACK. Stack size is %d" % len(self.ncq_register_stack)) # # add to our stack # self.ncq_register_stack.append(register_packet) #No ACKS # # change state to waiting for Register DTH # self.STATE = self.WAIT_FOR_REGISTER_ACK # # # deal with error checking when we get the Register DTH ACK back # return None # check if the spot belonging to the associated TAG is empty if (not self.ncq_transactions_outstanding[sata_header['tag']]): # This TAG is not taken, so we just add self.ncq_transactions_outstanding[ sata_header['tag']] = register_packet else: logger.error( "Received HTD NCQ Register Packet for TAG %d but it is already in use. Using it anyway." % sata_header['tag']) # still put it in there for now self.ncq_transactions_outstanding[ sata_header['tag']] = register_packet #don't need this if we accept the register packet anyway #return None # Associate this DTH Register packet # with the tag and prepare the disk sensor packet for aggregating data lba = sata_header['lba'] # NOTE: NCQ uses features field instead of count for sector count sector_count = sata_header['features'] disk_sensor_packet = DiskSensorPacket() disk_sensor_packet.sector = lba disk_sensor_packet.num_sectors = sector_count disk_sensor_packet.disk_operation = direction disk_sensor_packet.size = sector_count * self.sector_size disk_sensor_packet.data = "" self.ncq_data_outstanding[sata_header['tag']] = disk_sensor_packet # DO NOT set state to IDLE # Because now it looks like Register packets can come during other times # so we want to maintain the current state # # set state to IDLE # # self.STATE = self.DEVICE_IDLE return None # NCQ Management stuff elif sata_header['command'] == NCQCommandType.NCQQueueManagement: logger.debug( "Got Register Packet for NCQ Queue Management. Ignoring for now." ) # Don't need to change state return None # NON NCQ Register Packet else: logger.debug( "Got Non-NCQ HTD Register Packet, expected %d bytes." % (sata_header['count'] * self.sector_size)) logger.debug("Command field is %d" % sata_header['command']) # if len(self.ncq_register_stack) > 0: # logger.error("Have more than 0 outstanding NCQ HTD Register Packets. Non NCQ Register packets are not supposed to be sent while NCQ Register packets are still outstanding. Size of stack is %d" % len(self.regular_register_stack)) # if len(self.regular_register_stack) > 0: # logger.error("Will have more than one outstanding regular (non NCQ) HTD Register Packets. Size of stack is %d" % len(self.regular_register_stack)) # push this normal Register HTD packet on the stack self.regular_register_stack.append(register_packet) # prepare the disk sensor packet for aggregating data lba = sata_header['lba'] sector_count = sata_header['count'] direction = sata_header['direction'] # self.regular_disk_sensor_packet = DiskSensorPacket(lba, # sector_count, # direction, # sector_count*self.sector_size, # "") self.regular_disk_sensor_packet = DiskSensorPacket() self.regular_disk_sensor_packet.sector = lba self.regular_disk_sensor_packet.num_sectors = sector_count self.regular_disk_sensor_packet.disk_operation = direction self.regular_disk_sensor_packet.size = sector_count * self.sector_size self.regular_disk_sensor_packet.data = "" # Transition state now that we are waiting for data self.STATE = self.WAIT_FOR_NON_NCQ_DATA return None
def handle_register_HTD(self, register_packet): """ Handle a Register HTD Always returns None """ sata_header = register_packet.sata_header # Check if C bit is set to 0 -- see 11.2 Dl1 Note 1 -- no FIS is sent # I think we can ignore if C bit is set to 0 and go back to IDLE state # software reset could still happen -- not sure which bit is the SRST bit in the control register? if sata_header['C'] == 0: logger.debug("Got HTD Register Packet but C bit is set to 0. Ignoring.") return None # check if this is an NCQ command if sata_header['command'] == NCQCommandType.ReadFPDMAQueued or sata_header['command'] == NCQCommandType.WriteFPDMAQueued: cmd = "READ" direction = G.SATA_OP.DIRECTION.READ if sata_header['command'] == NCQCommandType.WriteFPDMAQueued: cmd = "WRITE" direction = G.SATA_OP.DIRECTION.WRITE # NCQ uses features field for sector count logger.debug("Got HTD Register Packet for NCQ %s -- TAG %d expecting %d bytes." % (cmd, sata_header['tag'], sata_header['features']*self.sector_size)) # if len(self.ncq_register_stack) > 0: # logger.error("Our NCQ register stack will be greater than 1, so we have at least one outstanding NCQ register packet with NO Register ACK. Stack size is %d" % len(self.ncq_register_stack)) # # add to our stack # self.ncq_register_stack.append(register_packet) #No ACKS # # change state to waiting for Register DTH # self.STATE = self.WAIT_FOR_REGISTER_ACK # # # deal with error checking when we get the Register DTH ACK back # return None # check if the spot belonging to the associated TAG is empty if (not self.ncq_transactions_outstanding[sata_header['tag']]): # This TAG is not taken, so we just add self.ncq_transactions_outstanding[sata_header['tag']] = register_packet else: logger.error("Received HTD NCQ Register Packet for TAG %d but it is already in use. Using it anyway." % sata_header['tag']) # still put it in there for now self.ncq_transactions_outstanding[sata_header['tag']] = register_packet #don't need this if we accept the register packet anyway #return None # Associate this DTH Register packet # with the tag and prepare the disk sensor packet for aggregating data lba = sata_header['lba'] # NOTE: NCQ uses features field instead of count for sector count sector_count = sata_header['features'] disk_sensor_packet = DiskSensorPacket() disk_sensor_packet.sector = lba disk_sensor_packet.num_sectors = sector_count disk_sensor_packet.disk_operation = direction disk_sensor_packet.size = sector_count*self.sector_size disk_sensor_packet.data = "" self.ncq_data_outstanding[sata_header['tag']] = disk_sensor_packet # DO NOT set state to IDLE # Because now it looks like Register packets can come during other times # so we want to maintain the current state # # set state to IDLE # # self.STATE = self.DEVICE_IDLE return None # NCQ Management stuff elif sata_header['command'] == NCQCommandType.NCQQueueManagement: logger.debug("Got Register Packet for NCQ Queue Management. Ignoring for now.") # Don't need to change state return None # NON NCQ Register Packet else: logger.debug("Got Non-NCQ HTD Register Packet, expected %d bytes." % (sata_header['count']*self.sector_size)) logger.debug("Command field is %d" % sata_header['command']) # if len(self.ncq_register_stack) > 0: # logger.error("Have more than 0 outstanding NCQ HTD Register Packets. Non NCQ Register packets are not supposed to be sent while NCQ Register packets are still outstanding. Size of stack is %d" % len(self.regular_register_stack)) # if len(self.regular_register_stack) > 0: # logger.error("Will have more than one outstanding regular (non NCQ) HTD Register Packets. Size of stack is %d" % len(self.regular_register_stack)) # push this normal Register HTD packet on the stack self.regular_register_stack.append(register_packet) # prepare the disk sensor packet for aggregating data lba = sata_header['lba'] sector_count = sata_header['count'] direction = sata_header['direction'] # self.regular_disk_sensor_packet = DiskSensorPacket(lba, # sector_count, # direction, # sector_count*self.sector_size, # "") self.regular_disk_sensor_packet = DiskSensorPacket() self.regular_disk_sensor_packet.sector = lba self.regular_disk_sensor_packet.num_sectors = sector_count self.regular_disk_sensor_packet.disk_operation = direction self.regular_disk_sensor_packet.size = sector_count*self.sector_size self.regular_disk_sensor_packet.data = "" # Transition state now that we are waiting for data self.STATE = self.WAIT_FOR_NON_NCQ_DATA return None