nsp_message.c 1.98 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5
/*==========================================================================
  NinjaSCSI-3 message handler
      By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>

   This software may be used and distributed according to the terms of
Linus Torvalds's avatar
Linus Torvalds committed
6
   the GNU General Public License.
Linus Torvalds's avatar
Linus Torvalds committed
7 8
 */

9
/* $Id: nsp_message.c,v 1.2 2002/09/20 04:06:58 gotom Exp $ */
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

static void nsp_message_in(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
{
	unsigned int  base = SCpnt->host->io_port;
	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;

	DEBUG(0, " msgin loop\n");
	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;

}

static void nsp_message_out(Scsi_Cmnd *SCpnt, nsp_hw_data *data)
{
	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).
	 */

	DEBUG(0, " msgout loop\n");
	do {
		if (nsp_xfer(SCpnt, data, BUSPHASE_MESSAGE_OUT)) {
67
			printk(KERN_DEBUG " %s msgout: xfer short\n", __FUNCTION__);
Linus Torvalds's avatar
Linus Torvalds committed
68 69 70 71 72 73 74 75 76
		}

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

}

/* end */