Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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(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(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 */ |