Ejemplo n.º 1
0
static void nsp_message_in(Scsi_Cmnd *SCpnt)
{
    unsigned int  base = SCpnt->device->host->io_port;
    nsp_hw_data  *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
    unsigned char data_reg, control_reg;
    int           ret, len;

    /*
     * XXX: NSP QUIRK
     * NSP invoke interrupts only in the case of scsi phase changes,
     * therefore we should poll the scsi phase here to catch
     * the next "msg in" if exists (no scsi phase changes).
     */
    ret = 16;
    len = 0;

    nsp_dbg(NSP_DEBUG_MSGINOCCUR, "msgin loop");
    do {
        /* read data */
        data_reg = nsp_index_read(base, SCSIDATAIN);

        /* assert ACK */
        control_reg = nsp_index_read(base, SCSIBUSCTRL);
        control_reg |= SCSI_ACK;
        nsp_index_write(base, SCSIBUSCTRL, control_reg);
        nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>");

        data->MsgBuffer[len] = data_reg;
        len++;

        /* deassert ACK */
        control_reg =  nsp_index_read(base, SCSIBUSCTRL);
        control_reg &= ~SCSI_ACK;
        nsp_index_write(base, SCSIBUSCTRL, control_reg);

        /* catch a next signal */
        ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ);
    } while (ret > 0 && MSGBUF_SIZE > len);

    data->MsgLen = len;

}
Ejemplo n.º 2
0
static void nsp_message_in(struct scsi_cmnd *SCpnt)
{
	unsigned int  base = SCpnt->device->host->io_port;
	nsp_hw_data  *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
	unsigned char data_reg, control_reg;
	int           ret, len;

	/*
                  
                                                                 
                                                          
                                                        
  */
	ret = 16;
	len = 0;

	nsp_dbg(NSP_DEBUG_MSGINOCCUR, "msgin loop");
	do {
		/*           */
		data_reg = nsp_index_read(base, SCSIDATAIN);

		/*            */
		control_reg = nsp_index_read(base, SCSIBUSCTRL);
		control_reg |= SCSI_ACK;
		nsp_index_write(base, SCSIBUSCTRL, control_reg);
		nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>");

		data->MsgBuffer[len] = data_reg; len++;

		/*              */
		control_reg =  nsp_index_read(base, SCSIBUSCTRL);
		control_reg &= ~SCSI_ACK;
		nsp_index_write(base, SCSIBUSCTRL, control_reg);

		/*                     */
		ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ);
	} while (ret > 0 && MSGBUF_SIZE > len);

	data->MsgLen = len;

}
Ejemplo n.º 3
0
static void nsp_message_out(struct scsi_cmnd *SCpnt)
{
	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
	int ret = 1;
	int len = data->MsgLen;

	/*
	 * XXX: NSP QUIRK
	 * NSP invoke interrupts only in the case of scsi phase changes,
	 * therefore we should poll the scsi phase here to catch 
	 * the next "msg out" if exists (no scsi phase changes).
	 */

	nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop");
	do {
		if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) {
			nsp_msg(KERN_DEBUG, "msgout: xfer short");
		}

		/* catch a next signal */
		ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, BUSMON_REQ);
	} while (ret > 0 && len-- > 0);

}
Ejemplo n.º 4
0
static void nsp_message_out(struct scsi_cmnd *SCpnt)
{
	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
	int ret = 1;
	int len = data->MsgLen;

	/*
                  
                                                                 
                                                          
                                                         
  */

	nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop");
	do {
		if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) {
			nsp_msg(KERN_DEBUG, "msgout: xfer short");
		}

		/*                     */
		ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, BUSMON_REQ);
	} while (ret > 0 && len-- > 0);

}
Ejemplo n.º 5
0
static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
			    void (*done)(struct scsi_cmnd *))
{
#ifdef NSP_DEBUG
	/*unsigned int host_id = SCpnt->device->host->this_id;*/
	/*unsigned int base    = SCpnt->device->host->io_port;*/
	unsigned char target = scmd_id(SCpnt);
#endif
	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;

	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
		"SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
		scsi_bufflen(SCpnt), scsi_sg_count(SCpnt));
	//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);

	SCpnt->scsi_done	= done;

	if (data->CurrentSC != NULL) {
		nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");
		SCpnt->result   = DID_BAD_TARGET << 16;
		nsp_scsi_done(SCpnt);
		return 0;
	}

#if 0
	/* XXX: pcmcia-cs generates SCSI command with "scsi_info" utility.
	        This makes kernel crash when suspending... */
	if (data->ScsiInfo->stop != 0) {
		nsp_msg(KERN_INFO, "suspending device. reject command.");
		SCpnt->result  = DID_BAD_TARGET << 16;
		nsp_scsi_done(SCpnt);
		return SCSI_MLQUEUE_HOST_BUSY;
	}
#endif

	show_command(SCpnt);

	data->CurrentSC		= SCpnt;

	SCpnt->SCp.Status	= CHECK_CONDITION;
	SCpnt->SCp.Message	= 0;
	SCpnt->SCp.have_data_in = IO_UNKNOWN;
	SCpnt->SCp.sent_command = 0;
	SCpnt->SCp.phase	= PH_UNDETERMINED;
	scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));

	/* setup scratch area
	   SCp.ptr		: buffer pointer
	   SCp.this_residual	: buffer length
	   SCp.buffer		: next buffer
	   SCp.buffers_residual : left buffers in list
	   SCp.phase		: current state of the command */
	if (scsi_bufflen(SCpnt)) {
		SCpnt->SCp.buffer	    = scsi_sglist(SCpnt);
		SCpnt->SCp.ptr		    = BUFFER_ADDR;
		SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
		SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
	} else {
		SCpnt->SCp.ptr		    = NULL;
		SCpnt->SCp.this_residual    = 0;
		SCpnt->SCp.buffer	    = NULL;
		SCpnt->SCp.buffers_residual = 0;
	}

	if (nsphw_start_selection(SCpnt) == FALSE) {
		nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");
		SCpnt->result   = DID_BUS_BUSY << 16;
		nsp_scsi_done(SCpnt);
		return 0;
	}


	//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "out");
#ifdef NSP_DEBUG
	data->CmdId++;
#endif
	return 0;
}