Add an ISA attachement to the aic7xxx driver to handle 284X controllers.

The ISA probe uses an identify routine to probe all slot locations from
1 to 14 that do not conflict with other allocated resources.  This required
making aic7770.c part of the driver core when compiled as a module.

aic7xxx.c:
aic79xx.c:
aic_osm_lib.c:
	Use aic_scb_timer_start() consistently to start the watchdog timer.
	This removes a few places that verbatum copied the code in
	aic_scb_timer_start().

	During recovery processing, allow commands to still be queued to
	the controller.  The only requirement we have is that our recovery
	command be queued first - something the code already guaranteed.
	The only other change required to make this work is to prevent
	timers from being started for these newly queued commands.

Approved by: re
This commit is contained in:
Justin T. Gibbs 2004-08-17 00:14:31 +00:00
parent 34c8a85fc8
commit 7afc02188a
14 changed files with 133 additions and 156 deletions

View File

@ -318,9 +318,9 @@ dev/ahb/ahb.c optional ahb eisa
dev/aic/aic.c optional aic
dev/aic/aic_pccard.c optional aic card
dev/aic/aic_pccard.c optional aic pccard
dev/aic7xxx/aic7770.c optional ahc eisa
dev/aic7xxx/aic7770.c optional ahc
dev/aic7xxx/ahc_eisa.c optional ahc eisa
#dev/aic7xxx/ahc_isa.c optional ahc isa
dev/aic7xxx/ahc_isa.c optional ahc isa
dev/aic7xxx/ahc_pci.c optional ahc pci
dev/aic7xxx/aic7xxx.c optional ahc
dev/aic7xxx/aic7xxx_93cx6.c optional ahc

View File

@ -159,41 +159,6 @@ aic7770_attach(device_t dev)
return (0);
}
int
aic7770_map_registers(struct ahc_softc *ahc, u_int unused_ioport_arg)
{
struct resource *regs;
int rid;
rid = 0;
regs = bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IOPORT, &rid,
RF_ACTIVE);
if (regs == NULL) {
device_printf(ahc->dev_softc, "Unable to map I/O space?!\n");
return ENOMEM;
}
ahc->platform_data->regs_res_type = SYS_RES_IOPORT;
ahc->platform_data->regs_res_id = rid,
ahc->platform_data->regs = regs;
ahc->tag = rman_get_bustag(regs);
ahc->bsh = rman_get_bushandle(regs);
return (0);
}
int
aic7770_map_int(struct ahc_softc *ahc, int irq)
{
int zero;
zero = 0;
ahc->platform_data->irq =
bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IRQ, &zero,
RF_ACTIVE);
if (ahc->platform_data->irq == NULL)
return (ENOMEM);
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
return (ahc_map_int(ahc));
}
static device_method_t ahc_eisa_device_methods[] = {
/* Device interface */

View File

@ -237,22 +237,3 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
ahc->platform_data->regs = regs;
return (0);
}
int
ahc_pci_map_int(struct ahc_softc *ahc)
{
int zero;
zero = 0;
ahc->platform_data->irq =
bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IRQ, &zero,
RF_ACTIVE | RF_SHAREABLE);
if (ahc->platform_data->irq == NULL) {
device_printf(ahc->dev_softc,
"bus_alloc_resource() failed to allocate IRQ\n");
return (ENOMEM);
}
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
return (ahc_map_int(ahc));
}

View File

@ -8351,8 +8351,13 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
ahd_queue_scb(ahd, scb);
/*
* Ensure we have enough time to actually
* retrieve the sense.
* retrieve the sense, but only schedule
* the timer if we are not in recovery or
* this is a recovery SCB that is allowed
* to have an active timer.
*/
if (ahd->scb_data.recovery_scbs == 0
|| (scb->flags & SCB_RECOVERY_SCB) != 0)
aic_scb_timer_reset(scb, 5 * 1000000);
break;
}
@ -9441,15 +9446,6 @@ bus_reset:
* In either case (selection or reselection),
* we will now issue a target reset to the
* timed-out device.
*
* Set the MK_MESSAGE control bit indicating
* that we desire to send a message. We
* also set the disconnected flag since
* in the paging case there is no guarantee
* that our SCB control byte matches the
* version on the card. We don't want the
* sequencer to abort the command thinking
* an unsolicited reselection occurred.
*/
scb->flags |= SCB_DEVICE_RESET;
scb->hscb->cdb_len = 0;

