bt(4): Sync with FreeBSD.
authorSascha Wildner <saw@online.de>
Thu, 29 Nov 2012 17:20:48 +0000 (18:20 +0100)
committerSascha Wildner <saw@online.de>
Thu, 29 Nov 2012 17:21:31 +0000 (18:21 +0100)
Main change is making it MPSAFE.

Taken-from: FreeBSD

share/man/man4/bt.4
sys/dev/disk/buslogic/bt.c
sys/dev/disk/buslogic/bt_pci.c
sys/dev/disk/buslogic/btreg.h

index d911014..586f8a8 100644 (file)
 .Nm bt
 .Nd Buslogic/Mylex MultiMaster SCSI host adapter driver
 .Sh SYNOPSIS
-.Cd device scbus
-.Cd device bt
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device scbus"
+.Cd "device bt"
+.Ed
 .Sh DESCRIPTION
 This driver provides access to the
 .Tn SCSI
 bus connected to a Buslogic/Mylex MultiMaster or compatible controller:
 .Bd -ragged -offset indent
-.Bl -column "BT-956CD " "PCI " "Commands " Description
 MultiMaster "W" Series Host Adapters:
-.Pp
-.Em "Adapter   Bus   Commands  Description"
-BT-948    PCI     192     ULtra SCSI-3
-BT-958    PCI     192     Wide ULtra SCSI-3
-BT-958D   PCI     192     Wide Differential ULtra SCSI-3
+.Bl -column "BT-956CD " "PCI " "Commands " "Description"
+.Em "Adapter" Ta Em "Bus" Ta Em "Commands" Ta Em "Description"
+BT-948 PCI     192     Ultra SCSI-3
+BT-958 PCI     192     Wide Ultra SCSI-3
+BT-958D        PCI     192     Wide Differential Ultra SCSI-3
 .El
-.Bl -column "BT-956CD " "PCI " "Commands " Description
-MultiMaster "C" Series Host Adapters:
 .Pp
-.Em "Adapter   Bus   Commands  Description"
-BT-946C   PCI     100     Fast SCSI-2
-BT-956C   PCI     100     Wide Fast SCSI-2
-BT-956CD  PCI     100     Wide Differential Fast SCSI-2
+MultiMaster "C" Series Host Adapters:
+.Bl -column "BT-956CD " "PCI " "Commands " "Description"
+.Em "Adapter" Ta Em "Bus" Ta Em "Commands" Ta Em "Description"
+BT-946C        PCI     100     Fast SCSI-2
+BT-956C        PCI     100     Wide Fast SCSI-2
+BT-956CD       PCI     100     Wide Differential Fast SCSI-2
 .El
 .Ed
 .Pp
@@ -65,7 +69,8 @@ Tagged queueing is supported on 'W' series adapters and 'C' series adapters
 with firmware of rev 4.42 and higher.
 .Pp
 Boards with certain firmware revisions may lock up under heavy load to
-certain devices, especially if tagged queueing is used.  Should you encounter
+certain devices, especially if tagged queueing is used.
+Should you encounter
 a problem with your adapter, contact Mylex technical support and ensure you
 have the latest firmware for your controller.
 .Sh FILES
@@ -93,7 +98,8 @@ patch kit.
 .An Julian Elischer
 wrote a driver for the Multimaster cards that appeared in the
 .Bx 386
-patch kit.  The driver was rewritten by
+patch kit.
+The driver was rewritten by
 .An Justin T. Gibbs
 to take advantage of new board features and work with the CAM SCSI framework in
 .Fx 3.0 .
@@ -101,6 +107,7 @@ to take advantage of new board features and work with the CAM SCSI framework in
 Special thanks to
 .An Leonard N. Zubkoff
 for writing such a complete and well documented Mylex/BusLogic MultiMaster
-driver for Linux.  Support in this driver for the wide range of MultiMaster
+driver for Linux.
+Support in this driver for the wide range of MultiMaster
 controllers and firmware revisions, with their otherwise undocumented quirks,
 would not have been possible without his efforts.
index ea5c30b..5d2c3da 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Generic driver for the BusLogic MultiMaster SCSI host adapters
  * Product specific probe and attach routines can be found in:
  * sys/dev/buslogic/bt_pci.c   BT-946, BT-948, BT-956, BT-958 cards
@@ -27,7 +27,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/buslogic/bt.c,v 1.25.2.1 2000/08/02 22:32:26 peter Exp $
+ * $FreeBSD: src/sys/dev/buslogic/bt.c,v 1.54 2012/11/17 01:51:40 svnexp Exp $
  */
 
  /*
 #include <sys/malloc.h>
 #include <sys/buf.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/sysctl.h>
 #include <sys/bus.h>
 #include <sys/rman.h>
-#include <sys/thread2.h>
  
-#include <machine/clock.h>
-
 #include <bus/cam/cam.h>
 #include <bus/cam/cam_ccb.h>
 #include <bus/cam/cam_sim.h>
@@ -60,7 +58,7 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>
  
-#include "btreg.h"
+#include <dev/disk/buslogic/btreg.h>
 
 /* MailBox Management functions */
 static __inline void   btnextinbox(struct bt_softc *bt);
