cam_xpt.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,349 行 · 第 1/5 页

C
2,349
字号
/* * Implementation of the Common Access Method Transport (XPT) layer. * * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. * 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: cam_xpt.c,v 1.42.2.10 1999/05/12 04:49:28 mjacob Exp $ */#include <sys/param.h>#include <sys/systm.h>#include <sys/types.h>#include <sys/malloc.h>#include <sys/device.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/fcntl.h>#include <sys/md5.h>#include <sys/devicestat.h>#include <sys/interrupt.h>#ifdef PC98#include <pc98/pc98/pc98_machdep.h>	/* geometry translation */#endif#include <machine/clock.h>#include <machine/ipl.h>#include <cam/cam.h>#include <cam/cam_conf.h>#include <cam/cam_ccb.h>#include <cam/cam_periph.h>#include <cam/cam_sim.h>#include <cam/cam_xpt.h>#include <cam/cam_xpt_sim.h>#include <cam/cam_xpt_periph.h>#include <cam/cam_debug.h>#include <cam/scsi/scsi_all.h>#include <cam/scsi/scsi_message.h>#include <cam/scsi/scsi_pass.h>#include "opt_cam.h"#include "opt_scsi.h"extern	void	(*ihandlers[32]) __P((void));/* Datastructures internal to the xpt layer *//* * Definition of an async handler callback block.  These are used to add * SIMs and peripherals to the async callback lists. */struct async_node {	SLIST_ENTRY(async_node)	links;	u_int32_t	event_enable;	/* Async Event enables */	void		(*callback)(void *arg, u_int32_t code,				    struct cam_path *path, void *args);	void		*callback_arg;};SLIST_HEAD(async_list, async_node);SLIST_HEAD(periph_list, cam_periph);static STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;/* * This is the maximum number of high powered commands (e.g. start unit) * that can be outstanding at a particular time. */#ifndef CAM_MAX_HIGHPOWER#define CAM_MAX_HIGHPOWER  4#endif/* * This is the number of seconds we wait for devices to settle after a SCSI * bus reset. */#ifndef SCSI_DELAY#define SCSI_DELAY 2000#endif/* * If someone sets this to 0, we assume that they want the minimum * allowable bus settle delay.  All devices need _some_ sort of bus settle * delay, so we'll set it to a minimum value of 100ms. */#if (SCSI_DELAY == 0)#undef SCSI_DELAY#define SCSI_DELAY 100#endif/* * Make sure the user isn't using seconds instead of milliseconds. */#if (SCSI_DELAY < 100)#error "SCSI_DELAY is in milliseconds, not seconds!  Please use a larger value"#endif/* number of high powered commands that can go through right now */static int num_highpower = CAM_MAX_HIGHPOWER;/* * Structure for queueing a device in a run queue. * There is one run queue for allocating new ccbs, * and another for sending ccbs to the controller. */struct cam_ed_qinfo {	cam_pinfo pinfo;	struct	  cam_ed *device;};/* * The CAM EDT (Existing Device Table) contains the device information for * all devices for all busses in the system.  The table contains a * cam_ed structure for each device on the bus. */struct cam_ed {	TAILQ_ENTRY(cam_ed) links;	struct	cam_ed_qinfo alloc_ccb_entry;	struct	cam_ed_qinfo send_ccb_entry;	struct	cam_et	 *target;	lun_id_t	 lun_id;	struct	camq drvq;		/*					 * Queue of type drivers wanting to do					 * work on this device.					 */	struct	cam_ccbq ccbq;		/* Queue of pending ccbs */	struct	async_list asyncs;	/* Async callback info for this B/T/L */	struct	periph_list periphs;	/* All attached devices */	u_int	generation;		/* Generation number */	struct	cam_periph *owner;	/* Peripheral driver's ownership tag */	struct	xpt_quirk_entry *quirk;	/* Oddities about this device */					/* Storage for the inquiry data */	struct	scsi_inquiry_data inq_data;	u_int8_t	 inq_flags;	/*					 * Current settings for inquiry flags.					 * This allows us to override settings					 * like disconnection and tagged					 * queuing for a device.					 */	u_int8_t	 queue_flags;	/* Queue flags from the control page */	u_int8_t	 *serial_num;	u_int8_t	 serial_num_len;	u_int32_t	 qfrozen_cnt;	u_int32_t	 flags;#define CAM_DEV_UNCONFIGURED	 	0x01#define CAM_DEV_REL_TIMEOUT_PENDING	0x02#define CAM_DEV_REL_ON_COMPLETE		0x04#define CAM_DEV_REL_ON_QUEUE_EMPTY	0x08#define CAM_DEV_RESIZE_QUEUE_NEEDED	0x10#define CAM_DEV_TAG_AFTER_COUNT		0x20	u_int32_t	 tag_delay_count;#define	CAM_TAG_DELAY_COUNT		5	u_int32_t	 refcount;	struct		 callout_handle c_handle;};/* * Each target is represented by an ET (Existing Target).  These * entries are created when a target is successfully probed with an * identify, and removed when a device fails to respond after a number * of retries, or a bus rescan finds the device missing. */struct cam_et { 	TAILQ_HEAD(, cam_ed) ed_entries;	TAILQ_ENTRY(cam_et) links;	struct	cam_eb	*bus;		target_id_t	target_id;	u_int32_t	refcount;		u_int		generation;};/* * Each bus is represented by an EB (Existing Bus).  These entries * are created by calls to xpt_bus_register and deleted by calls to * xpt_bus_deregister. */struct cam_eb { 	TAILQ_HEAD(, cam_et) et_entries;	TAILQ_ENTRY(cam_eb)  links;	path_id_t	     path_id;	struct cam_sim	     *sim;	u_int32_t	     flags;#define	CAM_EB_RUNQ_SCHEDULED	0x01	u_int32_t	     refcount;	u_int		     generation;};struct cam_path {	struct cam_periph *periph;	struct cam_eb	  *bus;	struct cam_et	  *target;	struct cam_ed	  *device;};struct xpt_quirk_entry {	struct scsi_inquiry_pattern inq_pat;	u_int8_t quirks;#define	CAM_QUIRK_NOLUNS	0x01#define	CAM_QUIRK_NOSERIAL	0x02	u_int mintags;	u_int maxtags;};typedef enum {	XPT_FLAG_OPEN		= 0x01} xpt_flags;struct xpt_softc {	xpt_flags	flags;	u_int32_t	generation;#ifdef DEVFS	void		*xpt_devfs_token;	void		*ctl_devfs_token;#endif};static const char quantum[] = "QUANTUM";static const char sony[] = "SONY";static const char west_digital[] = "WDIGTL";static const char samsung[] = "SAMSUNG";static const char seagate[] = "SEAGATE";static struct xpt_quirk_entry xpt_quirk_table[] = {	{		/* Reports QUEUE FULL for temporary resource shortages */		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" },		/*quirks*/0, /*mintags*/24, /*maxtags*/32	},	{		/* Reports QUEUE FULL for temporary resource shortages */		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" },		/*quirks*/0, /*mintags*/24, /*maxtags*/32	},	{		/* Reports QUEUE FULL for temporary resource shortages */		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" },		/*quirks*/0, /*mintags*/24, /*maxtags*/32	},	{		/* Broken tagged queuing drive */		{ T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},	{		/* Broken tagged queuing drive */		{ T_DIRECT, SIP_MEDIA_FIXED, "MICROP", "3391*", "x43h" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},	{		/*		 * Unfortunately, the Quantum Atlas III has the same		 * problem as the Atlas II drives above.		 * Reported by: "Johan Granlund" <johan@granlund.nu>		 *		 * For future reference, the drive with the problem was:		 * QUANTUM QM39100TD-SW N1B0		 * 		 * It's possible that Quantum will fix the problem in later		 * firmware revisions.  If that happens, the quirk entry		 * will need to be made specific to the firmware revisions		 * with the problem.		 * 		 */		/* Reports QUEUE FULL for temporary resource shortages */		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" },		/*quirks*/0, /*mintags*/24, /*maxtags*/32	},	{		/*		 * 18 Gig Atlas III, same problem as the 9G version.		 * Reported by: Andre Albsmeier		 *		<andre.albsmeier@mchp.siemens.de>		 *		 * For future reference, the drive with the problem was:		 * QUANTUM QM318000TD-S N491		 */		/* Reports QUEUE FULL for temporary resource shortages */		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" },		/*quirks*/0, /*mintags*/24, /*maxtags*/32	},	{		/*		 * Broken tagged queuing drive		 * Reported by: Bret Ford <bford@uop.cs.uop.edu>		 *         and: Martin Renters <martin@tdc.on.ca>		 */		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},		/*		 * The Seagate Medalist Pro drives have very poor write		 * performance with anything more than 2 tags.		 * 		 * Reported by:  Paul van der Zwan <paulz@trantor.xs4all.nl>		 * Drive:  <SEAGATE ST36530N 1444>		 *		 * Reported by:  Jeremy Lea <reg@shale.csir.co.za>		 * Drive:  <SEAGATE ST34520W 1281>		 *		 * No one has actually reported that the 9G version		 * (ST39140*) of the Medalist Pro has the same problem, but		 * we're assuming that it does because the 4G and 6.5G		 * versions of the drive are broken.		 */	{		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"},		/*quirks*/0, /*mintags*/2, /*maxtags*/2	},	{		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"},		/*quirks*/0, /*mintags*/2, /*maxtags*/2	},	{		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"},		/*quirks*/0, /*mintags*/2, /*maxtags*/2	},	{		/*		 * Slow when tagged queueing is enabled.  Write performance		 * steadily drops off with more and more concurrent		 * transactions.  Best sequential write performance with		 * tagged queueing turned off and write caching turned on.		 *		 * PR:  kern/10398		 * Submitted by:  Hideaki Okada <hokada@isl.melco.co.jp>		 * Drive:  DCAS-34330 w/ "S65A" firmware.		 *		 * The drive with the problem had the "S65A" firmware		 * revision, and has also been reported (by Stephen J.		 * Roznowski <sjr@home.net>) for a drive with the "S61A"		 * firmware revision.		 *		 * Although no one has reported problems with the 2 gig		 * version of the DCAS drive, the assumption is that it		 * has the same problems as the 4 gig version.  Therefore		 * this quirk entries disables tagged queueing for all		 * DCAS drives.		 */		{ T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},	{		/* Broken tagged queuing drive */		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},	{		/* Broken tagged queuing drive */ 		{ T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},	{		/*		 * Broken tagged queuing drive.		 * Submitted by:		 * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp>		 * in PR kern/9535		 */		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0	},        {		/*		 * Slow when tagged queueing is enabled. (1.5MB/sec versus		 * 8MB/sec.)		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>		 * Best performance with these drives is achieved with		 * tagged queueing turned off, and write caching turned on.		 */		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0        },        {		/*		 * Slow when tagged queueing is enabled. (1.5MB/sec versus		 * 8MB/sec.)		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>		 * Best performance with these drives is achieved with		 * tagged queueing turned off, and write caching turned on.		 */		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" },		/*quirks*/0, /*mintags*/0, /*maxtags*/0        },	{		/*		 * Doesn't handle queue full condition correctly,		 * so we need to limit maxtags to what the device		 * can handle instead of determining this automatically.		 */		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" },		/*quirks*/0, /*mintags*/2, /*maxtags*/32	},	{		/* Really only one LUN */		{			T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA*", "*"		},		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0	},	{		/* I can't believe we need a quirk for DPT volumes. */		{			T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE,			"DPT", "*", "*"		},		CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS,		/*mintags*/0, /*maxtags*/255	},	{		/*		 * Many Sony CDROM drives don't like multi-LUN probing.		 */		{			T_CDROM, SIP_MEDIA_REMOVABLE, sony,			"CD-ROM CDU*", "*"		},		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0	},	{		/*		 * This drive doesn't like multiple LUN probing.		 * Submitted by:  Parag Patel <parag@cgt.com>		 */		{			T_WORM, SIP_MEDIA_REMOVABLE, sony,			"CD-R   CDU9*", "*"		},		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0	},	{		/*		 * The 8200 doesn't like multi-lun probing, and probably		 * don't like serial number requests either.		 */		{			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",			"EXB-8200*", "*"		},		CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0	},	{		/*		 * This old revision of the TDC3600 is also SCSI-1, and		 * hangs upon serial number probing.		 */		{			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",			" TDC 3600", "U07:"		},

⌨️ 快捷键说明

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