SH4 support. my target is HITACHI PERSONA HPW650PA

This commit is contained in:
uch 2002-02-11 17:32:35 +00:00
parent dca6104509
commit 4dff96d2d9
10 changed files with 456 additions and 499 deletions

View File

@ -0,0 +1,82 @@
# $NetBSD: HPW650PA,v 1.1 2002/02/11 17:32:35 uch Exp $
#
# HITACHI PERSONA HPW650PA
#
include "arch/hpcsh/conf/std.hpcsh"
maxusers 32 # estimated number of users
options KLOADER_KERNEL_PATH="\"/netbsd\""
options KLOADER_DEBUG
options SH7750
options SH4
options INTERRUPT_MONITOR
options DDB # in-kernel debugger
options DIAGNOSTIC # extra kernel debugging checks
options DEBUG # extra kernel debugging support
options KTRACE # system call tracing support
options MSGBUFSIZE=65534
options PIPE_SOCKETPAIR # smaller, but slower pipe(2)
# Executable format options
options EXEC_COFF # 32-bit COFF executables
options EXEC_ELF32 # 32-bit ELF executables
# File systems
file-system FFS # UFS
file-system MSDOSFS # MS-DOS file system
file-system NFS # Sun NFS-compatible filesystem client
# Networking options
options INET # IP + ICMP + TCP + UDP
options INET6 # IPV6
options NFS_BOOT_DHCP
# Kernel root file system and dump configuration.
config netbsd root on ? type ?
options WSEMUL_VT100
options WSDISPLAY_DEFAULTSCREENS=1
options FONT_VT220L8x10
options WS_KERNEL_FG=WSCOL_BROWN
options WS_KERNEL_BG=WSCOL_BLUE
#
# Device configuration
#
mainbus0 at root
bivideo* at mainbus0
hpcfb* at bivideo?
wsdisplay* at hpcfb?
shb0 at mainbus?
hd64465if* at shb0 irq 11
com* at hd64465if?
hd64465pcmcia* at hd64465if?
# PCMCIA bus support
pcmcia* at hd64465pcmcia? controller ? socket ?
# PCMCIA network interfaces
ne* at pcmcia? function ? # NE2000-compatible Ethernet
ukphy* at mii? phy ? # generic unknown PHYs
# PCMCIA IDE disk
wdc* at pcmcia? function ?
wd* at wdc? channel ? drive ? flags 0x0000
# Pseudo-Devices
pseudo-device biconsdev 1 # build-in console device
pseudo-device pty # pseudo-terminals
pseudo-device bpfilter 1 # Berkeley packet filter
pseudo-device loop # network loopback
pseudo-device gif 1 # IPv[46] over IPv[46] tunnel (RFC1933)
pseudo-device rnd # /dev/random and in-kernel generator

View File

@ -1,4 +1,4 @@
# $NetBSD: files.hpcsh,v 1.16 2002/01/29 18:44:25 uch Exp $
# $NetBSD: files.hpcsh,v 1.17 2002/02/11 17:32:35 uch Exp $
#
maxpartitions 8
@ -15,6 +15,7 @@ file arch/hpcsh/hpcsh/clock.c
file arch/hpcsh/hpcsh/console.c
file arch/hpcsh/hpcsh/autoconf.c
file arch/hpcsh/hpcsh/bus_space.c
#file arch/hpcsh/hpcsh/bus_dma.c
file arch/hpcsh/hpcsh/procfs_machdep.c procfs
file arch/hpc/hpc/kloader.c
@ -93,11 +94,25 @@ attach hd64461video at hd64461if
file arch/hpcsh/dev/hd64461/hd64461video.c hd64461video needs-flag
file dev/hpc/video_subr.c hd64461video
# network devices MII bus
include "dev/mii/files.mii"
#
# HD64465
#
define hd64465if {}
device hd64465if: hd64465if
attach hd64465if at shb
file arch/hpcsh/dev/hd64465/hd64465.c hd64465if
#
# Workstation Console
#
attach com at hd64465if with hd64465uart
file arch/hpcsh/dev/hd64465/hd64465uart.c hd64465uart
device hd64465pcmcia: pcmciabus
attach hd64465pcmcia at hd64465if
file arch/hpcsh/dev/hd64465/hd64465pcmcia.c hd64465pcmcia
#attach ohci at hd64465if with hd64465ohci
#file arch/hpcsh/dev/hd64465/hd64465ohci.c hd64465ohci
include "dev/mii/files.mii"
include "dev/usb/files.usb"
include "dev/wscons/files.wscons"

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock.c,v 1.4 2002/02/01 17:52:55 uch Exp $ */
/* $NetBSD: clock.c,v 1.5 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -44,6 +44,7 @@
#include <sh3/tmureg.h>
#include <machine/shbvar.h>
#include <machine/debug.h>
#include <hpcsh/hpcsh/clockvar.h>
@ -139,6 +140,9 @@ clock_init()
DELAY_LOOP(10000000);
t0 = TMU_ELAPSED(0);
__cpuclock = (100000000 / t0) * RTC_CLOCK;
#ifdef SH4
__cpuclock >>= 1; /* two-issue */
#endif
__cnt_delay = (RTC_CLOCK * 10) / t0;
/*
@ -242,6 +246,7 @@ clockintr(void *arg) /* trap frame */
/* clear underflow status */
SHREG_TCR1 &= ~TCR_UNF;
__dbg_heart_beat(HEART_BEAT_WHITE);
hardclock(arg);
return (1);

View File

