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 + -
显示快捷键?