Merge bouyer-ide
This commit is contained in:
parent
5e62d8161d
commit
19fddaeeb5
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_pioc.c,v 1.6 1998/09/22 00:40:37 mark Exp $ */
|
||||
/* $NetBSD: wdc_pioc.c,v 1.7 1998/10/12 16:09:10 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-1998 Mark Brinicombe.
|
||||
@ -36,12 +36,14 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/irqhandler.h>
|
||||
|
||||
#include <arm32/mainbus/piocvar.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
#include "locators.h"
|
||||
@ -51,8 +53,8 @@
|
||||
#define WDC_PIOC_AUXREG_NPORTS 1
|
||||
|
||||
struct wdc_pioc_softc {
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct channel_softc wdc_channel;
|
||||
void *sc_ih;
|
||||
};
|
||||
|
||||
@ -79,7 +81,7 @@ wdc_pioc_probe(parent, cf, aux)
|
||||
void *aux;
|
||||
{
|
||||
struct pioc_attach_args *pa = aux;
|
||||
struct wdc_attachment_data ad;
|
||||
struct channel_softc ch = { 0 };
|
||||
int res;
|
||||
u_int iobase;
|
||||
|
||||
@ -91,22 +93,22 @@ wdc_pioc_probe(parent, cf, aux)
|
||||
return(0);
|
||||
|
||||
iobase = pa->pa_iobase + pa->pa_offset;
|
||||
memset(&ad, 0, sizeof(ad));
|
||||
ad.iot = pa->pa_iot;
|
||||
ad.auxiot = pa->pa_iot;
|
||||
ch.cmd_iot = pa->pa_iot;
|
||||
ch.ctl_iot = pa->pa_iot;
|
||||
|
||||
if (bus_space_map(ad.iot, iobase, WDC_PIOC_REG_NPORTS, 0, &ad.ioh))
|
||||
if (bus_space_map(ch.cmd_iot, iobase, WDC_PIOC_REG_NPORTS, 0,
|
||||
&ch.cmd_ioh))
|
||||
return(0);
|
||||
if (bus_space_map(ad.auxiot, iobase + WDC_PIOC_AUXREG_OFFSET,
|
||||
WDC_PIOC_AUXREG_NPORTS, 0, &ad.auxioh)) {
|
||||
bus_space_unmap(ad.iot, ad.ioh, WDC_PIOC_REG_NPORTS);
|
||||
if (bus_space_map(ch.ctl_iot, iobase + WDC_PIOC_AUXREG_OFFSET,
|
||||
WDC_PIOC_AUXREG_NPORTS, 0, &ch.ctl_ioh)) {
|
||||
bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, WDC_PIOC_REG_NPORTS);
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = wdcprobe(&ad);
|
||||
res = wdcprobe(&ch);
|
||||
|
||||
bus_space_unmap(ad.auxiot, ad.auxioh, WDC_PIOC_AUXREG_NPORTS);
|
||||
bus_space_unmap(ad.iot, ad.ioh, WDC_PIOC_REG_NPORTS);
|
||||
bus_space_unmap(ch.ctl_iot, ch.ctl_ioh, WDC_PIOC_AUXREG_NPORTS);
|
||||
bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, WDC_PIOC_REG_NPORTS);
|
||||
|
||||
if (res)
|
||||
pa->pa_iosize = WDC_PIOC_REG_NPORTS;
|
||||
@ -131,21 +133,33 @@ wdc_pioc_attach(parent, self, aux)
|
||||
printf("\n");
|
||||
|
||||
iobase = pa->pa_iobase + pa->pa_offset;
|
||||
sc->sc_ad.iot = pa->pa_iot;
|
||||
sc->sc_ad.auxiot = pa->pa_iot;
|
||||
if (bus_space_map(sc->sc_ad.iot, iobase, WDC_PIOC_REG_NPORTS, 0,
|
||||
&sc->sc_ad.ioh))
|
||||
sc->wdc_channel.cmd_iot = pa->pa_iot;
|
||||
sc->wdc_channel.ctl_iot = pa->pa_iot;
|
||||
if (bus_space_map(sc->wdc_channel.cmd_iot, iobase,
|
||||
WDC_PIOC_REG_NPORTS, 0, &sc->wdc_channel.cmd_ioh))
|
||||
panic("%s: couldn't map drive registers\n", self->dv_xname);
|
||||
|
||||
if (bus_space_map(sc->sc_ad.auxiot, iobase + WDC_PIOC_AUXREG_OFFSET,
|
||||
WDC_PIOC_AUXREG_NPORTS, 0, &sc->sc_ad.auxioh))
|
||||
if (bus_space_map(sc->wdc_channel.ctl_iot,
|
||||
iobase + WDC_PIOC_AUXREG_OFFSET, WDC_PIOC_AUXREG_NPORTS, 0,
|
||||
&sc->wdc_channel.ctl_ioh))
|
||||
panic("%s: couldn't map aux registers\n", self->dv_xname);
|
||||
|
||||
sc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "wdc", wdcintr, sc);
|
||||
if (!sc->sc_ih)
|
||||
panic("%s: Cannot claim IRQ %d\n", self->dv_xname, pa->pa_irq);
|
||||
|
||||
wdcattach(&sc->sc_wdcdev, &sc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
wdcattach(&sc->wdc_channel);
|
||||
}
|
||||
|
||||
/* End of wdc_pioc.c */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: icside.c,v 1.8 1998/09/22 00:40:37 mark Exp $ */
|
||||
/* $NetBSD: icside.c,v 1.9 1998/10/12 16:09:11 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-1998 Mark Brinicombe
|
||||
@ -44,6 +44,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/irqhandler.h>
|
||||
#include <machine/io.h>
|
||||
@ -52,6 +53,7 @@
|
||||
#include <arm32/podulebus/podules.h>
|
||||
#include <arm32/podulebus/icsidereg.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
/*
|
||||
@ -69,35 +71,26 @@
|
||||
*/
|
||||
|
||||
struct icside_softc {
|
||||
struct device sc_dev;
|
||||
struct wdc_softc sc_wdcdev; /* common wdc definitions */
|
||||
podule_t *sc_podule; /* Our podule */
|
||||
int sc_podule_number; /* Our podule number */
|
||||
struct bus_space sc_tag; /* custom tag */
|
||||
struct podule_attach_args *sc_pa; /* podule info */
|
||||
struct icside_channel {
|
||||
irqhandler_t ic_ih; /* interrupt handler */
|
||||
bus_space_tag_t ic_irqiot; /* Bus space tag */
|
||||
bus_space_handle_t ic_irqioh; /* handle for IRQ */
|
||||
} *icside_channels;
|
||||
};
|
||||
|
||||
int icside_probe __P((struct device *, struct cfdata *, void *));
|
||||
void icside_attach __P((struct device *, struct device *, void *));
|
||||
int icside_intr __P((void *));
|
||||
|
||||
struct cfattach icside_ca = {
|
||||
sizeof(struct icside_softc), icside_probe, icside_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Attach arguments for child devices.
|
||||
* Pass the podule details, the parent softc and the channel
|
||||
*/
|
||||
|
||||
struct icside_attach_args {
|
||||
struct podule_attach_args *ia_pa; /* podule info */
|
||||
struct icside_softc *ia_softc; /* parent softc */
|
||||
int ia_channel; /* IDE channel */
|
||||
bus_space_tag_t ia_iot; /* bus space tag */
|
||||
bus_space_handle_t ia_ioh; /* IDE drive regs */
|
||||
bus_space_handle_t ia_auxioh; /* Aux status regs */
|
||||
bus_space_handle_t ia_irqioh; /* IRQ regs */
|
||||
u_int ia_irqstatus; /* IRQ status address */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define prototypes for custom bus space functions.
|
||||
*/
|
||||
@ -140,21 +133,6 @@ struct ide_version {
|
||||
}
|
||||
};
|
||||
|
||||
/* Print function used during child config */
|
||||
|
||||
int
|
||||
icside_print(aux, name)
|
||||
void *aux;
|
||||
const char *name;
|
||||
{
|
||||
struct icside_attach_args *ia = aux;
|
||||
|
||||
if (!name)
|
||||
printf(": %s channel", (ia->ia_channel == 0) ? "primary" : "secondary");
|
||||
|
||||
return(QUIET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Card probe function
|
||||
*
|
||||
@ -187,12 +165,13 @@ icside_attach(parent, self, aux)
|
||||
{
|
||||
struct icside_softc *sc = (void *)self;
|
||||
struct podule_attach_args *pa = (void *)aux;
|
||||
struct icside_attach_args ia;
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ioh;
|
||||
irqhandler_t *ihp;
|
||||
struct ide_version *ide = NULL;
|
||||
u_int iobase;
|
||||
int channel;
|
||||
struct channel_softc *cp;
|
||||
int loop;
|
||||
int id;
|
||||
|
||||
@ -251,157 +230,97 @@ icside_attach(parent, self, aux)
|
||||
sc->sc_tag.bs_rm_2 = icside_bs_rm_2;
|
||||
sc->sc_tag.bs_wm_2 = icside_bs_wm_2;
|
||||
|
||||
/* Configure the children */
|
||||
ia.ia_softc = sc;
|
||||
ia.ia_pa = pa;
|
||||
ia.ia_iot = &sc->sc_tag;
|
||||
/* Initialize wdc struct */
|
||||
sc->sc_wdcdev.channels = malloc(
|
||||
sizeof(struct channel_softc) * ide->channels, M_DEVBUF, M_NOWAIT);
|
||||
sc->icside_channels = malloc(
|
||||
sizeof(struct icside_channel) * ide->channels, M_DEVBUF, M_NOWAIT);
|
||||
if (sc->sc_wdcdev.channels == NULL || sc->icside_channels == NULL) {
|
||||
printf("%s: can't allocate channel infos\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
sc->sc_wdcdev.nchannels = ide->channels;
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_pa = pa;
|
||||
|
||||
for (channel = 0; channel < ide->channels; ++channel) {
|
||||
cp = &sc->sc_wdcdev.channels[channel];
|
||||
cp->channel = channel;
|
||||
cp->wdc = &sc->sc_wdcdev;
|
||||
cp->ch_queue = malloc(sizeof(struct channel_queue), M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
if (cp->ch_queue == NULL) {
|
||||
printf("%s %s channel: "
|
||||
"can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname,
|
||||
(channel == 0) ? "primary" : "secondary");
|
||||
continue;
|
||||
}
|
||||
cp->cmd_iot = &sc->sc_tag;
|
||||
cp->ctl_iot = &sc->sc_tag;
|
||||
if (ide->modspace)
|
||||
iobase = pa->pa_podule->mod_base;
|
||||
else
|
||||
iobase = pa->pa_podule->fast_base;
|
||||
ia.ia_channel = channel;
|
||||
|
||||
if (bus_space_map(iot, iobase + ide->ideregs[channel],
|
||||
IDE_REGISTER_SPACE, 0, &ia.ia_ioh))
|
||||
IDE_REGISTER_SPACE, 0, &cp->cmd_ioh))
|
||||
return;
|
||||
if (bus_space_map(iot, iobase + ide->auxregs[channel],
|
||||
AUX_REGISTER_SPACE, 0, &ia.ia_auxioh))
|
||||
AUX_REGISTER_SPACE, 0, &cp->ctl_ioh))
|
||||
return;
|
||||
sc->icside_channels[channel].ic_irqiot = iot;
|
||||
if (bus_space_map(iot, iobase + ide->irqregs[channel],
|
||||
IRQ_REGISTER_SPACE, 0, &ia.ia_irqioh))
|
||||
IRQ_REGISTER_SPACE, 0,
|
||||
&sc->icside_channels[channel].ic_irqioh))
|
||||
return;
|
||||
|
||||
ia.ia_irqstatus = iobase + ide->irqstatregs[channel];
|
||||
config_found_sm(self, &ia, icside_print, NULL);
|
||||
/* Disable interrupts */
|
||||
(void)bus_space_read_1(iot,
|
||||
sc->icside_channels[channel].ic_irqioh, 0);
|
||||
/* Call common attach routines */
|
||||
wdcattach(cp);
|
||||
/* Disable interrupts */
|
||||
(void)bus_space_read_1(iot,
|
||||
sc->icside_channels[channel].ic_irqioh, 0);
|
||||
pa->pa_podule->irq_addr = iobase + ide->irqstatregs[channel];
|
||||
pa->pa_podule->irq_mask = IRQ_STATUS_REGISTER_MASK;
|
||||
ihp = &sc->icside_channels[channel].ic_ih;
|
||||
ihp->ih_func = icside_intr;
|
||||
ihp->ih_arg = cp;
|
||||
ihp->ih_level = IPL_BIO;
|
||||
ihp->ih_name = "icside";
|
||||
ihp->ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
ihp->ih_maskbits = pa->pa_podule->irq_mask;
|
||||
if (irq_claim(pa->pa_podule->interrupt, ihp)) {
|
||||
printf("%s: Cannot claim interrupt %d\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname,
|
||||
pa->pa_podule->interrupt);
|
||||
continue;
|
||||
}
|
||||
/* Enable interrupts */
|
||||
bus_space_write_1(iot, sc->icside_channels[channel].ic_irqioh,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ICS IDE probe and attach code for the wdc device.
|
||||
*
|
||||
* This provides a different pair of probe and attach functions
|
||||
* for attaching the wdc device (mainbus/wd.c) to the ICS IDE card.
|
||||
*/
|
||||
|
||||
struct wdc_ics_softc {
|
||||
struct wdc_softc sc_wdcdev; /* Device node */
|
||||
struct wdc_attachment_data sc_ad; /* Attachment data */
|
||||
irqhandler_t sc_ih; /* interrupt handler */
|
||||
bus_space_tag_t sc_irqiot; /* Bus space tag */
|
||||
bus_space_handle_t sc_irqioh; /* handle for IRQ */
|
||||
};
|
||||
|
||||
int wdc_ics_probe __P((struct device *, struct cfdata *, void *));
|
||||
void wdc_ics_attach __P((struct device *, struct device *, void *));
|
||||
int wdc_ics_intr __P((void *));
|
||||
void wdc_ics_intcontrol __P((void *wdc, int enable));
|
||||
|
||||
struct cfattach wdc_ics_ca = {
|
||||
sizeof(struct wdc_ics_softc), wdc_ics_probe, wdc_ics_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Controller probe function
|
||||
*
|
||||
* Map all the required I/O space for this channel, make sure interrupts
|
||||
* are disabled and probe the bus.
|
||||
*/
|
||||
|
||||
int
|
||||
wdc_ics_probe(parent, cf, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
struct icside_attach_args *ia = aux;
|
||||
struct wdc_attachment_data ad;
|
||||
int result;
|
||||
|
||||
bzero(&ad, sizeof ad);
|
||||
|
||||
ad.iot = ia->ia_iot;
|
||||
ad.ioh = ia->ia_ioh;
|
||||
ad.auxiot = ia->ia_iot;
|
||||
ad.auxioh = ia->ia_auxioh;
|
||||
|
||||
/* Disable interrupts */
|
||||
(void)bus_space_read_1(ia->ia_iot, ia->ia_irqioh, 0);
|
||||
|
||||
result = wdcprobe(&ad);
|
||||
|
||||
/* Disable interrupts */
|
||||
(void)bus_space_read_1(ia->ia_iot, ia->ia_irqioh, 0);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Controller attach function
|
||||
*
|
||||
* Map all the required I/O space for this channel, disble interrupts
|
||||
* and attach the controller. The generic attach will probe and attach
|
||||
* any devices.
|
||||
* Install an interrupt handler and we are ready to rock.
|
||||
*/
|
||||
|
||||
void
|
||||
wdc_ics_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct wdc_ics_softc *wdc = (void *)self;
|
||||
struct icside_attach_args *ia = (void *)aux;
|
||||
struct podule_attach_args *pa = ia->ia_pa;
|
||||
|
||||
printf("\n");
|
||||
|
||||
wdc->sc_irqiot = ia->ia_iot;
|
||||
wdc->sc_irqioh = ia->ia_irqioh;
|
||||
wdc->sc_ad.iot = ia->ia_iot;
|
||||
wdc->sc_ad.ioh = ia->ia_ioh;
|
||||
wdc->sc_ad.auxiot = ia->ia_iot;
|
||||
wdc->sc_ad.auxioh = ia->ia_auxioh;
|
||||
|
||||
/* Disable interrupts */
|
||||
(void)bus_space_read_1(wdc->sc_irqiot, wdc->sc_irqioh, 0);
|
||||
|
||||
wdcattach(&wdc->sc_wdcdev, &wdc->sc_ad);
|
||||
|
||||
pa->pa_podule->irq_addr = ia->ia_irqstatus;
|
||||
pa->pa_podule->irq_mask = IRQ_STATUS_REGISTER_MASK;
|
||||
|
||||
wdc->sc_ih.ih_func = wdc_ics_intr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
wdc->sc_ih.ih_level = IPL_BIO;
|
||||
wdc->sc_ih.ih_name = "icside";
|
||||
wdc->sc_ih.ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
wdc->sc_ih.ih_maskbits = pa->pa_podule->irq_mask;
|
||||
|
||||
if (irq_claim(pa->pa_podule->interrupt, &wdc->sc_ih))
|
||||
printf("%s: Cannot claim interrupt %d\n", self->dv_xname,
|
||||
pa->pa_podule->interrupt);
|
||||
|
||||
/* Enable interrupts */
|
||||
bus_space_write_1(wdc->sc_irqiot, wdc->sc_irqioh, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Podule interrupt handler
|
||||
*
|
||||
* If the interrupt was from our card pass it on to the wdc interrupt handler
|
||||
*/
|
||||
int
|
||||
wdc_ics_intr(arg)
|
||||
icside_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct wdc_ics_softc *wdc = arg;
|
||||
volatile u_char *intraddr = (volatile u_char *)wdc->sc_ih.ih_maskaddr;
|
||||
struct channel_softc *chp = arg;
|
||||
struct icside_softc *sc = (struct icside_softc*)chp->wdc;
|
||||
irqhandler_t *ihp = &sc->icside_channels[chp->channel].ic_ih;
|
||||
volatile u_char *intraddr = (volatile u_char *)ihp->ih_maskaddr;
|
||||
|
||||
/* XXX - not bus space yet - should really be handled by podulebus */
|
||||
if ((*intraddr) & wdc->sc_ih.ih_maskbits)
|
||||
wdcintr(arg);
|
||||
|
||||
if ((*intraddr) & ihp->ih_maskbits)
|
||||
wdcintr(chp);
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rapide.c,v 1.9 1998/09/22 00:40:37 mark Exp $ */
|
||||
/* $NetBSD: rapide.c,v 1.10 1998/10/12 16:09:11 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-1998 Mark Brinicombe
|
||||
@ -71,6 +71,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/irqhandler.h>
|
||||
#include <machine/io.h>
|
||||
@ -81,6 +82,7 @@
|
||||
#include <arm32/podulebus/podules.h>
|
||||
#include <arm32/podulebus/rapidereg.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
|
||||
@ -102,36 +104,29 @@
|
||||
*/
|
||||
|
||||
struct rapide_softc {
|
||||
struct device sc_dev; /* device node */
|
||||
struct wdc_softc sc_wdcdev; /* common wdc definitions */
|
||||
struct channel_softc wdc_channel[2]; /* channels definition */
|
||||
podule_t *sc_podule; /* Our podule info */
|
||||
int sc_podule_number; /* Our podule number */
|
||||
int sc_intr_enable_mask; /* Global intr mask */
|
||||
int sc_version; /* Card version */
|
||||
bus_space_tag_t sc_ctliot; /* Bus tag */
|
||||
bus_space_handle_t sc_ctlioh; /* control handler */
|
||||
struct rapide_channel {
|
||||
irqhandler_t rc_ih; /* interrupt handler */
|
||||
int rc_irqmask; /* IRQ mask for this channel */
|
||||
} rapide_channels[2];
|
||||
};
|
||||
|
||||
int rapide_probe __P((struct device *, struct cfdata *, void *));
|
||||
void rapide_attach __P((struct device *, struct device *, void *));
|
||||
void rapide_shutdown __P((void *arg));
|
||||
int rapide_intr __P((void *));
|
||||
|
||||
struct cfattach rapide_ca = {
|
||||
sizeof(struct rapide_softc), rapide_probe, rapide_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Attach arguments for child devices.
|
||||
* Pass the podule details, the parent softc and the channel
|
||||
*/
|
||||
|
||||
struct rapide_attach_args {
|
||||
struct podule_attach_args *ra_pa; /* podule info */
|
||||
struct rapide_softc *ra_softc; /* parent softc */
|
||||
bus_space_tag_t ra_iot; /* bus space tag */
|
||||
u_int ra_iobase; /* I/O base address */
|
||||
int ra_channel; /* IDE channel */
|
||||
};
|
||||
|
||||
/*
|
||||
* We have a private bus space tag.
|
||||
* This is created by copying the podulebus tag and then replacing
|
||||
@ -143,20 +138,25 @@ static struct bus_space rapide_bs_tag;
|
||||
bs_rm_4_proto(rapide);
|
||||
bs_wm_4_proto(rapide);
|
||||
|
||||
/* Print function used during child config */
|
||||
/*
|
||||
* Create an array of address structures. These define the addresses and
|
||||
* masks needed for the different channels for the card.
|
||||
*
|
||||
* XXX - Needs some work for issue 1 cards.
|
||||
*/
|
||||
|
||||
int
|
||||
rapide_print(aux, name)
|
||||
void *aux;
|
||||
const char *name;
|
||||
{
|
||||
struct rapide_attach_args *ra = aux;
|
||||
struct {
|
||||
u_int registers;
|
||||
u_int aux_register;
|
||||
u_int data_register;
|
||||
u_int irq_mask;
|
||||
} rapide_info[] = {
|
||||
{ PRIMARY_DRIVE_REGISTERS_OFFSET, PRIMARY_AUX_REGISTER_OFFSET,
|
||||
PRIMARY_DATA_REGISTER_OFFSET, PRIMARY_IRQ_MASK },
|
||||
{ SECONDARY_DRIVE_REGISTERS_OFFSET, SECONDARY_AUX_REGISTER_OFFSET,
|
||||
SECONDARY_DATA_REGISTER_OFFSET, SECONDARY_IRQ_MASK }
|
||||
};
|
||||
|
||||
if (!name)
|
||||
printf(": %s channel", (ra->ra_channel == 0) ? "primary" : "secondary");
|
||||
|
||||
return(QUIET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Card probe function
|
||||
@ -191,9 +191,12 @@ rapide_attach(parent, self, aux)
|
||||
{
|
||||
struct rapide_softc *sc = (void *)self;
|
||||
struct podule_attach_args *pa = (void *)aux;
|
||||
struct rapide_attach_args ra;
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ctlioh;
|
||||
u_int iobase;
|
||||
int channel;
|
||||
struct channel_softc *cp;
|
||||
irqhandler_t *ihp;
|
||||
|
||||
/* Note the podule number and validate */
|
||||
if (pa->pa_podule_number == -1)
|
||||
@ -235,18 +238,71 @@ rapide_attach(parent, self, aux)
|
||||
+ CONTROL_REGISTERS_OFFSET + IRQ_REQUEST_REGISTER_BYTE_OFFSET;
|
||||
sc->sc_podule->irq_mask = IRQ_MASK;
|
||||
|
||||
/* Configure the children */
|
||||
sc->sc_intr_enable_mask = 0;
|
||||
ra.ra_softc = sc;
|
||||
ra.ra_pa = pa;
|
||||
ra.ra_iot = iot;
|
||||
ra.ra_iobase = pa->pa_podule->easi_base;
|
||||
iobase = pa->pa_podule->easi_base;
|
||||
|
||||
ra.ra_channel = 0;
|
||||
config_found_sm(self, &ra, rapide_print, NULL);
|
||||
/* Fill in wdc and channel infos */
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA32;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 2;
|
||||
for (channel = 0 ; channel < 2; channel++) {
|
||||
cp = &sc->wdc_channel[channel];
|
||||
cp->channel = channel;
|
||||
cp->wdc = &sc->sc_wdcdev;
|
||||
cp->ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (cp->ch_queue == NULL) {
|
||||
printf("%s %s channel: can't allocate memory for "
|
||||
"command queue", self->dv_xname,
|
||||
(channel == 0) ? "primary" : "secondary");
|
||||
continue;
|
||||
}
|
||||
cp->cmd_iot = iot;
|
||||
cp->ctl_iot = iot;
|
||||
cp->data32iot = iot;
|
||||
|
||||
ra.ra_channel = 1;
|
||||
config_found_sm(self, &ra, rapide_print, NULL);
|
||||
if (bus_space_map(iot, iobase + rapide_info[channel].registers,
|
||||
DRIVE_REGISTERS_SPACE, 0, &cp->cmd_ioh))
|
||||
continue;
|
||||
if (bus_space_map(iot, iobase +
|
||||
rapide_info[channel].aux_register, 4, 0, &cp->ctl_ioh)) {
|
||||
bus_space_unmap(iot, cp->cmd_ioh,
|
||||
DRIVE_REGISTERS_SPACE);
|
||||
continue;
|
||||
}
|
||||
if (bus_space_map(iot, iobase +
|
||||
rapide_info[channel].data_register, 4, 0, &cp->data32ioh)) {
|
||||
bus_space_unmap(iot, cp->cmd_ioh,
|
||||
DRIVE_REGISTERS_SPACE);
|
||||
bus_space_unmap(iot, cp->ctl_ioh, 4);
|
||||
continue;
|
||||
}
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->rapide_channels[channel].rc_irqmask =
|
||||
rapide_info[channel].irq_mask;
|
||||
sc->sc_intr_enable_mask &=
|
||||
~sc->rapide_channels[channel].rc_irqmask;
|
||||
bus_space_write_1(iot, sc->sc_ctlioh, IRQ_MASK_REGISTER_OFFSET,
|
||||
sc->sc_intr_enable_mask);
|
||||
/* XXX - Issue 1 cards will need to clear any pending interrupts */
|
||||
wdcattach(cp);
|
||||
ihp = &sc->rapide_channels[channel].rc_ih;
|
||||
ihp->ih_func = rapide_intr;
|
||||
ihp->ih_arg = cp;
|
||||
ihp->ih_level = IPL_BIO;
|
||||
ihp->ih_name = "rapide";
|
||||
ihp->ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
ihp->ih_maskbits = sc->rapide_channels[channel].rc_irqmask;
|
||||
if (irq_claim(sc->sc_podule->interrupt, ihp))
|
||||
panic("%s: Cannot claim interrupt %d\n",
|
||||
self->dv_xname, sc->sc_podule->interrupt);
|
||||
/* clear any pending interrupts and enable interrupts */
|
||||
sc->sc_intr_enable_mask |=
|
||||
sc->rapide_channels[channel].rc_irqmask;
|
||||
bus_space_write_1(iot, sc->sc_ctlioh,
|
||||
IRQ_MASK_REGISTER_OFFSET, sc->sc_intr_enable_mask);
|
||||
/* XXX - Issue 1 cards will need to clear any pending interrupts */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -267,185 +323,6 @@ rapide_shutdown(arg)
|
||||
IRQ_MASK_REGISTER_OFFSET, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* RapIDE probe and attach code for the wdc device.
|
||||
*
|
||||
* This provides a different pair of probe and attach functions
|
||||
* for attaching the wdc device (mainbus/wd.c) to the RapIDE card.
|
||||
*/
|
||||
|
||||
struct wdc_rapide_softc {
|
||||
struct wdc_softc sc_wdcdev; /* Device node */
|
||||
struct wdc_attachment_data sc_ad; /* Attachment data */
|
||||
irqhandler_t sc_ih; /* interrupt handler */
|
||||
int sc_irqmask; /* IRQ mask for this channel */
|
||||
int sc_channel; /* channel number */
|
||||
int sc_pio_mode[2]; /* PIO mode */
|
||||
struct rapide_softc *sc_softc; /* pointer to parent */
|
||||
};
|
||||
|
||||
int wdc_rapide_probe __P((struct device *, struct cfdata *, void *));
|
||||
void wdc_rapide_attach __P((struct device *, struct device *, void *));
|
||||
int wdc_rapide_intr __P((void *));
|
||||
|
||||
struct cfattach wdc_rapide_ca = {
|
||||
sizeof(struct wdc_rapide_softc), wdc_rapide_probe, wdc_rapide_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Create an array of address structures. These define the addresses and
|
||||
* masks needed for the different channels for the card.
|
||||
*
|
||||
* XXX - Needs some work for issue 1 cards.
|
||||
*/
|
||||
|
||||
struct {
|
||||
u_int registers;
|
||||
u_int aux_register;
|
||||
u_int data_register;
|
||||
u_int irq_mask;
|
||||
} rapide_info[] = {
|
||||
{ PRIMARY_DRIVE_REGISTERS_OFFSET, PRIMARY_AUX_REGISTER_OFFSET,
|
||||
PRIMARY_DATA_REGISTER_OFFSET, PRIMARY_IRQ_MASK },
|
||||
{ SECONDARY_DRIVE_REGISTERS_OFFSET, SECONDARY_AUX_REGISTER_OFFSET,
|
||||
SECONDARY_DATA_REGISTER_OFFSET, SECONDARY_IRQ_MASK }
|
||||
};
|
||||
|
||||
/*
|
||||
* Controller probe function
|
||||
*
|
||||
* Map all the required I/O space for this channel, make sure interrupts
|
||||
* are disabled and probe the bus.
|
||||
*/
|
||||
|
||||
int
|
||||
wdc_rapide_probe(parent, cf, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
struct rapide_attach_args *ra = (void *)aux;
|
||||
struct rapide_softc *sc;
|
||||
struct wdc_attachment_data ad;
|
||||
int result = 0;
|
||||
|
||||
bzero(&ad, sizeof ad);
|
||||
sc = ra->ra_softc;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (ra->ra_channel < 0 || ra->ra_channel > 1)
|
||||
return(0);
|
||||
#endif /* DIAGNOSTIC */
|
||||
|
||||
ad.iot = ra->ra_iot;
|
||||
if (bus_space_map(ad.iot, ra->ra_iobase +
|
||||
rapide_info[ra->ra_channel].registers, DRIVE_REGISTERS_SPACE,
|
||||
0, &ad.ioh))
|
||||
return(0);
|
||||
|
||||
ad.auxiot = ra->ra_iot;
|
||||
if (bus_space_map(ad.auxiot, ra->ra_iobase +
|
||||
rapide_info[ra->ra_channel].aux_register, 4, 0, &ad.auxioh)) {
|
||||
bus_space_unmap(ad.iot, ad.ioh, DRIVE_REGISTERS_SPACE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
ad.data32iot = ra->ra_iot;
|
||||
ad.cap |= WDC_CAPABILITY_DATA32;
|
||||
if (bus_space_map(ad.data32iot, ra->ra_iobase +
|
||||
rapide_info[ra->ra_channel].data_register, 4, 0, &ad.data32ioh)) {
|
||||
bus_space_unmap(ad.iot, ad.ioh, DRIVE_REGISTERS_SPACE);
|
||||
bus_space_unmap(ad.auxiot, ad.auxioh, 4);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->sc_intr_enable_mask &= ~rapide_info[ra->ra_channel].irq_mask;
|
||||
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh, IRQ_MASK_REGISTER_OFFSET,
|
||||
sc->sc_intr_enable_mask);
|
||||
|
||||
/* XXX - Issue 1 cards will need to clear any pending interrupts */
|
||||
result = wdcprobe(&ad);
|
||||
|
||||
bus_space_unmap(ad.iot, ad.ioh, DRIVE_REGISTERS_SPACE);
|
||||
bus_space_unmap(ad.auxiot, ad.auxioh, 4);
|
||||
bus_space_unmap(ad.data32iot, ad.data32ioh, 4);
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Controller attach function
|
||||
*
|
||||
* Map all the required I/O space for this channel, disble interrupts
|
||||
* and attach the controller. The generic attach will probe and attach
|
||||
* any devices.
|
||||
* Install an interrupt handler and we are ready to rock.
|
||||
*/
|
||||
|
||||
void
|
||||
wdc_rapide_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct wdc_rapide_softc *wdc = (void *)self;
|
||||
struct rapide_attach_args *ra = (void *)aux;
|
||||
struct podule_attach_args *pa = ra->ra_pa;
|
||||
struct rapide_softc *sc;
|
||||
|
||||
printf("\n");
|
||||
|
||||
wdc->sc_channel = ra->ra_channel;
|
||||
wdc->sc_irqmask = rapide_info[ra->ra_channel].irq_mask;
|
||||
|
||||
wdc->sc_ad.iot = ra->ra_iot;
|
||||
wdc->sc_ad.auxiot = ra->ra_iot;
|
||||
wdc->sc_ad.data32iot = ra->ra_iot;
|
||||
wdc->sc_ad.cap |= WDC_CAPABILITY_DATA32;
|
||||
sc = ra->ra_softc;
|
||||
|
||||
if (bus_space_map(wdc->sc_ad.iot, ra->ra_iobase
|
||||
+ rapide_info[ra->ra_channel].registers,
|
||||
DRIVE_REGISTERS_SPACE, 0, &wdc->sc_ad.ioh))
|
||||
panic("%s: Cannot map drive registers\n", self->dv_xname);
|
||||
|
||||
if (bus_space_map(wdc->sc_ad.auxiot, ra->ra_iobase +
|
||||
rapide_info[ra->ra_channel].aux_register, 4, 0, &wdc->sc_ad.auxioh))
|
||||
panic("%s: Cannot map auxilary register\n", self->dv_xname);
|
||||
|
||||
if (bus_space_map(wdc->sc_ad.data32iot, ra->ra_iobase +
|
||||
rapide_info[ra->ra_channel].data_register, 4, 0, &wdc->sc_ad.data32ioh))
|
||||
panic("%s: Cannot map data register\n", self->dv_xname);
|
||||
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->sc_intr_enable_mask &= ~wdc->sc_irqmask;
|
||||
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
IRQ_MASK_REGISTER_OFFSET, sc->sc_intr_enable_mask);
|
||||
|
||||
/* XXX - Issue 1 cards will need to clear any pending interrupts */
|
||||
wdcattach(&wdc->sc_wdcdev, &wdc->sc_ad);
|
||||
|
||||
wdc->sc_ih.ih_func = wdc_rapide_intr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
wdc->sc_ih.ih_level = IPL_BIO;
|
||||
wdc->sc_ih.ih_name = "rapide";
|
||||
wdc->sc_ih.ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
wdc->sc_ih.ih_maskbits = wdc->sc_irqmask;
|
||||
|
||||
if (irq_claim(sc->sc_podule->interrupt, &wdc->sc_ih))
|
||||
panic("%s: Cannot claim interrupt %d\n", self->dv_xname,
|
||||
sc->sc_podule->interrupt);
|
||||
|
||||
/* clear any pending interrupts and enable interrupts */
|
||||
sc->sc_intr_enable_mask |= wdc->sc_irqmask;
|
||||
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
IRQ_MASK_REGISTER_OFFSET, sc->sc_intr_enable_mask);
|
||||
|
||||
/* XXX - Issue 1 cards will need to clear any pending interrupts */
|
||||
}
|
||||
|
||||
/*
|
||||
* Podule interrupt handler
|
||||
*
|
||||
@ -453,17 +330,19 @@ wdc_rapide_attach(parent, self, aux)
|
||||
*/
|
||||
|
||||
int
|
||||
wdc_rapide_intr(arg)
|
||||
rapide_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct wdc_rapide_softc *wdc = arg;
|
||||
volatile u_char *intraddr = (volatile u_char *)wdc->sc_ih.ih_maskaddr;
|
||||
struct channel_softc *chp = arg;
|
||||
struct rapide_softc *sc = (struct rapide_softc *)chp->wdc;
|
||||
irqhandler_t *ihp = &sc->rapide_channels[chp->channel].rc_ih;
|
||||
volatile u_char *intraddr = (volatile u_char *)ihp->ih_maskaddr;
|
||||
|
||||
/* XXX - Issue 1 cards will need to clear the interrupt */
|
||||
|
||||
/* XXX - not bus space yet - should really be handled by podulebus */
|
||||
if ((*intraddr) & wdc->sc_ih.ih_maskbits)
|
||||
wdcintr(arg);
|
||||
if ((*intraddr) & ihp->ih_maskbits)
|
||||
wdcintr(chp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: simide.c,v 1.7 1998/09/22 00:40:38 mark Exp $ */
|
||||
/* $NetBSD: simide.c,v 1.8 1998/10/12 16:09:11 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997-1998 Mark Brinicombe
|
||||
@ -43,6 +43,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/irqhandler.h>
|
||||
#include <machine/io.h>
|
||||
@ -51,6 +52,7 @@
|
||||
#include <arm32/podulebus/podules.h>
|
||||
#include <arm32/podulebus/simidereg.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
|
||||
@ -72,7 +74,8 @@
|
||||
*/
|
||||
|
||||
struct simide_softc {
|
||||
struct device sc_dev; /* device node */
|
||||
struct wdc_softc sc_wdcdev; /* common wdc definitions */
|
||||
struct channel_softc wdc_channel[2]; /* channels definition */
|
||||
podule_t *sc_podule; /* Our podule info */
|
||||
int sc_podule_number; /* Our podule number */
|
||||
int sc_ctl_reg; /* Global ctl reg */
|
||||
@ -80,28 +83,21 @@ struct simide_softc {
|
||||
bus_space_tag_t sc_ctliot; /* Bus tag */
|
||||
bus_space_handle_t sc_ctlioh; /* control handle */
|
||||
struct bus_space sc_tag; /* custom tag */
|
||||
struct simide_channel {
|
||||
irqhandler_t sc_ih; /* interrupt handler */
|
||||
int sc_irqmask; /* IRQ mask for this channel */
|
||||
} simide_channels[2];
|
||||
};
|
||||
|
||||
int simide_probe __P((struct device *, struct cfdata *, void *));
|
||||
void simide_attach __P((struct device *, struct device *, void *));
|
||||
void simide_shutdown __P((void *arg));
|
||||
int simide_intr __P((void *arg));
|
||||
|
||||
struct cfattach simide_ca = {
|
||||
sizeof(struct simide_softc), simide_probe, simide_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Attach arguments for child devices.
|
||||
* Pass the podule details, the parent softc and the channel
|
||||
*/
|
||||
|
||||
struct simide_attach_args {
|
||||
struct podule_attach_args *sa_pa; /* podule info */
|
||||
struct simide_softc *sa_softc; /* parent softc */
|
||||
bus_space_tag_t sa_iot; /* bus space tag */
|
||||
u_int sa_iobase; /* I/O base address */
|
||||
int sa_channel; /* IDE channel */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define prototypes for custom bus space functions.
|
||||
@ -110,20 +106,23 @@ struct simide_attach_args {
|
||||
bs_rm_2_proto(simide);
|
||||
bs_wm_2_proto(simide);
|
||||
|
||||
/* Print function used during child config */
|
||||
/*
|
||||
* Create an array of address structures. These define the addresses and
|
||||
* masks needed for the different channels.
|
||||
*
|
||||
* index = channel
|
||||
*/
|
||||
|
||||
int
|
||||
simide_print(aux, name)
|
||||
void *aux;
|
||||
const char *name;
|
||||
{
|
||||
struct simide_attach_args *sa = aux;
|
||||
|
||||
if (!name)
|
||||
printf(": %s channel", (sa->sa_channel == 0) ? "primary" : "secondary");
|
||||
|
||||
return(QUIET);
|
||||
}
|
||||
struct {
|
||||
u_int drive_registers;
|
||||
u_int aux_register;
|
||||
u_int irq_mask;
|
||||
} simide_info[] = {
|
||||
{ PRIMARY_DRIVE_REGISTERS_POFFSET, PRIMARY_AUX_REGISTER_POFFSET,
|
||||
CONTROL_PRIMARY_IRQ },
|
||||
{ SECONDARY_DRIVE_REGISTERS_POFFSET, SECONDARY_AUX_REGISTER_POFFSET,
|
||||
CONTROL_SECONDARY_IRQ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Card probe function
|
||||
@ -158,8 +157,11 @@ simide_attach(parent, self, aux)
|
||||
{
|
||||
struct simide_softc *sc = (void *)self;
|
||||
struct podule_attach_args *pa = (void *)aux;
|
||||
struct simide_attach_args sa;
|
||||
int status;
|
||||
u_int iobase;
|
||||
int channel;
|
||||
struct channel_softc *cp;
|
||||
irqhandler_t *ihp;
|
||||
|
||||
/* Note the podule number and validate */
|
||||
if (pa->pa_podule_number == -1)
|
||||
@ -236,17 +238,58 @@ simide_attach(parent, self, aux)
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
|
||||
/* Configure the children */
|
||||
sa.sa_softc = sc;
|
||||
sa.sa_pa = pa;
|
||||
sa.sa_iot = &sc->sc_tag;
|
||||
sa.sa_iobase = pa->pa_podule->mod_base;
|
||||
/* Fill in wdc and channel infos */
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 2;
|
||||
for (channel = 0 ; channel < 2; channel++) {
|
||||
cp = &sc->wdc_channel[channel];
|
||||
cp->channel = channel;
|
||||
cp->wdc = &sc->sc_wdcdev;
|
||||
cp->ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (cp->ch_queue == NULL) {
|
||||
printf("%s %s channel: can't allocate memory for "
|
||||
"command queue", self->dv_xname,
|
||||
(channel == 0) ? "primary" : "secondary");
|
||||
continue;
|
||||
}
|
||||
cp->cmd_iot = cp->ctl_iot = &sc->sc_tag;
|
||||
iobase = pa->pa_podule->mod_base;
|
||||
if (bus_space_map(cp->cmd_iot, iobase +
|
||||
simide_info[channel].drive_registers,
|
||||
DRIVE_REGISTERS_SPACE, 0, &cp->cmd_ioh))
|
||||
continue;
|
||||
if (bus_space_map(cp->ctl_iot, iobase +
|
||||
simide_info[channel].aux_register, 4, 0, &cp->ctl_ioh)) {
|
||||
bus_space_unmap(cp->cmd_iot, cp->cmd_ioh,
|
||||
DRIVE_REGISTERS_SPACE);
|
||||
continue;
|
||||
}
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->simide_channels[channel].sc_irqmask =
|
||||
simide_info[channel].irq_mask;
|
||||
sc->sc_ctl_reg &= ~sc->simide_channels[channel].sc_irqmask;
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
wdcattach(cp);
|
||||
ihp = &sc->simide_channels[channel].sc_ih;
|
||||
ihp->ih_func = simide_intr;
|
||||
ihp->ih_arg = cp;
|
||||
ihp->ih_level = IPL_BIO;
|
||||
ihp->ih_name = "simide";
|
||||
ihp->ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
ihp->ih_maskbits = sc->simide_channels[channel].sc_irqmask;
|
||||
if (irq_claim(sc->sc_podule->interrupt, ihp))
|
||||
panic("%s: Cannot claim interrupt %d\n",
|
||||
self->dv_xname, sc->sc_podule->interrupt);
|
||||
/* clear any pending interrupts and enable interrupts */
|
||||
sc->sc_ctl_reg |= sc->simide_channels[channel].sc_irqmask;
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
}
|
||||
|
||||
sa.sa_channel = 0;
|
||||
config_found_sm(self, &sa, simide_print, NULL);
|
||||
|
||||
sa.sa_channel = 1;
|
||||
config_found_sm(self, &sa, simide_print, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -269,179 +312,23 @@ simide_shutdown(arg)
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simtec IDE probe and attach code for the wdc device.
|
||||
*
|
||||
* This provides a different pair of probe and attach functions
|
||||
* for attaching the wdc device to the Simtec IDE card.
|
||||
*/
|
||||
|
||||
struct wdc_simide_softc {
|
||||
struct wdc_softc sc_wdcdev; /* Device node */
|
||||
struct wdc_attachment_data sc_ad; /* Attachment data */
|
||||
irqhandler_t sc_ih; /* interrupt handler */
|
||||
int sc_irqmask; /* IRQ mask for this channel */
|
||||
int sc_channel; /* channel number */
|
||||
struct simide_softc *sc_psoftc; /* pointer to parent */
|
||||
};
|
||||
|
||||
int wdc_simide_probe __P((struct device *, struct cfdata *, void *));
|
||||
void wdc_simide_attach __P((struct device *, struct device *, void *));
|
||||
int wdc_simide_intr __P((void *));
|
||||
|
||||
struct cfattach wdc_sim_ca = {
|
||||
sizeof(struct wdc_simide_softc), wdc_simide_probe, wdc_simide_attach
|
||||
};
|
||||
|
||||
/*
|
||||
* Create an array of address structures. These define the addresses and
|
||||
* masks needed for the different channels.
|
||||
*
|
||||
* index = channel
|
||||
*/
|
||||
|
||||
struct {
|
||||
u_int drive_registers;
|
||||
u_int aux_register;
|
||||
u_int irq_mask;
|
||||
} simide_info[] = {
|
||||
{ PRIMARY_DRIVE_REGISTERS_POFFSET, PRIMARY_AUX_REGISTER_POFFSET,
|
||||
CONTROL_PRIMARY_IRQ },
|
||||
{ SECONDARY_DRIVE_REGISTERS_POFFSET, SECONDARY_AUX_REGISTER_POFFSET,
|
||||
CONTROL_SECONDARY_IRQ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Controller probe function
|
||||
*
|
||||
* Map all the required I/O space for this channel, make sure interrupts
|
||||
* are disabled and probe the bus.
|
||||
*/
|
||||
|
||||
int
|
||||
wdc_simide_probe(parent, cf, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
struct simide_attach_args *sa = (void *)aux;
|
||||
struct wdc_attachment_data ad;
|
||||
struct simide_softc *sc;
|
||||
int result = 0;
|
||||
|
||||
bzero(&ad, sizeof ad);
|
||||
sc = sa->sa_softc;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sa->sa_channel < 0 || sa->sa_channel > 1)
|
||||
return(0);
|
||||
#endif /* DIAGNOSTIC */
|
||||
|
||||
ad.iot = sa->sa_iot;
|
||||
if (bus_space_map(ad.iot, sa->sa_iobase +
|
||||
simide_info[sa->sa_channel].drive_registers, DRIVE_REGISTERS_SPACE,
|
||||
0, &ad.ioh))
|
||||
return(0);
|
||||
|
||||
ad.auxiot = sa->sa_iot;
|
||||
if (bus_space_map(ad.auxiot, sa->sa_iobase +
|
||||
simide_info[sa->sa_channel].aux_register, 4, 0, &ad.auxioh)) {
|
||||
bus_space_unmap(ad.iot, ad.ioh, DRIVE_REGISTERS_SPACE);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->sc_ctl_reg &= ~simide_info[sa->sa_channel].irq_mask;
|
||||
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
|
||||
result = wdcprobe(&ad);
|
||||
|
||||
bus_space_unmap(ad.auxiot, ad.auxioh, DRIVE_REGISTERS_SPACE);
|
||||
bus_space_unmap(ad.iot, ad.ioh, 4);
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Controller attach function
|
||||
*
|
||||
* Map all the required I/O space for this channel, disble interrupts
|
||||
* and attach the controller. The generic attach will probe and attach
|
||||
* any devices.
|
||||
* Install an interrupt handler and we are ready to rock.
|
||||
*/
|
||||
|
||||
void
|
||||
wdc_simide_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct wdc_simide_softc *wdc = (void *)self;
|
||||
struct simide_attach_args *sa = (void *)aux;
|
||||
struct podule_attach_args *pa = sa->sa_pa;
|
||||
struct simide_softc *sc;
|
||||
|
||||
printf("\n");
|
||||
|
||||
wdc->sc_psoftc = sc = sa->sa_softc;
|
||||
|
||||
wdc->sc_channel = sa->sa_channel;
|
||||
wdc->sc_irqmask = simide_info[wdc->sc_channel].irq_mask;
|
||||
|
||||
bzero(&wdc->sc_ad, sizeof wdc->sc_ad);
|
||||
wdc->sc_ad.iot = sa->sa_iot;
|
||||
wdc->sc_ad.auxiot = sa->sa_iot;
|
||||
|
||||
if (bus_space_map(wdc->sc_ad.iot, sa->sa_iobase +
|
||||
simide_info[wdc->sc_channel].drive_registers,
|
||||
DRIVE_REGISTERS_SPACE, 0, &wdc->sc_ad.ioh))
|
||||
panic("%s: Cannot map drive registers\n", self->dv_xname);
|
||||
|
||||
if (bus_space_map(wdc->sc_ad.auxiot, sa->sa_iobase +
|
||||
simide_info[wdc->sc_channel].aux_register, 4, 0, &wdc->sc_ad.auxioh))
|
||||
panic("%s: Cannot map auxilary register\n", self->dv_xname);
|
||||
|
||||
/* Disable interrupts and clear any pending interrupts */
|
||||
sc->sc_ctl_reg &= ~wdc->sc_irqmask;
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
|
||||
wdcattach(&wdc->sc_wdcdev, &wdc->sc_ad);
|
||||
|
||||
wdc->sc_ih.ih_func = wdc_simide_intr;
|
||||
wdc->sc_ih.ih_arg = wdc;
|
||||
wdc->sc_ih.ih_level = IPL_BIO;
|
||||
wdc->sc_ih.ih_name = "simide";
|
||||
wdc->sc_ih.ih_maskaddr = pa->pa_podule->irq_addr;
|
||||
wdc->sc_ih.ih_maskbits = wdc->sc_irqmask;
|
||||
|
||||
if (irq_claim(pa->pa_podule->interrupt, &wdc->sc_ih))
|
||||
panic("%s: Cannot claim interrupt %d\n", self->dv_xname,
|
||||
pa->pa_podule->interrupt);
|
||||
|
||||
/* clear any pending interrupts and enable interrupts */
|
||||
sc->sc_ctl_reg |= wdc->sc_irqmask;
|
||||
|
||||
bus_space_write_1(sc->sc_ctliot, sc->sc_ctlioh,
|
||||
CONTROL_REGISTER_OFFSET, sc->sc_ctl_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Podule interrupt handler
|
||||
*
|
||||
* If the interrupt was from our card pass it on to the wdc interrupt handler
|
||||
*/
|
||||
int
|
||||
wdc_simide_intr(arg)
|
||||
simide_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct wdc_simide_softc *wdc = arg;
|
||||
volatile u_char *intraddr = (volatile u_char *)wdc->sc_ih.ih_maskaddr;
|
||||
struct channel_softc *chp = arg;
|
||||
struct simide_softc *sc = (struct simide_softc *)chp->wdc;
|
||||
irqhandler_t *ihp = &sc->simide_channels[chp->channel].sc_ih;
|
||||
volatile u_char *intraddr = (volatile u_char *)ihp->ih_maskaddr;
|
||||
|
||||
/* XXX - not bus space yet - should really be handled by podulebus */
|
||||
if ((*intraddr) & wdc->sc_ih.ih_maskbits)
|
||||
wdcintr(arg);
|
||||
if ((*intraddr) & ihp->ih_maskbits)
|
||||
wdcintr(chp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_mb.c,v 1.2 1998/08/15 10:11:01 mycroft Exp $ */
|
||||
/* $NetBSD: wdc_mb.c,v 1.3 1998/10/12 16:09:12 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -39,6 +39,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
@ -47,6 +48,7 @@
|
||||
#include <machine/mfp.h>
|
||||
#include <machine/dma.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
#include <m68k/asm_single.h>
|
||||
@ -59,10 +61,14 @@
|
||||
*/
|
||||
static int claim_hw __P((void *, int));
|
||||
static void free_hw __P((void *));
|
||||
static void read_multi_2_swap __P((bus_space_tag_t, bus_space_handle_t,
|
||||
bus_size_t, u_int16_t *, bus_size_t));
|
||||
static void write_multi_2_swap __P((bus_space_tag_t, bus_space_handle_t,
|
||||
bus_size_t, const u_int16_t *, bus_size_t));
|
||||
|
||||
struct wdc_mb_softc {
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct channel_softc wdc_channel;
|
||||
void *sc_ih;
|
||||
};
|
||||
|
||||
@ -79,33 +85,24 @@ wdc_mb_probe(parent, cfp, aux)
|
||||
struct cfdata *cfp;
|
||||
void *aux;
|
||||
{
|
||||
#if 0 /* XXX memset */
|
||||
struct wdc_attachment_data ad = { 0 };
|
||||
#else /* XXX memset */
|
||||
struct wdc_attachment_data ad;
|
||||
#endif /* XXX memset */
|
||||
struct channel_softc ch = { 0 };
|
||||
int result = 0;
|
||||
u_char sv_ierb;
|
||||
|
||||
#if 0 /* XXX memset */
|
||||
#else /* XXX memset */
|
||||
bzero(&ad, sizeof ad);
|
||||
#endif /* XXX memset */
|
||||
|
||||
if ((machineid & ATARI_TT) || strcmp("wdc", aux) || cfp->cf_unit != 0)
|
||||
return 0;
|
||||
if (!atari_realconfig)
|
||||
return 0;
|
||||
|
||||
ad.iot = ad.auxiot = mb_alloc_bus_space_tag();
|
||||
if (ad.iot == NULL)
|
||||
ch.cmd_iot = ch.ctl_iot = mb_alloc_bus_space_tag();
|
||||
if (ch.cmd_iot == NULL)
|
||||
return 0;
|
||||
ad.iot->stride = 2;
|
||||
ad.iot->wo_1 = 1;
|
||||
ch.cmd_iot->stride = 2;
|
||||
ch.cmd_iot->wo_1 = 1;
|
||||
|
||||
if (bus_space_map(ad.iot, 0xfff00000, 0x40, 0, &ad.ioh))
|
||||
if (bus_space_map(ch.cmd_iot, 0xfff00000, 0x40, 0, &ch.cmd_ioh))
|
||||
return 0;
|
||||
if (bus_space_subregion(ad.iot, ad.ioh, 0x38, 1, &ad.auxioh))
|
||||
if (bus_space_subregion(ch.cmd_iot, ch.cmd_ioh, 0x38, 1, &ch.ctl_ioh))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -120,12 +117,12 @@ wdc_mb_probe(parent, cfp, aux)
|
||||
if (machineid & ATARI_FALCON)
|
||||
ym2149_ser2(0);
|
||||
|
||||
result = wdcprobe(&ad);
|
||||
result = wdcprobe(&ch);
|
||||
|
||||
MFP->mf_ierb = sv_ierb;
|
||||
|
||||
bus_space_unmap(ad.iot, ad.ioh, 0x40);
|
||||
mb_free_bus_space_tag(ad.iot);
|
||||
bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, 0x40);
|
||||
mb_free_bus_space_tag(ch.cmd_iot);
|
||||
|
||||
return (result);
|
||||
}
|
||||
@ -139,17 +136,20 @@ wdc_mb_attach(parent, self, aux)
|
||||
|
||||
printf("\n");
|
||||
|
||||
sc->sc_ad.iot = sc->sc_ad.auxiot = mb_alloc_bus_space_tag();
|
||||
sc->sc_ad.iot->stride = 2;
|
||||
sc->sc_ad.iot->wo_1 = 1;
|
||||
if (bus_space_map(sc->sc_ad.iot, 0xfff00000, 0x40, 0,
|
||||
&sc->sc_ad.ioh)) {
|
||||
sc->wdc_channel.cmd_iot = sc->wdc_channel.ctl_iot =
|
||||
mb_alloc_bus_space_tag();
|
||||
sc->wdc_channel.cmd_iot->stride = 2;
|
||||
sc->wdc_channel.cmd_iot->wo_1 = 1;
|
||||
sc->wdc_channel.cmd_iot->abs_rms_2 = read_multi_2_swap;
|
||||
sc->wdc_channel.cmd_iot->abs_wms_2 = write_multi_2_swap;
|
||||
if (bus_space_map(sc->wdc_channel.cmd_iot, 0xfff00000, 0x40, 0,
|
||||
&sc->wdc_channel.cmd_ioh)) {
|
||||
printf("%s: couldn't map registers\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
if (bus_space_subregion(sc->sc_ad.iot, sc->sc_ad.ioh, 0x38, 1,
|
||||
&sc->sc_ad.auxioh))
|
||||
if (bus_space_subregion(sc->wdc_channel.cmd_iot,
|
||||
sc->wdc_channel.cmd_ioh, 0x38, 1, &sc->wdc_channel.ctl_ioh))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -159,16 +159,23 @@ wdc_mb_attach(parent, self, aux)
|
||||
*/
|
||||
MFP->mf_ierb &= ~IB_DINT;
|
||||
|
||||
/*
|
||||
* XXX: Is this true on all atari's??
|
||||
*/
|
||||
sc->sc_wdcdev.sc_flags |= WDCF_SINGLE;
|
||||
|
||||
sc->sc_ad.cap |= WDC_CAPABILITY_HWLOCK;
|
||||
sc->sc_ad.claim_hw = &claim_hw;
|
||||
sc->sc_ad.free_hw = &free_hw;
|
||||
|
||||
wdcattach(&sc->sc_wdcdev, &sc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_HWLOCK |
|
||||
WDC_CAPABILITY_ATA_NOSTREAM;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.claim_hw = &claim_hw;
|
||||
sc->sc_wdcdev.free_hw = &free_hw;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.wdc = &sc->sc_wdcdev;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
wdcattach(&sc->wdc_channel);
|
||||
|
||||
/*
|
||||
* Setup & enable disk related interrupts.
|
||||
@ -188,8 +195,6 @@ claim_hw(softc, maysleep)
|
||||
void *softc;
|
||||
int maysleep;
|
||||
{
|
||||
void wdcrestart __P((void *));
|
||||
|
||||
if (wd_lock != DMA_LOCK_GRANT) {
|
||||
if (wd_lock == DMA_LOCK_REQ) {
|
||||
/*
|
||||
@ -220,3 +225,40 @@ void *softc;
|
||||
/* if (machineid & ATARI_FALCON) */
|
||||
st_dmafree(softc, &wd_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* This piece of uglyness is caused by the fact that the byte lanes of
|
||||
* the data-register are swapped on the atari. This works OK for an IDE
|
||||
* disk, but turns into a nightmare when used on atapi devices.
|
||||
*/
|
||||
#define calc_addr(base, off, stride, wm) \
|
||||
((u_long)(base) + ((off) << (stride)) + (wm))
|
||||
|
||||
static void
|
||||
read_multi_2_swap(t, h, o, a, c)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t h;
|
||||
bus_size_t o, c;
|
||||
u_int16_t *a;
|
||||
{
|
||||
u_int16_t *ba;
|
||||
|
||||
ba = (u_int16_t *)calc_addr(h, o, t->stride, t->wo_2);
|
||||
for (; c; a++, c--)
|
||||
*a = bswap16(*ba);
|
||||
}
|
||||
|
||||
static void
|
||||
write_multi_2_swap(t, h, o, a, c)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t h;
|
||||
bus_size_t o, c;
|
||||
const u_int16_t *a;
|
||||
{
|
||||
u_int16_t *ba;
|
||||
|
||||
ba = (u_int16_t *)calc_addr(h, o, t->stride, t->wo_2);
|
||||
for (; c; a++, c--)
|
||||
*ba = bswap16(*a);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: GENERIC,v 1.188 1998/10/10 21:58:22 thorpej Exp $
|
||||
# $NetBSD: GENERIC,v 1.189 1998/10/12 16:09:13 bouyer Exp $
|
||||
#
|
||||
# GENERIC -- everything that's currently supported
|
||||
#
|
||||
@ -309,22 +309,26 @@ uk* at scsibus? target ? lun ? # SCSI unknown
|
||||
|
||||
|
||||
# IDE and Related Devices
|
||||
# PCI IDE controllers (CMD tech's PCI0640, Intel's PIIx).
|
||||
#pciide* at pci ? dev ? function ?
|
||||
|
||||
# ISA Plug-and-Play IDE controllers
|
||||
wdc* at isapnp?
|
||||
wdc* at isapnp? flags 0x0000
|
||||
|
||||
# PCMCIA IDE controllers
|
||||
wdc* at pcmcia? function ?
|
||||
wdc* at pcmcia? function ?
|
||||
|
||||
# ISA IDE controllers
|
||||
wdc0 at isa? port 0x1f0 irq 14 # ST506, ESDI, and IDE controllers
|
||||
# ISA ST506, ESDI, and IDE controllers
|
||||
wdc0 at isa? port 0x1f0 irq 14
|
||||
wdc1 at isa? port 0x170 irq 15
|
||||
|
||||
# IDE drives
|
||||
wd* at wdc? drive ? # the drives themselves
|
||||
wd* at wdc? channel ? drive ?
|
||||
#wd* at pciide? channel ? drive ?
|
||||
|
||||
# ATAPI bus support
|
||||
atapibus* at wdc?
|
||||
atapibus* at wdc? channel ?
|
||||
#atapibus* at pciide? channel ?
|
||||
|
||||
# ATAPI devices
|
||||
cd* at atapibus? drive ? # ATAPI CD-ROM drives
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.i386,v 1.122 1998/10/03 23:17:03 fvdl Exp $
|
||||
# $NetBSD: files.i386,v 1.123 1998/10/12 16:09:13 bouyer Exp $
|
||||
#
|
||||
# new style config file for i386 architecture
|
||||
#
|
||||
@ -129,17 +129,6 @@ major {wt = 3}
|
||||
attach lpt at puc with lpt_puc
|
||||
file dev/pci/lpt_puc.c lpt_puc
|
||||
|
||||
# XXX THE FOLLOWING BLOCK SHOULD GO INTO dev/pci/files.pci, BUT CANNOT
|
||||
# XXX BECAUSE NOT ALL PORTS USE THE MI DRIVER YET. (when the conf/files
|
||||
# XXX and files.isa bogons are fixed, this can be fixed as well.)
|
||||
|
||||
# PCI IDE controllers
|
||||
device pciide {[channel = -1]}
|
||||
attach pciide at pci
|
||||
file dev/pci/pciide.c pciide
|
||||
attach wdc at pciide with wdc_pciide
|
||||
file dev/pci/wdc_pciide.c wdc_pciide
|
||||
|
||||
file arch/i386/isa/isa_machdep.c isa
|
||||
|
||||
# PC clock
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files,v 1.248 1998/09/26 16:28:16 dante Exp $
|
||||
# $NetBSD: files,v 1.249 1998/10/12 16:09:14 bouyer Exp $
|
||||
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
@ -103,9 +103,10 @@ devclass tty
|
||||
define audio { }
|
||||
define midibus { }
|
||||
define midisyn
|
||||
define wdc_base
|
||||
define scsi {[channel = -1]}
|
||||
define ata {[drive = -1]}
|
||||
define atapi { }
|
||||
define ata {[channel = -1], [drive = -1]}
|
||||
define atapi {[channel = -1]}
|
||||
define mii {[phy = -1]}
|
||||
|
||||
# audio device attributes
|
||||
@ -303,10 +304,9 @@ file dev/ic/lsi64854.c lsi64854
|
||||
# XXX THE FOLLOWING BLOCK SHOULD BE UNCOMMENTED, BUT CANNOT
|
||||
# XXX BECAUSE NOT ALL PORTS USE THE MI wdc DRIVER YET.
|
||||
#
|
||||
# # ESDI/IDE/etc. controllers
|
||||
# device wdc: ata, atapi
|
||||
# file dev/ic/wdc.c
|
||||
# wdc & (wd | !wd) needs-flag # XXX
|
||||
# device wdc: ata, atapi, wdc_base
|
||||
# # Common code for ESDI/IDE/etc. controllers
|
||||
file dev/ic/wdc.c wdc_base
|
||||
|
||||
# Definitions for wscons
|
||||
# device attributes: display, display with emulator, keyboard, and mouse
|
||||
|
151
sys/dev/ata/ata.c
Normal file
151
sys/dev/ata/ata.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* $NetBSD: ata.c,v 1.2 1998/10/12 16:09:14 bouyer Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Manuel Bouyer.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define WDCDEBUG
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <dev/ic/wdcreg.h>
|
||||
#include <dev/ata/atareg.h>
|
||||
#include <dev/ata/atavar.h>
|
||||
|
||||
#define DEBUG_FUNCS 0x08
|
||||
#define DEBUG_PROBE 0x10
|
||||
#ifdef WDCDEBUG
|
||||
extern int wdcdebug_mask; /* init'ed in wdc.c */
|
||||
#define WDCDEBUG_PRINT(args, level) \
|
||||
if (wdcdebug_mask & (level)) \
|
||||
printf args
|
||||
#else
|
||||
#define WDCDEBUG_PRINT(args, level)
|
||||
#endif
|
||||
|
||||
/* Get the disk's parameters */
|
||||
int
|
||||
ata_get_params(drvp, flags, prms)
|
||||
struct ata_drive_datas *drvp;
|
||||
u_int8_t flags;
|
||||
struct ataparams *prms;
|
||||
{
|
||||
char tb[DEV_BSIZE];
|
||||
struct wdc_command wdc_c;
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
int i;
|
||||
u_int16_t *p;
|
||||
#endif
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_ata_get_parms\n"), DEBUG_FUNCS);
|
||||
|
||||
memset(tb, 0, DEV_BSIZE);
|
||||
memset(prms, 0, sizeof(struct ataparams));
|
||||
memset(&wdc_c, 0, sizeof(struct wdc_command));
|
||||
|
||||
if (drvp->drive_flags & DRIVE_ATA) {
|
||||
wdc_c.r_command = WDCC_IDENTIFY;
|
||||
wdc_c.r_st_bmask = WDCS_DRDY | WDCS_DSC;
|
||||
wdc_c.r_st_pmask = WDCS_DRDY | WDCS_DSC | WDCS_DRQ;
|
||||
} else {
|
||||
wdc_c.r_command = ATAPI_IDENTIFY_DEVICE;
|
||||
wdc_c.r_st_bmask = 0;
|
||||
wdc_c.r_st_pmask = WDCS_DRDY | WDCS_DRQ;
|
||||
}
|
||||
wdc_c.flags = AT_READ | flags;
|
||||
wdc_c.timeout = 1000; /* 1s */
|
||||
wdc_c.data = tb;
|
||||
wdc_c.bcount = DEV_BSIZE;
|
||||
if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE)
|
||||
return CMD_AGAIN;
|
||||
if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
|
||||
return CMD_ERR;
|
||||
} else {
|
||||
/* Read in parameter block. */
|
||||
memcpy(prms, tb, sizeof(struct ataparams));
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
/*
|
||||
* Shuffle string byte order.
|
||||
* ATAPI Mitsumi and NEC drives don't need this.
|
||||
*/
|
||||
if ((prms->atap_config & WDC_CFG_ATAPI_MASK) ==
|
||||
WDC_CFG_ATAPI &&
|
||||
((prms->atap_model[0] == 'N' &&
|
||||
prms->atap_model[1] == 'E') ||
|
||||
(prms->atap_model[0] == 'F' &&
|
||||
prms->atap_model[1] == 'X')))
|
||||
return 0;
|
||||
for (i = 0; i < sizeof(prms->atap_model); i += 2) {
|
||||
p = (u_short *)(prms->atap_model + i);
|
||||
*p = ntohs(*p);
|
||||
}
|
||||
for (i = 0; i < sizeof(prms->atap_serial); i += 2) {
|
||||
p = (u_short *)(prms->atap_serial + i);
|
||||
*p = ntohs(*p);
|
||||
}
|
||||
for (i = 0; i < sizeof(prms->atap_revision); i += 2) {
|
||||
p = (u_short *)(prms->atap_revision + i);
|
||||
*p = ntohs(*p);
|
||||
}
|
||||
#endif
|
||||
return CMD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ata_set_mode(drvp, mode, flags)
|
||||
struct ata_drive_datas *drvp;
|
||||
u_int8_t mode;
|
||||
u_int8_t flags;
|
||||
{
|
||||
struct wdc_command wdc_c;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_ata_set_mode=0x%x\n", mode), DEBUG_FUNCS);
|
||||
memset(&wdc_c, 0, sizeof(struct wdc_command));
|
||||
|
||||
wdc_c.r_command = SET_FEATURES;
|
||||
wdc_c.r_st_bmask = 0;
|
||||
wdc_c.r_st_pmask = 0;
|
||||
wdc_c.r_precomp = WDSF_SET_MODE;
|
||||
wdc_c.r_count = mode;
|
||||
wdc_c.flags = AT_READ | flags;
|
||||
wdc_c.timeout = 1000; /* 1s */
|
||||
if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE)
|
||||
return CMD_AGAIN;
|
||||
if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
|
||||
return CMD_ERR;
|
||||
}
|
||||
return CMD_OK;
|
||||
}
|
731
sys/dev/ata/ata_wdc.c
Normal file
731
sys/dev/ata/ata_wdc.c
Normal file
@ -0,0 +1,731 @@
|
||||
/* $NetBSD: ata_wdc.c,v 1.2 1998/10/12 16:09:15 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
|
||||
*
|
||||
* 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 NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#define WDCDEBUG
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
#ifndef __BUS_SPACE_HAS_STREAM_METHODS
|
||||
#define bus_space_write_multi_stream_2 bus_space_write_multi_2
|
||||
#define bus_space_write_multi_stream_4 bus_space_write_multi_4
|
||||
#define bus_space_read_multi_stream_2 bus_space_read_multi_2
|
||||
#define bus_space_read_multi_stream_4 bus_space_read_multi_4
|
||||
#endif /* __BUS_SPACE_HAS_STREAM_METHODS */
|
||||
|
||||
#include <dev/ata/atareg.h>
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcreg.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
#include <dev/ata/wdvar.h>
|
||||
|
||||
#define DEBUG_INTR 0x01
|
||||
#define DEBUG_XFERS 0x02
|
||||
#define DEBUG_STATUS 0x04
|
||||
#define DEBUG_FUNCS 0x08
|
||||
#define DEBUG_PROBE 0x10
|
||||
#ifdef WDCDEBUG
|
||||
int wdcdebug_wd_mask = DEBUG_PROBE;
|
||||
#define WDCDEBUG_PRINT(args, level) \
|
||||
if (wdcdebug_wd_mask & (level)) \
|
||||
printf args
|
||||
#else
|
||||
#define WDCDEBUG_PRINT(args, level)
|
||||
#endif
|
||||
|
||||
#define ATA_DELAY 10000 /* 10s for a drive I/O */
|
||||
|
||||
void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
|
||||
int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *));
|
||||
void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *));
|
||||
int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *));
|
||||
int wdc_ata_err __P((struct channel_softc *, struct ata_bio *));
|
||||
#define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
|
||||
#define WDC_ATA_RECOV 0x01 /* There was a recovered error */
|
||||
#define WDC_ATA_ERR 0x02 /* Drive reports an error */
|
||||
|
||||
/*
|
||||
* Handle block I/O operation. Return WDC_COMPLETE, WDC_QUEUED, or
|
||||
* WDC_TRY_AGAIN. Must be called at splio().
|
||||
*/
|
||||
int
|
||||
wdc_ata_bio(drvp, ata_bio)
|
||||
struct ata_drive_datas *drvp;
|
||||
struct ata_bio *ata_bio;
|
||||
{
|
||||
struct wdc_xfer *xfer;
|
||||
struct channel_softc *chp = drvp->chnl_softc;
|
||||
|
||||
xfer = wdc_get_xfer(WDC_NOSLEEP);
|
||||
if (xfer == NULL)
|
||||
return WDC_TRY_AGAIN;
|
||||
if (ata_bio->flags & ATA_POLL)
|
||||
xfer->c_flags |= C_POLL;
|
||||
if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
|
||||
(ata_bio->flags & ATA_SINGLE) == 0)
|
||||
xfer->c_flags |= C_DMA;
|
||||
xfer->drive = drvp->drive;
|
||||
xfer->cmd = ata_bio;
|
||||
xfer->databuf = ata_bio->databuf;
|
||||
xfer->c_bcount = ata_bio->bcount;
|
||||
xfer->c_start = wdc_ata_bio_start;
|
||||
xfer->c_intr = wdc_ata_bio_intr;
|
||||
wdc_exec_xfer(chp, xfer);
|
||||
return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
|
||||
}
|
||||
|
||||
void
|
||||
wdc_ata_bio_start(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct ata_bio *ata_bio = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
u_int16_t cyl;
|
||||
u_int8_t head, sect, cmd = 0;
|
||||
int nblks;
|
||||
int dma_flags = 0;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
|
||||
DEBUG_FUNCS | DEBUG_XFERS);
|
||||
|
||||
/* Do control operations specially. */
|
||||
if (drvp->state < READY) {
|
||||
/*
|
||||
* Actually, we want to be careful not to mess with the control
|
||||
* state if the device is currently busy, but we can assume
|
||||
* that we never get to this point if that's the case.
|
||||
*/
|
||||
/* at this point, we should only be in RECAL state */
|
||||
if (drvp->state != RECAL) {
|
||||
printf("%s:%d:%d: bad state %d in wdc_ata_bio_start\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive, drvp->state);
|
||||
panic("wdc_ata_bio_start: bad state");
|
||||
}
|
||||
xfer->c_intr = wdc_ata_ctrl_intr;
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY) != 0)
|
||||
goto timeout;
|
||||
wdccommandshort(chp, xfer->drive, WDCC_RECAL);
|
||||
drvp->state = RECAL_WAIT;
|
||||
if ((ata_bio->flags & ATA_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
|
||||
} else {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
delay(1);
|
||||
wdc_ata_ctrl_intr(chp, xfer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
|
||||
dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
|
||||
}
|
||||
again:
|
||||
/*
|
||||
*
|
||||
* When starting a multi-sector transfer, or doing single-sector
|
||||
* transfers...
|
||||
*/
|
||||
if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
|
||||
if (ata_bio->flags & ATA_SINGLE)
|
||||
nblks = 1;
|
||||
else
|
||||
nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
|
||||
/* Check for bad sectors and adjust transfer, if necessary. */
|
||||
if ((ata_bio->lp->d_flags & D_BADSECT) != 0) {
|
||||
long blkdiff;
|
||||
int i;
|
||||
for (i = 0; (blkdiff = ata_bio->badsect[i]) != -1;
|
||||
i++) {
|
||||
blkdiff -= ata_bio->blkno;
|
||||
if (blkdiff < 0)
|
||||
continue;
|
||||
if (blkdiff == 0) {
|
||||
/* Replace current block of transfer. */
|
||||
ata_bio->blkno =
|
||||
ata_bio->lp->d_secperunit -
|
||||
ata_bio->lp->d_nsectors - i - 1;
|
||||
}
|
||||
if (blkdiff < nblks) {
|
||||
/* Bad block inside transfer. */
|
||||
ata_bio->flags |= ATA_SINGLE;
|
||||
nblks = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Transfer is okay now. */
|
||||
}
|
||||
if (ata_bio->flags & ATA_LBA) {
|
||||
sect = (ata_bio->blkno >> 0) & 0xff;
|
||||
cyl = (ata_bio->blkno >> 8) & 0xffff;
|
||||
head = (ata_bio->blkno >> 24) & 0x0f;
|
||||
head |= WDSD_LBA;
|
||||
} else {
|
||||
int blkno = ata_bio->blkno;
|
||||
sect = blkno % ata_bio->lp->d_nsectors;
|
||||
sect++; /* Sectors begin with 1, not 0. */
|
||||
blkno /= ata_bio->lp->d_nsectors;
|
||||
head = blkno % ata_bio->lp->d_ntracks;
|
||||
blkno /= ata_bio->lp->d_ntracks;
|
||||
cyl = blkno;
|
||||
head |= WDSD_CHS;
|
||||
}
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
ata_bio->nblks = nblks;
|
||||
ata_bio->nbytes = xfer->c_bcount;
|
||||
cmd = (ata_bio->flags & ATA_READ) ?
|
||||
WDCC_READDMA : WDCC_WRITEDMA;
|
||||
nblks = ata_bio->nblks;
|
||||
/* Init the DMA channel. */
|
||||
if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive,
|
||||
xfer->databuf + xfer->c_skip, ata_bio->nbytes,
|
||||
dma_flags) != 0) {
|
||||
ata_bio->error = ERR_DMA;
|
||||
ata_bio->r_error = 0;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
/* Initiate command */
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
if (wait_for_ready(chp, ATA_DELAY) < 0)
|
||||
goto timeout;
|
||||
wdccommand(chp, xfer->drive, cmd, cyl,
|
||||
head, sect, nblks, 0);
|
||||
/* start the DMA channel */
|
||||
(*chp->wdc->dma_start)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive, dma_flags);
|
||||
/* wait for irq */
|
||||
goto intr;
|
||||
} /* else not DMA */
|
||||
ata_bio->nblks = min(nblks, ata_bio->multi);
|
||||
ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
|
||||
if (ata_bio->nblks > 1 && (ata_bio->flags & ATA_SINGLE) == 0) {
|
||||
cmd = (ata_bio->flags & ATA_READ) ?
|
||||
WDCC_READMULTI : WDCC_WRITEMULTI;
|
||||
} else {
|
||||
cmd = (ata_bio->flags & ATA_READ) ?
|
||||
WDCC_READ : WDCC_WRITE;
|
||||
}
|
||||
/* Initiate command! */
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
if (wait_for_ready(chp, ATA_DELAY) < 0)
|
||||
goto timeout;
|
||||
wdccommand(chp, xfer->drive, cmd, cyl,
|
||||
head, sect, nblks,
|
||||
(ata_bio->lp->d_type == DTYPE_ST506) ?
|
||||
ata_bio->lp->d_precompcyl / 4 : 0);
|
||||
} else if (ata_bio->nblks > 1) {
|
||||
/* The number of blocks in the last stretch may be smaller. */
|
||||
nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
|
||||
if (ata_bio->nblks > nblks) {
|
||||
ata_bio->nblks = nblks;
|
||||
ata_bio->nbytes = xfer->c_bcount;
|
||||
}
|
||||
}
|
||||
/* If this was a write and not using DMA, push the data. */
|
||||
if ((ata_bio->flags & ATA_READ) == 0) {
|
||||
if (wait_for_drq(chp, ATA_DELAY) != 0) {
|
||||
printf("%s:%d:%d: timeout waiting for DRQ, "
|
||||
"st=0x%02x, err=0x%02x\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive, chp->ch_status, chp->ch_error);
|
||||
if (wdc_ata_err(chp, ata_bio) != WDC_ATA_ERR)
|
||||
ata_bio->error = TIMEOUT;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
if (wdc_ata_err(chp, ata_bio) == WDC_ATA_ERR) {
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 1);
|
||||
}
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_stream_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intr: /* Wait for IRQ (either real or polled) */
|
||||
if ((ata_bio->flags & ATA_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
|
||||
} else {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
delay(1);
|
||||
wdc_ata_bio_intr(chp, xfer);
|
||||
if ((ata_bio->flags & ATA_ITSDONE) == 0)
|
||||
goto again;
|
||||
}
|
||||
return;
|
||||
timeout:
|
||||
printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
chp->ch_status, chp->ch_error);
|
||||
if (wdc_ata_err(chp, ata_bio) != WDC_ATA_ERR)
|
||||
ata_bio->error = TIMEOUT;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
wdc_ata_bio_intr(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct ata_bio *ata_bio = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
int drv_err;
|
||||
int dma_flags = 0;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
|
||||
DEBUG_INTR | DEBUG_XFERS);
|
||||
|
||||
|
||||
/* Is it not a transfer, but a control operation? */
|
||||
if (drvp->state < READY) {
|
||||
printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
drvp->state);
|
||||
panic("wdc_ata_bio_intr: bad state\n");
|
||||
}
|
||||
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
|
||||
dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
|
||||
}
|
||||
|
||||
/* Ack interrupt done by wait_for_unbusy */
|
||||
if (wait_for_unbusy(chp, ATA_DELAY) < 0) {
|
||||
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
xfer->c_bcount, xfer->c_skip);
|
||||
/* if we were using DMA, turn off DMA channel */
|
||||
if (xfer->c_flags & C_DMA)
|
||||
(*chp->wdc->dma_finish)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive, dma_flags);
|
||||
ata_bio->error = TIMEOUT;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
drv_err = wdc_ata_err(chp, ata_bio);
|
||||
|
||||
/* If we were using DMA, Turn off the DMA channel and check for error */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
if (ata_bio->flags & ATA_POLL) {
|
||||
/*
|
||||
* IDE drives deassert WDCS_BSY before trasfert is
|
||||
* complete when using DMA. Polling for DRQ to deassert
|
||||
* is not enouth DRQ is not required to be
|
||||
* asserted for DMA transferts, so poll for DRDY.
|
||||
*/
|
||||
if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,
|
||||
ATA_DELAY) < 0) {
|
||||
printf("%s:%d:%d: polled transfert timed out "
|
||||
"(st=0x%x)\n", chp->wdc->sc_dev.dv_xname,
|
||||
chp->channel, xfer->drive, chp->ch_status);
|
||||
ata_bio->error = TIMEOUT;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (chp->ch_status & WDCS_DRQ) {
|
||||
if (drv_err != WDC_ATA_ERR) {
|
||||
printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive, chp->ch_status);
|
||||
ata_bio->error = TIMEOUT;
|
||||
drv_err = WDC_ATA_ERR;
|
||||
}
|
||||
}
|
||||
if ((*chp->wdc->dma_finish)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive, dma_flags) != 0) {
|
||||
if (drv_err != WDC_ATA_ERR) {
|
||||
ata_bio->error = ERR_DMA;
|
||||
drv_err = WDC_ATA_ERR;
|
||||
}
|
||||
}
|
||||
if (drv_err != WDC_ATA_ERR)
|
||||
goto end;
|
||||
|
||||
}
|
||||
|
||||
/* if we had an error, end */
|
||||
if (drv_err == WDC_ATA_ERR) {
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If this was a read and not using DMA, fetch the data. */
|
||||
if ((ata_bio->flags & ATA_READ) != 0) {
|
||||
if ((chp->ch_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) !=
|
||||
(WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
|
||||
printf("%s:%d:%d: read intr before drq\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive);
|
||||
ata_bio->error = TIMEOUT;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_read_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 2);
|
||||
} else {
|
||||
bus_space_read_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 1);
|
||||
}
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_read_multi_stream_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 2);
|
||||
} else {
|
||||
bus_space_read_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
ata_bio->nbytes >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
ata_bio->blkno += ata_bio->nblks;
|
||||
ata_bio->blkdone += ata_bio->nblks;
|
||||
xfer->c_skip += ata_bio->nbytes;
|
||||
xfer->c_bcount -= ata_bio->nbytes;
|
||||
/* See if this transfer is complete. */
|
||||
if (xfer->c_bcount > 0) {
|
||||
if ((ata_bio->flags & ATA_POLL) == 0) {
|
||||
/* Start the next operation */
|
||||
wdc_ata_bio_start(chp, xfer);
|
||||
} else {
|
||||
/* Let wdc_ata_bio_start do the loop */
|
||||
return 1;
|
||||
}
|
||||
} else { /* Done with this transfer */
|
||||
ata_bio->error = NOERROR;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
wdc_ata_bio_done(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct ata_bio *ata_bio = xfer->cmd;
|
||||
int need_done = xfer->c_flags & C_NEEDDONE;
|
||||
int drive = xfer->drive;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_ata_bio_done: flags 0x%x\n", (u_int)xfer->c_flags),
|
||||
DEBUG_FUNCS);
|
||||
|
||||
/* feed back residual bcount to our caller */
|
||||
ata_bio->bcount = xfer->c_bcount;
|
||||
|
||||
/* remove this command from xfer queue */
|
||||
wdc_free_xfer(chp, xfer);
|
||||
|
||||
ata_bio->flags |= ATA_ITSDONE;
|
||||
if (need_done) {
|
||||
WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_FUNCS);
|
||||
wddone(chp->ch_drive[drive].drv_softc);
|
||||
}
|
||||
WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
|
||||
chp->ch_flags), DEBUG_FUNCS);
|
||||
wdcstart(chp->wdc, chp->channel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement operations needed before read/write.
|
||||
*/
|
||||
int
|
||||
wdc_ata_ctrl_intr(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct ata_bio *ata_bio = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
char *errstring = NULL;
|
||||
WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
|
||||
DEBUG_FUNCS);
|
||||
|
||||
again:
|
||||
switch (drvp->state) {
|
||||
case RECAL: /* Should not be in this state here */
|
||||
panic("wdc_ata_ctrl_intr: state==RECAL");
|
||||
break;
|
||||
|
||||
case RECAL_WAIT:
|
||||
errstring = "recal";
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case PIOMODE:
|
||||
/* Don't try to set modes if controller can't be adjusted */
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
|
||||
goto geometry;
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x08 | drvp->PIO_mode, WDSF_SET_MODE);
|
||||
drvp->state = PIOMODE_WAIT;
|
||||
break;
|
||||
|
||||
case PIOMODE_WAIT:
|
||||
errstring = "piomode";
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case DMAMODE:
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
|
||||
} else if (drvp->drive_flags & DRIVE_DMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
|
||||
} else {
|
||||
goto geometry;
|
||||
}
|
||||
drvp->state = DMAMODE_WAIT;
|
||||
break;
|
||||
case DMAMODE_WAIT:
|
||||
errstring = "dmamode";
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case GEOMETRY:
|
||||
geometry:
|
||||
if (ata_bio->flags & ATA_LBA)
|
||||
goto multimode;
|
||||
wdccommand(chp, xfer->drive, WDCC_IDP,
|
||||
ata_bio->lp->d_ncylinders,
|
||||
ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,
|
||||
(ata_bio->lp->d_type == DTYPE_ST506) ?
|
||||
ata_bio->lp->d_precompcyl / 4 : 0);
|
||||
drvp->state = GEOMETRY_WAIT;
|
||||
break;
|
||||
|
||||
case GEOMETRY_WAIT:
|
||||
errstring = "geometry";
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case MULTIMODE:
|
||||
multimode:
|
||||
if (ata_bio->multi == 1)
|
||||
goto ready;
|
||||
wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,
|
||||
ata_bio->multi, 0);
|
||||
drvp->state = MULTIMODE_WAIT;
|
||||
break;
|
||||
|
||||
case MULTIMODE_WAIT:
|
||||
errstring = "setmulti";
|
||||
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case READY:
|
||||
ready:
|
||||
drvp->state = READY;
|
||||
/*
|
||||
* The drive is usable now
|
||||
*/
|
||||
xfer->c_intr = wdc_ata_bio_intr;
|
||||
wdc_ata_bio_start(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((ata_bio->flags & ATA_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
|
||||
} else {
|
||||
goto again;
|
||||
}
|
||||
return 1;
|
||||
|
||||
timeout:
|
||||
if ((xfer->c_flags & C_TIMEOU) == 0 ) {
|
||||
return 0; /* IRQ was not for us */
|
||||
}
|
||||
printf("%s:%d:%d: %s timed out\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
|
||||
ata_bio->error = TIMEOUT;
|
||||
drvp->state = 0;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 0;
|
||||
error:
|
||||
printf("%s:%d:%d: %s ",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
errstring);
|
||||
if (chp->ch_status & WDCS_DWF) {
|
||||
printf("drive fault\n");
|
||||
ata_bio->error = ERR_DF;
|
||||
} else {
|
||||
printf("error (%x)\n", chp->ch_error);
|
||||
ata_bio->r_error = chp->ch_error;
|
||||
ata_bio->error = ERROR;
|
||||
}
|
||||
drvp->state = 0;
|
||||
wdc_ata_bio_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
wdc_ata_err(chp, ata_bio)
|
||||
struct channel_softc *chp;
|
||||
struct ata_bio *ata_bio;
|
||||
{
|
||||
ata_bio->error = 0;
|
||||
if (chp->ch_status & WDCS_BSY) {
|
||||
ata_bio->error = TIMEOUT;
|
||||
return WDC_ATA_ERR;
|
||||
}
|
||||
|
||||
if (chp->ch_status & WDCS_DWF) {
|
||||
ata_bio->error = ERR_DF;
|
||||
return WDC_ATA_ERR;
|
||||
}
|
||||
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
ata_bio->error = ERROR;
|
||||
ata_bio->r_error = chp->ch_error;
|
||||
if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
|
||||
WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
|
||||
return WDC_ATA_ERR;
|
||||
return WDC_ATA_NOERR;
|
||||
}
|
||||
|
||||
if (chp->ch_status & WDCS_CORR)
|
||||
ata_bio->flags |= ATA_CORR;
|
||||
return WDC_ATA_NOERR;
|
||||
}
|
139
sys/dev/ata/atareg.h
Normal file
139
sys/dev/ata/atareg.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* $NetBSD: atareg.h,v 1.2 1998/10/12 16:09:15 bouyer Exp $ */
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* Drive parameter structure for ATA/ATAPI.
|
||||
* Bit fields: WDC_* : common to ATA/ATAPI
|
||||
* ATA_* : ATA only
|
||||
* ATAPI_* : ATAPI only.
|
||||
*/
|
||||
struct ataparams {
|
||||
/* drive info */
|
||||
u_int16_t atap_config; /* 0: general configuration */
|
||||
#define WDC_CFG_ATAPI_MASK 0xc000
|
||||
#define WDC_CFG_ATAPI 0x8000
|
||||
#define ATA_CFG_REMOVABLE 0x0080
|
||||
#define ATA_CFG_FIXED 0x0040
|
||||
#define ATAPI_CFG_TYPE_MASK 0x1f00
|
||||
#define ATAPI_CFG_TYPE(x) (((x) & ATAPI_CFG_TYPE_MASK) >> 8)
|
||||
#define ATAPI_CFG_REMOV 0x0080
|
||||
#define ATAPI_CFG_DRQ_MASK 0x0060
|
||||
#define ATAPI_CFG_STD_DRQ 0x0000
|
||||
#define ATAPI_CFG_IRQ_DRQ 0x0020
|
||||
#define ATAPI_CFG_ACCEL_DRQ 0x0040
|
||||
#define ATAPI_CFG_CMD_MASK 0x0003
|
||||
#define ATAPI_CFG_CMD_12 0x0000
|
||||
#define ATAPI_CFG_CMD_16 0x0001
|
||||
/* words 1-9 are ATA only */
|
||||
u_int16_t atap_cylinders; /* 1: # of non-removable cylinders */
|
||||
u_int16_t __reserved1;
|
||||
u_int16_t atap_heads; /* 3: # of heads */
|
||||
u_int16_t __retired1[2]; /* 4-5: # of unform. bytes/track */
|
||||
u_int16_t atap_sectors; /* 6: # of sectors */
|
||||
u_int16_t __retired2[3];
|
||||
|
||||
u_int8_t atap_serial[20]; /* 10-19: serial number */
|
||||
u_int16_t __retired3[2];
|
||||
u_int16_t __obsolete1;
|
||||
u_int8_t atap_revision[8]; /* 23-26: firmware revision */
|
||||
u_int8_t atap_model[40]; /* 27-46: model number */
|
||||
u_int16_t atap_multi; /* 47: maximum sectors per irq (ATA) */
|
||||
u_int16_t __reserved2;
|
||||
u_int16_t atap_capabilities1; /* 49: capability flags */
|
||||
#define WDC_CAP_IORDY 0x0800
|
||||
#define WDC_CAP_IORDY_DSBL 0x0400
|
||||
#define WDC_CAP_LBA 0x0200
|
||||
#define WDC_CAP_DMA 0x0100
|
||||
#define ATA_CAP_STBY 0x2000
|
||||
#define ATAPI_CAP_INTERL_DMA 0x8000
|
||||
#define ATAPI_CAP_CMD_QUEUE 0x4000
|
||||
#define ATAPI_CAP_OVERLP 0X2000
|
||||
#define ATAPI_CAP_ATA_RST 0x1000
|
||||
u_int16_t atap_capabilities2; /* 50: capability flags (ATA) */
|
||||
u_int8_t __junk2;
|
||||
u_int8_t atap_oldpiotiming; /* 51: old PIO timing mode */
|
||||
u_int8_t __junk3;
|
||||
u_int8_t atap_olddmatiming; /* 52: old DMA timing mode (ATA) */
|
||||
u_int16_t atap_extensions; /* 53: extentions supported */
|
||||
#define WDC_EXT_UDMA_MODES 0x0004
|
||||
#define WDC_EXT_MODES 0x0002
|
||||
#define WDC_EXT_GEOM 0x0001
|
||||
/* words 54-62 are ATA only */
|
||||
u_int16_t atap_curcylinders; /* 54: current logical cyliners */
|
||||
u_int16_t atap_curheads; /* 55: current logical heads */
|
||||
u_int16_t atap_cursectors; /* 56: current logical sectors/tracks */
|
||||
u_int16_t atap_curcapacity[2]; /* 57-58: current capacity */
|
||||
u_int16_t atap_curmulti; /* 59: current multi-sector setting */
|
||||
#define WDC_MULTI_VALID 0x0100
|
||||
#define WDC_MULTI_MASK 0x00ff
|
||||
u_int16_t atap_capacity[2]; /* 60-61: total capacity (LBA only) */
|
||||
u_int16_t __retired4;
|
||||
u_int8_t atap_dmamode_supp; /* 63: multiword DMA mode supported */
|
||||
u_int8_t atap_dmamode_act; /* multiword DMA mode active */
|
||||
u_int8_t atap_piomode_supp; /* 64: PIO mode supported */
|
||||
u_int8_t __junk4;
|
||||
u_int16_t atap_dmatiming_mimi; /* 65: minimum DMA cycle time */
|
||||
u_int16_t atap_dmatiming_recom; /* 66: recomended DMA cycle time */
|
||||
u_int16_t atap_piotiming; /* 67: mini PIO cycle time without FC */
|
||||
u_int16_t atap_piotiming_iordy; /* 68: mini PIO cycle time with IORDY FC */
|
||||
u_int16_t __reserved3[2];
|
||||
/* words 71-72 are ATAPI only */
|
||||
u_int16_t atap_pkt_br; /* 71: time (ns) to bus release */
|
||||
u_int16_t atap_pkt_bsyclr; /* 72: tme to clear BSY after service */
|
||||
u_int16_t __reserved4[2];
|
||||
u_int16_t atap_queuedepth; /* 75: */
|
||||
#define WDC_QUEUE_DEPTH_MASK 0x0F
|
||||
u_int16_t __reserved5[4];
|
||||
u_int16_t atap_ata_major; /* 80: Major version number */
|
||||
#define WDC_VER_ATA1 0x0002
|
||||
#define WDC_VER_ATA2 0x0004
|
||||
#define WDC_VER_ATA3 0x0008
|
||||
#define WDC_VER_ATA4 0x0010
|
||||
u_int16_t atap_ata_minor; /* 81: Minor version number */
|
||||
u_int16_t atap_cmd_set1; /* 82: command set suported */
|
||||
#define WDC_CMD1_NOP 0x4000
|
||||
#define WDC_CMD1_RB 0x2000
|
||||
#define WDC_CMD1_WB 0x1000
|
||||
#define WDC_CMD1_HPA 0x0400
|
||||
#define WDC_CMD1_DVRST 0x0200
|
||||
#define WDC_CMD1_SRV 0x0100
|
||||
#define WDC_CMD1_RLSE 0x0080
|
||||
#define WDC_CMD1_AHEAD 0x0040
|
||||
#define WDC_CMD1_CACHE 0x0020
|
||||
#define WDC_CMD1_PKT 0x0010
|
||||
#define WDC_CMD1_PM 0x0008
|
||||
#define WDC_CMD1_REMOV 0x0004
|
||||
#define WDC_CMD1_SEC 0x0002
|
||||
#define WDC_CMD1_SMART 0x0001
|
||||
u_int16_t atap_cmd_set2; /* 83: command set suported */
|
||||
#define WDC_CMD2_RMSN 0x0010
|
||||
#define WDC_CMD2_DM 0x0001
|
||||
#define ATA_CMD2_APM 0x0008
|
||||
#define ATA_CMD2_CFA 0x0004
|
||||
#define ATA_CMD2_RWQ 0x0002
|
||||
u_int16_t atap_cmd_ext; /* 84: command/features supp. ext. */
|
||||
u_int16_t atap_cmd1_en; /* 85: cmd/features enabled */
|
||||
/* bits are the same as atap_cmd_set1 */
|
||||
u_int16_t atap_cmd2_en; /* 86: cmd/features enabled */
|
||||
/* bits are the same as atap_cmd_set2 */
|
||||
u_int16_t atap_cmd_def; /* 87: cmd/features default */
|
||||
u_int8_t atap_udmamode_supp; /* 88: Ultra-DMA mode supported */
|
||||
u_int8_t atap_udmamode_act; /* Ultra-DMA mode active */
|
||||
/* 89-92 are ATA-only */
|
||||
u_int16_t atap_seu_time; /* 89: Sec. Erase Unit compl. time */
|
||||
u_int16_t atap_eseu_time; /* 90: Enhanced SEU compl. time */
|
||||
u_int16_t atap_apm_val; /* 91: current APM value */
|
||||
u_int16_t __reserved6[35]; /* 92-126: reserved */
|
||||
u_int16_t atap_rmsn_supp; /* 127: remov. media status notif. */
|
||||
#define WDC_RMSN_SUPP_MASK 0x0003
|
||||
#define WDC_RMSN_SUPP 0x0001
|
||||
u_int16_t atap_sec_st; /* 128: security status */
|
||||
#define WDC_SEC_LEV_MAX 0x0100
|
||||
#define WDC_SEC_ESE_SUPP 0x0020
|
||||
#define WDC_SEC_EXP 0x0010
|
||||
#define WDC_SEC_FROZEN 0x0008
|
||||
#define WDC_SEC_LOCKED 0x0004
|
||||
#define WDC_SEC_EN 0x0002
|
||||
#define WDC_SEC_SUPP 0x0001
|
||||
};
|
||||
#endif /* _KERNEL */
|
135
sys/dev/ata/atavar.h
Normal file
135
sys/dev/ata/atavar.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* $NetBSD: atavar.h,v 1.2 1998/10/12 16:09:15 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Hight-level functions and structures used by both ATA and ATAPI devices */
|
||||
|
||||
/* Datas common to drives and controller drivers */
|
||||
struct ata_drive_datas {
|
||||
u_int8_t drive; /* drive number */
|
||||
u_int8_t drive_flags; /* bitmask for drives present/absent and cap */
|
||||
#define DRIVE_ATA 0x01
|
||||
#define DRIVE_ATAPI 0x02
|
||||
#define DRIVE (DRIVE_ATA|DRIVE_ATAPI)
|
||||
#define DRIVE_CAP32 0x04
|
||||
#define DRIVE_DMA 0x08
|
||||
#define DRIVE_UDMA 0x10
|
||||
/*
|
||||
* Current setting of drive's PIO, DMA and UDMA modes.
|
||||
* Is initialised by the disks drivers at attach time, and may be
|
||||
* changed later by the controller's code if needed
|
||||
*/
|
||||
u_int8_t PIO_mode; /* Current setting of drive's PIO mode */
|
||||
u_int8_t DMA_mode; /* Current setting of drive's DMA mode */
|
||||
u_int8_t UDMA_mode; /* Current setting of drive's UDMA mode */
|
||||
/*
|
||||
* Drive state. This is drive-type (ATA or ATAPI) dependant
|
||||
* This is reset to 0 after a channel reset.
|
||||
*/
|
||||
u_int8_t state;
|
||||
|
||||
struct device *drv_softc; /* ATA drives softc, if any */
|
||||
void* chnl_softc; /* channel softc */
|
||||
};
|
||||
|
||||
/* ATA/ATAPI common attachement datas */
|
||||
struct ata_atapi_attach {
|
||||
u_int8_t aa_type; /* Type of device */
|
||||
#define T_ATA 0
|
||||
#define T_ATAPI 1
|
||||
u_int8_t aa_channel; /* controller's channel */
|
||||
u_int8_t aa_openings; /* Number of simultaneous commands possible */
|
||||
struct ata_drive_datas *aa_drv_data;
|
||||
void *aa_bus_private; /* infos specifics to this bus */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ATA/ATAPI commands description
|
||||
*
|
||||
* This structure defines the interface between the ATA/ATAPI device driver
|
||||
* and the controller for short commands. It contains the command's parameter,
|
||||
* the len of data's to read/write (if any), and a function to call upon
|
||||
* completion.
|
||||
* If no sleep is allowed, the driver can poll for command completion.
|
||||
* Once the command completed, if the error registed is valid, the flag
|
||||
* AT_ERROR is set and the error register value is copied to r_error .
|
||||
* A separate interface is needed for read/write or ATAPI packet commands
|
||||
* (which need multiple interrupts per commands).
|
||||
*/
|
||||
struct wdc_command {
|
||||
u_int8_t r_command; /* Parameters to upload to registers */
|
||||
u_int8_t r_head;
|
||||
u_int16_t r_cyl;
|
||||
u_int8_t r_sector;
|
||||
u_int8_t r_count;
|
||||
u_int8_t r_precomp;
|
||||
u_int8_t r_st_bmask; /* status register mask to wait for before command */
|
||||
u_int8_t r_st_pmask; /* status register mask to wait for after command */
|
||||
u_int8_t r_error; /* error register after command done */
|
||||
volatile u_int16_t flags;
|
||||
#define AT_READ 0x0001 /* There is data to read */
|
||||
#define AT_WRITE 0x0002 /* There is data to write (excl. with AT_READ) */
|
||||
#define AT_WAIT 0x0008 /* wait in controller code for command completion */
|
||||
#define AT_POLL 0x0010 /* poll for command completion (no interrupts) */
|
||||
#define AT_DONE 0x0020 /* command is done */
|
||||
#define AT_ERROR 0x0040 /* command is done with error */
|
||||
#define AT_TIMEOU 0x0040 /* command timed out */
|
||||
#define AT_DF 0x0080 /* Drive fault */
|
||||
int timeout; /* timeout (in ms) */
|
||||
void *data; /* Data buffer address */
|
||||
int bcount; /* number of bytes to transfer */
|
||||
void (*callback) __P((void*)); /* command to call once command completed */
|
||||
void *callback_arg; /* argument passed to *callback() */
|
||||
};
|
||||
|
||||
int wdc_exec_command __P((struct ata_drive_datas *, struct wdc_command*));
|
||||
#define WDC_COMPLETE 0x01
|
||||
#define WDC_QUEUED 0x02
|
||||
#define WDC_TRY_AGAIN 0x03
|
||||
|
||||
void wdc_probe_caps __P((struct ata_drive_datas*));
|
||||
|
||||
void wdc_reset_channel __P((struct ata_drive_datas *));
|
||||
|
||||
struct ataparams;
|
||||
int ata_get_params __P((struct ata_drive_datas*, u_int8_t,
|
||||
struct ataparams *));
|
||||
int ata_set_mode __P((struct ata_drive_datas*, u_int8_t, u_int8_t));
|
||||
/* return code for these cmds */
|
||||
#define CMD_OK 0
|
||||
#define CMD_ERR 1
|
||||
#define CMD_AGAIN 2
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.ata,v 1.2 1998/02/16 22:12:50 thorpej Exp $
|
||||
# $NetBSD: files.ata,v 1.3 1998/10/12 16:09:16 bouyer Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent devices
|
||||
# which attach to ATA busses. Included by ports that need it. Ports
|
||||
@ -9,3 +9,6 @@
|
||||
device wd: disk
|
||||
attach wd at ata
|
||||
file dev/ata/wd.c wd needs-flag
|
||||
file dev/ata/ata_wdc.c wd & wdc_base
|
||||
|
||||
file dev/ata/ata.c ata | atapi
|
||||
|
829
sys/dev/ata/wd.c
829
sys/dev/ata/wd.c
File diff suppressed because it is too large
Load Diff
@ -1,134 +0,0 @@
|
||||
/* $NetBSD: wdlink.h,v 1.8 1998/08/15 10:10:48 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum and by Onno van der Linden.
|
||||
*
|
||||
* 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 NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX THIS FILE NEEDS TO BE GUTTED, AND TURNED INTO A REAL 'ATA'/'ATAPI'
|
||||
* XXX INTERFACE FILE.
|
||||
*/
|
||||
|
||||
#undef WDDEBUG
|
||||
/* #undef DIAGNOSTIC */
|
||||
|
||||
struct wd_link {
|
||||
u_int8_t type;
|
||||
#define ATA 0
|
||||
#define ATAPI 1
|
||||
u_int8_t channel;
|
||||
u_int8_t drive;
|
||||
caddr_t wdc_softc;
|
||||
caddr_t wd_softc;
|
||||
struct wdparams sc_params;
|
||||
|
||||
/* Long-term state: */
|
||||
u_int8_t openings;
|
||||
int sc_state; /* control state */
|
||||
#define RECAL 0 /* recalibrate */
|
||||
#define RECAL_WAIT 1 /* done recalibrating */
|
||||
#define GEOMETRY 2 /* upload geometry */
|
||||
#define GEOMETRY_WAIT 3 /* done uploading geometry */
|
||||
#define MULTIMODE 4 /* set multiple mode */
|
||||
#define MULTIMODE_WAIT 5 /* done setting multiple mode */
|
||||
#define READY 6 /* done with open */
|
||||
int sc_mode; /* transfer mode */
|
||||
#define WDM_PIOSINGLE 0 /* single-sector PIO */
|
||||
#define WDM_PIOMULTI 1 /* multi-sector PIO */
|
||||
#define WDM_DMA 2 /* DMA */
|
||||
int sc_multiple; /* multiple for WDM_PIOMULTI */
|
||||
int sc_flags; /* drive characteistics found */
|
||||
#define WDF_LOCKED 0x01
|
||||
#define WDF_WANTED 0x02
|
||||
#define WDF_WLABEL 0x04 /* label is writable */
|
||||
#define WDF_LABELLING 0x08 /* writing label */
|
||||
/*
|
||||
* XXX Nothing resets this yet, but disk change sensing will when ATA-4 is
|
||||
* more fully implemented.
|
||||
*/
|
||||
#define WDF_LOADED 0x10 /* parameters loaded */
|
||||
#define WDF_WAIT 0x20 /* waiting for resources */
|
||||
#define WDF_LBA 0x40 /* using LBA mode */
|
||||
int sc_capacity;
|
||||
|
||||
daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */
|
||||
struct disklabel *sc_lp; /* label info for this disk */
|
||||
};
|
||||
|
||||
struct wdc_xfer {
|
||||
struct wd_link *d_link; /* drive/bus structure info */
|
||||
volatile long c_flags; /* handle: scsi flags (0x0000ffff)
|
||||
b_read/b_write (0x00f00000)
|
||||
controllers flags (0x000f0000) */
|
||||
#define C_INUSE 0x010000
|
||||
#define C_ATAPI 0x020000
|
||||
#define C_ERROR 0x040000
|
||||
#define C_NEEDDONE 0x080000
|
||||
|
||||
/* Information about the current transfer */
|
||||
struct buf *c_bp;
|
||||
void *atapi_cmd;
|
||||
void *databuf;
|
||||
daddr_t c_blkno; /* starting block number */
|
||||
int c_bcount; /* byte count left */
|
||||
int c_skip; /* bytes already transferred */
|
||||
int c_nblks; /* number of blocks currently transferring */
|
||||
int c_nbytes; /* number of bytes currently transferring */
|
||||
TAILQ_ENTRY(wdc_xfer) c_xferchain;
|
||||
LIST_ENTRY(wdc_xfer) free_list;
|
||||
};
|
||||
|
||||
void wdc_exec_xfer __P((struct wdc_softc *, struct wd_link *,
|
||||
struct wdc_xfer *));
|
||||
struct wdc_xfer *wdc_get_xfer __P((int));
|
||||
int wdc_get_parms __P((struct wdc_softc *, struct wd_link *));
|
||||
void wdstart __P((void*));
|
||||
void wderror __P((struct wd_link* , struct buf *, char *));
|
||||
void wddone __P((struct wd_link*, struct buf*));
|
||||
int wdccommand __P((struct wdc_softc *, struct wd_link *, int, int,
|
||||
int, int, int, int));
|
||||
int wdccommandshort __P((struct wdc_softc *, int, int));
|
||||
int wdcwait __P((struct wdc_softc *, int));
|
||||
|
||||
/*
|
||||
* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
|
||||
* command is aborted.
|
||||
*/
|
||||
#define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
|
||||
#define wait_for_unbusy(d) wdcwait(d, 0)
|
||||
#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
|
||||
#define atapi_ready(d) wdcwait(d, WDCS_DRQ)
|
||||
|
||||
#define IDE_NOSLEEP 0x01
|
79
sys/dev/ata/wdvar.h
Normal file
79
sys/dev/ata/wdvar.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* $NetBSD: wdvar.h,v 1.2 1998/10/12 16:09:17 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Params needed by the controller to perform an ATA bio */
|
||||
struct ata_bio {
|
||||
volatile u_int16_t flags; /* cmd flags */
|
||||
#define ATA_NOSLEEP 0x0001 /* Can't sleep */
|
||||
#define ATA_POLL 0x0002 /* poll for completion */
|
||||
#define ATA_ITSDONE 0x0004 /* the transfer is as done as it gets */
|
||||
#define ATA_SINGLE 0x0008 /* transfer has to be done in single-sector mode */
|
||||
#define ATA_LBA 0x0010 /* tranfert uses LBA adressing */
|
||||
#define ATA_READ 0x0020 /* tranfert is a read (otherwise a write) */
|
||||
#define ATA_CORR 0x0040 /* transfert had a corrected error */
|
||||
int multi; /* number of blocks to transfert in multi-mode */
|
||||
struct disklabel *lp; /* pointer to drive's label info */
|
||||
daddr_t blkno; /* block addr */
|
||||
daddr_t blkdone; /* number of blks transfered */
|
||||
daddr_t nblks; /* number of block currently transfering */
|
||||
int nbytes; /* number of bytes currently transfering */
|
||||
long bcount; /* total number of bytes */
|
||||
char* databuf; /* data buffer adress */
|
||||
volatile int error;
|
||||
#define NOERROR 0 /* There was no error (r_error invalid) */
|
||||
#define ERROR 1 /* check r_error */
|
||||
#define ERR_DF 2 /* Drive fault */
|
||||
#define ERR_DMA 3 /* DMA error */
|
||||
#define TIMEOUT 4 /* device timed out */
|
||||
u_int8_t r_error; /* copy of error register */
|
||||
daddr_t badsect[127]; /* 126 plus trailing -1 marker */
|
||||
};
|
||||
|
||||
/* drive states stored in ata_drive_datas */
|
||||
#define RECAL 0
|
||||
#define RECAL_WAIT 1
|
||||
#define PIOMODE 2
|
||||
#define PIOMODE_WAIT 3
|
||||
#define DMAMODE 4
|
||||
#define DMAMODE_WAIT 5
|
||||
#define GEOMETRY 6
|
||||
#define GEOMETRY_WAIT 7
|
||||
#define MULTIMODE 8
|
||||
#define MULTIMODE_WAIT 9
|
||||
#define READY 10
|
||||
|
||||
int wdc_ata_bio __P((struct ata_drive_datas*, struct ata_bio*));
|
||||
|
||||
void wddone __P((void *));
|
2517
sys/dev/ic/wdc.c
2517
sys/dev/ic/wdc.c
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdcreg.h,v 1.17 1998/04/26 05:28:24 mycroft Exp $ */
|
||||
/* $NetBSD: wdcreg.h,v 1.18 1998/10/12 16:09:18 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
@ -46,7 +46,7 @@
|
||||
#define wd_data 0 /* data register (R/W - 16 bits) */
|
||||
#define wd_error 1 /* error register (R) */
|
||||
#define wd_precomp 1 /* write precompensation (W) */
|
||||
#define wd_features 1 /* features (W) */
|
||||
#define wd_features 1 /* features (W), same as wd_precomp */
|
||||
#define wd_seccnt 2 /* sector count (R/W) */
|
||||
#define wd_ireason 2 /* interrupt reason (R/W) (for atapi) */
|
||||
#define wd_sector 3 /* first sector number (R/W) */
|
||||
@ -95,6 +95,7 @@
|
||||
/*
|
||||
* Commands for Disk Controller.
|
||||
*/
|
||||
#define WDCC_NOP 0x00 /* NOP - Always fail with "aborted command" */
|
||||
#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */
|
||||
|
||||
#define WDCC_READ 0x20 /* disk read code */
|
||||
@ -118,23 +119,45 @@
|
||||
#define WDCC_UNLOCK 0xdf /* unlock drawer */
|
||||
|
||||
#define WDCC_IDENTIFY 0xec /* read parameters from controller */
|
||||
#define WDCC_CACHEC 0xef /* cache control */
|
||||
#define SET_FEATURES 0xef /* set features */
|
||||
|
||||
/* Subcommands for SET_FEATURES (features register ) */
|
||||
#define WDSF_EN_WR_CACHE 0x02
|
||||
#define WDSF_SET_MODE 0x03
|
||||
#define WDSF_REASSIGN_EN 0x04
|
||||
#define WDSF_RETRY_DS 0x33
|
||||
#define WDSF_SET_CACHE_SGMT 0x54
|
||||
#define WDSF_READAHEAD_DS 0x55
|
||||
#define WDSF_POD_DS 0x66
|
||||
#define WDSF_ECC_DS 0x77
|
||||
#define WDSF_WRITE_CACHE_DS 0x82
|
||||
#define WDSF_REASSIGN_DS 0x84
|
||||
#define WDSF_ECC_EN 0x88
|
||||
#define WDSF_RETRY_EN 0x99
|
||||
#define WDSF_SET_CURRENT 0x9A
|
||||
#define WDSF_READAHEAD_EN 0xAA
|
||||
#define WDSF_PREFETCH_SET 0xAB
|
||||
#define WDSF_POD_EN 0xCC
|
||||
|
||||
/* parameters uploaded to device/heads register */
|
||||
#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */
|
||||
#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */
|
||||
#define WDSD_LBA 0x40 /* logical block addressing */
|
||||
|
||||
/* Commands for ATAPI devices */
|
||||
#define ATAPI_CHECK_POWER_MODE 0xe5
|
||||
#define ATAPI_EXEC_DRIVE_DIAGS 0x90
|
||||
#define ATAPI_IDLE_IMMEDIATE 0xe1
|
||||
#define ATAPI_NOP 0x00
|
||||
#define ATAPI_PACKET_COMMAND 0xa0
|
||||
#define ATAPI_IDENTIFY_DEVICE 0xa1
|
||||
#define ATAPI_SOFT_RESET 0x08
|
||||
#define ATAPI_SET_FEATURES 0xef
|
||||
#define ATAPI_SLEEP 0xe6
|
||||
#define ATAPI_STANDBY_IMMEDIATE 0xe0
|
||||
#define ATAPI_CHECK_POWER_MODE 0xe5
|
||||
#define ATAPI_EXEC_DRIVE_DIAGS 0x90
|
||||
#define ATAPI_IDLE_IMMEDIATE 0xe1
|
||||
#define ATAPI_NOP 0x00
|
||||
#define ATAPI_PKT_CMD 0xa0
|
||||
#define ATAPI_IDENTIFY_DEVICE 0xa1
|
||||
#define ATAPI_SOFT_RESET 0x08
|
||||
#define ATAPI_SLEEP 0xe6
|
||||
#define ATAPI_STANDBY_IMMEDIATE 0xe0
|
||||
|
||||
/* Bytes used by ATAPI_PACKET_COMMAND ( feature register) */
|
||||
#define ATAPI_PKT_CMD_FTRE_DMA 0x01
|
||||
#define ATAPI_PKT_CMD_FTRE_OVL 0x02
|
||||
|
||||
/* ireason */
|
||||
#define WDCI_CMD 0x01 /* command(1) or data(0) */
|
||||
@ -147,56 +170,3 @@
|
||||
#define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
|
||||
#define PHASE_ABORTED 0
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* read parameters command returns this:
|
||||
*/
|
||||
struct wdparams {
|
||||
/* drive info */
|
||||
u_short wdp_config; /* general configuration */
|
||||
#define WD_CFG_REMOVABLE 0x0080
|
||||
#define WD_CFG_FIXED 0x0040
|
||||
u_short wdp_cylinders; /* number of non-removable cylinders */
|
||||
u_short __reserved1;
|
||||
u_short wdp_heads; /* number of heads */
|
||||
u_short __retired1[2]; /* number of unformatted bytes/track */
|
||||
u_short wdp_sectors; /* number of sectors */
|
||||
u_short __retired2[3];
|
||||
char wdp_serial[20]; /* serial number */
|
||||
u_short __retired3[2];
|
||||
u_short __obsolete1;
|
||||
char wdp_revision[8]; /* firmware revision */
|
||||
char wdp_model[40]; /* model name */
|
||||
u_short wdp_multi; /* maximum sectors per interrupt */
|
||||
u_short __reserved2;
|
||||
u_short wdp_capabilities1; /* capability flags */
|
||||
#define WD_CAP_LBA 0x0200
|
||||
#define WD_CAP_DMA 0x0100
|
||||
u_short wdp_capabilities2;
|
||||
char __junk2;
|
||||
char wdp_oldpiotiming; /* PIO timing mode */
|
||||
char __junk3;
|
||||
char wdp_olddmatiming; /* DMA timing mode */
|
||||
u_short wdp_extensions;
|
||||
u_short wdp_curcylinders;
|
||||
u_short wdp_curheads;
|
||||
u_short wdp_cursectors;
|
||||
u_short wdp_curcapacity[2];
|
||||
u_short wdp_curmulti;
|
||||
u_short wdp_capacity[2];
|
||||
u_short __retired4;
|
||||
u_short wdp_dmamode;
|
||||
u_short wdp_piomode;
|
||||
u_short wdp_dmatiming[2];
|
||||
u_short wdp_piotiming[2];
|
||||
u_short __reserved3[6];
|
||||
u_short wdp_queuedepth;
|
||||
u_short __reserved4[4];
|
||||
u_short wdp_ataversion;
|
||||
#define WD_VER_ATA1 0x0002
|
||||
#define WD_VER_ATA2 0x0004
|
||||
#define WD_VER_ATA3 0x0008
|
||||
#define WD_VER_ATA4 0x0010
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdcvar.h,v 1.5 1998/09/22 00:21:16 mark Exp $ */
|
||||
/* $NetBSD: wdcvar.h,v 1.6 1998/10/12 16:09:18 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -11,10 +11,10 @@
|
||||
* 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.
|
||||
* 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.
|
||||
* 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 NetBSD
|
||||
@ -36,74 +36,141 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
struct wdc_attachment_data {
|
||||
/* manadatory fields */
|
||||
int cap;
|
||||
int flags;
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ioh;
|
||||
bus_space_tag_t auxiot;
|
||||
bus_space_handle_t auxioh;
|
||||
#define WAITTIME (10 * hz) /* time to wait for a completion */
|
||||
/* this is a lot for hard drives, but not for cdroms */
|
||||
|
||||
struct channel_queue { /* per channel queue (may be shared) */
|
||||
TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
|
||||
};
|
||||
|
||||
struct channel_softc { /* Per channel data */
|
||||
/* Our location */
|
||||
int channel;
|
||||
/* Our controller's softc */
|
||||
struct wdc_softc *wdc;
|
||||
/* Our registers */
|
||||
bus_space_tag_t cmd_iot;
|
||||
bus_space_handle_t cmd_ioh;
|
||||
bus_space_tag_t ctl_iot;
|
||||
bus_space_handle_t ctl_ioh;
|
||||
/* data32{iot,ioh} are only used for 32 bit xfers */
|
||||
bus_space_tag_t data32iot;
|
||||
bus_space_handle_t data32ioh;
|
||||
bus_space_tag_t data32iot;
|
||||
bus_space_handle_t data32ioh;
|
||||
/* Our state */
|
||||
int ch_flags;
|
||||
#define WDCF_ACTIVE 0x01 /* channel is active */
|
||||
#define WDCF_IRQ_WAIT 0x10 /* controller is waiting for irq */
|
||||
u_int8_t ch_status; /* copy of status register */
|
||||
u_int8_t ch_error; /* copy of error register */
|
||||
/* per-drive infos */
|
||||
struct ata_drive_datas ch_drive[2];
|
||||
|
||||
/*
|
||||
* channel queues. May be the same for all channels, if hw channels
|
||||
* are not independants
|
||||
*/
|
||||
struct channel_queue *ch_queue;
|
||||
};
|
||||
|
||||
struct wdc_softc { /* Per controller state */
|
||||
struct device sc_dev;
|
||||
/* mandatory fields */
|
||||
int cap;
|
||||
/* Capabilities supported by the controller */
|
||||
#define WDC_CAPABILITY_DATA16 0x0001 /* can do 16-bit data access */
|
||||
#define WDC_CAPABILITY_DATA32 0x0002 /* can do 32-bit data access */
|
||||
#define WDC_CAPABILITY_MODE 0x0004 /* controller knows its PIO/DMA modes */
|
||||
#define WDC_CAPABILITY_DMA 0x0008 /* DMA */
|
||||
#define WDC_CAPABILITY_UDMA 0x0010 /* Ultra-DMA/33 */
|
||||
#define WDC_CAPABILITY_HWLOCK 0x0020 /* Needs to lock HW */
|
||||
#define WDC_CAPABILITY_ATA_NOSTREAM 0x0040 /* Don't use stream funcs on ATA */
|
||||
#define WDC_CAPABILITY_ATAPI_NOSTREAM 0x0080 /* Don't use stream f on ATAPI */
|
||||
#define WDC_CAPABILITY_NO_EXTRA_RESETS 0x0100 /* only reset once */
|
||||
u_int8_t pio_mode; /* highest PIO mode supported */
|
||||
u_int8_t dma_mode; /* highest DMA mode supported */
|
||||
int nchannels; /* Number of channels on this controller */
|
||||
struct channel_softc *channels; /* channels-specific datas (array) */
|
||||
|
||||
/* if WDC_CAPABILITY_DMA set in 'cap' */
|
||||
void *dma_arg;
|
||||
void (*dma_setup) __P((void *));
|
||||
void (*dma_start) __P((void *, void *, size_t,
|
||||
int));
|
||||
void (*dma_finish) __P((void *));
|
||||
void *dma_arg;
|
||||
int (*dma_init) __P((void *, int, int, void *, size_t,
|
||||
int));
|
||||
void (*dma_start) __P((void *, int, int, int));
|
||||
int (*dma_finish) __P((void *, int, int, int));
|
||||
/* flags passed to DMA functions */
|
||||
#define WDC_DMA_READ 0x01
|
||||
#define WDC_DMA_POLL 0x02
|
||||
|
||||
/* if WDC_CAPABILITY_HWLOCK set in 'cap' */
|
||||
int (*claim_hw) __P((void *, int));
|
||||
void (*free_hw) __P((void *));
|
||||
int (*claim_hw) __P((void *, int));
|
||||
void (*free_hw) __P((void *));
|
||||
};
|
||||
|
||||
/* Capabilities supported by the controller */
|
||||
#define WDC_CAPABILITY_DATA32 0x01 /* 32-bit data access */
|
||||
#define WDC_CAPABILITY_DMA 0x02 /* DMA */
|
||||
#define WDC_CAPABILITY_HWLOCK 0x04 /* Needs to lock HW */
|
||||
/*
|
||||
* Description of a command to be handled by a controller.
|
||||
* These commands are queued in a list.
|
||||
*/
|
||||
struct wdc_xfer {
|
||||
volatile u_int c_flags;
|
||||
#define C_INUSE 0x0001 /* xfer struct is in use */
|
||||
#define C_ATAPI 0x0002 /* xfer is ATAPI request */
|
||||
#define C_TIMEOU 0x0004 /* xfer processing timed out */
|
||||
#define C_NEEDDONE 0x0010 /* need to call upper-level done */
|
||||
#define C_POLL 0x0020 /* cmd is polled */
|
||||
#define C_DMA 0x0040 /* cmd uses DMA */
|
||||
|
||||
/* Flags passed from the attach routine to the wdc driver */
|
||||
#define WDC_NO_EXTRA_RESETS 0x01 /* Only reset once at attach */
|
||||
/* Information about our location */
|
||||
u_int8_t drive;
|
||||
u_int8_t channel;
|
||||
|
||||
struct wdc_softc {
|
||||
struct device sc_dev;
|
||||
const struct wdc_attachment_data *sc_adp;
|
||||
|
||||
struct wd_link *d_link[2];
|
||||
struct scsipi_link *ab_link;
|
||||
|
||||
TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
|
||||
int sc_flags;
|
||||
#define WDCF_ACTIVE 0x01 /* controller is active */
|
||||
#define WDCF_SINGLE 0x02 /* sector at a time mode */
|
||||
#define WDCF_ERROR 0x04 /* processing a disk error */
|
||||
#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
|
||||
#define WDCF_IRQ_WAIT 0x10 /* controller is waiting for irq */
|
||||
#define WDCF_ONESLAVE 0x20 /* ctrl. has one ATAPI slave attached */
|
||||
int sc_errors; /* errors during current transfer */
|
||||
u_char sc_status; /* copy of status register */
|
||||
u_char sc_error; /* copy of error register */
|
||||
u_char sc_drives_mask; /* bitmask for drives present/absent */
|
||||
/* Information about the current transfer */
|
||||
void *cmd; /* wdc, ata or scsipi command structure */
|
||||
void *databuf;
|
||||
int c_bcount; /* byte count left */
|
||||
int c_skip; /* bytes already transferred */
|
||||
TAILQ_ENTRY(wdc_xfer) c_xferchain;
|
||||
LIST_ENTRY(wdc_xfer) free_list;
|
||||
void (*c_start) __P((struct channel_softc *, struct wdc_xfer *));
|
||||
int (*c_intr) __P((struct channel_softc *, struct wdc_xfer *));
|
||||
};
|
||||
|
||||
#define sc_cap sc_adp->cap
|
||||
#define sc_iot sc_adp->iot
|
||||
#define sc_ioh sc_adp->ioh
|
||||
#define sc_auxiot sc_adp->auxiot
|
||||
#define sc_auxioh sc_adp->auxioh
|
||||
#define sc_data32iot sc_adp->data32iot
|
||||
#define sc_data32ioh sc_adp->data32ioh
|
||||
#define sc_dma_arg sc_adp->dma_arg
|
||||
#define sc_dma_setup sc_adp->dma_setup
|
||||
#define sc_dma_start sc_adp->dma_start
|
||||
#define sc_dma_finish sc_adp->dma_finish
|
||||
#define sc_claim_hw sc_adp->claim_hw
|
||||
#define sc_free_hw sc_adp->free_hw
|
||||
/*
|
||||
* Public functions which can be called by ATA or ATAPI specific parts,
|
||||
* or bus-specific backends.
|
||||
*/
|
||||
|
||||
void wdcattach(struct wdc_softc *, const struct wdc_attachment_data *);
|
||||
int wdcintr(void *);
|
||||
int wdcprobe(const struct wdc_attachment_data *);
|
||||
int wdcprobe __P((struct channel_softc *));
|
||||
void wdcattach __P((struct channel_softc *));
|
||||
int wdcintr __P((void *));
|
||||
void wdc_exec_xfer __P((struct channel_softc *, struct wdc_xfer *));
|
||||
struct wdc_xfer *wdc_get_xfer __P((int)); /* int = WDC_NOSLEEP/CANSLEEP */
|
||||
#define WDC_CANSLEEP 0x00
|
||||
#define WDC_NOSLEEP 0x01
|
||||
void wdc_free_xfer __P((struct channel_softc *, struct wdc_xfer *));
|
||||
void wdcstart __P((struct wdc_softc *, int));
|
||||
void wdcrestart __P((void*));
|
||||
int wdcreset __P((struct channel_softc *, int));
|
||||
#define VERBOSE 1
|
||||
#define SILENT 0 /* wdcreset will not print errors */
|
||||
int wdcwait __P((struct channel_softc *, int, int, int));
|
||||
void wdcbit_bucket __P(( struct channel_softc *, int));
|
||||
void wdccommand __P((struct channel_softc *, u_int8_t, u_int8_t, u_int16_t,
|
||||
u_int8_t, u_int8_t, u_int8_t, u_int8_t));
|
||||
void wdccommandshort __P((struct channel_softc *, int, int));
|
||||
void wdctimeout __P((void *arg));
|
||||
|
||||
/*
|
||||
* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
|
||||
* command is aborted.
|
||||
*/
|
||||
#define wait_for_drq(chp, timeout) wdcwait((chp), \
|
||||
WDCS_DRDY | WDCS_DSC | WDCS_DRQ, \
|
||||
WDCS_DRDY | WDCS_DSC | WDCS_DRQ, (timeout))
|
||||
#define wait_for_unbusy(chp, timeout) wdcwait((chp), 0, 0, (timeout))
|
||||
#define wait_for_ready(chp, timeout) wdcwait((chp), WDCS_DRDY | WDCS_DSC, \
|
||||
WDCS_DRDY | WDCS_DSC, (timeout))
|
||||
/* ATA/ATAPI specs says a device can take 31s to reset */
|
||||
#define WDC_RESET_WAIT 31000
|
||||
|
||||
void wdc_atapibus_attach __P((struct channel_softc *));
|
||||
int atapi_print __P((void *, const char *));
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.isa,v 1.76 1998/08/26 13:33:59 augustss Exp $
|
||||
# $NetBSD: files.isa,v 1.77 1998/10/12 16:09:19 bouyer Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent ISA code.
|
||||
# Included by ports that need it. Requires that the SCSI files be
|
||||
@ -121,9 +121,7 @@ file dev/isa/scd.c scd needs-flag
|
||||
# XXX BECAUSE NOT ALL PORTS USE THE MI DRIVER YET.
|
||||
|
||||
# ESDI/IDE/etc. controllers
|
||||
device wdc: ata, atapi
|
||||
file dev/ic/wdc.c
|
||||
wdc & (wd | !wd) needs-flag # XXX
|
||||
device wdc: ata, atapi, wdc_base
|
||||
|
||||
attach wdc at isa with wdc_isa: isadma
|
||||
file dev/isa/wdc_isa.c wdc_isa
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_isa.c,v 1.9 1998/08/15 10:10:52 mycroft Exp $ */
|
||||
/* $NetBSD: wdc_isa.c,v 1.10 1998/10/12 16:09:19 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -40,6 +40,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
@ -47,6 +48,7 @@
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
#define WDC_ISA_REG_NPORTS 8
|
||||
@ -58,8 +60,8 @@
|
||||
*/
|
||||
|
||||
struct wdc_isa_softc {
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct channel_softc wdc_channel;
|
||||
isa_chipset_tag_t sc_ic;
|
||||
void *sc_ih;
|
||||
int sc_drq;
|
||||
@ -72,9 +74,10 @@ struct cfattach wdc_isa_ca = {
|
||||
sizeof(struct wdc_isa_softc), wdc_isa_probe, wdc_isa_attach
|
||||
};
|
||||
|
||||
static void wdc_isa_dma_setup __P((void *));
|
||||
static void wdc_isa_dma_start __P((void *, void *, size_t, int));
|
||||
static void wdc_isa_dma_finish __P((void *));
|
||||
static void wdc_isa_dma_setup __P((struct wdc_isa_softc *));
|
||||
static int wdc_isa_dma_init __P((void*, int, int, void *, size_t, int));
|
||||
static void wdc_isa_dma_start __P((void*, int, int, int));
|
||||
static int wdc_isa_dma_finish __P((void*, int, int, int));
|
||||
|
||||
int
|
||||
wdc_isa_probe(parent, match, aux)
|
||||
@ -82,37 +85,29 @@ wdc_isa_probe(parent, match, aux)
|
||||
struct cfdata *match;
|
||||
void *aux;
|
||||
{
|
||||
#if 0 /* XXX memset */
|
||||
struct wdc_attachment_data ad = { 0 };
|
||||
#else /* XXX memset */
|
||||
struct wdc_attachment_data ad;
|
||||
#endif /* XXX memset */
|
||||
struct channel_softc ch = { 0 };
|
||||
struct isa_attach_args *ia = aux;
|
||||
int result = 0;
|
||||
|
||||
#if 0 /* XXX memset */
|
||||
#else /* XXX memset */
|
||||
bzero(&ad, sizeof ad);
|
||||
#endif /* XXX memset */
|
||||
ad.iot = ia->ia_iot;
|
||||
if (bus_space_map(ad.iot, ia->ia_iobase, WDC_ISA_REG_NPORTS, 0,
|
||||
&ad.ioh))
|
||||
ch.cmd_iot = ia->ia_iot;
|
||||
if (bus_space_map(ch.cmd_iot, ia->ia_iobase, WDC_ISA_REG_NPORTS, 0,
|
||||
&ch.cmd_ioh))
|
||||
goto out;
|
||||
|
||||
ad.auxiot = ia->ia_iot;
|
||||
if (bus_space_map(ad.auxiot, ia->ia_iobase + WDC_ISA_AUXREG_OFFSET,
|
||||
WDC_ISA_AUXREG_NPORTS, 0, &ad.auxioh))
|
||||
ch.ctl_iot = ia->ia_iot;
|
||||
if (bus_space_map(ch.ctl_iot, ia->ia_iobase + WDC_ISA_AUXREG_OFFSET,
|
||||
WDC_ISA_AUXREG_NPORTS, 0, &ch.ctl_ioh))
|
||||
goto outunmap;
|
||||
|
||||
result = wdcprobe(&ad);
|
||||
result = wdcprobe(&ch);
|
||||
if (result) {
|
||||
ia->ia_iosize = WDC_ISA_REG_NPORTS;
|
||||
ia->ia_msize = 0;
|
||||
}
|
||||
|
||||
bus_space_unmap(ad.auxiot, ad.auxioh, WDC_ISA_AUXREG_NPORTS);
|
||||
bus_space_unmap(ch.ctl_iot, ch.ctl_ioh, WDC_ISA_AUXREG_NPORTS);
|
||||
outunmap:
|
||||
bus_space_unmap(ad.iot, ad.ioh, WDC_ISA_REG_NPORTS);
|
||||
bus_space_unmap(ch.cmd_iot, ch.cmd_ioh, WDC_ISA_REG_NPORTS);
|
||||
out:
|
||||
return (result);
|
||||
}
|
||||
@ -127,66 +122,92 @@ wdc_isa_attach(parent, self, aux)
|
||||
|
||||
printf("\n");
|
||||
|
||||
sc->sc_ad.iot = ia->ia_iot;
|
||||
sc->sc_ad.auxiot = ia->ia_iot;
|
||||
sc->wdc_channel.cmd_iot = ia->ia_iot;
|
||||
sc->wdc_channel.ctl_iot = ia->ia_iot;
|
||||
sc->sc_ic = ia->ia_ic;
|
||||
if (bus_space_map(sc->sc_ad.iot, ia->ia_iobase, WDC_ISA_REG_NPORTS, 0,
|
||||
&sc->sc_ad.ioh) ||
|
||||
bus_space_map(sc->sc_ad.auxiot,
|
||||
if (bus_space_map(sc->wdc_channel.cmd_iot, ia->ia_iobase,
|
||||
WDC_ISA_REG_NPORTS, 0, &sc->wdc_channel.cmd_ioh) ||
|
||||
bus_space_map(sc->wdc_channel.ctl_iot,
|
||||
ia->ia_iobase + WDC_ISA_AUXREG_OFFSET, WDC_ISA_AUXREG_NPORTS,
|
||||
0, &sc->sc_ad.auxioh)) {
|
||||
0, &sc->wdc_channel.ctl_ioh)) {
|
||||
printf("%s: couldn't map registers\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
}
|
||||
sc->wdc_channel.data32iot = sc->wdc_channel.cmd_iot;
|
||||
sc->wdc_channel.data32ioh = sc->wdc_channel.cmd_ioh;
|
||||
|
||||
sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
|
||||
IPL_BIO, wdcintr, sc);
|
||||
IPL_BIO, wdcintr, &sc->wdc_channel);
|
||||
|
||||
if (ia->ia_drq != DRQUNK) {
|
||||
sc->sc_drq = ia->ia_drq;
|
||||
|
||||
sc->sc_ad.cap |= WDC_CAPABILITY_DMA;
|
||||
sc->sc_ad.dma_arg = sc;
|
||||
sc->sc_ad.dma_setup = &wdc_isa_dma_setup;
|
||||
sc->sc_ad.dma_start = &wdc_isa_dma_start;
|
||||
sc->sc_ad.dma_finish = &wdc_isa_dma_finish;
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
|
||||
sc->sc_wdcdev.dma_arg = sc;
|
||||
sc->sc_wdcdev.dma_init = wdc_isa_dma_init;
|
||||
sc->sc_wdcdev.dma_start = wdc_isa_dma_start;
|
||||
sc->sc_wdcdev.dma_finish = wdc_isa_dma_finish;
|
||||
wdc_isa_dma_setup(sc);
|
||||
}
|
||||
|
||||
wdcattach(&sc->sc_wdcdev, &sc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.wdc = &sc->sc_wdcdev;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
wdcattach(&sc->wdc_channel);
|
||||
}
|
||||
|
||||
static void
|
||||
wdc_isa_dma_setup(scv)
|
||||
void *scv;
|
||||
wdc_isa_dma_setup(sc)
|
||||
struct wdc_isa_softc *sc;
|
||||
{
|
||||
struct wdc_isa_softc *sc = scv;
|
||||
|
||||
if (isa_dmamap_create(sc->sc_ic, sc->sc_drq,
|
||||
MAXPHYS, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
|
||||
printf("%s: can't create map for drq %d\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname, sc->sc_drq);
|
||||
sc->sc_ad.cap &= ~WDC_CAPABILITY_DMA;
|
||||
sc->sc_wdcdev.cap &= ~WDC_CAPABILITY_DMA;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wdc_isa_dma_start(scv, buf, size, read)
|
||||
void *scv, *buf;
|
||||
size_t size;
|
||||
static int
|
||||
wdc_isa_dma_init(v, channel, drive, databuf, datalen, read)
|
||||
void *v;
|
||||
void *databuf;
|
||||
size_t datalen;
|
||||
int read;
|
||||
{
|
||||
struct wdc_isa_softc *sc = scv;
|
||||
struct wdc_isa_softc *sc = v;
|
||||
|
||||
isa_dmastart(sc->sc_ic, sc->sc_drq, buf,
|
||||
size, NULL, read ? DMAMODE_READ : DMAMODE_WRITE,
|
||||
isa_dmastart(sc->sc_ic, sc->sc_drq, databuf,
|
||||
datalen, NULL, read ? DMAMODE_READ : DMAMODE_WRITE,
|
||||
BUS_DMA_NOWAIT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wdc_isa_dma_finish(scv)
|
||||
void *scv;
|
||||
wdc_isa_dma_start(v, channel, drive, read)
|
||||
void *v;
|
||||
int channel, drive;
|
||||
{
|
||||
struct wdc_isa_softc *sc = scv;
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int
|
||||
wdc_isa_dma_finish(v, channel, drive, read)
|
||||
void *v;
|
||||
int channel, drive;
|
||||
int read;
|
||||
{
|
||||
struct wdc_isa_softc *sc = v;
|
||||
|
||||
isa_dmadone(sc->sc_ic, sc->sc_drq);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_isapnp.c,v 1.7 1998/09/12 21:40:22 wrstuden Exp $ */
|
||||
/* $NetBSD: wdc_isapnp.c,v 1.8 1998/10/12 16:09:19 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -40,6 +40,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
@ -51,12 +52,13 @@
|
||||
#include <dev/isapnp/isapnpvar.h>
|
||||
#include <dev/isapnp/isapnpdevs.h>
|
||||
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcreg.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
struct wdc_isapnp_softc {
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct channel_softc wdc_channel;
|
||||
isa_chipset_tag_t sc_ic;
|
||||
void *sc_ih;
|
||||
int sc_drq;
|
||||
@ -70,7 +72,7 @@ struct cfattach wdc_isapnp_ca = {
|
||||
};
|
||||
|
||||
#ifdef notyet
|
||||
static void wdc_isapnp_dma_setup __P((void *));
|
||||
static void wdc_isapnp_dma_setup __P((struct wdc_isapnp_softc *));
|
||||
static void wdc_isapnp_dma_start __P((void *, void *, size_t, int));
|
||||
static void wdc_isapnp_dma_finish __P((void *));
|
||||
#endif
|
||||
@ -113,51 +115,64 @@ wdc_isapnp_attach(parent, self, aux)
|
||||
printf("%s: %s %s\n", sc->sc_wdcdev.sc_dev.dv_xname, ipa->ipa_devident,
|
||||
ipa->ipa_devclass);
|
||||
|
||||
sc->sc_ad.iot = ipa->ipa_iot;
|
||||
sc->sc_ad.auxiot = ipa->ipa_iot;
|
||||
sc->wdc_channel.cmd_iot = ipa->ipa_iot;
|
||||
sc->wdc_channel.ctl_iot = ipa->ipa_iot;
|
||||
/*
|
||||
* An IDE controller can feed us the regions in any order. Pass
|
||||
* them along with the 8-byte region in sc_ad.ioh, and the other
|
||||
* (2 byte) region in auxioh.
|
||||
*/
|
||||
if (ipa->ipa_io[0].length == 8) {
|
||||
sc->sc_ad.ioh = ipa->ipa_io[0].h;
|
||||
sc->sc_ad.auxioh = ipa->ipa_io[1].h;
|
||||
sc->wdc_channel.cmd_ioh = ipa->ipa_io[0].h;
|
||||
sc->wdc_channel.ctl_ioh = ipa->ipa_io[1].h;
|
||||
} else {
|
||||
sc->sc_ad.ioh = ipa->ipa_io[1].h;
|
||||
sc->sc_ad.auxioh = ipa->ipa_io[0].h;
|
||||
sc->wdc_channel.cmd_ioh = ipa->ipa_io[1].h;
|
||||
sc->wdc_channel.ctl_ioh = ipa->ipa_io[0].h;
|
||||
}
|
||||
sc->sc_ic = ipa->ipa_ic;
|
||||
sc->wdc_channel.data32iot = sc->wdc_channel.cmd_iot;
|
||||
sc->wdc_channel.data32ioh = sc->wdc_channel.cmd_ioh;
|
||||
|
||||
sc->sc_ic = ipa->ipa_ic;
|
||||
sc->sc_ih = isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num,
|
||||
ipa->ipa_irq[0].type, IPL_BIO, wdcintr, sc);
|
||||
ipa->ipa_irq[0].type, IPL_BIO, wdcintr, &sc->wdc_channel);
|
||||
|
||||
#ifdef notyet
|
||||
if (ipa->ipa_ndrq > 0) {
|
||||
sc->sc_drq = ipa->ipa_drq[0].num;
|
||||
|
||||
sc->sc_ad.cap |= WDC_CAPABILITY_DMA;
|
||||
sc->sc_ad.dma_setup = &wdc_isapnp_dma_setup;
|
||||
sc->sc_ad.dma_start = &wdc_isapnp_dma_start;
|
||||
sc->sc_ad.dma_finish = &wdc_isapnp_dma_finish;
|
||||
wdc_isapnp_dma_setup(sc);
|
||||
}
|
||||
#endif
|
||||
|
||||
wdcattach(&sc->sc_wdcdev, &sc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.wdc = &sc->sc_wdcdev;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
wdcattach(&sc->wdc_channel);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
static void
|
||||
wdc_isapnp_dma_setup(scv)
|
||||
void *scv;
|
||||
wdc_isapnp_dma_setup(sc)
|
||||
struct wdc_isapnp_softc *sc;
|
||||
{
|
||||
struct wdc_isapnp_softc *sc = scv;
|
||||
|
||||
if (isa_dmamap_create(sc->sc_ic, sc->sc_drq,
|
||||
MAXPHYS, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
|
||||
printf("%s: can't create map for drq %d\n",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname, sc->sc_drq);
|
||||
sc->sc_ad.cap &= ~WDC_CAPABILITY_DMA;
|
||||
sc->sc_wdcdev.cap &= ~WDC_CAPABILITY_DMA;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_ofisa.c,v 1.2 1998/03/21 02:06:17 cgd Exp $ */
|
||||
/* $NetBSD: wdc_ofisa.c,v 1.3 1998/10/12 16:09:20 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1997, 1998
|
||||
@ -41,6 +41,7 @@
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
@ -50,12 +51,12 @@
|
||||
#include <dev/ofisa/ofisavar.h>
|
||||
|
||||
#include <dev/ic/wdcreg.h> /* ??? */
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
struct wdc_ofisa_softc {
|
||||
struct wdc_softc sc_wdc;
|
||||
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct channel_softc wdc_channel;
|
||||
void *sc_ih;
|
||||
};
|
||||
|
||||
@ -90,8 +91,7 @@ wdc_ofisa_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct wdc_ofisa_softc *osc = (void *)self;
|
||||
struct wdc_softc *sc = &osc->sc_wdc;
|
||||
struct wdc_ofisa_softc *sc = (void *)self;
|
||||
struct ofisa_attach_args *aa = aux;
|
||||
struct ofisa_reg_desc reg[2];
|
||||
struct ofisa_intr_desc intr;
|
||||
@ -127,25 +127,35 @@ wdc_ofisa_attach(parent, self, aux)
|
||||
return;
|
||||
}
|
||||
|
||||
bzero(&osc->sc_ad, sizeof osc->sc_ad);
|
||||
osc->sc_ad.iot =
|
||||
sc->wdc_channel.cmd_iot =
|
||||
(reg[0].type == OFISA_REG_TYPE_IO) ? aa->iot : aa->memt;
|
||||
osc->sc_ad.auxiot =
|
||||
sc->wdc_channel.ctl_iot =
|
||||
(reg[1].type == OFISA_REG_TYPE_IO) ? aa->iot : aa->memt;
|
||||
if (bus_space_map(osc->sc_ad.iot, reg[0].addr, 8, 0,
|
||||
&osc->sc_ad.ioh) ||
|
||||
bus_space_map(osc->sc_ad.auxiot, reg[1].addr, 1, 0,
|
||||
&osc->sc_ad.auxioh)) {
|
||||
if (bus_space_map(sc->wdc_channel.cmd_iot, reg[0].addr, 8, 0,
|
||||
&sc->wdc_channel.cmd_ioh) ||
|
||||
bus_space_map(sc->wdc_channel.ctl_iot, reg[1].addr, 1, 0,
|
||||
&sc->wdc_channel.ctl_ioh)) {
|
||||
printf(": can't map register spaces\n");
|
||||
return;
|
||||
}
|
||||
|
||||
osc->sc_ih = isa_intr_establish(aa->ic, intr.irq, intr.share,
|
||||
sc->sc_ih = isa_intr_establish(aa->ic, intr.irq, intr.share,
|
||||
IPL_BIO, wdcintr, sc);
|
||||
|
||||
printf("\n");
|
||||
|
||||
wdcattach(sc, &osc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.wdc = &sc->sc_wdcdev;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
wdcattach(&sc->wdc_channel);
|
||||
|
||||
#if 0
|
||||
printf("%s: registers: ", sc->sc_dev.dv_xname);
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.pci,v 1.46 1998/09/26 16:20:31 dante Exp $
|
||||
# $NetBSD: files.pci,v 1.47 1998/10/12 16:09:20 bouyer Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent PCI code.
|
||||
# Included by ports that need it. Requires that the SCSI files be
|
||||
@ -73,16 +73,10 @@ device ncr: scsi
|
||||
attach ncr at pci
|
||||
file dev/pci/ncr.c ncr
|
||||
|
||||
# XXX THE FOLLOWING BLOCK SHOULD GO INTO dev/pci/files.pci, BUT CANNOT
|
||||
# XXX BECAUSE NOT ALL PORTS USE THE MI DRIVER YET. (when the conf/files
|
||||
# XXX and files.isa bogons are fixed, this can be fixed as well.)
|
||||
|
||||
# # PCI IDE controllers
|
||||
# device pciide {[channel = -1]}
|
||||
# attach pciide at pci
|
||||
# file dev/pci/pciide.c pciide
|
||||
# attach wdc at pciide with wdc_pciide
|
||||
# file dev/pci/wdc_pciide.c wdc_pciide
|
||||
# PCI IDE controllers
|
||||
device pciide {[channel = -1]}: wdc_base, ata, atapi
|
||||
attach pciide at pci
|
||||
file dev/pci/pciide.c pciide
|
||||
|
||||
# PCI-PCI bridge chips
|
||||
device ppb: pcibus
|
||||
|
1516
sys/dev/pci/pciide.c
1516
sys/dev/pci/pciide.c
File diff suppressed because it is too large
Load Diff
92
sys/dev/pci/pciide_apollo_reg.h
Normal file
92
sys/dev/pci/pciide_apollo_reg.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* $NetBSD: pciide_apollo_reg.h,v 1.2 1998/10/12 16:09:21 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Registers definitions for VIA technologies's Apollo controllers (VT82V580VO,
|
||||
* VT82C586A and VT82C586B). Available from http://www.via.com.br/
|
||||
*/
|
||||
|
||||
/* misc. configuration registers */
|
||||
#define APO_IDECONF 0x40
|
||||
#define APO_IDECONF_EN(channel) (0x00000001 << (1 - (channel)))
|
||||
#define APO_IDECONF_SERR_EN 0x00000100 /* 580 only */
|
||||
#define APO_IDECONF_DS_SOURCE 0x00000200 /* 580 only */
|
||||
#define APO_IDECONF_ALT_INTR_EN 0x00000400 /* 580 only */
|
||||
#define APO_IDECONF_PERR_EN 0x00000800 /* 580 only */
|
||||
#define APO_IDECONF_WR_BUFF_EN(channel) (0x00001000 << ((1 - (channel)) << 1))
|
||||
#define APO_IDECONF_RD_PREF_EN(channel) (0x00002000 << ((1 - (channel)) << 1))
|
||||
#define APO_IDECONF_DEVSEL_TME 0x00010000 /* 580 only */
|
||||
#define APO_IDECONF_MAS_CMD_MON 0x00020000 /* 580 only */
|
||||
#define APO_IDECONF_IO_NAT(channel) \
|
||||
(0x00400000 << (1 - (channel))) /* 580 only */
|
||||
#define APO_IDECONF_FIFO_TRSH(channel, x) \
|
||||
((x) & 0x3) << ((1 - (channel)) << 1 + 24)
|
||||
#define APO_IDECONF_FIFO_CONF_MASK 0x60000000
|
||||
|
||||
/* Misc. controls register */
|
||||
#define APO_CTLMISC 0x44
|
||||
#define APO_CTLMISC_BM_STS_RTY 0x00000008
|
||||
#define APO_CTLMISC_FIFO_HWS 0x00000010
|
||||
#define APO_CTLMISC_WR_IRDY_WS 0x00000020
|
||||
#define APO_CTLMISC_RD_IRDY_WS 0x00000040
|
||||
#define APO_CTLMISC_INTR_SWP 0x00004000
|
||||
#define APO_CTLMISC_DRDY_TIME_MASK 0x00030000
|
||||
#define APO_CTLMISC_FIFO_FLSH_RD(channel) (0x00100000 << (1 - (channel)))
|
||||
#define APO_CTLMISC_FIFO_FLSH_DMA(channel) (0x00400000 << (1 - (channel)))
|
||||
|
||||
/* data port timings controls */
|
||||
#define APO_DATATIM 0x48
|
||||
#define APO_DATATIM_RECOV(channel, drive, x) (((x) & 0xf) << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
|
||||
#define APO_DATATIM_PULSE(channel, drive, x) (((x) & 0xf) << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3) + 4))
|
||||
|
||||
/* misc timings control */
|
||||
#define APO_MISCTIM 0x4c
|
||||
|
||||
/* Ultra-DMA/33 control (586A/B only) XXX check */
|
||||
#define APO_UDMA 0x50
|
||||
#define APO_UDMA_TIME(channel, drive, x) (((x) & 0x3) << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
|
||||
#define APO_UDMA_PIO_MODE(channel, drive) (0x20 << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
|
||||
#define APO_UDMA_EN(channel, drive) (0x40 << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
|
||||
#define APO_UDMA_EN_MTH(channel, drive) (0x80 << \
|
||||
(((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
|
||||
|
||||
static int8_t apollo_udma_tim[] = {0x03, 0x02, 0x00};
|
||||
static int8_t apollo_pio_set[] = {0x0a, 0x0a, 0x0a, 0x02, 0x02};
|
||||
static int8_t apollo_pio_rec[] = {0x08, 0x08, 0x08, 0x02, 0x00};
|
64
sys/dev/pci/pciide_cmd_reg.h
Normal file
64
sys/dev/pci/pciide_cmd_reg.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* $NetBSD: pciide_cmd_reg.h,v 1.2 1998/10/12 16:09:21 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Registers definitions for CMD Technologies's PCI 064x IDE controllers.
|
||||
* Available from http://www.cmd.com/
|
||||
*/
|
||||
|
||||
/* Configuration and drive 0 setup */
|
||||
#define CMD_CONF_CTRL0 0x50
|
||||
#define CMD_CONF_REV_MASK 0x00000003
|
||||
#define CMD_CONF_DRV0_INTR 0x00000004
|
||||
#define CMD_CONF_DEVID 0x00000018
|
||||
#define CMD_CONF_VESAPRT 0x00000020
|
||||
#define CMD_CONF_DSA1 0x00000040
|
||||
#define CMD_CONF_DSA0 0x00000080
|
||||
|
||||
#define CMD_CONF_HR_FIFO 0x00000100
|
||||
#define CMD_CONF_HW_FIFO 0x00000200
|
||||
#define CMD_CONF_DEVSEL 0x00000400
|
||||
#define CMD_CONF_2PORT 0x00000800
|
||||
#define CMD_CONF_PAR 0x00001000
|
||||
#define CMD_CONF_HW_HLD 0x00002000
|
||||
#define CMD_CONF_DRV0_RAHEAD 0x00004000
|
||||
#define CMD_CONF_DRV1_RAHEAD 0x00008000
|
||||
|
||||
#define CMD_CONF_CB_TIM_OFF 16
|
||||
#define CMD_CONF_CB_REC_OFF 20
|
||||
|
||||
#define CMD_DRV0_ADDRSET_OFF 30
|
||||
|
||||
|
109
sys/dev/pci/pciide_piix_reg.h
Normal file
109
sys/dev/pci/pciide_piix_reg.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* $NetBSD: pciide_piix_reg.h,v 1.2 1998/10/12 16:09:21 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Registers definitions for Intel's PIIX serie PCI IDE controllers.
|
||||
* See Intel's
|
||||
* "82371FB (PIIX) and 82371SB (PIIX3) PCI ISA IDE XCELERATOR" and
|
||||
* "82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)"
|
||||
* available from http://www.intel.com/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bus master interface base address register
|
||||
*/
|
||||
#define PIIX_BMIBA 0x20
|
||||
#define PIIX_BMIBA_ADDR(x) (x & 0x0000FFFF0)
|
||||
#define PIIX_BMIBA_RTE(x) (x & 0x000000001)
|
||||
#define PIIX_BMIBA_RTE_IO 0x000000001 /* base addr maps to I/O space */
|
||||
|
||||
/*
|
||||
* IDE timing register
|
||||
* 0x40/0x41 is for primary, 0x42/0x43 for secondary channel
|
||||
*/
|
||||
#define PIIX_IDETIM 0x40
|
||||
#define PIIX_IDETIM_READ(x, channel) (((x) >> (16 * (channel))) & 0x0000FFFF)
|
||||
#define PIIX_IDETIM_SET(x, bytes, channel) \
|
||||
((x) | ((bytes) << (16 * (channel))))
|
||||
#define PIIX_IDETIM_CLEAR(x, bytes, channel) \
|
||||
((x) & ~((bytes) << (16 * (channel))))
|
||||
|
||||
#define PIIX_IDETIM_IDE 0x8000 /* PIIX decode IDE registers */
|
||||
#define PIIX_IDETIM_SITRE 0x4000 /* slaves IDE timing registers
|
||||
enabled (PIIX3/4 only) */
|
||||
#define PIIX_IDETIM_ISP_MASK 0x3000 /* IOrdy sample point */
|
||||
#define PIIX_IDETIM_ISP_SHIFT 12
|
||||
#define PIIX_IDETIM_ISP_SET(x) ((x) << PIIX_IDETIM_ISP_SHIFT)
|
||||
#define PIIX_IDETIM_RTC_MASK 0x0300 /* recovery time */
|
||||
#define PIIX_IDETIM_RTC_SHIFT 8
|
||||
#define PIIX_IDETIM_RTC_SET(x) ((x) << PIIX_IDETIM_RTC_SHIFT)
|
||||
#define PIIX_IDETIM_DTE(d) (0x0008 << (4 * (d))) /* DMA timing only */
|
||||
#define PIIX_IDETIM_PPE(d) (0x0004 << (4 * (d))) /* prefetch/posting */
|
||||
#define PIIX_IDETIM_IE(d) (0x0002 << (4 * (d))) /* IORDY enable */
|
||||
#define PIIX_IDETIM_TIME(d) (0x0001 << (4 * (d))) /* Fast timing enable */
|
||||
/*
|
||||
* Slave IDE timing register (PIIX3/4 only)
|
||||
* This register must be enabled via the PIIX_IDETIM_SITRE bit
|
||||
*/
|
||||
#define PIIX_SIDETIM 0x44
|
||||
#define PIIX_SIDETIM_ISP_MASK(channel) (0x0c << ((channel) * 4))
|
||||
#define PIIX_SIDETIM_ISP_SHIFT 2
|
||||
#define PIIX_SIDETIM_ISP_SET(x, channel) \
|
||||
(x << (PIIX_SIDETIM_ISP_SHIFT + ((channel) * 4)))
|
||||
#define PIIX_SIDETIM_RTC_MASK(channel) (0x03 << ((channel) * 4))
|
||||
#define PIIX_SIDETIM_RTC_SHIFT 0
|
||||
#define PIIX_SIDETIM_RTC_SET(x, channel) \
|
||||
(x << (PIIX_SIDETIM_RTC_SHIFT + ((channel) * 4)))
|
||||
|
||||
/*
|
||||
* Ultra DMA/33 register (PIIX4 only)
|
||||
*/
|
||||
#define PIIX_UDMAREG 0x48
|
||||
/* Control register */
|
||||
#define PIIX_UDMACTL_DRV_EN(channel, drive) (0x01 << ((channel) * 2 + (drive)))
|
||||
/* Ultra DMA/33 timing register (PIIX4 only) */
|
||||
#define PIIX_UDMATIM_SHIFT 16
|
||||
#define PIIX_UDMATIM_SET(x, channel, drive) \
|
||||
(((x) << ((channel * 8) + (drive * 4))) << PIIX_UDMATIM_SHIFT)
|
||||
/*
|
||||
* these tables define the differents values to upload to the
|
||||
* ISP and RTC registers for the various PIO and DMA mode
|
||||
* (from the PIIX4 doc).
|
||||
*/
|
||||
static int8_t piix_isp_pio[] = {0x00, 0x00, 0x01, 0x02, 0x02};
|
||||
static int8_t piix_rtc_pio[] = {0x00, 0x00, 0x00, 0x01, 0x03};
|
||||
static int8_t piix_isp_dma[] = {0x00, 0x02, 0x02};
|
||||
static int8_t piix_rtc_dma[] = {0x00, 0x02, 0x03};
|
||||
static int8_t piix4_sct_udma[] = {0x00, 0x01, 0x02};
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pciidereg.h,v 1.2 1998/03/04 19:17:10 cgd Exp $ */
|
||||
/* $NetBSD: pciidereg.h,v 1.3 1998/10/12 16:09:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
|
||||
@ -68,3 +68,42 @@
|
||||
#define PCIIDE_COMPAT_CTL_BASE(chan) ((chan) == 0 ? 0x3f6 : 0x376)
|
||||
#define PCIIDE_COMPAT_CTL_SIZE 1
|
||||
#define PCIIDE_COMPAT_IRQ(chan) ((chan) == 0 ? 14 : 15)
|
||||
|
||||
/*
|
||||
* definitions for IDE DMA
|
||||
* XXX maybe this should go elsewhere
|
||||
*/
|
||||
|
||||
/* secondary channel registers offset */
|
||||
#define IDEDMA_SCH_OFFSET 0x08
|
||||
|
||||
/* Bus master command register */
|
||||
#define IDEDMA_CMD 0x00
|
||||
#define IDEDMA_CMD_WRITE 0x08
|
||||
#define IDEDMA_CMD_START 0x01
|
||||
|
||||
/* Bus master status register */
|
||||
#define IDEDMA_CTL 0x02
|
||||
#define IDEDMA_CTL_DRV_DMA(d) (0x20 << (d))
|
||||
#define IDEDMA_CTL_INTR 0x04
|
||||
#define IDEDMA_CTL_ERR 0x02
|
||||
#define IDEDMA_CTL_ACT 0x01
|
||||
|
||||
/* Bus master table pointer register */
|
||||
#define IDEDMA_TBL 0x04
|
||||
#define IDEDMA_TBL_MASK 0xfffffffc
|
||||
#define IDEDMA_TBL_ALIGN 0x00010000
|
||||
|
||||
/* bus master table descriptor */
|
||||
struct idedma_table {
|
||||
u_int32_t base_addr; /* physical base addr of memory region */
|
||||
u_int32_t byte_count; /* memory region length */
|
||||
#define IDEDMA_BYTE_COUNT_MASK 0x0000FFFF
|
||||
#define IDEDMA_BYTE_COUNT_EOT 0x80000000
|
||||
};
|
||||
|
||||
#define IDEDMA_BYTE_COUNT_MAX 0x00010000 /* Max I/O per table */
|
||||
#define IDEDMA_BYTE_COUNT_ALIGN 0x00010000
|
||||
|
||||
/* Number of idedma table needed */
|
||||
#define NIDEDMA_TABLES (MAXPHYS/NBPG + 1)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pciidevar.h,v 1.1 1998/03/04 06:35:11 cgd Exp $ */
|
||||
/* $NetBSD: pciidevar.h,v 1.2 1998/10/12 16:09:22 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
|
||||
@ -37,18 +37,6 @@
|
||||
*/
|
||||
|
||||
struct device;
|
||||
struct pci_attach_args;
|
||||
|
||||
/*
|
||||
* Attach args for devices that attach to pciide. Really, that's just wdc.
|
||||
*/
|
||||
struct pciide_attach_args {
|
||||
int channel;
|
||||
bus_space_tag_t cmd_iot, ctl_iot;
|
||||
bus_space_handle_t cmd_ioh, ctl_ioh;
|
||||
int (**ihandp) __P((void *));
|
||||
void **ihandargp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions defined by machine-dependent code.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc_pcmcia.c,v 1.11 1998/10/10 22:01:24 thorpej Exp $ */
|
||||
/* $NetBSD: wdc_pcmcia.c,v 1.12 1998/10/12 16:09:22 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -62,6 +62,7 @@
|
||||
#include <dev/pcmcia/pcmciadevs.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
|
||||
#define WDC_PCMCIA_REG_NPORTS 8
|
||||
@ -70,7 +71,7 @@
|
||||
|
||||
struct wdc_pcmcia_softc {
|
||||
struct wdc_softc sc_wdcdev;
|
||||
struct wdc_attachment_data sc_ad;
|
||||
struct channel_softc wdc_channel;
|
||||
struct pcmcia_io_handle sc_pioh;
|
||||
struct pcmcia_io_handle sc_auxpioh;
|
||||
int sc_iowindow;
|
||||
@ -208,11 +209,6 @@ wdc_pcmcia_attach(parent, self, aux)
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_ad.iot = sc->sc_pioh.iot;
|
||||
sc->sc_ad.ioh = sc->sc_pioh.ioh;
|
||||
sc->sc_ad.auxiot = sc->sc_auxpioh.iot;
|
||||
sc->sc_ad.auxioh = sc->sc_auxpioh.ioh;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pa->pf, cfe);
|
||||
if (pcmcia_function_enable(pa->pf)) {
|
||||
@ -252,15 +248,33 @@ wdc_pcmcia_attach(parent, self, aux)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_BIO, wdcintr, sc);
|
||||
sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_BIO, wdcintr,
|
||||
&sc->wdc_channel);
|
||||
if (sc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt\n", self->dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->wdc_channel.cmd_iot = sc->sc_pioh.iot;
|
||||
sc->wdc_channel.cmd_ioh = sc->sc_pioh.ioh;
|
||||
sc->wdc_channel.ctl_iot = sc->sc_auxpioh.iot;
|
||||
sc->wdc_channel.ctl_ioh = sc->sc_auxpioh.ioh;
|
||||
sc->wdc_channel.data32iot = sc->wdc_channel.cmd_iot;
|
||||
sc->wdc_channel.data32ioh = sc->wdc_channel.cmd_ioh;
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32;
|
||||
sc->sc_wdcdev.pio_mode = 0;
|
||||
sc->sc_wdcdev.channels = &sc->wdc_channel;
|
||||
sc->sc_wdcdev.nchannels = 1;
|
||||
sc->wdc_channel.channel = 0;
|
||||
sc->wdc_channel.wdc = &sc->sc_wdcdev;
|
||||
sc->wdc_channel.ch_queue = malloc(sizeof(struct channel_queue),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->wdc_channel.ch_queue == NULL) {
|
||||
printf("%s: can't allocate memory for command queue",
|
||||
sc->sc_wdcdev.sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
if (wpp->wpp_quirk_flag & WDC_PCMCIA_NO_EXTRA_RESETS)
|
||||
sc->sc_ad.flags |= WDC_NO_EXTRA_RESETS;
|
||||
|
||||
wdcattach(&sc->sc_wdcdev, &sc->sc_ad);
|
||||
sc->sc_wdcdev.cap |= WDC_CAPABILITY_NO_EXTRA_RESETS;
|
||||
wdcattach(&sc->wdc_channel);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapi_base.c,v 1.9 1998/08/15 10:10:55 mycroft Exp $ */
|
||||
/* $NetBSD: atapi_base.c,v 1.10 1998/10/12 16:09:23 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -183,11 +183,11 @@ atapi_print_addr(sc_link)
|
||||
struct scsipi_link *sc_link;
|
||||
{
|
||||
|
||||
printf("%s(%s:%d): ",
|
||||
printf("%s(%s:%d:%d): ",
|
||||
sc_link->device_softc ?
|
||||
((struct device *)sc_link->device_softc)->dv_xname : "probe",
|
||||
((struct device *)sc_link->adapter_softc)->dv_xname,
|
||||
sc_link->scsipi_atapi.drive);
|
||||
sc_link->scsipi_atapi.channel, sc_link->scsipi_atapi.drive);
|
||||
}
|
||||
|
||||
/*
|
||||
|
713
sys/dev/scsipi/atapi_wdc.c
Normal file
713
sys/dev/scsipi/atapi_wdc.c
Normal file
@ -0,0 +1,713 @@
|
||||
/* $NetBSD: atapi_wdc.c,v 1.2 1998/10/12 16:09:23 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define WDCDEBUG
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#ifndef __BUS_SPACE_HAS_STREAM_METHODS
|
||||
#define bus_space_write_multi_stream_2 bus_space_write_multi_2
|
||||
#define bus_space_write_multi_stream_4 bus_space_write_multi_4
|
||||
#define bus_space_read_multi_stream_2 bus_space_read_multi_2
|
||||
#define bus_space_read_multi_stream_4 bus_space_read_multi_4
|
||||
#endif /* __BUS_SPACE_HAS_STREAM_METHODS */
|
||||
|
||||
#include <dev/ata/atareg.h>
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/ic/wdcreg.h>
|
||||
#include <dev/ic/wdcvar.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsipiconf.h>
|
||||
#include <dev/scsipi/atapiconf.h>
|
||||
|
||||
#define DEBUG_INTR 0x01
|
||||
#define DEBUG_XFERS 0x02
|
||||
#define DEBUG_STATUS 0x04
|
||||
#define DEBUG_FUNCS 0x08
|
||||
#define DEBUG_PROBE 0x10
|
||||
#ifdef WDCDEBUG
|
||||
int wdcdebug_atapi_mask = DEBUG_PROBE;
|
||||
#define WDCDEBUG_PRINT(args, level) \
|
||||
if (wdcdebug_atapi_mask & (level)) \
|
||||
printf args
|
||||
#else
|
||||
#define WDCDEBUG_PRINT(args, level)
|
||||
#endif
|
||||
|
||||
#define ATAPI_DELAY 10 /* 10 ms, this is used only before sending a cmd */
|
||||
|
||||
void wdc_atapi_minphys __P((struct buf *bp));
|
||||
void wdc_atapi_start __P((struct channel_softc *,struct wdc_xfer *));
|
||||
int wdc_atapi_intr __P((struct channel_softc *, struct wdc_xfer *));
|
||||
int wdc_atapi_ctrl __P((struct channel_softc *, struct wdc_xfer *));
|
||||
void wdc_atapi_done __P((struct channel_softc *, struct wdc_xfer *));
|
||||
void wdc_atapi_reset __P((struct channel_softc *, struct wdc_xfer *));
|
||||
int wdc_atapi_send_cmd __P((struct scsipi_xfer *sc_xfer));
|
||||
|
||||
#define MAX_SIZE MAXPHYS
|
||||
|
||||
static struct scsipi_adapter wdc_switch = {
|
||||
wdc_atapi_send_cmd,
|
||||
wdc_atapi_minphys,
|
||||
NULL, /* scsipi_ioctl */
|
||||
};
|
||||
|
||||
void
|
||||
wdc_atapibus_attach(chp)
|
||||
struct channel_softc *chp;
|
||||
{
|
||||
struct wdc_softc *wdc = chp->wdc;
|
||||
int channel = chp->channel;
|
||||
struct ata_atapi_attach aa_link;
|
||||
|
||||
memset(&aa_link, 0, sizeof(struct ata_atapi_attach));
|
||||
aa_link.aa_type = T_ATAPI;
|
||||
aa_link.aa_channel = channel;
|
||||
aa_link.aa_openings = 1;
|
||||
aa_link.aa_drv_data = chp->ch_drive; /* pass the whole array */
|
||||
aa_link.aa_bus_private = &wdc_switch;
|
||||
(void)config_found(&wdc->sc_dev, (void *)&aa_link, atapi_print);
|
||||
}
|
||||
|
||||
void
|
||||
wdc_atapi_minphys (struct buf *bp)
|
||||
{
|
||||
if(bp->b_bcount > MAX_SIZE)
|
||||
bp->b_bcount = MAX_SIZE;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
int
|
||||
wdc_atapi_get_params(ab_link, drive, flags, id)
|
||||
struct scsipi_link *ab_link;
|
||||
u_int8_t drive;
|
||||
int flags;
|
||||
struct ataparams *id;
|
||||
{
|
||||
struct wdc_softc *wdc = (void*)ab_link->adapter_softc;
|
||||
struct channel_softc *chp =
|
||||
&wdc->channels[ab_link->scsipi_atapi.channel];
|
||||
struct wdc_command wdc_c;
|
||||
|
||||
/* if no ATAPI device detected at wdc attach time, skip */
|
||||
/*
|
||||
* XXX this will break scsireprobe if this is of any interest for
|
||||
* ATAPI devices one day.
|
||||
*/
|
||||
if ((chp->ch_drive[drive].drive_flags & DRIVE_ATAPI) == 0) {
|
||||
WDCDEBUG_PRINT(("wdc_atapi_get_params: drive %d not present\n",
|
||||
drive), DEBUG_PROBE);
|
||||
return -1;
|
||||
}
|
||||
memset(&wdc_c, 0, sizeof(struct wdc_command));
|
||||
wdc_c.r_command = ATAPI_SOFT_RESET;
|
||||
wdc_c.r_st_bmask = 0;
|
||||
wdc_c.r_st_pmask = 0;
|
||||
wdc_c.flags = AT_POLL;
|
||||
wdc_c.timeout = WDC_RESET_WAIT;
|
||||
if (wdc_exec_command(&chp->ch_drive[drive], &wdc_c) != WDC_COMPLETE) {
|
||||
printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for"
|
||||
" drive %s:%d:%d: driver failed\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, drive);
|
||||
panic("wdc_atapi_get_params");
|
||||
}
|
||||
if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
|
||||
WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET "
|
||||
"failed for drive %s:%d:%d: error 0x%x\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, drive,
|
||||
wdc_c.r_error), DEBUG_PROBE);
|
||||
return -1;
|
||||
}
|
||||
chp->ch_drive[drive].state = 0;
|
||||
|
||||
bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
|
||||
|
||||
/* Some ATAPI devices need a bit more time after software reset. */
|
||||
delay(5000);
|
||||
if (ata_get_params(&chp->ch_drive[drive], AT_POLL, id) != 0) {
|
||||
WDCDEBUG_PRINT(("wdc_atapi_get_params: ATAPI_IDENTIFY_DEVICE "
|
||||
"failed for drive %s:%d:%d: error 0x%x\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, drive,
|
||||
wdc_c.r_error), DEBUG_PROBE);
|
||||
return -1;
|
||||
}
|
||||
return COMPLETE;
|
||||
}
|
||||
|
||||
int
|
||||
wdc_atapi_send_cmd(sc_xfer)
|
||||
struct scsipi_xfer *sc_xfer;
|
||||
{
|
||||
struct scsipi_link *sc_link = sc_xfer->sc_link;
|
||||
struct wdc_softc *wdc = (void*)sc_link->adapter_softc;
|
||||
struct wdc_xfer *xfer;
|
||||
struct ata_drive_datas *drvp;
|
||||
int flags = sc_xfer->flags;
|
||||
int channel = sc_xfer->sc_link->scsipi_atapi.channel;
|
||||
int drive = sc_xfer->sc_link->scsipi_atapi.drive;
|
||||
int s, ret;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_send_cmd\n"), DEBUG_FUNCS);
|
||||
|
||||
xfer = wdc_get_xfer(flags & SCSI_NOSLEEP ? WDC_NOSLEEP : WDC_CANSLEEP);
|
||||
if (xfer == NULL) {
|
||||
return TRY_AGAIN_LATER;
|
||||
}
|
||||
if (sc_xfer->flags & SCSI_POLL)
|
||||
xfer->c_flags |= C_POLL;
|
||||
drvp = &wdc->channels[channel].ch_drive[drive];
|
||||
if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
|
||||
sc_xfer->datalen > 0)
|
||||
xfer->c_flags |= C_DMA;
|
||||
xfer->drive = drive;
|
||||
xfer->c_flags |= C_ATAPI;
|
||||
xfer->cmd = sc_xfer;
|
||||
xfer->databuf = sc_xfer->data;
|
||||
xfer->c_bcount = sc_xfer->datalen;
|
||||
xfer->c_start = wdc_atapi_start;
|
||||
xfer->c_intr = wdc_atapi_intr;
|
||||
s = splbio();
|
||||
wdc_exec_xfer(&wdc->channels[channel], xfer);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((sc_xfer->flags & SCSI_POLL) != 0 &&
|
||||
(sc_xfer->flags & ITSDONE) == 0)
|
||||
panic("wdc_atapi_send_cmd: polled command not done");
|
||||
#endif
|
||||
ret = (sc_xfer->flags & ITSDONE) ? COMPLETE : SUCCESSFULLY_QUEUED;
|
||||
splx(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
wdc_atapi_start(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct scsipi_xfer *sc_xfer = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_start, scsi flags 0x%x \n",sc_xfer->flags),
|
||||
DEBUG_FUNCS);
|
||||
/* Do control operations specially. */
|
||||
if (drvp->state < READY) {
|
||||
if (drvp->state != PIOMODE) {
|
||||
printf("%s:%d:%d: bad state %d in wdc_atapi_start\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive, drvp->state);
|
||||
panic("wdc_atapi_start: bad state");
|
||||
}
|
||||
wdc_atapi_ctrl(chp, xfer);
|
||||
return;
|
||||
}
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
if (wait_for_unbusy(chp, ATAPI_DELAY) < 0) {
|
||||
printf("wdc_atapi_start: not ready, st = %02x\n",
|
||||
chp->ch_status);
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even with WDCS_ERR, the device should accept a command packet
|
||||
* Limit length to what can be stuffed into the cylinder register
|
||||
* (16 bits). Some CD-ROMs seem to interpret '0' as 65536,
|
||||
* but not all devices do that and it's not obvious from the
|
||||
* ATAPI spec that that behaviour should be expected. If more
|
||||
* data is necessary, multiple data transfer phases will be done.
|
||||
*/
|
||||
wdccommand(chp, xfer->drive, ATAPI_PKT_CMD,
|
||||
sc_xfer->datalen <= 0xffff ? sc_xfer->datalen : 0xffff,
|
||||
0, 0, 0,
|
||||
(xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA : 0);
|
||||
|
||||
/*
|
||||
* If there is no interrupt for CMD input, busy-wait for it (done in
|
||||
* the interrupt routine. If it is a polled command, call the interrupt
|
||||
* routine until command is done.
|
||||
*/
|
||||
if ((sc_xfer->sc_link->scsipi_atapi.cap & 0x0300) != ACAP_DRQ_INTR ||
|
||||
sc_xfer->flags & SCSI_POLL) {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
delay(1);
|
||||
if (wdc_atapi_intr(chp, xfer) == 0) {
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (sc_xfer->flags & SCSI_POLL) {
|
||||
while ((sc_xfer->flags & ITSDONE) == 0) {
|
||||
/* Wait for at last 400ns for status bit to be valid */
|
||||
delay(1);
|
||||
if (wdc_atapi_intr(chp, xfer) == 0) {
|
||||
sc_xfer->error = XS_SELTIMEOUT;
|
||||
/* do we know more ? */
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
wdc_atapi_intr(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct scsipi_xfer *sc_xfer = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
int len, phase, i, retries=0;
|
||||
int ire, dma_err = 0;
|
||||
int dma_flags = 0;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr\n"), DEBUG_INTR);
|
||||
|
||||
/* Is it not a transfer, but a control operation? */
|
||||
if (drvp->state < READY) {
|
||||
printf("%s:%d:%d: bad state %d in wdc_atapi_intr\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
drvp->state);
|
||||
panic("wdc_atapi_intr: bad state\n");
|
||||
}
|
||||
/* Ack interrupt done in wait_for_unbusy */
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
if (wait_for_unbusy(chp, sc_xfer->timeout) != 0) {
|
||||
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
xfer->c_bcount, xfer->c_skip);
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
/* Error here only if the command is aborted */
|
||||
if ((chp->ch_status & WDCS_ERR) != 0 &&
|
||||
(chp->ch_error & WDCE_ABRT) != 0) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done(), "
|
||||
"sense 0x%x\n", sc_xfer->sense.atapi_sense), DEBUG_INTR);
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
dma_flags = (sc_xfer->flags & SCSI_DATA_IN) ?
|
||||
WDC_DMA_READ : 0;
|
||||
dma_flags |= sc_xfer->flags & SCSI_POLL ? WDC_DMA_POLL : 0;
|
||||
}
|
||||
again:
|
||||
len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo) +
|
||||
256 * bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_hi);
|
||||
ire = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_ireason);
|
||||
phase = (ire & (WDCI_CMD | WDCI_IN)) | (chp->ch_status & WDCS_DRQ);
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: c_bcount %d len %d st 0x%x err 0x%x "
|
||||
"ire 0x%x :", xfer->c_bcount,
|
||||
len, chp->ch_status, chp->ch_error, ire), DEBUG_INTR);
|
||||
|
||||
switch (phase) {
|
||||
case PHASE_CMDOUT:
|
||||
WDCDEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);
|
||||
/* Init the DMA channel if necessary */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive,
|
||||
xfer->databuf, sc_xfer->datalen, dma_flags) != 0) {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* send packet command */
|
||||
/* Commands are 12 or 16 bytes long. It's 32-bit aligned */
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
(u_int32_t *)sc_xfer->cmd,
|
||||
sc_xfer->cmdlen >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
(u_int16_t *)sc_xfer->cmd,
|
||||
sc_xfer->cmdlen >> 1);
|
||||
}
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
bus_space_write_multi_stream_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
(u_int32_t *)sc_xfer->cmd,
|
||||
sc_xfer->cmdlen >> 2);
|
||||
} else {
|
||||
bus_space_write_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
(u_int16_t *)sc_xfer->cmd,
|
||||
sc_xfer->cmdlen >> 1);
|
||||
}
|
||||
}
|
||||
/* Start the DMA channel if necessary */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
(*chp->wdc->dma_start)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive, dma_flags);
|
||||
}
|
||||
|
||||
if ((sc_xfer->flags & SCSI_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PHASE_DATAOUT:
|
||||
/* write data */
|
||||
WDCDEBUG_PRINT(("PHASE_DATAOUT\n"), DEBUG_INTR);
|
||||
if ((sc_xfer->flags & SCSI_DATA_OUT) == 0 ||
|
||||
(xfer->c_flags & C_DMA) != 0) {
|
||||
printf("wdc_atapi_intr: bad data phase DATAOUT");
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
printf(", falling back to PIO\n");
|
||||
drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
|
||||
}
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
if (xfer->c_bcount < len) {
|
||||
printf("wdc_atapi_intr: warning: write only "
|
||||
"%d of %d requested bytes\n", xfer->c_bcount, len);
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {
|
||||
bus_space_write_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
xfer->c_bcount >> 1);
|
||||
} else {
|
||||
bus_space_write_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip,
|
||||
xfer->c_bcount >> 1);
|
||||
}
|
||||
for (i = xfer->c_bcount; i < len; i += 2)
|
||||
bus_space_write_2(chp->cmd_iot, chp->cmd_ioh,
|
||||
wd_data, 0);
|
||||
xfer->c_skip += xfer->c_bcount;
|
||||
xfer->c_bcount = 0;
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM))
|
||||
bus_space_write_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip, len >> 2);
|
||||
else
|
||||
bus_space_write_multi_stream_4(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 2);
|
||||
|
||||
xfer->c_skip += len & 0xfffffffc;
|
||||
xfer->c_bcount -= len & 0xfffffffc;
|
||||
len = len & 0x03;
|
||||
}
|
||||
if (len > 0) {
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM))
|
||||
bus_space_write_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 1);
|
||||
else
|
||||
bus_space_write_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 1);
|
||||
xfer->c_skip += len;
|
||||
xfer->c_bcount -= len;
|
||||
}
|
||||
}
|
||||
if ((sc_xfer->flags & SCSI_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PHASE_DATAIN:
|
||||
/* Read data */
|
||||
WDCDEBUG_PRINT(("PHASE_DATAIN\n"), DEBUG_INTR);
|
||||
if ((sc_xfer->flags & SCSI_DATA_IN) == 0 ||
|
||||
(xfer->c_flags & C_DMA) != 0) {
|
||||
printf("wdc_atapi_intr: bad data phase DATAIN");
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
printf(", falling back to PIO\n");
|
||||
drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
|
||||
}
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
if (xfer->c_bcount < len) {
|
||||
printf("wdc_atapi_intr: warning: reading only "
|
||||
"%d of %d bytes\n", xfer->c_bcount, len);
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)) {
|
||||
bus_space_read_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, xfer->c_bcount >> 1);
|
||||
} else {
|
||||
bus_space_read_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, xfer->c_bcount >> 1);
|
||||
}
|
||||
wdcbit_bucket(chp, len - xfer->c_bcount);
|
||||
xfer->c_skip += xfer->c_bcount;
|
||||
xfer->c_bcount = 0;
|
||||
} else {
|
||||
if (drvp->drive_flags & DRIVE_CAP32) {
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM))
|
||||
bus_space_read_multi_4(chp->data32iot,
|
||||
chp->data32ioh, 0,
|
||||
xfer->databuf + xfer->c_skip, len >> 2);
|
||||
else
|
||||
bus_space_read_multi_stream_4(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 2);
|
||||
|
||||
xfer->c_skip += len & 0xfffffffc;
|
||||
xfer->c_bcount -= len & 0xfffffffc;
|
||||
len = len & 0x03;
|
||||
}
|
||||
if (len > 0) {
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM))
|
||||
bus_space_read_multi_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 1);
|
||||
else
|
||||
bus_space_read_multi_stream_2(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_data,
|
||||
xfer->databuf + xfer->c_skip, len >> 1);
|
||||
xfer->c_skip += len;
|
||||
xfer->c_bcount -=len;
|
||||
}
|
||||
}
|
||||
if ((sc_xfer->flags & SCSI_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case PHASE_ABORTED:
|
||||
case PHASE_COMPLETED:
|
||||
WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
|
||||
/* turn off DMA channel */
|
||||
if (xfer->c_flags & C_DMA) {
|
||||
dma_err = (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
|
||||
chp->channel, xfer->drive, dma_flags);
|
||||
xfer->c_bcount -= sc_xfer->datalen;
|
||||
}
|
||||
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
} else if (dma_err < 0) {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
if (xfer->c_bcount != 0) {
|
||||
printf("wdc_atapi_intr warning: bcount value "
|
||||
"is %d after io\n", xfer->c_bcount);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
if (++retries<500) {
|
||||
DELAY(100);
|
||||
chp->ch_status = bus_space_read_1(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_status);
|
||||
chp->ch_error = bus_space_read_1(chp->cmd_iot,
|
||||
chp->cmd_ioh, wd_error);
|
||||
goto again;
|
||||
}
|
||||
printf("wdc_atapi_intr: unknown phase 0x%x\n", phase);
|
||||
if (chp->ch_status & WDCS_ERR) {
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
} else {
|
||||
sc_xfer->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
WDCDEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done() (end), error 0x%x "
|
||||
"sense 0x%x\n", sc_xfer->error, sc_xfer->sense.atapi_sense),
|
||||
DEBUG_INTR);
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
wdc_atapi_ctrl(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct scsipi_xfer *sc_xfer = xfer->cmd;
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
char *errstring = NULL;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_ctrl state %d\n", drvp->state), DEBUG_INTR);
|
||||
/* Ack interrupt done in wait_for_unbusy */
|
||||
again:
|
||||
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
|
||||
WDSD_IBM | (xfer->drive << 4));
|
||||
switch (drvp->state) {
|
||||
case PIOMODE:
|
||||
/* Don't try to set mode if controller can't be adjusted */
|
||||
if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
|
||||
goto ready;
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x08 | drvp->PIO_mode, WDSF_SET_MODE);
|
||||
drvp->state = PIOMODE_WAIT;
|
||||
break;
|
||||
case PIOMODE_WAIT:
|
||||
errstring = "piomode";
|
||||
if (wait_for_unbusy(chp, ATAPI_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & WDCS_ERR)
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case DMAMODE:
|
||||
if (drvp->drive_flags & DRIVE_UDMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
|
||||
} else if (drvp->drive_flags & DRIVE_DMA) {
|
||||
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
|
||||
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
|
||||
} else {
|
||||
goto ready;
|
||||
}
|
||||
drvp->state = DMAMODE_WAIT;
|
||||
break;
|
||||
case DMAMODE_WAIT:
|
||||
errstring = "dmamode";
|
||||
if (wait_for_unbusy(chp, ATAPI_DELAY))
|
||||
goto timeout;
|
||||
if (chp->ch_status & WDCS_ERR)
|
||||
goto error;
|
||||
/* fall through */
|
||||
|
||||
case READY:
|
||||
ready:
|
||||
drvp->state = READY;
|
||||
xfer->c_intr = wdc_atapi_intr;
|
||||
wdc_atapi_start(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
if ((sc_xfer->flags & SCSI_POLL) == 0) {
|
||||
chp->ch_flags |= WDCF_IRQ_WAIT;
|
||||
xfer->c_intr = wdc_atapi_ctrl;
|
||||
timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
|
||||
} else {
|
||||
goto again;
|
||||
}
|
||||
return 1;
|
||||
|
||||
timeout:
|
||||
if ((xfer->c_flags & C_TIMEOU) == 0 ) {
|
||||
return 0; /* IRQ was not for us */
|
||||
}
|
||||
printf("%s:%d:%d: %s timed out\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
|
||||
wdc_atapi_reset(chp, xfer);
|
||||
return 1;
|
||||
error:
|
||||
printf("%s:%d:%d: %s ",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
|
||||
errstring);
|
||||
printf("error (%x)\n", chp->ch_error);
|
||||
sc_xfer->error = XS_SENSE;
|
||||
sc_xfer->sense.atapi_sense = chp->ch_error;
|
||||
drvp->state = 0;
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
wdc_atapi_done(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct scsipi_xfer *sc_xfer = xfer->cmd;
|
||||
struct wdc_softc *wdc = chp->wdc;
|
||||
int need_done = xfer->c_flags & C_NEEDDONE;
|
||||
|
||||
WDCDEBUG_PRINT(("wdc_atapi_done: flags 0x%x\n", (u_int)xfer->c_flags),
|
||||
DEBUG_FUNCS);
|
||||
sc_xfer->resid = xfer->c_bcount;
|
||||
/* remove this command from xfer queue */
|
||||
xfer->c_skip = 0;
|
||||
wdc_free_xfer(chp, xfer);
|
||||
sc_xfer->flags |= ITSDONE;
|
||||
if (need_done) {
|
||||
WDCDEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_FUNCS);
|
||||
scsipi_done(sc_xfer);
|
||||
}
|
||||
WDCDEBUG_PRINT(("wdcstart from wdc_atapi_done, flags 0x%x\n",
|
||||
chp->ch_flags), DEBUG_FUNCS);
|
||||
wdcstart(wdc, chp->channel);
|
||||
}
|
||||
|
||||
void
|
||||
wdc_atapi_reset(chp, xfer)
|
||||
struct channel_softc *chp;
|
||||
struct wdc_xfer *xfer;
|
||||
{
|
||||
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
|
||||
struct scsipi_xfer *sc_xfer = xfer->cmd;
|
||||
|
||||
wdccommandshort(chp, xfer->drive, ATAPI_SOFT_RESET);
|
||||
drvp->state = 0;
|
||||
if (wait_for_unbusy(chp, WDC_RESET_WAIT) != 0) {
|
||||
printf("%s:%d:%d: reset failed\n",
|
||||
chp->wdc->sc_dev.dv_xname, chp->channel,
|
||||
xfer->drive);
|
||||
sc_xfer->error = XS_SELTIMEOUT;
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return;
|
||||
}
|
||||
sc_xfer->error = XS_TIMEOUT;
|
||||
wdc_atapi_done(chp, xfer);
|
||||
return;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapiconf.c,v 1.12 1998/08/31 22:28:06 cgd Exp $ */
|
||||
/* $NetBSD: atapiconf.c,v 1.13 1998/10/12 16:09:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Manuel Bouyer. All rights reserved.
|
||||
@ -37,6 +37,8 @@
|
||||
#include <sys/buf.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <dev/ata/atareg.h>
|
||||
#include <dev/ata/atavar.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/atapi_all.h>
|
||||
#include <dev/scsipi/scsipiconf.h>
|
||||
@ -50,6 +52,7 @@ struct atapibus_softc {
|
||||
struct device sc_dev;
|
||||
struct scsipi_link *adapter_link; /* proto supplied by adapter */
|
||||
struct scsipi_link **sc_link; /* dynamically allocated */
|
||||
struct ata_drive_datas *sc_drvs; /* array supplied by adapter */
|
||||
};
|
||||
|
||||
int atapibusmatch __P((struct device *, struct cfdata *, void *));
|
||||
@ -99,12 +102,15 @@ atapibusmatch(parent, cf, aux)
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
struct scsipi_link *sc_link = aux;
|
||||
struct ata_atapi_attach *aa_link = aux;
|
||||
|
||||
if (sc_link == NULL)
|
||||
if (aa_link == NULL)
|
||||
return (0);
|
||||
if (sc_link->type != BUS_ATAPI)
|
||||
if (aa_link->aa_type != T_ATAPI)
|
||||
return (0);
|
||||
if (cf->cf_loc[ATAPICF_CHANNEL] != aa_link->aa_channel &&
|
||||
cf->cf_loc[ATAPICF_CHANNEL] != ATAPICF_CHANNEL_DEFAULT)
|
||||
return 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -128,7 +134,7 @@ void
|
||||
atapi_fixquirk(sc_link)
|
||||
struct scsipi_link *ad_link;
|
||||
{
|
||||
struct atapi_identify *id = &ad_link->id;
|
||||
struct ataparams *id = &ad_link->id;
|
||||
struct atapi_quirk_inquiry_pattern *quirk;
|
||||
|
||||
/*
|
||||
@ -145,8 +151,9 @@ atapibusattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct atapibus_softc *ab = (struct atapibus_softc *)self;
|
||||
struct scsipi_link *sc_link_proto = aux;
|
||||
struct atapibus_softc *sc_ab = (struct atapibus_softc *)self;
|
||||
struct ata_atapi_attach *aa_link = aux;
|
||||
struct scsipi_link *sc_link_proto;
|
||||
int nbytes;
|
||||
|
||||
printf("\n");
|
||||
@ -154,20 +161,33 @@ atapibusattach(parent, self, aux)
|
||||
/* Initialize shared data. */
|
||||
scsipi_init();
|
||||
|
||||
sc_link_proto->scsipi_atapi.atapibus = ab->sc_dev.dv_unit;
|
||||
sc_link_proto = malloc(sizeof(struct scsipi_link),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc_link_proto == NULL)
|
||||
printf("atapibusattach : can't allocate scsipi link proto\n");
|
||||
memset(sc_link_proto, 0, sizeof(struct scsipi_link));
|
||||
|
||||
sc_link_proto->type = BUS_ATAPI;
|
||||
sc_link_proto->openings = aa_link->aa_openings;
|
||||
sc_link_proto->scsipi_atapi.channel = aa_link->aa_channel;
|
||||
sc_link_proto->adapter_softc = parent;
|
||||
sc_link_proto->adapter = aa_link->aa_bus_private;
|
||||
sc_link_proto->scsipi_atapi.atapibus = sc_ab->sc_dev.dv_unit;
|
||||
sc_link_proto->scsipi_cmd = atapi_scsipi_cmd;
|
||||
sc_link_proto->scsipi_interpret_sense = atapi_interpret_sense;
|
||||
sc_link_proto->sc_print_addr = atapi_print_addr;
|
||||
|
||||
ab->adapter_link = sc_link_proto;
|
||||
|
||||
sc_ab->adapter_link = sc_link_proto;
|
||||
sc_ab->sc_drvs = aa_link->aa_drv_data;
|
||||
|
||||
nbytes = 2 * sizeof(struct scsipi_link **);
|
||||
ab->sc_link = (struct scsipi_link **)malloc(nbytes, M_DEVBUF,
|
||||
sc_ab->sc_link = (struct scsipi_link **)malloc(nbytes, M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
if (ab->sc_link == NULL)
|
||||
if (sc_ab->sc_link == NULL)
|
||||
panic("scsibusattach: can't allocate target links");
|
||||
bzero(ab->sc_link, nbytes);
|
||||
atapi_probe_bus(ab->sc_dev.dv_unit, -1);
|
||||
memset(sc_ab->sc_link, 0, nbytes);
|
||||
atapi_probe_bus(sc_ab->sc_dev.dv_unit, -1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -203,8 +223,9 @@ atapi_probedev(atapi, target)
|
||||
{
|
||||
struct scsipi_link *sc_link;
|
||||
struct scsipibus_attach_args sa;
|
||||
struct atapi_identify ids;
|
||||
struct atapi_identify *id = &ids;
|
||||
struct ataparams ids;
|
||||
struct ataparams *id = &ids;
|
||||
struct ata_drive_datas *drvp = &atapi->sc_drvs[target];
|
||||
struct cfdata *cf;
|
||||
struct scsi_quirk_inquiry_pattern *finger;
|
||||
int priority;
|
||||
@ -214,23 +235,14 @@ atapi_probedev(atapi, target)
|
||||
if (atapi->sc_link[target])
|
||||
return;
|
||||
|
||||
if (wdc_atapi_get_params(atapi->adapter_link, target, id)) {
|
||||
if (wdc_atapi_get_params(atapi->adapter_link, target,
|
||||
SCSI_POLL|SCSI_NOSLEEP, id) == COMPLETE) {
|
||||
#ifdef ATAPI_DEBUG_PROBE
|
||||
printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
|
||||
atapi->sc_dev.dv_xname, target,
|
||||
id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_MASK,
|
||||
id->config.cmd_drq_rem & ATAPI_DRQ_MASK);
|
||||
#endif
|
||||
/*
|
||||
* Shuffle string byte order.
|
||||
* Mitsumi and NEC drives don't need this.
|
||||
*/
|
||||
if (((id->model[0] == 'N' && id->model[1] == 'E') ||
|
||||
(id->model[0] == 'F' && id->model[1] == 'X')) == 0)
|
||||
bswap(id->model, sizeof(id->model));
|
||||
bswap(id->serial_number, sizeof(id->serial_number));
|
||||
bswap(id->firmware_revision, sizeof(id->firmware_revision));
|
||||
|
||||
/*
|
||||
* Allocate a device link and try and attach
|
||||
* a driver to this device. If we fail, free
|
||||
@ -250,25 +262,19 @@ atapi_probedev(atapi, target)
|
||||
if (DEBUGTARGET == -1 || target == DEBUGTARGET)
|
||||
sc_link->flags |= DEBUGLEVEL;
|
||||
#endif /* SCSIDEBUG */
|
||||
if (id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_16)
|
||||
if ((id->atap_config & ATAPI_CFG_CMD_MASK) == ATAPI_CFG_CMD_16)
|
||||
sc_link->scsipi_atapi.cap |= ACAP_LEN;
|
||||
sc_link->scsipi_atapi.cap |=
|
||||
(id->config.cmd_drq_rem & ATAPI_DRQ_MASK) << 3;
|
||||
#if 0
|
||||
bcopy(id, &ad_link->id, sizeof(*id));
|
||||
/* Fix strings and look through the quirk table. */
|
||||
atapi_fixquirk(ad_link, id);
|
||||
#endif
|
||||
(id->atap_config & ATAPI_CFG_DRQ_MASK);
|
||||
sa.sa_sc_link = sc_link;
|
||||
sa.sa_inqbuf.type = id->config.device_type & SID_TYPE;
|
||||
sa.sa_inqbuf.type = ATAPI_CFG_TYPE(id->atap_config);
|
||||
sa.sa_inqbuf.removable =
|
||||
id->config.cmd_drq_rem & ATAPI_REMOVABLE ?
|
||||
T_REMOV : T_FIXED;
|
||||
id->atap_config & ATAPI_CFG_REMOV ? T_REMOV : T_FIXED;
|
||||
if (sa.sa_inqbuf.removable)
|
||||
sc_link->flags |= SDEV_REMOVABLE;
|
||||
scsipi_strvis(model, 40, id->model, 40);
|
||||
scsipi_strvis(serial_number, 20, id->serial_number, 20);
|
||||
scsipi_strvis(firmware_revision, 8, id->firmware_revision, 8);
|
||||
scsipi_strvis(model, 40, id->atap_model, 40);
|
||||
scsipi_strvis(serial_number, 20, id->atap_serial, 20);
|
||||
scsipi_strvis(firmware_revision, 8, id->atap_revision, 8);
|
||||
sa.sa_inqbuf.vendor = model;
|
||||
sa.sa_inqbuf.product = serial_number;
|
||||
sa.sa_inqbuf.revision = firmware_revision;
|
||||
@ -284,7 +290,9 @@ atapi_probedev(atapi, target)
|
||||
if ((cf = config_search(atapibussubmatch, &atapi->sc_dev,
|
||||
&sa)) != 0) {
|
||||
atapi->sc_link[target] = sc_link;
|
||||
config_attach(&atapi->sc_dev, cf, &sa, atapibusprint);
|
||||
drvp->drv_softc = config_attach(&atapi->sc_dev, cf,
|
||||
&sa, atapibusprint);
|
||||
wdc_probe_caps(drvp);
|
||||
return;
|
||||
} else {
|
||||
atapibusprint(&sa, atapi->sc_dev.dv_xname);
|
||||
@ -292,12 +300,6 @@ atapi_probedev(atapi, target)
|
||||
free(sc_link, M_DEVBUF);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 /* WAS: */
|
||||
/* Try to find a match. */
|
||||
if (config_found(self, ad_link, atapiprint) == NULL)
|
||||
free(ad_link, M_DEVBUF);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: atapiconf.h,v 1.6 1998/02/13 08:28:23 enami Exp $ */
|
||||
/* $NetBSD: atapiconf.h,v 1.7 1998/10/12 16:09:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Manuel Bouyer. All rights reserved.
|
||||
@ -31,104 +31,18 @@
|
||||
|
||||
#include <dev/scsipi/scsipiconf.h>
|
||||
|
||||
struct atapi_identify {
|
||||
struct config_s {
|
||||
u_int8_t cmd_drq_rem;
|
||||
#define ATAPI_PACKET_SIZE_MASK 0x03
|
||||
#define ATAPI_PACKET_SIZE_12 0x00
|
||||
#define ATAPI_PACKET_SIZE_16 0x01
|
||||
/* drive states stored in ata_drive_datas */
|
||||
#define PIOMODE 0
|
||||
#define PIOMODE_WAIT 1
|
||||
#define DMAMODE 2
|
||||
#define DMAMODE_WAIT 3
|
||||
#define READY 4
|
||||
|
||||
#define ATAPI_DRQ_MASK 0x60
|
||||
#define ATAPI_MICROPROCESSOR_DRQ 0x00
|
||||
#define ATAPI_INTERRUPT_DRQ 0x20
|
||||
#define ATAPI_ACCELERATED_DRQ 0x40
|
||||
struct atapi_mode_header;
|
||||
struct ataparams;
|
||||
|
||||
#define ATAPI_REMOVABLE 0x80
|
||||
|
||||
u_int8_t device_type;
|
||||
#define ATAPI_DEVICE_TYPE_MASK 0x1f
|
||||
#define ATAPI_DEVICE_TYPE_DAD 0x00 /* direct access device */
|
||||
/* 0x1-0x4 reserved */
|
||||
#define ATAPI_DEVICE_TYPE_CD 0x05 /* CD-ROM */
|
||||
/* 0x6 reserved */
|
||||
#define ATAPI_DEVICE_TYPE_OMD 0x07 /* optical memory device */
|
||||
/* 0x8-0x1e reserved */
|
||||
#define ATAPI_DEVICE_TYPE_UNKNOWN 0x1f
|
||||
|
||||
#define ATAPI_GC_PROTOCOL_MASK 0xc0 /* mask of protocol bits */
|
||||
/* 0x00 and 0x01 are ATA */
|
||||
#define ATAPI_GC_PROTO_TYPE_ATAPI 0x80
|
||||
#define ATAPI_GC_PROTO_TYPE_RESERVED 0xc0
|
||||
} config; /* general configuration */
|
||||
|
||||
u_int8_t cylinders[2];
|
||||
u_int8_t reserved1[2];
|
||||
u_int8_t heads[2];
|
||||
u_int8_t unf_bytes_per_track[2];
|
||||
u_int8_t unf_bytes_per_sector[2];
|
||||
u_int8_t sectors_per_track[2];
|
||||
u_int8_t reserved2[6];
|
||||
char serial_number[20];
|
||||
u_int8_t buffer_type[2];
|
||||
u_int8_t buffer_size[2];
|
||||
u_int8_t ECC_bytes_available[2];
|
||||
char firmware_revision[8];
|
||||
char model[40];
|
||||
u_int8_t sector_count[2];
|
||||
u_int8_t double_word[2]; /* == 0 for CD-ROMs */
|
||||
|
||||
struct capabilities_s {
|
||||
u_int8_t vendor;
|
||||
u_int8_t capflags;
|
||||
#define ATAPI_CAP_DMA 0x01 /* DMA supported */
|
||||
#define ATAPI_CAP_LBA 0x02 /* LBA supported */
|
||||
#define ATAPI_IORDY_DISABLE 0x04 /* IORDY can be disabled */
|
||||
#define ATAPI_IORDY 0x08 /* IORDY supported */
|
||||
} capabilities;
|
||||
|
||||
u_int8_t reserved3[2];
|
||||
u_int8_t PIO_cycle_timing[2];
|
||||
u_int8_t DMA_cycle_timing[2];
|
||||
u_int8_t validity[2]; /* of words 54-58, 64-70 in this table */
|
||||
|
||||
#define ATAPI_VALID_FIRST 0x0 /* == 1 => words 54-58 are valid */
|
||||
#define ATAPI_VALID_SECOND 0x1 /* == 1 => words 64-70 are valid */
|
||||
|
||||
u_int8_t current_chs[6]; /* cylinder/head/sector */
|
||||
u_int8_t current_capacity[4];
|
||||
u_int8_t reserved4[2];
|
||||
u_int8_t user_addressable_sectors[4];
|
||||
u_int8_t singleword_DMA_mode[2];
|
||||
|
||||
#define ATAPI_SW_DMA_MODE_AVAIL 0x00ff /* Mode 0 is supported */
|
||||
#define ATAPI_SW_DMA_MODE_ACTIVE 0xff00 /* which mode is active */
|
||||
|
||||
u_int8_t multiword_DMA_mode[2];
|
||||
|
||||
#define ATAPI_MW_DMA_MODE_AVAIL 0x00ff /* Mode 0 is supported */
|
||||
#define ATAPI_MW_DMA_MODE_ACTIVE 0xff00 /* which mode is active */
|
||||
|
||||
u_int8_t enhanced_PIO_mode[2];
|
||||
|
||||
#define ATAPI_ENHANCED_PIO_AVAIL 0x0001 /* PIO Mode 3 is supported */
|
||||
|
||||
u_int8_t blind_PIO_minimum_cycles[2];
|
||||
u_int8_t mw_dma_tct[2]; /* multi-word DMA transfer cycle time */
|
||||
u_int8_t min_PIO_tct_no_flow_control[2];
|
||||
u_int8_t min_PIO_tct_with_flow_control[2];
|
||||
u_int8_t reserved5[4];
|
||||
u_int8_t reserved6[114];
|
||||
u_int8_t vendor[64]; /* vendor unique */
|
||||
u_int8_t reserved7[192];
|
||||
};
|
||||
|
||||
struct atapibus_attach_args {
|
||||
struct scsipi_link *sa_sc_link;
|
||||
struct atapi_identify *sa_inqbuf;
|
||||
};
|
||||
|
||||
int wdc_atapi_get_params __P((struct scsipi_link *, u_int8_t,
|
||||
struct atapi_identify *));
|
||||
int wdc_atapi_get_params __P((struct scsipi_link *, u_int8_t, int,
|
||||
struct ataparams *));
|
||||
void atapi_print_addr __P((struct scsipi_link *));
|
||||
int atapi_interpret_sense __P((struct scsipi_xfer *));
|
||||
int atapi_scsipi_cmd __P((struct scsipi_link *, struct scsipi_generic *,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.scsipi,v 1.16 1998/07/30 00:49:19 mjacob Exp $
|
||||
# $NetBSD: files.scsipi,v 1.17 1998/10/12 16:09:24 bouyer Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent SCSI code.
|
||||
# Included by ports that need it. Ports that use it must provide
|
||||
@ -12,6 +12,7 @@ file dev/scsipi/scsipi_ioctl.c scsi | atapi
|
||||
file dev/scsipi/scsi_base.c scsi
|
||||
file dev/scsipi/scsi_verbose.c scsi & scsiverbose
|
||||
file dev/scsipi/atapi_base.c atapi
|
||||
file dev/scsipi/atapi_wdc.c atapi & wdc_base
|
||||
|
||||
device scsibus {target = -1, lun = -1}
|
||||
attach scsibus at scsi
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: scsipiconf.h,v 1.19 1998/10/10 00:36:13 thorpej Exp $ */
|
||||
/* $NetBSD: scsipiconf.h,v 1.20 1998/10/12 16:09:25 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -216,19 +216,17 @@ struct scsipi_link {
|
||||
int max_target; /* XXX max target supported
|
||||
by adapter */
|
||||
} scsipi_scsi;
|
||||
struct atapi_link { /* XXX this must be in sync
|
||||
with wd_link */
|
||||
u_int8_t type; /* 0 = ATA, 1 = ATAPI, from
|
||||
wdlink.h */
|
||||
struct atapi_link {
|
||||
u_int8_t drive; /* drive number on the bus */
|
||||
u_int8_t channel; /* channel, i.e. bus # on
|
||||
controller */
|
||||
u_int8_t drive; /* drive number on the bus */
|
||||
u_int8_t atapibus;
|
||||
u_int8_t cap; /* drive capability */
|
||||
#define ACAP_DRQ_MPROC 0x0000 /* microprocessor DRQ */
|
||||
#define ACAP_DRQ_INTR 0x0100 /* interrupt DRQ */
|
||||
#define ACAP_DRQ_ACCEL 0x0200 /* accelerated DRQ */
|
||||
#define ACAP_LEN 0x0400 /* 16 bit commands */
|
||||
#define ACAP_DRQ_INTR 0x0200 /* interrupt DRQ */
|
||||
#define ACAP_DRQ_ACCEL 0x0400 /* accelerated DRQ */
|
||||
#define ACAP_DRQ_MASK 0x0600 /* same as in ataparams */
|
||||
#define ACAP_LEN 0x0100 /* 16 bit commands */
|
||||
} scsipi_atapi;
|
||||
} _scsipi_link;
|
||||
int (*scsipi_cmd) __P((struct scsipi_link *, struct scsipi_generic *,
|
||||
|
Loading…
Reference in New Issue
Block a user