Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

mnib.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or
00003  *  modify it under the terms of the GNU General Public License
00004  *  as published by the Free Software Foundation; either version
00005  *  2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2000-2005 Markus Brenner
00008  *  Copyright 2000-2005 Pete Rittwage
00009  *  Copyright 2005      Tim Schürmann
00010  *  Copyright 2005      Spiro Trikaliotis
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); // @@@ DATA_IN ???
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;    // ensure to read once more
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)) // @@@ CLK_IN ???
00248             {
00249                 if (to++ > TO_HANDSHAKED_WRITE)
00250                     break;
00251             }
00252         }
00253         else
00254         {
00255             while (!CBMIEC_GET(PP_DATA_IN)) // @@@ CLK_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; // @@@ retval = 1 ???
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; // FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
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; // FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
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 }

Generated on Sun Apr 30 18:45:55 2006 for opencbm by  doxygen 1.4.2