Deleted Added
full compact
ppc.c (35256) ppc.c (38061)
1/*-
1/*-
2 * Copyright (c) 1997 Nicolas Souchu
2 * Copyright (c) 1997, 1998 Nicolas Souchu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: ppc.c,v 1.2 1997/09/01 02:08:41 bde Exp $
26 * $Id: ppc.c,v 1.3 1998/04/17 22:36:37 des Exp $
27 *
28 */
29#include "ppc.h"
30
31#if NPPC > 0
32
33#include <sys/param.h>
34#include <sys/systm.h>

--- 4 unchanged lines hidden (view full) ---

39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <i386/isa/isa_device.h>
45
46#include <dev/ppbus/ppbconf.h>
27 *
28 */
29#include "ppc.h"
30
31#if NPPC > 0
32
33#include <sys/param.h>
34#include <sys/systm.h>

--- 4 unchanged lines hidden (view full) ---

39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <i386/isa/isa_device.h>
45
46#include <dev/ppbus/ppbconf.h>
47#include <dev/ppbus/ppb_msq.h>
48
47#include <i386/isa/ppcreg.h>
48
49static int ppcprobe(struct isa_device *);
50static int ppcattach(struct isa_device *);
51
52struct isa_driver ppcdriver = {
53 ppcprobe, ppcattach, "ppc"
54};
55
56static struct ppc_data *ppcdata[NPPC];
57static int nppc = 0;
58
59static char *ppc_types[] = {
49#include <i386/isa/ppcreg.h>
50
51static int ppcprobe(struct isa_device *);
52static int ppcattach(struct isa_device *);
53
54struct isa_driver ppcdriver = {
55 ppcprobe, ppcattach, "ppc"
56};
57
58static struct ppc_data *ppcdata[NPPC];
59static int nppc = 0;
60
61static char *ppc_types[] = {
60 "SMC", "SMC FDC37C665GT", "SMC FDC37C666GT",
61 "NatSemi", "PC87332", "PC87306",
62 "Intel 82091AA", "Generic", 0
62 "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
63 "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0
63};
64
64};
65
66/* list of available modes */
67static char *ppc_avms[] = {
68 "COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only",
69 "EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only",
70 "ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP",
71 "ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0
72};
73
74/* list of current executing modes
75 * Note that few modes do not actually exist.
76 */
65static char *ppc_modes[] = {
77static char *ppc_modes[] = {
66 "AUTODETECT", "NIBBLE", "PS/2", "EPP", "ECP+EPP", "ECP+PS/2", "ECP",
67 "UNKNOWN", 0
78 "COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP",
79 "EPP", "EPP", "EPP", "ECP",
80 "ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP",
81 "ECP+EPP", "ECP+EPP", "ECP+EPP", 0
68};
69
70static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
71
72/*
73 * BIOS printer list - used by BIOS probe.
74 */
75#define BIOS_PPC_PORTS 0x408

--- 29 unchanged lines hidden (view full) ---

105static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
106static void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); }
107static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
108static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
109
110static void ppc_reset_epp_timeout(int);
111static void ppc_ecp_sync(int);
112
82};
83
84static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
85
86/*
87 * BIOS printer list - used by BIOS probe.
88 */
89#define BIOS_PPC_PORTS 0x408

--- 29 unchanged lines hidden (view full) ---

