00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00023 #include <wdm.h>
00024 #include "cbm_driver.h"
00025 #include "i_iec.h"
00026
00054 NTSTATUS
00055 cbmiec_i_raw_write(PDEVICE_EXTENSION Pdx, const UCHAR *Buffer, ULONG Count, ULONG *Sent, BOOLEAN Atn, BOOLEAN Talk)
00056 {
00057 NTSTATUS ntStatus;
00058 ULONG sent;
00059 UCHAR c;
00060 ULONG i;
00061 LONG ret;
00062
00063 FUNC_ENTER();
00064
00065 ntStatus = STATUS_SUCCESS;
00066 sent = 0;
00067
00068 Pdx->Eoi = 0;
00069
00070 PERF_EVENT_VERBOSE(0x1010, 0);
00071
00072 ret = InterlockedExchange(&Pdx->IrqCount, 0);
00073 DBG_ASSERT(ret == 0);
00074
00075 DBG_IEC((DBG_PREFIX "About to send %d bytes%s", Count, Atn ? " with ATN" : ""));
00076
00077 PERF_EVENT_VERBOSE(0x1011, 0);
00078
00079 if (Atn)
00080 {
00081 CBMIEC_SET(PP_ATN_OUT);
00082 }
00083
00084
00085
00086 CBMIEC_SET(PP_CLK_OUT);
00087 CBMIEC_RELEASE(PP_DATA_OUT);
00088
00089
00090
00091 PERF_EVENT_VERBOSE(0x1012, 0);
00092
00093 for(i=0; (i<libiec_global_timeouts.T_9_Times) && !CBMIEC_GET(PP_DATA_IN); i++)
00094 {
00095 cbmiec_udelay(libiec_global_timeouts.T_9_SEND_WAIT_DEVICES_T_AT);
00096 }
00097
00098 PERF_EVENT_VERBOSE(0x1013, 0);
00099
00100
00101
00102
00103
00104 if(!CBMIEC_GET(PP_DATA_IN))
00105 {
00106 PERF_EVENT_VERBOSE(0x1014, 1);
00107 DBG_ERROR((DBG_PREFIX "no devices found!"));
00108 CBMIEC_RELEASE(PP_CLK_OUT | PP_ATN_OUT);
00109 ntStatus = STATUS_NO_SUCH_DEVICE;
00110 }
00111 else
00112 {
00113 PERF_EVENT_VERBOSE(0x1014, 0);
00114 if (Pdx->IsSMP)
00115 {
00116 cbmiec_udelay(libiec_global_timeouts.T_10_SEND_BEFORE_1ST_BYTE);
00117 }
00118 else
00119 {
00120 cbmiec_schedule_timeout(libiec_global_timeouts.T_10_SEND_BEFORE_1ST_BYTE);
00121 }
00122 }
00123
00124 PERF_EVENT_VERBOSE(0x1015, 0);
00125
00126 while(sent < Count && ntStatus == STATUS_SUCCESS)
00127 {
00128 c = *Buffer++;
00129
00130 PERF_EVENT_WRITE_BYTE_NO(sent);
00131 PERF_EVENT_WRITE_BYTE(c);
00132
00133 PERF_EVENT_VERBOSE(0x1016, sent);
00134
00135 cbmiec_udelay(libiec_global_timeouts.T_11_SEND_BEFORE_BYTE_DELAY);
00136
00137 PERF_EVENT_VERBOSE(0x1017, sent);
00138
00139 if(CBMIEC_GET(PP_DATA_IN))
00140 {
00141
00142
00143
00144
00145
00146
00147 PERF_EVENT_VERBOSE(0x1018, sent);
00148
00149 cbmiec_wait_for_listener(Pdx,
00150 ((sent == (Count-1)) && (Atn == 0)) ? TRUE : FALSE);
00151
00152 PERF_EVENT_VERBOSE(0x1019, sent);
00153
00154 if(QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00155 {
00156 PERF_EVENT_VERBOSE(0x1020, 1);
00157
00158 ntStatus = STATUS_CANCELLED;
00159 }
00160 else
00161 {
00162 PERF_EVENT_VERBOSE(0x1020, 0);
00163
00164 if(cbmiec_send_byte(Pdx,c))
00165 {
00166 sent++;
00167 PERF_EVENT_VERBOSE(0x1021, 0);
00168 cbmiec_udelay(libiec_global_timeouts.T_12_SEND_AFTER_BYTE_DELAY);
00169 PERF_EVENT_VERBOSE(0x1022, 0);
00170 }
00171 else
00172 {
00173 PERF_EVENT_VERBOSE(0x1021, 1);
00174 DBG_ERROR((DBG_PREFIX "I/O error on cbmiec_send_byte()"));
00175 ntStatus = STATUS_NO_SUCH_DEVICE;
00176 PERF_EVENT_VERBOSE(0x1022, 1);
00177 }
00178 }
00179 }
00180 else
00181 {
00182 DBG_ERROR((DBG_PREFIX "device not present"));
00183 ntStatus = STATUS_NO_SUCH_DEVICE;
00184 }
00185 }
00186
00187 #if DBG
00188 if (ntStatus == STATUS_SUCCESS)
00189 {
00190 DBG_SUCCESS((DBG_PREFIX "%d bytes sent", sent));
00191 }
00192 else
00193 {
00194 DBG_ERROR((DBG_PREFIX "%d bytes sent, Status=%s", sent, DebugNtStatus(ntStatus)));
00195 }
00196 #endif
00197
00198 if (ntStatus == STATUS_SUCCESS && Talk)
00199 {
00200
00201
00202 PERF_EVENT_VERBOSE(0x1030, 0);
00203
00204 cbmiec_block_irq(Pdx);
00205
00206 PERF_EVENT_VERBOSE(0x1031, 0);
00207
00208 CBMIEC_SET(PP_DATA_OUT);
00209 CBMIEC_RELEASE(PP_ATN_OUT);
00210
00211 PERF_EVENT_VERBOSE(0x1032, 0);
00212
00213 cbmiec_udelay(libiec_global_timeouts.T_13_SEND_TURN_AROUND_LISTENER_TALKER_T_TK);
00214
00215 PERF_EVENT_VERBOSE(0x1033, 0);
00216
00217 CBMIEC_RELEASE(PP_CLK_OUT);
00218
00219 PERF_EVENT_VERBOSE(0x1034, 0);
00220
00221 cbmiec_release_irq(Pdx);
00222
00223 PERF_EVENT_VERBOSE(0x1035, 0);
00224 }
00225 else
00226 {
00227 CBMIEC_RELEASE(PP_ATN_OUT);
00228 }
00229 PERF_EVENT_VERBOSE(0x1036, 0);
00230 cbmiec_udelay(libiec_global_timeouts.T_14_SEND_AT_END_DELAY);
00231 PERF_EVENT_VERBOSE(0x1037, 0);
00232
00233 DBG_ASSERT(Sent != NULL);
00234 *Sent = sent;
00235
00236 FUNC_LEAVE_NTSTATUS(ntStatus);
00237 }