@@ -105,7 +103,7 @@ static __inline struct bt_ccb *
 btccbptov(struct bt_softc *bt, u_int32_t ccb_addr)
 {
        return (bt->bt_ccb_array +
-               ((struct bt_ccb*)(uintptr_t)ccb_addr-(struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase));
+               ((struct bt_ccb*)(uintptr_t)ccb_addr - (struct bt_ccb*)(uintptr_t)bt->bt_ccb_physbase));
 }
 
 static __inline u_int32_t
@@ -134,6 +132,7 @@ static void         btallocccbs(struct bt_softc *bt);
 static bus_dmamap_callback_t btexecuteccb;
 static void            btdone(struct bt_softc *bt, struct bt_ccb *bccb,
                               bt_mbi_comp_code_t comp_code);
+static void            bt_intr_locked(struct bt_softc *bt);
 
 /* Host adapter command functions */
 static int     btreset(struct bt_softc* bt, int hard_reset);
@@ -155,9 +154,8 @@ static void btaction(struct cam_sim *sim, union ccb *ccb);
 static void    btpoll(struct cam_sim *sim);
 
 /* Our timeout handler */
-timeout_t bttimeout;
+static void    bttimeout(void *arg);
 
-u_long bt_unit = 0;
 
 /* Exported functions */
 void
@@ -170,12 +168,10 @@ bt_init_softc(device_t dev, struct resource *port,
        LIST_INIT(&bt->pending_ccbs);
        SLIST_INIT(&bt->sg_maps);
        bt->dev = dev;
-       bt->unit = device_get_unit(dev);
        bt->port = port;
        bt->irq = irq;
        bt->drq = drq;
-       bt->tag = rman_get_bustag(port);
-       bt->bsh = rman_get_bushandle(port);
+       lockinit(&bt->lock, "bt", 0, LK_CANRECURSE);
 }
 
 void
@@ -208,25 +204,33 @@ bt_free_softc(device_t dev)
        }
        case 7:
                bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap);
+               /* FALLTHROUGH */
        case 6:
                bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array,
                                bt->ccb_dmamap);
                bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap);
+               /* FALLTHROUGH */
        case 5:
                bus_dma_tag_destroy(bt->ccb_dmat);
+               /* FALLTHROUGH */
        case 4:
                bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap);
+               /* FALLTHROUGH */
        case 3:
                bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes,
                                bt->mailbox_dmamap);
                bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap);
+               /* FALLTHROUGH */
        case 2:
                bus_dma_tag_destroy(bt->buffer_dmat);
+               /* FALLTHROUGH */
        case 1:
                bus_dma_tag_destroy(bt->mailbox_dmat);
+               /* FALLTHROUGH */
        case 0:
                break;
        }
+       lockuninit(&bt->lock);
 }
 
 /*
@@ -276,7 +280,9 @@ bt_probe(device_t dev)
         * adapter and attempt to fetch the extended setup
         * information.  This should filter out all 1542 cards.
         */
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
        if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {
+               lockmgr(&bt->lock, LK_RELEASE);
                if (bootverbose)
                        device_printf(dev, "Failed Reset\n");
                return (ENXIO);
@@ -286,6 +292,7 @@ bt_probe(device_t dev)
        error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &param, /*parmlen*/1,
                       (u_int8_t*)&esetup_info, sizeof(esetup_info),
                       DEFAULT_CMD_TIMEOUT);
+       lockmgr(&bt->lock, LK_RELEASE);
        if (error != 0) {
                return (ENXIO);
        }
@@ -307,10 +314,12 @@ bt_fetch_adapter_info(device_t dev)
        u_int8_t length_param;
 
        /* First record the firmware version */
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
        error = bt_cmd(bt, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
                       (u_int8_t*)&board_id, sizeof(board_id),
                       DEFAULT_CMD_TIMEOUT);
        if (error != 0) {
+               lockmgr(&bt->lock, LK_RELEASE);
                device_printf(dev, "bt_fetch_adapter_info - Failed Get Board Info\n");
                return (error);
        }
@@ -329,6 +338,7 @@ bt_fetch_adapter_info(device_t dev)
                               (u_int8_t*)&bt->firmware_ver[3], 1,
                               DEFAULT_CMD_TIMEOUT);
                if (error != 0) {
+                       lockmgr(&bt->lock, LK_RELEASE);
                        device_printf(dev,
                                      "bt_fetch_adapter_info - Failed Get "
                                      "Firmware 3rd Digit\n");
@@ -345,6 +355,7 @@ bt_fetch_adapter_info(device_t dev)
                               (u_int8_t*)&bt->firmware_ver[4], 1,
                               DEFAULT_CMD_TIMEOUT);
                if (error != 0) {
+                       lockmgr(&bt->lock, LK_RELEASE);
                        device_printf(dev,
                                      "bt_fetch_adapter_info - Failed Get "
                                      "Firmware 4th Digit\n");
@@ -377,6 +388,7 @@ bt_fetch_adapter_info(device_t dev)
                       (u_int8_t*)&esetup_info, sizeof(esetup_info),
                       DEFAULT_CMD_TIMEOUT);
        if (error != 0) {
+               lockmgr(&bt->lock, LK_RELEASE);
                return (error);
        }
        
