Exemple #1
0
/********************************************************************************
 * Bring the controller down to a dormant state and detach all child devices.
 *
 * Note that we can assume that the bioq on the controller is empty, as we won't
 * allow shutdown if any device is open.
 */
static int
twe_shutdown(device_t dev)
{
    struct twe_softc	*sc = device_get_softc(dev);
    int			i, error = 0;

    debug_called(4);

    /* 
     * Delete all our child devices.
     */
    TWE_CONFIG_LOCK(sc);
    for (i = 0; i < TWE_MAX_UNITS; i++) {
	if (sc->twe_drive[i].td_disk != 0) {
	    if ((error = twe_detach_drive(sc, i)) != 0) {
		TWE_CONFIG_UNLOCK(sc);
		return (error);
	    }
	}
    }
    TWE_CONFIG_UNLOCK(sc);

    /*
     * Bring the controller down.
     */
    TWE_IO_LOCK(sc);
    twe_deinit(sc);
    TWE_IO_UNLOCK(sc);

    return(0);
}
Exemple #2
0
/********************************************************************************
 * Handle an I/O request.
 */
static void
twed_strategy(struct bio *bp)
{
    struct twed_softc	*sc = bp->bio_disk->d_drv1;

    debug_called(4);

    bp->bio_driver1 = &sc->twed_drive->td_twe_unit;
    TWED_BIO_IN;

    /* bogus disk? */
    if (sc == NULL || sc->twed_drive->td_disk == NULL) {
	bp->bio_error = EINVAL;
	bp->bio_flags |= BIO_ERROR;
	printf("twe: bio for invalid disk!\n");
	biodone(bp);
	TWED_BIO_OUT;
	return;
    }

    /* queue the bio on the controller */
    TWE_IO_LOCK(sc->twed_controller);
    twe_enqueue_bio(sc->twed_controller, bp);

    /* poke the controller to start I/O */
    twe_startio(sc->twed_controller);
    TWE_IO_UNLOCK(sc->twed_controller);
    return;
}
Exemple #3
0
/********************************************************************************
 * Disconnect from the controller completely, in preparation for unload.
 */
static int
twe_detach(device_t dev)
{
    struct twe_softc	*sc = device_get_softc(dev);

    debug_called(4);

    TWE_IO_LOCK(sc);
    if (sc->twe_state & TWE_STATE_OPEN) {
	TWE_IO_UNLOCK(sc);
	return (EBUSY);
    }
    sc->twe_state |= TWE_STATE_DETACHING;
    TWE_IO_UNLOCK(sc);

    /*	
     * Shut the controller down.
     */
    if (twe_shutdown(dev)) {
	TWE_IO_LOCK(sc);
	sc->twe_state &= ~TWE_STATE_DETACHING;
	TWE_IO_UNLOCK(sc);
	return (EBUSY);
    }

    twe_free(sc);

    return(0);
}
Exemple #4
0
/********************************************************************************
 * Handle an I/O request.
 */
static void
twed_strategy(twe_bio *bp)
{
    struct twed_softc	*sc = (struct twed_softc *)TWE_BIO_SOFTC(bp);

    debug_called(4);

    TWED_BIO_IN;

    /* bogus disk? */
    if (sc == NULL) {
	TWE_BIO_SET_ERROR(bp, EINVAL);
	printf("twe: bio for invalid disk!\n");
	TWE_BIO_DONE(bp);
	TWED_BIO_OUT;
	return;
    }

    /* perform accounting */
    TWE_BIO_STATS_START(bp);

    /* queue the bio on the controller */
    twe_enqueue_bio(sc->twed_controller, bp);

    /* poke the controller to start I/O */
    twe_startio(sc->twed_controller);
    return;
}
Exemple #5
0
/********************************************************************************
 * Detach from CAM
 */
