summaryrefslogtreecommitdiffstats
path: root/sys/dev/ppc
diff options
context:
space:
mode:
authornsouch <nsouch@FreeBSD.org>1998-10-31 11:37:09 +0000
committernsouch <nsouch@FreeBSD.org>1998-10-31 11:37:09 +0000
commit2ae8dc409583e4ed96ca74b7f4817f015685e45f (patch)
tree6c1dd20e560277a32eb4ff159dc40b87e98b90cc /sys/dev/ppc
parent3b006890f16badfe89b25127eb04b14cfc373659 (diff)
downloadFreeBSD-src-2ae8dc409583e4ed96ca74b7f4817f015685e45f.zip
FreeBSD-src-2ae8dc409583e4ed96ca74b7f4817f015685e45f.tar.gz
pcf.c: timeout management added
ppc.c: nsc code improved. Actually, a complete rewrite.
Diffstat (limited to 'sys/dev/ppc')
-rw-r--r--sys/dev/ppc/ppc.c291
-rw-r--r--sys/dev/ppc/ppcreg.h28
2 files changed, 219 insertions, 100 deletions
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index 39f4b4e..a22dfb0 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ppc.c,v 1.9 1998/09/20 14:47:01 nsouch Exp $
+ * $Id: ppc.c,v 1.10 1998/10/22 05:58:40 bde Exp $
*
*/
#include "ppc.h"
@@ -61,7 +61,7 @@ static int nppc = 0;
static char *ppc_types[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
- "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0
+ "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
};
/* list of available modes */
@@ -221,27 +221,44 @@ ppc_detect_port(struct ppc_data *ppc)
*/
static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
+static int pc873xx_irqtab[] = {5, 7, 5, 0};
+
+static int pc873xx_regstab[] = {
+ PC873_FER, PC873_FAR, PC873_PTR,
+ PC873_FCR, PC873_PCR, PC873_PMC,
+ PC873_TUP, PC873_SID, PC873_PNP0,
+ PC873_PNP1, PC873_LPTBA, -1
+};
+
+static char *pc873xx_rnametab[] = {
+ "FER", "FAR", "PTR", "FCR", "PCR",
+ "PMC", "TUP", "SID", "PNP0", "PNP1",
+ "LPTBA", NULL
+};
static int
ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */
{
static int index = 0;
- int base, idport;
- int val;
+ int base, idport, irq;
+ int ptr, pcr, val, i;
while ((idport = pc873xx_basetab[index++])) {
/* XXX should check first to see if this location is already claimed */
/*
- * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this
- * to locate the chip as it may already have been used by the BIOS.
+ * Pull the 873xx through the power-on ID cycle (2.2,1.).
+ * We can't use this to locate the chip as it may already have
+ * been used by the BIOS.
*/
- (void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport);
+ (void)inb(idport); (void)inb(idport);
+ (void)inb(idport); (void)inb(idport);
/*
* Read the SID byte. Possible values are :
*
+ * 01010xxx PC87334
* 0001xxxx PC87332
* 01110xxx PC87306
*/
@@ -251,14 +268,27 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
ppc->ppc_type = NS_PC87332;
} else if ((val & 0xf8) == 0x70) {
ppc->ppc_type = NS_PC87306;
+ } else if ((val & 0xf8) == 0x50) {
+ ppc->ppc_type = NS_PC87334;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
continue ; /* not recognised */
}
+
+ /* print registers */
+ if (bootverbose) {
+ printf("PC873xx");
+ for (i=0; pc873xx_regstab[i] != -1; i++) {
+ outb(idport, pc873xx_regstab[i]);
+ printf(" %s=0x%x", pc873xx_rnametab[i],
+ inb(idport + 1) & 0xff);
+ }
+ printf("\n");
+ }
/*
- * We think we have one. Is it enabled and where we want it to be?
+ * We think we have one. Is it enabled and where we want it to be?
*/
outb(idport, PC873_FER);
val = inb(idport + 1);
@@ -276,96 +306,168 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
pc873xx_porttab[val], ppc->ppc_base);
continue;
}
+
+ outb(idport, PC873_PTR);
+ ptr = inb(idport + 1);
+
+ /* get irq settings */
+ if (ppc->ppc_base == 0x378)
+ irq = (ptr & PC873_LPTBIRQ7) ? 7 : 5;
+ else
+ irq = pc873xx_irqtab[val];
+
+ if (bootverbose)
+ printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base);
- /*
- * This is the port we want. Can we dink with it to improve
- * our chances?
+ /*
+ * Check if irq settings are correct
*/
- outb(idport, PC873_PTR);
- val = inb(idport + 1);
- if (val & PC873_CFGLOCK) {
- if (bootverbose)
- printf("PC873xx locked\n");
-
- /* work out what mode we're in */
- ppc->ppc_avm |= PPB_NIBBLE; /* worst case */
-
- outb(idport, PC873_PCR);
- val = inb(idport + 1);
- if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
- outb(idport, PC873_PTR);
- val = inb(idport + 1);
- if (!(val & PC873_EPPRDIR)) {
- ppc->ppc_avm |= PPB_EPP; /* As we would have done it anwyay */
+ if (irq != ppc->ppc_irq) {
+ /*
+ * If the chipset is not locked and base address is 0x378,
+ * we have another chance
+ */
+ if (ppc->ppc_base == 0x378 && !(ptr & PC873_CFGLOCK)) {
+ if (ppc->ppc_irq == 7) {
+ outb(idport + 1, (ptr | PC873_LPTBIRQ7));
+ outb(idport + 1, (ptr | PC873_LPTBIRQ7));
+ } else {
+ outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
+ outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
+ }
+ if (bootverbose)
+ printf("PC873xx irq set to %d\n", ppc->ppc_irq);
+ } else {
+ if (bootverbose)
+ printf("PC873xx sorry, can't change irq setting\n");
}
- } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
- ppc->ppc_avm |= PPB_PS2; /* tolerable alternative */
- }
} else {
- if (bootverbose)
- printf("PC873xx unlocked, ");
-
-#if 0 /* broken */
- /*
- * Frob the zero-wait-state option if possible; it causes
- * unreliable operation.
- */
- outb(idport, PC873_FCR);
- val = inb(idport + 1);
- if ((ppc->ppc_type == NS_PC87306) || /* we are a '306 */
- !(val & PC873_ZWSPWDN)) { /* or pin _is_ ZWS */
- val &= ~PC873_ZWS;
- outb(idport + 1, val); /* must disable ZWS */
- outb(idport + 1, val);
-
if (bootverbose)
- printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled");
- }
+ printf("PC873xx irq settings are correct\n");
+ }
-#endif
+ outb(idport, PC873_PCR);
+ pcr = inb(idport + 1);
+
+ if ((ptr & PC873_CFGLOCK) || !chipset_mode) {
+ if (bootverbose)
+ printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked");
+
+ ppc->ppc_avm |= PPB_NIBBLE;
if (bootverbose)
- printf("reconfiguring for ");
-
- /*
- * if the chip is at 0x3bc, we can't use EPP as there's no room
- * for the extra registers.
- *
- * XXX should we use ECP mode always and use the EPP submode?
- */
- if (ppc->ppc_base != 0x3bc) {
+ printf(", NIBBLE");
+
+ if (pcr & PC873_EPPEN) {
+ ppc->ppc_avm |= PPB_EPP;
+
if (bootverbose)
- printf("EPP 1.9\n");
-
- /* configure for EPP 1.9 operation XXX should be configurable */
- outb(idport, PC873_PCR);
- val = inb(idport + 1);
- val &= ~(PC873_ECPEN | PC873_ECPCLK); /* disable ECP */
- val |= (PC873_EPPEN | PC873_EPP19); /* enable EPP */
- outb(idport + 1, val);
- outb(idport + 1, val);
-
- /* enable automatic direction turnover */
- outb(idport, PC873_PTR);
- val = inb(idport + 1);
- val &= ~PC873_EPPRDIR; /* disable "regular" direction change */
- outb(idport + 1, val);
- outb(idport + 1, val);
+ printf(", EPP");
- /* we are an EPP-32 port */
- ppc->ppc_avm |= PPB_EPP;
- } else {
+ if (pcr & PC873_EPP19)
+ ppc->ppc_epp = EPP_1_9;
+ else
+ ppc->ppc_epp = EPP_1_7;
+
+ if ((ppc->ppc_type == NS_PC87332) && bootverbose) {
+ outb(idport, PC873_PTR);
+ ptr = inb(idport + 1);
+ if (ptr & PC873_EPPRDIR)
+ printf(", Regular mode");
+ else
+ printf(", Automatic mode");
+ }
+ } else if (pcr & PC873_ECPEN) {
+ ppc->ppc_avm |= PPB_ECP;
if (bootverbose)
- printf("ECP\n");
-
- /* configure as an ECP port to get bidirectional operation for now */
- outb(idport, PC873_PCR);
- outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
+ printf(", ECP");
- /* we look like a PS/2 port */
- ppc->ppc_avm |= PPB_PS2;
+ if (pcr & PC873_ECPCLK) { /* XXX */
+ ppc->ppc_avm |= PPB_PS2;
+ if (bootverbose)
+ printf(", PS/2");
+ }
+ } else {
+ outb(idport, PC873_PTR);
+ ptr = inb(idport + 1);
+ if (ptr & PC873_EXTENDED) {
+ ppc->ppc_avm |= PPB_SPP;
+ if (bootverbose)
+ printf(", SPP");
+ }
}
+ } else {
+ if (bootverbose)
+ printf("PC873xx unlocked");
+
+ if (chipset_mode & PPB_ECP) {
+ if ((chipset_mode & PPB_EPP) && bootverbose)
+ printf(", ECP+EPP not supported");
+
+ pcr &= ~PC873_EPPEN;
+ pcr |= (PC873_ECPEN | PC873_ECPCLK); /* XXX */
+ outb(idport + 1, pcr);
+ outb(idport + 1, pcr);
+
+ if (bootverbose)
+ printf(", ECP");
+
+ } else if (chipset_mode & PPB_EPP) {
+ pcr &= ~(PC873_ECPEN | PC873_ECPCLK);
+ pcr |= (PC873_EPPEN | PC873_EPP19);
+ outb(idport + 1, pcr);
+ outb(idport + 1, pcr);
+
+ ppc->ppc_epp = EPP_1_9; /* XXX */
+
+ if (bootverbose)
+ printf(", EPP1.9");
+
+ /* enable automatic direction turnover */
+ if (ppc->ppc_type == NS_PC87332) {
+ outb(idport, PC873_PTR);
+ ptr = inb(idport + 1);
+ ptr &= ~PC873_EPPRDIR;
+ outb(idport + 1, ptr);
+ outb(idport + 1, ptr);
+
+ if (bootverbose)
+ printf(", Automatic mode");
+ }
+ } else {
+ pcr &= ~(PC873_ECPEN | PC873_ECPCLK | PC873_EPPEN);
+ outb(idport + 1, pcr);
+ outb(idport + 1, pcr);
+
+ /* configure extended bit in PTR */
+ outb(idport, PC873_PTR);
+ ptr = inb(idport + 1);
+
+ if (chipset_mode & PPB_PS2) {
+ ptr |= PC873_EXTENDED;
+
+ if (bootverbose)
+ printf(", PS/2");
+
+ } else {
+ /* default to NIBBLE mode */
+ ptr &= ~PC873_EXTENDED;
+
+ if (bootverbose)
+ printf(", NIBBLE");
+ }
+ outb(idport + 1, ptr);
+ outb(idport + 1, ptr);
+ }
+
+ ppc->ppc_avm = chipset_mode;
}
+ if (bootverbose)
+ printf("\n");
+
+ ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc_generic_setmode(ppc->ppc_unit, chipset_mode);
+
return(chipset_mode);
}
return(-1);
@@ -863,10 +965,18 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
*
* after detection, the port must support running in compatible mode
*/
- for (i=0; chipset_detect[i] != NULL; i++) {
- if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
- ppc->ppc_mode = mode;
- break;
+ if (ppc->ppc_flags & 0x40) {
+ if (bootverbose)
+ printf("ppc: chipset forced to generic\n");
+
+ ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
+
+ } else {
+ for (i=0; chipset_detect[i] != NULL; i++) {
+ if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
+ ppc->ppc_mode = mode;
+ break;
+ }
}
}
@@ -1232,6 +1342,9 @@ ppcprobe(struct isa_device *dvp)
ppc->ppc_unit = dvp->id_unit;
ppc->ppc_type = GENERIC;
+ /* store boot flags */
+ ppc->ppc_flags = dvp->id_flags;
+
ppc->ppc_mode = PPB_COMPATIBLE;
ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
@@ -1239,7 +1352,7 @@ ppcprobe(struct isa_device *dvp)
* XXX Try and detect if interrupts are working
*/
if (!(dvp->id_flags & 0x20))
- ppc->ppc_irq = (dvp->id_irq);
+ ppc->ppc_irq = ffs(dvp->id_irq) - 1;
ppcdata[ppc->ppc_unit] = ppc;
nppc ++;
diff --git a/sys/dev/ppc/ppcreg.h b/sys/dev/ppc/ppcreg.h
index fe7e724..af8c9db 100644
--- a/sys/dev/ppc/ppcreg.h
+++ b/sys/dev/ppc/ppcreg.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ppcreg.h,v 1.3 1998/08/03 19:14:33 msmith Exp $
+ * $Id: ppcreg.h,v 1.4 1998/09/13 18:26:44 nsouch Exp $
*
*/
#ifndef __PPCREG_H
@@ -32,16 +32,17 @@
/*
* Parallel Port Chipset type.
*/
-#define SMC_LIKE 0x0
-#define SMC_37C665GT 0x1
-#define SMC_37C666GT 0x2
-#define NS_PC87332 0x3
-#define NS_PC87306 0x4
-#define INTEL_820191AA 0x5 /* XXX not implemented */
-#define GENERIC 0x6
-#define WINB_W83877F 0x7
-#define WINB_W83877AF 0x8
-#define WINB_UNKNOWN 0x9
+#define SMC_LIKE 0
+#define SMC_37C665GT 1
+#define SMC_37C666GT 2
+#define NS_PC87332 3
+#define NS_PC87306 4
+#define INTEL_820191AA 5 /* XXX not implemented */
+#define GENERIC 6
+#define WINB_W83877F 7
+#define WINB_W83877AF 8
+#define WINB_UNKNOWN 9
+#define NS_PC87334 10
/*
* Generic structure to hold parallel port chipset info.
@@ -100,6 +101,8 @@ struct ppc_data {
#define PC873_PTR 0x02
#define PC873_CFGLOCK (1<<6)
#define PC873_EPPRDIR (1<<7)
+#define PC873_EXTENDED (1<<7)
+#define PC873_LPTBIRQ7 (1<<3)
#define PC873_FCR 0x03
#define PC873_ZWS (1<<5)
#define PC873_ZWSPWDN (1<<6)
@@ -111,6 +114,9 @@ struct ppc_data {
#define PC873_PMC 0x06
#define PC873_TUP 0x07
#define PC873_SID 0x08
+#define PC873_PNP0 0x1b
+#define PC873_PNP1 0x1c
+#define PC873_LPTBA 0x19
/*
* Register defines for the SMC FDC37C66xGT parts
OpenPOWER on IntegriCloud