OpenCBM
WINDOWS/iec.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-2001 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
8  * Copyright 2001-2005,2007-2010 Spiro Trikaliotis
9  *
10 */
11 
20 #include <windows.h>
21 #include <windowsx.h>
22 
23 #include <mmsystem.h>
24 
26 #define DBG_USERMODE
27 
29 #define DBG_DLL
30 
32 #define DBG_PROGNAME "OPENCBM.DLL"
33 
35 #define DBG_IS_DEBUG_C
36 
37 #include "debug.h"
38 
39 #include <winioctl.h>
40 #include "cbmioctl.h"
41 
42 #include <stdlib.h>
43 
45 #define DLL
46 #include "i_opencbm.h"
47 
49 #define OPENCBM_PLUGIN
50 #include "archlib.h"
51 
52 
74 static void
75 fastschedule_start(void)
76 {
77  FUNC_ENTER();
78 
79  if (timeBeginPeriod(1) != TIMERR_NOERROR)
80  {
81  DBG_WARN((DBG_PREFIX "Unable to decrease scheduling period."));
82  }
83 
84  FUNC_LEAVE();
85 }
86 
92 static void
93 fastschedule_stop(void)
94 {
95  FUNC_ENTER();
96 
97  if (timeEndPeriod(1) != TIMERR_NOERROR)
98  {
99  DBG_WARN((DBG_PREFIX "Unable to restore scheduling period."));
100  }
101 
102  FUNC_LEAVE();
103 }
104 
105 
130 BOOL WINAPI
131 DllMain(IN HANDLE Module, IN DWORD Reason, IN LPVOID Reserved)
132 {
133  static BOOL bIsOpen = FALSE;
134  BOOLEAN Status = TRUE;
135 
136  FUNC_ENTER();
137 
138 #if DBG
139 
140  if (Reason == DLL_PROCESS_ATTACH)
141  {
142  // Read the debugging flags from the registry
143 
144  cbm_get_debugging_flags("xa1541");
145  }
146 
147 #endif
148 
149  /* make sure the definitions in opencbm.h and cbmioctl.h
150  * match each other!
151  * Since we are the only instance which includes both files,
152  * we are the only one which can ensure this.
153  */
154 
159 
160  switch (Reason)
161  {
162  case DLL_PROCESS_ATTACH:
163 
165  {
166  // the driver is started automatically, do not try
167  // to start it
168 
169  Status = TRUE;
170  }
171  else
172  {
173  if (bIsOpen)
174  {
175  DBG_ERROR((DBG_PREFIX "No multiple instances are allowed!"));
176  Status = FALSE;
177  }
178  else
179  {
180  Status = TRUE;
181  bIsOpen = cbm_driver_start();
182  }
183  }
184 
186 
187  /* If the DLL loaded successfully, ask for fast scheduling */
188  if (Status)
189  {
190  fastschedule_start();
191  }
192  break;
193 
194  case DLL_PROCESS_DETACH:
195 
197  {
198  // the driver is started automatically, do not try
199  // to stop it
200 
201  Status = TRUE;
202  }
203  else
204  {
205  if (!bIsOpen)
206  {
207  DBG_ERROR((DBG_PREFIX "Driver is not running!"));
208  Status = FALSE;
209  }
210  else
211  {
212  // it is arguable if the driver should be stopped
213  // whenever the DLL is unloaded.
214 
215  cbm_driver_stop();
216  bIsOpen = FALSE;
217  }
218  }
219 
220  /* If the DLL unloaded successfully, we do not need fast scheduling anymore. */
221  if (Status)
222  {
223  fastschedule_stop();
224  }
225 
227  break;
228 
229  default:
230  break;
231 
232  }
233 
234  FUNC_LEAVE_BOOL(Status);
235 }
236 
261 void CBMAPIDECL
263 {
264  FUNC_ENTER();
265 
266  cbm_ioctl(HandleDevice, CBMCTRL(PARPORT_LOCK), NULL, 0, NULL, 0);
267 
268  FUNC_LEAVE();
269 }
270 
288 void CBMAPIDECL
290 {
291  FUNC_ENTER();
292 
293  cbm_ioctl(HandleDevice, CBMCTRL(PARPORT_UNLOCK), NULL, 0, NULL, 0);
294 
295  FUNC_LEAVE();
296 }
297 
322 int CBMAPIDECL
323 opencbm_plugin_raw_write(CBM_FILE HandleDevice, const void *Buffer, size_t Count)
324 {
325  DWORD BytesWritten;
326  OVERLAPPED overlapped;
327  BOOL result;
328 
329  FUNC_ENTER();
330 
331  WaitForIoCompletionConstruct(&overlapped);
332 
333  result = WriteFile(
334  HandleDevice,
335  Buffer,
336  Count,
337  &BytesWritten,
338  &overlapped
339  );
340 
341  WaitForIoCompletion(result, HandleDevice, &overlapped, &BytesWritten);
342 
343  FUNC_LEAVE_INT(BytesWritten);
344 }
345 
369 int CBMAPIDECL
370 opencbm_plugin_raw_read(CBM_FILE HandleDevice, void *Buffer, size_t Count)
371 {
372  DWORD bytesToRead = Count;
373  DWORD bytesRead;
374 
375  OVERLAPPED overlapped;
376  BOOL result;
377 
378  FUNC_ENTER();
379 
380  WaitForIoCompletionConstruct(&overlapped);
381 
382  result = ReadFile(
383  HandleDevice,
384  Buffer,
385  bytesToRead,
386  &bytesRead,
387  &overlapped
388  );
389 
390  WaitForIoCompletion(result, HandleDevice, &overlapped, &bytesRead);
391 
392  FUNC_LEAVE_INT(bytesRead);
393 }
394 
395 
396 
420 int CBMAPIDECL
421 opencbm_plugin_listen(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
422 {
423  CBMT_LISTEN_IN parameter;
424  int returnValue;
425 
426  FUNC_ENTER();
427 
428  parameter.PrimaryAddress = DeviceAddress;
429  parameter.SecondaryAddress = SecondaryAddress;
430 
431  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(LISTEN), &parameter, sizeof(parameter), NULL, 0)
432  ? 0 : 1;
433 
434  FUNC_LEAVE_INT(returnValue);
435 }
436 
460 int CBMAPIDECL
461 opencbm_plugin_talk(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
462 {
463  CBMT_TALK_IN parameter;
464  int returnValue;
465 
466  FUNC_ENTER();
467 
468  parameter.PrimaryAddress = DeviceAddress;
469  parameter.SecondaryAddress = SecondaryAddress;
470 
471  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(TALK), &parameter, sizeof(parameter), NULL, 0)
472  ? 0 : 1;
473 
474  FUNC_LEAVE_INT(returnValue);
475 }
476 
498 int CBMAPIDECL
499 opencbm_plugin_open(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
500 {
501  CBMT_OPEN_IN parameter;
502  int returnValue;
503 
504  FUNC_ENTER();
505 
506  parameter.PrimaryAddress = DeviceAddress;
507  parameter.SecondaryAddress = SecondaryAddress;
508 
509  if (cbm_ioctl(HandleDevice, CBMCTRL(OPEN), &parameter, sizeof(parameter), NULL, 0))
510  {
511  returnValue = 0;
512  }
513  else
514  {
515  returnValue = -1;
516  }
517 
518  FUNC_LEAVE_INT(returnValue);
519 }
520 
542 int CBMAPIDECL
543 opencbm_plugin_close(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
544 {
545  CBMT_CLOSE_IN parameter;
546  int returnValue;
547 
548  FUNC_ENTER();
549 
550  parameter.PrimaryAddress = DeviceAddress;
551  parameter.SecondaryAddress = SecondaryAddress;
552 
553  returnValue =
554  cbm_ioctl(HandleDevice, CBMCTRL(CLOSE), &parameter, sizeof(parameter), NULL, 0)
555  ? 0 : 1;
556 
557  FUNC_LEAVE_INT(returnValue);
558 }
559 
580 int CBMAPIDECL
582 {
583  int returnValue;
584 
585  FUNC_ENTER();
586 
587  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(UNLISTEN), NULL, 0, NULL, 0) ? 0 : 1;
588 
589  FUNC_LEAVE_INT(returnValue);
590 }
591 
612 int CBMAPIDECL
614 {
615  int returnValue;
616 
617  FUNC_ENTER();
618 
619  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(UNTALK), NULL, 0, NULL, 0) ? 0 : 1;
620 
621  FUNC_LEAVE_INT(returnValue);
622 }
623 
624 
645 int CBMAPIDECL
647 {
648  CBMT_GET_EOI_OUT result;
649 
650  FUNC_ENTER();
651 
652  cbm_ioctl(HandleDevice, CBMCTRL(GET_EOI), NULL, 0, &result, sizeof(result));
653 
654  FUNC_LEAVE_INT(result.Decision);
655 }
656 
672 int CBMAPIDECL
674 {
675  int returnValue;
676 
677  FUNC_ENTER();
678 
679  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(CLEAR_EOI), NULL, 0, NULL, 0);
680 
681  FUNC_LEAVE_INT(returnValue);
682 }
683 
705 int CBMAPIDECL
707 {
708  USHORT returnValue;
709 
710  FUNC_ENTER();
711 
712  //
713  // try to cancel any pending io operations.
714  //
716 
717  returnValue = cbm_ioctl(HandleDevice, CBMCTRL(RESET), NULL, 0, NULL, 0) ? 0 : 1;
718 
719  FUNC_LEAVE_INT(returnValue);
720 }
721 
722 
723 /*-------------------------------------------------------------------*/
724 /*--------- LOW-LEVEL PORT ACCESS -----------------------------------*/
725 
747 unsigned char CBMAPIDECL
749 {
750  CBMT_PP_READ_OUT result;
751 
752  FUNC_ENTER();
753 
754  cbm_ioctl(HandleDevice, CBMCTRL(PP_READ), NULL, 0, &result, sizeof(result));
755 
756  FUNC_LEAVE_UCHAR(result.Byte);
757 }
758 
782 void CBMAPIDECL
783 opencbm_plugin_pp_write(CBM_FILE HandleDevice, unsigned char Byte)
784 {
785  CBMT_PP_WRITE_IN parameter;
786 
787  FUNC_ENTER();
788 
789  parameter.Byte = Byte;
790 
791  cbm_ioctl(HandleDevice, CBMCTRL(PP_WRITE), &parameter, sizeof(parameter), NULL, 0);
792 
793  FUNC_LEAVE();
794 }
795 
817 int CBMAPIDECL
819 {
820  CBMT_IEC_POLL_OUT result;
821 
822  FUNC_ENTER();
823 
824  cbm_ioctl(HandleDevice, CBMCTRL(IEC_POLL), NULL, 0, &result, sizeof(result));
825 
826  FUNC_LEAVE_INT(result.Line);
827 }
828 
829 
848 void CBMAPIDECL
849 opencbm_plugin_iec_set(CBM_FILE HandleDevice, int Line)
850 {
851  CBMT_IEC_SET_IN parameter;
852 
853  FUNC_ENTER();
854 
855  parameter.Line = (UCHAR) Line;
856 
857  cbm_ioctl(HandleDevice, CBMCTRL(IEC_SET), &parameter, sizeof(parameter), NULL, 0);
858 
859  FUNC_LEAVE();
860 }
861 
880 void CBMAPIDECL
881 opencbm_plugin_iec_release(CBM_FILE HandleDevice, int Line)
882 {
883  CBMT_IEC_RELEASE_IN parameter;
884 
885  FUNC_ENTER();
886 
887  parameter.Line = (UCHAR) Line;
888 
889  cbm_ioctl(HandleDevice, CBMCTRL(IEC_RELEASE), &parameter, sizeof(parameter), NULL, 0);
890 
891  FUNC_LEAVE();
892 }
893 
921 void CBMAPIDECL
922 opencbm_plugin_iec_setrelease(CBM_FILE HandleDevice, int Set, int Release)
923 {
924  CBMT_IEC_SETRELEASE_IN parameter;
925 
926  FUNC_ENTER();
927 
928  parameter.State = (UCHAR) Set;
929  parameter.Line = (UCHAR) Release;
930 
931  cbm_ioctl(HandleDevice, CBMCTRL(IEC_SETRELEASE), &parameter, sizeof(parameter), NULL, 0);
932 
933  FUNC_LEAVE();
934 }
935 
962 int CBMAPIDECL
963 opencbm_plugin_iec_wait(CBM_FILE HandleDevice, int Line, int State)
964 {
965  CBMT_IEC_WAIT_IN parameter;
966  CBMT_IEC_WAIT_OUT result;
967 
968  FUNC_ENTER();
969 
970  parameter.Line = (UCHAR) Line;
971  parameter.State = (UCHAR) State;
972 
973  cbm_ioctl(HandleDevice, CBMCTRL(IEC_WAIT),
974  &parameter, sizeof(parameter),
975  &result, sizeof(result));
976 
977  FUNC_LEAVE_INT(result.Line);
978 }
979 
980 #if DBG
981 
990 int CBMAPIDECL
991 cbm_get_debugging_buffer(CBM_FILE HandleDevice, char *buffer, size_t len)
992 {
993  FUNC_ENTER();
994 
995  cbm_ioctl(HandleDevice, CBMCTRL(I_READDBG), NULL, 0, buffer, len);
996 
997  FUNC_LEAVE_INT(0);
998 }
999 
1000 #endif // #if DBG
1001 
1025 int CBMAPIDECL
1027 {
1028  CBMT_IEC_DBG_READ result;
1029  int returnValue = -1;
1030 
1031  FUNC_ENTER();
1032 
1033  if ( cbm_ioctl(HandleDevice, CBMCTRL(IEC_DBG_READ), NULL, 0, &result, sizeof(result)) ) {
1034  returnValue = result.Value;
1035  }
1036 
1037  FUNC_LEAVE_INT(returnValue);
1038 }
1039 
1069 int CBMAPIDECL
1070 opencbm_plugin_iec_dbg_write(CBM_FILE HandleDevice, unsigned char Value)
1071 {
1072  CBMT_IEC_DBG_WRITE parameter;
1073  int returnValue = -1;
1074 
1075  FUNC_ENTER();
1076 
1077  parameter.Value = Value;
1078 
1079  if ( cbm_ioctl(HandleDevice, CBMCTRL(IEC_DBG_WRITE), &parameter, sizeof(parameter), NULL, 0) ) {
1080  returnValue = 0;
1081  }
1082 
1083  FUNC_LEAVE_INT(returnValue);
1084 }
void CBMAPIDECL opencbm_plugin_iec_release(CBM_FILE HandleDevice, int Line)
Deactivate a line on the IEC serial bus.
Definition: WINDOWS/iec.c:881
#define FUNC_LEAVE_UCHAR(_xxx)
Definition: debug.h:364
void cbm_get_debugging_flags(const char *ModuleName)
Set the debugging flags.
Definition: registry.c:97
int CBMAPIDECL opencbm_plugin_open(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Open a file on the IEC serial bus.
Definition: WINDOWS/iec.c:499
BOOL WINAPI DllMain(IN HANDLE Module, IN DWORD Reason, IN LPVOID Reserved)
DLL initialization und unloading.
Definition: WINDOWS/iec.c:131
#define DBG_WARN(_xxx)
Definition: debug.h:395
#define FUNC_LEAVE_INT(_xxx)
Definition: debug.h:358
VOID WaitForIoCompletionCancelAll(VOID)
Cancel any running WaitForIoCompletion()
Definition: i_opencbm.c:179
Define makros for debugging purposes.
int CBMAPIDECL opencbm_plugin_close(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Close a file on the IEC serial bus.
Definition: WINDOWS/iec.c:543
VOID WaitForIoCompletionInit(VOID)
Initialize WaitForIoCompletion()
Definition: i_opencbm.c:129
#define CBMAPIDECL
Definition: opencbm.h:85
void CBMAPIDECL opencbm_plugin_iec_set(CBM_FILE HandleDevice, int Line)
Activate a line on the IEC serial bus.
Definition: WINDOWS/iec.c:849
#define WINAPI
Definition: opencbm.h:86
int CBMAPIDECL opencbm_plugin_iec_dbg_write(CBM_FILE HandleDevice, unsigned char Value)
Write a byte to the parallel port output register.
Definition: WINDOWS/iec.c:1070
#define CBMCTRL(_x_)
Definition: i_opencbm.h:37
int CBMAPIDECL opencbm_plugin_iec_poll(CBM_FILE HandleDevice)
Read status of all bus lines.
Definition: WINDOWS/iec.c:818
int CBMAPIDECL opencbm_plugin_unlisten(CBM_FILE HandleDevice)
Send an UNLISTEN on the IEC serial bus.
Definition: WINDOWS/iec.c:581
Define the IOCTL codes for the opencbm driver.
int CBMAPIDECL opencbm_plugin_raw_write(CBM_FILE HandleDevice, const void *Buffer, size_t Count)
Write data to the IEC serial bus.
Definition: WINDOWS/iec.c:323
int CBMAPIDECL opencbm_plugin_iec_dbg_read(CBM_FILE HandleDevice)
Read a byte from the parallel port input register.
Definition: WINDOWS/iec.c:1026
#define IEC_DATA
Definition: opencbm.h:97
int CBMAPIDECL opencbm_plugin_listen(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Send a LISTEN on the IEC serial bus.
Definition: WINDOWS/iec.c:421
#define FUNC_LEAVE()
Definition: debug.h:349
UCHAR PrimaryAddress
Definition: cbmioctl.h:90
void CBMAPIDECL opencbm_plugin_unlock(CBM_FILE HandleDevice)
Unlock the parallel port for the driver.
Definition: WINDOWS/iec.c:289
#define IEC_RESET
Definition: opencbm.h:100
#define CBM_FILE
Definition: opencbm.h:87
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define FUNC_LEAVE_BOOL(_xxx)
Definition: debug.h:354
#define IEC_ATN
Definition: opencbm.h:99
#define DBG_ERROR(_xxx)
Definition: debug.h:397
int CBMAPIDECL opencbm_plugin_reset(CBM_FILE HandleDevice)
RESET all devices.
Definition: WINDOWS/iec.c:706
UCHAR SecondaryAddress
Definition: cbmioctl.h:93
unsigned char CBMAPIDECL opencbm_plugin_pp_read(CBM_FILE HandleDevice)
Read a byte from a XP1541/XP1571 cable.
Definition: WINDOWS/iec.c:748
void CBMAPIDECL opencbm_plugin_iec_setrelease(CBM_FILE HandleDevice, int Set, int Release)
Activate and deactive a line on the IEC serial bus.
Definition: WINDOWS/iec.c:922
#define IEC_LINE_RESET
Definition: cbmioctl.h:80
int CBMAPIDECL opencbm_plugin_talk(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Send a TALK on the IEC serial bus.
Definition: WINDOWS/iec.c:461
VOID WaitForIoCompletionConstruct(LPOVERLAPPED Overlapped)
Boilerplate code for asynchronous I/O requests.
Definition: i_opencbm.c:217
int CBMAPIDECL opencbm_plugin_untalk(CBM_FILE HandleDevice)
Send an UNTALK on the IEC serial bus.
Definition: WINDOWS/iec.c:613
#define IEC_LINE_DATA
Definition: cbmioctl.h:74
BOOL cbm_ioctl(IN CBM_FILE HandleDevice, IN DWORD ControlCode, IN char *TextControlCode, IN PVOID InBuffer, IN ULONG InBufferSize, OUT PVOID OutBuffer, IN ULONG OutBufferSize)
Perform an ioctl on the driver.
Definition: i_opencbm.c:506
int CBMAPIDECL opencbm_plugin_clear_eoi(CBM_FILE HandleDevice)
Reset the EOI flag.
Definition: WINDOWS/iec.c:673
#define FUNC_ENTER()
Definition: debug.h:347
#define DBG_PREFIX
Definition: debug.h:320
int CBMAPIDECL opencbm_plugin_iec_wait(CBM_FILE HandleDevice, int Line, int State)
Wait for a line to have a specific state.
Definition: WINDOWS/iec.c:963
BOOL cbm_driver_stop(VOID)
Stop a device driver.
Definition: i_opencbm.c:639
BOOLEAN Decision
Definition: cbmioctl.h:136
void CBMAPIDECL opencbm_plugin_lock(CBM_FILE HandleDevice)
Lock the parallel port for the driver.
Definition: WINDOWS/iec.c:262
BOOL cbm_driver_start(VOID)
Start a device driver.
Definition: i_opencbm.c:564
int CBMAPIDECL opencbm_plugin_get_eoi(CBM_FILE HandleDevice)
Get EOI flag after bus read.
Definition: WINDOWS/iec.c:646
#define IEC_LINE_ATN
Definition: cbmioctl.h:78
Internal API for opencbm installation.
VOID WaitForIoCompletionDeinit(VOID)
Uninitialize WaitForIoCompletion()
Definition: i_opencbm.c:158
int CBMAPIDECL opencbm_plugin_raw_read(CBM_FILE HandleDevice, void *Buffer, size_t Count)
Read data from the IEC serial bus.
Definition: WINDOWS/iec.c:370
#define IEC_LINE_CLOCK
Definition: cbmioctl.h:76
int CBMAPIDECL cbm_get_debugging_buffer(CBM_FILE HandleDevice, char *buffer, size_t len)
Output contents of the debugging buffer.
Definition: WINDOWS/iec.c:991
#define IEC_CLOCK
Definition: opencbm.h:98
void CBMAPIDECL opencbm_plugin_pp_write(CBM_FILE HandleDevice, unsigned char Byte)
Write a byte to a XP1541/XP1571 cable.
Definition: WINDOWS/iec.c:783
BOOL WaitForIoCompletion(BOOL Result, CBM_FILE HandleDevice, LPOVERLAPPED Overlapped, DWORD *BytesTransferred)
Wait for the completion of an I/O operation.
Definition: i_opencbm.c:258
UCHAR Line
Definition: cbmioctl.h:112
BOOL IsDriverStartedAutomatically(VOID)
Is the driver started automatically?
Definition: i_opencbm.c:763