View File

@ -667,12 +667,15 @@ struct scb_data {
*/
struct scb *scbindex[AHD_SCB_MAX];
u_int recovery_scbs; /* Transactions currently in recovery */
/*
* "Bus" addresses of our data structures.
*/
bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */
bus_dma_tag_t sg_dmat; /* dmat for our sg segments */
bus_dma_tag_t sense_dmat; /* dmat for our sense buffers */
SLIST_HEAD(, map_node) hscb_maps;
SLIST_HEAD(, map_node) sg_maps;
SLIST_HEAD(, map_node) sense_maps;
@ -1068,6 +1071,8 @@ struct ahd_completion
uint8_t valid_tag;
};
#define AIC_SCB_DATA(softc) (&(softc)->scb_data)
struct ahd_softc {
bus_space_tag_t tags[2];
bus_space_handle_t bshs[2];

View File

@ -263,41 +263,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
}
#endif
/*
* If the recovery SCB completes, we have to be
* out of our timeout.
*/
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
struct scb *list_scb;
/*
* We were able to complete the command successfully,
* so reinstate the timeouts for all other pending
* commands.
*/
LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
union ccb *ccb;
uint64_t time;
ccb = list_scb->io_ctx;
if (ccb->ccb_h.timeout == CAM_TIME_INFINITY)
continue;
time = ccb->ccb_h.timeout;
time *= hz;
time /= 1000;
ccb->ccb_h.timeout_ch =
timeout(ahd_platform_timeout, list_scb, time);
}
ahd->scb_data.recovery_scbs--;
if (aic_get_transaction_status(scb) == CAM_BDR_SENT
|| aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if (ahd->scb_data.recovery_scbs == 0) {
/*
* All recovery actions have completed successfully,
* so reinstate the timeouts for all other pending
* commands.
*/
LIST_FOREACH(list_scb,
&ahd->pending_scbs, pending_links) {
aic_scb_timer_reset(scb, aic_get_timeout(scb));
}
ahd_print_path(ahd, scb);
printf("no longer in timeout, status = %x\n",
ccb->ccb_h.status);
}
}
/* Don't clobber any existing error state */
if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
@ -1123,18 +1114,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
ccb->ccb_h.status |= CAM_SIM_QUEUED;
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
uint64_t time;
if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
ccb->ccb_h.timeout = 5 * 1000;
time = ccb->ccb_h.timeout;
time *= hz;
time /= 1000;
ccb->ccb_h.timeout_ch =
timeout(ahd_platform_timeout, (caddr_t)scb, time);
}
aic_scb_timer_start(scb);
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
/* Define a mapping from our tag to the SCB. */

View File

@ -377,6 +377,9 @@ ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
if ((scb = TAILQ_FIRST(queue)) != NULL
&& (scb->flags & SCB_ACTIVE) == 0) {
scb->flags |= SCB_ACTIVE;
/*
* Timers are disabled while recovery is in progress.
*/
aic_scb_timer_start(scb);
ahc_queue_scb(ahc, scb);
}
@ -578,8 +581,13 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
ahc_outb(ahc, RETURN_1, SEND_SENSE);
/*
* Ensure we have enough time to actually
* retrieve the sense.
* retrieve the sense, but only schedule
* the timer if we are not in recovery or
* this is a recovery SCB that is allowed
* to have an active timer.
*/
if (ahc->scb_data->recovery_scbs == 0
|| (scb->flags & SCB_RECOVERY_SCB) != 0)
aic_scb_timer_reset(scb, 5 * 1000000);
break;
}

View File