@ -1,4 +1,4 @@
/* $NetBSD: console.c,v 1.6 2002/01/27 05:15:37 uch Exp $ */
/* $NetBSD: console.c,v 1.7 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@ -36,14 +36,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_kgdb.h"
#include "biconsdev.h"
#include "hpcfb.h"
#include "pfckbd.h"
#include "sci.h"
#include "scif.h"
#include "com.h"
#include "hd64461video.h"
#include "wskbd.h"
#include "pfckbd.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
@ -51,6 +55,12 @@
#include <machine/bootinfo.h>
#if !defined(NBICONSDEV) || !defined(NHPCFB) || !defined(NPFCKBD) || \
!defined(NHD64461VIDEO) || !defined(NSCI) || !defined(NSCIF) || \
!defined(NCOM)
#error
#endif
#if NBICONSDEV > 0
#include <dev/hpc/biconsvar.h>
#include <dev/hpc/bicons.h>
@ -61,6 +71,7 @@
#include <dev/rasops/rasops.h>
#include <dev/hpc/hpcfbvar.h>
#endif
#if NPFCKBD > 0
#include <hpcsh/dev/pfckbdvar.h>
#endif
@ -82,6 +93,7 @@ cons_decl(bicons);
#if NHD64461VIDEO > 0
cons_decl(hd64461video_);
#if NWSKBD > 0
#include <dev/wscons/wskbdvar.h>
#define hd64461video_cngetc wskbd_cngetc
#else
int
@ -110,19 +122,27 @@ struct consdev constab[] = {
#if NSCIF > 0
cons_init(scif),
#endif
#if NHD64461IF > 0 && NCOM > 0
#if NCOM > 0
cons_init(com),
#endif
{ 0 } /* terminator */
};
#define CN_ENABLE(x) set_console(x ## cnputc, x ## cnprobe)
#ifdef KGDB
#ifndef KGDB_DEVNAME
#define KGDB_DEVNAME "nodev"
#endif
const char kgdb_devname[] = KGDB_DEVNAME;
#endif
static int initialized;
static int attach_kbd = 1;
static int attach_kbd __attribute__((__unused__)) = 1;
static void set_console(void (*)(dev_t, int), void (*)(struct consdev *));
static void disable_console(void);
static void cn_nonprobe(struct consdev *);
#if NBICONSDEV > 0
static void enable_bicons(void);
#endif
void
consinit()
@ -155,20 +175,24 @@ consinit()
CN_ENABLE(scif);
#endif
break;
case BI_CNUSE_HD64465COM:
/* FALLTHROUGH */
case BI_CNUSE_HD64461COM:
#if NHD64461IF > 0 && NCOM > 0
#if NCOM > 0
CN_ENABLE(com);
#endif
break;
}
#if NBICONSDEV > 0
if (!initialized) /* use builtin console instead */
if (!initialized) { /* use builtin console instead */
enable_bicons();
}
#endif
if (initialized)
if (initialized) {
cninit();
}
#if NPFCKBD > 0
if (attach_kbd)
@ -208,6 +232,7 @@ disable_console()
static void
cn_nonprobe(struct consdev *cp)
{
cp->cn_pri = CN_DEAD;
}
@ -215,9 +240,10 @@ cn_nonprobe(struct consdev *cp)
static void
enable_bicons()
{
bootinfo->bi_cnuse = BI_CNUSE_BUILTIN;
bicons_set_priority(CN_INTERNAL);
CN_ENABLE(bicons);
attach_kbd = 1;
}
#endif
#endif /* NBICONSDEV > 0 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: kloader_machdep.c,v 1.2 2002/02/07 17:05:22 uch Exp $ */
/* $NetBSD: kloader_machdep.c,v 1.3 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@ -37,56 +37,82 @@
#include <sys/systm.h>
#include <sh3/mmureg.h>
#include <sh3/cache.h>
#include <sh3/cache_sh3.h>
#include <sh3/cache_sh4.h>
#include <machine/kloader.h>
#define SH3_CCA 0xf0000000
#define SH7709A_CACHE_LINESZ 16
#define SH7709A_CACHE_ENTRY 256
#define SH7709A_CACHE_WAY 4
#define SH7709A_CACHE_SIZE \
(SH7709A_CACHE_LINESZ * SH7709A_CACHE_ENTRY * SH7709A_CACHE_WAY)
#define SH7709A_CACHE_ENTRY_SHIFT 4
#define SH7709A_CACHE_ENTRY_MASK 0x00000ff0
#define SH7709A_CACHE_WAY_SHIFT 12
#define SH7709A_CACHE_WAY_MASK 0x00003000
#define _SH7709A_CACHE_FLUSH() \
do { \
u_int32_t __e, __w, __wa, __a; \
/*
* 2nd-bootloader. Make sure that PIC and its size is lower than page size.
*/
#define KLOADER_SH_BOOT(cpu, product) \
void \
kloader_sh ## cpu ## _boot(struct kloader_bootinfo *kbi, \
struct kloader_page_tag *p) \
{ \
int tmp; \
\
for (__w = 0; __w < SH7709A_CACHE_WAY; __w++) { \
__wa = SH3_CCA | __w << SH7709A_CACHE_WAY_SHIFT; \
for (__e = 0; __e < SH7709A_CACHE_ENTRY; __e++) { \
__a = __wa |(__e << SH7709A_CACHE_ENTRY_SHIFT); \
(*(__volatile__ u_int32_t *)__a) &= ~0x3; \
} \
} \
} while (/*CONSTCOND*/0)
/* Disable interrupt. block exception. */ \
__asm__ __volatile__( \
"stc sr, %1;" \
"or %0, %1;" \
"ldc %1, sr" : : "r"(0x500000f0), "r"(tmp)); \
\
/* Now I run on P1, TLB flush. and disable. */ \
SHREG_MMUCR = MMUCR_TF; \
\
do { \
u_int32_t *dst =(u_int32_t *)p->dst; \
u_int32_t *src =(u_int32_t *)p->src; \
u_int32_t sz = p->sz / sizeof (int); \
while (sz--) \
*dst++ = *src++; \
} while ((p = (struct kloader_page_tag *)p->next) != 0); \
\
SH ## product ## _CACHE_FLUSH(); \
\
/* jump to kernel entry. */ \
__asm__ __volatile__( \
"mov %0, r4;" \
"mov %1, r5;" \
"jmp @%3;" \
"mov %2, r6;" \
: : \
"r"(kbi->argc), \
"r"(kbi->argv), \
"r"(&kbi->bootinfo), \
"r"(kbi->entry)); \
/* NOTREACHED */ \
}
void kloader_sh3_jump(kloader_bootfunc_t *, vaddr_t,
void kloader_sh_jump(kloader_bootfunc_t *, vaddr_t,
struct kloader_bootinfo *, struct kloader_page_tag *);
kloader_bootfunc_t kloader_sh3_boot;
kloader_bootfunc_t kloader_sh4_boot;
struct kloader_ops kloader_sh3_ops = {
.jump = kloader_sh3_jump,
.boot = kloader_sh3_boot
struct kloader_ops kloader_sh_ops = {
.jump = kloader_sh_jump,
.boot = 0
};
void
kloader_reboot_setup(const char *filename)
{
__kloader_reboot_setup(&kloader_sh3_ops, filename);
#ifdef SH4
kloader_sh_ops.boot = kloader_sh4_boot;
#else
kloader_sh_ops.boot = kloader_sh3_boot;
#endif
__kloader_reboot_setup(&kloader_sh_ops, filename);
}
void
kloader_sh3_jump(kloader_bootfunc_t func, vaddr_t sp,
kloader_sh_jump(kloader_bootfunc_t func, vaddr_t sp,
struct kloader_bootinfo *info, struct kloader_page_tag *tag)
{
_SH7709A_CACHE_FLUSH();
sh_icache_sync_all(); /* also flush d-cache */
__asm__ __volatile__(
"mov %0, r4;"
@ -97,43 +123,5 @@ kloader_sh3_jump(kloader_bootfunc_t func, vaddr_t sp,
/* NOTREACHED */
}
/*
* 2nd-bootloader. Make sure that PIC and its size is lower than page size.
*/
void
kloader_sh3_boot(struct kloader_bootinfo *kbi, struct kloader_page_tag *p)
{
int tmp;
/* Disable interrupt. block exception.(TLB exception don't occur) */
__asm__ __volatile__(
"stc sr, %1;"
"or %0, %1;"
"ldc %1, sr" : : "r"(0x500000f0), "r"(tmp));
/* Now I run on P1, TLB flush. and disable. */
SHREG_MMUCR = MMUCR_TF;
do {
u_int32_t *dst =(u_int32_t *)p->dst;
u_int32_t *src =(u_int32_t *)p->src;
u_int32_t sz = p->sz / sizeof (int);
while (sz--)
*dst++ = *src++;
} while ((p = (struct kloader_page_tag *)p->next) != 0);
_SH7709A_CACHE_FLUSH();
/* jump to kernel entry. */
__asm__ __volatile__(
"mov %0, r4;"
"mov %1, r5;"
"jmp @%3;"
"mov %2, r6;"
: :
"r"(kbi->argc),
"r"(kbi->argv),
"r"(&kbi->bootinfo),
"r"(kbi->entry));
/* NOTREACHED */
}
KLOADER_SH_BOOT(3, 7709A)
KLOADER_SH_BOOT(4, 7750)

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.s,v 1.10 2001/10/27 03:46:20 msaitoh Exp $ */
/* $NetBSD: locore.s,v 1.11 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1997
@ -415,72 +415,6 @@ XXLwhichqs:
.long _C_LABEL(sched_whichqs)
#define PUSHALL \
mov.l r0, @-r15 ; \
mov.l r1, @-r15 ; \
mov.l r2, @-r15 ; \
mov.l r3, @-r15 ; \
mov.l r4, @-r15 ; \
mov.l r5, @-r15 ; \
mov.l r6, @-r15 ; \
mov.l r7, @-r15 ; \
mov.l r8, @-r15 ; \
mov.l r9, @-r15 ; \
mov.l r10, @-r15 ; \
mov.l r11, @-r15 ; \
mov.l r12, @-r15 ; \
mov.l r13, @-r15 ; \
mov.l r14, @-r15
#define POPALL \
mov.l @r15+, r14 ; \
mov.l @r15+, r13 ; \
mov.l @r15+, r12 ; \
mov.l @r15+, r11 ; \
mov.l @r15+, r10 ; \
mov.l @r15+, r9 ; \
mov.l @r15+, r8 ; \
mov.l @r15+, r7 ; \
mov.l @r15+, r6 ; \
mov.l @r15+, r5 ; \
mov.l @r15+, r4 ; \
mov.l @r15+, r3 ; \
mov.l @r15+, r2 ; \
mov.l @r15+, r1 ; \
mov.l @r15+, r0
#define PUSHALLBUTR0 \
mov.l r1, @-r15 ; \
mov.l r2, @-r15 ; \
mov.l r3, @-r15 ; \
mov.l r4, @-r15 ; \
mov.l r5, @-r15 ; \
mov.l r6, @-r15 ; \
mov.l r7, @-r15 ; \
mov.l r8, @-r15 ; \
mov.l r9, @-r15 ; \
mov.l r10, @-r15 ; \
mov.l r11, @-r15 ; \
mov.l r12, @-r15 ; \
mov.l r13, @-r15 ; \
mov.l r14, @-r15
#define POPALLBUTR0 \
mov.l @r15+, r14 ; \
mov.l @r15+, r13 ; \
mov.l @r15+, r12 ; \
mov.l @r15+, r11 ; \
mov.l @r15+, r10 ; \
mov.l @r15+, r9 ; \
mov.l @r15+, r8 ; \
mov.l @r15+, r7 ; \
mov.l @r15+, r6 ; \
mov.l @r15+, r5 ; \
mov.l @r15+, r4 ; \
mov.l @r15+, r3 ; \
mov.l @r15+, r2 ; \
mov.l @r15+, r1
#define DIAGNOSTIC 1
#ifdef DIAGNOSTIC
switch_error:
@ -1349,7 +1283,7 @@ XL_KCSAREA: .long 0x80000000
XXL_SHREG_TTB: .long SHREG_TTB
XL_P2AREA: .long 0xa0000000
#ifdef SH4
XL_cacheflush: .long _C_LABEL(sh4_cache_flush)
XL_cacheflush: .long _C_LABEL(sh4_icache_sync_all)
#endif
Xrecurse:

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.20 2002/02/07 17:06:00 uch Exp $ */
/* $NetBSD: machdep.c,v 1.21 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@ -36,6 +36,7 @@
#include "opt_md.h"
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_syscall_debug.h"
#include "fs_mfs.h"
#include "fs_nfs.h"
@ -55,7 +56,11 @@
#include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */
#ifdef DDB
#ifdef KGDB
#include <sys/kgdb.h>
#endif
#if defined(DDB) || defined(KGDB)
#include <machine/db_machdep.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
@ -64,7 +69,7 @@
#endif
#define ELFSIZE DB_ELFSIZE
#include <sys/exec_elf.h>
#endif
#endif /* DDB || KGDB */
#include <dev/cons.h> /* consdev */
#include <dev/md.h>
@ -76,6 +81,7 @@
#include <machine/kloader.h>
#include <hpcsh/hpcsh/clockvar.h>
#include <hpcsh/dev/hd64465/hd64465var.h>
#include <sh3/pclock.h>
#include <sh3/intcreg.h>
@ -196,9 +202,13 @@ machine_startup(int argc, char *argv[], struct bootinfo *bi)
SHREG_IPRA = 0;
SHREG_IPRB = 0;
SHREG_IPRC = 0;
#if defined(SH7709) || defined(SH7709A) //XXX
SHREG_IPRD = 0;
SHREG_IPRE = 0;
#endif
#if defined(SH4) //XXX
hd64465_intr_disable();
#endif
/* start to determine heap area */
kernend = (vaddr_t)sh3_round_page(end + symbolsize);
@ -250,8 +260,8 @@ machine_startup(int argc, char *argv[], struct bootinfo *bi)
*/
/* serial console requires PCLOCK. estimate here */
clock_init();
sh3_pclock = clock_get_pclock();
sh3_pclock = clock_get_pclock();
if (bootinfo->magic == BOOTINFO_MAGIC) {
platid.dw.dw0 = bootinfo->platid_cpu;
platid.dw.dw1 = bootinfo->platid_machine;
@ -263,7 +273,7 @@ machine_startup(int argc, char *argv[], struct bootinfo *bi)
uvm_setpagesize(); /* default page size (4KB) */
/* find memory cluster */
/* find memory cluster (# of pages) */
physmem = mem_cluster_init(SH3_P1SEG_TO_PHYS(kernend));
nkpde = ptoa(physmem) >> (PDSHIFT - 1);
DPRINTF(("physmem= %d, nkpde = %d\n", physmem, nkpde));
@ -334,10 +344,16 @@ machine_startup(int argc, char *argv[], struct bootinfo *bi)
if (symbolsize) {
ddb_init(symbolsize, &end, end + symbolsize);
DPRINTF(("symbol size = %d byte\n", symbolsize));
if (boothowto & RB_KDB)
Debugger();
}
#endif
if (boothowto & RB_KDB)
Debugger();
#endif /* DDB */
#ifdef KGDB
if (boothowto & RB_KDB) {
kgdb_debug_init = 1;
kgdb_connect(1);
}
#endif /* KGDB */
/* setup proc0 stack */
proc0_sp = (vaddr_t)p + NBPG + USPACE - 16 - sizeof(struct trapframe);
@ -369,23 +385,16 @@ machine_startup(int argc, char *argv[], struct bootinfo *bi)
void
cpu_startup()
{
platid_t cpu;
int cpuclock;
cpuclock = clock_get_cpuclock();
sh3_startup();
#define CPUIDMATCH(p) \
platid_match(&platid, &platid_mask_CPU_##p)
if (CPUIDMATCH(SH_3_7709))
sprintf(cpu_model, "%s Hitachi SH7709",
platid_name(&platid));
else if (CPUIDMATCH(SH_3_7709A))
sprintf(cpu_model, "%s Hitachi SH7709A",
platid_name(&platid));
else
sprintf(cpu_model, "%s Hitachi SH product unknown",
platid_name(&platid));
memcpy(&cpu, &platid, sizeof(platid_t));
cpu.dw.dw1 = 0; /* clear platform */
sprintf(cpu_model, "[%s] %s", platid_name(&platid), platid_name(&cpu));
#define MHZ(x) ((x) / 1000000), (((x) % 1000000) / 1000)
printf("%s %d.%02d MHz PCLOCK %d.%02d MHz\n", cpu_model,
@ -476,6 +485,9 @@ cpu_reboot(int howto, char *bootstr)
#endif
}
#ifdef SH4 //XXX
hd64465_intr_reboot();
#endif
goto *(u_int32_t *)0xa0000000;
while (1)
;
@ -560,7 +572,7 @@ mem_cluster_load()
DPRINTF(("loading 0x%lx,0x%lx\n", start, size));
start = SH3_PHYS_TO_P1SEG(start);
memset((void *)start, 0, size);
cacheflush();
sh_dcache_wbinv_all();
end = atop(start + size);
start = atop(start);
uvm_page_physload(start, end, start, end, VM_FREELIST_DEFAULT);
@ -574,7 +586,6 @@ mem_cluster_load()
start = SH3_PHYS_TO_P1SEG(start);
end = start + size;
memset((void *)start, 0, size);
cacheflush();
avail_start = start;
avail_end = end;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mainbus.c,v 1.5 2001/03/20 16:05:43 uch Exp $ */
/* $NetBSD: mainbus.c,v 1.6 2002/02/11 17:32:35 uch Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -55,12 +55,14 @@ struct cfattach mainbus_ca = {
static int
mainbus_match(struct device *parent, struct cfdata *cf, void *aux)
{
return (1);
}
static void
mainbus_attach(struct device *parent, struct device *self, void *aux)
{
printf("\n");
config_search(mainbus_search, self, 0);
@ -86,5 +88,6 @@ mainbus_search(struct device *parent, struct cfdata *cf, void *aux)
static int
mainbus_print(void *aux, const char *pnp)
{
return (pnp ? QUIET : UNCONF);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: shb.c,v 1.7 2002/01/29 18:53:02 uch Exp $ */
/* $NetBSD: shb.c,v 1.8 2002/02/11 17:32:36 uch Exp $ */
/*-
* Copyright (c) 1993, 1994 Charles Hannum. All rights reserved.
@ -31,46 +31,80 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <machine/autoconf.h>
#include <sh3/cpufunc.h>
#include <net/netisr.h>
#include <sh3/intcreg.h>
#include <sh3/trapreg.h>
#include <machine/shbvar.h>
#include <net/netisr.h>
#include <machine/shbvar.h>
#include <machine/autoconf.h>
#include <machine/debug.h>
int shbmatch __P((struct device *, struct cfdata *, void *));
void shbattach __P((struct device *, struct device *, void *));
int shbprint __P((void *, const char *));
void intr_calculatemasks __P((void));
int fakeintr __P((void *));
void *shb_intr_establish __P((int irq, int type,
int level, int (*ih_fun)(void *), void *ih_arg));
int intrhandler __P((int, int, int, int, struct trapframe));
int check_ipending __P((int, int, int, int, struct trapframe));
void mask_irq __P((int));
void unmask_irq __P((int));
void Xsoftserial __P((void));
void Xsoftnet __P((void));
void Xsoftclock __P((void));
void init_soft_intr_handler __P((void));
#include <hpcsh/dev/hd64465/hd64465var.h>
int shbmatch(struct device *, struct cfdata *, void *);
void shbattach(struct device *, struct device *, void *);
int shbprint(void *, const char *);
int shbsearch(struct device *, struct cfdata *, void *);
void intr_calculatemasks(void);
int fakeintr(void *);
void *shb_intr_establish(int, int, int, int (*_fun)(void *), void *);
int intrhandler(int, int, int, int, struct trapframe);
int check_ipending(int, int, int, int, struct trapframe);
void mask_irq(int);
void unmask_irq(int);
void Xsoftserial(void);
void Xsoftnet(void);
void Xsoftclock(void);
void __sh3_intr_debug_hook(void);
void __set_intr_level(u_int32_t);
static int __nih;
static struct intrhand __intr_handler[ICU_LEN];
int intrmask[ICU_LEN], intrlevel[ICU_LEN];
struct intrhand *intrhand[ICU_LEN];
struct cfattach shb_ca = {
sizeof(struct shb_softc), shbmatch, shbattach
sizeof(struct device), shbmatch, shbattach
};
int shbsearch __P((struct device *, struct cfdata *, void *));
#define SH_SR_MD 0x40000000
#define SH_SR_RB 0x20000000
#define SH_SR_BL 0x10000000
#define SH_SR_FD 0x00008000
#define SH_SR_M 0x00000200
#define SH_SR_IMASK 0x000000f0
#define SH_SR_IMASK_SHIFT 4
#define SH_SR_S 0x00000002
#define SH_SR_T 0x00000001
void
__set_intr_level(u_int32_t m)
{
u_int32_t sr;
m &= SH_SR_IMASK;
/* set new interrupt priority level */
__asm__ __volatile__("stc sr, %0" : "=r"(sr));
sr &= ~SH_SR_IMASK;
sr |= m;
__asm__ __volatile__("ldc %0, sr" :: "r"(sr));
}
void
__sh3_intr_debug_hook()
{
u_int32_t intevt = *(volatile u_int32_t *)0xffffffd8;
u_int32_t intevt2 = *(volatile u_int32_t *)0xa4000000;
if (intevt < 0xf00 && intevt != 0x420)
printf("INTEVT=%08x INTEVT2=%08x\n", intevt, intevt2);
}
int
shbmatch(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
shbmatch(struct device *parent, struct cfdata *cf, void *aux)
{
struct mainbus_attach_args *ma = aux;
@ -81,102 +115,51 @@ shbmatch(parent, cf, aux)
}
void
shbattach(parent, self, aux)
struct device *parent, *self;
void *aux;
shbattach(struct device *parent, struct device *self, void *aux)
{
struct shb_softc *sc = (struct shb_softc *)self;
printf("\n");
sc->sc_iot = 0;
sc->sc_memt = 0;
TAILQ_INIT(&sc->sc_subdevs);
config_search(shbsearch, self, NULL);
init_soft_intr_handler();
#include "sci.h"
#include "scif.h"
#include "com.h"
#if (NSCI > 0) || (NSCIF > 0) || (NCOM > 0)
shb_intr_establish(SIR_SERIAL, IST_LEVEL, IPL_SOFTSERIAL,
(int (*) (void *))Xsoftserial, NULL);
#endif
shb_intr_establish(SIR_NET, IST_LEVEL, IPL_SOFTNET,
(int (*) (void *))Xsoftnet, NULL);
shb_intr_establish(SIR_CLOCK, IST_LEVEL, IPL_SOFTCLOCK,
(int (*) (void *))Xsoftclock, NULL);
}
int
shbprint(aux, isa)
void *aux;
const char *isa;
shbprint(void *aux, const char *isa)
{
struct shb_attach_args *ia = aux;
if (ia->ia_iosize)
printf(" port 0x%x", ia->ia_iobase);
if (ia->ia_iosize > 1)
printf("-0x%x", ia->ia_iobase + ia->ia_iosize - 1);
if (ia->ia_msize)
printf(" iomem 0x%x", ia->ia_maddr);
if (ia->ia_msize > 1)
printf("-0x%x", ia->ia_maddr + ia->ia_msize - 1);
if (ia->ia_irq != IRQUNK)
printf(" irq %d", ia->ia_irq);
if (ia->ia_drq != DRQUNK)
printf(" drq %d", ia->ia_drq);
if (ia->ia_drq2 != DRQUNK)
printf(" drq2 %d", ia->ia_drq2);
return (UNCONF);
}
int
shbsearch(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
shbsearch(struct device *parent, struct cfdata *cf, void *aux)
{
struct shb_softc *sc = (struct shb_softc *)parent;
struct shb_attach_args ia;
int tryagain;
do {
ia.ia_iot = sc->sc_iot;
ia.ia_memt = sc->sc_memt;
/* ia.ia_dmat = sc->sc_dmat; */
/* ia.ia_ic = sc->sc_ic; */
ia.ia_iobase = cf->cf_iobase;
ia.ia_iosize = 0x666; /* cf->cf_iosize; */
ia.ia_maddr = cf->cf_maddr;
ia.ia_msize = cf->cf_msize;
ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq;
ia.ia_drq = cf->cf_drq;
ia.ia_drq2 = cf->cf_drq2;
/* ia.ia_delaybah = sc->sc_delaybah; */
ia.ia_irq = cf->cf_irq;
tryagain = 0;
if ((*cf->cf_attach->ca_match)(parent, cf, &ia) > 0) {
config_attach(parent, cf, &ia, shbprint);
tryagain = (cf->cf_fstate == FSTATE_STAR);
}
} while (tryagain);
if ((*cf->cf_attach->ca_match)(parent, cf, &ia) > 0)
config_attach(parent, cf, &ia, shbprint);
return (0);
}
char *
shb_intr_typename(type)
int type;
{
switch (type) {
case IST_NONE :
return ("none");
case IST_PULSE:
return ("pulsed");
case IST_EDGE:
return ("edge-triggered");
case IST_LEVEL:
return ("level-triggered");
default:
panic("shb_intr_typename: invalid type %d", type);
}
}
int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
struct intrhand *intrhand[ICU_LEN];
/*
* Recalculate the interrupt masks from scratch.
* We could code special registry and deregistry versions of this function that
@ -262,21 +245,6 @@ intr_calculatemasks()
irqs |= imask[q->ih_level];
intrmask[irq] = irqs;
}
#ifdef TODO
/* Lastly, determine which IRQs are actually in use. */
{
int irqs = 0;
for (irq = 0; irq < ICU_LEN; irq++)
if (intrhand[irq])
irqs |= 1 << irq;
if (irqs >= 0x100) /* any IRQs >= 8 in use */
irqs |= 1 << IRQ_SLAVE;
imen = ~irqs;
SET_ICUS();
}
#endif
}
/*
@ -284,42 +252,26 @@ intr_calculatemasks()
* XXX PRONE TO RACE CONDITIONS, UGLY, 'INTERESTING' INSERTION ALGORITHM.
*/
void *
shb_intr_establish(irq, type, level, ih_fun, ih_arg)
int irq;
int type;
int level;
int (*ih_fun) __P((void *));
void *ih_arg;
shb_intr_establish(int irq, int type, int level, int (*ih_fun)(void *),
void *ih_arg)
{
struct intrhand **p, *q, *ih;
static struct intrhand fakehand = {fakeintr};
int s;
/* no point in sleeping unless someone can free memory. */
ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
if (ih == NULL)
panic("shb_intr_establish: can't malloc handler info");
if (__nih == ICU_LEN)
panic("%s:: can't allocate handler info", __FUNCTION__);
ih = &__intr_handler[__nih++];
/*
* Figure out where to put the handler.
* This is O(N^2), but we want to preserve the order, and N is
* generally small.
*/
s = splhigh();
for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
;
/*
* Actually install a fake handler momentarily, since we might be doing
* this with interrupts enabled and don't want the real routine called
* until masking is set up.
*/
fakehand.ih_level = level;
*p = &fakehand;
intr_calculatemasks();
/*
* Poke the real handler in now.
*/
ih->ih_fun = ih_fun;
ih->ih_arg = ih_arg;
ih->ih_count = 0;
@ -328,9 +280,12 @@ shb_intr_establish(irq, type, level, ih_fun, ih_arg)
ih->ih_irq = irq;
*p = ih;
intr_calculatemasks();
/* unmask H/W interrupt mask register */
if (irq < SHB_MAX_HARDINTR)
unmask_irq(irq);
splx(s);
return (ih);
}
@ -343,34 +298,16 @@ fakeintr(arg)
return 0;
}
#define IRQ_BIT(irq_num) (1 << (irq_num))
/*ARGSUSED*/
int /* 1 = check ipending on return, 0 = fast intr return */
intrhandler(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* dummy param */
struct trapframe frame;
intrhandler(int p1, int p2, int p3, int p4, /* dummy param */
struct trapframe frame)
{
unsigned int irl;
struct intrhand *ih;
unsigned int irq_num;
int ocpl;
#if 0
u_int32_t intevt = *(volatile u_int32_t *)0xffffffd8;
u_int32_t intevt2 = *(volatile u_int32_t *)0xa4000000;
if (intevt < 0xf00 && intevt != 0x420)
printf("INTEVT=%08x INTEVT2=%08x\n", intevt, intevt2);
#endif
__dbg_heart_beat(HEART_BEAT_WHITE);
#if 0
printf("intr_handler:int_no %x spc %x ssr %x r15 %x curproc %x\n",
frame.tf_trapno, frame.tf_spc, frame.tf_ssr, frame.tf_r15,
(int)curproc);
#endif
irl = (unsigned int)frame.tf_trapno;
if (irl >= INTEVT_SOFT) {
@ -390,26 +327,22 @@ intrhandler(p1, p2, p3, p4, frame)
mask_irq(irq_num);
if (cpl & IRQ_BIT(irq_num)) {
ipending |= IRQ_BIT(irq_num);
return 0;
if (cpl & (1 << irq_num)) {
ipending |= (1 << irq_num);
return (0);
}
ocpl = cpl;
cpl |= intrmask[irq_num];
ih = intrhand[irq_num];
if (ih == NULL) {
/* this is stray interrupt */
cpl = ocpl;
#if 0 /* This is commented by T.Horiuchi */
unmask_irq(irq_num);
#endif
return 1;
printf("stray interrupt. INTEVT=0x%x\n", frame.tf_trapno);
return (1);
}
enable_ext_intr();
__set_intr_level(0);
while (ih) {
if (ih->ih_arg)
(*ih->ih_fun)(ih->ih_arg);
@ -417,40 +350,28 @@ intrhandler(p1, p2, p3, p4, frame)
(*ih->ih_fun)(&frame);
ih = ih->ih_next;
}
disable_ext_intr();
__set_intr_level(15);
cpl = ocpl;
unmask_irq(irq_num);
#if 0
printf("intr_handler:end\n");
#endif
return 1;
return (1);
}
int /* 1 = resume ihandler on return, 0 = go to fast intr return */
check_ipending(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* dummy param */
struct trapframe frame;
check_ipending(int p1, int p2, int p3, int p4, /* dummy param */
struct trapframe frame)
{
int ir;
int i;
int mask;
#define MASK_LEN 32
restart:
restart:
ir = (~cpl) & ipending;
if (ir == 0)
return 0;
#if 0
mask = 1;
for (i = 0; i < MASK_LEN; i++, mask <<= 1) {
if (ir & mask)
break;
}
#else
mask = 1 << IRQ_LOW;
for (i = IRQ_LOW; i <= IRQ_HIGH; i++, mask <<= 1) {
if (ir & mask)
@ -463,7 +384,6 @@ check_ipending(p1, p2, p3, p4, frame)
break;
}
}
#endif
if ((mask & ipending) == 0)
goto restart;
@ -481,21 +401,65 @@ check_ipending(p1, p2, p3, p4, frame)
return 1;
}
#ifdef SH7709A_BROKEN_IPR /* broken IPR patch */
#ifdef SH4
void
mask_irq(irq)
int irq;
{
switch (irq) {
case TMU1_IRQ:
SHREG_IPRA &= ~((15)<<8);
break;
case SCI_IRQ:
SHREG_IPRB &= ~((15)<<4);
break;
case SCIF_IRQ:
SHREG_IPRC &= ~((15)<<4);
break;
case 11:
hd64465_intr_mask();
break;
default:
if (irq < SHB_MAX_HARDINTR)
printf("masked unknown irq(%d)!\n", irq);
}
}
void
unmask_irq(irq)
int irq;
{
switch (irq) {
case TMU1_IRQ:
SHREG_IPRA |= ((15 - irq)<<8);
break;
case SCI_IRQ:
SHREG_IPRB |= ((15 - irq)<<4);
break;
case SCIF_IRQ:
SHREG_IPRC |= ((15 - irq)<<4);
break;
case 11:
hd64465_intr_unmask();
break;
default:
if (irq < SHB_MAX_HARDINTR)
printf("unmasked unknown irq(%d)!\n", irq);
}
}
#else /* SH4 */
#ifdef SH7709A_BROKEN_IPR /* broken IPR patch */
#define IPRA 0
#define IPRB 1
#define IPRC 2
#define IPRD 3
#define IPRE 4
static unsigned short ipr[ 5 ];
#endif /* SH7709A_BROKEN_IPR */
void
mask_irq(irq)
int irq;
mask_irq(int irq)
{
switch (irq) {
case TMU1_IRQ:
@ -583,34 +547,16 @@ unmask_irq(irq)
printf("unmasked unknown irq(%d)!\n", irq);
}
}
void
init_soft_intr_handler(void)
{
#include "sci.h"
#include "scif.h"
#include "com.h"
#if (NSCI > 0) || (NSCIF > 0) || (NCOM > 0)
shb_intr_establish(SIR_SERIAL, IST_LEVEL, IPL_SOFTSERIAL,
(int (*) (void *))Xsoftserial, NULL);
#endif
shb_intr_establish(SIR_NET, IST_LEVEL, IPL_SOFTNET,
(int (*) (void *))Xsoftnet, NULL);
shb_intr_establish(SIR_CLOCK, IST_LEVEL, IPL_SOFTCLOCK,
(int (*) (void *))Xsoftclock, NULL);
}
#endif /* SH4 */
#if (NSCI > 0) || (NSCIF > 0) || (NCOM > 0)
void scisoft __P((void *));
void scifsoft __P((void *));
void comsoft __P((void *));
void scisoft(void *);
void scifsoft(void *);
void comsoft(void *);
void
Xsoftserial(void)
{
__dbg_heart_beat(HEART_BEAT_BLUE);
#if (NSCI > 0)
scisoft(NULL);
@ -629,8 +575,6 @@ Xsoftnet(void)
{
int s, ni;
__dbg_heart_beat(HEART_BEAT_RED);
s = splhigh();
ni = netisr;
netisr = 0;
@ -649,107 +593,6 @@ Xsoftnet(void)
void
Xsoftclock(void)
{
__dbg_heart_beat(HEART_BEAT_GREEN);
softclock(NULL);
}
#define LEGAL_IRQ(x) ((x) >= 0 && (x) < SHB_MAX_HARDINTR && (x) != 2)
int
sh_intr_alloc(mask, type, irq)
int mask;
int type;
int *irq;
{
int i, tmp, bestirq, count;
struct intrhand **p, *q;
if (type == IST_NONE)
panic("intr_alloc: bogus type");
bestirq = -1;
count = -1;
/* some interrupts should never be dynamically allocated */
mask &= 0xdef8;
/*
* XXX some interrupts will be used later (6 for fdc, 12 for pms).
* the right answer is to do "breadth-first" searching of devices.
*/
mask &= 0xefbf;
for (i = 0; i < SHB_MAX_HARDINTR; i++) {
if (LEGAL_IRQ(i) == 0 || (mask & (1 << i)) == 0)
continue;
switch(intrtype[i]) {
case IST_NONE:
/*
* if nothing's using the irq, just return it
*/
*irq = i;
return (0);
case IST_EDGE:
case IST_LEVEL:
if (type != intrtype[i])
continue;
/*
* if the irq is shareable, count the number of other
* handlers, and if it's smaller than the last irq like
* this, remember it
*
* XXX We should probably also consider the
* interrupt level and stick IPL_TTY with other
* IPL_TTY, etc.
*/
for (p = &intrhand[i], tmp = 0; (q = *p) != NULL;
p = &q->ih_next, tmp++)
;
if ((bestirq == -1) || (count > tmp)) {
bestirq = i;
count = tmp;
}
break;
case IST_PULSE:
/* this just isn't shareable */
continue;
}
}
if (bestirq == -1)
return (1);
*irq = bestirq;
return (0);
}
/*
* Deregister an interrupt handler.
*/
void
shb_intr_disestablish(ic, arg)
void *ic;
void *arg;
{
struct intrhand *ih = arg;
int irq = ih->ih_irq;
struct intrhand **p, *q;
mask_irq(irq);
/*
* Remove the handler from the chain.
* This is O(n^2), too.
*/
for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
;
if (q)
*p = q->ih_next;
else
panic("shb_intr_disestablish: handler not registered");
free(ih, M_DEVBUF);
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: bus.h,v 1.5 2001/07/19 15:32:13 thorpej Exp $ */
/* $NetBSD: bus.h,v 1.6 2002/02/11 17:32:36 uch Exp $ */
/*-
* Copyright (c) 1997, 1998, 2000, 2001 The NetBSD Foundation, Inc.
* Copyright (c) 1997, 1998, 2000, 2001, 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -605,6 +605,11 @@ void bus_space_destroy(bus_space_tag_t);
#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
/*
* Private flags stored in the DMA map.
*/
#define HPCSH_DMAMAP_COHERENT 0x100 /* no cache flush necessary on sync */
/* Forwards needed by prototypes below. */
struct mbuf;
struct uio;
@ -629,6 +634,7 @@ typedef struct hpcsh_bus_dmamap *bus_dmamap_t;
struct hpcsh_bus_dma_segment {
bus_addr_t ds_addr; /* DMA address */
bus_size_t ds_len; /* length of transfer */
bus_addr_t _ds_vaddr; /* virtual address, 0 if invalid */
};
typedef struct hpcsh_bus_dma_segment bus_dma_segment_t;
@ -642,6 +648,10 @@ typedef struct hpcsh_bus_dma_segment bus_dma_segment_t;
struct hpcsh_bus_dma_tag {
void *_cookie; /* cookie used in the guts */
bus_addr_t _wbase; /* DMA window base */
bus_addr_t _physbase; /* physical base of the window */
bus_size_t _wsize; /* size of the window */
/*
* DMA mapping methods.
*/
@ -717,15 +727,55 @@ struct hpcsh_bus_dmamap {
bus_size_t _dm_maxsegsz; /* largest possible segment */
bus_size_t _dm_boundary; /* don't cross this */
int _dm_flags; /* misc. flags */
struct proc *_dm_proc; /* proc that owns the mapping */
void *_dm_cookie; /* cookie for bus-specific functions */
/*
* Private cookie to be used by the DMA back-end.
*/
void *_dm_cookie;
/*
* PUBLIC MEMBERS: these are used by machine-independent code.
*/
bus_size_t dm_mapsize; /* size of the mapping */
int dm_nsegs; /* # valid segments in mapping */
bus_dma_segment_t dm_segs[1]; /* segments; variable length */
bus_size_t dm_mapsize; /* size of the mapping */
};
#ifdef _HPCSH_BUS_DMA_PRIVATE
int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
bus_size_t, int, bus_dmamap_t *);
void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
bus_size_t, struct proc *, int);
int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
struct mbuf *, int);
int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
struct uio *, int);
int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
bus_dma_segment_t *, int, bus_size_t, int);
void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
bus_size_t, int);
int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
bus_size_t alignment, bus_size_t boundary,
bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
int nsegs);
int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
int nsegs, size_t size, caddr_t *kvap, int flags);
void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
size_t size);
paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
int nsegs, off_t off, int prot, int flags);
int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
bus_size_t alignment, bus_size_t boundary,
bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
vaddr_t low, vaddr_t high);
extern struct playstation2_bus_dma_tag playstation2_default_bus_dma_tag;
#endif /* _HPCSH_BUS_DMA_PRIVATE */
#endif /* _HPCSH_BUS_H_ */