diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-09-18 13:40:05 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-09-18 13:40:05 +0000 |
commit | 2157b0ba8b467d175588a39d0235e3f42cfa0167 (patch) | |
tree | ab27e576639f38402b47a6af61ab8711d85d7ce7 /sys/arch/amiga | |
parent | 9557efb948677ebfd961c6f49a7b69e3c722c206 (diff) |
Merge of NetBSD changes upto last week or so, with the exception of stand/
Diffstat (limited to 'sys/arch/amiga')
53 files changed, 4442 insertions, 4237 deletions
diff --git a/sys/arch/amiga/amiga/autoconf.c b/sys/arch/amiga/amiga/autoconf.c index 13b6488dbb7..1b69dea8d84 100644 --- a/sys/arch/amiga/amiga/autoconf.c +++ b/sys/arch/amiga/amiga/autoconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: autoconf.c,v 1.9 1997/01/16 09:23:15 niklas Exp $ */ -/* $NetBSD: autoconf.c,v 1.45 1996/12/23 09:15:39 veego Exp $ */ +/* $OpenBSD: autoconf.c,v 1.10 1997/09/18 13:39:32 niklas Exp $ */ +/* $NetBSD: autoconf.c,v 1.56 1997/08/31 16:33:13 is Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -71,7 +71,6 @@ configure() if (config_rootfound("mainbus", "mainbus") == NULL) panic("no mainbus found"); - splx(s); #ifdef DEBUG_KERNEL_START printf("survived autoconf, going to enable interrupts\n"); #endif @@ -88,6 +87,7 @@ configure() /* also enable hardware aided software interrupts */ custom.intena = INTF_SETCLR | INTF_SOFTINT; } + splx(s); #ifdef DEBUG_KERNEL_START printf("survived interrupt enable\n"); #endif @@ -247,18 +247,22 @@ mbattach(pdp, dp, auxp) { printf("\n"); config_found(dp, "clock", simple_devprint); + if (is_a3000() || is_a4000()) { + config_found(dp, "a34kbbc", simple_devprint); + } else if ( +#ifdef DRACO + !is_draco() && +#endif + !is_a1200()) { + + config_found(dp, "a2kbbc", simple_devprint); + } #ifdef DRACO if (is_draco()) { + config_found(dp, "drbbc", simple_devprint); config_found(dp, "kbd", simple_devprint); config_found(dp, "drsc", simple_devprint); - config_found(dp, "drcom", simple_devprint); - config_found(dp, "drcom", simple_devprint); - /* - * XXX -- missing here: - * SuperIO chip serial, parallel, floppy - * or maybe just make that into a pseudo - * ISA bus. - */ + config_found(dp, "drsupio", simple_devprint); } else #endif { @@ -277,6 +281,11 @@ mbattach(pdp, dp, auxp) config_found(dp, "zbus", simple_devprint); if (is_a3000()) config_found(dp, "ahsc", simple_devprint); +#ifdef DRACO + if (!is_draco()) +#endif + config_found(dp, "aucc", simple_devprint); + } int diff --git a/sys/arch/amiga/amiga/cc.c b/sys/arch/amiga/amiga/cc.c index 375f07678ff..33cf96103d5 100644 --- a/sys/arch/amiga/amiga/cc.c +++ b/sys/arch/amiga/amiga/cc.c @@ -1,5 +1,5 @@ -/* $OpenBSD: cc.c,v 1.5 1996/06/04 12:48:14 niklas Exp $ */ -/* $NetBSD: cc.c,v 1.9 1996/04/21 21:06:50 veego Exp $ */ +/* $OpenBSD: cc.c,v 1.6 1997/09/18 13:39:32 niklas Exp $ */ +/* $NetBSD: cc.c,v 1.11 1997/06/23 23:46:23 is Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -37,6 +37,7 @@ #include <amiga/amiga/custom.h> #include <amiga/amiga/cc.h> +#include "audio.h" #if defined (__GNUC__) #define INLINE inline @@ -325,11 +326,6 @@ copper_handler() * Audio stuff. */ -struct audio_channel { - u_short play_count; /* number of times to loop sample */ - handler_func_t handler; /* interupt handler for channel */ -}; - /* - channel[4] */ /* the data for each audio channel and what to do with it. */ struct audio_channel channel[4]; @@ -352,6 +348,7 @@ cc_init_audio() */ for (i=0; i < 4; i++) { channel[i].play_count = 0; + channel[i].isaudio = 0; channel[i].handler = defchannel_handler; } } @@ -372,12 +369,12 @@ audio_handler() /* * only check channels who have DMA enabled. */ - audio_dma &= (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3); + audio_dma &= AUCC_ALLDMAF; /* * disable all audio interupts with DMA set */ - custom.intena = (audio_dma << 7); + custom.intena = (audio_dma << INTB_AUD0) & AUCC_ALLINTF; /* * if no audio dma enabled then exit quick. @@ -386,34 +383,42 @@ audio_handler() /* * clear all interrupts. */ - custom.intreq = INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3; + custom.intreq = AUCC_ALLINTF; goto out; } - for (i = 0; i < 4; i++) { + for (i = 0; i < AUCC_MAXINT; i++) { flag = (1 << i); ir = custom.intreqr; /* * is this channel's interrupt is set? */ - if ((ir & (flag << 7)) == 0) + if ((ir & (flag << INTB_AUD0)) == 0) continue; +#if NAUDIO>0 + custom.intreq = (flag << INTB_AUD0); + /* call audio handler with channel number */ + if (channel[i].isaudio == 1) + if (channel[i].handler) + (*channel[i].handler)(i); +#endif + if (channel[i].handler) channel[i].handler(i); /* * clear this channels interrupt. */ - custom.intreq = (flag << 7); + custom.intreq = (flag << INTB_AUD0); } out: /* * enable audio interupts with dma still set. */ audio_dma = custom.dmaconr; - audio_dma &= (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3); - custom.intena = INTF_SETCLR | (audio_dma << 7); + audio_dma &= AUCC_ALLDMAF; + custom.intena = INTF_SETCLR | (audio_dma << INTB_AUD0); } /* @@ -433,7 +438,9 @@ defchannel_handler(i) * disable interrupts to this channel */ custom.dmacon = (1 << i); - custom.intena = (1 << (i + 7)); + custom.intena = (1 << (i + INTB_AUD0)); + if (channel[i].isaudio == -1) + channel[i].isaudio = 0; } } @@ -443,8 +450,19 @@ play_sample(len, data, period, volume, channels, count) u_long count; { u_short dmabits, ch; + int i; dmabits = channels & 0xf; + + /* check to see, whether all channels are free */ + for (i=0; i < 4; i++) { + if ((1 << i) & dmabits) + if (channel[i].isaudio) + return; /* allocated */ + else + channel[i].isaudio = -1; /* allocate */ + } + custom.dmacon = dmabits; /* turn off the correct channels */ /* load the channels */ @@ -454,16 +472,16 @@ play_sample(len, data, period, volume, channels, count) /* busy */ if (channel[ch].handler != defchannel_handler) continue; - channel[ch].play_count = count; - custom.aud[ch].per = period; - custom.aud[ch].vol = volume; custom.aud[ch].len = len; custom.aud[ch].lc = data; + custom.aud[ch].per = period; + custom.aud[ch].vol = volume; + channel[ch].play_count = count; } /* * turn on interrupts and enable dma for channels and */ - custom.intena = INTF_SETCLR | (dmabits << 7); + custom.intena = INTF_SETCLR | (dmabits << INTB_AUD0); custom.dmacon = DMAF_SETCLR | DMAF_MASTER | dmabits; } diff --git a/sys/arch/amiga/amiga/cc.h b/sys/arch/amiga/amiga/cc.h index 6a0157bf5a4..98a77c8f7ed 100644 --- a/sys/arch/amiga/amiga/cc.h +++ b/sys/arch/amiga/amiga/cc.h @@ -1,5 +1,5 @@ -/* $OpenBSD: cc.h,v 1.4 1996/06/04 12:48:15 niklas Exp $ */ -/* $NetBSD: cc.h,v 1.7 1996/04/21 21:06:52 veego Exp $ */ +/* $OpenBSD: cc.h,v 1.5 1997/09/18 13:39:33 niklas Exp $ */ +/* $NetBSD: cc.h,v 1.9 1997/06/23 23:46:24 is Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -44,6 +44,30 @@ #define LOADDR(x) (u_short)(((unsigned long)(x))&0xffff) #endif +/* + * Audio stuff + */ +typedef void (*handler_func_t) __P((int)); + +struct audio_channel { + u_short play_count; + short isaudio; + handler_func_t handler; +}; + +#ifdef LEV6_DEFER +#define AUCC_MAXINT 3 +#define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2) +#else +#define AUCC_MAXINT 4 +#define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3) +#endif +/* + * Define this one unconditionally; we may use AUD3 as slave channel + * with LEV6_DEFER + */ +#define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3) + /* * Vertical blank iterrupt sever chains. */ @@ -148,8 +172,6 @@ vm_offset_t chipmem_end; #define CHIPMEMTOP (0x00200000) #define NCHIPMEMPG btoc(CHIPMEMTOP - CHIPMEMBASE) -typedef void (*handler_func_t) __P((int)); - /* * Prototypes. */ diff --git a/sys/arch/amiga/amiga/conf.c b/sys/arch/amiga/amiga/conf.c index fe548b00df2..95f93de9a33 100644 --- a/sys/arch/amiga/amiga/conf.c +++ b/sys/arch/amiga/amiga/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.17 1997/05/13 13:24:46 niklas Exp $ */ +/* $OpenBSD: conf.c,v 1.18 1997/09/18 13:39:34 niklas Exp $ */ /* $NetBSD: conf.c,v 1.42 1997/01/07 11:35:03 mrg Exp $ */ /*- @@ -95,13 +95,14 @@ int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); #include "ms.h" #include "view.h" #include "mfcs.h" -#include "drcom.h" dev_decl(filedesc,open); #include "bpfilter.h" #include "tun.h" #include "com.h" #include "lpt.h" #include "uk.h" +#include "audio.h" +cdev_decl(audio); struct cdevsw cdevsw[] = { @@ -144,7 +145,7 @@ struct cdevsw cdevsw[] = cdev_uk_init(NUK,uk), /* 36: unknown SCSI */ cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */ cdev_disk_init(NACD,acd), /* 38: ATAPI CD-ROM */ - cdev_tty_init(NDRCOM,drcom), /* 39: DraCo com ports */ + cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */ cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */ cdev_disk_init(NRD,rd), /* 41: RAM disk */ }; diff --git a/sys/arch/amiga/amiga/genassym.cf b/sys/arch/amiga/amiga/genassym.cf index 938e88d1d78..97760606e16 100644 --- a/sys/arch/amiga/amiga/genassym.cf +++ b/sys/arch/amiga/amiga/genassym.cf @@ -1,7 +1,8 @@ -# $OpenBSD: genassym.cf,v 1.2 1997/03/27 16:18:02 niklas Exp $ +# $NetBSD: genassym.cf,v 1.3 1997/07/16 00:01:49 is Exp $ +# $OpenBSD: genassym.cf,v 1.3 1997/09/18 13:39:34 niklas Exp $ # -# Copyright (c) 1982, 1990 The Regents of the University of California. -# All rights reserved. +# Copyright (c) 1982, 1990, 1993 +# The Regents of the University of California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -31,7 +32,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# @(#)genassym.c 7.8 (Berkeley) 5/7/91 +# @(#)genassym.c 8.3 (Berkeley) 1/4/94 # include <sys/param.h> @@ -55,24 +56,45 @@ include <amiga/amiga/cia.h> include <amiga/amiga/isr.h> # values for mmutype -define MMU_68060 MMU_68060 -define MMU_68040 MMU_68040 -define MMU_68030 MMU_68030 -define MMU_68851 MMU_68851 +define MMU_68851 MMU_68851 +define MMU_68030 MMU_68030 +define MMU_68040 MMU_68040 +define MMU_68060 MMU_68060 # values for cputype -define CPU_68020 CPU_68020 -define CPU_68030 CPU_68030 -define CPU_68040 CPU_68040 -define CPU_68060 CPU_68060 +define CPU_68020 CPU_68020 +define CPU_68030 CPU_68030 +define CPU_68040 CPU_68040 +define CPU_68060 CPU_68060 + +# values for ectype +define EC_NONE EC_NONE + +# values for fputype +define FPU_NONE FPU_NONE +define FPU_68881 FPU_68881 +define FPU_68882 FPU_68882 +define FPU_68040 FPU_68040 +define FPU_68060 FPU_68060 +define FPU_UNKNOWN FPU_UNKNOWN + +ifdef FPU_EMULATE +define FPU_EMULATE FPU_EMULATE +endif # values for machineid define AMIGA_68020 AMIGA_68020 define AMIGA_68030 AMIGA_68030 define AMIGA_68040 AMIGA_68040 define AMIGA_68060 AMIGA_68060 +ifdef DRACO +define DRACO DRACO +endif +ifdef BB060STUPIDROM +define BB060STUPIDROM BB060STUPIDROM +endif -# proc fields and values +# proc structure fields and values define P_FORW offsetof(struct proc, p_forw) define P_BACK offsetof(struct proc, p_back) define P_VMSPACE offsetof(struct proc, p_vmspace) @@ -80,18 +102,24 @@ define P_ADDR offsetof(struct proc, p_addr) define P_PRIORITY offsetof(struct proc, p_priority) define P_STAT offsetof(struct proc, p_stat) define P_WCHAN offsetof(struct proc, p_wchan) -define P_PID offsetof(struct proc, p_pid) define P_MD_REGS offsetof(struct proc, p_md.md_regs) define SRUN SRUN # VM structure fields -define VM_PMAP offsetof(struct vmspace, vm_pmap) define PM_STCHG offsetof(struct pmap, pm_stchanged) +define VM_PMAP offsetof(struct vmspace, vm_map.pmap) # interrupt/fault metering define V_INTR offsetof(struct vmmeter, v_intr) +# general constants +define UPAGES UPAGES +define USPACE USPACE +define NBPG NBPG +define PGSHIFT PGSHIFT +define USRSTACK USRSTACK + # PSL values (should just include psl.h?) define PSL_S PSL_S define PSL_IPL7 PSL_IPL7 @@ -146,21 +174,16 @@ define FR_SP offsetof(struct frame, f_regs[15]) define FR_HW offsetof(struct frame, f_sr) define FR_ADJ offsetof(struct frame, f_stackadj) +# isr fields +define ISR_FORW offsetof(struct isr, isr_forw) +define ISR_INTR offsetof(struct isr, isr_intr) +define ISR_ARG offsetof(struct isr, isr_arg) + # system calls define SYS_exit SYS_exit define SYS_execve SYS_execve define SYS_sigreturn SYS_sigreturn -# Various constants -define UPAGES UPAGES -define USPACE USPACE -define NBPG NBPG -define PGSHIFT PGSHIFT -define USRSTACK USRSTACK -ifdef DRACO -define DRACO DRACO -endif - # user fields define U_PROF offsetof(struct user, u_stats.p_prof) define U_PROFSCALE offsetof(struct user, u_stats.p_prof.pr_scale) @@ -181,10 +204,5 @@ define T_FPERR T_FPERR define T_ASTFLT T_ASTFLT define T_TRAP15 T_TRAP15 -# Custom chip registers +# miscellaneous custom chip register offsets define CIAICR offsetof(struct CIA, icr) - -# Interrupt service routine entry fields -define ISR_FORW offsetof(struct isr, isr_forw) -define ISR_INTR offsetof(struct isr, isr_intr) -define ISR_ARG offsetof(struct isr, isr_arg) diff --git a/sys/arch/amiga/amiga/locore.s b/sys/arch/amiga/amiga/locore.s index 824a741b35b..6c4b70078ea 100644 --- a/sys/arch/amiga/amiga/locore.s +++ b/sys/arch/amiga/amiga/locore.s @@ -1,5 +1,5 @@ -/* $OpenBSD: locore.s,v 1.22 1997/07/20 07:35:37 niklas Exp $ */ -/* $NetBSD: locore.s,v 1.72 1996/12/17 11:09:10 is Exp $ */ +/* $OpenBSD: locore.s,v 1.23 1997/09/18 13:39:35 niklas Exp $ */ +/* $NetBSD: locore.s,v 1.89 1997/07/17 16:22:54 is Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -51,6 +51,7 @@ #include "assym.h" #include <machine/asm.h> +#include <machine/trap.h> .globl _kernel_text _kernel_text: @@ -953,9 +954,30 @@ Lsetcpu040: movl #CPU_68040,a1@ .word 0xf4f8 | cpusha bc - push and inval. caches movl #CACHE40_OFF,d0 | 68040 cache disable - btst #7,sp@(3) | XXX +#ifndef BB060STUPIDROM + btst #7,sp@(3) jeq Lstartnot040 + movl #CPU_68060,a1@ | set cputype orl #IC60_CABC,d0 | XXX and clear all 060 branch cache +#else + movc d0,cacr + bset #30,d0 | not allocate data cache bit + movc d0,cacr | does it stick? + movc cacr,d0 + tstl d0 + jeq Lstartnot040 + bset #7,sp@(3) | note it is '60 family in machineid + movl #CPU_68060,a1@ | and in the cputype + orl #IC60_CABC,d0 | XXX and clear all 060 branch cache + .word 0x4e7a,0x1808 | movc pcr,d1 + swap d1 + cmpw #0x430,d1 + jne Lstartnot040 | but no FPU + bset #6,sp@(3) | yes, we have FPU, note that + swap d1 + bclr #1,d1 | ... and switch it on. + .word 0x4e7b,0x1808 | movc d1,pcr +#endif Lstartnot040: movc d0,cacr | clear and disable on-chip cache(s) movl #_vectab,a0 @@ -988,9 +1010,9 @@ Lunshadow: #ifdef FPCOPROC clrl a1@(PCB_FPCTX) | ensure null FP context |WRONG! movl a1,sp@- - pea a1@(PCB_FPCTX) - jbsr _m68881_restore | restore it (does not kill a1) - addql #4,sp +| pea a1@(PCB_FPCTX) +| jbsr _m68881_restore | restore it (does not kill a1) +| addql #4,sp #endif /* flush TLB and turn on caches */ @@ -1082,38 +1104,15 @@ _proc_trampoline: addql #8,sp | pop sp and stack adjust jra rei | all done - /* - * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig(). - * - * Stack looks like: - * - * sp+0 -> signal number - * sp+4 pointer to siginfo (sip) - * sp+8 pointer to signal context frame (scp) - * sp+16 address of handler - * sp+30 saved hardware state - * . - * . - * scp+0-> beginning of signal context frame + * Use common m68k sigcode. */ - .globl _sigcode, _esigcode - .data -_sigcode: - movl sp@(12),a0 | signal handler addr (4 bytes) - jsr a0@ | call signal handler (2 bytes) - addql #4,sp | pop signo (2 bytes) - trap #1 | special syscall entry (2 bytes) - movl d0,sp@(4) | save errno (4 bytes) - moveq #1,d0 | syscall == exit (2 bytes) - trap #0 | exit(errno) (2 bytes) - .align 2 -_esigcode: +#include <m68k/m68k/sigcode.s> /* * Primitives */ -#include <m68k/asm.h> +#include <m68k/m68k/support.s> /* * update profiling information for the user @@ -1153,92 +1152,32 @@ Lauexit: movl sp@+,a2 | restore scratch reg rts -#include <m68k/m68k/support.s> +#ifdef notdef /* - * The following primitives manipulate the run queues. - * _whichqs tells which of the 32 queues _qs have processes - * in them. Setrunqueue puts processes into queues, remrunqueue - * removes them from queues. The running process is on no queue, - * other processes are on a queue related to p->p_priority, divided by 4 - * actually to shrink the 0-127 range of priorities into the 32 available - * queues. + * non-local gotos */ - +ENTRY(qsetjmp) + movl sp@(4),a0 | savearea pointer + lea a0@(40),a0 | skip regs we do not save + movl a6,a0@+ | save FP + movl sp,a0@+ | save SP + movl sp@,a0@ | and return address + moveq #0,d0 | return 0 + rts +#endif + .globl _whichqs,_qs,_cnt,_panic .globl _curproc .comm _want_resched,4 /* - * Setrunqueue(p) - * - * Call should be made at spl6(), and p->p_stat should be SRUN - */ -ENTRY(setrunqueue) - movl sp@(4),a0 - tstl a0@(P_BACK) - jeq Lset1 - movl #Lset2,sp@- - jbsr _panic -Lset1: - clrl d0 - movb a0@(P_PRIORITY),d0 - lsrb #2,d0 - movl _whichqs,d1 - bset d0,d1 - movl d1,_whichqs - lslb #3,d0 - addl #_qs,d0 - movl d0,a0@(P_FORW) - movl d0,a1 - movl a1@(P_BACK),a0@(P_BACK) - movl a0,a1@(P_BACK) - movl a0@(P_BACK),a1 - movl a0,a1@(P_FORW) - rts - -Lset2: - .asciz "setrunqueue" - .even - -/* - * remrunqueue(p) - * - * Call should be made at spl6(). + * Use common m68k process manipulation routines. */ -ENTRY(remrunqueue) - movl sp@(4),a0 - clrl d0 - movb a0@(P_PRIORITY),d0 - lsrb #2,d0 - movl _whichqs,d1 - bclr d0,d1 - jne Lrem1 - movl #Lrem3,sp@- - jbsr _panic -Lrem1: - movl d1,_whichqs - movl a0@(P_FORW),a1 - movl a0@(P_BACK),a1@(P_BACK) - movl a0@(P_BACK),a1 - movl a0@(P_FORW),a1@(P_FORW) - movl #_qs,a1 - movl d0,d1 - lslb #3,d1 - addl d1,a1 - cmpl a1@(P_FORW),a1 - jeq Lrem2 - movl _whichqs,d1 - bset d0,d1 - movl d1,_whichqs -Lrem2: - clrl a0@(P_BACK) - rts +#include <m68k/m68k/proc_subr.s> -Lrem3: - .asciz "remrunqueue" Lsw0: - .asciz "cpu_switch" + .asciz "cpu_switch" .even .globl _curpcb @@ -1373,6 +1312,10 @@ Lsw2: movl a2,a1@(PCB_USP) | and save it movl _CMAP2,a1@(PCB_CMAP2) | save temporary map PTE #ifdef FPCOPROC +#ifdef FPU_EMULATE + tstl _fputype | do we have any FPU? + jeq Lswnofpsave | no, dont save +#endif lea a1@(PCB_FPCTX),a2 | pointer to FP save area fsave a2@ | save FP state #if defined(M68020) || defined(M68030) || defined(M68040) @@ -1417,7 +1360,7 @@ Lswnofpsave: tstl a0 | map == VM_MAP_NULL? jeq Lbadsw | panic #endif - lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap + movl a0@(VM_PMAP),a0 | pmap = vmspace->vm_map.pmap tstl a0@(PM_STCHG) | pmap->st_changed? jeq Lswnochg | no, skip pea a1@ | push pcb (at p_addr) @@ -1462,6 +1405,14 @@ Lres5: movl a1@(PCB_USP),a0 movl a0,usp | and USP #ifdef FPCOPROC +#ifdef FPU_EMULATE + tstl _fputype | do we _have_ any fpu? + jne Lresnonofpatall + movw a1@(PCB_PS),sr | no, restore PS + moveq #1,d0 | return 1 (for alternate returns) + rts +Lresnonofpatall: +#endif lea a1@(PCB_FPCTX),a0 | pointer to FP save area #if defined(M68020) || defined(M68030) || defined(M68040) #ifdef M68060 @@ -1507,6 +1458,10 @@ ENTRY(savectx) moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers movl _CMAP2,a1@(PCB_CMAP2) | save temporary map PTE #ifdef FPCOPROC +#ifdef FPU_EMULATE + tstl _fputype + jeq Lsavedone +#endif lea a1@(PCB_FPCTX),a0 | pointer to FP save area fsave a0@ | save FP state #if defined(M68020) || defined(M68030) || defined(M68040) @@ -2271,11 +2226,13 @@ _fpeaemu60: tmpstk: .globl _mmutype,_cputype,_fputype,_protorp _mmutype: - .long 0 + .long MMU_68851 _cputype: - .long 0 + .long CPU_68020 +_ectype: + .long EC_NONE _fputype: - .long 0 + .long FPU_NONE _protorp: .long 0x80000002,0 | prototype root pointer .globl _cold @@ -2329,6 +2286,9 @@ _intrnames: .asciz "60fpeaemu" .asciz "60bpe" #endif +#ifdef FPU_EMULATE + .asciz "fpe" +#endif _eintrnames: .align 2 _intrcnt: @@ -2344,4 +2304,7 @@ L60fpdem: .long 0 L60fpeaem: .long 0 L60bpe: .long 0 #endif +#ifdef FPU_EMULATE +Lfpecnt: .long 0 +#endif _eintrcnt: diff --git a/sys/arch/amiga/amiga/machdep.c b/sys/arch/amiga/amiga/machdep.c index d5040d59697..ae0236aa554 100644 --- a/sys/arch/amiga/amiga/machdep.c +++ b/sys/arch/amiga/amiga/machdep.c @@ -1,5 +1,5 @@ -/* $OpenBSD: machdep.c,v 1.24 1997/07/23 06:58:17 denny Exp $ */ -/* $NetBSD: machdep.c,v 1.82 1996/12/17 07:32:54 is Exp $ */ +/* $OpenBSD: machdep.c,v 1.25 1997/09/18 13:39:36 niklas Exp $ */ +/* $NetBSD: machdep.c,v 1.95 1997/08/27 18:31:17 is Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -126,6 +126,9 @@ #include <netiso/iso.h> #include <netiso/clnp.h> #endif +#ifdef NETATALK +#include <netatalk/at_extern.h> +#endif #if NPPP > 0 #include <net/ppp_defs.h> #include <net/if_ppp.h> @@ -142,11 +145,10 @@ vm_offset_t reserve_dumppages __P((vm_offset_t)); void dumpsys __P((void)); void initcpu __P((void)); void straytrap __P((int, u_short)); -static void netintr __P((void)); -static void call_sicallbacks __P((void)); +void netintr __P((void)); +void call_sicallbacks __P((void)); +void _softintr_callit __P((void *, void *)); void intrhand __P((int)); -static void dumpmem __P((int *, int, int)); -static char *hexstr __P((int, int)); #if NSER > 0 void ser_outintr __P((void)); #endif @@ -189,6 +191,7 @@ unsigned char ssir; int safepri = PSL_LOWIPL; extern int freebufspace; extern u_int lowram; +extern short exframesize[]; #ifdef COMPAT_SUNOS extern struct emul emul_sunos; @@ -197,7 +200,7 @@ extern struct emul emul_sunos; /* used in init_main.c */ char *cpu_type = "m68k"; /* the following is used externally (sysctl_hw) */ -char machine[] = "amiga"; +char machine[] = MACHINE; /* from <machine/param.h> */ struct isr *isr_ports; #ifdef DRACO @@ -582,7 +585,12 @@ setregs(p, pack, stack, retval) #ifdef FPCOPROC /* restore a null state frame */ p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; - m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); +#ifdef FPU_EMULATE + if (!fputype) + bzero(&p->p_addr->u_pcb.pcb_fpregs, sizeof(struct fpframe)); + else +#endif + m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); #endif #ifdef COMPAT_SUNOS /* @@ -644,8 +652,16 @@ identifycpu() pcr & 0x10000 ? "LC/EC" : "", (pcr>>8)&0xff); cpu_type = cpubuf; mmu = "/MMU"; - fpu = "/FPU"; - fputype = FPU_68040; /* XXX */ + if (pcr & 2) { + fpu = "/FPU disabled"; + fputype = FPU_NONE; + } else if (m68060_pcr_init & 2){ + fpu = "/FPU will be disabled"; + fputype = FPU_NONE; + } else if (machineid & AMIGA_FPU40) { + fpu = "/FPU"; + fputype = FPU_68040; /* XXX */ + } } else #endif if (machineid & AMIGA_68040) { @@ -709,6 +725,334 @@ cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) /* NOTREACHED */ } +#define SS_RTEFRAME 1 +#define SS_FPSTATE 2 +#define SS_USERREGS 4 + +struct sigstate { + int ss_flags; /* which of the following are valid */ + struct frame ss_frame; /* original exception frame */ + struct fpframe ss_fpstate; /* 68881/68882 state info */ +}; + +/* + * WARNING: code in locore.s assumes the layout shown for sf_signum + * thru sf_handler so... don't screw with them! + */ +struct sigframe { + int sf_signum; /* signo for handler */ + siginfo_t *sf_sip; /* additional info for handler */ + struct sigcontext *sf_scp; /* context ptr for handler */ + sig_t sf_handler; /* handler addr for u_sigc */ + struct sigstate sf_state; /* state of the hardware */ + struct sigcontext sf_sc; /* actual context */ + siginfo_t sf_si; +}; + +#ifdef DEBUG +int sigdebug = 0x0; +int sigpid = 0; +#define SDB_FOLLOW 0x01 +#define SDB_KSTACK 0x02 +#define SDB_FPSTATE 0x04 +#endif + +/* + * Send an interrupt to process. + */ +void +sendsig(catcher, sig, mask, code, type, val) + sig_t catcher; + int sig, mask; + u_long code; + int type; + union sigval val; +{ + register struct proc *p = curproc; + register struct sigframe *fp, *kfp; + register struct frame *frame; + register struct sigacts *psp = p->p_sigacts; + register short ft; + int oonstack, fsize; + extern char sigcode[], esigcode[]; + + frame = (struct frame *)p->p_md.md_regs; + ft = frame->f_format; + oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + + /* + * Allocate and validate space for the signal handler + * context. Note that if the stack is in P0 space, the + * call to grow() is a nop, and the useracc() check + * will fail if the process has not already allocated + * the space with a `brk'. + */ + fsize = sizeof(struct sigframe); + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && + (psp->ps_sigonstack & sigmask(sig))) { + fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + + psp->ps_sigstk.ss_size - fsize); + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + fp = (struct sigframe *)(frame->f_regs[SP] - fsize); + if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) + (void)grow(p, (unsigned)fp); +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n", + p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft); +#endif + if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) { +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): useracc failed on sig %d\n", + p->p_pid, sig); +#endif + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + SIGACTION(p, SIGILL) = SIG_DFL; + sig = sigmask(SIGILL); + p->p_sigignore &= ~sig; + p->p_sigcatch &= ~sig; + p->p_sigmask &= ~sig; + psignal(p, SIGILL); + return; + } + kfp = (struct sigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK); + /* + * Build the argument list for the signal handler. + */ + kfp->sf_signum = sig; + kfp->sf_sip = NULL; + kfp->sf_scp = &fp->sf_sc; + kfp->sf_handler = catcher; + + /* + * Save necessary hardware state. Currently this includes: + * - general registers + * - original exception frame (if not a "normal" frame) + * - FP coprocessor state + */ + kfp->sf_state.ss_flags = SS_USERREGS; + bcopy((caddr_t)frame->f_regs, + (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs); + if (ft >= FMT7) { +#ifdef DEBUG + if (ft > 15 || exframesize[ft] < 0) + panic("sendsig: bogus frame type"); +#endif + kfp->sf_state.ss_flags |= SS_RTEFRAME; + kfp->sf_state.ss_frame.f_format = frame->f_format; + kfp->sf_state.ss_frame.f_vector = frame->f_vector; + bcopy((caddr_t)&frame->F_u, + (caddr_t)&kfp->sf_state.ss_frame.F_u, exframesize[ft]); + /* + * Leave an indicator that we need to clean up the kernel + * stack. We do this by setting the "pad word" above the + * hardware stack frame to the amount the stack must be + * adjusted by. + * + * N.B. we increment rather than just set f_stackadj in + * case we are called from syscall when processing a + * sigreturn. In that case, f_stackadj may be non-zero. + */ + frame->f_stackadj += exframesize[ft]; + frame->f_format = frame->f_vector = 0; +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sendsig(%d): copy out %d of frame %d\n", + p->p_pid, exframesize[ft], ft); +#endif + } + +#ifdef FPCOPROC + kfp->sf_state.ss_flags |= SS_FPSTATE; + if (fputype) + m68881_save(&kfp->sf_state.ss_fpstate); +#ifdef DEBUG + if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate) + printf("sendsig(%d): copy out FP state (%x) to %p\n", + p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate, + &kfp->sf_state.ss_fpstate); +#endif /* DEBUG */ +#endif /* FPCOPROC */ + /* + * Build the signal context to be used by sigreturn. + */ + kfp->sf_sc.sc_onstack = oonstack; + kfp->sf_sc.sc_mask = mask; + kfp->sf_sc.sc_sp = frame->f_regs[SP]; + kfp->sf_sc.sc_fp = frame->f_regs[A6]; + kfp->sf_sc.sc_ap = (int)&fp->sf_state; + kfp->sf_sc.sc_pc = frame->f_pc; + kfp->sf_sc.sc_ps = frame->f_sr; + + if (psp->ps_siginfo & sigmask(sig)) { + kfp->sf_sip = &fp->sf_si; + initsiginfo(&kfp->sf_si, sig, code, type, val); + } + + /* XXX do not copy out siginfo if not needed */ + (void)copyout((caddr_t)kfp, (caddr_t)fp, fsize); + frame->f_regs[SP] = (int)fp; +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", + p->p_pid, sig, kfp->sf_scp, fp, kfp->sf_sc.sc_sp, + kfp->sf_sc.sc_ap); +#endif /* DEBUG */ + /* + * Signal trampoline code is at base of user stack. + */ + frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode); +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); +#endif + free((caddr_t)kfp, M_TEMP); +} + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * psl to gain improper priviledges or to cause + * a machine fault. + */ +/* ARGSUSED */ +int +sys_sigreturn(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext *scp, context; + struct frame *frame; + int rf, flags; + struct sigstate tstate; + extern short exframesize[]; + + scp = SCARG(uap, sigcntxp); +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); +#endif + if ((int)scp & 1) + return(EINVAL); + /* + * Test and fetch the context structure. + * We grab it all at once for speed. + */ + if (useracc((caddr_t)scp, sizeof(*scp), B_WRITE) == 0 || + copyin(scp, &context, sizeof(context))) + return(EINVAL); + scp = &context; + if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) + return(EINVAL); + /* + * Restore the user supplied information + */ + if (scp->sc_onstack & 1) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = scp->sc_mask &~ sigcantmask; + frame = (struct frame *) p->p_md.md_regs; + frame->f_regs[SP] = scp->sc_sp; + frame->f_regs[A6] = scp->sc_fp; + frame->f_pc = scp->sc_pc; + frame->f_sr = scp->sc_ps; + /* + * Grab pointer to hardware state information. + * If zero, the user is probably doing a longjmp. + */ + if ((rf = scp->sc_ap) == 0) + return (EJUSTRETURN); + /* + * See if there is anything to do before we go to the + * expense of copying in close to 1/2K of data + */ + flags = fuword((caddr_t)rf); +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn(%d): sc_ap %x flags %x\n", + p->p_pid, rf, flags); +#endif + /* + * fuword failed (bogus sc_ap value). + */ + if (flags == -1) + return (EINVAL); + if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate)) + return (EJUSTRETURN); +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n", + p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp), + (flags&SS_RTEFRAME) ? tstate.ss_frame.f_format : -1); +#endif + /* + * Restore most of the users registers except for A6 and SP + * which were handled above. + */ + if (flags & SS_USERREGS) + bcopy((caddr_t)tstate.ss_frame.f_regs, + (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW); + /* + * Restore long stack frames. Note that we do not copy + * back the saved SR or PC, they were picked up above from + * the sigcontext structure. + */ + if (flags & SS_RTEFRAME) { + register int sz; + + /* grab frame type and validate */ + sz = tstate.ss_frame.f_format; + if (sz > 15 || (sz = exframesize[sz]) < 0) + return (EINVAL); + frame->f_stackadj -= sz; + frame->f_format = tstate.ss_frame.f_format; + frame->f_vector = tstate.ss_frame.f_vector; + bcopy((caddr_t)&tstate.ss_frame.F_u, (caddr_t)&frame->F_u, sz); +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn(%d): copy in %d of frame type %d\n", + p->p_pid, sz, tstate.ss_frame.f_format); +#endif + } +#ifdef FPCOPROC + /* + * Finally we restore the original FP context + */ +#ifdef FPU_EMULATE + if ((flags & SS_FPSTATE) && fputype) +#else + if (fputype) +#endif + m68881_restore(&tstate.ss_fpstate); +#ifdef DEBUG + if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) + printf("sigreturn(%d): copied in FP state (%x) at %p\n", + p->p_pid, *(u_int *)&tstate.ss_fpstate, + &tstate.ss_fpstate); +#endif +#endif +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) || + ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) + printf("sigreturn(%d): returns\n", p->p_pid); +#endif + return (EJUSTRETURN); +} + static int waittime = -1; void @@ -761,7 +1105,6 @@ boot(howto) /*NOTREACHED*/ } - unsigned dumpmag = 0x8fca0101; /* magic number for savecore */ int dumpsize = 0; /* also for savecore */ long dumplo = 0; @@ -967,57 +1310,106 @@ microtime(tvp) void initcpu() { + typedef void trapfun __P((void)); + /* XXX should init '40 vecs here, too */ -#if defined(M68060) || defined(DRACO) - extern caddr_t vectab[256]; +#if defined(M68060) || defined(M68040) || defined(DRACO) || defined(FPU_EMULATE) + extern trapfun *vectab[256]; +#endif + +#if defined(M68060) || defined(M68040) + extern trapfun addrerr4060; #endif #ifdef M68060 + extern trapfun buserr60; #if defined(M060SP) /*extern u_int8_t I_CALL_TOP[];*/ - extern u_int8_t intemu60, fpiemu60, fpdemu60, fpeaemu60; + extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60; extern u_int8_t FP_CALL_TOP[]; #else - extern u_int8_t illinst; + extern trapfun illinst; #endif - extern u_int8_t fpfault; + extern trapfun fpfault; +#endif + +#ifdef M68040 + extern trapfun buserr40; #endif #ifdef DRACO - extern u_int8_t DraCoIntr, DraCoLev1intr, DraCoLev2intr; + extern trapfun DraCoIntr, DraCoLev1intr, DraCoLev2intr; u_char dracorev; #endif +#ifdef FPU_EMULATE + extern trapfun fpemuli; +#endif + #ifdef M68060 if (machineid & AMIGA_68060) { + if (machineid & AMIGA_FPU40 && m68060_pcr_init & 2) { + /* + * in this case, we're about to switch the FPU off; + * do a FNOP to avoid stray FP traps later + */ + __asm("fnop"); + /* ... and mark FPU as absent for identifyfpu() */ + machineid &= ~(AMIGA_FPU40|AMIGA_68882|AMIGA_68881); + } asm volatile ("movl %0,d0; .word 0x4e7b,0x0808" : : "d"(m68060_pcr_init):"d0" ); + + /* bus/addrerr vectors */ + vectab[2] = buserr60; + vectab[3] = addrerr4060; #if defined(M060SP) /* integer support */ - vectab[61] = &intemu60/*&I_CALL_TOP[128 + 0x00]*/; + vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/; /* floating point support */ /* * XXX maybe we really should run-time check for the * stack frame format here: */ - vectab[11] = &fpiemu60/*&FP_CALL_TOP[128 + 0x30]*/; + vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/; - vectab[55] = &fpdemu60/*&FP_CALL_TOP[128 + 0x38]*/; - vectab[60] = &fpeaemu60/*&FP_CALL_TOP[128 + 0x40]*/; + vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/; + vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/; - vectab[54] = &FP_CALL_TOP[128 + 0x00]; - vectab[52] = &FP_CALL_TOP[128 + 0x08]; - vectab[53] = &FP_CALL_TOP[128 + 0x10]; - vectab[51] = &FP_CALL_TOP[128 + 0x18]; - vectab[50] = &FP_CALL_TOP[128 + 0x20]; - vectab[49] = &FP_CALL_TOP[128 + 0x28]; + vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00]; + vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08]; + vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10]; + vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18]; + vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20]; + vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28]; #else - vectab[61] = &illinst; + vectab[61] = illinst; #endif - vectab[48] = &fpfault; + vectab[48] = fpfault; + } +#endif + +/* + * Vector initialization for special motherboards + */ +#ifdef M68040 +#ifdef M68060 + else +#endif + if (machineid & AMIGA_68040) { + /* addrerr vector */ + vectab[2] = buserr40; + vectab[3] = addrerr4060; + } +#endif + +#ifdef FPU_EMULATE + if (!(machineid & (AMIGA_68881|AMIGA_68882|AMIGA_FPU40))) { + vectab[11] = fpemuli; + printf("FPU software emulation initialized.\n"); } #endif @@ -1029,16 +1421,16 @@ initcpu() dracorev = is_draco(); if (dracorev) { if (dracorev >= 4) { - vectab[24+1] = &DraCoLev1intr; - vectab[24+2] = &DraCoIntr; + vectab[24+1] = DraCoLev1intr; + vectab[24+2] = DraCoIntr; } else { - vectab[24+1] = &DraCoIntr; - vectab[24+2] = &DraCoLev2intr; + vectab[24+1] = DraCoIntr; + vectab[24+2] = DraCoLev2intr; } - vectab[24+3] = &DraCoIntr; - vectab[24+4] = &DraCoIntr; - vectab[24+5] = &DraCoIntr; - vectab[24+6] = &DraCoIntr; + vectab[24+3] = DraCoIntr; + vectab[24+4] = DraCoIntr; + vectab[24+5] = DraCoIntr; + vectab[24+6] = DraCoIntr; } #endif DCIS(); @@ -1096,7 +1488,7 @@ badbaddr(addr) return(0); } -static void +void netintr() { #ifdef INET @@ -1160,6 +1552,44 @@ static int ncb; /* number of callback blocks allocated */ static int ncbd; /* number of callback blocks dynamically allocated */ #endif +/* + * these are __GENERIC_SOFT_INTERRUPT wrappers; will be replaced + * once by the real thing once all drivers are converted. + * + * to help performance for converted drivers, the YYY_sicallback() function + * family can be implemented in terms of softintr_XXX() as an intermediate + * measure. + */ + +void +_softintr_callit(rock1, rock2) + void *rock1, *rock2; +{ + (*(void (*)(void *))rock1)(rock2); +} + +void * +softintr_establish(ipl, func, arg) + int ipl; + void func __P((void *)); + void *arg; +{ + struct si_callback *si; + + (void)ipl; + + si = (struct si_callback *)malloc(sizeof(*si), M_TEMP, M_NOWAIT); + if (si == NULL) + return (si); + + si->function = (void *)0; + si->rock1 = (void *)func; + si->rock2 = arg; + + alloc_sicallback(); + return ((void *)si); +} + void alloc_sicallback() { @@ -1179,6 +1609,16 @@ alloc_sicallback() } void +softintr_schedule(vsi) + void *vsi; +{ + struct si_callback *si; + si = vsi; + + add_sicallback(_softintr_callit, si->rock1, si->rock2); +} + +void add_sicallback (function, rock1, rock2) void (*function) __P((void *rock1, void *rock2)); void *rock1, *rock2; @@ -1258,7 +1698,7 @@ rem_sicallback(function) } /* purge the list */ -static void +void call_sicallbacks() { struct si_callback *si; @@ -1632,98 +2072,6 @@ nmihand(frame) } #endif -void -regdump(fp, sbytes) - struct frame *fp; /* must not be register */ - int sbytes; -{ - static int doingdump = 0; - register int i; - int s; - - if (doingdump) - return; - s = spl7(); - doingdump = 1; - printf("pid = %d, pc = %s, ", curproc ? curproc->p_pid : 0, - hexstr(fp->f_pc, 8)); - printf("ps = %s, ", hexstr(fp->f_sr, 4)); - printf("sfc = %s, ", hexstr(getsfc(), 4)); - printf("dfc = %s\n", hexstr(getdfc(), 4)); - printf("Registers:\n "); - for (i = 0; i < 8; i++) - printf(" %d", i); - printf("\ndreg:"); - for (i = 0; i < 8; i++) - printf(" %s", hexstr(fp->f_regs[i], 8)); - printf("\nareg:"); - for (i = 0; i < 8; i++) - printf(" %s", hexstr(fp->f_regs[i+8], 8)); - if (sbytes > 0) { - if (fp->f_sr & PSL_S) { - printf("\n\nKernel stack (%s):", - hexstr((int)(((int *)&fp)-1), 8)); - dumpmem(((int *)&fp)-1, sbytes, 0); - } else { - printf("\n\nUser stack (%s):", hexstr(fp->f_regs[SP], 8)); - dumpmem((int *)fp->f_regs[SP], sbytes, 1); - } - } - doingdump = 0; - splx(s); -} - -extern u_int proc0paddr; -#define KSADDR ((int *)((curproc ? (u_int)curproc->p_addr : proc0paddr) + USPACE - NBPG)) - -static void -dumpmem(ptr, sz, ustack) - register int *ptr; - int sz, ustack; -{ - register int i, val; - - for (i = 0; i < sz; i++) { - if ((i & 7) == 0) - printf("\n%s: ", hexstr((int)ptr, 6)); - else - printf(" "); - if (ustack == 1) { - if ((val = fuword(ptr++)) == -1) - break; - } else { - if (ustack == 0 && - (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1))) - break; - val = *ptr++; - } - printf("%s", hexstr(val, 8)); - } - printf("\n"); -} - -static char * -hexstr(val, len) - register int val; - int len; -{ - static char nbuf[9]; - register int x, i; - - if (len > 8) - return(""); - nbuf[len] = '\0'; - for (i = len-1; i >= 0; --i) { - x = val & 0xF; - if (x > 9) - nbuf[i] = x - 10 + 'A'; - else - nbuf[i] = x + '0'; - val >>= 4; - } - return(nbuf); -} - /* * should only get here, if no standard executable. This can currently * only mean, we're reading an old ZMAGIC file without MID, but since Amiga diff --git a/sys/arch/amiga/amiga/pmap.c b/sys/arch/amiga/amiga/pmap.c index 0b6b66a6cc8..8c0955558be 100644 --- a/sys/arch/amiga/amiga/pmap.c +++ b/sys/arch/amiga/amiga/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.9 1997/09/09 11:05:00 niklas Exp $ */ +/* $OpenBSD: pmap.c,v 1.10 1997/09/18 13:39:36 niklas Exp $ */ /* $NetBSD: pmap.c,v 1.39 1997/06/10 18:26:41 veego Exp $ */ /* @@ -2088,7 +2088,7 @@ vm_offset_t pmap_phys_address(ppn) int ppn; { - return(amiga_ptob(ppn)); + return(m68k_ptob(ppn)); } /* diff --git a/sys/arch/amiga/amiga/trap.c b/sys/arch/amiga/amiga/trap.c index 6ea8e96b9be..e1334bf0208 100644 --- a/sys/arch/amiga/amiga/trap.c +++ b/sys/arch/amiga/amiga/trap.c @@ -1,5 +1,5 @@ -/* $OpenBSD: trap.c,v 1.13 1997/04/10 08:51:04 niklas Exp $ */ -/* $NetBSD: trap.c,v 1.53 1997/01/16 15:30:57 gwr Exp $ */ +/* $OpenBSD: trap.c,v 1.14 1997/09/18 13:39:37 niklas Exp $ */ +/* $NetBSD: trap.c,v 1.56 1997/07/16 00:01:47 is Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -67,6 +67,8 @@ #include <machine/mtpr.h> #include <machine/pte.h> +#include <m68k/fpe/fpu_emulate.h> + #ifdef COMPAT_SUNOS #include <compat/sunos/sunos_syscall.h> extern struct emul emul_sunos; @@ -241,7 +243,7 @@ panictrap(type, code, v, fp) static int panicing = 0; if (panicing++ == 0) { printf("trap type %d, code = %x, v = %x\n", type, code, v); - regdump(fp, 128); + regdump((struct trapframe *)fp, 128); } type &= ~T_USER; #ifdef DEBUG @@ -617,6 +619,22 @@ trap(type, code, v, frame) v = frame.f_pc; break; + + case T_FPEMULI|T_USER: + case T_FPEMULD|T_USER: +#ifdef FPU_EMULATE + i = fpu_emulate(&frame, &p->p_addr->u_pcb.pcb_fpregs); + /* XXX - Deal with tracing? (frame.f_sr & PSL_T) */ + if (i == 0) + break; +#else + printf("pid %d killed: no floating point support\n", p->p_pid); + i = SIGILL; +#endif + typ = ILL_ILLTRP; + v = frame.f_pc; + break; + case T_TRAPVINST|T_USER: ucode = frame.f_format; typ = ILL_ILLTRP; @@ -708,14 +726,12 @@ trap(type, code, v, frame) case T_TRAP15|T_USER: #ifdef COMPAT_SUNOS /* - * SunOS uses Trap #2 for a "CPU cache flush" + * SunOS uses Trap #2 for a "CPU cache flush". * Just flush the on-chip caches and return. - * XXX - Too bad m68k BSD uses trap 2... */ if (p->p_emul == &emul_sunos) { ICIA(); DCIU(); - /* get out fast */ return; } #endif @@ -765,7 +781,8 @@ trap(type, code, v, frame) printf("trapsignal(%d, %d, %d, %x, %x)\n", p->p_pid, i, ucode, v, frame.f_pc); #endif - trapsignal(p, i, ucode, typ, (caddr_t)ucode); + if (i) + trapsignal(p, i, ucode, typ, (caddr_t)ucode); if ((type & T_USER) == 0) return; userret(p, frame.f_pc, sticks); @@ -921,7 +938,7 @@ syscall(code, frame) #ifdef COMPAT_SUNOS /* need new p-value for this */ if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ)) - frame.f_regs[SP] -= sizeof(int); + frame.f_regs[SP] -= sizeof (int); #endif userret(p, frame.f_pc, sticks); #ifdef KTRACE diff --git a/sys/arch/amiga/conf/DRACO b/sys/arch/amiga/conf/DRACO index fdd37d80573..73e3b99b287 100644 --- a/sys/arch/amiga/conf/DRACO +++ b/sys/arch/amiga/conf/DRACO @@ -1,4 +1,4 @@ -# $OpenBSD: DRACO,v 1.9 1997/03/25 16:53:58 niklas Exp $ +# $OpenBSD: DRACO,v 1.10 1997/09/18 13:39:38 niklas Exp $ # $NetBSD: DRACO,v 1.7 1996/12/20 19:18:16 veego Exp $ # @@ -135,11 +135,14 @@ mfcs1 at mfc0 unit 1 # MFC serial #mfcs3 at mfc1 unit 1 #mfcp1 at mfc1 unit 0 -le0 at zbus0 # Lance ethernet. +drbbc0 at mainbus0 # DraCo battery backed clock +drsupio0 at mainbus0 # DraCo superio chip +com* at drsupio? port ? # DraCo serial + +le* at zbus0 # Lance ethernet. ed0 at zbus0 # dp8390 ethernet es0 at zbus0 # SMC 91C90 ethernet qn0 at zbus0 # quicknet ethernet -ae0 at zbus0 # Ariadne ethernet bah* at zbus0 # C= arcnet @@ -160,5 +163,6 @@ pseudo-device pty 16 # pseudo terminals pseudo-device loop # network loopback pseudo-device bpfilter 2 # berkeley packet filters pseudo-device tun 2 +pseudo-device ppp 2 config bsd swap on generic diff --git a/sys/arch/amiga/conf/GENERIC b/sys/arch/amiga/conf/GENERIC index 95ef1b75362..323ee03d096 100644 --- a/sys/arch/amiga/conf/GENERIC +++ b/sys/arch/amiga/conf/GENERIC @@ -1,5 +1,5 @@ -# $OpenBSD: GENERIC,v 1.20 1997/03/25 16:53:56 niklas Exp $ -# $NetBSD: GENERIC,v 1.69 1997/01/17 14:29:42 is Exp $ +# $OpenBSD: GENERIC,v 1.21 1997/09/18 13:39:39 niklas Exp $ +# $NetBSD: GENERIC,v 1.85 1997/08/27 19:32:49 is Exp $ # # GENERIC AMIGA @@ -16,17 +16,24 @@ maxusers 8 # mainboards to support (in addition to Amiga) # option DRACO +option BB060STUPIDROM # You need this, if you have a non-DraCo + # 68060 with an OS ROM up to (at least) + # V40 (OS3.1) and want to boot with the + # bootblock. + # You don't need this if you have a DraCo, + # have no 68060 or NEVER use the bootblock # # processors this kernel should support # -option "M68060" # support for 060 -option "M060SP" # ...and MC68060 support package -option "M68040" # support for 040 +option M68060 # support for 060 +option M060SP # ...and MC68060 support package +option M68040 # support for 040 option FPSP # MC68040 floating point support -option "M68030" # support for 030 -option "M68020" # support for 020/851 +option M68030 # support for 030 +option M68020 # support for 020/851 option FPCOPROC # Support for MC6888[12] (Required) +option FPU_EMULATE # FPU emulation # # File systems @@ -135,13 +142,23 @@ mfcs1 at mfc0 unit 1 # MFC serial #mfcs3 at mfc1 unit 1 #mfcp1 at mfc1 unit 0 -le0 at zbus0 # Lance ethernet. +drbbc0 at mainbus0 # DraCo battery backed clock +drsupio0 at mainbus0 # DraCo superio chip +com* at drsupio? port ? # DraCo serial + +a2kbbc0 at mainbus0 # A2000 battery backed clock +a34kbbc0 at mainbus0 # A3000/A4000 battery backed clock +#aucc* at mainbus0 # Amiga CC audio +#audio* at aucc? + +# Ethernet cards +le* at zbus0 # Lance ethernet. ed0 at zbus0 # dp8390 ethernet es0 at zbus0 # SMC 91C90 ethernet qn0 at zbus0 # quicknet ethernet -ae0 at zbus0 # Ariadne ethernet -bah0 at zbus0 # C= arcnet +# Arcnet +bah* at zbus0 # C= arcnet # scsi stuff, all possible gvpbus* at zbus0 @@ -155,13 +172,13 @@ otgsc0 at zbus0 # 12 gauge scsi zssc0 at zbus0 # Zeus scsi mgnsc0 at zbus0 # Magnum scsi wesc0 at zbus0 # Warp Engine scsi -idesc0 at mainbus0 # A4000 & A1200 IDE afsc0 at zbus0 # A4091 scsi aftsc0 at mainbus0 # A4000T scsi flsc0 at zbus0 # FastlaneZ3 scsi bzsc0 at zbus0 # Blizzard 1230 I,II scsi bztzsc0 at zbus0 # Blizzard 2060 scsi empsc0 at zbus0 # Emplant scsi +idesc0 at mainbus0 # A4000 & A1200 IDE drsc0 at mainbus0 # DraCo scsi scsibus* at gtsc0 @@ -174,13 +191,13 @@ scsibus* at otgsc0 scsibus* at zssc0 scsibus* at mgnsc0 scsibus* at wesc0 -scsibus* at idesc0 scsibus* at afsc0 scsibus* at aftsc0 scsibus* at flsc0 scsibus* at bzsc0 scsibus* at bztzsc0 scsibus* at empsc0 +scsibus* at idesc0 scsibus* at drsc0 # each hard drive from low target to high diff --git a/sys/arch/amiga/conf/Makefile.amiga b/sys/arch/amiga/conf/Makefile.amiga index a67b578207f..9a48571df12 100644 --- a/sys/arch/amiga/conf/Makefile.amiga +++ b/sys/arch/amiga/conf/Makefile.amiga @@ -1,5 +1,5 @@ -# $OpenBSD: Makefile.amiga,v 1.21 1997/09/15 02:40:25 deraadt Exp $ -# $NetBSD: Makefile.amiga,v 1.52 1996/12/01 12:10:07 veego Exp $ +# $OpenBSD: Makefile.amiga,v 1.22 1997/09/18 13:39:39 niklas Exp $ +# $NetBSD: Makefile.amiga,v 1.60 1997/07/23 10:19:42 is Exp $ # Makefile for OpenBSD # @@ -35,8 +35,8 @@ S!= cd ../../../..; pwd .endif AMIGA= $S/arch/amiga -INCLUDES= -nostdinc -I. -I$S/arch -I$S -CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -Dmc68020 -Damiga +INCLUDES= -I. -I$S/arch -I$S -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dmc68020 -Damiga CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ -Wno-uninitialized -Wno-format @@ -83,13 +83,7 @@ LIBCOMPAT= ${COMPATLIB_PROF} # HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< - -DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< -DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< - NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< -NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $< .SUFFIXES: .o .g @@ -128,17 +122,17 @@ LINKFLAGS+= -S %LOAD -assym.h: $S/kern/genassym.sh ${AMIGA}/amiga/genassym.cf - sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \ - ${PARAM} < ${AMIGA}/amiga/genassym.cf > assym.h.tmp && \ - mv -f assym.h.tmp assym.h +assym.h: ${AMIGA}/amiga/genassym.cf $S/kern/genassym.sh + sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \ + < ${AMIGA}/amiga/genassym.cf > assym.h.tmp && \ + mv -f assym.h.tmp assym.h param.c: $S/conf/param.c rm -f param.c cp $S/conf/param.c . param.o: param.c Makefile - ${NORMAL_C_C} + ${NORMAL_C} ioconf.o: ioconf.c ${NORMAL_C} @@ -148,9 +142,10 @@ newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c -clean:: +clean:: cleankernel +cleankernel: rm -f eddep *bsd bsd.gdb tags *.[io] [a-z]*.s \ - [Ee]rrs linterrs makelinks genassym genassym.o assym.h + [Ee]rrs linterrs makelinks assym.h lint: @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB \ @@ -162,11 +157,10 @@ tags: links: egrep '#if' ${CFILES} | sed -f $S/conf/defines | \ - sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ - sort -u | comm -23 - dontlink | \ - sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' \ - > makelinks + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink SRCS= ${AMIGA}/amiga/locore.s \ @@ -177,6 +171,10 @@ depend:: .depend ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${AMIGA}/amiga/locore.s ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES} + sh $S/kern/genassym.sh ${MKDEP} -f assym.dep ${CFLAGS} \ + ${CPPFLAGS} < ${AMIGA}/amiga/genassym.cf + @sed -e 's/.*\.o:.*\.c/assym.h:/' < assym.dep >> .depend + @rm -f assym.dep # depend on root or device configuration autoconf.o conf.o: Makefile @@ -185,7 +183,7 @@ autoconf.o conf.o: Makefile uipc_proto.o vfs_conf.o: Makefile # depend on maxusers -assym.h machdep.o: Makefile +machdep.o: Makefile # depend on CPU configuration amiga_init.o locore.o pmap.o sys_machdep.o bzsc.o flsc.o sbic.o sfas.o: Makefile diff --git a/sys/arch/amiga/conf/RAMDISK b/sys/arch/amiga/conf/RAMDISK index b52bad2548f..5576e390593 100644 --- a/sys/arch/amiga/conf/RAMDISK +++ b/sys/arch/amiga/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.2 1997/05/18 13:18:27 niklas Exp $ +# $OpenBSD: RAMDISK,v 1.3 1997/09/18 13:39:40 niklas Exp $ # # A ramdisk kernel @@ -24,6 +24,7 @@ option FPSP # MC68040 floating point support option "M68030" # support for 030 option "M68020" # support for 020/851 option FPCOPROC # Support for MC6888[12] (Required) +option FPU_EMULATE # FPU emulation # # File systems @@ -141,7 +142,6 @@ le0 at zbus0 # Lance ethernet. ed0 at zbus0 # dp8390 ethernet es0 at zbus0 # SMC 91C90 ethernet qn0 at zbus0 # quicknet ethernet -ae0 at zbus0 # Ariadne ethernet bah0 at zbus0 # C= arcnet diff --git a/sys/arch/amiga/conf/files.amiga b/sys/arch/amiga/conf/files.amiga index 80995864d7c..e05fec2244e 100644 --- a/sys/arch/amiga/conf/files.amiga +++ b/sys/arch/amiga/conf/files.amiga @@ -1,8 +1,9 @@ -# $OpenBSD: files.amiga,v 1.21 1997/05/13 16:07:23 niklas Exp $ -# $NetBSD: files.amiga,v 1.51 1996/12/16 16:17:31 is Exp $ +# $OpenBSD: files.amiga,v 1.22 1997/09/18 13:39:40 niklas Exp $ +# $NetBSD: files.amiga,v 1.62 1997/08/27 19:32:47 is Exp $ + # maxpartitions must be first item in files.${ARCH} -maxpartitions 16 # NOTE THAT AMIGA IS SPECIAL! +maxpartitions 16 maxusers 2 8 64 @@ -23,6 +24,17 @@ file arch/amiga/dev/event.c event device clock attach clock at mainbus file arch/amiga/dev/clock.c +file dev/clock_subr.c + +# A2000 internal hwc +device a2kbbc +attach a2kbbc at mainbus +file arch/amiga/dev/a2kbbc.c a2kbbc + +# A3000/4000 internal hwc +device a34kbbc +attach a34kbbc at mainbus +file arch/amiga/dev/a34kbbc.c a34kbbc # keyboard device kbd: event @@ -39,11 +51,17 @@ device par attach par at mainbus file arch/amiga/dev/par.c par needs-count +# audio +device aucc: audio +attach aucc at mainbus +file arch/amiga/dev/aucc.c aucc needs-flag + # mouse device ms: event attach ms at mainbus file arch/amiga/dev/ms.c ms needs-flag +# floppy device fdc { unit = -1 } attach fdc at mainbus @@ -66,7 +84,7 @@ file arch/amiga/dev/kf_8x8.c ite file arch/amiga/dev/kf_8x11.c kfont_8x11 file arch/amiga/dev/kf_custom.c kfont_custom -# custom chips grf +# custom chips grf (ite0 grf0) device grfcc: grfbus attach grfcc at mainbus file arch/amiga/dev/grf_cc.c grfcc needs-flag @@ -83,52 +101,49 @@ file arch/amiga/dev/grfabs.c grfcc | view file arch/amiga/dev/grfabs_cc.c grfcc | view file arch/amiga/dev/grfabs_ccglb.c grfcc | view -# retina grf +# retina ZII grf (ite1 grf1) device grfrt: grfbus attach grfrt at zbus file arch/amiga/dev/grf_rt.c grfrt needs-flag file arch/amiga/dev/ite_rt.c grfrt & ite -# cirrus grf +# retina ZIII grf (it2 grf2) +device grfrh: grfbus +attach grfrh at zbus +file arch/amiga/dev/grf_rh.c grfrh needs-flag +file arch/amiga/dev/ite_rh.c grfrh & ite + +# cirrus grf (ite3 grf3) device grfcl: grfbus attach grfcl at zbus file arch/amiga/dev/grf_cl.c grfcl needs-flag file arch/amiga/dev/ite_cl.c grfcl & ite -# CyberVison 64 grf -device grfcv: grfbus -attach grfcv at zbus -file arch/amiga/dev/grf_cv.c grfcv needs-flag -file arch/amiga/dev/ite_cv.c grfcv & ite - -# A2410 grf +# A2410 grf (ite4 grf4) device grful: grfbus attach grful at zbus file arch/amiga/dev/grf_ul.c grful needs-flag file arch/amiga/dev/ite_ul.c grful & ite file arch/amiga/dev/grf_ultms.g grful -# retina ZIII grf -device grfrh: grfbus -attach grfrh at zbus -file arch/amiga/dev/grf_rh.c grfrh needs-flag -file arch/amiga/dev/ite_rh.c grfrh & ite +# CyberVison 64 grf (ite5 grf5) +device grfcv: grfbus +attach grfcv at zbus +file arch/amiga/dev/grf_cv.c grfcv needs-flag +file arch/amiga/dev/ite_cv.c grfcv & ite -# Tseng grf +# Tseng grf (ite6 grf6) device grfet: grfbus attach grfet at zbus file arch/amiga/dev/grf_et.c grfet needs-flag file arch/amiga/dev/ite_et.c grfet & ite -# handle gvp's odd autoconf info.. -device gvpbus {} -attach gvpbus at zbus -file arch/amiga/dev/gvpbus.c gvpbus - # device defined in sys/conf/files +# A2065, Ameristar, Ariadne ethernet cards attach le at zbus with le_zbus file arch/amiga/dev/if_le.c le_zbus needs-flag +# Hydra ethernet card device ed: ifnet, ether attach ed at zbus with ed_zbus file arch/amiga/dev/if_ed.c ed_zbus needs-flag @@ -138,18 +153,16 @@ device bah: ifnet, arc attach bah at zbus with bah_zbus file arch/amiga/dev/if_bah.c bah_zbus needs-flag +# CEI A4066 EthernetPLUS device es: ifnet, ether attach es at zbus file arch/amiga/dev/if_es.c es needs-flag +# Quicknet ethernet card device qn: ifnet, ether attach qn at zbus file arch/amiga/dev/if_qn.c qn needs-flag -device ae: ifnet, ether -attach ae at zbus -file arch/amiga/dev/if_ae.c ae needs-count - # A2232 msc serial ports device msc: tty attach msc at zbus @@ -165,22 +178,24 @@ device mfcp attach mfcp at mfc file arch/amiga/dev/mfc.c mfcs | mfcp needs-count -# DraCo internal com port -device drcom: tty -attach drcom at mainbus -file arch/amiga/dev/drcom.c drcom needs-count - +# DraCo superio chip +define supio {port = -1} + +device drsupio: supio +attach drsupio at mainbus +file arch/amiga/dev/drsupio.c drsupio + include "../../../scsi/files.scsi" +# handle gvp's odd autoconf info.. +device gvpbus {} +attach gvpbus at zbus +file arch/amiga/dev/gvpbus.c gvpbus + # wd 33c93 controllers define sbic file arch/amiga/dev/sbic.c sbic -# C= A2091 -device atzsc: scsi, sbic -attach atzsc at zbus -file arch/amiga/dev/atzsc.c atzsc needs-flag - # GVP series II device gtsc: scsi, sbic attach gtsc at gvpbus @@ -191,6 +206,35 @@ device ahsc: scsi, sbic attach ahsc at mainbus file arch/amiga/dev/ahsc.c ahsc needs-flag +# C= A2091 +device atzsc: scsi, sbic +attach atzsc at zbus +file arch/amiga/dev/atzsc.c atzsc needs-flag + +# ncr 5380 controllers +define sci +file arch/amiga/dev/sci.c sci + +# Supra Wordsync II +device wstsc: scsi, sci +attach wstsc at zbus +file arch/amiga/dev/wstsc.c wstsc needs-flag + +# IVS +device ivsc: scsi, sci +attach ivsc at zbus +file arch/amiga/dev/ivsc.c ivsc needs-flag + +# MLH +device mlhsc: scsi, sci +attach mlhsc at zbus +file arch/amiga/dev/mlhsc.c mlhsc needs-flag + +# CSA twelve gauge. +device otgsc: scsi, sci +attach otgsc at zbus +file arch/amiga/dev/otgsc.c otgsc needs-flag + # ncr 57c710 controllers define siop file arch/amiga/dev/siop.c siop @@ -205,17 +249,11 @@ device mgnsc: scsi, siop attach mgnsc at zbus file arch/amiga/dev/mgnsc.c mgnsc needs-flag -# MacroSystems Warp Engine +# MacroSystems USA Warp Engine device wesc: scsi, siop attach wesc at zbus file arch/amiga/dev/wesc.c wesc needs-flag - -# MacroSystem DraCo internal -device drsc: scsi, siop -attach drsc at mainbus -file arch/amiga/dev/drsc.c drsc needs-flag - # C= A4091 device afsc: scsi, siop attach afsc at zbus @@ -223,35 +261,6 @@ device aftsc: scsi, siop attach aftsc at mainbus file arch/amiga/dev/afsc.c afsc | aftsc needs-flag -# ncr 5380 controllers -define sci -file arch/amiga/dev/sci.c sci - -# Supra Wordsync II -device wstsc: scsi, sci -attach wstsc at zbus -file arch/amiga/dev/wstsc.c wstsc needs-flag - -# IVS -device ivsc: scsi, sci -attach ivsc at zbus -file arch/amiga/dev/ivsc.c ivsc needs-flag - -# CSA twelve gauge. -device otgsc: scsi, sci -attach otgsc at zbus -file arch/amiga/dev/otgsc.c otgsc needs-flag - -# MLH -device mlhsc: scsi, sci -attach mlhsc at zbus -file arch/amiga/dev/mlhsc.c mlhsc needs-flag - -# EMPLANT -device empsc: scsi, sci -attach empsc at zbus -file arch/amiga/dev/empsc.c empsc needs-flag - # Emulex ESP216 & FAS216 controllers define sfas file arch/amiga/dev/sfas.c sfas @@ -271,11 +280,26 @@ device bztzsc: scsi, sfas attach bztzsc at zbus file arch/amiga/dev/bztzsc.c bztzsc needs-flag +# EMPLANT +device empsc: scsi, sci +attach empsc at zbus +file arch/amiga/dev/empsc.c empsc needs-flag + # Amiga 4000/1200 IDE masquerading as SCSI device idesc: scsi attach idesc at mainbus file arch/amiga/dev/idesc.c idesc needs-flag +# MacroSystem DraCo internal +device drsc: scsi, siop +attach drsc at mainbus +file arch/amiga/dev/drsc.c drsc needs-flag + +# MacroSystem DraCo internal DS2404 hwc +device drbbc +attach drbbc at mainbus +file arch/amiga/dev/drbbc.c drbbc + # # Machine-independent ATAPI drivers # @@ -310,7 +334,13 @@ device isaed: ifnet, ether attach isaed at isa with isaed_isa file arch/amiga/isa/if_isaed.c isaed & isaed_isa needs-flag +# DraCo serial port +attach com at supio with com_supio +file arch/amiga/dev/com_supio.c com_supio + # list of standard files... +include "arch/m68k/fpe/files.fpe" + file dev/cons.c ite | ser file dev/cninit.c ite | ser file arch/amiga/amiga/amiga_init.c diff --git a/sys/arch/amiga/dev/a2kbbc.c b/sys/arch/amiga/dev/a2kbbc.c new file mode 100644 index 00000000000..16081b80221 --- /dev/null +++ b/sys/arch/amiga/dev/a2kbbc.c @@ -0,0 +1,248 @@ +/* $OpenBSD: a2kbbc.c,v 1.1 1997/09/18 13:39:41 niklas Exp $ */ +/* $NetBSD: a2kbbc.c,v 1.3 1997/07/23 10:19:44 is Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: clock.c 1.18 91/01/21$ + * + * @(#)clock.c 7.6 (Berkeley) 5/7/91 + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <machine/psl.h> +#include <machine/cpu.h> +#include <amiga/amiga/device.h> +#include <amiga/amiga/custom.h> +#include <amiga/amiga/cia.h> +#include <amiga/dev/rtc.h> +#include <amiga/dev/zbusvar.h> + +#include <dev/clock_subr.h> + +int a2kbbc_match __P((struct device *, void *, void *)); +void a2kbbc_attach __P((struct device *, struct device *, void *)); + +struct cfattach a2kbbc_ca = { + sizeof(struct device), a2kbbc_match, a2kbbc_attach +}; + +struct cfdriver a2kbbc_cd = { + NULL, "a2kbbc", DV_DULL, NULL, 0 +}; + +void *a2kclockaddr; +time_t a2gettod __P((void)); +int a2settod __P((time_t)); + +int +a2kbbc_match(pdp, match, auxp) + struct device *pdp; + void *match; + void *auxp; +{ + struct cfdata *cfp = match; + + if (!matchname("a2kbbc", auxp)) + return (0); + + if (cfp->cf_unit != 0) + return (0); /* only one of us please */ + + if (is_a1200() || is_a3000() || is_a4000() +#ifdef DRACO + || is_draco() +#endif + ) + return (0); + + a2kclockaddr = (void *)ztwomap(0xdc0000); + if (a2gettod() == 0) + return (0); + + return (1); +} + +/* + * Attach us to the rtc function pointers. + */ +void +a2kbbc_attach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ + printf("\n"); + a2kclockaddr = (void *)ztwomap(0xdc0000); + + gettod = a2gettod; + settod = a2settod; +} + +time_t +a2gettod() +{ + struct rtclock2000 *rt; + struct clock_ymdhms dt; + time_t secs; + int i; + + rt = a2kclockaddr; + + /* + * hold clock + */ + rt->control1 |= A2CONTROL1_HOLD; + i = 0x1000; + while (rt->control1 & A2CONTROL1_BUSY && i--) + ; + if (rt->control1 & A2CONTROL1_BUSY) + return (0); /* Give up and say it's not there */ + + /* Copy the info. Careful about the order! */ + dt.dt_sec = rt->second1 * 10 + rt->second2; + dt.dt_min = rt->minute1 * 10 + rt->minute2; + dt.dt_hour = (rt->hour1 & 3) * 10 + rt->hour2; + dt.dt_day = rt->day1 * 10 + rt->day2; + dt.dt_mon = rt->month1 * 10 + rt->month2; + dt.dt_year = rt->year1 * 10 + rt->year2; + dt.dt_wday = rt->weekday; + + /* + * The oki clock chip has a register to put the clock into + * 12/24h mode. + * + * clockmode | A2HOUR1_PM + * 24h 12h | am = 0, pm = 1 + * --------------------------------- + * 0 12 | 0 + * 1 1 | 0 + * .. .. | 0 + * 11 11 | 0 + * 12 12 | 1 + * 13 1 | 1 + * .. .. | 1 + * 23 11 | 1 + * + */ + + if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { + if ((rt->hour1 & A2HOUR1_PM) == 0 && dt.dt_hour == 12) + dt.dt_hour = 0; + else if ((rt->hour1 & A2HOUR1_PM) && dt.dt_hour != 12) + dt.dt_hour += 12; + } + + /* + * release the clock + */ + rt->control1 &= ~A2CONTROL1_HOLD; + + dt.dt_year += CLOCK_BASE_YEAR; + + if ((dt.dt_hour > 23) || + (dt.dt_day > 31) || + (dt.dt_mon > 12) || + (dt.dt_year < STARTOFTIME) || (dt.dt_year > 2036)) + return (0); + + secs = clock_ymdhms_to_secs(&dt); + return (secs); +} + +int +a2settod(secs) + time_t secs; +{ + struct rtclock2000 *rt; + struct clock_ymdhms dt; + int ampm, i; + + rt = a2kclockaddr; + /* + * there seem to be problems with the bitfield addressing + * currently used.. + */ + if (! rt) + return (0); + + clock_secs_to_ymdhms(secs, &dt); + dt.dt_year -= CLOCK_BASE_YEAR; + + /* + * hold clock + */ + rt->control1 |= A2CONTROL1_HOLD; + i = 0x1000; + while (rt->control1 & A2CONTROL1_BUSY && i--) + ; + if (rt->control1 & A2CONTROL1_BUSY) + return (0); /* Give up and say it's not there */ + + ampm = 0; + if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { + if (dt.dt_hour >= 12) { + ampm = A2HOUR1_PM; + if (dt.dt_hour != 12) + dt.dt_hour -= 12; + } else if (dt.dt_hour == 0) { + dt.dt_hour = 12; + } + } + rt->hour1 = (dt.dt_hour / 10) | ampm; + rt->hour2 = dt.dt_hour % 10; + rt->second1 = dt.dt_sec / 10; + rt->second2 = dt.dt_sec % 10; + rt->minute1 = dt.dt_min / 10; + rt->minute2 = dt.dt_min % 10; + rt->day1 = dt.dt_day / 10; + rt->day2 = dt.dt_day % 10; + rt->month1 = dt.dt_mon / 10; + rt->month2 = dt.dt_mon % 10; + rt->year1 = dt.dt_year / 10; + rt->year2 = dt.dt_year % 10; + rt->weekday = dt.dt_wday; + + /* + * release the clock + */ + rt->control2 &= ~A2CONTROL1_HOLD; + + return (1); +} diff --git a/sys/arch/amiga/dev/a34kbbc.c b/sys/arch/amiga/dev/a34kbbc.c new file mode 100644 index 00000000000..3f4cc8af7db --- /dev/null +++ b/sys/arch/amiga/dev/a34kbbc.c @@ -0,0 +1,188 @@ +/* $OpenBSD: a34kbbc.c,v 1.1 1997/09/18 13:39:42 niklas Exp $ */ +/* $NetBSD: a34kbbc.c,v 1.1 1997/07/19 00:01:42 is Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: clock.c 1.18 91/01/21$ + * + * @(#)clock.c 7.6 (Berkeley) 5/7/91 + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <machine/psl.h> +#include <machine/cpu.h> +#include <amiga/amiga/device.h> +#include <amiga/amiga/custom.h> +#include <amiga/amiga/cia.h> +#include <amiga/dev/rtc.h> +#include <amiga/dev/zbusvar.h> + +#include <dev/clock_subr.h> + +int a34kbbc_match __P((struct device *, void *, void *)); +void a34kbbc_attach __P((struct device *, struct device *, void *)); + +struct cfattach a34kbbc_ca = { + sizeof(struct device), a34kbbc_match, a34kbbc_attach +}; + +struct cfdriver a34kbbc_cd = { + NULL, "a34kbbc", DV_DULL, NULL, 0 +}; + + +void *a34kclockaddr; +time_t a3gettod __P((void)); +int a3settod __P((time_t)); + +int +a34kbbc_match(pdp, match, auxp) + struct device *pdp; + void *match; + void *auxp; +{ + struct cfdata *cfp = match; + + if (!matchname("a34kbbc", auxp)) + return(0); + + if (cfp->cf_unit) + return(0); /* only one of us please */ + + if (!(is_a3000() || is_a4000())) + return(0); + + a34kclockaddr = (void *)ztwomap(0xdc0000); + if (a3gettod() == 0) + return(0); + + return(1); +} + +/* + * Attach us to the rtc function pointers. + */ +void +a34kbbc_attach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ + printf("\n"); + a34kclockaddr = (void *)ztwomap(0xdc0000); + + gettod = a3gettod; + settod = a3settod; +} + +time_t +a3gettod() +{ + struct rtclock3000 *rt; + struct clock_ymdhms dt; + time_t secs; + + rt = a34kclockaddr; + + /* hold clock */ + rt->control1 = A3CONTROL1_HOLD_CLOCK; + + /* Copy the info. Careful about the order! */ + dt.dt_sec = rt->second1 * 10 + rt->second2; + dt.dt_min = rt->minute1 * 10 + rt->minute2; + dt.dt_hour = rt->hour1 * 10 + rt->hour2; + dt.dt_wday = rt->weekday; + dt.dt_day = rt->day1 * 10 + rt->day2; + dt.dt_mon = rt->month1 * 10 + rt->month2; + dt.dt_year = rt->year1 * 10 + rt->year2; + + dt.dt_year += CLOCK_BASE_YEAR; + + /* let it run again.. */ + rt->control1 = A3CONTROL1_FREE_CLOCK; + + if ((dt.dt_hour > 23) || + (dt.dt_wday > 6) || + (dt.dt_day > 31) || + (dt.dt_mon > 12) || + (dt.dt_year < STARTOFTIME) || (dt.dt_year > 2036)) + return (0); + + secs = clock_ymdhms_to_secs(&dt); + return (secs); +} + +int +a3settod(secs) + time_t secs; +{ + struct rtclock3000 *rt; + struct clock_ymdhms dt; + + rt = a34kclockaddr; + /* + * there seem to be problems with the bitfield addressing + * currently used.. + */ + + if (! rt) + return (0); + + clock_secs_to_ymdhms(secs, &dt); + dt.dt_year -= CLOCK_BASE_YEAR; + + rt->control1 = A3CONTROL1_HOLD_CLOCK; + rt->second1 = dt.dt_sec / 10; + rt->second2 = dt.dt_sec % 10; + rt->minute1 = dt.dt_min / 10; + rt->minute2 = dt.dt_min % 10; + rt->hour1 = dt.dt_hour / 10; + rt->hour2 = dt.dt_hour % 10; + rt->weekday = dt.dt_wday; + rt->day1 = dt.dt_day / 10; + rt->day2 = dt.dt_day % 10; + rt->month1 = dt.dt_mon / 10; + rt->month2 = dt.dt_mon % 10; + rt->year1 = dt.dt_year / 10; + rt->year2 = dt.dt_year % 10; + rt->control1 = A3CONTROL1_FREE_CLOCK; + + return (1); +} diff --git a/sys/arch/amiga/dev/aucc.c b/sys/arch/amiga/dev/aucc.c new file mode 100644 index 00000000000..ba60c5b9ba8 --- /dev/null +++ b/sys/arch/amiga/dev/aucc.c @@ -0,0 +1,978 @@ +/* $OpenBSD: aucc.c,v 1.1 1997/09/18 13:39:42 niklas Exp $ */ +/* $NetBSD: aucc.c,v 1.18 1997/08/24 22:31:23 augustss Exp $ */ +#undef AUDIO_DEBUG +/* + * Copyright (c) 1997 Stephan Thesing + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Stephan Thesing. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aucc.h" +#if NAUCC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/device.h> +#include <sys/proc.h> +#include <machine/cpu.h> + +#include <sys/audioio.h> +#include <dev/audio_if.h> +#include <amiga/amiga/cc.h> +#include <amiga/amiga/custom.h> +#include <amiga/amiga/device.h> +#include <amiga/dev/auccvar.h> + +#ifdef LEV6_DEFER +#define AUCC_MAXINT 3 +#define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2) +#else +#define AUCC_MAXINT 4 +#define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3) +#endif +/* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */ +#define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3) + +#ifdef AUDIO_DEBUG +/*extern printf __P((const char *,...));*/ +int auccdebug = 1; +#define DPRINTF(x) if (auccdebug) printf x +#else +#define DPRINTF(x) +#endif + +#ifdef splaudio +#undef splaudio +#endif + +#define splaudio() spl4(); + +/* clock frequency.. */ +extern int eclockfreq; + +/* hw audio ch */ +extern struct audio_channel channel[4]; + +/* + * Software state. + */ +struct aucc_softc { + struct device sc_dev; /* base device */ + + int sc_open; /* single use device */ + aucc_data_t sc_channel[4]; /* per channel freq, ... */ + u_int sc_encoding; /* encoding AUDIO_ENCODING_.*/ + int sc_channels; /* # of channels used */ + + int sc_intrcnt; /* interrupt count */ + int sc_channelmask; /* which channels are used ? */ +}; + +/* interrupt interfaces */ +void aucc_inthdl __P((int)); + +/* forward declarations */ +int init_aucc __P((struct aucc_softc *)); +u_int freqtoper __P((u_int)); +u_int pertofreq __P((u_int)); + +/* autoconfiguration driver */ +void auccattach __P((struct device *, struct device *, void *)); +int auccmatch __P((struct device *, void *, void *)); + +struct cfattach aucc_ca = { + sizeof(struct aucc_softc), + auccmatch, + auccattach +}; + +struct cfdriver aucc_cd = { + NULL, "aucc", DV_DULL, NULL, 0 +}; + +struct audio_device aucc_device = { + "Amiga-audio", + "x", + "aucc" +}; + +struct aucc_softc *aucc = NULL; + +unsigned char ulaw_to_lin[] = { + 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e, + 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe, + 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, + 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, + 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, + 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, + 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, + 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41, + 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, + 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, + 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, + 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, + 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, + 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, + 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * Define our interface to the higher level audio driver. + */ +int aucc_open __P((void *, int)); +void aucc_close __P((void *)); +int aucc_set_out_sr __P((void *, u_long)); +int aucc_query_encoding __P((void *, struct audio_encoding *)); +int aucc_round_blocksize __P((void *, int)); +int aucc_set_out_port __P((void *, int)); +int aucc_get_out_port __P((void *)); +int aucc_set_in_port __P((void *, int)); +int aucc_get_in_port __P((void *)); +int aucc_commit_settings __P((void *)); +int aucc_start_output __P((void *, void *, int, void (*)(void *), + void *)); +int aucc_start_input __P((void *, void *, int, void (*)(void *), + void *)); +int aucc_halt_output __P((void *)); +int aucc_halt_input __P((void *)); +int aucc_cont_output __P((void *)); +int aucc_cont_input __P((void *)); +int aucc_getdev __P((void *, struct audio_device *)); +int aucc_set_port __P((void *, mixer_ctrl_t *)); +int aucc_get_port __P((void *, mixer_ctrl_t *)); +int aucc_query_devinfo __P((void *, mixer_devinfo_t *)); +void aucc_encode __P((int, int, int, u_char *, u_short **)); +int aucc_set_params __P((void *, int, int, + struct audio_params *, struct audio_params *)); +int aucc_get_props __P((void *)); + +struct audio_hw_if sa_hw_if = { + aucc_open, + aucc_close, + NULL, + aucc_query_encoding, + aucc_set_params, + aucc_round_blocksize, + aucc_set_out_port, + aucc_get_out_port, + aucc_set_in_port, + aucc_get_in_port, + aucc_commit_settings, + NULL, + NULL, + aucc_start_output, + aucc_start_input, + aucc_halt_output, + aucc_halt_input, + aucc_cont_output, + aucc_cont_input, + NULL, + aucc_getdev, + NULL, + aucc_set_port, + aucc_get_port, + aucc_query_devinfo, + NULL, + NULL, + NULL, + NULL, + aucc_get_props, +}; + +/* autoconfig routines */ + +int +auccmatch(pdp, match, aux) + struct device *pdp; + void *match; + void *aux; +{ + struct cfdata *cfp = match; + + if (matchname((char *)aux, "aucc") && +#ifdef DRACO + !is_draco() && +#endif + (cfp->cf_unit == 0)) + return (1); + + return (0); +} + +/* + * Audio chip found. + */ +void +auccattach(parent, self, args) + struct device *parent, *self; + void *args; +{ + struct aucc_softc *sc = (struct aucc_softc *)self; + int i; + + printf("\n"); + + if((i = init_aucc(sc)) != 0) { + printf("audio: no chipmem\n"); + return; + } + + audio_attach_mi(&sa_hw_if, 0, sc, &sc->sc_dev); +} + +int +init_aucc(sc) + struct aucc_softc *sc; +{ + int i, err=0; + + /* init values per channel */ + for (i = 0; i < 4; i++) { + sc->sc_channel[i].nd_freq = 8000; + sc->sc_channel[i].nd_per = freqtoper(8000); + sc->sc_channel[i].nd_busy = 0; + sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE * 2); + if (sc->sc_channel[i].nd_dma == NULL) + err = 1; + sc->sc_channel[i].nd_dmalength = 0; + sc->sc_channel[i].nd_volume = 64; + sc->sc_channel[i].nd_intr = NULL; + sc->sc_channel[i].nd_intrdata = NULL; + sc->sc_channel[i].nd_doublebuf = 0; + DPRINTF(("dma buffer for channel %d is %p\n", i, + sc->sc_channel[i].nd_dma)); + + } + + if (err) { + for(i = 0; i < 4; i++) + if (sc->sc_channel[i].nd_dma) + free_chipmem(sc->sc_channel[i].nd_dma); + } + + sc->sc_channels = 1; + sc->sc_channelmask = 0xf; + + /* clear interrupts and dma: */ + custom.intena = AUCC_ALLINTF; + custom.dmacon = AUCC_ALLDMAF; + + sc->sc_encoding = AUDIO_ENCODING_ULAW; + + return (err); + +} + +int +aucc_open(addr, flags) + void *addr; + int flags; +{ + struct aucc_softc *sc = addr; + int i; + + DPRINTF(("sa_open: unit %p\n",sc)); + + if (sc->sc_open) + return (EBUSY); + sc->sc_open = 1; + for (i = 0; i < AUCC_MAXINT; i++) { + sc->sc_channel[i].nd_intr = NULL; + sc->sc_channel[i].nd_intrdata = NULL; + } + aucc = sc; + sc->sc_channelmask = 0xf; + + DPRINTF(("saopen: ok -> sc=0x%p\n",sc)); + + return (0); +} + +void +aucc_close(addr) + void *addr; +{ + struct aucc_softc *sc = addr; + + DPRINTF(("sa_close: sc=0x%p\n", sc)); + /* + * halt i/o, clear open flag, and done. + */ + aucc_halt_output(sc); + sc->sc_open = 0; + + DPRINTF(("sa_close: closed.\n")); +} + +int +aucc_set_out_sr(addr, sr) + void *addr; + u_long sr; +{ + struct aucc_softc *sc = addr; + u_long per; + int i; + + per = freqtoper(sr); + if (per > 0xffff) + return (EINVAL); + sr = pertofreq(per); + + for (i = 0; i < 4; i++) { + sc->sc_channel[i].nd_freq = sr; + sc->sc_channel[i].nd_per = per; + } + + return (0); +} + +int +aucc_query_encoding(addr, fp) + void *addr; + struct audio_encoding *fp; +{ + switch (fp->index) { + case 0: + strcpy(fp->name, AudioElinear); + fp->encoding = AUDIO_ENCODING_SLINEAR; + fp->precision = 8; + fp->flags = 0; + break; + case 1: + strcpy(fp->name, AudioEmulaw); + fp->encoding = AUDIO_ENCODING_ULAW; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + break; + + case 2: + strcpy(fp->name, AudioEulinear); + fp->encoding = AUDIO_ENCODING_ULINEAR; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + break; + + default: + return (EINVAL); + /*NOTREACHED*/ + } + return (0); +} + +int +aucc_set_params(addr, setmode, usemode, p, r) + void *addr; + int setmode, usemode; + struct audio_params *p, *r; +{ + struct aucc_softc *sc = addr; + +#if 0 + if (setmode & AUMODE_RECORD) + return (ENXIO); +#endif + +#ifdef AUCCDEBUG + printf("aucc_set_params(setmode 0x%x, usemode 0x%x, enc %d, bits %d," + "chn %d, sr %ld)\n", + setmode, usemode, p->encoding, p->precision, p->channels, + p->sample_rate); +#endif + + switch (p->encoding) { + case AUDIO_ENCODING_ULAW: + case AUDIO_ENCODING_SLINEAR: + case AUDIO_ENCODING_SLINEAR_BE: + case AUDIO_ENCODING_SLINEAR_LE: + case AUDIO_ENCODING_ULINEAR_BE: + case AUDIO_ENCODING_ULINEAR_LE: + break; + + default: + return EINVAL; + /* NOTREADCHED */ + } + + if (p->precision != 8) + return (EINVAL); + + if ((p->channels < 1) || (p->channels > 4)) + return (EINVAL); + + sc->sc_channels = p->channels; + sc->sc_encoding = p->encoding; + + return (aucc_set_out_sr(addr, p->sample_rate)); +} + +int +aucc_round_blocksize(addr, blk) + void *addr; + int blk; +{ + /* round up to even size */ + return (blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk); +} + +int +aucc_set_out_port(addr, port) /* can set channels */ + void *addr; + int port; +{ + struct aucc_softc *sc = addr; + + /* port is mask for channels 0..3 */ + if ((port < 0) || (port > 15)) + return (EINVAL); + + sc->sc_channelmask = port; + + return (0); +} + +int +aucc_get_out_port(addr) + void *addr; +{ + struct aucc_softc *sc = addr; + + return (sc->sc_channelmask); +} + +int +aucc_set_in_port(addr, port) + void *addr; + int port; +{ + return (EINVAL); /* no input possible */ +} + +int +aucc_get_in_port(addr) + void *addr; +{ + return (0); +} + +int +aucc_commit_settings(addr) + void *addr; +{ + struct aucc_softc *sc = addr; + int i; + + DPRINTF(("sa_commit.\n")); + + for (i = 0; i < 4; i++) { + custom.aud[i].vol = sc->sc_channel[i].nd_volume; + custom.aud[i].per = sc->sc_channel[i].nd_per; + } + + DPRINTF(("commit done\n")); + + return (0); +} + +static int masks[4] = {1, 3, 7, 15}; /* masks for n first channels */ +static int masks2[4] = {1, 2, 4, 8}; + +int +aucc_start_output(addr, p, cc, intr, arg) + void *addr; + void *p; + int cc; + void (*intr) __P((void *)); + void *arg; +{ + struct aucc_softc *sc; + int mask; + int i, j, k; + u_short *dmap[4]; + u_char *pp; + + sc = addr; + mask = sc->sc_channelmask; + + dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL; + + DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg)); + + if (sc->sc_channels > 1) + mask &= masks[sc->sc_channels - 1]; + /* we use first sc_channels channels */ + if (mask == 0) /* active and used channels are disjoint */ + return (EINVAL); + + for (i = 0; i < 4; i++) { /* channels available ? */ + if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy)) + return (EBUSY); /* channel is busy */ + if (channel[i].isaudio == -1) + return (EBUSY); /* system uses them */ + } + + /* enable interrupt on 1st channel */ + for (i= j = 0; i < AUCC_MAXINT; i++) { + if (masks2[i] & mask) { + DPRINTF(("first channel is %d\n", i)); + j = i; + sc->sc_channel[i].nd_intr = intr; + sc->sc_channel[i].nd_intrdata = arg; + break; + } + } + + DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1], + dmap[2], dmap[3], mask)); + + /* + * disable ints, dma for channels, until all parameters set + * XXX dont disable DMA! custom.dmacon = mask; + */ + custom.intreq = mask << INTB_AUD0; + custom.intena = mask << INTB_AUD0; + + /* copy data to dma buffer */ + + pp = (u_char *)p; + + if (sc->sc_channels == 1) { + dmap[0] = dmap[1] = dmap[2] = dmap[3] = + sc->sc_channel[j].nd_dma; + } else { + for (k = 0; k < 4; k++) { + if (masks2[k+j] & mask) + dmap[k] = sc->sc_channel[k+j].nd_dma; + } + } + + sc->sc_channel[j].nd_doublebuf ^= 1; + if (sc->sc_channel[j].nd_doublebuf) { + dmap[0] += AUDIO_BUF_SIZE / sizeof (u_short); + dmap[1] += AUDIO_BUF_SIZE / sizeof (u_short); + dmap[2] += AUDIO_BUF_SIZE / sizeof (u_short); + dmap[3] += AUDIO_BUF_SIZE / sizeof (u_short); + } + + aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap); + + /* dma buffers: we use same buffer 4 all channels */ + /* write dma location and length */ + for (i = k = 0; i < 4; i++) { + if (masks2[i] & mask) { + DPRINTF(("turning channel %d on\n", i)); + /* sc->sc_channel[i].nd_busy = 1;*/ + channel[i].isaudio = 1; + channel[i].play_count = 1; + channel[i].handler = NULL; + custom.aud[i].per = sc->sc_channel[i].nd_per; + custom.aud[i].vol = sc->sc_channel[i].nd_volume; + custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]); + custom.aud[i].len = cc / (sc->sc_channels * 2); + sc->sc_channel[i].nd_mask = mask; + DPRINTF(("per is %d, vol is %d, len is %d\n",\ + sc->sc_channel[i].nd_per, + sc->sc_channel[i].nd_volume, cc >> 1)); + + } + } + + channel[j].handler = aucc_inthdl; + + /* enable ints */ + custom.intena = INTF_SETCLR|INTF_INTEN|(masks2[j] << INTB_AUD0); + + DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0))); + + /* enable dma */ + custom.dmacon = DMAF_SETCLR|DMAF_MASTER|mask; + + DPRINTF(("enabled dma, mask=0x%x\n",mask)); + + return (0); +} + +/* ARGSUSED */ +int +aucc_start_input(addr, p, cc, intr, arg) + void *addr; + void *p; + int cc; + void (*intr) __P((void *)); + void *arg; +{ + return (ENXIO); /* no input */ +} + +int +aucc_halt_output(addr) + void *addr; +{ + struct aucc_softc *sc = addr; + int i; + + /* XXX only halt, if input is also halted ?? */ + /* stop dma, etc */ + custom.intena = AUCC_ALLINTF; + custom.dmacon = AUCC_ALLDMAF; + /* mark every busy unit idle */ + for (i = 0; i < 4; i++) { + sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0; + channel[i].isaudio = 0; + channel[i].play_count = 0; + } + + return (0); +} + +int +aucc_halt_input(addr) + void *addr; +{ + /* no input */ + + return (ENXIO); +} + +int +aucc_cont_output(addr) + void *addr; +{ + DPRINTF(("aucc_cont_output: never called, what should it do?!\n")); + /* reenable DMA XXX */ + return (ENXIO); +} + +int +aucc_cont_input(addr) + void *addr; +{ + DPRINTF(("aucc_cont_input: never called, what should it do?!\n")); + return (0); +} + +int +aucc_getdev(addr, retp) + void *addr; + struct audio_device *retp; +{ + *retp = aucc_device; + return (0); +} + +int +aucc_set_port(addr, cp) + void *addr; + mixer_ctrl_t *cp; +{ + struct aucc_softc *sc = addr; + int i,j; + + DPRINTF(("aucc_set_port: port=%d", cp->dev)); + + switch (cp->type) { + case AUDIO_MIXER_SET: + if (cp->dev != AUCC_CHANNELS) + return (EINVAL); + i = cp->un.mask; + if ((i < 1) || (i > 15)) + return (EINVAL); + sc->sc_channelmask = i; + break; + + case AUDIO_MIXER_VALUE: + i = cp->un.value.num_channels; + if ((i < 1) || (i > 4)) + return (EINVAL); + +#ifdef __XXXwhatsthat + if (cp->dev != AUCC_VOLUME) + return (EINVAL); +#endif + + /* set volume for channel 0..i-1 */ + if (i > 1) + for (j = 0; j < i; j++) + sc->sc_channel[j].nd_volume = + cp->un.value.level[j] >> 2; + else if (sc->sc_channels > 1) + for (j = 0; j < sc->sc_channels; j++) + sc->sc_channel[j].nd_volume = + cp->un.value.level[0] >> 2; + else + for (j = 0; j < 4; j++) + sc->sc_channel[j].nd_volume = + cp->un.value.level[0] >> 2; + break; + + default: + return (EINVAL); + break; + } + return (0); +} + +int +aucc_get_port(addr, cp) + void *addr; + mixer_ctrl_t *cp; +{ + struct aucc_softc *sc = addr; + int i, j; + + DPRINTF(("aucc_get_port: port=%d", cp->dev)); + + switch (cp->type) { + case AUDIO_MIXER_SET: + if (cp->dev != AUCC_CHANNELS) + return (EINVAL); + cp->un.mask = sc->sc_channelmask; + break; + + case AUDIO_MIXER_VALUE: + i = cp->un.value.num_channels; + if ((i < 1) || (i > 4)) + return (EINVAL); + + for (j = 0; j < i; j++) + cp->un.value.level[j] = + (sc->sc_channel[j].nd_volume << 2) + + (sc->sc_channel[j].nd_volume >> 4); + break; + + default: + return (EINVAL); + } + return (0); +} + +int +aucc_get_props(addr) + void *addr; +{ + return 0; +} + +int +aucc_query_devinfo(addr, dip) + void *addr; + register mixer_devinfo_t *dip; +{ + int i; + + switch (dip->index) { + case AUCC_CHANNELS: + dip->type = AUDIO_MIXER_SET; + dip->mixer_class = AUCC_OUTPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strcpy(dip->label.name, AudioNspeaker); + for (i = 0; i < 16; i++) { + sprintf(dip->un.s.member[i].label.name, + "channelmask%d", i); + dip->un.s.member[i].mask = i; + } + dip->un.s.num_mem = 16; + break; + + case AUCC_VOLUME: + dip->type = AUDIO_MIXER_VALUE; + dip->mixer_class = AUCC_OUTPUT_CLASS; + dip->prev = dip->next = AUDIO_MIXER_LAST; + strcpy(dip->label.name, AudioNspeaker); + dip->un.v.num_channels = 4; + strcpy(dip->un.v.units.name, AudioNvolume); + break; + + case AUCC_OUTPUT_CLASS: + dip->type = AUDIO_MIXER_CLASS; + dip->mixer_class = AUCC_OUTPUT_CLASS; + dip->next = dip->prev = AUDIO_MIXER_LAST; + strcpy(dip->label.name, AudioCOutputs); + break; + default: + return (ENXIO); + /*NOTREACHED*/ + } + + DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); + + return (0); +} + + +/* audio int handler */ +void +aucc_inthdl(ch) + int ch; +{ + int i; + int mask = aucc->sc_channel[ch].nd_mask; + + /* + * For all channels in this maskgroup: + * disable dma, int + * mark idle + */ + DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask)); + + custom.intreq = mask << INTB_AUD0; /* clear request */ + + /* + * XXX: maybe we can leave ints and/or DMA on, if another sample has + * to be played? + */ + custom.intena = mask << INTB_AUD0; + + /* + * XXX custom.dmacon = mask; NO!!! + */ + for (i = 0; i < 4; i++) { + if (masks2[i] && mask) { + DPRINTF(("marking channel %d idle\n", i)); + aucc->sc_channel[i].nd_busy = 0; + aucc->sc_channel[i].nd_mask = 0; + channel[i].isaudio = channel[i].play_count = 0; + } + } + + /* call handler */ + if (aucc->sc_channel[ch].nd_intr) { + DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr)); + (*(aucc->sc_channel[ch].nd_intr))( + aucc->sc_channel[ch].nd_intrdata); + } else + DPRINTF(("zero int handler\n")); + DPRINTF(("ints done\n")); +} + +/* transform frequency to period, adjust bounds */ +u_int +freqtoper(freq) + u_int freq; +{ + u_int per = eclockfreq * 5 / freq; + + if (per < 124) + per = 124; /* must have at least 124 ticks between samples */ + + return per; +} + +/* transform period to frequency */ +u_int +pertofreq(per) + u_int per; +{ + u_int freq = eclockfreq * 5 / per; + + return freq; +} + +void +aucc_encode(enc, channels, i, p, dmap) + int enc, channels, i; + u_char *p; + u_short **dmap; +{ + char *q, *r, *s, *t; + int off; + u_char *tab; +#ifdef AUCCDEBUG + static int debctl = 6; +#endif + + off = 0; + tab = NULL; + +#ifdef AUCCDEBUG + if (--debctl >= 0) + printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n", + enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]); +#endif + + switch (enc) { + case AUDIO_ENCODING_ULAW: + tab = ulaw_to_lin; + break; + case AUDIO_ENCODING_ULINEAR_BE: + case AUDIO_ENCODING_ULINEAR_LE: + off = -128; + break; + case AUDIO_ENCODING_SLINEAR_BE: + case AUDIO_ENCODING_SLINEAR_LE: + break; + default: + return; + } + + q = (char *)dmap[0]; + r = (char *)dmap[1]; + s = (char *)dmap[2]; + t = (char *)dmap[3]; + + if (tab) + while (i) { + switch (channels) { + case 4: *t++ = tab[*p++]; + case 3: *s++ = tab[*p++]; + case 2: *r++ = tab[*p++]; + case 1: *q++ = tab[*p++]; + } + i -= channels; + } + else + while (i) { + switch (channels) { + case 4: *t++ = *p++ + off; + case 3: *s++ = *p++ + off; + case 2: *r++ = *p++ + off; + case 1: *q++ = *p++ + off; + } + i -= channels; + } + +} + +#endif /* NAUCC > 0 */ diff --git a/sys/arch/amiga/dev/auccvar.h b/sys/arch/amiga/dev/auccvar.h new file mode 100644 index 00000000000..bb5e9d1ae17 --- /dev/null +++ b/sys/arch/amiga/dev/auccvar.h @@ -0,0 +1,65 @@ +/* $OpenBSD: auccvar.h,v 1.1 1997/09/18 13:39:43 niklas Exp $ */ +/* $NetBSD: auccvar.h,v 1.3 1997/07/04 21:00:18 is Exp $ */ + +/* + * Copyright (c) 1991-1993 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef _AUCCVAR_H_ +#define _AUCCVAR_H_ + +#define AUDIO_BUF_SIZE 8192 + +/* per channel data */ +typedef struct aucc_data { + u_int nd_freq; /* frequency */ + u_int nd_per; /* period = clock/freq */ + u_int nd_volume; /* 0..63 */ + u_int nd_busy; /* 1, if channel is busy */ + u_short *nd_dma; /* pointer to dma buffer */ + u_int nd_dmalength; /* length of dma data */ + int nd_mask; /* mask of active channels, + together with this one */ + void (*nd_intr) __P((void *)); /* interrupt routine */ + void *nd_intrdata; /* interrupt data */ + int nd_doublebuf; /* double buffering */ +} aucc_data_t; + +/* mixer sets */ +#define AUCC_CHANNELS 0 + +/* mixer values */ +#define AUCC_VOLUME 1 +#define AUCC_OUTPUT_CLASS 2 + +#endif /* _AUCCVAR_H_ */ diff --git a/sys/arch/amiga/dev/clock.c b/sys/arch/amiga/dev/clock.c index 6f8d075238d..2b2ffe33615 100644 --- a/sys/arch/amiga/dev/clock.c +++ b/sys/arch/amiga/dev/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.9 1997/01/16 09:23:52 niklas Exp $ */ +/* $OpenBSD: clock.c,v 1.10 1997/09/18 13:39:43 niklas Exp $ */ /* $NetBSD: clock.c,v 1.25 1997/01/02 20:59:42 is Exp $ */ /* @@ -100,8 +100,8 @@ struct clockframe hardclock_frame; int clockmatch __P((struct device *, void *, void *)); void clockattach __P((struct device *, struct device *, void *)); -void calibrate_delay __P((struct device *)); void cpu_initclocks __P((void)); +void calibrate_delay __P((struct device *)); int clockintr __P((void *)); struct cfattach clock_ca = { @@ -288,6 +288,20 @@ cpu_initclocks() static struct isr isr; #endif +#ifdef DRACO + unsigned char dracorev; + + dracorev = is_draco(); + if (dracorev >= 4) { + draco_ioct->io_timerlo = CLK_INTERVAL & 0xFF; + draco_ioct->io_timerhi = CLK_INTERVAL >> 8; + draco_ioct->io_timerrst = 0; /* any value resets */ + draco_ioct->io_status2 |= DRSTAT2_TMRINTENA; + + return; + } +#endif + /* * enable interrupts for timer A */ @@ -670,18 +684,6 @@ profclock(pc, ps) #endif #endif -/* this is a hook set by a clock driver for the configured realtime clock, - returning plain current unix-time */ -long (*gettod) __P((void)); -int (*settod) __P((long)); -void *clockaddr; - -long a3gettod __P((void)); -long a2gettod __P((void)); -int a3settod __P((long)); -int a2settod __P((long)); -int rtcinit __P((void)); - /* * Initialize the time of day register, based on the time base which is, e.g. * from a filesystem. @@ -690,9 +692,9 @@ void inittodr(base) time_t base; { - u_long timbuf = base; /* assume no battery clock exists */ + time_t timbuf = base; /* assume no battery clock exists */ - if (gettod == NULL && rtcinit() == 0) + if (gettod == NULL) printf("WARNING: no battery clock\n"); else timbuf = gettod(); @@ -712,319 +714,3 @@ resettodr() if (settod && settod(time.tv_sec) == 0) printf("Cannot set battery backed clock\n"); } - -int -rtcinit() -{ - clockaddr = (void *)ztwomap(0xdc0000); -#ifdef DRACO - if (is_draco()) { - /* XXX to be done */ - gettod = (void *)0; - settod = (void *)0; - return 0; - } else -#endif - if (is_a3000() || is_a4000()) { - if (a3gettod() == 0) - return(0); - gettod = a3gettod; - settod = a3settod; - } else { - if (a2gettod() == 0) - return(0); - gettod = a2gettod; - settod = a2settod; - } - return(1); -} - -static int month_days[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -long -a3gettod() -{ - struct rtclock3000 *rt; - int i, year, month, day, wday, hour, min, sec; - u_long tmp; - - rt = clockaddr; - - /* hold clock */ - rt->control1 = A3CONTROL1_HOLD_CLOCK; - - /* read it */ - sec = rt->second1 * 10 + rt->second2; - min = rt->minute1 * 10 + rt->minute2; - hour = rt->hour1 * 10 + rt->hour2; - wday = rt->weekday; - day = rt->day1 * 10 + rt->day2; - month = rt->month1 * 10 + rt->month2; - year = rt->year1 * 10 + rt->year2 + 1900; - - /* let it run again.. */ - rt->control1 = A3CONTROL1_FREE_CLOCK; - - if (range_test(hour, 0, 23)) - return(0); - if (range_test(wday, 0, 6)) - return(0); - if (range_test(day, 1, 31)) - return(0); - if (range_test(month, 1, 12)) - return(0); - if (range_test(year, STARTOFTIME, 2000)) - return(0); - - tmp = 0; - - for (i = STARTOFTIME; i < year; i++) - tmp += days_in_year(i); - if (leapyear(year) && month > FEBRUARY) - tmp++; - - for (i = 1; i < month; i++) - tmp += days_in_month(i); - - tmp += (day - 1); - tmp = ((tmp * 24 + hour) * 60 + min) * 60 + sec; - - return(tmp); -} - -int -a3settod(tim) - long tim; -{ - register int i; - register long hms, day; - u_char sec1, sec2; - u_char min1, min2; - u_char hour1, hour2; -/* u_char wday; */ - u_char day1, day2; - u_char mon1, mon2; - u_char year1, year2; - struct rtclock3000 *rt; - - rt = clockaddr; - /* - * there seem to be problems with the bitfield addressing - * currently used.. - */ - - if (! rt) - return 0; - - /* prepare values to be written to clock */ - day = tim / SECDAY; - hms = tim % SECDAY; - - hour2 = hms / 3600; - hour1 = hour2 / 10; - hour2 %= 10; - - min2 = (hms % 3600) / 60; - min1 = min2 / 10; - min2 %= 10; - - - sec2 = (hms % 3600) % 60; - sec1 = sec2 / 10; - sec2 %= 10; - - /* Number of years in days */ - for (i = STARTOFTIME - 1900; day >= days_in_year(i); i++) - day -= days_in_year(i); - year1 = i / 10; - year2 = i % 10; - - /* Number of months in days left */ - if (leapyear(i)) - days_in_month(FEBRUARY) = 29; - for (i = 1; day >= days_in_month(i); i++) - day -= days_in_month(i); - days_in_month(FEBRUARY) = 28; - - mon1 = i / 10; - mon2 = i % 10; - - /* Days are what is left over (+1) from all that. */ - day ++; - day1 = day / 10; - day2 = day % 10; - - rt->control1 = A3CONTROL1_HOLD_CLOCK; - rt->second1 = sec1; - rt->second2 = sec2; - rt->minute1 = min1; - rt->minute2 = min2; - rt->hour1 = hour1; - rt->hour2 = hour2; -/* rt->weekday = wday; */ - rt->day1 = day1; - rt->day2 = day2; - rt->month1 = mon1; - rt->month2 = mon2; - rt->year1 = year1; - rt->year2 = year2; - rt->control1 = A3CONTROL1_FREE_CLOCK; - - return 1; -} - -long -a2gettod() -{ - struct rtclock2000 *rt; - int i, year, month, day, hour, min, sec; - u_long tmp; - - rt = clockaddr; - - /* - * hold clock - */ - rt->control1 |= A2CONTROL1_HOLD; - i = 0x1000; - while (rt->control1 & A2CONTROL1_BUSY && i--) - ; - if (rt->control1 & A2CONTROL1_BUSY) - return (0); /* Give up and say it's not there */ - - /* - * read it - */ - sec = rt->second1 * 10 + rt->second2; - min = rt->minute1 * 10 + rt->minute2; - hour = (rt->hour1 & 3) * 10 + rt->hour2; - day = rt->day1 * 10 + rt->day2; - month = rt->month1 * 10 + rt->month2; - year = rt->year1 * 10 + rt->year2 + 1900; - - if ((rt->control3 & A2CONTROL3_24HMODE) == 0) { - if ((rt->hour1 & A2HOUR1_PM) == 0 && hour == 12) - hour = 0; - else if ((rt->hour1 & A2HOUR1_PM) && hour != 12) - hour += 12; - } - - /* - * release the clock - */ - rt->control1 &= ~A2CONTROL1_HOLD; - - if (range_test(hour, 0, 23)) - return(0); - if (range_test(day, 1, 31)) - return(0); - if (range_test(month, 1, 12)) - return(0); - if (range_test(year, STARTOFTIME, 2000)) - return(0); - - tmp = 0; - - for (i = STARTOFTIME; i < year; i++) - tmp += days_in_year(i); - if (leapyear(year) && month > FEBRUARY) - tmp++; - - for (i = 1; i < month; i++) - tmp += days_in_month(i); - - tmp += (day - 1); - tmp = ((tmp * 24 + hour) * 60 + min) * 60 + sec; - - return(tmp); -} - -/* - * there is some question as to whether this works - * I guess - */ -int -a2settod(tim) - long tim; -{ - - int i; - long hms, day; - u_char sec1, sec2; - u_char min1, min2; - u_char hour1, hour2; - u_char day1, day2; - u_char mon1, mon2; - u_char year1, year2; - struct rtclock2000 *rt; - - rt = clockaddr; - /* - * there seem to be problems with the bitfield addressing - * currently used.. - * - * XXX Check out the above where we (hour1 & 3) - */ - if (! rt) - return 0; - - /* prepare values to be written to clock */ - day = tim / SECDAY; - hms = tim % SECDAY; - - hour2 = hms / 3600; - hour1 = hour2 / 10; - hour2 %= 10; - - min2 = (hms % 3600) / 60; - min1 = min2 / 10; - min2 %= 10; - - - sec2 = (hms % 3600) % 60; - sec1 = sec2 / 10; - sec2 %= 10; - - /* Number of years in days */ - for (i = STARTOFTIME - 1900; day >= days_in_year(i); i++) - day -= days_in_year(i); - year1 = i / 10; - year2 = i % 10; - - /* Number of months in days left */ - if (leapyear(i)) - days_in_month(FEBRUARY) = 29; - for (i = 1; day >= days_in_month(i); i++) - day -= days_in_month(i); - days_in_month(FEBRUARY) = 28; - - mon1 = i / 10; - mon2 = i % 10; - - /* Days are what is left over (+1) from all that. */ - day ++; - day1 = day / 10; - day2 = day % 10; - - /* - * XXXX spin wait as with reading??? - */ - rt->control1 |= A2CONTROL1_HOLD; - rt->second1 = sec1; - rt->second2 = sec2; - rt->minute1 = min1; - rt->minute2 = min2; - rt->hour1 = hour1; - rt->hour2 = hour2; - rt->day1 = day1; - rt->day2 = day2; - rt->month1 = mon1; - rt->month2 = mon2; - rt->year1 = year1; - rt->year2 = year2; - rt->control2 &= ~A2CONTROL1_HOLD; - - return 1; -} diff --git a/sys/arch/amiga/dev/com_supio.c b/sys/arch/amiga/dev/com_supio.c new file mode 100644 index 00000000000..bb2fb7563c8 --- /dev/null +++ b/sys/arch/amiga/dev/com_supio.c @@ -0,0 +1,266 @@ +/* $OpenBSD: com_supio.c,v 1.1 1997/09/18 13:39:44 niklas Exp $ */ +/* $NetBSD: com_supio.c,v 1.3 1997/08/27 20:41:30 is Exp $ */ + +/*- + * Copyright (c) 1993, 1994, 1995, 1996 + * Charles M. Hannum. All rights reserved. + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)com.c 7.5 (Berkeley) 5/16/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/types.h> +#include <sys/device.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <dev/isa/isavar.h> +#include <dev/ic/comreg.h> +#include <dev/ic/comvar.h> + +#include <amiga/amiga/isr.h> +#include <amiga/dev/supio.h> + +struct comsupio_softc { + struct com_softc sc_com; + struct isr sc_isr; +}; + +int com_supio_match __P((struct device *, void *, void *)); +void com_supio_attach __P((struct device *, struct device *, void *)); +void com_supio_cleanup __P((void *)); + +static int comconsaddr; +static bus_space_handle_t comconsioh; +#if 0 +static int comconsattached; +static bus_space_tag_t comconstag; +static int comconsrate; +static tcflag_t comconscflag; +#endif + +struct cfattach com_supio_ca = { + sizeof(struct comsupio_softc), com_supio_match, com_supio_attach +}; + +/* Macros to clear/set/test flags. */ +#define SET(t, f) (t) |= (f) +#define CLR(t, f) (t) &= ~(f) +#define ISSET(t, f) ((t) & (f)) + +int +com_supio_match(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct cfdata *cfp = match; + bus_space_tag_t iot; + int iobase; + int rv = 1; + struct supio_attach_args *supa = aux; + + iot = supa->supio_iot; + iobase = supa->supio_iobase; + + if (strcmp(supa->supio_name,"com") || (cfp->cf_unit > 1)) + return 0; +#if 0 + /* if it's in use as console, it's there. */ + if (iobase != comconsaddr || comconsattached) { + if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) { + return 0; + } + rv = comprobe1(iot, ioh, iobase); + bus_space_unmap(iot, ioh, COM_NPORTS); + } +#endif + return (rv); +} + +void +com_supio_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ +#ifdef __OpenBSD__ + struct comsupio_softc *sc = (void *)self; + struct com_softc *csc = &sc->sc_com; + int iobase; + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct supio_attach_args *supa = aux; + + csc->sc_hwflags = 0; + csc->sc_swflags = 0; + + iobase = csc->sc_iobase = supa->supio_iobase; + iot = csc->sc_iot = supa->supio_iot; + if (iobase != comconsaddr) { + if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) + panic("comattach: io mapping failed"); + } else + ioh = comconsioh; + + csc->sc_iot = iot; + csc->sc_ioh = ioh; + csc->sc_iobase = iobase; + + if (iobase == comconsaddr) { + comconsattached = 1; + + /* + * Need to reset baud rate, etc. of next print so reset + * comconsinit. Also make sure console is always "hardwired". + */ + delay(1000); /* wait for output to finish */ + comconsinit = 0; + SET(csc->sc_hwflags, COM_HW_CONSOLE); + SET(csc->sc_swflags, COM_SW_SOFTCAR); + } + + + /* look for a NS 16550AF UART with FIFOs */ + bus_space_write_1(iot, ioh, com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); + delay(100); + if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK) == + IIR_FIFO_MASK) + if (ISSET(bus_space_read_1(iot, ioh, com_fifo), + FIFO_TRIGGER_14) == FIFO_TRIGGER_14) { + SET(csc->sc_hwflags, COM_HW_FIFO); + printf(": ns16550a, working fifo\n"); + } else + printf(": ns16550, broken fifo\n"); + else + printf(": ns8250 or ns16450, no fifo\n"); + bus_space_write_1(iot, ioh, com_fifo, 0); + + /* disable interrupts */ + bus_space_write_1(iot, ioh, com_ier, 0); + bus_space_write_1(iot, ioh, com_mcr, 0); + + if (amiga_ttyspl < (PSL_S|PSL_IPL5)) { + printf("%s: raising amiga_ttyspl from 0x%x to 0x%x\n", + csc->sc_dev.dv_xname, amiga_ttyspl, PSL_S|PSL_IPL5); + amiga_ttyspl = PSL_S|PSL_IPL5; + } + sc->sc_isr.isr_intr = comintr; + sc->sc_isr.isr_arg = csc; + sc->sc_isr.isr_ipl = 5; + add_isr(&sc->sc_isr); + +#ifdef KGDB + if (kgdb_dev == makedev(commajor, unit)) { + if (ISSET(csc->sc_hwflags, COM_HW_CONSOLE)) + kgdb_dev = -1; /* can't debug over console port */ + else { + cominit(iot, ioh, kgdb_rate); + if (kgdb_debug_init) { + /* + * Print prefix of device name, + * let kgdb_connect print the rest. + */ + printf("%s: ", csc->sc_dev.dv_xname); + kgdb_connect(1); + } else + printf("%s: kgdb enabled\n", + csc->sc_dev.dv_xname); + } + } +#endif + + /* XXX maybe move up some? */ + if (ISSET(csc->sc_hwflags, COM_HW_CONSOLE)) + printf("%s: console\n", csc->sc_dev.dv_xname); +#else /* __OpenBSD__ */ + struct comsupio_softc *sc = (void *)self; + struct com_softc *csc = &sc->sc_com; + int iobase; + bus_space_tag_t iot; + struct supio_attach_args *supa = aux; + + /* + * We're living on a superio chip. + */ + iobase = csc->sc_iobase = supa->supio_iobase; + iot = csc->sc_iot = supa->supio_iot; + if (iobase != comconsaddr) { + if (bus_space_map(iot, iobase, COM_NPORTS, 0, &csc->sc_ioh)) + panic("comattach: io mapping failed"); + } else + csc->sc_ioh = comconsioh; + + printf(" port 0x%x", iobase); + com_attach_subr(csc); + + if (amiga_ttyspl < (PSL_S|PSL_IPL5)) { + printf("%s: raising amiga_ttyspl from 0x%x to 0x%x\n", + csc->sc_dev.dv_xname, amiga_ttyspl, PSL_S|PSL_IPL5); + amiga_ttyspl = PSL_S|PSL_IPL5; + } + sc->sc_isr.isr_intr = comintr; + sc->sc_isr.isr_arg = csc; + sc->sc_isr.isr_ipl = 5; + add_isr(&sc->sc_isr); + + /* + * Shutdown hook for buggy BIOSs that don't recognize the UART + * without a disabled FIFO. + */ + if (shutdownhook_establish(com_supio_cleanup, csc) == NULL) + panic("comsupio: could not establish shutdown hook"); +#endif /* __OpenBSD__ */ +} + +void +com_supio_cleanup(arg) + void *arg; +{ + struct com_softc *sc = arg; + + if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) + bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_fifo, 0); +} diff --git a/sys/arch/amiga/dev/drbbc.c b/sys/arch/amiga/dev/drbbc.c new file mode 100644 index 00000000000..da4f0612cce --- /dev/null +++ b/sys/arch/amiga/dev/drbbc.c @@ -0,0 +1,205 @@ +/* $OpenBSD: drbbc.c,v 1.1 1997/09/18 13:39:44 niklas Exp $ */ +/* $NetBSD: drbbc.c,v 1.1 1997/07/17 23:29:30 is Exp $ */ + +/* + * Copyright (c) 1997 Ignatios Souvatzis. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ignatios Souvatzis + * for the NetBSD project. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/systm.h> +#if 0 +#include <machine/psl.h> +#endif +#include <machine/cpu.h> +#include <amiga/amiga/device.h> +#include <amiga/amiga/custom.h> +#include <amiga/amiga/cia.h> +#include <amiga/amiga/drcustom.h> +#include <amiga/dev/rtc.h> + +#include <dev/ic/ds.h> + +int draco_ds_read_bit __P((void *)); +void draco_ds_write_bit __P((void *, int)); +void draco_ds_reset __P((void *)); + +void drbbc_attach __P((struct device *, struct device *, void *)); +int drbbc_match __P((struct device *, void *, void *)); + +time_t dracogettod __P((void)); +#ifdef __NOTYET__ +int dracosettod __P((time_t)); +#endif + +struct drbbc_softc { + struct device sc_dev; + struct ds_handle sc_dsh; +}; + +struct cfattach drbbc_ca = { + sizeof(struct drbbc_softc), + drbbc_match, + drbbc_attach +}; + +struct cfdriver drbbc_cd = { + NULL, "drbbc", DV_DULL, NULL, 0 +}; + +struct drbbc_softc *drbbc_sc; + +int +drbbc_match(pdp, match, auxp) + struct device *pdp; + void *match; + void *auxp; +{ + struct cfdata *cfp = match; + + if (is_draco() && matchname(auxp, "drbbc") && (cfp->cf_unit == 0)) + return (1); + else + return (0); +} + +void +drbbc_attach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ + int i; + struct drbbc_softc *sc; + u_int8_t rombuf[8]; + + sc = (struct drbbc_softc *)dp; + + sc->sc_dsh.ds_read_bit = draco_ds_read_bit; + sc->sc_dsh.ds_write_bit = draco_ds_write_bit; + sc->sc_dsh.ds_reset = draco_ds_reset; + sc->sc_dsh.ds_hw_handle = (void *)(DRCCADDR + DRIOCTLPG*NBPG); + + sc->sc_dsh.ds_reset(sc->sc_dsh.ds_hw_handle); + + ds_write_byte(&sc->sc_dsh, DS_ROM_READ); + for (i=0; i<8; ++i) + rombuf[i] = ds_read_byte(&sc->sc_dsh); + + hostid = (rombuf[3] << 24) + (rombuf[2] << 16) + + (rombuf[1] << 8) + rombuf[7]; + + printf(": ROM %02x %02x%02x%02x%02x%02x%02x %02x (DraCo sernum %ld)\n", + rombuf[7], rombuf[6], rombuf[5], rombuf[4], + rombuf[3], rombuf[2], rombuf[1], rombuf[0], + hostid); + + gettod = dracogettod; + settod = (void *)0; + drbbc_sc = sc; +} + +int +draco_ds_read_bit(p) + void *p; +{ + struct drioct *draco_ioct; + + draco_ioct = p; + + while (draco_ioct->io_status & DRSTAT_CLKBUSY); + + draco_ioct->io_clockw1 = 0; + + while (draco_ioct->io_status & DRSTAT_CLKBUSY); + + return (draco_ioct->io_status & DRSTAT_CLKDAT); +} + +void +draco_ds_write_bit(p, b) + void *p; + int b; +{ + struct drioct *draco_ioct; + + draco_ioct = p; + + while (draco_ioct->io_status & DRSTAT_CLKBUSY); + + if (b) + draco_ioct->io_clockw1 = 0; + else + draco_ioct->io_clockw0 = 0; +} + +void +draco_ds_reset(p) + void *p; +{ + struct drioct *draco_ioct; + + draco_ioct = p; + + draco_ioct->io_clockrst = 0; +} + +/* + * We could return 1/256 of a seconds, but would need to change the interface + */ + +time_t +dracogettod() +{ + u_int32_t clkbuf; + + drbbc_sc->sc_dsh.ds_reset(drbbc_sc->sc_dsh.ds_hw_handle); + + ds_write_byte(&drbbc_sc->sc_dsh, DS_ROM_SKIP); + + ds_write_byte(&drbbc_sc->sc_dsh, DS_MEM_READ_MEMORY); + /* address of full seconds: */ + ds_write_byte(&drbbc_sc->sc_dsh, 0x03); + ds_write_byte(&drbbc_sc->sc_dsh, 0x02); + + clkbuf = ds_read_byte(&drbbc_sc->sc_dsh) + + (ds_read_byte(&drbbc_sc->sc_dsh)<<8) + + (ds_read_byte(&drbbc_sc->sc_dsh)<<16) + + (ds_read_byte(&drbbc_sc->sc_dsh)<<24); + + /* BSD time is wr. 1.1.1970; AmigaOS time wrt. 1.1.1978 */ + + clkbuf += (8*365 + 2) * 86400; + + return ((time_t)clkbuf); +} diff --git a/sys/arch/amiga/dev/drcom.c b/sys/arch/amiga/dev/drcom.c deleted file mode 100644 index c4ed739439f..00000000000 --- a/sys/arch/amiga/dev/drcom.c +++ /dev/null @@ -1,1285 +0,0 @@ -/* $OpenBSD: drcom.c,v 1.1 1997/01/16 09:23:55 niklas Exp $ */ -/* $NetBSD: drcom.c,v 1.2 1996/12/23 09:09:56 veego Exp $ */ - -/*- - * Copyright (c) 1993, 1994, 1995, 1996 - * Charles M. Hannum. All rights reserved. - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)drcom.c 7.5 (Berkeley) 5/16/91 - */ - -/* - * COM driver, based on HP dca driver - * uses National Semiconductor NS16450/NS16550AF UART - */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/tty.h> -#include <sys/ttycom.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/file.h> -#include <sys/uio.h> -#include <sys/kernel.h> -#include <sys/syslog.h> -#include <sys/types.h> -#include <sys/device.h> - -#include <sys/conf.h> -#include <machine/conf.h> - -#include <machine/cpu.h> - -#include <amiga/amiga/device.h> -#include <amiga/amiga/drcustom.h> -#include <amiga/amiga/isr.h> - -#include <amiga/dev/drisavar.h> -#include <amiga/dev/drcomreg.h> -#include <amiga/dev/drcomvar.h> - -#include <dev/ic/ns16550reg.h> - -#define com_lcr com_cfcr - -#include "drcom.h" - - -#define COM_IBUFSIZE (2 * 512) -#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4) - -struct drcom_softc { - struct device sc_dev; - void *sc_ih; - struct tty *sc_tty; - - int sc_overflows; - int sc_floods; - int sc_failures; - int sc_errors; - - int sc_halt; - - int sc_iobase; - - bus_chipset_tag_t sc_bc; - bus_io_handle_t sc_ioh; - - struct isr sc_isr; - - u_char sc_hwflags; -#define COM_HW_NOIEN 0x01 -#define COM_HW_FIFO 0x02 -#define COM_HW_HAYESP 0x04 -#define COM_HW_CONSOLE 0x40 - u_char sc_swflags; -#define COM_SW_SOFTCAR 0x01 -#define COM_SW_CLOCAL 0x02 -#define COM_SW_CRTSCTS 0x04 -#define COM_SW_MDMBUF 0x08 - u_char sc_msr, sc_mcr, sc_lcr, sc_ier; - u_char sc_dtr; - - u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend; - u_char sc_ibufs[2][COM_IBUFSIZE]; - - u_char sc_iir; -}; - -void drcomdiag __P((void *)); -int drcomspeed __P((long)); -int drcomparam __P((struct tty *, struct termios *)); -void drcomstart __P((struct tty *)); -void drcomsoft __P((void *)); -int drcomintr __P((void *)); - -struct consdev; -void drcomcnprobe __P((struct consdev *)); -void drcomcninit __P((struct consdev *)); -int drcomcngetc __P((dev_t)); -void drcomcnputc __P((dev_t, int)); -void drcomcnpollc __P((dev_t, int)); - -static u_char tiocm_xxx2mcr __P((int)); - -/* - * XXX the following two cfattach structs should be different, and possibly - * XXX elsewhere. - */ -int drcommatch __P((struct device *, struct cfdata *, void *)); -void drcomattach __P((struct device *, struct device *, void *)); - -struct cfattach drcom_ca = { - sizeof(struct drcom_softc), drcommatch, drcomattach -}; - -struct cfdriver drcom_cd = { - NULL, "drcom", DV_TTY -}; - -void drcominit __P((bus_chipset_tag_t, bus_io_handle_t, int)); - -#ifdef COMCONSOLE -int drcomdefaultrate = CONSPEED; /* XXX why set default? */ -#else -int drcomdefaultrate = 1200 /*TTYDEF_SPEED*/; -#endif -int drcomconsaddr; -int drcomconsinit; -int drcomconsattached; -bus_chipset_tag_t drcomconsbc; -bus_io_handle_t drcomconsioh; -tcflag_t drcomconscflag = TTYDEF_CFLAG; - -int drcommajor; -int drcomsopen = 0; -int drcomevents = 0; - -#ifdef KGDB -#include <machine/remote-sl.h> -extern int kgdb_dev; -extern int kgdb_rate; -extern int kgdb_debug_init; -#endif - -#define COMUNIT(x) (minor(x)) - -/* Macros to clear/set/test flags. */ -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~(f) -#define ISSET(t, f) ((t) & (f)) - -int -drcomspeed(speed) - long speed; -{ -#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ - - int x, err; - - if (speed == 0) - return 0; - if (speed < 0) - return -1; - x = divrnd((COM_FREQ / 16), speed); - if (x <= 0) - return -1; - err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000; - if (err < 0) - err = -err; - if (err > COM_TOLERANCE) - return -1; - return x; - -#undef divrnd(n, q) -} - -int -drcommatch(parent, cfp, auxp) - struct device *parent; - struct cfdata *cfp; - void *auxp; -{ - - /* Exactly two of us live on the DraCo */ - - if (is_draco() && matchname(auxp, "drcom") && - (cfp->cf_unit >= 0) && (cfp->cf_unit < 2)) - return 1; - - return 0; -} - -void -drcomattach(parent, self, auxp) - struct device *parent, *self; - void *auxp; -{ - struct drcom_softc *sc = (void *)self; - int iobase; - bus_chipset_tag_t bc; - bus_io_handle_t ioh; - - /* - * XXX should be broken out into functions for isa attach and - * XXX for drcommulti attach, with a helper function that contains - * XXX most of the interesting stuff. - */ - sc->sc_hwflags = 0; - sc->sc_swflags = 0; - - bc = 0; - iobase = self->dv_cfdata->cf_unit ? 0x2f8 : 0x3f8; - - if (iobase != drcomconsaddr) { - (void)bus_io_map(bc, iobase, COM_NPORTS, &ioh); - } else { - ioh = drcomconsioh; - } - - sc->sc_bc = bc; - sc->sc_ioh = ioh; - sc->sc_iobase = iobase; - - if (iobase == drcomconsaddr) { - drcomconsattached = 1; - - /* - * Need to reset baud rate, etc. of next print so reset - * drcomconsinit. Also make sure console is always "hardwired". - */ - delay(1000); /* wait for output to finish */ - drcomconsinit = 0; - SET(sc->sc_hwflags, COM_HW_CONSOLE); - SET(sc->sc_swflags, COM_SW_SOFTCAR); - } - - - /* look for a NS 16550AF UART with FIFOs */ - bus_io_write_1(bc, ioh, com_fifo, - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); - delay(100); - if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK) - if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) { - SET(sc->sc_hwflags, COM_HW_FIFO); - printf(": ns16550a, working fifo\n"); - } else - printf(": ns16550, broken fifo\n"); - else - printf(": ns8250 or ns16450, no fifo\n"); - bus_io_write_1(bc, ioh, com_fifo, 0); -#ifdef COM_HAYESP - } -#endif - - if (amiga_ttyspl < (PSL_S|PSL_IPL5)) { - printf("%s: raising amiga_ttyspl from 0x%x to 0x%x\n", - sc->sc_dev.dv_xname, amiga_ttyspl, PSL_S|PSL_IPL5); - amiga_ttyspl = PSL_S|PSL_IPL5; - } - - /* disable interrupts */ - (void)bus_io_read_1(bc, ioh, com_iir); - bus_io_write_1(bc, ioh, com_ier, 0); - bus_io_write_1(bc, ioh, com_mcr, 0); - - sc->sc_isr.isr_intr = drcomintr; - sc->sc_isr.isr_arg = sc; - sc->sc_isr.isr_ipl = 5; - add_isr(&sc->sc_isr); - -#ifdef KGDB - if (kgdb_dev == makedev(drcommajor, unit)) { - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) - kgdb_dev = -1; /* can't debug over console port */ - else { - drcominit(bc, ioh, kgdb_rate); - if (kgdb_debug_init) { - /* - * Print prefix of device name, - * let kgdb_connect print the rest. - */ - printf("%s: ", sc->sc_dev.dv_xname); - kgdb_connect(1); - } else - printf("%s: kgdb enabled\n", - sc->sc_dev.dv_xname); - } - } -#endif - - /* XXX maybe move up some? */ - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) - printf("%s: console\n", sc->sc_dev.dv_xname); -} - -int -drcomopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - int unit = COMUNIT(dev); - struct drcom_softc *sc; - bus_chipset_tag_t bc; - bus_io_handle_t ioh; - struct tty *tp; - int s; - int error = 0; - - if (unit >= drcom_cd.cd_ndevs) - return ENXIO; - sc = drcom_cd.cd_devs[unit]; - if (!sc) - return ENXIO; - - if (!sc->sc_tty) { - tp = sc->sc_tty = ttymalloc(); - tty_attach(tp); - } else - tp = sc->sc_tty; - - tp->t_oproc = drcomstart; - tp->t_param = drcomparam; - tp->t_dev = dev; - if (!ISSET(tp->t_state, TS_ISOPEN)) { - SET(tp->t_state, TS_WOPEN); - ttychars(tp); - tp->t_iflag = TTYDEF_IFLAG; - tp->t_oflag = TTYDEF_OFLAG; - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) - tp->t_cflag = drcomconscflag; - else - tp->t_cflag = TTYDEF_CFLAG; - if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) - SET(tp->t_cflag, CLOCAL); - if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) - SET(tp->t_cflag, CRTSCTS); - if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) - SET(tp->t_cflag, MDMBUF); - tp->t_lflag = TTYDEF_LFLAG; - tp->t_ispeed = tp->t_ospeed = drcomdefaultrate; - - s = spltty(); - - drcomparam(tp, &tp->t_termios); - ttsetwater(tp); - - if (drcomsopen++ == 0) - timeout(drcomsoft, NULL, 1); - - sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; - sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; - sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; - - bc = sc->sc_bc; - ioh = sc->sc_ioh; -#ifdef COM_HAYESP - /* Setup the ESP board */ - if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { - bus_io_handle_t hayespioh = sc->sc_hayespioh; - - bus_io_write_1(bc, ioh, com_fifo, - FIFO_DMA_MODE|FIFO_ENABLE| - FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8); - - /* Set 16550 drcompatibility mode */ - bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, - HAYESP_MODE_FIFO|HAYESP_MODE_RTS| - HAYESP_MODE_SCALE); - - /* Set RTS/CTS flow control */ - bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS); - - /* Set flow control levels */ - bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, - HAYESP_HIBYTE(HAYESP_RXHIWMARK)); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, - HAYESP_LOBYTE(HAYESP_RXHIWMARK)); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, - HAYESP_HIBYTE(HAYESP_RXLOWMARK)); - bus_io_write_1(bc, hayespioh, HAYESP_CMD2, - HAYESP_LOBYTE(HAYESP_RXLOWMARK)); - } else -#endif - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) - /* Set the FIFO threshold based on the receive speed. */ - bus_io_write_1(bc, ioh, com_fifo, - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | - (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); - /* flush any pending I/O */ - while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY)) - (void) bus_io_read_1(bc, ioh, com_data); - /* you turn me on, baby */ - sc->sc_mcr = MCR_DTR | MCR_RTS; - if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) - SET(sc->sc_mcr, MCR_IENABLE); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; - bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); - - sc->sc_msr = bus_io_read_1(bc, ioh, com_msr); - if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || - ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) - SET(tp->t_state, TS_CARR_ON); - else - CLR(tp->t_state, TS_CARR_ON); - } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) - return EBUSY; - else - s = spltty(); - - /* wait for carrier if necessary */ - if (!ISSET(flag, O_NONBLOCK)) - while (!ISSET(tp->t_cflag, CLOCAL) && - !ISSET(tp->t_state, TS_CARR_ON)) { - SET(tp->t_state, TS_WOPEN); - error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, - ttopen, 0); - if (error) { - /* XXX should turn off chip if we're the - only waiter */ - splx(s); - return error; - } - } - splx(s); - - return (*linesw[tp->t_line].l_open)(dev, tp); -} - -int -drcomclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - int unit = COMUNIT(dev); - struct drcom_softc *sc = drcom_cd.cd_devs[unit]; - struct tty *tp = sc->sc_tty; - bus_chipset_tag_t bc = sc->sc_bc; - bus_io_handle_t ioh = sc->sc_ioh; - int s; - - /* XXX This is for cons.c. */ - if (!ISSET(tp->t_state, TS_ISOPEN)) - return 0; - - (*linesw[tp->t_line].l_close)(tp, flag); - s = spltty(); - CLR(sc->sc_lcr, LCR_SBREAK); - bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); - bus_io_write_1(bc, ioh, com_ier, 0); - if (ISSET(tp->t_cflag, HUPCL) && - !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { - /* XXX perhaps only clear DTR */ - bus_io_write_1(bc, ioh, com_mcr, 0); - bus_io_write_1(bc, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST); - } - CLR(tp->t_state, TS_BUSY | TS_FLUSH); - if (--drcomsopen == 0) - untimeout(drcomsoft, NULL); - splx(s); - ttyclose(tp); -#ifdef notyet /* XXXX */ - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { - ttyfree(tp); - sc->sc_tty = 0; - } -#endif - return 0; -} - -int -drcomread(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct drcom_softc *sc = drcom_cd.cd_devs[COMUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); -} - -int -drcomwrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct drcom_softc *sc = drcom_cd.cd_devs[COMUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); -} - -struct tty * -drcomtty(dev) - dev_t dev; -{ - struct drcom_softc *sc = drcom_cd.cd_devs[COMUNIT(dev)]; - struct tty *tp = sc->sc_tty; - - return (tp); -} - -static u_char -tiocm_xxx2mcr(data) - int data; -{ - u_char m = 0; - - if (ISSET(data, TIOCM_DTR)) - SET(m, MCR_DTR); - if (ISSET(data, TIOCM_RTS)) - SET(m, MCR_RTS); - return m; -} - -int -drcomioctl(dev, cmd, data, flag, p) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct proc *p; -{ - int unit = COMUNIT(dev); - struct drcom_softc *sc = drcom_cd.cd_devs[unit]; - struct tty *tp = sc->sc_tty; - bus_chipset_tag_t bc = sc->sc_bc; - bus_io_handle_t ioh = sc->sc_ioh; - int error; - - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); - if (error >= 0) - return error; - - error = ttioctl(tp, cmd, data, flag, p); - if (error >= 0) - return error; - - switch (cmd) { - case TIOCSBRK: - SET(sc->sc_lcr, LCR_SBREAK); - bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); - break; - case TIOCCBRK: - CLR(sc->sc_lcr, LCR_SBREAK); - bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr); - break; - case TIOCSDTR: - SET(sc->sc_mcr, sc->sc_dtr); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - break; - case TIOCCDTR: - CLR(sc->sc_mcr, sc->sc_dtr); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - break; - case TIOCMSET: - CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); - case TIOCMBIS: - SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - break; - case TIOCMBIC: - CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - break; - case TIOCMGET: { - u_char m; - int bits = 0; - - m = sc->sc_mcr; - if (ISSET(m, MCR_DTR)) - SET(bits, TIOCM_DTR); - if (ISSET(m, MCR_RTS)) - SET(bits, TIOCM_RTS); - m = sc->sc_msr; - if (ISSET(m, MSR_DCD)) - SET(bits, TIOCM_CD); - if (ISSET(m, MSR_CTS)) - SET(bits, TIOCM_CTS); - if (ISSET(m, MSR_DSR)) - SET(bits, TIOCM_DSR); - if (ISSET(m, MSR_RI | MSR_TERI)) - SET(bits, TIOCM_RI); - if (bus_io_read_1(bc, ioh, com_ier)) - SET(bits, TIOCM_LE); - *(int *)data = bits; - break; - } - case TIOCGFLAGS: { - int driverbits, userbits = 0; - - driverbits = sc->sc_swflags; - if (ISSET(driverbits, COM_SW_SOFTCAR)) - SET(userbits, TIOCFLAG_SOFTCAR); - if (ISSET(driverbits, COM_SW_CLOCAL)) - SET(userbits, TIOCFLAG_CLOCAL); - if (ISSET(driverbits, COM_SW_CRTSCTS)) - SET(userbits, TIOCFLAG_CRTSCTS); - if (ISSET(driverbits, COM_SW_MDMBUF)) - SET(userbits, TIOCFLAG_MDMBUF); - - *(int *)data = userbits; - break; - } - case TIOCSFLAGS: { - int userbits, driverbits = 0; - - error = suser(p->p_ucred, &p->p_acflag); - if (error != 0) { - return(EPERM); - } - - userbits = *(int *)data; - if (ISSET(userbits, TIOCFLAG_SOFTCAR) || - ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) - SET(driverbits, COM_SW_SOFTCAR); - if (ISSET(userbits, TIOCFLAG_CLOCAL)) - SET(driverbits, COM_SW_CLOCAL); - if (ISSET(userbits, TIOCFLAG_CRTSCTS)) - SET(driverbits, COM_SW_CRTSCTS); - if (ISSET(userbits, TIOCFLAG_MDMBUF)) - SET(driverbits, COM_SW_MDMBUF); - - sc->sc_swflags = driverbits; - break; - } - default: - return ENOTTY; - } - - return 0; -} - -int -drcomparam(tp, t) - struct tty *tp; - struct termios *t; -{ - struct drcom_softc *sc = drcom_cd.cd_devs[COMUNIT(tp->t_dev)]; - bus_chipset_tag_t bc = sc->sc_bc; - bus_io_handle_t ioh = sc->sc_ioh; - int ospeed = drcomspeed(t->c_ospeed); - u_char lcr; - tcflag_t oldcflag; - int s; - - /* check requested parameters */ - if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) - return EINVAL; - - lcr = ISSET(sc->sc_lcr, LCR_SBREAK); - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - SET(lcr, LCR_5BITS); - break; - case CS6: - SET(lcr, LCR_6BITS); - break; - case CS7: - SET(lcr, LCR_7BITS); - break; - case CS8: - SET(lcr, LCR_8BITS); - break; - } - if (ISSET(t->c_cflag, PARENB)) { - SET(lcr, LCR_PENAB); - if (!ISSET(t->c_cflag, PARODD)) - SET(lcr, LCR_PEVEN); - } - if (ISSET(t->c_cflag, CSTOPB)) - SET(lcr, LCR_STOPB); - - sc->sc_lcr = lcr; - - s = spltty(); - - if (ospeed == 0) { - CLR(sc->sc_mcr, MCR_DTR); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } - - /* - * Set the FIFO threshold based on the receive speed, if we are - * changing it. - */ -#if 1 - if (tp->t_ispeed != t->c_ispeed) { -#else - if (1) { -#endif - if (ospeed != 0) { - /* - * Make sure the transmit FIFO is empty before - * proceeding. If we don't do this, some revisions - * of the UART will hang. Interestingly enough, - * even if we do this will the last character is - * still being pushed out, they don't hang. This - * seems good enough. - */ - while (ISSET(tp->t_state, TS_BUSY)) { - int error; - - ++sc->sc_halt; - error = ttysleep(tp, &tp->t_outq, - TTOPRI | PCATCH, "drcomprm", 0); - --sc->sc_halt; - if (error) { - splx(s); - drcomstart(tp); - return (error); - } - } - - bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB); - bus_io_write_1(bc, ioh, com_dlbl, ospeed); - bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8); - bus_io_write_1(bc, ioh, com_lcr, lcr); - SET(sc->sc_mcr, MCR_DTR); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } else - bus_io_write_1(bc, ioh, com_lcr, lcr); - - if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) && - ISSET(sc->sc_hwflags, COM_HW_FIFO)) - bus_io_write_1(bc, ioh, com_fifo, - FIFO_ENABLE | - (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); - } else - bus_io_write_1(bc, ioh, com_lcr, lcr); - - /* When not using CRTSCTS, RTS follows DTR. */ - if (!ISSET(t->c_cflag, CRTSCTS)) { - if (ISSET(sc->sc_mcr, MCR_DTR)) { - if (!ISSET(sc->sc_mcr, MCR_RTS)) { - SET(sc->sc_mcr, MCR_RTS); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } - } else { - if (ISSET(sc->sc_mcr, MCR_RTS)) { - CLR(sc->sc_mcr, MCR_RTS); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } - } - sc->sc_dtr = MCR_DTR | MCR_RTS; - } else - sc->sc_dtr = MCR_DTR; - - /* and copy to tty */ - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - oldcflag = tp->t_cflag; - tp->t_cflag = t->c_cflag; - - /* - * If DCD is off and MDMBUF is changed, ask the tty layer if we should - * stop the device. - */ - if (!ISSET(sc->sc_msr, MSR_DCD) && - !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && - ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) && - (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { - CLR(sc->sc_mcr, sc->sc_dtr); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } - - /* Just to be sure... */ - splx(s); - drcomstart(tp); - return 0; -} - -void -drcomstart(tp) - struct tty *tp; -{ - struct drcom_softc *sc = drcom_cd.cd_devs[COMUNIT(tp->t_dev)]; - bus_chipset_tag_t bc = sc->sc_bc; - bus_io_handle_t ioh = sc->sc_ioh; - int s; - - s = spltty(); - if (ISSET(tp->t_state, TS_BUSY)) - goto out; - if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || - sc->sc_halt > 0) - goto stopped; - if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS)) - goto stopped; - if (tp->t_outq.c_cc <= tp->t_lowat) { - if (ISSET(tp->t_state, TS_ASLEEP)) { - CLR(tp->t_state, TS_ASLEEP); - wakeup(&tp->t_outq); - } - if (tp->t_outq.c_cc == 0) - goto stopped; - selwakeup(&tp->t_wsel); - } - SET(tp->t_state, TS_BUSY); - - if (!ISSET(sc->sc_ier, IER_ETXRDY)) { - SET(sc->sc_ier, IER_ETXRDY); - bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); - } -#ifdef COM_HAYESP - if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { - u_char buffer[1024], *cp = buffer; - int n = q_to_b(&tp->t_outq, cp, sizeof buffer); - do - bus_io_write_1(bc, ioh, com_data, *cp++); - while (--n); - } - else -#endif - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { - u_char buffer[16], *cp = buffer; - int n = q_to_b(&tp->t_outq, cp, sizeof buffer); - do { - bus_io_write_1(bc, ioh, com_data, *cp++); - } while (--n); - } else - bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq)); -out: - splx(s); - return; -stopped: - if (ISSET(sc->sc_ier, IER_ETXRDY)) { - CLR(sc->sc_ier, IER_ETXRDY); - bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); - } - splx(s); -} - -/* - * Stop output on a line. - */ -void -drcomstop(tp, flag) - struct tty *tp; - int flag; -{ - int s; - - s = spltty(); - if (ISSET(tp->t_state, TS_BUSY)) - if (!ISSET(tp->t_state, TS_TTSTOP)) - SET(tp->t_state, TS_FLUSH); - splx(s); -} - -void -drcomdiag(arg) - void *arg; -{ - struct drcom_softc *sc = arg; - int overflows, floods, failures; - int s; - - s = spltty(); - sc->sc_errors = 0; - overflows = sc->sc_overflows; - sc->sc_overflows = 0; - floods = sc->sc_floods; - sc->sc_floods = 0; - failures = sc->sc_failures; - sc->sc_failures = 0; - splx(s); - - log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s, %d uart failure%s\n", - sc->sc_dev.dv_xname, - overflows, overflows == 1 ? "" : "s", - floods, floods == 1 ? "" : "s", - failures, failures == 1 ? "" : "s"); -} - -void -drcomsoft(arg) - void *arg; -{ - int unit; - struct drcom_softc *sc; - struct tty *tp; - register u_char *ibufp; - u_char *ibufend; - register int c; - int s; - static int lsrmap[8] = { - 0, TTY_PE, - TTY_FE, TTY_PE|TTY_FE, - TTY_FE, TTY_PE|TTY_FE, - TTY_FE, TTY_PE|TTY_FE - }; - - s = spltty(); - if (drcomevents == 0) { - splx(s); - goto out; - } - drcomevents = 0; - splx(s); - - for (unit = 0; unit < drcom_cd.cd_ndevs; unit++) { - sc = drcom_cd.cd_devs[unit]; - if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf) - continue; - - tp = sc->sc_tty; - - s = spltty(); - - ibufp = sc->sc_ibuf; - ibufend = sc->sc_ibufp; - - if (ibufp == ibufend) { - splx(s); - continue; - } - - sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? - sc->sc_ibufs[1] : sc->sc_ibufs[0]; - sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; - sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; - - if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) { - splx(s); - continue; - } - - if (ISSET(tp->t_cflag, CRTSCTS) && - !ISSET(sc->sc_mcr, MCR_RTS)) { - /* XXX */ - SET(sc->sc_mcr, MCR_RTS); - bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr, - sc->sc_mcr); - } - - splx(s); - - while (ibufp < ibufend) { - c = *ibufp++; - if (*ibufp & LSR_OE) { - sc->sc_overflows++; - if (sc->sc_errors++ == 0) - timeout(drcomdiag, sc, 60 * hz); - } - /* This is ugly, but fast. */ - c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2]; - (*linesw[tp->t_line].l_rint)(c, tp); - } - } - -out: - timeout(drcomsoft, NULL, 1); -} - -int -drcomintr(arg) - void *arg; -{ - struct drcom_softc *sc = arg; - bus_chipset_tag_t bc = sc->sc_bc; - bus_io_handle_t ioh = sc->sc_ioh; - struct tty *tp; - u_char iir, lsr, data, msr, delta; -#ifdef COM_DEBUG - int n; - struct { - u_char iir, lsr, msr; - } iter[32]; -#endif - -#ifdef COM_DEBUG - n = 0; - iter[n].iir = -#endif - iir = bus_io_read_1(bc, ioh, com_iir); - if (ISSET(iir, IIR_NOPEND)) - return (0); - - tp = sc->sc_tty; - - for (;;) { -#ifdef COM_DEBUG - iter[n].lsr = -#endif - lsr = bus_io_read_1(bc, ioh, com_lsr); - - if (ISSET(lsr, LSR_RXRDY)) { - register u_char *p = sc->sc_ibufp; - - drcomevents = 1; - do { - data = bus_io_read_1(bc, ioh, com_data); - if (ISSET(lsr, LSR_BI)) { -#ifdef notdef - printf("break %02x %02x %02x %02x\n", - sc->sc_msr, sc->sc_mcr, sc->sc_lcr, - sc->sc_dtr); -#endif -#ifdef DDB - if (ISSET(sc->sc_hwflags, - COM_HW_CONSOLE)) { - Debugger(); - goto next; - } -#endif - } - if (p >= sc->sc_ibufend) { - sc->sc_floods++; - if (sc->sc_errors++ == 0) - timeout(drcomdiag, sc, 60 * hz); - } else { - *p++ = data; - *p++ = lsr; - if (p == sc->sc_ibufhigh && - ISSET(tp->t_cflag, CRTSCTS)) { - /* XXX */ - CLR(sc->sc_mcr, MCR_RTS); - bus_io_write_1(bc, ioh, - com_mcr, sc->sc_mcr); - } - } -#ifdef DDB - next: -#endif -#ifdef COM_DEBUG - if (++n >= 32) - goto ohfudge; - iter[n].lsr = -#endif - lsr = bus_io_read_1(bc, ioh, com_lsr); - } while (ISSET(lsr, LSR_RXRDY)); - - sc->sc_ibufp = p; - } else { -#ifdef COM_DEBUG - if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE)) - printf("weird lsr %02x\n", lsr); -#endif - if ((iir & IIR_IMASK) == IIR_RXRDY) { - sc->sc_failures++; - if (sc->sc_errors++ == 0) - timeout(drcomdiag, sc, 60 * hz); - bus_io_write_1(bc, ioh, com_ier, 0); - delay(10); - bus_io_write_1(bc, ioh, com_ier, sc->sc_ier); - iir = IIR_NOPEND; - continue; - } - } - -#ifdef COM_DEBUG - iter[n].msr = -#endif - msr = bus_io_read_1(bc, ioh, com_msr); - - if (msr != sc->sc_msr) { - delta = msr ^ sc->sc_msr; - sc->sc_msr = msr; - if (ISSET(delta, MSR_DCD) && - !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && - (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { - CLR(sc->sc_mcr, sc->sc_dtr); - bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr); - } - if (ISSET(delta & msr, MSR_CTS) && - ISSET(tp->t_cflag, CRTSCTS)) { - /* the line is up and we want to do rts/cts flow control */ - (*linesw[tp->t_line].l_start)(tp); - } - } - - if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) { - CLR(tp->t_state, TS_BUSY | TS_FLUSH); - if (sc->sc_halt > 0) - wakeup(&tp->t_outq); - (*linesw[tp->t_line].l_start)(tp); - } - -#ifdef COM_DEBUG - if (++n >= 32) - goto ohfudge; - iter[n].iir = -#endif - iir = bus_io_read_1(bc, ioh, com_iir); - if (ISSET(iir, IIR_NOPEND)) - return (1); - } - -#ifdef COM_DEBUG -ohfudge: - printf("drcomintr: too many iterations"); - for (n = 0; n < 32; n++) { - if ((n % 4) == 0) - printf("\ndrcomintr: iter[%02d]", n); - printf(" %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr); - } - printf("\n"); - printf("drcomintr: msr %02x mcr %02x lcr %02x ier %02x\n", - sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier); - printf("drcomintr: state %08x cc %d\n", sc->sc_tty->t_state, - sc->sc_tty->t_outq.c_cc); - return (1); -#endif -} - -/* - * Following are all routines needed for COM to act as console - */ -#include <dev/cons.h> - -void -drcomcnprobe(cp) - struct consdev *cp; -{ - /* XXX NEEDS TO BE FIXED XXX */ - bus_chipset_tag_t bc = 0; - bus_io_handle_t ioh; - int found; - - if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) { - cp->cn_pri = CN_DEAD; - return; - } - found = 1/*drcomprobe1(bc, ioh, CONADDR)*/; - bus_io_unmap(bc, ioh, COM_NPORTS); - if (!found) { - cp->cn_pri = CN_DEAD; - return; - } - - /* locate the major number */ - for (drcommajor = 0; drcommajor < nchrdev; drcommajor++) - if (cdevsw[drcommajor].d_open == drcomopen) - break; - - /* initialize required fields */ - cp->cn_dev = makedev(drcommajor, CONUNIT); -#ifdef COMCONSOLE - cp->cn_pri = CN_REMOTE; /* Force a serial port console */ -#else - cp->cn_pri = CN_NORMAL; -#endif -} - -void -drcomcninit(cp) - struct consdev *cp; -{ - -#if 0 - XXX NEEDS TO BE FIXED XXX - drcomconsbc = ???; -#endif - if (bus_io_map(drcomconsbc, CONADDR, COM_NPORTS, &drcomconsioh)) - panic("drcomcninit: mapping failed"); - - drcominit(drcomconsbc, drcomconsioh, drcomdefaultrate); - drcomconsaddr = CONADDR; - drcomconsinit = 0; -} - -void -drcominit(bc, ioh, rate) - bus_chipset_tag_t bc; - bus_io_handle_t ioh; - int rate; -{ - int s = splhigh(); - u_char stat; - - bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB); - rate = drcomspeed(drcomdefaultrate); - bus_io_write_1(bc, ioh, com_dlbl, rate); - bus_io_write_1(bc, ioh, com_dlbh, rate >> 8); - bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS); - bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY); - bus_io_write_1(bc, ioh, com_fifo, - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); - bus_io_write_1(bc, ioh, com_mcr, MCR_DTR | MCR_RTS); - DELAY(100); - stat = bus_io_read_1(bc, ioh, com_iir); - splx(s); -} - -int -drcomcngetc(dev) - dev_t dev; -{ - int s = splhigh(); - bus_chipset_tag_t bc = drcomconsbc; - bus_io_handle_t ioh = drcomconsioh; - u_char stat, c; - - while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY)) - ; - c = bus_io_read_1(bc, ioh, com_data); - stat = bus_io_read_1(bc, ioh, com_iir); - splx(s); - return c; -} - -/* - * Console kernel output character routine. - */ -void -drcomcnputc(dev, c) - dev_t dev; - int c; -{ - int s = splhigh(); - bus_chipset_tag_t bc = drcomconsbc; - bus_io_handle_t ioh = drcomconsioh; - u_char stat; - register int timo; - -#ifdef KGDB - if (dev != kgdb_dev) -#endif - if (drcomconsinit == 0) { - drcominit(bc, ioh, drcomdefaultrate); - drcomconsinit = 1; - } - /* wait for any pending transmission to finish */ - timo = 50000; - while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo) - ; - bus_io_write_1(bc, ioh, com_data, c); - /* wait for this transmission to drcomplete */ - timo = 1500000; - while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo) - ; - /* clear any interrupts generated by this transmission */ - stat = bus_io_read_1(bc, ioh, com_iir); - splx(s); -} - -void -drcomcnpollc(dev, on) - dev_t dev; - int on; -{ - -} diff --git a/sys/arch/amiga/dev/drisavar.h b/sys/arch/amiga/dev/drisavar.h deleted file mode 100644 index 04e102ea750..00000000000 --- a/sys/arch/amiga/dev/drisavar.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $OpenBSD: drisavar.h,v 1.1 1997/01/16 09:23:57 niklas Exp $ */ -/* $NetBSD: drisavar.h,v 1.1 1996/11/30 00:43:05 is Exp $ */ - -#ifndef DRISAVAR_H - -#ifndef DRCCADDR -#include <amiga/amiga/drcustom.h> -#endif - -#define i2drabs(io) (DRCCADDR + NBPG * DRSUPIOPG + (io << 2) + 1) -#define i2drrel(ioh,io) (ioh + (io << 2)) - -#define bus_chipset_tag_t void * -#define bus_io_handle_t vm_offset_t - -#define bus_io_map(bc, iob, n, iohp) (*(iohp) = i2drabs(iob), 0) -#define bus_io_unmap(bc, ioh, n) do {(void)bc; (void)ioh; (void)n;} while (0) - -#define bus_io_read_1(bt, ioh, off) ((void)bc, *(u_int8_t *)i2drrel(ioh, off)) -#define bus_io_write_1(bt, ioh, off, val) do {\ - (void)bt; *(u_int8_t *)i2drrel(ioh, off) = (val); } while (0) - -#endif diff --git a/sys/arch/amiga/dev/drsupio.c b/sys/arch/amiga/dev/drsupio.c new file mode 100644 index 00000000000..779fa48a741 --- /dev/null +++ b/sys/arch/amiga/dev/drsupio.c @@ -0,0 +1,172 @@ +/* $OpenBSD: drsupio.c,v 1.1 1997/09/18 13:39:47 niklas Exp $ */ +/* $NetBSD: drsupio.c,v 1.1 1997/08/27 19:32:53 is Exp $ */ + +/* + * Copyright (c) 1997 Ignatios Souvatzis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ignatios Souvatzis + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DraCo multi-io chip bus space stuff + */ + +#include <sys/types.h> + +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/param.h> + +#include <machine/bus.h> +#include <machine/conf.h> + +#include <amiga/include/cpu.h> + +#include <amiga/amiga/device.h> +#include <amiga/amiga/drcustom.h> + +#include <amiga/dev/supio.h> + + +struct drsupio_softc { + struct device sc_dev; + struct amiga_bus_space sc_bst; +}; + +int drsupiomatch __P((struct device *, void *, void *)); +void drsupioattach __P((struct device *, struct device *, void *)); +int drsupprint __P((void *auxp, const char *)); + +struct cfattach drsupio_ca = { + sizeof(struct drsupio_softc), drsupiomatch, drsupioattach +}; + +struct cfdriver drsupio_cd = { + NULL, "drsupio", DV_DULL +}; + +int drsupio_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *)); +int drsupio_unmap __P((bus_space_tag_t, bus_space_handle_t, bus_size_t)); + +int +drsupiomatch(parent, match, auxp) + struct device *parent; + void *match; + void *auxp; +{ + struct cfdata *cfp = match; + + /* Exactly one of us lives on the DraCo */ + + if (is_draco() && matchname(auxp, "drsupio") && (cfp->cf_unit == 0)) + return 1; + + return 0; +} + +struct drsupio_devs { + char *name; + int off; +} drsupiodevs[] = { + { "com", 0x3f8 }, + { "com", 0x2f8 }, + { "lpt", 0x378 }, + { "fdc", 0x3f0 }, + /* WD port? */ + { 0 } +}; + +int +drsupio_map(bst, addr, sz, cacheable, handle) + bus_space_tag_t bst; + bus_addr_t addr; + bus_size_t sz; + int cacheable; + bus_space_handle_t *handle; +{ + *handle = DRCCADDR + NBPG * DRSUPIOPG + 1 + (addr << bst->bs_shift); + return (0); +} + +int +drsupio_unmap(bst, handle, sz) + bus_space_tag_t bst; + bus_space_handle_t handle; + bus_size_t sz; +{ + return (0); +} + +void +drsupioattach(parent, self, auxp) + struct device *parent, *self; + void *auxp; +{ + struct drsupio_softc *drsc; + struct drsupio_devs *drsd; + struct supio_attach_args supa; + + drsc = (struct drsupio_softc *)self; + drsd = drsupiodevs; + + if (parent) + printf("\n"); + + drsc->sc_bst.bs_map = drsupio_map; + drsc->sc_bst.bs_unmap = drsupio_unmap; + drsc->sc_bst.bs_swapped = 0; + drsc->sc_bst.bs_shift = 2; + + supa.supio_iot = &drsc->sc_bst; + + while (drsd->name) { + supa.supio_name = drsd->name; + supa.supio_iobase = drsd->off; + config_found(self, &supa, drsupprint); /* XXX */ + ++drsd; + } +} + +int +drsupprint(auxp, pnp) + void *auxp; + const char *pnp; +{ + struct supio_attach_args *supa; + supa = auxp; + + if (pnp == NULL) + return(QUIET); + + printf("%s at %s port 0x%02x", + supa->supio_name, pnp, supa->supio_iobase); + + return(UNCONF); +} diff --git a/sys/arch/amiga/dev/grf_cl.c b/sys/arch/amiga/dev/grf_cl.c index 03c48dd9b1e..48d73c07712 100644 --- a/sys/arch/amiga/dev/grf_cl.c +++ b/sys/arch/amiga/dev/grf_cl.c @@ -1,7 +1,8 @@ -/* $OpenBSD: grf_cl.c,v 1.9 1997/01/16 09:24:10 niklas Exp $ */ -/* $NetBSD: grf_cl.c,v 1.18 1996/12/23 09:10:04 veego Exp $ */ +/* $OpenBSD: grf_cl.c,v 1.10 1997/09/18 13:39:47 niklas Exp $ */ +/* $NetBSD: grf_cl.c,v 1.20 1997/07/29 17:46:24 veego Exp $ */ /* + * Copyright (c) 1997 Klaus Burkert * Copyright (c) 1995 Ezra Story * Copyright (c) 1995 Kari Mettinen * Copyright (c) 1994 Markus Wild @@ -51,6 +52,10 @@ * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95 * Picasso/040 patches (wee!) by crest 01/96 * + * PicassoIV support bz Klaus "crest" Burkert. + * Fixed interlace and doublescan, added clockdoubling and + * HiColor&TrueColor suuport by crest 01/97 + * * Thanks to Village Tronic Marketing Gmbh for providing me with * a Picasso-II board. * Thanks for Integrated Electronics Oy Ab for providing me with @@ -78,44 +83,45 @@ #include <amiga/dev/grf_clreg.h> #include <amiga/dev/zbusvar.h> -int cl_mondefok __P((struct grfvideo_mode *)); -void cl_boardinit __P((struct grf_softc *)); -static void cl_CompFQ __P((u_int, u_char *, u_char *)); -int cl_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); -int cl_setvmode __P((struct grf_softc *, unsigned int)); -int cl_toggle __P((struct grf_softc *, unsigned short)); -int cl_getcmap __P((struct grf_softc *, struct grf_colormap *)); -int cl_putcmap __P((struct grf_softc *, struct grf_colormap *)); +int cl_mondefok __P((struct grfvideo_mode *)); +void cl_boardinit __P((struct grf_softc *)); +void cl_CompFQ __P((u_int, u_char *, u_char *, u_char *)); +int cl_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); +int cl_setvmode __P((struct grf_softc *, unsigned int)); +int cl_toggle __P((struct grf_softc *, unsigned short)); +int cl_getcmap __P((struct grf_softc *, struct grf_colormap *)); +int cl_putcmap __P((struct grf_softc *, struct grf_colormap *)); #ifndef CL5426CONSOLE -void cl_off __P((struct grf_softc *)); +void cl_off __P((struct grf_softc *)); #endif -void cl_inittextmode __P((struct grf_softc *)); -int cl_ioctl __P((register struct grf_softc *, u_long, void *)); -int cl_getmousepos __P((struct grf_softc *, struct grf_position *)); -int cl_setmousepos __P((struct grf_softc *, struct grf_position *)); -static int cl_setspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *)); -int cl_getspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *)); -static int cl_getspritemax __P((struct grf_softc *, struct grf_position *)); -int cl_blank __P((struct grf_softc *, int *)); -int cl_setmonitor __P((struct grf_softc *, struct grfvideo_mode *)); -void cl_writesprpos __P((volatile char *, short, short)); -void writeshifted __P((volatile char *, char, char)); - -static void RegWakeup __P((volatile caddr_t)); -static void RegOnpass __P((volatile caddr_t)); -static void RegOffpass __P((volatile caddr_t)); - -void grfclattach __P((struct device *, struct device *, void *)); -int grfclprint __P((void *, const char *)); -int grfclmatch __P((struct device *, void *, void *)); -void cl_memset __P((unsigned char *, unsigned char, int)); +void cl_inittextmode __P((struct grf_softc *)); +int cl_ioctl __P((register struct grf_softc *, u_long, void *)); +int cl_getmousepos __P((struct grf_softc *, struct grf_position *)); +int cl_setmousepos __P((struct grf_softc *, struct grf_position *)); +int cl_setspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *)); +int cl_getspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *)); +int cl_getspritemax __P((struct grf_softc *, struct grf_position *)); +int cl_blank __P((struct grf_softc *, int *)); +int cl_setmonitor __P((struct grf_softc *, struct grfvideo_mode *)); +void cl_writesprpos __P((volatile char *, short, short)); +void writeshifted __P((volatile char *, char, char)); + +void RegWakeup __P((volatile caddr_t)); +void RegOnpass __P((volatile caddr_t)); +void RegOffpass __P((volatile caddr_t)); + +void grfclattach __P((struct device *, struct device *, void *)); +int grfclprint __P((void *, const char *)); +int grfclmatch __P((struct device *, void *, void *)); +void cl_memset __P((unsigned char *, unsigned char, int)); /* Graphics display definitions. * These are filled by 'grfconfig' using GRFIOCSETMON. */ -#define monitor_def_max 8 -static struct grfvideo_mode monitor_def[8] = { - {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} +#define monitor_def_max 24 +static struct grfvideo_mode monitor_def[24] = { + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, }; static struct grfvideo_mode *monitor_current = &monitor_def[0]; @@ -138,8 +144,8 @@ unsigned long cl_maxpixelclock = 86000000; extern unsigned char CIRRUSFONT[]; struct grfcltext_mode clconsole_mode = { - {255, "", 25200000, 640, 480, 4, 80, 100, 94, 99, 100, 481, 522, 490, - 498, 522}, + {255, "", 25200000, 640, 480, 4, 640/8, 752/8, 792/8, 800/8, + 481, 490, 498, 522, 0}, 8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255 }; /* Console colors */ @@ -148,10 +154,11 @@ unsigned char clconscolors[3][3] = { /* background, foreground, hilite */ }; int cltype = 0; /* Picasso, Spectrum or Piccolo */ -int cl_sd64 = 0; +int cl_64bit = 0; unsigned char pass_toggle; /* passthru status tracker */ -/* because all 5426-boards have 2 configdev entries, one for +/* + * because all 542x-boards have 2 configdev entries, one for * framebuffer mem and the other for regs, we have to hold onto * the pointers globally until we match on both. This and 'cltype' * are the primary obsticles to multiple board support, but if you @@ -160,8 +167,10 @@ unsigned char pass_toggle; /* passthru status tracker */ static void *cl_fbaddr = 0; /* framebuffer */ static void *cl_regaddr = 0; /* registers */ static int cl_fbsize; /* framebuffer size */ +static int cl_fbautosize; /* framebuffer autoconfig size */ -/* current sprite info, if you add support for multiple boards +/* + * current sprite info, if you add support for multiple boards * make this an array or something */ struct grf_spriteinfo cl_cursprite; @@ -191,9 +200,10 @@ grfclmatch(pdp, match, auxp) struct cfdata *cfp = match; #endif struct zbus_args *zap; - static int regprod, fbprod; + static int regprod, fbprod, fbprod2; int error; + fbprod2 = 0; zap = auxp; #ifndef CL5426CONSOLE @@ -207,11 +217,38 @@ grfclmatch(pdp, match, auxp) if (cltype == 0) { switch (zap->manid) { case PICASSO: - if (zap->prodid != 12 && zap->prodid != 11) - return (0); - regprod = 12; - fbprod = 11; - break; + switch (zap->prodid) { + case 11: + case 12: + regprod = 12; + fbprod = 11; + error = 0; + break; + case 22: + fbprod2 = 22; + error = 0; + break; + case 21: + case 23: + regprod = 23; + fbprod = 21; + cl_64bit = 1; + error = 0; + break; + case 24: + regprod = 24; + fbprod = 24; + cl_64bit = 1; + error = 0; + break; + default: + error = 1; + break; + } + if (error == 1) + return (0); + else + break; case SPECTRUM: if (zap->prodid != 2 && zap->prodid != 1) return (0); @@ -230,7 +267,7 @@ grfclmatch(pdp, match, auxp) case 11: regprod = 11; fbprod = 10; - cl_sd64 = 1; + cl_64bit = 1; error = 0; break; default: @@ -252,14 +289,39 @@ grfclmatch(pdp, match, auxp) } /* Configure either registers or framebuffer in any order */ - if (zap->prodid == regprod) - cl_regaddr = zap->va; - else - if (zap->prodid == fbprod) { + if ((cltype == PICASSO) && (cl_64bit == 1)) { + switch (zap->prodid) { + case 21: cl_fbaddr = zap->va; - cl_fbsize = zap->size; - } else + cl_fbautosize = zap->size; + break; + case 22: + cl_fbautosize += zap->size; + break; + case 23: + cl_regaddr = (void *)((unsigned long)(zap->va) + + 0x10000); + break; + case 24: + cl_regaddr = (void *)((unsigned long)(zap->va) + + 0x600000); + cl_fbaddr = (void *)((unsigned long)(zap->va) + + 0x01000000); + cl_fbautosize = 0x400000; + break; + default: return (0); + } + } else { + if (zap->prodid == regprod) + cl_regaddr = zap->va; + else + if (zap->prodid == fbprod) { + cl_fbaddr = zap->va; + cl_fbautosize = zap->size; + } else + return (0); + } #ifdef CL5426CONSOLE if (amiga_realconfig == 0) { @@ -326,15 +388,41 @@ grfclattach(pdp, dp, auxp) printf("grfcl: %dMB ", cl_fbsize / 0x100000); switch (cltype) { case PICASSO: - printf("Picasso II"); - cl_maxpixelclock = 86000000; + if (cl_64bit == 1) { + printf("Picasso IV"); + /* 135MHz will be supported if we + * have a palette doubling mode. + */ + cl_maxpixelclock = 86000000; + } else { + printf("Picasso II"); + + /* check for PicassoII+ (crest) */ + if (zap->serno == 0x00100000) + printf("+"); + + /* determine used Gfx/chipset (crest) */ + vgaw(gp->g_regkva, CRT_ADDRESS, 0x27); + switch(vgar(gp->g_regkva, CRT_ADDRESS_R)>>2) { + case 0x24: + printf(" (with CL-GD5426)"); + break; + case 0x26: + printf(" (with CL-GD5428)"); + break; + case 0x27: + printf(" (with CL-GD5429)"); + break; + } + cl_maxpixelclock = 86000000; + } break; case SPECTRUM: printf("Spectrum"); cl_maxpixelclock = 90000000; break; case PICCOLO: - if (cl_sd64 == 1) { + if (cl_64bit == 1) { printf("Piccolo SD64"); /* 110MHz will be supported if we * have a palette doubling mode. @@ -373,98 +461,112 @@ cl_boardinit(gp) unsigned char *ba = gp->g_regkva; int x; - /* wakeup board and flip passthru OFF */ - - RegWakeup(ba); - RegOnpass(ba); + if ((cltype == PICASSO) && (cl_64bit == 1)) { /* PicassoIV */ + /* disable capture (FlickerFixer) */ + WCrt(ba, 0x51, 0x00); + /* wait some time (two frames as of now) */ + delay(200000); + /* get Blitter into 542x */ + WGfx(ba, 0x2f, 0x00); + /* compatibility mode */ + WGfx(ba, GCT_ID_RESERVED, 0x00); + /* or at least, try so... */ + WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); + cl_fbsize = cl_fbautosize; + } else { - vgaw(ba, 0x46e8, 0x16); - vgaw(ba, 0x102, 1); - vgaw(ba, 0x46e8, 0x0e); - if (cl_sd64 != 1) - vgaw(ba, 0x3c3, 1); + /* wakeup board and flip passthru OFF */ + RegWakeup(ba); + RegOnpass(ba); - /* setup initial unchanging parameters */ + vgaw(ba, 0x46e8, 0x16); + vgaw(ba, 0x102, 1); + vgaw(ba, 0x46e8, 0x0e); + if (cl_64bit != 1) + vgaw(ba, 0x3c3, 1); - WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot - display off */ - vgaw(ba, GREG_MISC_OUTPUT_W, 0xed); /* mem disable */ + cl_fbsize = cl_fbautosize; - WGfx(ba, GCT_ID_OFFSET_1, 0xec); /* magic cookie */ - WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12); /* yum! cookies! */ + /* setup initial unchanging parameters */ - if (cl_sd64 == 1) { - WSeq(ba, SEQ_ID_CONF_RBACK, 0x00); - WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8); - } else { - WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0); - } - WSeq(ba, SEQ_ID_RESET, 0x03); - WSeq(ba, SEQ_ID_MAP_MASK, 0xff); - WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); - WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */ - WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x20 : 0x80); - WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00); - if (cl_sd64 == 1) - WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a); - else - WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a); /* mouse 0a fa */ - WSeq(ba, SEQ_ID_SIG_CNTL, 0x02); - WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04); + /* 8 dot - display off */ + WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); + vgaw(ba, GREG_MISC_OUTPUT_W, 0xed); /* mem disable */ - if (cl_sd64 == 1) - WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c); - else - WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22); - - WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); - WCrt(ba, CRT_ID_CURSOR_START, 0x00); - WCrt(ba, CRT_ID_CURSOR_END, 0x08); - WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); - WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); - WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); - WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); - - WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07); - WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */ - WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */ - WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22); - if (cl_sd64 == 1) { - WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00); - WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40); - } - WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c); /* mouse 0x00 */ - - WGfx(ba, GCT_ID_SET_RESET, 0x00); - WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); - WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); - WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); - WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00); - WGfx(ba, GCT_ID_MISC, 0x01); - WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); - WGfx(ba, GCT_ID_BITMASK, 0xff); - WGfx(ba, GCT_ID_MODE_EXT, 0x28); - - for (x = 0; x < 0x10; x++) - WAttr(ba, x, x); - WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); - WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); - WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); - WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); - WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); + WGfx(ba, GCT_ID_OFFSET_1, 0xec); /* magic cookie */ + WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12); /* yum! cookies! */ - delay(200000); - WAttr(ba, 0x34, 0x00); - delay(200000); + if (cl_64bit == 1) { + WSeq(ba, SEQ_ID_CONF_RBACK, 0x00); + WSeq(ba, SEQ_ID_DRAM_CNTL, + (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8); + } else { + WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0); + } + WSeq(ba, SEQ_ID_RESET, 0x03); + WSeq(ba, SEQ_ID_MAP_MASK, 0xff); + WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); + WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */ + WSeq(ba, SEQ_ID_EXT_SEQ_MODE, + (cltype == PICASSO) ? 0x21 : 0x81); + WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00); + if (cl_64bit == 1) + WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a); + else + /* mouse 0a fa */ + WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a); + WSeq(ba, SEQ_ID_SIG_CNTL, 0x02); + WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04); + if (cl_64bit == 1) + WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c); + else + WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22); - vgaw(ba, VDAC_MASK, 0xff); - delay(200000); - vgaw(ba, GREG_MISC_OUTPUT_W, 0xef); + WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); + WCrt(ba, CRT_ID_CURSOR_START, 0x00); + WCrt(ba, CRT_ID_CURSOR_END, 0x08); + WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00); + WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00); + WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); + WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); - WGfx(ba, GCT_ID_BLT_STAT_START, 0x04); - WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); + WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07); + WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); + WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */ + WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22); + if (cl_64bit == 1) { + WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00); + WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40); + } + WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c); /* mouse 0x00 */ + + WGfx(ba, GCT_ID_SET_RESET, 0x00); + WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); + WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); + WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); + WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00); + WGfx(ba, GCT_ID_MISC, 0x01); + WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); + WGfx(ba, GCT_ID_BITMASK, 0xff); + WGfx(ba, GCT_ID_MODE_EXT, 0x28); + + for (x = 0; x < 0x10; x++) + WAttr(ba, x, x); + WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); + WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00); + WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f); + WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00); + WAttr(ba, ACT_ID_COLOR_SELECT, 0x00); + WAttr(ba, 0x34, 0x00); + + vgaw(ba, VDAC_MASK, 0xff); + vgaw(ba, GREG_MISC_OUTPUT_W, 0xef); + + WGfx(ba, GCT_ID_BLT_STAT_START, 0x04); + WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); + } /* colors initially set to greyscale */ - vgaw(ba, VDAC_ADDRESS_W, 0); for (x = 255; x >= 0; x--) { vgaw(ba, VDAC_DATA, x); @@ -477,6 +579,23 @@ cl_boardinit(gp) cl_cursprite.cmap.red = cl_sprred; cl_cursprite.cmap.green = cl_sprgreen; cl_cursprite.cmap.blue = cl_sprblue; + + if (cl_64bit == 0) { + /* check for 1MB or 2MB board (crest) */ + volatile unsigned long *cl_fbtestaddr; + cl_fbtestaddr = (volatile unsigned long *)gp->g_fbkva; + + WGfx(ba, GCT_ID_OFFSET_0, 0x40); + *cl_fbtestaddr = 0x12345678; + + if (*cl_fbtestaddr != 0x12345678) { + WSeq(ba, SEQ_ID_DRAM_CNTL, 0x30); + cl_fbsize = 0x100000; + } else { + cl_fbsize = 0x200000; + } + } + WGfx(ba, GCT_ID_OFFSET_0, 0x00); } @@ -510,7 +629,6 @@ cl_getvmode(gp, vm) /* adjust internal values to pixel values */ vm->hblank_start *= 8; - vm->hblank_stop *= 8; vm->hsync_start *= 8; vm->hsync_stop *= 8; vm->htotal *= 8; @@ -540,11 +658,14 @@ cl_off(gp) { char *ba = gp->g_regkva; - /* we'll put the pass-through on for cc ite and set Full Bandwidth bit + /* + * we'll put the pass-through on for cc ite and set Full Bandwidth bit * on just in case it didn't work...but then it doesn't matter does - * it? =) */ + * it? =) + */ RegOnpass(ba); - WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); + vgaw(ba, SEQ_ADDRESS, SEQ_ID_CLOCKING_MODE); + vgaw(ba, SEQ_ADDRESS_W, vgar(ba, SEQ_ADDRESS_W) | 0x20); } #endif @@ -679,13 +800,14 @@ cl_writesprpos(ba, x, y) cwp = ba + 0x3c4; wp = (unsigned short *)cwp; - /* don't ask me why, but apparently you can't do a 16-bit write with - * x-position like with y-position below (dagge) */ + /* + * don't ask me why, but apparently you can't do a 16-bit write with + * x-position like with y-position below (dagge) + */ cwp[0] = 0x10 | ((x << 5) & 0xff); cwp[1] = (x >> 3) & 0xff; *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff); - } void @@ -704,7 +826,8 @@ writeshifted(to, shiftx, shifty) shiftx = shiftx < 0 ? 0 : shiftx; shifty = shifty < 0 ? 0 : shifty; - /* start reading shifty lines down, and + /* + * start reading shifty lines down, and * shift each line in by shiftx */ for (y = shifty; y < 64; y++) { @@ -747,7 +870,8 @@ cl_setmousepos(gp, data) prx = cl_cursprite.pos.x - cl_cursprite.hot.x; pry = cl_cursprite.pos.y - cl_cursprite.hot.y; - /* if we are/were on an edge, create (un)shifted bitmap -- + /* + * if we are/were on an edge, create (un)shifted bitmap -- * ripped out optimization (not extremely worthwhile, * and kind of buggy anyhow). */ @@ -776,7 +900,7 @@ cl_getspriteinfo(gp, data) return (0); } -static int +int cl_setspriteinfo(gp, data) struct grf_softc *gp; struct grf_spriteinfo *data; @@ -912,7 +1036,7 @@ cl_setspriteinfo(gp, data) return (0); } -static int +int cl_getspritemax(gp, data) struct grf_softc *gp; struct grf_position *data; @@ -938,11 +1062,10 @@ cl_setmonitor(gp, gv) /* handle interactive setting of console mode */ if (gv->mode_num == 255) { bcopy(gv, &clconsole_mode.gv, sizeof(struct grfvideo_mode)); - clconsole_mode.gv.hblank_start /= 8; - clconsole_mode.gv.hblank_stop /= 8; - clconsole_mode.gv.hsync_start /= 8; - clconsole_mode.gv.hsync_stop /= 8; - clconsole_mode.gv.htotal /= 8; + clconsole_mode.gv.hblank_start /= 8; + clconsole_mode.gv.hsync_start /= 8; + clconsole_mode.gv.hsync_stop /= 8; + clconsole_mode.gv.htotal /= 8; clconsole_mode.rows = gv->disp_height / clconsole_mode.fy; clconsole_mode.cols = gv->disp_width / clconsole_mode.fx; if (!(gp->g_flags & GF_GRFON)) @@ -955,13 +1078,12 @@ cl_setmonitor(gp, gv) md = monitor_def + (gv->mode_num - 1); bcopy(gv, md, sizeof(struct grfvideo_mode)); - /* adjust pixel oriented values to internal rep. */ + /* adjust pixel oriented values to internal rep. */ - md->hblank_start /= 8; - md->hblank_stop /= 8; - md->hsync_start /= 8; - md->hsync_stop /= 8; - md->htotal /= 8; + md->hblank_start /= 8; + md->hsync_start /= 8; + md->hsync_stop /= 8; + md->htotal /= 8; return (0); } @@ -987,12 +1109,22 @@ cl_getcmap(gfp, cmap) vgaw(ba, VDAC_ADDRESS_R, cmap->index); x = cmap->count - 1; -/* Some sort 'o Magic. Spectrum has some changes on the board to speed +/* + * Some sort 'o Magic. Spectrum has some changes on the board to speed * up 15 and 16Bit modes. They can access these modes with easy-to-programm * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb * is swapped to bgr. I wonder if we need to check for 8Bit though, ill */ +/* + * The source for the above comment is somewhat unknow to me. + * The Spectrum, Piccolo and PiccoloSD64 have the analog Red and Blue + * lines swapped. In 24BPP this provides RGB instead of BGR as it would + * be native to the chipset. This requires special programming for the + * CLUT in 8BPP to compensate and avoid false colors. + * I didn't find any special stuff for 15 and 16BPP though, crest. + */ + switch (cltype) { case SPECTRUM: case PICCOLO: @@ -1088,19 +1220,17 @@ cl_toggle(gp, wopp) if (pass_toggle) { RegOffpass(ba); } else { - /* This was in the original.. is it needed? */ - if (cltype == PICASSO || cltype == PICCOLO) - RegWakeup(ba); RegOnpass(ba); } return (0); } -static void -cl_CompFQ(fq, num, denom) +void +cl_CompFQ(fq, num, denom, clkdoub) u_int fq; u_char *num; u_char *denom; + u_char *clkdoub; { #define OSC 14318180 /* OK, here's what we're doing here: @@ -1136,19 +1266,34 @@ denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even) mind = 0; p = 0; - for (d = 1; d < 0x20; d++) { - for (n = 1; n < 0x80; n++) { - err = abs(count(n, d, p) - fq); - if (err < minerr) { - minerr = err; - minn = n; - mind = d; - minp = p; + if ((cl_64bit == 1) && (fq >= 86000000)) { + for (d = 1; d < 0x20; d++) { + for (n = 1; n < 0x80; n++) { + err = abs(count(n, d, 0) - fq); + if (err < minerr) { + minerr = err; + minn = n; + mind = d; + minp = 1; + } } } - if (d == 0x1f && p == 0) { - p = 1; - d = 0x0f; + *clkdoub = 1; + } else { + for (d = 1; d < 0x20; d++) { + for (n = 1; n < 0x80; n++) { + err = abs(count(n, d, p) - fq); + if (err < minerr) { + minerr = err; + minn = n; + mind = d; + minp = p; + } + } + if (d == 0x1f && p == 0) { + p = 1; + d = 0x0f; + } } } @@ -1170,25 +1315,56 @@ cl_mondefok(gv) return(0); switch (gv->depth) { - case 4: + case 4: if (gv->mode_num != 255) return(0); - case 1: - case 8: - maxpix = cl_maxpixelclock; + case 1: + case 8: + maxpix = cl_maxpixelclock; + if (cl_64bit == 1) + { + if (cltype == PICASSO) /* Picasso IV */ + maxpix = 135000000; + else /* Piccolo SD64 */ + maxpix = 110000000; + } break; - case 15: - case 16: - maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3); + case 15: + case 16: + if (cl_64bit == 1) + maxpix = 85000000; + else + maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3); break; - case 24: - maxpix = cl_maxpixelclock / 3; + case 24: + if ((cltype == PICASSO) && (cl_64bit == 1)) + maxpix = 85000000; + else + maxpix = cl_maxpixelclock / 3; + break; + case 32: + if ((cltype == PICCOLO) && (cl_64bit == 1)) + maxpix = 50000000; + else + maxpix = 0; break; default: + printf("grfcl: Illegal depth in mode %d\n", + (int) gv->mode_num); return (0); } - if (gv->pixel_clock > maxpix) + + if (gv->pixel_clock > maxpix) { + printf("grfcl: Pixelclock too high in mode %d\n", + (int) gv->mode_num); return (0); + } + + if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { + printf("grfcl: sync-on-green is not supported\n"); + return (0); + } + return (1); } @@ -1200,31 +1376,36 @@ cl_load_mon(gp, md) struct grfvideo_mode *gv; struct grfinfo *gi; volatile caddr_t ba, fb; - unsigned char num0, denom0; + unsigned char num0, denom0, clkdoub; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; - char LACE, DBLSCAN, TEXT; - unsigned short clkdiv; - int uplim, lowlim; + int clkmul, offsmul, clkmode; + int vmul; int sr15; + unsigned char hvsync_pulse; + char TEXT; /* identity */ gv = &md->gv; TEXT = (gv->depth == 4); if (!cl_mondefok(gv)) { - printf("mondef not ok\n"); + printf("grfcl: Monitor definition not ok\n"); return (0); } + ba = gp->g_regkva; fb = gp->g_fbkva; - /* provide all needed information in grf device-independant locations */ - gp->g_data = (caddr_t) gv; + /* + * provide all needed information in grf device-independant + * locations + */ + gp->g_data = (caddr_t)gv; gi = &gp->g_display; - gi->gd_regaddr = (caddr_t) ztwopa(ba); + gi->gd_regaddr = (caddr_t)kvtop(ba); gi->gd_regsize = 64 * 1024; - gi->gd_fbaddr = (caddr_t) kvtop(fb); + gi->gd_fbaddr = (caddr_t)kvtop(fb); gi->gd_fbsize = cl_fbsize; gi->gd_colors = 1 << gv->depth; gi->gd_planes = gv->depth; @@ -1245,14 +1426,14 @@ cl_load_mon(gp, md) /* get display mode parameters */ HBS = gv->hblank_start; - HBE = gv->hblank_stop; HSS = gv->hsync_start; HSE = gv->hsync_stop; + HBE = gv->htotal - 1; HT = gv->htotal; VBS = gv->vblank_start; VSS = gv->vsync_start; VSE = gv->vsync_stop; - VBE = gv->vblank_stop; + VBE = gv->vtotal - 1; VT = gv->vtotal; if (TEXT) @@ -1261,27 +1442,68 @@ cl_load_mon(gp, md) HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ VDE = gv->disp_height - 1; - /* figure out whether lace or dblscan is needed */ + /* adjustments */ + switch (gv->depth) { + case 8: + clkmul = 1; + offsmul = 1; + clkmode = 0x0; + break; + case 15: + case 16: + clkmul = 1; + offsmul = 2; + clkmode = 0x6; + break; + case 24: + /* Picasso IV? */ + if ((cltype == PICASSO) && (cl_64bit == 1)) + clkmul = 1; + else + clkmul = 3; + offsmul = 3; + clkmode = 0x4; + break; + case 32: + clkmul = 1; + offsmul = 2; + clkmode = 0x8; + break; + default: + clkmul = 1; + offsmul = 1; + clkmode = 0x0; + break; + } - uplim = gv->disp_height + (gv->disp_height / 4); - lowlim = gv->disp_height - (gv->disp_height / 4); - LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; - DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; + if ((VT > 1023) && (!(gv->disp_flags & GRF_FLAGS_LACE))) { + WCrt(ba, CRT_ID_MODE_CONTROL, 0xe7); + } else + WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); - /* adjustments */ + vmul = 2; + if ((VT > 1023) || (gv->disp_flags & GRF_FLAGS_LACE)) + vmul = 1; + if (gv->disp_flags & GRF_FLAGS_DBLSCAN) + vmul = 4; - if (LACE) - VDE /= 2; + VDE = VDE * vmul / 2; + VBS = VBS * vmul / 2; + VSS = VSS * vmul / 2; + VSE = VSE * vmul / 2; + VBE = VBE * vmul / 2; + VT = VT * vmul / 2; WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); - if (cl_sd64 == 1) { + if (cl_64bit == 1) { if (TEXT || (gv->depth == 1)) - sr15 = 0x90; + sr15 = 0xd0; else sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8); WSeq(ba, SEQ_ID_CONF_RBACK, 0x00); } else { sr15 = (TEXT || (gv->depth == 1)) ? 0xd0 : 0xb0; + sr15 &= ((cl_fbsize / 0x100000) == 2) ? 0xff : 0x7f; } WSeq(ba, SEQ_ID_DRAM_CNTL, sr15); WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); @@ -1290,8 +1512,30 @@ cl_load_mon(gp, md) /* Set clock */ - cl_CompFQ((gv->depth == 24) ? gv->pixel_clock * 3 : gv->pixel_clock, - &num0, &denom0); + cl_CompFQ(gv->pixel_clock * clkmul, &num0, &denom0, &clkdoub); + + /* Horizontal/Vertical Sync Pulse */ + hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); + if (gv->disp_flags & GRF_FLAGS_PHSYNC) + hvsync_pulse &= ~0x40; + else + hvsync_pulse |= 0x40; + if (gv->disp_flags & GRF_FLAGS_PVSYNC) + hvsync_pulse &= ~0x80; + else + hvsync_pulse |= 0x80; + vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); + + if (clkdoub) { + HDE /= 2; + HBS /= 2; + HSS /= 2; + HSE /= 2; + HBE /= 2; + HT /= 2; + clkmode = 0x6; + } + WSeq(ba, SEQ_ID_VCLK_3_NUM, num0); WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0); @@ -1316,13 +1560,11 @@ cl_load_mon(gp, md) ((VDE & 0x200) ? 0x40 : 0x00) | ((VSS & 0x200) ? 0x80 : 0x00)); - WCrt(ba, CRT_ID_CHAR_HEIGHT, 0x40 | /* TEXT ? 0x00 ??? */ - (DBLSCAN ? 0x80 : 0x00) | + ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | ((VBS & 0x200) ? 0x20 : 0x00) | (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); - WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3); /* text cursor */ @@ -1351,48 +1593,23 @@ cl_load_mon(gp, md) WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); WCrt(ba, CRT_ID_LACE_END, HT / 2); /* MW/16 */ WCrt(ba, CRT_ID_LACE_CNTL, - (LACE ? 0x01 : 0x00) | + ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x01 : 0x00) | ((HBE & 0x40) ? 0x10 : 0x00) | ((HBE & 0x80) ? 0x20 : 0x00) | ((VBE & 0x100) ? 0x40 : 0x00) | ((VBE & 0x200) ? 0x80 : 0x00)); - /* depth dependent stuff */ - - switch (gv->depth) { - case 1: - case 4: - case 8: - clkdiv = 0; - break; - case 15: - case 16: - clkdiv = 3; - break; - case 24: - clkdiv = 2; - break; - default: - clkdiv = 0; - panic("grfcl: Unsuported depth: %i", gv->depth); - break; - } - WGfx(ba, GCT_ID_GRAPHICS_MODE, ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); WSeq(ba, SEQ_ID_EXT_SEQ_MODE, ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) | - ((cltype == PICASSO) ? 0x20 : 0x80) | - (clkdiv << 1)); - - delay(200000); + ((cltype == PICASSO) ? 0x20 : 0x80) | clkmode); /* write 0x00 to VDAC_MASK before accessing HDR this helps sometimes, out of "secret" application note (crest) */ vgaw(ba, VDAC_MASK, 0); - delay(200000); /* reset HDR "magic" access counter (crest) */ vgar(ba, VDAC_ADDRESS); @@ -1406,53 +1623,54 @@ cl_load_mon(gp, md) vgar(ba, VDAC_MASK); delay(200000); switch (gv->depth) { - case 1: - case 4: /* text */ + case 1: + case 4: /* text */ vgaw(ba, VDAC_MASK, 0); HDE = gv->disp_width / 16; break; - case 8: - vgaw(ba, VDAC_MASK, 0); + case 8: + if (clkdoub) + vgaw(ba, VDAC_MASK, 0x4a); /* Clockdouble Magic */ + else + vgaw(ba, VDAC_MASK, 0); HDE = gv->disp_width / 8; break; - case 15: + case 15: vgaw(ba, VDAC_MASK, 0xd0); HDE = gv->disp_width / 4; break; - case 16: + case 16: vgaw(ba, VDAC_MASK, 0xc1); HDE = gv->disp_width / 4; break; - case 24: + case 24: vgaw(ba, VDAC_MASK, 0xc5); HDE = (gv->disp_width / 8) * 3; break; + case 32: + vgaw(ba, VDAC_MASK, 0xc5); + HDE = (gv->disp_width / 4); + break; } - delay(20000); /* reset HDR "magic" access counter (crest) */ vgar(ba, VDAC_ADDRESS); - delay(200000); /* then enable all bit in VDAC_MASK afterwards (crest) */ vgaw(ba, VDAC_MASK, 0xff); - delay(20000); WCrt(ba, CRT_ID_OFFSET, HDE); - if (cl_sd64 == 1) { + if (cl_64bit == 1) { WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00); WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40); } WCrt(ba, CRT_ID_EXT_DISP_CNTL, ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) | 0x22 | - ((HDE > 0xff) ? 0x10 : 0x00)); /* text? */ + ((HDE > 0xff) ? 0x10 : 0x00)); - delay(200000); WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01)); - delay(200000); WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA, (gv->depth == 1) ? 0x01 : 0x0f); - delay(200000); /* text initialization */ @@ -1506,7 +1724,6 @@ cl_inittextmode(gp) /* set colors (B&W) */ - vgaw(ba, VDAC_ADDRESS_W, 0); for (z = 0; z < 256; z++) { unsigned char r, g, b; @@ -1538,13 +1755,14 @@ cl_memset(d, c, l) *d++ = c; } -/* Special wakeup/passthrough registers on graphics boards +/* + * Special wakeup/passthrough registers on graphics boards * * The methods have diverged a bit for each board, so * WPass(P) has been converted into a set of specific * inline functions. */ -static void +void RegWakeup(ba) volatile caddr_t ba; { @@ -1554,19 +1772,20 @@ RegWakeup(ba) vgaw(ba, PASS_ADDRESS_W, 0x1f); break; case PICASSO: - vgaw(ba, PASS_ADDRESS_W, 0xff); + /* Picasso needs no wakeup */ break; case PICCOLO: - if (cl_sd64 == 1) + if (cl_64bit == 1) vgaw(ba, PASS_ADDRESS_W, 0x1f); else - vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x10); + vgaw(ba, PASS_ADDRESS_W, + vgar(ba, PASS_ADDRESS) | 0x10); break; } delay(200000); } -static void +void RegOnpass(ba) volatile caddr_t ba; { @@ -1579,7 +1798,7 @@ RegOnpass(ba) vgaw(ba, PASS_ADDRESS_WP, 0x01); break; case PICCOLO: - if (cl_sd64 == 1) + if (cl_64bit == 1) vgaw(ba, PASS_ADDRESS_W, 0x4f); else vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) & 0xdf); @@ -1589,7 +1808,7 @@ RegOnpass(ba) delay(200000); } -static void +void RegOffpass(ba) volatile caddr_t ba; { @@ -1599,15 +1818,15 @@ RegOffpass(ba) vgaw(ba, PASS_ADDRESS_W, 0x6f); break; case PICASSO: - vgaw(ba, PASS_ADDRESS_W, 0xff); - delay(200000); - vgaw(ba, PASS_ADDRESS_W, 0xff); + if (cl_64bit == 0) + vgaw(ba, PASS_ADDRESS_W, 0xff); break; case PICCOLO: - if (cl_sd64 == 1) + if (cl_64bit == 1) vgaw(ba, PASS_ADDRESS_W, 0x6f); else - vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x20); + vgaw(ba, PASS_ADDRESS_W, + vgar(ba, PASS_ADDRESS) | 0x20); break; } pass_toggle = 0; diff --git a/sys/arch/amiga/dev/grf_clreg.h b/sys/arch/amiga/dev/grf_clreg.h index 048cc22105e..3644079e66a 100644 --- a/sys/arch/amiga/dev/grf_clreg.h +++ b/sys/arch/amiga/dev/grf_clreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_clreg.h,v 1.6 1997/01/16 09:24:11 niklas Exp $ */ -/* $NetBSD: grf_clreg.h,v 1.5 1996/10/08 23:18:51 thorpej Exp $ */ +/* $OpenBSD: grf_clreg.h,v 1.7 1997/09/18 13:39:49 niklas Exp $ */ +/* $NetBSD: grf_clreg.h,v 1.6 1997/03/21 09:40:58 veego Exp $ */ /* * Copyright (c) 1995 Ezra Story @@ -264,9 +264,11 @@ struct grfcltext_mode { /* Video DAC */ #define VDAC_ADDRESS 0x03c8 #define VDAC_ADDRESS_W 0x03c8 -#define VDAC_ADDRESS_R ((cltype==PICASSO)?0x03c7+0xfff:0x3c7) +#define VDAC_ADDRESS_R \ + (((cltype == PICASSO) && (cl_64bit == 0)) ? 0x03c7 + 0xfff : 0x3c7) #define VDAC_STATE 0x03c7 -#define VDAC_DATA ((cltype==PICASSO)?0x03c9+0xfff:0x3c9) +#define VDAC_DATA \ + (((cltype == PICASSO) && (cl_64bit == 0)) ? 0x03c9 + 0xfff : 0x3c9) #define VDAC_MASK 0x03c6 #define HDR 0x03c6 /* Hidden DAC register, 4 reads to access */ diff --git a/sys/arch/amiga/dev/grf_cv.c b/sys/arch/amiga/dev/grf_cv.c index 1dc6fddfc17..034cd957ae7 100644 --- a/sys/arch/amiga/dev/grf_cv.c +++ b/sys/arch/amiga/dev/grf_cv.c @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_cv.c,v 1.14 1997/01/16 09:24:13 niklas Exp $ */ -/* $NetBSD: grf_cv.c,v 1.20 1996/12/23 09:10:05 veego Exp $ */ +/* $OpenBSD: grf_cv.c,v 1.15 1997/09/18 13:39:49 niklas Exp $ */ +/* $NetBSD: grf_cv.c,v 1.24 1997/07/30 11:05:55 veego Exp $ */ /* * Copyright (c) 1995 Michael Teske @@ -16,7 +16,7 @@ * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Ezra Story, by Kari - * Mettinen and by Bernd Ernesti. + * Mettinen, Michael Teske and by Bernd Ernesti. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -39,18 +39,12 @@ * * Modified for CV64 from * Kari Mettinen's Cirrus driver by Michael Teske 10/95 - * For questions mail me at teske@mail.desy.de * * Thanks to Tekelec Airtronic for providing me with a S3 Trio64 documentation. * Thanks to Bernd 'the fabulous bug-finder' Ernesti for bringing my messy * source to NetBSD style :) - * - * TODO: - * Bugfree Hardware Cursor support. - * The HWC routines provided here are buggy in 16/24 bit - * and may cause a Vertical Bar Crash of the Trio64. - * On the other hand it's better to put the routines in the Xserver, - * so please _don't_ put CV_HARDWARE_CURSOR in your config file. + * Thanks to Harald Koenig for providing information about undocumented + * Trio64 Bugs. */ #include <sys/param.h> @@ -59,10 +53,16 @@ #include <sys/device.h> #include <sys/malloc.h> #include <sys/systm.h> +#include <sys/syslog.h> + #include <machine/cpu.h> +#include <machine/intr.h> + #include <dev/cons.h> + #include <amiga/dev/itevar.h> #include <amiga/amiga/device.h> +#include <amiga/amiga/isr.h> #include <amiga/dev/grfioctl.h> #include <amiga/dev/grfvar.h> #include <amiga/dev/grf_cvreg.h> @@ -72,8 +72,9 @@ int grfcvmatch __P((struct device *, void *, void *)); void grfcvattach __P((struct device *, struct device *, void *)); int grfcvprint __P((void *, const char *)); -static int cv_has_4mb __P((volatile caddr_t)); -static unsigned short cv_compute_clock __P((unsigned long)); +int cvintr __P((void *)); +int cv_has_4mb __P((volatile caddr_t)); +unsigned short cv_compute_clock __P((unsigned long)); void cv_boardinit __P((struct grf_softc *)); int cv_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); int cv_setvmode __P((struct grf_softc *, unsigned int)); @@ -87,20 +88,27 @@ int cv_toggle __P((struct grf_softc *)); int cv_mondefok __P((struct grfvideo_mode *)); int cv_load_mon __P((struct grf_softc *, struct grfcvtext_mode *)); void cv_inittextmode __P((struct grf_softc *)); -static inline void cv_write_port __P((unsigned short, volatile caddr_t)); -static inline void cvscreen __P((int, volatile caddr_t)); -static inline void gfx_on_off __P((int, volatile caddr_t)); +static __inline void cv_write_port __P((unsigned short, volatile caddr_t)); +static __inline void cvscreen __P((int, volatile caddr_t)); +static __inline void gfx_on_off __P((int, volatile caddr_t)); -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR int cv_getspritepos __P((struct grf_softc *, struct grf_position *)); int cv_setspritepos __P((struct grf_softc *, struct grf_position *)); +static __inline short M2I __P((short)); int cv_getspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); -void cv_setup_hwc __P((struct grf_softc *, - unsigned char, unsigned char, unsigned char, unsigned char, - const unsigned long *)); +void cv_setup_hwc __P((struct grf_softc *)); int cv_setspriteinfo __P((struct grf_softc *,struct grf_spriteinfo *)); int cv_getspritemax __P((struct grf_softc *,struct grf_position *)); -#endif /* CV_HARDWARE_CURSOR */ +#endif /* !CV_NO_HARDWARE_CURSOR */ + +/* + * Extension to grf_softc for interrupt support + */ +struct grf_cv_softc { + struct grf_softc gcs_sc; + struct isr gcs_isr; +}; /* Graphics display definitions. * These are filled by 'grfconfig' using GRFIOCSETMON. @@ -137,8 +145,8 @@ extern unsigned char S3FONT[]; * (Internally, we still have to use hvalues/8!) */ struct grfcvtext_mode cvconsole_mode = { - {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8, - 481, 521, 491, 493, 525}, + { 255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, + 481, 521, 491, 493, 525 }, 8, S3FONTY, 80, 480 / S3FONTY, S3FONT, 32, 255 }; @@ -250,7 +258,7 @@ long cv_memclk = 50000000; /* standard driver stuff */ struct cfattach grfcv_ca = { - sizeof(struct grf_softc), grfcvmatch, grfcvattach + sizeof(struct grf_cv_softc), grfcvmatch, grfcvattach }; struct cfdriver grfcv_cd = { @@ -258,6 +266,85 @@ struct cfdriver grfcv_cd = { }; static struct cfdata *grfcv_cfdata; +#define CV_INT_NUM 6 /* CV interrupt Level: #2 or #6 */ +#define CV_ULCURSOR 1 /* Underlined Cursor in textmode */ + +#ifndef CV_NO_HARDWARE_CURSOR + +#define HWC_OFF (cv_fbsize - 1024*2) +#define HWC_SIZE 1024 + +static unsigned short cv_cursor_storage[HWC_SIZE/2]; +static short curs_update_flag = 0; +#endif /* !CV_NO_HARDWARE_CURSOR */ + +/* + * Interrupt handler + * This is used for updating the cursor shape (because it _must not_ + * be changed while cursor is displayed) + * and maybe later to avoid busy waiting + * for Vertical Blank and/or gfx engine busy + */ +int +cvintr(arg) + void * arg; +{ +#ifndef CV_NO_HARDWARE_CURSOR + register unsigned long *csrc, *cdest; + int i; +#endif /* !CV_NO_HARDWARE_CURSOR */ + struct grf_softc *gp = arg; + volatile caddr_t ba = gp->g_regkva; + unsigned char test; + unsigned char cridx; /* Save the cr Register index */ + + if (gp == NULL) + return 0; + + test = vgar(ba, GREG_INPUT_STATUS0_R); + + if (test & 0x80) { /* VR int pending */ + /* Save old CR index */ + cridx = vgar (ba, CRT_ADDRESS); + +#if 0 + test = RCrt(ba, CRT_ID_END_VER_RETR); + /* Clear int (bit 4) */ + test &= ~0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#else + vgaw(ba, CRT_ADDRESS, CRT_ID_END_VER_RETR); + asm volatile ("bclr #4,%0@(0x3d5);nop" : : "a" (ba)); +#endif + +#ifndef CV_NO_HARDWARE_CURSOR + /* update the hardware cursor, if necessary */ + if (curs_update_flag) { + csrc = (unsigned long *)cv_cursor_storage; + cdest = (unsigned long *)((volatile char *)gp->g_fbkva + + HWC_OFF); + for (i = 0; i < HWC_SIZE / sizeof(long); i++) + *cdest++ = *csrc++; + curs_update_flag = 0; + } + /* Reenable int */ +#if 0 + test |= 0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#else + /* I don't trust the optimizer here... */ + asm volatile ("bset #4,%0@(0x3d5);nop" : : "a" (ba)); +#endif + cv_setspritepos (gp, NULL); + + /* Restore the old CR index */ + vgaw(ba, CRT_ADDRESS, cridx); + __asm volatile ("nop"); +#endif /* !CV_NO_HARDWARE_CURSOR */ + return (1); + } + return (0); +} /* * Get frambuffer memory size. @@ -265,7 +352,7 @@ static struct cfdata *grfcv_cfdata; * so we have to do it this way. * Return 0 for 2MB, 1 for 4MB */ -static int +int cv_has_4mb(fb) volatile caddr_t fb; { @@ -301,7 +388,7 @@ grfcvmatch(pdp, match, auxp) #ifdef CV64CONSOLE struct cfdata *cfp = match; static int cvcons_unit = -1; -#endif +#endif /* CV64CONSOLE */ struct zbus_args *zap; zap = auxp; @@ -309,7 +396,7 @@ grfcvmatch(pdp, match, auxp) if (amiga_realconfig == 0) #ifdef CV64CONSOLE if (cvcons_unit != -1) -#endif +#endif /* CV64CONSOLE */ return (0); /* Lets be Paranoid: Test man and prod id */ @@ -323,7 +410,7 @@ grfcvmatch(pdp, match, auxp) cvcons_unit = cfp->cf_unit; grfcv_cfdata = cfp; } -#endif +#endif /* CV64CONSOLE */ return (1); } @@ -333,9 +420,10 @@ grfcvattach(pdp, dp, auxp) struct device *pdp, *dp; void *auxp; { - static struct grf_softc congrf; + static struct grf_cv_softc congrf; struct zbus_args *zap; struct grf_softc *gp; + struct grf_cv_softc *gcp; static char attachflag = 0; zap = auxp; @@ -346,28 +434,32 @@ grfcvattach(pdp, dp, auxp) */ if (dp == NULL) /* console init */ - gp = &congrf; + gcp = &congrf; else - gp = (struct grf_softc *)dp; + gcp = (struct grf_cv_softc *)dp; - if (dp != NULL && congrf.g_regkva != 0) { + gp = &gcp->gcs_sc; + + if (dp != NULL && congrf.gcs_sc.g_regkva != 0) { /* * inited earlier, just copy (not device struct) */ printf("\n"); -#ifdef CV64CONSOLE - bcopy(&congrf.g_display, &gp->g_display, - (char *) &gp[1] - (char *) &gp->g_display); -#else - gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; - gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; - - gp->g_unit = GRF_CV64_UNIT; - gp->g_mode = cv_mode; - gp->g_conpri = grfcv_cnprobe(); - gp->g_flags = GF_ALIVE; -#endif + bcopy(&congrf.gcs_sc.g_display, &gp->g_display, + (char *) &gcp->gcs_isr - (char *) &gp->g_display); + + /* ... and transfer the isr */ + gcp->gcs_isr.isr_ipl = CV_INT_NUM; +#if CV_INT_NUM == 6 + gcp->gcs_isr.isr_mapped_ipl = IPL_TTY; +#endif /* CV_INT_NUM == 6 */ + gcp->gcs_isr.isr_intr = cvintr; + gcp->gcs_isr.isr_arg = (void *)gp; + + /* First add new isr */ + add_isr(&gcp->gcs_isr); + remove_isr(&congrf.gcs_isr); } else { gp->g_regkva = (volatile caddr_t)cv_boardaddr + 0x02000000; gp->g_fbkva = (volatile caddr_t)cv_boardaddr + 0x01400000; @@ -377,13 +469,22 @@ grfcvattach(pdp, dp, auxp) gp->g_conpri = grfcv_cnprobe(); gp->g_flags = GF_ALIVE; + /* add Interrupt Handler */ + gcp->gcs_isr.isr_ipl = CV_INT_NUM; +#if CV_INT_NUM == 6 + gcp->gcs_isr.isr_mapped_ipl = IPL_TTY; +#endif /* CV_INT_NUM == 6 */ + gcp->gcs_isr.isr_intr = cvintr; + gcp->gcs_isr.isr_arg = (void *)gp; + add_isr(&gcp->gcs_isr); + /* wakeup the board */ cv_boardinit(gp); #ifdef CV64CONSOLE grfcv_iteinit(gp); (void)cv_load_mon(gp, &cvconsole_mode); -#endif +#endif /* CV64CONSOLE */ } /* @@ -391,7 +492,8 @@ grfcvattach(pdp, dp, auxp) */ if (amiga_config_found(grfcv_cfdata, &gp->g_device, gp, grfcvprint)) { if (dp != NULL) - printf("grfcv: CyberVision64 with %dMB being used\n", cv_fbsize/0x100000); + printf("grfcv: CyberVision64 with %dMB being used\n", + cv_fbsize/0x100000); attachflag = 1; } else { if (!attachflag) @@ -421,7 +523,7 @@ grfcvprint(auxp, pnp) * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 */ -static unsigned short +unsigned short cv_compute_clock(freq) unsigned long freq; { @@ -492,6 +594,17 @@ cv_boardinit(gp) WCrt(ba, CRT_ID_REGISTER_LOCK_1, 0x48); /* unlock S3 VGA regs */ WCrt(ba, CRT_ID_REGISTER_LOCK_2, 0xA5); /* unlock syscontrol */ + /* + * The default board interrupt is #6. + * Set the roxxler register to use interrupt #2, not #6. + */ +#if CV_INT_NUM == 2 + cv_write_port(0x8080, ba - 0x02000000); +#endif /* CV_INT_NUM == 2 */ + + /* Enable board interrupts */ + cv_write_port(0x8008, ba - 0x02000000); + test = RCrt(ba, CRT_ID_SYSTEM_CONFIG); test = test | 0x01; /* enable enhaced register access */ test = test & 0xEF; /* clear bit 4, 0 wait state */ @@ -504,8 +617,8 @@ cv_boardinit(gp) */ vgaw(ba, ECR_ADV_FUNC_CNTL, 0x31); - /* enable cpu acess, color mode, high 64k page */ - vgaw(ba, GREG_MISC_OUTPUT_W, 0x23); + /* enable color mode (bit0), cpu acess (bit1), high 64k page (bit5) */ + vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* Cpu base addr */ WCrt(ba, CRT_ID_EXT_SYS_CNTL_4, 0x00); @@ -752,7 +865,6 @@ cv_getvmode(gp, vm) /* adjust internal values to pixel values */ vm->hblank_start *= 8; - vm->hblank_stop *= 8; vm->hsync_start *= 8; vm->hsync_stop *= 8; vm->htotal *= 8; @@ -812,11 +924,11 @@ cv_mode(gp, cmd, arg, a2, a3) case GM_GRFOFF: #ifndef CV64CONSOLE - cvscreen(1, gp->g_regkva - 0x02000000) -#else + cvscreen(1, gp->g_regkva - 0x02000000); +#else /* !CV64CONSOLE */ cv_load_mon(gp, &cvconsole_mode); ite_reinit(gp->g_itedev); -#endif +#endif /* !CV64CONSOLE */ return (0); case GM_GRFCONFIG: @@ -854,7 +966,7 @@ cv_ioctl (gp, cmd, data) void *data; { switch (cmd) { -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR case GRFIOCGSPRITEPOS: return(cv_getspritepos (gp, (struct grf_position *) data)); @@ -869,14 +981,14 @@ cv_ioctl (gp, cmd, data) case GRFIOCGSPRITEMAX: return(cv_getspritemax (gp, (struct grf_position *) data)); -#else /* CV_HARDWARE_CURSOR */ +#else /* !CV_NO_HARDWARE_CURSOR */ case GRFIOCGSPRITEPOS: case GRFIOCSSPRITEPOS: case GRFIOCSSPRITEINF: case GRFIOCGSPRITEINF: case GRFIOCGSPRITEMAX: break; -#endif /* CV_HARDWARE_CURSOR */ +#endif /* !CV_NO_HARDWARE_CURSOR */ case GRFIOCGETCMAP: return (cv_getcmap (gp, (struct grf_colormap *) data)); @@ -915,7 +1027,6 @@ cv_setmonitor(gp, gv) if (gv->mode_num == 255) { bcopy(gv, &cvconsole_mode.gv, sizeof(struct grfvideo_mode)); cvconsole_mode.gv.hblank_start /= 8; - cvconsole_mode.gv.hblank_stop /= 8; cvconsole_mode.gv.hsync_start /= 8; cvconsole_mode.gv.hsync_stop /= 8; cvconsole_mode.gv.htotal /= 8; @@ -936,7 +1047,7 @@ cv_setmonitor(gp, gv) */ if (gp->g_flags & GF_GRFON) if (md == monitor_current) { - printf("grf_cv: Changing the used mode not allowed!\n"); + printf("grfcv: Changing the used mode not allowed!\n"); return (EINVAL); } @@ -945,7 +1056,6 @@ cv_setmonitor(gp, gv) /* adjust pixel oriented values to internal rep. */ md->hblank_start /= 8; - md->hblank_stop /= 8; md->hsync_start /= 8; md->hsync_stop /= 8; md->htotal /= 8; @@ -1091,13 +1201,13 @@ cv_mondefok(gv) #endif break; default: - printf("grf_cv: Illegal depth in mode %d\n", + printf("grfcv: Illegal depth in mode %d\n", (int) gv->mode_num); return (0); } if (gv->pixel_clock > maxpix) { - printf("grf_cv: Pixelclock too high in mode %d\n", + printf("grfcv: Pixelclock too high in mode %d\n", (int) gv->mode_num); return (0); } @@ -1112,6 +1222,11 @@ cv_mondefok(gv) } } + if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { + printf("grfcv: sync-on-green is not supported\n"); + return (0); + } + return (1); } @@ -1127,12 +1242,13 @@ cv_load_mon(gp, md) unsigned short mnr; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; - char LACE, DBLSCAN, TEXT, CONSOLE; - int uplim, lowlim; int cr50, sr15, sr18, clock_mode, test; int m, n; /* For calc'ing display FIFO */ int tfillm, temptym; /* FIFO fill and empty mclk's */ int hmul; /* Multiplier for hor. Values */ + unsigned char hvsync_pulse; + char TEXT, CONSOLE; + /* identity */ gv = &md->gv; @@ -1140,13 +1256,18 @@ cv_load_mon(gp, md) CONSOLE = (gv->mode_num == 255); if (!cv_mondefok(gv)) { - printf("grfcv: The monitor definition is illegal.\n"); - printf("grfcv: See the manpage of grfconfig for more informations\n"); + printf("grfcv: Monitor definition not ok\n"); return (0); } + ba = gp->g_regkva; fb = gp->g_fbkva; + /* Disable Interrupts */ + test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); + test &= ~0x10; + WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); + /* turn gfx off, don't mess up the display */ gfx_on_off(1, ba); @@ -1171,24 +1292,24 @@ cv_load_mon(gp, md) /* get display mode parameters */ switch (gv->depth) { - case 15: - case 16: - hmul = 2; - break; - default: - hmul = 1; - break; + case 15: + case 16: + hmul = 2; + break; + default: + hmul = 1; + break; } HBS = gv->hblank_start * hmul; - HBE = gv->hblank_stop * hmul; HSS = gv->hsync_start * hmul; HSE = gv->hsync_stop * hmul; - HT = gv->htotal*hmul - 5; + HBE = gv->htotal * hmul - 6; + HT = gv->htotal * hmul - 5; VBS = gv->vblank_start - 1; VSS = gv->vsync_start; VSE = gv->vsync_stop; - VBE = gv->vblank_stop; + VBE = gv->vtotal - 3; VT = gv->vtotal - 2; /* Disable enhanced Mode for text display */ @@ -1201,17 +1322,36 @@ cv_load_mon(gp, md) HDE = (gv->disp_width + 3) * hmul / 8 - 1; /*HBS;*/ VDE = gv->disp_height - 1; - /* figure out whether lace or dblscan is needed */ - - uplim = gv->disp_height + (gv->disp_height / 4); - lowlim = gv->disp_height - (gv->disp_height / 4); - LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; - DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; - /* adjustments */ + if (gv->disp_flags & GRF_FLAGS_LACE) { + VDE = VDE / 2; + VBS = VBS / 2; + VSS = VSS / 2; + VSE = VSE / 2; + VBE = VBE / 2; + VT = VT / 2; + } - if (LACE) - VDE /= 2; + /* Horizontal/Vertical Sync Pulse */ + /* + * GREG_MISC_OUTPUT_W Register: + * bit description (0/1) + * 0 Monochrome/Color emulation + * 1 Disable/Enable access of the display memory from the CPU + * 5 Select the low/high 64K page of memory + * 6 Select a positive/negative horizontal retrace sync pulse + * 7 Select a positive/negative vertical retrace sync pulse + */ + hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R); + if (gv->disp_flags & GRF_FLAGS_PHSYNC) + hvsync_pulse &= ~0x40; + else + hvsync_pulse |= 0x40; + if (gv->disp_flags & GRF_FLAGS_PVSYNC) + hvsync_pulse &= ~0x80; + else + hvsync_pulse |= 0x80; + vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse); /* GFX hardware cursor off */ WCrt(ba, CRT_ID_HWGC_MODE, 0x00); @@ -1269,7 +1409,7 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_MAX_SCAN_LINE, 0x40 | /* TEXT ? 0x00 ??? */ - (DBLSCAN ? 0x80 : 0x00) | + ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | ((VBS & 0x200) ? 0x20 : 0x00) | (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); @@ -1278,13 +1418,13 @@ cv_load_mon(gp, md) /* text cursor */ if (TEXT) { -#if 1 +#if CV_ULCURSOR WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1); -#else +#else /* CV_ULCURSOR */ WCrt(ba, CRT_ID_CURSOR_START, 0x00); WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f); -#endif +#endif /* CV_ULCURSOR */ WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f); WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); @@ -1302,7 +1442,8 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); WCrt(ba, CRT_ID_LACE_RETR_START, HT / 2); - WCrt(ba, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); + WCrt(ba, CRT_ID_LACE_CONTROL, + ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x20 : 0x00)); WGfx(ba, GCT_ID_GRAPHICS_MODE, ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40)); @@ -1318,9 +1459,9 @@ cv_load_mon(gp, md) WCrt(ba, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); sr15 = RSeq(ba, SEQ_ID_CLKSYN_CNTL_2); - sr15 &= 0xef; + sr15 &= ~0x10; sr18 = RSeq(ba, SEQ_ID_RAMDAC_CNTL); - sr18 &= 0x7f; + sr18 &= ~0x80; clock_mode = 0x00; cr50 = 0x00; @@ -1471,12 +1612,28 @@ cv_load_mon(gp, md) } } - /* Some kind of Magic */ + /* Set display enable flag */ WAttr(ba, 0x33, 0); /* turn gfx on again */ gfx_on_off(0, ba); + /* enable interrupts */ + test = RCrt(ba, CRT_ID_BACKWAD_COMP_1); + test |= 0x10; + WCrt(ba, CRT_ID_BACKWAD_COMP_1, test); + + test = RCrt(ba, CRT_ID_END_VER_RETR); + test &= ~0x20; + WCrt(ba, CRT_ID_END_VER_RETR, test); + test &= ~0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); + test |= 0x10; + WCrt(ba, CRT_ID_END_VER_RETR, test); +#ifndef CV_NO_HARDWARE_CURSOR + cv_setup_hwc(gp); +#endif + /* Pass-through */ cvscreen(0, ba - 0x02000000); @@ -1539,7 +1696,7 @@ cv_inittextmode(gp) } -static inline void +static __inline void cv_write_port(bits, BoardAddr) unsigned short bits; volatile caddr_t BoardAddr; @@ -1566,7 +1723,7 @@ cv_write_port(bits, BoardAddr) * 1 = Amiga Signal, * ba = boardaddr */ -static inline void +static __inline void cvscreen(toggle, ba) int toggle; volatile caddr_t ba; @@ -1581,7 +1738,7 @@ cvscreen(toggle, ba) /* 0 = on, 1= off */ /* ba= registerbase */ -static inline void +static __inline void gfx_on_off(toggle, ba) int toggle; volatile caddr_t ba; @@ -1592,46 +1749,55 @@ gfx_on_off(toggle, ba) toggle = toggle << 5; r = RSeq(ba, SEQ_ID_CLOCKING_MODE); - r &= 0xdf; /* set Bit 5 to 0 */ + r &= ~0x20; /* set Bit 5 to 0 */ WSeq(ba, SEQ_ID_CLOCKING_MODE, r | toggle); } - -#ifdef CV_HARDWARE_CURSOR +#ifndef CV_NO_HARDWARE_CURSOR static unsigned char cv_hotx = 0, cv_hoty = 0; +static char cv_cursor_on = 0; /* Hardware Cursor handling routines */ int -cv_getspritepos (gp, pos) +cv_getspritepos(gp, pos) struct grf_softc *gp; struct grf_position *pos; { int hi,lo; volatile caddr_t ba = gp->g_regkva; - hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI); - lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO); + hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI); + lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO); pos->y = (hi << 8) + lo; - hi = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI); - lo = RCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO); + hi = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI); + lo = RCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO); pos->x = (hi << 8) + lo; return (0); } - int -cv_setspritepos (gp, pos) +cv_setspritepos(gp, pos) struct grf_softc *gp; struct grf_position *pos; { volatile caddr_t ba = gp->g_regkva; - short x = pos->x, y = pos->y; + short x, y; + static short savex, savey; short xoff, yoff; + if (pos) { + x = pos->x; + y = pos->y; + savex = x; + savey= y; + } else { /* restore cursor */ + x = savex; + y = savey; + } x -= cv_hotx; y -= cv_hoty; if (x < 0) { @@ -1648,37 +1814,26 @@ cv_setspritepos (gp, pos) yoff = 0; } - WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); - WCrt (ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_X_HI, (x >> 8)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_X_LO, (x & 0xff)); - WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); - WCrt (ba, CRT_ID_HWGC_DSTART_X, xoff); - WCrt (ba, CRT_ID_HWGC_DSTART_Y, yoff); - WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); + WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_LO, (y & 0xff)); + WCrt(ba, CRT_ID_HWGC_DSTART_X, xoff); + WCrt(ba, CRT_ID_HWGC_DSTART_Y, yoff); + WCrt(ba, CRT_ID_HWGC_ORIGIN_Y_HI, (y >> 8)); - return(0); + return (0); } -static inline short -M2I(short val) { - asm volatile (" rorw #8,%0 ; \ - swap %0 ; \ - rorw #8,%0 ; " : "=d" (val) : "0" (val)); - return (val); +static __inline short +M2I(val) + short val; +{ + return (((val & 0xff00) >> 8) | ((val & 0xff) << 8)); } -#define M2INS(val) \ - asm volatile (" rorw #8,%0 ; \ - swap %0 ; \ - rorw #8,%0 ; \ - swap %0 ; " : "=d" (val) : "0" (val)); - -#define HWC_OFF (cv_fbsize - 1024*2) -#define HWC_SIZE 1024 - - int -cv_getspriteinfo (gp, info) +cv_getspriteinfo(gp, info) struct grf_softc *gp; struct grf_spriteinfo *info; { @@ -1728,40 +1883,52 @@ cv_getspriteinfo (gp, info) void -cv_setup_hwc (gp, col1, col2, hsx, hsy, data) +cv_setup_hwc(gp) struct grf_softc *gp; - unsigned char col1; - unsigned char col2; - unsigned char hsx; - unsigned char hsy; - const unsigned long *data; { volatile caddr_t ba = gp->g_regkva; - unsigned long *c = (unsigned long *)(gp->g_fbkva + HWC_OFF); - const unsigned long *s = data; + volatile caddr_t hwc; int test; - short x = (HWC_SIZE / (4*4)) - 1; - /* copy only, if there is a data pointer. */ - if (data) do { - *c++ = *s++; - *c++ = *s++; - *c++ = *s++; - *c++ = *s++; - } while (x-- > 0); + if (gp->g_display.gd_planes <= 4) + cv_cursor_on = 0; /* don't enable hwc in text modes */ + if (cv_cursor_on == 0) + return; /* reset colour stack */ +#if 0 test = RCrt(ba, CRT_ID_HWGC_MODE); - asm volatile("nop"); - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + __asm volatile ("nop"); +#else + /* do it in assembler, the above does't seem to work */ + __asm volatile ("moveb #0x45, %1@(0x3d4); moveb %1@(0x3d5),%0" : + "=r" (test) : "a" (ba)); +#endif + WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + *hwc = 0; + +#if 0 test = RCrt(ba, CRT_ID_HWGC_MODE); - asm volatile("nop"); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0x1); + __asm volatile ("nop"); +#else + /* do it in assembler, the above does't seem to work */ + __asm volatile ("moveb #0x45, %1@(0x3d4); moveb %1@(0x3d5),%0" : + "=r" (test) : "a" (ba)); +#endif + switch (gp->g_display.gd_planes) { + case 8: + WCrt(ba, CRT_ID_HWGC_BG_STACK, 0x1); + *hwc = 1; + break; + default: + WCrt(ba, CRT_ID_HWGC_BG_STACK, 0xff); + *hwc = 0xff; + *hwc = 0xff; + } test = HWC_OFF / HWC_SIZE; WCrt (ba, CRT_ID_HWGC_START_AD_HI, (test >> 8)); @@ -1770,14 +1937,21 @@ cv_setup_hwc (gp, col1, col2, hsx, hsy, data) WCrt (ba, CRT_ID_HWGC_DSTART_X , 0); WCrt (ba, CRT_ID_HWGC_DSTART_Y , 0); - WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ + WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x10); /* Cursor X11 Mode */ + /* + * Put it into Windoze Mode or you'll see sometimes a white stripe + * on the right side (in double clocking modes with a screen bigger + * > 1023 pixels). + */ + WCrt (ba, CRT_ID_EXT_DAC_CNTL, 0x00); /* Cursor Windoze Mode */ WCrt (ba, CRT_ID_HWGC_MODE, 0x01); } - -/* This is the reason why you shouldn't use the HGC in the Kernel:( */ - +/* + * This was the reason why you shouldn't use the HWC in the Kernel:( + * Obsoleted now by use of interrupts :-) + */ #define VerticalRetraceWait(ba) \ { \ while (vgar(ba, GREG_INPUT_STATUS1_R) == 0x00) ; \ @@ -1809,6 +1983,7 @@ cv_setspriteinfo (gp, info) u_char *imp, *mp; unsigned short row; +#ifdef CV_NO_INT /* Cursor off */ WCrt (ba, CRT_ID_HWGC_MODE, 0x00); @@ -1827,6 +2002,10 @@ cv_setspriteinfo (gp, info) * (thanks to Harald Koenig for this tip!) */ + /* + * Remark 06/06/96: Update in interrupt obsoletes this, + * but the warning should stay there! + */ VerticalRetraceWait(ba); WCrt (ba, CRT_ID_HWGC_ORIGIN_X_HI, 0x7); @@ -1835,6 +2014,7 @@ cv_setspriteinfo (gp, info) WCrt (ba, CRT_ID_HWGC_DSTART_X, 0x3f); WCrt (ba, CRT_ID_HWGC_DSTART_Y, 0x3f); WCrt (ba, CRT_ID_HWGC_ORIGIN_Y_HI, 0x7); +#endif /* CV_NO_INT */ if (info->size.y > 64) info->size.y = 64; @@ -1849,11 +2029,14 @@ cv_setspriteinfo (gp, info) copyin(info->image, image, info->size.y * info->size.x / 8); copyin(info->mask, mask, info->size.y * info->size.x / 8); - hwp = (u_short *)(fb +HWC_OFF); +#ifdef CV_NO_INT + hwp = (u_short *)(fb + HWC_OFF); /* This is necessary in order not to crash the board */ - VerticalRetraceWait(ba); +#else /* CV_NO_INT */ + hwp = (u_short *) cv_cursor_storage; +#endif /* CV_NO_INT */ /* * setting it is slightly more difficult, because we can't @@ -1865,28 +2048,33 @@ cv_setspriteinfo (gp, info) row < info->size.y; row++) { u_short im1, im2, im3, im4, m1, m2, m3, m4; - im1 = *(unsigned short *)imp; - imp += 2; - m1 = *(unsigned short *)mp; + m1 = ~(*(unsigned short *)mp); + im1 = *(unsigned short *)imp & *(unsigned short *)mp; mp += 2; - - im2 = *(unsigned short *)imp; imp += 2; - m2 = *(unsigned short *)mp; + + m2 = ~(*(unsigned short *)mp); + im2 = *(unsigned short *)imp & *(unsigned short *)mp; mp += 2; + imp += 2; if (info->size.x > 32) { - im3 = *(unsigned long *)imp; - imp += 4; - m3 = *(unsigned long *)mp; - mp += 4; - im4 = *(unsigned long *)imp; - imp += 4; - m4 = *(unsigned long *)mp; - mp += 4; + m3 = ~(*(unsigned short *)mp); + im3 = *(unsigned short *)imp & + *(unsigned short *)mp; + mp += 2; + imp += 2; + m4 = ~(*(unsigned short *)mp); + im4 = *(unsigned short *)imp & + *(unsigned short *)mp; + mp += 2; + imp += 2; + } else { + m3 = 0xffff; + im3 = 0; + m4 = 0xffff; + im4 = 0; } - else - im3 = m3 = im4 = m4 = 0; switch (depth) { case 8: @@ -1923,68 +2111,100 @@ cv_setspriteinfo (gp, info) break; } } - for (; row < 64; row++) { - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; - *hwp++ = 0x0000; + + if (depth < 24) { + for (; row < 64; row++) { + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + } + } else { + for (; row < 64; row++) { + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + *hwp++ = 0x0000; + *hwp++ = 0xffff; + } } + free(image, M_TEMP); - cv_setup_hwc(gp, 1, 0, 0, 0, NULL); + /* cv_setup_hwc(gp); */ cv_hotx = info->hot.x; cv_hoty = info->hot.y; +#ifdef CV_NO_INT /* One must not write twice per vertical blank :-( */ - /* VerticalRetraceWait(ba); */ - + VerticalRetraceWait(ba); cv_setspritepos (gp, &info->pos); +#else /* CV_NO_INT */ + cv_setspritepos (gp, &info->pos); + curs_update_flag = 1; +#endif /* CV_NO_INT */ } if (info->set & GRFSPRSET_CMAP) { + volatile caddr_t hwc; int test; - VerticalRetraceWait(ba); - /* reset colour stack */ test = RCrt(ba, CRT_ID_HWGC_MODE); asm volatile("nop"); switch (depth) { - case 32: - case 24: - WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); - case 16: - case 8: - /* info->cmap.green[1] */ + case 8: + case 15: + case 16: WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + break; + case 32: + case 24: WCrt (ba, CRT_ID_HWGC_FG_STACK, 0); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0; + *hwc = 0; + break; } test = RCrt(ba, CRT_ID_HWGC_MODE); asm volatile("nop"); switch (depth) { - case 8: - WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); + case 8: WCrt (ba, CRT_ID_HWGC_BG_STACK, 1); + hwc = ba + CRT_ADDRESS_W; + *hwc = 1; break; - case 32: case 24: - WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); - case 16: + case 15: + case 16: WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0xff; + break; + case 32: + case 24: WCrt (ba, CRT_ID_HWGC_BG_STACK, 0xff); + hwc = ba + CRT_ADDRESS_W; + *hwc = 0xff; + *hwc = 0xff; + break; } } if (info->set & GRFSPRSET_ENABLE) { -#if 0 - if (info->enable) - control = 0x85; - else - control = 0; - WSeq(ba, SEQ_ID_CURSOR_CONTROL, control); -#endif + if (info->enable) { + cv_cursor_on = 1; + cv_setup_hwc(gp); + /* WCrt(ba, CRT_ID_HWGC_MODE, 0x01); */ + } else + WCrt(ba, CRT_ID_HWGC_MODE, 0x00); } if (info->set & GRFSPRSET_POS) cv_setspritepos(gp, &info->pos); @@ -2009,6 +2229,6 @@ cv_getspritemax (gp, pos) return(0); } -#endif /* CV_HARDWARE_CURSOR */ +#endif /* CV_NO_HARDWARE_CURSOR */ #endif /* NGRFCV */ diff --git a/sys/arch/amiga/dev/grf_cvreg.h b/sys/arch/amiga/dev/grf_cvreg.h index 96ba25955b2..21ea223a67e 100644 --- a/sys/arch/amiga/dev/grf_cvreg.h +++ b/sys/arch/amiga/dev/grf_cvreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: grf_cvreg.h,v 1.6 1996/05/29 10:15:04 niklas Exp $ */ +/* $OpenBSD: grf_cvreg.h,v 1.7 1997/09/18 13:39:50 niklas Exp $ */ /* $NetBSD: grf_cvreg.h,v 1.5 1996/05/19 21:05:30 veego Exp $ */ /* @@ -84,12 +84,12 @@ struct grfcvtext_mode { int grfcv_cnprobe __P((void)); void grfcv_iteinit __P((struct grf_softc *)); -static inline void GfxBusyWait __P((volatile caddr_t)); -static inline void GfxFifoWait __P((volatile caddr_t)); -static inline unsigned char RAttr __P((volatile caddr_t, short)); -static inline unsigned char RSeq __P((volatile caddr_t, short)); -static inline unsigned char RCrt __P((volatile caddr_t, short)); -static inline unsigned char RGfx __P((volatile caddr_t, short)); +static __inline void GfxBusyWait __P((volatile caddr_t)); +static __inline void GfxFifoWait __P((volatile caddr_t)); +static __inline unsigned char RAttr __P((volatile caddr_t, short)); +static __inline unsigned char RSeq __P((volatile caddr_t, short)); +static __inline unsigned char RCrt __P((volatile caddr_t, short)); +static __inline unsigned char RGfx __P((volatile caddr_t, short)); /* @@ -363,7 +363,7 @@ static inline unsigned char RGfx __P((volatile caddr_t, short)); /* Gfx engine busy wait */ -static inline void +static __inline void GfxBusyWait (ba) volatile caddr_t ba; { @@ -376,7 +376,7 @@ GfxBusyWait (ba) } -static inline void +static __inline void GfxFifoWait(ba) volatile caddr_t ba; { @@ -395,7 +395,7 @@ GfxFifoWait(ba) * inline functions. */ -static inline unsigned char +static __inline unsigned char RAttr(ba, idx) volatile caddr_t ba; short idx; @@ -406,7 +406,7 @@ RAttr(ba, idx) return vgar(ba, ACT_ADDRESS_R); } -static inline unsigned char +static __inline unsigned char RSeq(ba, idx) volatile caddr_t ba; short idx; @@ -415,7 +415,7 @@ RSeq(ba, idx) return vgar(ba, SEQ_ADDRESS_R); } -static inline unsigned char +static __inline unsigned char RCrt(ba, idx) volatile caddr_t ba; short idx; @@ -424,7 +424,7 @@ RCrt(ba, idx) return vgar(ba, CRT_ADDRESS_R); } -static inline unsigned char +static __inline unsigned char RGfx(ba, idx) volatile caddr_t ba; short idx; diff --git a/sys/arch/amiga/dev/grf_et.c b/sys/arch/amiga/dev/grf_et.c index 0459d347c3c..95712b6df7d 100644 --- a/sys/arch/amiga/dev/grf_et.c +++ b/sys/arch/amiga/dev/grf_et.c @@ -1,7 +1,8 @@ -/* $OpenBSD: grf_et.c,v 1.6 1997/05/29 01:15:40 niklas Exp $ */ -/* $NetBSD: grf_et.c,v 1.8 1996/12/23 09:10:06 veego Exp $ */ +/* $OpenBSD: grf_et.c,v 1.7 1997/09/18 13:39:51 niklas Exp $ */ +/* $NetBSD: grf_et.c,v 1.10 1997/07/29 17:46:31 veego Exp $ */ /* + * Copyright (c) 1997 Klaus Burkert * Copyright (c) 1996 Tobias Abt * Copyright (c) 1995 Ezra Story * Copyright (c) 1995 Kari Mettinen @@ -49,6 +50,8 @@ * Modified for Tseng ET4000 from * Kari Mettinen's Cirrus driver by Tobias Abt * + * Fixed Merlin in Z-III, fixed LACE and DBLSCAN, added Domino16M proto + * and AT&T ATT20c491 DAC, added memory-size detection by Klaus Burkert. * * TODO: * @@ -74,7 +77,7 @@ int et_mondefok __P((struct grfvideo_mode *gv)); void et_boardinit __P((struct grf_softc *gp)); -static void et_CompFQ __P((u_int fq, u_char *num, u_char *denom)); +void et_CompFQ __P((u_int fq, u_char *num, u_char *denom)); int et_getvmode __P((struct grf_softc *gp, struct grfvideo_mode *vm)); int et_setvmode __P((struct grf_softc *gp, unsigned int mode)); int et_toggle __P((struct grf_softc *gp, unsigned short)); @@ -88,16 +91,15 @@ int et_ioctl __P((register struct grf_softc *gp, u_long cmd, void *data)); int et_getmousepos __P((struct grf_softc *gp, struct grf_position *data)); void et_writesprpos __P((volatile char *ba, short x, short y)); int et_setmousepos __P((struct grf_softc *gp, struct grf_position *data)); -static int et_setspriteinfo __P((struct grf_softc *gp, - struct grf_spriteinfo *data)); +int et_setspriteinfo __P((struct grf_softc *gp, + struct grf_spriteinfo *data)); int et_getspriteinfo __P((struct grf_softc *gp, - struct grf_spriteinfo *data)); -static int et_getspritemax __P((struct grf_softc *gp, - struct grf_position *data)); + struct grf_spriteinfo *data)); +int et_getspritemax __P((struct grf_softc *gp, struct grf_position *data)); int et_setmonitor __P((struct grf_softc *gp, struct grfvideo_mode *gv)); int et_blank __P((struct grf_softc *gp, int *on)); -static int et_getControllerType __P((struct grf_softc *gp)); -static int et_getDACType __P((struct grf_softc *gp)); +int et_getControllerType __P((struct grf_softc *gp)); +int et_getDACType __P((struct grf_softc *gp)); int grfetmatch __P((struct device *, void *, void *)); void grfetattach __P((struct device *, struct device *, void *)); @@ -108,9 +110,11 @@ void et_memset __P((unsigned char *d, unsigned char c, int l)); * Graphics display definitions. * These are filled by 'grfconfig' using GRFIOCSETMON. */ -#define monitor_def_max 8 -static struct grfvideo_mode monitor_def[8] = { - {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} +#define monitor_def_max 24 +static struct grfvideo_mode monitor_def[24] = { + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, }; static struct grfvideo_mode *monitor_current = &monitor_def[0]; @@ -130,8 +134,8 @@ static struct grfvideo_mode *monitor_current = &monitor_def[0]; extern unsigned char TSENGFONT[]; struct grfettext_mode etconsole_mode = { - {255, "", 25000000, 640, 480, 4, 640/8, 784/8, 680/8, 768/8, 800/8, - 481, 521, 491, 493, 525}, + { 255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8, + 481, 491, 493, 525, 0 }, 8, TSENGFONTY, 640 / 8, 480 / TSENGFONTY, TSENGFONT, 32, 255 }; @@ -191,7 +195,7 @@ grfetmatch(pdp, match, auxp) struct cfdata *cfp = match; #endif struct zbus_args *zap; - static int regprod, fbprod; + static int regprod, regprod2 = 0, fbprod; zap = auxp; @@ -212,9 +216,12 @@ grfetmatch(pdp, match, auxp) fbprod = 0; break; case DOMINO: - if (zap->prodid != 2 && zap->prodid != 1) + /* 2167/3 is Domino16M proto (crest) */ + if (zap->prodid != 3 && zap->prodid != 2 && + zap->prodid != 1) return (0); regprod = 2; + regprod2 = 3; fbprod = 1; break; case MERLIN: @@ -245,7 +252,7 @@ grfetmatch(pdp, match, auxp) et_fbsize = zap->size; } } else { - if (zap->prodid == regprod) { + if (zap->prodid == regprod || zap->prodid == regprod2) { et_regaddr = zap->va; } else { if (zap->prodid == fbprod) { @@ -353,7 +360,10 @@ grfetattach(pdp, dp, auxp) printf("MUSIC DAC"); break; case MERLINDAC: - printf("BrookTree DAC"); + printf("BrookTree Bt482 DAC"); + break; + case ATT20C491: + printf("AT&T ATT20c491 DAC"); break; } printf(" being used\n"); @@ -428,7 +438,7 @@ et_boardinit(gp) WSeq(ba, SEQ_ID_MAP_MASK, 0x0f); WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); -/* WSeq(ba, SEQ_ID_TS_STATE_CONTROL, 0x00); */ + WSeq(ba, SEQ_ID_STATE_CONTROL, 0x00); WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00); @@ -439,36 +449,40 @@ et_boardinit(gp) WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00); WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00); - WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07); - WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */ - WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */ -/* ET4000 special */ + WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x67); + WCrt(ba, CRT_ID_MODE_CONTROL, 0xc3); + WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); + + /* ET4000 special */ WCrt(ba, CRT_ID_RASCAS_CONFIG, 0x28); - WCrt(ba, CTR_ID_EXT_START, 0x00); + WCrt(ba, CRT_ID_EXT_START, 0x00); WCrt(ba, CRT_ID_6845_COMPAT, 0x08); - WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); - WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); /* assume ZorroII first */ - - if (iszthreepa(ba)) { - if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) | - (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24 ) - WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* ZorroIII */ + + /* ET4000/W32 special (currently only for Merlin (crest) */ + if (ettype == MERLIN) { + WCrt(ba, CRT_ID_SEGMENT_COMP, 0x1c); + WCrt(ba, CRT_ID_GENERAL_PURPOSE, 0x00); + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); + } + else { + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); } + WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x0f); WCrt(ba, CRT_ID_HOR_OVERFLOW, 0x00); + vgaw(ba, GREG_SEGMENTSELECT, 0x00); + WGfx(ba, GCT_ID_SET_RESET, 0x00); WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00); WGfx(ba, GCT_ID_COLOR_COMPARE, 0x00); WGfx(ba, GCT_ID_DATA_ROTATE, 0x00); WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00); - WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00); + WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x40); WGfx(ba, GCT_ID_MISC, 0x01); WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f); WGfx(ba, GCT_ID_BITMASK, 0xff); - vgaw(ba, GREG_SEGMENTSELECT, 0x00); - for (x = 0; x < 0x10; x++) WAttr(ba, x, x); WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01); @@ -480,10 +494,9 @@ et_boardinit(gp) vgaw(ba, VDAC_MASK, 0xff); delay(200000); - vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */ + vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* colors initially set to greyscale */ - switch(ettype) { case MERLIN: vgaw(ba, MERLIN_VDAC_INDEX, 0); @@ -509,20 +522,43 @@ et_boardinit(gp) et_cursprite.cmap.red = et_sprred; et_cursprite.cmap.green = et_sprgreen; et_cursprite.cmap.blue = et_sprblue; - - /* card spezific initialisations */ + + /* card specific initialisations */ switch(ettype) { case OMNIBUS: etctype = et_getControllerType(gp); etdtype = et_getDACType(gp); break; + vgaw(ba, GREG_SEGMENTSELECT2, 0x00); + if (((vgar(ba, GREG_FEATURE_CONTROL_R) & 12) | + (vgar(ba, GREG_STATUS0_R) & 0x60)) == 0x24) { + WCrt(ba, CRT_ID_VIDEO_CONFIG2, 0x07); /* 1Mx4 RAM */ + et_fbsize = 0x400000; /* 4 MB */ + } + else { + /* check for 1MB or 2MB board (crest) */ + /* has there a 1MB Merlin ever been sold ??? */ + volatile unsigned long *et_fbtestaddr; + et_fbtestaddr = (volatile unsigned long *)gp->g_fbkva; + *et_fbtestaddr = 0x0; + vgaw(ba, GREG_SEGMENTSELECT2, 0x11); /* 1MB offset */ + *et_fbtestaddr = 0x12345678; + vgaw(ba, GREG_SEGMENTSELECT2, 0x00); + if (*et_fbtestaddr == 0x0) + et_fbsize = 0x200000; /* 2 MB */ + else + et_fbsize = 0x100000; /* 1 MB */ + } + /* ZorroII can map 2 MB max ... */ + if (!iszthreepa(gp->g_fbkva) && et_fbsize == 0x400000) + et_fbsize = 0x200000; case MERLIN: etctype = ETW32; etdtype = MERLINDAC; break; case DOMINO: etctype = ET4000; - etdtype = SIERRA11483; + etdtype = et_getDACType(gp); break; } } @@ -558,7 +594,6 @@ et_getvmode(gp, vm) /* adjust internal values to pixel values */ vm->hblank_start *= 8; - vm->hblank_stop *= 8; vm->hsync_start *= 8; vm->hsync_stop *= 8; vm->htotal *= 8; @@ -566,7 +601,6 @@ et_getvmode(gp, vm) return (0); } - int et_setvmode(gp, mode) struct grf_softc *gp; @@ -710,6 +744,7 @@ et_getmousepos(gp, data) { data->x = et_cursprite.pos.x; data->y = et_cursprite.pos.y; + return (0); } @@ -765,7 +800,7 @@ et_getspriteinfo(gp, data) } -static int +int et_setspriteinfo(gp, data) struct grf_softc *gp; struct grf_spriteinfo *data; @@ -775,7 +810,7 @@ et_setspriteinfo(gp, data) } -static int +int et_getspritemax(gp, data) struct grf_softc *gp; struct grf_position *data; @@ -800,7 +835,6 @@ et_setmonitor(gp, gv) if (gv->mode_num == 255) { bcopy(gv, &etconsole_mode.gv, sizeof(struct grfvideo_mode)); etconsole_mode.gv.hblank_start /= 8; - etconsole_mode.gv.hblank_stop /= 8; etconsole_mode.gv.hsync_start /= 8; etconsole_mode.gv.hsync_stop /= 8; etconsole_mode.gv.htotal /= 8; @@ -819,7 +853,6 @@ et_setmonitor(gp, gv) /* adjust pixel oriented values to internal rep. */ md->hblank_start /= 8; - md->hblank_stop /= 8; md->hsync_start /= 8; md->hsync_stop /= 8; md->htotal /= 8; @@ -985,7 +1018,7 @@ static u_int et_clockfreqs[ET_NUMCLOCKS] = { }; -static void +void et_CompFQ(fq, num, denom) u_int fq; u_char *num; @@ -1010,23 +1043,46 @@ int et_mondefok(gv) struct grfvideo_mode *gv; { + unsigned long maxpix; + if (gv->mode_num < 1 || gv->mode_num > monitor_def_max) if (gv->mode_num != 255 || gv->depth != 4) return(0); switch (gv->depth) { - case 4: + case 4: if (gv->mode_num != 255) return(0); - case 1: - case 8: - case 15: - case 16: - case 24: + case 1: + case 8: + maxpix = 85000000; break; - default: + case 15: + case 16: + maxpix = 45000000; + break; + case 24: + maxpix = 28000000; + break; + case 32: + maxpix = 21000000; + break; + default: + printf("grfet: Illegal depth in mode %d\n", (int)gv->mode_num); return (0); } + + if (gv->pixel_clock > maxpix) { + printf("grfet: Pixelclock too high in mode %d\n", + (int)gv->mode_num); + return (0); + } + + if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) { + printf("grfet: sync-on-green is not supported\n"); + return (0); + } + return (1); } @@ -1042,21 +1098,25 @@ et_load_mon(gp, md) unsigned char num0, denom0; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; - char LACE, DBLSCAN, TEXT; - unsigned char seq; - int uplim, lowlim; + unsigned char hvsync_pulse, seq; + char TEXT; + int hmul; /* identity */ gv = &md->gv; TEXT = (gv->depth == 4); if (!et_mondefok(gv)) { - printf("mondef not ok\n"); + printf("grfet: Monitor definition not ok\n"); return (0); } + ba = gp->g_regkva; - /* provide all needed information in grf device-independant locations */ + /* + * Provide all needed information in grf device-independant + * locations. + */ gp->g_data = (caddr_t) gv; gi = &gp->g_display; gi->gd_regaddr = (caddr_t) ztwopa(ba); @@ -1082,14 +1142,14 @@ et_load_mon(gp, md) /* get display mode parameters */ HBS = gv->hblank_start; - HBE = gv->hblank_stop; HSS = gv->hsync_start; HSE = gv->hsync_stop; + HBE = gv->htotal - 1; HT = gv->htotal; VBS = gv->vblank_start; VSS = gv->vsync_start; VSE = gv->vsync_stop; - VBE = gv->vblank_stop; + VBE = gv->vtotal - 1; VT = gv->vtotal; if (TEXT) @@ -1098,17 +1158,43 @@ et_load_mon(gp, md) HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */ VDE = gv->disp_height - 1; - /* figure out whether lace or dblscan is needed */ - - uplim = gv->disp_height + (gv->disp_height / 4); - lowlim = gv->disp_height - (gv->disp_height / 4); - LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0; - DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0; + /* adjustments (crest) */ + switch (gv->depth) { + case 15: + case 16: + hmul = 2; + break; + case 24: + hmul = 3; + break; + case 32: + hmul = 4; + break; + default: + hmul = 1; + break; + } - /* adjustments */ + HDE *= hmul; + HBS *= hmul; + HSS *= hmul; + HSE *= hmul; + HBE *= hmul; + HT *= hmul; - if (LACE) + if (gv->disp_flags & GRF_FLAGS_LACE) { VDE /= 2; + VT = VT + 1; + } + + if (gv->disp_flags & GRF_FLAGS_DBLSCAN) { + VDE *= 2; + VBS *= 2; + VSS *= 2; + VSE *= 2; + VBE *= 2; + VT *= 2; + } WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e); @@ -1117,36 +1203,46 @@ et_load_mon(gp, md) WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* Set clock */ + et_CompFQ(gv->pixel_clock * hmul, &num0, &denom0); - et_CompFQ( gv->pixel_clock, &num0, &denom0); + /* Horizontal/Vertical Sync Pulse */ + hvsync_pulse = 0xe3; + if (gv->disp_flags & GRF_FLAGS_PHSYNC) + hvsync_pulse &= ~0x40; + else + hvsync_pulse |= 0x40; + if (gv->disp_flags & GRF_FLAGS_PVSYNC) + hvsync_pulse &= ~0x80; + else + hvsync_pulse |= 0x80; - vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3 | ((num0 & 3) << 2)); + vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse | ((num0 & 3) << 2)); WCrt(ba, CRT_ID_6845_COMPAT, (num0 & 4) ? 0x0a : 0x08); - seq=RSeq(ba, SEQ_ID_CLOCKING_MODE); + seq = RSeq(ba, SEQ_ID_CLOCKING_MODE); switch(denom0) { - case 0: + case 0: WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xb4); WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); break; - case 1: + case 1: WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf4); WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); break; - case 2: + case 2: WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); WSeq(ba, SEQ_ID_CLOCKING_MODE, seq & 0xf7); break; - case 3: + case 3: WSeq(ba, SEQ_ID_AUXILIARY_MODE, 0xf5); WSeq(ba, SEQ_ID_CLOCKING_MODE, seq | 0x08); break; - } + } + /* load display parameters into board */ - WCrt(ba, CRT_ID_HOR_TOTAL, HT); WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE)); WCrt(ba, CRT_ID_START_HOR_BLANK, HBS); - WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */ + WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); WCrt(ba, CRT_ID_START_HOR_RETR, HSS); WCrt(ba, CRT_ID_END_HOR_RETR, (HSE & 0x1f) | @@ -1163,8 +1259,8 @@ et_load_mon(gp, md) ((VSS & 0x200) ? 0x80 : 0x00)); WCrt(ba, CRT_ID_MAX_ROW_ADDRESS, - 0x40 | /* TEXT ? 0x00 ??? */ - (DBLSCAN ? 0x80 : 0x00) | + 0x40 | /* splitscreen not visible */ + ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) | ((VBS & 0x200) ? 0x20 : 0x00) | (TEXT ? ((md->fy - 1) & 0x1f) : 0x00)); @@ -1172,7 +1268,6 @@ et_load_mon(gp, md) ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xab)); /* text cursor */ - if (TEXT) { #if ET_ULCURSOR WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2); @@ -1205,7 +1300,7 @@ et_load_mon(gp, md) ((VDE & 0x400) ? 0x04 : 0x00) | ((VSS & 0x400) ? 0x08 : 0x00) | 0x10 | - (LACE ? 0x80 : 0x00)); + ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x80 : 0x00)); WCrt(ba, CRT_ID_HOR_OVERFLOW, ((HT & 0x100) ? 0x01 : 0x00) | @@ -1225,90 +1320,100 @@ et_load_mon(gp, md) vgar(ba, VDAC_MASK); vgar(ba, VDAC_MASK); switch (gv->depth) { - case 1: - case 4: /* text */ + case 1: + case 4: /* text */ switch(etdtype) { - case SIERRA11483: - case SIERRA15025: - case MUSICDAC: + case SIERRA11483: + case SIERRA15025: + case MUSICDAC: vgaw(ba, VDAC_MASK, 0); break; - case MERLINDAC: + case ATT20C491: + vgaw(ba, VDAC_MASK, 0x02); + break; + case MERLINDAC: setMerlinDACmode(ba, 0); break; } HDE = gv->disp_width / 16; break; - case 8: + case 8: switch(etdtype) { - case SIERRA11483: - case SIERRA15025: - case MUSICDAC: + case SIERRA11483: + case SIERRA15025: + case MUSICDAC: vgaw(ba, VDAC_MASK, 0); break; - case MERLINDAC: + case ATT20C491: + vgaw(ba, VDAC_MASK, 0x02); + break; + case MERLINDAC: setMerlinDACmode(ba, 0); break; } HDE = gv->disp_width / 8; break; - case 15: + case 15: switch(etdtype) { - case SIERRA11483: - case SIERRA15025: - case MUSICDAC: + case SIERRA11483: + case SIERRA15025: + case MUSICDAC: + case ATT20C491: vgaw(ba, VDAC_MASK, 0xa0); break; - case MERLINDAC: + case MERLINDAC: setMerlinDACmode(ba, 0xa0); break; } HDE = gv->disp_width / 4; break; - case 16: + case 16: switch(etdtype) { - case SIERRA11483: + case SIERRA11483: vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ break; - case SIERRA15025: + case SIERRA15025: vgaw(ba, VDAC_MASK, 0xe0); break; - case MUSICDAC: + case MUSICDAC: + case ATT20C491: vgaw(ba, VDAC_MASK, 0xc0); break; - case MERLINDAC: + case MERLINDAC: setMerlinDACmode(ba, 0xe0); break; } HDE = gv->disp_width / 4; break; - case 24: + case 24: switch(etdtype) { - case SIERRA11483: + case SIERRA11483: vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ break; - case SIERRA15025: + case SIERRA15025: vgaw(ba, VDAC_MASK, 0xe1); break; - case MUSICDAC: + case MUSICDAC: + case ATT20C491: vgaw(ba, VDAC_MASK, 0xe0); break; - case MERLINDAC: + case MERLINDAC: setMerlinDACmode(ba, 0xf0); break; } HDE = (gv->disp_width / 8) * 3; break; - case 32: + case 32: switch(etdtype) { - case SIERRA11483: - case MUSICDAC: + case SIERRA11483: + case MUSICDAC: + case ATT20C491: vgaw(ba, VDAC_MASK, 0); /* illegal mode! */ break; - case SIERRA15025: + case SIERRA15025: vgaw(ba, VDAC_MASK, 0x61); break; - case MERLINDAC: + case MERLINDAC: setMerlinDACmode(ba, 0xb0); break; } @@ -1320,6 +1425,9 @@ et_load_mon(gp, md) (gv->depth == 1) ? 0x01 : 0x0f); WCrt(ba, CRT_ID_OFFSET, HDE); + vgaw(ba, CRT_ADDRESS, CRT_ID_HOR_OVERFLOW); + vgaw(ba, CRT_ADDRESS_W, + (vgar(ba, CRT_ADDRESS_R) & 0x7f) | ((HDE & 0x100) ? 0x80: 0x00)); /* text initialization */ if (TEXT) { @@ -1370,16 +1478,15 @@ et_inittextmode(gp) c = (unsigned char *) (fb) + (tm->cols - 16); strcpy(c, "TSENG"); - c[6] = 0x20; + c[5] = 0x20; /* set colors (B&W) */ - switch(ettype) { case MERLIN: vgaw(ba, MERLIN_VDAC_INDEX, 0); for (z = 0; z < 256; z++) { y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; - + vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][0]); vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][1]); vgaw(ba, MERLIN_VDAC_COLORS, etconscolors[y][2]); @@ -1389,7 +1496,7 @@ et_inittextmode(gp) vgaw(ba, VDAC_ADDRESS_W, 0); for (z = 0; z < 256; z++) { y = (z & 1) ? ((z > 7) ? 2 : 1) : 0; - + vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), etconscolors[y][0] >> etcmap_shift); vgaw(ba, VDAC_DATA + ((ettype == DOMINO) ? 0x0fff : 0), @@ -1413,7 +1520,7 @@ et_memset(d, c, l) } -static int +int et_getControllerType(gp) struct grf_softc * gp; { @@ -1424,7 +1531,12 @@ et_getControllerType(gp) *mem = 0; /* make ACL visible */ - WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb); + if (ettype == MERLIN) { + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xbb); + } else { + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xfb); + } + WIma(ba, IMA_PORTCONTROL, 0x01); *((unsigned long *)mmu) = 0; @@ -1434,13 +1546,17 @@ et_getControllerType(gp) /* hide ACL */ WIma(ba, IMA_PORTCONTROL, 0x00); - WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); - return((*mem == 0xff) ? ETW32 : ET4000); + if (ettype == MERLIN) { + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0x93); + } else { + WCrt(ba, CRT_ID_VIDEO_CONFIG1, 0xd3); + } + return ((*mem == 0xff) ? ETW32 : ET4000); } -static int +int et_getDACType(gp) struct grf_softc * gp; { @@ -1497,7 +1613,27 @@ et_getDACType(gp) vgaw(ba, VDAC_MASK, 0xff); return (MUSICDAC); -} + } + + /* check for AT&T ATT20c491 DAC (crest) */ + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + vgaw(ba, HDR, 0xff); + vgaw(ba, VDAC_MASK, 0x01); + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + if (vgar(ba, HDR) == 0xff) { + /* do not shift color values */ + etcmap_shift = 0; + + vgaw(ba, VDAC_MASK, 0xff); + return (ATT20C491); + } + + /* restore PowerUp settings (crest) */ + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + if (vgar(ba, HDR)); if (vgar(ba, HDR)); + vgaw(ba, HDR, 0x00); /* * nothing else found, so let us pretend it is a stupid @@ -1508,7 +1644,7 @@ et_getDACType(gp) etcmap_shift = 2; vgaw(ba, VDAC_MASK, 0xff); - return(SIERRA11483); + return (SIERRA11483); } #endif /* NGRFET */ diff --git a/sys/arch/amiga/dev/grf_etreg.h b/sys/arch/amiga/dev/grf_etreg.h index a5b3832b7cb..e98b886100f 100644 --- a/sys/arch/amiga/dev/grf_etreg.h +++ b/sys/arch/amiga/dev/grf_etreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_etreg.h,v 1.3 1997/01/16 09:24:17 niklas Exp $ */ -/* $NetBSD: grf_etreg.h,v 1.2 1996/06/09 13:21:11 veego Exp $ */ +/* $OpenBSD: grf_etreg.h,v 1.4 1997/09/18 13:39:51 niklas Exp $ */ +/* $NetBSD: grf_etreg.h,v 1.4 1997/07/29 17:42:06 veego Exp $ */ /* * Copyright (c) 1996 Tobias Abt @@ -78,6 +78,7 @@ struct grfettext_mode { #define SIERRA15025 1 /* Sierra 15025 TrueColor DAC */ #define MUSICDAC 2 /* MUSIC TrueColor DAC */ #define MERLINDAC 3 /* Merlin's BrookTree TrueColor DAC */ +#define ATT20C491 4 /* AT&T 20c491 TrueColor DAC */ /* read VGA register */ #define vgar(ba, reg) (*(((volatile unsigned char *)ba)+reg)) @@ -112,6 +113,7 @@ struct grfettext_mode { #define GREG_COLORSELECT 0x03D9 #define GREG_ATNTMODECONTROL 0x03DE #define GREG_SEGMENTSELECT 0x03CD +#define GREG_SEGMENTSELECT2 0x03CB /* ETW32 special */ #define W32mappedRegs 0xfff00 @@ -216,7 +218,7 @@ struct grfettext_mode { #define CRT_ID_SEGMENT_COMP 0x30 #define CRT_ID_GENERAL_PURPOSE 0x31 #define CRT_ID_RASCAS_CONFIG 0x32 -#define CTR_ID_EXT_START 0x33 +#define CRT_ID_EXT_START 0x33 #define CRT_ID_6845_COMPAT 0x34 #define CRT_ID_OVERFLOW_HIGH 0x35 #define CRT_ID_VIDEO_CONFIG1 0x36 diff --git a/sys/arch/amiga/dev/grf_rh.c b/sys/arch/amiga/dev/grf_rh.c index 0bd1839facb..a94c31ec102 100644 --- a/sys/arch/amiga/dev/grf_rh.c +++ b/sys/arch/amiga/dev/grf_rh.c @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_rh.c,v 1.12 1997/01/16 09:24:18 niklas Exp $ */ -/* $NetBSD: grf_rh.c,v 1.26 1996/12/31 17:54:28 is Exp $ */ +/* $OpenBSD: grf_rh.c,v 1.13 1997/09/18 13:39:52 niklas Exp $ */ +/* $NetBSD: grf_rh.c,v 1.27 1997/07/29 17:52:05 veego Exp $ */ /* * Copyright (c) 1994 Markus Wild @@ -1637,6 +1637,7 @@ rh_getvmode(gp, vm) struct grfvideo_mode *vm; { struct MonDef *md; + int vmul; if (vm->mode_num && vm->mode_num > rh_mon_max) return(EINVAL); @@ -1668,25 +1669,34 @@ rh_getvmode(gp, vm) * - Ignatios Souvatzis */ - if (md->DEP == 4) { + if (md->DEP != 4) { vm->hblank_start = md->HBS * 32 / md->DEP; - vm->hblank_stop = md->HBE * 32 / md->DEP; vm->hsync_start = md->HSS * 32 / md->DEP; vm->hsync_stop = md->HSE * 32 / md->DEP; vm->htotal = md->HT * 32 / md->DEP; } else { vm->hblank_start = md->HBS * md->FX; - vm->hblank_stop = md->HBE * md->FX; vm->hsync_start = md->HSS * md->FX; vm->hsync_stop = md->HSE * md->FX; vm->htotal = md->HT * md->FX; } - vm->vblank_start = md->VBS; - vm->vblank_stop = md->VBE; - vm->vsync_start = md->VSS; - vm->vsync_stop = md->VSE; - vm->vtotal = md->VT; + /* XXX move vm->disp_flags and vmul to rh_load_mon + * if rh_setvmode can add new modes with grfconfig */ + vm->disp_flags = 0; + vmul = 2; + if (md->FLG & MDF_DBL) { + vm->disp_flags |= GRF_FLAGS_DBLSCAN; + vmul = 4; + } + if (md->FLG & MDF_LACE) { + vm->disp_flags |= GRF_FLAGS_LACE; + vmul = 1; + } + vm->vblank_start = md->VBS * vmul / 2; + vm->vsync_start = md->VSS * vmul / 2; + vm->vsync_stop = md->VSE * vmul / 2; + vm->vtotal = md->VT * vmul / 2; return(0); } diff --git a/sys/arch/amiga/dev/grf_rhreg.h b/sys/arch/amiga/dev/grf_rhreg.h index d4dd0d0526f..454b264fcdc 100644 --- a/sys/arch/amiga/dev/grf_rhreg.h +++ b/sys/arch/amiga/dev/grf_rhreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_rhreg.h,v 1.3 1996/05/29 10:15:13 niklas Exp $ */ -/* $NetBSD: grf_rhreg.h,v 1.7 1996/05/19 21:05:41 veego Exp $ */ +/* $OpenBSD: grf_rhreg.h,v 1.4 1997/09/18 13:39:52 niklas Exp $ */ +/* $NetBSD: grf_rhreg.h,v 1.8 1997/07/29 17:42:09 veego Exp $ */ /* * Copyright (c) 1994 Markus Wild @@ -653,22 +653,42 @@ struct MonDef { vgaw(ba, PLL_ADDRESS_W, (val >> 8)); } while (0) -static inline unsigned char RAttr(volatile void * ba, short idx) { +static __inline unsigned char RAttr __P((volatile void *, short)); +static __inline unsigned char +RAttr(ba, idx) + volatile void *ba; + short idx; +{ vgaw (ba, ACT_ADDRESS, idx); return vgar (ba, ACT_ADDRESS_R); } -static inline unsigned char RSeq(volatile void * ba, short idx) { +static __inline unsigned char RSeq __P((volatile void *, short)); +static __inline unsigned char +RSeq(ba, idx) + volatile void *ba; + short idx; +{ vgaw (ba, SEQ_ADDRESS, idx); return vgar (ba, SEQ_ADDRESS_R); } -static inline unsigned char RCrt(volatile void * ba, short idx) { +static __inline unsigned char RCrt __P((volatile void *, short)); +static __inline unsigned char +RCrt(ba, idx) + volatile void *ba; + short idx; +{ vgaw (ba, CRT_ADDRESS, idx); return vgar (ba, CRT_ADDRESS_R); } -static inline unsigned char RGfx(volatile void * ba, short idx) { +static __inline unsigned char RGfx __P((volatile void *, short)); +static __inline unsigned char +RGfx(ba, idx) + volatile void *ba; + short idx; +{ vgaw(ba, GCT_ADDRESS, idx); return vgar (ba, GCT_ADDRESS_R); } diff --git a/sys/arch/amiga/dev/grf_rt.c b/sys/arch/amiga/dev/grf_rt.c index 17d9013be25..27ba8c7506f 100644 --- a/sys/arch/amiga/dev/grf_rt.c +++ b/sys/arch/amiga/dev/grf_rt.c @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_rt.c,v 1.10 1997/01/16 09:24:20 niklas Exp $ */ -/* $NetBSD: grf_rt.c,v 1.34 1996/12/23 09:10:09 veego Exp $ */ +/* $OpenBSD: grf_rt.c,v 1.11 1997/09/18 13:39:53 niklas Exp $ */ +/* $NetBSD: grf_rt.c,v 1.35 1997/07/29 17:52:09 veego Exp $ */ /* * Copyright (c) 1993 Markus Wild @@ -259,7 +259,7 @@ static struct MonDef *default_monitor = &DEFAULT_MONDEF; #endif int retina_alive __P((struct MonDef *)); -static int rt_load_mon __P((struct grf_softc *, struct MonDef *)); +int rt_load_mon __P((struct grf_softc *, struct MonDef *)); /* @@ -284,7 +284,7 @@ retina_alive(mdp) return(0); } -static int +int rt_load_mon(gp, md) struct grf_softc *gp; struct MonDef *md; @@ -769,8 +769,8 @@ int grfrtprint __P((void *, const char *)); int grfrtmatch __P((struct device *, void *, void *)); int rt_mode __P((struct grf_softc *, u_long, void *, u_long, int)); -static int rt_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); -static int rt_setvmode __P((struct grf_softc *, unsigned, int)); +int rt_getvmode __P((struct grf_softc *, struct grfvideo_mode *)); +int rt_setvmode __P((struct grf_softc *, unsigned, int)); int rt_getspritepos __P((struct grf_softc *, struct grf_position *)); int rt_setspritepos __P((struct grf_softc *, struct grf_position *)); int rt_getspriteinfo __P((struct grf_softc *, struct grf_spriteinfo *)); @@ -900,12 +900,13 @@ grfrtprint(auxp, pnp) return(UNCONF); } -static int +int rt_getvmode (gp, vm) struct grf_softc *gp; struct grfvideo_mode *vm; { struct MonDef *md; + int vmul; if (vm->mode_num && vm->mode_num > retina_mon_max) return (EINVAL); @@ -925,41 +926,51 @@ rt_getvmode (gp, vm) * From observation of the monitor definition table above, I guess that * the horizontal timings are in units of longwords. Hence, I get the * pixels by multiplication with 32 and division by the depth. - * The text modes, apparently marked by depth == 4, are even more wierd. - * According to a comment above, they are computed from a depth==8 mode - * (thats for us: * 32 / 8) by applying another factor of 4 / font width. - * Reverse applying the latter formula most of the constants cancel - * themselves and we are left with a nice (* font width). - * That is, internal timings are in units of longwords for graphics - * modes, or in units of characters widths for text modes. + * The text modes, apparently marked by depth == 4, are even more + * wierd. According to a comment above, they are computed from a + * depth==8 mode (thats for us: * 32 / 8) by applying another factor of + * 4 / font width. Reverse applying the latter formula most of the + * constants cancel themselves and we are left with a nice (* font + * width). That is, internal timings are in units of longwords for + * graphics modes, or in units of characters widths for text modes. * We better don't WRITE modes until this has been real live checked. * - Ignatios Souvatzis */ - if (md->DEP == 4) { + if (md->DEP != 4) { vm->hblank_start = md->HBS * 32 / md->DEP; - vm->hblank_stop = md->HBE * 32 / md->DEP; vm->hsync_start = md->HSS * 32 / md->DEP; vm->hsync_stop = md->HSE * 32 / md->DEP; vm->htotal = md->HT * 32 / md->DEP; } else { vm->hblank_start = md->HBS * md->FX; - vm->hblank_stop = md->HBE * md->FX; vm->hsync_start = md->HSS * md->FX; vm->hsync_stop = md->HSE * md->FX; vm->htotal = md->HT * md->FX; } - vm->vblank_start = md->VBS; - vm->vblank_stop = md->VBE; - vm->vsync_start = md->VSS; - vm->vsync_stop = md->VSE; - vm->vtotal = md->VT; + + /* XXX move vm->disp_flags and vmul to rt_load_mon + * if rt_setvmode can add new modes with grfconfig */ + vm->disp_flags = 0; + vmul = 2; + if (md->FLG & MDF_DBL) { + vm->disp_flags |= GRF_FLAGS_DBLSCAN; + vmul = 4; + } + if (md->FLG & MDF_LACE) { + vm->disp_flags |= GRF_FLAGS_LACE; + vmul = 1; + } + vm->vblank_start = md->VBS * vmul / 2; + vm->vsync_start = md->VSS * vmul / 2; + vm->vsync_stop = md->VSE * vmul / 2; + vm->vtotal = md->VT * vmul / 2; return (0); } -static int +int rt_setvmode (gp, mode, txtonly) struct grf_softc *gp; unsigned mode; diff --git a/sys/arch/amiga/dev/grf_ul.c b/sys/arch/amiga/dev/grf_ul.c index 54ec3261e16..42491fb5afb 100644 --- a/sys/arch/amiga/dev/grf_ul.c +++ b/sys/arch/amiga/dev/grf_ul.c @@ -1,5 +1,5 @@ -/* $OpenBSD: grf_ul.c,v 1.12 1997/01/16 09:24:21 niklas Exp $ */ -/* $NetBSD: grf_ul.c,v 1.23 1996/12/23 09:10:10 veego Exp $ */ +/* $OpenBSD: grf_ul.c,v 1.13 1997/09/18 13:39:54 niklas Exp $ */ +/* $NetBSD: grf_ul.c,v 1.24 1997/07/29 17:50:01 veego Exp $ */ #define UL_DEBUG @@ -91,48 +91,45 @@ u_int8_t ul_ovl_palette[] = { struct grfvideo_mode ul_monitor_defs[] = { /* - * Horizontal values are given in TMS units, that is, for the - * A2410 board, units of 16 pixels. The ioctl multiplies (when - * exporting) or divides (when importing) them by 16 to conform to. + * We give all these values in MI units, that is: + * horizontal timings in units of pixels + * vertical timings in units of lines + * point of reference is blanking end. * - * XXX This used to be in units of 8 pixel times. We - * must also change amiga/stand/grfconfig/grfconfig.c, - * grf_{rt,rh,cl,cv}.c and egsgrfconfig (the latter to generate the - * horizontal timings in units of pixels instead of 8 pixels. - * You will also have to write warnings in BIG BOLD RED BLINKING - * LETTERS all over the docs, and still people will fry their monitors. + * The ul_load_mon transforms these values right before loading + * them into the chip. * - * btw, the _totals are always sync_start+1, to compute the frequencies - * correctly. (see TMS34010 manual) + * This leaves us with a single point where things are transformed, + * which should make life easier if we ever change things again. */ /* 1024x768, 60Hz */ - {1, "1024x768", 66667000, 1024, 768, 8, - 82, 18, 86, 12, 87, 794, 26, 797, 2, 798}, + { 1, "1024x768", 66667000, 1024, 768, 8, + 1024, 1008, 1296, 1392, 768, 771, 774, 798, 0 }, /* 864x648, 70Hz */ - {2, "864x648", 50000000, 864, 648, 8, - 61, 7, 65, 3, 66, 667, 19, 677, 4, 678}, + { 2, "864x648", 50000000, 864, 648, 8, + 864, 928, 992, 1056, 648, 658, 663, 678, 0 }, /* 800x600, 60Hz */ - {3, "800x600", 36000000, 800, 600, 8, - 57, 7, 61, 3, 62, 619, 19, 629, 4, 630}, + { 3, "800x600", 36000000, 800, 600, 8, + 800, 864, 928, 992, 600, 610, 615, 630, 0 }, - /* 640x400, 60 Hz, interlaced */ - {4, "640x400I", 14318000, 640, 400, 8, - 48, 8, 56, 3, 57, 239, 39, 262, 2, 240}, + /* 640x400, 60 Hz, interlaced */ + { 4, "640x400i", 14318000, 640, 400, 8, + 640, 768, 832, 912, 200, 223, 203, 240, 1 }, - /* 1024x768, 65Hz interlaced, s.th. is strange */ - {5, "1024x768?I", 44980000, 1024, 768, 8, - 76, 12, 79, 3, 80, 512, 24, 533, 2, 534}, + /* 1024x768, 65Hz interlaced, s.th. is strange */ + { 5, "1024x768?i", 44980000, 1024, 768, 8, + 1024, 1072, 1136, 1280, 488, 509, 512, 534, 1 }, - /* 1024x1024, 60Hz */ - {6, "1024x1024", 80000000, 1024,1024, 8, - 77, 13, 78, 5, 78,1051, 27,1054, 2,1055}, + /* 1024x1024, 60Hz */ + { 6, "1024x1024", 80000000, 1024, 1024, 8, + 1024, 1040, 1120, 1248, 1024, 1027, 1030, 1055, 0 }, - /* 736x480, 60 Hz */ - {7, "736x480", 28636300, 736, 480, 8, - 54, 8, 57, 3, 58, 503, 23, 514, 3, 515}, + /* 736x480, 60 Hz */ + { 7, "736x480", 28636300, 736, 480, 8, + 736, 784, 848, 928, 480, 491, 495, 515, 0 }, }; int ulowell_mon_max = sizeof (ul_monitor_defs)/sizeof (ul_monitor_defs[0]); @@ -391,14 +388,16 @@ ul_load_mon(gp, md) ba->hstadrh = 0xC000; ba->hstadrl = 0x0000; - ba->data = md->hsync_stop; - ba->data = md->hblank_stop; - ba->data = md->hblank_start; - ba->data = md->hsync_start; - ba->data = md->vsync_stop; - ba->data = md->vblank_stop; - ba->data = md->vblank_start; - ba->data = md->vsync_start; + + ba->data = (md->hsync_stop - md->hsync_start)/16; + ba->data = (md->htotal - md->hsync_start)/16 - 1; + ba->data = (md->hblank_start + md->htotal - md->hsync_start)/16 - 1; + ba->data = md->htotal/16 - 1; + + ba->data = md->vsync_stop - md->vsync_start; + ba->data = md->vtotal - md->vsync_start - 1; + ba->data = md->vblank_start + md->vtotal - md->vsync_start - 1; + ba->data = md->vtotal - 1; ba->ctrl &= ~INCW; ba->hstadrh = 0xFE90; @@ -418,8 +417,7 @@ ul_load_mon(gp, md) ba->ctrl |= LBL | INCW; ba->hstadrh = 0xC000; ba->hstadrl = 0x0080; - ba->data = (md->vblank_start - md->vblank_stop == md->disp_height ? - 0xf020 : 0xb020); + ba->data = md->disp_flags & GRF_FLAGS_LACE ? 0xb020 : 0xf020; /* I guess this should be in the yet unimplemented mode select ioctl */ /* Hm.. maybe not. We always put the console on overlay plane no 0. */ @@ -604,18 +602,17 @@ ul_getvmode (gp, vm) vm->disp_height = md->disp_height; vm->depth = md->depth; - vm->hblank_start = (md->hblank_start - md->hblank_stop) * 16; - vm->hblank_stop = (md->htotal - 1) * 16; - vm->hsync_start = (md->hsync_start - md->hblank_stop) * 16; - vm->hsync_stop = (md->hsync_stop + md->htotal - md->hblank_stop) * 16; - vm->htotal = md->htotal * 16; + vm->hblank_start = md->hblank_start; + vm->hsync_start = md->hsync_start; + vm->hsync_stop = md->hsync_stop; + vm->htotal = md->htotal; - vm->vblank_start = md->vblank_start - md->vblank_stop; - vm->vblank_stop = md->vtotal - 1; - vm->vsync_start = md->vsync_start - md->vblank_stop; - vm->vsync_stop = md->vsync_stop + md->vtotal - md->vblank_stop; + vm->vblank_start = md->vblank_start; + vm->vsync_start = md->vsync_start; + vm->vsync_stop = md->vsync_stop; vm->vtotal = md->vtotal; + vm->disp_flags = md->disp_flags; return 0; } diff --git a/sys/arch/amiga/dev/if_ae.c b/sys/arch/amiga/dev/if_ae.c deleted file mode 100644 index 893ab0d478d..00000000000 --- a/sys/arch/amiga/dev/if_ae.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* $OpenBSD: if_ae.c,v 1.9 1997/01/16 09:24:35 niklas Exp $ */ -/* $NetBSD: if_ae.c,v 1.12 1996/12/23 09:10:13 veego Exp $ */ - -/* - * Copyright (c) 1995 Bernd Ernesti and Klaus Burkert. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bernd Ernesti, by Klaus - * Burkert, by Michael van Elst, and by the University of California, - * Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_le.c 8.1 (Berkeley) 6/10/93 - * - * This is based on the original LANCE files, as the PCnet-ISA used on - * the Ariadne is a LANCE-descendant optimized for the PC-ISA bus. - * This causes some modifications, all data that is to go into registers - * or to structures (buffer-descriptors, init-block) has to be - * byte-swapped. In addition ALL write accesses to the board have to be - * WORD or LONG, BYTE-access is prohibited!! - */ - -#include "ae.h" -#if NAE > 0 - -#include "bpfilter.h" - -/* - * AMD 79C960 PCnet-ISA - * - * This driver will generate and accept tailer encapsulated packets even - * though it buys us nothing. The motivation was to avoid incompatibilities - * with VAXen, SUNs, and others that handle and benefit from them. - * This reasoning is dubious. - */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/buf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/syslog.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/device.h> - -#include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#if defined(CCITT) && defined(LLC) -#include <sys/socketvar.h> -#include <netccitt/x25.h> -#include <net/if_dl.h> -#include <net/if_llc.h> -#include <netccitt/dll.h> -#include <netccitt/llc_var.h> -#include <netccitt/pk.h> -#include <netccitt/pk_var.h> -#include <netccitt/pk_extern.h> -#endif - -#if NBPFILTER > 0 -#include <net/bpf.h> -#include <net/bpfdesc.h> -#endif - -#include <machine/cpu.h> -#include <machine/mtpr.h> -#include <amiga/amiga/device.h> -#include <amiga/amiga/isr.h> -#include <amiga/dev/zbusvar.h> -#include <amiga/dev/if_aereg.h> - -/* - * Ethernet software status per interface. - * - * Each interface is referenced by a network interface structure, - * ae_if, which the routing code uses to locate the interface. - * This structure contains the output queue for the interface, its address, ... - */ -struct ae_softc { - struct device sc_dev; - struct isr sc_isr; - struct arpcom sc_arpcom; /* common Ethernet structures */ - void *sc_base; /* base address of board */ - struct aereg1 *sc_r1; /* LANCE registers */ - struct aereg2 *sc_r2; /* dual-port RAM */ - int sc_rmd; /* predicted next rmd to process */ - int sc_tmd; /* next tmd to use */ - int sc_no_td; /* number of tmds in use */ -} ae_softc[NAE]; - -/* offsets for: ID, REGS, MEM */ -int aestd[] = { 0, 0x0370, 0x8000 }; -static u_int16_t revision; - -int aematch __P((struct device *, void *, void *)); -void aeattach __P((struct device *, struct device *, void *)); -void aewatchdog __P((struct ifnet *)); -void aestop __P((struct ae_softc *)); -void aememinit __P((struct ae_softc *)); -void aereset __P((struct ae_softc *)); -void aeinit __P((struct ae_softc *)); -void aestart __P((struct ifnet *)); -int aeintr __P((void *)); -void aetint __P((struct ae_softc *)); -void aerint __P((struct ae_softc *)); -void aeread __P((struct ae_softc *, u_char *, int)); -static void wcopyfrom __P((char *, char *, int)); -static void wcopyto __P((char *, char *, int)); -static void wzero __P((char *, int)); -int aeput __P((char *, struct mbuf *)); -struct mbuf *aeget __P((struct ae_softc *, u_char *, int)); -int aeioctl __P((struct ifnet *, u_long, caddr_t)); -void aesetladrf __P((struct arpcom *, u_int16_t *)); - -struct cfattach ae_ca = { - sizeof(struct ae_softc), aematch, aeattach -}; - -struct cfdriver ae_cd = { - NULL, "ae", DV_IFNET -}; - -int -aematch(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct zbus_args *zap; - - zap = (struct zbus_args *)aux; - - /* Ariadne ethernet card */ - if (zap->manid == 2167 && zap->prodid == 201) - return (1); - - return (0); -} - -/* - * Interface exists: make available by filling in network interface - * record. System will initialize the interface when it is ready - * to accept packets. - */ -void -aeattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct aereg2 *aer2; - struct zbus_args *zap; - struct ae_softc *sc = (void *)self; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - unsigned long ser; - int s = splhigh (); - - zap =(struct zbus_args *)aux; - - /* - * Make config msgs look nicer. - */ - printf("\n"); - - sc->sc_base = zap->va; - sc->sc_r1 = (struct aereg1 *)(aestd[1] + (int)zap->va); - aer2 = sc->sc_r2 = (struct aereg2 *)(aestd[2] + (int)zap->va); - - /* - * Serial number for board is used as host ID. - */ - ser = (unsigned long) zap->serno; - - /* - * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID. - */ - - sc->sc_arpcom.ac_enaddr[0] = 0x00; - sc->sc_arpcom.ac_enaddr[1] = 0x60; - sc->sc_arpcom.ac_enaddr[2] = 0x30; - - sc->sc_arpcom.ac_enaddr[3] = (ser >> 16) & 0xff; - sc->sc_arpcom.ac_enaddr[4] = (ser >> 8) & 0xff; - sc->sc_arpcom.ac_enaddr[5] = ser & 0xff; - - printf("%s: hardware address %s 32K", sc->sc_dev.dv_xname, - ether_sprintf(sc->sc_arpcom.ac_enaddr)); - - aestop(sc); - delay(100); - - /* get the chip version of the lance chip */ - sc->sc_r1->aer1_rap = 0x5900; - revision = ((sc->sc_r1->aer1_rdp >> 4) -2); - printf(" chip-revision: B%x\n", revision); - - splx (s); - - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_ioctl = aeioctl; - ifp->if_watchdog = aewatchdog; - ifp->if_output = ether_output; - ifp->if_start = aestart; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; - - if_attach(ifp); - ether_ifattach(ifp); - -#if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif - - sc->sc_isr.isr_intr = aeintr; - sc->sc_isr.isr_arg = sc; - sc->sc_isr.isr_ipl = 2; - add_isr (&sc->sc_isr); - return; -} - -void -aewatchdog(ifp) - struct ifnet *ifp; -{ - struct ae_softc *sc = ifp->if_softc; - - log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); - ++sc->sc_arpcom.ac_if.if_oerrors; - - aereset(sc); -} - -void -aestop(sc) - struct ae_softc *sc; -{ - sc->sc_r1->aer1_rap = AE_CSR0; - sc->sc_r1->aer1_rdp = AE_STOP; -} - - -/* - * Set up the initialization block and the descriptor rings. - */ -void -aememinit(sc) - register struct ae_softc *sc; -{ -#if NBPFILTER > 0 - register struct ifnet *ifp = &sc->sc_arpcom.ac_if; -#endif - /* - * This structure is referenced from the CARD's/PCnet-ISA's point - * of view, thus the 0x8000 address which is the buffer RAM area - * of the Ariadne card. This pointer is manipulated - * with the PCnet-ISA's view of memory and NOT the Amiga's. FYI. - */ - register struct aereg2 *aemem = (struct aereg2 *) 0x8000; - register struct aereg2 *aer2 = sc->sc_r2; - register int i; - - -#if NBPFILTER > 0 - if (ifp->if_flags & IFF_PROMISC) - /* set the promiscuous bit */ - aer2->aer2_mode = AE_MODE | AE_PROM; - else -#endif - aer2->aer2_mode = AE_MODE; - /* you know: no BYTE access.... */ - aer2->aer2_padr[0] = - (sc->sc_arpcom.ac_enaddr[0] << 8) | sc->sc_arpcom.ac_enaddr[1]; - aer2->aer2_padr[1] = - (sc->sc_arpcom.ac_enaddr[2] << 8) | sc->sc_arpcom.ac_enaddr[3]; - aer2->aer2_padr[2] = - (sc->sc_arpcom.ac_enaddr[4] << 8) | sc->sc_arpcom.ac_enaddr[5]; - aesetladrf(&sc->sc_arpcom, aer2->aer2_ladrf); - - sc->sc_no_td = sc->sc_tmd = sc->sc_rmd = 0; - - aer2->aer2_rlen = SWAP(AE_RLEN); - aer2->aer2_rdra = SWAP((int)aemem->aer2_rmd); - aer2->aer2_tlen = SWAP(AE_TLEN); - aer2->aer2_tdra = SWAP((int)aemem->aer2_tmd); - - for (i = 0; i < AERBUF; i++) { - aer2->aer2_rmd[i].rmd0 = SWAP((int)aemem->aer2_rbuf[i]); - aer2->aer2_rmd[i].rmd1 = AE_OWN; - aer2->aer2_rmd[i].rmd2 = SWAP(-ETHER_MAX_LEN); - aer2->aer2_rmd[i].rmd3 = 0; - } - - for (i = 0; i < AETBUF; i++) { - aer2->aer2_tmd[i].tmd0 = SWAP((int)aemem->aer2_tbuf[i]); - aer2->aer2_tmd[i].tmd1 = 0; - aer2->aer2_tmd[i].tmd2 = 0; - aer2->aer2_tmd[i].tmd3 = 0; - } -} - -void -aereset(sc) - struct ae_softc *sc; -{ - int s; - - s = splnet(); - aeinit(sc); - splx(s); -} - -/* - * Initialization of interface; set up initialization block - * and transmit/receive descriptor rings. - */ -void -aeinit(sc) - struct ae_softc *sc; -{ - register struct aereg1 *aer1 = sc->sc_r1; - register struct ifnet *ifp = &sc->sc_arpcom.ac_if; - register struct aereg2 *aemem = (struct aereg2 *) 0x8000; - - register int timo = 0; - volatile int dummy; - - aestop(sc); - delay(100); - - dummy = aer1->aer1_reset; /* Reset PCNet-ISA */ - - aememinit(sc); - - /* Give LANCE the physical address of its init block. */ - aer1->aer1_rap = AE_CSR1; - aer1->aer1_rdp = SWAP((int)&aemem->aer2_mode); - aer1->aer1_rap = AE_CSR2; - aer1->aer1_rdp = 0; - -/* - * re-program LEDs to match meaning used on the Ariadne board - */ - aer1->aer1_rap = 0x0500; - aer1->aer1_idp = 0x9000; - aer1->aer1_rap = 0x0600; - aer1->aer1_idp = 0x8100; - aer1->aer1_rap = 0x0700; - aer1->aer1_idp = 0x8400; - -/* - * you can `ifconfig (link0|-link0) ae0' to get the following - * behaviour: - * -link0 enable autoselect between 10Base-T (UTP) and 10Base2 (BNC) - * if an active 10Base-T line is connected then 10Base-T - * is used otherwise 10Base2. - * this is the default behaviour, so there is no need to set - * -link0 when you want autoselect. - * link0 -link1 disable autoselect. enable BNC. - * link0 link1 disable autoselect. enable UTP. - */ - if (!(ifp->if_flags & IFF_LINK0)) { - /* enable autoselect */ - aer1->aer1_rap = 0x0200; - aer1->aer1_idp = 0x0200; - } else { - /* disable autoselect */ - aer1->aer1_rap = 0x0200; - aer1->aer1_idp = 0x0000; - if (!(ifp->if_flags & IFF_LINK1)) { - /* enable BNC */ - sc->sc_r2->aer2_mode = 0x0000; - } else { - /* enable UTP */ - sc->sc_r2->aer2_mode = 0x8000; - } - } - - /* Try to initialize the LANCE. */ - delay(100); - aer1->aer1_rap = AE_CSR0; - aer1->aer1_rdp = AE_INIT; - - /* Wait for initialization to finish. */ - do { - if (++timo == 10000) { - printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname); - break; - } - } while ((aer1->aer1_rdp & AE_IDON) == 0); - - /* Start the LANCE. */ - aer1->aer1_rap = AE_CSR0; - aer1->aer1_rdp = AE_STRT | AE_INEA | AE_IDON; - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_timer = 0; - aestart(ifp); -} - -#define AENEXTTMP \ - if (++bix == AETBUF) bix = 0, tmd = sc->sc_r2->aer2_tmd; else ++tmd - -/* - * Start output on interface. Get another datagram to send - * off of the interface queue, and copy it to the interface - * before starting the output. - */ -void -aestart(ifp) - struct ifnet *ifp; -{ - register struct ae_softc *sc = ifp->if_softc; - register int bix; - register struct aetmd *tmd; - register struct mbuf *m; - int len; - - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; - - bix = sc->sc_tmd; - tmd = &sc->sc_r2->aer2_tmd[bix]; - - for (;;) { - if (sc->sc_no_td >= AETBUF) { - ifp->if_flags |= IFF_OACTIVE; - break; - } - - IF_DEQUEUE(&ifp->if_snd, m); - if (m == 0) - break; - - ++sc->sc_no_td; - -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m); -#endif - - sc->sc_r1->aer1_rdp = AE_TINT | AE_INEA; - len = aeput(sc->sc_r2->aer2_tbuf[bix], m); - -#ifdef AEDEBUG - if (len > ETHER_MAX_LEN) - printf("packet length %d\n", len); -#endif - - ifp->if_timer = 5; - - tmd->tmd1 = AE_OWN | AE_STP | AE_ENP; - tmd->tmd2 = SWAP(-len); - tmd->tmd3 = 0; - - sc->sc_r1->aer1_rdp = AE_INEA | AE_TDMD; - - AENEXTTMP; - } - - sc->sc_tmd = bix; -} - -int -aeintr(arg) - void *arg; -{ - register struct ae_softc *sc = arg; - register struct aereg1 *aer1; - register struct ifnet *ifp = &sc->sc_arpcom.ac_if; - register u_int16_t stat; - - /* if not even initialized, don't do anything further.. */ - if (sc->sc_base == 0) - return (0); - - aer1 = sc->sc_r1; - stat = aer1->aer1_rdp; - - if ((stat & AE_INTR) == 0) - return (0); - - aer1->aer1_rdp = (stat & (AE_INEA | AE_BABL | AE_MISS | AE_MERR | - AE_RINT | AE_TINT | AE_IDON)); - if (stat & AE_SERR) { - if (stat & AE_MERR) { - printf("%s: memory error\n", sc->sc_dev.dv_xname); - aereset(sc); - return (1); - } - if (stat & AE_BABL) { - printf("%s: babble\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - } -#if 0 - if (stat & AE_CERR) { - printf("%s: collision error\n", sc->sc_dev.dv_xname); - ifp->if_collisions++; - } -#endif - if (stat & AE_MISS) { - printf("%s: missed packet\n", sc->sc_dev.dv_xname); - ifp->if_ierrors++; - } - aer1->aer1_rdp = AE_BABL | AE_CERR | AE_MISS | AE_INEA; - } - if ((stat & AE_RXON) == 0) { - printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); - ifp->if_ierrors++; - aereset(sc); - return (1); - } - if ((stat & AE_TXON) == 0) { - printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - aereset(sc); - return (1); - } - if (stat & AE_RINT) { - /* Reset watchdog timer. */ - ifp->if_timer = 0; - aerint(sc); - } - if (stat & AE_TINT) { - /* Reset watchdog timer. */ - ifp->if_timer = 0; - aetint(sc); - } - - return (1); -} - -/* - * Ethernet interface transmitter interrupt. - * Start another output if more data to send. - */ -void -aetint(sc) - struct ae_softc *sc; -{ - register int bix = (sc->sc_tmd - sc->sc_no_td + AETBUF) % AETBUF; - struct aetmd *tmd = &sc->sc_r2->aer2_tmd[bix]; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - - if (tmd->tmd1 & AE_OWN) { -#ifdef AEDEBUG - printf("%s: extra tint\n", sc->sc_dev.dv_xname); -#endif - return; - } - ifp->if_flags &= ~IFF_OACTIVE; - - do { - if (sc->sc_no_td <= 0) - break; - ifp->if_opackets++; - --sc->sc_no_td; - - if (tmd->tmd1 & AE_ERR) { - if (tmd->tmd3 & AE_TBUFF) - printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & AE_UFLO) - printf("%s: underflow\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & (AE_TBUFF | AE_UFLO)) { - aereset(sc); - return; - } - if (tmd->tmd3 & AE_LCAR) - printf("%s: lost carrier\n", sc->sc_dev.dv_xname); - if (tmd->tmd3 & AE_LCOL) { - printf("%s: late collision\n", sc->sc_dev.dv_xname); - ifp->if_collisions++; - } - if (tmd->tmd3 & AE_RTRY) { - printf("%s: excessive collisions, tdr %d\n", - sc->sc_dev.dv_xname, tmd->tmd3 & AE_TDR_MASK); - ifp->if_collisions += 16; - } - } else if (tmd->tmd1 & AE_ONE) { - ifp->if_collisions++; - } - else if (tmd->tmd1 & AE_MORE) { - /* Real number is unknown. */ - ifp->if_collisions += 2; - } - AENEXTTMP; - } while ((tmd->tmd1 & AE_OWN) == 0); - - aestart(ifp); - if (sc->sc_no_td == 0) - ifp->if_timer = 0; -} - -#define AENEXTRMP \ - if (++bix == AERBUF) bix = 0, rmd = sc->sc_r2->aer2_rmd; else ++rmd - -/* - * Ethernet interface receiver interrupt. - * If input error just drop packet. - * Decapsulate packet based on type and pass to type specific - * higher-level input routine. - */ -void -aerint(sc) - struct ae_softc *sc; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - register int bix = sc->sc_rmd; - register struct aermd *rmd = &sc->sc_r2->aer2_rmd[bix]; - - /* - * Out of sync with hardware, should never happen? - */ - if (rmd->rmd1 & AE_OWN) { -#ifdef AEDEBUG - printf("%s: extra rint\n", sc->sc_dev.dv_xname); -#endif - return; - } - - /* - * Process all buffers with valid data - */ - do { - sc->sc_r1->aer1_rdp = AE_RINT | AE_INEA; - if (rmd->rmd1 & (AE_FRAM | AE_OFLO | AE_CRC | AE_RBUFF)) { - ifp->if_ierrors++; - if ((rmd->rmd1 & (AE_FRAM | AE_OFLO | AE_ENP)) == (AE_FRAM | AE_ENP)) - printf("%s: framing error\n", sc->sc_dev.dv_xname); - if ((rmd->rmd1 & (AE_OFLO | AE_ENP)) == AE_OFLO) - printf("%s: overflow\n", sc->sc_dev.dv_xname); - if ((rmd->rmd1 & (AE_CRC | AE_OFLO | AE_ENP)) == (AE_CRC | AE_ENP)) - printf("%s: crc mismatch\n", sc->sc_dev.dv_xname); - if (rmd->rmd1 & AE_RBUFF) - printf("%s: receive buffer error\n", sc->sc_dev.dv_xname); - } else if ((rmd->rmd1 & (AE_STP | AE_ENP)) != (AE_STP | AE_ENP)) { - do { - rmd->rmd3 = 0; - rmd->rmd1 = AE_OWN; - AENEXTRMP; - } while ((rmd->rmd1 & (AE_OWN | AE_ERR | AE_STP | AE_ENP)) == 0); - - sc->sc_rmd = bix; - printf("%s: chained buffer\n", sc->sc_dev.dv_xname); - if ((rmd->rmd1 & (AE_OWN | AE_ERR | AE_STP | AE_ENP)) != AE_ENP) { - aereset(sc); - return; - } - } else - aeread(sc, sc->sc_r2->aer2_rbuf[bix], SWAP(rmd->rmd3) - 4); - - rmd->rmd1 = AE_OWN; - rmd->rmd2 = SWAP(-ETHER_MAX_LEN); - rmd->rmd3 = 0; - - AENEXTRMP; - } while ((rmd->rmd1 & AE_OWN) == 0); - - sc->sc_rmd = bix; -} - -void -aeread(sc, buf, len) - register struct ae_softc *sc; - u_char *buf; - int len; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - struct mbuf *m; - struct ether_header *eh; - - if (len <= sizeof(struct ether_header) || len > ETHER_MAX_LEN) { - printf("%s: invalid packet size %d; dropping\n", - sc->sc_dev.dv_xname, len); - ifp->if_ierrors++; - return; - } - - /* Pull packet off interface. */ - m = aeget(sc, buf, len); - if (m == 0) { - ifp->if_ierrors++; - return; - } - - ifp->if_ipackets++; - - /* We assume that the header fit entirely in one mbuf. */ - eh = mtod(m, struct ether_header *); - -#if NBPFILTER > 0 - /* - * Check if there's a bpf filter listening on this interface. - * If so, hand off the raw packet to bpf, which must deal with - * trailers in its own way. - */ - if (ifp->if_bpf) { - bpf_mtap(ifp->if_bpf, m); - - /* - * Note that the interface cannot be in promiscuous mode if - * there are no bpf listeners. And if we are in promiscuous - * mode, we have to check if this packet is really ours. - */ - if ((ifp->if_flags & IFF_PROMISC) && - (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ - bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, - sizeof(eh->ether_dhost)) != 0) { - m_freem(m); - return; - } - } -#endif - - /* We assume that the header fit entirely in one mbuf. */ - m_adj(m, sizeof(struct ether_header)); - ether_input(ifp, eh, m); -} - -/* - * Here come the two replacements for bcopy() and bzero() as - * WORD-access for writing to the board is absolutely required! - * They could use some tuning as this is time-critical (copying - * packet-data) and should be processed as fast as possible. - * - * Thanks to Michael van Elst for pointing me to the problems - * that kept the 1.3 code from running under NetBSD current - * although it did mystically under 1.0 ... - */ - -#define isodd(p) (((size_t)(p)) & 1) -#define align(p) ((ushort *)(((size_t)(p)) & ~1)) - -/* - * the first function copies WORD-aligned from the source to - * an arbitrary destination. It assumes that the CPU can handle - * mis-aligned writes to the destination itself. - */ -static void -wcopyfrom(a1, a2, length) /* bcopy() word-wise */ - char *a1, *a2; - int length; -{ - ushort i, *b1, *b2; - - if (length > 0 && isodd(a1)) { - b1 = align(a1); - *a2 = *b1 & 0x00ff; /* copy first byte with word access */ - ++a2; - ++b1; - --length; - } else - b1 = (ushort *)a1; - b2 = (ushort *)a2; - - i = length / 2; - - while(i--) /* copy all words */ - *b2++ = *b1++; - - if (length & 0x0001) /* copy trailing byte */ - a2[length-1] = *b1 >> 8; -} - -/* - * the second function copies WORD-aligned from an arbitrary - * source to the destination. It assumes that the CPU can handle - * mis-aligned reads from the source itself. - */ -static void -wcopyto(a1, a2, length) /* bcopy() word-wise */ - char *a1, *a2; - int length; -{ - ushort i, *b1, *b2; - - if (length > 0 && isodd(a2)) { - b2 = align(a2); - i = (*b2 & 0xff00) | (*a1 & 0x00ff); /* copy first byte with word access */ - *b2 = i; - ++a1; - ++b2; - --length; - } else - b2 = (ushort *)a2; - b1 = (ushort *)a1; - - i = length / 2; - - while(i--) /* copy all words */ - *b2++ = *b1++; - - if (length & 0x0001) { - i = (*b2 & 0x00ff) | (a1[length-1] & 0x00ff)<<8; /* copy trailing byte */ - *b2 = i; - } -} - -static void -wzero(a1, length) /* bzero() word-wise */ - char *a1; - int length; -{ - ushort i, *b1; - - /* - * Is the destination word-aligned? - * If not, handle the leading byte... - */ - - if((length > 0) && ((size_t)a1 & 1)) { - b1 = (ushort *)((size_t)a1 & ~1); - *b1 &= 0xff00; - --length; - ++a1; - } - - /* - * Perform the main zeroing word-wise... - */ - - b1 = (ushort *)a1; - i = length / 2; - while(i--) - *b1++ = 0; - - /* - * Do we have to handle a trailing byte? - */ - - if (length & 0x0001) - *b1 &= 0x00ff; -} - -/* - * Routine to copy from mbuf chain to transmit - * buffer in board local memory. - */ -int -aeput(buffer, m) - register char *buffer; - register struct mbuf *m; -{ - register struct mbuf *n; - register int len = 0, tlen = 0; - - for (; m; m = n) { - len = m->m_len; - if (len == 0) { - MFREE(m, n); - continue; - } - wcopyto(mtod(m, char *), buffer, len); - buffer += len; - tlen += len; - MFREE(m, n); - } - - if (tlen < ETHER_MIN_LEN) { - wzero(buffer, ETHER_MIN_LEN - tlen); - tlen = ETHER_MIN_LEN; - } - - return(tlen); -} - -/* - * Routine to copy from board local memory into mbufs. - */ -struct mbuf * -aeget(sc, buffer, totlen) - struct ae_softc *sc; - u_char *buffer; - int totlen; -{ - register struct mbuf *m; - struct mbuf *top, **mp; - int len; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return (0); - m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if; - m->m_pkthdr.len = totlen; - len = MHLEN; - top = 0; - mp = ⊤ - - while (totlen > 0) { - if (top) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - m_freem(top); - return (0); - } - len = MLEN; - } - - if (totlen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if (m->m_flags & M_EXT) - len = MCLBYTES; - } - m->m_len = len = min(totlen, len); - wcopyfrom((caddr_t)buffer, mtod(m, caddr_t), len); - buffer += len; - totlen -= len; - *mp = m; - mp = &m->m_next; - } - - return (top); -} - -/* - * Process an ioctl request. - */ -int -aeioctl(ifp, cmd, data) - register struct ifnet *ifp; - u_long cmd; - caddr_t data; -{ - struct ae_softc *sc = ifp->if_softc; - struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - - s = splnet(); - - if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) { - splx(s); - return error; - } - - switch (cmd) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - aeinit(sc); - arp_ifinit(&sc->sc_arpcom, ifa); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; - - if (ns_nullhost(*ina)) - ina->x_host = - *(union ns_host *)(sc->sc_arpcom.ac_enaddr); - else - wcopyto(ina->x_host.c_host, - sc->sc_arpcom.ac_enaddr, - sizeof(sc->sc_arpcom.ac_enaddr)); - aeinit(sc); /* does ae_setaddr() */ - break; - } -#endif - default: - aeinit(sc); - break; - } - break; - -#if defined(CCITT) && defined(LLC) - case SIOCSIFCONF_X25: - ifp->if_flags |= IFF_UP; - ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ - error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); - if (error == 0) - aeinit(sc); - break; -#endif /* CCITT && LLC */ - - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) == 0 && - (ifp->if_flags & IFF_RUNNING) != 0) { - /* - * If interface is marked down and it is running, then - * stop it. - */ - aestop(sc); - ifp->if_flags &= ~IFF_RUNNING; - } else if ((ifp->if_flags & IFF_UP) != 0 && - (ifp->if_flags & IFF_RUNNING) == 0) { - /* - * If interface is marked up and it is stopped, then - * start it. - */ - aeinit(sc); - } else { - /* - * Reset the interface to pick up changes in any other - * flags that affect hardware registers. - */ - aeinit(sc); - } - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - error = (cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->sc_arpcom): - ether_delmulti(ifr, &sc->sc_arpcom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - aereset(sc); - error = 0; - } - break; - - default: - error = EINVAL; - break; - } - splx(s); - return (error); -} - -/* - * Set up the logical address filter. - */ -void -aesetladrf(ac, af) - struct arpcom *ac; - u_int16_t *af; -{ - struct ifnet *ifp = &ac->ac_if; - struct ether_multi *enm; - register u_char *cp, c; - register u_int32_t crc; - register int i, len; - struct ether_multistep step; - - /* - * Set up multicast address filter by passing all multicast addresses - * through a crc generator, and then using the high order 6 bits as an - * index into the 64 bit logical address filter. The high order bit - * selects the word, while the rest of the bits select the bit within - * the word. - */ - - if (ifp->if_flags & IFF_PROMISC) - goto allmulti; - - af[0] = af[1] = af[2] = af[3] = 0x0000; - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, - sizeof(enm->enm_addrlo)) != 0) { - /* - * We must listen to a range of multicast addresses. - * For now, just accept all multicasts, rather than - * trying to set only those filter bits needed to match - * the range. (At this time, the only use of address - * ranges is for IP multicast routing, for which the - * range is big enough to require all bits set.) - */ - goto allmulti; - } - - cp = enm->enm_addrlo; - crc = 0xffffffff; - for (len = sizeof(enm->enm_addrlo); --len >= 0;) { - c = *cp++; - for (i = 8; --i >= 0;) { - if ((crc & 0x01) ^ (c & 0x01)) { - crc >>= 1; - crc ^= 0xedb88320; - } else - crc >>= 1; - c >>= 1; - } - } - /* Just want the 6 most significant bits. */ - crc >>= 26; - - /* Turn on the corresponding bit in the filter. */ - af[crc >> 4] |= 1 << SWAP(crc & 0x1f); - - ETHER_NEXT_MULTI(step, enm); - } - ifp->if_flags &= ~IFF_ALLMULTI; - return; - -allmulti: - ifp->if_flags |= IFF_ALLMULTI; - af[0] = af[1] = af[2] = af[3] = 0xffff; -} - -#endif /* NAE > 0 */ diff --git a/sys/arch/amiga/dev/if_aereg.h b/sys/arch/amiga/dev/if_aereg.h deleted file mode 100644 index c08eede7d49..00000000000 --- a/sys/arch/amiga/dev/if_aereg.h +++ /dev/null @@ -1,156 +0,0 @@ -/* $OpenBSD: if_aereg.h,v 1.2 1997/01/16 09:24:37 niklas Exp $ */ -/* $NetBSD: if_aereg.h,v 1.2 1995/08/18 15:53:32 chopps Exp $ */ - -/* - * Copyright (c) 1995 Bernd Ernesti and Klaus Burkert. All rights reserved. - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bernd Ernesti, by Klaus - * Burkert, by Michael van Elst, and by the University of California, - * Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)if_lereg.h 8.1 (Berkeley) 6/10/93 - * - * This is based on the original LANCE files, as the PCnet-ISA used on - * the Ariadne is a LANCE-descendant optimized for the PC-ISA bus. - * This causes some modifications, all data that is to go into registers - * or to structures (buffer-descriptors, init-block) has to be - * byte-swapped. In addition ALL write accesses to the board have to be - * WORD or LONG, BYTE-access is prohibited!! - */ - -#define ETHER_MAX_LEN 1518 -#define ETHER_MIN_LEN 64 - -#define AERBUF 16 /* 16 receive buffers */ -#define AERBUFLOG2 4 -#define AETBUF 4 /* 4 transmit buffers */ -#define AETBUFLOG2 2 - -#define AE_RLEN (AERBUFLOG2 << 13) -#define AE_TLEN (AETBUFLOG2 << 13) - -/* - * PCnet-ISA registers. - */ - -struct aereg1 { - u_int16_t aer1_rdp; /* data port */ - u_int16_t aer1_rap; /* register select port */ - u_int16_t aer1_reset; /* reading this resets the PCnet-ISA */ - u_int16_t aer1_idp; /* isa configuration port */ -}; - -struct aereg2 { - /* init block */ - u_int16_t aer2_mode; /* +0x0000 */ - u_int16_t aer2_padr[3]; /* +0x0002 */ - u_int16_t aer2_ladrf[4]; /* +0x0008 */ - u_int16_t aer2_rdra; /* +0x0010 */ - u_int16_t aer2_rlen; /* +0x0012 */ - u_int16_t aer2_tdra; /* +0x0014 */ - u_int16_t aer2_tlen; /* +0x0016 */ - /* receive message descriptors */ - struct aermd { /* +0x0018 */ - u_int16_t rmd0; - u_int16_t rmd1; - int16_t rmd2; - u_int16_t rmd3; - } aer2_rmd[AERBUF]; - /* transmit message descriptors */ - struct aetmd { /* +0x0058 */ - u_int16_t tmd0; - u_int16_t tmd1; - int16_t tmd2; - u_int16_t tmd3; - } aer2_tmd[AETBUF]; - char aer2_rbuf[AERBUF][ETHER_MAX_LEN]; /* +0x0060 */ - char aer2_tbuf[AETBUF][ETHER_MAX_LEN]; /* +0x2FD0 */ -}; - - -/* - * Control and status bits -- aereg1 - */ -#define AE_CSR0 0x0000 /* Control and status register */ -#define AE_CSR1 0x0100 /* low address of init block */ -#define AE_CSR2 0x0200 /* high address of init block */ -#define AE_CSR3 0x0300 /* Bus master and control */ - -/* Control and status register 0 (csr0) */ -#define AE_SERR 0x0080 /* error summary */ -#define AE_BABL 0x0040 /* transmitter timeout error */ -#define AE_CERR 0x0020 /* collision */ -#define AE_MISS 0x0010 /* missed a packet */ -#define AE_MERR 0x0008 /* memory error */ -#define AE_RINT 0x0004 /* receiver interrupt */ -#define AE_TINT 0x0002 /* transmitter interrupt */ -#define AE_IDON 0x0001 /* initalization done */ -#define AE_INTR 0x8000 /* interrupt condition */ -#define AE_INEA 0x4000 /* interrupt enable */ -#define AE_RXON 0x2000 /* receiver on */ -#define AE_TXON 0x1000 /* transmitter on */ -#define AE_TDMD 0x0800 /* transmit demand */ -#define AE_STOP 0x0400 /* disable all external activity */ -#define AE_STRT 0x0200 /* enable external activity */ -#define AE_INIT 0x0100 /* begin initalization */ - -#define AE_PROM 0x0080 /* promiscuous mode */ -#define AE_MODE 0x0000 - -/* - * Control and status bits -- aereg2 - */ -#define AE_OWN 0x0080 /* LANCE owns the packet */ -#define AE_ERR 0x0040 /* error summary */ -#define AE_STP 0x0002 /* start of packet */ -#define AE_ENP 0x0001 /* end of packet */ - -#define AE_MORE 0x0010 /* multiple collisions */ -#define AE_ONE 0x0008 /* single collision */ -#define AE_DEF 0x0004 /* defferred transmit */ - -#define AE_FRAM 0x0020 /* framing error */ -#define AE_OFLO 0x0010 /* overflow error */ -#define AE_CRC 0x0008 /* CRC error */ -#define AE_RBUFF 0x0004 /* buffer error */ - -/* Transmit message descriptor 3 (tmd3) */ -#define AE_TBUFF 0x0080 /* buffer error */ -#define AE_UFLO 0x0040 /* underflow error */ -#define AE_LCOL 0x0010 /* late collision */ -#define AE_LCAR 0x0008 /* loss of carrier */ -#define AE_RTRY 0x0004 /* retry error */ -#define AE_TDR_MASK 0xff03 /* time domain reflectometry counter */ - -#define SWAP(x) (((x & 0xff) << 8 ) | (( x >> 8) & 0xff)) - diff --git a/sys/arch/amiga/dev/if_bah.c b/sys/arch/amiga/dev/if_bah.c index 82abd456f03..213a10ac44c 100644 --- a/sys/arch/amiga/dev/if_bah.c +++ b/sys/arch/amiga/dev/if_bah.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_bah.c,v 1.7 1997/01/16 09:24:38 niklas Exp $ */ -/* $NetBSD: if_bah.c,v 1.25 1996/12/23 09:10:15 veego Exp $ */ +/* $OpenBSD: if_bah.c,v 1.8 1997/09/18 13:39:55 niklas Exp $ */ +/* $NetBSD: if_bah.c,v 1.30 1997/04/04 06:27:32 is Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -1033,7 +1033,11 @@ bahintr(arg) #endif if (maskedisr & ARC_POR) { - sc->sc_arccom.ac_anaddr = sc->sc_base->dipswitches; + /* + * XXX We should never see this. Don't bother to store + * the address. + * sc->sc_arccom.ac_anaddr = sc->sc_base->dipswitches; + */ sc->sc_base->command = ARC_CLR(CLR_POR); log(LOG_WARNING, "%s: intr: got spurious power on reset int\n", sc->sc_dev.dv_xname); @@ -1048,8 +1052,8 @@ bahintr(arg) sc->sc_arccom.ac_if.if_collisions++; /* -! * If less than 2 seconds per reconfig: -! * If ARC_EXCESSIVE_RECONFIGS + * If less than 2 seconds per reconfig: + * If ARC_EXCESSIVE_RECONFIGS * since last burst, complain and set treshold for * warnings to ARC_EXCESSIVE_RECONS_REWARN. * diff --git a/sys/arch/amiga/dev/if_ed.c b/sys/arch/amiga/dev/if_ed.c index e918ba94219..8244c5d7590 100644 --- a/sys/arch/amiga/dev/if_ed.c +++ b/sys/arch/amiga/dev/if_ed.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_ed.c,v 1.10 1997/02/21 11:08:48 niklas Exp $ */ -/* $NetBSD: if_ed.c,v 1.24 1996/12/23 09:10:16 veego Exp $ */ +/* $OpenBSD: if_ed.c,v 1.11 1997/09/18 13:39:56 niklas Exp $ */ +/* $NetBSD: if_ed.c,v 1.26 1997/03/17 17:51:42 is Exp $ */ /* * Device driver for National Semiconductor DS8390/WD83C690 based ethernet diff --git a/sys/arch/amiga/dev/if_levar.h b/sys/arch/amiga/dev/if_levar.h index 2a2676424ee..ffeb241b69a 100644 --- a/sys/arch/amiga/dev/if_levar.h +++ b/sys/arch/amiga/dev/if_levar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if_levar.h,v 1.3 1996/05/09 22:40:01 niklas Exp $ */ -/* $NetBSD: if_levar.h,v 1.3 1996/05/07 00:46:45 thorpej Exp $ */ +/* $OpenBSD: if_levar.h,v 1.4 1997/09/18 13:39:56 niklas Exp $ */ +/* $NetBSD: if_levar.h,v 1.5 1997/03/27 21:15:14 veego Exp $ */ /* * Copyright (c) 1982, 1990 The Regents of the University of California. @@ -35,11 +35,16 @@ */ /* - * LANCE registers. + * LANCE and PCnet-ISA registers. */ struct lereg1 { - u_short ler1_rdp; /* data port */ - u_short ler1_rap; /* register select port */ + u_int16_t ler1_rdp; /* data port */ + u_int16_t ler1_rap; /* register select port */ + /* + * The next two registers are only available on PCnet-ISA cards. + */ + u_int16_t ler1_reset; /* reading this resets the PCnet-ISA */ + u_int16_t ler1_idp; /* isa configuration port */ }; /* diff --git a/sys/arch/amiga/dev/if_qn.c b/sys/arch/amiga/dev/if_qn.c index 46909ff8413..546bcd9e611 100644 --- a/sys/arch/amiga/dev/if_qn.c +++ b/sys/arch/amiga/dev/if_qn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_qn.c,v 1.9 1997/01/16 09:24:47 niklas Exp $ */ +/* $OpenBSD: if_qn.c,v 1.10 1997/09/18 13:39:57 niklas Exp $ */ /* $NetBSD: if_qn.c,v 1.10 1996/12/23 09:10:19 veego Exp $ */ /* @@ -490,10 +490,6 @@ word_copy_to_card(a, card, len) /* * Copy packet from mbuf to the board memory - * - * Uses an extra buffer/extra memory copy, - * unless the whole packet fits in one mbuf. - * */ u_short qn_put(addr, m) @@ -510,7 +506,6 @@ qn_put(addr, m) for (; m != NULL; m = m->m_next) { data = mtod(m, u_short *); len = m->m_len; - totlen += len; if (len > 0) { totlen += len; diff --git a/sys/arch/amiga/dev/ite.c b/sys/arch/amiga/dev/ite.c index 48d5142027a..58e0d9634d4 100644 --- a/sys/arch/amiga/dev/ite.c +++ b/sys/arch/amiga/dev/ite.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ite.c,v 1.9 1997/01/16 09:24:50 niklas Exp $ */ +/* $OpenBSD: ite.c,v 1.10 1997/09/18 13:39:58 niklas Exp $ */ /* $NetBSD: ite.c,v 1.47 1996/12/23 09:10:20 veego Exp $ */ /* @@ -59,7 +59,6 @@ #include <sys/proc.h> #include <dev/cons.h> #include <amiga/amiga/cc.h> -#include <amiga/amiga/kdassert.h> #include <amiga/amiga/color.h> /* DEBUG */ #include <amiga/amiga/custom.h> /* DEBUG */ #include <amiga/amiga/device.h> diff --git a/sys/arch/amiga/dev/ite_et.c b/sys/arch/amiga/dev/ite_et.c index 0942bb03fb1..2a45cd6bc43 100644 --- a/sys/arch/amiga/dev/ite_et.c +++ b/sys/arch/amiga/dev/ite_et.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ite_et.c,v 1.3 1997/01/16 09:24:51 niklas Exp $ */ -/* $NetBSD: ite_et.c,v 1.2 1996/10/08 23:18:54 thorpej Exp $ */ +/* $OpenBSD: ite_et.c,v 1.4 1997/09/18 13:39:58 niklas Exp $ */ +/* $NetBSD: ite_et.c,v 1.3 1997/03/05 22:50:41 veego Exp $ */ /* * Copyright (c) 1995 Ezra Story @@ -130,7 +130,7 @@ et_cursor(ip, flag) flag = ip->curx + ip->cury * ip->cols; WCrt(ba, CRT_ID_CURSOR_LOC_LOW, flag & 0xff); WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, (flag >> 8) & 0xff); - WCrt(ba, CTR_ID_EXT_START, (flag >> (16-2)) & 0x0c); + WCrt(ba, CRT_ID_EXT_START, (flag >> (16-2)) & 0x0c); ip->cursorx = ip->curx; ip->cursory = ip->cury; diff --git a/sys/arch/amiga/dev/rtc.h b/sys/arch/amiga/dev/rtc.h index 417a8146192..53f33209c90 100644 --- a/sys/arch/amiga/dev/rtc.h +++ b/sys/arch/amiga/dev/rtc.h @@ -1,5 +1,5 @@ -/* $OpenBSD: rtc.h,v 1.2 1996/05/02 06:44:25 niklas Exp $ */ -/* $NetBSD: rtc.h,v 1.3 1996/04/21 21:12:19 veego Exp $ */ +/* $OpenBSD: rtc.h,v 1.3 1997/09/18 13:39:59 niklas Exp $ */ +/* $NetBSD: rtc.h,v 1.5 1997/07/17 23:29:28 is Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -36,6 +36,12 @@ #ifndef _RTCVAR_H_ #define _RTCVAR_H_ +/* this is a hook set by a clock driver for the configured realtime clock, + returning plain current unix-time */ + +time_t (*gettod) __P((void)); +int (*settod) __P((time_t)); + struct rtclock2000 { u_int :28, second2:4; /* lower digit */ u_int :28, second1:4; /* upper digit */ @@ -49,7 +55,7 @@ struct rtclock2000 { u_int :28, month1:4; /* upper digit */ u_int :28, year2:4; /* lower digit */ u_int :28, year1:4; /* upper digit */ - u_int :28, week:4; /* week */ + u_int :28, weekday:4; /* weekday */ u_int :28, control1:4; /* control-byte 1 */ u_int :28, control2:4; /* control-byte 2 */ u_int :28, control3:4; /* control-byte 3 */ @@ -92,15 +98,10 @@ struct rtclock3000 { #define A3BBC_READ_REG 0xc3 #define A3NUM_BBC_REGS 12 -#define FEBRUARY 2 +/* + * Our clock starts at 1/1/1970, but counts the years from 1900. + */ #define STARTOFTIME 1970 -#define SECDAY 86400L -#define SECYR (SECDAY * 365) - - -#define leapyear(y) ((((y)%4)==0 && ((y)%100)!=0) || ((y)%400) == 0) -#define range_test(n, l, h) ((n) < (l) || (n) > (h)) -#define days_in_year(a) (leapyear(a) ? 366 : 365) -#define days_in_month(a) (month_days[(a) - 1]) +#define CLOCK_BASE_YEAR 1900 #endif /* _RTCVAR_H_ */ diff --git a/sys/arch/amiga/dev/ser.c b/sys/arch/amiga/dev/ser.c index 8561cf2f0c2..afb7e0c1434 100644 --- a/sys/arch/amiga/dev/ser.c +++ b/sys/arch/amiga/dev/ser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ser.c,v 1.6 1997/01/16 09:25:22 niklas Exp $ */ +/* $OpenBSD: ser.c,v 1.7 1997/09/18 13:39:59 niklas Exp $ */ /* $NetBSD: ser.c,v 1.39 1996/12/23 09:10:29 veego Exp $ */ /* @@ -364,6 +364,7 @@ serclose(dev, flag, mode, p) if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN || (tp->t_state & TS_ISOPEN) == 0) #endif + (void) sermctl(dev, 0, DMSET); ttyclose(tp); #if not_yet if (tp != &ser_cons) { diff --git a/sys/arch/amiga/dev/drcomvar.h b/sys/arch/amiga/dev/supio.h index f6431d2a4b4..bcf214d8d9c 100644 --- a/sys/arch/amiga/dev/drcomvar.h +++ b/sys/arch/amiga/dev/supio.h @@ -1,8 +1,9 @@ -/* $OpenBSD: drcomvar.h,v 1.1 1997/01/16 09:23:56 niklas Exp $ */ -/* $NetBSD: drcomvar.h,v 1.1 1996/11/30 00:43:04 is Exp $ */ +/* $OpenBSD: supio.h,v 1.1 1997/09/18 13:40:00 niklas Exp $ */ +/* $NetBSD: supio.h,v 1.1 1997/08/27 19:32:52 is Exp $ */ /* - * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1997 Ignatios Souvatzis + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -14,8 +15,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou - * for the NetBSD Project. + * This product includes software developed by Ignatios Souvatzis + * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -31,10 +32,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -int comintr __P((void *)); +/* + * DraCo multi-io chip bus space stuff definitions + */ -extern int comconsaddr; -extern int comconsattached; -extern bus_chipset_tag_t comconsbc; -extern bus_io_handle_t comconsioh; -extern tcflag_t comconscflag; +struct supio_attach_args { + bus_space_tag_t supio_iot; + char *supio_name; + int supio_iobase; +}; diff --git a/sys/arch/amiga/include/conf.h b/sys/arch/amiga/include/conf.h index 84f54aeed03..ec8b7b25957 100644 --- a/sys/arch/amiga/include/conf.h +++ b/sys/arch/amiga/include/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.8 1997/05/16 18:54:18 niklas Exp $ */ +/* $OpenBSD: conf.h,v 1.9 1997/09/18 13:40:01 niklas Exp $ */ /* $NetBSD: conf.h,v 1.4 1996/11/30 01:13:07 is Exp $ */ /* @@ -35,8 +35,6 @@ cdev_decl(acd); cdev_decl(com); -cdev_decl(drcom); - bdev_decl(fd); cdev_decl(fd); diff --git a/sys/arch/amiga/include/cpu.h b/sys/arch/amiga/include/cpu.h index d63e077db00..9b1733a4b65 100644 --- a/sys/arch/amiga/include/cpu.h +++ b/sys/arch/amiga/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.9 1997/01/16 09:25:46 niklas Exp $ */ +/* $OpenBSD: cpu.h,v 1.10 1997/09/18 13:40:01 niklas Exp $ */ /* $NetBSD: cpu.h,v 1.36 1996/09/11 00:11:42 thorpej Exp $ */ /* @@ -227,8 +227,6 @@ int badaddr __P((caddr_t)); int badbaddr __P((caddr_t)); void bootsync __P((void)); void dumpconf __P((void)); -struct frame; -void regdump __P((struct frame *, int)); /* * Prototypes from sys_machdep.c: diff --git a/sys/arch/amiga/include/mtpr.h b/sys/arch/amiga/include/mtpr.h index 623c88ab546..6723b955520 100644 --- a/sys/arch/amiga/include/mtpr.h +++ b/sys/arch/amiga/include/mtpr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mtpr.h,v 1.3 1997/01/16 09:25:57 niklas Exp $ */ +/* $OpenBSD: mtpr.h,v 1.4 1997/09/18 13:40:02 niklas Exp $ */ /* $NetBSD: mtpr.h,v 1.10 1996/05/09 20:31:53 is Exp $ */ /* @@ -81,6 +81,9 @@ extern unsigned char ssir; #define setsoftclock() (ssir |= SIR_CLOCK, setsoftint()) #define setsoftcback() (ssir |= SIR_CBACK, setsoftint()) +void softintr_schedule __P((void *)); +void *softintr_establish __P((int, void (*)(void *), void *)); + #endif /* _KERNEL */ #endif /* !_MACHINE_MPTR_H_ */ diff --git a/sys/arch/amiga/include/param.h b/sys/arch/amiga/include/param.h index be4d5b0b21d..5b04b0daf87 100644 --- a/sys/arch/amiga/include/param.h +++ b/sys/arch/amiga/include/param.h @@ -1,5 +1,5 @@ -/* $OpenBSD: param.h,v 1.9 1997/09/17 17:44:05 downsj Exp $ */ -/* $NetBSD: param.h,v 1.30 1996/09/28 15:54:04 mhitch Exp $ */ +/* $OpenBSD: param.h,v 1.10 1997/09/18 13:40:02 niklas Exp $ */ +/* $NetBSD: param.h,v 1.35 1997/07/10 08:22:36 veego Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -42,119 +42,49 @@ * * @(#)param.h 7.8 (Berkeley) 6/28/91 */ -#ifndef _MACHINE_PARAM_H_ -#define _MACHINE_PARAM_H_ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ /* * Machine dependent constants for amiga */ #define _MACHINE amiga #define MACHINE "amiga" -#define _MACHINE_ARCH m68k -#define MACHINE_ARCH "m68k" -#define MID_MACHINE MID_M68K - -/* - * Round p (pointer or byte index) up to a correctly-aligned value - * for all data types (int, long, ...). The result is u_int and - * must be cast to any desired pointer type. - */ -#define ALIGNBYTES (sizeof(int) - 1) -#define ALIGN(p) (((u_int)(p) + (sizeof(int) - 1)) &~ (sizeof(int) - 1)) -#define NBPG 8192 /* bytes/page */ -#define PGOFSET (NBPG-1) /* byte offset into page */ #define PGSHIFT 13 /* LOG2(NBPG) */ -#define NPTEPG (NBPG/(sizeof(u_int))) +#define KERNBASE 0x00000000 /* start of kernel virtual */ -#define NBSEG ((mmutype == MMU_68040) ? 32*NBPG : 2048*NBPG) /* bytes/segment */ -#define SEGOFSET (NBSEG-1) /* byte offset into segment */ #define SEGSHIFT 24 /* LOG2(NBSEG) [68030 value] */ - -#define KERNBASE 0x0 /* start of kernel virtual */ -#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT) - -#define DEV_BSIZE 512 -#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ -#define BLKDEV_IOSIZE 2048 -#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ - -#define CLSIZE 1 -#define CLSIZELOG2 0 - -/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */ -#define SSIZE 1 /* initial stack size/NBPG */ -#define SINCR 1 /* increment of stack/NBPG */ +/* bytes/segment */ +/* (256 * (1 << PGSHIFT)) == (1 << SEGSHIFT) */ +#define NBSEG ((mmutype == MMU_68040) \ + ? (32 * (1 << PGSHIFT)) : (256 * (1 << PGSHIFT))) +#define SEGOFSET (NBSEG-1) /* byte offset into segment */ #define UPAGES 2 /* pages of u-area */ -#define USPACE (UPAGES * NBPG) -/* - * Constants related to network buffer management. - * MCLBYTES must be no larger than CLBYTES (the software page size), and, - * on machines that exchange pages of input or output buffers with mbuf - * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple - * of the hardware page size. - */ -#define MSIZE 128 /* size of an mbuf */ -#define MCLSHIFT 11 -#define MCLBYTES (1 << MCLSHIFT) -#define MCLOFSET (MCLBYTES - 1) -#ifndef NMBCLUSTERS -#ifdef GATEWAY -#define NMBCLUSTERS 1024 /* map size, max cluster allocation */ -#else -#define NMBCLUSTERS 512 /* map size, max cluster allocation */ -#endif -#endif +#include <m68k/param.h> + +#define NPTEPG (NBPG/(sizeof (pt_entry_t))) /* * Size of kernel malloc arena in CLBYTES-sized logical pages - */ + */ #ifndef NKMEMCLUSTERS -#define NKMEMCLUSTERS (3072*1024/CLBYTES) +#define NKMEMCLUSTERS (3072 * 1024 / CLBYTES) #endif -/* pages ("clicks") to disk blocks */ -#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT)) -#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT)) - -/* pages to bytes */ -#define ctob(x) ((x) << PGSHIFT) -#define btoc(x) (((x) + PGOFSET) >> PGSHIFT) - -/* bytes to disk blocks */ -#define btodb(x) ((x) >> DEV_BSHIFT) -#define dbtob(x) ((x) << DEV_BSHIFT) - -/* - * Map a ``block device block'' to a file system block. - * This should be device dependent, and should use the bsize - * field from the disk label. - * For now though just use DEV_BSIZE. - */ -#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE)) - -/* - * Mach derived conversion macros - */ -#define amiga_round_seg(x) ((((unsigned)(x)) + NBSEG - 1) & ~(NBSEG-1)) -#define amiga_trunc_seg(x) ((unsigned)(x) & ~(NBSEG-1)) -#define amiga_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1)) -#define amiga_trunc_page(x) ((unsigned)(x) & ~(NBPG-1)) -#define amiga_btop(x) ((unsigned)(x) >> PGSHIFT) -#define amiga_ptob(x) ((unsigned)(x) << PGSHIFT) - /* * spl functions; all are normally done in-line */ #include <machine/psl.h> #ifdef _KERNEL -#ifndef _LOCORE -void delay __P((u_int)); -void DELAY __P((u_int)); -#endif -#endif +#ifndef _LOCORE +void delay __P((int)); +void DELAY __P((int)); +#endif /* !_LOCORE */ +#endif /* _KERNEL */ #endif /* !_MACHINE_PARAM_H_ */ diff --git a/sys/arch/amiga/include/pmap.h b/sys/arch/amiga/include/pmap.h index e627e170091..da51ee3ed92 100644 --- a/sys/arch/amiga/include/pmap.h +++ b/sys/arch/amiga/include/pmap.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pmap.h,v 1.2 1997/01/16 09:26:01 niklas Exp $ */ -/* $NetBSD: pmap.h,v 1.16 1995/09/29 13:52:08 chopps Exp $ */ +/* $OpenBSD: pmap.h,v 1.3 1997/09/18 13:40:03 niklas Exp $ */ +/* $NetBSD: pmap.h,v 1.17 1997/06/10 18:34:52 veego Exp $ */ /* * Copyright (c) 1987 Carnegie-Mellon University @@ -83,7 +83,7 @@ typedef struct pmap *pmap_t; #define PMAP_ACTIVATE(pmapp, pcbp, iscurproc) \ if ((pmapp) != NULL && (pmapp)->pm_stchanged) { \ (pcbp)->pcb_ustp = \ - amiga_btop((vm_offset_t)(pmapp)->pm_stpa); \ + m68k_btop((vm_offset_t)(pmapp)->pm_stpa); \ if (iscurproc) \ loadustp((pcbp)->pcb_ustp); \ (pmapp)->pm_stchanged = FALSE; \ diff --git a/sys/arch/amiga/include/proc.h b/sys/arch/amiga/include/proc.h index 22e636ee922..bff72acd8c1 100644 --- a/sys/arch/amiga/include/proc.h +++ b/sys/arch/amiga/include/proc.h @@ -1,5 +1,5 @@ -/* $OpenBSD: proc.h,v 1.3 1997/01/16 09:26:02 niklas Exp $ */ -/* $NetBSD: proc.h,v 1.10 1994/10/26 02:06:27 cgd Exp $ */ +/* $OpenBSD: proc.h,v 1.4 1997/09/18 13:40:03 niklas Exp $ */ +/* $NetBSD: proc.h,v 1.12 1997/06/08 10:35:39 veego Exp $ */ /* * Copyright (c) 1991 Regents of the University of California. @@ -47,10 +47,9 @@ struct mdproc { }; /* md_flags */ -#define MDP_AST 0x0001 /* async trap pending */ -#define MDP_STACKADJ 0x0002 /* frame SP adjusted, might have to +#define MDP_STACKADJ 0x0001 /* frame SP adjusted, might have to undo when system call returns ERESTART. */ -#define MDP_UNCACHE_WX 0x0004 /* The process might modify code, so +#define MDP_UNCACHE_WX 0x0002 /* The process might modify code, so don't cache writeable executable pages. */ #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/arch/amiga/include/psl.h b/sys/arch/amiga/include/psl.h index e3c5def73aa..4c52270e45c 100644 --- a/sys/arch/amiga/include/psl.h +++ b/sys/arch/amiga/include/psl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: psl.h,v 1.8 1997/01/16 09:26:04 niklas Exp $ */ +/* $OpenBSD: psl.h,v 1.9 1997/09/18 13:40:04 niklas Exp $ */ /* $NetBSD: psl.h,v 1.11 1996/11/30 00:33:49 is Exp $ */ #ifndef _MACHINE_PSL_H_ @@ -115,7 +115,7 @@ spllower(npsl) * * XXX should ttyspl be volatile? I think not; it is intended to be set only * during xxx_attach() time, and will be used only later. - * -is + * -is */ extern u_int16_t amiga_ttyspl; diff --git a/sys/arch/amiga/include/vmparam.h b/sys/arch/amiga/include/vmparam.h index c8053c4b8b5..28738d5982b 100644 --- a/sys/arch/amiga/include/vmparam.h +++ b/sys/arch/amiga/include/vmparam.h @@ -1,5 +1,5 @@ -/* $OpenBSD: vmparam.h,v 1.3 1996/08/04 01:15:15 niklas Exp $ */ -/* $NetBSD: vmparam.h,v 1.14 1996/04/21 21:13:23 veego Exp $ */ +/* $OpenBSD: vmparam.h,v 1.4 1997/09/18 13:40:04 niklas Exp $ */ +/* $NetBSD: vmparam.h,v 1.16 1997/07/12 16:18:36 perry Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -141,6 +141,10 @@ * so we loan each swapped in process memory worth 100$, or just admit * that we don't consider it worthwhile and swap it out to disk which costs * $30/mb or about $0.75. + * Update: memory prices have changed recently (9/96). At the current + * value of $6 per megabyte, we lend each swapped in process memory worth + * $0.15, or just admit that we don't consider it worthwhile and swap it out + * to disk which costs $0.20/MB, or just under half a cent. */ #define SAFERSS 4 /* nominal ``small'' resident set size protected against replacement */ |