diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-04-21 19:33:48 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-04-21 19:33:48 +0000 |
commit | 6091432ef10a115d6df3da0ffff5bf63a26d6a31 (patch) | |
tree | fdfefa72cb48139405d4f21b9f77abf73aaee5d0 /sys | |
parent | 403a35f383969fa15140ed4da996a8be56ac6470 (diff) |
More reworking of interrupt handling and VME support, and rename various
board-specific defines to prevent any risk of collision. This also adds
clock support for AV530 family, and timecounter support (cio code sync'ed
with mvme88k). And various bugs fixed in the process.
This is enough to get models 4600 and 530 to run multiuser with a Hawk
Ethernet VME card (the onboard Ethernet is not supported yet, coming soon).
There is no way to share a disk with DG/UX yet, the kernel (and fdisk(8))
needs to become aware of its ways.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/aviion/aviion/av400_machdep.c | 103 | ||||
-rw-r--r-- | sys/arch/aviion/aviion/av530_machdep.c | 137 | ||||
-rw-r--r-- | sys/arch/aviion/aviion/cio_clock.c | 166 | ||||
-rw-r--r-- | sys/arch/aviion/aviion/machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/aviion/aviion/rtc_clock.c | 123 | ||||
-rw-r--r-- | sys/arch/aviion/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/aviion/conf/files.aviion | 5 | ||||
-rw-r--r-- | sys/arch/aviion/dev/mainbus.c | 4 | ||||
-rw-r--r-- | sys/arch/aviion/dev/nvram.c | 54 | ||||
-rw-r--r-- | sys/arch/aviion/dev/oosiop_syscon.c | 29 | ||||
-rw-r--r-- | sys/arch/aviion/dev/syscon.c | 6 | ||||
-rw-r--r-- | sys/arch/aviion/dev/sysconvar.h | 4 | ||||
-rw-r--r-- | sys/arch/aviion/dev/vme.c | 524 | ||||
-rw-r--r-- | sys/arch/aviion/dev/vmevar.h | 30 | ||||
-rw-r--r-- | sys/arch/aviion/include/_types.h | 5 | ||||
-rw-r--r-- | sys/arch/aviion/include/av400.h | 59 | ||||
-rw-r--r-- | sys/arch/aviion/include/av530.h | 162 | ||||
-rw-r--r-- | sys/arch/aviion/include/avcommon.h | 59 | ||||
-rw-r--r-- | sys/arch/aviion/include/board.h | 40 |
19 files changed, 919 insertions, 598 deletions
diff --git a/sys/arch/aviion/aviion/av400_machdep.c b/sys/arch/aviion/aviion/av400_machdep.c index 8b4502c7bc7..85493f1add1 100644 --- a/sys/arch/aviion/aviion/av400_machdep.c +++ b/sys/arch/aviion/aviion/av400_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: av400_machdep.c,v 1.15 2010/04/18 22:04:37 miod Exp $ */ +/* $OpenBSD: av400_machdep.c,v 1.16 2010/04/21 19:33:45 miod Exp $ */ /* * Copyright (c) 2006, 2007, Miodrag Vallat. * @@ -167,11 +167,23 @@ av400_ptable[] = { UVM_PROT_RW, CACHE_INH }, #if 0 /* mapped by the hardcoded BATC entries */ { AV400_UTILITY,AV400_UTILITY, AV400_UTILITY_SIZE, - UVM_PROT_RW, CACHE_INHIBIT }, + UVM_PROT_RW, CACHE_INH }, #endif { 0, 0, (vsize_t)-1, 0, 0 } }; +const struct vme_range vme_av400[] = { + { VME_A16, + AV400_VME16_START, AV400_VME16_END, AV400_VME16_BASE }, + { VME_A24, + AV400_VME24_START, AV400_VME24_END, AV400_VME24_BASE }, + { VME_A32, + AV400_VME32_START1, AV400_VME32_END1, AV400_VME32_BASE }, + { VME_A32, + AV400_VME32_START2, AV400_VME32_END2, AV400_VME32_BASE }, + { 0 } +}; + const struct board board_av400 = { "100/200/300/400/3000/4000/4300 series", av400_bootstrap, @@ -185,14 +197,7 @@ const struct board board_av400 = { av400_intsrc, av400_ptable, - - AV400_VME16_BASE, - AV400_VME16_START, AV400_VME16_END, - AV400_VME24_BASE, - AV400_VME24_START, AV400_VME24_END, - AV400_VME32_BASE, - AV400_VME32_START1, AV400_VME32_END1, - AV400_VME32_START2, AV400_VME32_END2 + vme_av400 }; /* @@ -208,7 +213,7 @@ const struct board board_av400 = { * Note that, on the AV400 design, the interrupt enable registers are * write-only and read back as 0xffffffff. */ -static u_int32_t int_mask_reg[] = { 0, 0, 0, 0 }; +u_int32_t av400_int_mask_reg[] = { 0, 0, 0, 0 }; u_int av400_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH }; @@ -216,7 +221,7 @@ u_int av400_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH }; /* * Interrupts allowed on secondary processors. */ -#define SLAVE_MASK 0 /* IRQ_SWI0 | IRQ_SWI1 */ +#define SLAVE_MASK 0 /* AV400_IRQ_SWI0 | AV400_IRQ_SWI1 */ #endif /* @@ -246,8 +251,6 @@ av400_startup() { } -int32_t cpuid, sysid; - void av400_bootstrap() { @@ -318,7 +321,7 @@ av400_setipl(u_int level) #endif av400_curspl[cpu] = level; - *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask; + *(u_int32_t *)AV_IEN(cpu) = av400_int_mask_reg[cpu] = mask; /* * We do not flush the pipeline here, because interrupts are disabled, * and set_psr() will synchronize the pipeline. @@ -345,7 +348,7 @@ av400_raiseipl(u_int level) #endif av400_curspl[cpu] = level; - *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask; + *(u_int32_t *)AV_IEN(cpu) = av400_int_mask_reg[cpu] = mask; } /* * We do not flush the pipeline here, because interrupts are disabled, @@ -364,23 +367,23 @@ av400_intsrc(int i) { static const u_int32_t intsrc[] = { 0, - IRQ_ABORT, - IRQ_ACF, - IRQ_SF, - IRQ_CIOI, - IRQ_DI1, - IRQ_DI2, - IRQ_ECI, + AV400_IRQ_ABORT, + AV400_IRQ_ACF, + AV400_IRQ_SF, + AV400_IRQ_CIOI, + AV400_IRQ_DI1, + AV400_IRQ_DI2, + AV400_IRQ_ECI, 0, - IRQ_SCI, + AV400_IRQ_SCI, 0, - IRQ_VME1, - IRQ_VME2, - IRQ_VME3, - IRQ_VME4, - IRQ_VME5, - IRQ_VME6, - IRQ_VME7 + AV400_IRQ_VME1, + AV400_IRQ_VME2, + AV400_IRQ_VME3, + AV400_IRQ_VME4, + AV400_IRQ_VME5, + AV400_IRQ_VME6, + AV400_IRQ_VME7 }; return ((u_int64_t)intsrc[i]); @@ -389,31 +392,31 @@ av400_intsrc(int i) /* * Provide the interrupt source for a given interrupt status bit. */ -static const u_int obio_vec[32] = { +static const u_int av400_obio_vec[32] = { 0, /* SWI0 */ 0, /* SWI1 */ 0, 0, - INTSRC_VME, /* VME1 */ + INTSRC_VME(1), /* VME1 */ INTSRC_SCSI1, /* SCI */ - INTSRC_VME, /* VME2 */ + INTSRC_VME(2), /* VME2 */ 0, 0, 0, /* DVB */ - INTSRC_VME, /* VME3 */ + INTSRC_VME(3), /* VME3 */ 0, /* DWP */ - INTSRC_VME, /* VME4 */ + INTSRC_VME(4), /* VME4 */ 0, /* DTC */ - INTSRC_VME, /* VME5 */ + INTSRC_VME(5), /* VME5 */ INTSRC_ETHERNET1, /* ECI */ INTSRC_DUART2, /* DI2 */ INTSRC_DUART1, /* DI1 */ 0, /* PPI */ - INTSRC_VME, /* VME6 */ + INTSRC_VME(6), /* VME6 */ INTSRC_SYSFAIL, /* SF */ - INTSRC_CIO, /* CIOI */ + INTSRC_CLOCK, /* CIOI */ 0, /* KBD */ - INTSRC_VME, /* VME7 */ + INTSRC_VME(7), /* VME7 */ 0, /* PAR */ 0, /* VID */ 0, /* ZBUF */ @@ -431,6 +434,9 @@ static const u_int obio_vec[32] = { #define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */ #define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */ +#define ISR_GET_CURRENT_MASK(cpu) \ + (*(volatile u_int *)AV_IST & av400_int_mask_reg[cpu]) + void av400_intr(struct trapframe *eframe) { @@ -481,14 +487,16 @@ av400_intr(struct trapframe *eframe) /* find the first bit set in the current mask */ warn = 0; intbit = ff1(cur_mask); - intsrc = obio_vec[intbit]; + intsrc = av400_obio_vec[intbit]; if (intsrc == 0) panic("%s: unexpected interrupt source (bit %d), " "level %d, mask 0x%b", - __func__, intbit, level, cur_mask, IST_STRING); + __func__, intbit, level, + cur_mask, AV400_IST_STRING); - if (intsrc == INTSRC_VME) { + if (IS_VME_INTSRC(intsrc)) { + level = VME_INTSRC_LEVEL(intsrc); ivec = AV400_VIRQLV + (level << 2); vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK; if (vec & VME_BERR_MASK) { @@ -496,7 +504,7 @@ av400_intr(struct trapframe *eframe) "interrupt vector, " "level %d, mask 0x%b\n", __func__, level, - cur_mask, IST_STRING); + cur_mask, AV400_IST_STRING); ign_mask |= 1 << intbit; continue; } @@ -531,18 +539,19 @@ av400_intr(struct trapframe *eframe) if (warn != 0) { ign_mask |= 1 << intbit; - if (intsrc == INTSRC_VME) + if (IS_VME_INTSRC(intsrc)) printf("%s: %s VME interrupt, " "level %d, vec 0x%x, mask 0x%b\n", __func__, warn == 1 ? "spurious" : "unclaimed", - level, vec, cur_mask, IST_STRING); + level, vec, + cur_mask, AV400_IST_STRING); else printf("%s: %s interrupt, " "level %d, bit %d, mask 0x%b\n", __func__, warn == 1 ? "spurious" : "unclaimed", - level, intbit, cur_mask, IST_STRING); + level, intbit, cur_mask, AV400_IST_STRING); } } while (((cur_mask = ISR_GET_CURRENT_MASK(cpu)) & ~ign_mask) != 0); diff --git a/sys/arch/aviion/aviion/av530_machdep.c b/sys/arch/aviion/aviion/av530_machdep.c index f965852693c..fd0e138da20 100644 --- a/sys/arch/aviion/aviion/av530_machdep.c +++ b/sys/arch/aviion/aviion/av530_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: av530_machdep.c,v 1.1 2010/04/18 22:04:37 miod Exp $ */ +/* $OpenBSD: av530_machdep.c,v 1.2 2010/04/21 19:33:45 miod Exp $ */ /* * Copyright (c) 2006, 2007, 2010 Miodrag Vallat. * @@ -50,38 +50,42 @@ u_int av530_safe_level(u_int, u_int, u_int); -const pmap_table_entry -av530_ptable[] = { +const pmap_table_entry av530_ptable[] = { { AV530_PROM, AV530_PROM, AV530_PROM_SIZE, UVM_PROT_RW, CACHE_INH }, #if 0 /* mapped by the hardcoded BATC entries */ { AV530_UTILITY,AV530_UTILITY, AV530_UTILITY_SIZE, - UVM_PROT_RW, CACHE_INHIBIT }, + UVM_PROT_RW, CACHE_INH }, #endif { 0, 0, (vsize_t)-1, 0, 0 } }; +const struct vme_range vme_av530[] = { + { VME_A16, + AV530_VME16_START, AV530_VME16_END, AV530_VME16_BASE }, + { VME_A24, + AV530_VME24_START, AV530_VME24_END, AV530_VME24_BASE }, + { VME_A32, + AV530_VME32_START1, AV530_VME32_END1, AV530_VME32_BASE }, + { VME_A32, + AV530_VME32_START2, AV530_VME32_END2, AV530_VME32_BASE }, + { 0 } +}; + const struct board board_av530 = { "530/4600 series", av530_bootstrap, av530_memsize, av530_startup, av530_intr, - NULL, /* XXX need PIT clock code */ + rtc_init_clocks, av530_getipl, av530_setipl, av530_raiseipl, av530_intsrc, av530_ptable, - - AV530_VME16_BASE, - AV530_VME16_START, AV530_VME16_END, - AV530_VME24_BASE, - AV530_VME24_START, AV530_VME24_END, - AV530_VME32_BASE, - AV530_VME32_START1, AV530_VME32_END1, - AV530_VME32_START2, AV530_VME32_END2 + vme_av530 }; /* @@ -94,11 +98,9 @@ const struct board board_av530 = { /* * Copy of the interrupt enable registers for each CPU. - * Note that, on the AV530 design, the interrupt enable registers are - * write-only and read back as 0xffffffff. */ -static u_int32_t int_mask_reg[] = { 0, 0, 0, 0 }; -static u_int32_t ext_int_mask_reg[] = { 0, 0, 0, 0 }; +u_int32_t av530_int_mask_reg[] = { 0, 0, 0, 0 }; +u_int32_t av530_ext_int_mask_reg[] = { 0, 0, 0, 0 }; u_int av530_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH }; @@ -106,7 +108,7 @@ u_int av530_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH }; /* * Interrupts allowed on secondary processors. */ -#define SLAVE_MASK 0 /* IRQ_SWI0 | IRQ_SWI1 */ +#define SLAVE_MASK 0 /* AV530_IRQ_SWI0 | AV530_IRQ_SWI1 */ #define SLAVE_EXMASK 0 #endif @@ -137,13 +139,13 @@ av530_startup() { } -int32_t cpuid, sysid; - void av530_bootstrap() { extern struct cmmu_p cmmu8820x; +#if 0 extern u_char hostaddr[6]; +#endif uint32_t whoami; /* @@ -185,14 +187,16 @@ av530_bootstrap() * Get all the information we'll need later from the PROM, while * we can still use it. */ +#if 0 scm_getenaddr(hostaddr); +#endif cpuid = scm_cpuid(); sysid = scm_sysid(); } /* * Return the next ipl >= ``curlevel'' at which we can reenable interrupts - * while keeping ``mask'' masked. + * while keeping ``mask'' and ``exmask'' masked. */ u_int av530_safe_level(u_int mask, u_int exmask, u_int curlevel) @@ -233,8 +237,8 @@ av530_setipl(u_int level) #endif av530_curspl[cpu] = level; - *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask; - *(u_int32_t *)AV_EXIEN(cpu) = ext_int_mask_reg[cpu] = exmask; + *(u_int32_t *)AV_IEN(cpu) = av530_int_mask_reg[cpu] = mask; + *(u_int32_t *)AV_EXIEN(cpu) = av530_ext_int_mask_reg[cpu] = exmask; /* * We do not flush the pipeline here, because interrupts are disabled, * and set_psr() will synchronize the pipeline. @@ -264,8 +268,9 @@ av530_raiseipl(u_int level) #endif av530_curspl[cpu] = level; - *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask; - *(u_int32_t *)AV_EXIEN(cpu) = ext_int_mask_reg[cpu] = exmask; + *(u_int32_t *)AV_IEN(cpu) = av530_int_mask_reg[cpu] = mask; + *(u_int32_t *)AV_EXIEN(cpu) = + av530_ext_int_mask_reg[cpu] = exmask; } /* * We do not flush the pipeline here, because interrupts are disabled, @@ -284,35 +289,35 @@ av530_intsrc(int i) { static const u_int32_t intsrc[] = { 0, - IRQ_ABORT, - IRQ_ACF, - IRQ_SF, - 0, /* XXX no clock */ - IRQ_DI, + AV530_IRQ_ABORT, + AV530_IRQ_ACF, + AV530_IRQ_SF, 0, + AV530_IRQ_DI, 0, 0, 0, 0, - IRQ_VME1, - IRQ_VME2, - IRQ_VME3, - IRQ_VME4, - IRQ_VME5, - IRQ_VME6, - IRQ_VME7 - }, ext_intsrc[] = { 0, + AV530_IRQ_VME1, + AV530_IRQ_VME2, + AV530_IRQ_VME3, + AV530_IRQ_VME4, + AV530_IRQ_VME5, + AV530_IRQ_VME6, + AV530_IRQ_VME7 + }, ext_intsrc[] = { 0, 0, 0, 0, + AV530_EXIRQ_PIT0OF, 0, - EXIRQ_DUART2, - EXIRQ_LAN0, - EXIRQ_LAN1, - EXIRQ_SCSI0, - EXIRQ_SCSI1, + AV530_EXIRQ_DUART2, + AV530_EXIRQ_LAN0, + AV530_EXIRQ_LAN1, + AV530_EXIRQ_SCSI0, + AV530_EXIRQ_SCSI1, 0, 0, 0, @@ -331,31 +336,31 @@ av530_intsrc(int i) /* * Provide the interrupt source for a given interrupt status bit. */ -static const u_int obio_vec[32] = { +static const u_int av530_obio_vec[32] = { 0, /* SWI0 */ 0, /* SWI1 */ 0, /* SWI2 */ 0, /* SWI3 */ - INTSRC_VME, /* VME1 */ + INTSRC_VME(1), /* VME1 */ 0, - INTSRC_VME, /* VME2 */ + INTSRC_VME(2), /* VME2 */ 0, /* SIGLPI */ 0, /* LMI */ 0, - INTSRC_VME, /* VME3 */ + INTSRC_VME(3), /* VME3 */ 0, - INTSRC_VME, /* VME4 */ + INTSRC_VME(4), /* VME4 */ 0, - INTSRC_VME, /* VME5 */ + INTSRC_VME(5), /* VME5 */ 0, 0, /* HPI */ INTSRC_DUART1, /* DI */ 0, /* MEM */ - INTSRC_VME, /* VME6 */ + INTSRC_VME(6), /* VME6 */ INTSRC_SYSFAIL, /* SF */ 0, 0, /* KBD */ - INTSRC_VME, /* VME7 */ + INTSRC_VME(7), /* VME7 */ 0, /* SWI4 */ 0, /* SWI5 */ 0, /* SWI6 */ @@ -365,7 +370,7 @@ static const u_int obio_vec[32] = { INTSRC_ACFAIL, /* ACF */ INTSRC_ABORT /* ABORT */ }; -static const u_int obio_exvec[32] = { +static const u_int av530_obio_exvec[32] = { 0, 0, 0, @@ -393,7 +398,7 @@ static const u_int obio_exvec[32] = { 0, /* DMA3C */ 0, /* DMA4C */ 0, - 0, /* PIT0OF */ + INTSRC_CLOCK, /* PIT0OF */ 0, /* PIT1OF */ 0, /* PIT2OF */ 0, /* PIT3OF */ @@ -407,6 +412,11 @@ static const u_int obio_exvec[32] = { #define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */ #define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */ +#define ISR_GET_CURRENT_MASK(cpu) \ + (*(volatile u_int *)AV_IST & av530_int_mask_reg[cpu]) +#define EXISR_GET_CURRENT_MASK(cpu) \ + (*(volatile u_int *)AV_EXIST & av530_ext_int_mask_reg[cpu]) + void av530_intr(struct trapframe *eframe) { @@ -467,25 +477,26 @@ av530_intr(struct trapframe *eframe) warn = 0; if (cur_mask != 0) { intbit = ff1(cur_mask); - intsrc = obio_vec[intbit]; + intsrc = av530_obio_vec[intbit]; if (intsrc == 0) panic("%s: unexpected interrupt source" " (bit %d), level %d, mask 0x%b", __func__, intbit, level, - cur_mask, IST_STRING); + cur_mask, AV530_IST_STRING); } else { intbit = ff1(cur_exmask); - intsrc = obio_exvec[intbit]; + intsrc = av530_obio_exvec[intbit]; if (intsrc == 0) panic("%s: unexpected extended interrupt source" " (bit %d), level %d, mask 0x%b", __func__, intbit, level, - cur_exmask, EXIST_STRING); + cur_exmask, AV530_EXIST_STRING); } - if (intsrc == INTSRC_VME) { + if (IS_VME_INTSRC(intsrc)) { + level = VME_INTSRC_LEVEL(intsrc); ivec = AV530_VIRQLV + (level << 2); vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK; if (vec & VME_BERR_MASK) { @@ -494,7 +505,7 @@ av530_intr(struct trapframe *eframe) "interrupt vector, " "level %d, mask 0x%b\n", __func__, level, - cur_mask, IST_STRING); + cur_mask, AV530_IST_STRING); ign_mask |= 1 << intbit; continue; } @@ -532,12 +543,12 @@ av530_intr(struct trapframe *eframe) else ign_exmask |= 1 << intbit; - if (intsrc == INTSRC_VME) + if (IS_VME_INTSRC(intsrc)) printf("%s: %s VME interrupt, " "level %d, vec 0x%x, mask 0x%b\n", __func__, warn == 1 ? "spurious" : "unclaimed", - level, vec, cur_mask, IST_STRING); + level, vec, cur_mask, AV530_IST_STRING); else { if (cur_mask != 0) printf("%s: %s interrupt, " @@ -546,7 +557,7 @@ av530_intr(struct trapframe *eframe) warn == 1 ? "spurious" : "unclaimed", level, intbit, - cur_mask, IST_STRING); + cur_mask, AV530_IST_STRING); else printf("%s: %s extended interrupt, " "level %d, bit %d, mask 0x%b\n", @@ -554,7 +565,7 @@ av530_intr(struct trapframe *eframe) warn == 1 ? "spurious" : "unclaimed", level, intbit, - cur_exmask, EXIST_STRING); + cur_exmask, AV530_EXIST_STRING); } } } diff --git a/sys/arch/aviion/aviion/cio_clock.c b/sys/arch/aviion/aviion/cio_clock.c index 38fa20edb6a..7d405cefdc6 100644 --- a/sys/arch/aviion/aviion/cio_clock.c +++ b/sys/arch/aviion/aviion/cio_clock.c @@ -1,6 +1,6 @@ -/* $OpenBSD: cio_clock.c,v 1.1 2007/12/19 22:05:04 miod Exp $ */ +/* $OpenBSD: cio_clock.c,v 1.2 2010/04/21 19:33:45 miod Exp $ */ /* - * Copyright (c) 2006, 2007, Miodrag Vallat. + * Copyright (c) 2006, 2007, 2009 Miodrag Vallat. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -138,22 +138,16 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/errno.h> +#include <sys/mutex.h> +#include <sys/timetc.h> #include <uvm/uvm_extern.h> -#include <machine/asm_macro.h> #include <machine/board.h> -#include <machine/cmmu.h> -#include <machine/cpu.h> -#include <machine/reg.h> -#include <machine/trap.h> - -#include <machine/m88100.h> -#include <machine/m8820x.h> #include <machine/avcommon.h> -#include <machine/prom.h> #include <aviion/dev/sysconvar.h> +#include <dev/ic/z8536reg.h> /* * Z8536 (CIO) Clock routines @@ -163,29 +157,27 @@ void cio_clock_init(u_int); u_int read_cio(int); void write_cio(int, u_int); -struct intrhand clock_ih; +struct intrhand cio_clock_ih; int cio_clockintr(void *); int cio_calibrateintr(void *); +u_int cio_get_timecount(struct timecounter *); volatile int cio_calibrate_phase = 0; extern u_int aviion_delay_const; -struct simplelock cio_clock_lock; +uint32_t cio_step; +uint32_t cio_refcnt; +uint32_t cio_lastcnt; -#define CIO_LOCK simple_lock(&acio_clock_lock) -#define CIO_UNLOCK simple_unlock(&cio_clock__lock) +struct mutex cio_mutex = MUTEX_INITIALIZER(IPL_CLOCK); -/* - * Statistics clock interval and variance, in usec. Variance must be a - * power of two. Since this gives us an even number, not an odd number, - * we discard one case and compensate. That is, a variance of 4096 would - * give us offsets in [0..4095]. Instead, we take offsets in [1..4095]. - * This is symmetric about the point 2048, or statvar/2, and thus averages - * to that value (assuming uniform random numbers). - */ -int statvar = 8192; -int statmin; /* statclock interval - 1/2*variance */ +struct timecounter cio_timecounter = { + .tc_get_timecount = cio_get_timecount, + .tc_counter_mask = 0xffffffff, + .tc_name = "cio", + .tc_quality = 0 +}; /* * Notes on the AV400 clock usage: @@ -211,8 +203,6 @@ cio_init_clocks(void) psr = get_psr(); set_psr(psr | PSR_IND); - simple_lock_init(&cio_clock_lock); - #ifdef DIAGNOSTIC if (1000000 % hz) { printf("cannot get %d Hz clock; using 100 Hz\n", hz); @@ -223,16 +213,16 @@ cio_init_clocks(void) cio_clock_init(tick); - stathz = 0; + profhz = stathz = 0; /* * Calibrate delay const. */ - clock_ih.ih_fn = cio_calibrateintr; - clock_ih.ih_arg = 0; - clock_ih.ih_flags = INTR_WANTFRAME; - clock_ih.ih_ipl = IPL_CLOCK; - sysconintr_establish(INTSRC_CIO, &clock_ih, "clock"); + cio_clock_ih.ih_fn = cio_calibrateintr; + cio_clock_ih.ih_arg = 0; + cio_clock_ih.ih_flags = INTR_WANTFRAME; + cio_clock_ih.ih_ipl = IPL_CLOCK; + sysconintr_establish(INTSRC_CLOCK, &cio_clock_ih, "clock"); aviion_delay_const = 1; set_psr(psr); @@ -250,22 +240,21 @@ cio_init_clocks(void) set_psr(psr | PSR_IND); - sysconintr_disestablish(INTSRC_CIO, &clock_ih); - clock_ih.ih_fn = cio_clockintr; - sysconintr_establish(INTSRC_CIO, &clock_ih, "clock"); + sysconintr_disestablish(INTSRC_CLOCK, &cio_clock_ih); + cio_clock_ih.ih_fn = cio_clockintr; + sysconintr_establish(INTSRC_CLOCK, &cio_clock_ih, "clock"); set_psr(psr); + + tc_init(&cio_timecounter); } int cio_calibrateintr(void *eframe) { - CIO_LOCK; - write_cio(CIO_CSR1, CIO_GCB | CIO_CIP); /* Ack the interrupt */ - - /* restart counter */ - write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); - CIO_UNLOCK; + /* no need to grab the mutex, only one processor is running for now */ + /* ack the interrupt */ + write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_C_IP); cio_calibrate_phase++; @@ -275,12 +264,11 @@ cio_calibrateintr(void *eframe) int cio_clockintr(void *eframe) { - CIO_LOCK; - write_cio(CIO_CSR1, CIO_GCB | CIO_CIP); /* Ack the interrupt */ - - /* restart counter */ - write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); - CIO_UNLOCK; + mtx_enter(&cio_mutex); + /* ack the interrupt */ + write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_C_IP); + cio_refcnt += cio_step; + mtx_leave(&cio_mutex); hardclock(eframe); @@ -291,35 +279,25 @@ cio_clockintr(void *eframe) void write_cio(int reg, u_int val) { - int s; volatile int i; volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL; - s = splclock(); - CIO_LOCK; - i = *cio_ctrl; /* goto state 1 */ *cio_ctrl = 0; /* take CIO out of RESET */ i = *cio_ctrl; /* reset CIO state machine */ *cio_ctrl = (reg & 0xff); /* select register */ *cio_ctrl = (val & 0xff); /* write the value */ - - CIO_UNLOCK; - splx(s); } /* Read CIO register */ u_int read_cio(int reg) { - int c, s; + int c; volatile int i; volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL; - s = splclock(); - CIO_LOCK; - /* select register */ *cio_ctrl = (reg & 0xff); /* delay for a short time to allow 8536 to settle */ @@ -327,8 +305,6 @@ read_cio(int reg) ; /* read the value */ c = *cio_ctrl; - CIO_UNLOCK; - splx(s); return (c & 0xff); } @@ -341,33 +317,71 @@ cio_clock_init(u_int period) { volatile int i; - CIO_LOCK; - /* Start by forcing chip into known state */ - read_cio(CIO_MICR); - write_cio(CIO_MICR, CIO_MICR_RESET); /* Reset the CTC */ + read_cio(ZCIO_MIC); + write_cio(ZCIO_MIC, ZCIO_MIC_RESET); /* Reset the CTC */ for (i = 0; i < 1000; i++) /* Loop to delay */ ; /* Clear reset and start init seq. */ - write_cio(CIO_MICR, 0x00); + write_cio(ZCIO_MIC, 0x00); /* Wait for chip to come ready */ - while ((read_cio(CIO_MICR) & CIO_MICR_RJA) == 0) + while ((read_cio(ZCIO_MIC) & ZCIO_MIC_RJA) == 0) ; /* Initialize the 8536 for real */ - write_cio(CIO_MICR, - CIO_MICR_MIE /* | CIO_MICR_NV */ | CIO_MICR_RJA | CIO_MICR_DLC); - write_cio(CIO_CTMS1, CIO_CTMS_CSC); /* Continuous count */ - write_cio(CIO_PDCB, 0xff); /* set port B to input */ + write_cio(ZCIO_MIC, + ZCIO_MIC_MIE /* | ZCIO_MIC_NV */ | ZCIO_MIC_RJA | ZCIO_MIC_DLC); + write_cio(ZCIO_CT1MD, ZCIO_CTMD_CSC); /* Continuous count */ + write_cio(ZCIO_PBDIR, 0xff); /* set port B to input */ period <<= 1; /* CT#1 runs at PCLK/2, hence 2MHz */ - write_cio(CIO_CT1MSB, period >> 8); - write_cio(CIO_CT1LSB, period); + write_cio(ZCIO_CT1TCM, period >> 8); + write_cio(ZCIO_CT1TCL, period); /* enable counter #1 */ - write_cio(CIO_MCCR, CIO_MCCR_CT1E | CIO_MCCR_PBE); - write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); + write_cio(ZCIO_MCC, ZCIO_MCC_CT1E | ZCIO_MCC_PBE); + write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_TCB | ZCIO_CTCS_S_IE); + + cio_step = period; + cio_timecounter.tc_frequency = (uint64_t)cio_step * hz; +} + +u_int +cio_get_timecount(struct timecounter *tc) +{ + u_int cmsb, clsb, counter, curcnt; + + /* + * The CIO counter is free running, but by setting the + * RCC bit in its control register, we can read a frozen + * value of the counter. + * The counter will automatically unfreeze after reading + * its LSB. + */ + + mtx_enter(&cio_mutex); + write_cio(ZCIO_CT1CS, ZCIO_CTCS_GCB | ZCIO_CTCS_RCC); + cmsb = read_cio(ZCIO_CT1CCM); + clsb = read_cio(ZCIO_CT1CCL); + curcnt = cio_refcnt; + + counter = (cmsb << 8) | clsb; +#if 0 /* this will never happen unless the period itself is 65536 */ + if (counter == 0) + counter = 65536; +#endif + + /* + * The counter counts down from its initialization value to 1. + */ + counter = cio_step - counter; + + curcnt += counter; + if (curcnt < cio_lastcnt) + curcnt += cio_step; - CIO_UNLOCK; + cio_lastcnt = curcnt; + mtx_leave(&cio_mutex); + return curcnt; } diff --git a/sys/arch/aviion/aviion/machdep.c b/sys/arch/aviion/aviion/machdep.c index 344476bc6e2..1ad3b855ae7 100644 --- a/sys/arch/aviion/aviion/machdep.c +++ b/sys/arch/aviion/aviion/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.34 2010/04/18 18:37:37 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.35 2010/04/21 19:33:45 miod Exp $ */ /* * Copyright (c) 2007 Miodrag Vallat. * @@ -162,6 +162,8 @@ const char *prom_bootargs; /* set in locore.S */ char bootargs[256]; /* local copy */ u_int bootdev, bootunit, bootpart; /* set in locore.S */ +int32_t cpuid, sysid; + int cputyp; /* set in locore.S */ int avtyp; const struct board *platform; diff --git a/sys/arch/aviion/aviion/rtc_clock.c b/sys/arch/aviion/aviion/rtc_clock.c new file mode 100644 index 00000000000..696ad7861a4 --- /dev/null +++ b/sys/arch/aviion/aviion/rtc_clock.c @@ -0,0 +1,123 @@ +/* $OpenBSD: rtc_clock.c,v 1.1 2010/04/21 19:33:45 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Clock routines using a freerunning RTC counter (models 530/4600) + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/timetc.h> + +#include <machine/board.h> +#include <machine/avcommon.h> +#include <machine/av530.h> + +#include <aviion/dev/sysconvar.h> + +extern u_int aviion_delay_const; + +struct intrhand rtc_clock_ih; + +int rtc_clockintr(void *); +u_int rtc_get_timecount(struct timecounter *); + +struct timecounter rtc_timecounter = { + .tc_get_timecount = rtc_get_timecount, + .tc_counter_mask = 0xffffffff, + .tc_name = "rtc", + .tc_quality = 0 +}; + +uint32_t pit_step; + +void +rtc_init_clocks() +{ + uint rtc_speed, pit_interval; + +#ifdef DIAGNOSTIC + if (1000000 % hz) { + printf("cannot get %d Hz clock; using 100 Hz\n", hz); + hz = 100; + } +#endif + tick = 1000000 / hz; + + profhz = stathz = 0; + + /* + * According to the documentation, systems of this family run + * at 33MHz; however other sources seem to imply model 530 + * runs at 25Mhz only. + * If this turns out to be the case, proper calibration of the + * system clock will be necessary. + */ + aviion_delay_const = 33; + rtc_speed = 33333333 / 2; /* apparently RTC runs at half CPUCLK */ + + /* + * RTC is free running; we can get a periodic interrupt at any + * multiple of 0x100 RTC ticks. We use PIT0 for this purpose. + * Therefore to get a proper system clock, we need an interrupt + * every (rtc_speed / hz) ticks, rounded down. + * With hz being 100, this won't be an exact 100Hz clock, but the + * timecounter code will make sure time is kept accurately. + */ + + /* disable and reset all counters */ + *(volatile uint32_t *)AV530_PIT_CMD_ALL = AV530_PIT_RESET; + /* setup countdown interrupt threshold */ + pit_interval = rtc_speed / hz; + pit_step = 0xffffff00 & (-pit_interval); + *(volatile uint32_t *)AV530_PIT0_CNT = pit_step; + /* start timer */ + *(volatile uint32_t *)AV530_PIT0_CS = AV530_PIT_CTEN; + + rtc_clock_ih.ih_fn = rtc_clockintr; + rtc_clock_ih.ih_arg = 0; + rtc_clock_ih.ih_flags = INTR_WANTFRAME; + rtc_clock_ih.ih_ipl = IPL_CLOCK; + sysconintr_establish(INTSRC_CLOCK, &rtc_clock_ih, "clock"); + + rtc_timecounter.tc_frequency = rtc_speed; + tc_init(&rtc_timecounter); +} + +int +rtc_clockintr(void *frame) +{ + /* + * Not only does the PIT stop upon overflow (requiring us to + * rearm it after acknowledging the interrupt), but also the + * comparison value is lost and needs to be setup again. + */ + *(volatile uint32_t *)AV530_PIT0_CS = AV530_PIT_IACK | AV530_PIT_RESET; + *(volatile uint32_t *)AV530_PIT0_CNT = pit_step; + *(volatile uint32_t *)AV530_PIT0_CS = AV530_PIT_CTEN; + hardclock(frame); + + return 1; +} + +u_int +rtc_get_timecount(struct timecounter *tc) +{ + return *(volatile uint32_t *)AV530_RTC_CNT; +} diff --git a/sys/arch/aviion/conf/GENERIC b/sys/arch/aviion/conf/GENERIC index ced7d0af819..ed0fd8bcad5 100644 --- a/sys/arch/aviion/conf/GENERIC +++ b/sys/arch/aviion/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.4 2010/04/20 22:53:23 miod Exp $ +# $OpenBSD: GENERIC,v 1.5 2010/04/21 19:33:47 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -61,6 +61,7 @@ le0 at syscon? offset 0x8c000 ipl 1 # on-board ethernet dart1 at syscon? offset 0x82040 ipl 3 #ssi0 at syscon? offset 0x8d000 ipl 3 oosiop0 at syscon? offset 0xb0000 ipl 2 +oosiop1 at syscon? offset 0xb0080 ipl 2 #ile0 at syscon? offset 0xb00c0 ipl 1 #ile1 at syscon? offset 0xb0140 ipl 1 diff --git a/sys/arch/aviion/conf/files.aviion b/sys/arch/aviion/conf/files.aviion index c7e5bdce58d..9829595bbc7 100644 --- a/sys/arch/aviion/conf/files.aviion +++ b/sys/arch/aviion/conf/files.aviion @@ -1,4 +1,4 @@ -# $OpenBSD: files.aviion,v 1.6 2010/04/20 22:53:23 miod Exp $ +# $OpenBSD: files.aviion,v 1.7 2010/04/21 19:33:47 miod Exp $ # maxpartitions 16 @@ -72,9 +72,10 @@ file arch/aviion/aviion/av400_machdep.c av400 file arch/aviion/aviion/av530_machdep.c av530 file arch/aviion/aviion/av5000_machdep.c av5000 file arch/aviion/aviion/av6280_machdep.c av6280 -file arch/aviion/aviion/cio_clock.c av400 | av530 | +file arch/aviion/aviion/cio_clock.c av400 | av5000 | av6280 file arch/aviion/aviion/m8820x.c m88100 file arch/aviion/aviion/mem.c file arch/aviion/aviion/pmap_table.c file arch/aviion/aviion/prom.c +file arch/aviion/aviion/rtc_clock.c av530 diff --git a/sys/arch/aviion/dev/mainbus.c b/sys/arch/aviion/dev/mainbus.c index 403ee92812f..8d034f1c597 100644 --- a/sys/arch/aviion/dev/mainbus.c +++ b/sys/arch/aviion/dev/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.3 2010/04/20 22:53:24 miod Exp $ */ +/* $OpenBSD: mainbus.c,v 1.4 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 2004, Miodrag Vallat. @@ -36,6 +36,7 @@ #include <uvm/uvm_extern.h> #include <machine/autoconf.h> +#include <machine/board.h> #include <machine/bus.h> #include <machine/cmmu.h> #include <machine/cpu.h> @@ -128,7 +129,6 @@ void mainbus_attach(struct device *parent, struct device *self, void *args) { extern char cpu_model[]; - extern int32_t cpuid, sysid; printf(": %s, cpuid 0x%x", cpu_model, cpuid); if (sysid != -1) diff --git a/sys/arch/aviion/dev/nvram.c b/sys/arch/aviion/dev/nvram.c index 767e189d2f1..7a9f8f17469 100644 --- a/sys/arch/aviion/dev/nvram.c +++ b/sys/arch/aviion/dev/nvram.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nvram.c,v 1.5 2007/12/20 05:19:35 miod Exp $ */ +/* $OpenBSD: nvram.c,v 1.6 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -33,6 +33,7 @@ #include <sys/proc.h> #include <sys/ioctl.h> #include <sys/uio.h> +#include <sys/timetc.h> #include <machine/autoconf.h> #include <machine/conf.h> @@ -118,38 +119,6 @@ nvramattach(parent, self, args) printf(": MK48T0%d\n", sc->sc_len / 1024); } -/* - * Return the best possible estimate of the time in the timeval - * to which tvp points. We do this by returning the current time - * plus the amount of time since the last clock interrupt (clock.c:clkread). - * - * Check that this time is no less than any previously-reported time, - * which could happen around the time of a clock adjustment. Just for fun, - * we guarantee that the time will be greater than the value obtained by a - * previous call. - */ -void -microtime(tvp) - struct timeval *tvp; -{ - int s = splhigh(); - static struct timeval lasttime; - - *tvp = time; - while (tvp->tv_usec >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - if (tvp->tv_sec == lasttime.tv_sec && - tvp->tv_usec <= lasttime.tv_usec && - (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - lasttime = *tvp; - splx(s); -} - #define LEAPYEAR(y) (((y) & 3) == 0) /* @@ -212,7 +181,7 @@ void timetochip(c) struct chiptime *c; { - int t, t2, t3, now = time.tv_sec; + int t, t2, t3, now = time_second; /* January 1 1970 was a Thursday (4 in unix wdays) */ /* compute the days since the epoch */ @@ -268,6 +237,9 @@ inittodr(base) struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0]; int sec, min, hour, day, mon, year; int badbase = 0, waszero = base == 0; + struct timespec ts; + + ts.tv_sec = ts.tv_nsec = 0; if (base < 36 * SECYR) { /* this code did not exist until 2006 */ /* @@ -302,7 +274,7 @@ inittodr(base) bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_regs + (CLK_CSR << 2)) & ~CLK_READ); - if ((time.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) { + if ((ts.tv_sec = chiptotime(sec, min, hour, day, mon, year)) == 0) { printf("WARNING: bad date in nvram"); #ifdef DEBUG printf("\nday = %d, mon = %d, year = %d, hour = %d, min = %d, sec = %d", @@ -313,20 +285,22 @@ inittodr(base) * Believe the time in the file system for lack of * anything better, resetting the clock. */ - time.tv_sec = base; + ts.tv_sec = base; if (!badbase) resettodr(); } else { - int deltat = time.tv_sec - base; + int deltat = ts.tv_sec - base; if (deltat < 0) deltat = -deltat; if (waszero || deltat < 2 * SECDAY) - return; + goto done; printf("WARNING: clock %s %d days", - time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + ts.tv_sec < base ? "lost" : "gained", deltat / SECDAY); } printf(" -- CHECK AND RESET THE DATE!\n"); +done: + tc_setclock(&ts); } /* @@ -341,7 +315,7 @@ resettodr() struct nvramsoftc *sc = (struct nvramsoftc *) nvram_cd.cd_devs[0]; struct chiptime c; - if (!time.tv_sec || sc == NULL) + if (time_second == 0 || sc == NULL) return; timetochip(&c); diff --git a/sys/arch/aviion/dev/oosiop_syscon.c b/sys/arch/aviion/dev/oosiop_syscon.c index d0647999cdb..d82bbb99b5b 100644 --- a/sys/arch/aviion/dev/oosiop_syscon.c +++ b/sys/arch/aviion/dev/oosiop_syscon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: oosiop_syscon.c,v 1.1 2010/04/20 22:53:24 miod Exp $ */ +/* $OpenBSD: oosiop_syscon.c,v 1.2 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -27,6 +27,7 @@ #include <machine/autoconf.h> #include <machine/board.h> #include <machine/bus.h> +#include <machine/av530.h> #include <aviion/dev/sysconvar.h> @@ -49,11 +50,29 @@ const struct cfattach oosiop_syscon_ca = { int oosiop_syscon_match(struct device *parent, void *match, void *aux) { + struct confargs *ca = aux; + paddr_t fuse; + if (avtyp != AV_530) return 0; - /* XXX check IOFUSE register */ - return 1; + switch (ca->ca_paddr) { + case AV530_SCSI1: + fuse = AV530_IOFUSE0; + break; + case AV530_SCSI2: + fuse = AV530_IOFUSE1; + break; + default: + return 0; + } + + /* check IOFUSE register */ + if (badaddr(fuse, 1) != 0) + return 0; + + /* check fuse status */ + return ISSET(*(volatile uint8_t *)fuse, AV530_IOFUSE_SCSI); } void @@ -63,6 +82,7 @@ oosiop_syscon_attach(struct device *parent, struct device *self, void *aux) struct oosiop_softc *sc = (struct oosiop_softc *)self; struct confargs *ca = aux; bus_space_handle_t ioh; + int intsrc; if (bus_space_map(ca->ca_iot, ca->ca_paddr, OOSIOP_NREGS, 0, &ioh) != 0) { @@ -88,5 +108,6 @@ oosiop_syscon_attach(struct device *parent, struct device *self, void *aux) ssc->sc_ih.ih_arg = sc; ssc->sc_ih.ih_flags = 0; ssc->sc_ih.ih_ipl = ca->ca_ipl; - sysconintr_establish(INTSRC_SCSI1, &ssc->sc_ih, self->dv_xname); + intsrc = ca->ca_paddr == AV530_SCSI1 ? INTSRC_SCSI1 : INTSRC_SCSI2; + sysconintr_establish(intsrc, &ssc->sc_ih, self->dv_xname); } diff --git a/sys/arch/aviion/dev/syscon.c b/sys/arch/aviion/dev/syscon.c index 85d0c0e9376..9c6c8920efe 100644 --- a/sys/arch/aviion/dev/syscon.c +++ b/sys/arch/aviion/dev/syscon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: syscon.c,v 1.4 2007/12/19 22:05:06 miod Exp $ */ +/* $OpenBSD: syscon.c,v 1.5 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2007 Miodrag Vallat. * @@ -95,7 +95,7 @@ sysconattach(struct device *parent, struct device *self, void *args) /* * Set up interrupt handlers. */ - for (i = 0; i < INTSRC_VME; i++) + for (i = 0; i < NINTSRC_SYSCON; i++) SLIST_INIT(&sysconintr_handlers[i]); /* @@ -163,7 +163,7 @@ syscon_print(void *args, const char *pnp) * Interrupt related code */ -intrhand_t sysconintr_handlers[INTSRC_VME]; +intrhand_t sysconintr_handlers[NINTSRC_SYSCON]; int sysconintr_establish(u_int intsrc, struct intrhand *ih, const char *name) diff --git a/sys/arch/aviion/dev/sysconvar.h b/sys/arch/aviion/dev/sysconvar.h index f9d09534d3a..b9883b31bfe 100644 --- a/sys/arch/aviion/dev/sysconvar.h +++ b/sys/arch/aviion/dev/sysconvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysconvar.h,v 1.1 2007/12/19 22:05:06 miod Exp $ */ +/* $OpenBSD: sysconvar.h,v 1.2 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2007 Miodrag Vallat. @@ -17,7 +17,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -extern intrhand_t sysconintr_handlers[INTSRC_VME]; +extern intrhand_t sysconintr_handlers[NINTSRC_SYSCON]; int sysconintr_establish(u_int, struct intrhand *, const char *); void sysconintr_disestablish(u_int, struct intrhand *); diff --git a/sys/arch/aviion/dev/vme.c b/sys/arch/aviion/dev/vme.c index f07c6fb8f2d..784b841664c 100644 --- a/sys/arch/aviion/dev/vme.c +++ b/sys/arch/aviion/dev/vme.c @@ -1,6 +1,6 @@ -/* $OpenBSD: vme.c,v 1.6 2010/04/20 22:53:24 miod Exp $ */ +/* $OpenBSD: vme.c,v 1.7 2010/04/21 19:33:47 miod Exp $ */ /* - * Copyright (c) 2006, 2007, Miodrag Vallat. + * Copyright (c) 2006, 2007, 2010 Miodrag Vallat. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,10 +24,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* - * XXX TODO: Finish /dev/vme{a16,a24,a32}{d8,d16,d32} interface. - */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -47,25 +43,33 @@ #include <machine/avcommon.h> -struct vmesoftc { +struct vme_softc { struct device sc_dev; struct extent *sc_ext_a16; struct extent *sc_ext_a24; struct extent *sc_ext_a32; + + const struct vme_range *sc_ranges; }; int vmematch(struct device *, void *, void *); void vmeattach(struct device *, struct device *, void *); -struct cfattach vme_ca = { - sizeof(struct vmesoftc), vmematch, vmeattach +const struct cfattach vme_ca = { + sizeof(struct vme_softc), vmematch, vmeattach }; struct cfdriver vme_cd = { NULL, "vme", DV_DULL }; +/* minor device number encoding */ +#define AWIDTH_FIELD(minor) (minor & 0x0f) +#define AWIDTH(w) ((w) << 3) +#define DWIDTH_FIELD(minor) ((minor & 0xf0) >> 4) +#define DWIDTH(w) ((w) << 3) + uint16_t vme_d8_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); void vme_d8_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, uint8_t *, bus_size_t); @@ -102,28 +106,33 @@ int vme_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, bus_space_handle_t *); void * vme_vaddr(bus_space_tag_t, bus_space_handle_t); -int vme_map(struct extent *, paddr_t, bus_addr_t, bus_size_t, int, - bus_space_handle_t *); -void vme_unmap(struct extent *, vme_addr_t, vaddr_t, bus_size_t); +int vme_map(struct vme_softc *, struct extent *, u_int, + bus_addr_t, bus_size_t, int, vaddr_t *); +int vme_map_r(const struct vme_range *, paddr_t, psize_t, int, vm_prot_t, + vaddr_t *); +void vme_unmap(struct vme_softc *, struct extent *, u_int, + vaddr_t, paddr_t, bus_size_t); int vmeprint(void *, const char *); int vmescan(struct device *, void *, void *); +int vmerw(struct vme_softc *, int, int, struct uio *, int); + int vmematch(struct device *parent, void *vcf, void *aux) { /* XXX no VME on AV100/AV200/AV300, though */ - return (vme_cd.cd_ndevs == 0); + return (platform->vme_ranges != NULL && vme_cd.cd_ndevs == 0); } void vmeattach(struct device *parent, struct device *self, void *aux) { - struct vmesoftc *sc = (struct vmesoftc *)self; + struct vme_softc *sc = (struct vme_softc *)self; + const struct vme_range *r; + const char *fmt; u_int32_t ucsr; int i; - printf("\n"); - /* * Set up interrupt handlers. */ @@ -135,10 +144,16 @@ vmeattach(struct device *parent, struct device *self, void *aux) */ sc->sc_ext_a16 = extent_create("vme a16", 0, 1 << (16 - PAGE_SHIFT), M_DEVBUF, NULL, 0, EX_NOWAIT); + if (sc->sc_ext_a16 == NULL) + goto out1; sc->sc_ext_a24 = extent_create("vme a24", 0, 1 << (24 - PAGE_SHIFT), M_DEVBUF, NULL, 0, EX_NOWAIT); + if (sc->sc_ext_a24 == NULL) + goto out2; sc->sc_ext_a32 = extent_create("vme a32", 0, 1 << (32 - PAGE_SHIFT), M_DEVBUF, NULL, 0, EX_NOWAIT); + if (sc->sc_ext_a32 == NULL) + goto out3; /* * Force a reasonable timeout for VME data transfers. @@ -160,20 +175,38 @@ vmeattach(struct device *parent, struct device *self, void *aux) */ *(volatile u_int32_t *)AV_EXTAM = 0x0d; + sc->sc_ranges = platform->vme_ranges; + printf("\n"); + /* * Display VME ranges. */ - printf("%s: A32 %08x-%08x\n", self->dv_xname, - platform->vme32_start1, platform->vme32_end1); - printf("%s: A32 %08x-%08x\n", self->dv_xname, - platform->vme32_start2, platform->vme32_end2); - printf("%s: A24 %08x-%08x\n", self->dv_xname, - platform->vme24_start, platform->vme24_end); - printf("%s: A16 %08x-%08x\n", self->dv_xname, - platform->vme16_start, platform->vme16_end); + for (r = sc->sc_ranges; r->vr_width != 0; r++) { + switch (r->vr_width) { + default: + case VME_A32: + fmt = "%s: A32 %08x-%08x\n"; + break; + case VME_A24: + fmt = "%s: A24 %06x-%06x\n"; + break; + case VME_A16: + fmt = "%s: A16 %04x-%04x\n"; + break; + } + printf(fmt, self->dv_xname, r->vr_start, r->vr_end); + } /* scan for child devices */ config_search(vmescan, self, aux); + return; + +out3: + extent_destroy(sc->sc_ext_a24); +out2: + extent_destroy(sc->sc_ext_a16); +out1: + printf(": can't allocate memory\n", self->dv_xname); } int @@ -189,10 +222,10 @@ vmescan(struct device *parent, void *vcf, void *aux) vaa.vaa_ipl = (u_int)cf->cf_loc[3]; if ((*cf->cf_attach->ca_match)(parent, cf, &vaa) == 0) - return (0); + return 0; config_attach(parent, cf, &vaa, vmeprint); - return (1); + return 1; } int @@ -209,7 +242,7 @@ vmeprint(void *aux, const char *pnp) if (vaa->vaa_ipl != (u_int)-1) printf(" ipl %u", vaa->vaa_ipl); - return (UNCONF); + return UNCONF; } /* @@ -242,7 +275,7 @@ vmeintr_allocate(u_int count, int flags, int ipl, u_int *array) } } if (ISSET(flags, VMEINTR_EXCLUSIVE)) - return (EPERM); + return EPERM; /* * Try to find a range of count contiguous vectors, @@ -263,10 +296,10 @@ vmeintr_allocate(u_int count, int flags, int ipl, u_int *array) if (v == 0) { for (v = 0; v < count; v++) *array++ = vec++; - return (0); + return 0; } } - return (EPERM); + return EPERM; } /* @@ -276,7 +309,7 @@ vmeintr_allocate(u_int count, int flags, int ipl, u_int *array) if (SLIST_EMPTY(&vmeintr_handlers[vec])) { *array++ = vec; if (--count == 0) - return (0); + return 0; } } @@ -288,14 +321,14 @@ vmeintr_allocate(u_int count, int flags, int ipl, u_int *array) if (ih->ih_ipl == ipl && !ISSET(ih->ih_flags, INTR_EXCLUSIVE)) { *array++ = vec; if (--count == 0) - return (0); + return 0; } } /* * There are not enough vectors to share. */ - return (EPERM); + return EPERM; } int @@ -313,14 +346,14 @@ vmeintr_establish(u_int vec, struct intrhand *ih, const char *name) " it uses ipl %d\n", __func__, ih->ih_ipl, vec, intr->ih_ipl); #endif - return (EINVAL); + return EINVAL; } if (ISSET(intr->ih_flags, INTR_EXCLUSIVE) || ISSET(ih->ih_flags, INTR_EXCLUSIVE)) { #ifdef DIAGNOSTIC printf("%s: can't share vector %x\n", __func__, vec); #endif - return (EINVAL); + return EINVAL; } } @@ -331,9 +364,9 @@ vmeintr_establish(u_int vec, struct intrhand *ih, const char *name) /* * Enable VME interrupt source for this level. */ - intsrc_enable(INTSRC_VME + (ih->ih_ipl - 1), ih->ih_ipl); + intsrc_enable(INTSRC_VME(ih->ih_ipl), ih->ih_ipl); - return (0); + return 0; } void @@ -359,90 +392,119 @@ vmeintr_disestablish(u_int vec, struct intrhand *ih) break; } if (vec == NVMEINTR) - intsrc_disable(INTSRC_VME + (ih->ih_ipl - 1)); + intsrc_disable(INTSRC_VME(ih->ih_ipl)); } /* * bus_space specific functions */ -#define ISVMEA32(addr) \ - (((addr) >= platform->vme32_start1 && (addr) <= platform->vme32_end1) || \ - ((addr) >= platform->vme32_start2 && (addr) <= platform->vme32_end2)) -#define ISVMEA24(addr) \ - ((addr) >= platform->vme24_start && (addr) <= platform->vme24_end) -#define ISVMEA16(addr) \ - ((addr) >= platform->vme16_start && (addr) <= platform->vme16_end) - int vme_a16_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; - - if (ISVMEA16(addr) && ISVMEA16(addr + size - 1)) - return vme_map(sc->sc_ext_a16, addr + platform->vme16_base, - addr, size, flags, ret); + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va; + int rc; - return EINVAL; + rc = vme_map(sc, sc->sc_ext_a16, VME_A16, addr, size, flags, &va); + *ret = (bus_space_handle_t)va; + return rc; } int vme_a24_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; - - if (ISVMEA24(addr) && ISVMEA24(addr + size - 1)) - return vme_map(sc->sc_ext_a24, addr + platform->vme24_base, - addr, size, flags, ret); + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va; + int rc; - return EINVAL; + rc = vme_map(sc, sc->sc_ext_a24, VME_A24, addr, size, flags, &va); + *ret = (bus_space_handle_t)va; + return rc; } int vme_a32_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; - - if (ISVMEA32(addr) && ISVMEA32(addr + size - 1)) - return vme_map(sc->sc_ext_a32, addr + platform->vme32_base, - addr, size, flags, ret); + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va; + int rc; - return EINVAL; + rc = vme_map(sc, sc->sc_ext_a32, VME_A32, addr, size, flags, &va); + *ret = (bus_space_handle_t)va; + return rc; } int -vme_map(struct extent *ext, paddr_t paddr, bus_addr_t addr, bus_size_t size, - int flags, bus_space_handle_t *ret) +vme_map(struct vme_softc *sc, struct extent *ext, u_int awidth, + bus_addr_t addr, bus_size_t size, int flags, vaddr_t *rva) { + const struct vme_range *r; int rc; paddr_t pa; - psize_t len; - vaddr_t ova, va; - u_int pg; + psize_t offs, len; - pa = trunc_page(paddr); - len = round_page(paddr + size) - pa; + /* + * Since we need to map VME address ranges on demand, we will allocate + * with a page granularity. + */ + pa = trunc_page(addr); + offs = addr - pa; + len = round_page(addr + size) - pa; + + /* + * Check that the mapping fits within the available address ranges. + */ + for (r = sc->sc_ranges; r->vr_width != 0; r++) { + if (r->vr_width == awidth && + r->vr_start <= addr && r->vr_end >= addr + size - 1) + break; + } + if (r->vr_width == 0) + return EINVAL; + /* + * Register this range in the per-width extent. + */ if (ext != NULL) { - rc = extent_alloc_region(ext, atop(addr), atop(len), + rc = extent_alloc_region(ext, atop(pa), atop(len), EX_NOWAIT | EX_MALLOCOK); if (rc != 0) - return (rc); + return rc; } - ova = va = uvm_km_valloc(kernel_map, len); - if (va == NULL) { - rc = ENOMEM; - goto fail; + /* + * Allocate virtual memory for the range and map it. + */ + rc = vme_map_r(r, pa, len, flags, UVM_PROT_RW, rva); + if (rc != 0) { + if (ext != NULL) + (void)extent_free(ext, atop(pa), atop(len), + EX_NOWAIT | EX_MALLOCOK); + return rc; } - *ret = (bus_space_handle_t)va; + *rva += offs; + return 0; +} +int +vme_map_r(const struct vme_range *r, paddr_t pa, psize_t len, int flags, + vm_prot_t prot, vaddr_t *rva) +{ + vaddr_t ova, va; + u_int pg; + + ova = va = uvm_km_valloc(kernel_map, len); + if (va == NULL) + return ENOMEM; + + pa += r->vr_base; for (pg = atop(len); pg != 0; pg--) { - pmap_kenter_pa(va, pa, UVM_PROT_RW); + pmap_kenter_pa(va, pa, prot); va += PAGE_SIZE; pa += PAGE_SIZE; } @@ -450,69 +512,96 @@ vme_map(struct extent *ext, paddr_t paddr, bus_addr_t addr, bus_size_t size, pmap_cache_ctrl(pmap_kernel(), ova, ova + len, CACHE_GLOBAL); pmap_update(pmap_kernel()); - return (0); + *rva = ova; -fail: - if (ext != NULL) - extent_free(ext, atop(addr), atop(len), EX_NOWAIT | EX_MALLOCOK); - return (rc); + return 0; } void vme_a16_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va = (vaddr_t)handle; paddr_t pa; - if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE) + if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) return; - pa -= platform->vme16_base; - return (vme_unmap(sc->sc_ext_a16, pa, (vaddr_t)handle, size)); + return vme_unmap(sc, sc->sc_ext_a16, VME_A16, va, pa, size); } void vme_a24_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va = (vaddr_t)handle; paddr_t pa; - if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE) + if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) return; - pa -= platform->vme24_base; - return (vme_unmap(sc->sc_ext_a24, pa, (vaddr_t)handle, size)); + return vme_unmap(sc, sc->sc_ext_a24, VME_A24, va, pa, size); } void vme_a32_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { - struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; + struct vme_softc *sc = (void *)vme_cd.cd_devs[0]; + vaddr_t va = (vaddr_t)handle; paddr_t pa; - if (pmap_extract(pmap_kernel(), (vaddr_t)handle, &pa) == FALSE) + if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) return; - pa -= platform->vme32_base; - return (vme_unmap(sc->sc_ext_a32, pa, (vaddr_t)handle, size)); + return vme_unmap(sc, sc->sc_ext_a32, VME_A32, va, pa, size); } void -vme_unmap(struct extent *ext, vme_addr_t addr, vaddr_t vaddr, bus_size_t size) +vme_unmap(struct vme_softc *sc, struct extent *ext, u_int awidth, + vaddr_t vaddr, paddr_t paddr, bus_size_t size) { + const struct vme_range *r; vaddr_t va; - vsize_t len; + paddr_t pa, addr; + psize_t len; va = trunc_page(vaddr); - len = round_page(vaddr + size) - va; + pa = trunc_page(paddr); + len = round_page(paddr + size) - pa; + /* + * Retrieve the address range this mapping comes from. + */ + for (r = sc->sc_ranges; r->vr_width != 0; r++) { + if (r->vr_width != awidth) + continue; + addr = paddr - r->vr_base; + if (r->vr_width == awidth && + r->vr_start <= addr && r->vr_end >= addr + size - 1) + break; + } + if (r->vr_width == 0) { +#ifdef DIAGNOSTIC + printf("%s: non-sensical A%d mapping at va %p pa %p\n", + __func__, AWIDTH(awidth), vaddr, paddr); +#endif + return; + } + + /* + * Undo the mapping. + */ pmap_kremove(va, len); pmap_update(pmap_kernel()); uvm_km_free(kernel_map, va, len); - if (ext != NULL) - extent_free(ext, atop(addr), atop(len), - EX_NOWAIT | EX_MALLOCOK); + /* + * Unregister mapping. + */ + if (ext != NULL) { + pa -= r->vr_base; + extent_free(ext, atop(pa), atop(len), EX_NOWAIT | EX_MALLOCOK); + } } int @@ -520,29 +609,30 @@ vme_subregion(bus_space_tag_t tag, bus_space_handle_t handle, bus_addr_t offset, bus_size_t size, bus_space_handle_t *ret) { /* since vme_map produces linear mappings, this is safe */ + /* XXX does not check range overflow */ *ret = handle + offset; - return (0); + return 0; } void * vme_vaddr(bus_space_tag_t tag, bus_space_handle_t handle) { - return ((void *)handle); + return (void *)handle; } /* - * D8 routines + * D8 access routines */ uint16_t -vme_d8_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +vme_d8_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { volatile uint8_t *addr = (volatile uint8_t *)(h + o); return ((uint16_t)addr[0] << 8) | ((uint16_t)addr[1]); } uint32_t -vme_d8_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +vme_d8_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { volatile uint8_t *addr = (volatile uint8_t *)(h + o); return ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | @@ -550,7 +640,7 @@ vme_d8_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) } void -vme_d8_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, +vme_d8_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v) { volatile uint8_t *addr = (volatile uint8_t *)(h + o); @@ -559,7 +649,7 @@ vme_d8_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, } void -vme_d8_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, +vme_d8_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v) { volatile uint8_t *addr = (volatile uint8_t *)(h + o); @@ -570,61 +660,61 @@ vme_d8_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, } void -vme_d8_space_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d8_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, uint8_t *buf, bus_size_t len) { len >>= 1; while (len-- != 0) { - *(uint16_t *)buf = vme_d8_space_read_2(t, h, o); + *(uint16_t *)buf = vme_d8_read_2(t, h, o); buf += 2; } } void -vme_d8_space_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d8_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, const uint8_t *buf, bus_size_t len) { len >>= 1; while (len-- != 0) { - vme_d8_space_write_2(t, h, o, *(uint16_t *)buf); + vme_d8_write_2(t, h, o, *(uint16_t *)buf); buf += 2; } } void -vme_d8_space_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d8_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, uint8_t *buf, bus_size_t len) { len >>= 2; while (len-- != 0) { - *(uint32_t *)buf = vme_d8_space_read_4(t, h, o); + *(uint32_t *)buf = vme_d8_read_4(t, h, o); buf += 4; } } void -vme_d8_space_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d8_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, const uint8_t *buf, bus_size_t len) { len >>= 2; while (len-- != 0) { - vme_d8_space_write_4(t, h, o, *(uint32_t *)buf); + vme_d8_write_4(t, h, o, *(uint32_t *)buf); buf += 4; } } /* - * D16 routines + * D16 access routines */ uint32_t -vme_d16_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +vme_d16_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) { volatile uint16_t *addr = (volatile uint16_t *)(h + o); return ((uint32_t)addr[0] << 16) | ((uint32_t)addr[1]); } void -vme_d16_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, +vme_d16_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v) { volatile uint16_t *addr = (volatile uint16_t *)(h + o); @@ -633,31 +723,29 @@ vme_d16_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, } void -vme_d16_space_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d16_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, uint8_t *buf, bus_size_t len) { len >>= 2; while (len-- != 0) { - *(uint32_t *)buf = vme_d16_space_read_4(t, h, o); + *(uint32_t *)buf = vme_d16_read_4(t, h, o); buf += 4; } } void -vme_d16_space_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, +vme_d16_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, const uint8_t *buf, bus_size_t len) { len >>= 2; while (len-- != 0) { - vme_d16_space_write_4(t, h, o, *(uint32_t *)buf); + vme_d16_write_4(t, h, o, *(uint32_t *)buf); buf += 4; } } /* * Get a bus_space_tag for the requested address and data access modes. - * - * On aviion, we do not honour the dspace yet. */ int vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, @@ -671,7 +759,7 @@ vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, case VME_D8: break; default: - return (EINVAL); + return EINVAL; } switch (aspace) { @@ -680,13 +768,13 @@ vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, case VME_A16: break; default: - return (EINVAL); + return EINVAL; } tag = (struct aviion_bus_space_tag *)malloc(sizeof *tag, M_DEVBUF, M_NOWAIT); if (tag == NULL) - return (ENOMEM); + return ENOMEM; switch (aspace) { default: @@ -710,6 +798,7 @@ vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, tag->_space_write_1 = generic_space_write_1; switch (dspace) { + default: case VME_D32: tag->_space_read_2 = generic_space_read_2; tag->_space_write_2 = generic_space_write_2; @@ -723,27 +812,27 @@ vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, case VME_D16: tag->_space_read_2 = generic_space_read_2; tag->_space_write_2 = generic_space_write_2; - tag->_space_read_4 = vme_d16_space_read_4; - tag->_space_write_4 = vme_d16_space_write_4; + tag->_space_read_4 = vme_d16_read_4; + tag->_space_write_4 = vme_d16_write_4; tag->_space_read_raw_2 = generic_space_read_raw_2; tag->_space_write_raw_2 = generic_space_write_raw_2; - tag->_space_read_raw_4 = vme_d16_space_read_raw_4; - tag->_space_write_raw_4 = vme_d16_space_write_raw_4; + tag->_space_read_raw_4 = vme_d16_read_raw_4; + tag->_space_write_raw_4 = vme_d16_write_raw_4; break; case VME_D8: - tag->_space_read_2 = vme_d8_space_read_2; - tag->_space_write_2 = vme_d8_space_write_2; - tag->_space_read_4 = vme_d8_space_read_4; - tag->_space_write_4 = vme_d8_space_write_4; - tag->_space_read_raw_2 = vme_d8_space_read_raw_2; - tag->_space_write_raw_2 = vme_d8_space_write_raw_2; - tag->_space_read_raw_4 = vme_d8_space_read_raw_4; - tag->_space_write_raw_4 = vme_d8_space_write_raw_4; + tag->_space_read_2 = vme_d8_read_2; + tag->_space_write_2 = vme_d8_write_2; + tag->_space_read_4 = vme_d8_read_4; + tag->_space_write_4 = vme_d8_write_4; + tag->_space_read_raw_2 = vme_d8_read_raw_2; + tag->_space_write_raw_2 = vme_d8_write_raw_2; + tag->_space_read_raw_4 = vme_d8_read_raw_4; + tag->_space_write_raw_4 = vme_d8_write_raw_4; break; } *bst = tag; - return (0); + return 0; } void @@ -756,17 +845,17 @@ vmebus_release_bst(struct device *vsc, bus_space_tag_t b) * /dev/vme* access routines */ -/* minor device number encoding */ -#define AWIDTH_FIELD(minor) (minor & 0x0f) -#define AWIDTH(w) ((w) << 3) -#define DWIDTH_FIELD(minor) ((minor & 0xf0) >> 4) -#define DWIDTH(w) ((w) << 3) - int vmeopen(dev_t dev, int flags, int type, struct proc *p) { - if (vme_cd.cd_ndevs == 0 || vme_cd.cd_devs[0] == NULL) - return (ENODEV); + struct vme_softc *sc; + + if (minor(dev) >= vme_cd.cd_ndevs || + (sc = vme_cd.cd_devs[minor(dev)]) == NULL) + return ENODEV; + + if (sc->sc_ranges == NULL) /* failed attach */ + return ENODEV; switch (AWIDTH_FIELD(minor(dev))) { case VME_A32: @@ -774,7 +863,7 @@ vmeopen(dev_t dev, int flags, int type, struct proc *p) case VME_A16: break; default: - return (ENODEV); + return ENODEV; } switch (DWIDTH_FIELD(minor(dev))) { @@ -783,28 +872,106 @@ vmeopen(dev_t dev, int flags, int type, struct proc *p) case VME_D8: break; default: - return (ENODEV); + return ENODEV; } - return (0); + return 0; } int vmeclose(dev_t dev, int flags, int type, struct proc *p) { - return (0); + return 0; } int vmeread(dev_t dev, struct uio *uio, int flags) { - return (EIO); + struct vme_softc *sc; + int awidth, dwidth; + + sc = vme_cd.cd_devs[minor(dev)]; + awidth = AWIDTH_FIELD(minor(dev)); + dwidth = DWIDTH_FIELD(minor(dev)); + + return vmerw(sc, awidth, dwidth, uio, flags); } int vmewrite(dev_t dev, struct uio *uio, int flags) { - return (EIO); + struct vme_softc *sc; + int awidth, dwidth; + + sc = vme_cd.cd_devs[minor(dev)]; + awidth = AWIDTH_FIELD(minor(dev)); + dwidth = DWIDTH_FIELD(minor(dev)); + + return vmerw(sc, awidth, dwidth, uio, flags); +} + +int +vmerw(struct vme_softc *sc, int awidth, int dwidth, struct uio *uio, int flags) +{ + const struct vme_range *r; + struct iovec *iov; + psize_t delta, len; + vaddr_t vmepg; + int rc = 0; + + while (uio->uio_resid > 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("bogus uio %p", uio); + continue; + } + + /* + * Figure out which range we will be working on; + * if we hit the end of a range we'll report EFAULT. + */ + for (r = sc->sc_ranges; r->vr_width != 0; r++) { + if (r->vr_width != awidth) + continue; + if ((off_t)r->vr_start <= uio->uio_offset && + (off_t)r->vr_end >= uio->uio_offset) + break; + } + if (r->vr_width == 0) { + rc = EFAULT; /* outside any valid range */ + break; + } + + delta = uio->uio_offset & PAGE_MASK; + len = min(uio->uio_resid, PAGE_SIZE - delta); + /* len = min(len, (off_t)r->vr_end - uio->uio_offset); */ + + rc = vme_map_r(r, trunc_page(uio->uio_offset), PAGE_SIZE, 0, + uio->uio_rw == UIO_READ ? UVM_PROT_R : UVM_PROT_RW, &vmepg); + if (rc != 0) + break; + + /* XXX wrap this because of dwidth */ + rc = uiomove((caddr_t)vmepg + delta, len, uio); + + /* inline vme_unmap */ + pmap_kremove(vmepg, PAGE_SIZE); + pmap_update(pmap_kernel()); + uvm_km_free(kernel_map, vmepg, PAGE_SIZE); + + if (rc != 0) + break; + + iov->iov_base += len; + iov->iov_len -= len; + uio->uio_offset += len; + uio->uio_resid -= len; + } + + return rc; } int @@ -812,44 +979,35 @@ vmeioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { switch (cmd) { default: - return (ENOTTY); + return ENOTTY; } } paddr_t vmemmap(dev_t dev, off_t off, int prot) { + struct vme_softc *sc; + const struct vme_range *r; int awidth; - paddr_t pa; - - if ((off & PAGE_MASK) != 0) - return (-1); + sc = vme_cd.cd_devs[minor(dev)]; awidth = AWIDTH_FIELD(minor(dev)); - /* check offset range */ - if (off < 0 || off >= (1ULL << AWIDTH(awidth))) - return (-1); - - pa = (paddr_t)off; + if ((off & PAGE_MASK) != 0) + return -1; - switch (awidth) { - case VME_A32: - if (!ISVMEA32(pa)) - return (-1); - pa += platform->vme32_base; - break; - case VME_A24: - if (!ISVMEA24(pa)) - return (-1); - pa += platform->vme24_base; - break; - case VME_A16: - if (!ISVMEA16(pa)) - return (-1); - pa += platform->vme16_base; - break; + /* + * Figure out which range we will be working on. + */ + for (r = sc->sc_ranges; r->vr_width != 0; r++) { + if (r->vr_width != awidth) + continue; + if ((off_t)r->vr_start <= off && + (off_t)r->vr_end >= off) + break; } + if (r->vr_width == 0) + return -1; - return (atop(pa)); + return atop(r->vr_base + (paddr_t)off); } diff --git a/sys/arch/aviion/dev/vmevar.h b/sys/arch/aviion/dev/vmevar.h index 9098585ce8c..3d30a2d5b00 100644 --- a/sys/arch/aviion/dev/vmevar.h +++ b/sys/arch/aviion/dev/vmevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmevar.h,v 1.3 2007/12/19 22:05:06 miod Exp $ */ +/* $OpenBSD: vmevar.h,v 1.4 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2006, 2007, Miodrag Vallat * @@ -30,6 +30,28 @@ typedef u_int32_t vme_addr_t; /* + * VME address and data widths + */ + +#define VME_A32 0x04 /* 100..000 */ +#define VME_A24 0x03 /* 011..000 */ +#define VME_A16 0x02 /* 010..000 */ +#define VME_D32 0x04 /* 100..000 */ +#define VME_D16 0x02 /* 010..000 */ +#define VME_D8 0x01 /* 001..000 */ + +/* + * VME address range + */ + +struct vme_range { + u_int vr_width; + vme_addr_t vr_start; + vme_addr_t vr_end; + paddr_t vr_base; +}; + +/* * Attachment information for VME devices. * * Drivers are supposed to do their interrupt vector allocation @@ -71,12 +93,6 @@ int vmeintr_establish(u_int, struct intrhand *, const char *); * when bus accesses are no longer necessary. */ int vmebus_get_bst(struct device *, u_int, u_int, bus_space_tag_t *); -#define VME_A32 0x04 /* 100..000 */ -#define VME_A24 0x03 /* 011..000 */ -#define VME_A16 0x02 /* 010..000 */ -#define VME_D32 0x04 /* 100..000 */ -#define VME_D16 0x02 /* 010..000 */ -#define VME_D8 0x01 /* 001..000 */ void vmebus_release_bst(struct device *, bus_space_tag_t); #endif /* _AVIION_VME_H_ */ diff --git a/sys/arch/aviion/include/_types.h b/sys/arch/aviion/include/_types.h index 2daea26703b..f532a0ac698 100644 --- a/sys/arch/aviion/include/_types.h +++ b/sys/arch/aviion/include/_types.h @@ -1,4 +1,7 @@ -/* $OpenBSD: _types.h,v 1.2 2007/05/15 01:56:46 deraadt Exp $ */ +/* $OpenBSD: _types.h,v 1.3 2010/04/21 19:33:47 miod Exp $ */ /* public domain */ #include <m88k/_types.h> + +/* Feature test macros */ +#define __HAVE_TIMECOUNTER diff --git a/sys/arch/aviion/include/av400.h b/sys/arch/aviion/include/av400.h index c7a38af64e3..919cb1a51fc 100644 --- a/sys/arch/aviion/include/av400.h +++ b/sys/arch/aviion/include/av400.h @@ -1,4 +1,4 @@ -/* $OpenBSD: av400.h,v 1.6 2010/04/18 22:04:39 miod Exp $ */ +/* $OpenBSD: av400.h,v 1.7 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -85,7 +85,6 @@ #define AV400_VIACK6V 0xfff85018 #define AV400_VIACK7V 0xfff8501c #define AV400_VIRQV 0xfff85020 -#define AV400_IVEC 0x40 /* vector returned upon AV400 int */ /* * IEN and IST register bits @@ -93,35 +92,35 @@ * 400, 3000 and 4000 series'', section 3 (Interrupts). */ -#define IRQ_RESERVED 0x1800018c /* all reserved bits */ -#define IRQ_ABORT 0x80000000 /* 31 - Abort */ -#define IRQ_ACF 0x40000000 /* 30 - AC Fail */ -#define IRQ_ARBTO 0x20000000 /* 29 - VME Arbiter Timeout */ -#define IRQ_ZBUF 0x04000000 /* 26 - Z Buffer */ -#define IRQ_VID 0x02000000 /* 25 - Video */ -#define IRQ_PAR 0x01000000 /* 24 - Parity Error */ -#define IRQ_VME7 0x00800000 /* 23 - VMEBus level 7 */ -#define IRQ_KBD 0x00400000 /* 22 - Keyboard */ -#define IRQ_CIOI 0x00200000 /* 21 - CIO */ -#define IRQ_SF 0x00100000 /* 20 - System Failure */ -#define IRQ_VME6 0x00080000 /* 19 - VMEBus level 6 */ -#define IRQ_PPI 0x00040000 /* 18 - Parallel Port */ -#define IRQ_DI1 0x00020000 /* 17 - DUART1 */ -#define IRQ_DI2 0x00010000 /* 16 - DUART2 */ -#define IRQ_ECI 0x00008000 /* 15 - Ethernet Controller */ -#define IRQ_VME5 0x00004000 /* 14 - VMEBus level 5 */ -#define IRQ_DTC 0x00002000 /* 13 - DMA Terminal Count */ -#define IRQ_VME4 0x00001000 /* 12 - VMEBus level 4 */ -#define IRQ_DWP 0x00000800 /* 11 - DMA Write Protect */ -#define IRQ_VME3 0x00000400 /* 10 - VMEBus level 3 */ -#define IRQ_DVB 0x00000200 /* 09 - DMA Valid Bit */ -#define IRQ_VME2 0x00000040 /* 06 - VMEBus level 2 */ -#define IRQ_SCI 0x00000020 /* 05 - SCSI Controller */ -#define IRQ_VME1 0x00000010 /* 04 - VMEBus level 1 */ -#define IRQ_SWI1 0x00000002 /* 01 - SW Interrupt level 1 */ -#define IRQ_SWI0 0x00000001 /* 00 - SW Interrupt level 0 */ +#define AV400_IRQ_RESERVED 0x1800018c /* all reserved bits */ +#define AV400_IRQ_ABORT 0x80000000 /* 31 - Abort */ +#define AV400_IRQ_ACF 0x40000000 /* 30 - AC Fail */ +#define AV400_IRQ_ARBTO 0x20000000 /* 29 - VME Arbiter Timeout */ +#define AV400_IRQ_ZBUF 0x04000000 /* 26 - Z Buffer */ +#define AV400_IRQ_VID 0x02000000 /* 25 - Video */ +#define AV400_IRQ_PAR 0x01000000 /* 24 - Parity Error */ +#define AV400_IRQ_VME7 0x00800000 /* 23 - VMEBus level 7 */ +#define AV400_IRQ_KBD 0x00400000 /* 22 - Keyboard */ +#define AV400_IRQ_CIOI 0x00200000 /* 21 - CIO */ +#define AV400_IRQ_SF 0x00100000 /* 20 - System Failure */ +#define AV400_IRQ_VME6 0x00080000 /* 19 - VMEBus level 6 */ +#define AV400_IRQ_PPI 0x00040000 /* 18 - Parallel Port */ +#define AV400_IRQ_DI1 0x00020000 /* 17 - DUART1 */ +#define AV400_IRQ_DI2 0x00010000 /* 16 - DUART2 */ +#define AV400_IRQ_ECI 0x00008000 /* 15 - Ethernet Controller */ +#define AV400_IRQ_VME5 0x00004000 /* 14 - VMEBus level 5 */ +#define AV400_IRQ_DTC 0x00002000 /* 13 - DMA Terminal Count */ +#define AV400_IRQ_VME4 0x00001000 /* 12 - VMEBus level 4 */ +#define AV400_IRQ_DWP 0x00000800 /* 11 - DMA Write Protect */ +#define AV400_IRQ_VME3 0x00000400 /* 10 - VMEBus level 3 */ +#define AV400_IRQ_DVB 0x00000200 /* 09 - DMA Valid Bit */ +#define AV400_IRQ_VME2 0x00000040 /* 06 - VMEBus level 2 */ +#define AV400_IRQ_SCI 0x00000020 /* 05 - SCSI Controller */ +#define AV400_IRQ_VME1 0x00000010 /* 04 - VMEBus level 1 */ +#define AV400_IRQ_SWI1 0x00000002 /* 01 - SW Interrupt level 1 */ +#define AV400_IRQ_SWI0 0x00000001 /* 00 - SW Interrupt level 0 */ -#define IST_STRING "\20" \ +#define AV400_IST_STRING "\20" \ "\40ABRT\37ACF\36ARBTO\33ZBUF\32VID\31PAR" \ "\30IRQ7\27KBD\26CIOI\25SF\24IRQ6\23PPI\22DI1\21DI2" \ "\20ECI\17IRQ5\16DTC\15IRQ4\14DWP\13IRQ3\12DVB" \ diff --git a/sys/arch/aviion/include/av530.h b/sys/arch/aviion/include/av530.h index d5bb22b5827..73965e000b9 100644 --- a/sys/arch/aviion/include/av530.h +++ b/sys/arch/aviion/include/av530.h @@ -1,4 +1,4 @@ -/* $OpenBSD: av530.h,v 1.1 2010/04/18 22:04:39 miod Exp $ */ +/* $OpenBSD: av530.h,v 1.2 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2006, 2010 Miodrag Vallat * @@ -71,35 +71,35 @@ * 530 series'', section 3 (Interrupts). */ -#define IRQ_RESERVED 0x0020aa00 /* all reserved bits */ -#define IRQ_ABORT 0x80000000 /* 31 - Abort */ -#define IRQ_ACF 0x40000000 /* 30 - AC Fail */ -#define IRQ_ARBTO 0x20000000 /* 29 - VME Arbiter Timeout */ -#define IRQ_DTI 0x10000000 /* 28 - DUART Timer Interrupt */ -#define IRQ_SWI7 0x08000000 /* 27 - SW Interrupt level 7 */ -#define IRQ_SWI6 0x04000000 /* 26 - SW Interrupt level 6 */ -#define IRQ_SWI5 0x02000000 /* 25 - SW Interrupt level 5 */ -#define IRQ_SWI4 0x01000000 /* 24 - SW Interrupt level 4 */ -#define IRQ_VME7 0x00800000 /* 23 - VMEBus level 7 */ -#define IRQ_KBD 0x00400000 /* 22 - Keyboard */ -#define IRQ_SF 0x00100000 /* 20 - System Failure */ -#define IRQ_VME6 0x00080000 /* 19 - VMEBus level 6 */ -#define IRQ_MEM 0x00040000 /* 18 - Memory Error */ -#define IRQ_DI 0x00020000 /* 17 - DUART */ -#define IRQ_SIGHPI 0x00010000 /* 16 - SIGHPI */ -#define IRQ_VME5 0x00004000 /* 14 - VMEBus level 5 */ -#define IRQ_VME4 0x00001000 /* 12 - VMEBus level 4 */ -#define IRQ_VME3 0x00000400 /* 10 - VMEBus level 3 */ -#define IRQ_LMI 0x00000100 /* 08 - Location Monitor */ -#define IRQ_SIGLPI 0x00000080 /* 07 - SIGLPI */ -#define IRQ_VME2 0x00000040 /* 06 - VMEBus level 2 */ -#define IRQ_VME1 0x00000010 /* 04 - VMEBus level 1 */ -#define IRQ_SWI3 0x00000008 /* 03 - SW Interrupt level 3 */ -#define IRQ_SWI2 0x00000004 /* 02 - SW Interrupt level 2 */ -#define IRQ_SWI1 0x00000002 /* 01 - SW Interrupt level 1 */ -#define IRQ_SWI0 0x00000001 /* 00 - SW Interrupt level 0 */ - -#define IST_STRING "\20" \ +#define AV530_IRQ_RESERVED 0x0020aa00 /* all reserved bits */ +#define AV530_IRQ_ABORT 0x80000000 /* 31 - Abort */ +#define AV530_IRQ_ACF 0x40000000 /* 30 - AC Fail */ +#define AV530_IRQ_ARBTO 0x20000000 /* 29 - VME Arbiter Timeout */ +#define AV530_IRQ_DTI 0x10000000 /* 28 - DUART Timer Interrupt */ +#define AV530_IRQ_SWI7 0x08000000 /* 27 - SW Interrupt level 7 */ +#define AV530_IRQ_SWI6 0x04000000 /* 26 - SW Interrupt level 6 */ +#define AV530_IRQ_SWI5 0x02000000 /* 25 - SW Interrupt level 5 */ +#define AV530_IRQ_SWI4 0x01000000 /* 24 - SW Interrupt level 4 */ +#define AV530_IRQ_VME7 0x00800000 /* 23 - VMEBus level 7 */ +#define AV530_IRQ_KBD 0x00400000 /* 22 - Keyboard */ +#define AV530_IRQ_SF 0x00100000 /* 20 - System Failure */ +#define AV530_IRQ_VME6 0x00080000 /* 19 - VMEBus level 6 */ +#define AV530_IRQ_MEM 0x00040000 /* 18 - Memory Error */ +#define AV530_IRQ_DI 0x00020000 /* 17 - DUART */ +#define AV530_IRQ_SIGHPI 0x00010000 /* 16 - SIGHPI */ +#define AV530_IRQ_VME5 0x00004000 /* 14 - VMEBus level 5 */ +#define AV530_IRQ_VME4 0x00001000 /* 12 - VMEBus level 4 */ +#define AV530_IRQ_VME3 0x00000400 /* 10 - VMEBus level 3 */ +#define AV530_IRQ_LMI 0x00000100 /* 08 - Location Monitor */ +#define AV530_IRQ_SIGLPI 0x00000080 /* 07 - SIGLPI */ +#define AV530_IRQ_VME2 0x00000040 /* 06 - VMEBus level 2 */ +#define AV530_IRQ_VME1 0x00000010 /* 04 - VMEBus level 1 */ +#define AV530_IRQ_SWI3 0x00000008 /* 03 - SW Interrupt level 3 */ +#define AV530_IRQ_SWI2 0x00000004 /* 02 - SW Interrupt level 2 */ +#define AV530_IRQ_SWI1 0x00000002 /* 01 - SW Interrupt level 1 */ +#define AV530_IRQ_SWI0 0x00000001 /* 00 - SW Interrupt level 0 */ + +#define AV530_IST_STRING "\20" \ "\40ABRT\37ACF\36ARBTO\35DTI\34SWI7\33SWI6\32SWI5\31SWI4" \ "\30IRQ7\27KBD\25SF\24IRQ6\23MEM\22DI\21SIGHPI" \ "\17IRQ5\15IRQ4\13IRQ3\11LMI" \ @@ -119,53 +119,91 @@ #define AV_EXIST 0xfff8e040 -#define EXISR_GET_CURRENT_MASK(cpu) \ - (*(volatile u_int *)AV_EXIST & ext_int_mask_reg[cpu]) - /* * EXIEN and EXIST register bits - * See ``Programming System control and I/O registers for the 4600 and 530 - * series'', section 3 (Interrupts). + * See ``Programming System Control and I/O Registers: AViiON 4600 and + * 530 series'', section 3 (Interrupts). */ -#define EXIRQ_RESERVED 0x04000e9f /* all reserved bits */ -#define EXIRQ_RTCOF 0x80000000 /* 31 - RTC Overflow */ -#define EXIRQ_PIT3OF 0x40000000 /* 30 - PIT 3 Overflow */ -#define EXIRQ_PIT2OF 0x20000000 /* 29 - PIT 2 Overflow */ -#define EXIRQ_PIT1OF 0x10000000 /* 28 - PIT 1 Overflow */ -#define EXIRQ_PIT0OF 0x08000000 /* 27 - PIT 0 Overflow */ -#define EXIRQ_DMA4C 0x02000000 /* 25 - DMA4 Channel Complete */ -#define EXIRQ_DMA3C 0x01000000 /* 24 - DMA3 Channel Complete */ -#define EXIRQ_DMA2C 0x00800000 /* 23 - DMA2 Channel Complete */ -#define EXIRQ_DMA1C 0x00400000 /* 22 - DMA1 Channel Complete */ -#define EXIRQ_DMA0C 0x00200000 /* 21 - DMA0 Channel Complete */ -#define EXIRQ_SCC 0x00100000 /* 20 - SCC */ -#define EXIRQ_LAN0 0x00080000 /* 19 - Ethernet 0 */ -#define EXIRQ_LAN1 0x00040000 /* 18 - Ethernet 1 */ -#define EXIRQ_SCSI0 0x00020000 /* 17 - SCSI0 */ -#define EXIRQ_SCSI1 0x00010000 /* 16 - SCSI1 */ -#define EXIRQ_VIDEO 0x00008000 /* 15 - Video */ -#define EXIRQ_ZBUF 0x00004000 /* 14 - Z Buffer */ -#define EXIRQ_DUART2 0x00002000 /* 13 - DUART2 */ -#define EXIRQ_VDMA 0x00001000 /* 12 - VDMA */ -#define EXIRQ_IOEXP1 0x00000100 /* 8 - IO Expansion 1 */ -#define EXIRQ_IOEXP2 0x00000040 /* 6 - IO Expansion 2 */ -#define EXIRQ_PDMA 0x00000020 /* 5 - Parallel Printer DMA */ - -#define EXIST_STRING "\20" \ +#define AV530_EXIRQ_RESERVED 0x04000e9f /* all reserved bits */ +#define AV530_EXIRQ_RTCOF 0x80000000 /* 31 - RTC Overflow */ +#define AV530_EXIRQ_PIT3OF 0x40000000 /* 30 - PIT 3 Overflow */ +#define AV530_EXIRQ_PIT2OF 0x20000000 /* 29 - PIT 2 Overflow */ +#define AV530_EXIRQ_PIT1OF 0x10000000 /* 28 - PIT 1 Overflow */ +#define AV530_EXIRQ_PIT0OF 0x08000000 /* 27 - PIT 0 Overflow */ +#define AV530_EXIRQ_DMA4C 0x02000000 /* 25 - DMA4 Channel Complete */ +#define AV530_EXIRQ_DMA3C 0x01000000 /* 24 - DMA3 Channel Complete */ +#define AV530_EXIRQ_DMA2C 0x00800000 /* 23 - DMA2 Channel Complete */ +#define AV530_EXIRQ_DMA1C 0x00400000 /* 22 - DMA1 Channel Complete */ +#define AV530_EXIRQ_DMA0C 0x00200000 /* 21 - DMA0 Channel Complete */ +#define AV530_EXIRQ_SCC 0x00100000 /* 20 - SCC */ +#define AV530_EXIRQ_LAN0 0x00080000 /* 19 - Ethernet 0 */ +#define AV530_EXIRQ_LAN1 0x00040000 /* 18 - Ethernet 1 */ +#define AV530_EXIRQ_SCSI0 0x00020000 /* 17 - SCSI0 */ +#define AV530_EXIRQ_SCSI1 0x00010000 /* 16 - SCSI1 */ +#define AV530_EXIRQ_VIDEO 0x00008000 /* 15 - Video */ +#define AV530_EXIRQ_ZBUF 0x00004000 /* 14 - Z Buffer */ +#define AV530_EXIRQ_DUART2 0x00002000 /* 13 - DUART2 */ +#define AV530_EXIRQ_VDMA 0x00001000 /* 12 - VDMA */ +#define AV530_EXIRQ_IOEXP1 0x00000100 /* 8 - IO Expansion 1 */ +#define AV530_EXIRQ_IOEXP2 0x00000040 /* 6 - IO Expansion 2 */ +#define AV530_EXIRQ_PDMA 0x00000020 /* 5 - Parallel Printer DMA */ + +#define AV530_EXIST_STRING "\20" \ "\40RTCOF\37PIT3OF\36PIT2OF\35PIT1OF\34PIT0OF\32DMA4\31DMA3" \ "\30DMA2\27DMA1\26DMA0\25SCC\24LAN0\23LAN1\22SCSI0\21SCSI1" \ "\20VIDEO\17ZBUF\16DUART2\15VDMA\11IOEXP1" \ "\7IOEXP2\6PDMA" +/* + * Miscellaneous registers + */ + #define AV530_SRST 0xfff83100 /* software reset */ #define SRST_KBD 0x08 #define SRST_DUART2 0x02 #define SRST_DUART1 0x01 -#define AV530_IOBRDID0 0xfffcf000 -#define AV530_IOBRDID1 0xfffcf004 +#define AV530_IOBRDID0 0xfffcf000 /* byte access */ +#define AV530_IOBRDID1 0xfffcf004 /* byte access */ #define AV530_CONFIG 0xfff8fffc +#define AV530_IOFUSE0 0xfffb0040 /* byte access */ +#define AV530_IOFUSE1 0xfffb00c0 /* byte access */ +#define AV530_IOFUSE_LAN 0x02 +#define AV530_IOFUSE_SCSI 0x01 + +/* + * PIT and RTC + */ + +#define AV530_PIT0_CNT 0xfff8f004 +#define AV530_PIT1_CNT 0xfff8f008 +#define AV530_PIT2_CNT 0xfff8f010 +#define AV530_PIT3_CNT 0xfff8f020 +#define AV530_PIT0_CS 0xfff8f044 +#define AV530_PIT1_CS 0xfff8f048 +#define AV530_PIT2_CS 0xfff8f050 +#define AV530_PIT3_CS 0xfff8f060 +#define AV530_PIT_CMD_ALL 0xfff8f07c +#define AV530_PIT_CTEN 0x00000008 +#define AV530_PIT_TEST 0x00000004 +#define AV530_PIT_IACK 0x00000002 +#define AV530_PIT_RESET 0x00000001 + +#define AV530_RTC_CNT 0xfff8f084 +#define AV530_RTC_CS 0xfff8f088 +#define AV530_RTC_IACK 0x00000002 +#define AV530_RTC_RESET 0x00000001 + +/* + * Onboard device addresses + */ + +#define AV530_SCSI1 0xfffb0000 +#define AV530_SCSI2 0xfffb0080 +#define AV530_LAN1 0xfffb00c0 +#define AV530_LAN2 0xfffb0140 + /* * CMMU addresses */ diff --git a/sys/arch/aviion/include/avcommon.h b/sys/arch/aviion/include/avcommon.h index f2a7f5b4e41..d2f31566634 100644 --- a/sys/arch/aviion/include/avcommon.h +++ b/sys/arch/aviion/include/avcommon.h @@ -1,4 +1,4 @@ -/* $OpenBSD: avcommon.h,v 1.4 2007/12/19 22:05:06 miod Exp $ */ +/* $OpenBSD: avcommon.h,v 1.5 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -62,9 +62,6 @@ #define AV_IST 0xfff84040 /* interrupt status register */ -#define ISR_GET_CURRENT_MASK(cpu) \ - (*(volatile u_int *)AV_IST & int_mask_reg[cpu]) - #define AV_ISTATE 0xfff84088 /* HW interrupt status */ #define AV_CLRINT 0xfff8408c /* reset HW interrupt */ @@ -122,65 +119,13 @@ #define VTO128US 0x10 /* 128 usec */ #define VTODISABLE 0x18 /* disabled */ -/* these are the various Z8536 CIO counter/timer registers */ +/* Z8536 counter/timer register (not found on all models) */ #define CIO_BASE 0xfff83000 #define CIO_PORTC 0xfff83000 #define CIO_PORTB 0xfff83004 #define CIO_PORTA 0xfff83008 #define CIO_CTRL 0xfff8300c -#define CIO_MICR 0x00 /* Master interrupt control register */ -#define CIO_MICR_MIE 0x80 -#define CIO_MICR_DLC 0x40 -#define CIO_MICR_NV 0x20 -#define CIO_MICR_PAVIS 0x10 -#define CIO_MICR_PBVIS 0x08 -#define CIO_MICR_CTVIS 0x04 -#define CIO_MICR_RJA 0x02 -#define CIO_MICR_RESET 0x01 - -#define CIO_MCCR 0x01 /* Master config control register */ -#define CIO_MCCR_PBE 0x80 -#define CIO_MCCR_CT1E 0x40 -#define CIO_MCCR_CT2E 0x20 -#define CIO_MCCR_CT3E 0x10 -#define CIO_MCCR_PLC 0x08 -#define CIO_MCCR_PAE 0x04 - -#define CIO_CTMS1 0x1c /* Counter/timer mode specification #1 */ -#define CIO_CTMS2 0x1d /* Counter/timer mode specification #2 */ -#define CIO_CTMS3 0x1e /* Counter/timer mode specification #3 */ -#define CIO_CTMS_CSC 0x80 /* Continuous Single Cycle */ -#define CIO_CTMS_EOE 0x40 /* External Output Enable */ -#define CIO_CTMS_ECE 0x20 /* External Count Enable */ -#define CIO_CTMS_ETE 0x10 /* External Trigger Enable */ -#define CIO_CTMS_EGE 0x08 /* External Gate Enable */ -#define CIO_CTMS_REB 0x04 /* Retrigger Enable Bit */ -#define CIO_CTMS_PO 0x00 /* Pulse Output */ -#define CIO_CTMS_OSO 0x01 /* One Shot Output */ -#define CIO_CTMS_SWO 0x02 /* Square Wave Output */ - -#define CIO_IVR 0x04 /* Interrupt vector register */ - -#define CIO_CSR1 0x0a /* Command and status register CTC #1 */ -#define CIO_CSR2 0x0b /* Command and status register CTC #2 */ -#define CIO_CSR3 0x0c /* Command and status register CTC #3 */ - -#define CIO_CT1MSB 0x16 /* CTC #1 Timer constant - MSB */ -#define CIO_CT1LSB 0x17 /* CTC #1 Timer constant - LSB */ -#define CIO_CT2MSB 0x18 /* CTC #2 Timer constant - MSB */ -#define CIO_CT2LSB 0x19 /* CTC #2 Timer constant - LSB */ -#define CIO_CT3MSB 0x1a /* CTC #3 Timer constant - MSB */ -#define CIO_CT3LSB 0x1b /* CTC #3 Timer constant - LSB */ -#define CIO_PDCA 0x23 /* Port A data direction control */ -#define CIO_PDCB 0x2b /* Port B data direction control */ - -#define CIO_GCB 0x04 /* CTC Gate command bit */ -#define CIO_TCB 0x02 /* CTC Trigger command bit */ -#define CIO_IE 0xc0 /* CTC Interrupt enable (set) */ -#define CIO_CIP 0x20 /* CTC Clear interrupt pending */ -#define CIO_IP 0x20 /* CTC Interrupt pending */ - #define CONSOLE_DART_BASE 0xfff82000 #if defined(_KERNEL) && !defined(_LOCORE) diff --git a/sys/arch/aviion/include/board.h b/sys/arch/aviion/include/board.h index a9975f6ca31..2e894275dee 100644 --- a/sys/arch/aviion/include/board.h +++ b/sys/arch/aviion/include/board.h @@ -1,4 +1,4 @@ -/* $OpenBSD: board.h,v 1.5 2010/04/18 22:04:39 miod Exp $ */ +/* $OpenBSD: board.h,v 1.6 2010/04/21 19:33:47 miod Exp $ */ /* * Copyright (c) 2006, 2007, Miodrag Vallat * @@ -31,25 +31,25 @@ #include <machine/pmap_table.h> +struct vme_range; + struct board { - const char *descr; - void (*bootstrap)(void); - vaddr_t (*memsize)(void); - void (*startup)(void); + const char *descr; + void (*bootstrap)(void); + vaddr_t (*memsize)(void); + void (*startup)(void); - void (*intr)(struct trapframe *); - void (*init_clocks)(void); - u_int (*getipl)(void); - u_int (*setipl)(u_int); - u_int (*raiseipl)(u_int); + void (*intr)(struct trapframe *); + void (*init_clocks)(void); + u_int (*getipl)(void); + u_int (*setipl)(u_int); + u_int (*raiseipl)(u_int); - u_int64_t (*intsrc)(int); + u_int64_t (*intsrc)(int); - pmap_table_t ptable; + pmap_table_t ptable; - vaddr_t vme16_base, vme16_start, vme16_end; - vaddr_t vme24_base, vme24_start, vme24_end; - vaddr_t vme32_base, vme32_start1, vme32_end1, vme32_start2, vme32_end2; + const struct vme_range *vme_ranges; }; #define md_interrupt_func(f) platform->intr(f) @@ -80,21 +80,27 @@ DECLARE_BOARD(6280); #define INTSRC_ABORT 1 /* abort button */ #define INTSRC_ACFAIL 2 /* AC failure */ #define INTSRC_SYSFAIL 3 /* system failure */ -#define INTSRC_CIO 4 /* Z8536 */ +#define INTSRC_CLOCK 4 /* clock chip */ #define INTSRC_DUART1 5 /* console MC68692 */ #define INTSRC_DUART2 6 /* secondary MC68692 */ #define INTSRC_ETHERNET1 7 /* first on-board Ethernet */ #define INTSRC_ETHERNET2 8 /* second on-board Ethernet */ #define INTSRC_SCSI1 9 /* first on-board SCSI controller */ #define INTSRC_SCSI2 10 /* second on-board SCSI controller */ -#define INTSRC_VME 11 /* seven VME interrupt levels */ +#define NINTSRC_SYSCON 11 /* total number of non-VME sources */ +#define INTSRC_VME(lvl) (NINTSRC_SYSCON + (lvl) - 1) /* seven VME levels */ + +#define IS_VME_INTSRC(intsrc) ((intsrc) >= NINTSRC_SYSCON) +#define VME_INTSRC_LEVEL(intsrc) ((intsrc) - NINTSRC_SYSCON + 1) void intsrc_enable(u_int, int); void intsrc_disable(u_int); +extern int32_t cpuid, sysid; extern const struct board *platform;/* just to have people confuse both names */ void cio_init_clocks(void); +void rtc_init_clocks(void); #endif /* _LOCORE */ #endif /* _MACHINE_BOARD_H_ */ |