OpenCBM
i_rawwrite.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 
53 NTSTATUS
54 cbmiec_i_raw_write(PDEVICE_EXTENSION Pdx, const UCHAR *Buffer, ULONG Count, ULONG *Sent, BOOLEAN Atn, BOOLEAN Talk)
55 {
56  NTSTATUS ntStatus;
57  ULONG sent;
58  UCHAR c;
59  ULONG i;
60  LONG ret;
61 
62  FUNC_ENTER();
63 
64  ntStatus = cbmiec_checkcable(Pdx);
65 
66  if (!NT_SUCCESS(ntStatus))
67  {
68  FUNC_LEAVE_NTSTATUS(ntStatus);
69  }
70 
71  sent = 0;
72 
73  Pdx->Eoi = FALSE;
74 
75  PERF_EVENT_VERBOSE(0x1010, 0);
76 
77  ret = InterlockedExchange(&Pdx->IrqCount, 0);
78  DBG_ASSERT(ret == 0);
79 
80  DBG_IEC((DBG_PREFIX "About to send %d bytes%s", Count, Atn ? " with ATN" : ""));
81 
82  PERF_EVENT_VERBOSE(0x1011, 0);
83 
84  if (Atn)
85  {
87  }
88 
89  // Signal: We have something to send
90 
93 
94  // Wait for DATA to be set by the drive(s)
95 
96  PERF_EVENT_VERBOSE(0x1012, 0);
97 
99  {
101  }
102 
103  PERF_EVENT_VERBOSE(0x1013, 0);
104 
105  // cbmiec_show_state(Pdx,"!GET(PP_DATA_IN)");
106 
107  // If DATA was not set, there is no device present
108 
109  if(!CBMIEC_GET(PP_DATA_IN))
110  {
111  PERF_EVENT_VERBOSE(0x1014, 1);
112  DBG_ERROR((DBG_PREFIX "no devices found!"));
114  ntStatus = STATUS_NO_SUCH_DEVICE;
115  }
116  else
117  {
118  PERF_EVENT_VERBOSE(0x1014, 0);
119  if (Pdx->IsSMP)
120  {
122  }
123  else
124  {
126  }
127  }
128 
129  PERF_EVENT_VERBOSE(0x1015, 0);
130 
131  while(sent < Count && ntStatus == STATUS_SUCCESS)
132  {
133  c = *Buffer++;
134 
137 
138  PERF_EVENT_VERBOSE(0x1016, sent);
139 
141 
142  PERF_EVENT_VERBOSE(0x1017, sent);
143 
145  {
146  // Wait for the listener
147  // We might have to signal an EOI. That is signaled
148  // *before* the last byte has been sent.
149  // Anyway, if we are sending with ATN asserted, then
150  // no EOI signaling is allowed.
151 
152  PERF_EVENT_VERBOSE(0x1018, sent);
153 
155  ((sent == (Count-1)) && (Atn == 0)) ? TRUE : FALSE);
156 
157  PERF_EVENT_VERBOSE(0x1019, sent);
158 
159  if(QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
160  {
161  PERF_EVENT_VERBOSE(0x1020, 1);
162 
163  ntStatus = STATUS_CANCELLED;
164  }
165  else
166  {
167  PERF_EVENT_VERBOSE(0x1020, 0);
168 
169  if(cbmiec_send_byte(Pdx,c))
170  {
171  sent++;
172  PERF_EVENT_VERBOSE(0x1021, 0);
174  PERF_EVENT_VERBOSE(0x1022, 0);
175  }
176  else
177  {
178  PERF_EVENT_VERBOSE(0x1021, 1);
179  DBG_ERROR((DBG_PREFIX "I/O error on cbmiec_send_byte()"));
180  ntStatus = STATUS_NO_SUCH_DEVICE;
181  PERF_EVENT_VERBOSE(0x1022, 1);
182  }
183  }
184  }
185  else
186  {
187  DBG_ERROR((DBG_PREFIX "device not present"));
188  ntStatus = STATUS_NO_SUCH_DEVICE;
189  }
190  }
191 
192 #if DBG
193  if (ntStatus == STATUS_SUCCESS)
194  {
195  DBG_SUCCESS((DBG_PREFIX "%d bytes sent", sent));
196  }
197  else
198  {
199  DBG_ERROR((DBG_PREFIX "%d bytes sent, Status=%s", sent, DebugNtStatus(ntStatus)));
200  }
201 #endif
202 
203  if (ntStatus == STATUS_SUCCESS)
204  {
206  }
207  else
208  {
210  }
211 
212  if (ntStatus == STATUS_SUCCESS && Talk)
213  {
214  // Talk-attention turn around (reverse Talker and Listener)
215 
216  PERF_EVENT_VERBOSE(0x1030, 0);
217 
218  cbmiec_block_irq(Pdx);
219 
220  PERF_EVENT_VERBOSE(0x1031, 0);
221 
224 
225  PERF_EVENT_VERBOSE(0x1033, 0);
226 
228 
229  PERF_EVENT_VERBOSE(0x1032, 0);
230 
231  while (!CBMIEC_GET(PP_CLK_IN) && !QueueShouldCancelCurrentIrp(&Pdx->IrpQueue))
232  ;
233 
234  PERF_EVENT_VERBOSE(0x1034, 0);
235 
236  cbmiec_release_irq(Pdx);
237 
238  PERF_EVENT_VERBOSE(0x1035, 0);
239  }
240  else
241  {
243  }
244  PERF_EVENT_VERBOSE(0x1036, 0);
246  PERF_EVENT_VERBOSE(0x1037, 0);
247 
248  DBG_ASSERT(Sent != NULL);
249  *Sent = sent;
250 
251  FUNC_LEAVE_NTSTATUS(ntStatus);
252 }
VOID cbmiec_udelay(IN ULONG howlong)
Wait for a timeout.
Definition: libiec/util.c:66
IEC_TIMEOUTS libiec_global_timeouts
Definition: libiec/init.c:28
#define CBMIEC_GET(_line)
Definition: i_iec.h:75
#define PP_ATN_OUT
The ATN OUT bit.
Definition: i_iec.h:39
NTSTATUS cbmiec_i_raw_write(PDEVICE_EXTENSION Pdx, const UCHAR *Buffer, ULONG Count, ULONG *Sent, BOOLEAN Atn, BOOLEAN Talk)
Write some bytes to the IEC bus.
Definition: i_rawwrite.c:54
ULONG T_11_SEND_BEFORE_BYTE_DELAY
= 50 us: Extra wait before sending of every single byte
Definition: i_iec.h:139
#define PP_DATA_OUT
The DATA OUT bit.
Definition: i_iec.h:41
BOOLEAN cbmiec_send_byte(IN PDEVICE_EXTENSION Pdx, IN UCHAR Byte)
Write one byte to the IEC bus.
Definition: sendbyte.c:39
ULONG T_10_SEND_BEFORE_1ST_BYTE
= 20 us: Extra wait before sending 1st byte
Definition: i_iec.h:136
#define PP_CLK_IN
The CLOCK IN bit.
Definition: i_iec.h:50
ULONG T_14_SEND_AT_END_DELAY
= 100 us: Extra wait after sending a block
Definition: i_iec.h:148
ULONG T_12_SEND_AFTER_BYTE_DELAY
= 100 us: Extra wait after sending every single byte
Definition: i_iec.h:142
ULONG T_9_SEND_WAIT_DEVICES_T_AT
= 10 us: Granularity: On send, how long to wait for driver to set DATA
Definition: i_iec.h:133
#define CBMIEC_SET(_set)
Definition: i_iec.h:64
BOOLEAN QueueShouldCancelCurrentIrp(PQUEUE Queue)
Should the current IRP be cancelled?
Definition: queue.c:1041
Internal functions and definitions of the libiec library.
#define PERF_EVENT_WRITE_BYTE_NO(_x_)
Definition: cbm_driver.h:85
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
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
#define DBG_SUCCESS(_xxx)
Definition: debug.h:393
#define CBMIEC_RELEASE(_rel)
Definition: i_iec.h:66
#define PERF_EVENT_WRITE_BYTE(_x_)
Definition: cbm_driver.h:87
#define PP_CLK_OUT
The CLOCK OUT bit.
Definition: i_iec.h:40
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
const UCHAR * DebugNtStatus(NTSTATUS Value)
Return the description of an NTSTATUS code.
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320
VOID cbmiec_wait_for_listener(IN PDEVICE_EXTENSION Pdx, IN BOOLEAN SendEoi)
Wait until listener is ready to receive.
Definition: waitlistener.c:80
ULONG T_9_Times
x T_9a, is 100: On send, how long to wait for driver to set DATA
Definition: i_iec.h:130
VOID cbmiec_release_irq(PDEVICE_EXTENSION Pdx)
Release the interrupts.
Definition: libiec/util.c:118