Add locking to adv(4) driver and mark it MPSAFE.

- Disable the support for the second channel on twin-channel EISA cards as
  the current incarnation can't possibly work correctly (it hasn't worked
  since switching to new-bus where new-bus allocates the softc).  If anyone
  bothers to test this again it can be fixed properly and brought back.
- Use device_printf() and device_get_nameunit() instead of adv_name().
- Remove use of explicit bus space handles and tags.
- Use PCI bus accessors and helper routines rather than accessing
  config registers directly.
- Handle failures from adv_attach().

Tested by:	no one (hope it works)
This commit is contained in:
John Baldwin 2012-10-12 21:31:44 +00:00
parent 5b0ae76514
commit ae09eb7337
7 changed files with 207 additions and 172 deletions

View File

@ -131,17 +131,27 @@ adv_eisa_probe(device_t dev)
return 0; return 0;
} }
/*
* The adv_b stuff to handle twin-channel cards will not work in its current
* incarnation. It tries to reuse the same softc since adv_alloc() doesn't
* actually allocate a softc. It also tries to reuse the same unit number
* for both sims. This can be re-enabled if someone fixes it properly.
*/
static int static int
adv_eisa_attach(device_t dev) adv_eisa_attach(device_t dev)
{ {
struct adv_softc *adv; struct adv_softc *adv;
#if 0
struct adv_softc *adv_b; struct adv_softc *adv_b;
#endif
struct resource *io; struct resource *io;
struct resource *irq; struct resource *irq;
int rid, error; int rid, error;
void *ih; void *ih;
#if 0
adv_b = NULL; adv_b = NULL;
#endif
rid = 0; rid = 0;
io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
@ -162,8 +172,8 @@ adv_eisa_attach(device_t dev)
switch (eisa_get_id(dev) & ~0xF) { switch (eisa_get_id(dev) & ~0xF) {
case EISA_DEVICE_ID_ADVANSYS_750: case EISA_DEVICE_ID_ADVANSYS_750:
adv_b = adv_alloc(dev, rman_get_bustag(io), #if 0
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2); adv_b = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN2);
if (adv_b == NULL) if (adv_b == NULL)
goto bad; goto bad;
@ -183,26 +193,28 @@ adv_eisa_attach(device_t dev)
/* nsegments */ ~0, /* nsegments */ ~0,
/* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&adv_b->parent_dmat); &adv_b->parent_dmat);
if (error != 0) { if (error != 0) {
printf("%s: Could not allocate DMA tag - error %d\n", device_printf(dev, "Could not allocate DMA tag - error %d\n",
adv_name(adv_b), error); error);
adv_free(adv_b); adv_free(adv_b);
goto bad; goto bad;
} }
adv_b->init_level++; adv_b->init_level++;
#endif
/* FALLTHROUGH */ /* FALLTHROUGH */
case EISA_DEVICE_ID_ADVANSYS_740: case EISA_DEVICE_ID_ADVANSYS_740:
adv = adv_alloc(dev, rman_get_bustag(io), adv = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN1);
rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
if (adv == NULL) { if (adv == NULL) {
#if 0
if (adv_b != NULL) if (adv_b != NULL)
adv_free(adv_b); adv_free(adv_b);
#endif
goto bad; goto bad;
} }
@ -222,13 +234,13 @@ adv_eisa_attach(device_t dev)
/* nsegments */ ~0, /* nsegments */ ~0,
/* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&adv->parent_dmat); &adv->parent_dmat);
if (error != 0) { if (error != 0) {
printf("%s: Could not allocate DMA tag - error %d\n", device_printf(dev, "Could not allocate DMA tag - error %d\n",
adv_name(adv), error); error);
adv_free(adv); adv_free(adv);
goto bad; goto bad;
} }
@ -244,7 +256,7 @@ adv_eisa_attach(device_t dev)
if (overrun_buf == NULL) { if (overrun_buf == NULL) {
/* Need to allocate our overrun buffer */ /* Need to allocate our overrun buffer */
if (bus_dma_tag_create( if (bus_dma_tag_create(
/* parent */ adv->parent_dmat, /* parent */ bus_get_dma_tag(dev),
/* alignment */ 8, /* alignment */ 8,
/* boundary */ 0, /* boundary */ 0,
/* lowaddr */ ADV_EISA_MAX_DMA_ADDR, /* lowaddr */ ADV_EISA_MAX_DMA_ADDR,
@ -255,8 +267,8 @@ adv_eisa_attach(device_t dev)
/* nsegments */ 1, /* nsegments */ 1,
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&overrun_dmat) != 0) { &overrun_dmat) != 0) {
adv_free(adv); adv_free(adv);
goto bad; goto bad;
@ -292,14 +304,17 @@ adv_eisa_attach(device_t dev)
if (adv_init(adv) != 0) { if (adv_init(adv) != 0) {
adv_free(adv); adv_free(adv);
#if 0
if (adv_b != NULL) if (adv_b != NULL)
adv_free(adv_b); adv_free(adv_b);
return(-1); #endif
goto bad;
} }
adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
#if 0
if (adv_b != NULL) { if (adv_b != NULL) {
/* /*
* Stop the chip. * Stop the chip.
@ -317,24 +332,33 @@ adv_eisa_attach(device_t dev)
adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
} }
} }
#endif
/* /*
* Enable our interrupt handler. * Enable our interrupt handler.
*/ */
bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL,
adv, &ih); adv_intr, adv, &ih) != 0) {
adv_free(adv);
goto bad;
}
/* Attach sub-devices - always succeeds */ /* Attach sub-devices */
adv_attach(adv); if (adv_attach(adv) != 0) {
adv_free(adv);
goto bad;
}
#if 0
if (adv_b != NULL) if (adv_b != NULL)
adv_attach(adv_b); adv_attach(adv_b);
#endif
return 0; return 0;
bad: bad:
bus_release_resource(dev, SYS_RES_IOPORT, 0, io); bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
bus_release_resource(dev, SYS_RES_IRQ, 0, irq); bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
return -1; return ENXIO;
} }
static device_method_t adv_eisa_methods[] = { static device_method_t adv_eisa_methods[] = {

View File

@ -135,12 +135,13 @@ adv_isa_probe(device_t dev)
if ((port_index > max_port_index) if ((port_index > max_port_index)
|| (iobase != adv_isa_ioports[port_index])) { || (iobase != adv_isa_ioports[port_index])) {
if (bootverbose) if (bootverbose)
printf("adv%d: Invalid baseport of 0x%lx specified. " device_printf(dev,
"Nearest valid baseport is 0x%x. Failing " "Invalid baseport of 0x%lx specified. "
"probe.\n", device_get_unit(dev), iobase, "Nearest valid baseport is 0x%x. Failing "
(port_index <= max_port_index) ? "probe.\n", iobase,
adv_isa_ioports[port_index] : (port_index <= max_port_index) ?
adv_isa_ioports[max_port_index]); adv_isa_ioports[port_index] :
adv_isa_ioports[max_port_index]);
return ENXIO; return ENXIO;
} }
max_port_index = port_index; max_port_index = port_index;
@ -169,8 +170,7 @@ adv_isa_probe(device_t dev)
if (iores == NULL) if (iores == NULL)
continue; continue;
if (adv_find_signature(rman_get_bustag(iores), if (adv_find_signature(iores) == 0) {
rman_get_bushandle(iores)) == 0) {
bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
continue; continue;
} }
@ -179,8 +179,7 @@ adv_isa_probe(device_t dev)
* Got one. Now allocate our softc * Got one. Now allocate our softc
* and see if we can initialize the card. * and see if we can initialize the card.
*/ */
adv = adv_alloc(dev, rman_get_bustag(iores), adv = adv_alloc(dev, iores, 0);
rman_get_bushandle(iores));
if (adv == NULL) { if (adv == NULL) {
bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
break; break;
@ -238,13 +237,13 @@ adv_isa_probe(device_t dev)
/* nsegments */ ~0, /* nsegments */ ~0,
/* maxsegsz */ maxsegsz, /* maxsegsz */ maxsegsz,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&adv->parent_dmat); &adv->parent_dmat);
if (error != 0) { if (error != 0) {
printf("%s: Could not allocate DMA tag - error %d\n", device_printf(dev,
adv_name(adv), error); "Could not allocate DMA tag - error %d\n", error);
adv_free(adv); adv_free(adv);
bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
break; break;
@ -335,8 +334,11 @@ adv_isa_probe(device_t dev)
irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE); RF_ACTIVE);
if (irqres == NULL || if (irqres == NULL ||
bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|
NULL, adv_intr, adv, &ih)) { INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) {
if (irqres != NULL)
bus_release_resource(dev, SYS_RES_IRQ, rid,
irqres);
bus_dmamap_unload(overrun_dmat, overrun_dmamap); bus_dmamap_unload(overrun_dmat, overrun_dmamap);
bus_dmamem_free(overrun_dmat, overrun_buf, bus_dmamem_free(overrun_dmat, overrun_buf,
overrun_dmamap); overrun_dmamap);

View File

@ -138,7 +138,6 @@ adv_pci_attach(device_t dev)
{ {
struct adv_softc *adv; struct adv_softc *adv;
u_int32_t id; u_int32_t id;
u_int32_t command;
int error, rid, irqrid; int error, rid, irqrid;
void *ih; void *ih;
struct resource *iores, *irqres; struct resource *iores, *irqres;
@ -146,19 +145,8 @@ adv_pci_attach(device_t dev)
/* /*
* Determine the chip version. * Determine the chip version.
*/ */
id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); id = pci_get_devid(dev);
command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); pci_enable_busmaster(dev);
/*
* These cards do not allow memory mapped accesses, so we must
* ensure that I/O accesses are available or we won't be able
* to talk to them.
*/
if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN))
!= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) {
command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN;
pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
}
/* /*
* Early chips can't handle non-zero latency timer settings. * Early chips can't handle non-zero latency timer settings.
@ -174,13 +162,12 @@ adv_pci_attach(device_t dev)
if (iores == NULL) if (iores == NULL)
return ENXIO; return ENXIO;
if (adv_find_signature(rman_get_bustag(iores), if (adv_find_signature(iores) == 0) {
rman_get_bushandle(iores)) == 0) {
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
return ENXIO; return ENXIO;
} }
adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); adv = adv_alloc(dev, iores, 0);
if (adv == NULL) { if (adv == NULL) {
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
return ENXIO; return ENXIO;
@ -199,13 +186,13 @@ adv_pci_attach(device_t dev)
/* nsegments */ ~0, /* nsegments */ ~0,
/* maxsegsz */ ADV_PCI_MAX_DMA_COUNT, /* maxsegsz */ ADV_PCI_MAX_DMA_COUNT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&adv->parent_dmat); &adv->parent_dmat);
if (error != 0) { if (error != 0) {
printf("%s: Could not allocate DMA tag - error %d\n", device_printf(dev, "Could not allocate DMA tag - error %d\n",
adv_name(adv), error); error);
adv_free(adv); adv_free(adv);
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
return ENXIO; return ENXIO;
@ -227,8 +214,8 @@ adv_pci_attach(device_t dev)
/* nsegments */ 1, /* nsegments */ 1,
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ NULL,
/* lockarg */ &Giant, /* lockarg */ NULL,
&overrun_dmat) != 0) { &overrun_dmat) != 0) {
bus_dma_tag_destroy(adv->parent_dmat); bus_dma_tag_destroy(adv->parent_dmat);
adv_free(adv); adv_free(adv);
@ -308,14 +295,22 @@ adv_pci_attach(device_t dev)
irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid, irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid,
RF_SHAREABLE | RF_ACTIVE); RF_SHAREABLE | RF_ACTIVE);
if (irqres == NULL || if (irqres == NULL ||
bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, NULL, bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE,
adv_intr, adv, &ih)) { NULL, adv_intr, adv, &ih) != 0) {
if (irqres != NULL)
bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres);
adv_free(adv); adv_free(adv);
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
return ENXIO; return ENXIO;
} }
adv_attach(adv); if (adv_attach(adv) != 0) {
bus_teardown_intr(dev, irqres, ih);
bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres);
adv_free(adv);
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores);
return ENXIO;
}
return 0; return 0;
} }

