u_int lun, int alloc) 
u_int lun) 
static aic_option_callback_t ahc_linux_setup_tag_info;static int  aic7xxx_setup(char *s);static int  ahc_linux_next_unit(void);/********************************* Inlines ************************************/static __inline struct ahc_linux_device*		     ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,					  u_int target, u_int lun, int alloc);static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,		 		      struct ahc_dma_seg *sg,				      dma_addr_t addr, bus_size_t len);static __inline struct ahc_linux_device*ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,		     u_int lun, int alloc){	struct ahc_linux_target *targ;	struct ahc_linux_device *dev;	u_int target_offset;	target_offset = target;	if (channel != 0)		target_offset += 8;	targ = ahc->platform_data->targets[target_offset];	if (targ == NULL) {		if (alloc != 0) {			targ = ahc_linux_alloc_target(ahc, channel, target);			if (targ == NULL)				return (NULL);		} else			return (NULL);	}	dev = targ->devices[lun];	if (dev == NULL && alloc != 0)		dev = ahc_linux_alloc_device(ahc, targ, lun);	return (dev);}static __inline voidahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb){	struct scsi_cmnd *cmd;	cmd = scb->io_ctx;	ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);	if (cmd->use_sg != 0) {		struct scatterlist *sg;		sg = (struct scatterlist *)cmd->request_buffer;		pci_unmap_sg(ahc->dev_softc, sg, cmd->use_sg,			     cmd->sc_data_direction);	} else if (cmd->request_bufflen != 0) {		pci_unmap_single(ahc->dev_softc,				 scb->platform_data->buf_busaddr,				 cmd->request_bufflen,				 cmd->sc_data_direction);	}}static __inline intahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,		  struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len){	int	 consumed;	if ((scb->sg_count + 1) > AHC_NSEG)		panic("Too few segs for dma mapping.  "		      "Increase AHC_NSEG\n");	consumed = 1;	sg->addr = ahc_htole32(addr & 0xFFFFFFFF);	scb->platform_data->xfer_len += len;	if (sizeof(dma_addr_t) > 4	 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0)		len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK;	sg->len = ahc_htole32(len);	return (consumed);}/* * Try to detect an Adaptec 7XXX controller. */static intahc_linux_detect(struct scsi_host_template *template){	struct	ahc_softc *ahc;	int     found = 0;	/*	 * Sanity checking of Linux SCSI data structures so	 * that some of our hacks^H^H^H^H^Hassumptions aren't	 * violated.	 */	if (offsetof(struct ahc_cmd_internal, end)	  > offsetof(struct scsi_cmnd, host_scribble)) {		printf("ahc_linux_detect: SCSI data structures changed.\n");		printf("ahc_linux_detect: Unable to attach\n");		return (0);	}	/*	 * If we've been passed any parameters, process them now.	 */	if (aic7xxx)		aic7xxx_setup(aic7xxx);	template->proc_name = "aic7xxx";	/*	 * Initialize our softc list lock prior to	 * probing for any adapters.	 */	ahc_list_lockinit();	found = ahc_linux_pci_init();	if (!ahc_linux_eisa_init())		found++;		/*	 * Register with the SCSI layer all	 * controllers we've found.	 */	TAILQ_FOREACH(ahc, &ahc_tailq, links) {		if (ahc_linux_register_host(ahc, template) == 0)			found++;	}	aic7xxx_detect_complete++;	return (found);}/* * Return a string describing the driver. */static const char *ahc_linux_info(struct Scsi_Host *host){	static char buffer[512];	char	ahc_info[256];	char   *bp;	struct ahc_softc *ahc;	bp = &buffer[0];	ahc = *(struct ahc_softc **)host->hostdata;	memset(bp, 0, sizeof(buffer));	strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev ");	strcat(bp, AIC7XXX_DRIVER_VERSION);	strcat(bp, "\n");	strcat(bp, "        <");	strcat(bp, ahc->description);	strcat(bp, ">\n");	strcat(bp, "        ");	ahc_controller_info(ahc, ahc_info);	strcat(bp, ahc_info);	strcat(bp, "\n");	return (bp);}/* * Queue an SCB to the controller. */static intahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)){	struct	 ahc_softc *ahc;	struct	 ahc_linux_device *dev;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	/*	 * Save the callback on completion function.	 */	cmd->scsi_done = scsi_done;	/*	 * Close the race of a command that was in the process of	 * being queued to us just as our simq was frozen.  Let	 * DV commands through so long as we are only frozen to	 * perform DV.	 */	if (ahc->platform_data->qfrozen != 0)		return SCSI_MLQUEUE_HOST_BUSY;	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,				   cmd->device->lun, /*alloc*/TRUE);	BUG_ON(dev == NULL);	cmd->result = CAM_REQ_INPROG << 16;	return ahc_linux_run_command(ahc, dev, cmd);}static intahc_linux_slave_alloc(struct scsi_device *device){	struct	ahc_softc *ahc;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);	return (0);}static intahc_linux_slave_configure(struct scsi_device *device){	struct	ahc_softc *ahc;	struct	ahc_linux_device *dev;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);	/*	 * Since Linux has attached to the device, configure	 * it so we don't free and allocate the device	 * structure on every command.	 */	dev = ahc_linux_get_device(ahc, device->channel,				   device->id, device->lun,				   /*alloc*/TRUE);	if (dev != NULL) {		dev->flags &= ~AHC_DEV_UNCONFIGURED;		dev->scsi_device = device;		ahc_linux_device_queue_depth(ahc, dev);	}	/* Initial Domain Validation */	if (!spi_initial_dv(device->sdev_target))		spi_dv_device(device);	return (0);}static voidahc_linux_slave_destroy(struct scsi_device *device){	struct	ahc_softc *ahc;	struct	ahc_linux_device *dev;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);	dev = ahc_linux_get_device(ahc, device->channel,				   device->id, device->lun,					   /*alloc*/FALSE);	/*	 * Filter out "silly" deletions of real devices by only	 * deleting devices that have had slave_configure()	 * called on them.  All other devices that have not	 * been configured will automatically be deleted by	 * the refcounting process.	 */	if (dev != NULL	 && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {		dev->flags |= AHC_DEV_UNCONFIGURED;		if (dev->active == 0	 	 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)			ahc_linux_free_device(ahc, dev);	}}#if defined(__i386__)/* * Return the disk geometry for the given SCSI device. */static intahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,		    sector_t capacity, int geom[]){	uint8_t *bh;	int	 heads;	int	 sectors;	int	 cylinders;	int	 ret;	int	 extended;	struct	 ahc_softc *ahc;	u_int	 channel;	ahc = *((struct ahc_softc **)sdev->host->hostdata);	channel = sdev->channel;	bh = scsi_bios_ptable(bdev);	if (bh) {		ret = scsi_partsize(bh, capacity,				    &geom[2], &geom[0], &geom[1]);		kfree(bh);		if (ret != -1)			return (ret);	}	heads = 64;	sectors = 32;	cylinders = aic_sector_div(capacity, heads, sectors);	if (aic7xxx_extended != 0)		extended = 1;	else if (channel == 0)		extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0;	else		extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0;	if (extended && cylinders >= 1024) {		heads = 255;		sectors = 63;		cylinders = aic_sector_div(capacity, heads, sectors);	}	geom[0] = heads;	geom[1] = sectors;	geom[2] = cylinders;	return (0);}#endif/* * Abort the current SCSI command(s). */static intahc_linux_abort(struct scsi_cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);	if (error != 0)		printf("aic7xxx_abort returns 0x%x\n", error);	return (error);}/* * Attempt to send a target reset message to the device that timed out. */static intahc_linux_dev_reset(struct scsi_cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);	if (error != 0)		printf("aic7xxx_dev_reset returns 0x%x\n", error);	return (error);}/* * Reset the SCSI bus. */static intahc_linux_bus_reset(struct scsi_cmnd *cmd){	struct ahc_softc *ahc;	int    found;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	found = ahc_reset_channel(ahc, cmd->device->channel + 'A',				  /*initiate reset*/TRUE);	if (bootverbose)		printf("%s: SCSI bus reset delivered. "		       "%d SCBs aborted.\n", ahc_name(ahc), found);	return SUCCESS;}struct scsi_host_template aic7xxx_driver_template = {	.module			= THIS_MODULE,	.name			= "aic7xxx",	.proc_info		= ahc_linux_proc_info,	.info			= ahc_linux_info,	.queuecommand		= ahc_linux_queue,	.eh_abort_handler	= ahc_linux_abort,	.eh_device_reset_handler = ahc_linux_dev_reset,	.eh_bus_reset_handler	= ahc_linux_bus_reset,#if defined(__i386__)	.bios_param		= ahc_linux_biosparam,#endif	.can_queue		= AHC_MAX_QUEUE,	.this_id		= -1,	.cmd_per_lun		= 2,	.use_clustering		= ENABLE_CLUSTERING,	.slave_alloc		= ahc_linux_slave_alloc,	.slave_configure	= ahc_linux_slave_configure,	.slave_destroy		= ahc_linux_slave_destroy,};/**************************** Tasklet Handler *********************************//******************************** Macros **************************************/#define BUILD_SCSIID(ahc, cmd)						    \	((((cmd)->device->id << TID_SHIFT) & TID)			    \	| (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \	| (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))/******************************** Bus DMA *************************************/intahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent,		   bus_size_t alignment, bus_size_t boundary,		   dma_addr_t lowaddr, dma_addr_t highaddr,		   bus_dma_filter_t *filter, void *filterarg,		   bus_size_t maxsize, int nsegments,		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag){	bus_dma_tag_t dmat;	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);	if (dmat == NULL)		return (ENOMEM);	/*	 * Linux is very simplistic about DMA memory.  For now don't	 * maintain all specification information.  Once Linux supplies	 * better facilities for doing these operations, or the	 * needs of this particular driver change, we might need to do	 * more here.	 */	dmat->alignment = alignment;	dmat->boundary = boundary;	dmat->maxsize = maxsize;	*ret_tag = dmat;	return (0);}voidahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat){	free(dmat, M_DEVBUF);}intahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,		 int flags, bus_dmamap_t *mapp){	*vaddr = pci_alloc_consistent(ahc->dev_softc,				      dmat->maxsize, mapp);	if (*vaddr == NULL)		return ENOMEM;	return 0;}voidahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat,		void* vaddr, bus_dmamap_t map){	pci_free_consistent(ahc->dev_softc, dmat->maxsize,			    vaddr, map);}intahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,		void *cb_arg, int flags){	/*	 * Assume for now that this will only be used during	 * initialization and not for per-transaction buffer mapping.	 */	bus_dma_segment_t stack_sg;	stack_sg.ds_addr = map;	stack_sg.ds_len = dmat->maxsize;	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);	return (0);}voidahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map){}intahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map){	/* Nothing to do */	return (0);}/********************* Platform Dependent Functions ***************************//* * Compare "left hand" softc with "right hand" softc, returning: * < 0 - lahc has a lower priority than rahc *   0 - Softcs are equal * > 0 - lahc has a higher priority than rahc */intahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc){	int	value;	int	rvalue;	int	lvalue;	/*	 * Under Linux, cards are ordered as follows:	 *	1) VLB/EISA BIOS enabled devices sorted by BIOS address.	 *	2) PCI devices with BIOS enabled sorted by bus/slot/func.	 *	3) All remaining VLB/EISA devices sorted by ioport.	 *	4) All remaining PCI devices sorted by bus/slot/func.	 */	value = (lahc->flags & AHC_BIOS_ENABLED)	      - (rahc->flags & AHC_BIOS_ENABLED);	if (value != 0)		/* Controllers with BIOS enabled have a *higher* priority */		return (value);	/*	 * Same BIOS setting, now sort based on bus type.	 * EISA and VL controllers sort together.  EISA/VL	 * have higher priority than PCI.	 */	rvalue = (rahc->chip & AHC_BUS_MASK); 	if (rvalue == AHC_VL)		rvalue = AHC_EISA;	lvalue = (lahc->chip & AHC_BUS_MASK); 	if (lvalue == AHC_VL)		lvalue = AHC_EISA;	value = rvalue - lvalue;	if (value != 0)		return (value);	/* Still equal.  Sort by BIOS address, ioport, or bus/slot/func. */	switch (rvalue) {#ifdef CONFIG_PCI	case AHC_PCI:	{		char primary_channel;		if (aic7xxx_reverse_scan != 0)			value = ahc_get_pci_bus(lahc->dev_softc)			      - ahc_get_pci_bus(rahc->dev_softc);		else			value = ahc_get_pci_bus(rahc->dev_softc)			      - ahc_get_pci_bus(lahc->dev_softc);		if (value != 0)			break;		if (aic7xxx_reverse_scan != 0)			value = ahc_get_pci_slot(lahc->dev_softc)			      - ahc_get_pci_slot(rahc->dev_softc);		else			value = ahc_get_pci_slot(rahc->dev_softc)			      - ahc_get_pci_slot(lahc->dev_softc);		if (value != 0)			break;		/*		 * On multi-function devices, the user can choose		 * to have function 1 probed before function 0.		 * Give whichever channel is the primary channel		 * the highest priority.		 */		primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A';		value = -1;		if (lahc->channel == primary_channel)			value = 1;		break;	}#endif	case AHC_EISA:		if ((rahc->flags & AHC_BIOS_ENABLED) != 0) {			value = rahc->platform_data->bios_address			      - lahc->platform_data->bios_address; 		} else {			value = rahc->bsh.ioport			      - lahc->bsh.ioport; 		}		break;	default:		panic("ahc_softc_sort: invalid bus type");	}	return (value);}static voidahc_linux_setup_tag_info_global(char *p){	int tags, i, j;	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;	printf("Setting Global Tags= %d\n", tags);	for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) {		for (j = 0; j < AHC_NUM_TARGETS; j++) {			aic7xxx_tag_info[i].tag_commands[j] = tags;		}	}}static voidahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value){	if ((instance >= 0) && (targ >= 0)	 && (instance < NUM_ELEMENTS(aic7xxx_tag_info))	 && (targ < AHC_NUM_TARGETS)) {		aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff;		if (bootverbose)			printf("tag_info[%d:%d] = %d\n", instance, targ, value);	}}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/c7525233d2df39b95552f6f49c6b390a9c4d2e80/aic7xxx_osm.c/buggy/drivers/scsi/aic7xxx/aic7xxx_osm.c