OpenCBM
i_rawread.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 1999-2004 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
8  * Copyright 2001-2004 Spiro Trikaliotis
9  *
10  */
11 
22 #include <wdm.h>
23 #include "cbm_driver.h"
24 #include "i_iec.h"
25 
44 NTSTATUS
45 cbmiec_i_raw_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Buffer, ULONG Count, OUT ULONG *Received)
46 {
47  NTSTATUS ntStatus;
48  BOOLEAN ok;
49  ULONG received;
50  ULONG bit;
51  ULONG b;
52  ULONG i;
53  ULONG flags;
54 
55  FUNC_ENTER();
56 
57  DBG_ASSERT(Received != NULL);
58 
59  ok = TRUE;
60  received = 0;
61  *Received = 0;
62 
63  ntStatus = cbmiec_checkcable(Pdx);
64 
65  if (!NT_SUCCESS(ntStatus))
66  {
67  FUNC_LEAVE_NTSTATUS(ntStatus);
68  }
69 
70  // If there was already an eoi, we are ready
71 
72  if (Pdx->Eoi)
73  {
74  FUNC_LEAVE_NTSTATUS_CONST(STATUS_END_OF_FILE);
75  }
76 
77  // loop until we have read all bytes, or there was an eoi or an error
78 
79  do
80  {
81  PERF_EVENT_READ_BYTE_NO(received);
82 
83  i = 0;
84  while (CBMIEC_GET(PP_CLK_IN))
85  {
86  if (Pdx->IsSMP)
87  {
89  }
90  else
91  {
93  }
94 
95  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
96  {
97  *Received = received;
98  FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
99  }
100  }
101 
102  // As we need very exact timing, don't allow anyone to disturb us
103 
104  cbmiec_block_irq(Pdx);
105 
106  // Signal "We're ready for reading" to the other side
107 
109 
110  // Wait up to 400 us for a reply of the other side (TALKer)
111 
112  for(i = 0; (i < libiec_global_timeouts.T_2_Times) && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
113  {
115  }
116 
117  // Did we get an answer?
118 
119  if (!ok)
120  {
121  DBG_IEC((DBG_PREFIX "Got an EOI"));
122 
123  // No, so, the other device signals an EOI
124 
125  Pdx->Eoi = TRUE;
126 
127  // Tell the TALKer we recognized the EOI
128 
132  }
133 
134  // Now, wait up to 2 ms for the TALKer
135  // If we did an non-EOI answer, this loop will not be executed at all
136 
137  for (i = 0; (i < libiec_global_timeouts.T_4_Times) && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
138  {
139  DBG_IEC((DBG_PREFIX "Wait after EOI"));
141  }
142 
143 #if DBG
144  if (!ok)
145  {
146  DBG_ERROR((DBG_PREFIX "NOT OK after Wait after EOI"));
147  }
148 #endif // #if DBG
149 
150  for (bit = b = 0; (bit < 8) && ok; bit++)
151  {
153 
154  // Wait for CLK to be activated
155  // For this to occur, wait up to 200*T_5 (=2ms)
156 
157  for (i = 0; (i < libiec_global_timeouts.T_5_Times) && !(ok=(CBMIEC_GET(PP_CLK_IN)==0)); i++)
158  {
160  }
161 
162  // Did we get a CLK pulse?
163 
164  if (ok)
165  {
166  // Yes, shift the data to the right
167 
168  b >>= 1;
169 
170  // If the DATA pin is 0, we got a "1" bit; else, it is a "0"
171 
172  if (CBMIEC_GET(PP_DATA_IN) == 0)
173  {
174  // Set the highest bit (bits are given in LSB first
175  b |= 0x80;
176  }
177 
178  // Wait for CLK to be deactivated again
179  // For this to occur, wait up to 100 * T_6 (=2ms)
180 
181  for (i = 0; i < libiec_global_timeouts.T_6_Times && !(ok=CBMIEC_GET(PP_CLK_IN)); i++)
182  {
184  }
185 
186 #if DBG
187  if (!ok)
188  {
189  DBG_ERROR((DBG_PREFIX "CLK WAS NOT DEACTIVATED AGAIN"));
190  }
191 #endif // #if DBG
192  }
193  else
194  {
195  // An error occurred, it does not make sense to get more bits
196  DBG_ERROR((DBG_PREFIX "BREAKING OUT OF BIT-LOOP, no CLK pulse received. Bit %u, Value = %u", (unsigned int) bit, (unsigned int) b));
197  break;
198  }
199  }
200 
201  // If everything went fine, acknowledge the byte
202 
203  if (ok)
204  {
205  // set acknowledgement
207  }
208 #if DBG
209  else
210  {
211  DBG_ERROR((DBG_PREFIX "!OK -> no ACK"));
212  }
213 #endif // #if DBG
214 
215  // Our timing is not critical anymore, go back to the old IRQL
216 
217  cbmiec_release_irq(Pdx);
218 
219  // If everything went fine, remember the read byte
220 
221  if (ok)
222  {
224 
225  // One more byte has been received
226 
227  received++;
228 
229  // Store the received byte into the buffer
230 
231  *Buffer++ = (UCHAR) b;
232 
233  // Wait 70us between two bytes. Anyway, as we don't
234  // want to monopolize the complete CPU, schedule a
235  // timeout every 256 bytes.
236 
237  if (received % 256)
238  {
240  }
241  else
242  {
244  }
245  }
246  } while(received < Count && ok && !Pdx->Eoi);
247 
248 
249  if (ok)
250  {
251  DBG_SUCCESS((DBG_PREFIX "received=%d, count=%d, ok=%d, eoi=%d",
252  received, Count, ok, Pdx->Eoi));
253 
255  ntStatus = STATUS_SUCCESS;
256  }
257  else
258  {
259  DBG_ERROR((DBG_PREFIX "I/O error: received=%d, count=%d, ok=%d, eoi=%d",
260  received, Count, ok, Pdx->Eoi));
261 
263  Pdx->Eoi = FALSE;
264  ntStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
265  }
266 
267  DBG_ASSERT(Received != NULL);
268  *Received = received;
269 
270  FUNC_LEAVE_NTSTATUS(ntStatus);
271 }
VOID cbmiec_udelay(IN ULONG howlong)
Wait for a timeout.
Definition: libiec/util.c:66
ULONG T_1_RECV_WAIT_CLK_LOW_DATA_READY_GRANU
= 20 us: Starting reception, granularity for the wait until CLK is low
Definition: i_iec.h:91
IEC_TIMEOUTS libiec_global_timeouts
Definition: libiec/init.c:28
#define CBMIEC_GET(_line)
Definition: i_iec.h:75
#define PP_DATA_OUT
The DATA OUT bit.
Definition: i_iec.h:41
NTSTATUS cbmiec_i_raw_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Buffer, ULONG Count, OUT ULONG *Received)
Read some bytes from the IEC bus.
Definition: i_rawread.c:45
#define PP_CLK_IN
The CLOCK IN bit.
Definition: i_iec.h:50
ULONG T_5_Times
x T_5, is 200: How long to wait for CLK high (=active) for every single bit
Definition: i_iec.h:109
#define CBMIEC_SET(_set)
Definition: i_iec.h:64
ULONG T_5_RECV_BIT_WAIT_CLK_HIGH
= 10 us: Granularity: How long to wait for CLK high (=active) for every single bit ...
Definition: i_iec.h:112
ULONG T_6_Times
x T_6, is 100: How long to wait for CLK low again (=inactive) after every single bit ...
Definition: i_iec.h:115
ULONG T_4_Times
x T_4, is 100: Wait for CLK high after an EOI
Definition: i_iec.h:103
BOOLEAN QueueShouldCancelCurrentIrp(PQUEUE Queue)
Should the current IRP be cancelled?
Definition: queue.c:1041
Internal functions and definitions of the libiec library.
ULONG T_4_RECV_WAIT_CLK_HIGH_AFTER_EOI_GRANU
= 20 us: Granularity: Wait for CLK high after an EOI
Definition: i_iec.h:106
ULONG T_2_RECV_WAIT_CLK_HIGH_T_NE
= 10 us: Granularity: How long do we wait for the data of the other site
Definition: i_iec.h:97
VOID cbmiec_schedule_timeout(IN ULONG howlong)
Schedule a timeout.
Definition: libiec/util.c:34
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define DBG_ERROR(_xxx)
Definition: debug.h:397
ULONG T_7_RECV_INTER_BYTE_DELAY
= 70 us: Inter-byte delay on reception
Definition: i_iec.h:121
VOID cbmiec_setcablestate(PDEVICE_EXTENSION Pdx, CABLESTATE State)
Set the current state of the cable detection.
Definition: checkcable.c:494
#define PP_DATA_IN
The DATA IN bit.
Definition: i_iec.h:51
ULONG T_3_RECV_EOI_RECOGNIZED
= 70 us: How long to set DATA to ack an EOI
Definition: i_iec.h:100
#define DBG_SUCCESS(_xxx)
Definition: debug.h:393
#define CBMIEC_RELEASE(_rel)
Definition: i_iec.h:66
#define PERF_EVENT_READ_BYTE_NO(_x_)
Definition: cbm_driver.h:79
VOID cbmiec_block_irq(PDEVICE_EXTENSION Pdx)
Block all interrupts.
Definition: libiec/util.c:94
#define FUNC_ENTER()
Definition: debug.h:347
NTSTATUS cbmiec_checkcable(PDEVICE_EXTENSION Pdx)
Determine the type of cable (XA1541/XM1541) on the IEC bus.
Definition: checkcable.c:334
ULONG T_6_RECV_BIT_WAIT_CLK_LOW
= 20 us: How long to wait for CLK low again (=inactive) after every single bit
Definition: i_iec.h:118
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320
#define PERF_EVENT_READ_BYTE(_x_)
Definition: cbm_driver.h:81
VOID cbmiec_release_irq(PDEVICE_EXTENSION Pdx)
Release the interrupts.
Definition: libiec/util.c:118
#define PERF_EVENT_READ_BIT_NO(_x_)
Definition: cbm_driver.h:83
ULONG T_2_Times
x T_2 is 40
Definition: i_iec.h:94