View File

@ -49,6 +49,7 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/conf.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/kernel.h> #include <sys/kernel.h>
@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
static void adv_action(struct cam_sim *sim, union ccb *ccb); static void adv_action(struct cam_sim *sim, union ccb *ccb);
static void adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs, static void adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
int nsegments, int error); int nsegments, int error);
static void adv_intr_locked(struct adv_softc *adv);
static void adv_poll(struct cam_sim *sim); static void adv_poll(struct cam_sim *sim);
static void adv_run_doneq(struct adv_softc *adv); static void adv_run_doneq(struct adv_softc *adv);
static struct adv_ccb_info * static struct adv_ccb_info *
@ -97,15 +99,14 @@ static __inline struct adv_ccb_info *
adv_get_ccb_info(struct adv_softc *adv) adv_get_ccb_info(struct adv_softc *adv)
{ {
struct adv_ccb_info *cinfo; struct adv_ccb_info *cinfo;
int opri;
opri = splcam(); if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
if ((cinfo = SLIST_FIRST(&adv->free_ccb_infos)) != NULL) { if ((cinfo = SLIST_FIRST(&adv->free_ccb_infos)) != NULL) {
SLIST_REMOVE_HEAD(&adv->free_ccb_infos, links); SLIST_REMOVE_HEAD(&adv->free_ccb_infos, links);
} else { } else {
cinfo = adv_alloc_ccb_info(adv); cinfo = adv_alloc_ccb_info(adv);
} }
splx(opri);
return (cinfo); return (cinfo);
} }
@ -113,12 +114,11 @@ adv_get_ccb_info(struct adv_softc *adv)
static __inline void static __inline void
adv_free_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo) adv_free_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo)
{ {
int opri;
opri = splcam(); if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
cinfo->state = ACCB_FREE; cinfo->state = ACCB_FREE;
SLIST_INSERT_HEAD(&adv->free_ccb_infos, cinfo, links); SLIST_INSERT_HEAD(&adv->free_ccb_infos, cinfo, links);
splx(opri);
} }
static __inline void static __inline void
@ -139,6 +139,9 @@ adv_clear_state(struct adv_softc *adv, union ccb* ccb)
static void static void
adv_clear_state_really(struct adv_softc *adv, union ccb* ccb) adv_clear_state_really(struct adv_softc *adv, union ccb* ccb)
{ {
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
if ((adv->state & ADV_BUSDMA_BLOCK_CLEARED) != 0) if ((adv->state & ADV_BUSDMA_BLOCK_CLEARED) != 0)
adv->state &= ~(ADV_BUSDMA_BLOCK_CLEARED|ADV_BUSDMA_BLOCK); adv->state &= ~(ADV_BUSDMA_BLOCK_CLEARED|ADV_BUSDMA_BLOCK);
if ((adv->state & ADV_RESOURCE_SHORTAGE) != 0) { if ((adv->state & ADV_RESOURCE_SHORTAGE) != 0) {
@ -164,13 +167,14 @@ adv_clear_state_really(struct adv_softc *adv, union ccb* ccb)
*/ */
ccb_h = LIST_FIRST(&adv->pending_ccbs); ccb_h = LIST_FIRST(&adv->pending_ccbs);
while (ccb_h != NULL) { while (ccb_h != NULL) {
ccb_h->timeout_ch = cinfo = ccb_h->ccb_cinfo_ptr;
timeout(adv_timeout, (caddr_t)ccb_h, callout_reset(&cinfo->timer,
(ccb_h->timeout * hz) / 1000); ccb_h->timeout * hz / 1000, adv_timeout,
ccb_h);
ccb_h = LIST_NEXT(ccb_h, sim_links.le); ccb_h = LIST_NEXT(ccb_h, sim_links.le);
} }
adv->state &= ~ADV_IN_TIMEOUT; adv->state &= ~ADV_IN_TIMEOUT;
printf("%s: No longer in timeout\n", adv_name(adv)); device_printf(adv->dev, "No longer in timeout\n");
} }
} }
if (adv->state == 0) if (adv->state == 0)
@ -186,15 +190,6 @@ adv_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
*physaddr = segs->ds_addr; *physaddr = segs->ds_addr;
} }
char *
adv_name(struct adv_softc *adv)
{
static char name[10];
snprintf(name, sizeof(name), "adv%d", adv->unit);
return (name);
}
static void static void
adv_action(struct cam_sim *sim, union ccb *ccb) adv_action(struct cam_sim *sim, union ccb *ccb)
{ {
@ -203,6 +198,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("adv_action\n")); CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("adv_action\n"));
adv = (struct adv_softc *)cam_sim_softc(sim); adv = (struct adv_softc *)cam_sim_softc(sim);
mtx_assert(&adv->lock, MA_OWNED);
switch (ccb->ccb_h.func_code) { switch (ccb->ccb_h.func_code) {
/* Common cases first */ /* Common cases first */
@ -229,10 +225,8 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
* to a single buffer * to a single buffer
*/ */
if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
int s;
int error; int error;
s = splsoftvm();
error = error =
bus_dmamap_load(adv->buffer_dmat, bus_dmamap_load(adv->buffer_dmat,
cinfo->dmamap, cinfo->dmamap,
@ -250,7 +244,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
adv_set_state(adv, adv_set_state(adv,
ADV_BUSDMA_BLOCK); ADV_BUSDMA_BLOCK);
} }
splx(s);
} else { } else {
struct bus_dma_segment seg; struct bus_dma_segment seg;
@ -299,7 +292,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
target_bit_vector targ_mask; target_bit_vector targ_mask;
struct adv_transinfo *tconf; struct adv_transinfo *tconf;
u_int update_type; u_int update_type;
int s;
cts = &ccb->cts; cts = &ccb->cts;
targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id); targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
@ -320,7 +312,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
break; break;
} }
s = splcam();
scsi = &cts->proto_specific.scsi; scsi = &cts->proto_specific.scsi;
spi = &cts->xport_specific.spi; spi = &cts->xport_specific.spi;
if ((update_type & ADV_TRANS_GOAL) != 0) { if ((update_type & ADV_TRANS_GOAL) != 0) {
@ -387,7 +378,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
spi->sync_offset, update_type); spi->sync_offset, update_type);
} }
splx(s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb); xpt_done(ccb);
break; break;
@ -400,7 +390,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts; struct ccb_trans_settings *cts;
struct adv_transinfo *tconf; struct adv_transinfo *tconf;
target_bit_vector target_mask; target_bit_vector target_mask;
int s;
cts = &ccb->cts; cts = &ccb->cts;
target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id); target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
@ -416,7 +405,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
s = splcam();
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
tconf = &adv->tinfo[cts->ccb_h.target_id].current; tconf = &adv->tinfo[cts->ccb_h.target_id].current;
if ((adv->disc_enable & target_mask) != 0) if ((adv->disc_enable & target_mask) != 0)
@ -432,7 +420,6 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
} }
spi->sync_period = tconf->period; spi->sync_period = tconf->period;
spi->sync_offset = tconf->offset; spi->sync_offset = tconf->offset;
splx(s);
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
spi->valid = CTS_SPI_VALID_SYNC_RATE spi->valid = CTS_SPI_VALID_SYNC_RATE
| CTS_SPI_VALID_SYNC_OFFSET | CTS_SPI_VALID_SYNC_OFFSET
@ -454,13 +441,10 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
} }
case XPT_RESET_BUS: /* Reset the specified SCSI bus */ case XPT_RESET_BUS: /* Reset the specified SCSI bus */
{ {
int s;
s = splcam();
adv_stop_execution(adv); adv_stop_execution(adv);
adv_reset_bus(adv, /*initiate_reset*/TRUE); adv_reset_bus(adv, /*initiate_reset*/TRUE);
adv_start_execution(adv); adv_start_execution(adv);
splx(s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb); xpt_done(ccb);
@ -521,13 +505,14 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
struct adv_ccb_info *cinfo; struct adv_ccb_info *cinfo;
struct adv_scsi_q scsiq; struct adv_scsi_q scsiq;
struct adv_sg_head sghead; struct adv_sg_head sghead;
int s;
csio = (struct ccb_scsiio *)arg; csio = (struct ccb_scsiio *)arg;
ccb_h = &csio->ccb_h; ccb_h = &csio->ccb_h;
sim = xpt_path_sim(ccb_h->path); sim = xpt_path_sim(ccb_h->path);
adv = (struct adv_softc *)cam_sim_softc(sim); adv = (struct adv_softc *)cam_sim_softc(sim);
cinfo = (struct adv_ccb_info *)csio->ccb_h.ccb_cinfo_ptr; cinfo = (struct adv_ccb_info *)csio->ccb_h.ccb_cinfo_ptr;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
/* /*
* Setup our done routine to release the simq on * Setup our done routine to release the simq on
@ -596,8 +581,6 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
scsiq.sg_head = NULL; scsiq.sg_head = NULL;
} }
s = splcam();
/* /*
* Last time we need to check if this SCB needs to * Last time we need to check if this SCB needs to
* be aborted. * be aborted.
@ -608,7 +591,6 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
adv_clear_state(adv, (union ccb *)csio); adv_clear_state(adv, (union ccb *)csio);
adv_free_ccb_info(adv, cinfo); adv_free_ccb_info(adv, cinfo);
xpt_done((union ccb *)csio); xpt_done((union ccb *)csio);
splx(s);
return; return;
} }
@ -621,16 +603,14 @@ adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
adv_clear_state(adv, (union ccb *)csio); adv_clear_state(adv, (union ccb *)csio);
adv_free_ccb_info(adv, cinfo); adv_free_ccb_info(adv, cinfo);
xpt_done((union ccb *)csio); xpt_done((union ccb *)csio);
splx(s);
return; return;
} }
cinfo->state |= ACCB_ACTIVE; cinfo->state |= ACCB_ACTIVE;
ccb_h->status |= CAM_SIM_QUEUED; ccb_h->status |= CAM_SIM_QUEUED;
LIST_INSERT_HEAD(&adv->pending_ccbs, ccb_h, sim_links.le); LIST_INSERT_HEAD(&adv->pending_ccbs, ccb_h, sim_links.le);
/* Schedule our timeout */ /* Schedule our timeout */
ccb_h->timeout_ch = callout_reset(&cinfo->timer, ccb_h->timeout * hz /1000, adv_timeout,
timeout(adv_timeout, csio, (ccb_h->timeout * hz)/1000); csio);
splx(s);
} }
static struct adv_ccb_info * static struct adv_ccb_info *
@ -641,11 +621,12 @@ adv_alloc_ccb_info(struct adv_softc *adv)
cinfo = &adv->ccb_infos[adv->ccb_infos_allocated]; cinfo = &adv->ccb_infos[adv->ccb_infos_allocated];
cinfo->state = ACCB_FREE; cinfo->state = ACCB_FREE;
callout_init_mtx(&cinfo->timer, &adv->lock, 0);
error = bus_dmamap_create(adv->buffer_dmat, /*flags*/0, error = bus_dmamap_create(adv->buffer_dmat, /*flags*/0,
&cinfo->dmamap); &cinfo->dmamap);
if (error != 0) { if (error != 0) {
printf("%s: Unable to allocate CCB info " device_printf(adv->dev, "Unable to allocate CCB info "
"dmamap - error %d\n", adv_name(adv), error); "dmamap - error %d\n", error);
return (NULL); return (NULL);
} }
adv->ccb_infos_allocated++; adv->ccb_infos_allocated++;
@ -655,28 +636,28 @@ adv_alloc_ccb_info(struct adv_softc *adv)
static void static void
adv_destroy_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo) adv_destroy_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo)
{ {
callout_drain(&cinfo->timer);
bus_dmamap_destroy(adv->buffer_dmat, cinfo->dmamap); bus_dmamap_destroy(adv->buffer_dmat, cinfo->dmamap);
} }
void void
adv_timeout(void *arg) adv_timeout(void *arg)
{ {
int s;
union ccb *ccb; union ccb *ccb;
struct adv_softc *adv; struct adv_softc *adv;
struct adv_ccb_info *cinfo; struct adv_ccb_info *cinfo, *cinfo2;
ccb = (union ccb *)arg; ccb = (union ccb *)arg;
adv = (struct adv_softc *)xpt_path_sim(ccb->ccb_h.path)->softc; adv = (struct adv_softc *)xpt_path_sim(ccb->ccb_h.path)->softc;
cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr; cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr;
mtx_assert(&adv->lock, MA_OWNED);
xpt_print_path(ccb->ccb_h.path); xpt_print_path(ccb->ccb_h.path);
printf("Timed out\n"); printf("Timed out\n");
s = splcam();
/* Have we been taken care of already?? */ /* Have we been taken care of already?? */
if (cinfo == NULL || cinfo->state == ACCB_FREE) { if (cinfo == NULL || cinfo->state == ACCB_FREE) {
splx(s);
return; return;
} }
@ -702,7 +683,8 @@ adv_timeout(void *arg)
ccb_h = LIST_FIRST(&adv->pending_ccbs); ccb_h = LIST_FIRST(&adv->pending_ccbs);
while (ccb_h != NULL) { while (ccb_h != NULL) {
untimeout(adv_timeout, ccb_h, ccb_h->timeout_ch); cinfo2 = ccb_h->ccb_cinfo_ptr;
callout_stop(&cinfo2->timer);
ccb_h = LIST_NEXT(ccb_h, sim_links.le); ccb_h = LIST_NEXT(ccb_h, sim_links.le);
} }
@ -713,8 +695,7 @@ adv_timeout(void *arg)
adv_abort_ccb(adv, ccb->ccb_h.target_id, adv_abort_ccb(adv, ccb->ccb_h.target_id,
ccb->ccb_h.target_lun, ccb, ccb->ccb_h.target_lun, ccb,
CAM_CMD_TIMEOUT, /*queued_only*/FALSE); CAM_CMD_TIMEOUT, /*queued_only*/FALSE);
ccb->ccb_h.timeout_ch = callout_reset(&cinfo->timer, 2 * hz, adv_timeout, ccb);
timeout(adv_timeout, ccb, 2 * hz);
} else { } else {
/* Our attempt to perform an abort failed, go for a reset */ /* Our attempt to perform an abort failed, go for a reset */
xpt_print_path(ccb->ccb_h.path); xpt_print_path(ccb->ccb_h.path);
@ -724,11 +705,10 @@ adv_timeout(void *arg)
adv_reset_bus(adv, /*initiate_reset*/TRUE); adv_reset_bus(adv, /*initiate_reset*/TRUE);
} }
adv_start_execution(adv); adv_start_execution(adv);
splx(s);
} }
struct adv_softc * struct adv_softc *
adv_alloc(device_t dev, bus_space_tag_t tag, bus_space_handle_t bsh) adv_alloc(device_t dev, struct resource *res, long offset)
{ {
struct adv_softc *adv = device_get_softc(dev); struct adv_softc *adv = device_get_softc(dev);
@ -738,9 +718,9 @@ adv_alloc(device_t dev, bus_space_tag_t tag, bus_space_handle_t bsh)
LIST_INIT(&adv->pending_ccbs); LIST_INIT(&adv->pending_ccbs);
SLIST_INIT(&adv->free_ccb_infos); SLIST_INIT(&adv->free_ccb_infos);
adv->dev = dev; adv->dev = dev;
adv->unit = device_get_unit(dev); adv->res = res;
adv->tag = tag; adv->reg_off = offset;
adv->bsh = bsh; mtx_init(&adv->lock, "adv", NULL, MTX_DEF);
return(adv); return(adv);
} }
@ -773,6 +753,7 @@ adv_free(struct adv_softc *adv)
if (adv->ccb_infos != NULL) if (adv->ccb_infos != NULL)
free(adv->ccb_infos, M_DEVBUF); free(adv->ccb_infos, M_DEVBUF);
case 0: case 0:
mtx_destroy(&adv->lock);
break; break;
} }
} }
@ -786,6 +767,7 @@ adv_init(struct adv_softc *adv)
u_int16_t config_lsw; u_int16_t config_lsw;
u_int16_t config_msw; u_int16_t config_msw;
mtx_lock(&adv->lock);
adv_lib_init(adv); adv_lib_init(adv);
/* /*
@ -794,14 +776,16 @@ adv_init(struct adv_softc *adv)
adv_write_lram_16(adv, ADV_HALTCODE_W, 0x00FE); adv_write_lram_16(adv, ADV_HALTCODE_W, 0x00FE);
adv_stop_execution(adv); adv_stop_execution(adv);
if (adv_stop_chip(adv) == 0 || adv_is_chip_halted(adv) == 0) { if (adv_stop_chip(adv) == 0 || adv_is_chip_halted(adv) == 0) {
printf("adv%d: Unable to halt adapter. Initialization" mtx_unlock(&adv->lock);
"failed\n", adv->unit); device_printf(adv->dev,
"Unable to halt adapter. Initialization failed\n");
return (1); return (1);
} }
ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR); ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) { if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) {
printf("adv%d: Unable to set program counter. Initialization" mtx_unlock(&adv->lock);
"failed\n", adv->unit); device_printf(adv->dev,
"Unable to set program counter. Initialization failed\n");
return (1); return (1);
} }
@ -876,8 +860,8 @@ adv_init(struct adv_softc *adv)
} else { } else {
u_int8_t sync_data; u_int8_t sync_data;
printf("adv%d: Warning EEPROM Checksum mismatch. " device_printf(adv->dev, "Warning EEPROM Checksum mismatch. "
"Using default device parameters\n", adv->unit); "Using default device parameters\n");
/* Set reasonable defaults since we can't read the EEPROM */ /* Set reasonable defaults since we can't read the EEPROM */
adv->isa_dma_speed = /*ADV_DEF_ISA_DMA_SPEED*/1; adv->isa_dma_speed = /*ADV_DEF_ISA_DMA_SPEED*/1;
@ -940,13 +924,15 @@ adv_init(struct adv_softc *adv)
* to be 100% correct. * to be 100% correct.
*/ */
if (adv_set_eeprom_config(adv, &eeprom_config) != 0) if (adv_set_eeprom_config(adv, &eeprom_config) != 0)
printf("%s: WARNING! Failure writing to EEPROM.\n", device_printf(adv->dev,
adv_name(adv)); "WARNING! Failure writing to EEPROM.\n");
#endif #endif
adv_set_chip_scsiid(adv, adv->scsi_id); adv_set_chip_scsiid(adv, adv->scsi_id);
if (adv_init_lram_and_mcode(adv)) if (adv_init_lram_and_mcode(adv)) {
mtx_unlock(&adv->lock);
return (1); return (1);
}
adv->disc_enable = adv->user_disc_enable; adv->disc_enable = adv->user_disc_enable;
@ -969,10 +955,12 @@ adv_init(struct adv_softc *adv)
} }
adv_write_lram_8(adv, ADVV_USE_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET); adv_write_lram_8(adv, ADVV_USE_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);
adv_write_lram_8(adv, ADVV_CAN_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET); adv_write_lram_8(adv, ADVV_CAN_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);
printf("adv%d: AdvanSys %s Host Adapter, SCSI ID %d, queue depth %d\n", device_printf(adv->dev,
adv->unit, (adv->type & ADV_ULTRA) && (max_sync == 0) "AdvanSys %s Host Adapter, SCSI ID %d, queue depth %d\n",
? "Ultra SCSI" : "SCSI", (adv->type & ADV_ULTRA) && (max_sync == 0)
adv->scsi_id, adv->max_openings); ? "Ultra SCSI" : "SCSI",
adv->scsi_id, adv->max_openings);
mtx_unlock(&adv->lock);
return (0); return (0);
} }
@ -980,14 +968,24 @@ void
adv_intr(void *arg) adv_intr(void *arg)
{ {
struct adv_softc *adv; struct adv_softc *adv;
adv = arg;
mtx_lock(&adv->lock);
adv_intr_locked(adv);
mtx_unlock(&adv->lock);
}
void
adv_intr_locked(struct adv_softc *adv)
{
u_int16_t chipstat; u_int16_t chipstat;
u_int16_t saved_ram_addr; u_int16_t saved_ram_addr;
u_int8_t ctrl_reg; u_int8_t ctrl_reg;
u_int8_t saved_ctrl_reg; u_int8_t saved_ctrl_reg;
u_int8_t host_flag; u_int8_t host_flag;
adv = (struct adv_softc *)arg; if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
chipstat = ADV_INW(adv, ADV_CHIP_STATUS); chipstat = ADV_INW(adv, ADV_CHIP_STATUS);
/* Is it for us? */ /* Is it for us? */
@ -1000,7 +998,7 @@ adv_intr(void *arg)
ADV_CC_TEST)); ADV_CC_TEST));
if ((chipstat & (ADV_CSW_SCSI_RESET_LATCH|ADV_CSW_SCSI_RESET_ACTIVE))) { if ((chipstat & (ADV_CSW_SCSI_RESET_LATCH|ADV_CSW_SCSI_RESET_ACTIVE))) {
printf("Detected Bus Reset\n"); device_printf(adv->dev, "Detected Bus Reset\n");
adv_reset_bus(adv, /*initiate_reset*/FALSE); adv_reset_bus(adv, /*initiate_reset*/FALSE);
return; return;
} }
@ -1128,9 +1126,11 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
{ {
struct adv_ccb_info *cinfo; struct adv_ccb_info *cinfo;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr; cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr;
LIST_REMOVE(&ccb->ccb_h, sim_links.le); LIST_REMOVE(&ccb->ccb_h, sim_links.le);
untimeout(adv_timeout, ccb, ccb->ccb_h.timeout_ch); callout_stop(&cinfo->timer);
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
bus_dmasync_op_t op; bus_dmasync_op_t op;
@ -1239,7 +1239,7 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
case QHSTA_M_MICRO_CODE_ERROR_HALT: case QHSTA_M_MICRO_CODE_ERROR_HALT:
default: default:
panic("%s: Unhandled Host status error %x", panic("%s: Unhandled Host status error %x",
adv_name(adv), host_stat); device_get_nameunit(adv->dev), host_stat);
/* NOTREACHED */ /* NOTREACHED */
} }
break; break;
@ -1280,7 +1280,8 @@ adv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,
static void static void
adv_poll(struct cam_sim *sim) adv_poll(struct cam_sim *sim)
{ {
adv_intr(cam_sim_softc(sim));
adv_intr_locked(cam_sim_softc(sim));
} }
/* /*
@ -1350,7 +1351,7 @@ adv_attach(adv)
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ BUS_DMA_ALLOCNOW, /* flags */ BUS_DMA_ALLOCNOW,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ busdma_lock_mutex,
/* lockarg */ &Giant, /* lockarg */ &adv->lock,
&adv->buffer_dmat) != 0) { &adv->buffer_dmat) != 0) {
return (ENXIO); return (ENXIO);
} }
@ -1371,7 +1372,7 @@ adv_attach(adv)
/* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT,
/* flags */ 0, /* flags */ 0,
/* lockfunc */ busdma_lock_mutex, /* lockfunc */ busdma_lock_mutex,
/* lockarg */ &Giant, /* lockarg */ &adv->lock,
&adv->sense_dmat) != 0) { &adv->sense_dmat) != 0) {
return (ENXIO); return (ENXIO);
} }
@ -1398,8 +1399,8 @@ adv_attach(adv)
* Fire up the chip * Fire up the chip
*/ */
if (adv_start_chip(adv) != 1) { if (adv_start_chip(adv) != 1) {
printf("adv%d: Unable to start on board processor. Aborting.\n", device_printf(adv->dev,
adv->unit); "Unable to start on board processor. Aborting.\n");
return (ENXIO); return (ENXIO);
} }
@ -1413,8 +1414,8 @@ adv_attach(adv)
/* /*
* Construct our SIM entry. * Construct our SIM entry.
*/ */
adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv, adv->unit, adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv,
&Giant, 1, adv->max_openings, devq); device_get_unit(adv->dev), &adv->lock, 1, adv->max_openings, devq);
if (adv->sim == NULL) if (adv->sim == NULL)
return (ENOMEM); return (ENOMEM);
@ -1423,8 +1424,10 @@ adv_attach(adv)
* *
* XXX Twin Channel EISA Cards??? * XXX Twin Channel EISA Cards???
*/ */
mtx_lock(&adv->lock);
if (xpt_bus_register(adv->sim, adv->dev, 0) != CAM_SUCCESS) { if (xpt_bus_register(adv->sim, adv->dev, 0) != CAM_SUCCESS) {
cam_sim_free(adv->sim, /*free devq*/TRUE); cam_sim_free(adv->sim, /*free devq*/TRUE);
mtx_unlock(&adv->lock);
return (ENXIO); return (ENXIO);
} }
@ -1433,6 +1436,7 @@ adv_attach(adv)
!= CAM_REQ_CMP) { != CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path(adv->sim)); xpt_bus_deregister(cam_sim_path(adv->sim));
cam_sim_free(adv->sim, /*free devq*/TRUE); cam_sim_free(adv->sim, /*free devq*/TRUE);
mtx_unlock(&adv->lock);
return (ENXIO); return (ENXIO);
} }
@ -1442,6 +1446,7 @@ adv_attach(adv)
csa.callback = advasync; csa.callback = advasync;
csa.callback_arg = adv; csa.callback_arg = adv;
xpt_action((union ccb *)&csa); xpt_action((union ccb *)&csa);
mtx_unlock(&adv->lock);
return (0); return (0);
} }
MODULE_DEPEND(adv, cam, 1, 1, 1); MODULE_DEPEND(adv, cam, 1, 1, 1);

