diff options
author | gibbs <gibbs@FreeBSD.org> | 2004-08-17 00:14:31 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 2004-08-17 00:14:31 +0000 |
commit | 5c67ec4668e0f194d323b210e1b6302bd2b996ce (patch) | |
tree | 1f605d3851fde8ce9f9fdf9c7ffc02dc19fb336b /sys | |
parent | 45d2f83e648a04e901a1108589958b2c268fe6ae (diff) | |
download | FreeBSD-src-5c67ec4668e0f194d323b210e1b6302bd2b996ce.zip FreeBSD-src-5c67ec4668e0f194d323b210e1b6302bd2b996ce.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/dev/aic7xxx/ahc_eisa.c | 35 | ||||
-rw-r--r-- | sys/dev/aic7xxx/ahc_pci.c | 19 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx.c | 18 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx.h | 5 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic79xx_osm.c | 56 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 12 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.h | 4 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.c | 83 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx_osm.h | 32 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic_osm_lib.c | 10 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic_osm_lib.h | 3 | ||||
-rw-r--r-- | sys/modules/aic7xxx/ahc/Makefile | 4 | ||||
-rw-r--r-- | sys/modules/aic7xxx/ahc/ahc_eisa/Makefile | 4 |
14 files changed, 133 insertions, 156 deletions
diff --git a/sys/conf/files b/sys/conf/files index 922047a..3c702c1 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c index 9c773aa..b3fa8e3 100644 --- a/sys/dev/aic7xxx/ahc_eisa.c +++ b/sys/dev/aic7xxx/ahc_eisa.c @@ -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 */ diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c index 4050d7f..ba6ab22 100644 --- a/sys/dev/aic7xxx/ahc_pci.c +++ b/sys/dev/aic7xxx/ahc_pci.c @@ -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)); -} - diff --git a/sys/dev/aic7xxx/aic79xx.c b/sys/dev/aic7xxx/aic79xx.c index 1f3b209..612595b 100644 --- a/sys/dev/aic7xxx/aic79xx.c +++ b/sys/dev/aic7xxx/aic79xx.c @@ -8351,9 +8351,14 @@ 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. */ - aic_scb_timer_reset(scb, 5 * 1000000); + if (ahd->scb_data.recovery_scbs == 0 + || (scb->flags & SCB_RECOVERY_SCB) != 0) + aic_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: @@ -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; diff --git a/sys/dev/aic7xxx/aic79xx.h b/sys/dev/aic7xxx/aic79xx.h index 292458c..6ef0e1d 100644 --- a/sys/dev/aic7xxx/aic79xx.h +++ b/sys/dev/aic7xxx/aic79xx.h @@ -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]; diff --git a/sys/dev/aic7xxx/aic79xx_osm.c b/sys/dev/aic7xxx/aic79xx_osm.c index 3ea6207..458f634 100644 --- a/sys/dev/aic7xxx/aic79xx_osm.c +++ b/sys/dev/aic7xxx/aic79xx_osm.c @@ -263,40 +263,31 @@ 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); - ahd_print_path(ahd, scb); - printf("no longer in timeout, status = %x\n", - ccb->ccb_h.status); + 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 */ @@ -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. */ diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c index 7430503..4bf6466 100644 --- a/sys/dev/aic7xxx/aic7xxx.c +++ b/sys/dev/aic7xxx/aic7xxx.c @@ -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,9 +581,14 @@ 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. */ - aic_scb_timer_reset(scb, 5 * 1000000); + if (ahc->scb_data->recovery_scbs == 0 + || (scb->flags & SCB_RECOVERY_SCB) != 0) + aic_scb_timer_reset(scb, 5 * 1000000); break; } default: diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h index 7458ebc..6273a90 100644 --- a/sys/dev/aic7xxx/aic7xxx.h +++ b/sys/dev/aic7xxx/aic7xxx.h @@ -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; diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c index 1c11f76..ba1eca2 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/aic7xxx/aic7xxx_osm.c @@ -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,22 +381,28 @@ 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); - ahc_print_path(ahc, scb); - printf("no longer in timeout, status = %x\n", - ccb->ccb_h.status); + + 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 */ @@ -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; diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h index 69cb3f0..55d9697 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.h +++ b/sys/dev/aic7xxx/aic7xxx_osm.h @@ -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); diff --git a/sys/dev/aic7xxx/aic_osm_lib.c b/sys/dev/aic7xxx/aic_osm_lib.c index 295044c..525fdcc 100644 --- a/sys/dev/aic7xxx/aic_osm_lib.c +++ b/sys/dev/aic7xxx/aic_osm_lib.c @@ -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 diff --git a/sys/dev/aic7xxx/aic_osm_lib.h b/sys/dev/aic7xxx/aic_osm_lib.h index ca7a088..f00d80b 100644 --- a/sys/dev/aic7xxx/aic_osm_lib.h +++ b/sys/dev/aic7xxx/aic_osm_lib.h @@ -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; diff --git a/sys/modules/aic7xxx/ahc/Makefile b/sys/modules/aic7xxx/ahc/Makefile index 6ef8ae0..34a47f5 100644 --- a/sys/modules/aic7xxx/ahc/Makefile +++ b/sys/modules/aic7xxx/ahc/Makefile @@ -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 diff --git a/sys/modules/aic7xxx/ahc/ahc_eisa/Makefile b/sys/modules/aic7xxx/ahc/ahc_eisa/Makefile index da63774..5e5d9c2 100644 --- a/sys/modules/aic7xxx/ahc/ahc_eisa/Makefile +++ b/sys/modules/aic7xxx/ahc/ahc_eisa/Makefile @@ -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.. |