@@ -398,6 +410,7 @@ bt_fetch_adapter_info(device_t dev)
                               (u_int8_t*)&model_data, sizeof(model_data),
                               DEFAULT_CMD_TIMEOUT);
                if (error != 0) {
+                       lockmgr(&bt->lock, LK_RELEASE);
                        device_printf(dev,
                                      "bt_fetch_adapter_info - Failed Inquire "
                                      "Model Number\n");
@@ -484,6 +497,7 @@ bt_fetch_adapter_info(device_t dev)
                               sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);
 
                if (error != 0) {
+                       lockmgr(&bt->lock, LK_RELEASE);
                        device_printf(dev,
                                      "bt_fetch_adapter_info - Failed "
                                      "Get Auto SCSI Info\n");
@@ -519,6 +533,7 @@ bt_fetch_adapter_info(device_t dev)
                               sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
 
                if (error != 0) {
+                       lockmgr(&bt->lock, LK_RELEASE);
                        device_printf(dev,
                                      "bt_fetch_adapter_info - Failed "
                                      "Get Setup Info\n");
@@ -546,6 +561,7 @@ bt_fetch_adapter_info(device_t dev)
        error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
                       (u_int8_t*)&config_data, sizeof(config_data),
                       DEFAULT_CMD_TIMEOUT);
+       lockmgr(&bt->lock, LK_RELEASE);
        if (error != 0) {
                device_printf(dev,
                              "bt_fetch_adapter_info - Failed Get Config\n");
@@ -592,35 +608,44 @@ bt_init(device_t dev)
         */
 
        /* DMA tag for mapping buffers into device visible space. */
-       if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0,
-                              /*lowaddr*/BUS_SPACE_MAXADDR,
-                              /*highaddr*/BUS_SPACE_MAXADDR,
-                              /*filter*/NULL, /*filterarg*/NULL,
-                              /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG,
-                              /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*flags*/BUS_DMA_ALLOCNOW,
-                              &bt->buffer_dmat) != 0) {
+       if (bus_dma_tag_create( /* parent       */ bt->parent_dmat,
+                               /* alignment    */ 1,
+                               /* boundary     */ 0,
+                               /* lowaddr      */ BUS_SPACE_MAXADDR,
+                               /* highaddr     */ BUS_SPACE_MAXADDR,
+                               /* filter       */ NULL,
+                               /* filterarg    */ NULL,
+                               /* maxsize      */ MAXBSIZE,
+                               /* nsegments    */ BT_NSEG,
+                               /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* flags        */ BUS_DMA_ALLOCNOW,
+                               &bt->buffer_dmat) != 0) {
                goto error_exit;
        }
 
        bt->init_level++;
        /* DMA tag for our mailboxes */
-       if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0,
-                              /*lowaddr*/BUS_SPACE_MAXADDR,
-                              /*highaddr*/BUS_SPACE_MAXADDR,
-                              /*filter*/NULL, /*filterarg*/NULL,
-                              bt->num_boxes * (sizeof(bt_mbox_in_t)
-                                             + sizeof(bt_mbox_out_t)),
-                              /*nsegments*/1,
-                              /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*flags*/0, &bt->mailbox_dmat) != 0) {
+       if (bus_dma_tag_create( /* parent       */ bt->parent_dmat,
+                               /* alignment    */ 1,
+                               /* boundary     */ 0,
+                               /* lowaddr      */ BUS_SPACE_MAXADDR,
+                               /* highaddr     */ BUS_SPACE_MAXADDR,
+                               /* filter       */ NULL,
+                               /* filterarg    */ NULL,
+                               /* maxsize      */ bt->num_boxes *
+                                                  (sizeof(bt_mbox_in_t) +
+                                                   sizeof(bt_mbox_out_t)),
+                               /* nsegments    */ 1,
+                               /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* flags        */ 0,
+                               &bt->mailbox_dmat) != 0) {
                goto error_exit;
         }
 
        bt->init_level++;
 
        /* Allocation for our mailboxes */
-       if (bus_dmamem_alloc(bt->mailbox_dmat, (void *)&bt->out_boxes,
+       if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes,
                             BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) {
                goto error_exit;
        }
@@ -638,24 +663,31 @@ bt_init(device_t dev)
 
        bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes];
 
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
        btinitmboxes(bt);
+       lockmgr(&bt->lock, LK_RELEASE);
 
        /* DMA tag for our ccb structures */
-       if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0,
-                              /*lowaddr*/BUS_SPACE_MAXADDR,
-                              /*highaddr*/BUS_SPACE_MAXADDR,
-                              /*filter*/NULL, /*filterarg*/NULL,
-                              bt->max_ccbs * sizeof(struct bt_ccb),
-                              /*nsegments*/1,
-                              /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*flags*/0, &bt->ccb_dmat) != 0) {
+       if (bus_dma_tag_create( /* parent       */ bt->parent_dmat,
+                               /* alignment    */ 1,
+                               /* boundary     */ 0,
+                               /* lowaddr      */ BUS_SPACE_MAXADDR,
+                               /* highaddr     */ BUS_SPACE_MAXADDR,
+                               /* filter       */ NULL,
+                               /* filterarg    */ NULL,
+                               /* maxsize      */ bt->max_ccbs *
+                                                  sizeof(struct bt_ccb),
+                               /* nsegments    */ 1,
+                               /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* flags        */ 0,
+                               &bt->ccb_dmat) != 0) {
                goto error_exit;
         }
 
        bt->init_level++;
 
        /* Allocation for our ccbs */
-       if (bus_dmamem_alloc(bt->ccb_dmat, (void *)&bt->bt_ccb_array,
+       if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array,
                             BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) {
                goto error_exit;
        }
@@ -671,13 +703,18 @@ bt_init(device_t dev)
        bt->init_level++;
 
        /* DMA tag for our S/G structures.  We allocate in page sized chunks */
-       if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1, /*boundary*/0,
-                              /*lowaddr*/BUS_SPACE_MAXADDR,
-                              /*highaddr*/BUS_SPACE_MAXADDR,
-                              /*filter*/NULL, /*filterarg*/NULL,
-                              PAGE_SIZE, /*nsegments*/1,
-                              /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*flags*/0, &bt->sg_dmat) != 0) {
+       if (bus_dma_tag_create( /* parent       */ bt->parent_dmat,
+                               /* alignment    */ 1,
+                               /* boundary     */ 0,
+                               /* lowaddr      */ BUS_SPACE_MAXADDR,
+                               /* highaddr     */ BUS_SPACE_MAXADDR,
+                               /* filter       */ NULL,
+                               /* filterarg    */ NULL,
+                               /* maxsize      */ PAGE_SIZE,
+                               /* nsegments    */ 1,
+                               /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* flags        */ 0,
+                               &bt->sg_dmat) != 0) {
                goto error_exit;
         }
 
@@ -694,7 +731,7 @@ bt_init(device_t dev)
        }
 
        /*
-        * Note that we are going and return (to probe)
+        * Note that we are going and return (to attach)
         */
        return 0;
 
