⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ahb.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * CAM SCSI device driver for the Adaptec 174X SCSI Host adapter * * Copyright (c) 1998 Justin T. Gibbs * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice immediately at the beginning of the file, without modification, *    this list of conditions, and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	$Id: ahb.c,v 1.4.2.3 1999/05/07 00:43:40 ken Exp $ */#include "eisa.h"#if NEISA > 0#include <stddef.h>	/* For offsetof() */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/malloc.h>#include <machine/bus_pio.h>#include <machine/bus.h>#include <machine/clock.h>#include <cam/cam.h>#include <cam/cam_ccb.h>#include <cam/cam_sim.h>#include <cam/cam_xpt_sim.h>#include <cam/cam_debug.h>#include <cam/scsi/scsi_message.h>#include <i386/eisa/eisaconf.h>#include <i386/eisa/ahbreg.h>#define ccb_ecb_ptr spriv_ptr0#define ccb_ahb_ptr spriv_ptr1#define MIN(a, b) ((a) < (b) ? (a) : (b))#define ahb_inb(ahb, port)				\	bus_space_read_1((ahb)->tag, (ahb)->bsh, port)#define ahb_inl(ahb, port)				\	bus_space_read_4((ahb)->tag, (ahb)->bsh, port)#define ahb_outb(ahb, port, value)			\	bus_space_write_1((ahb)->tag, (ahb)->bsh, port, value)#define ahb_outl(ahb, port, value)			\	bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value)static const char		*ahbmatch(eisa_id_t type);static int			 ahbprobe(void);static int			 ahbattach(struct eisa_device *dev);static struct ahb_softc		*ahballoc(u_long unit, u_int iobase, u_int irq);static void			 ahbfree(struct ahb_softc *ahb);static int			 ahbreset(struct ahb_softc *ahb);static void			 ahbmapecbs(void *arg, bus_dma_segment_t *segs,					    int nseg, int error);static int			 ahbxptattach(struct ahb_softc *ahb);static void			 ahbhandleimmed(struct ahb_softc *ahb,						u_int32_t mbox, u_int intstat);static void			 ahbcalcresid(struct ahb_softc *ahb,					      struct ecb *ecb, union ccb *ccb);static __inline void		 ahbdone(struct ahb_softc *ahb, u_int32_t mbox,					 u_int intstat);static void			 ahbintr(void *arg);static bus_dmamap_callback_t	 ahbexecuteecb;static void			 ahbaction(struct cam_sim *sim, union ccb *ccb);static void			 ahbpoll(struct cam_sim *sim);/* Our timeout handler */timeout_t ahbtimeout;static __inline struct ecb*	ahbecbget(struct ahb_softc *ahb);static __inline void	 	ahbecbfree(struct ahb_softc* ahb,					   struct ecb* ecb);static __inline u_int32_t	ahbecbvtop(struct ahb_softc *ahb,					   struct ecb *ecb);static __inline struct ecb*	ahbecbptov(struct ahb_softc *ahb,					   u_int32_t ecb_addr);static __inline u_int32_t	ahbstatuspaddr(u_int32_t ecb_paddr);static __inline u_int32_t	ahbsensepaddr(u_int32_t ecb_paddr);static __inline u_int32_t	ahbsgpaddr(u_int32_t ecb_paddr);static __inline void		ahbqueuembox(struct ahb_softc *ahb,					     u_int32_t mboxval,					     u_int attn_code);static __inline struct ecb*ahbecbget(struct ahb_softc *ahb){	struct	ecb* ecb;	int	s;	s = splcam();	if ((ecb = SLIST_FIRST(&ahb->free_ecbs)) != NULL)		SLIST_REMOVE_HEAD(&ahb->free_ecbs, links);	splx(s);	return (ecb);}static __inline voidahbecbfree(struct ahb_softc* ahb, struct ecb* ecb){	int s;	s = splcam();	ecb->state = ECB_FREE;	SLIST_INSERT_HEAD(&ahb->free_ecbs, ecb, links);	splx(s);}static __inline u_int32_tahbecbvtop(struct ahb_softc *ahb, struct ecb *ecb){	return (ahb->ecb_physbase	      + (u_int32_t)((caddr_t)ecb - (caddr_t)ahb->ecb_array));}static __inline struct ecb*ahbecbptov(struct ahb_softc *ahb, u_int32_t ecb_addr){	return (ahb->ecb_array	      + ((struct ecb*)ecb_addr - (struct ecb*)ahb->ecb_physbase));}static __inline u_int32_tahbstatuspaddr(u_int32_t ecb_paddr){	return (ecb_paddr + offsetof(struct ecb, status));}static __inline u_int32_tahbsensepaddr(u_int32_t ecb_paddr){	return (ecb_paddr + offsetof(struct ecb, sense));}static __inline u_int32_tahbsgpaddr(u_int32_t ecb_paddr){	return (ecb_paddr + offsetof(struct ecb, sg_list));}static __inline voidahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code){	u_int loopmax = 300;	while (--loopmax) {		u_int status;		status = ahb_inb(ahb, HOSTSTAT);		if ((status & (HOSTSTAT_MBOX_EMPTY|HOSTSTAT_BUSY))		   == HOSTSTAT_MBOX_EMPTY)			break;		DELAY(20);	}	if (loopmax == 0)		panic("ahb%ld: adapter not taking commands\n", ahb->unit);	ahb_outl(ahb, MBOXOUT0, mboxval);	ahb_outb(ahb, ATTN, attn_code);}static  u_long ahbunit;static struct eisa_driver ahb_eisa_driver ={	"ahb",	ahbprobe,	ahbattach,	/*shutdown*/NULL,	&ahbunit};DATA_SET (eisadriver_set, ahb_eisa_driver);static const char *ahbmatch(eisa_id_t type){                         	switch(type & 0xfffffe00) {		case EISA_DEVICE_ID_ADAPTEC_1740:			return ("Adaptec 174x SCSI host adapter");			break;		default:			break;	}	return (NULL);} static intahbprobe(void)      {       	struct eisa_device *e_dev = NULL;	u_int32_t iobase;	u_int32_t irq;	int count;                      	count = 0;      	while ((e_dev = eisa_match_dev(e_dev, ahbmatch))) {		u_int8_t  intdef;      		iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE) +			 AHB_EISA_SLOT_OFFSET;                        		eisa_add_iospace(e_dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE);				intdef = inb(INTDEF + iobase);		switch (intdef & 0x7) {		case INT9:  			irq = 9;			break;		case INT10: 			irq = 10;			break;		case INT11:			irq = 11;			break;		case INT12:			irq = 12; 			break;		case INT14:	                irq = 14;			break;		case INT15:			irq = 15;			break;		default:		        printf("Adaptec 174X at slot %d: illegal "			       "irq setting %d\n", e_dev->ioconf.slot,			       (intdef & 0x7));			irq = 0;			break;		}               		if (irq == 0)			continue;		eisa_add_intr(e_dev, irq);		eisa_registerdev(e_dev, &ahb_eisa_driver);		count++;        	}               	return count;   }static intahbattach(struct eisa_device *e_dev){	/*	 * find unit and check we have that many defined	 */	struct	    ahb_softc *ahb;	struct	    ecb* next_ecb;	resvaddr_t *iospace;	u_int	    irq;	if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)		return (-1);	irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;	iospace = e_dev->ioconf.ioaddrs.lh_first;	if (iospace == NULL)		return (-1);	eisa_reg_start(e_dev);	if (eisa_reg_iospace(e_dev, iospace)) {		eisa_reg_end(e_dev);		return (-1);	}	if ((ahb = ahballoc(e_dev->unit, iospace->addr, irq)) == NULL) {		eisa_reg_end(e_dev);		return (-1);	}	if (ahbreset(ahb) != 0)		return (-1);	if (eisa_reg_intr(e_dev, irq, ahbintr, (void *)ahb, &cam_imask,			  (ahb_inb(ahb, INTDEF) & INTLEVEL) ? TRUE : FALSE)) {		eisa_reg_end(e_dev);		ahbfree(ahb);		return (-1);	}	/*	 * Create our DMA tags.  These tags define the kinds of device	 * accessable memory allocations and memory mappings we will 	 * need to perform during normal operation.	 */	/* DMA tag for mapping buffers into device visible space. */	/* XXX Should be a child of the EISA bus dma tag */	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       /*maxsize*/MAXBSIZE, /*nsegments*/AHB_NSEG,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/BUS_DMA_ALLOCNOW,			       &ahb->buffer_dmat) != 0)		goto error_exit;	ahb->init_level++;	/* DMA tag for our ccb structures and ha inquiry data */	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       (AHB_NECB * sizeof(struct ecb))			       + sizeof(*ahb->ha_inq_data),			       /*nsegments*/1,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/0, &ahb->ecb_dmat) != 0)		goto error_exit;	ahb->init_level++;	/* Allocation for our ccbs */	if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array,			     BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0)		goto error_exit;	ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB];	ahb->init_level++;	/* And permanently map them */	bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap,			ahb->ecb_array, AHB_NSEG * sizeof(struct ecb),			ahbmapecbs, ahb, /*flags*/0);	ahb->init_level++;	/* Allocate the buffer dmamaps for each of our ECBs */	bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb))	      + sizeof(*ahb->ha_inq_data));	next_ecb = ahb->ecb_array;	while (ahb->num_ecbs < AHB_NECB) {		u_int32_t ecb_paddr;		if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0,				      &next_ecb->dmamap))			break;		ecb_paddr = ahbecbvtop(ahb, next_ecb);		next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr);		next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr);		ahb->num_ecbs++;		ahbecbfree(ahb, next_ecb);		next_ecb++;	}	if (ahb->num_ecbs == 0)		goto error_exit;	ahb->init_level++;	eisa_reg_end(e_dev);	/*	 * Now that we know we own the resources we need, register	 * our bus with the XPT.	 */	if (ahbxptattach(ahb))		goto error_exit;	/* Enable our interrupt */	eisa_enable_intr(e_dev, irq);	return (0);error_exit:	/*	 * The board's IRQ line will not be left enabled	 * if we can't intialize correctly, so its safe	 * to release the irq.	 */	eisa_release_intr(e_dev, irq, ahbintr);	ahbfree(ahb);	return (-1);}static struct ahb_softc *ahballoc(u_long unit,  u_int iobase, u_int irq){	struct	ahb_softc *ahb;	/*	 * Allocate a storage area for us	 */	ahb = malloc(sizeof(struct ahb_softc), M_TEMP, M_NOWAIT);	if (!ahb) {		printf("ahb%ld: cannot malloc!\n", unit);		return (NULL);	}	bzero(ahb, sizeof(struct ahb_softc));	SLIST_INIT(&ahb->free_ecbs);	LIST_INIT(&ahb->pending_ccbs);	ahb->unit = unit;	ahb->tag = I386_BUS_SPACE_IO;	ahb->bsh = iobase;	ahb->disc_permitted = ~0;	ahb->tags_permitted = ~0;	return (ahb);}static void    ahbfree(struct ahb_softc *ahb){	switch (ahb->init_level) {	default:	case 4:		bus_dmamap_unload(ahb->ecb_dmat, ahb->ecb_dmamap);	case 3:		bus_dmamem_free(ahb->ecb_dmat, ahb->ecb_array,				ahb->ecb_dmamap);		bus_dmamap_destroy(ahb->ecb_dmat, ahb->ecb_dmamap);	case 2:		bus_dma_tag_destroy(ahb->ecb_dmat);	case 1:		bus_dma_tag_destroy(ahb->buffer_dmat);	case 0:	}	free(ahb, M_DEVBUF);}/* * reset board, If it doesn't respond, return failure */static int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -