Merged from the following changes.

sys/isa/ppc.c      revisions from 1.27 to 1.34
  sys/isa/ppcreg.h   revisions from 1.10 to 1.15
  sys/isa/isareg.h   revision 1.6
This commit is contained in:
Yoshihiro Takahashi 2001-06-26 11:53:12 +00:00
parent 50c2952249
commit 15bf31ded3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78815
6 changed files with 540 additions and 166 deletions

View File

@ -120,6 +120,8 @@
#define IO_ICUSIZE 16 /* 8259A interrupt controllers */
#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */
#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */
#define IO_LPTSIZE_EXTENDED 8 /* "Extended" LPT controllers */
#define IO_LPTSIZE_NORMAL 4 /* "Normal" LPT controllers */
#define IO_MDASIZE 16 /* Monochrome display controllers */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
#define IO_PMPSIZE 2 /* 82347 power management peripheral */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1997-2000 Nicolas Souchu
* Copyright (c) 2001 Alcove - Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -118,7 +118,8 @@ static driver_t ppc_driver = {
static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334",
"SMC FDC37C935", "PC87303", 0
};
/* list of available modes */
@ -159,7 +160,7 @@ ppc_ecp_sync(device_t dev) {
int i, r;
struct ppc_data *ppc = DEVTOSOFTC(dev);
if (!(ppc->ppc_avm & PPB_ECP))
if (!(ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_dtm & PPB_ECP))
return;
r = r_ecr(ppc);
@ -342,7 +343,7 @@ ppc_generic_setmode(struct ppc_data *ppc, int mode)
return (EINVAL);
/* if ECP mode, configure ecr register */
if (ppc->ppc_avm & PPB_ECP) {
if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
/* return to byte mode (keeping direction bit),
* no interrupt, no DMA to be able to change to
* ECP
@ -387,7 +388,7 @@ ppc_smclike_setmode(struct ppc_data *ppc, int mode)
return (EINVAL);
/* if ECP mode, configure ecr register */
if (ppc->ppc_avm & PPB_ECP) {
if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
/* return to byte mode (keeping direction bit),
* no interrupt, no DMA to be able to change to
* ECP or EPP mode
@ -467,6 +468,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
* 01010xxx PC87334
* 0001xxxx PC87332
* 01110xxx PC87306
* 00110xxx PC87303
*/
outb(idport, PC873_SID);
val = inb(idport + 1);
@ -476,6 +478,10 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
ppc->ppc_model = NS_PC87306;
} else if ((val & 0xf8) == 0x50) {
ppc->ppc_model = NS_PC87334;
} else if ((val & 0xf8) == 0x40) { /* Should be 0x30 by the
documentation, but probing
yielded 0x40... */
ppc->ppc_model = NS_PC87303;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
@ -504,12 +510,47 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
continue;
}
outb(idport, PC873_FAR);
val = inb(idport + 1) & 0x3;
val = inb(idport + 1);
/* XXX we should create a driver instance for every port found */
if (pc873xx_porttab[val] != ppc->ppc_base) {
if (bootverbose)
printf("PC873xx at 0x%x not for driver at port 0x%x\n",
pc873xx_porttab[val], ppc->ppc_base);
if (pc873xx_porttab[val & 0x3] != ppc->ppc_base) {
/* First try to change the port address to that requested... */
switch(ppc->ppc_base) {
case 0x378:
val &= 0xfc;
break;
case 0x3bc:
val &= 0xfd;
break;
case 0x278:
val &= 0xfe;
break;
default:
val &= 0xfd;
break;
}
outb(idport, PC873_FAR);
outb(idport + 1, val);
outb(idport + 1, val);
/* Check for success by reading back the value we supposedly
wrote and comparing...*/
outb(idport, PC873_FAR);
val = inb(idport + 1) & 0x3;
/* If we fail, report the failure... */
if (pc873xx_porttab[val] != ppc->ppc_base) {
if (bootverbose)
printf("PC873xx at 0x%x not for driver at port 0x%x\n",
pc873xx_porttab[val], ppc->ppc_base);
}
continue;
}
@ -888,6 +929,91 @@ end_detect:
return (chipset_mode);
}
/*
* SMC FDC37C935 configuration
* Found on many Alpha machines
*/
static int
ppc_smc37c935_detect(struct ppc_data *ppc, int chipset_mode)
{
int s;
int type = -1;
s = splhigh();
outb(SMC935_CFG, 0x55); /* enter config mode */
outb(SMC935_CFG, 0x55);
splx(s);
outb(SMC935_IND, SMC935_ID); /* check device id */
if (inb(SMC935_DAT) == 0x2)
type = SMC_37C935;
if (type == -1) {
outb(SMC935_CFG, 0xaa); /* exit config mode */
return (-1);
}
ppc->ppc_model = type;
outb(SMC935_IND, SMC935_LOGDEV); /* select parallel port, */
outb(SMC935_DAT, 3); /* which is logical device 3 */
/* set io port base */
outb(SMC935_IND, SMC935_PORTHI);
outb(SMC935_DAT, (u_char)((ppc->ppc_base & 0xff00) >> 8));
outb(SMC935_IND, SMC935_PORTLO);
outb(SMC935_DAT, (u_char)(ppc->ppc_base & 0xff));
if (!chipset_mode)
ppc->ppc_avm = PPB_COMPATIBLE; /* default mode */
else {
ppc->ppc_avm = chipset_mode;
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_CENT); /* start in compatible mode */
/* SPP + EPP or just plain SPP */
if (chipset_mode & (PPB_SPP)) {
if (chipset_mode & PPB_EPP) {
if (ppc->ppc_epp == EPP_1_9) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_EPP19SPP);
}
if (ppc->ppc_epp == EPP_1_7) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_EPP17SPP);
}
} else {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_SPP);
}
}
/* ECP + EPP or just plain ECP */
if (chipset_mode & PPB_ECP) {
if (chipset_mode & PPB_EPP) {
if (ppc->ppc_epp == EPP_1_9) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECPEPP19);
}
if (ppc->ppc_epp == EPP_1_7) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECPEPP17);
}
} else {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECP);
}
}
}
outb(SMC935_CFG, 0xaa); /* exit config mode */
ppc->ppc_type = PPC_TYPE_SMCLIKE;
ppc_smclike_setmode(ppc, chipset_mode);
return (chipset_mode);
}
/*
* Winbond W83877F stuff
*
@ -1095,48 +1221,48 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (bootverbose)
printf("ppc%d:", ppc->ppc_unit);
if (!chipset_mode) {
/* first, check for ECP */
w_ecr(ppc, PPC_ECR_PS2);
if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) {
ppc->ppc_avm |= PPB_ECP | PPB_SPP;
if (bootverbose)
printf(" ECP SPP");
/* search for SMC style ECP+EPP mode */
w_ecr(ppc, PPC_ECR_EPP);
}
/* try to reset EPP timeout bit */
if (ppc_check_epp_timeout(ppc)) {
ppc->ppc_avm |= PPB_EPP;
if (ppc->ppc_avm & PPB_ECP) {
/* SMC like chipset found */
ppc->ppc_model = SMC_LIKE;
ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
} else {
if (bootverbose)
printf(" EPP");
}
} else {
/* restore to standard mode */
w_ecr(ppc, PPC_ECR_STD);
}
/* XXX try to detect NIBBLE and PS2 modes */
ppc->ppc_avm |= PPB_NIBBLE;
/* first, check for ECP */
w_ecr(ppc, PPC_ECR_PS2);
if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) {
ppc->ppc_dtm |= PPB_ECP | PPB_SPP;
if (bootverbose)
printf(" SPP");
printf(" ECP SPP");
} else {
ppc->ppc_avm = chipset_mode;
/* search for SMC style ECP+EPP mode */
w_ecr(ppc, PPC_ECR_EPP);
}
/* try to reset EPP timeout bit */
if (ppc_check_epp_timeout(ppc)) {
ppc->ppc_dtm |= PPB_EPP;
if (ppc->ppc_dtm & PPB_ECP) {
/* SMC like chipset found */
ppc->ppc_model = SMC_LIKE;
ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
} else {
if (bootverbose)
printf(" EPP");
}
} else {
/* restore to standard mode */
w_ecr(ppc, PPC_ECR_STD);
}
/* XXX try to detect NIBBLE and PS2 modes */
ppc->ppc_dtm |= PPB_NIBBLE;
if (bootverbose)
printf(" SPP");
if (chipset_mode)
ppc->ppc_avm = chipset_mode;
else
ppc->ppc_avm = ppc->ppc_dtm;
if (bootverbose)
printf("\n");
@ -1168,6 +1294,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
ppc_pc873xx_detect,
ppc_smc37c66xgt_detect,
ppc_w83877f_detect,
ppc_smc37c935_detect,
ppc_generic_detect,
NULL
};
@ -1234,8 +1361,9 @@ ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
struct ppb_microseq *stack = 0;
/* microsequence registers are equivalent to PC-like port registers */
#define r_reg(register,ppc) (inb((ppc)->ppc_base + register))
#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
#define r_reg(register,ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, register))
#define w_reg(register, ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, register, byte))
#define INCR_PC (mi ++) /* increment program counter */
@ -1536,7 +1664,7 @@ ppc_write(device_t dev, char *buf, int len, int how)
*/
if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
if (ppc->ppc_dmachan >= 0) {
if (ppc->ppc_dmachan > 0) {
/* byte mode, no intr, no DMA, dir=0, flush fifo
*/
@ -1764,11 +1892,13 @@ ppc_probe(device_t dev)
port = PC98_IEEE_1284_PORT;
next_bios_ppc += 1;
if (bootverbose)
device_printf(dev, "parallel port found at 0x%x\n",
(int) port);
device_printf(dev,
"parallel port found at 0x%x\n",
(int) port);
}
#endif
bus_set_resource(dev, SYS_RES_IOPORT, 0, port, IO_LPTSIZE);
bus_set_resource(dev, SYS_RES_IOPORT, 0, port,
IO_LPTSIZE_EXTENDED);
}
#endif
#ifdef __alpha__
@ -1776,19 +1906,40 @@ ppc_probe(device_t dev)
* There isn't a bios list on alpha. Put it in the usual place.
*/
if (error) {
bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc, IO_LPTSIZE);
bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc,
IO_LPTSIZE_NORMAL);
}
#endif
/* IO port is mandatory */
/* Try "extended" IO port range...*/
ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
&ppc->rid_ioport, 0, ~0,
IO_LPTSIZE, RF_ACTIVE);
if (ppc->res_ioport == 0) {
device_printf(dev, "cannot reserve I/O port range\n");
goto error;
IO_LPTSIZE_EXTENDED, RF_ACTIVE);
if (ppc->res_ioport != 0) {
if (bootverbose)
device_printf(dev, "using extended I/O port range\n");
} else {
/* Failed? If so, then try the "normal" IO port range... */
ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
&ppc->rid_ioport, 0, ~0,
IO_LPTSIZE_NORMAL,
RF_ACTIVE);
if (ppc->res_ioport != 0) {
if (bootverbose)
device_printf(dev, "using normal I/O port range\n");
} else {
device_printf(dev, "cannot reserve I/O port range\n");
goto error;
}
}
ppc->ppc_base = rman_get_start(ppc->res_ioport);
ppc->ppc_base = rman_get_start(ppc->res_ioport);
ppc->bsh = rman_get_bushandle(ppc->res_ioport);
ppc->bst = rman_get_bustag(ppc->res_ioport);
ppc->ppc_flags = device_get_flags(dev);
@ -1921,22 +2072,22 @@ ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
switch (iop) {
case PPB_OUTSB_EPP:
outsb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
break;
case PPB_OUTSW_EPP:
outsw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
break;
case PPB_OUTSL_EPP:
outsl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
break;
case PPB_INSB_EPP:
insb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
break;
case PPB_INSW_EPP:
insw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
break;
case PPB_INSL_EPP:
insl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
break;
case PPB_RDTR:
return (r_dtr(ppc));

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1997 Nicolas Souchu
* Copyright (c) 2001 Alcove - Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,8 @@
#define WINB_W83877AF 8
#define WINB_UNKNOWN 9
#define NS_PC87334 10
#define SMC_37C935 11
#define NS_PC87303 12
/*
* Parallel Port Chipset Type. SMC versus GENERIC (others)
@ -61,6 +63,7 @@ struct ppc_data {
int ppc_mode; /* chipset current mode */
int ppc_avm; /* chipset available modes */
int ppc_dtm; /* chipset detected modes */
#define PPC_IRQ_NONE 0x0
#define PPC_IRQ_nACK 0x1
@ -103,6 +106,9 @@ struct ppc_data {
int rid_irq, rid_drq, rid_ioport;
struct resource *res_irq, *res_drq, *res_ioport;
bus_space_handle_t bsh;
bus_space_tag_t bst;
void *intr_cookie;
int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
@ -144,23 +150,25 @@ struct ppc_data {
#define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR)
#define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR)
#define r_dtr(ppc) (inb((ppc)->ppc_base + PPC_SPP_DTR))
#define r_str(ppc) (inb((ppc)->ppc_base + PPC_SPP_STR))
#define r_ctr(ppc) (inb((ppc)->ppc_base + PPC_SPP_CTR))
#define r_epp_A(ppc) (inb((ppc)->ppc_base + PPC_EPP_ADDR))
#define r_epp_D(ppc) (inb((ppc)->ppc_base + PPC_EPP_DATA))
#define r_cnfgA(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGA))
#define r_cnfgB(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGB))
#define r_ecr(ppc) (inb((ppc)->ppc_base + PPC_ECP_ECR))
#define r_fifo(ppc) (inb((ppc)->ppc_base + PPC_ECP_D_FIFO))
#define r_dtr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR))
#define r_str(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR))
#define r_ctr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR))
#define w_dtr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_DTR, byte)
#define w_str(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_STR, byte)
#define w_ctr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_CTR, byte)
#define w_epp_A(ppc,byte) outb((ppc)->ppc_base + PPC_EPP_ADDR, byte)
#define w_epp_D(ppc,byte) outb((ppc)->ppc_base + PPC_EPP_DATA, byte)
#define w_ecr(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_ECR, byte)
#define w_fifo(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_D_FIFO, byte)
#define r_epp_A(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR))
#define r_epp_D(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA))
#define r_cnfgA(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGA))
#define r_cnfgB(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGB))
#define r_ecr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR))
#define r_fifo(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO))
#define w_dtr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR, byte))
#define w_str(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR, byte))
#define w_ctr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR, byte))
#define w_epp_A(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR, byte))
#define w_epp_D(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA, byte))
#define w_ecr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR, byte))
#define w_fifo(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO, byte))
/*
* Register defines for the PC873xx parts
@ -213,6 +221,32 @@ struct ppc_data {
#define SMC_ECP 0x2 /* ECP */
#define SMC_ECPEPP 0x3 /* ECP and EPP */
/*
* Register defines for the SMC FDC37C935 parts
*/
/* Configuration ports */
#define SMC935_CFG 0x370
#define SMC935_IND 0x370
#define SMC935_DAT 0x371
/* Registers */
#define SMC935_LOGDEV 0x7
#define SMC935_ID 0x20
#define SMC935_PORTHI 0x60
#define SMC935_PORTLO 0x61
#define SMC935_PPMODE 0xf0
/* Parallel port modes */
#define SMC935_SPP 0x38 + 0
#define SMC935_EPP19SPP 0x38 + 1
#define SMC935_ECP 0x38 + 2
#define SMC935_ECPEPP19 0x38 + 3
#define SMC935_CENT 0x38 + 4
#define SMC935_EPP17SPP 0x38 + 5
#define SMC935_UNUSED 0x38 + 6
#define SMC935_ECPEPP17 0x38 + 7
/*
* Register defines for the Winbond W83877F parts
*/

View File

@ -120,6 +120,8 @@
#define IO_ICUSIZE 16 /* 8259A interrupt controllers */
#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */
#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */
#define IO_LPTSIZE_EXTENDED 8 /* "Extended" LPT controllers */
#define IO_LPTSIZE_NORMAL 4 /* "Normal" LPT controllers */
#define IO_MDASIZE 16 /* Monochrome display controllers */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
#define IO_PMPSIZE 2 /* 82347 power management peripheral */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1997-2000 Nicolas Souchu
* Copyright (c) 2001 Alcove - Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -118,7 +118,8 @@ static driver_t ppc_driver = {
static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334",
"SMC FDC37C935", "PC87303", 0
};
/* list of available modes */
@ -159,7 +160,7 @@ ppc_ecp_sync(device_t dev) {
int i, r;
struct ppc_data *ppc = DEVTOSOFTC(dev);
if (!(ppc->ppc_avm & PPB_ECP))
if (!(ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_dtm & PPB_ECP))
return;
r = r_ecr(ppc);
@ -342,7 +343,7 @@ ppc_generic_setmode(struct ppc_data *ppc, int mode)
return (EINVAL);
/* if ECP mode, configure ecr register */
if (ppc->ppc_avm & PPB_ECP) {
if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
/* return to byte mode (keeping direction bit),
* no interrupt, no DMA to be able to change to
* ECP
@ -387,7 +388,7 @@ ppc_smclike_setmode(struct ppc_data *ppc, int mode)
return (EINVAL);
/* if ECP mode, configure ecr register */
if (ppc->ppc_avm & PPB_ECP) {
if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
/* return to byte mode (keeping direction bit),
* no interrupt, no DMA to be able to change to
* ECP or EPP mode
@ -467,6 +468,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
* 01010xxx PC87334
* 0001xxxx PC87332
* 01110xxx PC87306
* 00110xxx PC87303
*/
outb(idport, PC873_SID);
val = inb(idport + 1);
@ -476,6 +478,10 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
ppc->ppc_model = NS_PC87306;
} else if ((val & 0xf8) == 0x50) {
ppc->ppc_model = NS_PC87334;
} else if ((val & 0xf8) == 0x40) { /* Should be 0x30 by the
documentation, but probing
yielded 0x40... */
ppc->ppc_model = NS_PC87303;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
@ -504,12 +510,47 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
continue;
}
outb(idport, PC873_FAR);
val = inb(idport + 1) & 0x3;
val = inb(idport + 1);
/* XXX we should create a driver instance for every port found */
if (pc873xx_porttab[val] != ppc->ppc_base) {
if (bootverbose)
printf("PC873xx at 0x%x not for driver at port 0x%x\n",
pc873xx_porttab[val], ppc->ppc_base);
if (pc873xx_porttab[val & 0x3] != ppc->ppc_base) {
/* First try to change the port address to that requested... */
switch(ppc->ppc_base) {
case 0x378:
val &= 0xfc;
break;
case 0x3bc:
val &= 0xfd;
break;
case 0x278:
val &= 0xfe;
break;
default:
val &= 0xfd;
break;
}
outb(idport, PC873_FAR);
outb(idport + 1, val);
outb(idport + 1, val);
/* Check for success by reading back the value we supposedly
wrote and comparing...*/
outb(idport, PC873_FAR);
val = inb(idport + 1) & 0x3;
/* If we fail, report the failure... */
if (pc873xx_porttab[val] != ppc->ppc_base) {
if (bootverbose)
printf("PC873xx at 0x%x not for driver at port 0x%x\n",
pc873xx_porttab[val], ppc->ppc_base);
}
continue;
}
@ -888,6 +929,91 @@ end_detect:
return (chipset_mode);
}
/*
* SMC FDC37C935 configuration
* Found on many Alpha machines
*/
static int
ppc_smc37c935_detect(struct ppc_data *ppc, int chipset_mode)
{
int s;
int type = -1;
s = splhigh();
outb(SMC935_CFG, 0x55); /* enter config mode */
outb(SMC935_CFG, 0x55);
splx(s);
outb(SMC935_IND, SMC935_ID); /* check device id */
if (inb(SMC935_DAT) == 0x2)
type = SMC_37C935;
if (type == -1) {
outb(SMC935_CFG, 0xaa); /* exit config mode */
return (-1);
}
ppc->ppc_model = type;
outb(SMC935_IND, SMC935_LOGDEV); /* select parallel port, */
outb(SMC935_DAT, 3); /* which is logical device 3 */
/* set io port base */
outb(SMC935_IND, SMC935_PORTHI);
outb(SMC935_DAT, (u_char)((ppc->ppc_base & 0xff00) >> 8));
outb(SMC935_IND, SMC935_PORTLO);
outb(SMC935_DAT, (u_char)(ppc->ppc_base & 0xff));
if (!chipset_mode)
ppc->ppc_avm = PPB_COMPATIBLE; /* default mode */
else {
ppc->ppc_avm = chipset_mode;
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_CENT); /* start in compatible mode */
/* SPP + EPP or just plain SPP */
if (chipset_mode & (PPB_SPP)) {
if (chipset_mode & PPB_EPP) {
if (ppc->ppc_epp == EPP_1_9) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_EPP19SPP);
}
if (ppc->ppc_epp == EPP_1_7) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_EPP17SPP);
}
} else {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_SPP);
}
}
/* ECP + EPP or just plain ECP */
if (chipset_mode & PPB_ECP) {
if (chipset_mode & PPB_EPP) {
if (ppc->ppc_epp == EPP_1_9) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECPEPP19);
}
if (ppc->ppc_epp == EPP_1_7) {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECPEPP17);
}
} else {
outb(SMC935_IND, SMC935_PPMODE);
outb(SMC935_DAT, SMC935_ECP);
}
}
}
outb(SMC935_CFG, 0xaa); /* exit config mode */
ppc->ppc_type = PPC_TYPE_SMCLIKE;
ppc_smclike_setmode(ppc, chipset_mode);
return (chipset_mode);
}
/*
* Winbond W83877F stuff
*
@ -1095,48 +1221,48 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (bootverbose)
printf("ppc%d:", ppc->ppc_unit);
if (!chipset_mode) {
/* first, check for ECP */
w_ecr(ppc, PPC_ECR_PS2);
if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) {
ppc->ppc_avm |= PPB_ECP | PPB_SPP;
if (bootverbose)
printf(" ECP SPP");
/* search for SMC style ECP+EPP mode */
w_ecr(ppc, PPC_ECR_EPP);
}
/* try to reset EPP timeout bit */
if (ppc_check_epp_timeout(ppc)) {
ppc->ppc_avm |= PPB_EPP;
if (ppc->ppc_avm & PPB_ECP) {
/* SMC like chipset found */
ppc->ppc_model = SMC_LIKE;
ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
} else {
if (bootverbose)
printf(" EPP");
}
} else {
/* restore to standard mode */
w_ecr(ppc, PPC_ECR_STD);
}
/* XXX try to detect NIBBLE and PS2 modes */
ppc->ppc_avm |= PPB_NIBBLE;
/* first, check for ECP */
w_ecr(ppc, PPC_ECR_PS2);
if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) {
ppc->ppc_dtm |= PPB_ECP | PPB_SPP;
if (bootverbose)
printf(" SPP");
printf(" ECP SPP");
} else {
ppc->ppc_avm = chipset_mode;
/* search for SMC style ECP+EPP mode */
w_ecr(ppc, PPC_ECR_EPP);
}
/* try to reset EPP timeout bit */
if (ppc_check_epp_timeout(ppc)) {
ppc->ppc_dtm |= PPB_EPP;
if (ppc->ppc_dtm & PPB_ECP) {
/* SMC like chipset found */
ppc->ppc_model = SMC_LIKE;
ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
} else {
if (bootverbose)
printf(" EPP");
}
} else {
/* restore to standard mode */
w_ecr(ppc, PPC_ECR_STD);
}
/* XXX try to detect NIBBLE and PS2 modes */
ppc->ppc_dtm |= PPB_NIBBLE;
if (bootverbose)
printf(" SPP");
if (chipset_mode)
ppc->ppc_avm = chipset_mode;
else
ppc->ppc_avm = ppc->ppc_dtm;
if (bootverbose)
printf("\n");
@ -1168,6 +1294,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
ppc_pc873xx_detect,
ppc_smc37c66xgt_detect,
ppc_w83877f_detect,
ppc_smc37c935_detect,
ppc_generic_detect,
NULL
};
@ -1234,8 +1361,9 @@ ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
struct ppb_microseq *stack = 0;
/* microsequence registers are equivalent to PC-like port registers */
#define r_reg(register,ppc) (inb((ppc)->ppc_base + register))
#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
#define r_reg(register,ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, register))
#define w_reg(register, ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, register, byte))
#define INCR_PC (mi ++) /* increment program counter */
@ -1536,7 +1664,7 @@ ppc_write(device_t dev, char *buf, int len, int how)
*/
if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
if (ppc->ppc_dmachan >= 0) {
if (ppc->ppc_dmachan > 0) {
/* byte mode, no intr, no DMA, dir=0, flush fifo
*/
@ -1764,11 +1892,13 @@ ppc_probe(device_t dev)
port = PC98_IEEE_1284_PORT;
next_bios_ppc += 1;
if (bootverbose)
device_printf(dev, "parallel port found at 0x%x\n",
(int) port);
device_printf(dev,
"parallel port found at 0x%x\n",
(int) port);
}
#endif
bus_set_resource(dev, SYS_RES_IOPORT, 0, port, IO_LPTSIZE);
bus_set_resource(dev, SYS_RES_IOPORT, 0, port,
IO_LPTSIZE_EXTENDED);
}
#endif
#ifdef __alpha__
@ -1776,19 +1906,40 @@ ppc_probe(device_t dev)
* There isn't a bios list on alpha. Put it in the usual place.
*/
if (error) {
bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc, IO_LPTSIZE);
bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc,
IO_LPTSIZE_NORMAL);
}
#endif
/* IO port is mandatory */
/* Try "extended" IO port range...*/
ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
&ppc->rid_ioport, 0, ~0,
IO_LPTSIZE, RF_ACTIVE);
if (ppc->res_ioport == 0) {
device_printf(dev, "cannot reserve I/O port range\n");
goto error;
IO_LPTSIZE_EXTENDED, RF_ACTIVE);
if (ppc->res_ioport != 0) {
if (bootverbose)
device_printf(dev, "using extended I/O port range\n");
} else {
/* Failed? If so, then try the "normal" IO port range... */
ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
&ppc->rid_ioport, 0, ~0,
IO_LPTSIZE_NORMAL,
RF_ACTIVE);
if (ppc->res_ioport != 0) {
if (bootverbose)
device_printf(dev, "using normal I/O port range\n");
} else {
device_printf(dev, "cannot reserve I/O port range\n");
goto error;
}
}
ppc->ppc_base = rman_get_start(ppc->res_ioport);
ppc->ppc_base = rman_get_start(ppc->res_ioport);
ppc->bsh = rman_get_bushandle(ppc->res_ioport);
ppc->bst = rman_get_bustag(ppc->res_ioport);
ppc->ppc_flags = device_get_flags(dev);
@ -1921,22 +2072,22 @@ ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
switch (iop) {
case PPB_OUTSB_EPP:
outsb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
break;
case PPB_OUTSW_EPP:
outsw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
break;
case PPB_OUTSL_EPP:
outsl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
break;
case PPB_INSB_EPP:
insb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt);
break;
case PPB_INSW_EPP:
insw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
break;
case PPB_INSL_EPP:
insl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
break;
case PPB_RDTR:
return (r_dtr(ppc));

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1997 Nicolas Souchu
* Copyright (c) 2001 Alcove - Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,8 @@
#define WINB_W83877AF 8
#define WINB_UNKNOWN 9
#define NS_PC87334 10
#define SMC_37C935 11
#define NS_PC87303 12
/*
* Parallel Port Chipset Type. SMC versus GENERIC (others)
@ -61,6 +63,7 @@ struct ppc_data {
int ppc_mode; /* chipset current mode */
int ppc_avm; /* chipset available modes */
int ppc_dtm; /* chipset detected modes */
#define PPC_IRQ_NONE 0x0
#define PPC_IRQ_nACK 0x1
@ -103,6 +106,9 @@ struct ppc_data {
int rid_irq, rid_drq, rid_ioport;
struct resource *res_irq, *res_drq, *res_ioport;
bus_space_handle_t bsh;
bus_space_tag_t bst;
void *intr_cookie;
int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
@ -144,23 +150,25 @@ struct ppc_data {
#define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR)
#define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR)
#define r_dtr(ppc) (inb((ppc)->ppc_base + PPC_SPP_DTR))
#define r_str(ppc) (inb((ppc)->ppc_base + PPC_SPP_STR))
#define r_ctr(ppc) (inb((ppc)->ppc_base + PPC_SPP_CTR))
#define r_epp_A(ppc) (inb((ppc)->ppc_base + PPC_EPP_ADDR))
#define r_epp_D(ppc) (inb((ppc)->ppc_base + PPC_EPP_DATA))
#define r_cnfgA(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGA))
#define r_cnfgB(ppc) (inb((ppc)->ppc_base + PPC_ECP_CNFGB))
#define r_ecr(ppc) (inb((ppc)->ppc_base + PPC_ECP_ECR))
#define r_fifo(ppc) (inb((ppc)->ppc_base + PPC_ECP_D_FIFO))
#define r_dtr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR))
#define r_str(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR))
#define r_ctr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR))
#define w_dtr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_DTR, byte)
#define w_str(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_STR, byte)
#define w_ctr(ppc,byte) outb((ppc)->ppc_base + PPC_SPP_CTR, byte)
#define w_epp_A(ppc,byte) outb((ppc)->ppc_base + PPC_EPP_ADDR, byte)
#define w_epp_D(ppc,byte) outb((ppc)->ppc_base + PPC_EPP_DATA, byte)
#define w_ecr(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_ECR, byte)
#define w_fifo(ppc,byte) outb((ppc)->ppc_base + PPC_ECP_D_FIFO, byte)
#define r_epp_A(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR))
#define r_epp_D(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA))
#define r_cnfgA(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGA))
#define r_cnfgB(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGB))
#define r_ecr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR))
#define r_fifo(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO))
#define w_dtr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR, byte))
#define w_str(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR, byte))
#define w_ctr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR, byte))
#define w_epp_A(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR, byte))
#define w_epp_D(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA, byte))
#define w_ecr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR, byte))
#define w_fifo(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO, byte))
/*
* Register defines for the PC873xx parts
@ -213,6 +221,32 @@ struct ppc_data {
#define SMC_ECP 0x2 /* ECP */
#define SMC_ECPEPP 0x3 /* ECP and EPP */
/*
* Register defines for the SMC FDC37C935 parts
*/
/* Configuration ports */
#define SMC935_CFG 0x370
#define SMC935_IND 0x370
#define SMC935_DAT 0x371
/* Registers */
#define SMC935_LOGDEV 0x7
#define SMC935_ID 0x20
#define SMC935_PORTHI 0x60
#define SMC935_PORTLO 0x61
#define SMC935_PPMODE 0xf0
/* Parallel port modes */
#define SMC935_SPP 0x38 + 0
#define SMC935_EPP19SPP 0x38 + 1
#define SMC935_ECP 0x38 + 2
#define SMC935_ECPEPP19 0x38 + 3
#define SMC935_CENT 0x38 + 4
#define SMC935_EPP17SPP 0x38 + 5
#define SMC935_UNUSED 0x38 + 6
#define SMC935_ECPEPP17 0x38 + 7
/*
* Register defines for the Winbond W83877F parts
*/