119static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
120static void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); }
121static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
122static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
123
124static void ppc_reset_epp_timeout(int);
125static void ppc_ecp_sync(int);
126
127static int ppc_exec_microseq(int, struct ppb_microseq *, int *);
128static int ppc_generic_setmode(int, int);
129
113static struct ppb_adapter ppc_adapter = {
114
115 0, /* no intr handler, filled by chipset dependent code */
116
117 ppc_reset_epp_timeout, ppc_ecp_sync,
118
130static struct ppb_adapter ppc_adapter = {
131
132 0, /* no intr handler, filled by chipset dependent code */
133
134 ppc_reset_epp_timeout, ppc_ecp_sync,
135
136 ppc_exec_microseq,
137
138 ppc_generic_setmode,
139
119 ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
120 ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
121
122 ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
123 ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
124};
125
126/*

--- 11 unchanged lines hidden (view full) ---

138
139 for (i = 0; i < 100; i++) {
140 r = r_ecr(ppc);
141 if (r & 0x1)
142 return;
143 DELAY(100);
144 }
145
140 ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
141 ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
142
143 ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
144 ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
145};
146
147/*

--- 11 unchanged lines hidden (view full) ---

159
160 for (i = 0; i < 100; i++) {
161 r = r_ecr(ppc);
162 if (r & 0x1)
163 return;
164 DELAY(100);
165 }
166
146 printf("ppc: ECP sync failed as data still " \
147 "present in FIFO.\n");
167 printf("ppc%d: ECP sync failed as data still " \
168 "present in FIFO.\n", unit);
148
149 return;
150}
151
152void
153ppcintr(int unit)
154{
155 /* call directly upper code */
156 ppb_intr(&ppcdata[unit]->ppc_link);
157
158 return;
159}
160
169
170 return;
171}
172
173void
174ppcintr(int unit)
175{
176 /* call directly upper code */
177 ppb_intr(&ppcdata[unit]->ppc_link);
178
179 return;
180}
181
182static void
183ppc_ecp_config(struct ppc_data *ppc, int chipset_mode)
184{
185 /* XXX disable DMA, enable interrupts */
186 if (chipset_mode & PPB_EPP)
187 /* select EPP mode */
188 w_ecr(ppc, 0x80);
189 else if (chipset_mode & PPB_PS2)
190 /* select PS2 mode with ECP */
191 w_ecr(ppc, 0x20);
192 else
193 /* keep ECP mode alone, default for NIBBLE */
194 w_ecr(ppc, 0x70);
195
196 return;
197}
198
199static int
200ppc_detect_port(struct ppc_data *ppc)
201{
202
203 w_ctr(ppc, 0x0c); /* To avoid missing PS2 ports */
204 w_dtr(ppc, 0xaa);
205 if (r_dtr(ppc) != (char) 0xaa)
206 return (0);
207
208 return (1);
209}
210
161/*
162 * ppc_pc873xx_detect
163 *
164 * Probe for a Natsemi PC873xx-family part.
165 *
166 * References in this function are to the National Semiconductor
167 * PC87332 datasheet TL/C/11930, May 1995 revision.
168 */
169static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
170static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
171
172static int
211/*
212 * ppc_pc873xx_detect
213 *
214 * Probe for a Natsemi PC873xx-family part.
215 *
216 * References in this function are to the National Semiconductor
217 * PC87332 datasheet TL/C/11930, May 1995 revision.
218 */
219static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
220static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
221
222static int
173ppc_pc873xx_detect(struct ppc_data *ppc)
223ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */
174{
175 static int index = 0;
176 int base, idport;
224{
225 static int index = 0;
226 int base, idport;
177 int val, mode;
227 int val;
178
179 while ((idport = pc873xx_basetab[index++])) {
180
181 /* XXX should check first to see if this location is already claimed */
182
183 /*
184 * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this
185 * to locate the chip as it may already have been used by the BIOS.

--- 44 unchanged lines hidden (view full) ---

230 */
231 outb(idport, PC873_PTR);
232 val = inb(idport + 1);
233 if (val & PC873_CFGLOCK) {
234 if (bootverbose)
235 printf("PC873xx locked\n");
236
237 /* work out what mode we're in */
228
229 while ((idport = pc873xx_basetab[index++])) {
230
231 /* XXX should check first to see if this location is already claimed */
232
233 /*
234 * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this
235 * to locate the chip as it may already have been used by the BIOS.

--- 44 unchanged lines hidden (view full) ---

280 */
281 outb(idport, PC873_PTR);
282 val = inb(idport + 1);
283 if (val & PC873_CFGLOCK) {
284 if (bootverbose)
285 printf("PC873xx locked\n");
286
287 /* work out what mode we're in */
238 mode = PPB_NIBBLE; /* worst case */
288 ppc->ppc_avm |= PPB_NIBBLE; /* worst case */
239
240 outb(idport, PC873_PCR);
241 val = inb(idport + 1);
242 if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
243 outb(idport, PC873_PTR);
244 val = inb(idport + 1);
245 if (!(val & PC873_EPPRDIR)) {
289
290 outb(idport, PC873_PCR);
291 val = inb(idport + 1);
292 if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
293 outb(idport, PC873_PTR);
294 val = inb(idport + 1);
295 if (!(val & PC873_EPPRDIR)) {
246 mode = PPB_EPP; /* As we would have done it anwyay */
296 ppc->ppc_avm |= PPB_EPP; /* As we would have done it anwyay */
247 }
248 } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
297 }
298 } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
249 mode = PPB_PS2; /* tolerable alternative */
299 ppc->ppc_avm |= PPB_PS2; /* tolerable alternative */
250 }
251 } else {
252 if (bootverbose)
253 printf("PC873xx unlocked, ");
254
255#if 0 /* broken */
256 /*
257 * Frob the zero-wait-state option if possible; it causes

--- 36 unchanged lines hidden (view full) ---

294 /* enable automatic direction turnover */
295 outb(idport, PC873_PTR);
296 val = inb(idport + 1);
297 val &= ~PC873_EPPRDIR; /* disable "regular" direction change */
298 outb(idport + 1, val);
299 outb(idport + 1, val);
300
301 /* we are an EPP-32 port */
300 }
301 } else {
302 if (bootverbose)
303 printf("PC873xx unlocked, ");
304
305#if 0 /* broken */
306 /*
307 * Frob the zero-wait-state option if possible; it causes

--- 36 unchanged lines hidden (view full) ---

344 /* enable automatic direction turnover */
345 outb(idport, PC873_PTR);
346 val = inb(idport + 1);
347 val &= ~PC873_EPPRDIR; /* disable "regular" direction change */
348 outb(idport + 1, val);
349 outb(idport + 1, val);
350
351 /* we are an EPP-32 port */
302 mode = PPB_EPP;
352 ppc->ppc_avm |= PPB_EPP;
303 } else {
304 if (bootverbose)
305 printf("ECP\n");
306
307 /* configure as an ECP port to get bidirectional operation for now */
308 outb(idport, PC873_PCR);
309 outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
310
311 /* we look like a PS/2 port */
353 } else {
354 if (bootverbose)
355 printf("ECP\n");
356
357 /* configure as an ECP port to get bidirectional operation for now */
358 outb(idport, PC873_PCR);
359 outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
360
361 /* we look like a PS/2 port */
312 mode = PPB_PS2;
362 ppc->ppc_avm |= PPB_PS2;
313 }
314 }
363 }
364 }
315 return(mode);
365
366 return(chipset_mode);
316 }
367 }
317 return(0);
368 return(-1);
318}
319
320static int
369}
370
371static int
321ppc_detect_ps2(struct ppc_data *ppc)
372ppc_check_epp_timeout(struct ppc_data *ppc)
322{
373{
323 char save_control, r;
374 ppc_reset_epp_timeout(ppc->ppc_unit);
324
375
325 save_control = r_ctr(ppc);
326
327 /* Try PS/2 mode */
328 w_ctr(ppc, 0xec);
329 w_dtr(ppc, 0x55);
330
331 /* needed if in ECP mode */
332 if (ppc->ppc_mode == PPB_ECP)
333 w_ctr(ppc, PCD | 0xec);
334 r = r_dtr(ppc);
335
336 if (r != (char) 0xff) {
337 if (r != (char) 0x55)
338 return 0;
339
340 w_dtr(ppc, 0xaa);
341 r = r_dtr(ppc);
342 if (r != (char) 0xaa)
343 return 0;
344
345 return (PPB_NIBBLE);
346 } else
347 w_ctr(ppc, save_control);
348
349 return (PPB_PS2);
376 return (!(r_str(ppc) & TIMEOUT));
350}
351
352/*
353 * ppc_smc37c66xgt_detect
354 *
355 * SMC FDC37C66xGT configuration.
356 */
357static int
377}
378
379/*
380 * ppc_smc37c66xgt_detect
381 *
382 * SMC FDC37C66xGT configuration.
383 */
384static int
358ppc_smc37c66xgt_detect(struct ppc_data *ppc, int mode)
385ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
359{
360 int s, i;
361 char r;
386{
387 int s, i;
388 char r;
362 int retry = 0; /* boolean */
363 int type = -1;
364 int csr = SMC66x_CSR; /* initial value is 0x3F0 */
365
366 int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
367
368
369#define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */
370

--- 28 unchanged lines hidden (view full) ---

399 csr = SMC666_CSR;
400 }
401
402config:
403 /*
404 * If chipset not found, do not continue.
405 */
406 if (type == -1)
389 int type = -1;
390 int csr = SMC66x_CSR; /* initial value is 0x3F0 */
391
392 int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
393
394
395#define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */
396

--- 28 unchanged lines hidden (view full) ---

425 csr = SMC666_CSR;
426 }
427
428config:
429 /*
430 * If chipset not found, do not continue.
431 */
432 if (type == -1)
407 return (0);
433 return (-1);
408
409 /* select CR1 */
410 outb(csr, 0x1);
411
412 /* read the port's address: bits 0 and 1 of CR1 */
413 r = inb(cio) & SMC_CR1_ADDR;
414 if (port_address[r] != ppc->ppc_base)
434
435 /* select CR1 */
436 outb(csr, 0x1);
437
438 /* read the port's address: bits 0 and 1 of CR1 */
439 r = inb(cio) & SMC_CR1_ADDR;
440 if (port_address[r] != ppc->ppc_base)
415 return (0);
441 return (-1);
416
417 ppc->ppc_type = type;
418
419 /*
420 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
442
443 ppc->ppc_type = type;
444
445 /*
446 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
421 * If SPP mode is detected, try to set ECP+EPP mode end retry
422 * detection to verify.
447 * If SPP mode is detected, try to set ECP+EPP mode
423 */
424
448 */
449
425retry:
426 /* select CR1 register */
450 if (bootverbose) {
451 outb(csr, 0x1);
452 printf("SMC registers CR1=0x%x", ppc->ppc_unit,
453 inb(cio) & 0xff);
454
455 outb(csr, 0x4);
456 printf(" CR4=0x%x", inb(cio) & 0xff);
457 }
458
459 /* select CR1 */
427 outb(csr, 0x1);
428
460 outb(csr, 0x1);
461
429 if (!mode) {
462 if (!chipset_mode) {
430 /* autodetect mode */
431
463 /* autodetect mode */
464
432 /* 666GT chipset is hardwired to an extended mode */
433 if (type == SMC_37C666GT)
434 mode = PPB_ECP_EPP;
465 /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
466 if (type == SMC_37C666GT) {
467 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
435
468
436 else if ((inb(cio) & SMC_CR1_MODE) == 0) {
469 } else
470 if ((inb(cio) & SMC_CR1_MODE) == 0) {
437 /* already in extended parallel port mode, read CR4 */
438 outb(csr, 0x4);
439 r = (inb(cio) & SMC_CR4_EMODE);
440
441 switch (r) {
442 case SMC_SPP:
471 /* already in extended parallel port mode, read CR4 */
472 outb(csr, 0x4);
473 r = (inb(cio) & SMC_CR4_EMODE);
474
475 switch (r) {
476 case SMC_SPP:
443 /* let's detect NIBBLE or PS/2 later */
477 ppc->ppc_avm |= PPB_SPP;
444 break;
445
446 case SMC_EPPSPP:
478 break;
479
480 case SMC_EPPSPP:
447 mode = PPB_EPP;
481 ppc->ppc_avm |= PPB_EPP | PPB_SPP;
448 break;
449
450 case SMC_ECP:
482 break;
483
484 case SMC_ECP:
451 /*
452 * Yet, don't know what to do with it! XXX
453 * So, consider ECP mode as PS/2.
454 * (see configuration later).
455 */
456 mode = PPB_ECP;
485 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
457 break;
458
459 case SMC_ECPEPP:
486 break;
487
488 case SMC_ECPEPP:
460 mode = PPB_ECP_EPP;
489 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
461 break;
462 }
490 break;
491 }
463 }
492 } else {
493 /* not an extended port mode */
494 ppc->ppc_avm |= PPB_SPP;
495 }
496
464 } else {
465 /* mode forced */
466
497 } else {
498 /* mode forced */
499
467 /* 666GT chipset is hardwired to an extended mode */
500 /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
468 if (type == SMC_37C666GT)
469 goto end_detect;
470
471 r = inb(cio);
501 if (type == SMC_37C666GT)
502 goto end_detect;
503
504 r = inb(cio);
472 if (mode == PPB_NIBBLE || mode == PPB_PS2) {
473 /* do not use ECP when the mode is forced to SPP */
505 if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) {
506 /* do not use ECP when the mode is not forced to */
474 outb(cio, r | SMC_CR1_MODE);
475 } else {
476 /* an extended mode is selected */
477 outb(cio, r & ~SMC_CR1_MODE);
478
479 /* read CR4 register and reset mode field */
480 outb(csr, 0x4);
481 r = inb(cio) & ~SMC_CR4_EMODE;
482
507 outb(cio, r | SMC_CR1_MODE);
508 } else {
509 /* an extended mode is selected */
510 outb(cio, r & ~SMC_CR1_MODE);
511
512 /* read CR4 register and reset mode field */
513 outb(csr, 0x4);
514 r = inb(cio) & ~SMC_CR4_EMODE;
515
483 switch (mode) {
484 case PPB_EPP:
516 if (chipset_mode & PPB_ECP) {
517 if (chipset_mode & PPB_EPP) {
518 outb(cio, r | SMC_ECPEPP);
519 } else {
520 outb(cio, r | SMC_ECP);
521 }
522 } else {
523 /* PPB_EPP is set */
485 outb(cio, r | SMC_EPPSPP);
524 outb(cio, r | SMC_EPPSPP);
486 break;
487
488 case PPB_ECP:
489 case PPB_ECP_PS2:
490 outb(cio, r | SMC_ECP);
491 break;
492
493 case PPB_ECP_EPP:
494 outb(cio, r | SMC_ECPEPP);
495 break;
496
497 default:
498 printf("ppc: unknown mode (%d)\n",
499 mode);
500 return (0);
501 }
502 }
525 }
526 }
527 ppc->ppc_avm = chipset_mode;
503 }
504
505end_detect:
528 }
529
530end_detect:
506 if (PPB_IS_EPP(mode)) {
531
532 if (bootverbose)
533 printf ("\n");
534
535 if (chipset_mode & PPB_EPP) {
507 /* select CR4 */
508 outb(csr, 0x4);
509 r = inb(cio);
510
511 /*
512 * Set the EPP protocol...
513 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
536 /* select CR4 */
537 outb(csr, 0x4);
538 r = inb(cio);
539
540 /*
541 * Set the EPP protocol...
542 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
514 * ...then check the result.
515 */
516 if (ppc->ppc_epp == EPP_1_9)
517 outb(cio, (r & ~SMC_CR4_EPPTYPE));
543 */
544 if (ppc->ppc_epp == EPP_1_9)
545 outb(cio, (r & ~SMC_CR4_EPPTYPE));
518
519 else
520 outb(cio, (r | SMC_CR4_EPPTYPE));
521 }
522
523 /* end config mode */
524 outb(csr, 0xaa);
525
546 else
547 outb(cio, (r | SMC_CR4_EPPTYPE));
548 }
549
550 /* end config mode */
551 outb(csr, 0xaa);
552
526 /*
527 * Write 100 to the mode bits and disable DMA, enable intr.
528 */
529 if (mode == PPB_ECP_EPP)
530 w_ecr(ppc, 0x80);
553 if (ppc->ppc_avm & PPB_ECP)
554 ppc_ecp_config(ppc, chipset_mode);
531
555
532 /*
533 * Write 001 to the mode bits and disable DMA, enable intr.
534 */
535 if (mode == PPB_ECP)
536 w_ecr(ppc, 0x20);
556 return (chipset_mode);
557}
537
558
538 if (PPB_IS_EPP(mode)) {
559/*
560 * Winbond W83877F stuff
561 *
562 * EFER: extended function enable register
563 * EFIR: extended function index register
564 * EFDR: extended function data register
565 */
566#define efir ((efer == 0x250) ? 0x251 : 0x3f0)
567#define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
568
569static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 };
570static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 };
571static int w83877f_keyiter[] = { 1, 2, 2, 1 };
572static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 };
573
574static int
575ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
576{
577 int i, j, efer, base;
578 unsigned char r, hefere, hefras;
579
580 for (i = 0; i < 4; i ++) {
581 /* first try to enable configuration registers */
582 efer = w83877f_efers[i];
583
584 /* write the key to the EFER */
585 for (j = 0; j < w83877f_keyiter[i]; j ++)
586 outb (efer, w83877f_keys[i]);
587
588 /* then check HEFERE and HEFRAS bits */
589 outb (efir, 0x0c);
590 hefere = inb(efdr) & WINB_HEFERE;
591
592 outb (efir, 0x16);
593 hefras = inb(efdr) & WINB_HEFRAS;
594
539 /*
595 /*
540 * Try to reset EPP timeout bit.
541 * If it fails, try PS/2 and NIBBLE modes.
596 * HEFRAS HEFERE
597 * 0 1 write 89h to 250h (power-on default)
598 * 1 0 write 86h twice to 3f0h
599 * 1 1 write 87h twice to 3f0h
600 * 0 0 write 88h to 250h
542 */
601 */
543 ppc_reset_epp_timeout(ppc->ppc_unit);
602 if ((hefere | hefras) == w83877f_hefs[i])
603 goto found;
604 }
544
605
545 r = r_str(ppc);
546 if (!(r & TIMEOUT))
547 return (mode);
548 } else {
549 if (mode)
550 return (mode);
606 return (-1); /* failed */
607
608found:
609 /* check base port address - read from CR23 */
610 outb(efir, 0x23);
611 if (ppc->ppc_base != inb(efdr) * 4) /* 4 bytes boundaries */
612 return (-1);
613
614 /* read CHIP ID from CR9/bits0-3 */
615 outb(efir, 0x9);
616
617 switch (inb(efdr) & WINB_CHIPID) {
618 case WINB_W83877F_ID:
619 ppc->ppc_type = WINB_W83877F;
620 break;
621
622 case WINB_W83877AF_ID:
623 ppc->ppc_type = WINB_W83877AF;
624 break;
625
626 default:
627 ppc->ppc_type = WINB_UNKNOWN;
551 }
552
628 }
629
553 /* detect PS/2 or NIBBLE mode */
554 return (ppc_detect_ps2(ppc));
555}
630 if (bootverbose) {
631 /* dump of registers */
632 printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]);
633 for (i = 0; i <= 0xd; i ++) {
634 outb(efir, i);
635 printf("0x%x ", inb(efdr));
636 }
637 for (i = 0x10; i <= 0x17; i ++) {
638 outb(efir, i);
639 printf("0x%x ", inb(efdr));
640 }
641 outb(efir, 0x1e);
642 printf("0x%x ", inb(efdr));
643 for (i = 0x20; i <= 0x29; i ++) {
644 outb(efir, i);
645 printf("0x%x ", inb(efdr));
646 }
647 printf("\n");
648 }
556
649
557static int
558ppc_check_ecpepp_timeout(struct ppc_data *ppc)
559{
560 char r;
650 if (!chipset_mode) {
651 /* autodetect mode */
561
652
562 ppc_reset_epp_timeout(ppc->ppc_unit);
653 /* select CR0 */
654 outb(efir, 0x0);
655 r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
563
656
564 r = r_str(ppc);
565 if (!(r & TIMEOUT)) {
566 return (PPB_ECP_EPP);
657 /* select CR9 */
658 outb(efir, 0x9);
659 r |= (inb(efdr) & WINB_PRTMODS2);
660
661 switch (r) {
662 case WINB_W83757:
663 if (bootverbose)
664 printf("ppc%d: W83757 compatible mode\n",
665 ppc->ppc_unit);
666 return (-1); /* generic or SMC-like */
667
668 case WINB_EXTFDC:
669 case WINB_EXTADP:
670 case WINB_EXT2FDD:
671 case WINB_JOYSTICK:
672 if (bootverbose)
673 printf("ppc%d: not in parallel port mode\n",
674 ppc->ppc_unit);
675 return (-1);
676
677 case (WINB_PARALLEL | WINB_EPP_SPP):
678 ppc->ppc_avm |= PPB_EPP | PPB_SPP;
679 break;
680
681 case (WINB_PARALLEL | WINB_ECP):
682 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
683 break;
684
685 case (WINB_PARALLEL | WINB_ECP_EPP):
686 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
687 break;
688 default:
689 printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r);
690 }
691
692 } else {
693 /* mode forced */
694
695 /* select CR9 and set PRTMODS2 bit */
696 outb(efir, 0x9);
697 outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
698
699 /* select CR0 and reset PRTMODSx bits */
700 outb(efir, 0x0);
701 outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
702
703 if (chipset_mode & PPB_ECP) {
704 if (chipset_mode & PPB_EPP)
705 outb(efdr, inb(efdr) | WINB_ECP_EPP);
706 else
707 outb(efdr, inb(efdr) | WINB_ECP);
708 } else {
709 /* select EPP_SPP otherwise */
710 outb(efdr, inb(efdr) | WINB_EPP_SPP);
711 }
712 ppc->ppc_avm = chipset_mode;
567 }
713 }
714
715 /* exit configuration mode */
716 outb(efer, 0xaa);
568
717
569 /* If EPP timeout bit is not reset, DON'T use EPP */
570 w_ecr(ppc, 0x20);
718 if (ppc->ppc_avm & PPB_ECP)
719 ppc_ecp_config(ppc, chipset_mode);
571
720
572 return (PPB_ECP_PS2);
721 return (chipset_mode);
573}
574
575/*
576 * ppc_generic_detect
577 */
578static int
722}
723
724/*
725 * ppc_generic_detect
726 */
727static int
579ppc_generic_detect(struct ppc_data *ppc, int mode)
728ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
580{
729{
581 char save_control, r;
730 char save_control;
582
731
583 /* don't know what to do here */
584 if (mode)
585 return (mode);
732 if (!chipset_mode) {
733 /* first, check for ECP */
734 w_ecr(ppc, 0x20);
735 if ((r_ecr(ppc) & 0xe0) == 0x20) {
736 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
586
737
587 /* try to reset EPP timeout bit */
588 ppc_reset_epp_timeout(ppc->ppc_unit);
738 /* search for SMC style ECP+EPP mode */
739 w_ecr(ppc, 0x80);
740 }
589
741
590 r = r_str(ppc);
591 if (!(r & TIMEOUT)) {
592 return (PPB_EPP);
593 }
742 /* try to reset EPP timeout bit */
743 if (ppc_check_epp_timeout(ppc)) {
744 ppc->ppc_avm |= PPB_EPP;
594
745
595 /* Now check for ECP */
596 w_ecr(ppc, 0x20);
597 r = r_ecr(ppc);
598 if ((r & 0xe0) == 0x20) {
599 /* Search for SMC style EPP+ECP mode */
600 w_ecr(ppc, 0x80);
746 if (ppc->ppc_avm & PPB_ECP)
747 /* SMC like chipset found */
748 ppc->ppc_type = SMC_LIKE;
749 }
601
750
602 return (ppc_check_ecpepp_timeout(ppc));
603 }
751 /* XXX try to detect NIBBLE mode */
752 ppc->ppc_avm |= PPB_NIBBLE;
604
753
605 return (ppc_detect_ps2(ppc));
754 } else
755 ppc->ppc_avm = chipset_mode;
756
757 if (ppc->ppc_avm & PPB_ECP)
758 ppc_ecp_config(ppc, chipset_mode);
759
760 return (chipset_mode);
606}
607
608/*
609 * ppc_detect()
610 *
611 * mode is the mode suggested at boot
612 */
613static int
761}
762
763/*
764 * ppc_detect()
765 *
766 * mode is the mode suggested at boot
767 */
768static int
614ppc_detect(struct ppc_data *ppc, int mode) {
769ppc_detect(struct ppc_data *ppc, int chipset_mode) {
615
770
616 if (!ppc->ppc_mode && (ppc->ppc_mode = ppc_pc873xx_detect(ppc)))
617 goto end_detect;
771 int i, mode;
618
772
619 if (!ppc->ppc_mode && (ppc->ppc_mode =
620 ppc_smc37c66xgt_detect(ppc, mode)))
621 goto end_detect;
773 /* list of supported chipsets */
774 int (*chipset_detect[])(struct ppc_data *, int) = {
775 ppc_pc873xx_detect,
776 ppc_smc37c66xgt_detect,
777 ppc_w83877f_detect,
778 ppc_generic_detect,
779 NULL
780 };
622
781
623 if (!ppc->ppc_mode && (ppc->ppc_mode = ppc_generic_detect(ppc, mode)))
624 goto end_detect;
782 /* if can't find the port and mode not forced return error */
783 if (!ppc_detect_port(ppc) && chipset_mode == 0)
784 return (EIO); /* failed, port not present */
625
785
626 printf("ppc: port not present at 0x%x.\n", ppc->ppc_base);
627 return (PPC_ENOPORT);
786 /* assume centronics compatible mode is supported */
787 ppc->ppc_avm = PPB_COMPATIBLE;
628
788
629end_detect:
789 /* we have to differenciate available chipset modes,
790 * chipset running modes and IEEE-1284 operating modes
791 *
792 * after detection, the port must support running in compatible mode
793 */
794 for (i=0; chipset_detect[i] != NULL; i++) {
795 if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
796 ppc->ppc_mode = mode;
797 break;
798 }
799 }
630
631 return (0);
632}
633
634/*
800
801 return (0);
802}
803
804/*
805 * ppc_exec_microseq()
806 *
807 * Execute a microsequence.
808 * Microsequence mechanism is supposed to handle fast I/O operations.
809 */
810static int
811ppc_exec_microseq(int unit, struct ppb_microseq *msq, int *ppbpc)
812{
813 struct ppc_data *ppc = ppcdata[unit];
814 struct ppb_microseq *pc;
815 char cc, *p;
816 int i, iter, reg;
817 int error;
818
819 /* static to be reused after few ppc_exec_microseq()/return calls
820 * XXX should be in a context variable shared with ppb level */
821 static int accum;
822 static char *ptr;
823
824 struct ppb_microseq *microseq_stack = 0;
825 struct ppb_microseq *pc_stack = 0;
826
827/* microsequence registers are equivalent to PC-like port registers */
828#define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register))
829#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
830
831#define INCR_PC (pc ++) /* increment program counter */
832#define mi pc /* microinstruction currently executed */
833
834 /* get the state of pc from ppb level of execution */
835 pc = &msq[*ppbpc];
836
837 for (;;) {
838
839 switch (mi->opcode) {
840 case MS_OP_RSET:
841 cc = r_reg(mi->arg[0].i, ppc);
842 cc &= mi->arg[2].c; /* clear mask */
843 cc |= mi->arg[1].c; /* assert mask */
844 w_reg(mi->arg[0].i, ppc, cc);
845 INCR_PC;
846 break;
847
848 case MS_OP_RASSERT_P:
849 for (i=0; i<mi->arg[0].i; i++)
850 w_reg(mi->arg[1].i, ppc, *ptr++);
851 INCR_PC;
852 break;
853
854 case MS_OP_RFETCH_P:
855 for (i=0; i<mi->arg[0].i; i++)
856 *ptr++ = r_reg(mi->arg[1].i, ppc) &
857 mi->arg[2].c;
858 INCR_PC;
859 break;
860
861 case MS_OP_RFETCH:
862 *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
863 mi->arg[1].c;
864 INCR_PC;
865 break;
866
867 case MS_OP_RASSERT:
868
869 /* let's suppose the next instr. is the same */
870 prefetch:
871 for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
872 w_reg(mi->arg[0].i, ppc, mi->arg[1].c);
873
874 if (mi->opcode == MS_OP_DELAY) {
875 DELAY(mi->arg[0].i);
876 INCR_PC;
877 goto prefetch;
878 }
879 break;
880
881 case MS_OP_DELAY:
882 DELAY(mi->arg[0].i);
883 INCR_PC;
884 break;
885
886 case MS_OP_TRIG:
887 reg = mi->arg[0].i;
888 iter = mi->arg[1].i;
889 p = (char *)mi->arg[2].p;
890
891 for (i=0; i<iter; i++) {
892 w_reg(reg, ppc, *p++);
893 DELAY((unsigned char)*p++);
894 }
895 INCR_PC;
896 break;
897
898 case MS_OP_SET:
899 accum = mi->arg[0].i;
900 INCR_PC;
901 break;
902
903 case MS_OP_DBRA:
904 if (--accum > 0)
905 pc += mi->arg[0].i;
906 else
907 INCR_PC;
908 break;
909
910 case MS_OP_BRSET:
911 cc = r_str(ppc);
912 if ((cc & mi->arg[0].c) == mi->arg[0].c)
913 pc += mi->arg[1].i;
914 else
915 INCR_PC;
916 break;
917
918 case MS_OP_BRCLEAR:
919 cc = r_str(ppc);
920 if ((cc & mi->arg[0].c) == 0)
921 pc += mi->arg[1].i;
922 else
923 INCR_PC;
924 break;
925
926 case MS_OP_C_CALL:
927 /*
928 * If the C call returns !0 then end the microseq.
929 * The current state of ptr is passed to the C function
930 */
931 if ((error = mi->arg[0].f(mi->arg[1].p, ptr)))
932 return (error);
933
934 INCR_PC;
935 break;
936
937 case MS_OP_PTR:
938 ptr = (char *)mi->arg[0].p;
939 INCR_PC;
940 break;
941
942 case MS_OP_CALL:
943 if (microseq_stack)
944 panic("%s: too much calls", __FUNCTION__);
945
946 if (mi->arg[0].p) {
947 /* store the state of the actual
948 * microsequence
949 */
950 microseq_stack = msq;
951 pc_stack = pc;
952
953 /* jump to the new microsequence */
954 msq = (struct ppb_microseq *)mi->arg[0].p;
955 pc = msq;
956 } else
957 INCR_PC;
958
959 break;
960
961 case MS_OP_SUBRET:
962 /* retrieve microseq and pc state before the call */
963 msq = microseq_stack;
964 pc = pc_stack;
965
966 /* reset the stack */
967 microseq_stack = 0;
968
969 /* XXX return code */
970
971 INCR_PC;
972 break;
973
974 case MS_OP_PUT:
975 case MS_OP_GET:
976 case MS_OP_RET:
977 /* can't return to ppb level during the execution
978 * of a submicrosequence */
979 if (microseq_stack)
980 panic("%s: can't return to ppb level",
981 __FUNCTION__);
982
983 /* update pc for ppb level of execution */
984 *ppbpc = (int)(pc - msq);
985
986 /* return to ppb level of execution */
987 return (0);
988
989 default:
990 panic("%s: unknown microsequence opcode 0x%x",
991 __FUNCTION__, mi->opcode);
992 }
993 }
994
995 /* unreached */
996}
997
998/*
999 * Configure current operating mode
1000 */
1001static int
1002ppc_generic_setmode(int unit, int mode)
1003{
1004 struct ppc_data *ppc = ppcdata[unit];
1005
1006 /* back to compatible mode, XXX don't know yet what to do here */
1007 if (mode == 0) {
1008 ppc->ppc_mode = PPB_COMPATIBLE;
1009 return (0);
1010 }
1011
1012 /* check if mode is available */
1013 if (!(ppc->ppc_avm & mode))
1014 return (EOPNOTSUPP);
1015
1016 /* if ECP mode, configure ecr register */
1017 if (ppc->ppc_avm & PPB_ECP)
1018 ppc_ecp_config(ppc, mode);
1019
1020 ppc->ppc_mode = mode;
1021
1022 return (0);
1023}
1024
1025/*
635 * EPP timeout, according to the PC87332 manual
636 * Semantics of clearing EPP timeout bit.
637 * PC87332 - reading SPP_STR does it...
638 * SMC - write 1 to EPP timeout bit XXX
639 * Others - (???) write 0 to EPP timeout bit
640 */
641static void
642ppc_reset_epp_timeout(int unit)

