diff options
author | nyan <nyan@FreeBSD.org> | 2001-06-26 11:53:12 +0000 |
---|---|---|
committer | nyan <nyan@FreeBSD.org> | 2001-06-26 11:53:12 +0000 |
commit | ce61f5e2402a5b89d21f887ec1de3b40b6798cf1 (patch) | |
tree | c5ab67d277d34f0abfe35eaf29fb4c464f07347f /sys | |
parent | 0f2397a09b11be58a4ce42281b27213029525963 (diff) | |
download | FreeBSD-src-ce61f5e2402a5b89d21f887ec1de3b40b6798cf1.zip FreeBSD-src-ce61f5e2402a5b89d21f887ec1de3b40b6798cf1.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/pc98/cbus/cbus.h | 2 | ||||
-rw-r--r-- | sys/pc98/cbus/ppc.c | 269 | ||||
-rw-r--r-- | sys/pc98/cbus/ppcreg.h | 70 | ||||
-rw-r--r-- | sys/pc98/pc98/pc98.h | 2 | ||||
-rw-r--r-- | sys/pc98/pc98/ppc.c | 269 | ||||
-rw-r--r-- | sys/pc98/pc98/ppcreg.h | 70 |
6 files changed, 528 insertions, 154 deletions
diff --git a/sys/pc98/cbus/cbus.h b/sys/pc98/cbus/cbus.h index e148441..44cfba6 100644 --- a/sys/pc98/cbus/cbus.h +++ b/sys/pc98/cbus/cbus.h @@ -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 */ diff --git a/sys/pc98/cbus/ppc.c b/sys/pc98/cbus/ppc.c index e20e5b5..d5badd1 100644 --- a/sys/pc98/cbus/ppc.c +++ b/sys/pc98/cbus/ppc.c @@ -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; } @@ -889,6 +930,91 @@ end_detect: } /* + * 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 * * EFER: extended function enable register @@ -1095,47 +1221,47 @@ 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"); + /* 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(" ECP SPP"); - /* search for SMC style ECP+EPP mode */ - w_ecr(ppc, PPC_ECR_EPP); - } + /* 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; + /* try to reset EPP timeout bit */ + if (ppc_check_epp_timeout(ppc)) { + ppc->ppc_dtm |= PPB_EPP; - if (ppc->ppc_avm & PPB_ECP) { - /* SMC like chipset found */ - ppc->ppc_model = SMC_LIKE; - ppc->ppc_type = PPC_TYPE_SMCLIKE; + 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"); - } + if (bootverbose) + printf(" ECP+EPP"); } else { - /* restore to standard mode */ - w_ecr(ppc, PPC_ECR_STD); + 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; + /* XXX try to detect NIBBLE and PS2 modes */ + ppc->ppc_dtm |= PPB_NIBBLE; - if (bootverbose) - printf(" SPP"); + if (bootverbose) + printf(" SPP"); - } else { + 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)); diff --git a/sys/pc98/cbus/ppcreg.h b/sys/pc98/cbus/ppcreg.h index 96e93b7..2aa5ce4 100644 --- a/sys/pc98/cbus/ppcreg.h +++ b/sys/pc98/cbus/ppcreg.h @@ -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 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_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 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 @@ -214,6 +222,32 @@ struct ppc_data { #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 */ diff --git a/sys/pc98/pc98/pc98.h b/sys/pc98/pc98/pc98.h index e148441..44cfba6 100644 --- a/sys/pc98/pc98/pc98.h +++ b/sys/pc98/pc98/pc98.h @@ -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 */ diff --git a/sys/pc98/pc98/ppc.c b/sys/pc98/pc98/ppc.c index e20e5b5..d5badd1 100644 --- a/sys/pc98/pc98/ppc.c +++ b/sys/pc98/pc98/ppc.c @@ -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; } @@ -889,6 +930,91 @@ end_detect: } /* + * 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 * * EFER: extended function enable register @@ -1095,47 +1221,47 @@ 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"); + /* 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(" ECP SPP"); - /* search for SMC style ECP+EPP mode */ - w_ecr(ppc, PPC_ECR_EPP); - } + /* 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; + /* try to reset EPP timeout bit */ + if (ppc_check_epp_timeout(ppc)) { + ppc->ppc_dtm |= PPB_EPP; - if (ppc->ppc_avm & PPB_ECP) { - /* SMC like chipset found */ - ppc->ppc_model = SMC_LIKE; - ppc->ppc_type = PPC_TYPE_SMCLIKE; + 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"); - } + if (bootverbose) + printf(" ECP+EPP"); } else { - /* restore to standard mode */ - w_ecr(ppc, PPC_ECR_STD); + 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; + /* XXX try to detect NIBBLE and PS2 modes */ + ppc->ppc_dtm |= PPB_NIBBLE; - if (bootverbose) - printf(" SPP"); + if (bootverbose) + printf(" SPP"); - } else { + 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)); diff --git a/sys/pc98/pc98/ppcreg.h b/sys/pc98/pc98/ppcreg.h index 96e93b7..2aa5ce4 100644 --- a/sys/pc98/pc98/ppcreg.h +++ b/sys/pc98/pc98/ppcreg.h @@ -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 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_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 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 @@ -214,6 +222,32 @@ struct ppc_data { #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 */ |