@@ -730,14 +767,16 @@ bt_attach(device_t dev)
        /*
         * Construct our SIM entry
         */
-       bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit,
-                               &sim_mplock, 2, tagged_dev_openings, devq);
+       bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt,
+           device_get_unit(bt->dev), &bt->lock, 2, tagged_dev_openings, devq);
        cam_simq_release(devq);
        if (bt->sim == NULL)
                return (ENOMEM);
-       
+
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
        if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) {
                cam_sim_free(bt->sim);
+               lockmgr(&bt->lock, LK_RELEASE);
                return (ENXIO);
        }
        
@@ -746,14 +785,16 @@ bt_attach(device_t dev)
                            CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
                xpt_bus_deregister(cam_sim_path(bt->sim));
                cam_sim_free(bt->sim);
+               lockmgr(&bt->lock, LK_RELEASE);
                return (ENXIO);
        }
+       lockmgr(&bt->lock, LK_RELEASE);
                
        /*
         * Setup interrupt.
         */
-       error = bus_setup_intr(dev, bt->irq, 0,
-                              bt_intr, bt, &bt->ih, NULL);
+       error = bus_setup_intr(dev, bt->irq,
+           INTR_MPSAFE, bt_intr, bt, &bt->ih, NULL);
        if (error) {
                device_printf(dev, "bus_setup_intr() failed: %d\n", error);
                return (error);
@@ -781,7 +822,7 @@ btallocccbs(struct bt_softc *bt)
        sg_map = kmalloc(sizeof(*sg_map), M_DEVBUF, M_WAITOK);
 
        /* Allocate S/G space for the next batch of CCBS */
-       if (bus_dmamem_alloc(bt->sg_dmat, (void *)&sg_map->sg_vaddr,
+       if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr,
                             BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
                kfree(sg_map, M_DEVBUF);
                goto error_exit;
@@ -802,6 +843,7 @@ btallocccbs(struct bt_softc *bt)
                next_ccb->sg_list = segs;
                next_ccb->sg_list_phys = physaddr;
                next_ccb->flags = BCCB_FREE;
+               callout_init_mp(&next_ccb->timer);
                error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0,
                                          &next_ccb->dmamap);
                if (error != 0)
@@ -829,7 +871,8 @@ error_exit:
 static __inline void
 btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb)
 {
-       crit_enter();
+       if (!dumping)
+               KKASSERT(lockowned(&bt->lock));
        if ((bccb->flags & BCCB_ACTIVE) != 0)
                LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);
        if (bt->resource_shortage != 0
@@ -840,7 +883,6 @@ btfreeccb(struct bt_softc *bt, struct bt_ccb *bccb)
        bccb->flags = BCCB_FREE;
        SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links);
        bt->active_ccbs--;
-       crit_exit();
 }
 
 static __inline struct bt_ccb*
@@ -848,7 +890,8 @@ btgetccb(struct bt_softc *bt)
 {
        struct  bt_ccb* bccb;
 
-       crit_enter();
+       if (!dumping)
+               KKASSERT(lockowned(&bt->lock));
        if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) {
                SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);
                bt->active_ccbs++;
@@ -860,7 +903,6 @@ btgetccb(struct bt_softc *bt)
                        bt->active_ccbs++;
                }
        }
