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

📄 bt.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Generic driver for the BusLogic MultiMaster SCSI host adapters * Product specific probe and attach routines can be found in: * i386/isa/bt_isa.c	BT-54X, BT-445 cards * i386/eisa/bt_eisa.c	BT-74x, BT-75x cards * pci/bt_pci.c		BT-946, BT-948, BT-956, BT-958 cards * * Copyright (c) 1998, 1999 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, this list of conditions, and the following disclaimer, *    without modification, immediately at the beginning of the file. * 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: bt.c,v 1.13.2.3 1999/05/07 00:43:31 ken Exp $ */ /*  * Special thanks to 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 controllers and  * firmware revisions, with their otherwise undocumented quirks, would not  * have been possible without his efforts.  */#include <sys/param.h>#include <sys/systm.h> #include <sys/malloc.h>#include <sys/buf.h>#include <sys/kernel.h>#include <sys/sysctl.h> /* * XXX It appears that BusLogic PCI adapters go out to lunch if you  *     attempt to perform memory mapped I/O. */#if 0#include "pci.h"#if NPCI > 0#include <machine/bus_memio.h>#endif#endif#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 <vm/vm.h>#include <vm/pmap.h> #include <dev/buslogic/btreg.h>#ifndef MAX#define MAX(a, b) ((a) > (b) ? (a) : (b))#endifstruct bt_softc *bt_softcs[NBT];/* MailBox Management functions */static __inline void	btnextinbox(struct bt_softc *bt);static __inline void	btnextoutbox(struct bt_softc *bt);static __inline voidbtnextinbox(struct bt_softc *bt){	if (bt->cur_inbox == bt->last_inbox)		bt->cur_inbox = bt->in_boxes;	else		bt->cur_inbox++;}static __inline voidbtnextoutbox(struct bt_softc *bt){	if (bt->cur_outbox == bt->last_outbox)		bt->cur_outbox = bt->out_boxes;	else		bt->cur_outbox++;}/* CCB Mangement functions */static __inline u_int32_t		btccbvtop(struct bt_softc *bt,						  struct bt_ccb *bccb);static __inline struct bt_ccb*		btccbptov(struct bt_softc *bt,						  u_int32_t ccb_addr);static __inline u_int32_t		btsensepaddr(struct bt_softc *bt,						     struct bt_ccb *bccb);static __inline struct scsi_sense_data* btsensevaddr(struct bt_softc *bt,						     struct bt_ccb *bccb);static __inline u_int32_tbtccbvtop(struct bt_softc *bt, struct bt_ccb *bccb){	return (bt->bt_ccb_physbase	      + (u_int32_t)((caddr_t)bccb - (caddr_t)bt->bt_ccb_array));}static __inline struct bt_ccb *btccbptov(struct bt_softc *bt, u_int32_t ccb_addr){	return (bt->bt_ccb_array +	        ((struct bt_ccb*)ccb_addr-(struct bt_ccb*)bt->bt_ccb_physbase));}static __inline u_int32_tbtsensepaddr(struct bt_softc *bt, struct bt_ccb *bccb){	u_int index;	index = (u_int)(bccb - bt->bt_ccb_array);	return (bt->sense_buffers_physbase		+ (index * sizeof(struct scsi_sense_data)));}static __inline struct scsi_sense_data *btsensevaddr(struct bt_softc *bt, struct bt_ccb *bccb){	u_int index;	index = (u_int)(bccb - bt->bt_ccb_array);	return (bt->sense_buffers + index);}static __inline struct bt_ccb*	btgetccb(struct bt_softc *bt);static __inline void		btfreeccb(struct bt_softc *bt,					  struct bt_ccb *bccb);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);/* Host adapter command functions */static int	btreset(struct bt_softc* bt, int hard_reset);/* Initialization functions */static int			btinitmboxes(struct bt_softc *bt);static bus_dmamap_callback_t	btmapmboxes;static bus_dmamap_callback_t	btmapccbs;static bus_dmamap_callback_t	btmapsgs;/* Transfer Negotiation Functions */static void btfetchtransinfo(struct bt_softc *bt,			     struct ccb_trans_settings *cts);/* CAM SIM entry points */#define ccb_bccb_ptr spriv_ptr0#define ccb_bt_ptr spriv_ptr1static void	btaction(struct cam_sim *sim, union ccb *ccb);static void	btpoll(struct cam_sim *sim);/* Our timeout handler */timeout_t bttimeout;u_long bt_unit = 0;/* * XXX * Do our own re-probe protection until a configuration * manager can do it for us.  This ensures that we don't * reprobe a card already found by the EISA or PCI probes. */struct bt_isa_port bt_isa_ports[] ={	{ 0x130, 0, 4 },	{ 0x134, 0, 5 },	{ 0x230, 0, 2 },	{ 0x234, 0, 3 },	{ 0x330, 0, 0 },	{ 0x334, 0, 1 }};/* * I/O ports listed in the order enumerated by the * card for certain op codes. */u_int16_t bt_board_ports[] ={	0x330,	0x334,	0x230,	0x234,	0x130,	0x134};/* Exported functions */struct bt_softc *bt_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh){	struct  bt_softc *bt;  	if (unit != BT_TEMP_UNIT) {		if (unit >= NBT) {			printf("bt: unit number (%d) too high\n", unit);			return NULL;		}		/*		 * Allocate a storage area for us		 */		if (bt_softcs[unit]) {    			printf("bt%d: memory already allocated\n", unit);			return NULL;    		}	}	bt = malloc(sizeof(struct bt_softc), M_DEVBUF, M_NOWAIT);	if (!bt) {		printf("bt%d: cannot malloc!\n", unit);		return NULL;    	}	bzero(bt, sizeof(struct bt_softc));	SLIST_INIT(&bt->free_bt_ccbs);	LIST_INIT(&bt->pending_ccbs);	SLIST_INIT(&bt->sg_maps);	bt->unit = unit;	bt->tag = tag;	bt->bsh = bsh;	if (bt->unit != BT_TEMP_UNIT) {		bt_softcs[unit] = bt;	}	return (bt);}voidbt_free(struct bt_softc *bt){	switch (bt->init_level) {	default:	case 11:		bus_dmamap_unload(bt->sense_dmat, bt->sense_dmamap);	case 10:		bus_dmamem_free(bt->sense_dmat, bt->sense_buffers,				bt->sense_dmamap);	case 9:		bus_dma_tag_destroy(bt->sense_dmat);	case 8:	{		struct sg_map_node *sg_map;		while ((sg_map = SLIST_FIRST(&bt->sg_maps))!= NULL) {			SLIST_REMOVE_HEAD(&bt->sg_maps, links);			bus_dmamap_unload(bt->sg_dmat,					  sg_map->sg_dmamap);			bus_dmamem_free(bt->sg_dmat, sg_map->sg_vaddr,					sg_map->sg_dmamap);			free(sg_map, M_DEVBUF);		}		bus_dma_tag_destroy(bt->sg_dmat);	}	case 7:		bus_dmamap_unload(bt->ccb_dmat, bt->ccb_dmamap);	case 6:		bus_dmamem_free(bt->ccb_dmat, bt->bt_ccb_array,				bt->ccb_dmamap);		bus_dmamap_destroy(bt->ccb_dmat, bt->ccb_dmamap);	case 5:		bus_dma_tag_destroy(bt->ccb_dmat);	case 4:		bus_dmamap_unload(bt->mailbox_dmat, bt->mailbox_dmamap);	case 3:		bus_dmamem_free(bt->mailbox_dmat, bt->in_boxes,				bt->mailbox_dmamap);		bus_dmamap_destroy(bt->mailbox_dmat, bt->mailbox_dmamap);	case 2:		bus_dma_tag_destroy(bt->buffer_dmat);	case 1:		bus_dma_tag_destroy(bt->mailbox_dmat);	case 0:		break;	}	if (bt->unit != BT_TEMP_UNIT) {		bt_softcs[bt->unit] = NULL;	}	free(bt, M_DEVBUF);}intbt_port_probe(struct bt_softc *bt, struct bt_probe_info *info){	config_data_t config_data;	int error;	/* See if there is really a card present */	if (bt_probe(bt) || bt_fetch_adapter_info(bt))		return(1);	/*	 * Determine our IRQ, and DMA settings and	 * export them to the configuration system.	 */	error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,		       (u_int8_t*)&config_data, sizeof(config_data),		       DEFAULT_CMD_TIMEOUT);	if (error != 0) {		printf("bt_port_probe: Could not determine IRQ or DMA "		       "settings for adapter.\n");		return (1);	}	if (bt->model[0] == '5') {		/* DMA settings only make sense for ISA cards */		switch (config_data.dma_chan) {		case DMA_CHAN_5:			info->drq = 5;			break;		case DMA_CHAN_6:			info->drq = 6;			break;		case DMA_CHAN_7:			info->drq = 7;			break;		default:			printf("bt_port_probe: Invalid DMA setting "			       "detected for adapter.\n");			return (1);		}	} else {		/* VL/EISA/PCI DMA */		info->drq = -1;	}	switch (config_data.irq) {	case IRQ_9:	case IRQ_10:	case IRQ_11:	case IRQ_12:	case IRQ_14:	case IRQ_15:		info->irq = ffs(config_data.irq) + 8;		break;	default:		printf("bt_port_probe: Invalid IRQ setting %x"		       "detected for adapter.\n", config_data.irq);		return (1);	}	return (0);}/* * Probe the adapter and verify that the card is a BusLogic. */intbt_probe(struct bt_softc* bt){	esetup_info_data_t esetup_info;	u_int	 status;	u_int	 intstat;	u_int	 geometry;	int	 error;	u_int8_t param;	/*	 * See if the three I/O ports look reasonable.	 * Touch the minimal number of registers in the	 * failure case.	 */	status = bt_inb(bt, STATUS_REG);	if ((status == 0)	 || (status & (DIAG_ACTIVE|CMD_REG_BUSY|		       STATUS_REG_RSVD|CMD_INVALID)) != 0) {		if (bootverbose)			printf("%s: Failed Status Reg Test - %x\n", bt_name(bt),			       status);		return (ENXIO);	}	intstat = bt_inb(bt, INTSTAT_REG);	if ((intstat & INTSTAT_REG_RSVD) != 0) {		printf("%s: Failed Intstat Reg Test\n", bt_name(bt));		return (ENXIO);	}	geometry = bt_inb(bt, GEOMETRY_REG);	if (geometry == 0xFF) {		if (bootverbose)			printf("%s: Failed Geometry Reg Test\n", bt_name(bt));		return (ENXIO);	}	/*	 * Looking good so far.  Final test is to reset the	 * adapter and attempt to fetch the extended setup	 * information.  This should filter out all 1542 cards.	 */	if ((error = btreset(bt, /*hard_reset*/TRUE)) != 0) {		if (bootverbose)			printf("%s: Failed Reset\n", bt_name(bt));		return (ENXIO);	}		param = sizeof(esetup_info);	error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &param, /*parmlen*/1,		       (u_int8_t*)&esetup_info, sizeof(esetup_info),		       DEFAULT_CMD_TIMEOUT);	if (error != 0) {		return (ENXIO);	}	return (0);}/* * Pull the boards setup information and record it in our softc. */intbt_fetch_adapter_info(struct bt_softc *bt){	board_id_data_t	board_id;	esetup_info_data_t esetup_info;	config_data_t config_data;	int	 error;	u_int8_t length_param;	/* First record the firmware version */	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) {		printf("%s: bt_fetch_adapter_info - Failed Get Board Info\n",		       bt_name(bt));		return (error);	}	bt->firmware_ver[0] = board_id.firmware_rev_major;	bt->firmware_ver[1] = '.';	bt->firmware_ver[2] = board_id.firmware_rev_minor;	bt->firmware_ver[3] = '\0';			/*	 * Depending on the firmware major and minor version,	 * we may be able to fetch additional minor version info.	 */	if (bt->firmware_ver[0] > '0') {				error = bt_cmd(bt, BOP_INQUIRE_FW_VER_3DIG, NULL, /*parmlen*/0,			       (u_int8_t*)&bt->firmware_ver[3], 1,			       DEFAULT_CMD_TIMEOUT);		if (error != 0) {			printf("%s: bt_fetch_adapter_info - Failed Get "			       "Firmware 3rd Digit\n", bt_name(bt));			return (error);		}		if (bt->firmware_ver[3] == ' ')			bt->firmware_ver[3] = '\0';		bt->firmware_ver[4] = '\0';	}	if (strcmp(bt->firmware_ver, "3.3") >= 0) {		error = bt_cmd(bt, BOP_INQUIRE_FW_VER_4DIG, NULL, /*parmlen*/0,			       (u_int8_t*)&bt->firmware_ver[4], 1,			       DEFAULT_CMD_TIMEOUT);		if (error != 0) {			printf("%s: bt_fetch_adapter_info - Failed Get "			       "Firmware 4th Digit\n", bt_name(bt));			return (error);		}		if (bt->firmware_ver[4] == ' ')			bt->firmware_ver[4] = '\0';		bt->firmware_ver[5] = '\0';	}	/*	 * Some boards do not handle the "recently documented"	 * Inquire Board Model Number command correctly or do not give	 * exact information.  Use the Firmware and Extended Setup	 * information in these cases to come up with the right answer.	 * The major firmware revision number indicates:	 *	 * 	5.xx	BusLogic "W" Series Host Adapters:	 *		BT-948/958/958D	 *	4.xx	BusLogic "C" Series Host Adapters:	 *		BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF	 *	3.xx	BusLogic "S" Series Host Adapters:	 *		BT-747S/747D/757S/757D/445S/545S/542D	 *		BT-542B/742A (revision H)	 *	2.xx	BusLogic "A" Series Host Adapters:	 *		BT-542B/742A (revision G and below)	 *	0.xx	AMI FastDisk VLB/EISA BusLogic Clone Host Adapter	 */	length_param = sizeof(esetup_info);	error = bt_cmd(bt, BOP_INQUIRE_ESETUP_INFO, &length_param, /*parmlen*/1,		       (u_int8_t*)&esetup_info, sizeof(esetup_info),		       DEFAULT_CMD_TIMEOUT);	if (error != 0) {		return (error);	}	  	bt->bios_addr = esetup_info.bios_addr << 12;	if (esetup_info.bus_type == 'A'	 && bt->firmware_ver[0] == '2') {		snprintf(bt->model, sizeof(bt->model), "542B");	} else if (esetup_info.bus_type == 'E'		&& (strncmp(bt->firmware_ver, "2.1", 3) == 0		 || strncmp(bt->firmware_ver, "2.20", 4) == 0)) {		snprintf(bt->model, sizeof(bt->model), "742A");	} else if (esetup_info.bus_type == 'E'		&& bt->firmware_ver[0] == '0') {		/* AMI FastDisk EISA Series 441 0.x */		snprintf(bt->model, sizeof(bt->model), "747A");	} else {		ha_model_data_t model_data;		int i;		length_param = sizeof(model_data);		error = bt_cmd(bt, BOP_INQUIRE_MODEL, &length_param, 1,			       (u_int8_t*)&model_data, sizeof(model_data),			       DEFAULT_CMD_TIMEOUT);		if (error != 0) {			printf("%s: bt_fetch_adapter_info - Failed Inquire "			       "Model Number\n", bt_name(bt));			return (error);		}		for (i = 0; i < sizeof(model_data.ascii_model); i++) {			bt->model[i] = model_data.ascii_model[i];			if (bt->model[i] == ' ')				break;		}		bt->model[i] = '\0';	}	bt->level_trigger_ints = esetup_info.level_trigger_ints ? 1 : 0;	/* SG element limits */	bt->max_sg = esetup_info.max_sg;	/* Set feature flags */	bt->wide_bus = esetup_info.wide_bus;	bt->diff_bus = esetup_info.diff_bus;	bt->ultra_scsi = esetup_info.ultra_scsi;	if ((bt->firmware_ver[0] == '5')	 || (bt->firmware_ver[0] == '4' && bt->wide_bus))		bt->extended_lun = TRUE;	bt->strict_rr = (strcmp(bt->firmware_ver, "3.31") >= 0);	bt->extended_trans =	    ((bt_inb(bt, GEOMETRY_REG) & EXTENDED_TRANSLATION) != 0);	/*	 * Determine max CCB count and whether tagged queuing is	 * available based on controller type. Tagged queuing	 * only works on 'W' series adapters, 'C' series adapters	 * with firmware of rev 4.42 and higher, and 'S' series	 * adapters with firmware of rev 3.35 and higher.  The	 * maximum CCB counts are as follows:	 *	 *	192	BT-948/958/958D	 *	100	BT-946C/956C/956CD/747C/757C/757CD/445C	 * 	50	BT-545C/540CF	 * 	30	BT-747S/747D/757S/757D/445S/545S/542D/542B/742A	 */	if (bt->firmware_ver[0] == '5') {		bt->max_ccbs = 192;		bt->tag_capable = TRUE;	} else if (bt->firmware_ver[0] == '4') {		if (bt->model[0] == '5')			bt->max_ccbs = 50;		else			bt->max_ccbs = 100;		bt->tag_capable = (strcmp(bt->firmware_ver, "4.22") >= 0);

⌨️ 快捷键说明

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