void
mly_cam_detach(struct mly_softc *sc)
{
    int		chn, nchn, first;

    debug_called(1);

    nchn = sc->mly_controllerinfo->physical_channels_present +
	sc->mly_controllerinfo->virtual_channels_present;

    /*
     * Iterate over channels, deregistering as we go.
     */
    nchn = sc->mly_controllerinfo->physical_channels_present +
	sc->mly_controllerinfo->virtual_channels_present;
    for (chn = 0, first = 1; chn < nchn; chn++) {

	/*
	 * If a sim was registered for this channel, free it.
	 */
	if (sc->mly_cam_sim[chn] != NULL) {
	    debug(1, "deregister bus %d", chn);
	    xpt_bus_deregister(cam_sim_path(sc->mly_cam_sim[chn]));
	    debug(1, "free sim for channel %d (%sfree queue)", chn, first ? "" : "don't ");
	    cam_sim_free(sc->mly_cam_sim[chn], first ? TRUE : FALSE);
	    first = 0;
	}
    }
}
Exemple #6
0
/*
 * Read/write routine for a buffer.  Finds the proper unit, range checks
 * arguments, and schedules the transfer.  Does not wait for the transfer
 * to complete.  Multi-page transfers are supported.  All I/O requests must
 * be a multiple of a sector in length.
 */
static void
mlxd_strategy(struct bio *bp)
{
    struct mlxd_softc	*sc = bp->bio_disk->d_drv1;

    debug_called(1);

    /* bogus disk? */
    if (sc == NULL) {
        bp->bio_error = EINVAL;
        bp->bio_flags |= BIO_ERROR;
        goto bad;
    }

    /* XXX may only be temporarily offline - sleep? */
    MLX_IO_LOCK(sc->mlxd_controller);
    if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) {
        MLX_IO_UNLOCK(sc->mlxd_controller);
        bp->bio_error = ENXIO;
        bp->bio_flags |= BIO_ERROR;
        goto bad;
    }

    mlx_submit_buf(sc->mlxd_controller, bp);
    MLX_IO_UNLOCK(sc->mlxd_controller);
    return;

bad:
    /*
     * Correctly set the bio to indicate a failed tranfer.
     */
    bp->bio_resid = bp->bio_bcount;
    biodone(bp);
    return;
}
Exemple #7
0
/********************************************************************************
 * Bring the controller down to a dormant state and detach all child devices.
 *
 * Note that we can assume that the bioq on the controller is empty, as we won't
 * allow shutdown if any device is open.
 */
static int
twe_shutdown(device_t dev)
{
    struct twe_softc	*sc = device_get_softc(dev);
    int			i, s, error;

    debug_called(4);

    s = splbio();
    error = 0;

    /* 
     * Delete all our child devices.
     */
    for (i = 0; i < TWE_MAX_UNITS; i++) {
	if (sc->twe_drive[i].td_disk != 0) {
	    if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[i].td_disk)) != 0)
		goto out;
	    sc->twe_drive[i].td_disk = 0;
	}
    }

    /*
     * Bring the controller down.
     */
    twe_deinit(sc);

 out:
    splx(s);
    return(error);
}
Exemple #8
0
/********************************************************************************
 * Bring the controller down to a dormant state and detach all child devices.
 *
 * This function is called before detach, system shutdown, or before performing
 * an operation which may add or delete system disks.  (Call amr_startup to
 * resume normal operation.)
 *
 * Note that we can assume that the bioq on the controller is empty, as we won't
 * allow shutdown if any device is open.
 */
static int
amr_pci_shutdown(device_t dev)
{
    struct amr_softc	*sc = device_get_softc(dev);
    int			i,error;

    debug_called(1);

    /* mark ourselves as in-shutdown */
    sc->amr_state |= AMR_STATE_SHUTDOWN;


    /* flush controller */
    device_printf(sc->amr_dev, "flushing cache...");
    printf("%s\n", amr_flush(sc) ? "failed" : "done");

    error = 0;

    /* delete all our child devices */
    for(i = 0 ; i < AMR_MAXLD; i++) {
	if( sc->amr_drive[i].al_disk != 0) {
	    if((error = device_delete_child(sc->amr_dev,sc->amr_drive[i].al_disk)) != 0)
		goto shutdown_out;
	    sc->amr_drive[i].al_disk = 0;
	}
    }

    /* XXX disable interrupts? */

shutdown_out:
    return(error);
}
Exemple #9
0
/********************************************************************************
 * Free all of the resources associated with (sc).
 *
 * Should not be called if the controller is active.
 */