-       crit_exit();
 
        return (bccb);
 }
@@ -873,7 +915,8 @@ btaction(struct cam_sim *sim, union ccb *ccb)
        CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n"));
        
        bt = (struct bt_softc *)cam_sim_softc(sim);
-       
+       KKASSERT(lockowned(&bt->lock));
+
        switch (ccb->ccb_h.func_code) {
        /* Common cases first */
        case XPT_SCSI_IO:       /* Execute the requested I/O operation */
@@ -886,9 +929,7 @@ btaction(struct cam_sim *sim, union ccb *ccb)
                 * get a bccb to use.
                 */
                if ((bccb = btgetccb(bt)) == NULL) {
-                       crit_enter();
                        bt->resource_shortage = TRUE;
-                       crit_exit();
                        xpt_freeze_simq(bt->sim, /*count*/1);
                        ccb->ccb_h.status = CAM_REQUEUE_REQ;
                        xpt_done(ccb);
@@ -972,7 +1013,6 @@ btaction(struct cam_sim *sim, union ccb *ccb)
                                        if ((ccbh->flags & CAM_DATA_PHYS)==0) {
                                                int error;
 
-                                               crit_enter();
                                                error = bus_dmamap_load(
                                                    bt->buffer_dmat,
                                                    bccb->dmamap,
@@ -994,7 +1034,6 @@ btaction(struct cam_sim *sim, union ccb *ccb)
                                                        csio->ccb_h.status |=
                                                            CAM_RELEASE_SIMQ;
                                                }
-                                               crit_exit();
                                        } else {
                                                struct bus_dma_segment seg; 
 
@@ -1255,8 +1294,6 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
                bccb->hccb.data_addr = 0;
        }
 
-       crit_enter();
-
        /*
         * Last time we need to check if this CCB needs to
         * be aborted.
@@ -1266,7 +1303,6 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
                        bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
                btfreeccb(bt, bccb);
                xpt_done(ccb);
-               crit_exit();
                return;
        }
                
@@ -1274,7 +1310,7 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
        ccb->ccb_h.status |= CAM_SIM_QUEUED;
        LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le);
 
-       callout_reset(&ccb->ccb_h.timeout_ch, (ccb->ccb_h.timeout * hz) / 1000,
+       callout_reset(&bccb->timer, (ccb->ccb_h.timeout * hz) / 1000,
            bttimeout, bccb);
 
        /* Tell the adapter about this command */
@@ -1291,7 +1327,7 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
                              "Encountered busy mailbox with %d out of %d "
                              "commands active!!!\n", bt->active_ccbs,
                              bt->max_ccbs);
-               callout_stop(&ccb->ccb_h.timeout_ch);
+               callout_stop(&bccb->timer);
                if (nseg != 0)
                        bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);
                btfreeccb(bt, bccb);
@@ -1299,22 +1335,29 @@ btexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
                xpt_freeze_simq(bt->sim, /*count*/1);
                ccb->ccb_h.status = CAM_REQUEUE_REQ;
                xpt_done(ccb);
-               crit_exit();
                return;
        }
        bt->cur_outbox->action_code = BMBO_START;       
        bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
        btnextoutbox(bt);
-       crit_exit();
 }
 
 void
 bt_intr(void *arg)
 {
        struct  bt_softc *bt;
+
+       bt = arg;
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
+       bt_intr_locked(bt);
+       lockmgr(&bt->lock, LK_RELEASE);
+}
+
+void
+bt_intr_locked(struct bt_softc *bt)
+{
        u_int   intstat;
 
-       bt = (struct bt_softc *)arg;
        while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) {
 
                if ((intstat & CMD_COMPLETE) != 0) {
@@ -1400,7 +1443,7 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
                                ccb_h = LIST_NEXT(ccb_h, sim_links.le);
                                btdone(bt, pending_bccb, BMBI_ERROR);
                        } else {
-                               callout_reset(&ccb_h->timeout_ch,
+                               callout_reset(&pending_bccb->timer,
                                    (ccb_h->timeout * hz) / 1000,
                                    bttimeout, pending_bccb);
                                ccb_h = LIST_NEXT(ccb_h, sim_links.le);
@@ -1410,7 +1453,7 @@ btdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code)
                return;
        }
 
-       callout_stop(&ccb->ccb_h.timeout_ch);
+       callout_stop(&bccb->timer);
 
        switch (comp_code) {
        case BMBI_FREE:
@@ -1593,8 +1636,9 @@ btreset(struct bt_softc* bt, int hard_reset)
        }
        if (timeout == 0) {
                if (bootverbose)
-                       kprintf("%s: btreset - Diagnostic Active failed to "
-                               "assert. status = 0x%x\n", bt_name(bt), status);
+                       device_printf(bt->dev,
+                           "btreset - Diagnostic Active failed to "
+                           "assert. status = 0x%x\n", status);
                return (ETIMEDOUT);
        }
 
@@ -1621,20 +1665,22 @@ btreset(struct bt_softc* bt, int hard_reset)
                DELAY(100);
        }
        if (timeout == 0) {
-               kprintf("%s: btreset - Host adapter failed to come ready. "
-                      "status = 0x%x\n", bt_name(bt), status);
+               device_printf(bt->dev,
+                   "btreset - Host adapter failed to come ready. "
+                   "status = 0x%x\n", status);
                return (ETIMEDOUT);
        }
 
        /* If the diagnostics failed, tell the user */
        if ((status & DIAG_FAIL) != 0
         || (status & HA_READY) == 0) {
-               kprintf("%s: btreset - Adapter failed diagnostics\n",
-                      bt_name(bt));
+               device_printf(bt->dev,
+                   "btreset - Adapter failed diagnostics\n");
 
                if ((status & DATAIN_REG_READY) != 0)
-                       kprintf("%s: btreset - Host Adapter Error code = 0x%x\n",
-                              bt_name(bt), bt_inb(bt, DATAIN_REG));
+                       device_printf(bt->dev,
+                           "btreset - Host Adapter Error code = 0x%x\n",
+                           bt_inb(bt, DATAIN_REG));
                return (ENXIO);
        }
 
