summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1999-06-05 13:30:13 +0000
committerdfr <dfr@FreeBSD.org>1999-06-05 13:30:13 +0000
commit5d698a672d010c9c1953515f78b626af1f2b23c8 (patch)
tree2c54ebf6283cdabc63a25afd53742d93bbe5eba8 /sys
parentb5f25689234ab13b40ae7c1bfdd723ac8c3dc9d3 (diff)
downloadFreeBSD-src-5d698a672d010c9c1953515f78b626af1f2b23c8.zip
FreeBSD-src-5d698a672d010c9c1953515f78b626af1f2b23c8.tar.gz
* Implement ISA dma (only for CIA now but more chipsets to follow).
* Port the fd driver to alpha.
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/alpha/busdma_machdep.c59
-rw-r--r--sys/alpha/alpha/sgmap.c196
-rw-r--r--sys/alpha/conf/GENERIC6
-rw-r--r--sys/alpha/conf/NOTES6
-rw-r--r--sys/alpha/conf/files.alpha5
-rw-r--r--sys/alpha/include/bus.h6
-rw-r--r--sys/alpha/include/chipset.h9
-rw-r--r--sys/alpha/include/ioctl_fd.h126
-rw-r--r--sys/alpha/include/sgmap.h49
-rw-r--r--sys/alpha/isa/isa.c36
-rw-r--r--sys/alpha/isa/isa_dma.c487
-rw-r--r--sys/alpha/pci/cia.c145
-rw-r--r--sys/conf/files.alpha5
13 files changed, 1115 insertions, 20 deletions
diff --git a/sys/alpha/alpha/busdma_machdep.c b/sys/alpha/alpha/busdma_machdep.c
index 5deba06..60d9bcf 100644
--- a/sys/alpha/alpha/busdma_machdep.c
+++ b/sys/alpha/alpha/busdma_machdep.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: busdma_machdep.c,v 1.1 1998/09/16 08:20:45 dfr Exp $
+ * $Id: busdma_machdep.c,v 1.2 1999/05/26 23:01:36 gallatin Exp $
*/
#include <sys/param.h>
@@ -35,6 +35,7 @@
#include <vm/vm_page.h>
#include <machine/bus.h>
+#include <machine/sgmap.h>
#include <machine/md_var.h>
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
@@ -81,8 +82,10 @@ struct bus_dmamap {
bus_dma_tag_t dmat;
void *buf; /* unmapped buffer pointer */
bus_size_t buflen; /* unmapped buffer length */
+ vm_offset_t busaddress; /* address in bus space */
bus_dmamap_callback_t *callback;
void *callback_arg;
+ void *sgmaphandle; /* handle into sgmap */
STAILQ_ENTRY(bus_dmamap) links;
};
@@ -237,6 +240,25 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
error = 0;
+ if (dmat->flags & BUS_DMA_ISA) {
+ bus_dmamap_t map;
+ map = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF,
+ M_NOWAIT);
+ if (map == NULL) {
+ return (ENOMEM);
+ } else {
+ bzero(map, sizeof(*map));
+ map->busaddress =
+ sgmap_alloc_region(chipset.sgmap,
+ dmat->maxsize,
+ dmat->boundary,
+ &map->sgmaphandle);
+ dmat->map_count++;
+ *mapp = map;
+ return (0);
+ }
+ }
+
if (dmat->lowaddr < ptoa(Maxmem)) {
/* Must bounce */
int maxpages;
@@ -294,6 +316,10 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
int
bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
{
+ if (dmat->flags & BUS_DMA_ISA) {
+ sgmap_free_region(chipset.sgmap, map->sgmaphandle);
+ }
+
if (map != NULL) {
if (STAILQ_FIRST(&map->bpages) != NULL)
return (EBUSY);
@@ -376,6 +402,28 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
int error;
error = 0;
+
+ if (dmat->flags & BUS_DMA_ISA) {
+ /*
+ * For ISA dma, we use the chipset's scatter-gather
+ * map to map the tranfer into the ISA reachable range
+ * of the bus address space.
+ */
+ vaddr = trunc_page((vm_offset_t) buf);
+ dm_segments[0].ds_addr =
+ map->busaddress + (vm_offset_t) buf - vaddr;
+ dm_segments[0].ds_len = buflen;
+ buflen = round_page((vm_offset_t) buf + buflen) - vaddr;
+ sgmap_load_region(chipset.sgmap,
+ map->busaddress,
+ vaddr,
+ buflen);
+ map->buflen = buflen;
+ (*callback)(callback_arg, dm_segments, 1, error);
+
+ return (0);
+ }
+
/*
* If we are being called during a callback, pagesneeded will
* be non-zero, so we can avoid doing the work twice.
@@ -479,6 +527,13 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
{
struct bounce_page *bpage;
+ if (dmat->flags & BUS_DMA_ISA) {
+ sgmap_unload_region(chipset.sgmap,
+ map->busaddress,
+ map->buflen);
+ return;
+ }
+
while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
STAILQ_REMOVE_HEAD(&map->bpages, links);
free_bounce_page(dmat, bpage);
@@ -637,7 +692,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
}
void
-busdma_swi()
+busdma_swi(void)
{
int s;
struct bus_dmamap *map;
diff --git a/sys/alpha/alpha/sgmap.c b/sys/alpha/alpha/sgmap.c
new file mode 100644
index 0000000..493a2b1
--- /dev/null
+++ b/sys/alpha/alpha/sgmap.c
@@ -0,0 +1,196 @@
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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 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 AUTHOR 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.
+ *
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <machine/bus.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <machine/sgmap.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_prot.h>
+#include <vm/vm_map.h>
+
+MALLOC_DEFINE(M_SGMAP, "sgmap", "Scatter Gather mapping");
+
+struct sgmap {
+ struct rman rm; /* manage range of bus addresses */
+ sgmap_map_callback *map; /* map one page in the sgmap */
+ void *arg; /* argument to map function */
+ bus_addr_t sba;
+ bus_addr_t eba;
+};
+
+void *overflow_page = 0;
+vm_offset_t overflow_page_pa;
+
+vm_offset_t
+sgmap_overflow_page(void)
+{
+ /*
+ * Allocate the overflow page if necessary.
+ */
+ if (!overflow_page) {
+ overflow_page = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+ if (!overflow_page)
+ panic("sgmap_alloc_region: can't allocate overflow page");
+ overflow_page_pa = pmap_kextract((vm_offset_t) overflow_page);
+ }
+
+ return overflow_page_pa;
+}
+
+/*
+ * Create an sgmap to manage a range of bus addresses which map
+ * physical memory using a scatter-gather map.
+ */
+struct sgmap *
+sgmap_map_create(bus_addr_t sba, bus_addr_t eba,
+ sgmap_map_callback *map, void *arg)
+{
+ struct sgmap *sgmap;
+
+ sgmap = malloc(sizeof *sgmap, M_SGMAP, M_NOWAIT);
+ if (!sgmap)
+ return 0;
+
+
+ sgmap->rm.rm_start = sba;
+ sgmap->rm.rm_end = eba;
+ sgmap->rm.rm_type = RMAN_ARRAY;
+ sgmap->rm.rm_descr = "Scatter Gather Bus Addresses";
+ rman_init(&sgmap->rm);
+ rman_manage_region(&sgmap->rm, sba, eba);
+ sgmap->map = map;
+ sgmap->arg = arg;
+ sgmap->sba = sba;
+ sgmap->eba = eba;
+
+ return sgmap;
+}
+
+/*
+ * Destroy an sgmap created with sgmap_map_create().
+ */
+void
+sgmap_map_destroy(struct sgmap *sgmap)
+{
+ rman_fini(&sgmap->rm);
+ free(sgmap, M_SGMAP);
+}
+
+/*
+ * Map a range of virtual addresses using the sgmap and return the bus
+ * address of the mapped region. An opaque handle for the mapped
+ * region is also returned in *mhp. This handle should be passed to
+ * sgmap_free_region() when the mapping is no longer required.
+ */
+bus_addr_t
+sgmap_alloc_region(struct sgmap *sgmap,
+ bus_size_t size,
+ bus_size_t boundary,
+ void **mhp)
+{
+ struct resource *res;
+ bus_addr_t ba, nba;
+
+ /*
+ * This ensures allocations are on page boundaries. The extra
+ * page is used as a guard page since dma prefetching can
+ * generate accesses to addresses outside the transfer range.
+ */
+ size = round_page(size);
+
+ /*
+ * Attempt to allocate within each boundary delimited region.
+ */
+ res = 0;
+ for (ba = sgmap->sba; ba < sgmap->eba; ba = nba) {
+ nba = (ba + boundary) & ~(boundary - 1);
+ res = rman_reserve_resource(&sgmap->rm,
+ ba, nba - 1, size + PAGE_SIZE,
+ RF_ACTIVE, 0);
+ if (res)
+ break;
+ }
+
+ if (res == 0)
+ return 0;
+
+ *mhp = (void *) res;
+ return rman_get_start(res);
+}
+
+void
+sgmap_load_region(struct sgmap *sgmap,
+ bus_addr_t sba,
+ vm_offset_t va,
+ bus_size_t size)
+{
+ bus_addr_t ba, eba;
+
+ /*
+ * Call the chipset to map each page in the mapped range to
+ * the correct physical page.
+ */
+ for (ba = sba, eba = sba + size; ba < eba;
+ ba += PAGE_SIZE, va += PAGE_SIZE) {
+ vm_offset_t pa = pmap_kextract(va);
+ sgmap->map(sgmap->arg, ba, pa);
+ }
+ sgmap->map(sgmap->arg, ba, overflow_page_pa);
+}
+
+void
+sgmap_unload_region(struct sgmap *sgmap,
+ bus_addr_t sba,
+ bus_size_t size)
+{
+ bus_addr_t ba, eba;
+
+ /*
+ * Call the chipset to unmap each page.
+ */
+ for (ba = sba, eba = sba + size; ba < eba; ba += PAGE_SIZE) {
+ sgmap->map(sgmap->arg, ba, 0);
+ }
+ sgmap->map(sgmap->arg, ba, 0);
+}
+
+/*
+ * Free a region allocated using sgmap_alloc_region().
+ */
+void
+sgmap_free_region(struct sgmap *sgmap, void *mh)
+{
+ struct resource *res = mh;
+ rman_release_resource(res);
+}
diff --git a/sys/alpha/conf/GENERIC b/sys/alpha/conf/GENERIC
index 865313b..8497209 100644
--- a/sys/alpha/conf/GENERIC
+++ b/sys/alpha/conf/GENERIC
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC,v 1.22 1999/05/10 13:30:51 dfr Exp $
+# $Id: GENERIC,v 1.23 1999/05/26 23:22:14 gallatin Exp $
machine "alpha"
cpu "EV4"
@@ -91,6 +91,10 @@ device cd0
# real time clock
device mcclock0 at isa0 port 0x70
+# Not enabled since it only works on CIA chipsets
+#controller fdc0 at isa? port IO_FD1 irq 6 drq 2
+#disk fd0 at fdc0 drive 0
+
controller atkbdc0 at isa? port IO_KBD
device atkbd0 at atkbdc? irq 1
device psm0 at atkbdc? irq 12
diff --git a/sys/alpha/conf/NOTES b/sys/alpha/conf/NOTES
index 865313b..8497209 100644
--- a/sys/alpha/conf/NOTES
+++ b/sys/alpha/conf/NOTES
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC,v 1.22 1999/05/10 13:30:51 dfr Exp $
+# $Id: GENERIC,v 1.23 1999/05/26 23:22:14 gallatin Exp $
machine "alpha"
cpu "EV4"
@@ -91,6 +91,10 @@ device cd0
# real time clock
device mcclock0 at isa0 port 0x70
+# Not enabled since it only works on CIA chipsets
+#controller fdc0 at isa? port IO_FD1 irq 6 drq 2
+#disk fd0 at fdc0 drive 0
+
controller atkbdc0 at isa? port IO_KBD
device atkbd0 at atkbdc? irq 1
device psm0 at atkbdc? irq 12
diff --git a/sys/alpha/conf/files.alpha b/sys/alpha/conf/files.alpha
index b589354..6b3f3e8 100644
--- a/sys/alpha/conf/files.alpha
+++ b/sys/alpha/conf/files.alpha
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.alpha,v 1.18 1999/04/16 21:21:34 peter Exp $
+# $Id: files.alpha,v 1.19 1999/05/26 23:22:13 gallatin Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -35,6 +35,7 @@ alpha/alpha/mountroot.c optional slice
alpha/alpha/ipl_funcs.c standard
alpha/alpha/pal.s standard
alpha/alpha/busdma_machdep.c standard
+alpha/alpha/sgmap.c standard
alpha/alpha/cons.c standard
alpha/alpha/prom.c standard
alpha/alpha/promcons.c standard
@@ -124,6 +125,7 @@ alpha/pci/tsunami.c optional tsunami
alpha/pci/tsunami_pci.c optional tsunami
alpha/pci/pcibus.c optional pci
alpha/isa/isa.c optional isa
+alpha/isa/isa_dma.c optional isa
alpha/isa/mcclock_isa.c optional isa
alpha/alpha/elf_machdep.c standard
libkern/bcd.c standard
@@ -163,6 +165,7 @@ dev/syscons/syscons.c optional sc device-driver
dev/syscons/scvidctl.c optional sc device-driver
isa/syscons_isa.c optional sc device-driver
isa/psm.c optional psm device-driver
+isa/fd.c optional fd device-driver
dev/ata/ata-all.c optional ata device-driver
dev/ata/ata-dma.c optional ata device-driver
dev/ata/atapi-all.c optional ata device-driver
diff --git a/sys/alpha/include/bus.h b/sys/alpha/include/bus.h
index f515b71..86f80ea 100644
--- a/sys/alpha/include/bus.h
+++ b/sys/alpha/include/bus.h
@@ -67,7 +67,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $Id$ */
+/* $Id: bus.h,v 1.2 1998/09/16 08:22:57 dfr Exp $ */
#ifndef _ALPHA_BUS_H_
#define _ALPHA_BUS_H_
@@ -1025,8 +1025,8 @@ bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */
#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */
#define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */
-#define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */
-#define BUS_DMA_BUS2 0x20
+#define BUS_DMA_ISA 0x10 /* map memory for ISA dma */
+#define BUS_DMA_BUS2 0x20 /* placeholders for bus functions... */
#define BUS_DMA_BUS3 0x40
#define BUS_DMA_BUS4 0x80
diff --git a/sys/alpha/include/chipset.h b/sys/alpha/include/chipset.h
index ec34810..e9dbe87 100644
--- a/sys/alpha/include/chipset.h
+++ b/sys/alpha/include/chipset.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: chipset.h,v 1.7 1999/04/16 21:21:35 peter Exp $
+ * $Id: chipset.h,v 1.8 1999/05/20 15:33:16 gallatin Exp $
*/
#ifndef _MACHINE_CHIPSET_H_
@@ -57,6 +57,8 @@ typedef vm_offset_t alpha_chipset_addrcvt_t(vm_offset_t);
typedef u_int64_t alpha_chipset_read_hae_t(void);
typedef void alpha_chipset_write_hae_t(u_int64_t);
+struct sgmap;
+
typedef struct alpha_chipset {
/*
* I/O port access
@@ -100,6 +102,11 @@ typedef struct alpha_chipset {
*/
alpha_chipset_read_hae_t* read_hae;
alpha_chipset_write_hae_t* write_hae;
+
+ /*
+ * Scatter-Gather map for ISA dma.
+ */
+ struct sgmap* sgmap;
} alpha_chipset_t;
extern alpha_chipset_t chipset;
diff --git a/sys/alpha/include/ioctl_fd.h b/sys/alpha/include/ioctl_fd.h
new file mode 100644
index 0000000..970d247
--- /dev/null
+++ b/sys/alpha/include/ioctl_fd.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden
+ * 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(S) ``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(S) 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.
+ *
+ * $Id$
+ * from: ioctl_fd.h,v 1.11
+ */
+
+#ifndef _MACHINE_IOCTL_FD_H_
+#define _MACHINE_IOCTL_FD_H_
+
+#ifndef KERNEL
+#include <sys/types.h>
+#endif
+#include <sys/ioccom.h>
+
+#define FD_FORMAT_VERSION 110 /* used to validate before formatting */
+#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */
+ /* 2.88 MB drives */
+
+struct fd_formb {
+ int format_version; /* == FD_FORMAT_VERSION */
+ int cyl, head;
+ int transfer_rate; /* fdreg.h: FDC_???KBPS */
+
+ union {
+ struct fd_form_data {
+ /*
+ * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS
+ * it is hardware-dependent since it exactly
+ * matches the byte sequence to write to FDC
+ * during its `format track' operation
+ */
+ u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */
+ u_char nsecs; /* must be <= FD_MAX_NSEC */
+ u_char gaplen; /* GAP 3 length; usually 84 */
+ u_char fillbyte; /* usually 0xf6 */
+ struct fd_idfield_data {
+ /*
+ * data to write into id fields;
+ * for obscure formats, they mustn't match
+ * the real values (but mostly do)
+ */
+ u_char cylno; /* 0 thru 79 (or 39) */
+ u_char headno; /* 0, or 1 */
+ u_char secno; /* starting at 1! */
+ u_char secsize; /* usually 2 */
+ } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */
+ } structured;
+ u_char raw[1]; /* to have continuous indexed access */
+ } format_info;
+};
+
+/* make life easier */
+# define fd_formb_secshift format_info.structured.secshift
+# define fd_formb_nsecs format_info.structured.nsecs
+# define fd_formb_gaplen format_info.structured.gaplen
+# define fd_formb_fillbyte format_info.structured.fillbyte
+/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */
+# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno
+# define fd_formb_headno(i) format_info.structured.idfields[i].headno
+# define fd_formb_secno(i) format_info.structured.idfields[i].secno
+# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize
+
+struct fd_type {
+ int sectrac; /* sectors per track */
+ int secsize; /* size code for sectors */
+ int datalen; /* data len when secsize = 0 */
+ int gap; /* gap len between sectors */
+ int tracks; /* total num of tracks */
+ int size; /* size of disk in sectors */
+ int steptrac; /* steps per cylinder */
+ int trans; /* transfer speed code */
+ int heads; /* number of heads */
+ int f_gap; /* format gap len */
+ int f_inter; /* format interleave factor */
+};
+
+#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */
+#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */
+#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */
+
+#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */
+#define FD_SOPTS _IOW('F', 65, int)
+
+#define FD_DEBUG _IOW('F', 66, int)
+
+#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */
+
+/*
+ * The following definitions duplicate those in sys/i386/isa/fdreg.h
+ * They are here since their values are to be used in the above
+ * structure when formatting a floppy. For very obvious reasons, both
+ * definitions must match ;-)
+ */
+#ifndef FDC_500KBPS
+#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */
+#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */
+#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
+#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */
+ /* for some controllers 1MPBS instead */
+#endif /* FDC_500KBPS */
+
+#endif /* !_MACHINE_IOCTL_FD_H_ */
diff --git a/sys/alpha/include/sgmap.h b/sys/alpha/include/sgmap.h
new file mode 100644
index 0000000..65299c7
--- /dev/null
+++ b/sys/alpha/include/sgmap.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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 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 AUTHOR 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.
+ *
+ * $Id$
+ */
+
+#ifndef _MACHINE_SGMAP_H_
+#define _MACHINE_SGMAP_H_
+
+struct sgmap;
+
+typedef void sgmap_map_callback(void *arg, bus_addr_t ba, vm_offset_t pa);
+
+vm_offset_t sgmap_overflow_page(void);
+struct sgmap *sgmap_map_create(bus_addr_t sba, bus_addr_t eba,
+ sgmap_map_callback *map, void *arg);
+void sgmap_map_destroy(struct sgmap *sgmap);
+bus_addr_t sgmap_alloc_region(struct sgmap *sgmap,
+ bus_size_t size, bus_size_t boundary,
+ void **mhp);
+void sgmap_load_region(struct sgmap *sgmap, bus_addr_t sba,
+ vm_offset_t va, bus_size_t size);
+void sgmap_unload_region(struct sgmap *sgmap,
+ bus_addr_t sba, bus_size_t size);
+void sgmap_free_region(struct sgmap *sgmap, void *mh);
+
+#endif /* !_MACHINE_SGMAP_H_ */
diff --git a/sys/alpha/isa/isa.c b/sys/alpha/isa/isa.c
index 3878e6a..920751f 100644
--- a/sys/alpha/isa/isa.c
+++ b/sys/alpha/isa/isa.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: isa.c,v 1.15 1999/05/18 20:43:49 dfr Exp $
+ * $Id: isa.c,v 1.16 1999/05/22 15:18:15 dfr Exp $
*/
#include <sys/param.h>
@@ -44,6 +44,7 @@
#include <machine/resource.h>
static struct rman isa_irq_rman;
+static struct rman isa_drq_rman;
static void
isa_intr_enable(int irq)
@@ -112,6 +113,14 @@ isa_init_intr(void)
|| rman_manage_region(&isa_irq_rman, 3, 15))
panic("isa_probe isa_irq_rman");
+ isa_drq_rman.rm_start = 0;
+ isa_drq_rman.rm_end = 7;
+ isa_drq_rman.rm_type = RMAN_ARRAY;
+ isa_drq_rman.rm_descr = "ISA DMA request lines";
+ if (rman_init(&isa_drq_rman)
+ || rman_manage_region(&isa_drq_rman, 0, 7))
+ panic("isa_probe isa_drq_rman");
+
/* mask all isa interrupts */
outb(IO_ICU1+1, 0xff);
outb(IO_ICU2+1, 0xff);
@@ -150,8 +159,8 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
{
/*
* Consider adding a resource definition. We allow rid 0-1 for
- * irq, drq and memory and rid 0-7 for ports which is sufficient for
- * isapnp.
+ * irq and drq, 0-3 for memory and 0-7 for ports which is
+ * sufficient for isapnp.
*/
int passthrough = (device_get_parent(child) != bus);
int isdefault = (start == 0UL && end == ~0UL);
@@ -165,7 +174,11 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (!rle) {
if (*rid < 0)
return 0;
- if (type != SYS_RES_IOPORT && *rid > 1)
+ if (type == SYS_RES_IRQ && *rid > 1)
+ return 0;
+ if (type == SYS_RES_DRQ && *rid > 1)
+ return 0;
+ if (type != SYS_RES_MEMORY && *rid > 3)
return 0;
if (type == SYS_RES_IOPORT && *rid > 7)
return 0;
@@ -173,13 +186,13 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
}
}
- if (type != SYS_RES_IRQ)
+ if (type != SYS_RES_IRQ && type != SYS_RES_DRQ)
return resource_list_alloc(bus, child, type, rid,
start, end, count, flags);
if (!passthrough) {
rl = device_get_ivars(child);
- rle = resource_list_find(rl, SYS_RES_IRQ, *rid);
+ rle = resource_list_find(rl, type, *rid);
if (!rle)
return 0;
if (rle->res)
@@ -190,11 +203,16 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
}
}
- res = isa_alloc_intr(bus, child, start);
-
+ if (type == SYS_RES_IRQ)
+ res = rman_reserve_resource(&isa_irq_rman, start, start, 1,
+ 0, child);
+ else
+ res = rman_reserve_resource(&isa_drq_rman, start, start, 1,
+ 0, child);
+
if (res && !passthrough) {
rl = device_get_ivars(child);
- rle = resource_list_find(rl, SYS_RES_IRQ, *rid);
+ rle = resource_list_find(rl, type, *rid);
rle->start = rman_get_start(res);
rle->end = rman_get_end(res);
rle->count = 1;
diff --git a/sys/alpha/isa/isa_dma.c b/sys/alpha/isa/isa_dma.c
new file mode 100644
index 0000000..2cb3e2c
--- /dev/null
+++ b/sys/alpha/isa/isa_dma.c
@@ -0,0 +1,487 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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: @(#)isa.c 7.2 (Berkeley) 5/13/91
+ * from: isa_dma.c,v 1.3 1999/05/09 23:56:00 peter Exp $
+ * $Id$
+ */
+
+/*
+ * code to manage AT bus
+ *
+ * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com):
+ * Fixed uninitialized variable problem and added code to deal
+ * with DMA page boundaries in isa_dmarangecheck(). Fixed word
+ * mode DMA count compution and reorganized DMA setup code in
+ * isa_dmastart()
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h> /* B_READ and B_RAW */
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <isa/isareg.h>
+#include <isa/isavar.h>
+#include <i386/isa/ic/i8237.h>
+#include <machine/bus.h>
+
+/*
+** Register definitions for DMA controller 1 (channels 0..3):
+*/
+#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */
+#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */
+#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */
+#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */
+#define DMA1_RESET (IO_DMA1 + 1*13) /* reset */
+
+/*
+** Register definitions for DMA controller 2 (channels 4..7):
+*/
+#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */
+#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */
+#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
+#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
+#define DMA2_RESET (IO_DMA2 + 2*13) /* reset */
+
+static bus_dma_tag_t dma_tag[8];
+static bus_dmamap_t dma_map[8];
+static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */
+static u_int8_t dma_inuse = 0; /* User for acquire/release */
+static u_int8_t dma_auto_mode = 0;
+
+#define VALID_DMA_MASK (7)
+
+/* high byte of address is stored in this port for i-th dma channel */
+static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
+
+/*
+ * Setup a DMA channel's bounce buffer.
+ */
+void
+isa_dmainit(chan, bouncebufsize)
+ int chan;
+ u_int bouncebufsize;
+{
+ static int initted = 0;
+ bus_addr_t boundary = chan >= 4 ? 0x20000 : 0x10000;
+
+ if (!initted) {
+ /*
+ * Reset the DMA hardware.
+ */
+ outb(DMA1_RESET, 0);
+ outb(DMA2_RESET, 0);
+ isa_dmacascade(4);
+
+ initted = 1;
+ }
+
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dmainit: channel out of range");
+
+ if (dma_tag[chan] || dma_map[chan])
+ panic("isa_dmainit: impossible request");
+#endif
+
+ if (bus_dma_tag_create(/*parent*/NULL,
+ /*alignment*/2,
+ /*boundary*/boundary,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/bouncebufsize,
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/BUS_DMA_ISA,
+ &dma_tag[chan]) != 0) {
+ panic("isa_dmainit: unable to create dma tag\n");
+ }
+
+ if (bus_dmamap_create(dma_tag[chan], 0, &dma_map[chan])) {
+ panic("isa_dmainit: unable to create dma map\n");
+ }
+
+}
+
+/*
+ * Register a DMA channel's usage. Usually called from a device driver
+ * in open() or during its initialization.
+ */
+int
+isa_dma_acquire(chan)
+ int chan;
+{
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dma_acquire: channel out of range");
+#endif
+
+ if (dma_inuse & (1 << chan)) {
+ printf("isa_dma_acquire: channel %d already in use\n", chan);
+ return (EBUSY);
+ }
+ dma_inuse |= (1 << chan);
+ dma_auto_mode &= ~(1 << chan);
+
+ return (0);
+}
+
+/*
+ * Unregister a DMA channel's usage. Usually called from a device driver
+ * during close() or during its shutdown.
+ */
+void
+isa_dma_release(chan)
+ int chan;
+{
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dma_release: channel out of range");
+
+ if ((dma_inuse & (1 << chan)) == 0)
+ printf("isa_dma_release: channel %d not in use\n", chan);
+#endif
+
+ if (dma_busy & (1 << chan)) {
+ dma_busy &= ~(1 << chan);
+ /*
+ * XXX We should also do "dma_bounced &= (1 << chan);"
+ * because we are acting on behalf of isa_dmadone() which
+ * was not called to end the last DMA operation. This does
+ * not matter now, but it may in the future.
+ */
+ }
+
+ dma_inuse &= ~(1 << chan);
+ dma_auto_mode &= ~(1 << chan);
+}
+
+/*
+ * isa_dmacascade(): program 8237 DMA controller channel to accept
+ * external dma control by a board.
+ */
+void
+isa_dmacascade(chan)
+ int chan;
+{
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dmacascade: channel out of range");
+#endif
+
+ /* set dma channel mode, and set dma channel mode */
+ if ((chan & 4) == 0) {
+ outb(DMA1_MODE, DMA37MD_CASCADE | chan);
+ outb(DMA1_SMSK, chan);
+ } else {
+ outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3));
+ outb(DMA2_SMSK, chan & 3);
+ }
+}
+
+/*
+ * isa_dmastart(): program 8237 DMA controller channel.
+ */
+
+struct isa_dmastart_arg {
+ int chan;
+ int flags;
+};
+
+static void isa_dmastart_cb(void *arg, bus_dma_segment_t *segs, int nseg,
+ int error)
+{
+ int chan = ((struct isa_dmastart_arg *) arg)->chan;
+ int flags = ((struct isa_dmastart_arg *) arg)->flags;
+ bus_addr_t phys = segs->ds_addr;
+ int nbytes = segs->ds_len;
+ int waport;
+
+ if (nseg != 1)
+ panic("isa_dmastart: transfer mapping not contiguous");
+
+ if ((chan & 4) == 0) {
+ /*
+ * Program one of DMA channels 0..3. These are
+ * byte mode channels.
+ */
+ /* set dma channel mode, and reset address ff */
+
+ /* If B_RAW flag is set, then use autoinitialise mode */
+ if (flags & B_RAW) {
+ if (flags & B_READ)
+ outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan);
+ else
+ outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan);
+ }
+ else
+ if (flags & B_READ)
+ outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
+ else
+ outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
+ outb(DMA1_FFC, 0);
+
+ /* send start address */
+ waport = DMA1_CHN(chan);
+ outb(waport, phys);
+ outb(waport, phys>>8);
+ outb(dmapageport[chan], phys>>16);
+
+ /* send count */
+ outb(waport + 1, --nbytes);
+ outb(waport + 1, nbytes>>8);
+
+ /* unmask channel */
+ outb(DMA1_SMSK, chan);
+ } else {
+ /*
+ * Program one of DMA channels 4..7. These are
+ * word mode channels.
+ */
+ /* set dma channel mode, and reset address ff */
+
+ /* If B_RAW flag is set, then use autoinitialise mode */
+ if (flags & B_RAW) {
+ if (flags & B_READ)
+ outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3));
+ else
+ outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3));
+ }
+ else
+ if (flags & B_READ)
+ outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
+ else
+ outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
+ outb(DMA2_FFC, 0);
+
+ /* send start address */
+ waport = DMA2_CHN(chan - 4);
+ outb(waport, phys>>1);
+ outb(waport, phys>>9);
+ outb(dmapageport[chan], phys>>16);
+
+ /* send count */
+ nbytes >>= 1;
+ outb(waport + 2, --nbytes);
+ outb(waport + 2, nbytes>>8);
+
+ /* unmask channel */
+ outb(DMA2_SMSK, chan & 3);
+ }
+}
+
+void
+isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
+{
+ struct isa_dmastart_arg args;
+
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dmastart: channel out of range");
+
+ if ((chan < 4 && nbytes > (1<<16))
+ || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1)))
+ panic("isa_dmastart: impossible request");
+
+ if ((dma_inuse & (1 << chan)) == 0)
+ printf("isa_dmastart: channel %d not acquired\n", chan);
+#endif
+
+#if 0
+ /*
+ * XXX This should be checked, but drivers like ad1848 only call
+ * isa_dmastart() once because they use Auto DMA mode. If we
+ * leave this in, drivers that do this will print this continuously.
+ */
+ if (dma_busy & (1 << chan))
+ printf("isa_dmastart: channel %d busy\n", chan);
+#endif
+
+ if (!dma_tag || !dma_map[chan])
+ panic("isa_dmastart: called without isa_dmainit");
+
+ dma_busy |= (1 << chan);
+
+ if (flags & B_RAW) {
+ dma_auto_mode |= (1 << chan);
+ } else {
+ dma_auto_mode &= ~(1 << chan);
+ }
+
+ /*
+ * Freeze dma while updating registers.
+ */
+ outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4);
+
+ args.chan = chan;
+ args.flags = flags;
+ bus_dmamap_load(dma_tag[chan], dma_map[chan], addr, nbytes,
+ isa_dmastart_cb, &args, 0);
+}
+
+void
+isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
+{
+#ifdef DIAGNOSTIC
+ if (chan & ~VALID_DMA_MASK)
+ panic("isa_dmadone: channel out of range");
+
+ if ((dma_inuse & (1 << chan)) == 0)
+ printf("isa_dmadone: channel %d not acquired\n", chan);
+#endif
+
+ if (((dma_busy & (1 << chan)) == 0) &&
+ (dma_auto_mode & (1 << chan)) == 0 )
+ printf("isa_dmadone: channel %d not busy\n", chan);
+
+ if ((dma_auto_mode & (1 << chan)) == 0) {
+ outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4);
+ bus_dmamap_unload(dma_tag[chan], dma_map[chan]);
+ }
+
+ dma_busy &= ~(1 << chan);
+}
+
+/*
+ * Query the progress of a transfer on a DMA channel.
+ *
+ * To avoid having to interrupt a transfer in progress, we sample
+ * each of the high and low databytes twice, and apply the following
+ * logic to determine the correct count.
+ *
+ * Reads are performed with interrupts disabled, thus it is to be
+ * expected that the time between reads is very small. At most
+ * one rollover in the low count byte can be expected within the
+ * four reads that are performed.
+ *
+ * There are three gaps in which a rollover can occur :
+ *
+ * - read low1
+ * gap1
+ * - read high1
+ * gap2
+ * - read low2
+ * gap3
+ * - read high2
+ *
+ * If a rollover occurs in gap1 or gap2, the low2 value will be
+ * greater than the low1 value. In this case, low2 and high2 are a
+ * corresponding pair.
+ *
+ * In any other case, low1 and high1 can be considered to be correct.
+ *
+ * The function returns the number of bytes remaining in the transfer,
+ * or -1 if the channel requested is not active.
+ *
+ */
+int
+isa_dmastatus(int chan)
+{
+ u_long cnt = 0;
+ int ffport, waport;
+ u_long low1, high1, low2, high2;
+ int s;
+
+ /* channel active? */
+ if ((dma_inuse & (1 << chan)) == 0) {
+ printf("isa_dmastatus: channel %d not active\n", chan);
+ return(-1);
+ }
+ /* channel busy? */
+
+ if (((dma_busy & (1 << chan)) == 0) &&
+ (dma_auto_mode & (1 << chan)) == 0 ) {
+ printf("chan %d not busy\n", chan);
+ return -2 ;
+ }
+ if (chan < 4) { /* low DMA controller */
+ ffport = DMA1_FFC;
+ waport = DMA1_CHN(chan) + 1;
+ } else { /* high DMA controller */
+ ffport = DMA2_FFC;
+ waport = DMA2_CHN(chan - 4) + 2;
+ }
+
+ s = splhigh(); /* no interrupts Mr Jones! */
+ outb(ffport, 0); /* clear register LSB flipflop */
+ low1 = inb(waport);
+ high1 = inb(waport);
+ outb(ffport, 0); /* clear again */
+ low2 = inb(waport);
+ high2 = inb(waport);
+ splx(s); /* enable interrupts again */
+
+ /*
+ * Now decide if a wrap has tried to skew our results.
+ * Note that after TC, the count will read 0xffff, while we want
+ * to return zero, so we add and then mask to compensate.
+ */
+ if (low1 >= low2) {
+ cnt = (low1 + (high1 << 8) + 1) & 0xffff;
+ } else {
+ cnt = (low2 + (high2 << 8) + 1) & 0xffff;
+ }
+
+ if (chan >= 4) /* high channels move words */
+ cnt *= 2;
+ return(cnt);
+}
+
+/*
+ * Stop a DMA transfer currently in progress.
+ */
+int
+isa_dmastop(int chan)
+{
+ if ((dma_inuse & (1 << chan)) == 0)
+ printf("isa_dmastop: channel %d not acquired\n", chan);
+
+ if (((dma_busy & (1 << chan)) == 0) &&
+ ((dma_auto_mode & (1 << chan)) == 0)) {
+ printf("chan %d not busy\n", chan);
+ return -2 ;
+ }
+
+ if ((chan & 4) == 0) {
+ outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */);
+ } else {
+ outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */);
+ }
+ return(isa_dmastatus(chan));
+}
diff --git a/sys/alpha/pci/cia.c b/sys/alpha/pci/cia.c
index aaa78b9..ce5fae0 100644
--- a/sys/alpha/pci/cia.c
+++ b/sys/alpha/pci/cia.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cia.c,v 1.17 1999/05/08 21:58:41 dfr Exp $
+ * $Id: cia.c,v 1.18 1999/05/20 15:33:21 gallatin Exp $
*/
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -95,6 +95,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/malloc.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
@@ -109,6 +110,11 @@
#include <machine/cpuconf.h>
#include <machine/rpb.h>
#include <machine/resource.h>
+#include <machine/sgmap.h>
+
+#include <vm/vm.h>
+#include <vm/vm_prot.h>
+#include <vm/vm_page.h>
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
@@ -673,6 +679,142 @@ static driver_t cia_driver = {
sizeof(struct cia_softc),
};
+#define CIA_SGMAP_BASE (8*1024*1024)
+#define CIA_SGMAP_SIZE (8*1024*1024)
+#define CIA_PYXIS_BUG_BASE (128*1024*1024)
+#define CIA_PYXIS_BUG_SIZE (2*1024*1024)
+
+static void
+cia_sgmap_invalidate(void)
+{
+ REGVAL(CIA_PCI_TBIA) = CIA_PCI_TBIA_ALL;
+ alpha_mb();
+}
+
+static void
+cia_sgmap_invalidate_pyxis(void)
+{
+ volatile u_int64_t dummy;
+ u_int32_t ctrl;
+ int i, s;
+
+ s = splhigh();
+
+ /*
+ * Put the Pyxis into PCI loopback mode.
+ */
+ alpha_mb();
+ ctrl = REGVAL(CIA_CSR_CTRL);
+ REGVAL(CIA_CSR_CTRL) = ctrl | CTRL_PCI_LOOP_EN;
+ alpha_mb();
+
+ /*
+ * Now, read from PCI dense memory space at offset 128M (our
+ * target window base), skipping 64k on each read. This forces
+ * S/G TLB misses.
+ *
+ * XXX Looks like the TLB entries are `not quite LRU'. We need
+ * XXX to read more times than there are actual tags!
+ */
+ for (i = 0; i < CIA_TLB_NTAGS + 4; i++) {
+ dummy = *((volatile u_int64_t *)
+ ALPHA_PHYS_TO_K0SEG(CIA_PCI_DENSE + CIA_PYXIS_BUG_BASE +
+ (i * 65536)));
+ }
+
+ /*
+ * Restore normal PCI operation.
+ */
+ alpha_mb();
+ REGVAL(CIA_CSR_CTRL) = ctrl;
+ alpha_mb();
+
+ splx(s);
+}
+
+static void
+cia_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
+{
+ u_int64_t *sgtable = arg;
+ int index = alpha_btop(ba - CIA_SGMAP_BASE);
+
+ if (pa) {
+ if (pa > (1L<<32))
+ panic("cia_sgmap_map: can't map address 0x%lx", pa);
+ sgtable[index] = ((pa >> 13) << 1) | 1;
+ } else {
+ sgtable[index] = 0;
+ }
+ alpha_mb();
+
+ if (cia_ispyxis)
+ cia_sgmap_invalidate_pyxis();
+ else
+ cia_sgmap_invalidate();
+}
+
+static void
+cia_init_sgmap(void)
+{
+ void *sgtable;
+
+ /*
+ * First setup Window 0 to map 8Mb to 16Mb with an
+ * sgmap. Allocate the map aligned to a 32 boundary.
+ */
+ REGVAL(CIA_PCI_W0BASE) = (CIA_SGMAP_BASE
+ | CIA_PCI_WnBASE_SG_EN
+ | CIA_PCI_WnBASE_W_EN);
+ alpha_mb();
+
+ REGVAL(CIA_PCI_W0MASK) = CIA_PCI_WnMASK_8M;
+ alpha_mb();
+
+ sgtable = contigmalloc(8192, M_DEVBUF, M_NOWAIT,
+ 0, (1L<<34),
+ 32*1024, (1L<<34));
+ if (!sgtable)
+ panic("cia_init_sgmap: can't allocate page table");
+ REGVAL(CIA_PCI_T0BASE) =
+ (pmap_kextract((vm_offset_t) sgtable) >> CIA_PCI_TnBASE_SHIFT);
+
+ chipset.sgmap = sgmap_map_create(CIA_SGMAP_BASE,
+ CIA_SGMAP_BASE + CIA_SGMAP_SIZE,
+ cia_sgmap_map, sgtable);
+
+ if (cia_ispyxis) {
+ /*
+ * Pyxis has broken TLB invalidate. We use the NetBSD
+ * workaround of using another region to spill entries
+ * out of the TLB. The 'bug' region is 2Mb mapped at
+ * 128Mb.
+ */
+ int i;
+ vm_offset_t pa;
+ u_int64_t *bugtable;
+
+ REGVAL(CIA_PCI_W2BASE) = CIA_PYXIS_BUG_BASE |
+ CIA_PCI_WnBASE_SG_EN | CIA_PCI_WnBASE_W_EN;
+ alpha_mb();
+
+ REGVAL(CIA_PCI_W2MASK) = CIA_PCI_WnMASK_2M;
+ alpha_mb();
+
+ bugtable = contigmalloc(8192, M_DEVBUF, M_NOWAIT,
+ 0, (1L<<34),
+ 2*1024, (1L<<34));
+ if (!bugtable)
+ panic("cia_init_sgmap: can't allocate page table");
+ REGVAL(CIA_PCI_T2BASE) =
+ (pmap_kextract((vm_offset_t) bugtable)
+ >> CIA_PCI_TnBASE_SHIFT);
+
+ pa = sgmap_overflow_page();
+ for (i = 0; i < alpha_btop(CIA_PYXIS_BUG_SIZE); i++)
+ bugtable[i] = ((pa >> 13) << 1) | 1;
+ }
+}
+
void
cia_init()
{
@@ -730,6 +872,7 @@ cia_probe(device_t dev)
pci_init_resources();
isa_init_intr();
+ cia_init_sgmap();
device_add_child(dev, "pcib", 0, 0);
diff --git a/sys/conf/files.alpha b/sys/conf/files.alpha
index b589354..6b3f3e8 100644
--- a/sys/conf/files.alpha
+++ b/sys/conf/files.alpha
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.alpha,v 1.18 1999/04/16 21:21:34 peter Exp $
+# $Id: files.alpha,v 1.19 1999/05/26 23:22:13 gallatin Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -35,6 +35,7 @@ alpha/alpha/mountroot.c optional slice
alpha/alpha/ipl_funcs.c standard
alpha/alpha/pal.s standard
alpha/alpha/busdma_machdep.c standard
+alpha/alpha/sgmap.c standard
alpha/alpha/cons.c standard
alpha/alpha/prom.c standard
alpha/alpha/promcons.c standard
@@ -124,6 +125,7 @@ alpha/pci/tsunami.c optional tsunami
alpha/pci/tsunami_pci.c optional tsunami
alpha/pci/pcibus.c optional pci
alpha/isa/isa.c optional isa
+alpha/isa/isa_dma.c optional isa
alpha/isa/mcclock_isa.c optional isa
alpha/alpha/elf_machdep.c standard
libkern/bcd.c standard
@@ -163,6 +165,7 @@ dev/syscons/syscons.c optional sc device-driver
dev/syscons/scvidctl.c optional sc device-driver
isa/syscons_isa.c optional sc device-driver
isa/psm.c optional psm device-driver
+isa/fd.c optional fd device-driver
dev/ata/ata-all.c optional ata device-driver
dev/ata/ata-dma.c optional ata device-driver
dev/ata/atapi-all.c optional ata device-driver
OpenPOWER on IntegriCloud