Add driver for ELBOX FastATA 1200 Mk-III/Mk-IV (and the man page).

This commit is contained in:
rkujawa 2011-10-27 22:12:23 +00:00
parent d2b3be01af
commit 25abb1786a
8 changed files with 828 additions and 6 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1350 2011/10/18 10:19:11 wiz Exp $
# $NetBSD: mi,v 1.1351 2011/10/27 22:12:24 rkujawa Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -728,6 +728,7 @@
./usr/share/man/cat4/amiga/bppcsc.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/console.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/ed.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/efa.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/es.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/fdc.0 man-sys-catman .cat
./usr/share/man/cat4/amiga/grf.0 man-sys-catman .cat
@ -3604,6 +3605,7 @@
./usr/share/man/html4/amiga/bppcsc.html man-sys-htmlman html
./usr/share/man/html4/amiga/console.html man-sys-htmlman html
./usr/share/man/html4/amiga/ed.html man-sys-htmlman html
./usr/share/man/html4/amiga/efa.html man-sys-htmlman html
./usr/share/man/html4/amiga/es.html man-sys-htmlman html
./usr/share/man/html4/amiga/fdc.html man-sys-htmlman html
./usr/share/man/html4/amiga/grf.html man-sys-htmlman html
@ -6177,6 +6179,7 @@
./usr/share/man/man4/amiga/bppcsc.4 man-sys-man .man
./usr/share/man/man4/amiga/console.4 man-sys-man .man
./usr/share/man/man4/amiga/ed.4 man-sys-man .man
./usr/share/man/man4/amiga/efa.4 man-sys-man .man
./usr/share/man/man4/amiga/es.4 man-sys-man .man
./usr/share/man/man4/amiga/fdc.4 man-sys-man .man
./usr/share/man/man4/amiga/grf.4 man-sys-man .man

View File

@ -1,8 +1,8 @@
# from: @(#)Makefile 8.2 (Berkeley) 2/16/94
# $NetBSD: Makefile,v 1.20 2011/09/17 17:04:22 rkujawa Exp $
# $NetBSD: Makefile,v 1.21 2011/10/27 22:12:24 rkujawa Exp $
MAN= afsc.4 ahsc.4 amidisplaycc.4 atzsc.4 autoconf.4 console.4 bah.4 \
bppcsc.4 ed.4 es.4 fdc.4 grf.4 \
bppcsc.4 ed.4 efa.4 es.4 fdc.4 grf.4 \
grfcl.4 grfcv.4 grfcv3d.4 grfet.4 grfrh.4 grfrt.4 grful.4 \
gtsc.4 intro.4 ite.4 mem.4 mfcs.4 mgnsc.4 mppb.4 p5pb.4 \
qn.4 ser.4 wesc.4 zssc.4

View File