@@ -1704,8 +1750,9 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                DELAY(100);
        }
        if (timeout == 0) {
-               kprintf("%s: bt_cmd: Timeout waiting for adapter ready, "
-                      "status = 0x%x\n", bt_name(bt), status);
+               device_printf(bt->dev,
+                   "bt_cmd: Timeout waiting for adapter ready, "
+                   "status = 0x%x\n", status);
                return (ETIMEDOUT);
        }
 
@@ -1715,16 +1762,14 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
        bt_outb(bt, COMMAND_REG, opcode);
 
        /*
-        * Wait for up to 1sec for each byte of the the
+        * Wait for up to 1sec for each byte of the
         * parameter list sent to be sent.
         */
        timeout = 10000;
        while (param_len && --timeout) {
                DELAY(100);
-               crit_enter();
                status = bt_inb(bt, STATUS_REG);
                intstat = bt_inb(bt, INTSTAT_REG);
-               crit_exit();
        
                if ((intstat & (INTR_PENDING|CMD_COMPLETE))
                 == (INTR_PENDING|CMD_COMPLETE)) {
@@ -1746,8 +1791,8 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                }
        }
        if (timeout == 0) {
-               kprintf("%s: bt_cmd: Timeout sending parameters, "
-                      "status = 0x%x\n", bt_name(bt), status);
+               device_printf(bt->dev, "bt_cmd: Timeout sending parameters, "
+                   "status = 0x%x\n", status);
                cmd_complete = 1;
                saved_status = status;
                error = ETIMEDOUT;
@@ -1757,8 +1802,6 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
         * Wait for the command to complete.
         */
        while (cmd_complete == 0 && --cmd_timeout) {
-
-               crit_enter();
                status = bt_inb(bt, STATUS_REG);
                intstat = bt_inb(bt, INTSTAT_REG);
                /*
@@ -1770,8 +1813,7 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                 */
                if ((intstat & (INTR_PENDING|IMB_LOADED))
                 == (INTR_PENDING|IMB_LOADED))
-                       bt_intr(bt);
-               crit_exit();
+                       bt_intr_locked(bt);
 
                if (bt->command_cmp != 0) {
                        /*
@@ -1805,9 +1847,9 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                        if (reply_len < reply_buf_size) {
                                *reply_data++ = data;
                        } else {
-                               kprintf("%s: bt_cmd - Discarded reply data byte "
-                                      "for opcode 0x%x\n", bt_name(bt),
-                                      opcode);
+                               device_printf(bt->dev,
+                                   "bt_cmd - Discarded reply data byte "
+                                   "for opcode 0x%x\n", opcode);
                        }
                        /*
                         * Reset timeout to ensure at least a second
@@ -1824,20 +1866,18 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                DELAY(100);
        }
        if (cmd_timeout == 0) {
-               kprintf("%s: bt_cmd: Timeout waiting for command (%x) "
-                      "to complete.\n%s: status = 0x%x, intstat = 0x%x, "
-                      "rlen %d\n", bt_name(bt), opcode,
-                      bt_name(bt), status, intstat, reply_len);
+               device_printf(bt->dev,
+                   "bt_cmd: Timeout waiting for command (%x) "
+                   "to complete.\n", opcode);
+               device_printf(bt->dev, "status = 0x%x, intstat = 0x%x, "
+                   "rlen %d\n", status, intstat, reply_len);
                error = (ETIMEDOUT);
        }
 
        /*
-        * Clear any pending interrupts.  Block interrupts so our
-        * interrupt handler is not re-entered.
+        * Clear any pending interrupts.
         */
-       crit_enter();
-       bt_intr(bt);
-       crit_exit();
+       bt_intr_locked(bt);
        
        if (error != 0)
                return (error);
@@ -1853,7 +1893,7 @@ bt_cmd(struct bt_softc *bt, bt_op_t opcode, u_int8_t *params, u_int param_len,
                 * reset above), perform a soft reset.
                 */
                if (bootverbose)
-                       kprintf("%s: Invalid Command 0x%x\n", bt_name(bt), 
+                       device_printf(bt->dev, "Invalid Command 0x%x\n",
                                opcode);
                DELAY(1000);
                status = bt_inb(bt, STATUS_REG);
@@ -1921,8 +1961,8 @@ btinitmboxes(struct bt_softc *bt) {
                        kprintf("btinitmboxes: Unable to enable strict RR\n");
                        error = 0;
                } else if (bootverbose) {
-                       kprintf("%s: Using Strict Round Robin Mailbox Mode\n",
-                              bt_name(bt));
+                       device_printf(bt->dev,
+                           "Using Strict Round Robin Mailbox Mode\n");
                }
        }
        
@@ -1969,8 +2009,9 @@ btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts)
                       DEFAULT_CMD_TIMEOUT);
 
        if (error != 0) {
-               kprintf("%s: btfetchtransinfo - Inquire Setup Info Failed %x\n",
-                      bt_name(bt), error);
+               device_printf(bt->dev,
+                   "btfetchtransinfo - Inquire Setup Info Failed %x\n",
+                   error);
                return;
        }
 
@@ -2024,8 +2065,9 @@ btfetchtransinfo(struct bt_softc *bt, struct ccb_trans_settings *cts)
                               DEFAULT_CMD_TIMEOUT);
                
                if (error != 0) {
-                       kprintf("%s: btfetchtransinfo - Inquire Sync "
-                              "Info Failed 0x%x\n", bt_name(bt), error);
+                       device_printf(bt->dev,
+                           "btfetchtransinfo - Inquire Sync "
+                           "Info Failed 0x%x\n", error);
                        return;
                }
                sync_period = sync_info.sync_rate[target] * 100;
