]>
Commit | Line | Data |
---|---|---|
5e3d963b | 1 | #include <stdio.h> |
2 | #include <fcntl.h> | |
3 | #include <errno.h> | |
4 | #include <string.h> | |
5 | #include <unistd.h> | |
6 | #include <inttypes.h> | |
7 | #include <sys/types.h> | |
8 | #include <sys/ioctl.h> | |
9 | #include <linux/parport.h> | |
10 | #include <linux/ppdev.h> | |
11 | #include "usb-driver.h" | |
12 | #include "parport.h" | |
13 | ||
14 | static int parportfd = -1; | |
15 | ||
25ba7a49 | 16 | int parport_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num) { |
5e3d963b | 17 | int ret = 0; |
18 | int i; | |
19 | unsigned long port; | |
20 | unsigned char val; | |
21 | static unsigned char last_pp_write = 0; | |
22 | ||
cf55ed64 MG |
23 | if (parportfd < 0) |
24 | return ret; | |
25 | ||
26 | if (ioctl(parportfd, PPCLAIM) == -1) | |
27 | return -1; | |
28 | ||
5e3d963b | 29 | for (i = 0; i < num; i++) { |
30 | DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n", | |
31 | (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes, | |
32 | tr[i].fAutoinc, tr[i].dwOptions); | |
33 | ||
34 | port = (unsigned long)tr[i].dwPort; | |
35 | val = tr[i].Data.Byte; | |
36 | ||
37 | #ifdef DEBUG | |
38 | if (tr[i].cmdTrans == 13) | |
39 | DPRINTF("write byte: %d\n", val); | |
40 | #endif | |
41 | ||
5e3d963b | 42 | if (port == ppbase + PP_DATA) { |
43 | DPRINTF("data port\n"); | |
44 | switch(tr[i].cmdTrans) { | |
45 | case PP_READ: | |
46 | ret = 0; /* We don't support reading of the data port */ | |
47 | break; | |
48 | ||
49 | case PP_WRITE: | |
50 | ret = ioctl(parportfd, PPWDATA, &val); | |
51 | last_pp_write = val; | |
52 | break; | |
53 | ||
54 | default: | |
55 | fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans); | |
56 | ret = -1; | |
57 | break; | |
58 | } | |
59 | } else if (port == ppbase + PP_STATUS) { | |
60 | DPRINTF("status port (last write: %d)\n", last_pp_write); | |
61 | switch(tr[i].cmdTrans) { | |
62 | case PP_READ: | |
63 | ret = ioctl(parportfd, PPRSTATUS, &val); | |
64 | #ifdef FORCE_PC3_IDENT | |
65 | val &= 0x5f; | |
66 | if (last_pp_write & 0x40) | |
67 | val |= 0x20; | |
68 | else | |
69 | val |= 0x80; | |
70 | #endif | |
71 | break; | |
72 | ||
73 | case PP_WRITE: | |
74 | ret = 0; /* Status Port is readonly */ | |
75 | break; | |
76 | ||
77 | default: | |
78 | fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans); | |
79 | ret = -1; | |
80 | break; | |
81 | } | |
82 | } else if (port == ppbase + PP_CONTROL) { | |
83 | DPRINTF("control port\n"); | |
84 | switch(tr[i].cmdTrans) { | |
85 | case PP_READ: | |
86 | ret = ioctl(parportfd, PPRCONTROL, &val); | |
87 | break; | |
88 | ||
89 | case PP_WRITE: | |
90 | ret = ioctl(parportfd, PPWCONTROL, &val); | |
91 | break; | |
92 | ||
93 | default: | |
94 | fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans); | |
95 | ret = -1; | |
96 | break; | |
97 | } | |
98 | } else if ((port == ecpbase + PP_ECP_CFGA) && ecpbase) { | |
99 | DPRINTF("ECP_CFGA port\n"); | |
100 | } else if ((port == ecpbase + PP_ECP_CFGB) && ecpbase) { | |
101 | DPRINTF("ECP_CFGB port\n"); | |
102 | } else if ((port == ecpbase + PP_ECP_ECR) && ecpbase) { | |
103 | DPRINTF("ECP_ECR port\n"); | |
104 | } else { | |
105 | DPRINTF("access to unsupported address range!\n"); | |
106 | ret = 0; | |
107 | } | |
108 | ||
109 | tr[i].Data.Byte = val; | |
110 | ||
111 | DPRINTF("dwPortReturn: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n", | |
112 | (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes, | |
113 | tr[i].fAutoinc, tr[i].dwOptions); | |
114 | #ifdef DEBUG | |
115 | if (tr[i].cmdTrans == 10) | |
116 | DPRINTF("read byte: %d\n", tr[i].Data.Byte); | |
117 | #endif | |
118 | } | |
119 | ||
cf55ed64 MG |
120 | ioctl(parportfd, PPRELEASE); |
121 | ||
5e3d963b | 122 | return ret; |
123 | } | |
124 | ||
125 | int parport_open(int num) { | |
126 | char ppdev[32]; | |
127 | ||
128 | if (parportfd < 0) { | |
129 | snprintf(ppdev, sizeof(ppdev), "/dev/parport%u", num); | |
130 | DPRINTF("opening %s\n", ppdev); | |
131 | parportfd = open(ppdev, O_RDWR|O_EXCL); | |
132 | ||
133 | if (parportfd < 0) | |
134 | fprintf(stderr,"Can't open %s: %s\n", ppdev, strerror(errno)); | |
135 | } | |
136 | ||
137 | if (parportfd >= 0) { | |
138 | int pmode; | |
139 | ||
140 | if (ioctl(parportfd, PPCLAIM) == -1) | |
141 | return -1; | |
142 | ||
143 | pmode = IEEE1284_MODE_COMPAT; | |
144 | if (ioctl(parportfd, PPNEGOT, &pmode) == -1) | |
145 | return -1; | |
146 | ||
cf55ed64 | 147 | ioctl(parportfd, PPRELEASE); |
5e3d963b | 148 | #if 0 |
149 | if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr) { | |
150 | DPRINTF("ECP mode requested\n"); | |
151 | ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr; | |
152 | /* TODO: Implement ECP mode */ | |
153 | pmode = IEEE1284_MODE_ECP; | |
154 | ||
155 | if (ioctl(parportfd, PPNEGOT, &pmode) == -1) { | |
156 | ecpbase = 0; | |
157 | pmode = IEEE1284_MODE_COMPAT; | |
158 | if (ioctl(parportfd, PPNEGOT, &pmode) == -1) | |
159 | return ret; | |
160 | } | |
161 | } | |
162 | #endif | |
163 | } | |
164 | ||
165 | return parportfd; | |
166 | } | |
167 | ||
168 | void parport_close(int handle) { | |
169 | if (parportfd == handle && parportfd >= 0) { | |
170 | ioctl(parportfd, PPRELEASE); | |
171 | close(parportfd); | |
172 | parportfd = -1; | |
173 | } | |
174 | } |