@ -0,0 +1,110 @@
.\" $NetBSD: efa.4,v 1.1 2011/10/27 22:12:24 rkujawa Exp $
.\"
.\" Copyright (c) 2011 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Radoslaw Kujawa.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd October 25, 2011
.Dt EFA 4 amiga
.Os
.Sh NAME
.Nm efa
.Nd ELBOX FastATA 1200 IDE disk controller driver
.Sh SYNOPSIS
.Cd "efa0 at mainbus0"
.\".Cd "options EFA_32BIT_IO"
.\".Cd "options EFA_NO_INTR"
.Sh DESCRIPTION
The
.Nm
driver provides support for the FastATA 1200 family of IDE controllers and
provides the interface with the hardware for the
.Xr ata 4
driver. PIO modes 0, 3, 4 and 5 are supported.
.\".Pp
.\"The following kernel configuration options are available:
.\".Bl -ohang
.\".It Cd options EFA_32BIT_IO
.\"Use 32-bit data port.
.\".It Cd options EFA_GAYLE_COMPAT
.\"Drive FastATA in Gayle IDE compatibility mode. Use if the driver does not
.\"work correctly in native (default) mode. Limits operation to PIO0 mode.
.\".El
.Sh HARDWARE
The
.Nm
driver supports the following hardware:
.Bl -tag -width "ELBOX FastATA 1200 Mk-IV" -offset indent
.It Em ELBOX FastATA 1200 Mk-III
.It Em ELBOX FastATA 1200 Mk-IV
.El
.Sh SEE ALSO
.Xr ata 4 ,
.Xr wdc 4
.Sh HISTORY
The
.Nm
device first appeared in
.Nx 6.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Radoslaw Kujawa Aq radoslaw.kujawa@gmail.com .
.Sh CAVEATS
Older versions of FastATA 1200 are NOT supported:
.Bl -tag -width "ELBOX FastATA 1200 Mk-II" -offset indent
.It Em ELBOX FastATA 1200 Mk-I
.It Em ELBOX FastATA 1200 Lite
.It Em ELBOX FastATA 1200 GOLD
.It Em ELBOX FastATA 1200 Mk-II
.El
.Pp
These devices do not generate hardware interrupts and need to be driven in
non-standard polling mode. Code needed to support it is present in driver
but does not work correctly.
.Pp
Some of the above devices were also marketed under PowerFlyer and Winner brands.
.Pp
The
.Nm
driver can not coexist with
.Xr wdc 4
driver attached to
.Xr mainbus 4 ,
because FastATA 1200 hardware uses portions of the on-board Gayle IDE
controller. These
drivers should not be enabled in the same kernel.
.Pp
DMA modes are not supported, this is a hardware limitation.
.Sh BUGS
Performance is worse than with official AmigaOS driver from ELBOX.
.Pp
Disks paritioned in split mode, which is specific to official AmigaOS FastATA
driver, are not recognized in NetBSD.
.Pp
Improved probe procedure should be written.

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC.in,v 1.84 2011/09/19 19:15:29 rkujawa Exp $
# $NetBSD: GENERIC.in,v 1.85 2011/10/27 22:12:23 rkujawa Exp $
#
##
# GENERIC machine description file
@ -57,7 +57,7 @@ include "arch/amiga/conf/std.amiga"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.84 $"
#ident "GENERIC-$Revision: 1.85 $"
m4_ifdef(`INSTALL_CONFIGURATION', `m4_dnl
makeoptions COPTS="-Os"
@ -528,8 +528,10 @@ scsibus* at empsc0
wdc0 at mainbus0 # A4000 & A1200 IDE bus
wdc* at zbus0 # Buddha / Catweasel
#efa0 at mainbus0 # ELBOX FastATA 1200 Mk-III/Mk-IV
atabus* at wdc? channel ? # ATA bus
#atabus* at efa? channel ? # ATA bus
wd* at atabus? drive ? # + drives
atapibus* at atabus? # ATAPI bus
cd* at atapibus? drive ? # ATAPI CD-ROM drives

View File

@ -1,4 +1,4 @@
# $NetBSD: files.amiga,v 1.148 2011/09/19 19:15:29 rkujawa Exp $
# $NetBSD: files.amiga,v 1.149 2011/10/27 22:12:23 rkujawa Exp $
# maxpartitions must be first item in files.${ARCH}.newconf
maxpartitions 16 # NOTE THAT AMIGA IS SPECIAL!
@ -470,6 +470,11 @@ file arch/amiga/dev/wdc_amiga.c wdc_amiga
attach wdc at zbus with wdc_buddha
file arch/amiga/dev/wdc_buddha.c wdc_buddha
# FastATA
device efa: ata,wdc_common
attach efa at mainbus
file arch/amiga/dev/efa.c efa
# Compatibility modules
# NetBSD m68k a.out Binary Compatibility (COMPAT_AOUT_M68K)

558
sys/arch/amiga/dev/efa.c Normal file
View File

@ -0,0 +1,558 @@
/* $NetBSD: efa.c,v 1.1 2011/10/27 22:12:23 rkujawa Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Radoslaw Kujawa.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Driver for FastATA 1200 EIDE controller, manufactured by ELBOX Computer.
*
* Gayle-related stuff inspired by wdc_amiga.c written by Michael L. Hitch
* and Aymeric Vincent.
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <sys/bswap.h>
#include <amiga/amiga/cia.h>
#include <amiga/amiga/custom.h>
#include <amiga/amiga/device.h>
#include <amiga/amiga/gayle.h>
#include <amiga/dev/zbusvar.h>
#include <dev/ata/atavar.h>
#include <dev/ic/wdcvar.h>
#include <amiga/dev/efareg.h>
#include <amiga/dev/efavar.h>
/* #define EFA_32BIT_IO 1 */
/* #define EFA_NO_INTR 1 */
/* #define EFA_DEBUG 1 */
int efa_probe(device_t, cfdata_t, void *);
void efa_attach(device_t, device_t, void *);
int efa_intr(void *);
int efa_intr_soft(void *arg);
static void efa_set_opts(struct efa_softc *sc);
static bool efa_mapbase(struct efa_softc *sc);
static bool efa_mapreg_gayle(struct efa_softc *sc);
static bool efa_mapreg_native(struct efa_softc *sc);
static void efa_fata_subregion_pio0(struct wdc_regs *wdr_fata);
static void efa_fata_subregion_pion(struct wdc_regs *wdr_fata, bool data32);
static void efa_setup_channel(struct ata_channel *chp);
static void efa_attach_channel(struct efa_softc *sc, int i);
static void efa_select_regset(struct efa_softc *sc, int chnum,
uint8_t piomode);
static void efa_poll_kthread(void *arg);
#ifdef EFA_DEBUG
static void efa_debug_print_regmapping(struct wdc_regs *wdr_fata);
#endif /* EFA_DEBUG */
CFATTACH_DECL_NEW(efa, sizeof(struct efa_softc),
efa_probe, efa_attach, NULL, NULL);
#define PIO_NSUPP 0xFFFFFFFF
static const bus_addr_t pio_offsets[] =
{ FATA1_PIO0_OFF, PIO_NSUPP, PIO_NSUPP, FATA1_PIO3_OFF, FATA1_PIO4_OFF,
FATA1_PIO5_OFF };
static const unsigned int wdr_offsets_pio0[] =
{ FATA1_PIO0_OFF_DATA, FATA1_PIO0_OFF_ERROR, FATA1_PIO0_OFF_SECCNT,
FATA1_PIO0_OFF_SECTOR, FATA1_PIO0_OFF_CYL_LO, FATA1_PIO0_OFF_CYL_HI,
FATA1_PIO0_OFF_SDH, FATA1_PIO0_OFF_COMMAND };
static const unsigned int wdr_offsets_pion[] =
{ FATA1_PION_OFF_DATA, FATA1_PION_OFF_ERROR, FATA1_PION_OFF_SECCNT,
FATA1_PION_OFF_SECTOR, FATA1_PION_OFF_CYL_LO, FATA1_PION_OFF_CYL_HI,
FATA1_PION_OFF_SDH, FATA1_PION_OFF_COMMAND };
static const unsigned int wdr_offsets_pion32[] =
{ FATA1_PION_OFF_DATA32, FATA1_PION_OFF_ERROR, FATA1_PION_OFF_SECCNT,
FATA1_PION_OFF_SECTOR, FATA1_PION_OFF_CYL_LO, FATA1_PION_OFF_CYL_HI,
FATA1_PION_OFF_SDH, FATA1_PION_OFF_COMMAND };
int
efa_probe(device_t parent, cfdata_t cfp, void *aux)
{
/* FastATA 1200 uses portions of Gayle IDE interface, and efa driver
* can't coexist with wdc_amiga. Match "wdc" on an A1200, because
* FastATA 1200 does not autoconfigure. */
if( !matchname(aux, "wdc") || !is_a1200() )
return(0);
return 100;
}
void
efa_attach(device_t parent, device_t self, void *aux)
{
int i;
struct efa_softc *sc = device_private(self);
aprint_normal(": ELBOX FastATA 1200\n");
gayle_init();
sc->sc_dev = self;
efa_set_opts(sc);
if(!efa_mapbase(sc)) {
aprint_error_dev(self, "couldn't map base addresses\n");
return;
}
if(!efa_mapreg_gayle(sc)) {
aprint_error_dev(self, "couldn't map Gayle registers\n");
return;
}
if(!efa_mapreg_native(sc)) {
aprint_error_dev(self, "couldn't map FastATA regsters\n");
return;
}
sc->sc_wdcdev.sc_atac.atac_pio_cap = 5;
sc->sc_wdcdev.sc_atac.atac_nchannels = FATA1_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_set_modes = efa_setup_channel;
sc->sc_wdcdev.sc_atac.atac_dev = self;
sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_chanlist;
if(sc->sc_32bit_io)
sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA32;
else
sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16;
/*
* The following should work for polling mode, but it does not.
* if(sc->sc_no_intr)
* sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_NOIRQ;
*/
wdc_allocate_regs(&sc->sc_wdcdev);
sc->sc_intreg = &gayle.intreq;
for(i = 0; i < FATA1_CHANNELS; i++) {
efa_attach_channel(sc, i);
}
if(sc->sc_no_intr) {
sc->sc_fata_softintr = softint_establish(SOFTINT_BIO,
(void (*)(void *))efa_intr_soft, sc);
if (sc->sc_fata_softintr == NULL) {
aprint_error_dev(self, "couldn't create soft intr\n");
return;
}
if (kthread_create(PRI_NONE, 0, NULL, efa_poll_kthread, sc,
NULL, "efa")) {
aprint_error_dev(self, "couldn't create kthread\n");
return;
}
} else {
sc->sc_isr.isr_intr = efa_intr;
sc->sc_isr.isr_arg = sc;
sc->sc_isr.isr_ipl = 2;
add_isr (&sc->sc_isr);
gayle.intena |= GAYLE_INT_IDE;
}
}
static void
efa_attach_channel(struct efa_softc *sc, int chnum)
{
sc->sc_chanlist[chnum] = &sc->sc_ports[chnum].chan;
sc->sc_ports[chnum].chan.ch_channel = chnum;
sc->sc_ports[chnum].chan.ch_atac = &sc->sc_wdcdev.sc_atac;
sc->sc_ports[chnum].chan.ch_queue = &sc->sc_ports[chnum].queue;
sc->sc_ports[chnum].chan.ch_ndrive = 2;
if(!sc->sc_32bit_io)
efa_select_regset(sc, chnum, 0); /* Start in PIO0. */
else
efa_select_regset(sc, chnum, 3);
wdc_init_shadow_regs(&sc->sc_ports[chnum].chan);
wdcattach(&sc->sc_ports[chnum].chan);
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev, "done init for channel %d\n", chnum);
#endif
}
/* TODO: convert to callout(9) */
static void
efa_poll_kthread(void *arg)
{
struct efa_softc *sc = arg;
for(;;) {
/* TODO: actually check if interrupt status register is set */
softint_schedule(sc->sc_fata_softintr);
/* TODO: convert to kpause */
tsleep(arg, PWAIT, "efa_poll", hz);
}
}
static void
efa_set_opts(struct efa_softc *sc)
{
#ifdef EFA_32BIT_IO
sc->sc_32bit_io = true; /* XXX: bus_space_read_multi_stream_4 */
#else
sc->sc_32bit_io = false;
#endif /* EFA_32BIT_IO */
#ifdef EFA_NO_INTR
sc->sc_no_intr = true; /* XXX: not yet! */
#else
sc->sc_no_intr = false;
#endif /* EFA_NO_INTR */
if(sc->sc_no_intr)
aprint_verbose_dev(sc->sc_dev, "hardware interrupt disabled\n");
if(sc->sc_32bit_io)
aprint_verbose_dev(sc->sc_dev, "32-bit I/O enabled\n");
}
int
efa_intr_soft(void *arg)
{
int ret = 0;
struct efa_softc *sc = (struct efa_softc *)arg;
/* TODO: check which channel needs servicing */
/*
uint8_t fataintreq;
fataintreq = bus_space_read_1(sc->sc_ports[0].wdr[piom].cmd_iot,
sc->sc_ports[chnum].intst[piom], 0);
*/
ret = wdcintr(&sc->sc_ports[0].chan);
ret = wdcintr(&sc->sc_ports[1].chan);
return ret;
}
int
efa_intr(void *arg)
{
struct efa_softc *sc = (struct efa_softc *)arg;
int r1, r2;
u_char intreq = *sc->sc_intreg;
int ret = 0;
if (intreq & GAYLE_INT_IDE) {
gayle.intreq = 0x7c | (intreq & 0x03);
/* How to check which channel caused interrupt?
* Interrupt status register is not very useful here. */
r1 = wdcintr(&sc->sc_ports[0].chan);
r2 = wdcintr(&sc->sc_ports[1].chan);
ret = r1 | r2;
}
return ret;
}
static bool
efa_mapbase(struct efa_softc *sc)
{
int i, j;
static struct bus_space_tag fata_cmd_iot;
static struct bus_space_tag gayle_cmd_iot;
gayle_cmd_iot.base = (bus_addr_t) ztwomap(GAYLE_IDE_BASE + 2);
gayle_cmd_iot.absm = &amiga_bus_stride_4swap;
fata_cmd_iot.base = (bus_addr_t) ztwomap(FATA1_BASE);
fata_cmd_iot.absm = &amiga_bus_stride_4swap;
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev, "Gayle %x -> %x, FastATA %x -> %x\n",
GAYLE_IDE_BASE, gayle_cmd_iot.base, FATA1_BASE, fata_cmd_iot.base);
#endif
if(!gayle_cmd_iot.base)
return false;
if(!fata_cmd_iot.base)
return false;
sc->sc_gayle_wdc_regs.cmd_iot = &gayle_cmd_iot;
sc->sc_gayle_wdc_regs.ctl_iot = &gayle_cmd_iot;
for(i = 0; i < FATA1_CHANNELS; i++) {
for(j = 0; j < PIO_COUNT; j++) {
sc->sc_ports[i].wdr[j].cmd_iot = &fata_cmd_iot;
sc->sc_ports[i].wdr[j].ctl_iot = &gayle_cmd_iot;
}
}
return true;
}
/* Gayle IDE register mapping, we need it anyway. */
static bool
efa_mapreg_gayle(struct efa_softc *sc)
{
int i;
struct wdc_regs *wdr = &sc->sc_gayle_wdc_regs;
if (bus_space_map(wdr->cmd_iot, 0, 0x40, 0,
&wdr->cmd_baseioh)) {
return false;
}
for (i = 0; i < WDC_NREG; i++) {
if (bus_space_subregion(wdr->cmd_iot,
wdr->cmd_baseioh, i, i == 0 ? 4 : 1,
&wdr->cmd_iohs[i]) != 0) {
bus_space_unmap(wdr->cmd_iot,
wdr->cmd_baseioh, 0x40);
return false;
}
}
if (bus_space_subregion(wdr->cmd_iot,
wdr->cmd_baseioh, 0x406, 1, &wdr->ctl_ioh))
return false;
return true;
}
/* Native FastATA register mapping, suitable for PIO modes 0 to 5. */
static bool
efa_mapreg_native(struct efa_softc *sc) {
int i,j;
struct wdc_regs *wdr_gayle = &sc->sc_gayle_wdc_regs;
struct wdc_regs *wdr_fata;
for(i = 0; i < FATA1_CHANNELS; i++) {
for(j = 0; j < PIO_COUNT; j++) {
wdr_fata = &sc->sc_ports[i].wdr[j];
sc->sc_ports[i].mode_ok[j] = false;
if(pio_offsets[j] == PIO_NSUPP) {
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev,
"Skipping mapping for PIO mode %x\n", j);
#endif
continue;
}
if(bus_space_map(wdr_fata->cmd_iot,
pio_offsets[j] + FATA1_CHAN_SIZE * i,
FATA1_CHAN_SIZE, 0, &wdr_fata->cmd_baseioh)) {
return false;
}
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev,
"Chan %x PIO mode %x mapped %x -> %x\n",
i, j, (bus_addr_t) kvtop((void*)
wdr_fata->cmd_baseioh), (unsigned int)
wdr_fata->cmd_baseioh);
#endif
sc->sc_ports[i].mode_ok[j] = true;
if(j == 0)
efa_fata_subregion_pio0(wdr_fata);
else {
if(sc->sc_32bit_io)
efa_fata_subregion_pion(wdr_fata,
true);
else
efa_fata_subregion_pion(wdr_fata,
false);
bus_space_subregion(wdr_fata->cmd_iot,
wdr_fata->cmd_baseioh, FATA1_PION_OFF_INTST,
1, &sc->sc_ports[i].intst[j]);
}
/* No 32-bit register for PIO0 ... */
if(j == 0 && sc->sc_32bit_io)
sc->sc_ports[i].mode_ok[j] = false;
wdr_fata->ctl_ioh = wdr_gayle->ctl_ioh;
};
}
return true;
}
static void
efa_fata_subregion_pio0(struct wdc_regs *wdr_fata)
{
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_DATA, 4, &wdr_fata->cmd_iohs[wd_data]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_ERROR, 1, &wdr_fata->cmd_iohs[wd_error]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_SECCNT, 1, &wdr_fata->cmd_iohs[wd_seccnt]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_SECTOR, 1, &wdr_fata->cmd_iohs[wd_sector]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_CYL_LO, 1, &wdr_fata->cmd_iohs[wd_cyl_lo]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_CYL_HI, 1, &wdr_fata->cmd_iohs[wd_cyl_hi]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_SDH, 1, &wdr_fata->cmd_iohs[wd_sdh]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PIO0_OFF_COMMAND, 1, &wdr_fata->cmd_iohs[wd_command]);
}
static void
efa_fata_subregion_pion(struct wdc_regs *wdr_fata, bool data32)
{
if(data32)
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_DATA32, 8, &wdr_fata->cmd_iohs[wd_data]);
else
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_DATA, 4, &wdr_fata->cmd_iohs[wd_data]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_ERROR, 1, &wdr_fata->cmd_iohs[wd_error]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_SECCNT, 1, &wdr_fata->cmd_iohs[wd_seccnt]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_SECTOR, 1, &wdr_fata->cmd_iohs[wd_sector]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_CYL_LO, 1, &wdr_fata->cmd_iohs[wd_cyl_lo]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_CYL_HI, 1, &wdr_fata->cmd_iohs[wd_cyl_hi]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_SDH, 1, &wdr_fata->cmd_iohs[wd_sdh]);
bus_space_subregion(wdr_fata->cmd_iot, wdr_fata->cmd_baseioh,
FATA1_PION_OFF_COMMAND, 1, &wdr_fata->cmd_iohs[wd_command]);
}
static void
efa_setup_channel(struct ata_channel *chp)
{
int drive, chnum;
uint8_t mode;
struct atac_softc *atac;
struct ata_drive_datas *drvp;
struct efa_softc *sc;
int ipl;
chnum = chp->ch_channel;
atac = chp->ch_atac;
sc = device_private(atac->atac_dev);
mode = 5; /* start with fastest possible setting */
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev, "efa_setup_channel for ch %d\n",
chnum);
#endif /* EFA_DEBUG */
/* We might be in the middle of something... so raise IPL. */
ipl = splvm();
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
if ((drvp->drive_flags & DRIVE) == 0)
continue; /* nothing to see here */
if(drvp->PIO_cap < mode);
mode = drvp->PIO_cap;
/* TODO: check if sc_ports->mode_ok */
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev, "drive %d supports %d\n",
drive, drvp->PIO_cap);
#endif /* EFA_DEBUG */
drvp->PIO_mode = mode;
}
/* Change FastATA register set. */
efa_select_regset(sc, chnum, mode);
/* re-init shadow regs */
wdc_init_shadow_regs(&sc->sc_ports[chnum].chan);
splx(ipl);
}
static void
efa_select_regset(struct efa_softc *sc, int chnum, uint8_t piomode)
{
struct wdc_softc *wdc;
wdc = CHAN_TO_WDC(&sc->sc_ports[chnum].chan);
wdc->regs[chnum] = sc->sc_ports[chnum].wdr[piomode];
#ifdef EFA_DEBUG
aprint_normal_dev(sc->sc_dev, "switched ch %d to PIO %d\n",
chnum, piomode);
efa_debug_print_regmapping(&wdc->regs[chnum]);
#endif /* EFA_DEBUG */
}
#ifdef EFA_DEBUG
static void
efa_debug_print_regmapping(struct wdc_regs *wdr_fata)
{
int i;
aprint_normal("base %x->%x",
(bus_addr_t) kvtop((void*) wdr_fata->cmd_baseioh),
(bus_addr_t) wdr_fata->cmd_baseioh);
for (i = 0; i < WDC_NREG; i++) {
aprint_normal("reg %x, %x->%x, ", i,
(bus_addr_t) kvtop((void*) wdr_fata->cmd_iohs[i]),
(bus_addr_t) wdr_fata->cmd_iohs[i]);
}
aprint_normal("\n");
}
#endif /* EFA_DEBUG */