View File

@ -38,9 +38,7 @@
#include <dev/advansys/advlib.h> #include <dev/advansys/advlib.h>
struct adv_softc * adv_alloc(device_t dev, bus_space_tag_t tag, struct adv_softc * adv_alloc(device_t dev, struct resource *res, long offset);
bus_space_handle_t bsh);
char * adv_name(struct adv_softc *adv);
void adv_map(void *arg, bus_dma_segment_t *segs, void adv_map(void *arg, bus_dma_segment_t *segs,
int nseg, int error); int nseg, int error);
void adv_free(struct adv_softc *adv); void adv_free(struct adv_softc *adv);
@ -50,6 +48,6 @@ int adv_attach(struct adv_softc *adv);
void adv_done(struct adv_softc *adv, union ccb* ccb, void adv_done(struct adv_softc *adv, union ccb* ccb,
u_int done_stat, u_int host_stat, u_int done_stat, u_int host_stat,
u_int scsi_stat, u_int q_no); u_int scsi_stat, u_int q_no);
timeout_t adv_timeout; void adv_timeout(void *arg);
#endif /* _ADVANSYS_H_ */ #endif /* _ADVANSYS_H_ */

View File

@ -45,7 +45,10 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <sys/conf.h>
#include <sys/lock.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/mutex.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <machine/bus.h> #include <machine/bus.h>
@ -298,6 +301,7 @@ advasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
struct adv_softc *adv; struct adv_softc *adv;
adv = (struct adv_softc *)callback_arg; adv = (struct adv_softc *)callback_arg;
mtx_assert(&adv->lock, MA_OWNED);
switch (code) { switch (code) {
case AC_FOUND_DEVICE: case AC_FOUND_DEVICE:
{ {
@ -460,12 +464,12 @@ adv_write_lram_16(struct adv_softc *adv, u_int16_t addr, u_int16_t value)
* found, 0 otherwise. * found, 0 otherwise.
*/ */
int int
adv_find_signature(bus_space_tag_t tag, bus_space_handle_t bsh) adv_find_signature(struct resource *res)
{ {
u_int16_t signature; u_int16_t signature;
if (bus_space_read_1(tag, bsh, ADV_SIGNATURE_BYTE) == ADV_1000_ID1B) { if (bus_read_1(res, ADV_SIGNATURE_BYTE) == ADV_1000_ID1B) {
signature = bus_space_read_2(tag, bsh, ADV_SIGNATURE_WORD); signature = bus_read_2(res, ADV_SIGNATURE_WORD);
if ((signature == ADV_1000_ID0W) if ((signature == ADV_1000_ID0W)
|| (signature == ADV_1000_ID0W_FIX)) || (signature == ADV_1000_ID0W_FIX))
return (1); return (1);
@ -594,8 +598,8 @@ adv_init_lram_and_mcode(struct adv_softc *adv)
retval = adv_load_microcode(adv, 0, (u_int16_t *)adv_mcode, retval = adv_load_microcode(adv, 0, (u_int16_t *)adv_mcode,
adv_mcode_size); adv_mcode_size);
if (retval != adv_mcode_chksum) { if (retval != adv_mcode_chksum) {
printf("adv%d: Microcode download failed checksum!\n", device_printf(adv->dev,
adv->unit); "Microcode download failed checksum!\n");
return (1); return (1);
} }
@ -692,6 +696,8 @@ adv_execute_scsi_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
u_int8_t sg_entry_cnt_minus_one; u_int8_t sg_entry_cnt_minus_one;
u_int8_t tid_no; u_int8_t tid_no;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
scsiq->q1.q_no = 0; scsiq->q1.q_no = 0;
retval = 1; /* Default to error case */ retval = 1; /* Default to error case */
target_ix = scsiq->q2.target_ix; target_ix = scsiq->q2.target_ix;
@ -938,6 +944,8 @@ adv_isr_chip_halted(struct adv_softc *adv)
u_int8_t q_cntl; u_int8_t q_cntl;
u_int8_t tid_no; u_int8_t tid_no;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
int_halt_code = adv_read_lram_16(adv, ADVV_HALTCODE_W); int_halt_code = adv_read_lram_16(adv, ADVV_HALTCODE_W);
halt_qp = adv_read_lram_8(adv, ADVV_CURCDB_B); halt_qp = adv_read_lram_8(adv, ADVV_CURCDB_B);
halt_q_addr = ADV_QNO_TO_QADDR(halt_qp); halt_q_addr = ADV_QNO_TO_QADDR(halt_qp);
@ -966,6 +974,7 @@ adv_isr_chip_halted(struct adv_softc *adv)
target_mask, tid_no); target_mask, tid_no);
} else if (int_halt_code == ADV_HALT_CHK_CONDITION) { } else if (int_halt_code == ADV_HALT_CHK_CONDITION) {
struct adv_target_transinfo* tinfo; struct adv_target_transinfo* tinfo;
struct adv_ccb_info *cinfo;
union ccb *ccb; union ccb *ccb;
u_int32_t cinfo_index; u_int32_t cinfo_index;
u_int8_t tag_code; u_int8_t tag_code;
@ -1008,6 +1017,7 @@ adv_isr_chip_halted(struct adv_softc *adv)
*/ */
cinfo_index = cinfo_index =
adv_read_lram_32(adv, halt_q_addr + ADV_SCSIQ_D_CINFO_IDX); adv_read_lram_32(adv, halt_q_addr + ADV_SCSIQ_D_CINFO_IDX);
cinfo = &adv->ccb_infos[cinfo_index];
ccb = adv->ccb_infos[cinfo_index].ccb; ccb = adv->ccb_infos[cinfo_index].ccb;
xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
ccb->ccb_h.status |= CAM_DEV_QFRZN; ccb->ccb_h.status |= CAM_DEV_QFRZN;
@ -1021,9 +1031,7 @@ adv_isr_chip_halted(struct adv_softc *adv)
* Ensure we have enough time to actually * Ensure we have enough time to actually
* retrieve the sense. * retrieve the sense.
*/ */
untimeout(adv_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); callout_reset(&cinfo->timer, 5 * hz, adv_timeout, ccb);
ccb->ccb_h.timeout_ch =
timeout(adv_timeout, (caddr_t)ccb, 5 * hz);
} else if (int_halt_code == ADV_HALT_SDTR_REJECTED) { } else if (int_halt_code == ADV_HALT_SDTR_REJECTED) {
struct ext_msg out_msg; struct ext_msg out_msg;
@ -1090,6 +1098,7 @@ adv_set_syncrate(struct adv_softc *adv, struct cam_path *path,
u_int old_offset; u_int old_offset;
u_int8_t sdtr_data; u_int8_t sdtr_data;
mtx_assert(&adv->lock, MA_OWNED);
tinfo = &adv->tinfo[tid]; tinfo = &adv->tinfo[tid];
/* Filter our input */ /* Filter our input */
@ -1102,10 +1111,8 @@ adv_set_syncrate(struct adv_softc *adv, struct cam_path *path,
if ((type & ADV_TRANS_CUR) != 0 if ((type & ADV_TRANS_CUR) != 0
&& ((old_period != period || old_offset != offset) && ((old_period != period || old_offset != offset)
|| period == 0 || offset == 0) /*Changes in asyn fix settings*/) { || period == 0 || offset == 0) /*Changes in asyn fix settings*/) {
int s;
int halted; int halted;
s = splcam();
halted = adv_is_chip_halted(adv); halted = adv_is_chip_halted(adv);
if (halted == 0) if (halted == 0)
/* Must halt the chip first */ /* Must halt the chip first */
@ -1125,7 +1132,6 @@ adv_set_syncrate(struct adv_softc *adv, struct cam_path *path,
/* Start the chip again */ /* Start the chip again */
adv_start_chip(adv); adv_start_chip(adv);
splx(s);
tinfo->current.period = period; tinfo->current.period = period;
tinfo->current.offset = offset; tinfo->current.offset = offset;
@ -1235,8 +1241,8 @@ adv_mset_lram_16(struct adv_softc *adv, u_int16_t s_addr,
u_int16_t set_value, int count) u_int16_t set_value, int count)
{ {
ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr); ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
bus_space_set_multi_2(adv->tag, adv->bsh, ADV_LRAM_DATA, bus_set_multi_2(adv->res, adv->reg_off + ADV_LRAM_DATA,
set_value, count); set_value, count);
} }
static u_int32_t static u_int32_t
@ -1507,8 +1513,8 @@ adv_init_microcode_var(struct adv_softc *adv)
ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR); ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) { if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) {
printf("adv%d: Unable to set program counter. Aborting.\n", device_printf(adv->dev,
adv->unit); "Unable to set program counter. Aborting.\n");
return (1); return (1);
} }
return (0); return (0);
@ -2002,6 +2008,8 @@ adv_abort_ccb(struct adv_softc *adv, int target, int lun, union ccb *ccb,
u_int8_t target_ix; u_int8_t target_ix;
int count; int count;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
scsiq = &scsiq_buf; scsiq = &scsiq_buf;
target_ix = ADV_TIDLUN_TO_IX(target, lun); target_ix = ADV_TIDLUN_TO_IX(target, lun);
count = 0; count = 0;
@ -2045,6 +2053,8 @@ adv_reset_bus(struct adv_softc *adv, int initiate_bus_reset)
int i; int i;
union ccb *ccb; union ccb *ccb;
if (!dumping)
mtx_assert(&adv->lock, MA_OWNED);
i = 200; i = 200;
while ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_SCSI_RESET_ACTIVE) != 0 while ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_SCSI_RESET_ACTIVE) != 0
&& i--) && i--)

View File

@ -94,6 +94,7 @@ typedef enum {
struct adv_ccb_info { struct adv_ccb_info {
adv_ccb_state state; adv_ccb_state state;
bus_dmamap_t dmamap; bus_dmamap_t dmamap;
struct callout timer;
union ccb* ccb; union ccb* ccb;
SLIST_ENTRY(adv_ccb_info) links; SLIST_ENTRY(adv_ccb_info) links;
}; };
@ -496,8 +497,8 @@ struct adv_target_transinfo {
struct adv_softc { struct adv_softc {
device_t dev; device_t dev;
bus_space_tag_t tag; struct resource *res;
bus_space_handle_t bsh; long reg_off;
struct cam_sim *sim; struct cam_sim *sim;
LIST_HEAD(, ccb_hdr) pending_ccbs; LIST_HEAD(, ccb_hdr) pending_ccbs;
struct adv_ccb_info *ccb_infos; struct adv_ccb_info *ccb_infos;
@ -539,8 +540,7 @@ struct adv_softc {
adv_state state; adv_state state;
struct cam_path *path; struct cam_path *path;
int unit; int init_level;
int init_level;
u_int32_t max_dma_addr; u_int32_t max_dma_addr;
u_int32_t max_dma_count; u_int32_t max_dma_count;
u_int8_t isa_dma_speed; u_int8_t isa_dma_speed;
@ -554,6 +554,7 @@ struct adv_softc {
u_int8_t ccb_infos_allocated; u_int8_t ccb_infos_allocated;
u_int8_t *sdtr_period_tbl; u_int8_t *sdtr_period_tbl;
u_int8_t sdtr_period_tbl_size; u_int8_t sdtr_period_tbl_size;
struct mtx lock;
}; };
/* /*
@ -793,7 +794,7 @@ void adv_write_lram_16(struct adv_softc *adv, u_int16_t addr,
u_int16_t value); u_int16_t value);
/* Intialization */ /* Intialization */
int adv_find_signature(bus_space_tag_t tag, bus_space_handle_t bsh); int adv_find_signature(struct resource *res);
void adv_lib_init(struct adv_softc *adv); void adv_lib_init(struct adv_softc *adv);
u_int16_t adv_get_eeprom_config(struct adv_softc *adv, u_int16_t adv_get_eeprom_config(struct adv_softc *adv,
@ -846,11 +847,11 @@ void advasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg); struct cam_path *path, void *arg);
#define ADV_INB(adv, offset) \ #define ADV_INB(adv, offset) \
bus_space_read_1((adv)->tag, (adv)->bsh, offset) bus_read_1((adv)->res, (adv)->reg_off + offset)
#define ADV_INW(adv, offset) \ #define ADV_INW(adv, offset) \
bus_space_read_2((adv)->tag, (adv)->bsh, offset) bus_read_2((adv)->res, (adv)->reg_off + offset)
#define ADV_INSB(adv, offset, valp, count) \ #define ADV_INSB(adv, offset, valp, count) \
bus_space_read_multi_1((adv)->tag, (adv)->bsh, offset, valp, count) bus_read_multi_1((adv)->res, (adv)->reg_off + offset, valp, count)
/* These controllers seem to have problems with PIO on some fast processors */ /* These controllers seem to have problems with PIO on some fast processors */
static __inline void ADV_INSW(struct adv_softc *, u_int, u_int16_t *, u_int); static __inline void ADV_INSW(struct adv_softc *, u_int, u_int16_t *, u_int);
@ -858,13 +859,13 @@ static __inline void
ADV_INSW(struct adv_softc *adv, u_int offset, u_int16_t *valp, u_int count) ADV_INSW(struct adv_softc *adv, u_int offset, u_int16_t *valp, u_int count)
{ {
while (count--) while (count--)
*valp++ = bus_space_read_2(adv->tag, adv->bsh, offset); *valp++ = bus_read_2(adv->res, adv->reg_off + offset);
} }
#define ADV_OUTB(adv, offset, val) \ #define ADV_OUTB(adv, offset, val) \
bus_space_write_1((adv)->tag, (adv)->bsh, offset, val) bus_write_1((adv)->res, (adv)->reg_off + offset, val)
#define ADV_OUTW(adv, offset, val) \ #define ADV_OUTW(adv, offset, val) \
bus_space_write_2((adv)->tag, (adv)->bsh, offset, val) bus_write_2((adv)->res, (adv)->reg_off + offset, val)
/* These controllers seem to have problems with PIO on some fast processors */ /* These controllers seem to have problems with PIO on some fast processors */
static __inline void ADV_OUTSW(struct adv_softc *, u_int, u_int16_t *, u_int); static __inline void ADV_OUTSW(struct adv_softc *, u_int, u_int16_t *, u_int);
@ -872,7 +873,7 @@ static __inline void
ADV_OUTSW(struct adv_softc *adv, u_int offset, u_int16_t *valp, u_int count) ADV_OUTSW(struct adv_softc *adv, u_int offset, u_int16_t *valp, u_int count)
{ {
while (count--) while (count--)
bus_space_write_2(adv->tag, adv->bsh, offset, *valp++); bus_write_2(adv->res, adv->reg_off + offset, *valp++);
} }
#endif /* _ADVLIB_H_ */ #endif /* _ADVLIB_H_ */