Index: head/release/texts/HARDWARE.TXT =================================================================== --- head/release/texts/HARDWARE.TXT (revision 64057) +++ head/release/texts/HARDWARE.TXT (revision 64058) @@ -1,876 +1,880 @@ Table of Contents ----------------- 0. Document Conventions 1. Default Configuration (GENERIC kernel) 2. Using UserConfig to change FreeBSD kernel settings 3. LINT - other possible configurations 4. Supported Hardware See TROUBLE.TXT for Q&A on known hardware problems. ========================================================================= 0. Document Conventions -- -------------------- We have `underlined' text which represents user input with `-' symbols throughout this document to differentiate it from the machine output. 1. Default (GENERIC) Configuration -- ------------------------------- The following table contains a list of all of the devices that are present in the GENERIC kernel. This is the essential part of the operating system that is placed in your root partition during the installation process. A compressed version of the GENERIC kernel is also used on the installation floppy diskette and DOS boot image. The table describes the various parameters used by the driver to communicate with the hardware in your system. There are four parameters in the table, though not all are used by each and every device: Port The starting I/O port used by the device, shown in hexadecimal. IOMem The lowest (or starting) memory address used by the device, also shown in hexadecimal. IRQ The interrupt the device uses to alert the driver to an event, given in decimal. DRQ The DMA (direct memory access) channel the device uses to move data to and from main memory, also given in decimal. If an entry in the table has `n/a' for a value then it means that the parameter in question does not apply to that device. A value of `dyn' means that the correct value should be determined automatically by the kernel when the system boots and that you don't need to worry about it. If an entry is marked with an *, it means that support is currently not available for it but should be back as soon as someone converts the driver to work within the new 4.0 framework. FreeBSD GENERIC kernel: Port IRQ DRQ IOMem Description ---- --- --- ----- --------------------------------- fdc0 3f0 6 2 n/a Floppy disk controller ata0 170 14 n/a n/a ATA/ATAPI controller ata1 170 15 n/a n/a ATA/ATAPI controller atadisk0 n/a n/a n/a n/a ATA disk drives atapicd0 n/a n/a n/a n/a ATAPI CDROM drives atapifd0 n/a n/a n/a n/a ATAPI floppy drives atapist0 n/a n/a n/a n/a ATAPI tape drives adv0 n/a n/a n/a n/a AdvanSys Narrow SCSI controllers adw0 n/a n/a n/a n/a AdvanSys Wide SCSI controllers amd0 n/a n/a n/a n/a AMD 53C974 (Tekram DC390(T)) ncr0 n/a n/a n/a n/a NCR PCI SCSI controller bt0 330 dyn dyn dyn Buslogic SCSI controller aha0 330 dyn 5 dyn Adaptec 154x/1535 SCSI controller ahb0 dyn dyn dyn dyn Adaptec 174x SCSI controller ahc0 dyn dyn dyn dyn Adaptec 274x/284x/294x SCSI controller aic0 340 11 dyn dyn Adaptec 152x/AIC-6360/AIC-6260 SCSI controller isp0 dyn dyn dyn dyn QLogic 10X0, 1240 Ultra SCSI, 1080/1280 Ultra2 SCSI, 12160 Ultra3 SCSI, 2X00 Fibre Channel SCSI controller dpt0 dyn dyn n/a n/a DPT RAID SCSI controllers amr0 dyn dyn n/a n/a AMI MegaRAID controllers mlx0 dyn dyn n/a dyn Mylex DAC960 RAID controllers wt0 300 5 1 dyn Wangtek and Archive QIC-02/QIC-36 psm0 60 12 n/a n/a PS/2 Mouse mcd0 300 10 n/a n/a Mitsumi CD-ROM matcd0 230 n/a n/a n/a Matsushita/Panasonic CD-ROM scd0 230 n/a n/a n/a Sony CD-ROM sio0 3f8 4 n/a n/a Serial Port 0 (COM1) sio1 2f8 3 n/a n/a Serial Port 1 (COM2) ppc0 dyn 7 n/a n/a Printer ports dc0 n/a n/a n/a n/a DEC/Intel 21143 cards and workalikes de0 n/a n/a n/a n/a DEC DC21x40 PCI based cards (including 21140 100bT cards) ed0 280 10 dyn d8000 WD & SMC 80xx; Novell NE1000 & NE2000; 3Com 3C503; HP PC Lan+ ep0 300 10 dyn dyn 3Com 3C509, 3C529, 3C556, 3C562D, 3C563D, 3C572, 3C574X, 3C579, 3C589 ex0 dyn dyn dyn n/a Intel EtherExpress Pro/10 cards fe0 300 dyn n/a n/a Allied-Telesyn AT1700, RE2000 and Fujitsu FMV-180 series cards. fxp0 dyn dyn n/a dyn Intel EtherExpress Pro/100B and Intel PRO/100+ Management Adapter ie0 300 10 dyn d0000 AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210; Intel EtherExpress (8/16,16[TP]) cards le0 300 5 dyn d0000 Digital Equipment EtherWorks 2 and EtherWorks 3 lnc0 280 10 n/a dyn Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL, some PCnet-PCI cards) rl0 dyn dyn n/a dyn RealTek 8129/8139 fast ethernet sf0 dyn dyn n/a dyn Adaptec AIC-6915 fast ethernet sis0 dyn dyn n/a dyn SiS 900/SiS 7016 fast ethernet sn0 0x300 10 n/a n/a SMC 91xx ethernet ste0 dyn dyn n/a dyn Sundance ST201 fast ethernet tl0 dyn dyn n/a dyn TI TNET100 'ThunderLAN' cards. tx0 dyn dyn n/a dyn SMC 9432 'Epic' fast ethernet wb0 dyn dyn n/a dyn Winbond W89C840F PCI based cards. vr0 dyn dyn n/a dyn VIA VT3043/VT86C100A PCI based cards. vx0 dyn dyn n/a dyn 3Com 3c59x ((Fast) Etherlink III) xl0 dyn dyn n/a dyn 3Com 3c900, 3c905, 3c905B, 3c905C, 3c980, 3cSOHO100 ((Fast) Etherlink XL) cs0 0x300 dyn n/a n/a Crystal Semiconductor CS89x0-based cards. --- End of table --- If the hardware in your computer is not set to the same settings as those shown in the table and the item in conflict is not marked 'dyn', you will have to either reconfigure your hardware or use UserConfig to reconfigure the kernel to match the way your hardware is currently set (see the next section). If the settings do not match, the kernel may be unable to locate or reliably access the devices in your system. 2. Using UserConfig to change FreeBSD kernel settings -- -------------------------------------------------- The FreeBSD kernel on the install floppy contains drivers for every piece of hardware that could conceivably be used to install the rest of the system with. Unfortunately, PC hardware being what it is, some of these devices can be difficult to detect accurately, and for some, the process of detecting another can cause irreversible confusion. To make this process easier, FreeBSD provides UserConfig. With this tool the user can configure and disable device drivers before the kernel is loaded, avoiding potential conflicts, and eliminating the need to reconfigure hardware to suit the default driver settings. Once FreeBSD is installed, it will remember the changes made using UserConfig, so that they only need be made once. It is important to disable drivers that are not relevant to a system in order to minimize the possibility of interference, which can cause problems that are difficult to track down. UserConfig features a command line interface for users with serial consoles or a need to type commands, and a full screen 'visual' interface, which provides point-and-shoot configuration functionality. Here is a sample UserConfig screen shot in 'visual' mode: ---Active Drivers---------------------------10 Conflicts------Dev---IRQ--Port-- Storage : (Collapsed) Network : NE1000,NE2000,3C503,WD/SMC80xx Ethernet adapters CONF ed0 5 0x280 NE1000,NE2000,3C503,WD/SMC80xx Ethernet adapters CONF ed1 5 0x300 Communications : (Collapsed) Input : (Collapsed) Multimedia : ---Inactive Drivers-------------------------------------------Dev-------------- Storage : Network : (Collapsed) Communications : Input : Multimedia : ---Parameters-for-device-ed0--------------------------------------------------- Port address : 0x280 Memory address : 0xd8000 IRQ number : 5 Memory size : 0x2000 Flags : 0x0000 ------------------------------------------------------------------------------- IO Port address (Hexadecimal, 0x1-0x2000) [TAB] Change fields [Q] Save device parameters The screen is divided into four sections : - Active Drivers. Listed here are the device drivers that are currently enabled, and their basic parameters. - Inactive Drivers. These drivers are present, but are disabled. - Parameter edit field. This area is used for editing driver parameters. - Help area. Keystroke help is displayed here. One of the Active and Inactive lists is always in use, and the current entry in the list will be shown with a highlight bar. If there are more entries in a list than can be shown, it will scroll. The bar can be moved up and down using the cursor keys, and moved between lists with the TAB key. Drivers in the Active list may be marked "CONF". This indicates that one or more of their parameters conflicts with another device, and indicates a potential for problems. The total number of conflicts is displayed at the top of the screen. As a general rule, conflicts should be avoided, either by disabling conflicting devices that are not present in the system, or by altering their configuration so that they match the installed hardware. In the list areas, drivers are grouped by their basic function. Groups can be 'Collapsed' to simplify the display (this is the default state for all groups). If a group is collapsed, it will be shown with '(Collapsed)' in the list, as above. To Expand a Collapsed group, position the highlight bar over the group heading and press Enter. To Collapse it again, repeat the process. When a device driver in the Active list is highlighted, its full parameters are displayed in the Parameter edit area. Note that not all drivers use all possible parameters, and some hardware supported by drivers may not use all the parameters the driver supports. To disable a driver, go to the Active list, Expand the group it is in, highlight the driver and press Del. The driver will move to its group in the Inactive list. (If the group is collapsed or off the screen, you may not see the driver in its new location.) To enable a driver, go to the Inactive list, Expand the group it is in, highlight the driver and press Enter. The highlight will move to the Active list, and the driver you have just enabled will be highlighted, ready to be configured. To configure a driver, go to the Active list, Expand the group it is in, highlight the driver and press Enter. The cursor will move to the Parameter edit area, and the device's parameters may be edited. While editing parameters, the TAB and cursor keys can be used to move between fields. Most numeric values (except IRQ) are entered in hexadecimal, as indicated by the '0x' at the beginning of the field. The allowable values for a given field are show in the Key Help area when the field is active. To finish configuring a driver, press 'Q'. Note that PCI, Microchannel and EISA devices can be probed reliably, therefore they are not shown in the table above nor can their settings be changed using UserConfig. 3. LINT - other possible configurations -- ------------------------------------ The following drivers are not in the GENERIC kernel but remain available to those who do not mind compiling a custom kernel (see section 6 of FreeBSD.FAQ). The LINT configuration file (/sys/i386/conf/LINT) also contains prototype entries for just about every device supported by FreeBSD and is a good general reference. The device names and a short description of each are listed below. The port numbers, etc, are not meaningful here since you will need to compile a custom kernel to gain access to these devices anyway and can thus adjust the addresses to match the hardware in your computer in the process. The LINT file contains prototype entries for all of the below which you can easily cut-and-paste into your own file (or simply copy LINT and edit it to taste): ata: Alternate high-performance driver for IDE controllers ctx: Cortex-I frame grabber cx: Cronyx/Sigma multiport sync/async cy: Cyclades high-speed serial driver el: 3Com 3C501 fea: DEC DEFEA EISA FDDI adapter fpa: DEC DEFPA PCI FDDI adapter gp: National Instruments AT-GPIB and AT-GPIB/TNT board gsc: Genius GS-4500 hand scanner gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX gusxvi: Gravis Ultrasound 16-bit PCM hea: Efficient ENI-155p ATM PCI adapter hfa: FORE PCA-200E ATM PCI adapter isic: isdn4bsd Siemens ISDN Chipset driver joy: Joystick labpc: National Instrument's Lab-PC and Lab-PC+ meteor: Matrox Meteor frame-grabber card bktr: Brooktree Bt848 / Bt 878 based frame-grabber cards. mpu: Roland MPU-401 stand-alone card mse: Microsoft, Logitech, ATI bus mouse ports mss: Microsoft Sound System opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum pas: ProAudioSpectrum PCM and MIDI pca: PCM audio ("/dev/audio") through your PC speaker pcm: PCM audio on most modern PCI/ISA audio codecs psm: PS/2 mouse port rc: RISCom/8 multiport card sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum sbmidi: SoundBlaster 16 MIDI interface sbxvi: SoundBlaster 16 si: Specialix SI/XIO/SX (old and enhanced ISA, PCI, EISA) serial sym: Alternate high-performance driver for NCR/LSI Logic SCSI controllers spigot: Creative Labs Video Spigot video-acquisition board uart: Stand-alone 6850 UART for MIDI wds: Western Digital WD7000 IDE --- end of list --- 4. Supported Hardware -- ------------------ FreeBSD currently runs on a wide variety of ISA, VLB, EISA, Microchannel and PCI bus based PC's, ranging from 386sx to Pentium class machines (though the 386sx is not recommended). Support for generic IDE or ESDI drive configurations, various SCSI controller, network and serial cards is also provided. What follows is a list of all peripherals currently known to work with FreeBSD. Other configurations may also work, we have simply not as yet received confirmation of this. 4.1. Disk Controllers ---- ---------------- IDE ATA controllers: Acerlabs Aladdin AMD 756 CMD 646 Cypress 82C693 HighPoint HPT366 Intel PIIX Intel PIIX3 Intel PIIX4 Intel ICH Promise Fasttrak-33 Promise Fasttrak-66 Promise Ultra-33 Promise Ultra-66 SiS 5591 VIA 82C586 VIA 82C686 WD1003 (any generic MFM/RLL - obsolete) WD1007 (any generic ESDI - obsolete) * Note: now that the wd driver has been replaced by the ata driver framework, which does not have bad144 support, the true MFM/RLL/ESDI drives/adapters have become obsolete. Adaptec 1535 ISA SCSI controllers Adaptec 154x series ISA SCSI controllers Adaptec 174x series EISA SCSI controller in standard and enhanced mode. Adaptec 274X/284X/2920C/294x/2950/19160/29160/3940/3950/39160 Narrow/Wide/Twin series EISA/VLB/PCI SCSI controllers. Adaptec AIC7850, AIC7860, AIC7880, AIC789x, on-board SCSI controllers. Adaptec 1510 series ISA SCSI controllers (not for bootable devices) Adaptec 152x series ISA SCSI controllers Adaptec AIC-6260 and AIC-6360 based boards, which includes the AHA-152x and SoundBlaster SCSI cards. AdvanSys SCSI controllers (all models). BusLogic MultiMaster controllers: [ Please note that BusLogic/Mylex "Flashpoint" adapters are NOT yet supported ] BusLogic MultiMaster "W" Series Host Adapters: BT-948, BT-958, BT-958D BusLogic MultiMaster "C" Series Host Adapters: BT-946C, BT-956C, BT-956CD, BT-445C, BT-747C, BT-757C, BT-757CD, BT-545C, BT-540CF BusLogic MultiMaster "S" Series Host Adapters: BT-445S, BT-747S, BT-747D, BT-757S, BT-757D, BT-545S, BT-542D, BT-742A, BT-542B BusLogic MultiMaster "A" Series Host Adapters: BT-742A, BT-542B AMI FastDisk controllers that are true BusLogic MultiMaster clones are also supported. DPT SmartCACHE Plus, SmartCACHE III, SmartRAID III, SmartCACHE IV and SmartRAID IV SCSI/RAID controllers are supported. The DPT SmartRAID/CACHE V is not yet supported. AMI MegaRAID Express and Enterprise family RAID controllers: MegaRAID 418 MegaRAID Enterprise 1200 (428) MegaRAID Enterprise 1300 MegaRAID Enterprise 1400 MegaRAID Enterprise 1500 MegaRAID Elite 1500 MegaRAID Express 200 MegaRAID Express 300 Dell PERC Dell PERC 2/SC Dell PERC 2/DC Some HP NetRAID controllers are OEM versions of AMI designs, and these are also supported. Mylex DAC960 and DAC1100 RAID controllers with 2.x, 3.x, 4.x and 5.x firmware: DAC960P DAC960PD DAC960PDU DAC960PL DAC960PJ DAC960PG AcceleRAID 150 AcceleRAID 250 eXtremeRAID 1100 This list includes controllers sold by Digital/Compaq in Alpha systems in the StorageWorks family, eg. KZPSC, KZPAC. EISA adaptes are not supported. Qlogic Controllers: Qlogic 1020, 1040 SCSI and Ultra SCSI Host Adaptes Qlogic 1240 dual Ultra SCSI controllers Qlogic 1080 Ultra2 LVD and 1280 Dual Ultra2 LVD Controllers Qlogic 12160 Ultra3 LVD Controllers Qlogic 2100 and Qlogic 2200 Fibre Channel SCSI Controllers SymBios (formerly NCR) 53C810, 53C810a, 53C815, 53C820, 53C825a, 53C860, 53C875, 53C875e, 53C875j, 53C885, 53C895 and 53C896 PCI SCSI controllers: ASUS SC-200 Data Technology DTC3130 (all variants) DawiControl DC2976UW Diamond FirePort (all) NCR cards (all) Symbios cards (all) Tekram DC390W, 390U and 390F Tyan S1365 DTC 3290 EISA SCSI controller in 1542 emulation mode. Tekram DC390 and DC390T controllers (maybe other cards based on the AMD 53c974 as well). With all supported SCSI controllers, full support is provided for SCSI-I & SCSI-II peripherals, including hard disks, optical disks, tape drives (including DAT and 8mm Exabyte), medium changers, processor target devices and CDROM drives. WORM devices that support CDROM commands are supported for read-only access by the CDROM driver. WORM/CD-R/CD-RW writing support is provided by cdrecord, which is in the ports tree. The following CD-ROM type systems are supported at this time: (cd) SCSI interface (also includes SoundBlaster SCSI) (matcd) Matsushita/Panasonic (Creative SoundBlaster) proprietary interface (562/563 models) (scd) Sony proprietary interface (all models) (acd) ATAPI IDE interface Unmaintained drivers, they might or might not work for your hardware: (mcd) Mitsumi proprietary CD-ROM interface (all models) 4.2. Network cards ---- ------------- Adaptec Duralink PCI fast ethernet adapters based on the Adaptec AIC-6915 fast ethernet controller chip, including the following: ANA-62011 64-bit single port 10/100baseTX adapter ANA-62022 64-bit dual port 10/100baseTX adapter ANA-62044 64-bit quad port 10/100baseTX adapter ANA-69011 32-bit single port 10/100baseTX adapter ANA-62020 64-bit single port 100baseFX adapter Allied-Telesyn AT1700 and RE2000 cards Alteon Networks PCI gigabit ethernet NICs based on the Tigon 1 and Tigon 2 chipsets, including the following: 3Com 3c985-SX (Tigon 1 and 2) Alteon AceNIC (Tigon 1 and 2) DEC/Compaq EtherWORKS 1000 NEC Gigabit Ethernet Netgear GA620 (Tigon 2) Silicon Graphics Gigabit Ethernet AMD PCnet/PCI (79c970 & 53c974 or 79c974) SMC Elite 16 WD8013 ethernet interface, and most other WD8003E, WD8003EBT, WD8003W, WD8013W, WD8003S, WD8003SBT and WD8013EBT based clones. SMC Elite Ultra is also supported. RealTek 8129/8139 fast ethernet NICs including the following: Accton "Cheetah" EN1027D (MPX 5030/5038; RealTek 8139 clone?) Allied Telesyn AT2550 Allied Telesyn AT2500TX Genius GF100TXR (RTL8139) KTX-9130TX 10/100 Fast Ethernet NDC Communications NE100TX-E Netronix Inc. EA-1210 NetEther 10/100 OvisLink LEF-8129TX OvisLink LEF-8139TX SMC EZ Card 10/100 PCI 1211-TX Lite-On 82c168/82c169 PNIC fast ethernet NICs including the following: Kingston KNE110TX LinkSys EtherFast LNE100TX Matrox FastNIC 10/100 NetGear FA310-TX Rev. D1 Macronix 98713, 98713A, 98715, 98715A and 98725 fast ethernet NICs Accton EN1217 (98715A) Adico AE310TX (98715A) CNet Pro120A (98713 or 98713A) CNet Pro120B (98715) NDC Communications SFA100A (98713A) SVEC PN102TX (98713) Macronix/Lite-On PNIC II LC82C115 fast ethernet NICs including the following: LinkSys EtherFast LNE100TX Version 2 Winbond W89C840F fast ethernet NICs including the following: Trendware TE100-PCIE VIA Technologies VT3043 "Rhine I" and VT86C100A "Rhine II" fast ethernet NICs including the following: AOpen/Acer ALN-320 D-Link DFE-530TX Hawking Technologies PN102TX Silicon Integrated Systems SiS 900 and SiS 7016 PCI fast ethernet NICs National Semiconductor DP83815 fast ethernet NICs including the following: NetGear FA312-TX Sundance Technologies ST201 PCI fast ethernet NICs including the following: D-Link DFE-550TX SysKonnect SK-984x PCI gigabit ethernet cards including the following: SK-9841 1000baseLX single mode fiber, single port SK-9842 1000baseSX multimode fiber, single port SK-9843 1000baseLX single mode fiber, dual port SK-9844 1000baseSX multimode fiber, dual port Texas Instruments ThunderLAN PCI NICs, including the following: Compaq Netelligent 10, 10/100, 10/100 Proliant, 10/100 Dual-Port Compaq Netelligent 10/100 TX Embedded UTP, 10 T PCI UTP/Coax, 10/100 TX UTP Compaq NetFlex 3P, 3P Integrated, 3P w/ BNC Olicom OC-2135/2138, OC-2325, OC-2326 10/100 TX UTP Racore 8165 10/100baseTX Racore 8148 10baseT/100baseTX/100baseFX multi-personality ADMtek Inc. AL981-based PCI fast ethernet NICs ADMtek Inc. AN985-based PCI fast ethernet NICs ADMtek Inc. AN986-based USB ethernet NICs including the following: Billionton USB100 D-Link DSB-650TX LinkSys USB100TX Melco Inc. LU-ATX SMC 2202USB CATC USB-EL1210A-based USB ethernet NICs including the following: Belkin F5U011 Belkin F5U111 CATC Netmate CATC Netmate II Kawasaki LSI KU5KUSB101B-based USB ethernet NICs including the following: 3Com 3c19250 ADS Technologies USB-10BT ATen UC10T Corega USB-T D-Link DSB-650 Entrega NET-USB-E45 LinkSys USB10T Netgear EA101 Peracom USB Ethernet Adapter SMC 2102USB SMC 2104USB ASIX Electronics AX88140A PCI NICs, including the following: Alfa Inc. GFC2204 CNet Pro110B DEC EtherWORKS III NICs (DE203, DE204, and DE205) DEC EtherWORKS II NICs (DE200, DE201, DE202, and DE422) DEC DC21040, DC21041, or DC21140 based NICs (SMC Etherpower 8432T, DE245, etc) DEC FDDI (DEFPA/DEFEA) NICs Davicom DM9100 and DM9102 PCI fast ethernet NICs, including the following: Jaton Corporation XPressNet Efficient ENI-155p ATM PCI FORE PCA-200E ATM PCI Fujitsu MB86960A/MB86965A HP PC Lan+ cards (model numbers: 27247B and 27252A). Intel EtherExpress (not recommended due to driver instability) Intel EtherExpress Pro/10 Intel EtherExpress Pro/100B PCI Fast Ethernet Intel PRO/100+ Management Adapter Intel Gigabit Ethernet (PRO/1000) Isolan AT 4141-0 (16 bit) Isolink 4110 (8 bit) Novell NE1000, NE2000, and NE2100 ethernet interface. PCI network cards emulating the NE2000: RealTek 8029, NetVin 5000, Winbond W89C940, Surecom NE-34, VIA VT86C926, etc. 3Com 3C501 cards 3Com 3C503 Etherlink II 3Com 3C507 Etherlink 16/TP 3Com 3C509, 3C529, 3C556, 3C562D, 3C563D, 3C572, 3C574X, 3C579, 3C589/589B/589C/589D/589E/XE589ET/574TX/574B (PC-card/PCMCIA), 3C590/592/595/900/905/905B/905C PCI and EISA (Fast) Etherlink III / (Fast) Etherlink XL 3Com 3c980/3c980B Fast Etherlink XL server adapter 3Com 3cSOHO100-TX OfficeConnect adapter Toshiba ethernet cards NE2000 compatible PC-Card (PCMCIA) Ethernet/FastEthernet cards, including the following: AR-P500 Ethernet card Accton EN2212/EN2216/UE2216(OEM) Allied Telesis CentreCOM LA100-PCM_V2 AmbiCom 10BaseT card BayNetworks NETGEAR FA410TXC Fast Ethernet CNet BC40 adapter COREGA Ether PCC-T/EtherII PCC-T Compex Net-A adapter CyQ've ELA-010 D-Link DE-650/660 Danpex EN-6200P2 IO DATA PCLATE IBM Creditcard Ethernet I/II IC-CARD Ethernet/IC-CARD+ Ethernet Linksys EC2T/PCMPC100 Melco LPC-T NDC Ethernet Instant-Link National Semiconductor InfoMover NE4100 Network Everywhere Ethernet 10BaseT PC Card Planex FNW-3600-T Socket LP-E Surecom EtherPerfect EP-427 Telecom Device SuperSocket RE450T Megahertz X-Jack Ethernet PC-Card CC-10BT 4.3. USB ---- --- A range of USB peripherals are supported. Owing to the generic nature of most USB devices, with some exceptions any device of a given class will be supported even if not explicitly listed here. USB keyboards. USB mice. USB printers and USB to parallel printer conversion cables. USB hubs. USB ethernet controllers. USB Host Controllers: ALi Aladdin-V. AMD-756. CMD Tech 670 & 673. Intel 82371SB (PIIX3). Intel 82371AB and EB chipsets (PIIX4). NEC uPD 9210. OPTi 82C861 (FireLink). SiS 5571. VIA 83C572 USB. and any other UHCI or OHCI compliant motherboard chipset (no exceptions known). PCI plug-in USB host controllers: ADS Electronics PCI plug-in card (2 ports). Entrega PCI plug-in card (4 ports). Specific devices reported to be working (see for USB ethernet devices supported above): ActiveWire I/O Board. Agiler Mouse 29UO. Andromeda hub. Apple iMac mouse. Apple iMac keyboard. ATen parallel printer adapter. Belkin F5U002 parallel printer adapter. Belkin Mouse. BTC BTC7935 keyboard with mouse port. Cherry G81-3504 keyboard. Chic mouse. Cypress mouse. Entrega USB-to-parallel printer adapter. Genius Niche mouse. Iomega USB Zip 100Mb (primitive support still). Kensington Mouse-in-a-Box. Logitech M2452 keyboard. Logitech wheel mouse (3 buttons). Logitech PS/2 / USB mouse (3 buttons). MacAlly mouse (3 buttons). MacAlly self powered hub (4 ports). MacAlly iKey keyboard. +Matshita CF-VFDU03 floppy drive. + Microsoft IntelliMouse (3 buttons). Microsoft keyboard. Microtech USB-SCSI-HD 50 USB to SCSI cable. NEC hub. + +Panasonic floppy drive. Trust Ami Mouse (3 buttons). Y-E Data floppy drive (720/1.44/2.88Mb). 4.4. ISDN (European DSS1 [Q.921/Q.931] protocol) ---- ------------------------------------------- Asuscom ISDNlink 128K PnP AVM A1 AVM Fritz!Card classic AVM Fritz!Card PCI Creatix ISDN-S0/8 Creatix ISDN-S0/16 Creatix ISDN-S0 PnP Dr.Neuhaus Niccy 1008 Dr.Neuhaus Niccy 1016 Dr.Neuhaus Niccy GO@ (ISA PnP) ELSA QuickStep 1000pro ISA ELSA MicroLink ISDN/PCI (same as ELSA QuickStep 1000pro PCI) ELSA PCC-16 Sagem Cybermod (ISA PnP) Sedlbauer Win Speed Siemens I-Surf 2.0 Teles S0/8 Teles S0/16 Teles S0/16.3 (the "c" Versions - like 16.3c - are unsupported !) Teles S0/16.3 PnP 4.5. Misc ---- ---- AST 4 port serial card using shared IRQ. ARNET 8 port serial card using shared IRQ. ARNET (now Digiboard) Sync 570/i high-speed serial. Boca BB1004 4-Port serial card (Modems NOT supported) Boca IOAT66 6-Port serial card (Modems supported) Boca BB1008 8-Port serial card (Modems NOT supported) Boca BB2016 16-Port serial card (Modems supported) Cyclades Cyclom-y Serial Board. STB 4 port card using shared IRQ. SDL Communications Riscom/8 Serial Board. SDL Communications RISCom/N2 and N2pci high-speed sync serial boards. Specialix SI/XIO/SX multiport serial cards, with both the older SIHOST2.x and the new "enhanced" (transputer based, aka JET) host cards. ISA, EISA and PCI are supported. Stallion multiport serial boards: EasyIO, EasyConnection 8/32 & 8/64, ONboard 4/16 and Brumby. HP4020, HP6020, Philips CDD2000/CDD2660 and Plasmon CD-R drives. Bus mice PS/2 mice Standard PC Joystick X-10 power controllers GPIB and Transputer drivers. Genius and Mustek hand scanners. Lucent Technologies WaveLAN/IEEE 802.11 PCMCIA and ISA standard speed (2Mbps) and turbo speed (6Mbps) wireless network adapters and workalikes (NCR WaveLAN/IEEE 802.11, Cabletron RoamAbout 802.11 DS). Note: the ISA versions of these adapters are actually PCMCIA cards combined with an ISA to PCMCIA bridge card, so both kinds of devices work with the same driver. Aironet 4500/4800 series 802.11 wireless adapters. The PCMCIA, PCI and ISA adapters are all supported. 4.6. Microchannel ---- ------------ Experimental support for Microchannel systems is new in FreeBSD 4.0 Drivers with support for Microchannel peripherals are: aha: Adaptec AHA-1640 SCSI controller bt: Buslogic BT-640A and Storage Dimensions SDC3211 SCSI controllers ep: 3Com 3C529 network adapter 4.7. Multimedia ---- ---------- Soundcards supported by newpcm: Advance Asound 100, 110 and Logic ALS120 Crystal Semiconductor CS461x/462x/428x ENSONIQ ES1370/1371 soundcards including the following: ENSONIQ AudioPCI64 ES1370/1371 ESS ES1868, ES1869, ES1879 and ES1888 Gravis UltraSound MAX/PnP MSS/WSS Compatible DSPs NeoMagic 256AV/ZX OPTi 931/82C931 SoundBlaster, Soundblaster Pro, Soundblaster AWE-32, Soundblaster AWE-64 Trident 4DWave DX/NX Matrox Meteor Video frame grabber Creative Labs Video Spigot frame grabber Cortex1 frame grabber Various Frame grabbers based on Brooktree Bt848 and Bt878 chip. Index: head/share/man/man4/umass.4 =================================================================== --- head/share/man/man4/umass.4 (revision 64057) +++ head/share/man/man4/umass.4 (revision 64058) @@ -1,112 +1,112 @@ .\" Copyright (c) 1999 .\" Nick Hibma . 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. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by Bill Paul. .\" 4. Neither the name of the author nor the names of any co-contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY NICK HIBMA 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 NICK HIBMA OR THE VOICES IN HIS HEAD .\" 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. .\" .\" $FreeBSD$ .\" .Dd May 3, 1999 .Dt UMASS 4 .Os FreeBSD .Sh NAME .Nm umass .Nd USB Mass Storage Devices Driver .Sh SYNOPSIS .Cd "device umass" .Sh DESCRIPTION The .Nm driver provides support for Mass Storage devices that attach to the USB port. Supported are .Pp .Bl -tag -compact -width xxxxxx .It Iomega USB Zip 100 drive .It Iomega USB Zip 250 drive -.It Y-E Data Flashbuster-U -.It VAIO floppy drive .It Microtech International, Inc. USB-SCSI-HD 50 USB to SCSI cable. +.It Panasonic ("Matshita FDD CF-VFDU03") +.It VAIO floppy drive (includes Y-E Data Flashbuster-U) .El .Pp .Nm usb and one of .Nm uhci or .Nm ohci must be configured in the kernel as well. Last but not least, support for SCSI drives, .Nm da .Sh EXAMPLE .Dl device umass .Dl device scbus .Dl device da .Dl device pass .Pp Add the .Nm umass driver to the kernel. .Pp .Dl camcontrol rescan 0 .Pp Rescan a Zip drive that was added after boot. The command above assumes that the Zip drive is the first SCSI bus in the system. .Pp .Dl disklabel -w -r da0 zip100 .Dl newfs da0c .Dl mount -t ufs /dev/da0c /mnt .Pp Write a disklabel to the Zip drive (see .Nm vpo for the .Nm disktab entry), creates the filesystem and mounts the new filesystem on /mnt. .Pp .Dl newfs_msdos /dev/da0 .Pp Create a new FAT type filesystem. .Sh SEE ALSO .Xr ohci 4 , .Xr uhci 4 , .Xr usb 4 , .Xr vpo 4 , .Xr disktab 5 , .Xr camcontrol 8 , .Xr disklabel 8 .\".Sh HISTORY .Sh AUTHORS The .Nm umass driver was written by .An MAEKAWA Masahide Aq bishop@rr.iij4u.or.jp and .An Nick Hibma Aq n_hibma@freebsd.org . .Pp This manual page was written by .An Nick Hibma Aq n_hibma@freebsd.org . Index: head/sys/cam/scsi/scsi_da.c =================================================================== --- head/sys/cam/scsi/scsi_da.c (revision 64057) +++ head/sys/cam/scsi/scsi_da.c (revision 64058) @@ -1,1602 +1,1608 @@ /* * Implementation of SCSI Direct Access Peripheral driver for CAM. * * Copyright (c) 1997 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. * * $FreeBSD$ */ #ifdef _KERNEL #include "opt_hw_wdog.h" #endif /* _KERNEL */ #include #ifdef _KERNEL #include #include #include #endif /* _KERNEL */ #include #include #include #include #include #include #include #include #include #ifndef _KERNEL #include #include #endif /* _KERNEL */ #include #include #include #include #include #include #ifndef _KERNEL #include #endif /* !_KERNEL */ #ifdef _KERNEL typedef enum { DA_STATE_PROBE, DA_STATE_NORMAL } da_state; typedef enum { DA_FLAG_PACK_INVALID = 0x001, DA_FLAG_NEW_PACK = 0x002, DA_FLAG_PACK_LOCKED = 0x004, DA_FLAG_PACK_REMOVABLE = 0x008, DA_FLAG_TAGGED_QUEUING = 0x010, DA_FLAG_NEED_OTAG = 0x020, DA_FLAG_WENT_IDLE = 0x040, DA_FLAG_RETRY_UA = 0x080, DA_FLAG_OPEN = 0x100 } da_flags; typedef enum { DA_Q_NONE = 0x00, DA_Q_NO_SYNC_CACHE = 0x01, DA_Q_NO_6_BYTE = 0x02 } da_quirks; typedef enum { DA_CCB_PROBE = 0x01, DA_CCB_BUFFER_IO = 0x02, DA_CCB_WAITING = 0x03, DA_CCB_DUMP = 0x04, DA_CCB_TYPE_MASK = 0x0F, DA_CCB_RETRY_UA = 0x10 } da_ccb_state; /* Offsets into our private area for storing information */ #define ccb_state ppriv_field0 #define ccb_bp ppriv_ptr1 struct disk_params { u_int8_t heads; u_int16_t cylinders; u_int8_t secs_per_track; u_int32_t secsize; /* Number of bytes/sector */ u_int32_t sectors; /* total number sectors */ }; struct da_softc { struct bio_queue_head bio_queue; struct devstat device_stats; SLIST_ENTRY(da_softc) links; LIST_HEAD(, ccb_hdr) pending_ccbs; da_state state; da_flags flags; da_quirks quirks; int minimum_cmd_size; int ordered_tag_count; struct disk_params params; struct disk disk; union ccb saved_ccb; }; struct da_quirk_entry { struct scsi_inquiry_pattern inq_pat; da_quirks quirks; }; static struct da_quirk_entry da_quirk_table[] = { { /* * This particular Fujitsu drive doesn't like the * synchronize cache command. * Reported by: Tom Jackson */ {T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE }, { /* * This drive doesn't like the synchronize cache command * either. Reported by: Matthew Jacob * in NetBSD PR kern/6027, August 24, 1998. */ {T_DIRECT, SIP_MEDIA_FIXED, "MICROP", "2217*", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE }, { /* * This drive doesn't like the synchronize cache command * either. Reported by: Hellmuth Michaelis (hm@kts.org) * (PR 8882). */ {T_DIRECT, SIP_MEDIA_FIXED, "MICROP", "2112*", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE }, { /* * Doesn't like the synchronize cache command. * Reported by: Blaz Zupan */ {T_DIRECT, SIP_MEDIA_FIXED, "NEC", "D3847*", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE }, { /* * Doesn't work correctly with 6 byte reads/writes. * Returns illegal request, and points to byte 9 of the * 6-byte CDB. * Reported by: Adam McDougall */ {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "VIKING 4*", "*"}, /*quirks*/ DA_Q_NO_6_BYTE }, { /* * See above. */ {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "VIKING 2*", "*"}, /*quirks*/ DA_Q_NO_6_BYTE }, { /* * This USB floppy drive uses the UFI command set. This * command set is a derivative of the ATAPI command set and * does not support READ_6 commands only READ_10. It also does * not support sync cache (0x35). */ {T_DIRECT, SIP_MEDIA_REMOVABLE, "Y-E DATA", "USB-FDU", "*"}, /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE + }, + { + /* Another USB floppy */ + {T_DIRECT, SIP_MEDIA_REMOVABLE, "MATSHITA", "FDD CF-VFDU*","*"}, + /*quirks*/ DA_Q_NO_6_BYTE|DA_Q_NO_SYNC_CACHE } + }; static d_open_t daopen; static d_close_t daclose; static d_strategy_t dastrategy; static d_ioctl_t daioctl; static d_dump_t dadump; static periph_init_t dainit; static void daasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); static periph_ctor_t daregister; static periph_dtor_t dacleanup; static periph_start_t dastart; static periph_oninv_t daoninvalidate; static void dadone(struct cam_periph *periph, union ccb *done_ccb); static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags); static void daprevent(struct cam_periph *periph, int action); static void dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap); static timeout_t dasendorderedtag; static void dashutdown(void *arg, int howto); #ifndef DA_DEFAULT_TIMEOUT #define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */ #endif /* * DA_ORDEREDTAG_INTERVAL determines how often, relative * to the default timeout, we check to see whether an ordered * tagged transaction is appropriate to prevent simple tag * starvation. Since we'd like to ensure that there is at least * 1/2 of the timeout length left for a starved transaction to * complete after we've sent an ordered tag, we must poll at least * four times in every timeout period. This takes care of the worst * case where a starved transaction starts during an interval that * meets the requirement "don't send an ordered tag" test so it takes * us two intervals to determine that a tag must be sent. */ #ifndef DA_ORDEREDTAG_INTERVAL #define DA_ORDEREDTAG_INTERVAL 4 #endif static struct periph_driver dadriver = { dainit, "da", TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0 }; DATA_SET(periphdriver_set, dadriver); #define DA_CDEV_MAJOR 13 #define DA_BDEV_MAJOR 4 /* For 2.2-stable support */ #ifndef D_DISK #define D_DISK 0 #endif static struct cdevsw da_cdevsw = { /* open */ daopen, /* close */ daclose, /* read */ physread, /* write */ physwrite, /* ioctl */ daioctl, /* poll */ nopoll, /* mmap */ nommap, /* strategy */ dastrategy, /* name */ "da", /* maj */ DA_CDEV_MAJOR, /* dump */ dadump, /* psize */ nopsize, /* flags */ D_DISK, /* bmaj */ DA_BDEV_MAJOR }; static struct cdevsw dadisk_cdevsw; static SLIST_HEAD(,da_softc) softc_list; static struct extend_array *daperiphs; static int daopen(dev_t dev, int flags, int fmt, struct proc *p) { struct cam_periph *periph; struct da_softc *softc; struct disklabel *label; int unit; int part; int error; int s; unit = dkunit(dev); part = dkpart(dev); periph = cam_extend_get(daperiphs, unit); if (periph == NULL) return (ENXIO); softc = (struct da_softc *)periph->softc; CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("daopen: dev=%s (unit %d , partition %d)\n", devtoname(dev), unit, part)); if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { return (error); /* error code from tsleep */ } if (cam_periph_acquire(periph) != CAM_REQ_CMP) return(ENXIO); softc->flags |= DA_FLAG_OPEN; s = splsoftcam(); if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) { /* Invalidate our pack information. */ disk_invalidate(&softc->disk); softc->flags &= ~DA_FLAG_PACK_INVALID; } splx(s); /* Do a read capacity */ { struct scsi_read_capacity_data *rcap; union ccb *ccb; rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), M_TEMP, M_WAITOK); ccb = cam_periph_getccb(periph, /*priority*/1); scsi_read_capacity(&ccb->csio, /*retries*/1, /*cbfncp*/dadone, MSG_SIMPLE_Q_TAG, rcap, SSD_FULL_SIZE, /*timeout*/60000); ccb->ccb_h.ccb_bp = NULL; error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0, /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO, &softc->device_stats); xpt_release_ccb(ccb); if (error == 0) { dasetgeom(periph, rcap); } free(rcap, M_TEMP); } if (error == 0) { struct ccb_getdev cgd; /* Build label for whole disk. */ label = &softc->disk.d_label; bzero(label, sizeof(*label)); label->d_type = DTYPE_SCSI; /* * Grab the inquiry data to get the vendor and product names. * Put them in the typename and packname for the label. */ xpt_setup_ccb(&cgd.ccb_h, periph->path, /*priority*/ 1); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); strncpy(label->d_typename, cgd.inq_data.vendor, min(SID_VENDOR_SIZE, sizeof(label->d_typename))); strncpy(label->d_packname, cgd.inq_data.product, min(SID_PRODUCT_SIZE, sizeof(label->d_packname))); label->d_secsize = softc->params.secsize; label->d_nsectors = softc->params.secs_per_track; label->d_ntracks = softc->params.heads; label->d_ncylinders = softc->params.cylinders; label->d_secpercyl = softc->params.heads * softc->params.secs_per_track; label->d_secperunit = softc->params.sectors; if (((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)) { daprevent(periph, PR_PREVENT); } /* * Check to see whether or not the blocksize is set yet. * If it isn't, set it and then clear the blocksize * unavailable flag for the device statistics. */ if ((softc->device_stats.flags & DEVSTAT_BS_UNAVAILABLE) != 0){ softc->device_stats.block_size = softc->params.secsize; softc->device_stats.flags &= ~DEVSTAT_BS_UNAVAILABLE; } } if (error != 0) { if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) { daprevent(periph, PR_ALLOW); } } cam_periph_unlock(periph); return (error); } static int daclose(dev_t dev, int flag, int fmt, struct proc *p) { struct cam_periph *periph; struct da_softc *softc; int unit; int error; unit = dkunit(dev); periph = cam_extend_get(daperiphs, unit); if (periph == NULL) return (ENXIO); softc = (struct da_softc *)periph->softc; if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { return (error); /* error code from tsleep */ } if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { union ccb *ccb; ccb = cam_periph_getccb(periph, /*priority*/1); scsi_synchronize_cache(&ccb->csio, /*retries*/1, /*cbfcnp*/dadone, MSG_SIMPLE_Q_TAG, /*begin_lba*/0,/* Cover the whole disk */ /*lb_count*/0, SSD_FULL_SIZE, 5 * 60 * 1000); cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, /*sense_flags*/SF_RETRY_UA, &softc->device_stats); if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { int asc, ascq; int sense_key, error_code; scsi_extract_sense(&ccb->csio.sense_data, &error_code, &sense_key, &asc, &ascq); if (sense_key != SSD_KEY_ILLEGAL_REQUEST) scsi_sense_print(&ccb->csio); } else { xpt_print_path(periph->path); printf("Synchronize cache failed, status " "== 0x%x, scsi status == 0x%x\n", ccb->csio.ccb_h.status, ccb->csio.scsi_status); } } if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, /*getcount_only*/0); xpt_release_ccb(ccb); } if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) { daprevent(periph, PR_ALLOW); /* * If we've got removeable media, mark the blocksize as * unavailable, since it could change when new media is * inserted. */ softc->device_stats.flags |= DEVSTAT_BS_UNAVAILABLE; } softc->flags &= ~DA_FLAG_OPEN; cam_periph_unlock(periph); cam_periph_release(periph); return (0); } /* * Actually translate the requested transfer into one the physical driver * can understand. The transfer is described by a buf and will include * only one physical transfer. */ static void dastrategy(struct bio *bp) { struct cam_periph *periph; struct da_softc *softc; u_int unit; u_int part; int s; unit = dkunit(bp->bio_dev); part = dkpart(bp->bio_dev); periph = cam_extend_get(daperiphs, unit); if (periph == NULL) { bp->bio_error = ENXIO; goto bad; } softc = (struct da_softc *)periph->softc; #if 0 /* * check it's not too big a transfer for our adapter */ scsi_minphys(bp,&sd_switch); #endif /* * Mask interrupts so that the pack cannot be invalidated until * after we are in the queue. Otherwise, we might not properly * clean up one of the buffers. */ s = splbio(); /* * If the device has been made invalid, error out */ if ((softc->flags & DA_FLAG_PACK_INVALID)) { splx(s); bp->bio_error = ENXIO; goto bad; } /* * Place it in the queue of disk activities for this disk */ bioqdisksort(&softc->bio_queue, bp); splx(s); /* * Schedule ourselves for performing the work. */ xpt_schedule(periph, /* XXX priority */1); return; bad: bp->bio_flags |= BIO_ERROR; /* * Correctly set the buf to indicate a completed xfer */ bp->bio_resid = bp->bio_bcount; biodone(bp); return; } /* For 2.2-stable support */ #ifndef ENOIOCTL #define ENOIOCTL -1 #endif static int daioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct cam_periph *periph; struct da_softc *softc; int unit; int error; unit = dkunit(dev); periph = cam_extend_get(daperiphs, unit); if (periph == NULL) return (ENXIO); softc = (struct da_softc *)periph->softc; CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("daioctl\n")); if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { return (error); /* error code from tsleep */ } error = cam_periph_ioctl(periph, cmd, addr, daerror); cam_periph_unlock(periph); return (error); } static int dadump(dev_t dev) { struct cam_periph *periph; struct da_softc *softc; u_int unit; u_int part; u_int secsize; u_int num; /* number of sectors to write */ u_int blknum; long blkcnt; vm_offset_t addr; struct ccb_scsiio csio; int error; /* toss any characters present prior to dump */ while (cncheckc() != -1) ; unit = dkunit(dev); part = dkpart(dev); periph = cam_extend_get(daperiphs, unit); if (periph == NULL) { return (ENXIO); } softc = (struct da_softc *)periph->softc; if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) return (ENXIO); error = disk_dumpcheck(dev, &num, &blknum, &secsize); if (error) return (error); addr = 0; /* starting address */ blkcnt = howmany(PAGE_SIZE, secsize); while (num > 0) { void *va; if (is_physical_memory(addr)) { va = pmap_kenter_temporary(trunc_page(addr)); } else { va = pmap_kenter_temporary(trunc_page(0)); } xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); csio.ccb_h.ccb_state = DA_CCB_DUMP; scsi_read_write(&csio, /*retries*/1, dadone, MSG_ORDERED_Q_TAG, /*read*/FALSE, /*byte2*/0, /*minimum_cmd_size*/ softc->minimum_cmd_size, blknum, blkcnt, /*data_ptr*/(u_int8_t *) va, /*dxfer_len*/blkcnt * secsize, /*sense_len*/SSD_FULL_SIZE, DA_DEFAULT_TIMEOUT * 1000); xpt_polled_action((union ccb *)&csio); if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { printf("Aborting dump due to I/O error.\n"); if ((csio.ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) scsi_sense_print(&csio); else printf("status == 0x%x, scsi status == 0x%x\n", csio.ccb_h.status, csio.scsi_status); return(EIO); } if (addr % (1024 * 1024) == 0) { #ifdef HW_WDOG if (wdog_tickler) (*wdog_tickler)(); #endif /* HW_WDOG */ /* Count in MB of data left to write */ printf("%d ", (num * softc->params.secsize) / (1024 * 1024)); } /* update block count */ num -= blkcnt; blknum += blkcnt; addr += PAGE_SIZE; /* operator aborting dump? */ if (cncheckc() != -1) return (EINTR); } /* * Sync the disk cache contents to the physical media. */ if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1); csio.ccb_h.ccb_state = DA_CCB_DUMP; scsi_synchronize_cache(&csio, /*retries*/1, /*cbfcnp*/dadone, MSG_SIMPLE_Q_TAG, /*begin_lba*/0,/* Cover the whole disk */ /*lb_count*/0, SSD_FULL_SIZE, 5 * 60 * 1000); xpt_polled_action((union ccb *)&csio); if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((csio.ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { int asc, ascq; int sense_key, error_code; scsi_extract_sense(&csio.sense_data, &error_code, &sense_key, &asc, &ascq); if (sense_key != SSD_KEY_ILLEGAL_REQUEST) scsi_sense_print(&csio); } else { xpt_print_path(periph->path); printf("Synchronize cache failed, status " "== 0x%x, scsi status == 0x%x\n", csio.ccb_h.status, csio.scsi_status); } } } return (0); } static void dainit(void) { cam_status status; struct cam_path *path; /* * Create our extend array for storing the devices we attach to. */ daperiphs = cam_extend_new(); SLIST_INIT(&softc_list); if (daperiphs == NULL) { printf("da: Failed to alloc extend array!\n"); return; } /* * Install a global async callback. This callback will * receive async callbacks like "new device found". */ status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); if (status == CAM_REQ_CMP) { struct ccb_setasync csa; xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_FOUND_DEVICE; csa.callback = daasync; csa.callback_arg = NULL; xpt_action((union ccb *)&csa); status = csa.ccb_h.status; xpt_free_path(path); } if (status != CAM_REQ_CMP) { printf("da: Failed to attach master async callback " "due to status 0x%x!\n", status); } else { /* * Schedule a periodic event to occasioanly send an * ordered tag to a device. */ timeout(dasendorderedtag, NULL, (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL); /* Register our shutdown event handler */ if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown, NULL, SHUTDOWN_PRI_DEFAULT)) == NULL) printf("dainit: shutdown event registration failed!\n"); } } static void daoninvalidate(struct cam_periph *periph) { int s; struct da_softc *softc; struct bio *q_bp; struct ccb_setasync csa; softc = (struct da_softc *)periph->softc; /* * De-register any async callbacks. */ xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = 0; csa.callback = daasync; csa.callback_arg = periph; xpt_action((union ccb *)&csa); softc->flags |= DA_FLAG_PACK_INVALID; /* * Although the oninvalidate() routines are always called at * splsoftcam, we need to be at splbio() here to keep the buffer * queue from being modified while we traverse it. */ s = splbio(); /* * Return all queued I/O with ENXIO. * XXX Handle any transactions queued to the card * with XPT_ABORT_CCB. */ while ((q_bp = bioq_first(&softc->bio_queue)) != NULL){ bioq_remove(&softc->bio_queue, q_bp); q_bp->bio_resid = q_bp->bio_bcount; q_bp->bio_error = ENXIO; q_bp->bio_flags |= BIO_ERROR; biodone(q_bp); } splx(s); SLIST_REMOVE(&softc_list, softc, da_softc, links); xpt_print_path(periph->path); printf("lost device\n"); } static void dacleanup(struct cam_periph *periph) { struct da_softc *softc; softc = (struct da_softc *)periph->softc; devstat_remove_entry(&softc->device_stats); cam_extend_release(daperiphs, periph->unit_number); xpt_print_path(periph->path); printf("removing device entry\n"); free(softc, M_DEVBUF); } static void daasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) { struct cam_periph *periph; periph = (struct cam_periph *)callback_arg; switch (code) { case AC_FOUND_DEVICE: { struct ccb_getdev *cgd; cam_status status; cgd = (struct ccb_getdev *)arg; if (SID_TYPE(&cgd->inq_data) != T_DIRECT && SID_TYPE(&cgd->inq_data) != T_OPTICAL) break; /* * Allocate a peripheral instance for * this device and start the probe * process. */ status = cam_periph_alloc(daregister, daoninvalidate, dacleanup, dastart, "da", CAM_PERIPH_BIO, cgd->ccb_h.path, daasync, AC_FOUND_DEVICE, cgd); if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) printf("daasync: Unable to attach to new device " "due to status 0x%x\n", status); break; } case AC_SENT_BDR: case AC_BUS_RESET: { struct da_softc *softc; struct ccb_hdr *ccbh; int s; softc = (struct da_softc *)periph->softc; s = splsoftcam(); /* * Don't fail on the expected unit attention * that will occur. */ softc->flags |= DA_FLAG_RETRY_UA; for (ccbh = LIST_FIRST(&softc->pending_ccbs); ccbh != NULL; ccbh = LIST_NEXT(ccbh, periph_links.le)) ccbh->ccb_state |= DA_CCB_RETRY_UA; splx(s); /* FALLTHROUGH*/ } default: cam_periph_async(periph, code, path, arg); break; } } static cam_status daregister(struct cam_periph *periph, void *arg) { int s; struct da_softc *softc; struct ccb_setasync csa; struct ccb_getdev *cgd; caddr_t match; cgd = (struct ccb_getdev *)arg; if (periph == NULL) { printf("daregister: periph was NULL!!\n"); return(CAM_REQ_CMP_ERR); } if (cgd == NULL) { printf("daregister: no getdev CCB, can't register device\n"); return(CAM_REQ_CMP_ERR); } softc = (struct da_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT); if (softc == NULL) { printf("daregister: Unable to probe new device. " "Unable to allocate softc\n"); return(CAM_REQ_CMP_ERR); } bzero(softc, sizeof(*softc)); LIST_INIT(&softc->pending_ccbs); softc->state = DA_STATE_PROBE; bioq_init(&softc->bio_queue); if (SID_IS_REMOVABLE(&cgd->inq_data)) softc->flags |= DA_FLAG_PACK_REMOVABLE; if ((cgd->inq_data.flags & SID_CmdQue) != 0) softc->flags |= DA_FLAG_TAGGED_QUEUING; periph->softc = softc; cam_extend_set(daperiphs, periph->unit_number, periph); /* * See if this device has any quirks. */ match = cam_quirkmatch((caddr_t)&cgd->inq_data, (caddr_t)da_quirk_table, sizeof(da_quirk_table)/sizeof(*da_quirk_table), sizeof(*da_quirk_table), scsi_inquiry_match); if (match != NULL) softc->quirks = ((struct da_quirk_entry *)match)->quirks; else softc->quirks = DA_Q_NONE; if (softc->quirks & DA_Q_NO_6_BYTE) softc->minimum_cmd_size = 10; else softc->minimum_cmd_size = 6; /* * Block our timeout handler while we * add this softc to the dev list. */ s = splsoftclock(); SLIST_INSERT_HEAD(&softc_list, softc, links); splx(s); /* * The DA driver supports a blocksize, but * we don't know the blocksize until we do * a read capacity. So, set a flag to * indicate that the blocksize is * unavailable right now. We'll clear the * flag as soon as we've done a read capacity. */ devstat_add_entry(&softc->device_stats, "da", periph->unit_number, 0, DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) | DEVSTAT_TYPE_IF_SCSI, DEVSTAT_PRIORITY_DISK); /* * Register this media as a disk */ disk_create(periph->unit_number, &softc->disk, 0, &da_cdevsw, &dadisk_cdevsw); /* * Add async callbacks for bus reset and * bus device reset calls. I don't bother * checking if this fails as, in most cases, * the system will function just fine without * them and the only alternative would be to * not attach the device on failure. */ xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE; csa.callback = daasync; csa.callback_arg = periph; xpt_action((union ccb *)&csa); /* * Lock this peripheral until we are setup. * This first call can't block */ (void)cam_periph_lock(periph, PRIBIO); xpt_schedule(periph, /*priority*/5); return(CAM_REQ_CMP); } static void dastart(struct cam_periph *periph, union ccb *start_ccb) { struct da_softc *softc; softc = (struct da_softc *)periph->softc; switch (softc->state) { case DA_STATE_NORMAL: { /* Pull a buffer from the queue and get going on it */ struct bio *bp; int s; /* * See if there is a buf with work for us to do.. */ s = splbio(); bp = bioq_first(&softc->bio_queue); if (periph->immediate_priority <= periph->pinfo.priority) { CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, ("queuing for immediate ccb\n")); start_ccb->ccb_h.ccb_state = DA_CCB_WAITING; SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, periph_links.sle); periph->immediate_priority = CAM_PRIORITY_NONE; splx(s); wakeup(&periph->ccb_list); } else if (bp == NULL) { splx(s); xpt_release_ccb(start_ccb); } else { int oldspl; u_int8_t tag_code; bioq_remove(&softc->bio_queue, bp); devstat_start_transaction(&softc->device_stats); if ((bp->bio_flags & BIO_ORDERED) != 0 || (softc->flags & DA_FLAG_NEED_OTAG) != 0) { softc->flags &= ~DA_FLAG_NEED_OTAG; softc->ordered_tag_count++; tag_code = MSG_ORDERED_Q_TAG; } else { tag_code = MSG_SIMPLE_Q_TAG; } scsi_read_write(&start_ccb->csio, /*retries*/4, dadone, tag_code, bp->bio_cmd == BIO_READ, /*byte2*/0, softc->minimum_cmd_size, bp->bio_pblkno, bp->bio_bcount / softc->params.secsize, bp->bio_data, bp->bio_bcount, /*sense_len*/SSD_FULL_SIZE, DA_DEFAULT_TIMEOUT * 1000); start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO; /* * Block out any asyncronous callbacks * while we touch the pending ccb list. */ oldspl = splcam(); LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h, periph_links.le); splx(oldspl); /* We expect a unit attention from this device */ if ((softc->flags & DA_FLAG_RETRY_UA) != 0) { start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA; softc->flags &= ~DA_FLAG_RETRY_UA; } start_ccb->ccb_h.ccb_bp = bp; bp = bioq_first(&softc->bio_queue); splx(s); xpt_action(start_ccb); } if (bp != NULL) { /* Have more work to do, so ensure we stay scheduled */ xpt_schedule(periph, /* XXX priority */1); } break; } case DA_STATE_PROBE: { struct ccb_scsiio *csio; struct scsi_read_capacity_data *rcap; rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), M_TEMP, M_NOWAIT); if (rcap == NULL) { printf("dastart: Couldn't malloc read_capacity data\n"); /* da_free_periph??? */ break; } csio = &start_ccb->csio; scsi_read_capacity(csio, /*retries*/4, dadone, MSG_SIMPLE_Q_TAG, rcap, SSD_FULL_SIZE, /*timeout*/5000); start_ccb->ccb_h.ccb_bp = NULL; start_ccb->ccb_h.ccb_state = DA_CCB_PROBE; xpt_action(start_ccb); break; } } } static void dadone(struct cam_periph *periph, union ccb *done_ccb) { struct da_softc *softc; struct ccb_scsiio *csio; softc = (struct da_softc *)periph->softc; csio = &done_ccb->csio; switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) { case DA_CCB_BUFFER_IO: { struct bio *bp; int oldspl; bp = (struct bio *)done_ccb->ccb_h.ccb_bp; if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { int error; int s; int sf; if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0) sf = SF_RETRY_UA; else sf = 0; /* Retry selection timeouts */ sf |= SF_RETRY_SELTO; if ((error = daerror(done_ccb, 0, sf)) == ERESTART) { /* * A retry was scheuled, so * just return. */ return; } if (error != 0) { struct bio *q_bp; s = splbio(); if (error == ENXIO) { /* * Catastrophic error. Mark our pack as * invalid. */ /* XXX See if this is really a media * change first. */ xpt_print_path(periph->path); printf("Invalidating pack\n"); softc->flags |= DA_FLAG_PACK_INVALID; } /* * return all queued I/O with EIO, so that * the client can retry these I/Os in the * proper order should it attempt to recover. */ while ((q_bp = bioq_first(&softc->bio_queue)) != NULL) { bioq_remove(&softc->bio_queue, q_bp); q_bp->bio_resid = q_bp->bio_bcount; q_bp->bio_error = EIO; q_bp->bio_flags |= BIO_ERROR; biodone(q_bp); } splx(s); bp->bio_error = error; bp->bio_resid = bp->bio_bcount; bp->bio_flags |= BIO_ERROR; } else { bp->bio_resid = csio->resid; bp->bio_error = 0; if (bp->bio_resid != 0) { /* Short transfer ??? */ bp->bio_flags |= BIO_ERROR; } } if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(done_ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, /*getcount_only*/0); } else { bp->bio_resid = csio->resid; if (csio->resid > 0) bp->bio_flags |= BIO_ERROR; } /* * Block out any asyncronous callbacks * while we touch the pending ccb list. */ oldspl = splcam(); LIST_REMOVE(&done_ccb->ccb_h, periph_links.le); splx(oldspl); if (softc->device_stats.busy_count == 0) softc->flags |= DA_FLAG_WENT_IDLE; devstat_end_transaction_bio(&softc->device_stats, bp); biodone(bp); break; } case DA_CCB_PROBE: { struct scsi_read_capacity_data *rdcap; char announce_buf[80]; rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { struct disk_params *dp; dasetgeom(periph, rdcap); dp = &softc->params; snprintf(announce_buf, sizeof(announce_buf), "%luMB (%u %u byte sectors: %dH %dS/T %dC)", (unsigned long) (((u_int64_t)dp->secsize * dp->sectors) / (1024*1024)), dp->sectors, dp->secsize, dp->heads, dp->secs_per_track, dp->cylinders); } else { int error; announce_buf[0] = '\0'; /* * Retry any UNIT ATTENTION type errors. They * are expected at boot. */ error = daerror(done_ccb, 0, SF_RETRY_UA | SF_RETRY_SELTO | SF_NO_PRINT); if (error == ERESTART) { /* * A retry was scheuled, so * just return. */ return; } else if (error != 0) { struct scsi_sense_data *sense; int asc, ascq; int sense_key, error_code; int have_sense; cam_status status; struct ccb_getdev cgd; /* Don't wedge this device's queue */ cam_release_devq(done_ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, /*getcount_only*/0); status = done_ccb->ccb_h.status; xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, /* priority */ 1); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0) || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0) || ((status & CAM_AUTOSNS_VALID) == 0)) have_sense = FALSE; else have_sense = TRUE; if (have_sense) { sense = &csio->sense_data; scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); } /* * Attach to anything that claims to be a * direct access or optical disk device, * as long as it doesn't return a "Logical * unit not supported" (0x25) error. */ if ((have_sense) && (asc != 0x25) && (error_code == SSD_CURRENT_ERROR)) snprintf(announce_buf, sizeof(announce_buf), "Attempt to query device " "size failed: %s, %s", scsi_sense_key_text[sense_key], scsi_sense_desc(asc,ascq, &cgd.inq_data)); else { if (have_sense) scsi_sense_print( &done_ccb->csio); else { xpt_print_path(periph->path); printf("got CAM status %#x\n", done_ccb->ccb_h.status); } xpt_print_path(periph->path); printf("fatal error, failed" " to attach to device\n"); /* * Free up resources. */ cam_periph_invalidate(periph); } } } free(rdcap, M_TEMP); if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); softc->state = DA_STATE_NORMAL; /* * Since our peripheral may be invalidated by an error * above or an external event, we must release our CCB * before releasing the probe lock on the peripheral. * The peripheral will only go away once the last lock * is removed, and we need it around for the CCB release * operation. */ xpt_release_ccb(done_ccb); cam_periph_unlock(periph); return; } case DA_CCB_WAITING: { /* Caller will release the CCB */ wakeup(&done_ccb->ccb_h.cbfcnp); return; } case DA_CCB_DUMP: /* No-op. We're polling */ return; default: break; } xpt_release_ccb(done_ccb); } static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) { struct da_softc *softc; struct cam_periph *periph; periph = xpt_path_periph(ccb->ccb_h.path); softc = (struct da_softc *)periph->softc; /* * XXX * Until we have a better way of doing pack validation, * don't treat UAs as errors. */ sense_flags |= SF_RETRY_UA; return(cam_periph_error(ccb, cam_flags, sense_flags, &softc->saved_ccb)); } static void daprevent(struct cam_periph *periph, int action) { struct da_softc *softc; union ccb *ccb; int error; softc = (struct da_softc *)periph->softc; if (((action == PR_ALLOW) && (softc->flags & DA_FLAG_PACK_LOCKED) == 0) || ((action == PR_PREVENT) && (softc->flags & DA_FLAG_PACK_LOCKED) != 0)) { return; } ccb = cam_periph_getccb(periph, /*priority*/1); scsi_prevent(&ccb->csio, /*retries*/1, /*cbcfp*/dadone, MSG_SIMPLE_Q_TAG, action, SSD_FULL_SIZE, 5000); error = cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0, /*sense_flags*/0, &softc->device_stats); if (error == 0) { if (action == PR_ALLOW) softc->flags &= ~DA_FLAG_PACK_LOCKED; else softc->flags |= DA_FLAG_PACK_LOCKED; } xpt_release_ccb(ccb); } static void dasetgeom(struct cam_periph *periph, struct scsi_read_capacity_data * rdcap) { struct ccb_calc_geometry ccg; struct da_softc *softc; struct disk_params *dp; softc = (struct da_softc *)periph->softc; dp = &softc->params; dp->secsize = scsi_4btoul(rdcap->length); dp->sectors = scsi_4btoul(rdcap->addr) + 1; /* * Have the controller provide us with a geometry * for this disk. The only time the geometry * matters is when we boot and the controller * is the only one knowledgeable enough to come * up with something that will make this a bootable * device. */ xpt_setup_ccb(&ccg.ccb_h, periph->path, /*priority*/1); ccg.ccb_h.func_code = XPT_CALC_GEOMETRY; ccg.block_size = dp->secsize; ccg.volume_size = dp->sectors; ccg.heads = 0; ccg.secs_per_track = 0; ccg.cylinders = 0; xpt_action((union ccb*)&ccg); dp->heads = ccg.heads; dp->secs_per_track = ccg.secs_per_track; dp->cylinders = ccg.cylinders; } static void dasendorderedtag(void *arg) { struct da_softc *softc; int s; for (softc = SLIST_FIRST(&softc_list); softc != NULL; softc = SLIST_NEXT(softc, links)) { s = splsoftcam(); if ((softc->ordered_tag_count == 0) && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) { softc->flags |= DA_FLAG_NEED_OTAG; } if (softc->device_stats.busy_count > 0) softc->flags &= ~DA_FLAG_WENT_IDLE; softc->ordered_tag_count = 0; splx(s); } /* Queue us up again */ timeout(dasendorderedtag, NULL, (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL); } /* * Step through all DA peripheral drivers, and if the device is still open, * sync the disk cache to physical media. */ static void dashutdown(void * arg, int howto) { struct cam_periph *periph; struct da_softc *softc; for (periph = TAILQ_FIRST(&dadriver.units); periph != NULL; periph = TAILQ_NEXT(periph, unit_links)) { union ccb ccb; softc = (struct da_softc *)periph->softc; /* * We only sync the cache if the drive is still open, and * if the drive is capable of it.. */ if (((softc->flags & DA_FLAG_OPEN) == 0) || (softc->quirks & DA_Q_NO_SYNC_CACHE)) continue; xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1); ccb.ccb_h.ccb_state = DA_CCB_DUMP; scsi_synchronize_cache(&ccb.csio, /*retries*/1, /*cbfcnp*/dadone, MSG_SIMPLE_Q_TAG, /*begin_lba*/0, /* whole disk */ /*lb_count*/0, SSD_FULL_SIZE, 5 * 60 * 1000); xpt_polled_action(&ccb); if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if (((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){ int error_code, sense_key, asc, ascq; scsi_extract_sense(&ccb.csio.sense_data, &error_code, &sense_key, &asc, &ascq); if (sense_key != SSD_KEY_ILLEGAL_REQUEST) scsi_sense_print(&ccb.csio); } else { xpt_print_path(periph->path); printf("Synchronize cache failed, status " "== 0x%x, scsi status == 0x%x\n", ccb.ccb_h.status, ccb.csio.scsi_status); } } if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, /*getcount_only*/0); } } #else /* !_KERNEL */ /* * XXX This is only left out of the kernel build to silence warnings. If, * for some reason this function is used in the kernel, the ifdefs should * be moved so it is included both in the kernel and userland. */ void scsi_format_unit(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) { struct scsi_format_unit *scsi_cmd; scsi_cmd = (struct scsi_format_unit *)&csio->cdb_io.cdb_bytes; scsi_cmd->opcode = FORMAT_UNIT; scsi_cmd->byte2 = byte2; scsi_ulto2b(ileave, scsi_cmd->interleave); cam_fill_csio(csio, retries, cbfcnp, /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE, tag_action, data_ptr, dxfer_len, sense_len, sizeof(*scsi_cmd), timeout); } #endif /* _KERNEL */