| 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 |  | 
| Henrik Kretzschmar | 0fc82d5 | 2006-10-10 14:41:41 -0700 | [diff] [blame] | 11 | static void nsp_message_in(struct scsi_cmnd *SCpnt) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Henrik Kretzschmar | 0fc82d5 | 2006-10-10 14:41:41 -0700 | [diff] [blame] | 53 | static void nsp_message_out(struct scsi_cmnd *SCpnt) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 */ |