static void
twe_free(struct twe_softc *sc)
{
    struct twe_request	*tr;

    debug_called(4);

    /* throw away any command buffers */
    while ((tr = twe_dequeue_free(sc)) != NULL)
	twe_free_request(tr);

    /* destroy the data-transfer DMA tag */
    if (sc->twe_buffer_dmat)
	bus_dma_tag_destroy(sc->twe_buffer_dmat);

    /* disconnect the interrupt handler */
    if (sc->twe_intr)
	bus_teardown_intr(sc->twe_dev, sc->twe_irq, sc->twe_intr);
    if (sc->twe_irq != NULL)
	bus_release_resource(sc->twe_dev, SYS_RES_IRQ, 0, sc->twe_irq);

    /* destroy the parent DMA tag */
    if (sc->twe_parent_dmat)
	bus_dma_tag_destroy(sc->twe_parent_dmat);

    /* release the register window mapping */
    if (sc->twe_io != NULL)
	bus_release_resource(sc->twe_dev, SYS_RES_IOPORT, TWE_IO_CONFIG_REG, sc->twe_io);

    /* destroy control device */
    if (sc->twe_dev_t != (dev_t)NULL)
	destroy_dev(sc->twe_dev_t);
}
Exemple #10
0
/********************************************************************************
 * Disconnect from the controller completely, in preparation for unload.
 */
static int
twe_detach(device_t dev)
{
    struct twe_softc	*sc = device_get_softc(dev);
    int			s, error;

    debug_called(4);

    error = EBUSY;
    s = splbio();
    if (sc->twe_state & TWE_STATE_OPEN)
	goto out;

    /*	
     * Shut the controller down.
     */
    if ((error = twe_shutdown(dev)))
	goto out;

    twe_free(sc);

    error = 0;
 out:
    splx(s);
    return(error);
}
Exemple #11
0
static void
_inq(struct cam_sim *sim, union ccb *ccb)
{
     struct ccb_pathinq *cpi = &ccb->cpi;
     isc_session_t *sp = cam_sim_softc(sim);

     debug_called(8);
     debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun);

     cpi->version_num = 1; /* XXX??? */
     cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
     cpi->target_sprt = 0;
     cpi->hba_misc = 0;
     cpi->hba_eng_cnt = 0;
     cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1;
     cpi->initiator_id = ISCSI_MAX_TARGETS;
     cpi->max_lun = sp->opt.maxluns - 1;
     cpi->bus_id = cam_sim_bus(sim);
     cpi->base_transfer_speed = 3300; // 40000; // XXX:
     strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
     strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
     strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
     cpi->unit_number = cam_sim_unit(sim);
     cpi->ccb_h.status = CAM_REQ_CMP;
#if defined(KNOB_VALID_ADDRESS)
     cpi->transport = XPORT_ISCSI;
     cpi->transport_version = 0;
#endif
}
Exemple #12
0
/*
 | this is a kludge,
 | the jury is not back with a veredict, user or kernel
 */