@@ -2086,7 +2128,7 @@ btmapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 static void
 btpoll(struct cam_sim *sim)
 {
-       bt_intr(cam_sim_softc(sim));
+       bt_intr_locked(cam_sim_softc(sim));
 }
 
 void
@@ -2099,16 +2141,15 @@ bttimeout(void *arg)
        bccb = (struct bt_ccb *)arg;
        ccb = bccb->ccb;
        bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;
+       lockmgr(&bt->lock, LK_EXCLUSIVE);
        xpt_print_path(ccb->ccb_h.path);
        kprintf("CCB %p - timed out\n", (void *)bccb);
 
-       crit_enter();
-
        if ((bccb->flags & BCCB_ACTIVE) == 0) {
                xpt_print_path(ccb->ccb_h.path);
                kprintf("CCB %p - timed out CCB already completed\n",
                       (void *)bccb);
-               crit_exit();
+               lockmgr(&bt->lock, LK_RELEASE);
                return;
        }
 
@@ -2135,7 +2176,7 @@ bttimeout(void *arg)
                        struct bt_ccb *pending_bccb;
 
                        pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;
-                       callout_stop(&ccb_h->timeout_ch);
+                       callout_stop(&pending_bccb->timer);
                        ccb_h = LIST_NEXT(ccb_h, sim_links.le);
                }
        }
@@ -2158,7 +2199,7 @@ bttimeout(void *arg)
                 */
                ccb->ccb_h.status = CAM_CMD_TIMEOUT;
                btreset(bt, /*hardreset*/TRUE);
-               kprintf("%s: No longer in timeout\n", bt_name(bt));
+               device_printf(bt->dev, "No longer in timeout\n");
        } else {
                /*    
                 * Send a Bus Device Reset message:
@@ -2172,7 +2213,7 @@ bttimeout(void *arg)
                 * later which will attempt a bus reset.
                 */
                bccb->flags |= BCCB_DEVICE_RESET;
-               callout_reset(&ccb->ccb_h.timeout_ch, 2 * hz, bttimeout, bccb);
+               callout_reset(&bccb->timer, 2 * hz, bttimeout, bccb);
 
                bt->recovery_bccb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
 
@@ -2189,7 +2230,8 @@ bttimeout(void *arg)
                bt_outb(bt, COMMAND_REG, BOP_START_MBOX);
                btnextoutbox(bt);
        }
-
-       crit_exit();
+       lockmgr(&bt->lock, LK_RELEASE);
 }
 
+MODULE_VERSION(bt, 1);
+MODULE_DEPEND(bt, cam, 1, 1, 1);
index 30c1cf9..b6e5bd0 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Product specific probe and attach routines for:
  *      Buslogic BT946, BT948, BT956, BT958 SCSI controllers
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/buslogic/bt_pci.c,v 1.11 2000/01/17 12:38:00 nyan Exp $
+ * $FreeBSD: src/sys/dev/buslogic/bt_pci.c,v 1.25 2012/11/17 01:51:40 svnexp Exp $
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/module.h>
 #include <sys/bus.h>
 #include <sys/rman.h>
 #include <sys/thread2.h>
@@ -41,8 +42,8 @@
 
 #include "btreg.h"
 
-#define BT_PCI_IOADDR  PCIR_MAPS
-#define BT_PCI_MEMADDR PCIR_MAPS + 4
+#define BT_PCI_IOADDR  PCIR_BAR(0)
+#define BT_PCI_MEMADDR PCIR_BAR(1)
 
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER     0x1040104Bul
 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC  0x0140104Bul
