3b06f6f887
configured, but after all adapters have been configured. When multiple adapters are present, only the last configured adapter could be matched to the boot device slot. The adapter attach routines now check if that adapter slot matches the boot device slot and saves the softc pointer for that controller. Then when the disks are configured, dk_establish() matches the appropriate controller.
189 lines
4.1 KiB
C
189 lines
4.1 KiB
C
/* $NetBSD: asc_tc.c,v 1.13 2000/03/04 05:43:51 mhitch Exp $ */
|
|
|
|
/*
|
|
* Copyright 1996 The Board of Trustees of The Leland Stanford
|
|
* Junior University. All Rights Reserved.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software and its documentation for any purpose and without
|
|
* fee is hereby granted, provided that the above copyright
|
|
* notice appear in all copies. Stanford University
|
|
* makes no representations about the suitability of this
|
|
* software for any purpose. It is provided "as is" without
|
|
* express or implied warranty.
|
|
*
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/types.h>
|
|
#include <sys/device.h>
|
|
|
|
#include <dev/tc/tcvar.h>
|
|
#include <dev/tc/ioasicvar.h>
|
|
|
|
#include <pmax/dev/device.h> /* XXX */
|
|
#include <pmax/dev/scsi.h> /* XXX */
|
|
|
|
#include <pmax/dev/ascreg.h> /* XXX */
|
|
#include <dev/tc/ascvar.h>
|
|
|
|
/*XXX*/
|
|
|
|
|
|
/*
|
|
* Autoconfiguration data for config.
|
|
*/
|
|
int asc_tc_match __P((struct device *, struct cfdata *, void *));
|
|
void asc_tc_attach __P((struct device *, struct device *, void *));
|
|
|
|
struct cfattach asc_tc_ca = {
|
|
sizeof(struct asc_softc), asc_tc_match, asc_tc_attach
|
|
};
|
|
|
|
/*
|
|
* DMA callbacks
|
|
*/
|
|
|
|
static int
|
|
tc_dma_start __P((struct asc_softc *asc, struct scsi_state *state,
|
|
caddr_t cp, int flag, int len, int off));
|
|
|
|
static void
|
|
tc_dma_end __P((struct asc_softc *asc, struct scsi_state *state,
|
|
int flag));
|
|
|
|
|
|
int
|
|
asc_tc_match(parent, match, aux)
|
|
struct device *parent;
|
|
struct cfdata *match;
|
|
void *aux;
|
|
{
|
|
struct tc_attach_args *t = aux;
|
|
|
|
if (strncmp(t->ta_modname, "PMAZ-AA ", TC_ROM_LLEN))
|
|
return (0);
|
|
|
|
return (1);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
asc_tc_attach(parent, self, aux)
|
|
struct device *parent;
|
|
struct device *self;
|
|
void *aux;
|
|
{
|
|
register struct tc_attach_args *t = aux;
|
|
register asc_softc_t asc = (asc_softc_t) self;
|
|
u_char *buff;
|
|
int i, speed;
|
|
int unit;
|
|
/* XXX Hook for dk_establish() to determine boot device */
|
|
extern int booted_slot;
|
|
extern struct device *booted_controller;
|
|
|
|
/* Is this the controller we booted from? */
|
|
if (booted_slot == t->ta_slot)
|
|
booted_controller = self;
|
|
/* XXX */
|
|
|
|
unit = asc->sc_dev.dv_unit;
|
|
|
|
/*
|
|
* Initialize hw descriptor, cache some pointers
|
|
*/
|
|
asc->regs = (asc_regmap_t *)(t->ta_addr + ASC_OFFSET_53C94);
|
|
|
|
/*
|
|
* Set up machine dependencies.
|
|
* (1) how to do dma
|
|
* (2) timing based on turbochannel frequency
|
|
*/
|
|
|
|
/*
|
|
* Fall through for turbochannel option.
|
|
*/
|
|
asc->dmar = (volatile int *)(t->ta_addr + ASC_OFFSET_DMAR);
|
|
buff = (u_char *)(t->ta_addr + ASC_OFFSET_RAM);
|
|
|
|
/*
|
|
* Statically partition the DMA buffer between targets.
|
|
* This way we will eventually be able to attach/detach
|
|
* drives on-fly. And 18k/target is plenty for normal use.
|
|
*/
|
|
|
|
/*
|
|
* Give each target its own DMA buffer region.
|
|
* We may want to try ping ponging buffers later.
|
|
*/
|
|
for (i = 0; i < ASC_NCMD; i++)
|
|
asc->st[i].dmaBufAddr = buff + PER_TGT_DMA_SIZE * i;
|
|
|
|
asc->dma_start = tc_dma_start;
|
|
asc->dma_end = tc_dma_end;
|
|
|
|
/*
|
|
* Now for timing. The 3max has a 25Mhz tb whereas the 3min and
|
|
* maxine are 12.5Mhz.
|
|
*/
|
|
printf(" (bus speed: %s MHz) ", t->ta_busspeed? "25" : "12.5");
|
|
|
|
switch (t->ta_busspeed) {
|
|
case TC_SPEED_25_MHZ:
|
|
speed = ASC_SPEED_25_MHZ;
|
|
break;
|
|
|
|
default:
|
|
printf(" (unknown TC speed, assuming 12.5MHz) ");
|
|
/* FALLTHROUGH*/
|
|
case TC_SPEED_12_5_MHZ:
|
|
speed = ASC_SPEED_12_5_MHZ;
|
|
break;
|
|
};
|
|
|
|
ascattach(asc, speed);
|
|
|
|
/* tie pseudo-slot to device */
|
|
tc_intr_establish(parent, t->ta_cookie, TC_IPL_BIO,
|
|
asc_intr, asc);
|
|
}
|
|
|
|
|
|
/*
|
|
* DMA handling routines. For a turbochannel device, just set the dmar.
|
|
* For the I/O ASIC, handle the actual DMA interface.
|
|
*/
|
|
static int
|
|
tc_dma_start(asc, state, cp, flag, len, off)
|
|
asc_softc_t asc;
|
|
State *state;
|
|
caddr_t cp;
|
|
int flag;
|
|
int len;
|
|
int off;
|
|
{
|
|
|
|
if (len > PER_TGT_DMA_SIZE)
|
|
len = PER_TGT_DMA_SIZE;
|
|
if (flag == ASCDMA_WRITE)
|
|
bcopy(cp, state->dmaBufAddr + off, len);
|
|
if (flag == ASCDMA_WRITE)
|
|
*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(state->dmaBufAddr + off);
|
|
else
|
|
*asc->dmar = ASC_DMA_ADDR(state->dmaBufAddr + off);
|
|
return (len);
|
|
}
|
|
|
|
static void
|
|
tc_dma_end(asc, state, flag)
|
|
asc_softc_t asc;
|
|
State *state;
|
|
int flag;
|
|
{
|
|
if (flag == ASCDMA_READ)
|
|
bcopy(state->dmaBufAddr, state->buf, state->dmalen);
|
|
}
|