diff --exclude CVS -urN sys/arch/dreamcast.orig/conf/DCEXT sys/arch/dreamcast/conf/DCEXT --- sys/arch/dreamcast.orig/conf/DCEXT 1970-01-01 01:00:00.000000000 +0100 +++ sys/arch/dreamcast/conf/DCEXT 2012-07-29 11:55:20.000000000 +0100 @@ -0,0 +1,38 @@ +include "arch/dreamcast/conf/GENERIC" + +# Enable experimental buffer queue strategy for better responsiveness under +# high disk I/O load. Likely stable but not yet the default. +#options BUFQ_READPRIO +options BUFQ_PRIOCSCAN + +no options EXEC_COFF + +no options SYMTAB_SPACE +options SYMTAB_SPACE=331740 + +no options FONT_BOLD8x16 +options FONT_VT220ISO8x16 + +no config netbsd +config netbsd root on wd0a type ? + +# +# DCext bus +# irq = IDE | IRQ9 | IRQ5 | IRQ11 | IRQ10 +# +dcext0 at g2bus? + +wdc0 at dcext? port 0x400 irq 14 +atabus* at wdc? channel ? +wd* at atabus? drive ? flags 0x0000 + +atapibus* at atapi? +cd* at atapibus? drive ? flags 0x0000 +#sd* at atapibus? drive ? flags 0x0000 +#uk* at atapibus? drive ? flags 0x0000 + +ne0 at dcext? port 0x280 irq 9 +ne1 at dcext? port 0x300 irq 5 + +no pseudo-device accf_data +no pseudo-device accf_http diff --exclude CVS -urN sys/arch/dreamcast.orig/conf/files.dreamcast sys/arch/dreamcast/conf/files.dreamcast --- sys/arch/dreamcast.orig/conf/files.dreamcast 2012-07-29 12:08:25.000000000 +0100 +++ sys/arch/dreamcast/conf/files.dreamcast 2012-07-29 11:27:26.000000000 +0100 @@ -104,4 +104,15 @@ attach aica at g2bus file arch/dreamcast/dev/g2/aica.c aica needs-flag +device dcext { [port = -1], [irq = -1] } +attach dcext at g2bus +file arch/dreamcast/dev/g2/dcext.c dcext +file arch/dreamcast/dev/g2/dcext_bus_mem.c dcext + +attach wdc at dcext with wdc_dcext +file arch/dreamcast/dev/g2/wdc_dcext.c wdc_dcext + +attach ne at dcext with ne_dcext: rtl80x9 +file arch/dreamcast/dev/g2/if_ne_dcext.c ne_dcext + include "arch/dreamcast/conf/majors.dreamcast" diff --exclude CVS -urN sys/arch/dreamcast.orig/dev/g2/dcext.c sys/arch/dreamcast/dev/g2/dcext.c --- sys/arch/dreamcast.orig/dev/g2/dcext.c 1970-01-01 01:00:00.000000000 +0100 +++ sys/arch/dreamcast/dev/g2/dcext.c 2012-07-29 11:27:26.000000000 +0100 @@ -0,0 +1,270 @@ +/* $NetBSD$ */ + +/*- + * Copyright (C) 2002,2003 Izumi Tsutsui. 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. + * + * 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 +#include +#include +#include +#include + +#include + +#include + +#include "locators.h" + +/* #define DCEXT_EVENT_COUNTERS */ + +static const int isatodcextirq[] = { + -1, /* 0: N/A */ + -1, /* 1: N/A */ + -1, /* 2: N/A */ + -1, /* 3: N/A */ + -1, /* 4: N/A */ + 0x0004, /* 5: ISA slot */ + -1, /* 6: N/A */ + -1, /* 7: N/A */ + -1, /* 8: N/A */ + 0x0008, /* 9: N/A */ + 0x0001, /* 10: ISA slot */ + 0x0002, /* 11: ISA slot */ + -1, /* 12: N/A */ + -1, /* 13: N/A */ + 0x0010, /* 14: wdc port */ + -1 /* 15: N/A */ +}; + +int dcext_match(struct device *, struct cfdata *, void *); +void dcext_attach(struct device *, struct device *, void *); +int dcext_print(void *, const char *); +int dcext_search(struct device *, struct cfdata *, const int *, void *); + +CFATTACH_DECL(dcext, sizeof(struct dcext_softc), + dcext_match, dcext_attach, NULL, NULL); + +struct dcext_intr dcext_intr_list; + +int +dcext_match(struct device *parent, struct cfdata *cf, void *aux) +{ + volatile uint16_t *irqaddr, *reset; + + /* XXX needs real probe strategy */ + reset = (void *)DCEXT_RESETADDR; + *reset = 0x0000; + delay(1000); + *reset = 0x0001; + delay(1000); + *reset = 0x0000; + delay(1000); + + irqaddr = (void *)DCEXT_IRQADDR; + + if ((*irqaddr & 0x1000) != 0) /* XXX */ + return 0; + + return 1; +} + +void +dcext_attach(struct device *parent, struct device *self, void *aux) +{ + struct dcext_softc *sc = (void *)self; + volatile uint16_t *reset; + + printf(": Dreamcast Extension board\n"); + printf("%s: using %s\n", sc->sc_dev.dv_xname, + sysasic_intr_string(SYSASIC_IRL11)); + + TAILQ_INIT(&sc->sc_subdevs); + + reset = (void *)DCEXT_RESETADDR; + *reset = 0x0000; + delay(1000); + *reset = 0x0001; + delay(1000); + *reset = 0x0000; + delay(1000); + + dcext_bus_mem_init(sc); + + config_search_ia(dcext_search, self, "dcext", NULL); +} + +int +dcext_print(void *aux, const char *pnp) +{ + struct dcext_attach_args *da = aux; + + printf(" port 0x%x", da->da_iobase); + if (da->da_irq > 0) + printf(" irq %d", da->da_irq); + + return UNCONF; +} + +int +dcext_search(struct device *parent, struct cfdata *cf, + const int *ldesc, void *aux) +{ + struct dcext_attach_args da; + struct dcext_softc *sc = (void *)parent; + + da.da_iot = &sc->sc_memt; + da.da_iobase = cf->cf_loc[DCEXTCF_PORT]; + da.da_irq = cf->cf_loc[DCEXTCF_IRQ]; + + if (config_match(parent, cf, &da) > 0) + config_attach(parent, cf, &da, dcext_print); + + return 0; +} + +void +dcext_intr_init(void) +{ + struct dcext_intr *di; + + di = &dcext_intr_list; + LIST_INIT(&di->di_q); +#ifdef DCEXT_EVENT_COUNTERS + evcnt_attach_dynamic(&di->di_evcnt, EVCNT_TYPE_INTR, + NULL, "intr", "dcext"); +#endif + + sysasic_intr_establish(SYSASIC_EVENT_EXT, IPL_NET, SYSASIC_IRL11, + dcext_intr_dispatch, NULL); +} + +void * +dcext_intr_establish(int irq, int ipl, int (*func)(void *), void *arg, + const char *ev_name) +{ + struct dcext_intr *di; + struct dcext_intrhand *newih, *curih; + + /* check IRQ value */ + if (irq < 0 || irq > 15 || isatodcextirq[irq] == -1) { + printf("dcext_intr_establish: invalid IRQ value\n"); + return NULL; + } + + di = &dcext_intr_list; + + newih = malloc(sizeof *newih, M_DEVBUF, M_NOWAIT); + if (newih == NULL) + panic("dcext_intr_establish: can't allocate memory"); + + /* fill in the new entry */ + newih->ih_func = func; + newih->ih_arg = arg; + newih->ih_ipl = ipl; + newih->ih_irq = isatodcextirq[irq]; + + evcnt_attach_dynamic(&newih->ih_evcnt, EVCNT_TYPE_INTR, + NULL, "dcext", ev_name); + + if (LIST_EMPTY(&di->di_q)) { + dcext_intr_init(); + LIST_INSERT_HEAD(&di->di_q, newih, ih_q); + goto done; + } + + for (curih = LIST_FIRST(&di->di_q); + LIST_NEXT(curih, ih_q) != NULL; + curih = LIST_NEXT(curih, ih_q)) { + if (newih->ih_ipl > curih->ih_ipl) { + LIST_INSERT_BEFORE(curih, newih, ih_q); + goto done; + } + } + + LIST_INSERT_AFTER(curih, newih, ih_q); + + done: + return newih; +} + +void +dcext_intr_disestablish(void *arg) +{ + struct dcext_intrhand *ih = arg; + + LIST_REMOVE(ih, ih_q); + free(ih, M_DEVBUF); +} + +int +dcext_intr_dispatch(void *arg) +{ + struct dcext_intrhand *ih; + struct dcext_intr *list; + int handled, rv; + u_int irqs; + static int straycount, unexpected; + int s; + + s = _cpu_intr_suspend(); + + handled = 0; + irqs = *(volatile uint16_t *)DCEXT_IRQADDR; + list = &dcext_intr_list; + + if (__predict_false(LIST_EMPTY(&list->di_q))) { + printf("dcext_intr_dispatch: unexpected interrupt\n"); + if (++unexpected > 10) + panic("too many unexpected interrupts"); + goto out; + } + + LIST_FOREACH(ih, &list->di_q, ih_q) { + if ((ih->ih_irq & irqs) != 0) { + _cpu_intr_resume(s); + rv = (*ih->ih_func)(ih->ih_arg); + s = _cpu_intr_suspend(); + if (rv != 0) { + handled = 1; + ih->ih_evcnt.ev_count++; + } + } + } + + if (__predict_true(handled)) { +#ifdef DCEXT_EVENT_COUNTERS + list->di_evcnt.ev_count++; +#endif + straycount = 0; + } else if (++straycount > 50) + panic("dcext_intr_dispatch: too many stray interrupts"); + else + printf("dcext_intr_dispatch: stray interrupt: irqs = 0x%04x\n", + irqs); + + out: + _cpu_intr_resume(s); + + return handled; +} diff --exclude CVS -urN sys/arch/dreamcast.orig/dev/g2/dcext_bus_mem.c sys/arch/dreamcast/dev/g2/dcext_bus_mem.c --- sys/arch/dreamcast.orig/dev/g2/dcext_bus_mem.c 1970-01-01 01:00:00.000000000 +0100 +++ sys/arch/dreamcast/dev/g2/dcext_bus_mem.c 2012-07-29 11:35:17.000000000 +0100 @@ -0,0 +1,114 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Bus space implementation for the dcext devices. + */ + +#include /* RCS ID & Copyright macro defns */ + +#include +#include +#include + +#include +#include + +#include +#include + +int dcext_bus_mem_map(void *, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void dcext_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t); + +int dcext_space_subregion(void *, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); + +void +dcext_bus_mem_init(struct dcext_softc *sc) +{ + bus_space_tag_t t = &sc->sc_memt; + + memset(t, 0, sizeof(*t)); + + t->dbs_map = dcext_bus_mem_map; + t->dbs_unmap = dcext_bus_mem_unmap; + + t->dbs_r_1 = g2bus_sparse_bus_mem_read_1; + t->dbs_r_2 = g2bus_sparse_bus_mem_read_2; + t->dbs_r_4 = g2bus_sparse_bus_mem_read_4; + + t->dbs_w_1 = g2bus_sparse_bus_mem_write_1; + t->dbs_w_2 = g2bus_sparse_bus_mem_write_2; + t->dbs_w_4 = g2bus_sparse_bus_mem_write_4; + + t->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1; + + t->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1; + + t->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1; + t->dbs_rm_2 = g2bus_sparse_bus_mem_read_multi_2; + + t->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1; + t->dbs_wm_2 = g2bus_sparse_bus_mem_write_multi_2; + + t->dbs_subregion = dcext_space_subregion; +} + +int +dcext_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags, + bus_space_handle_t *shp) +{ + + KASSERT((addr & SH3_PHYS_MASK) == addr); + + addr |= 0xb4000000; + *shp = SH3_PHYS_TO_P2SEG(addr); + + return 0; +} + +void +dcext_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size) +{ + + KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END); + /* Nothing to do. */ +} + +int +dcext_space_subregion(void *v, bus_space_handle_t handle, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nhandlep) +{ + + *nhandlep = handle + (offset << DCEXT_STRIDE); + return 0; +} diff --exclude CVS -urN sys/arch/dreamcast.orig/dev/g2/dcextvar.h sys/arch/dreamcast/dev/g2/dcextvar.h --- sys/arch/dreamcast.orig/dev/g2/dcextvar.h 1970-01-01 01:00:00.000000000 +0100 +++ sys/arch/dreamcast/dev/g2/dcextvar.h 2012-07-29 11:34:56.000000000 +0100 @@ -0,0 +1,95 @@ +/* $NetBSD$ */ + +/*- + * Copyright (C) 2002 Izumi Tsutsui. 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. + * + * 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. + */ + +#ifndef _DREAMCAST_DPPBUSVAR_H_ +#define _DREAMCAST_DPPBUSVAR_H_ + +#include +#include "locators.h" + +/* + * DCext driver attach arguments + */ +struct dcext_attach_args { + bus_space_tag_t da_iot; + int da_iobase; /* base i/o address */ + int da_irq; /* interrupt request */ +}; + +/* + * Per-device DCext variables + */ +struct dcextdev { + struct device *dd_dev; /* back pointer to generic */ + TAILQ_ENTRY(dcextdev) + dd_bchain; /* bus chain */ +}; + +/* + * master bus + */ +struct dcext_softc { + struct device sc_dev; /* base device */ + struct dreamcast_bus_space sc_memt; + TAILQ_HEAD(, dcextdev) + sc_subdevs; /* list of all children */ +}; + +/* + * structures for interrupt handling + */ +struct dcext_intrhand { + LIST_ENTRY(dcext_intrhand) ih_q; + int (*ih_func)(void *); + void *ih_arg; + int ih_ipl; + int ih_irq; + struct evcnt ih_evcnt; +}; + +struct dcext_intr { + LIST_HEAD(, dcext_intrhand) di_q; + struct evcnt di_evcnt; +}; + +#define DCEXT_IRQADDR 0xb400c000 +#define DCEXT_RESETADDR 0xb400f000 +#define DCEXT_STRIDE 2 + +#define DCEXT_ISAIOTOPA(ioaddr) ((ioaddr) << DCEXT_STRIDE) + +/* + * functions declarations + */ + +void dcext_bus_mem_init(struct dcext_softc *); + +void dcext_intr_init(void); +void *dcext_intr_establish(int, int, int (*)(void *), void *, const char *); +void dcext_intr_disestablish(void *); +int dcext_intr_dispatch(void *); + +#endif /* _DREAMCAST_DPPBUSVAR_H_ */ diff --exclude CVS -urN sys/arch/dreamcast.orig/dev/g2/g2bus_bus_mem.c sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c --- sys/arch/dreamcast.orig/dev/g2/g2bus_bus_mem.c 2012-07-29 12:08:25.000000000 +0100 +++ sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c 2012-07-29 11:27:26.000000000 +0100 @@ -55,57 +55,6 @@ void g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t); paddr_t g2bus_bus_mem_mmap(void *, bus_addr_t, off_t, int, int); -uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); -uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); -uint32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); - -void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, - uint8_t); -void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, - uint16_t); -void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, - uint32_t); - -void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t, - uint8_t *, bus_size_t); -void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t, - uint16_t *, bus_size_t); -void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t, - uint32_t *, bus_size_t); - -void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t, - const uint8_t *, bus_size_t); -void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t, - const uint16_t *, bus_size_t); -void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t, - const uint32_t *, bus_size_t); - -void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t, - uint32_t, bus_size_t); - -uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); -uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); -uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); - -void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, - uint8_t); -void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, - uint16_t); -void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, - uint32_t); - -void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t, - bus_size_t, uint8_t *, bus_size_t); - -void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t, - bus_size_t, const uint8_t *, bus_size_t); - -void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t, - bus_size_t, uint8_t *, bus_size_t); - -void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t, - bus_size_t, const uint8_t *, bus_size_t); - void g2bus_bus_mem_init(struct g2bus_softc *sc) { @@ -185,6 +134,8 @@ _cpu_intr_resume(__s); \ } while (/*CONSTCOND*/0) +#define G2BUSMEM_UNROLL_ITERATIONS + uint8_t g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off) { @@ -277,6 +228,31 @@ volatile const uint8_t *baddr = (uint8_t *)(sh + off); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + *addr++ = *baddr++; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) *addr++ = *baddr++; @@ -322,6 +298,31 @@ volatile uint8_t *baddr = (uint8_t *)(sh + off); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + *baddr++ = *addr++; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) *baddr++ = *addr++; @@ -487,6 +488,31 @@ volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4)); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 8; len -= 8) { + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + *addr++ = *baddr; + baddr += 4; + if (((len & ~0x7) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) { *addr++ = *baddr; @@ -504,6 +530,31 @@ volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4)); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 8; len -= 8) { + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + *baddr = *addr++; + baddr += 4; + if (((len & ~0x7) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) { *baddr = *addr++; @@ -521,6 +572,73 @@ volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4)); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ + + while (len--) + *addr++ = *baddr; + + G2_UNLOCK(); +} + +void +g2bus_sparse_bus_mem_read_multi_2(void *v, bus_space_handle_t sh, + bus_size_t off, uint16_t *addr, bus_size_t len) +{ + G2LOCK_DECL; + __volatile uint16_t *baddr; + + baddr = (uint16_t *)(sh + (off * 4)); + + G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + *addr++ = *baddr; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) *addr++ = *baddr; @@ -536,6 +654,73 @@ volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4)); G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ + + while (len--) + *baddr = *addr++; + + G2_UNLOCK(); +} + +void +g2bus_sparse_bus_mem_write_multi_2(void *v, bus_space_handle_t sh, + bus_size_t off, const uint16_t *addr, bus_size_t len) +{ + G2LOCK_DECL; + __volatile uint16_t *baddr; + + baddr = (uint16_t *)(sh + (off * 4)); + + G2_LOCK(); +#ifdef G2BUSMEM_UNROLL_ITERATIONS + for (; len >= 16; len -= 16) { + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + *baddr = *addr++; + if (((len & ~0xf) & 0x1ff) == 0) { + /* drain pending interrupts */ + G2_UNLOCK(); + G2_LOCK(); + } + } +#endif /* G2BUSMEM_UNROLL_ITERATIONS */ while (len--) *baddr = *addr++; diff --exclude CVS -urN sys/arch/dreamcast.orig/dev/g2/g2busvar.h sys/arch/dreamcast/dev/g2/g2busvar.h --- sys/arch/dreamcast.orig/dev/g2/g2busvar.h 2012-07-29 12:08:25.000000000 +0100 +++ sys/arch/dreamcast/dev/g2/g2busvar.h 2012-07-29 11:27:26.000000000 +0100 @@ -66,4 +66,59 @@ void g2bus_bus_mem_init(struct g2bus_softc *); void g2bus_set_bus_mem_sparse(bus_space_tag_t); +u_int8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); +u_int16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); +u_int32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); + +void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, + u_int8_t); +void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, + u_int16_t); +void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, + u_int32_t); + +void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); +void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); +void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t, + u_int32_t *, bus_size_t); + +void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t, + const u_int8_t *, bus_size_t); +void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t, + const u_int16_t *, bus_size_t); +void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t, + const u_int32_t *, bus_size_t); + +void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t, + u_int32_t, bus_size_t); + +u_int8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); +u_int16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); +u_int32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); + +void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, + u_int8_t); +void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, + u_int16_t); +void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, + u_int32_t); + +void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + +void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + +void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); +void g2bus_sparse_bus_mem_read_multi_2(void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + +void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); +void g2bus_sparse_bus_mem_write_multi_2(void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + #endif /* _DREAMCAST_G2BUSVAR_H_ */ diff --exclude CVS -urN sys/arch/dreamcast.orig/dreamcast/machdep.c sys/arch/dreamcast/dreamcast/machdep.c --- sys/arch/dreamcast.orig/dreamcast/machdep.c 2012-07-29 12:08:25.000000000 +0100 +++ sys/arch/dreamcast/dreamcast/machdep.c 2012-07-29 11:27:26.000000000 +0100 @@ -177,6 +177,10 @@ strcpy(cpu_model, "SEGA Dreamcast\n"); sh_startup(); + +#ifdef FORCE_RB_SINGLE + boothowto |= RB_SINGLE; +#endif } SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")