]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/parport/parport.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / parport / parport.c
1
2 #include <stdio.h>
3 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <fcntl.h>
8 #include <dos.h>
9
10 #include <hw/cpu/cpu.h>
11 #include <hw/dos/dos.h>
12 #include <hw/dos/doswin.h>
13 #include <hw/parport/parport.h>
14
15 const char *parport_type_str[PARPORT_MAX] = {
16         "Standard",
17         "Bi-directional",
18         "ECP",
19         "EPP",
20         "ECP+EPP"
21 };
22
23 int                             init_parports = 0;
24 int                             bios_parports = 0;
25 uint16_t                        standard_parport_ports[STANDARD_PARPORT_PORTS] = {0x3BC,0x378,0x278};
26 struct info_parport             info_parport[MAX_PARPORTS];
27 int                             info_parports=0;
28
29 int already_got_parport(uint16_t port) {
30         unsigned int i;
31
32         for (i=0;i < (unsigned int)info_parports;i++) {
33                 if (info_parport[i].port == port)
34                         return 1;
35         }
36
37         return 0;
38 }
39
40 uint16_t get_bios_parport(unsigned int index) {
41         if (index >= (unsigned int)bios_parports)
42                 return 0;
43
44 #if TARGET_MSDOS == 32
45         return *((uint16_t*)(0x400 + 8 + (index*2)));
46 #else
47         return *((uint16_t far*)MK_FP(0x40,8 + (index*2)));
48 #endif
49 }
50
51 int init_parport() {
52         if (!init_parports) {
53                 uint16_t eqw;
54
55                 bios_parports = 0;
56                 info_parports = 0;
57                 init_parports = 1;
58
59                 memset(info_parport,0,sizeof(info_parport));
60
61                 /* read the BIOS equipment word[11-9]. how many serial ports? */
62 #if TARGET_MSDOS == 32
63                 eqw = *((uint16_t*)(0x400 + 0x10));
64 #else
65                 eqw = *((uint16_t far*)MK_FP(0x40,0x10));
66 #endif
67                 bios_parports = (eqw >> 14) & 3;
68
69         }
70         return 1;
71 }
72
73 /* TODO: Add code where if caller guesses by PnP info the port is ECP or EPP (or both) we
74  *       omit some tests and assume it's correct.
75  *
76  *       Example: If the BIOS reports two I/O ports and they are 0x400 apart, then the port
77  *       is an ECP type and ECP type tests are unnecessary. If PnP data lists the I/O range
78  *       as being 8 ports long, then it's probably an EPP type port too and we can omit
79  *       those tests. */
80 int add_pnp_parport(uint16_t port,int irq,int dma,int type) {
81         struct info_parport *prt;
82         char bit10 = 0;
83
84         if (port == 0)
85                 return 0;
86         if (already_got_parport(port))
87                 return 0;
88         if (info_parports >= MAX_PARPORTS)
89                 return 0;
90         prt = &info_parport[info_parports];
91         prt->bit10 = 0;
92         prt->max_xfer_size = 1;
93         prt->port = port;
94         prt->output_mode = PARPORT_MODE_STANDARD_STROBE_ACK;
95         prt->type = PARPORT_STANDARD;
96         prt->irq = irq;
97         prt->dma = dma;
98
99         if (type >= 0) {
100                 /* if the caller knows better than us, then take his word for it */
101                 prt->type = type;
102
103                 if (PARPORT_SUPPORTS_ECP(prt->type)) {
104                         unsigned char a,b;
105
106                         /* detect ECP by attempting to enable the configuration mode */
107                         outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5);
108                         a = inp(prt->port+PARPORT_IO_ECP_REG_A);
109                         b = inp(prt->port+PARPORT_IO_ECP_REG_B);
110
111                         if (a != 0xFF && b != 0xFF) {
112                                 prt->type = PARPORT_ECP;
113
114                                 switch ((a >> 4) & 7) {
115                                         case 0: prt->max_xfer_size = 2; break;
116                                         case 1: prt->max_xfer_size = 1; break;
117                                         case 2: prt->max_xfer_size = 4; break;
118                                 }
119
120                                 if (prt->irq < 0) {
121                                         switch ((b >> 3) & 7) {
122                                                 case 1: prt->irq = 7; break;
123                                                 case 2: prt->irq = 9; break;
124                                                 case 3: prt->irq = 10; break;
125                                                 case 4: prt->irq = 11; break;
126                                                 case 5: prt->irq = 14; break;
127                                                 case 6: prt->irq = 15; break;
128                                                 case 7: prt->irq = 5; break;
129                                         }
130                                 }
131
132                                 if (prt->dma < 0) {
133                                         switch (b&7) {
134                                                 case 1: prt->dma = 1; break;
135                                                 case 2: prt->dma = 2; break;
136                                                 case 3: prt->dma = 3; break;
137                                                 case 5: prt->dma = 5; break;
138                                                 case 6: prt->dma = 6; break;
139                                                 case 7: prt->dma = 7; break;
140                                         }
141                                 }
142                         }
143
144                         /* switch to EPP mode for the test below if the ECP port supports it */
145                         if (prt->type == PARPORT_ECP)
146                                 outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5);
147                 }
148         }
149         else {
150                 /* this might be one of those EPP/ECP ports, set it to "standard byte mode" to enable the below test to find the port.
151                  * documentation mentions that "in ECP mode the SPP ports may disappear" so to successfully probe ports left in ECP
152                  * mode we have to write to the control register to bring it back.
153                  *
154                  * The (minimal) documentation I have doesn't say whether this port can be read back.
155                  * On older 10-bit decode hardware, this will probably only end up writing over the control bits (0x77A -> 0x37A)
156                  * and should be safe to carry out. On newer hardware (mid 90's) it's highly unlikely anything would be assigned
157                  * to I/O ports 0x778-0x77F. On newer PCI hardware, it's even less likely. */
158                 outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5);  /* mode=byte (bi-directional) ecpint=0 dma=0 ecpserv=0 */
159
160                 /* put it back into Standard mode, disable bi-directional */
161                 outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 */
162                 /* control ports are usually readable. if what we wrote didn't take then this is probably not a parallel port */
163                 if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) != 0x4) return 0;
164
165                 /* write to the control port again. if this is ancient 10-bit decode hardware, then it is probably NOT ECP/EPP
166                  * compliant. we detect this by whether this IO write corrupts the control register.
167                  * note control = port+2 and extended control = port+0x402 */
168                 outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0xC);  /* CONTROL = sets bidirectional, and two control lines. EXTCTRL = maintains byte mode and turns on ECP interrupt+DMA */
169                 if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) == 0xC) /* if the +0x402 IO write changed the control register, then it's 10-bit decode and not EPP/ECP */
170                         bit10 = 1;
171
172                 outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0x0); /* regain sane extended control */
173                 outp(prt->port+PARPORT_IO_CONTROL,0x04);
174
175                 /* the data port is write only, though you are always allowed to read it back.
176                  * on bidirectional ports this is how you read back data.
177                  * we do not attempt to write to the status port. it is read only. worse, on modern
178                  * systems it can conflict with the ISA Plug & Play protocol (0x279) */
179                 outp(prt->port,0x55); if (inp(prt->port) != 0x55) return 0;
180                 outp(prt->port,0xAA); if (inp(prt->port) != 0xAA) return 0;
181                 outp(prt->port,0xFF); if (inp(prt->port) != 0xFF) return 0;
182                 outp(prt->port,0x00); if (inp(prt->port) != 0x00) return 0;
183
184                 /* do a parport init printer */
185                 outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 */
186                 if ((inp(prt->port+PARPORT_IO_CONTROL)&0xF) != 0x4) return 0;
187
188                 /* try to toggle bit 5 (bi-directional enable) */
189                 outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */
190                 if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) == 0) {
191                         outp(prt->port+PARPORT_IO_CONTROL,0x24);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=1 */
192                         if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) != 0)
193                                 prt->type = PARPORT_BIDIRECTIONAL;
194
195                         outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */
196                 }
197
198                 /* standard I/O locations have standard IRQ assignments, apparently */
199                 prt->bit10 = bit10;
200                 if (!bit10) { /* if not 10-bit decode, then check for ECP control registers */
201                         unsigned char a,b;
202
203                         /* detect ECP by attempting to enable the configuration mode */
204                         outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5);
205                         a = inp(prt->port+PARPORT_IO_ECP_REG_A);
206                         b = inp(prt->port+PARPORT_IO_ECP_REG_B);
207
208                         if (a != 0xFF && b != 0xFF) {
209                                 prt->type = PARPORT_ECP;
210
211                                 switch ((a >> 4) & 7) {
212                                         case 0: prt->max_xfer_size = 2; break;
213                                         case 1: prt->max_xfer_size = 1; break;
214                                         case 2: prt->max_xfer_size = 4; break;
215                                 }
216
217                                 if (prt->irq < 0) {
218                                         switch ((b >> 3) & 7) {
219                                                 case 1: prt->irq = 7; break;
220                                                 case 2: prt->irq = 9; break;
221                                                 case 3: prt->irq = 10; break;
222                                                 case 4: prt->irq = 11; break;
223                                                 case 5: prt->irq = 14; break;
224                                                 case 6: prt->irq = 15; break;
225                                                 case 7: prt->irq = 5; break;
226                                         }
227                                 }
228
229                                 if (prt->dma < 0) {
230                                         switch (b&7) {
231                                                 case 1: prt->dma = 1; break;
232                                                 case 2: prt->dma = 2; break;
233                                                 case 3: prt->dma = 3; break;
234                                                 case 5: prt->dma = 5; break;
235                                                 case 6: prt->dma = 6; break;
236                                                 case 7: prt->dma = 7; break;
237                                         }
238                                 }
239                         }
240
241                         /* switch to EPP mode for the test below if the ECP port supports it */
242                         if (prt->type == PARPORT_ECP)
243                                 outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5);
244                 }
245         }
246
247         if (type < 0 || PARPORT_SUPPORTS_EPP(type)) {
248                 /* the caller might be autodetecting EPP based on the I/O length.
249                  * we double-check to be sure, it might be some bullshit BIOS
250                  * reporting 8 ports long for a device that only responds to the
251                  * first three */
252
253                 /* an EPP port could conceivably exist on a 10-bit decode ISA card */
254                 /* NOTES: Toshiba laptops do NOT support EPP mode, only ECP. There appears to be a hardware
255                  *        bug in decoding the 0x778-0x77F I/O region where port 0x77A is repeated on 0x77B,
256                  *        0x77C, etc.
257                  *
258                  *        The Compaq LTE Elite supports EPP and ECP. It follows the standard in ignoring
259                  *        the bidir bit when setting mode 0, but does not disable EPP registers when
260                  *        mode is not EPP.
261                  *          ... erm, well, at least I think the extra registers are EPP. The address port
262                  *          always returns 0x00 and the data port always returns 0x25 (this is with nothing
263                  *          attached to the parallel port). The problem is we can only detect if something
264                  *          is there, we can't tell if it's an EPP port or just some ancient ISA card that
265                  *          responds to 0x3FB-0x3FF with it's own weirdness. A Google search for Compaq LTE
266                  *          Elite and parallel port suggests that there are tools to configure the port as
267                  *          EPP, so obviously at some level it speaks EPP mode. */
268                 if (inp(prt->port+PARPORT_IO_EPP_ADDRESS) != 0xFF && inp(prt->port+PARPORT_IO_EPP_DATA) != 0xFF) {
269                         if (prt->type == PARPORT_ECP)
270                                 prt->type = PARPORT_ECP_AND_EPP;
271                         else
272                                 prt->type = PARPORT_EPP;
273                 }
274         }
275
276         /* return the port to standard bidir mode */
277         if (PARPORT_SUPPORTS_ECP(prt->type))
278                 outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5);
279
280         /* shut off the lines */
281         outp(prt->port+PARPORT_IO_CONTROL,0x00);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */
282         outp(prt->port+PARPORT_IO_DATA,0x00);
283
284         info_parports++;
285         return 1;
286 }
287
288 int probe_parport(uint16_t port) {
289         struct info_parport *prt;
290         char bit10 = 0;
291
292         if (port == 0)
293                 return 0;
294         if (already_got_parport(port))
295                 return 0;
296         if (info_parports >= MAX_PARPORTS)
297                 return 0;
298         prt = &info_parport[info_parports];
299         prt->bit10 = 0;
300         prt->max_xfer_size = 1;
301         prt->port = port;
302         prt->output_mode = PARPORT_MODE_STANDARD_STROBE_ACK;
303         prt->type = PARPORT_STANDARD;
304         prt->irq = -1;
305         prt->dma = -1;
306
307         /* this might be one of those EPP/ECP ports, set it to "standard byte mode" to enable the below test to find the port.
308          * documentation mentions that "in ECP mode the SPP ports may disappear" so to successfully probe ports left in ECP
309          * mode we have to write to the control register to bring it back.
310          *
311          * The (minimal) documentation I have doesn't say whether this port can be read back.
312          * On older 10-bit decode hardware, this will probably only end up writing over the control bits (0x77A -> 0x37A)
313          * and should be safe to carry out. On newer hardware (mid 90's) it's highly unlikely anything would be assigned
314          * to I/O ports 0x778-0x77F. On newer PCI hardware, it's even less likely. */
315         outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5);  /* mode=byte (bi-directional) ecpint=0 dma=0 ecpserv=0 */
316
317         /* put it back into Standard mode, disable bi-directional */
318         outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 */
319         /* control ports are usually readable. if what we wrote didn't take then this is probably not a parallel port */
320         if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) != 0x4) return 0;
321
322         /* write to the control port again. if this is ancient 10-bit decode hardware, then it is probably NOT ECP/EPP
323          * compliant. we detect this by whether this IO write corrupts the control register.
324          * note control = port+2 and extended control = port+0x402 */
325         outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0xC);  /* CONTROL = sets bidirectional, and two control lines. EXTCTRL = maintains byte mode and turns on ECP interrupt+DMA */
326         if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) == 0xC) /* if the +0x402 IO write changed the control register, then it's 10-bit decode and not EPP/ECP */
327                 bit10 = 1;
328
329         outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0x0); /* regain sane extended control */
330         outp(prt->port+PARPORT_IO_CONTROL,0x04);
331
332         /* the data port is write only, though you are always allowed to read it back.
333          * on bidirectional ports this is how you read back data.
334          * we do not attempt to write to the status port. it is read only. worse, on modern
335          * systems it can conflict with the ISA Plug & Play protocol (0x279) */
336         outp(prt->port,0x55); if (inp(prt->port) != 0x55) return 0;
337         outp(prt->port,0xAA); if (inp(prt->port) != 0xAA) return 0;
338         outp(prt->port,0xFF); if (inp(prt->port) != 0xFF) return 0;
339         outp(prt->port,0x00); if (inp(prt->port) != 0x00) return 0;
340
341         /* do a parport init printer */
342         outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 */
343         if ((inp(prt->port+PARPORT_IO_CONTROL)&0xF) != 0x4) return 0;
344
345         /* try to toggle bit 5 (bi-directional enable) */
346         outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */
347         if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) == 0) {
348                 outp(prt->port+PARPORT_IO_CONTROL,0x24);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=1 */
349                 if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) != 0)
350                         prt->type = PARPORT_BIDIRECTIONAL;
351
352                 outp(prt->port+PARPORT_IO_CONTROL,0x04);        /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */
353         }
354
355         /* standard I/O locations have standard IRQ assignments, apparently */
356         prt->bit10 = bit10;
357         if (prt->port == 0x3BC)
358                 prt->irq = 2;
359         else if (prt->port == 0x378)
360                 prt->irq = 7;
361         else if (prt->port == 0x278)
362                 prt->irq = 5;
363
364         if (!bit10) { /* if not 10-bit decode, then check for ECP control registers */
365                 unsigned char a,b;
366
367                 /* detect ECP by attempting to enable the configuration mode */
368                 outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5);
369                 a = inp(prt->port+PARPORT_IO_ECP_REG_A);
370                 b = inp(prt->port+PARPORT_IO_ECP_REG_B);
371
372                 if (a != 0xFF && b != 0xFF) {
373                         prt->type = PARPORT_ECP;
374
375                         switch ((a >> 4) & 7) {
376                                 case 0: prt->max_xfer_size = 2; break;
377                                 case 1: prt->max_xfer_size = 1; break;
378                                 case 2: prt->max_xfer_size = 4; break;
379                         }
380
381                         switch ((b >> 3) & 7) {
382                                 case 1: prt->irq = 7; break;
383                                 case 2: prt->irq = 9; break;
384                                 case 3: prt->irq = 10; break;
385                                 case 4: prt->irq = 11; break;
386                                 case 5: prt->irq = 14; break;
387                                 case 6: prt->irq = 15; break;
388                                 case 7: prt->irq = 5; break;
389                         }
390
391                         switch (b&7) {
392                                 case 1: prt->dma = 1; break;
393                                 case 2: prt->dma = 2; break;
394                                 case 3: prt->dma = 3; break;
395                                 case 5: prt->dma = 5; break;
396                                 case 6: prt->dma = 6; break;
397                                 case 7: prt->dma = 7; break;
398                         }
399                 }
400
401                 /* switch to EPP mode for the test below if the ECP port supports it */
402                 if (prt->type == PARPORT_ECP)
403                         outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5);
404         }
405
406         /* an EPP port could conceivably exist on a 10-bit decode ISA card */
407         /* NOTES: Toshiba laptops do NOT support EPP mode, only ECP. There appears to be a hardware
408          *        bug in decoding the 0x778-0x77F I/O region where port 0x77A is repeated on 0x77B,
409          *        0x77C, etc.
410          *
411          *        The Compaq LTE Elite supports EPP and ECP. It follows the standard in ignoring
412          *        the bidir bit when setting mode 0, but does not disable EPP registers when
413          *        mode is not EPP.
414          *          ... erm, well, at least I think the extra registers are EPP. The address port
415          *          always returns 0x00 and the data port always returns 0x25 (this is with nothing
416          *          attached to the parallel port). The problem is we can only detect if something
417          *          is there, we can't tell if it's an EPP port or just some ancient ISA card that
418          *          responds to 0x3FB-0x3FF with it's own weirdness. A Google search for Compaq LTE
419          *          Elite and parallel port suggests that there are tools to configure the port as
420          *          EPP, so obviously at some level it speaks EPP mode. */
421         if (inp(prt->port+PARPORT_IO_EPP_ADDRESS) != 0xFF && inp(prt->port+PARPORT_IO_EPP_DATA) != 0xFF) {
422                 if (prt->type == PARPORT_ECP)
423                         prt->type = PARPORT_ECP_AND_EPP;
424                 else
425                         prt->type = PARPORT_EPP;
426         }
427
428         /* return the port to standard bidir mode */
429         if (PARPORT_SUPPORTS_ECP(prt->type))
430                 outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5);
431
432         /* shut off the lines */
433         outp(prt->port+PARPORT_IO_CONTROL,0x00);        /* select=0 init=0 autolinefeed=0 strobe=0 bidir=0 */
434         outp(prt->port+PARPORT_IO_DATA,0x00);
435
436         info_parports++;
437         return 1;
438 }
439