1 /*========================================================================== 2 NinjaSCSI-3 message handler 3 By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp> 4 5 This software may be used and distributed according to the terms of 6 the GNU General Public License. 7 */ 8 9 /* $Id: nsp_message.c,v 1.6 2003/07/26 14:21:09 elca Exp $ */ 10 11 static void nsp_message_in(struct scsi_cmnd *SCpnt) 12 { 13 unsigned int base = SCpnt->device->host->io_port; 14 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 15 unsigned char data_reg, control_reg; 16 int ret, len; 17 18 /* 19 * XXX: NSP QUIRK 20 * NSP invoke interrupts only in the case of scsi phase changes, 21 * therefore we should poll the scsi phase here to catch 22 * the next "msg in" if exists (no scsi phase changes). 23 */ 24 ret = 16; 25 len = 0; 26 27 nsp_dbg(NSP_DEBUG_MSGINOCCUR, "msgin loop"); 28 do { 29 /* read data */ 30 data_reg = nsp_index_read(base, SCSIDATAIN); 31 32 /* assert ACK */ 33 control_reg = nsp_index_read(base, SCSIBUSCTRL); 34 control_reg |= SCSI_ACK; 35 nsp_index_write(base, SCSIBUSCTRL, control_reg); 36 nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>"); 37 38 data->MsgBuffer[len] = data_reg; len++; 39 40 /* deassert ACK */ 41 control_reg = nsp_index_read(base, SCSIBUSCTRL); 42 control_reg &= ~SCSI_ACK; 43 nsp_index_write(base, SCSIBUSCTRL, control_reg); 44 45 /* catch a next signal */ 46 ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ); 47 } while (ret > 0 && MSGBUF_SIZE > len); 48 49 data->MsgLen = len; 50 51 } 52 53 static void nsp_message_out(struct scsi_cmnd *SCpnt) 54 { 55 nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; 56 int ret = 1; 57 int len = data->MsgLen; 58 59 /* 60 * XXX: NSP QUIRK 61 * NSP invoke interrupts only in the case of scsi phase changes, 62 * therefore we should poll the scsi phase here to catch 63 * the next "msg out" if exists (no scsi phase changes). 64 */ 65 66 nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop"); 67 do { 68 if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) { 69 nsp_msg(KERN_DEBUG, "msgout: xfer short"); 70 } 71 72 /* catch a next signal */ 73 ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, BUSMON_REQ); 74 } while (ret > 0 && len-- > 0); 75 76 } 77 78 /* end */ 79