@@ -60,23 +61,21 @@ bt_pci_alloc_resources(device_t dev)
        if (command & PCIM_CMD_MEMEN) {
                type = SYS_RES_MEMORY;
                rid = BT_PCI_MEMADDR;
-               regs = bus_alloc_resource(dev, type, &rid,
-                                         0, ~0, 1, RF_ACTIVE);
+               regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE);
        }
 #else
        if (!regs && (command & PCIM_CMD_PORTEN)) {
                type = SYS_RES_IOPORT;
                rid = BT_PCI_IOADDR;
-               regs = bus_alloc_resource(dev, type, &rid,
-                                         0, ~0, 1, RF_ACTIVE);
+               regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE);
        }
 #endif
        if (!regs)
                return (ENOMEM);
        
        zero = 0;
-       irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero,
-                                0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+       irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero,
+                                    RF_ACTIVE | RF_SHAREABLE);
        if (!irq) {
                bus_release_resource(dev, type, rid, regs);
                return (ENOMEM);
@@ -132,36 +131,28 @@ bt_pci_attach(device_t dev)
 
        /* Allocate a dmatag for our CCB DMA maps */
        /* XXX Should be a child of the PCI bus dma tag */
-       if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0,
-                              /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-                              /*highaddr*/BUS_SPACE_MAXADDR,
-                              /*filter*/NULL, /*filterarg*/NULL,
-                              /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*nsegments*/BUS_SPACE_UNRESTRICTED,
-                              /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
-                              /*flags*/0, &bt->parent_dmat) != 0) {
+       if (bus_dma_tag_create( /* parent       */ NULL,
+                               /* alignemnt    */ 1,
+                               /* boundary     */ 0,
+                               /* lowaddr      */ BUS_SPACE_MAXADDR_32BIT,
+                               /* highaddr     */ BUS_SPACE_MAXADDR,
+                               /* filter       */ NULL,
+                               /* filterarg    */ NULL,
+                               /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* nsegments    */ ~0,
+                               /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
+                               /* flags        */ 0,
+                               &bt->parent_dmat) != 0) {
                bt_pci_release_resources(dev);
                return (ENOMEM);
        }
 
-       /*
-        * Protect ourself from spurrious interrupts during
-        * intialization and attach.  We should really rely
-        * on interrupts during attach, but we don't have
-        * access to our interrupts during ISA probes, so until
-        * that changes, we mask our interrupts during attach
-        * too.
-        */
-       crit_enter();
-
        if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) {
                bt_pci_release_resources(dev);
-               crit_exit();
                return (ENXIO);
        }
 
        error = bt_attach(dev);
-       crit_exit();
 
        if (error) {
                bt_pci_release_resources(dev);
@@ -188,3 +179,4 @@ static driver_t bt_pci_driver = {
 static devclass_t bt_devclass;
 
 DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, NULL, NULL);
+MODULE_DEPEND(bt, pci, 1, 1, 1);
index f3d43bf..683d35e 100644 (file)
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/buslogic/btreg.h,v 1.10.2.2 2001/09/03 02:45:22 peter Exp $
+ * $FreeBSD: src/sys/dev/buslogic/btreg.h,v 1.18 2012/11/17 01:51:40 svnexp Exp $
  */
 
 #ifndef _BTREG_H_
@@ -558,6 +558,7 @@ struct bt_ccb {
        u_int32_t                flags;
        union ccb               *ccb;
        bus_dmamap_t             dmamap;
+       struct callout           timer;
        bt_sg_t                 *sg_list;
        u_int32_t                sg_list_phys;
 };
@@ -575,8 +576,7 @@ struct bt_softc {
        struct resource         *irq;
        struct resource         *drq;
        void                    *ih;
-       bus_space_tag_t          tag;
-       bus_space_handle_t       bsh;
+       struct lock              lock;
        struct  cam_sim         *sim;
        struct  cam_path        *path;
        bt_mbox_out_t           *cur_outbox;
@@ -612,7 +612,6 @@ struct bt_softc {
        u_int                    num_ccbs;      /* Number of CCBs malloc'd */
        u_int                    max_ccbs;      /* Maximum allocatable CCBs */
        u_int                    max_sg;
-       u_int                    unit;
        u_int                    scsi_id;
        u_int32_t                extended_trans    :1,
                                 wide_bus          :1,
@@ -639,8 +638,6 @@ struct bt_softc {
        char                     model[5];
 };
 
-extern u_long bt_unit;
-
 #define BT_TEMP_UNIT 0xFF              /* Unit for probes */
 void                   bt_init_softc(device_t dev,
                                      struct resource *port,
@@ -661,10 +658,10 @@ int                       bt_cmd(struct bt_softc *bt, bt_op_t opcode,
 
 #define bt_name(bt)    device_get_nameunit(bt->dev)
 
-#define bt_inb(bt, port)                               \
-       bus_space_read_1((bt)->tag, (bt)->bsh, port)
+#define bt_inb(bt, reg)                                \
+       bus_read_1((bt)->port, reg)
 
-#define bt_outb(bt, port, value)                       \
-       bus_space_write_1((bt)->tag, (bt)->bsh, port, value)
+#define bt_outb(bt, reg, value)                        \
+       bus_write_1((bt)->port, reg, value)
 
 #endif /* _BT_H_ */