--- 40 unchanged lines hidden (view full) ---

683 goto error;
684 }
685 bzero(ppc, sizeof(struct ppc_data));
686
687 ppc->ppc_base = dvp->id_iobase;
688 ppc->ppc_unit = dvp->id_unit;
689 ppc->ppc_type = GENERIC;
690
1026 * EPP timeout, according to the PC87332 manual
1027 * Semantics of clearing EPP timeout bit.
1028 * PC87332 - reading SPP_STR does it...
1029 * SMC - write 1 to EPP timeout bit XXX
1030 * Others - (???) write 0 to EPP timeout bit
1031 */
1032static void
1033ppc_reset_epp_timeout(int unit)

--- 40 unchanged lines hidden (view full) ---

1074 goto error;
1075 }
1076 bzero(ppc, sizeof(struct ppc_data));
1077
1078 ppc->ppc_base = dvp->id_iobase;
1079 ppc->ppc_unit = dvp->id_unit;
1080 ppc->ppc_type = GENERIC;
1081
691 /* PPB_AUTODETECT is default to allow chipset detection even if
692 * mode is forced by dvp->id_flags (see later, ppc_detect() call) */
693 ppc->ppc_mode = PPB_AUTODETECT;
694 ppc->ppc_epp = (dvp->id_flags & 0x8) >> 3;
1082 ppc->ppc_mode = PPB_COMPATIBLE;
1083 ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
695
696 /*
697 * XXX
698 * Try and detect if interrupts are working.
699 */
1084
1085 /*
1086 * XXX
1087 * Try and detect if interrupts are working.
1088 */
700 if (!(dvp->id_flags & 0x10))
1089 if (!(dvp->id_flags & 0x20))
701 ppc->ppc_irq = (dvp->id_irq);
702
703 ppcdata[ppc->ppc_unit] = ppc;
704 nppc ++;
705
706 /*
707 * Try to detect the chipset and its mode.
708 */
1090 ppc->ppc_irq = (dvp->id_irq);
1091
1092 ppcdata[ppc->ppc_unit] = ppc;
1093 nppc ++;
1094
1095 /*
1096 * Try to detect the chipset and its mode.
1097 */
709 if (ppc_detect(ppc, dvp->id_flags & 0x7))
1098 if (ppc_detect(ppc, dvp->id_flags & 0xf))
710 goto error;
711
712end_probe:
713
714 return (1);
715
716error:
717 return (0);
718}
719
720static int
721ppcattach(struct isa_device *isdp)
722{
723 struct ppc_data *ppc = ppcdata[isdp->id_unit];
724 struct ppb_data *ppbus;
1099 goto error;
1100
1101end_probe:
1102
1103 return (1);
1104
1105error:
1106 return (0);
1107}
1108
1109static int
1110ppcattach(struct isa_device *isdp)
1111{
1112 struct ppc_data *ppc = ppcdata[isdp->id_unit];
1113 struct ppb_data *ppbus;
1114 char * mode;
725
726 /*
727 * Link the Parallel Port Chipset (adapter) to
728 * the future ppbus.
729 */
730 ppc->ppc_link.adapter_unit = ppc->ppc_unit;
731 ppc->ppc_link.adapter = &ppc_adapter;
732
1115
1116 /*
1117 * Link the Parallel Port Chipset (adapter) to
1118 * the future ppbus.
1119 */
1120 ppc->ppc_link.adapter_unit = ppc->ppc_unit;
1121 ppc->ppc_link.adapter = &ppc_adapter;
1122
733 printf("ppc%d: %s chipset in %s mode%s\n", ppc->ppc_unit,
734 ppc_types[ppc->ppc_type], ppc_modes[ppc->ppc_mode],
735 (PPB_IS_EPP(ppc->ppc_mode)) ?
1123 printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
1124 ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
1125 ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
736 ppc_epp_protocol[ppc->ppc_epp] : "");
737
738 /*
739 * Prepare ppbus data area for upper level code.
740 */
741 ppbus = ppb_alloc_bus();
742
743 if (!ppbus)

--- 13 unchanged lines hidden ---
1126 ppc_epp_protocol[ppc->ppc_epp] : "");
1127
1128 /*
1129 * Prepare ppbus data area for upper level code.
1130 */
1131 ppbus = ppb_alloc_bus();
1132
1133 if (!ppbus)

--- 13 unchanged lines hidden ---