ce36c22380
for calling match_podule() rather than using hardcoded values.
376 lines
9.5 KiB
C
376 lines
9.5 KiB
C
/* $NetBSD: oak.c,v 1.9 1996/10/14 23:42:18 mark Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1995 Melvin Tang-Richardson 1996.
|
|
* 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 RiscBSD.
|
|
* 4. The name of the company nor the name of the author may be used to
|
|
* endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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.
|
|
*/
|
|
|
|
/*
|
|
* Oak SCSI Driver using the NCR5380 generic driver
|
|
*/
|
|
|
|
#undef USE_OWN_PIO_ROUTINES
|
|
|
|
/* Some system includes *****************************************************/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/cdefs.h>
|
|
#include <sys/time.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/param.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/syslog.h>
|
|
#include <sys/device.h>
|
|
#include <sys/buf.h>
|
|
/*#include <machine/bootconfig.h>*/
|
|
|
|
/* SCSI bus includes */
|
|
|
|
#include <scsi/scsi_all.h>
|
|
#include <scsi/scsiconf.h>
|
|
|
|
/* Hardware related include chip/card/bus ***********************************/
|
|
|
|
#include <machine/io.h>
|
|
#include <machine/irqhandler.h>
|
|
#include <machine/katelib.h>
|
|
#include <arm32/podulebus/podulebus.h>
|
|
#include <arm32/podulebus/ncr5380reg.h>
|
|
#include <arm32/podulebus/ncr5380var.h>
|
|
#include <arm32/podulebus/podules.h>
|
|
|
|
/****************************************************************************/
|
|
/* Some useful definitions **************************************************/
|
|
/****************************************************************************/
|
|
|
|
#define MAX_DMA_LEN (0xe000)
|
|
|
|
/****************************************************************************/
|
|
/* Prototype internal data structures ***************************************/
|
|
/****************************************************************************/
|
|
|
|
struct oak_softc {
|
|
struct ncr5380_softc ncr_sc;
|
|
int sc_podule_number;
|
|
podule_t *sc_podule;
|
|
int sc_base;
|
|
};
|
|
|
|
/****************************************************************************/
|
|
/* Function and data prototypes *********************************************/
|
|
/****************************************************************************/
|
|
|
|
int oakprobe __P((struct device *, void *, void *));
|
|
void oakattach __P((struct device *, struct device *, void *));
|
|
void oakminphys __P((struct buf *));
|
|
|
|
#ifdef USE_OWN_PIO_ROUTINES
|
|
int oak_pio_in __P((struct ncr5380_softc *, int, int, unsigned char *));
|
|
int oak_pio_out __P((struct ncr5380_softc *, int, int, unsigned char *));
|
|
#endif
|
|
|
|
struct scsi_adapter oak_adapter = {
|
|
ncr5380_scsi_cmd,
|
|
oakminphys,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
struct scsi_device oak_device = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
int
|
|
oakprobe(parent, match, aux)
|
|
struct device *parent;
|
|
void *match;
|
|
void *aux;
|
|
{
|
|
struct podule_attach_args *pa = (void *) aux;
|
|
|
|
/* Look for the card */
|
|
|
|
if (matchpodule(pa, MANUFACTURER_OAK, PODULE_OAK_SCSI, -1) == 0)
|
|
return(0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
oakattach(parent, self, aux)
|
|
struct device *parent;
|
|
struct device *self;
|
|
void *aux;
|
|
{
|
|
struct oak_softc *sc = (void *) self;
|
|
struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
|
|
struct podule_attach_args *pa = (void *)aux;
|
|
|
|
if (pa->pa_podule_number == -1)
|
|
panic("Podule has disappeared !");
|
|
|
|
sc->sc_podule_number = pa->pa_podule_number;
|
|
sc->sc_podule = pa->pa_podule;
|
|
podules[sc->sc_podule_number].attached = 1;
|
|
sc->sc_base = sc->sc_podule->mod_base;
|
|
|
|
printf(" 16-bit");
|
|
|
|
ncr_sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
|
|
ncr_sc->sc_link.adapter_softc = sc;
|
|
ncr_sc->sc_link.adapter_target = 7;
|
|
ncr_sc->sc_link.adapter = &oak_adapter;
|
|
ncr_sc->sc_link.device = &oak_device;
|
|
|
|
ncr_sc->sci_r0 = (volatile u_char *)sc->sc_base + 0x00;
|
|
ncr_sc->sci_r1 = (volatile u_char *)sc->sc_base + 0x04;
|
|
ncr_sc->sci_r2 = (volatile u_char *)sc->sc_base + 0x08;
|
|
ncr_sc->sci_r3 = (volatile u_char *)sc->sc_base + 0x0c;
|
|
ncr_sc->sci_r4 = (volatile u_char *)sc->sc_base + 0x10;
|
|
ncr_sc->sci_r5 = (volatile u_char *)sc->sc_base + 0x14;
|
|
ncr_sc->sci_r6 = (volatile u_char *)sc->sc_base + 0x18;
|
|
ncr_sc->sci_r7 = (volatile u_char *)sc->sc_base + 0x1c;
|
|
|
|
#ifdef USE_OWN_PIO_ROUTINES
|
|
printf ( ", my pio" );
|
|
ncr_sc->sc_pio_out = oak_pio_out;
|
|
ncr_sc->sc_pio_in = oak_pio_in;
|
|
#else
|
|
printf ( ", normal pio" );
|
|
ncr_sc->sc_pio_out = ncr5380_pio_out;
|
|
ncr_sc->sc_pio_in = ncr5380_pio_in;
|
|
#endif
|
|
|
|
ncr_sc->sc_dma_alloc = NULL;
|
|
ncr_sc->sc_dma_free = NULL;
|
|
ncr_sc->sc_dma_poll = NULL;
|
|
ncr_sc->sc_dma_setup = NULL;
|
|
ncr_sc->sc_dma_start = NULL;
|
|
ncr_sc->sc_dma_eop = NULL;
|
|
ncr_sc->sc_dma_stop = NULL;
|
|
|
|
printf(", polling");
|
|
ncr_sc->sc_intr_on = NULL;
|
|
ncr_sc->sc_intr_off = NULL;
|
|
|
|
ncr_sc->sc_flags = NCR5380_FORCE_POLLING;
|
|
|
|
ncr5380_init(ncr_sc);
|
|
ncr5380_reset_scsibus(ncr_sc);
|
|
|
|
printf(" UNDER DEVELOPMENT\n");
|
|
|
|
config_found(self, &(ncr_sc->sc_link), scsiprint);
|
|
}
|
|
|
|
|
|
void
|
|
oakminphys(bp)
|
|
struct buf *bp;
|
|
{
|
|
if (bp->b_bcount > MAX_DMA_LEN) {
|
|
printf("oak: DEBUG reducing dma length\n");
|
|
bp->b_bcount = MAX_DMA_LEN;
|
|
}
|
|
minphys(bp);
|
|
}
|
|
|
|
struct cfattach oak_ca = {
|
|
sizeof(struct oak_softc), oakprobe, oakattach
|
|
};
|
|
|
|
struct cfdriver oak_cd = {
|
|
NULL, "oak", DV_DISK, NULL, 0,
|
|
};
|
|
|
|
#ifdef USE_OWN_PIO_ROUTINES
|
|
|
|
/****************************************************************************/
|
|
/* Copyright (c) 1996 Melvin Tang-Richardson */
|
|
/* Copyright (c) 1995 David Jones, Gordon W. Rose */
|
|
/* Copyright (c) 1994 Jarle Greipsland */
|
|
/****************************************************************************/
|
|
|
|
static ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS */
|
|
static ncr5380_wait_nrq_timo = 1000 * 25; /* X2 = 50 mS */
|
|
|
|
/* Return zero on success. */
|
|
static __inline__ int ncr5380_wait_req(sc)
|
|
struct ncr5380_softc *sc;
|
|
{
|
|
register int timo = ncr5380_wait_req_timo;
|
|
for (;;) {
|
|
if (*sc->sci_bus_csr & SCI_BUS_REQ) {
|
|
timo = 0; /* return 0 */
|
|
break;
|
|
}
|
|
if (--timo < 0)
|
|
break; /* return -1 */
|
|
delay(2);
|
|
}
|
|
return (timo);
|
|
}
|
|
|
|
/* Return zero on success. */
|
|
static __inline__ int ncr5380_wait_not_req(sc)
|
|
struct ncr5380_softc *sc;
|
|
{
|
|
register int timo = ncr5380_wait_nrq_timo;
|
|
for (;;) {
|
|
if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
|
|
timo = 0; /* return 0 */
|
|
break;
|
|
}
|
|
if (--timo < 0)
|
|
break; /* return -1 */
|
|
delay(2);
|
|
}
|
|
return (timo);
|
|
}
|
|
|
|
int
|
|
oak_pio_out(sc, phase, count, data)
|
|
struct ncr5380_softc *sc;
|
|
int phase, count;
|
|
unsigned char *data;
|
|
{
|
|
register u_char icmd;
|
|
register int resid;
|
|
register int error;
|
|
|
|
printf("oak: pio_out %d %d\n", phase, count);
|
|
|
|
icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
|
|
|
|
icmd |= SCI_ICMD_DATA;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
resid = count;
|
|
while (resid > 0) {
|
|
if (!SCI_BUSY(sc)) {
|
|
NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
if (ncr5380_wait_req(sc)) {
|
|
NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
|
|
break;
|
|
|
|
/* Put the data on the bus. */
|
|
*sc->sci_odata = *data++;
|
|
|
|
/* Tell the target it's there. */
|
|
icmd |= SCI_ICMD_ACK;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
/* Wait for target to get it. */
|
|
error = ncr5380_wait_not_req(sc);
|
|
|
|
/* OK, it's got it (or we gave up waiting). */
|
|
icmd &= ~SCI_ICMD_ACK;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
if (error) {
|
|
NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
|
|
--resid;
|
|
}
|
|
|
|
/* Stop driving the data bus. */
|
|
icmd &= ~SCI_ICMD_DATA;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
return (count - resid);
|
|
}
|
|
|
|
int
|
|
oak_pio_in(sc, phase, count, data)
|
|
struct ncr5380_softc *sc;
|
|
int phase, count;
|
|
unsigned char *data;
|
|
{
|
|
register u_char icmd;
|
|
register int resid;
|
|
register int error;
|
|
|
|
printf("oak: pio_in %d %d\n", phase, count);
|
|
|
|
icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
|
|
|
|
resid = count;
|
|
while (resid > 0) {
|
|
if (!SCI_BUSY(sc)) {
|
|
NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
if (ncr5380_wait_req(sc)) {
|
|
NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
/* A phase change is not valid until AFTER REQ rises! */
|
|
if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
|
|
break;
|
|
|
|
/* Read the data bus. */
|
|
*data++ = *sc->sci_data;
|
|
|
|
/* Tell target we got it. */
|
|
icmd |= SCI_ICMD_ACK;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
/* Wait for target to drop REQ... */
|
|
error = ncr5380_wait_not_req(sc);
|
|
|
|
/* OK, we can drop ACK. */
|
|
icmd &= ~SCI_ICMD_ACK;
|
|
*sc->sci_icmd = icmd;
|
|
|
|
if (error) {
|
|
NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
|
|
break;
|
|
}
|
|
|
|
--resid;
|
|
}
|
|
|
|
return (count - resid);
|
|
}
|
|
|
|
#endif /* USE_OWN_PIO_ROUTINES */
|
|
|