static void
_nop_out(isc_session_t *sp)
{
     pduq_t	*pq;
     nop_out_t	*nop_out;

     debug_called(8);

     sdebug(4, "cws=%d", sp->cws);
     if(sp->cws == 0) {
	  /*
	   | only send a nop if window is closed.
	   */
	  if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
	       // I guess we ran out of resources
	       return;
	  nop_out = &pq->pdu.ipdu.nop_out;
	  nop_out->opcode = ISCSI_NOP_OUT;
	  nop_out->itt = htonl(sp->sn.itt);
	  nop_out->ttt = -1;
	  nop_out->I = 1;
	  nop_out->F = 1;
	  if(isc_qout(sp, pq) != 0) {
	       sdebug(1, "failed");
	       pdu_free(sp->isc, pq);
	  }
     }
}
Exemple #13
0
static int
ic_scan(isc_session_t *sp)
{
     union ccb	*ccb;

     debug_called(8);
     sdebug(2, "scanning sid=%d", sp->sid);

     sp->flags &= ~ISC_CAMDEVS;
     sp->flags |= ISC_SCANWAIT;

     ccb = xpt_alloc_ccb();
     ccb->ccb_h.path		= sp->cam_path;
     ccb->ccb_h.cbfcnp		= scan_callback;
     ccb->ccb_h.spriv_ptr0	= sp;

     xpt_rescan(ccb);

     while(sp->flags & ISC_SCANWAIT)
	  tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should
					    // be configurable
     sdebug(2, "# of luns=%d", sp->target_nluns);

     if(sp->target_nluns > 0) {
	  sp->flags |= ISC_CAMDEVS;
	  return 0;
     }

     return ENODEV;
}
Exemple #14
0
static int
chapSHA1(char id, char *cp, char *chapSecret, unsigned char *digest)
{
     SHA1_CTX	ctx;
     char	*tmp;
     int	len;

     debug_called(3);

     SHA1_Init(&ctx);
     
     SHA1_Update(&ctx, &id, 1);

     if((len = str2bin(chapSecret, &tmp)) == 0) {
	  // print error
	  return -1;
     }
     SHA1_Update(&ctx, tmp, len);
     free(tmp);

     if((len = str2bin(cp, &tmp)) == 0) {
	  // print error
	  return -1;
     }
     SHA1_Update(&ctx, tmp, len);
     free(tmp);

     SHA1_Final(digest, &ctx);

     return 0;
    
}
/*
 * Read/write routine for a buffer.  Finds the proper unit, range checks
 * arguments, and schedules the transfer.  Does not wait for the transfer
 * to complete.  Multi-page transfers are supported.  All I/O requests must
 * be a multiple of a sector in length.
 */
