* Implement ISA dma (only for CIA now but more chipsets to follow).
* Port the fd driver to alpha.
This commit is contained in:
parent
7389b9fd55
commit
37b094f876
@ -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;
|
||||
|
196
sys/alpha/alpha/sgmap.c
Normal file
196
sys/alpha/alpha/sgmap.c
Normal file
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
126
sys/alpha/include/ioctl_fd.h
Normal file
126
sys/alpha/include/ioctl_fd.h
Normal file
@ -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_ */
|
49
sys/alpha/include/sgmap.h
Normal file
49
sys/alpha/include/sgmap.h
Normal file
@ -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_ */
|
@ -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;
|
||||
|
487
sys/alpha/isa/isa_dma.c
Normal file
487
sys/alpha/isa/isa_dma.c
Normal file
@ -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));
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user