@ -613,6 +613,8 @@ struct scb_data {
struct scb *scbarray; /* Array of kernel SCBs */
struct scsi_sense_data *sense; /* Per SCB sense data */
u_int recovery_scbs; /* Transactions currently in recovery */
/*
* "Bus" addresses of our data structures.
*/
@ -920,6 +922,8 @@ typedef int (*ahc_bus_suspend_t)(struct ahc_softc *);
typedef int (*ahc_bus_resume_t)(struct ahc_softc *);
typedef void ahc_callback_t (void *);
#define AIC_SCB_DATA(softc) ((softc)->scb_data)
struct ahc_softc {
bus_space_tag_t tag;
bus_space_handle_t bsh;

View File

@ -90,6 +90,20 @@ int
ahc_map_int(struct ahc_softc *ahc)
{
int error;
int zero;
int shareable;
zero = 0;
shareable = (ahc->flags & AHC_EDGE_INTERRUPT) ? 0: RF_SHAREABLE;
ahc->platform_data->irq =
bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IRQ, &zero,
RF_ACTIVE | shareable);
if (ahc->platform_data->irq == NULL) {
device_printf(ahc->dev_softc,
"bus_alloc_resource() failed to allocate IRQ\n");
return (ENOMEM);
}
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
/* Hook up our interrupt handler */
error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
@ -102,6 +116,27 @@ ahc_map_int(struct ahc_softc *ahc)
return (error);
}
int
aic7770_map_registers(struct ahc_softc *ahc, u_int unused_ioport_arg)
{
struct resource *regs;
int rid;
rid = 0;
regs = bus_alloc_resource_any(ahc->dev_softc, SYS_RES_IOPORT, &rid,
RF_ACTIVE);
if (regs == NULL) {
device_printf(ahc->dev_softc, "Unable to map I/O space?!\n");
return ENOMEM;
}
ahc->platform_data->regs_res_type = SYS_RES_IOPORT;
ahc->platform_data->regs_res_id = rid,
ahc->platform_data->regs = regs;
ahc->tag = rman_get_bustag(regs);
ahc->bsh = rman_get_bushandle(regs);
return (0);
}
/*
* Attach all the sub-devices we can find
*/
@ -346,23 +381,29 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
struct scb *list_scb;
/*
* We were able to complete the command successfully,
* so renew the timeouts for all other pending
* commands.
*/
LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
aic_scb_timer_reset(scb, aic_get_timeout(scb));
}
ahc->scb_data->recovery_scbs--;
if (aic_get_transaction_status(scb) == CAM_BDR_SENT
|| aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if (ahc->scb_data->recovery_scbs == 0) {
/*
* All recovery actions have completed successfully,
* so reinstate the timeouts for all other pending
* commands.
*/
LIST_FOREACH(list_scb, &ahc->pending_scbs,
pending_links) {
aic_scb_timer_reset(scb, aic_get_timeout(scb));
}
ahc_print_path(ahc, scb);
printf("no longer in timeout, status = %x\n",
ccb->ccb_h.status);
}
}
/* Don't clobber any existing error state */
if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
@ -1230,19 +1271,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
ccb->ccb_h.status |= CAM_SIM_QUEUED;
if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
uint64_t time;
if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
ccb->ccb_h.timeout = 5 * 1000;
time = ccb->ccb_h.timeout;
time *= hz;
time /= 1000;
ccb->ccb_h.timeout_ch =
timeout(ahc_platform_timeout, (caddr_t)scb, time);
}
/*
* We only allow one untagged transaction
* per target in the initiator role unless
@ -1265,6 +1293,11 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
}
scb->flags |= SCB_ACTIVE;
/*
* Timers are disabled while recovery is in progress.
*/
aic_scb_timer_start(scb);
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
/* Define a mapping from our tag to the SCB. */
ahc->scb_data->scbindex[scb->hscb->tag] = scb;

View File