static void
mlxd_strategy(mlx_bio *bp)
{
    struct mlxd_softc	*sc = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);

    debug_called(1);

    /* bogus disk? */
    if (sc == NULL) {
	MLX_BIO_SET_ERROR(bp, EINVAL);
	goto bad;
    }

    /* XXX may only be temporarily offline - sleep? */
    if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) {
	MLX_BIO_SET_ERROR(bp, ENXIO);
	goto bad;
    }

    MLX_BIO_STATS_START(bp);
    mlx_submit_buf(sc->mlxd_controller, bp);
    return;

 bad:
    /*
     * Correctly set the bio to indicate a failed tranfer.
     */
    MLX_BIO_RESID(bp) = MLX_BIO_LENGTH(bp);
    MLX_BIO_DONE(bp);
    return;
}
Exemple #16
0
static void
_reject(isc_session_t *sp, pduq_t *pq)
{
     pduq_t	*opq;
     pdu_t	*pdu;
     reject_t	*reject;
     int	itt;

     debug_called(8);
     pdu = mtod(pq->mp, pdu_t *);
     itt = pdu->ipdu.bhs.itt;
     reject = &pq->pdu.ipdu.reject;
     sdebug(2, "itt=%x reason=0x%x", ntohl(itt), reject->reason);
     opq = i_search_hld(sp, itt, 0);
     if(opq != NULL)
	  iscsi_reject(sp, opq, pq);
     else {
	  switch(pq->pdu.ipdu.bhs.opcode) {
	  case ISCSI_LOGOUT_CMD: // XXX: wasabi does this - can't figure out why
	       sdebug(2, "ISCSI_LOGOUT_CMD ...");
	       break;
	  default:
	       xdebug("%d] we lost something itt=%x",
		      sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
	  }
     }
     pdu_free(sp->isc, pq);
}
Exemple #17
0
static trans_t
doLogin(isess_t *sess)
{
     isc_opt_t	*op = sess->op;
     int	status, count;

     debug_called(3);

     if(op->chapSecret == NULL && op->tgtChapSecret == NULL)
	  /*
	   | don't need any security negotiation
	   | or in other words: we don't have any secrets to exchange
	   */
	  sess->csg = LON_PHASE;
     else
	  sess->csg = SN_PHASE;

     if(sess->tsih) {
	  sess->tsih = 0;	// XXX: no 'reconnect' yet
	  sess->flags &= ~SESS_NEGODONE; // XXX: KLUDGE
     }
     count = 10; // should be more than enough
     do {
	  debug(3, "count=%d csg=%d", count, sess->csg);
	  status = loginPhase(sess);
	  if(count-- == 0)
	       // just in case we get into a loop
	       status = -1;
     } while(status == 0 && (sess->csg != FF_PHASE));

     sess->flags &= ~SESS_INITIALLOGIN;
     debug(3, "status=%d", status);

     switch(status) {
     case 0: // all is ok ...
	  sess->flags |= SESS_LOGGEDIN;
	  if(strcmp(sess->op->sessionType, "Discovery") == 0)
	       doDiscovery(sess);
	  return T5;

     case 1:	// redirect - temporary/permanent
	  /*
	   | start from scratch?
	   */
	  sess->flags &= ~SESS_NEGODONE;
	  sess->flags |= (SESS_REDIRECT | SESS_INITIALLOGIN1);
	  syslog(LOG_DEBUG, "target sent REDIRECT");
	  return T7;

     case 2: // initiator terminal error
	  return 0;
     case 3: // target terminal error -- could retry ...
	  sleep(5);
	  return T7; // lets try
     default:
	  return 0;
     }
}
Exemple #18
0
int
ic_init(isc_session_t *sp)
{
     struct cam_sim	*sim;
     struct cam_devq	*devq;

     debug_called(8);

     if((devq = cam_simq_alloc(256)) == NULL)
	  return ENOMEM;

#if __FreeBSD_version >= 700000
     mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF);
#else
     isp->cam_mtx = Giant;
#endif
     sim = cam_sim_alloc(ic_action,
			 ic_poll,
			 "iscsi",
			 sp,
			 sp->sid,	// unit
#if __FreeBSD_version >= 700000
			 &sp->cam_mtx,
#endif
			 1,		// max_dev_transactions
			 0,		// max_tagged_dev_transactions
			 devq);
     if(sim == NULL) {
	  cam_simq_free(devq);
#if __FreeBSD_version >= 700000
	  mtx_destroy(&sp->cam_mtx);
#endif
	  return ENXIO;
     }

     CAM_LOCK(sp);
     if(xpt_bus_register(sim,
#if __FreeBSD_version >= 700000
			 NULL,
#endif
			 0/*bus_number*/) != CAM_SUCCESS) {

	  cam_sim_free(sim, /*free_devq*/TRUE);
	  CAM_UNLOCK(sp);
#if __FreeBSD_version >= 700000
	  mtx_destroy(&sp->cam_mtx);
#endif
	  return ENXIO;
     }
     sp->cam_sim = sim;
     CAM_UNLOCK(sp);

     sdebug(1, "cam subsystem initialized");

     ic_scan(sp);

     return 0;
}
Exemple #19
0
/********************************************************************************
 * Check for possibly-completed commands.
 */
static void
mly_cam_poll(struct cam_sim *sim)
{
    struct mly_softc	*sc = cam_sim_softc(sim);

    debug_called(2);

    mly_done(sc);
}
Exemple #20
0
static int
mlxd_probe(device_t dev)
{

    debug_called(1);

    device_set_desc(dev, "Mylex System Drive");
    return (0);
}
Exemple #21
0
static void
_async(isc_session_t *sp, pduq_t *pq)
{
     debug_called(8);

     iscsi_async(sp, pq);

     pdu_free(sp->isc, pq);
}
Exemple #22
0
/********************************************************************************
 * Save the physical address of the memory mailbox 
 */
