static int
int
static ADW_CCB *adw_get_ccb __P((ADW_SOFTC *, int));static int adw_queue_ccb __P((ADW_SOFTC *, ADW_CCB *, int));static int adw_scsi_cmd __P((struct scsi_xfer *));static int adw_build_req __P((struct scsi_xfer *, ADW_CCB *, int));static void adw_build_sglist __P((ADW_CCB *, ADW_SCSI_REQ_Q *, ADW_SG_BLOCK *));static void adwminphys __P((struct buf *));static void adw_isr_callback __P((ADW_SOFTC *, ADW_SCSI_REQ_Q *));static void adw_async_callback __P((ADW_SOFTC *, u_int8_t));static void adw_print_info __P((ADW_SOFTC *, int));static int adw_poll __P((ADW_SOFTC *, struct scsi_xfer *, int));static void adw_timeout __P((void *));static void adw_reset_bus __P((ADW_SOFTC *));/******************************************************************************/struct cfdriver adw_cd = {	NULL, "adw", DV_DULL};/* the below structure is so we have a default dev struct for our link struct */struct scsi_device adw_dev ={	NULL,			/* Use default error handler */	NULL,			/* have a queue, served by this */	NULL,			/* have no async handler */	NULL,			/* Use default 'done' routine */};/******************************************************************************//* scsi_xfer queue routines                                                   *//******************************************************************************//* * Insert a scsi_xfer into the software queue.  We overload xs->free_list * to avoid having to allocate additional resources (since we're used * only during resource shortages anyhow. */static voidadw_enqueue(sc, xs, infront)	ADW_SOFTC      *sc;	struct scsi_xfer *xs;	int             infront;{	if (infront || sc->sc_queue.lh_first == NULL) {		if (sc->sc_queue.lh_first == NULL)			sc->sc_queuelast = xs;		LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);		return;	}	LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);	sc->sc_queuelast = xs;}/* * Pull a scsi_xfer off the front of the software queue. */static struct scsi_xfer *adw_dequeue(sc)	ADW_SOFTC      *sc;{	struct scsi_xfer *xs;	xs = sc->sc_queue.lh_first;	LIST_REMOVE(xs, free_list);	if (sc->sc_queue.lh_first == NULL)		sc->sc_queuelast = NULL;	return (xs);}/******************************************************************************//*                       DMA Mapping for Control Blocks                       *//******************************************************************************/static intadw_alloc_controls(sc)	ADW_SOFTC      *sc;{	bus_dma_segment_t seg;	int             error, rseg;	/*         * Allocate the control structure.         */	if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct adw_control),			   NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to allocate control structures,"		       " error = %d\n", sc->sc_dev.dv_xname, error);		return (error);	}	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,		   sizeof(struct adw_control), (caddr_t *) & sc->sc_control,				 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {		printf("%s: unable to map control structures, error = %d\n",		       sc->sc_dev.dv_xname, error);		return (error);	}	/*         * Create and load the DMA map used for the control blocks.         */	if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct adw_control),			   1, sizeof(struct adw_control), 0, BUS_DMA_NOWAIT,				       &sc->sc_dmamap_control)) != 0) {		printf("%s: unable to create control DMA map, error = %d\n",		       sc->sc_dev.dv_xname, error);		return (error);	}	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,			   sc->sc_control, sizeof(struct adw_control), NULL,				     BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to load control DMA map, error = %d\n",		       sc->sc_dev.dv_xname, error);		return (error);	}	return (0);}static intadw_alloc_carriers(sc)	ADW_SOFTC      *sc;{	bus_dma_segment_t seg;	int             error, rseg;	/*         * Allocate the control structure.         */	sc->sc_control->carriers = 		malloc(sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, M_DEVBUF, 		       M_NOWAIT);	if (sc->sc_control->carriers == NULL)		return (ENOMEM);	if ((error = bus_dmamem_alloc(sc->sc_dmat,			sizeof(ADW_CARRIER) * ADW_MAX_CARRIER,			0x10, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to allocate carrier structures,"		       " error = %d\n", sc->sc_dev.dv_xname, error);		return (error);	}	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,			sizeof(ADW_CARRIER) * ADW_MAX_CARRIER,			(caddr_t *) &sc->sc_control->carriers,			BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {		printf("%s: unable to map carrier structures,"			" error = %d\n", sc->sc_dev.dv_xname, error);		return (error);	}	/*         * Create and load the DMA map used for the control blocks.         */	if ((error = bus_dmamap_create(sc->sc_dmat,			sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 1,			sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, 0,BUS_DMA_NOWAIT,			&sc->sc_dmamap_carrier)) != 0) {		printf("%s: unable to create carriers DMA map,"			" error = %d\n", sc->sc_dev.dv_xname, error);		return (error);	}	if ((error = bus_dmamap_load(sc->sc_dmat,			sc->sc_dmamap_carrier, sc->sc_control->carriers,			sizeof(ADW_CARRIER) * ADW_MAX_CARRIER, NULL,			BUS_DMA_NOWAIT)) != 0) {		printf("%s: unable to load carriers DMA map,"			" error = %d\n", sc->sc_dev.dv_xname, error);		return (error);	}	return (0);}/******************************************************************************//*                           Control Blocks routines                          *//******************************************************************************//* * Create a set of ccbs and add them to the free list.  Called once * by adw_init().  We return the number of CCBs successfully created. */static intadw_create_ccbs(sc, ccbstore, count)	ADW_SOFTC      *sc;	ADW_CCB        *ccbstore;	int             count;{	ADW_CCB        *ccb;	int             i, error;	for (i = 0; i < count; i++) {		ccb = &ccbstore[i];		if ((error = adw_init_ccb(sc, ccb)) != 0) {			printf("%s: unable to initialize ccb, error = %d\n",			       sc->sc_dev.dv_xname, error);			return (i);		}		TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);	}	return (i);}/* * A ccb is put onto the free list. */static voidadw_free_ccb(sc, ccb)	ADW_SOFTC      *sc;	ADW_CCB        *ccb;{	int             s;	s = splbio();	adw_reset_ccb(ccb);	TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);	/*         * If there were none, wake anybody waiting for one to come free,         * starting with queued entries.         */	if (ccb->chain.tqe_next == 0)		wakeup(&sc->sc_free_ccb);	splx(s);}static voidadw_reset_ccb(ccb)	ADW_CCB        *ccb;{	ccb->flags = 0;}static intadw_init_ccb(sc, ccb)	ADW_SOFTC      *sc;	ADW_CCB        *ccb;{	int	hashnum, error;	/*         * Create the DMA map for this CCB.         */	error = bus_dmamap_create(sc->sc_dmat,				  (ADW_MAX_SG_LIST - 1) * PAGE_SIZE,			 ADW_MAX_SG_LIST, (ADW_MAX_SG_LIST - 1) * PAGE_SIZE,		   0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer);	if (error) {		printf("%s: unable to create CCB DMA map, error = %d\n",		       sc->sc_dev.dv_xname, error);		return (error);	}	/*	 * put in the phystokv hash table	 * Never gets taken out.	 */	ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +	    ADW_CCB_OFF(ccb);	hashnum = CCB_HASH(ccb->hashkey);	ccb->nexthash = sc->sc_ccbhash[hashnum];	sc->sc_ccbhash[hashnum] = ccb;	adw_reset_ccb(ccb);	return (0);}/* * Get a free ccb * * If there are none, see if we can allocate a new one */static ADW_CCB *adw_get_ccb(sc, flags)	ADW_SOFTC      *sc;	int             flags;{	ADW_CCB        *ccb = 0;	int             s;	s = splbio();	/*         * If we can and have to, sleep waiting for one to come free         * but only if we can't allocate a new one.         */	for (;;) {		ccb = sc->sc_free_ccb.tqh_first;		if (ccb) {			TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);			break;		}		if ((flags & SCSI_NOSLEEP) != 0)			goto out;		tsleep(&sc->sc_free_ccb, PRIBIO, "adwccb", 0);	}	ccb->flags |= CCB_ALLOC;out:	splx(s);	return (ccb);}