--- linux-2.6.10/drivers/scsi/pcmcia/nsp_message.c      2004-10-19 
06:53:46.000000000 +0900
+++ linux-2.6.10-nsp/drivers/scsi/pcmcia/nsp_message.c  2004-08-15 
09:23:57.000000000 +0900
@@ -1,19 +1,129 @@
 /*==========================================================================
   NinjaSCSI-3 message handler
-      By: YOKOTA Hiroshi <[EMAIL PROTECTED]>
+      By: YOKOTA Hiroshi <yokota<at>netlab.is.tsukuba.ac.jp>
 
    This software may be used and distributed according to the terms of
    the GNU General Public License.
  */
 
-/* $Id: nsp_message.c,v 1.6 2003/07/26 14:21:09 elca Exp $ */
+/* $Id: nsp_message.c,v 1.12 2004/08/15 00:23:57 elca Exp $ */
 
-static void nsp_message_in(Scsi_Cmnd *SCpnt)
+
+/*
+ * IDENTIFY Message
+ */
+static void nsp_build_identify(const Scsi_Cmnd *SCpnt)
+{
+       nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+       int          pos  = data->MsgOutLen;
+
+       data->MsgOutBuffer[pos] = IDENTIFY(TRUE, SCpnt->device->lun); pos++;
+       data->MsgOutLen = pos;
+}
+
+/*
+ * SDTR Message Routine
+ */
+static void nsp_build_sdtr(const Scsi_Cmnd *SCpnt,
+                                 unsigned char period,
+                                 unsigned char offset)
+{
+       nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+       int          pos  = data->MsgOutLen;
+
+       data->MsgOutBuffer[pos] = EXTENDED_MESSAGE;  pos++;
+       data->MsgOutBuffer[pos] = EXTENDED_SDTR_LEN; pos++;
+       data->MsgOutBuffer[pos] = EXTENDED_SDTR;     pos++;
+       data->MsgOutBuffer[pos] = period;            pos++;
+       data->MsgOutBuffer[pos] = offset;            pos++;
+
+       data->MsgOutLen = pos;
+}
+
+/*
+ * No Operation Message
+ */
+static void nsp_build_nop(const Scsi_Cmnd *SCpnt)
 {
-       unsigned int  base = SCpnt->device->host->io_port;
+       nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+       int          pos  = data->MsgOutLen;
+
+       if (pos != 0) {
+               nsp_msg(KERN_WARNING,
+                       "Some messages are already contained!");
+               return;
+       }
+
+       data->MsgOutBuffer[pos] = NOP; pos++;
+       data->MsgOutLen = pos;
+}
+
+
+/*
+ * transfer SCSI message
+ */
+static int nsp_xfer(const Scsi_Cmnd *SCpnt, int phase)
+{
+       const unsigned int base = SCpnt->device->host->io_port;
+       nsp_hw_data   *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+       unsigned char *buf;
+       int            ptr, ret;
+       size_t         len;
+
+       //nsp_dbg(NSP_DEBUG_DATA_IO, "in");
+
+       if (phase & BUSMON_IO) {
+               len = min(sizeof(data->MsgInBuffer), data->MsgInLen);
+               buf = data->MsgInBuffer;
+       } else {
+               len = min(sizeof(data->MsgOutBuffer), data->MsgOutLen);
+               buf = data->MsgOutBuffer;
+       }
+
+       for (ptr = 0; len > 0; len--, ptr++) {
+               int sig;
+
+               sig = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);
+               if (sig <= 0) {
+                       nsp_msg(KERN_DEBUG, "xfer quit");
+                       ret = 0;
+                       goto out;
+               }
+
+               /* if last byte, negate ATN */
+               if (len == 1 && SCpnt->SCp.phase == PH_MSG_OUT) {
+                       nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | 
ACKENB);
+               }
+
+               /* read & write message */
+               if (phase & BUSMON_IO) {
+                       nsp_dbg(NSP_DEBUG_DATA_IO, "read msg");
+                       buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK);
+               } else {
+                       nsp_dbg(NSP_DEBUG_DATA_IO, "write msg");
+                       nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]);
+               }
+               nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>");
+
+       }
+       ret = 1;
+
+ out:
+       if (phase & BUSMON_IO) {
+               data->MsgInLen = len;
+       } else {
+               data->MsgOutLen = len;
+       }
+
+       return ret;
+}
+
+static void nsp_message_in(const Scsi_Cmnd *SCpnt)
+{
+       const 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;
+       int           sig = 1;
+       size_t        len = 0;
 
        /*
         * XXX: NSP QUIRK
@@ -21,11 +131,11 @@
         * 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 {
+               unsigned char data_reg, control_reg;
+
                /* read data */
                data_reg = nsp_index_read(base, SCSIDATAIN);
 
@@ -35,7 +145,7 @@
                nsp_index_write(base, SCSIBUSCTRL, control_reg);
                nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>");
 
-               data->MsgBuffer[len] = data_reg; len++;
+               data->MsgInBuffer[len] = data_reg; len++;
 
                /* deassert ACK */
                control_reg =  nsp_index_read(base, SCSIBUSCTRL);
@@ -43,18 +153,17 @@
                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;
+               sig = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ);
+       } while (sig > 0 && sizeof(data->MsgInBuffer) > len);
 
+       data->MsgInLen = len;
 }
 
-static void nsp_message_out(Scsi_Cmnd *SCpnt)
+static void nsp_message_out(const Scsi_Cmnd *SCpnt)
 {
-       nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
-       int ret = 1;
-       int len = data->MsgLen;
+       const nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
+       int sig = 1;
+       int tmp;
 
        /*
         * XXX: NSP QUIRK
@@ -63,15 +172,21 @@
         * the next "msg out" if exists (no scsi phase changes).
         */
 
+       if (data->MsgOutLen == 0) {
+               nsp_build_nop(SCpnt);
+       }
+
        nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop");
        do {
-               if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) {
-                       nsp_msg(KERN_DEBUG, "msgout: xfer short");
+               tmp = nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT);
+
+               if (tmp == 0) {
+                       nsp_msg(KERN_DEBUG, "msgout: xfer short, tmp=%d, 
len=%d", tmp, data->MsgOutLen);
                }
 
                /* catch a next signal */
-               ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, 
BUSMON_REQ);
-       } while (ret > 0 && len-- > 0);
+               sig = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, 
BUSMON_REQ);
+       } while (sig > 0 && data->MsgOutLen > 0);
 
 }
 
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to