📄 ide.c
字号:
/* * linux/drivers/block/ide.c Version 5.53 Jun 24, 1997 * * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) */#define _IDE_C /* needed by <linux/blk.h> *//* * Maintained by Mark Lord <mlord@pobox.com> * and Gadi Oxman <gadio@netvision.net.il> * * This is the multiple IDE interface driver, as evolved from hd.c. * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15). * There can be up to two drives per interface, as per the ATA-2 spec. * * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 * * It is easy to extend ide.c to handle more than four interfaces: * * Change the MAX_HWIFS constant in ide.h. * * Define some new major numbers (in major.h), and insert them into * the ide_hwif_to_major table in ide.c. * * Fill in the extra values for the new interfaces into the two tables * inside ide.c: default_io_base[] and default_irqs[]. * * Create the new request handlers by cloning "do_ide3_request()" * for each new interface, and add them to the switch statement * in the ide_init() function in ide.c. * * Recompile, create the new /dev/ entries, and it will probably work. * * From hd.c: * | * | It traverses the request-list, using interrupts to jump between functions. * | As nearly all functions can be called within interrupts, we may not sleep. * | Special care is recommended. Have Fun! * | * | modified by Drew Eckhardt to check nr of hd's from the CMOS. * | * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug * | in the early extended-partition checks and added DM partitions. * | * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). * | * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", * | and general streamlining by Mark Lord (mlord@pobox.com). * * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: * * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) * Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2") * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) * * This was a rewrite of just about everything from hd.c, though some original * code is still sprinkled about. Think of it as a major evolution, with * inspiration from lots of linux users, esp. hamish@zot.apana.org.au * * Version 1.0 ALPHA initial code, primary i/f working okay * Version 1.3 BETA dual i/f on shared irq tested & working! * Version 1.4 BETA added auto probing for irq(s) * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms, * ... * Version 3.5 correct the bios_cyl field if it's too small * (linux 1.1.76) (to help fdisk with brain-dead BIOSs) * Version 3.6 cosmetic corrections to comments and stuff * (linux 1.1.77) reorganise probing code to make it understandable * added halfway retry to probing for drive identification * added "hdx=noprobe" command line option * allow setting multmode even when identification fails * Version 3.7 move set_geometry=1 from do_identify() to ide_init() * increase DRQ_WAIT to eliminate nuisance messages * wait for DRQ_STAT instead of DATA_READY during probing * (courtesy of Gary Thomas gary@efland.UU.NET) * Version 3.8 fixed byte-swapping for confused Mitsumi cdrom drives * update of ide-cd.c from Scott, allows blocksize=1024 * cdrom probe fixes, inspired by jprang@uni-duisburg.de * Version 3.9 don't use LBA if lba_capacity looks funny * correct the drive capacity calculations * fix probing for old Seagates without IDE_ALTSTATUS_REG * fix byte-ordering for some NEC cdrom drives * Version 3.10 disable multiple mode by default; was causing trouble * Version 3.11 fix mis-identification of old WD disks as cdroms * Version 3,12 simplify logic for selecting initial mult_count * (fixes problems with buggy WD drives) * Version 3.13 remove excess "multiple mode disabled" messages * Version 3.14 fix ide_error() handling of BUSY_STAT * fix byte-swapped cdrom strings (again.. arghh!) * ignore INDEX bit when checking the ALTSTATUS reg * Version 3.15 add SINGLE_THREADED flag for use with dual-CMD i/f * ignore WRERR_STAT for non-write operations * added vlb_sync support for DC-2000A & others, * (incl. some Promise chips), courtesy of Frank Gockel * Version 3.16 convert vlb_32bit and vlb_sync into runtime flags * add ioctls to get/set VLB flags (HDIO_[SG]ET_CHIPSET) * rename SINGLE_THREADED to SUPPORT_SERIALIZE, * add boot flag to "serialize" operation for CMD i/f * add optional support for DTC2278 interfaces, * courtesy of andy@cercle.cts.com (Dyan Wile). * add boot flag to enable "dtc2278" probe * add probe to avoid EATA (SCSI) interfaces, * courtesy of neuffer@goofy.zdv.uni-mainz.de. * Version 4.00 tidy up verify_area() calls - heiko@colossus.escape.de * add flag to ignore WRERR_STAT for some drives * courtesy of David.H.West@um.cc.umich.edu * assembly syntax tweak to vlb_sync * removable drive support from scuba@cs.tu-berlin.de * add transparent support for DiskManager-6.0x "Dynamic * Disk Overlay" (DDO), most of this is in genhd.c * eliminate "multiple mode turned off" message at boot * Version 4.10 fix bug in ioctl for "hdparm -c3" * fix DM6:DDO support -- now works with LILO, fdisk, ... * don't treat some naughty WD drives as removable * Version 4.11 updated DM6 support using info provided by OnTrack * Version 5.00 major overhaul, multmode setting fixed, vlb_sync fixed * added support for 3rd/4th/alternative IDE ports * created ide.h; ide-cd.c now compiles separate from ide.c * hopefully fixed infinite "unexpected_intr" from cdroms * zillions of other changes and restructuring * somehow reduced overall memory usage by several kB * probably slowed things down slightly, but worth it * Version 5.01 AT LAST!! Finally understood why "unexpected_intr" * was happening at various times/places: whenever the * ide-interface's ctl_port was used to "mask" the irq, * it also would trigger an edge in the process of masking * which would result in a self-inflicted interrupt!! * (such a stupid way to build a hardware interrupt mask). * This is now fixed (after a year of head-scratching). * Version 5.02 got rid of need for {enable,disable}_irq_list() * Version 5.03 tune-ups, comments, remove "busy wait" from drive resets * removed PROBE_FOR_IRQS option -- no longer needed * OOOPS! fixed "bad access" bug for 2nd drive on an i/f * Version 5.04 changed "ira %d" to "irq %d" in DEBUG message * added more comments, cleaned up unexpected_intr() * OOOPS! fixed null pointer problem in ide reset code * added autodetect for Triton chipset -- no effect yet * Version 5.05 OOOPS! fixed bug in revalidate_disk() * OOOPS! fixed bug in ide_do_request() * added ATAPI reset sequence for cdroms * Version 5.10 added Bus-Mastered DMA support for Triton Chipset * some (mostly) cosmetic changes * Version 5.11 added ht6560b support by malafoss@snakemail.hut.fi * reworked PCI scanning code * added automatic RZ1000 detection/support * added automatic PCI CMD640 detection/support * added option for VLB CMD640 support * tweaked probe to find cdrom on hdb with disks on hda,hdc * Version 5.12 some performance tuning * added message to alert user to bad /dev/hd[cd] entries * OOOPS! fixed bug in atapi reset * driver now forces "serialize" again for all cmd640 chips * noticed REALLY_SLOW_IO had no effect, moved it to ide.c * made do_drive_cmd() into public ide_do_drive_cmd() * Version 5.13 fixed typo ('B'), thanks to houston@boyd.geog.mcgill.ca * fixed ht6560b support * Version 5.13b (sss) fix problem in calling ide_cdrom_setup() * don't bother invalidating nonexistent partitions * Version 5.14 fixes to cmd640 support.. maybe it works now(?) * added & tested full EZ-DRIVE support -- don't use LILO! * don't enable 2nd CMD640 PCI port during init - conflict * Version 5.15 bug fix in init_cmd640_vlb() * bug fix in interrupt sharing code * Version 5.16 ugh.. fix "serialize" support, broken in 5.15 * remove "Huh?" from cmd640 code * added qd6580 interface speed select from Colten Edwards * Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards * Version 5.18 new CMD640 code, moved to cmd640.c, #include'd for now * new UMC8672 code, moved to umc8672.c, #include'd for now * disallow turning on DMA when h/w not capable of DMA * Version 5.19 fix potential infinite timeout on resets * extend reset poll into a general purpose polling scheme * add atapi tape drive support from Gadi Oxman * simplify exit from _intr routines -- no IDE_DO_REQUEST * Version 5.20 leave current rq on blkdev request list during I/O * generalized ide_do_drive_cmd() for tape/cdrom driver use * Version 5.21 fix nasty cdrom/tape bug (ide_preempt was messed up) * Version 5.22 fix ide_xlate_1024() to work with/without drive->id * Version 5.23 miscellaneous touch-ups * Version 5.24 fix #if's for SUPPORT_CMD640 * Version 5.25 more touch-ups, fix cdrom resets, ... * cmd640.c now configs/compiles separate from ide.c * Version 5.26 keep_settings now maintains the using_dma flag * fix [EZD] remap message to only output at boot time * fix "bad /dev/ entry" message to say hdc, not hdc0 * fix ide_xlate_1024() to respect user specified CHS * use CHS from partn table if it looks translated * re-merged flags chipset,vlb_32bit,vlb_sync into io_32bit * keep track of interface chipset type, when known * add generic PIO mode "tuneproc" mechanism * fix cmd640_vlb option * fix ht6560b support (was completely broken) * umc8672.c now configures/compiles separate from ide.c * move dtc2278 support to dtc2278.c * move ht6560b support to ht6560b.c * move qd6580 support to qd6580.c * add ali14xx support in ali14xx.c * Version 5.27 add [no]autotune parameters to help cmd640 * move rz1000 support to rz1000.c * Version 5.28 #include "ide_modes.h" * fix disallow_unmask: now per-interface "no_unmask" bit * force io_32bit to be the same on drive pairs of dtc2278 * improved IDE tape error handling, and tape DMA support * bugfix in ide_do_drive_cmd() for cdroms + serialize * Version 5.29 fixed non-IDE check for too many physical heads * don't use LBA if capacity is smaller than CHS * Version 5.30 remove real_devices kludge, formerly used by genhd.c * Version 5.32 change "KB" to "kB" * fix serialize (was broken in kernel 1.3.72) * add support for "hdparm -I" * use common code for disk/tape/cdrom IDE_DRIVE_CMDs * add support for Promise DC4030VL caching card * improved serialize support * put partition check back into alphabetical order * add config option for PCMCIA baggage * try to make PCMCIA support safer to use * improve security on ioctls(): all are suser() only * Version 5.33 improve handling of HDIO_DRIVE_CMDs that read data * Version 5.34 fix irq-sharing problem from 5.33 * fix cdrom ioctl problem from 5.33 * Version 5.35 cosmetic changes * fix cli() problem in try_to_identify() * Version 5.36 fixes to optional PCMCIA support * Version 5.37 don't use DMA when "noautotune" is specified * Version 5.37a (go) fix shared irq probing (was broken in kernel 1.3.72) * call unplug_device() from ide_do_drive_cmd() * Version 5.38 add "hdx=none" option, courtesy of Joel Maslak * mask drive irq after use, if sharing with another hwif * add code to help debug weird cmd640 problems * Version 5.39 fix horrible error in earlier irq sharing "fix" * Version 5.40 fix serialization -- was broken in 5.39 * help sharing by masking device irq after probing * Version 5.41 more fixes to irq sharing/serialize detection * disable io_32bit by default on drive reset * Version 5.42 simplify irq-masking after probe * fix NULL pointer deref in save_match() * Version 5.43 Ugh.. unexpected_intr is back: try to exterminate it * Version 5.44 Fix for "irq probe failed" on cmd640 * change path on message regarding MAKEDEV.ide * add a throttle to the unexpected_intr() messages * Version 5.45 fix ugly parameter parsing bugs (thanks Derek) * include Gadi's magic fix for cmd640 unexpected_intr * include mc68000 patches from Geert Uytterhoeven * add Gadi's fix for PCMCIA cdroms * Version 5.46 remove the mc68000 #ifdefs for 2.0.x * Version 5.47 fix set_tune race condition * fix bug in earlier PCMCIA cdrom update * Version 5.48 if def'd, invoke CMD640_DUMP_REGS when irq probe fails * lengthen the do_reset1() pulse, for laptops * add idebus=xx parameter for cmd640 and ali chipsets * no_unmask flag now per-drive instead of per-hwif * fix tune_req so that it gets done immediately * fix missing restore_flags() in ide_ioctl * prevent use of io_32bit on cmd640 with no prefetch * Version 5.49 fix minor quirks in probing routines * Version 5.50 allow values as small as 20 for idebus= * Version 5.51 force non io_32bit in drive_cmd_intr() * change delay_10ms() to delay_50ms() to fix problems * Version 5.52 fix incorrect invalidation of removable devices * add "hdx=slow" command line option * Version 5.53 add ATAPI floppy drive support * change default media for type 0 to floppy * add support for Exabyte Nest * add missing set_blocksize() in revalidate_disk() * handle bad status bit sequencing in ide_wait_stat() * support partition table translations with 255 heads * probe all interfaces by default * add probe for the i82371AB chipset * acknowledge media change on removable drives * add work-around for BMI drives * remove "LBA" from boot messages * Version 5.53.1 add UDMA "CRC retry" support * Version 5.53.2 add Promise/33 auto-detection and DMA support * fix MC_ERR handling * fix mis-detection of NEC cdrom as floppy * issue ATAPI reset and re-probe after "no response" * * Some additional driver compile-time options are in ide.h * * To do, in likely order of completion: * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f*/#undef REALLY_SLOW_IO /* most systems can safely undef this */#include <linux/config.h>#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/major.h>#include <linux/blkdev.h>#include <linux/errno.h>#include <linux/hdreg.h>#include <linux/genhd.h>#include <linux/malloc.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/segment.h>#include <asm/io.h>#ifdef CONFIG_PCI#include <linux/bios32.h>#include <linux/pci.h>#endif /* CONFIG_PCI */#include "ide.h"#include "ide_modes.h"#ifdef CONFIG_BLK_DEV_PROMISE#include "promise.h"#define IS_PROMISE_DRIVE (HWIF(drive)->chipset == ide_promise)#else#define IS_PROMISE_DRIVE (0) /* auto-NULLs out Promise code */#endif /* CONFIG_BLK_DEV_PROMISE */static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};static int idebus_parameter; /* holds the "idebus=" parameter */static int system_bus_speed; /* holds what we think is VESA/PCI bus speed *//* * This is declared extern in ide.h, for access by other IDE modules: */ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */#if (DISK_RECOVERY_TIME > 0)/* * For really screwy hardware (hey, at least it *can* be used with Linux) * we can enforce a minimum delay time between successive operations. */static unsigned long read_timer(void){ unsigned long t, flags; int i; save_flags(flags); cli(); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); i |= inb(0x40) << 8; restore_flags(flags); return (t - i);}static void set_recovery_timer (ide_hwif_t *hwif){ hwif->last_time = read_timer();}#define SET_RECOVERY_TIMER(drive) set_recovery_timer (drive)#else#define SET_RECOVERY_TIMER(drive)#endif /* DISK_RECOVERY_TIME *//* * Do not even *think* about calling this! */static void init_hwif_data (unsigned int index){ byte *p; unsigned int unit; ide_hwif_t *hwif = &ide_hwifs[index]; /* bulk initialize hwif & drive info with zeros */ p = ((byte *) hwif) + sizeof(ide_hwif_t); do { *--p = 0; } while (p > (byte *) hwif); /* fill in any non-zero initial values */ hwif->index = index; hwif->io_base = default_io_base[index]; hwif->ctl_port = hwif->io_base ? hwif->io_base+0x206 : 0x000;#ifdef CONFIG_BLK_DEV_HD if (hwif->io_base == HD_DATA) hwif->noprobe = 1; /* may be overridden by ide_setup() */#endif /* CONFIG_BLK_DEV_HD */ hwif->major = ide_hwif_to_major[index]; hwif->name[0] = 'i'; hwif->name[1] = 'd'; hwif->name[2] = 'e'; hwif->name[3] = '0' + index;#ifdef CONFIG_BLK_DEV_IDETAPE hwif->tape_drive = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -