1 | /** |
---|
2 | * The Paper Tape Project -- Punching Subproject |
---|
3 | * Windows NT User mode driver |
---|
4 | * |
---|
5 | * This Driver should work at Windows NT/2000/XP systems. |
---|
6 | * It uses the WinIo library (http://www.internals.com/) |
---|
7 | * for kernel mode calls. |
---|
8 | * |
---|
9 | * It compiles with MinGW/MSYS, C++!. No Microsoft development |
---|
10 | * environment or DDK toolkit neccessary. |
---|
11 | * |
---|
12 | * |
---|
13 | * Started at 02.09.2008 at winXP development workstation |
---|
14 | * in susanne@M66. |
---|
15 | * |
---|
16 | * (c) 2008 Sven Köppel |
---|
17 | * |
---|
18 | * |
---|
19 | **/ |
---|
20 | |
---|
21 | #include <stdio.h> |
---|
22 | #include <stdlib.h> |
---|
23 | #include "backend.h" |
---|
24 | |
---|
25 | /* Stupid */ |
---|
26 | void puncher_backend_stop(PuncherBackend* c); |
---|
27 | |
---|
28 | /* Windows/WinIo specific header fil1es */ |
---|
29 | #include <windows.h> |
---|
30 | #include "backend.win/WinIo.h" |
---|
31 | |
---|
32 | /* Parport positions */ |
---|
33 | #define PARPORT_BASE_REGISTER 0x378 |
---|
34 | #define PARPORT_DATA_REGISTER PARPORT_BASE_REGISTER + 0 |
---|
35 | #define PARPORT_STATUS_REGISTER PARPORT_BASE_REGISTER + 1 |
---|
36 | #define PARPORT_CONTROL_REGISTER PARPORT_BASE_REGISTER + 2 |
---|
37 | |
---|
38 | /* Magic numbers. See <linux/include/linux/parport.h> at linux ;-) */ |
---|
39 | #define PARPORT_CONTROL_STROBE 0x01 /* C0 */ |
---|
40 | #define PARPORT_STATUS_BUSY 0x80 /* S7 */ |
---|
41 | |
---|
42 | /** |
---|
43 | * A windows workaround for the unix gettimeofday function which |
---|
44 | * gives the usecs back. |
---|
45 | * |
---|
46 | **/ |
---|
47 | //DWORD puncher_backend_mtime(DWORD since) { |
---|
48 | /*if(!since) { |
---|
49 | GetTickCount |
---|
50 | }*/ |
---|
51 | |
---|
52 | /*long usec; |
---|
53 | union { |
---|
54 | long long ns100; |
---|
55 | FILETIME ft; |
---|
56 | } now; |
---|
57 | |
---|
58 | GetSystemTimeAsFileTime (&now.ft); |
---|
59 | |
---|
60 | usec = (long) ((now.ns100 / 10LL) % 1000000LL); |
---|
61 | return usec*1000 - since*/ |
---|
62 | //} |
---|
63 | |
---|
64 | PuncherBackend* puncher_backend_new(int debug_flag) { |
---|
65 | PuncherBackend* c = (PuncherBackend*) malloc(sizeof(PuncherBackend)); |
---|
66 | c->debug_flag = debug_flag; |
---|
67 | |
---|
68 | if( !InitializeWinIo() ) { |
---|
69 | printf("Bad error while initialisiing WinIo library!\n"); |
---|
70 | return NULL; |
---|
71 | } |
---|
72 | |
---|
73 | PUNCHER_BACKEND_DPRINTF("WinIo initialized.\n"); |
---|
74 | puncher_backend_stop(c); |
---|
75 | |
---|
76 | return c; |
---|
77 | } |
---|
78 | |
---|
79 | void puncher_backend_stop(PuncherBackend *c) { |
---|
80 | // turn Punch Instruction Off! |
---|
81 | if(! SetPortVal(PARPORT_CONTROL_REGISTER, PARPORT_CONTROL_STROBE, 1)) { |
---|
82 | printf("Backend Error: Could not turn PI off\n"); |
---|
83 | } |
---|
84 | PUNCHER_BACKEND_DPRINTF("Switched PI off\n"); |
---|
85 | } |
---|
86 | |
---|
87 | int puncher_backend_destroy(PuncherBackend* c) { |
---|
88 | puncher_backend_stop(c); |
---|
89 | // so that's it. |
---|
90 | ShutdownWinIo(); |
---|
91 | PUNCHER_BACKEND_DPRINTF("WinIo shutdown finished. Backend destroyed.\n"); |
---|
92 | } |
---|
93 | |
---|
94 | int puncher_backend_write_byte(PuncherBackend* c, unsigned char buf) { |
---|
95 | DWORD time, wait_time; |
---|
96 | unsigned char status; |
---|
97 | // so here we are. Let's punch! ;-) |
---|
98 | |
---|
99 | // Set Data pins |
---|
100 | if( !SetPortVal(PARPORT_DATA_REGISTER, buf, 1) ) |
---|
101 | return -2; |
---|
102 | |
---|
103 | time = GetTickCount(); |
---|
104 | |
---|
105 | Sleep(10 / 1000); // Take some time... |
---|
106 | |
---|
107 | |
---|
108 | /* anti "pulse" strobe => Turns Punch Instruction on */ |
---|
109 | if( !SetPortVal(PARPORT_CONTROL_REGISTER, 0x0, 1) ) |
---|
110 | return -3; |
---|
111 | |
---|
112 | PUNCHER_BACKEND_DPRINTF("data set; strobe pulsed...\n"); |
---|
113 | |
---|
114 | // sleep the defined time |
---|
115 | Sleep(220 / 1000); // 220us |
---|
116 | |
---|
117 | // only for debugging, get status values: |
---|
118 | if( !GetPortVal(PARPORT_STATUS_REGISTER, (PDWORD) &status, 1)) |
---|
119 | return -4; |
---|
120 | |
---|
121 | // end strobe + data pins |
---|
122 | PUNCHER_BACKEND_DPRINTF("Control is %x. Ending data pins... ", status); |
---|
123 | if( !SetPortVal(PARPORT_DATA_REGISTER, 0x0, 1) ) |
---|
124 | return -5; |
---|
125 | PUNCHER_BACKEND_DPRINTF("+ strobe... "); |
---|
126 | if( !SetPortVal(PARPORT_CONTROL_REGISTER, PARPORT_CONTROL_STROBE, 1) ) |
---|
127 | return -5; |
---|
128 | |
---|
129 | // Wait until Puncher is ready to give out Punch Ready |
---|
130 | wait_time = 40 - (GetTickCount() - time); |
---|
131 | PUNCHER_BACKEND_DPRINTF("\nWaiting for Puncher Ready (%i msec)...\n", wait_time); |
---|
132 | if(wait_time > 0) |
---|
133 | Sleep(wait_time); // ms! |
---|
134 | //Sleep(1000); // debugging: 4 sec |
---|
135 | |
---|
136 | // Check status another time. |
---|
137 | if( !GetPortVal(PARPORT_STATUS_REGISTER, (PDWORD) &status, 1) ) |
---|
138 | return -6; |
---|
139 | if( (status & PARPORT_STATUS_BUSY) == PARPORT_STATUS_BUSY) { |
---|
140 | PUNCHER_BACKEND_DPRINTF("Still busy (%x).\n", status); |
---|
141 | return 1; |
---|
142 | } else { |
---|
143 | PUNCHER_BACKEND_DPRINTF("Finished successfully (%x)\n", status); |
---|
144 | return 0; |
---|
145 | } |
---|
146 | } // puncher_backend_write_byte |
---|