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

i_rawread.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 1999-2004 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
00008  *  Copyright 2001-2004 Spiro Trikaliotis
00009  *
00010  */
00011 
00023 #include <wdm.h>
00024 #include "cbm_driver.h"
00025 #include "i_iec.h"
00026 
00045 NTSTATUS
00046 cbmiec_i_raw_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Buffer, ULONG Count, OUT ULONG *Received)
00047 {
00048     NTSTATUS ntStatus;
00049     BOOLEAN ok;
00050     ULONG received;
00051     ULONG bit;
00052     ULONG b;
00053     ULONG i;
00054     ULONG flags;
00055 
00056     FUNC_ENTER();
00057 
00058     DBG_ASSERT(Received != NULL);
00059 
00060     ok = TRUE;
00061     received = 0;
00062     *Received = 0;
00063 
00064     // If there was already an eoi, we are ready
00065 
00066     if (Pdx->Eoi)
00067     {
00068         FUNC_LEAVE_NTSTATUS_CONST(STATUS_END_OF_FILE);
00069     }
00070 
00071     // loop until we have read all bytes, or there was an eoi or an error
00072 
00073     do
00074     {
00075         PERF_EVENT_READ_BYTE_NO(received);
00076 
00077         i = 0;
00078         while (CBMIEC_GET(PP_CLK_IN))
00079         {
00080             if (Pdx->IsSMP)
00081             {
00082                 cbmiec_udelay(libiec_global_timeouts.T_1_RECV_WAIT_CLK_LOW_DATA_READY_GRANU);
00083             }
00084             else
00085             {
00086                 cbmiec_schedule_timeout(libiec_global_timeouts.T_1_RECV_WAIT_CLK_LOW_DATA_READY_GRANU);
00087             }
00088 
00089             if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
00090             {
00091                 *Received = received;
00092                 FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
00093             }
00094         }
00095 
00096         // As we need very exact timing, don't allow anyone to disturb us
00097 
00098         cbmiec_block_irq(Pdx);
00099 
00100         // Signal "We're ready for reading" to the other side
00101 
00102         CBMIEC_RELEASE(PP_DATA_OUT);
00103 
00104         // Wait up to 400 us for a reply of the other side (TALKer)
00105 
00106         for(i = 0; (i < libiec_global_timeouts.T_2_Times) && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
00107         {
00108             cbmiec_udelay(libiec_global_timeouts.T_2_RECV_WAIT_CLK_HIGH_T_NE);
00109         }
00110 
00111         // Did we get an answer?
00112 
00113         if (!ok)
00114         {
00115             DBG_IEC((DBG_PREFIX "Got an EOI"));
00116 
00117             // No, so, the other device signals an EOI
00118 
00119             Pdx->Eoi = TRUE;
00120 
00121             // Tell the TALKer we recognized the EOI
00122 
00123             CBMIEC_SET(PP_DATA_OUT);
00124             cbmiec_udelay(libiec_global_timeouts.T_3_RECV_EOI_RECOGNIZED);
00125             CBMIEC_RELEASE(PP_DATA_OUT);
00126         }
00127 
00128         // Now, wait up to 2 ms for the TALKer 
00129         // If we did an non-EOI answer, this loop will not be executed at all
00130 
00131         for (i = 0; (i < libiec_global_timeouts.T_4_Times) && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
00132         {
00133             DBG_IEC((DBG_PREFIX "Wait after EOI"));
00134             cbmiec_udelay(libiec_global_timeouts.T_4_RECV_WAIT_CLK_HIGH_AFTER_EOI_GRANU);
00135         }
00136 
00137 #if DBG
00138         if (!ok)
00139         {
00140             DBG_ERROR((DBG_PREFIX "NOT OK after Wait after EOI"));
00141         }
00142 #endif // #if DBG
00143 
00144         for (bit = b = 0; (bit < 8) && ok; bit++)
00145         {
00146             PERF_EVENT_READ_BIT_NO(bit);
00147 
00148             // Wait for CLK to be activated 
00149             // For this to occur, wait up to 200*T_5 (=2ms)
00150 
00151             for (i = 0; (i < libiec_global_timeouts.T_5_Times) && !(ok=(CBMIEC_GET(PP_CLK_IN)==0)); i++)
00152             {
00153                 cbmiec_udelay(libiec_global_timeouts.T_5_RECV_BIT_WAIT_CLK_HIGH);
00154             }
00155 
00156             // Did we get a CLK pulse?
00157 
00158             if (ok)
00159             {
00160                 // Yes, shift the data to the right
00161 
00162                 b >>= 1;
00163 
00164                 // If the DATA pin is 0, we got a "1" bit; else, it is a "0"
00165 
00166                 if (CBMIEC_GET(PP_DATA_IN) == 0)
00167                 {
00168                     // Set the highest bit (bits are given in LSB first
00169                     b |= 0x80;
00170                 }
00171 
00172                 // Wait for CLK to be deactivated again
00173                 // For this to occur, wait up to 100 * T_6 (=2ms)
00174 
00175                 for (i = 0; i < libiec_global_timeouts.T_6_Times && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
00176                 {
00177                     cbmiec_udelay(libiec_global_timeouts.T_6_RECV_BIT_WAIT_CLK_LOW);
00178                 }
00179 
00180 #if DBG
00181                 if (!ok)
00182                 {
00183                     DBG_ERROR((DBG_PREFIX "CLK WAS NOT DEACTIVATED AGAIN"));
00184                 }
00185 #endif // #if DBG
00186             }
00187             else
00188             {
00189                 // An error occurred, it does not make sense to get more bits 
00190                 DBG_ERROR((DBG_PREFIX "BREAKING OUT OF BIT-LOOP, no CLK pulse received. Bit %u, Value = %u", (unsigned int) bit, (unsigned int) b));
00191                 break;
00192             }
00193         }
00194 
00195         // If everything went fine, acknowledge the byte
00196 
00197         if (ok)
00198         {
00199             // set acknowledgement
00200             CBMIEC_SET(PP_DATA_OUT);
00201         }
00202 #if DBG
00203         else
00204         {
00205             DBG_ERROR((DBG_PREFIX "!OK -> no ACK"));
00206         }
00207 #endif // #if DBG
00208 
00209         // Our timing is not critical anymore, go back to the old IRQL
00210 
00211         cbmiec_release_irq(Pdx);
00212 
00213         // If everything went fine, remember the read byte
00214 
00215         if (ok)
00216         {
00217             PERF_EVENT_READ_BYTE(b);
00218 
00219             // One more byte has been received
00220 
00221             received++;
00222 
00223             // Store the received byte into the buffer
00224 
00225             *Buffer++ = (UCHAR) b;
00226 
00227             // Wait 70us between two bytes. Anyway, as we don't
00228             // want to monopolize the complete CPU, schedule a
00229             // timeout every 256 bytes.
00230 
00231             if (Count % 256)
00232             {
00233                 cbmiec_udelay(libiec_global_timeouts.T_7_RECV_INTER_BYTE_DELAY);
00234             }
00235             else
00236             {
00237                 cbmiec_schedule_timeout(libiec_global_timeouts.T_7_RECV_INTER_BYTE_DELAY);
00238             }
00239         }
00240     } while(received < Count && ok && !Pdx->Eoi);
00241 
00242 
00243     if (ok) 
00244     {
00245         DBG_SUCCESS((DBG_PREFIX "received=%d, count=%d, ok=%d, eoi=%d",
00246             received, Count, ok, Pdx->Eoi));
00247 
00248         ntStatus = STATUS_SUCCESS;
00249     }
00250     else
00251     {
00252         DBG_ERROR((DBG_PREFIX "I/O error: received=%d, count=%d, ok=%d, eoi=%d",
00253             received, Count, ok, Pdx->Eoi));
00254 
00255         Pdx->Eoi = 0;
00256         ntStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
00257     }
00258 
00259     DBG_ASSERT(Received != NULL);
00260     *Received = received;
00261 
00262     FUNC_LEAVE_NTSTATUS(ntStatus);
00263 }

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