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

📄 aic79xx_core.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Core routines and tables shareable across OS platforms. * * Copyright (c) 1994-2001 Justin T. Gibbs. * Copyright (c) 2000-2002 Adaptec Inc. * 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. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    substantially similar to the "NO WARRANTY" disclaimer below *    ("Disclaimer") and any redistribution must be conditioned upon *    including a substantially similar Disclaimer requirement for further *    binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. * * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#79 $ * * $FreeBSD$ */#ifdef __linux__#include "aic79xx_osm.h"#include "aic79xx_inline.h"#include "aicasm/aicasm_insformat.h"#else#include <dev/aic7xxx/aic79xx_osm.h>#include <dev/aic7xxx/aic79xx_inline.h>#include <dev/aic7xxx/aicasm/aicasm_insformat.h>#endif/****************************** Softc Data ************************************/struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);/***************************** Lookup Tables **********************************/char *ahd_chip_names[] ={	"NONE",	"aic7901",	"aic7902"};static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names);/* * Hardware error codes. */struct ahd_hard_error_entry {        uint8_t errno;	char *errmesg;};static struct ahd_hard_error_entry ahd_hard_errors[] = {	{ DSCTMOUT,	"Discard Timer has timed out" },	{ ILLOPCODE,	"Illegal Opcode in sequencer program" },	{ SQPARERR,	"Sequencer Parity Error" },	{ DPARERR,	"Data-path Parity Error" },	{ MPARERR,	"Scratch or SCB Memory Parity Error" },	{ CIOPARERR,	"CIOBUS Parity Error" },};static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors);static struct ahd_phase_table_entry ahd_phase_table[] ={	{ P_DATAOUT,	MSG_NOOP,		"in Data-out phase"	},	{ P_DATAIN,	MSG_INITIATOR_DET_ERR,	"in Data-in phase"	},	{ P_DATAOUT_DT,	MSG_NOOP,		"in DT Data-out phase"	},	{ P_DATAIN_DT,	MSG_INITIATOR_DET_ERR,	"in DT Data-in phase"	},	{ P_COMMAND,	MSG_NOOP,		"in Command phase"	},	{ P_MESGOUT,	MSG_NOOP,		"in Message-out phase"	},	{ P_STATUS,	MSG_INITIATOR_DET_ERR,	"in Status phase"	},	{ P_MESGIN,	MSG_PARITY_ERROR,	"in Message-in phase"	},	{ P_BUSFREE,	MSG_NOOP,		"while idle"		},	{ 0,		MSG_NOOP,		"in unknown phase"	}};/* * In most cases we only wish to itterate over real phases, so * exclude the last element from the count. */static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1;/* Our Sequencer Program */#include "aic79xx_seq.h"/**************************** Function Declarations ***************************/static void		ahd_handle_transmission_error(struct ahd_softc *ahd);static void		ahd_handle_lqiphase_error(struct ahd_softc *ahd,						  u_int lqistat1);static int		ahd_handle_pkt_busfree(struct ahd_softc *ahd,					       u_int busfreetime);static int		ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);static void		ahd_force_renegotiation(struct ahd_softc *ahd,						struct ahd_devinfo *devinfo);static struct ahd_tmode_tstate*			ahd_alloc_tstate(struct ahd_softc *ahd,					 u_int scsi_id, char channel);#ifdef AHD_TARGET_MODEstatic void		ahd_free_tstate(struct ahd_softc *ahd,					u_int scsi_id, char channel, int force);#endifstatic void		ahd_devlimited_syncrate(struct ahd_softc *ahd,					        struct ahd_initiator_tinfo *,						u_int *period,						u_int *ppr_options,						role_t role);static void		ahd_update_neg_table(struct ahd_softc *ahd,					     struct ahd_devinfo *devinfo,					     struct ahd_transinfo *tinfo);static void		ahd_update_pending_scbs(struct ahd_softc *ahd);static void		ahd_fetch_devinfo(struct ahd_softc *ahd,					  struct ahd_devinfo *devinfo);static void		ahd_scb_devinfo(struct ahd_softc *ahd,					struct ahd_devinfo *devinfo,					struct scb *scb);static void		ahd_setup_initiator_msgout(struct ahd_softc *ahd,						   struct ahd_devinfo *devinfo,						   struct scb *scb);static void		ahd_build_transfer_msg(struct ahd_softc *ahd,					       struct ahd_devinfo *devinfo);static void		ahd_construct_sdtr(struct ahd_softc *ahd,					   struct ahd_devinfo *devinfo,					   u_int period, u_int offset);static void		ahd_construct_wdtr(struct ahd_softc *ahd,					   struct ahd_devinfo *devinfo,					   u_int bus_width);static void		ahd_construct_ppr(struct ahd_softc *ahd,					  struct ahd_devinfo *devinfo,					  u_int period, u_int offset,					  u_int bus_width, u_int ppr_options);static void		ahd_clear_msg_state(struct ahd_softc *ahd);static void		ahd_handle_message_phase(struct ahd_softc *ahd);typedef enum {	AHDMSG_1B,	AHDMSG_2B,	AHDMSG_EXT} ahd_msgtype;static int		ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,				     u_int msgval, int full);static int		ahd_parse_msg(struct ahd_softc *ahd,				      struct ahd_devinfo *devinfo);static int		ahd_handle_msg_reject(struct ahd_softc *ahd,					      struct ahd_devinfo *devinfo);static void		ahd_handle_ign_wide_residue(struct ahd_softc *ahd,						struct ahd_devinfo *devinfo);static void		ahd_reinitialize_dataptrs(struct ahd_softc *ahd);static void		ahd_handle_devreset(struct ahd_softc *ahd,					    struct ahd_devinfo *devinfo,					    cam_status status, char *message,					    int verbose_level);#if AHD_TARGET_MODEstatic void		ahd_setup_target_msgin(struct ahd_softc *ahd,					       struct ahd_devinfo *devinfo,					       struct scb *scb);#endifstatic bus_size_t	ahd_sglist_size(struct ahd_softc *ahd);static bus_size_t	ahd_sglist_allocsize(struct ahd_softc *ahd);static bus_dmamap_callback_t			ahd_dmamap_cb; static void		ahd_initialize_hscbs(struct ahd_softc *ahd);static int		ahd_init_scbdata(struct ahd_softc *ahd);static void		ahd_fini_scbdata(struct ahd_softc *ahd);static void		ahd_setup_iocell_workaround(struct ahd_softc *ahd);static void		ahd_iocell_first_selection(struct ahd_softc *ahd);static void		ahd_chip_init(struct ahd_softc *ahd);static void		ahd_qinfifo_requeue(struct ahd_softc *ahd,					    struct scb *prev_scb,					    struct scb *scb);static int		ahd_qinfifo_count(struct ahd_softc *ahd);static int		ahd_search_scb_list(struct ahd_softc *ahd, int target,					    char channel, int lun, u_int tag,					    role_t role, uint32_t status,					    ahd_search_action action,					    u_int *list_head, u_int tid);static void		ahd_stitch_tid_list(struct ahd_softc *ahd,					    u_int tid_prev, u_int tid_cur,					    u_int tid_next);static void		ahd_add_scb_to_free_list(struct ahd_softc *ahd,						 u_int scbid);static u_int		ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,				     u_int prev, u_int next, u_int tid);static void		ahd_reset_current_bus(struct ahd_softc *ahd);static ahd_callback_t	ahd_reset_poll;#ifdef AHD_DUMP_SEQstatic void		ahd_dumpseq(struct ahd_softc *ahd);#endifstatic void		ahd_loadseq(struct ahd_softc *ahd);static int		ahd_check_patch(struct ahd_softc *ahd,					struct patch **start_patch,					u_int start_instr, u_int *skip_addr);static u_int		ahd_resolve_seqaddr(struct ahd_softc *ahd,					    u_int address);static void		ahd_download_instr(struct ahd_softc *ahd,					   u_int instrptr, uint8_t *dconsts);#ifdef AHD_TARGET_MODEstatic void		ahd_queue_lstate_event(struct ahd_softc *ahd,					       struct ahd_tmode_lstate *lstate,					       u_int initiator_id,					       u_int event_type,					       u_int event_arg);static void		ahd_update_scsiid(struct ahd_softc *ahd,					  u_int targid_mask);static int		ahd_handle_target_cmd(struct ahd_softc *ahd,					      struct target_cmd *cmd);#endif/******************************** Private Inlines *****************************/static __inline void	ahd_assert_atn(struct ahd_softc *ahd);static __inline int	ahd_currently_packetized(struct ahd_softc *ahd);static __inline int	ahd_set_active_fifo(struct ahd_softc *ahd);static __inline voidahd_assert_atn(struct ahd_softc *ahd){	ahd_outb(ahd, SCSISIGO, ATNO);}/* * Determine if the current connection has a packetized * agreement.  This does not necessarily mean that we * are currently in a packetized transfer.  We could * just as easily be sending or receiving a message. */static __inline intahd_currently_packetized(struct ahd_softc *ahd){	ahd_mode_state	 saved_modes;	int		 packetized;	saved_modes = ahd_save_modes(ahd);	if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {		/*		 * The packetized bit refers to the last		 * connection, not the current one.  Check		 * for non-zero LQISTATE instead.		 */		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);		packetized = ahd_inb(ahd, LQISTATE) != 0;	} else {		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);		packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;	}	ahd_restore_modes(ahd, saved_modes);	return (packetized);}static __inline intahd_set_active_fifo(struct ahd_softc *ahd){	u_int active_fifo;	AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);	active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;/* XXX This is a three possition switch in the B. */	switch (active_fifo) {	case 0:	case 1:		ahd_set_modes(ahd, active_fifo, active_fifo);		return (1);	default:		return (0);	}}/************************* Sequencer Execution Control ************************//* * Restart the sequencer program from address zero */voidahd_restart(struct ahd_softc *ahd){	ahd_pause(ahd);	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	/* No more pending messages */	ahd_clear_msg_state(ahd);	ahd_outb(ahd, SCSISIGO, 0);		/* De-assert BSY */	ahd_outb(ahd, MSG_OUT, MSG_NOOP);	/* No message to send */	ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);	ahd_outb(ahd, SEQINTCTL, 0);	ahd_outb(ahd, LASTPHASE, P_BUSFREE);	ahd_outb(ahd, SEQ_FLAGS, 0);	ahd_outb(ahd, SAVED_SCSIID, 0xFF);	ahd_outb(ahd, SAVED_LUN, 0xFF);	/*	 * Ensure that the sequencer's idea of TQINPOS	 * matches our own.  The sequencer increments TQINPOS	 * only after it sees a DMA complete and a reset could	 * occur before the increment leaving the kernel to believe	 * the command arrived but the sequencer to not.	 */	ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);	/* Always allow reselection */	ahd_outb(ahd, SCSISEQ1,		 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));	/* Ensure that no DMA operations are in progress */	ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);	ahd_outb(ahd, SCBHCNT, 0);	ahd_outb(ahd, CCSCBCTL, CCSCBRESET);	ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);	ahd_unpause(ahd);}voidahd_clear_fifo(struct ahd_softc *ahd, u_int fifo){	ahd_mode_state	 saved_modes;#if AHD_DEBUG	if ((ahd_debug & AHD_SHOW_FIFOS) != 0)		printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);#endif	saved_modes = ahd_save_modes(ahd);	ahd_set_modes(ahd, fifo, fifo);	ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);	if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)		ahd_outb(ahd, CCSGCTL, CCSGRESET);	ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);	ahd_outb(ahd, SG_STATE, 0);	ahd_restore_modes(ahd, saved_modes);}/************************* Input/Output Queues ********************************/voidahd_run_qoutfifo(struct ahd_softc *ahd){	struct scb *scb;	u_int  scb_index;	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);	while (ahd->qoutfifo[ahd->qoutfifonext] != SCB_LIST_NULL_LE) {		scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]);		scb = ahd_lookup_scb(ahd, scb_index);		if (scb == NULL) {			printf("%s: WARNING no command for scb %d "			       "(cmdcmplt)\nQOUTPOS = %d\n",			       ahd_name(ahd), scb_index,			       ahd->qoutfifonext);			ahd_dump_card_state(ahd);			ahd->qoutfifonext = AHD_QOUT_WRAP(ahd->qoutfifonext+1);			continue;		}		if ((ahd->qoutfifonext & 0x01) == 0x01) {			/*			 * Clear 32bits of QOUTFIFO at a time			 * so that we don't clobber an incoming			 * 16bit DMA to the array on architectures			 * that only support 32bit load and store			 * operations.			 */			ahd->qoutfifo[ahd->qoutfifonext - 1] = SCB_LIST_NULL_LE;			ahd->qoutfifo[ahd->qoutfifonext] = SCB_LIST_NULL_LE;			ahd_dmamap_sync(ahd, ahd->shared_data_dmat,					ahd->shared_data_dmamap,					/*offset*/(ahd->qoutfifonext - 1)*2,					/*len*/4, BUS_DMASYNC_PREREAD);		}		ahd->qoutfifonext = AHD_QOUT_WRAP(ahd->qoutfifonext+1);		ahd_complete_scb(ahd, scb);	}}voidahd_run_untagged_queues(struct ahd_softc *ahd){	int i;	for (i = 0; i < 16; i++)		ahd_run_untagged_queue(ahd, &ahd->untagged_queues[i]);}voidahd_run_untagged_queue(struct ahd_softc *ahd, struct scb_tailq *queue){	struct scb *scb;	if (ahd->untagged_queue_lock != 0)		return;	if ((scb = TAILQ_FIRST(queue)) != NULL	 && (scb->flags & SCB_ACTIVE) == 0) {		scb->flags |= SCB_ACTIVE;		ahd_queue_scb(ahd, scb);	}}/************************* Interrupt Handling *********************************/voidahd_handle_hwerrint(struct ahd_softc *ahd){	/*	 * Some catastrophic hardware error has occurred.	 * Print it for the user and disable the controller.	 */	int i;	int error;	error = ahd_inb(ahd, ERROR);	for (i = 0; i < num_errors; i++) {		if ((error & ahd_hard_errors[i].errno) != 0)			printf("%s: hwerrint, %s\n",			       ahd_name(ahd), ahd_hard_errors[i].errmesg);

⌨️ 快捷键说明

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