@ -256,15 +256,35 @@ ahc_list_unlock(unsigned long *flags)
{
}
/************************* Initialization/Teardown ****************************/
int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
void ahc_platform_free(struct ahc_softc *ahc);
int ahc_map_int(struct ahc_softc *ahc);
int ahc_attach(struct ahc_softc *);
int ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc);
int ahc_detach(device_t);
/********************************** PCI ***************************************/
#ifdef AIC_PCI_CONFIG
int ahc_pci_map_registers(struct ahc_softc *ahc);
int ahc_pci_map_int(struct ahc_softc *ahc);
#define ahc_pci_map_int ahc_map_int
#endif /*AIC_PCI_CONFIG*/
/******************************** VL/EISA *************************************/
int aic7770_map_registers(struct ahc_softc *ahc, u_int port);
int aic7770_map_int(struct ahc_softc *ahc, int irq);
static __inline int aic7770_map_int(struct ahc_softc *, int);
static __inline int
aic7770_map_int(struct ahc_softc *ahc, int irq)
{
/*
* The IRQ is unused in the FreeBSD
* implementation since the EISA and
* ISA attachments register the IRQ
* with newbus before the core is called.
*/
return ahc_map_int(ahc);
}
/********************************* Debug **************************************/
static __inline void ahc_print_path(struct ahc_softc *, struct scb *);
@ -287,14 +307,6 @@ void ahc_notify_xfer_settings_change(struct ahc_softc *,
void ahc_platform_set_tags(struct ahc_softc *, struct ahc_devinfo *,
int /*enable*/);
/************************* Initialization/Teardown ****************************/
int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
void ahc_platform_free(struct ahc_softc *ahc);
int ahc_map_int(struct ahc_softc *ahc);
int ahc_attach(struct ahc_softc *);
int ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc);
int ahc_detach(device_t);
/****************************** Interrupts ************************************/
void ahc_platform_intr(void *);
static __inline void ahc_platform_flushwork(struct ahc_softc *ahc);

View File

@ -46,15 +46,7 @@ aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb)
scb->flags |= SCB_RECOVERY_SCB;
/*
* Take all queued, but not sent SCBs out of the equation.
* Also ensure that no new CCBs are queued to us while we
* try to fix this problem.
*/
if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
xpt_freeze_simq(SCB_GET_SIM(aic, scb), /*count*/1);
scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
}
AIC_SCB_DATA(aic)->recovery_scbs++;
/*
* Go through all of our pending SCBs and remove

View File

@ -223,7 +223,8 @@ static __inline void
aic_scb_timer_start(struct scb *scb)
{
if (scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) {
if (AIC_SCB_DATA(scb->aic_softc)->recovery_scbs == 0
&& scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) {
uint64_t time;
time = scb->io_ctx->ccb_h.timeout;

View File

@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../dev/aic7xxx
KMOD= ahc
SUBDIR= ahc_eisa ahc_pci
SUBDIR= ahc_eisa ahc_isa ahc_pci
GENSRCS= aic7xxx_{seq,reg}.h
AHC_REG_PRETTY_PRINT=1
@ -29,7 +29,7 @@ ${GENSRCS}: \
${.CURDIR}/../../../dev/aic7xxx/aic7xxx.seq
SRCS= ${GENSRCS}
SRCS+= aic7xxx.c aic7xxx_93cx6.c aic7xxx_osm.c
SRCS+= aic7xxx.c aic7xxx_93cx6.c aic7xxx_osm.c aic7770.c
SRCS+= opt_scsi.h opt_aic7xxx.h opt_cam.h
SRCS+= device_if.h bus_if.h pci_if.h

View File

@ -7,8 +7,8 @@ KMOD= ahc_eisa
../aic7xxx_reg.h:
( cd .. ; ${MAKE} aic7xxx_reg.h )
SRCS= ahc_eisa.c aic7770.c ../aic7xxx_reg.h
SRCS+= device_if.h bus_if.h pci_if.h eisa_if.h
SRCS= ahc_eisa.c ../aic7xxx_reg.h
SRCS+= device_if.h bus_if.h eisa_if.h
SRCS+= opt_scsi.h opt_cam.h opt_aic7xxx.h
CFLAGS+= -I${.CURDIR}/../../../../dev/aic7xxx -I..