static void
mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
    struct mly_softc	*sc = (struct mly_softc *)arg;

    debug_called(2);

    sc->mly_mmbox_busaddr = segs->ds_addr;
}
Exemple #23
0
static int
handleLoginResp(isess_t *sess, pdu_t *pp)
{
    login_rsp_t *lp = (login_rsp_t *)pp;
    uint	st_class, status = ntohs(lp->status);

    debug_called(3);
    debug(4, "Tbit=%d csg=%d nsg=%d status=%x", lp->T, lp->CSG, lp->NSG, status);

    st_class  = status >> 8;
    if(status) {
        int	st_detail = status & 0xff;

        switch(st_class) {
        case 1: // Redirect
            switch(st_detail) {
            // the ITN (iSCSI target Name) requests a:
            case 1: // temporary address change
            case 2: // permanent address change
                status = 0;
            }
            break;

        case 2: // Initiator Error
            if(st_detail < CLASS1_ERRS)
                printf("0x%04x: %s\n", status, status_class1[st_detail]);
            break;

        case 3:
            if(st_detail < CLASS3_ERRS)
                printf("0x%04x: %s\n", status, status_class3[st_detail]);
            break;
        }
    }

    if(status == 0) {
        processParams(sess, pp);
        setOptions(sess, 0); // XXX: just in case ...

        if(lp->T) {
            isc_opt_t	*op = sess->op;

            if(sess->csg == SN_PHASE && (op->tgtChapDigest != NULL))
                if(handleTgtResp(sess, pp) != 0)
                    return 1; // XXX: Authentication failure ...
            sess->csg = lp->NSG;
            if(sess->csg == FF_PHASE) {
                // XXX: will need this when implementing reconnect.
                sess->tsih = lp->tsih;
                debug(2, "TSIH=%x", sess->tsih);
            }
        }
    }

    return st_class;
}
Exemple #24
0
/********************************************************************************
 * Free all of the resources associated with (sc)
 *
 * Should not be called if the controller is active.
 */
static void
amr_pci_free(struct amr_softc *sc)
{
    void *p;

    debug_called(1);

    amr_free(sc);

    /* destroy data-transfer DMA tag */
    if (sc->amr_buffer_dmat)
	bus_dma_tag_destroy(sc->amr_buffer_dmat);
    if (sc->amr_buffer64_dmat)
	bus_dma_tag_destroy(sc->amr_buffer64_dmat);

    /* free and destroy DMA memory and tag for passthrough pool */
    if (sc->amr_ccb) {
	bus_dmamap_unload(sc->amr_ccb_dmat, sc->amr_ccb_dmamap);
	bus_dmamem_free(sc->amr_ccb_dmat, sc->amr_ccb, sc->amr_ccb_dmamap);
    }
    if (sc->amr_ccb_dmat)
	bus_dma_tag_destroy(sc->amr_ccb_dmat);

    /* free and destroy DMA memory and tag for s/g lists */
    if (sc->amr_sgtable) {
	bus_dmamap_unload(sc->amr_sg_dmat, sc->amr_sg_dmamap);
	bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap);
    }
    if (sc->amr_sg_dmat)
	bus_dma_tag_destroy(sc->amr_sg_dmat);

    /* free and destroy DMA memory and tag for mailbox */
    p = (void *)(uintptr_t)(volatile void *)sc->amr_mailbox64;
    if (sc->amr_mailbox) {
	bus_dmamap_unload(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap);
	bus_dmamem_free(sc->amr_mailbox_dmat, p, sc->amr_mailbox_dmamap);
    }
    if (sc->amr_mailbox_dmat)
	bus_dma_tag_destroy(sc->amr_mailbox_dmat);

    /* disconnect the interrupt handler */
    if (sc->amr_intr)
	bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr);
    if (sc->amr_irq != NULL)
	bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq);

    /* destroy the parent DMA tag */
    if (sc->amr_parent_dmat)
	bus_dma_tag_destroy(sc->amr_parent_dmat);

    /* release the register window mapping */
    if (sc->amr_reg != NULL)
	bus_release_resource(sc->amr_dev,
			     AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT,
			     PCIR_BAR(0), sc->amr_reg);
}
Exemple #25
0
/********************************************************************************
 * Free all of the resources associated with (sc)
 *
 * Should not be called if the controller is active.
 */
