00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00025 #define TO_HANDSHAKED_READ libiec_global_timeouts.T_PARALLEL_BURST_READ_BYTE_HANDSHAKED
00026 #define TO_HANDSHAKED_WRITE libiec_global_timeouts.T_PARALLEL_BURST_WRITE_BYTE_HANDSHAKED
00027
00028 #include <wdm.h>
00029 #include "cbm_driver.h"
00030 #include "i_iec.h"
00031
00032 #define PERF_EVENT_PARBURST_PAR_READ_ENTER() PERF_EVENT(0x5000, 0)
00033 #define PERF_EVENT_PARBURST_PAR_READ_DELAY1(_x_) PERF_EVENT(0x5001, _x_)
00034 #define PERF_EVENT_PARBURST_PAR_READ_PP_READ() PERF_EVENT(0x5002, 0)
00035 #define PERF_EVENT_PARBURST_PAR_READ_RELEASED(_x_) PERF_EVENT(0x5003, _x_)
00036 #define PERF_EVENT_PARBURST_PAR_READ_DELAY2(_x_) PERF_EVENT(0x5004, _x_)
00037 #define PERF_EVENT_PARBURST_PAR_READ_TIMEOUT(_x_) PERF_EVENT(0x5005, _x_)
00038 #define PERF_EVENT_PARBURST_PAR_READ_EXIT(_x_) PERF_EVENT(0x5006, _x_)
00039
00040 #define PERF_EVENT_PARBURST_PAR_WRITE_ENTER() PERF_EVENT(0x5100, 0)
00041 #define PERF_EVENT_PARBURST_PAR_WRITE_DELAY1(_x_) PERF_EVENT(0x5101, _x_)
00042 #define PERF_EVENT_PARBURST_PAR_WRITE_PP_WRITE(_x_) PERF_EVENT(0x5102, _x_)
00043 #define PERF_EVENT_PARBURST_PAR_WRITE_RELEASE() PERF_EVENT(0x5103, 0)
00044 #define PERF_EVENT_PARBURST_PAR_WRITE_DELAY2(_x_) PERF_EVENT(0x5104, _x_)
00045 #define PERF_EVENT_PARBURST_PAR_WRITE_DUMMY_READ(_x_) PERF_EVENT(0x5105, _x_)
00046
00047 #define PERF_EVENT_PARBURST_SEND_CMD(_x_) PERF_EVENT(0x5200, _x_)
00048
00049 #define PERF_EVENT_PARBURST_NREAD_RELEASE() PERF_EVENT(0x5300, 0)
00050 #define PERF_EVENT_PARBURST_NREAD_AFTERDELAY() PERF_EVENT(0x5301, 0)
00051 #define PERF_EVENT_PARBURST_NREAD_EXIT(_x_) PERF_EVENT(0x5302, _x_)
00052
00053 #define PERF_EVENT_PARBURST_NWRITE_RELEASE() PERF_EVENT(0x5400, 0)
00054 #define PERF_EVENT_PARBURST_NWRITE_VALUE(_x_) PERF_EVENT(0x5401, _x_)
00055 #define PERF_EVENT_PARBURST_NWRITE_EXIT(_x_) PERF_EVENT(0x5402, _x_)
00056
00057 #define PERF_EVENT_PARBURST_READ_TRACK_ENTER() PERF_EVENT(0x5500, 0)
00058 #define PERF_EVENT_PARBURST_READ_TRACK_STARTLOOP() PERF_EVENT(0x5500, 0)
00059 #define PERF_EVENT_PARBURST_READ_TRACK_VALUE(_x_) PERF_EVENT(0x5500, _x_)
00060 #define PERF_EVENT_PARBURST_READ_TRACK_TIMEOUT(_x_) PERF_EVENT(0x5500, _x_)
00061 #define PERF_EVENT_PARBURST_READ_TRACK_READ_DUMMY(_x_) PERF_EVENT(0x5500, _x_)
00062 #define PERF_EVENT_PARBURST_READ_TRACK_EXIT(_x_) PERF_EVENT(0x5500, _x_)
00063
00064 #define PERF_EVENT_PARBURST_WRITE_TRACK_ENTER() PERF_EVENT(0x5500, 0)
00065 #define PERF_EVENT_PARBURST_WRITE_TRACK_STARTLOOP() PERF_EVENT(0x5500, 0)
00066 #define PERF_EVENT_PARBURST_WRITE_TRACK_VALUE(_x_) PERF_EVENT(0x5500, _x_)
00067 #define PERF_EVENT_PARBURST_WRITE_TRACK_TIMEOUT(_x_) PERF_EVENT(0x5500, _x_)
00068 #define PERF_EVENT_PARBURST_WRITE_TRACK_EXIT(_x_) PERF_EVENT(0x5500, _x_)
00069
00070 NTSTATUS
00071 cbmiec_parallel_burst_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR* Byte)
00072 {
00073 FUNC_ENTER();
00074
00075 PERF_EVENT_PARBURST_PAR_READ_ENTER();
00076
00077 CBMIEC_RELEASE(PP_DATA_OUT|PP_CLK_OUT);
00078 CBMIEC_SET(PP_ATN_OUT);
00079
00080 PERF_EVENT_PARBURST_PAR_READ_DELAY1(0);
00081 cbmiec_udelay(200);
00082 PERF_EVENT_PARBURST_PAR_READ_DELAY1(1);
00083
00084 while(CBMIEC_GET(PP_DATA_IN))
00085 {
00086 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00087 {
00088 PERF_EVENT_PARBURST_PAR_READ_TIMEOUT(0);
00089 FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
00090 }
00091 }
00092
00093 PERF_EVENT_PARBURST_PAR_READ_PP_READ();
00094 cbmiec_pp_read(Pdx, Byte);
00095
00096 cbmiec_udelay(5);
00097 PERF_EVENT_PARBURST_PAR_READ_RELEASED(0);
00098 CBMIEC_RELEASE(PP_ATN_OUT);
00099 PERF_EVENT_PARBURST_PAR_READ_RELEASED(1);
00100
00101 PERF_EVENT_PARBURST_PAR_READ_DELAY2(0);
00102 cbmiec_udelay(10);
00103 PERF_EVENT_PARBURST_PAR_READ_DELAY2(1);
00104 while(!CBMIEC_GET(PP_DATA_IN))
00105 {
00106 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00107 {
00108 PERF_EVENT_PARBURST_PAR_READ_TIMEOUT(1);
00109 FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
00110 }
00111 }
00112
00113 PERF_EVENT_PARBURST_PAR_READ_EXIT(*Byte);
00114 FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
00115 }
00116
00117 NTSTATUS
00118 cbmiec_parallel_burst_write(IN PDEVICE_EXTENSION Pdx, IN UCHAR Byte)
00119 {
00120 UCHAR dummy;
00121 int j,to;
00122
00123 FUNC_ENTER();
00124
00125 PERF_EVENT_PARBURST_PAR_WRITE_ENTER();
00126
00127 CBMIEC_RELEASE(PP_DATA_OUT|PP_CLK_OUT);
00128 CBMIEC_SET(PP_ATN_OUT);
00129 PERF_EVENT_PARBURST_PAR_WRITE_DELAY1(0);
00130 cbmiec_udelay(200);
00131 PERF_EVENT_PARBURST_PAR_WRITE_DELAY1(1);
00132
00133 while(CBMIEC_GET(PP_DATA_IN))
00134 {
00135 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00136 {
00137 FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
00138 }
00139 }
00140
00141 PERF_EVENT_PARBURST_PAR_WRITE_PP_WRITE(Byte);
00142 cbmiec_pp_write(Pdx, Byte);
00143
00144 cbmiec_udelay(5);
00145 CBMIEC_RELEASE(PP_ATN_OUT);
00146 PERF_EVENT_PARBURST_PAR_WRITE_DELAY2(0);
00147 cbmiec_udelay(20);
00148 PERF_EVENT_PARBURST_PAR_WRITE_DELAY2(1);
00149
00150 while(!CBMIEC_GET(PP_DATA_IN))
00151 {
00152 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00153 {
00154 FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
00155 }
00156 }
00157
00158 PERF_EVENT_PARBURST_PAR_WRITE_DUMMY_READ(0);
00159 cbmiec_pp_read(Pdx, &dummy);
00160 PERF_EVENT_PARBURST_PAR_WRITE_DUMMY_READ(dummy);
00161
00162 FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
00163 }
00164
00165 static int
00166 cbm_handshaked_read(PDEVICE_EXTENSION Pdx, int Toggle)
00167 {
00168 unsigned int to = 0;
00169 int j;
00170 int returnValue;
00171
00172 FUNC_ENTER();
00173
00174 PERF_EVENT_PARBURST_NREAD_RELEASE();
00175 CBMIEC_RELEASE(PP_DATA_OUT);
00176
00177 cbmiec_udelay(2);
00178 PERF_EVENT_PARBURST_NREAD_AFTERDELAY();
00179
00180 if (!Toggle)
00181 {
00182 while (CBMIEC_GET(PP_DATA_IN))
00183 {
00184 if (to++ > TO_HANDSHAKED_READ)
00185 break;
00186 }
00187 }
00188 else
00189 {
00190 while (!CBMIEC_GET(PP_DATA_IN))
00191 {
00192 if (to++ > TO_HANDSHAKED_READ)
00193 break;
00194 }
00195 }
00196
00197 PERF_EVENT_PARBURST_NREAD_EXIT(to > TO_HANDSHAKED_READ ? -1 : 0);
00198
00199 if (to > TO_HANDSHAKED_READ)
00200 {
00201 returnValue = -1;
00202 }
00203 else
00204 {
00205 static int oldValue = -1;
00206
00207 int returnValue2, returnValue3, timeoutCount=0;
00208
00209 returnValue3 = READ_PORT_UCHAR(PAR_PORT);
00210 returnValue2 = ~returnValue3;
00211
00212 do {
00213 if (++timeoutCount >= 8)
00214 {
00215 DBG_PRINT((DBG_PREFIX "Triple-Debounce TIMEOUT: 0x%02x, 0x%02x, 0x%02x (%d, 0x%02x)",
00216 returnValue, returnValue2, returnValue3, timeoutCount, oldValue));
00217 break;
00218 }
00219 returnValue = returnValue2;
00220 returnValue2 = returnValue3;
00221 returnValue3 = READ_PORT_UCHAR(PAR_PORT);
00222 } while ((returnValue != returnValue2) || (returnValue != returnValue3));
00223
00224 oldValue = returnValue3;
00225 }
00226
00227 return returnValue;
00228 }
00229
00230 static int
00231 cbm_handshaked_write(PDEVICE_EXTENSION Pdx, char Data, int Toggle)
00232 {
00233 unsigned int to=0;
00234 int retval;
00235
00236 FUNC_ENTER();
00237
00238 PERF_EVENT_PARBURST_NWRITE_RELEASE();
00239 CBMIEC_RELEASE(PP_CLK_IN);
00240
00241 do
00242 {
00243 retval = 1;
00244
00245 if (!Toggle)
00246 {
00247 while (CBMIEC_GET(PP_DATA_IN))
00248 {
00249 if (to++ > TO_HANDSHAKED_WRITE)
00250 break;
00251 }
00252 }
00253 else
00254 {
00255 while (!CBMIEC_GET(PP_DATA_IN))
00256 {
00257 if (to++ > TO_HANDSHAKED_WRITE)
00258 break;
00259 }
00260 }
00261
00262 if (to++ <= TO_HANDSHAKED_WRITE)
00263 {
00264 PERF_EVENT_PARBURST_NWRITE_VALUE(Data);
00265 cbmiec_pp_write(Pdx, Data);
00266 retval = 0;
00267 }
00268
00269 } while (0);
00270
00271 PERF_EVENT_PARBURST_NWRITE_EXIT(retval);
00272 FUNC_LEAVE_INT(retval);
00273 }
00274
00275 #define enable() cbmiec_release_irq(Pdx)
00276 #define disable() cbmiec_block_irq(Pdx)
00277
00278 NTSTATUS
00279 cbmiec_parallel_burst_read_track(IN PDEVICE_EXTENSION Pdx, OUT UCHAR* Buffer, IN ULONG ReturnLength)
00280 {
00281 NTSTATUS ntStatus;
00282 ULONG i;
00283 UCHAR dummy;
00284
00285 int timeout = 0;
00286 int byte;
00287
00288 FUNC_ENTER();
00289
00290 PERF_EVENT_PARBURST_READ_TRACK_ENTER();
00291
00292 disable();
00293
00294 PERF_EVENT_PARBURST_READ_TRACK_STARTLOOP();
00295
00296 for (i = 0; i < ReturnLength; i ++)
00297 {
00298 byte = cbm_handshaked_read(Pdx, i&1);
00299 PERF_EVENT_PARBURST_READ_TRACK_VALUE(byte);
00300 if (byte == -1)
00301 {
00302 PERF_EVENT_PARBURST_READ_TRACK_TIMEOUT(0);
00303 timeout = 1;
00304 break;
00305 }
00306 Buffer[i] = (UCHAR) byte;
00307
00308 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00309 {
00310 PERF_EVENT_PARBURST_READ_TRACK_TIMEOUT(1);
00311 timeout = 1;
00312 }
00313 }
00314
00315 if(!timeout)
00316 {
00317 cbmiec_parallel_burst_read(Pdx, &dummy);
00318 PERF_EVENT_PARBURST_READ_TRACK_READ_DUMMY(dummy);
00319 enable();
00320 ntStatus = STATUS_SUCCESS;
00321 }
00322 else
00323 {
00324 enable();
00325 DBG_PRINT((DBG_PREFIX "timeout failure! Wanted to read %u, but only read %u",
00326 ReturnLength, i));
00327 ntStatus = STATUS_DATA_ERROR;
00328 }
00329
00330 PERF_EVENT_PARBURST_READ_TRACK_EXIT(ntStatus);
00331
00332 FUNC_LEAVE_NTSTATUS(ntStatus);
00333 }
00334
00335 NTSTATUS
00336 cbmiec_parallel_burst_write_track(IN PDEVICE_EXTENSION Pdx, IN UCHAR* Buffer, IN ULONG BufferLength)
00337 {
00338 NTSTATUS ntStatus;
00339 UCHAR dummy;
00340
00341 ULONG i = 0;
00342
00343 int timeout = 0;
00344
00345 FUNC_ENTER();
00346
00347 PERF_EVENT_PARBURST_WRITE_TRACK_ENTER();
00348
00349 disable();
00350
00351 PERF_EVENT_PARBURST_WRITE_TRACK_STARTLOOP();
00352
00353 for (i = 0; i < BufferLength; i++)
00354 {
00355 PERF_EVENT_PARBURST_WRITE_TRACK_VALUE(Buffer[i]);
00356 if(cbm_handshaked_write(Pdx, Buffer[i], i&1))
00357 {
00358 PERF_EVENT_PARBURST_WRITE_TRACK_TIMEOUT(0);
00359 timeout = 1;
00360 break;
00361 }
00362
00363 if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00364 {
00365 PERF_EVENT_PARBURST_WRITE_TRACK_TIMEOUT(1);
00366 timeout = 1;
00367 }
00368 }
00369
00370 if(!timeout)
00371 {
00372 cbm_handshaked_write(Pdx, 0, i&1);
00373 cbmiec_parallel_burst_read(Pdx, &dummy);
00374 enable();
00375 ntStatus = STATUS_SUCCESS;
00376 }
00377 else
00378 {
00379 enable();
00380 DBG_PRINT((DBG_PREFIX "timeout failure! Wanted to write %u, but only wrote %u",
00381 BufferLength, i));
00382 ntStatus = STATUS_DATA_ERROR;
00383 }
00384
00385 PERF_EVENT_PARBURST_WRITE_TRACK_EXIT(ntStatus);
00386
00387 FUNC_LEAVE_NTSTATUS(ntStatus);
00388 }