OpenCBM
mnib.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 2000-2005 Markus Brenner
8  * Copyright 2000-2005 Pete Rittwage
9  * Copyright 2005 Tim Schürmann
10  * Copyright 2005,2009 Spiro Trikaliotis
11  * Copyright 2009 Arnd M.
12  *
13  */
14 
25 #define TO_HANDSHAKED_READ libiec_global_timeouts.T_PARALLEL_BURST_READ_BYTE_HANDSHAKED
26 #define TO_HANDSHAKED_WRITE libiec_global_timeouts.T_PARALLEL_BURST_WRITE_BYTE_HANDSHAKED
28 #include <wdm.h>
29 #include "cbm_driver.h"
30 #include "i_iec.h"
31 
32 #define PERF_EVENT_PARBURST_PAR_READ_ENTER() PERF_EVENT(0x5000, 0)
33 #define PERF_EVENT_PARBURST_PAR_READ_DELAY1(_x_) PERF_EVENT(0x5001, _x_)
34 #define PERF_EVENT_PARBURST_PAR_READ_PP_READ() PERF_EVENT(0x5002, 0)
35 #define PERF_EVENT_PARBURST_PAR_READ_RELEASED(_x_) PERF_EVENT(0x5003, _x_)
36 #define PERF_EVENT_PARBURST_PAR_READ_DELAY2(_x_) PERF_EVENT(0x5004, _x_)
37 #define PERF_EVENT_PARBURST_PAR_READ_TIMEOUT(_x_) PERF_EVENT(0x5005, _x_)
38 #define PERF_EVENT_PARBURST_PAR_READ_EXIT(_x_) PERF_EVENT(0x5006, _x_)
40 #define PERF_EVENT_PARBURST_PAR_WRITE_ENTER() PERF_EVENT(0x5100, 0)
41 #define PERF_EVENT_PARBURST_PAR_WRITE_DELAY1(_x_) PERF_EVENT(0x5101, _x_)
42 #define PERF_EVENT_PARBURST_PAR_WRITE_PP_WRITE(_x_) PERF_EVENT(0x5102, _x_)
43 #define PERF_EVENT_PARBURST_PAR_WRITE_RELEASE() PERF_EVENT(0x5103, 0)
44 #define PERF_EVENT_PARBURST_PAR_WRITE_DELAY2(_x_) PERF_EVENT(0x5104, _x_)
45 #define PERF_EVENT_PARBURST_PAR_WRITE_DUMMY_READ(_x_) PERF_EVENT(0x5105, _x_)
47 #define PERF_EVENT_PARBURST_SEND_CMD(_x_) PERF_EVENT(0x5200, _x_)
49 #define PERF_EVENT_PARBURST_NREAD_RELEASE() PERF_EVENT(0x5300, 0)
50 #define PERF_EVENT_PARBURST_NREAD_AFTERDELAY() PERF_EVENT(0x5301, 0)
51 #define PERF_EVENT_PARBURST_NREAD_EXIT(_x_) PERF_EVENT(0x5302, _x_)
53 #define PERF_EVENT_PARBURST_NWRITE_RELEASE() PERF_EVENT(0x5400, 0)
54 #define PERF_EVENT_PARBURST_NWRITE_VALUE(_x_) PERF_EVENT(0x5401, _x_)
55 #define PERF_EVENT_PARBURST_NWRITE_EXIT(_x_) PERF_EVENT(0x5402, _x_)
57 #define PERF_EVENT_PARBURST_READ_TRACK_ENTER() PERF_EVENT(0x5500, 0)
58 #define PERF_EVENT_PARBURST_READ_TRACK_STARTLOOP() PERF_EVENT(0x5500, 0)
59 #define PERF_EVENT_PARBURST_READ_TRACK_VALUE(_x_) PERF_EVENT(0x5500, _x_)
60 #define PERF_EVENT_PARBURST_READ_TRACK_TIMEOUT(_x_) PERF_EVENT(0x5500, _x_)
61 #define PERF_EVENT_PARBURST_READ_TRACK_READ_DUMMY(_x_) PERF_EVENT(0x5500, _x_)
62 #define PERF_EVENT_PARBURST_READ_TRACK_EXIT(_x_) PERF_EVENT(0x5500, _x_)
64 #define PERF_EVENT_PARBURST_WRITE_TRACK_ENTER() PERF_EVENT(0x5500, 0)
65 #define PERF_EVENT_PARBURST_WRITE_TRACK_STARTLOOP() PERF_EVENT(0x5500, 0)
66 #define PERF_EVENT_PARBURST_WRITE_TRACK_VALUE(_x_) PERF_EVENT(0x5500, _x_)
67 #define PERF_EVENT_PARBURST_WRITE_TRACK_TIMEOUT(_x_) PERF_EVENT(0x5500, _x_)
68 #define PERF_EVENT_PARBURST_WRITE_TRACK_EXIT(_x_) PERF_EVENT(0x5500, _x_)
78 NTSTATUS
79 cbmiec_parallel_burst_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR* Byte)
80 {
81  FUNC_ENTER();
82 
84 
87 
89  cbmiec_udelay(200);
91 
92  while(CBMIEC_GET(PP_DATA_IN))
93  {
94  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
95  {
97  FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
98  }
99  }
100 
102  cbmiec_pp_read(Pdx, Byte);
103 
104  cbmiec_udelay(5);
108 
110  cbmiec_udelay(10);
112  while(!CBMIEC_GET(PP_DATA_IN))
113  {
114  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
115  {
117  FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
118  }
119  }
120 
122  FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
123 }
124 
133 NTSTATUS
134 cbmiec_parallel_burst_write(IN PDEVICE_EXTENSION Pdx, IN UCHAR Byte)
135 {
136  UCHAR dummy;
137  int j,to;
138 
139  FUNC_ENTER();
140 
142 
146  cbmiec_udelay(200);
148 
149  while(CBMIEC_GET(PP_DATA_IN))
150  {
151  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
152  {
153  FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
154  }
155  }
156 
158  cbmiec_pp_write(Pdx, Byte);
159 
160  cbmiec_udelay(5);
163  cbmiec_udelay(20);
165 
166  while(!CBMIEC_GET(PP_DATA_IN))
167  {
168  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
169  {
170  FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
171  }
172  }
173 
175  cbmiec_pp_read(Pdx, &dummy);
177 
178  FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
179 }
180 
189 static int
190 cbm_handshaked_read(PDEVICE_EXTENSION Pdx, int Toggle)
191 {
192  unsigned int to = 0;
193  int j;
194  int returnValue;
195 
196  FUNC_ENTER();
197 
199  CBMIEC_RELEASE(PP_DATA_OUT); // @@@ DATA_IN ???
200 
201  cbmiec_udelay(2);
203 
204  if (!Toggle)
205  {
206  while (CBMIEC_GET(PP_DATA_IN))
207  {
208  if (to++ > TO_HANDSHAKED_READ)
209  break;
210  }
211  }
212  else
213  {
214  while (!CBMIEC_GET(PP_DATA_IN))
215  {
216  if (to++ > TO_HANDSHAKED_READ)
217  break;
218  }
219  }
220 
222 
223  if (to > TO_HANDSHAKED_READ)
224  {
225  returnValue = -1;
226  }
227  else
228  {
229  returnValue = cbmiec_i_pp_read_debounced(Pdx);
230  }
231 
232  return returnValue;
233 }
234 
245 static int
246 cbm_handshaked_write(PDEVICE_EXTENSION Pdx, char Data, int Toggle)
247 {
248  unsigned int to=0;
249  int retval;
250 
251  FUNC_ENTER();
252 
255 
256  do
257  {
258  retval = 1;
259 
260  if (!Toggle)
261  {
262  while (CBMIEC_GET(PP_DATA_IN)) // @@@ CLK_IN ???
263  {
264  if (to++ > TO_HANDSHAKED_WRITE)
265  break;
266  }
267  }
268  else
269  {
270  while (!CBMIEC_GET(PP_DATA_IN)) // @@@ CLK_IN ???
271  {
272  if (to++ > TO_HANDSHAKED_WRITE)
273  break;
274  }
275  }
276 
277  if (to++ <= TO_HANDSHAKED_WRITE)
278  {
280  cbmiec_pp_write(Pdx, Data);
281  retval = 0; // @@@ retval = 1 ???
282  }
283 
284  } while (0);
285 
287  FUNC_LEAVE_INT(retval);
288 }
289 
290 #define enable() cbmiec_release_irq(Pdx)
291 #define disable() cbmiec_block_irq(Pdx)
303 NTSTATUS
304 cbmiec_parallel_burst_read_track(IN PDEVICE_EXTENSION Pdx, OUT UCHAR* Buffer, IN ULONG ReturnLength)
305 {
306  NTSTATUS ntStatus;
307  ULONG i;
308  UCHAR dummy;
309 
310  int timeout = 0;
311  int byte;
312 
313  FUNC_ENTER();
314 
316 
317  disable();
318 
320 
321  for (i = 0; i < ReturnLength; i ++)
322  {
323  byte = cbm_handshaked_read(Pdx, i&1);
325  if (byte == -1)
326  {
328  timeout = 1;
329  break;
330  }
331  Buffer[i] = (UCHAR) byte;
332 
333  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
334  {
336  timeout = 1; // FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
337  }
338  }
339 
340  if(!timeout)
341  {
342  cbmiec_parallel_burst_read(Pdx, &dummy);
344  enable();
345  ntStatus = STATUS_SUCCESS;
346  }
347  else
348  {
349  enable();
350  DBG_PRINT((DBG_PREFIX "timeout failure! Wanted to read %u, but only read %u",
351  ReturnLength, i));
352  ntStatus = STATUS_DATA_ERROR;
353  }
354 
356 
357  FUNC_LEAVE_NTSTATUS(ntStatus);
358 }
359 
370 NTSTATUS
371 cbmiec_parallel_burst_read_track_var(IN PDEVICE_EXTENSION Pdx, OUT UCHAR* Buffer, IN ULONG ReturnLength)
372 {
373  NTSTATUS ntStatus;
374  ULONG i;
375  UCHAR dummy;
376 
377  int timeout = 0;
378  int byte;
379 
380  FUNC_ENTER();
381 
383 
384  disable();
385 
387 
388  for (i = 0; i < ReturnLength; i ++)
389  {
390  byte = cbm_handshaked_read(Pdx, i&1);
392  if (byte == -1)
393  {
395  timeout = 1;
396  break;
397  }
398  Buffer[i] = (UCHAR) byte;
399  if (byte == 0x55) break;
400 
401  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
402  {
404  timeout = 1; // FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
405  }
406  }
407 
408  if(!timeout)
409  {
410  cbmiec_parallel_burst_read(Pdx, &dummy);
412  enable();
413  ntStatus = STATUS_SUCCESS;
414  }
415  else
416  {
417  enable();
418  DBG_PRINT((DBG_PREFIX "timeout failure! Wanted to read %u, but only read %u",
419  ReturnLength, i));
420  ntStatus = STATUS_DATA_ERROR;
421  }
422 
424 
425  FUNC_LEAVE_NTSTATUS(ntStatus);
426 }
427 
428 NTSTATUS
429 cbmiec_parallel_burst_write_track(IN PDEVICE_EXTENSION Pdx, IN UCHAR* Buffer, IN ULONG BufferLength)
430 {
431  NTSTATUS ntStatus;
432  UCHAR dummy;
433 
434  ULONG i = 0;
435 
436  int timeout = 0;
437 
438  FUNC_ENTER();
439 
441 
442  disable();
443 
445 
446  for (i = 0; i < BufferLength; i++)
447  {
449  if(cbm_handshaked_write(Pdx, Buffer[i], i&1))
450  {
452  timeout = 1;
453  break;
454  }
455 
456  if (QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
457  {
459  timeout = 1; // FUNC_LEAVE_NTSTATUS_CONST(STATUS_TIMEOUT);
460  }
461  }
462 
463  if(!timeout)
464  {
465  cbm_handshaked_write(Pdx, 0, i&1);
466  cbmiec_parallel_burst_read(Pdx, &dummy);
467  enable();
468  ntStatus = STATUS_SUCCESS;
469  }
470  else
471  {
472  enable();
473  DBG_PRINT((DBG_PREFIX "timeout failure! Wanted to write %u, but only wrote %u",
474  BufferLength, i));
475  ntStatus = STATUS_DATA_ERROR;
476  }
477 
479 
480  FUNC_LEAVE_NTSTATUS(ntStatus);
481 }
VOID cbmiec_udelay(IN ULONG howlong)
Wait for a timeout.
Definition: libiec/util.c:66
#define PERF_EVENT_PARBURST_PAR_WRITE_DELAY1(_x_)
Definition: mnib.c:41
#define PERF_EVENT_PARBURST_READ_TRACK_READ_DUMMY(_x_)
Definition: mnib.c:61
#define CBMIEC_GET(_line)
Definition: i_iec.h:75
#define PP_ATN_OUT
The ATN OUT bit.
Definition: i_iec.h:39
#define TO_HANDSHAKED_READ
Definition: mnib.c:25
#define PERF_EVENT_PARBURST_NWRITE_EXIT(_x_)
Definition: mnib.c:55
#define PP_DATA_OUT
The DATA OUT bit.
Definition: i_iec.h:41
#define PERF_EVENT_PARBURST_PAR_READ_DELAY2(_x_)
Definition: mnib.c:36
#define FUNC_LEAVE_INT(_xxx)
Definition: debug.h:358
#define PP_CLK_IN
The CLOCK IN bit.
Definition: i_iec.h:50
#define PERF_EVENT_PARBURST_PAR_READ_EXIT(_x_)
Definition: mnib.c:38
#define PERF_EVENT_PARBURST_PAR_READ_PP_READ()
Definition: mnib.c:34
NTSTATUS cbmiec_parallel_burst_read_track_var(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Buffer, IN ULONG ReturnLength)
@@@
Definition: mnib.c:371
#define PERF_EVENT_PARBURST_NWRITE_VALUE(_x_)
Definition: mnib.c:54
#define PERF_EVENT_PARBURST_WRITE_TRACK_EXIT(_x_)
Definition: mnib.c:68
NTSTATUS cbmiec_parallel_burst_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Byte)
@@@
Definition: mnib.c:79
NTSTATUS cbmiec_parallel_burst_write(IN PDEVICE_EXTENSION Pdx, IN UCHAR Byte)
@@@
Definition: mnib.c:134
#define PERF_EVENT_PARBURST_NREAD_AFTERDELAY()
Definition: mnib.c:50
#define TO_HANDSHAKED_WRITE
Definition: mnib.c:26
#define CBMIEC_SET(_set)
Definition: i_iec.h:64
NTSTATUS cbmiec_parallel_burst_read_track(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Buffer, IN ULONG ReturnLength)
@@@
Definition: mnib.c:304
BOOLEAN QueueShouldCancelCurrentIrp(PQUEUE Queue)
Should the current IRP be cancelled?
Definition: queue.c:1041
#define PERF_EVENT_PARBURST_READ_TRACK_TIMEOUT(_x_)
Definition: mnib.c:60
Internal functions and definitions of the libiec library.
#define PERF_EVENT_PARBURST_NREAD_RELEASE()
Definition: mnib.c:49
#define PERF_EVENT_PARBURST_PAR_READ_DELAY1(_x_)
Definition: mnib.c:33
#define PERF_EVENT_PARBURST_READ_TRACK_ENTER()
Definition: mnib.c:57
#define PERF_EVENT_PARBURST_PAR_READ_RELEASED(_x_)
Definition: mnib.c:35
#define disable()
Definition: mnib.c:291
#define PP_DATA_IN
The DATA IN bit.
Definition: i_iec.h:51
#define PERF_EVENT_PARBURST_PAR_WRITE_ENTER()
Definition: mnib.c:40
#define CBMIEC_RELEASE(_rel)
Definition: i_iec.h:66
#define PP_CLK_OUT
The CLOCK OUT bit.
Definition: i_iec.h:40
LONG cbmiec_i_pp_read_debounced(IN PDEVICE_EXTENSION Pdx)
Read a byte from the X[M|A]P1541 cable. Make sure to debounce it.
Definition: ppread.c:39
#define PERF_EVENT_PARBURST_WRITE_TRACK_ENTER()
Definition: mnib.c:64
#define PERF_EVENT_PARBURST_PAR_READ_ENTER()
Definition: mnib.c:32
#define PERF_EVENT_PARBURST_WRITE_TRACK_VALUE(_x_)
Definition: mnib.c:66
#define FUNC_ENTER()
Definition: debug.h:347
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320
#define PERF_EVENT_PARBURST_WRITE_TRACK_TIMEOUT(_x_)
Definition: mnib.c:67
#define PERF_EVENT_PARBURST_PAR_WRITE_DELAY2(_x_)
Definition: mnib.c:44
#define PERF_EVENT_PARBURST_PAR_READ_TIMEOUT(_x_)
Definition: mnib.c:37
#define PERF_EVENT_PARBURST_NREAD_EXIT(_x_)
Definition: mnib.c:51
#define PERF_EVENT_PARBURST_READ_TRACK_STARTLOOP()
Definition: mnib.c:58
#define PERF_EVENT_PARBURST_WRITE_TRACK_STARTLOOP()
Definition: mnib.c:65
#define PERF_EVENT_PARBURST_NWRITE_RELEASE()
Definition: mnib.c:53
#define PERF_EVENT_PARBURST_READ_TRACK_EXIT(_x_)
Definition: mnib.c:62
#define PERF_EVENT_PARBURST_PAR_WRITE_DUMMY_READ(_x_)
Definition: mnib.c:45
NTSTATUS cbmiec_pp_write(IN PDEVICE_EXTENSION Pdx, IN UCHAR Byte)
Write a byte to the X[M|A]P1541 cable.
Definition: ppwrite.c:42
#define enable()
Definition: mnib.c:290
#define PERF_EVENT_PARBURST_PAR_WRITE_PP_WRITE(_x_)
Definition: mnib.c:42
#define PERF_EVENT_PARBURST_READ_TRACK_VALUE(_x_)
Definition: mnib.c:59
#define DBG_PRINT(_xxx)
Definition: debug.h:403
NTSTATUS cbmiec_pp_read(IN PDEVICE_EXTENSION Pdx, OUT UCHAR *Byte)
Read a byte from the X[M|A]P1541 cable.
Definition: ppread.c:79