void
mly_free(struct mly_softc *sc)
{
    struct mly_command_cluster	*mcc;

    debug_called(1);

    /* detach from CAM */
    mly_cam_detach(sc);

    /* throw away any command buffers */
    while ((mcc = mly_dequeue_cluster(sc)) != NULL)
	mly_free_command_cluster(mcc);

    /* throw away the controllerinfo structure */
    if (sc->mly_controllerinfo != NULL)
	free(sc->mly_controllerinfo, M_DEVBUF);

    /* throw away the controllerparam structure */
    if (sc->mly_controllerparam != NULL)
	free(sc->mly_controllerparam, M_DEVBUF);

    /* destroy data-transfer DMA tag */
    if (sc->mly_buffer_dmat)
	bus_dma_tag_destroy(sc->mly_buffer_dmat);

    /* free and destroy DMA memory and tag for s/g lists */
    if (sc->mly_sg_table) {
	bus_dmamap_unload(sc->mly_sg_dmat, sc->mly_sg_dmamap);
	bus_dmamem_free(sc->mly_sg_dmat, sc->mly_sg_table, sc->mly_sg_dmamap);
    }
    if (sc->mly_sg_dmat)
	bus_dma_tag_destroy(sc->mly_sg_dmat);

    /* free and destroy DMA memory and tag for memory mailbox */
    if (sc->mly_mmbox) {
	bus_dmamap_unload(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap);
	bus_dmamem_free(sc->mly_mmbox_dmat, sc->mly_mmbox, sc->mly_mmbox_dmamap);
    }
    if (sc->mly_mmbox_dmat)
	bus_dma_tag_destroy(sc->mly_mmbox_dmat);

    /* disconnect the interrupt handler */
    if (sc->mly_intr)
	bus_teardown_intr(sc->mly_dev, sc->mly_irq, sc->mly_intr);
    if (sc->mly_irq != NULL)
	bus_release_resource(sc->mly_dev, SYS_RES_IRQ, sc->mly_irq_rid, sc->mly_irq);

    /* destroy the parent DMA tag */
    if (sc->mly_parent_dmat)
	bus_dma_tag_destroy(sc->mly_parent_dmat);

    /* release the register window mapping */
    if (sc->mly_regs_resource != NULL)
	bus_release_resource(sc->mly_dev, SYS_RES_MEMORY, sc->mly_regs_rid, sc->mly_regs_resource);
}
Exemple #26
0
/********************************************************************************
 * Save the physical address of the base of the s/g table.
 */
static void
mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
    struct mly_softc	*sc = (struct mly_softc *)arg;

    debug_called(2);

    /* save base of s/g table's address in bus space */
    sc->mly_sg_busaddr = segs->ds_addr;
}
Exemple #27
0
/*******************************************************************************
 * Take an interrupt, or be poked by other code to look for interrupt-worthy
 * status.
 */
static void
amr_pci_intr(void *arg)
{
    struct amr_softc	*sc = (struct amr_softc *)arg;

    debug_called(3);

    /* collect finished commands, queue anything waiting */
    amr_done(sc);
}
Exemple #28
0
/********************************************************************************
 * Bring the controller down to a dormant state and detach all child devices.
 *
 * This function is called before detach or system shutdown.
 *
 * Note that we can assume that the camq on the controller is empty, as we won't
 * allow shutdown if any device is open.
 */
static int
mly_pci_shutdown(device_t dev)
{
    struct mly_softc	*sc = device_get_softc(dev);

    debug_called(1);

    mly_detach(sc);
    return(0);
}
Exemple #29
0
/********************************************************************************
 * Allocate and map the scatter/gather table in bus space.
 */
static void
amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
    uint32_t *addr;

    debug_called(1);

    addr = arg;
    *addr = segs[0].ds_addr;
}
Exemple #30
0
/********************************************************************************
 * Bring the controller back to a state ready for operation.
 */
static int
mly_pci_resume(device_t dev)
{
    struct mly_softc	*sc = device_get_softc(dev);

    debug_called(1);
    sc->mly_state &= ~MLY_STATE_SUSPEND;
    MLY_UNMASK_INTERRUPTS(sc);
    return(0);
}