View File

@ -0,0 +1,74 @@
/* $NetBSD: efareg.h,v 1.1 2011/10/27 22:12:23 rkujawa Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Radoslaw Kujawa.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _AMIGA_EFAREG_H_
#define GAYLE_IDE_BASE 0xDA0000
#define FATA1_BASE 0xDA2000
/* Offsets. Stride of 4 is used, so multiply any offset by 4. */
#define FATA1_PIO0_OFF 0x0 // XXX 0
#define FATA1_PIO3_OFF 0x4000
#define FATA1_PIO4_OFF 0x5000
#define FATA1_PIO5_OFF 0x4800
#define FATA1_CHAN_SIZE 0x400
#define FATA1_REGS_SIZE 0x4BC0
/* PIO0 */
#define FATA1_PIO0_OFF_DATA 0x0
#define FATA1_PIO0_OFF_ERROR 0x1
#define FATA1_PIO0_OFF_SECCNT 0x2
#define FATA1_PIO0_OFF_SECTOR 0x3
#define FATA1_PIO0_OFF_CYL_LO 0x4
#define FATA1_PIO0_OFF_CYL_HI 0x5
#define FATA1_PIO0_OFF_SDH 0x6
#define FATA1_PIO0_OFF_COMMAND 0x7
/* PIO3-5 */
#define FATA1_PION_OFF_DATA 0x82 /* 16-bit data port */
#define FATA1_PION_OFF_DATA32 0x0 /* 32-bit data port, 2 cycles to HD */
#define FATA1_PION_OFF_ERROR 0x80
#define FATA1_PION_OFF_SECCNT 0x100
#define FATA1_PION_OFF_SECTOR 0x180
#define FATA1_PION_OFF_CYL_LO 0x200
#define FATA1_PION_OFF_CYL_HI 0x280
#define FATA1_PION_OFF_SDH 0x300
#define FATA1_PION_OFF_COMMAND 0x380
#define FATA1_PION_OFF_INTST 0x140 /* FastATA interrupt status */
#define FATA1_INT_ANY 0x80
#define FATA1_INT_DRIVE0 0x40
#define FATA1_INT_DRIVE1 0x20
#endif /* _AMIGA_EFAREG_H_ */

View File

@ -0,0 +1,70 @@
/* $NetBSD: efavar.h,v 1.1 2011/10/27 22:12:23 rkujawa Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Radoslaw Kujawa.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <dev/ata/atavar.h>
#include <dev/ic/wdcvar.h>
#define FATA1_CHANNELS 2
#define PIO_COUNT 6
struct efa_port {
struct ata_channel chan;
struct ata_queue queue;
uint8_t mode; /* currently set mode */
struct wdc_regs wdr[6]; /* PIO0-5 */
bus_space_handle_t intst[6]; /* interrupt status register */
bool mode_ok[6]; /* is this PIO mode usable? */
};
struct efa_softc {
device_t sc_dev;
struct wdc_softc sc_wdcdev;
struct ata_channel *sc_chanlist[FATA1_CHANNELS];
struct efa_port sc_ports[FATA1_CHANNELS];
/* Force 32-bit data port, otherwise always use 16-bit */
bool sc_32bit_io;
/* Disable hw interrupt support (for FastATA 1200 older than Mk-III) */
bool sc_no_intr;
struct isr sc_isr;
volatile u_char *sc_intreg;
void *sc_fata_softintr;
struct wdc_regs sc_gayle_wdc_regs;
};