| File: | obj-scan-build/../linux/src/drivers/block/ide.c |
| Location: | line 2388, column 1 |
| Description: | Address of stack memory associated with local variable 'rq' is still referred to by the global variable 'blk_dev' upon returning to the caller. This will be a dangling reference |
| 1 | /* | |||
| 2 | * linux/drivers/block/ide.c Version 5.53 Jun 24, 1997 | |||
| 3 | * | |||
| 4 | * Copyright (C) 1994-1996 Linus Torvalds & authors (see below) | |||
| 5 | */ | |||
| 6 | #define _IDE_C /* needed by <linux/blk.h> */ | |||
| 7 | ||||
| 8 | /* | |||
| 9 | * Maintained by Mark Lord <mlord@pobox.com> | |||
| 10 | * and Gadi Oxman <gadio@netvision.net.il> | |||
| 11 | * | |||
| 12 | * This is the multiple IDE interface driver, as evolved from hd.c. | |||
| 13 | * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15). | |||
| 14 | * There can be up to two drives per interface, as per the ATA-2 spec. | |||
| 15 | * | |||
| 16 | * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 | |||
| 17 | * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 | |||
| 18 | * Tertiary: ide2, port 0x???; major=33; hde is minor=0; hdf is minor=64 | |||
| 19 | * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 | |||
| 20 | * | |||
| 21 | * It is easy to extend ide.c to handle more than four interfaces: | |||
| 22 | * | |||
| 23 | * Change the MAX_HWIFS constant in ide.h. | |||
| 24 | * | |||
| 25 | * Define some new major numbers (in major.h), and insert them into | |||
| 26 | * the ide_hwif_to_major table in ide.c. | |||
| 27 | * | |||
| 28 | * Fill in the extra values for the new interfaces into the two tables | |||
| 29 | * inside ide.c: default_io_base[] and default_irqs[]. | |||
| 30 | * | |||
| 31 | * Create the new request handlers by cloning "do_ide3_request()" | |||
| 32 | * for each new interface, and add them to the switch statement | |||
| 33 | * in the ide_init() function in ide.c. | |||
| 34 | * | |||
| 35 | * Recompile, create the new /dev/ entries, and it will probably work. | |||
| 36 | * | |||
| 37 | * From hd.c: | |||
| 38 | * | | |||
| 39 | * | It traverses the request-list, using interrupts to jump between functions. | |||
| 40 | * | As nearly all functions can be called within interrupts, we may not sleep. | |||
| 41 | * | Special care is recommended. Have Fun! | |||
| 42 | * | | |||
| 43 | * | modified by Drew Eckhardt to check nr of hd's from the CMOS. | |||
| 44 | * | | |||
| 45 | * | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug | |||
| 46 | * | in the early extended-partition checks and added DM partitions. | |||
| 47 | * | | |||
| 48 | * | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI). | |||
| 49 | * | | |||
| 50 | * | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", | |||
| 51 | * | and general streamlining by Mark Lord (mlord@pobox.com). | |||
| 52 | * | |||
| 53 | * October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by: | |||
| 54 | * | |||
| 55 | * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) | |||
| 56 | * Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2") | |||
| 57 | * Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) | |||
| 58 | * | |||
| 59 | * This was a rewrite of just about everything from hd.c, though some original | |||
| 60 | * code is still sprinkled about. Think of it as a major evolution, with | |||
| 61 | * inspiration from lots of linux users, esp. hamish@zot.apana.org.au | |||
| 62 | * | |||
| 63 | * Version 1.0 ALPHA initial code, primary i/f working okay | |||
| 64 | * Version 1.3 BETA dual i/f on shared irq tested & working! | |||
| 65 | * Version 1.4 BETA added auto probing for irq(s) | |||
| 66 | * Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms, | |||
| 67 | * ... | |||
| 68 | * Version 3.5 correct the bios_cyl field if it's too small | |||
| 69 | * (linux 1.1.76) (to help fdisk with brain-dead BIOSs) | |||
| 70 | * Version 3.6 cosmetic corrections to comments and stuff | |||
| 71 | * (linux 1.1.77) reorganise probing code to make it understandable | |||
| 72 | * added halfway retry to probing for drive identification | |||
| 73 | * added "hdx=noprobe" command line option | |||
| 74 | * allow setting multmode even when identification fails | |||
| 75 | * Version 3.7 move set_geometry=1 from do_identify() to ide_init() | |||
| 76 | * increase DRQ_WAIT to eliminate nuisance messages | |||
| 77 | * wait for DRQ_STAT instead of DATA_READY during probing | |||
| 78 | * (courtesy of Gary Thomas gary@efland.UU.NET) | |||
| 79 | * Version 3.8 fixed byte-swapping for confused Mitsumi cdrom drives | |||
| 80 | * update of ide-cd.c from Scott, allows blocksize=1024 | |||
| 81 | * cdrom probe fixes, inspired by jprang@uni-duisburg.de | |||
| 82 | * Version 3.9 don't use LBA if lba_capacity looks funny | |||
| 83 | * correct the drive capacity calculations | |||
| 84 | * fix probing for old Seagates without IDE_ALTSTATUS_REG | |||
| 85 | * fix byte-ordering for some NEC cdrom drives | |||
| 86 | * Version 3.10 disable multiple mode by default; was causing trouble | |||
| 87 | * Version 3.11 fix mis-identification of old WD disks as cdroms | |||
| 88 | * Version 3,12 simplify logic for selecting initial mult_count | |||
| 89 | * (fixes problems with buggy WD drives) | |||
| 90 | * Version 3.13 remove excess "multiple mode disabled" messages | |||
| 91 | * Version 3.14 fix ide_error() handling of BUSY_STAT | |||
| 92 | * fix byte-swapped cdrom strings (again.. arghh!) | |||
| 93 | * ignore INDEX bit when checking the ALTSTATUS reg | |||
| 94 | * Version 3.15 add SINGLE_THREADED flag for use with dual-CMD i/f | |||
| 95 | * ignore WRERR_STAT for non-write operations | |||
| 96 | * added vlb_sync support for DC-2000A & others, | |||
| 97 | * (incl. some Promise chips), courtesy of Frank Gockel | |||
| 98 | * Version 3.16 convert vlb_32bit and vlb_sync into runtime flags | |||
| 99 | * add ioctls to get/set VLB flags (HDIO_[SG]ET_CHIPSET) | |||
| 100 | * rename SINGLE_THREADED to SUPPORT_SERIALIZE, | |||
| 101 | * add boot flag to "serialize" operation for CMD i/f | |||
| 102 | * add optional support for DTC2278 interfaces, | |||
| 103 | * courtesy of andy@cercle.cts.com (Dyan Wile). | |||
| 104 | * add boot flag to enable "dtc2278" probe | |||
| 105 | * add probe to avoid EATA (SCSI) interfaces, | |||
| 106 | * courtesy of neuffer@goofy.zdv.uni-mainz.de. | |||
| 107 | * Version 4.00 tidy up verify_area() calls - heiko@colossus.escape.de | |||
| 108 | * add flag to ignore WRERR_STAT for some drives | |||
| 109 | * courtesy of David.H.West@um.cc.umich.edu | |||
| 110 | * assembly syntax tweak to vlb_sync | |||
| 111 | * removable drive support from scuba@cs.tu-berlin.de | |||
| 112 | * add transparent support for DiskManager-6.0x "Dynamic | |||
| 113 | * Disk Overlay" (DDO), most of this is in genhd.c | |||
| 114 | * eliminate "multiple mode turned off" message at boot | |||
| 115 | * Version 4.10 fix bug in ioctl for "hdparm -c3" | |||
| 116 | * fix DM6:DDO support -- now works with LILO, fdisk, ... | |||
| 117 | * don't treat some naughty WD drives as removable | |||
| 118 | * Version 4.11 updated DM6 support using info provided by OnTrack | |||
| 119 | * Version 5.00 major overhaul, multmode setting fixed, vlb_sync fixed | |||
| 120 | * added support for 3rd/4th/alternative IDE ports | |||
| 121 | * created ide.h; ide-cd.c now compiles separate from ide.c | |||
| 122 | * hopefully fixed infinite "unexpected_intr" from cdroms | |||
| 123 | * zillions of other changes and restructuring | |||
| 124 | * somehow reduced overall memory usage by several kB | |||
| 125 | * probably slowed things down slightly, but worth it | |||
| 126 | * Version 5.01 AT LAST!! Finally understood why "unexpected_intr" | |||
| 127 | * was happening at various times/places: whenever the | |||
| 128 | * ide-interface's ctl_port was used to "mask" the irq, | |||
| 129 | * it also would trigger an edge in the process of masking | |||
| 130 | * which would result in a self-inflicted interrupt!! | |||
| 131 | * (such a stupid way to build a hardware interrupt mask). | |||
| 132 | * This is now fixed (after a year of head-scratching). | |||
| 133 | * Version 5.02 got rid of need for {enable,disable}_irq_list() | |||
| 134 | * Version 5.03 tune-ups, comments, remove "busy wait" from drive resets | |||
| 135 | * removed PROBE_FOR_IRQS option -- no longer needed | |||
| 136 | * OOOPS! fixed "bad access" bug for 2nd drive on an i/f | |||
| 137 | * Version 5.04 changed "ira %d" to "irq %d" in DEBUG message | |||
| 138 | * added more comments, cleaned up unexpected_intr() | |||
| 139 | * OOOPS! fixed null pointer problem in ide reset code | |||
| 140 | * added autodetect for Triton chipset -- no effect yet | |||
| 141 | * Version 5.05 OOOPS! fixed bug in revalidate_disk() | |||
| 142 | * OOOPS! fixed bug in ide_do_request() | |||
| 143 | * added ATAPI reset sequence for cdroms | |||
| 144 | * Version 5.10 added Bus-Mastered DMA support for Triton Chipset | |||
| 145 | * some (mostly) cosmetic changes | |||
| 146 | * Version 5.11 added ht6560b support by malafoss@snakemail.hut.fi | |||
| 147 | * reworked PCI scanning code | |||
| 148 | * added automatic RZ1000 detection/support | |||
| 149 | * added automatic PCI CMD640 detection/support | |||
| 150 | * added option for VLB CMD640 support | |||
| 151 | * tweaked probe to find cdrom on hdb with disks on hda,hdc | |||
| 152 | * Version 5.12 some performance tuning | |||
| 153 | * added message to alert user to bad /dev/hd[cd] entries | |||
| 154 | * OOOPS! fixed bug in atapi reset | |||
| 155 | * driver now forces "serialize" again for all cmd640 chips | |||
| 156 | * noticed REALLY_SLOW_IO had no effect, moved it to ide.c | |||
| 157 | * made do_drive_cmd() into public ide_do_drive_cmd() | |||
| 158 | * Version 5.13 fixed typo ('B'), thanks to houston@boyd.geog.mcgill.ca | |||
| 159 | * fixed ht6560b support | |||
| 160 | * Version 5.13b (sss) fix problem in calling ide_cdrom_setup() | |||
| 161 | * don't bother invalidating nonexistent partitions | |||
| 162 | * Version 5.14 fixes to cmd640 support.. maybe it works now(?) | |||
| 163 | * added & tested full EZ-DRIVE support -- don't use LILO! | |||
| 164 | * don't enable 2nd CMD640 PCI port during init - conflict | |||
| 165 | * Version 5.15 bug fix in init_cmd640_vlb() | |||
| 166 | * bug fix in interrupt sharing code | |||
| 167 | * Version 5.16 ugh.. fix "serialize" support, broken in 5.15 | |||
| 168 | * remove "Huh?" from cmd640 code | |||
| 169 | * added qd6580 interface speed select from Colten Edwards | |||
| 170 | * Version 5.17 kludge around bug in BIOS32 on Intel triton motherboards | |||
| 171 | * Version 5.18 new CMD640 code, moved to cmd640.c, #include'd for now | |||
| 172 | * new UMC8672 code, moved to umc8672.c, #include'd for now | |||
| 173 | * disallow turning on DMA when h/w not capable of DMA | |||
| 174 | * Version 5.19 fix potential infinite timeout on resets | |||
| 175 | * extend reset poll into a general purpose polling scheme | |||
| 176 | * add atapi tape drive support from Gadi Oxman | |||
| 177 | * simplify exit from _intr routines -- no IDE_DO_REQUEST | |||
| 178 | * Version 5.20 leave current rq on blkdev request list during I/O | |||
| 179 | * generalized ide_do_drive_cmd() for tape/cdrom driver use | |||
| 180 | * Version 5.21 fix nasty cdrom/tape bug (ide_preempt was messed up) | |||
| 181 | * Version 5.22 fix ide_xlate_1024() to work with/without drive->id | |||
| 182 | * Version 5.23 miscellaneous touch-ups | |||
| 183 | * Version 5.24 fix #if's for SUPPORT_CMD640 | |||
| 184 | * Version 5.25 more touch-ups, fix cdrom resets, ... | |||
| 185 | * cmd640.c now configs/compiles separate from ide.c | |||
| 186 | * Version 5.26 keep_settings now maintains the using_dma flag | |||
| 187 | * fix [EZD] remap message to only output at boot time | |||
| 188 | * fix "bad /dev/ entry" message to say hdc, not hdc0 | |||
| 189 | * fix ide_xlate_1024() to respect user specified CHS | |||
| 190 | * use CHS from partn table if it looks translated | |||
| 191 | * re-merged flags chipset,vlb_32bit,vlb_sync into io_32bit | |||
| 192 | * keep track of interface chipset type, when known | |||
| 193 | * add generic PIO mode "tuneproc" mechanism | |||
| 194 | * fix cmd640_vlb option | |||
| 195 | * fix ht6560b support (was completely broken) | |||
| 196 | * umc8672.c now configures/compiles separate from ide.c | |||
| 197 | * move dtc2278 support to dtc2278.c | |||
| 198 | * move ht6560b support to ht6560b.c | |||
| 199 | * move qd6580 support to qd6580.c | |||
| 200 | * add ali14xx support in ali14xx.c | |||
| 201 | * Version 5.27 add [no]autotune parameters to help cmd640 | |||
| 202 | * move rz1000 support to rz1000.c | |||
| 203 | * Version 5.28 #include "ide_modes.h" | |||
| 204 | * fix disallow_unmask: now per-interface "no_unmask" bit | |||
| 205 | * force io_32bit to be the same on drive pairs of dtc2278 | |||
| 206 | * improved IDE tape error handling, and tape DMA support | |||
| 207 | * bugfix in ide_do_drive_cmd() for cdroms + serialize | |||
| 208 | * Version 5.29 fixed non-IDE check for too many physical heads | |||
| 209 | * don't use LBA if capacity is smaller than CHS | |||
| 210 | * Version 5.30 remove real_devices kludge, formerly used by genhd.c | |||
| 211 | * Version 5.32 change "KB" to "kB" | |||
| 212 | * fix serialize (was broken in kernel 1.3.72) | |||
| 213 | * add support for "hdparm -I" | |||
| 214 | * use common code for disk/tape/cdrom IDE_DRIVE_CMDs | |||
| 215 | * add support for Promise DC4030VL caching card | |||
| 216 | * improved serialize support | |||
| 217 | * put partition check back into alphabetical order | |||
| 218 | * add config option for PCMCIA baggage | |||
| 219 | * try to make PCMCIA support safer to use | |||
| 220 | * improve security on ioctls(): all are suser() only | |||
| 221 | * Version 5.33 improve handling of HDIO_DRIVE_CMDs that read data | |||
| 222 | * Version 5.34 fix irq-sharing problem from 5.33 | |||
| 223 | * fix cdrom ioctl problem from 5.33 | |||
| 224 | * Version 5.35 cosmetic changes | |||
| 225 | * fix cli() problem in try_to_identify() | |||
| 226 | * Version 5.36 fixes to optional PCMCIA support | |||
| 227 | * Version 5.37 don't use DMA when "noautotune" is specified | |||
| 228 | * Version 5.37a (go) fix shared irq probing (was broken in kernel 1.3.72) | |||
| 229 | * call unplug_device() from ide_do_drive_cmd() | |||
| 230 | * Version 5.38 add "hdx=none" option, courtesy of Joel Maslak | |||
| 231 | * mask drive irq after use, if sharing with another hwif | |||
| 232 | * add code to help debug weird cmd640 problems | |||
| 233 | * Version 5.39 fix horrible error in earlier irq sharing "fix" | |||
| 234 | * Version 5.40 fix serialization -- was broken in 5.39 | |||
| 235 | * help sharing by masking device irq after probing | |||
| 236 | * Version 5.41 more fixes to irq sharing/serialize detection | |||
| 237 | * disable io_32bit by default on drive reset | |||
| 238 | * Version 5.42 simplify irq-masking after probe | |||
| 239 | * fix NULL pointer deref in save_match() | |||
| 240 | * Version 5.43 Ugh.. unexpected_intr is back: try to exterminate it | |||
| 241 | * Version 5.44 Fix for "irq probe failed" on cmd640 | |||
| 242 | * change path on message regarding MAKEDEV.ide | |||
| 243 | * add a throttle to the unexpected_intr() messages | |||
| 244 | * Version 5.45 fix ugly parameter parsing bugs (thanks Derek) | |||
| 245 | * include Gadi's magic fix for cmd640 unexpected_intr | |||
| 246 | * include mc68000 patches from Geert Uytterhoeven | |||
| 247 | * add Gadi's fix for PCMCIA cdroms | |||
| 248 | * Version 5.46 remove the mc68000 #ifdefs for 2.0.x | |||
| 249 | * Version 5.47 fix set_tune race condition | |||
| 250 | * fix bug in earlier PCMCIA cdrom update | |||
| 251 | * Version 5.48 if def'd, invoke CMD640_DUMP_REGS when irq probe fails | |||
| 252 | * lengthen the do_reset1() pulse, for laptops | |||
| 253 | * add idebus=xx parameter for cmd640 and ali chipsets | |||
| 254 | * no_unmask flag now per-drive instead of per-hwif | |||
| 255 | * fix tune_req so that it gets done immediately | |||
| 256 | * fix missing restore_flags() in ide_ioctl | |||
| 257 | * prevent use of io_32bit on cmd640 with no prefetch | |||
| 258 | * Version 5.49 fix minor quirks in probing routines | |||
| 259 | * Version 5.50 allow values as small as 20 for idebus= | |||
| 260 | * Version 5.51 force non io_32bit in drive_cmd_intr() | |||
| 261 | * change delay_10ms() to delay_50ms() to fix problems | |||
| 262 | * Version 5.52 fix incorrect invalidation of removable devices | |||
| 263 | * add "hdx=slow" command line option | |||
| 264 | * Version 5.53 add ATAPI floppy drive support | |||
| 265 | * change default media for type 0 to floppy | |||
| 266 | * add support for Exabyte Nest | |||
| 267 | * add missing set_blocksize() in revalidate_disk() | |||
| 268 | * handle bad status bit sequencing in ide_wait_stat() | |||
| 269 | * support partition table translations with 255 heads | |||
| 270 | * probe all interfaces by default | |||
| 271 | * add probe for the i82371AB chipset | |||
| 272 | * acknowledge media change on removable drives | |||
| 273 | * add work-around for BMI drives | |||
| 274 | * remove "LBA" from boot messages | |||
| 275 | * Version 5.53.1 add UDMA "CRC retry" support | |||
| 276 | * Version 5.53.2 add Promise/33 auto-detection and DMA support | |||
| 277 | * fix MC_ERR handling | |||
| 278 | * fix mis-detection of NEC cdrom as floppy | |||
| 279 | * issue ATAPI reset and re-probe after "no response" | |||
| 280 | * | |||
| 281 | * Some additional driver compile-time options are in ide.h | |||
| 282 | * | |||
| 283 | * To do, in likely order of completion: | |||
| 284 | * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f | |||
| 285 | */ | |||
| 286 | ||||
| 287 | #undef REALLY_SLOW_IO /* most systems can safely undef this */ | |||
| 288 | ||||
| 289 | #include <linux/config.h> | |||
| 290 | #include <linux/types.h> | |||
| 291 | #include <linux/string.h> | |||
| 292 | #include <linux/kernel.h> | |||
| 293 | #include <linux/delay.h> | |||
| 294 | #include <linux/timer.h> | |||
| 295 | #include <linux/mm.h> | |||
| 296 | #include <linux/ioport.h> | |||
| 297 | #include <linux/interrupt.h> | |||
| 298 | #include <linux/major.h> | |||
| 299 | #include <linux/blkdev.h> | |||
| 300 | #include <linux/errno.h> | |||
| 301 | #include <linux/hdreg.h> | |||
| 302 | #include <linux/genhd.h> | |||
| 303 | #include <linux/malloc.h> | |||
| 304 | ||||
| 305 | #include <ahci.h> | |||
| 306 | ||||
| 307 | #include <asm/byteorder.h> | |||
| 308 | #include <asm/irq.h> | |||
| 309 | #include <asm/segment.h> | |||
| 310 | #include <asm/io.h> | |||
| 311 | ||||
| 312 | #ifdef CONFIG_PCI1 | |||
| 313 | #include <linux/bios32.h> | |||
| 314 | #include <linux/pci.h> | |||
| 315 | #endif /* CONFIG_PCI */ | |||
| 316 | ||||
| 317 | #include "ide.h" | |||
| 318 | #include "ide_modes.h" | |||
| 319 | ||||
| 320 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 321 | #include "promise.h" | |||
| 322 | #define IS_PROMISE_DRIVE(0) (HWIF(drive)((ide_hwif_t *)((drive)->hwif))->chipset == ide_promise) | |||
| 323 | #else | |||
| 324 | #define IS_PROMISE_DRIVE(0) (0) /* auto-NULLs out Promise code */ | |||
| 325 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 326 | ||||
| 327 | static const byte ide_hwif_to_major[MAX_HWIFS4] = {IDE0_MAJOR3, IDE1_MAJOR22, IDE2_MAJOR33, IDE3_MAJOR34}; | |||
| 328 | static const unsigned short default_io_base[MAX_HWIFS4] = {0x1f0, 0x170, 0x1e8, 0x168}; | |||
| 329 | static const byte default_irqs[MAX_HWIFS4] = {14, 15, 11, 10}; | |||
| 330 | static int idebus_parameter; /* holds the "idebus=" parameter */ | |||
| 331 | static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ | |||
| 332 | ||||
| 333 | /* | |||
| 334 | * This is declared extern in ide.h, for access by other IDE modules: | |||
| 335 | */ | |||
| 336 | ide_hwif_t ide_hwifs[MAX_HWIFS4]; /* master data repository */ | |||
| 337 | ||||
| 338 | #if (DISK_RECOVERY_TIME0 > 0) | |||
| 339 | /* | |||
| 340 | * For really screwy hardware (hey, at least it *can* be used with Linux) | |||
| 341 | * we can enforce a minimum delay time between successive operations. | |||
| 342 | */ | |||
| 343 | static unsigned long read_timer(void) | |||
| 344 | { | |||
| 345 | unsigned long t, flags; | |||
| 346 | int i; | |||
| 347 | ||||
| 348 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 349 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 350 | t = jiffies * 11932; | |||
| 351 | outb_p(0, 0x43)((__builtin_constant_p((0x43)) && (0x43) < 256) ? __outbc_p ((0),(0x43)) : __outb_p((0),(0x43))); | |||
| 352 | i = inb_p(0x40)((__builtin_constant_p((0x40)) && (0x40) < 256) ? __inbc_p (0x40) : __inb_p(0x40)); | |||
| 353 | i |= inb(0x40)((__builtin_constant_p((0x40)) && (0x40) < 256) ? __inbc (0x40) : __inb(0x40)) << 8; | |||
| 354 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 355 | return (t - i); | |||
| 356 | } | |||
| 357 | ||||
| 358 | static void set_recovery_timer (ide_hwif_t *hwif) | |||
| 359 | { | |||
| 360 | hwif->last_time = read_timer(); | |||
| 361 | } | |||
| 362 | #define SET_RECOVERY_TIMER(drive) set_recovery_timer (drive) | |||
| 363 | ||||
| 364 | #else | |||
| 365 | ||||
| 366 | #define SET_RECOVERY_TIMER(drive) | |||
| 367 | ||||
| 368 | #endif /* DISK_RECOVERY_TIME */ | |||
| 369 | ||||
| 370 | ||||
| 371 | /* | |||
| 372 | * Do not even *think* about calling this! | |||
| 373 | */ | |||
| 374 | static void init_hwif_data (unsigned int index) | |||
| 375 | { | |||
| 376 | byte *p; | |||
| 377 | unsigned int unit; | |||
| 378 | ide_hwif_t *hwif = &ide_hwifs[index]; | |||
| 379 | ||||
| 380 | /* bulk initialize hwif & drive info with zeros */ | |||
| 381 | p = ((byte *) hwif) + sizeof(ide_hwif_t); | |||
| 382 | do { | |||
| 383 | *--p = 0; | |||
| 384 | } while (p > (byte *) hwif); | |||
| 385 | ||||
| 386 | /* fill in any non-zero initial values */ | |||
| 387 | hwif->index = index; | |||
| 388 | hwif->io_base = default_io_base[index]; | |||
| 389 | hwif->ctl_port = hwif->io_base ? hwif->io_base+0x206 : 0x000; | |||
| 390 | #ifdef CONFIG_BLK_DEV_HD | |||
| 391 | if (hwif->io_base == HD_DATA0x1f0) | |||
| 392 | hwif->noprobe = 1; /* may be overridden by ide_setup() */ | |||
| 393 | #endif /* CONFIG_BLK_DEV_HD */ | |||
| 394 | hwif->major = ide_hwif_to_major[index]; | |||
| 395 | hwif->name[0] = 'i'; | |||
| 396 | hwif->name[1] = 'd'; | |||
| 397 | hwif->name[2] = 'e'; | |||
| 398 | hwif->name[3] = '0' + index; | |||
| 399 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 400 | hwif->tape_drive = NULL((void *) 0); | |||
| 401 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 402 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 403 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 404 | ||||
| 405 | drive->select.all = (unit<<4)|0xa0; | |||
| 406 | drive->hwif = hwif; | |||
| 407 | drive->ctl = 0x08; | |||
| 408 | drive->ready_stat = READY_STAT0x40; | |||
| 409 | drive->bad_wstat = BAD_W_STAT((0x80 | 0x01) | 0x20); | |||
| 410 | drive->special.b.recalibrate = 1; | |||
| 411 | drive->special.b.set_geometry = 1; | |||
| 412 | drive->name[0] = 'h'; | |||
| 413 | drive->name[1] = 'd'; | |||
| 414 | #ifdef MACH1 | |||
| 415 | drive->name[2] = '0' + (index * MAX_DRIVES2) + unit; | |||
| 416 | #else | |||
| 417 | drive->name[2] = 'a' + (index * MAX_DRIVES2) + unit; | |||
| 418 | #endif | |||
| 419 | } | |||
| 420 | } | |||
| 421 | ||||
| 422 | /* | |||
| 423 | * init_ide_data() sets reasonable default values into all fields | |||
| 424 | * of all instances of the hwifs and drives, but only on the first call. | |||
| 425 | * Subsequent calls have no effect (they don't wipe out anything). | |||
| 426 | * | |||
| 427 | * This routine is normally called at driver initialization time, | |||
| 428 | * but may also be called MUCH earlier during kernel "command-line" | |||
| 429 | * parameter processing. As such, we cannot depend on any other parts | |||
| 430 | * of the kernel (such as memory allocation) to be functioning yet. | |||
| 431 | * | |||
| 432 | * This is too bad, as otherwise we could dynamically allocate the | |||
| 433 | * ide_drive_t structs as needed, rather than always consuming memory | |||
| 434 | * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them. | |||
| 435 | */ | |||
| 436 | #define MAGIC_COOKIE0x12345678 0x12345678 | |||
| 437 | static void init_ide_data (void) | |||
| 438 | { | |||
| 439 | unsigned int index; | |||
| 440 | static unsigned long magic_cookie = MAGIC_COOKIE0x12345678; | |||
| 441 | ||||
| 442 | if (magic_cookie != MAGIC_COOKIE0x12345678) | |||
| 443 | return; /* already initialized */ | |||
| 444 | magic_cookie = 0; | |||
| 445 | ||||
| 446 | for (index = 0; index < MAX_HWIFS4; ++index) | |||
| 447 | init_hwif_data(index); | |||
| 448 | ||||
| 449 | idebus_parameter = 0; | |||
| 450 | system_bus_speed = 0; | |||
| 451 | } | |||
| 452 | ||||
| 453 | /* | |||
| 454 | * ide_system_bus_speed() returns what we think is the system VESA/PCI | |||
| 455 | * bus speed (in Mhz). This is used for calculating interface PIO timings. | |||
| 456 | * The default is 40 for known PCI systems, 50 otherwise. | |||
| 457 | * The "idebus=xx" parameter can be used to override this value. | |||
| 458 | * The actual value to be used is computed/displayed the first time through. | |||
| 459 | */ | |||
| 460 | int ide_system_bus_speed (void) | |||
| 461 | { | |||
| 462 | if (!system_bus_speed) { | |||
| 463 | if (idebus_parameter) | |||
| 464 | system_bus_speed = idebus_parameter; /* user supplied value */ | |||
| 465 | #ifdef CONFIG_PCI1 | |||
| 466 | else if (pcibios_present()) | |||
| 467 | system_bus_speed = 40; /* safe default value for PCI */ | |||
| 468 | #endif /* CONFIG_PCI */ | |||
| 469 | else | |||
| 470 | system_bus_speed = 50; /* safe default value for VESA and PCI */ | |||
| 471 | printk("ide: Assuming %dMhz system bus speed for PIO modes; override with idebus=xx\n", system_bus_speed); | |||
| 472 | } | |||
| 473 | return system_bus_speed; | |||
| 474 | } | |||
| 475 | ||||
| 476 | #if SUPPORT_VLB_SYNC1 | |||
| 477 | /* | |||
| 478 | * Some localbus EIDE interfaces require a special access sequence | |||
| 479 | * when using 32-bit I/O instructions to transfer data. We call this | |||
| 480 | * the "vlb_sync" sequence, which consists of three successive reads | |||
| 481 | * of the sector count register location, with interrupts disabled | |||
| 482 | * to ensure that the reads all happen together. | |||
| 483 | */ | |||
| 484 | static inlineinline __attribute__((always_inline)) void do_vlb_sync (unsigned short port) { | |||
| 485 | (void) inb (port)((__builtin_constant_p((port)) && (port) < 256) ? __inbc (port) : __inb(port)); | |||
| 486 | (void) inb (port)((__builtin_constant_p((port)) && (port) < 256) ? __inbc (port) : __inb(port)); | |||
| 487 | (void) inb (port)((__builtin_constant_p((port)) && (port) < 256) ? __inbc (port) : __inb(port)); | |||
| 488 | } | |||
| 489 | #endif /* SUPPORT_VLB_SYNC */ | |||
| 490 | ||||
| 491 | /* | |||
| 492 | * This is used for most PIO data transfers *from* the IDE interface | |||
| 493 | */ | |||
| 494 | void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) | |||
| 495 | { | |||
| 496 | unsigned short io_base = HWIF(drive)((ide_hwif_t *)((drive)->hwif))->io_base; | |||
| 497 | unsigned short data_reg = io_base+IDE_DATA_OFFSET(0); | |||
| 498 | byte io_32bit = drive->io_32bit; | |||
| 499 | ||||
| 500 | if (io_32bit) { | |||
| 501 | #if SUPPORT_VLB_SYNC1 | |||
| 502 | if (io_32bit & 2) { | |||
| 503 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 504 | do_vlb_sync(io_base+IDE_NSECTOR_OFFSET(2)); | |||
| 505 | insl(data_reg, buffer, wcount); | |||
| 506 | if (drive->unmask) | |||
| 507 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 508 | } else | |||
| 509 | #endif /* SUPPORT_VLB_SYNC */ | |||
| 510 | insl(data_reg, buffer, wcount); | |||
| 511 | } else { | |||
| 512 | #if SUPPORT_SLOW_DATA_PORTS1 | |||
| 513 | if (drive->slow) { | |||
| 514 | unsigned short *ptr = (unsigned short *) buffer; | |||
| 515 | while (wcount--) { | |||
| 516 | *ptr++ = inw_p(data_reg)((__builtin_constant_p((data_reg)) && (data_reg) < 256) ? __inwc_p(data_reg) : __inw_p(data_reg)); | |||
| 517 | *ptr++ = inw_p(data_reg)((__builtin_constant_p((data_reg)) && (data_reg) < 256) ? __inwc_p(data_reg) : __inw_p(data_reg)); | |||
| 518 | } | |||
| 519 | } else | |||
| 520 | #endif /* SUPPORT_SLOW_DATA_PORTS */ | |||
| 521 | insw(data_reg, buffer, wcount<<1); | |||
| 522 | } | |||
| 523 | } | |||
| 524 | ||||
| 525 | /* | |||
| 526 | * This is used for most PIO data transfers *to* the IDE interface | |||
| 527 | */ | |||
| 528 | void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) | |||
| 529 | { | |||
| 530 | unsigned short io_base = HWIF(drive)((ide_hwif_t *)((drive)->hwif))->io_base; | |||
| 531 | unsigned short data_reg = io_base+IDE_DATA_OFFSET(0); | |||
| 532 | byte io_32bit = drive->io_32bit; | |||
| 533 | ||||
| 534 | if (io_32bit) { | |||
| 535 | #if SUPPORT_VLB_SYNC1 | |||
| 536 | if (io_32bit & 2) { | |||
| 537 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 538 | do_vlb_sync(io_base+IDE_NSECTOR_OFFSET(2)); | |||
| 539 | outsl(data_reg, buffer, wcount); | |||
| 540 | if (drive->unmask) | |||
| 541 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 542 | } else | |||
| 543 | #endif /* SUPPORT_VLB_SYNC */ | |||
| 544 | outsl(data_reg, buffer, wcount); | |||
| 545 | } else { | |||
| 546 | #if SUPPORT_SLOW_DATA_PORTS1 | |||
| 547 | if (drive->slow) { | |||
| 548 | unsigned short *ptr = (unsigned short *) buffer; | |||
| 549 | while (wcount--) { | |||
| 550 | outw_p(*ptr++, data_reg)((__builtin_constant_p((data_reg)) && (data_reg) < 256) ? __outwc_p((*ptr++),(data_reg)) : __outw_p((*ptr++),(data_reg ))); | |||
| 551 | outw_p(*ptr++, data_reg)((__builtin_constant_p((data_reg)) && (data_reg) < 256) ? __outwc_p((*ptr++),(data_reg)) : __outw_p((*ptr++),(data_reg ))); | |||
| 552 | } | |||
| 553 | } else | |||
| 554 | #endif /* SUPPORT_SLOW_DATA_PORTS */ | |||
| 555 | outsw(data_reg, buffer, wcount<<1); | |||
| 556 | } | |||
| 557 | } | |||
| 558 | ||||
| 559 | /* | |||
| 560 | * The following routines are mainly used by the ATAPI drivers. | |||
| 561 | * | |||
| 562 | * These routines will round up any request for an odd number of bytes, | |||
| 563 | * so if an odd bytecount is specified, be sure that there's at least one | |||
| 564 | * extra byte allocated for the buffer. | |||
| 565 | */ | |||
| 566 | void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) | |||
| 567 | { | |||
| 568 | ++bytecount; | |||
| 569 | ide_input_data (drive, buffer, bytecount / 4); | |||
| 570 | if ((bytecount & 0x03) >= 2) | |||
| 571 | insw (IDE_DATA_REG(((ide_hwif_t *)((drive)->hwif))->io_base+(0)), ((byte *)buffer) + (bytecount & ~0x03), 1); | |||
| 572 | } | |||
| 573 | ||||
| 574 | void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) | |||
| 575 | { | |||
| 576 | ++bytecount; | |||
| 577 | ide_output_data (drive, buffer, bytecount / 4); | |||
| 578 | if ((bytecount & 0x03) >= 2) | |||
| 579 | outsw (IDE_DATA_REG(((ide_hwif_t *)((drive)->hwif))->io_base+(0)), ((byte *)buffer) + (bytecount & ~0x03), 1); | |||
| 580 | } | |||
| 581 | ||||
| 582 | /* | |||
| 583 | * This should get invoked any time we exit the driver to | |||
| 584 | * wait for an interrupt response from a drive. handler() points | |||
| 585 | * at the appropriate code to handle the next interrupt, and a | |||
| 586 | * timer is started to prevent us from waiting forever in case | |||
| 587 | * something goes wrong (see the timer_expiry() handler later on). | |||
| 588 | */ | |||
| 589 | void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout) | |||
| 590 | { | |||
| 591 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 592 | #ifdef DEBUG | |||
| 593 | if (hwgroup->handler != NULL((void *) 0)) { | |||
| 594 | printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n", | |||
| 595 | drive->name, hwgroup->handler, handler); | |||
| 596 | } | |||
| 597 | #endif | |||
| 598 | hwgroup->handler = handler; | |||
| 599 | hwgroup->timer.expires = jiffies + timeout; | |||
| 600 | add_timer(&(hwgroup->timer)); | |||
| 601 | } | |||
| 602 | ||||
| 603 | /* | |||
| 604 | * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" | |||
| 605 | * value for this drive (from its reported identification information). | |||
| 606 | * | |||
| 607 | * Returns: 1 if lba_capacity looks sensible | |||
| 608 | * 0 otherwise | |||
| 609 | * | |||
| 610 | * Note: we must not change id->cyls here, otherwise a second call | |||
| 611 | * of this routine might no longer find lba_capacity ok. | |||
| 612 | */ | |||
| 613 | static int lba_capacity_is_ok (struct hd_driveid *id) | |||
| 614 | { | |||
| 615 | unsigned long lba_sects = id->lba_capacity; | |||
| 616 | unsigned long chs_sects = id->cyls * id->heads * id->sectors; | |||
| 617 | unsigned long _10_percent = chs_sects / 10; | |||
| 618 | ||||
| 619 | /* | |||
| 620 | * The ATA spec tells large drives to return | |||
| 621 | * C/H/S = 16383/16/63 independent of their size. | |||
| 622 | * Some drives can be jumpered to use 15 heads instead of 16. | |||
| 623 | */ | |||
| 624 | if (id->cyls == 16383 && id->sectors == 63 && | |||
| 625 | (id->heads == 15 || id->heads == 16) && | |||
| 626 | id->lba_capacity >= 16383*63*id->heads) | |||
| 627 | return 1; /* lba_capacity is our only option */ | |||
| 628 | ||||
| 629 | /* perform a rough sanity check on lba_sects: within 10% is "okay" */ | |||
| 630 | if ((lba_sects - chs_sects) < _10_percent) | |||
| 631 | return 1; /* lba_capacity is good */ | |||
| 632 | ||||
| 633 | /* some drives have the word order reversed */ | |||
| 634 | lba_sects = (lba_sects << 16) | (lba_sects >> 16); | |||
| 635 | if ((lba_sects - chs_sects) < _10_percent) { | |||
| 636 | id->lba_capacity = lba_sects; /* fix it */ | |||
| 637 | return 1; /* lba_capacity is (now) good */ | |||
| 638 | } | |||
| 639 | return 0; /* lba_capacity value is bad */ | |||
| 640 | } | |||
| 641 | ||||
| 642 | /* | |||
| 643 | * current_capacity() returns the capacity (in sectors) of a drive | |||
| 644 | * according to its current geometry/LBA settings. | |||
| 645 | * | |||
| 646 | * It also sets select.b.lba. | |||
| 647 | */ | |||
| 648 | static unsigned long current_capacity (ide_drive_t *drive) | |||
| 649 | { | |||
| 650 | struct hd_driveid *id = drive->id; | |||
| 651 | unsigned long capacity; | |||
| 652 | ||||
| 653 | if (!drive->present) | |||
| 654 | return 0; | |||
| 655 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 656 | if (drive->media == ide_floppy) | |||
| 657 | return idefloppy_capacity(drive); | |||
| 658 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 659 | if (drive->media != ide_disk) | |||
| 660 | return 0x7fffffff; /* cdrom or tape */ | |||
| 661 | ||||
| 662 | drive->select.b.lba = 0; | |||
| 663 | /* Determine capacity, and use LBA if the drive properly supports it */ | |||
| 664 | capacity = drive->cyl * drive->head * drive->sect; | |||
| 665 | if (id != NULL((void *) 0) && (id->capability & 2) && lba_capacity_is_ok(id)) { | |||
| 666 | if (id->lba_capacity >= capacity) { | |||
| 667 | capacity = id->lba_capacity; | |||
| 668 | drive->select.b.lba = 1; | |||
| 669 | } | |||
| 670 | } | |||
| 671 | return (capacity - drive->sect0); | |||
| 672 | } | |||
| 673 | ||||
| 674 | /* | |||
| 675 | * ide_geninit() is called exactly *once* for each major, from genhd.c, | |||
| 676 | * at the beginning of the initial partition check for the drives. | |||
| 677 | */ | |||
| 678 | static void ide_geninit (struct gendisk *gd) | |||
| 679 | { | |||
| 680 | unsigned int unit; | |||
| 681 | ide_hwif_t *hwif = gd->real_devices; | |||
| 682 | ||||
| 683 | for (unit = 0; unit < gd->nr_real; ++unit) { | |||
| 684 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 685 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 686 | if (drive->present && drive->media == ide_cdrom) | |||
| 687 | ide_cdrom_setup(drive); | |||
| 688 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 689 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 690 | if (drive->present && drive->media == ide_tape) | |||
| 691 | idetape_setup(drive); | |||
| 692 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 693 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 694 | if (drive->present && drive->media == ide_floppy) | |||
| 695 | idefloppy_setup(drive); | |||
| 696 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 697 | drive->part[0].nr_sects = current_capacity(drive); | |||
| 698 | if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) || | |||
| 699 | !drive->part[0].nr_sects) { | |||
| 700 | drive->part[0].start_sect = -1; /* skip partition check */ | |||
| 701 | } | |||
| 702 | } | |||
| 703 | } | |||
| 704 | ||||
| 705 | /* | |||
| 706 | * init_gendisk() (as opposed to ide_geninit) is called for each major device, | |||
| 707 | * after probing for drives, to allocate partition tables and other data | |||
| 708 | * structures needed for the routines in genhd.c. ide_geninit() gets called | |||
| 709 | * somewhat later, during the partition check. | |||
| 710 | */ | |||
| 711 | static void init_gendisk (ide_hwif_t *hwif) | |||
| 712 | { | |||
| 713 | struct gendisk *gd, **gdp; | |||
| 714 | unsigned int unit, units, minors; | |||
| 715 | int *bs; | |||
| 716 | ||||
| 717 | /* figure out maximum drive number on the interface */ | |||
| 718 | for (units = MAX_DRIVES2; units > 0; --units) { | |||
| 719 | if (hwif->drives[units-1].present) | |||
| 720 | break; | |||
| 721 | } | |||
| 722 | minors = units * (1<<PARTN_BITS6); | |||
| 723 | gd = kmalloclinux_kmalloc (sizeof(struct gendisk), GFP_KERNEL0x03); | |||
| 724 | gd->sizes = kmalloclinux_kmalloc (minors * sizeof(int), GFP_KERNEL0x03); | |||
| 725 | gd->part = kmalloclinux_kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL0x03); | |||
| 726 | bs = kmalloclinux_kmalloc (minors*sizeof(int), GFP_KERNEL0x03); | |||
| 727 | ||||
| 728 | memset(gd->part, 0, minors * sizeof(struct hd_struct))(__builtin_constant_p(0) ? (__builtin_constant_p((minors * sizeof (struct hd_struct))) ? __constant_c_and_count_memset(((gd-> part)),((0x01010101UL*(unsigned char)(0))),((minors * sizeof( struct hd_struct)))) : __constant_c_memset(((gd->part)),(( 0x01010101UL*(unsigned char)(0))),((minors * sizeof(struct hd_struct ))))) : (__builtin_constant_p((minors * sizeof(struct hd_struct ))) ? __memset_generic((((gd->part))),(((0))),(((minors * sizeof (struct hd_struct))))) : __memset_generic(((gd->part)),((0 )),((minors * sizeof(struct hd_struct)))))); | |||
| 729 | ||||
| 730 | /* cdroms and msdos f/s are examples of non-1024 blocksizes */ | |||
| 731 | blksize_size[hwif->major] = bs; | |||
| 732 | for (unit = 0; unit < minors; ++unit) | |||
| 733 | *bs++ = BLOCK_SIZE1024; | |||
| 734 | ||||
| 735 | for (unit = 0; unit < units; ++unit) | |||
| 736 | hwif->drives[unit].part = &gd->part[unit << PARTN_BITS6]; | |||
| 737 | ||||
| 738 | gd->major = hwif->major; /* our major device number */ | |||
| 739 | gd->major_name = IDE_MAJOR_NAME"ide"; /* treated special in genhd.c */ | |||
| 740 | gd->minor_shift = PARTN_BITS6; /* num bits for partitions */ | |||
| 741 | gd->max_p = 1<<PARTN_BITS6; /* 1 + max partitions / drive */ | |||
| 742 | gd->max_nr = units; /* max num real drives */ | |||
| 743 | gd->nr_real = units; /* current num real drives */ | |||
| 744 | gd->init = ide_geninit; /* initialization function */ | |||
| 745 | gd->real_devices= hwif; /* ptr to internal data */ | |||
| 746 | gd->next = NULL((void *) 0); /* linked list of major devs */ | |||
| 747 | ||||
| 748 | for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) ; | |||
| 749 | hwif->gd = *gdp = gd; /* link onto tail of list */ | |||
| 750 | } | |||
| 751 | ||||
| 752 | static void do_reset1 (ide_drive_t *, int); /* needed below */ | |||
| 753 | ||||
| 754 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 755 | /* | |||
| 756 | * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms | |||
| 757 | * during an atapi drive reset operation. If the drive has not yet responded, | |||
| 758 | * and we have not yet hit our maximum waiting time, then the timer is restarted | |||
| 759 | * for another 50ms. | |||
| 760 | */ | |||
| 761 | static void atapi_reset_pollfunc (ide_drive_t *drive) | |||
| 762 | { | |||
| 763 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 764 | byte stat; | |||
| 765 | ||||
| 766 | OUT_BYTE (drive->select.all, IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((drive->select .all)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6)) ))) : __outb_p(((drive->select.all)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(6)))))); | |||
| 767 | udelay (10)(__builtin_constant_p(10) ? __const_udelay((10) * 0x10c6ul) : __udelay(10)); | |||
| 768 | ||||
| 769 | if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)(((stat=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&( (0)|(0x80)))==(0))) { | |||
| 770 | printk("%s: ATAPI reset complete\n", drive->name); | |||
| 771 | } else { | |||
| 772 | if (jiffies < hwgroup->poll_timeout) { | |||
| 773 | ide_set_handler (drive, &atapi_reset_pollfunc, HZ100/20); | |||
| 774 | return; /* continue polling */ | |||
| 775 | } | |||
| 776 | hwgroup->poll_timeout = 0; /* end of polling */ | |||
| 777 | printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); | |||
| 778 | do_reset1 (drive, 1); /* do it the old fashioned way */ | |||
| 779 | return; | |||
| 780 | } | |||
| 781 | hwgroup->poll_timeout = 0; /* done polling */ | |||
| 782 | } | |||
| 783 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 784 | ||||
| 785 | /* | |||
| 786 | * reset_pollfunc() gets invoked to poll the interface for completion every 50ms | |||
| 787 | * during an ide reset operation. If the drives have not yet responded, | |||
| 788 | * and we have not yet hit our maximum waiting time, then the timer is restarted | |||
| 789 | * for another 50ms. | |||
| 790 | */ | |||
| 791 | static void reset_pollfunc (ide_drive_t *drive) | |||
| 792 | { | |||
| 793 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 794 | ide_hwif_t *hwif = HWIF(drive)((ide_hwif_t *)((drive)->hwif)); | |||
| 795 | byte tmp; | |||
| 796 | ||||
| 797 | if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)(((tmp=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive) ->hwif))->io_base+(7)))) && ((((ide_hwif_t *)(( drive)->hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&((0)|(0x80)))== (0))) { | |||
| 798 | if (jiffies < hwgroup->poll_timeout) { | |||
| 799 | ide_set_handler (drive, &reset_pollfunc, HZ100/20); | |||
| 800 | return; /* continue polling */ | |||
| 801 | } | |||
| 802 | printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); | |||
| 803 | } else { | |||
| 804 | printk("%s: reset: ", hwif->name); | |||
| 805 | if ((tmp = GET_ERR()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(1)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(1))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(1))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(1))))) == 1) | |||
| 806 | printk("success\n"); | |||
| 807 | else { | |||
| 808 | #if FANCY_STATUS_DUMPS1 | |||
| 809 | printk("master: "); | |||
| 810 | switch (tmp & 0x7f) { | |||
| 811 | case 1: printk("passed"); | |||
| 812 | break; | |||
| 813 | case 2: printk("formatter device error"); | |||
| 814 | break; | |||
| 815 | case 3: printk("sector buffer error"); | |||
| 816 | break; | |||
| 817 | case 4: printk("ECC circuitry error"); | |||
| 818 | break; | |||
| 819 | case 5: printk("controlling MPU error"); | |||
| 820 | break; | |||
| 821 | default:printk("error (0x%02x?)", tmp); | |||
| 822 | } | |||
| 823 | if (tmp & 0x80) | |||
| 824 | printk("; slave: failed"); | |||
| 825 | printk("\n"); | |||
| 826 | #else | |||
| 827 | printk("failed\n"); | |||
| 828 | #endif /* FANCY_STATUS_DUMPS */ | |||
| 829 | } | |||
| 830 | } | |||
| 831 | hwgroup->poll_timeout = 0; /* done polling */ | |||
| 832 | } | |||
| 833 | ||||
| 834 | /* | |||
| 835 | * do_reset1() attempts to recover a confused drive by resetting it. | |||
| 836 | * Unfortunately, resetting a disk drive actually resets all devices on | |||
| 837 | * the same interface, so it can really be thought of as resetting the | |||
| 838 | * interface rather than resetting the drive. | |||
| 839 | * | |||
| 840 | * ATAPI devices have their own reset mechanism which allows them to be | |||
| 841 | * individually reset without clobbering other devices on the same interface. | |||
| 842 | * | |||
| 843 | * Unfortunately, the IDE interface does not generate an interrupt to let | |||
| 844 | * us know when the reset operation has finished, so we must poll for this. | |||
| 845 | * Equally poor, though, is the fact that this may a very long time to complete, | |||
| 846 | * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, | |||
| 847 | * we set a timer to poll at 50ms intervals. | |||
| 848 | */ | |||
| 849 | static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
| 850 | { | |||
| 851 | unsigned int unit; | |||
| 852 | unsigned long flags; | |||
| 853 | ide_hwif_t *hwif = HWIF(drive)((ide_hwif_t *)((drive)->hwif)); | |||
| 854 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 855 | ||||
| 856 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 857 | cli()__asm__ __volatile__ ("cli": : :"memory"); /* Why ? */ | |||
| 858 | ||||
| 859 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 860 | /* For an ATAPI device, first try an ATAPI SRST. */ | |||
| 861 | if (drive->media != ide_disk) { | |||
| 862 | if (!do_not_try_atapi) { | |||
| 863 | if (!drive->keep_settings) { | |||
| 864 | drive->unmask = 0; | |||
| 865 | drive->io_32bit = 0; | |||
| 866 | } | |||
| 867 | OUT_BYTE (drive->select.all, IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((drive->select .all)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6)) ))) : __outb_p(((drive->select.all)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(6)))))); | |||
| 868 | udelay (20)(__builtin_constant_p(20) ? __const_udelay((20) * 0x10c6ul) : __udelay(20)); | |||
| 869 | OUT_BYTE (WIN_SRST, IDE_COMMAND_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(7))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) < 256) ? __outbc_p(((0x08)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) : __outb_p(((0x08) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))); | |||
| 870 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE(30*100); | |||
| 871 | ide_set_handler (drive, &atapi_reset_pollfunc, HZ100/20); | |||
| 872 | restore_flags (flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 873 | return; | |||
| 874 | } | |||
| 875 | } | |||
| 876 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 877 | ||||
| 878 | /* | |||
| 879 | * First, reset any device state data we were maintaining | |||
| 880 | * for any of the drives on this interface. | |||
| 881 | */ | |||
| 882 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 883 | ide_drive_t *rdrive = &hwif->drives[unit]; | |||
| 884 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 885 | if (rdrive->media == ide_tape) | |||
| 886 | rdrive->tape.reset_issued = 1; | |||
| 887 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 888 | rdrive->special.all = 0; | |||
| 889 | rdrive->special.b.set_geometry = 1; | |||
| 890 | rdrive->special.b.recalibrate = 1; | |||
| 891 | if (OK_TO_RESET_CONTROLLER1) | |||
| 892 | rdrive->mult_count = 0; | |||
| 893 | if (!rdrive->keep_settings) { | |||
| 894 | rdrive->mult_req = 0; | |||
| 895 | rdrive->unmask = 0; | |||
| 896 | rdrive->io_32bit = 0; | |||
| 897 | if (rdrive->using_dma) { | |||
| 898 | rdrive->using_dma = 0; | |||
| 899 | printk("%s: disabled DMA\n", rdrive->name); | |||
| 900 | } | |||
| 901 | } | |||
| 902 | if (rdrive->mult_req != rdrive->mult_count) | |||
| 903 | rdrive->special.b.set_multmode = 1; | |||
| 904 | } | |||
| 905 | ||||
| 906 | #if OK_TO_RESET_CONTROLLER1 | |||
| 907 | /* | |||
| 908 | * Note that we also set nIEN while resetting the device, | |||
| 909 | * to mask unwanted interrupts from the interface during the reset. | |||
| 910 | * However, due to the design of PC hardware, this will cause an | |||
| 911 | * immediate interrupt due to the edge transition it produces. | |||
| 912 | * This single interrupt gives us a "fast poll" for drives that | |||
| 913 | * recover from reset very quickly, saving us the first 50ms wait time. | |||
| 914 | */ | |||
| 915 | OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl|6)),(( (((ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl|6)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); /* set SRST and nIEN */ | |||
| 916 | udelay(10)(__builtin_constant_p(10) ? __const_udelay((10) * 0x10c6ul) : __udelay(10)); /* more than enough time */ | |||
| 917 | OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl|2)),(( (((ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl|2)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); /* clear SRST, leave nIEN */ | |||
| 918 | udelay(10)(__builtin_constant_p(10) ? __const_udelay((10) * 0x10c6ul) : __udelay(10)); /* more than enough time */ | |||
| 919 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE(30*100); | |||
| 920 | ide_set_handler (drive, &reset_pollfunc, HZ100/20); | |||
| 921 | #endif /* OK_TO_RESET_CONTROLLER */ | |||
| 922 | ||||
| 923 | restore_flags (flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 924 | } | |||
| 925 | ||||
| 926 | /* | |||
| 927 | * ide_do_reset() is the entry point to the drive/interface reset code. | |||
| 928 | */ | |||
| 929 | void ide_do_reset (ide_drive_t *drive) | |||
| 930 | { | |||
| 931 | do_reset1 (drive, 0); | |||
| 932 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 933 | if (drive->media == ide_tape) | |||
| 934 | drive->tape.reset_issued=1; | |||
| 935 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 936 | } | |||
| 937 | ||||
| 938 | /* | |||
| 939 | * Clean up after success/failure of an explicit drive cmd | |||
| 940 | */ | |||
| 941 | void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err) | |||
| 942 | { | |||
| 943 | unsigned long flags; | |||
| 944 | struct request *rq = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq; | |||
| 945 | ||||
| 946 | if (rq->cmd == IDE_DRIVE_CMD99) { | |||
| 947 | byte *args = (byte *) rq->buffer; | |||
| 948 | rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40)); | |||
| 949 | if (args) { | |||
| 950 | args[0] = stat; | |||
| 951 | args[1] = err; | |||
| 952 | args[2] = IN_BYTE(IDE_NSECTOR_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(2)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(2))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(2))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(2)))); | |||
| 953 | } | |||
| 954 | } | |||
| 955 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 956 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 957 | blk_dev[MAJOR(rq->rq_dev)((rq->rq_dev) >> 8)].current_request = rq->next; | |||
| 958 | HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq = NULL((void *) 0); | |||
| 959 | rq->rq_status = RQ_INACTIVE(-1); | |||
| 960 | if (rq->sem != NULL((void *) 0)) | |||
| 961 | up(rq->sem); | |||
| 962 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 963 | } | |||
| 964 | ||||
| 965 | /* | |||
| 966 | * Error reporting, in human readable form (luxurious, but a memory hog). | |||
| 967 | */ | |||
| 968 | byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) | |||
| 969 | { | |||
| 970 | unsigned long flags; | |||
| 971 | byte err = 0; | |||
| 972 | ||||
| 973 | save_flags (flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 974 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 975 | printk("%s: %s: status=0x%02x", drive->name, msg, stat); | |||
| 976 | #if FANCY_STATUS_DUMPS1 | |||
| 977 | if (drive->media == ide_disk) { | |||
| 978 | printk(" { "); | |||
| 979 | if (stat & BUSY_STAT0x80) | |||
| 980 | printk("Busy "); | |||
| 981 | else { | |||
| 982 | if (stat & READY_STAT0x40) printk("DriveReady "); | |||
| 983 | if (stat & WRERR_STAT0x20) printk("DeviceFault "); | |||
| 984 | if (stat & SEEK_STAT0x10) printk("SeekComplete "); | |||
| 985 | if (stat & DRQ_STAT0x08) printk("DataRequest "); | |||
| 986 | if (stat & ECC_STAT0x04) printk("CorrectedError "); | |||
| 987 | if (stat & INDEX_STAT0x02) printk("Index "); | |||
| 988 | if (stat & ERR_STAT0x01) printk("Error "); | |||
| 989 | } | |||
| 990 | printk("}"); | |||
| 991 | } | |||
| 992 | #endif /* FANCY_STATUS_DUMPS */ | |||
| 993 | printk("\n"); | |||
| 994 | if ((stat & (BUSY_STAT0x80|ERR_STAT0x01)) == ERR_STAT0x01) { | |||
| 995 | err = GET_ERR()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(1)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(1))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(1))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(1)))); | |||
| 996 | printk("%s: %s: error=0x%02x", drive->name, msg, err); | |||
| 997 | #if FANCY_STATUS_DUMPS1 | |||
| 998 | if (drive->media == ide_disk) { | |||
| 999 | printk(" { "); | |||
| 1000 | if (err & ICRC_ERR0x80) printk((err & ABRT_ERR0x04) ? "BadCRC " : "BadSector "); | |||
| 1001 | if (err & ECC_ERR0x40) printk("UncorrectableError "); | |||
| 1002 | if (err & ID_ERR0x10) printk("SectorIdNotFound "); | |||
| 1003 | if (err & ABRT_ERR0x04) printk("DriveStatusError "); | |||
| 1004 | if (err & TRK0_ERR0x02) printk("TrackZeroNotFound "); | |||
| 1005 | if (err & MARK_ERR0x01) printk("AddrMarkNotFound "); | |||
| 1006 | printk("}"); | |||
| 1007 | if (err & (BBD_ERR0x80|ECC_ERR0x40|ID_ERR0x10|MARK_ERR0x01)) { | |||
| 1008 | byte cur = IN_BYTE(IDE_SELECT_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(6))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(6))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(6)))); | |||
| 1009 | if (cur & 0x40) { /* using LBA? */ | |||
| 1010 | printk(", LBAsect=%ld", (unsigned long) | |||
| 1011 | ((cur&0xf)<<24) | |||
| 1012 | |(IN_BYTE(IDE_HCYL_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(5)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(5))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(5))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(5))))<<16) | |||
| 1013 | |(IN_BYTE(IDE_LCYL_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(4)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(4))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(4))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(4))))<<8) | |||
| 1014 | | IN_BYTE(IDE_SECTOR_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(3)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(3))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(3))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(3))))); | |||
| 1015 | } else { | |||
| 1016 | printk(", CHS=%d/%d/%d", | |||
| 1017 | (IN_BYTE(IDE_HCYL_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(5)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(5))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(5))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(5))))<<8) + | |||
| 1018 | IN_BYTE(IDE_LCYL_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(4)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(4))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(4))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(4)))), | |||
| 1019 | cur & 0xf, | |||
| 1020 | IN_BYTE(IDE_SECTOR_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(3)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(3))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(3))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(3))))); | |||
| 1021 | } | |||
| 1022 | if (HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq) | |||
| 1023 | printk(", sector=%ld", HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq->sector); | |||
| 1024 | } | |||
| 1025 | } | |||
| 1026 | #endif /* FANCY_STATUS_DUMPS */ | |||
| 1027 | printk("\n"); | |||
| 1028 | } | |||
| 1029 | restore_flags (flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 1030 | return err; | |||
| 1031 | } | |||
| 1032 | ||||
| 1033 | /* | |||
| 1034 | * try_to_flush_leftover_data() is invoked in response to a drive | |||
| 1035 | * unexpectedly having its DRQ_STAT bit set. As an alternative to | |||
| 1036 | * resetting the drive, this routine tries to clear the condition | |||
| 1037 | * by read a sector's worth of data from the drive. Of course, | |||
| 1038 | * this may not help if the drive is *waiting* for data from *us*. | |||
| 1039 | */ | |||
| 1040 | static void try_to_flush_leftover_data (ide_drive_t *drive) | |||
| 1041 | { | |||
| 1042 | int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS(512 / 4); | |||
| 1043 | ||||
| 1044 | while (i > 0) { | |||
| 1045 | unsigned long buffer[16]; | |||
| 1046 | unsigned int wcount = (i > 16) ? 16 : i; | |||
| 1047 | i -= wcount; | |||
| 1048 | ide_input_data (drive, buffer, wcount); | |||
| 1049 | } | |||
| 1050 | } | |||
| 1051 | ||||
| 1052 | /* | |||
| 1053 | * ide_error() takes action based on the error returned by the controller. | |||
| 1054 | */ | |||
| 1055 | void ide_error (ide_drive_t *drive, const char *msg, byte stat) | |||
| 1056 | { | |||
| 1057 | struct request *rq; | |||
| 1058 | byte err; | |||
| 1059 | ||||
| 1060 | err = ide_dump_status(drive, msg, stat); | |||
| 1061 | if ((rq = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq) == NULL((void *) 0) || drive == NULL((void *) 0)) | |||
| 1062 | return; | |||
| 1063 | /* retry only "normal" I/O: */ | |||
| 1064 | if (rq->cmd == IDE_DRIVE_CMD99) { | |||
| 1065 | rq->errors = 1; | |||
| 1066 | ide_end_drive_cmd(drive, stat, err); | |||
| 1067 | return; | |||
| 1068 | } | |||
| 1069 | if (stat & BUSY_STAT0x80) { /* other bits are useless when BUSY */ | |||
| 1070 | rq->errors |= ERROR_RESET3; | |||
| 1071 | } else { | |||
| 1072 | if (drive->media == ide_disk && (stat & ERR_STAT0x01)) { | |||
| 1073 | /* err has different meaning on cdrom and tape */ | |||
| 1074 | if (err == ABRT_ERR0x04) { | |||
| 1075 | if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))) == WIN_SPECIFY0x91) | |||
| 1076 | return; /* some newer drives don't support WIN_SPECIFY */ | |||
| 1077 | } else if ((err & (ABRT_ERR0x04 | ICRC_ERR0x80)) == (ABRT_ERR0x04 | ICRC_ERR0x80)) | |||
| 1078 | ; /* UDMA crc error -- just retry the operation */ | |||
| 1079 | else if (err & (BBD_ERR0x80 | ECC_ERR0x40)) /* retries won't help these */ | |||
| 1080 | rq->errors = ERROR_MAX8; | |||
| 1081 | else if (err & TRK0_ERR0x02) /* help it find track zero */ | |||
| 1082 | rq->errors |= ERROR_RECAL1; | |||
| 1083 | else if (err & MC_ERR0x20) | |||
| 1084 | drive->special.b.mc = 1; | |||
| 1085 | } | |||
| 1086 | if ((stat & DRQ_STAT0x08) && rq->cmd != WRITE1) | |||
| 1087 | try_to_flush_leftover_data(drive); | |||
| 1088 | } | |||
| 1089 | if (GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))) & (BUSY_STAT0x80|DRQ_STAT0x08)) | |||
| 1090 | rq->errors |= ERROR_RESET3; /* Mmmm.. timing problem */ | |||
| 1091 | ||||
| 1092 | if (rq->errors >= ERROR_MAX8) { | |||
| 1093 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 1094 | if (drive->media == ide_tape) { | |||
| 1095 | rq->errors = 0; | |||
| 1096 | idetape_end_request(0, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1097 | } else | |||
| 1098 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 1099 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 1100 | if (drive->media == ide_floppy) { | |||
| 1101 | rq->errors = 0; | |||
| 1102 | idefloppy_end_request(0, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1103 | } else | |||
| 1104 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 1105 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 1106 | if (drive->media == ide_scsi) { | |||
| 1107 | rq->errors = 0; | |||
| 1108 | idescsi_end_request(0, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1109 | } else | |||
| 1110 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 1111 | ide_end_request(0, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1112 | } | |||
| 1113 | else { | |||
| 1114 | if ((rq->errors & ERROR_RESET3) == ERROR_RESET3) { | |||
| 1115 | ++rq->errors; | |||
| 1116 | ide_do_reset(drive); | |||
| 1117 | return; | |||
| 1118 | } else if ((rq->errors & ERROR_RECAL1) == ERROR_RECAL1) | |||
| 1119 | drive->special.b.recalibrate = 1; | |||
| 1120 | ++rq->errors; | |||
| 1121 | } | |||
| 1122 | } | |||
| 1123 | ||||
| 1124 | /* | |||
| 1125 | * read_intr() is the handler for disk read/multread interrupts | |||
| 1126 | */ | |||
| 1127 | static void read_intr (ide_drive_t *drive) | |||
| 1128 | { | |||
| 1129 | byte stat; | |||
| 1130 | int i; | |||
| 1131 | unsigned int msect, nsect; | |||
| 1132 | struct request *rq; | |||
| 1133 | ||||
| 1134 | if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)(((stat=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&( ((0x08))|((0x80 | 0x01))))==((0x08)))) { | |||
| 1135 | ide_error(drive, "read_intr", stat); | |||
| 1136 | return; | |||
| 1137 | } | |||
| 1138 | msect = drive->mult_count; | |||
| 1139 | read_next: | |||
| 1140 | rq = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq; | |||
| 1141 | if (msect) { | |||
| 1142 | if ((nsect = rq->current_nr_sectors) > msect) | |||
| 1143 | nsect = msect; | |||
| 1144 | msect -= nsect; | |||
| 1145 | } else | |||
| 1146 | nsect = 1; | |||
| 1147 | i = rq->nr_sectors - nsect; | |||
| 1148 | if (i > 0 && !msect) | |||
| 1149 | ide_set_handler (drive, &read_intr, WAIT_CMD(10*100)); | |||
| 1150 | ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS(512 / 4)); | |||
| 1151 | #ifdef DEBUG | |||
| 1152 | printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", | |||
| 1153 | drive->name, rq->sector, rq->sector+nsect-1, | |||
| 1154 | (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); | |||
| 1155 | #endif | |||
| 1156 | rq->sector += nsect; | |||
| 1157 | rq->buffer += nsect<<9; | |||
| 1158 | rq->errors = 0; | |||
| 1159 | rq->nr_sectors = i; | |||
| 1160 | if ((rq->current_nr_sectors -= nsect) <= 0) | |||
| 1161 | ide_end_request(1, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1162 | if (i > 0 && msect) | |||
| 1163 | goto read_next; | |||
| 1164 | } | |||
| 1165 | ||||
| 1166 | /* | |||
| 1167 | * write_intr() is the handler for disk write interrupts | |||
| 1168 | */ | |||
| 1169 | static void write_intr (ide_drive_t *drive) | |||
| 1170 | { | |||
| 1171 | byte stat; | |||
| 1172 | int i; | |||
| 1173 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 1174 | struct request *rq = hwgroup->rq; | |||
| 1175 | ||||
| 1176 | if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)(((stat=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&( ((0x40 | 0x10))|(drive->bad_wstat)))==((0x40 | 0x10)))) { | |||
| 1177 | #ifdef DEBUG | |||
| 1178 | printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", | |||
| 1179 | drive->name, rq->sector, (unsigned long) rq->buffer, | |||
| 1180 | rq->nr_sectors-1); | |||
| 1181 | #endif | |||
| 1182 | if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT0x08) != 0)) { | |||
| 1183 | rq->sector++; | |||
| 1184 | rq->buffer += 512; | |||
| 1185 | rq->errors = 0; | |||
| 1186 | i = --rq->nr_sectors; | |||
| 1187 | --rq->current_nr_sectors; | |||
| 1188 | if (rq->current_nr_sectors <= 0) | |||
| 1189 | ide_end_request(1, hwgroup); | |||
| 1190 | if (i > 0) { | |||
| 1191 | ide_set_handler (drive, &write_intr, WAIT_CMD(10*100)); | |||
| 1192 | ide_output_data (drive, rq->buffer, SECTOR_WORDS(512 / 4)); | |||
| 1193 | } | |||
| 1194 | return; | |||
| 1195 | } | |||
| 1196 | } | |||
| 1197 | ide_error(drive, "write_intr", stat); | |||
| 1198 | } | |||
| 1199 | ||||
| 1200 | /* | |||
| 1201 | * ide_multwrite() transfers a block of up to mcount sectors of data | |||
| 1202 | * to a drive as part of a disk multiple-sector write operation. | |||
| 1203 | */ | |||
| 1204 | void ide_multwrite (ide_drive_t *drive, unsigned int mcount) | |||
| 1205 | { | |||
| 1206 | struct request *rq = &HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->wrq; | |||
| 1207 | ||||
| 1208 | do { | |||
| 1209 | unsigned int nsect = rq->current_nr_sectors; | |||
| 1210 | if (nsect > mcount) | |||
| 1211 | nsect = mcount; | |||
| 1212 | mcount -= nsect; | |||
| 1213 | ||||
| 1214 | ide_output_data(drive, rq->buffer, nsect<<7); | |||
| 1215 | #ifdef DEBUG | |||
| 1216 | printk("%s: multwrite: sector %ld, buffer=0x%08lx, count=%d, remaining=%ld\n", | |||
| 1217 | drive->name, rq->sector, (unsigned long) rq->buffer, | |||
| 1218 | nsect, rq->nr_sectors - nsect); | |||
| 1219 | #endif | |||
| 1220 | if ((rq->nr_sectors -= nsect) <= 0) | |||
| 1221 | break; | |||
| 1222 | if ((rq->current_nr_sectors -= nsect) == 0) { | |||
| 1223 | if ((rq->bh = rq->bh->b_reqnext) != NULL((void *) 0)) { | |||
| 1224 | rq->current_nr_sectors = rq->bh->b_size>>9; | |||
| 1225 | rq->buffer = rq->bh->b_data; | |||
| 1226 | } else { | |||
| 1227 | panic("%s: buffer list corrupted\n", drive->name); | |||
| 1228 | break; | |||
| 1229 | } | |||
| 1230 | } else { | |||
| 1231 | rq->buffer += nsect << 9; | |||
| 1232 | } | |||
| 1233 | } while (mcount); | |||
| 1234 | } | |||
| 1235 | ||||
| 1236 | /* | |||
| 1237 | * multwrite_intr() is the handler for disk multwrite interrupts | |||
| 1238 | */ | |||
| 1239 | static void multwrite_intr (ide_drive_t *drive) | |||
| 1240 | { | |||
| 1241 | byte stat; | |||
| 1242 | int i; | |||
| 1243 | ide_hwgroup_t *hwgroup = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup )); | |||
| 1244 | struct request *rq = &hwgroup->wrq; | |||
| 1245 | ||||
| 1246 | if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)(((stat=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&( ((0x40 | 0x10))|(drive->bad_wstat)))==((0x40 | 0x10)))) { | |||
| 1247 | if (stat & DRQ_STAT0x08) { | |||
| 1248 | if (rq->nr_sectors) { | |||
| 1249 | ide_set_handler (drive, &multwrite_intr, WAIT_CMD(10*100)); | |||
| 1250 | ide_multwrite(drive, drive->mult_count); | |||
| 1251 | return; | |||
| 1252 | } | |||
| 1253 | } else { | |||
| 1254 | if (!rq->nr_sectors) { /* all done? */ | |||
| 1255 | rq = hwgroup->rq; | |||
| 1256 | for (i = rq->nr_sectors; i > 0;){ | |||
| 1257 | i -= rq->current_nr_sectors; | |||
| 1258 | ide_end_request(1, hwgroup); | |||
| 1259 | } | |||
| 1260 | return; | |||
| 1261 | } | |||
| 1262 | } | |||
| 1263 | } | |||
| 1264 | ide_error(drive, "multwrite_intr", stat); | |||
| 1265 | } | |||
| 1266 | ||||
| 1267 | /* | |||
| 1268 | * Issue a simple drive command | |||
| 1269 | * The drive must be selected beforehand. | |||
| 1270 | */ | |||
| 1271 | static void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) | |||
| 1272 | { | |||
| 1273 | ide_set_handler (drive, handler, WAIT_CMD(10*100)); | |||
| 1274 | OUT_BYTE(drive->ctl,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl)),(((( (ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); | |||
| 1275 | OUT_BYTE(nsect,IDE_NSECTOR_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(2))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(2)))) < 256) ? __outbc_p(((nsect)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(2))))) : __outb_p(((nsect )),(((((ide_hwif_t *)((drive)->hwif))->io_base+(2)))))); | |||
| 1276 | OUT_BYTE(cmd,IDE_COMMAND_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(7))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) < 256) ? __outbc_p(((cmd)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) : __outb_p(((cmd)) ,(((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))); | |||
| 1277 | } | |||
| 1278 | ||||
| 1279 | /* | |||
| 1280 | * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. | |||
| 1281 | */ | |||
| 1282 | static void set_multmode_intr (ide_drive_t *drive) | |||
| 1283 | { | |||
| 1284 | byte stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1285 | ||||
| 1286 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1287 | if (OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40))) { | |||
| 1288 | drive->mult_count = drive->mult_req; | |||
| 1289 | } else { | |||
| 1290 | drive->mult_req = drive->mult_count = 0; | |||
| 1291 | drive->special.b.recalibrate = 1; | |||
| 1292 | (void) ide_dump_status(drive, "set_multmode", stat); | |||
| 1293 | } | |||
| 1294 | } | |||
| 1295 | ||||
| 1296 | /* | |||
| 1297 | * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd. | |||
| 1298 | */ | |||
| 1299 | static void set_geometry_intr (ide_drive_t *drive) | |||
| 1300 | { | |||
| 1301 | byte stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1302 | ||||
| 1303 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1304 | if (!OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40))) | |||
| 1305 | ide_error(drive, "set_geometry_intr", stat); | |||
| 1306 | } | |||
| 1307 | ||||
| 1308 | /* | |||
| 1309 | * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd. | |||
| 1310 | */ | |||
| 1311 | static void recal_intr (ide_drive_t *drive) | |||
| 1312 | { | |||
| 1313 | byte stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1314 | ||||
| 1315 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1316 | if (!OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40))) | |||
| 1317 | ide_error(drive, "recal_intr", stat); | |||
| 1318 | } | |||
| 1319 | ||||
| 1320 | /* | |||
| 1321 | * mc_intr() is invoked on completion of a WIN_ACKMC cmd. | |||
| 1322 | */ | |||
| 1323 | static void mc_intr (ide_drive_t *drive) | |||
| 1324 | { | |||
| 1325 | byte stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1326 | ||||
| 1327 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1328 | if (!OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40))) | |||
| 1329 | ide_error(drive, "mc_intr", stat); | |||
| 1330 | drive->special.b.mc = 0; | |||
| 1331 | } | |||
| 1332 | ||||
| 1333 | /* | |||
| 1334 | * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. | |||
| 1335 | */ | |||
| 1336 | static void drive_cmd_intr (ide_drive_t *drive) | |||
| 1337 | { | |||
| 1338 | struct request *rq = HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq; | |||
| 1339 | byte *args = (byte *) rq->buffer; | |||
| 1340 | byte stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1341 | ||||
| 1342 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1343 | if ((stat & DRQ_STAT0x08) && args && args[3]) { | |||
| 1344 | byte io_32bit = drive->io_32bit; | |||
| 1345 | drive->io_32bit = 0; | |||
| 1346 | ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS(512 / 4)); | |||
| 1347 | drive->io_32bit = io_32bit; | |||
| 1348 | stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); | |||
| 1349 | } | |||
| 1350 | if (OK_STAT(stat,READY_STAT,BAD_STAT)(((stat)&((0x40)|(((0x80 | 0x01) | 0x08))))==(0x40))) | |||
| 1351 | ide_end_drive_cmd (drive, stat, GET_ERR()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(1)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(1))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(1))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(1))))); | |||
| 1352 | else | |||
| 1353 | ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ | |||
| 1354 | } | |||
| 1355 | ||||
| 1356 | /* | |||
| 1357 | * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT | |||
| 1358 | * commands to a drive. It used to do much more, but has been scaled back. | |||
| 1359 | */ | |||
| 1360 | static inlineinline __attribute__((always_inline)) void do_special (ide_drive_t *drive) | |||
| 1361 | { | |||
| 1362 | special_t *s = &drive->special; | |||
| 1363 | ||||
| 1364 | #ifdef DEBUG | |||
| 1365 | printk("%s: do_special: 0x%02x\n", drive->name, s->all); | |||
| 1366 | #endif | |||
| 1367 | if (s->b.set_geometry) { | |||
| 1368 | s->b.set_geometry = 0; | |||
| 1369 | if (drive->media == ide_disk && !drive->no_geom) { | |||
| 1370 | OUT_BYTE(drive->sect,IDE_SECTOR_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(3))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(3)))) < 256) ? __outbc_p(((drive->sect) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(3))))) : __outb_p(((drive->sect)),(((((ide_hwif_t *)((drive)->hwif ))->io_base+(3)))))); | |||
| 1371 | OUT_BYTE(drive->cyl,IDE_LCYL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(4))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(4)))) < 256) ? __outbc_p(((drive->cyl)) ,(((((ide_hwif_t *)((drive)->hwif))->io_base+(4))))) : __outb_p (((drive->cyl)),(((((ide_hwif_t *)((drive)->hwif))-> io_base+(4)))))); | |||
| 1372 | OUT_BYTE(drive->cyl>>8,IDE_HCYL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(5))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(5)))) < 256) ? __outbc_p(((drive->cyl>> 8)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(5))))) : __outb_p(((drive->cyl>>8)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(5)))))); | |||
| 1373 | OUT_BYTE(((drive->head-1)|drive->select.all)&0xBF,IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((((drive->head -1)|drive->select.all)&0xBF)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(6))))) : __outb_p(((((drive->head -1)|drive->select.all)&0xBF)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(6)))))); | |||
| 1374 | if (!IS_PROMISE_DRIVE(0)) | |||
| 1375 | ide_cmd(drive, WIN_SPECIFY0x91, drive->sect, &set_geometry_intr); | |||
| 1376 | } | |||
| 1377 | } else if (s->b.recalibrate) { | |||
| 1378 | s->b.recalibrate = 0; | |||
| 1379 | if (drive->media == ide_disk && !IS_PROMISE_DRIVE(0)) | |||
| 1380 | ide_cmd(drive, WIN_RESTORE0x10, drive->sect, &recal_intr); | |||
| 1381 | } else if (s->b.set_tune) { | |||
| 1382 | ide_tuneproc_t *tuneproc = HWIF(drive)((ide_hwif_t *)((drive)->hwif))->tuneproc; | |||
| 1383 | s->b.set_tune = 0; | |||
| 1384 | if (tuneproc != NULL((void *) 0)) | |||
| 1385 | tuneproc(drive, drive->tune_req); | |||
| 1386 | } else if (s->b.set_multmode) { | |||
| 1387 | s->b.set_multmode = 0; | |||
| 1388 | if (drive->media == ide_disk) { | |||
| 1389 | if (drive->id && drive->mult_req > drive->id->max_multsect) | |||
| 1390 | drive->mult_req = drive->id->max_multsect; | |||
| 1391 | if (!IS_PROMISE_DRIVE(0)) | |||
| 1392 | ide_cmd(drive, WIN_SETMULT0xC6, drive->mult_req, &set_multmode_intr); | |||
| 1393 | } else | |||
| 1394 | drive->mult_req = 0; | |||
| 1395 | } else if (s->b.mc) { | |||
| 1396 | s->b.mc = 0; | |||
| 1397 | if (drive->media == ide_disk && !IS_PROMISE_DRIVE(0)) | |||
| 1398 | ide_cmd(drive, WIN_ACKMC0xdb, drive->sect, &mc_intr); | |||
| 1399 | } else if (s->all) { | |||
| 1400 | int special = s->all; | |||
| 1401 | s->all = 0; | |||
| 1402 | printk("%s: bad special flag: 0x%02x\n", drive->name, special); | |||
| 1403 | } | |||
| 1404 | } | |||
| 1405 | ||||
| 1406 | /* | |||
| 1407 | * This routine busy-waits for the drive status to be not "busy". | |||
| 1408 | * It then checks the status for all of the "good" bits and none | |||
| 1409 | * of the "bad" bits, and if all is okay it returns 0. All other | |||
| 1410 | * cases return 1 after invoking ide_error() -- caller should just return. | |||
| 1411 | * | |||
| 1412 | * This routine should get fixed to not hog the cpu during extra long waits.. | |||
| 1413 | * That could be done by busy-waiting for the first jiffy or two, and then | |||
| 1414 | * setting a timer to wake up at half second intervals thereafter, | |||
| 1415 | * until timeout is achieved, before timing out. | |||
| 1416 | */ | |||
| 1417 | int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout) | |||
| 1418 | { | |||
| 1419 | byte stat; | |||
| 1420 | unsigned long flags; | |||
| 1421 | ||||
| 1422 | udelay(1)(__builtin_constant_p(1) ? __const_udelay((1) * 0x10c6ul) : __udelay (1)); /* spec allows drive 400ns to assert "BUSY" */ | |||
| 1423 | if ((stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) & BUSY_STAT0x80) { | |||
| 1424 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 1425 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1426 | timeout += jiffies; | |||
| 1427 | while ((stat = GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) & BUSY_STAT0x80) { | |||
| 1428 | if (jiffies > timeout) { | |||
| 1429 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 1430 | ide_error(drive, "status timeout", stat); | |||
| 1431 | return 1; | |||
| 1432 | } | |||
| 1433 | } | |||
| 1434 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 1435 | } | |||
| 1436 | udelay(1)(__builtin_constant_p(1) ? __const_udelay((1) * 0x10c6ul) : __udelay (1)); /* allow status to settle, then read it again */ | |||
| 1437 | if (OK_STAT((stat = GET_STAT()), good, bad)((((stat = (byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7))))))& ((good)|(bad)))==(good))) | |||
| 1438 | return 0; | |||
| 1439 | ide_error(drive, "status error", stat); | |||
| 1440 | return 1; | |||
| 1441 | } | |||
| 1442 | ||||
| 1443 | /* | |||
| 1444 | * do_rw_disk() issues READ and WRITE commands to a disk, | |||
| 1445 | * using LBA if supported, or CHS otherwise, to address sectors. | |||
| 1446 | * It also takes care of issuing special DRIVE_CMDs. | |||
| 1447 | */ | |||
| 1448 | static inlineinline __attribute__((always_inline)) void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) | |||
| 1449 | { | |||
| 1450 | ide_hwif_t *hwif = HWIF(drive)((ide_hwif_t *)((drive)->hwif)); | |||
| 1451 | unsigned short io_base = hwif->io_base; | |||
| 1452 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 1453 | int use_promise_io = 0; | |||
| 1454 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 1455 | ||||
| 1456 | OUT_BYTE(drive->ctl,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl)),(((( (ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); | |||
| 1457 | OUT_BYTE(rq->nr_sectors,io_base+IDE_NSECTOR_OFFSET)((__builtin_constant_p(((io_base+(2)))) && ((io_base+ (2))) < 256) ? __outbc_p(((rq->nr_sectors)),((io_base+( 2)))) : __outb_p(((rq->nr_sectors)),((io_base+(2))))); | |||
| 1458 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 1459 | if (IS_PROMISE_DRIVE(0)) { | |||
| 1460 | if (hwif->is_promise2 || rq->cmd == READ0) { | |||
| 1461 | use_promise_io = 1; | |||
| 1462 | } | |||
| 1463 | } | |||
| 1464 | if (drive->select.b.lba || use_promise_io) { | |||
| 1465 | #else /* !CONFIG_BLK_DEV_PROMISE */ | |||
| 1466 | if (drive->select.b.lba) { | |||
| 1467 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 1468 | #ifdef DEBUG | |||
| 1469 | printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n", | |||
| 1470 | drive->name, (rq->cmd==READ0)?"read":"writ", | |||
| 1471 | block, rq->nr_sectors, (unsigned long) rq->buffer); | |||
| 1472 | #endif | |||
| 1473 | OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET)((__builtin_constant_p(((io_base+(3)))) && ((io_base+ (3))) < 256) ? __outbc_p(((block)),((io_base+(3)))) : __outb_p (((block)),((io_base+(3))))); | |||
| 1474 | OUT_BYTE(block>>=8,io_base+IDE_LCYL_OFFSET)((__builtin_constant_p(((io_base+(4)))) && ((io_base+ (4))) < 256) ? __outbc_p(((block>>=8)),((io_base+(4) ))) : __outb_p(((block>>=8)),((io_base+(4))))); | |||
| 1475 | OUT_BYTE(block>>=8,io_base+IDE_HCYL_OFFSET)((__builtin_constant_p(((io_base+(5)))) && ((io_base+ (5))) < 256) ? __outbc_p(((block>>=8)),((io_base+(5) ))) : __outb_p(((block>>=8)),((io_base+(5))))); | |||
| 1476 | OUT_BYTE(((block>>8)&0x0f)|drive->select.all,io_base+IDE_SELECT_OFFSET)((__builtin_constant_p(((io_base+(6)))) && ((io_base+ (6))) < 256) ? __outbc_p(((((block>>8)&0x0f)|drive ->select.all)),((io_base+(6)))) : __outb_p(((((block>> 8)&0x0f)|drive->select.all)),((io_base+(6))))); | |||
| 1477 | } else { | |||
| 1478 | unsigned int sect,head,cyl,track; | |||
| 1479 | track = block / drive->sect; | |||
| 1480 | sect = block % drive->sect + 1; | |||
| 1481 | OUT_BYTE(sect,io_base+IDE_SECTOR_OFFSET)((__builtin_constant_p(((io_base+(3)))) && ((io_base+ (3))) < 256) ? __outbc_p(((sect)),((io_base+(3)))) : __outb_p (((sect)),((io_base+(3))))); | |||
| 1482 | head = track % drive->head; | |||
| 1483 | cyl = track / drive->head; | |||
| 1484 | OUT_BYTE(cyl,io_base+IDE_LCYL_OFFSET)((__builtin_constant_p(((io_base+(4)))) && ((io_base+ (4))) < 256) ? __outbc_p(((cyl)),((io_base+(4)))) : __outb_p (((cyl)),((io_base+(4))))); | |||
| 1485 | OUT_BYTE(cyl>>8,io_base+IDE_HCYL_OFFSET)((__builtin_constant_p(((io_base+(5)))) && ((io_base+ (5))) < 256) ? __outbc_p(((cyl>>8)),((io_base+(5)))) : __outb_p(((cyl>>8)),((io_base+(5))))); | |||
| 1486 | OUT_BYTE(head|drive->select.all,io_base+IDE_SELECT_OFFSET)((__builtin_constant_p(((io_base+(6)))) && ((io_base+ (6))) < 256) ? __outbc_p(((head|drive->select.all)),((io_base +(6)))) : __outb_p(((head|drive->select.all)),((io_base+(6 ))))); | |||
| 1487 | #ifdef DEBUG | |||
| 1488 | printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", | |||
| 1489 | drive->name, (rq->cmd==READ0)?"read":"writ", cyl, | |||
| 1490 | head, sect, rq->nr_sectors, (unsigned long) rq->buffer); | |||
| 1491 | #endif | |||
| 1492 | } | |||
| 1493 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 1494 | if (use_promise_io) { | |||
| 1495 | do_promise_io (drive, rq); | |||
| 1496 | return; | |||
| 1497 | } | |||
| 1498 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 1499 | if (rq->cmd == READ0) { | |||
| 1500 | #ifdef CONFIG_BLK_DEV_TRITON1 | |||
| 1501 | if (drive->using_dma && !(HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc(ide_dma_read, drive))) | |||
| 1502 | return; | |||
| 1503 | #endif /* CONFIG_BLK_DEV_TRITON */ | |||
| 1504 | ide_set_handler(drive, &read_intr, WAIT_CMD(10*100)); | |||
| 1505 | OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, io_base+IDE_COMMAND_OFFSET)((__builtin_constant_p(((io_base+(7)))) && ((io_base+ (7))) < 256) ? __outbc_p(((drive->mult_count ? 0xC4 : 0x20 )),((io_base+(7)))) : __outb_p(((drive->mult_count ? 0xC4 : 0x20)),((io_base+(7))))); | |||
| 1506 | return; | |||
| 1507 | } | |||
| 1508 | if (rq->cmd == WRITE1) { | |||
| 1509 | #ifdef CONFIG_BLK_DEV_TRITON1 | |||
| 1510 | if (drive->using_dma && !(HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc(ide_dma_write, drive))) | |||
| 1511 | return; | |||
| 1512 | #endif /* CONFIG_BLK_DEV_TRITON */ | |||
| 1513 | if (drive->mult_count) | |||
| 1514 | ide_set_handler (drive, &multwrite_intr, WAIT_CMD(10*100)); | |||
| 1515 | else | |||
| 1516 | ide_set_handler (drive, &write_intr, WAIT_CMD(10*100)); | |||
| 1517 | OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, io_base+IDE_COMMAND_OFFSET)((__builtin_constant_p(((io_base+(7)))) && ((io_base+ (7))) < 256) ? __outbc_p(((drive->mult_count ? 0xC5 : 0x30 )),((io_base+(7)))) : __outb_p(((drive->mult_count ? 0xC5 : 0x30)),((io_base+(7))))); | |||
| 1518 | if (ide_wait_stat(drive, DATA_READY(0x08), drive->bad_wstat, WAIT_DRQ(1*100))) { | |||
| 1519 | printk("%s: no DRQ after issuing %s\n", drive->name, | |||
| 1520 | drive->mult_count ? "MULTWRITE" : "WRITE"); | |||
| 1521 | return; | |||
| 1522 | } | |||
| 1523 | if (!drive->unmask) | |||
| 1524 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1525 | if (drive->mult_count) { | |||
| 1526 | HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->wrq = *rq; /* scratchpad */ | |||
| 1527 | ide_multwrite(drive, drive->mult_count); | |||
| 1528 | } else { | |||
| 1529 | ide_output_data(drive, rq->buffer, SECTOR_WORDS(512 / 4)); | |||
| 1530 | } | |||
| 1531 | return; | |||
| 1532 | } | |||
| 1533 | printk("%s: bad command: %d\n", drive->name, rq->cmd); | |||
| 1534 | ide_end_request(0, HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1535 | } | |||
| 1536 | ||||
| 1537 | /* | |||
| 1538 | * execute_drive_cmd() issues a special drive command, | |||
| 1539 | * usually initiated by ioctl() from the external hdparm program. | |||
| 1540 | */ | |||
| 1541 | static void execute_drive_cmd (ide_drive_t *drive, struct request *rq) | |||
| 1542 | { | |||
| 1543 | byte *args = (byte *)rq->buffer; | |||
| 1544 | if (args) { | |||
| 1545 | #ifdef DEBUG | |||
| 1546 | printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n", | |||
| 1547 | drive->name, args[0], args[1], args[2], args[3]); | |||
| 1548 | #endif | |||
| 1549 | OUT_BYTE(args[2],IDE_FEATURE_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(1))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(1)))) < 256) ? __outbc_p(((args[2])),((((( ide_hwif_t *)((drive)->hwif))->io_base+(1))))) : __outb_p (((args[2])),(((((ide_hwif_t *)((drive)->hwif))->io_base +(1)))))); | |||
| 1550 | ide_cmd(drive, args[0], args[1], &drive_cmd_intr); | |||
| 1551 | return; | |||
| 1552 | } else { | |||
| 1553 | /* | |||
| 1554 | * NULL is actually a valid way of waiting for | |||
| 1555 | * all current requests to be flushed from the queue. | |||
| 1556 | */ | |||
| 1557 | #ifdef DEBUG | |||
| 1558 | printk("%s: DRIVE_CMD (null)\n", drive->name); | |||
| 1559 | #endif | |||
| 1560 | ide_end_drive_cmd(drive, GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))), GET_ERR()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(1)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(1))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(1))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(1))))); | |||
| 1561 | return; | |||
| 1562 | } | |||
| 1563 | } | |||
| 1564 | ||||
| 1565 | /* | |||
| 1566 | * do_request() initiates handling of a new I/O request | |||
| 1567 | */ | |||
| 1568 | static inlineinline __attribute__((always_inline)) void do_request (ide_hwif_t *hwif, struct request *rq) | |||
| 1569 | { | |||
| 1570 | unsigned int minor, unit; | |||
| 1571 | unsigned long block, blockend; | |||
| 1572 | ide_drive_t *drive; | |||
| 1573 | ||||
| 1574 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1575 | #ifdef DEBUG | |||
| 1576 | printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); | |||
| 1577 | #endif | |||
| 1578 | minor = MINOR(rq->rq_dev)((rq->rq_dev) & ((1<<8) - 1)); | |||
| 1579 | unit = minor >> PARTN_BITS6; | |||
| 1580 | if (MAJOR(rq->rq_dev)((rq->rq_dev) >> 8) != hwif->major || unit >= MAX_DRIVES2) { | |||
| 1581 | printk("%s: bad device number: %s\n", | |||
| 1582 | hwif->name, kdevname(rq->rq_dev)); | |||
| 1583 | goto kill_rq; | |||
| 1584 | } | |||
| 1585 | drive = &hwif->drives[unit]; | |||
| 1586 | #ifdef DEBUG | |||
| 1587 | if (rq->bh && !buffer_locked(rq->bh)) { | |||
| 1588 | printk("%s: block not locked\n", drive->name); | |||
| 1589 | goto kill_rq; | |||
| 1590 | } | |||
| 1591 | #endif | |||
| 1592 | block = rq->sector; | |||
| 1593 | blockend = block + rq->nr_sectors; | |||
| 1594 | if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK((1<<6)-1)].nr_sects)) { | |||
| 1595 | #ifdef MACH1 | |||
| 1596 | printk ("%s%c: bad access: block=%ld, count=%ld, blockend=%ld, nr_sects%ld\n", | |||
| 1597 | drive->name, (minor&PARTN_MASK((1<<6)-1))?'0'+(minor&PARTN_MASK((1<<6)-1)):' ', | |||
| 1598 | block, rq->nr_sectors, blockend, drive->part[minor&PARTN_MASK((1<<6)-1)].nr_sects); | |||
| 1599 | #else | |||
| 1600 | printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name, | |||
| 1601 | (minor&PARTN_MASK((1<<6)-1))?'0'+(minor&PARTN_MASK((1<<6)-1)):' ', block, rq->nr_sectors); | |||
| 1602 | #endif | |||
| 1603 | goto kill_rq; | |||
| 1604 | } | |||
| 1605 | block += drive->part[minor&PARTN_MASK((1<<6)-1)].start_sect + drive->sect0; | |||
| 1606 | #if FAKE_FDISK_FOR_EZDRIVE1 | |||
| 1607 | if (block == 0 && drive->remap_0_to_1) | |||
| 1608 | block = 1; /* redirect MBR access to EZ-Drive partn table */ | |||
| 1609 | #endif /* FAKE_FDISK_FOR_EZDRIVE */ | |||
| 1610 | ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive; | |||
| 1611 | #if (DISK_RECOVERY_TIME0 > 0) | |||
| 1612 | while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME0); | |||
| 1613 | #endif | |||
| 1614 | ||||
| 1615 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 1616 | POLL_HWIF_TAPE_DRIVE; /* macro from ide-tape.h */ | |||
| 1617 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 1618 | ||||
| 1619 | SELECT_DRIVE(hwif,drive)((__builtin_constant_p(((hwif->io_base+(6)))) && ( (hwif->io_base+(6))) < 256) ? __outbc_p((((drive)->select .all)),((hwif->io_base+(6)))) : __outb_p((((drive)->select .all)),((hwif->io_base+(6)))));; | |||
| 1620 | if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT0x80|DRQ_STAT0x08, WAIT_READY(3*100/100))) { | |||
| 1621 | printk("%s: drive not ready for command\n", drive->name); | |||
| 1622 | return; | |||
| 1623 | } | |||
| 1624 | ||||
| 1625 | if (!drive->special.all) { | |||
| 1626 | if (rq->cmd == IDE_DRIVE_CMD99) { | |||
| 1627 | execute_drive_cmd(drive, rq); | |||
| 1628 | return; | |||
| 1629 | } | |||
| 1630 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 1631 | switch (drive->media) { | |||
| 1632 | case ide_disk: | |||
| 1633 | do_rw_disk (drive, rq, block); | |||
| 1634 | return; | |||
| 1635 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 1636 | case ide_cdrom: | |||
| 1637 | ide_do_rw_cdrom (drive, block); | |||
| 1638 | return; | |||
| 1639 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 1640 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 1641 | case ide_tape: | |||
| 1642 | idetape_do_request (drive, rq, block); | |||
| 1643 | return; | |||
| 1644 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 1645 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 1646 | case ide_floppy: | |||
| 1647 | idefloppy_do_request (drive, rq, block); | |||
| 1648 | return; | |||
| 1649 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 1650 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 1651 | case ide_scsi: | |||
| 1652 | idescsi_do_request (drive, rq, block); | |||
| 1653 | return; | |||
| 1654 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 1655 | ||||
| 1656 | default: | |||
| 1657 | printk("%s: media type %d not supported\n", | |||
| 1658 | drive->name, drive->media); | |||
| 1659 | goto kill_rq; | |||
| 1660 | } | |||
| 1661 | #else | |||
| 1662 | do_rw_disk (drive, rq, block); /* simpler and faster */ | |||
| 1663 | return; | |||
| 1664 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 1665 | } | |||
| 1666 | do_special(drive); | |||
| 1667 | return; | |||
| 1668 | kill_rq: | |||
| 1669 | ide_end_request(0, hwif->hwgroup); | |||
| 1670 | } | |||
| 1671 | ||||
| 1672 | /* | |||
| 1673 | * The driver enables interrupts as much as possible. In order to do this, | |||
| 1674 | * (a) the device-interrupt is always masked before entry, and | |||
| 1675 | * (b) the timeout-interrupt is always disabled before entry. | |||
| 1676 | * | |||
| 1677 | * If we enter here from, say irq14, and then start a new request for irq15, | |||
| 1678 | * (possible with "serialize" option) then we cannot ensure that we exit | |||
| 1679 | * before the irq15 hits us. So, we must be careful not to let this bother us. | |||
| 1680 | * | |||
| 1681 | * Interrupts are still masked (by default) whenever we are exchanging | |||
| 1682 | * data/cmds with a drive, because some drives seem to have very poor | |||
| 1683 | * tolerance for latency during I/O. For devices which don't suffer from | |||
| 1684 | * this problem (most don't), the unmask flag can be set using the "hdparm" | |||
| 1685 | * utility, to permit other interrupts during data/cmd transfers. | |||
| 1686 | */ | |||
| 1687 | void ide_do_request (ide_hwgroup_t *hwgroup) | |||
| 1688 | { | |||
| 1689 | cli()__asm__ __volatile__ ("cli": : :"memory"); /* paranoia */ | |||
| 1690 | if (hwgroup->handler != NULL((void *) 0)) { | |||
| 1691 | printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name); | |||
| 1692 | return; | |||
| 1693 | } | |||
| 1694 | do { | |||
| 1695 | ide_hwif_t *hwif = hwgroup->hwif; | |||
| 1696 | struct request *rq; | |||
| 1697 | if ((rq = hwgroup->rq) == NULL((void *) 0)) { | |||
| 1698 | if (hwif->sharing_irq && hwgroup->drive) /* set nIEN */ | |||
| 1699 | OUT_BYTE(hwgroup->drive->ctl|2,hwif->ctl_port)((__builtin_constant_p(((hwif->ctl_port))) && ((hwif ->ctl_port)) < 256) ? __outbc_p(((hwgroup->drive-> ctl|2)),((hwif->ctl_port))) : __outb_p(((hwgroup->drive ->ctl|2)),((hwif->ctl_port)))); | |||
| 1700 | /* | |||
| 1701 | * hwgroup->next_hwif is different from hwgroup->hwif | |||
| 1702 | * only when a request is inserted using "ide_next". | |||
| 1703 | * This saves wear and tear on IDE tapes. | |||
| 1704 | */ | |||
| 1705 | hwif = hwgroup->next_hwif; | |||
| 1706 | do { | |||
| 1707 | rq = blk_dev[hwif->major].current_request; | |||
| 1708 | if (rq != NULL((void *) 0) && rq->rq_status != RQ_INACTIVE(-1)) | |||
| 1709 | goto got_rq; | |||
| 1710 | } while ((hwif = hwif->next) != hwgroup->next_hwif); | |||
| 1711 | hwgroup->active = 0; | |||
| 1712 | return; /* no work left for this hwgroup */ | |||
| 1713 | } | |||
| 1714 | got_rq: | |||
| 1715 | do_request(hwgroup->hwif = hwgroup->next_hwif = hwif, hwgroup->rq = rq); | |||
| 1716 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1717 | } while (hwgroup->handler == NULL((void *) 0)); | |||
| 1718 | } | |||
| 1719 | ||||
| 1720 | /* | |||
| 1721 | * do_hwgroup_request() invokes ide_do_request() after first masking | |||
| 1722 | * all possible interrupts for the current hwgroup. This prevents race | |||
| 1723 | * conditions in the event that an unexpected interrupt occurs while | |||
| 1724 | * we are in the driver. | |||
| 1725 | * | |||
| 1726 | * Note that when an interrupt is used to reenter the driver, the first level | |||
| 1727 | * handler will already have masked the irq that triggered, but any other ones | |||
| 1728 | * for the hwgroup will still be unmasked. The driver tries to be careful | |||
| 1729 | * about such things. | |||
| 1730 | */ | |||
| 1731 | static void do_hwgroup_request (ide_hwgroup_t *hwgroup) | |||
| 1732 | { | |||
| 1733 | if (hwgroup->handler == NULL((void *) 0)) { | |||
| 1734 | ide_hwif_t *hgif = hwgroup->hwif; | |||
| 1735 | ide_hwif_t *hwif = hgif; | |||
| 1736 | hwgroup->active = 1; | |||
| 1737 | do { | |||
| 1738 | disable_irq(hwif->irq); | |||
| 1739 | } while ((hwif = hwif->next) != hgif); | |||
| 1740 | ide_do_request (hwgroup); | |||
| 1741 | do { | |||
| 1742 | enable_irq(hwif->irq); | |||
| 1743 | } while ((hwif = hwif->next) != hgif); | |||
| 1744 | } | |||
| 1745 | } | |||
| 1746 | ||||
| 1747 | static void do_ide0_request (void) /* invoked with cli() */ | |||
| 1748 | { | |||
| 1749 | do_hwgroup_request (ide_hwifs[0].hwgroup); | |||
| 1750 | } | |||
| 1751 | ||||
| 1752 | #if MAX_HWIFS4 > 1 | |||
| 1753 | static void do_ide1_request (void) /* invoked with cli() */ | |||
| 1754 | { | |||
| 1755 | do_hwgroup_request (ide_hwifs[1].hwgroup); | |||
| 1756 | } | |||
| 1757 | #endif | |||
| 1758 | ||||
| 1759 | #if MAX_HWIFS4 > 2 | |||
| 1760 | static void do_ide2_request (void) /* invoked with cli() */ | |||
| 1761 | { | |||
| 1762 | do_hwgroup_request (ide_hwifs[2].hwgroup); | |||
| 1763 | } | |||
| 1764 | #endif | |||
| 1765 | ||||
| 1766 | #if MAX_HWIFS4 > 3 | |||
| 1767 | static void do_ide3_request (void) /* invoked with cli() */ | |||
| 1768 | { | |||
| 1769 | do_hwgroup_request (ide_hwifs[3].hwgroup); | |||
| 1770 | } | |||
| 1771 | #endif | |||
| 1772 | ||||
| 1773 | static void timer_expiry (unsigned long data) | |||
| 1774 | { | |||
| 1775 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; | |||
| 1776 | ide_drive_t *drive = hwgroup->drive; | |||
| 1777 | unsigned long flags; | |||
| 1778 | ||||
| 1779 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 1780 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1781 | ||||
| 1782 | if (hwgroup->poll_timeout != 0) { /* polling in progress? */ | |||
| 1783 | ide_handler_t *handler = hwgroup->handler; | |||
| 1784 | hwgroup->handler = NULL((void *) 0); | |||
| 1785 | handler(drive); | |||
| 1786 | } else if (hwgroup->handler == NULL((void *) 0)) { /* not waiting for anything? */ | |||
| 1787 | sti()__asm__ __volatile__ ("sti": : :"memory"); /* drive must have responded just as the timer expired */ | |||
| 1788 | printk("%s: marginal timeout\n", drive->name); | |||
| 1789 | } else { | |||
| 1790 | hwgroup->handler = NULL((void *) 0); /* abort the operation */ | |||
| 1791 | if (hwgroup->hwif->dmaproc) | |||
| 1792 | (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive); | |||
| 1793 | ide_error(drive, "irq timeout", GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))); | |||
| 1794 | } | |||
| 1795 | if (hwgroup->handler == NULL((void *) 0)) | |||
| 1796 | do_hwgroup_request (hwgroup); | |||
| 1797 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 1798 | } | |||
| 1799 | ||||
| 1800 | /* | |||
| 1801 | * There's nothing really useful we can do with an unexpected interrupt, | |||
| 1802 | * other than reading the status register (to clear it), and logging it. | |||
| 1803 | * There should be no way that an irq can happen before we're ready for it, | |||
| 1804 | * so we needn't worry much about losing an "important" interrupt here. | |||
| 1805 | * | |||
| 1806 | * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the | |||
| 1807 | * drive enters "idle", "standby", or "sleep" mode, so if the status looks | |||
| 1808 | * "good", we just ignore the interrupt completely. | |||
| 1809 | * | |||
| 1810 | * This routine assumes cli() is in effect when called. | |||
| 1811 | * | |||
| 1812 | * If an unexpected interrupt happens on irq15 while we are handling irq14 | |||
| 1813 | * and if the two interfaces are "serialized" (CMD640), then it looks like | |||
| 1814 | * we could screw up by interfering with a new request being set up for irq15. | |||
| 1815 | * | |||
| 1816 | * In reality, this is a non-issue. The new command is not sent unless the | |||
| 1817 | * drive is ready to accept one, in which case we know the drive is not | |||
| 1818 | * trying to interrupt us. And ide_set_handler() is always invoked before | |||
| 1819 | * completing the issuance of any new drive command, so we will not be | |||
| 1820 | * accidently invoked as a result of any valid command completion interrupt. | |||
| 1821 | * | |||
| 1822 | */ | |||
| 1823 | static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) | |||
| 1824 | { | |||
| 1825 | byte stat; | |||
| 1826 | unsigned int unit; | |||
| 1827 | ide_hwif_t *hwif = hwgroup->hwif; | |||
| 1828 | ||||
| 1829 | /* | |||
| 1830 | * handle the unexpected interrupt | |||
| 1831 | */ | |||
| 1832 | do { | |||
| 1833 | if (hwif->irq == irq) { | |||
| 1834 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 1835 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 1836 | if (!drive->present) | |||
| 1837 | continue; | |||
| 1838 | SELECT_DRIVE(hwif,drive)((__builtin_constant_p(((hwif->io_base+(6)))) && ( (hwif->io_base+(6))) < 256) ? __outbc_p((((drive)->select .all)),((hwif->io_base+(6)))) : __outb_p((((drive)->select .all)),((hwif->io_base+(6)))));; | |||
| 1839 | udelay(100)(__builtin_constant_p(100) ? __const_udelay((100) * 0x10c6ul) : __udelay(100)); /* Ugly, but wait_stat() may not be safe here */ | |||
| 1840 | if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)(((stat=(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive )->hwif))->io_base+(7)))) && ((((ide_hwif_t *)( (drive)->hwif))->io_base+(7))) < 256) ? __inbc_p(((( ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p( (((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&( (drive->ready_stat)|(((0x80 | 0x01) | 0x08))))==(drive-> ready_stat))) { | |||
| 1841 | /* Try to not flood the console with msgs */ | |||
| 1842 | static unsigned long last_msgtime = 0; | |||
| 1843 | if ((last_msgtime + (HZ100/2)) < jiffies) { | |||
| 1844 | last_msgtime = jiffies; | |||
| 1845 | (void) ide_dump_status(drive, "unexpected_intr", stat); | |||
| 1846 | } | |||
| 1847 | } | |||
| 1848 | if ((stat & DRQ_STAT0x08)) | |||
| 1849 | try_to_flush_leftover_data(drive); | |||
| 1850 | } | |||
| 1851 | } | |||
| 1852 | } while ((hwif = hwif->next) != hwgroup->hwif); | |||
| 1853 | SELECT_DRIVE(hwif,hwgroup->drive)((__builtin_constant_p(((hwif->io_base+(6)))) && ( (hwif->io_base+(6))) < 256) ? __outbc_p((((hwgroup-> drive)->select.all)),((hwif->io_base+(6)))) : __outb_p( (((hwgroup->drive)->select.all)),((hwif->io_base+(6) ))));; /* Ugh.. probably interrupts current I/O */ | |||
| 1854 | udelay(100)(__builtin_constant_p(100) ? __const_udelay((100) * 0x10c6ul) : __udelay(100)); /* Ugly, but wait_stat() may not be safe here */ | |||
| 1855 | } | |||
| 1856 | ||||
| 1857 | /* | |||
| 1858 | * entry point for all interrupts, caller does cli() for us | |||
| 1859 | */ | |||
| 1860 | void ide_intr (int irq, void *dev_id, struct pt_regs *regs) | |||
| 1861 | { | |||
| 1862 | ide_hwgroup_t *hwgroup = dev_id; | |||
| 1863 | ide_handler_t *handler; | |||
| 1864 | ||||
| 1865 | if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL((void *) 0)) { | |||
| 1866 | ide_drive_t *drive = hwgroup->drive; | |||
| 1867 | hwgroup->handler = NULL((void *) 0); | |||
| 1868 | del_timer(&(hwgroup->timer)); | |||
| 1869 | if (drive->unmask) | |||
| 1870 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1871 | handler(drive); | |||
| 1872 | cli()__asm__ __volatile__ ("cli": : :"memory"); /* this is necessary, as next rq may be different irq */ | |||
| 1873 | if (hwgroup->handler == NULL((void *) 0)) { | |||
| 1874 | SET_RECOVERY_TIMER(HWIF(drive)); | |||
| 1875 | ide_do_request(hwgroup); | |||
| 1876 | } | |||
| 1877 | } else { | |||
| 1878 | unexpected_intr(irq, hwgroup); | |||
| 1879 | } | |||
| 1880 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1881 | } | |||
| 1882 | ||||
| 1883 | /* | |||
| 1884 | * get_info_ptr() returns the (ide_drive_t *) for a given device number. | |||
| 1885 | * It returns NULL if the given device number does not match any present drives. | |||
| 1886 | */ | |||
| 1887 | static ide_drive_t *get_info_ptr (kdev_t i_rdev) | |||
| 1888 | { | |||
| 1889 | int major = MAJOR(i_rdev)((i_rdev) >> 8); | |||
| 1890 | unsigned int h; | |||
| 1891 | ||||
| 1892 | for (h = 0; h < MAX_HWIFS4; ++h) { | |||
| 1893 | ide_hwif_t *hwif = &ide_hwifs[h]; | |||
| 1894 | if (hwif->present && major == hwif->major) { | |||
| 1895 | unsigned unit = DEVICE_NR(i_rdev)(((i_rdev) & ((1<<8) - 1)) >> 6); | |||
| 1896 | if (unit < MAX_DRIVES2) { | |||
| 1897 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 1898 | if (drive->present) | |||
| 1899 | return drive; | |||
| 1900 | } else if (major == IDE0_MAJOR3 && unit < 4) { | |||
| 1901 | printk("ide: probable bad entry for /dev/hd%c\n", 'a'+unit); | |||
| 1902 | printk("ide: to fix it, run: /usr/src/linux/scripts/MAKEDEV.ide\n"); | |||
| 1903 | } | |||
| 1904 | break; | |||
| 1905 | } | |||
| 1906 | } | |||
| 1907 | return NULL((void *) 0); | |||
| 1908 | } | |||
| 1909 | ||||
| 1910 | /* | |||
| 1911 | * This function is intended to be used prior to invoking ide_do_drive_cmd(). | |||
| 1912 | */ | |||
| 1913 | void ide_init_drive_cmd (struct request *rq) | |||
| 1914 | { | |||
| 1915 | rq->buffer = NULL((void *) 0); | |||
| 1916 | rq->cmd = IDE_DRIVE_CMD99; | |||
| 1917 | rq->sector = 0; | |||
| 1918 | rq->nr_sectors = 0; | |||
| 1919 | rq->current_nr_sectors = 0; | |||
| 1920 | rq->sem = NULL((void *) 0); | |||
| 1921 | rq->bh = NULL((void *) 0); | |||
| 1922 | rq->bhtail = NULL((void *) 0); | |||
| 1923 | rq->next = NULL((void *) 0); | |||
| 1924 | ||||
| 1925 | #if 0 /* these are done each time through ide_do_drive_cmd() */ | |||
| 1926 | rq->errors = 0; | |||
| 1927 | rq->rq_status = RQ_ACTIVE1; | |||
| 1928 | rq->rq_dev = ????; | |||
| 1929 | #endif | |||
| 1930 | rq->quiet = 0; | |||
| 1931 | } | |||
| 1932 | ||||
| 1933 | /* | |||
| 1934 | * This function issues a special IDE device request | |||
| 1935 | * onto the request queue. | |||
| 1936 | * | |||
| 1937 | * If action is ide_wait, then the rq is queued at the end of the | |||
| 1938 | * request queue, and the function sleeps until it has been processed. | |||
| 1939 | * This is for use when invoked from an ioctl handler. | |||
| 1940 | * | |||
| 1941 | * If action is ide_preempt, then the rq is queued at the head of | |||
| 1942 | * the request queue, displacing the currently-being-processed | |||
| 1943 | * request and this function returns immediately without waiting | |||
| 1944 | * for the new rq to be completed. This is VERY DANGEROUS, and is | |||
| 1945 | * intended for careful use by the ATAPI tape/cdrom driver code. | |||
| 1946 | * | |||
| 1947 | * If action is ide_next, then the rq is queued immediately after | |||
| 1948 | * the currently-being-processed-request (if any), and the function | |||
| 1949 | * returns without waiting for the new rq to be completed. As above, | |||
| 1950 | * This is VERY DANGEROUS, and is intended for careful use by the | |||
| 1951 | * ATAPI tape/cdrom driver code. | |||
| 1952 | * | |||
| 1953 | * If action is ide_end, then the rq is queued at the end of the | |||
| 1954 | * request queue, and the function returns immediately without waiting | |||
| 1955 | * for the new rq to be completed. This is again intended for careful | |||
| 1956 | * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c, | |||
| 1957 | * when operating in the pipelined operation mode). | |||
| 1958 | */ | |||
| 1959 | int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) | |||
| 1960 | { | |||
| 1961 | unsigned long flags; | |||
| 1962 | unsigned int major = HWIF(drive)((ide_hwif_t *)((drive)->hwif))->major; | |||
| 1963 | struct request *cur_rq; | |||
| 1964 | struct blk_dev_struct *bdev = &blk_dev[major]; | |||
| 1965 | struct semaphore sem = MUTEX_LOCKED((struct semaphore) { 0, 0, 0, ((void *) 0) }); | |||
| 1966 | ||||
| 1967 | if (IS_PROMISE_DRIVE(0) && rq->buffer != NULL((void *) 0)) | |||
| 1968 | return -ENOSYS38; /* special drive cmds not supported */ | |||
| 1969 | rq->errors = 0; | |||
| 1970 | rq->rq_status = RQ_ACTIVE1; | |||
| 1971 | rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS)(((major) << 8) | ((drive->select.b.unit)<<6)); | |||
| 1972 | if (action == ide_wait) | |||
| 1973 | rq->sem = &sem; | |||
| 1974 | unplug_device(bdev); | |||
| 1975 | ||||
| 1976 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 1977 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1978 | if (action == ide_next) | |||
| 1979 | HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->next_hwif = HWIF(drive)((ide_hwif_t *)((drive)->hwif)); | |||
| 1980 | cur_rq = bdev->current_request; | |||
| 1981 | ||||
| 1982 | if (cur_rq == NULL((void *) 0) || action == ide_preempt) { | |||
| 1983 | rq->next = cur_rq; | |||
| 1984 | bdev->current_request = rq; | |||
| 1985 | if (action == ide_preempt) | |||
| 1986 | HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->rq = NULL((void *) 0); | |||
| 1987 | } else { | |||
| 1988 | if (action == ide_wait || action == ide_end) { | |||
| 1989 | while (cur_rq->next != NULL((void *) 0)) /* find end of list */ | |||
| 1990 | cur_rq = cur_rq->next; | |||
| 1991 | } | |||
| 1992 | rq->next = cur_rq->next; | |||
| 1993 | cur_rq->next = rq; | |||
| 1994 | } | |||
| 1995 | if (!HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))->active) { | |||
| 1996 | do_hwgroup_request(HWGROUP(drive)((ide_hwgroup_t *)(((ide_hwif_t *)((drive)->hwif))->hwgroup ))); | |||
| 1997 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1998 | } | |||
| 1999 | if (action == ide_wait && rq->rq_status != RQ_INACTIVE(-1)) | |||
| 2000 | down(&sem); /* wait for it to be serviced */ | |||
| 2001 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2002 | return rq->errors ? -EIO5 : 0; /* return -EIO if errors */ | |||
| 2003 | } | |||
| 2004 | ||||
| 2005 | static int ide_open(struct inode * inode, struct file * filp) | |||
| 2006 | { | |||
| 2007 | ide_drive_t *drive; | |||
| 2008 | unsigned long flags; | |||
| 2009 | ||||
| 2010 | if ((drive = get_info_ptr(inode->i_rdev)) == NULL((void *) 0)) | |||
| 2011 | return -ENXIO6; | |||
| 2012 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2013 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 2014 | while (drive->busy) | |||
| 2015 | sleep_on(&drive->wqueue); | |||
| 2016 | drive->usage++; | |||
| 2017 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2018 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2019 | if (drive->media == ide_cdrom) | |||
| 2020 | return ide_cdrom_open (inode, filp, drive); | |||
| 2021 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2022 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 2023 | if (drive->media == ide_tape) | |||
| 2024 | return idetape_blkdev_open (inode, filp, drive); | |||
| 2025 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 2026 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 2027 | if (drive->media == ide_floppy) | |||
| 2028 | return idefloppy_open (inode, filp, drive); | |||
| 2029 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 2030 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 2031 | if (drive->media == ide_scsi) | |||
| 2032 | return idescsi_open (inode, filp, drive); | |||
| 2033 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 2034 | if (drive->removable && drive->usage == 1) { | |||
| 2035 | byte door_lock[] = {WIN_DOORLOCK0xde,0,0,0}; | |||
| 2036 | struct request rq; | |||
| 2037 | check_disk_change(inode->i_rdev); | |||
| 2038 | ide_init_drive_cmd (&rq); | |||
| 2039 | rq.buffer = (char *)door_lock; | |||
| 2040 | /* | |||
| 2041 | * Ignore the return code from door_lock, | |||
| 2042 | * since the open() has already succeeded, | |||
| 2043 | * and the door_lock is irrelevant at this point. | |||
| 2044 | */ | |||
| 2045 | (void) ide_do_drive_cmd(drive, &rq, ide_wait); | |||
| 2046 | } | |||
| 2047 | return 0; | |||
| 2048 | } | |||
| 2049 | ||||
| 2050 | /* | |||
| 2051 | * Releasing a block device means we sync() it, so that it can safely | |||
| 2052 | * be forgotten about... | |||
| 2053 | */ | |||
| 2054 | static void ide_release(struct inode * inode, struct file * file) | |||
| 2055 | { | |||
| 2056 | ide_drive_t *drive; | |||
| 2057 | ||||
| 2058 | if ((drive = get_info_ptr(inode->i_rdev)) != NULL((void *) 0)) { | |||
| 2059 | fsync_dev(inode->i_rdev); | |||
| 2060 | drive->usage--; | |||
| 2061 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2062 | if (drive->media == ide_cdrom) { | |||
| 2063 | ide_cdrom_release (inode, file, drive); | |||
| 2064 | return; | |||
| 2065 | } | |||
| 2066 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2067 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 2068 | if (drive->media == ide_tape) { | |||
| 2069 | idetape_blkdev_release (inode, file, drive); | |||
| 2070 | return; | |||
| 2071 | } | |||
| 2072 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 2073 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 2074 | if (drive->media == ide_floppy) { | |||
| 2075 | idefloppy_release (inode, file, drive); | |||
| 2076 | return; | |||
| 2077 | } | |||
| 2078 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 2079 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 2080 | if (drive->media == ide_scsi) { | |||
| 2081 | idescsi_ide_release (inode, file, drive); | |||
| 2082 | return; | |||
| 2083 | } | |||
| 2084 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 2085 | if (drive->removable && !drive->usage) { | |||
| 2086 | byte door_unlock[] = {WIN_DOORUNLOCK0xdf,0,0,0}; | |||
| 2087 | struct request rq; | |||
| 2088 | invalidate_buffers(inode->i_rdev); | |||
| 2089 | ide_init_drive_cmd (&rq); | |||
| 2090 | rq.buffer = (char *)door_unlock; | |||
| 2091 | (void) ide_do_drive_cmd(drive, &rq, ide_wait); | |||
| 2092 | } | |||
| 2093 | } | |||
| 2094 | } | |||
| 2095 | ||||
| 2096 | /* | |||
| 2097 | * This routine is called to flush all partitions and partition tables | |||
| 2098 | * for a changed disk, and then re-read the new partition table. | |||
| 2099 | * If we are revalidating a disk because of a media change, then we | |||
| 2100 | * enter with usage == 0. If we are using an ioctl, we automatically have | |||
| 2101 | * usage == 1 (we need an open channel to use an ioctl :-), so this | |||
| 2102 | * is our limit. | |||
| 2103 | */ | |||
| 2104 | static int revalidate_disk(kdev_t i_rdev) | |||
| 2105 | { | |||
| 2106 | ide_drive_t *drive; | |||
| 2107 | unsigned int p, major, minor; | |||
| 2108 | long flags; | |||
| 2109 | ||||
| 2110 | if ((drive = get_info_ptr(i_rdev)) == NULL((void *) 0)) | |||
| 2111 | return -ENODEV19; | |||
| 2112 | ||||
| 2113 | major = MAJOR(i_rdev)((i_rdev) >> 8); | |||
| 2114 | minor = drive->select.b.unit << PARTN_BITS6; | |||
| 2115 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2116 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 2117 | if (drive->busy || (drive->usage > 1)) { | |||
| 2118 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2119 | return -EBUSY16; | |||
| 2120 | }; | |||
| 2121 | drive->busy = 1; | |||
| 2122 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2123 | ||||
| 2124 | for (p = 0; p < (1<<PARTN_BITS6); ++p) { | |||
| 2125 | if (drive->part[p].nr_sects > 0) { | |||
| 2126 | kdev_t devp = MKDEV(major, minor+p)(((major) << 8) | (minor+p)); | |||
| 2127 | fsync_dev (devp); | |||
| 2128 | invalidate_inodes (devp); | |||
| 2129 | invalidate_buffers (devp); | |||
| 2130 | set_blocksize(devp, 1024); | |||
| 2131 | } | |||
| 2132 | drive->part[p].start_sect = 0; | |||
| 2133 | drive->part[p].nr_sects = 0; | |||
| 2134 | }; | |||
| 2135 | ||||
| 2136 | drive->part[0].nr_sects = current_capacity(drive); | |||
| 2137 | if ((drive->media != ide_disk && drive->media != ide_floppy) || !drive->part[0].nr_sects) | |||
| 2138 | drive->part[0].start_sect = -1; | |||
| 2139 | resetup_one_dev(HWIF(drive)((ide_hwif_t *)((drive)->hwif))->gd, drive->select.b.unit); | |||
| 2140 | ||||
| 2141 | drive->busy = 0; | |||
| 2142 | wake_up(&drive->wqueue); | |||
| 2143 | return 0; | |||
| 2144 | } | |||
| 2145 | ||||
| 2146 | static int write_fs_long (unsigned long useraddr, long value) | |||
| 2147 | { | |||
| 2148 | int err; | |||
| 2149 | ||||
| 2150 | if (NULL((void *) 0) == (long *)useraddr) | |||
| 2151 | return -EINVAL22; | |||
| 2152 | if ((err = verify_area(VERIFY_WRITE1, (long *)useraddr, sizeof(long)))) | |||
| 2153 | return err; | |||
| 2154 | put_user((unsigned)value, (long *) useraddr)__put_user((unsigned long)((unsigned)value),((long *) useraddr ),sizeof(*((long *) useraddr))); | |||
| 2155 | return 0; | |||
| 2156 | } | |||
| 2157 | ||||
| 2158 | static int ide_ioctl (struct inode *inode, struct file *file, | |||
| 2159 | unsigned int cmd, unsigned long arg) | |||
| 2160 | { | |||
| 2161 | int err; | |||
| 2162 | ide_drive_t *drive; | |||
| 2163 | unsigned long flags; | |||
| 2164 | struct request rq; | |||
| 2165 | ||||
| 2166 | if (!inode || !(inode->i_rdev)) | |||
| ||||
| 2167 | return -EINVAL22; | |||
| 2168 | if ((drive = get_info_ptr(inode->i_rdev)) == NULL((void *) 0)) | |||
| 2169 | return -ENODEV19; | |||
| 2170 | ide_init_drive_cmd (&rq); | |||
| 2171 | switch (cmd) { | |||
| 2172 | case HDIO_GETGEO0x0301: | |||
| 2173 | { | |||
| 2174 | struct hd_geometry *loc = (struct hd_geometry *) arg; | |||
| 2175 | if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL22; | |||
| 2176 | #ifdef MACH1 | |||
| 2177 | loc->heads = drive->bios_head; | |||
| 2178 | loc->sectors = drive->bios_sect; | |||
| 2179 | loc->cylinders = drive->bios_cyl; | |||
| 2180 | loc->start | |||
| 2181 | = (drive->part[MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1))&PARTN_MASK((1<<6)-1)] | |||
| 2182 | .start_sect); | |||
| 2183 | #else | |||
| 2184 | err = verify_area(VERIFY_WRITE1, loc, sizeof(*loc)); | |||
| 2185 | if (err) return err; | |||
| 2186 | put_user(drive->bios_head, (byte *) &loc->heads)__put_user((unsigned long)(drive->bios_head),((byte *) & loc->heads),sizeof(*((byte *) &loc->heads))); | |||
| 2187 | put_user(drive->bios_sect, (byte *) &loc->sectors)__put_user((unsigned long)(drive->bios_sect),((byte *) & loc->sectors),sizeof(*((byte *) &loc->sectors))); | |||
| 2188 | put_user(drive->bios_cyl, (unsigned short *) &loc->cylinders)__put_user((unsigned long)(drive->bios_cyl),((unsigned short *) &loc->cylinders),sizeof(*((unsigned short *) & loc->cylinders))); | |||
| 2189 | put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,__put_user((unsigned long)((unsigned)drive->part[((inode-> i_rdev) & ((1<<8) - 1))&((1<<6)-1)].start_sect ),((unsigned long *) &loc->start),sizeof(*((unsigned long *) &loc->start))) | |||
| 2190 | (unsigned long *) &loc->start)__put_user((unsigned long)((unsigned)drive->part[((inode-> i_rdev) & ((1<<8) - 1))&((1<<6)-1)].start_sect ),((unsigned long *) &loc->start),sizeof(*((unsigned long *) &loc->start))); | |||
| 2191 | #endif | |||
| 2192 | return 0; | |||
| 2193 | } | |||
| 2194 | case BLKFLSBUF(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((97)) << 0) | ((0) << ((0 +8)+8))): | |||
| 2195 | if (!suser()) return -EACCES13; | |||
| 2196 | fsync_dev(inode->i_rdev); | |||
| 2197 | invalidate_buffers(inode->i_rdev); | |||
| 2198 | return 0; | |||
| 2199 | ||||
| 2200 | case BLKRASET(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((98)) << 0) | ((0) << ((0 +8)+8))): | |||
| 2201 | if (!suser()) return -EACCES13; | |||
| 2202 | if(arg > 0xff) return -EINVAL22; | |||
| 2203 | read_ahead[MAJOR(inode->i_rdev)((inode->i_rdev) >> 8)] = arg; | |||
| 2204 | return 0; | |||
| 2205 | ||||
| 2206 | case BLKRAGET(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((99)) << 0) | ((0) << ((0 +8)+8))): | |||
| 2207 | return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)((inode->i_rdev) >> 8)]); | |||
| 2208 | ||||
| 2209 | case BLKGETSIZE(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((96)) << 0) | ((0) << ((0 +8)+8))): /* Return device size */ | |||
| 2210 | return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1))&PARTN_MASK((1<<6)-1)].nr_sects); | |||
| 2211 | case BLKRRPART(((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((95)) << 0) | ((0) << ((0 +8)+8))): /* Re-read partition tables */ | |||
| 2212 | if (!suser()) return -EACCES13; | |||
| 2213 | return revalidate_disk(inode->i_rdev); | |||
| 2214 | ||||
| 2215 | case HDIO_GET_KEEPSETTINGS0x0308: | |||
| 2216 | return write_fs_long(arg, drive->keep_settings); | |||
| 2217 | ||||
| 2218 | case HDIO_GET_UNMASKINTR0x0302: | |||
| 2219 | return write_fs_long(arg, drive->unmask); | |||
| 2220 | ||||
| 2221 | case HDIO_GET_DMA0x030b: | |||
| 2222 | return write_fs_long(arg, drive->using_dma); | |||
| 2223 | ||||
| 2224 | case HDIO_GET_32BIT0x0309: | |||
| 2225 | return write_fs_long(arg, drive->io_32bit); | |||
| 2226 | ||||
| 2227 | case HDIO_GET_MULTCOUNT0x0304: | |||
| 2228 | return write_fs_long(arg, drive->mult_count); | |||
| 2229 | ||||
| 2230 | case HDIO_GET_IDENTITY0x030d: | |||
| 2231 | if (!arg || (MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1)) & PARTN_MASK((1<<6)-1))) | |||
| 2232 | return -EINVAL22; | |||
| 2233 | if (drive->id == NULL((void *) 0)) | |||
| 2234 | return -ENOMSG42; | |||
| 2235 | err = verify_area(VERIFY_WRITE1, (char *)arg, sizeof(*drive->id)); | |||
| 2236 | if (!err) | |||
| 2237 | memcpy_tofs((char *)arg, (char *)drive->id, sizeof(*drive->id)); | |||
| 2238 | return err; | |||
| 2239 | ||||
| 2240 | case HDIO_GET_NOWERR0x030a: | |||
| 2241 | return write_fs_long(arg, drive->bad_wstat == BAD_R_STAT(0x80 | 0x01)); | |||
| 2242 | ||||
| 2243 | case HDIO_SET_DMA0x0326: | |||
| 2244 | if (!suser()) return -EACCES13; | |||
| 2245 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2246 | if (drive->media == ide_cdrom) | |||
| 2247 | return -EPERM1; | |||
| 2248 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2249 | if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc) | |||
| 2250 | return -EPERM1; | |||
| 2251 | case HDIO_SET_KEEPSETTINGS0x0323: | |||
| 2252 | case HDIO_SET_UNMASKINTR0x0322: | |||
| 2253 | case HDIO_SET_NOWERR0x0325: | |||
| 2254 | if (arg > 1) | |||
| 2255 | return -EINVAL22; | |||
| 2256 | case HDIO_SET_32BIT0x0324: | |||
| 2257 | if (!suser()) return -EACCES13; | |||
| 2258 | if ((MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1)) & PARTN_MASK((1<<6)-1))) | |||
| 2259 | return -EINVAL22; | |||
| 2260 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2261 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 2262 | switch (cmd) { | |||
| 2263 | case HDIO_SET_DMA0x0326: | |||
| 2264 | if (!(HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc)) { | |||
| 2265 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2266 | return -EPERM1; | |||
| 2267 | } | |||
| 2268 | drive->using_dma = arg; | |||
| 2269 | break; | |||
| 2270 | case HDIO_SET_KEEPSETTINGS0x0323: | |||
| 2271 | drive->keep_settings = arg; | |||
| 2272 | break; | |||
| 2273 | case HDIO_SET_UNMASKINTR0x0322: | |||
| 2274 | if (arg && drive->no_unmask) { | |||
| 2275 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2276 | return -EPERM1; | |||
| 2277 | } | |||
| 2278 | drive->unmask = arg; | |||
| 2279 | break; | |||
| 2280 | case HDIO_SET_NOWERR0x0325: | |||
| 2281 | drive->bad_wstat = arg ? BAD_R_STAT(0x80 | 0x01) : BAD_W_STAT((0x80 | 0x01) | 0x20); | |||
| 2282 | break; | |||
| 2283 | case HDIO_SET_32BIT0x0324: | |||
| 2284 | if (arg > (1 + (SUPPORT_VLB_SYNC1<<1))) { | |||
| 2285 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2286 | return -EINVAL22; | |||
| 2287 | } | |||
| 2288 | if (arg && drive->no_io_32bit) { | |||
| 2289 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2290 | return -EPERM1; | |||
| 2291 | } | |||
| 2292 | drive->io_32bit = arg; | |||
| 2293 | #ifdef CONFIG_BLK_DEV_DTC2278 | |||
| 2294 | if (HWIF(drive)((ide_hwif_t *)((drive)->hwif))->chipset == ide_dtc2278) | |||
| 2295 | HWIF(drive)((ide_hwif_t *)((drive)->hwif))->drives[!drive->select.b.unit].io_32bit = arg; | |||
| 2296 | #endif /* CONFIG_BLK_DEV_DTC2278 */ | |||
| 2297 | break; | |||
| 2298 | } | |||
| 2299 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2300 | return 0; | |||
| 2301 | ||||
| 2302 | case HDIO_SET_MULTCOUNT0x0321: | |||
| 2303 | if (!suser()) return -EACCES13; | |||
| 2304 | if (MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1)) & PARTN_MASK((1<<6)-1)) | |||
| 2305 | return -EINVAL22; | |||
| 2306 | if (drive->id && arg > drive->id->max_multsect) | |||
| 2307 | return -EINVAL22; | |||
| 2308 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2309 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 2310 | if (drive->special.b.set_multmode) { | |||
| 2311 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2312 | return -EBUSY16; | |||
| 2313 | } | |||
| 2314 | drive->mult_req = arg; | |||
| 2315 | drive->special.b.set_multmode = 1; | |||
| 2316 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2317 | (void) ide_do_drive_cmd (drive, &rq, ide_wait); | |||
| 2318 | return (drive->mult_count == arg) ? 0 : -EIO5; | |||
| 2319 | ||||
| 2320 | case HDIO_DRIVE_CMD0x031f: | |||
| 2321 | { | |||
| 2322 | byte args[4], *argbuf = args; | |||
| 2323 | int argsize = 4; | |||
| 2324 | if (!suser() || securelevel > 0) return -EACCES13; | |||
| 2325 | if (NULL((void *) 0) == (void *) arg) { | |||
| 2326 | err = ide_do_drive_cmd(drive, &rq, ide_wait); | |||
| 2327 | } else if (!(err = verify_area(VERIFY_READ0,(void *)arg, 4))) { | |||
| 2328 | memcpy_fromfs(args, (void *)arg, 4); | |||
| 2329 | if (args[3]) { | |||
| 2330 | argsize = 4 + (SECTOR_WORDS(512 / 4) * 4 * args[3]); | |||
| 2331 | argbuf = kmalloclinux_kmalloc(argsize, GFP_KERNEL0x03); | |||
| 2332 | if (argbuf == NULL((void *) 0)) | |||
| 2333 | return -ENOMEM12; | |||
| 2334 | argbuf[0] = args[0]; | |||
| 2335 | argbuf[1] = args[1]; | |||
| 2336 | argbuf[2] = args[2]; | |||
| 2337 | argbuf[3] = args[3]; | |||
| 2338 | } | |||
| 2339 | if (!(err = verify_area(VERIFY_WRITE1,(void *)arg, argsize))) { | |||
| 2340 | rq.buffer = (char *)argbuf; | |||
| 2341 | err = ide_do_drive_cmd(drive, &rq, ide_wait); | |||
| 2342 | memcpy_tofs((void *)arg, argbuf, argsize); | |||
| 2343 | } | |||
| 2344 | if (argsize > 4) | |||
| 2345 | kfreelinux_kfree(argbuf); | |||
| 2346 | } | |||
| 2347 | return err; | |||
| 2348 | } | |||
| 2349 | case HDIO_SET_PIO_MODE0x0327: | |||
| 2350 | if (!suser()) return -EACCES13; | |||
| 2351 | if (MINOR(inode->i_rdev)((inode->i_rdev) & ((1<<8) - 1)) & PARTN_MASK((1<<6)-1)) | |||
| 2352 | return -EINVAL22; | |||
| 2353 | if (!HWIF(drive)((ide_hwif_t *)((drive)->hwif))->tuneproc) | |||
| 2354 | return -ENOSYS38; | |||
| 2355 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2356 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 2357 | if (drive->special.b.set_tune) { | |||
| 2358 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2359 | return -EBUSY16; | |||
| 2360 | } | |||
| 2361 | drive->tune_req = (byte) arg; | |||
| 2362 | drive->special.b.set_tune = 1; | |||
| 2363 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2364 | (void) ide_do_drive_cmd (drive, &rq, ide_wait); | |||
| 2365 | return 0; | |||
| 2366 | ||||
| 2367 | RO_IOCTLS(inode->i_rdev, arg)case (((0U) << (((0 +8)+8)+14)) | (((0x12)) << (0 +8)) | (((93)) << 0) | ((0) << ((0 +8)+8))): { int __err; if (!suser()) return -13; __err = verify_area(0, (void *) (arg), sizeof(long)); if (!__err) set_device_ro((inode-> i_rdev),__get_user((const unsigned int *)((long *) (arg)),4)) ; return __err; } case (((0U) << (((0 +8)+8)+14)) | ((( 0x12)) << (0 +8)) | (((94)) << 0) | ((0) << ((0 +8)+8))): { int __err = verify_area(1, (void *) (arg), sizeof (long)); if (!__err) __put_user((0!=is_read_only(inode->i_rdev )),(unsigned int *)((long *) (arg)),4); return __err; }; | |||
| 2368 | ||||
| 2369 | default: | |||
| 2370 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2371 | if (drive->media == ide_cdrom) | |||
| 2372 | return ide_cdrom_ioctl(drive, inode, file, cmd, arg); | |||
| 2373 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2374 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 2375 | if (drive->media == ide_tape) | |||
| 2376 | return idetape_blkdev_ioctl(drive, inode, file, cmd, arg); | |||
| 2377 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 2378 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 2379 | if (drive->media == ide_floppy) | |||
| 2380 | return idefloppy_ioctl(drive, inode, file, cmd, arg); | |||
| 2381 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 2382 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 2383 | if (drive->media == ide_scsi) | |||
| 2384 | return idescsi_ioctl(drive, inode, file, cmd, arg); | |||
| 2385 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 2386 | return -EPERM1; | |||
| 2387 | } | |||
| 2388 | } | |||
| ||||
| 2389 | ||||
| 2390 | static int ide_check_media_change (kdev_t i_rdev) | |||
| 2391 | { | |||
| 2392 | ide_drive_t *drive; | |||
| 2393 | ||||
| 2394 | if ((drive = get_info_ptr(i_rdev)) == NULL((void *) 0)) | |||
| 2395 | return -ENODEV19; | |||
| 2396 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2397 | if (drive->media == ide_cdrom) | |||
| 2398 | return ide_cdrom_check_media_change (drive); | |||
| 2399 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2400 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 2401 | if (drive->media == ide_floppy) | |||
| 2402 | return idefloppy_media_change (drive); | |||
| 2403 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 2404 | if (drive->removable) /* for disks */ | |||
| 2405 | return 1; /* always assume it was changed */ | |||
| 2406 | return 0; | |||
| 2407 | } | |||
| 2408 | ||||
| 2409 | void ide_fixstring (byte *s, const int bytecount, const int byteswap) | |||
| 2410 | { | |||
| 2411 | byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */ | |||
| 2412 | ||||
| 2413 | if (byteswap) { | |||
| 2414 | /* convert from big-endian to host byte order */ | |||
| 2415 | for (p = end ; p != s;) { | |||
| 2416 | unsigned short *pp = (unsigned short *) (p -= 2); | |||
| 2417 | *pp = ntohs(*pp); | |||
| 2418 | } | |||
| 2419 | } | |||
| 2420 | ||||
| 2421 | /* strip leading blanks */ | |||
| 2422 | while (s != end && *s == ' ') | |||
| 2423 | ++s; | |||
| 2424 | ||||
| 2425 | /* compress internal blanks and strip trailing blanks */ | |||
| 2426 | while (s != end && *s) { | |||
| 2427 | if (*s++ != ' ' || (s != end && *s && *s != ' ')) | |||
| 2428 | *p++ = *(s-1); | |||
| 2429 | } | |||
| 2430 | ||||
| 2431 | /* wipe out trailing garbage */ | |||
| 2432 | while (p != end) | |||
| 2433 | *p++ = '\0'; | |||
| 2434 | } | |||
| 2435 | ||||
| 2436 | static inlineinline __attribute__((always_inline)) void do_identify (ide_drive_t *drive, byte cmd) | |||
| 2437 | { | |||
| 2438 | int bswap; | |||
| 2439 | struct hd_driveid *id; | |||
| 2440 | unsigned long capacity, check; | |||
| 2441 | ||||
| 2442 | id = drive->id = kmalloclinux_kmalloc (SECTOR_WORDS(512 / 4)*4, GFP_KERNEL0x03); | |||
| 2443 | ide_input_data(drive, id, SECTOR_WORDS(512 / 4));/* read 512 bytes of id info */ | |||
| 2444 | sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 2445 | ||||
| 2446 | #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO1) || defined (CONFIG_SCSI_EATA1) | |||
| 2447 | /* | |||
| 2448 | * EATA SCSI controllers do a hardware ATA emulation: | |||
| 2449 | * Ignore them if there is a driver for them available. | |||
| 2450 | */ | |||
| 2451 | if ((id->model[0] == 'P' && id->model[1] == 'M') | |||
| 2452 | || (id->model[0] == 'S' && id->model[1] == 'K')) { | |||
| 2453 | printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); | |||
| 2454 | drive->present = 0; | |||
| 2455 | return; | |||
| 2456 | } | |||
| 2457 | #endif | |||
| 2458 | ||||
| 2459 | /* | |||
| 2460 | * WIN_IDENTIFY returns little-endian info, | |||
| 2461 | * WIN_PIDENTIFY *usually* returns little-endian info. | |||
| 2462 | */ | |||
| 2463 | bswap = 1; | |||
| 2464 | if (cmd == WIN_PIDENTIFY0xA1) { | |||
| 2465 | if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */ | |||
| 2466 | || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ | |||
| 2467 | || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ | |||
| 2468 | bswap = 0; /* Vertos drives may still be weird */ | |||
| 2469 | } | |||
| 2470 | ide_fixstring (id->model, sizeof(id->model), bswap); | |||
| 2471 | ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); | |||
| 2472 | ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); | |||
| 2473 | ||||
| 2474 | if (strstr((char *)id->model, "E X A B Y T E N E S T")) | |||
| 2475 | return; | |||
| 2476 | ||||
| 2477 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 2478 | /* | |||
| 2479 | * Check for an ATAPI device | |||
| 2480 | */ | |||
| 2481 | if (cmd == WIN_PIDENTIFY0xA1) { | |||
| 2482 | byte type = (id->config >> 8) & 0x1f; | |||
| 2483 | printk("%s: %s, ATAPI ", drive->name, id->model); | |||
| 2484 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 2485 | if (HWIF(drive)((ide_hwif_t *)((drive)->hwif))->is_promise2) { | |||
| 2486 | printk(" -- not supported on 2nd Promise port\n"); | |||
| 2487 | drive->present = 0; | |||
| 2488 | return; | |||
| 2489 | } | |||
| 2490 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 2491 | if (!drive->ide_scsi) switch (type) { | |||
| 2492 | case 0: | |||
| 2493 | if (!strstr((char *)id->model, "oppy") && | |||
| 2494 | !strstr((char *)id->model, "poyp") && | |||
| 2495 | !strstr((char *)id->model, "ZIP")) | |||
| 2496 | printk("cdrom or floppy?, assuming "); | |||
| 2497 | if (drive->media != ide_cdrom && | |||
| 2498 | !strstr((char *)id->model, "CD-ROM")) { | |||
| 2499 | #ifdef CONFIG_BLK_DEV_IDEFLOPPY | |||
| 2500 | printk("FLOPPY drive\n"); | |||
| 2501 | drive->media = ide_floppy; | |||
| 2502 | if (idefloppy_identify_device(drive, id)) | |||
| 2503 | drive->present = 1; | |||
| 2504 | return; | |||
| 2505 | #else | |||
| 2506 | printk("FLOPPY "); | |||
| 2507 | break; | |||
| 2508 | #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ | |||
| 2509 | } | |||
| 2510 | /* Early cdrom models used zero */ | |||
| 2511 | case 5: | |||
| 2512 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2513 | printk ("CDROM drive\n"); | |||
| 2514 | drive->media = ide_cdrom; | |||
| 2515 | drive->present = 1; | |||
| 2516 | drive->removable = 1; | |||
| 2517 | return; | |||
| 2518 | #else | |||
| 2519 | printk ("CDROM "); | |||
| 2520 | break; | |||
| 2521 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2522 | case 1: | |||
| 2523 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 2524 | printk ("TAPE drive"); | |||
| 2525 | if (idetape_identify_device (drive,id)) { | |||
| 2526 | drive->media = ide_tape; | |||
| 2527 | drive->present = 1; | |||
| 2528 | drive->removable = 1; | |||
| 2529 | if (drive->autotune != 2 && HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc != NULL((void *) 0)) { | |||
| 2530 | if (!HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc(ide_dma_check, drive)) | |||
| 2531 | printk(", DMA"); | |||
| 2532 | } | |||
| 2533 | printk("\n"); | |||
| 2534 | } | |||
| 2535 | else { | |||
| 2536 | drive->present = 0; | |||
| 2537 | printk ("\nide-tape: the tape is not supported by this version of the driver\n"); | |||
| 2538 | } | |||
| 2539 | return; | |||
| 2540 | #else | |||
| 2541 | printk ("TAPE "); | |||
| 2542 | break; | |||
| 2543 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 2544 | default: | |||
| 2545 | drive->present = 0; | |||
| 2546 | printk("Type %d - Unknown device\n", type); | |||
| 2547 | return; | |||
| 2548 | } | |||
| 2549 | #ifdef CONFIG_BLK_DEV_IDESCSI | |||
| 2550 | printk("drive - enabling SCSI emulation\n"); | |||
| 2551 | drive->media = ide_scsi; | |||
| 2552 | drive->present = 1; | |||
| 2553 | idescsi_setup(drive); | |||
| 2554 | #else | |||
| 2555 | drive->present = 0; | |||
| 2556 | printk("- not supported by this kernel\n"); | |||
| 2557 | #endif /* CONFIG_BLK_DEV_IDESCSI */ | |||
| 2558 | return; | |||
| 2559 | } | |||
| 2560 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 2561 | ||||
| 2562 | /* check for removable disks (eg. SYQUEST), ignore 'WD' drives */ | |||
| 2563 | if (id->config & (1<<7)) { /* removable disk ? */ | |||
| 2564 | if (id->model[0] != 'W' || id->model[1] != 'D') | |||
| 2565 | drive->removable = 1; | |||
| 2566 | } | |||
| 2567 | ||||
| 2568 | /* SunDisk drives: treat as non-removable, force one unit */ | |||
| 2569 | if (id->model[0] == 'S' && id->model[1] == 'u') { | |||
| 2570 | drive->removable = 0; | |||
| 2571 | if (drive->select.all & (1<<4)) { | |||
| 2572 | drive->present = 0; | |||
| 2573 | return; | |||
| 2574 | } | |||
| 2575 | } | |||
| 2576 | ||||
| 2577 | drive->media = ide_disk; | |||
| 2578 | /* Extract geometry if we did not already have one for the drive */ | |||
| 2579 | if (!drive->present) { | |||
| 2580 | drive->present = 1; | |||
| 2581 | drive->cyl = drive->bios_cyl = id->cyls; | |||
| 2582 | drive->head = drive->bios_head = id->heads; | |||
| 2583 | drive->sect = drive->bios_sect = id->sectors; | |||
| 2584 | } | |||
| 2585 | /* Handle logical geometry translation by the drive */ | |||
| 2586 | if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads | |||
| 2587 | && (id->cur_heads <= 16) && id->cur_sectors) { | |||
| 2588 | /* | |||
| 2589 | * Extract the physical drive geometry for our use. | |||
| 2590 | * Note that we purposely do *not* update the bios info. | |||
| 2591 | * This way, programs that use it (like fdisk) will | |||
| 2592 | * still have the same logical view as the BIOS does, | |||
| 2593 | * which keeps the partition table from being screwed. | |||
| 2594 | * | |||
| 2595 | * An exception to this is the cylinder count, | |||
| 2596 | * which we reexamine later on to correct for 1024 limitations. | |||
| 2597 | */ | |||
| 2598 | drive->cyl = id->cur_cyls; | |||
| 2599 | drive->head = id->cur_heads; | |||
| 2600 | drive->sect = id->cur_sectors; | |||
| 2601 | ||||
| 2602 | /* check for word-swapped "capacity" field in id information */ | |||
| 2603 | capacity = drive->cyl * drive->head * drive->sect; | |||
| 2604 | check = (id->cur_capacity0 << 16) | id->cur_capacity1; | |||
| 2605 | if (check == capacity) { /* was it swapped? */ | |||
| 2606 | /* yes, bring it into little-endian order: */ | |||
| 2607 | id->cur_capacity0 = (capacity >> 0) & 0xffff; | |||
| 2608 | id->cur_capacity1 = (capacity >> 16) & 0xffff; | |||
| 2609 | } | |||
| 2610 | } | |||
| 2611 | /* Use physical geometry if what we have still makes no sense */ | |||
| 2612 | if ((!drive->head || drive->head > 16) && | |||
| 2613 | id->heads && id->heads <= 16) { | |||
| 2614 | drive->cyl = id->cyls; | |||
| 2615 | drive->head = id->heads; | |||
| 2616 | drive->sect = id->sectors; | |||
| 2617 | } | |||
| 2618 | ||||
| 2619 | /* calculate drive capacity, and select LBA if possible */ | |||
| 2620 | capacity = current_capacity (drive); | |||
| 2621 | ||||
| 2622 | /* | |||
| 2623 | * if possible, give fdisk access to more of the drive, | |||
| 2624 | * by correcting bios_cyls: | |||
| 2625 | */ | |||
| 2626 | if (capacity > drive->bios_cyl * drive->bios_head * drive->bios_sect | |||
| 2627 | && !drive->forced_geom && drive->bios_sect && drive->bios_head) { | |||
| 2628 | int cyl = (capacity / drive->bios_sect) / drive->bios_head; | |||
| 2629 | if (cyl <= 65535) | |||
| 2630 | drive->bios_cyl = cyl; | |||
| 2631 | else { | |||
| 2632 | /* OK until 539 GB */ | |||
| 2633 | drive->bios_sect = 63; | |||
| 2634 | drive->bios_head = 255; | |||
| 2635 | drive->bios_cyl = capacity / (63*255); | |||
| 2636 | } | |||
| 2637 | } | |||
| 2638 | ||||
| 2639 | if (!strncmp((char *)id->model, "BMI ", 4) && | |||
| 2640 | strstr((char *)id->model, " ENHANCED IDE ") && | |||
| 2641 | drive->select.b.lba) | |||
| 2642 | drive->no_geom = 1; | |||
| 2643 | ||||
| 2644 | printk ("%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d", | |||
| 2645 | drive->name, id->model, current_capacity(drive)/2048L, id->buf_size/2, | |||
| 2646 | drive->bios_cyl, drive->bios_head, drive->bios_sect); | |||
| 2647 | ||||
| 2648 | drive->mult_count = 0; | |||
| 2649 | if (id->max_multsect) { | |||
| 2650 | drive->mult_req = INITIAL_MULT_COUNT16; | |||
| 2651 | if (drive->mult_req > id->max_multsect) | |||
| 2652 | drive->mult_req = id->max_multsect; | |||
| 2653 | if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) | |||
| 2654 | drive->special.b.set_multmode = 1; | |||
| 2655 | } | |||
| 2656 | if (drive->autotune != 2 && HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc != NULL((void *) 0)) { | |||
| 2657 | if (!(HWIF(drive)((ide_hwif_t *)((drive)->hwif))->dmaproc(ide_dma_check, drive))) { | |||
| 2658 | if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) | |||
| 2659 | printk(", UDMA"); | |||
| 2660 | else | |||
| 2661 | printk(", DMA"); | |||
| 2662 | } | |||
| 2663 | } | |||
| 2664 | printk("\n"); | |||
| 2665 | } | |||
| 2666 | ||||
| 2667 | /* | |||
| 2668 | * Delay for *at least* 50ms. As we don't know how much time is left | |||
| 2669 | * until the next tick occurs, we wait an extra tick to be safe. | |||
| 2670 | * This is used only during the probing/polling for drives at boot time. | |||
| 2671 | */ | |||
| 2672 | static void delay_50ms (void) | |||
| 2673 | { | |||
| 2674 | unsigned long timer = jiffies + ((HZ100 + 19)/20) + 1; | |||
| 2675 | while (timer > jiffies); | |||
| 2676 | } | |||
| 2677 | ||||
| 2678 | /* | |||
| 2679 | * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive | |||
| 2680 | * and waits for a response. It also monitors irqs while this is | |||
| 2681 | * happening, in hope of automatically determining which one is | |||
| 2682 | * being used by the interface. | |||
| 2683 | * | |||
| 2684 | * Returns: 0 device was identified | |||
| 2685 | * 1 device timed-out (no response to identify request) | |||
| 2686 | * 2 device aborted the command (refused to identify itself) | |||
| 2687 | */ | |||
| 2688 | static int try_to_identify (ide_drive_t *drive, byte cmd) | |||
| 2689 | { | |||
| 2690 | int hd_status, rc; | |||
| 2691 | unsigned long timeout; | |||
| 2692 | unsigned long irqs_on = 0; | |||
| 2693 | int irq_off; | |||
| 2694 | ||||
| 2695 | if (!HWIF(drive)((ide_hwif_t *)((drive)->hwif))->irq) { /* already got an IRQ? */ | |||
| 2696 | probe_irq_off(probe_irq_on()); /* clear dangling irqs */ | |||
| 2697 | irqs_on = probe_irq_on(); /* start monitoring irqs */ | |||
| 2698 | OUT_BYTE(drive->ctl,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl)),(((( (ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); /* enable device irq */ | |||
| 2699 | } | |||
| 2700 | ||||
| 2701 | delay_50ms(); /* take a deep breath */ | |||
| 2702 | if ((IN_BYTE(IDE_ALTSTATUS_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->ctl_port))) && ((((ide_hwif_t *)((drive)->hwif ))->ctl_port)) < 256) ? __inbc_p((((ide_hwif_t *)((drive )->hwif))->ctl_port)) : __inb_p((((ide_hwif_t *)((drive )->hwif))->ctl_port))) ^ IN_BYTE(IDE_STATUS_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) & ~INDEX_STAT0x02) { | |||
| 2703 | printk("%s: probing with STATUS instead of ALTSTATUS\n", drive->name); | |||
| 2704 | hd_status = IDE_STATUS_REG(((ide_hwif_t *)((drive)->hwif))->io_base+(7)); /* ancient Seagate drives */ | |||
| 2705 | } else | |||
| 2706 | hd_status = IDE_ALTSTATUS_REG(((ide_hwif_t *)((drive)->hwif))->ctl_port); /* use non-intrusive polling */ | |||
| 2707 | ||||
| 2708 | #if CONFIG_BLK_DEV_PROMISE | |||
| 2709 | if (IS_PROMISE_DRIVE(0)) { | |||
| 2710 | if (promise_cmd(drive,PROMISE_IDENTIFY)) { | |||
| 2711 | if (irqs_on) | |||
| 2712 | (void) probe_irq_off(irqs_on); | |||
| 2713 | return 1; | |||
| 2714 | } | |||
| 2715 | } else | |||
| 2716 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 2717 | OUT_BYTE(cmd,IDE_COMMAND_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(7))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) < 256) ? __outbc_p(((cmd)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) : __outb_p(((cmd)) ,(((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))); /* ask drive for ID */ | |||
| 2718 | timeout = ((cmd == WIN_IDENTIFY0xEC) ? WAIT_WORSTCASE(30*100) : WAIT_PIDENTIFY(1*100)) / 2; | |||
| 2719 | timeout += jiffies; | |||
| 2720 | do { | |||
| 2721 | if (jiffies > timeout) { | |||
| 2722 | if (irqs_on) | |||
| 2723 | (void) probe_irq_off(irqs_on); | |||
| 2724 | return 1; /* drive timed-out */ | |||
| 2725 | } | |||
| 2726 | delay_50ms(); /* give drive a breather */ | |||
| 2727 | } while (IN_BYTE(hd_status)(byte)((__builtin_constant_p((hd_status)) && (hd_status ) < 256) ? __inbc_p(hd_status) : __inb_p(hd_status)) & BUSY_STAT0x80); | |||
| 2728 | ||||
| 2729 | delay_50ms(); /* wait for IRQ and DRQ_STAT */ | |||
| 2730 | if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)((((byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)-> hwif))->io_base+(7)))) && ((((ide_hwif_t *)((drive )->hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&((0x08)|((0x80 | 0x01))))==(0x08))) { | |||
| 2731 | unsigned long flags; | |||
| 2732 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2733 | cli()__asm__ __volatile__ ("cli": : :"memory"); /* some systems need this */ | |||
| 2734 | do_identify(drive, cmd); /* drive returned ID */ | |||
| 2735 | rc = 0; /* drive responded with ID */ | |||
| 2736 | (void) GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); /* clear drive IRQ */ | |||
| 2737 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 2738 | } else | |||
| 2739 | rc = 2; /* drive refused ID */ | |||
| 2740 | if (!HWIF(drive)((ide_hwif_t *)((drive)->hwif))->irq) { | |||
| 2741 | irq_off = probe_irq_off(irqs_on); /* get our irq number */ | |||
| 2742 | if (irq_off > 0) { | |||
| 2743 | HWIF(drive)((ide_hwif_t *)((drive)->hwif))->irq = irq_off; /* save it for later */ | |||
| 2744 | irqs_on = probe_irq_on(); | |||
| 2745 | OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> ctl_port)))) && (((((ide_hwif_t *)((drive)->hwif)) ->ctl_port))) < 256) ? __outbc_p(((drive->ctl|2)),(( (((ide_hwif_t *)((drive)->hwif))->ctl_port)))) : __outb_p (((drive->ctl|2)),(((((ide_hwif_t *)((drive)->hwif))-> ctl_port))))); /* mask device irq */ | |||
| 2746 | udelay(5)(__builtin_constant_p(5) ? __const_udelay((5) * 0x10c6ul) : __udelay (5)); | |||
| 2747 | (void) probe_irq_off(irqs_on); | |||
| 2748 | (void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */ | |||
| 2749 | (void) GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); /* clear drive IRQ */ | |||
| 2750 | ||||
| 2751 | } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ | |||
| 2752 | printk("%s: IRQ probe failed (%d)\n", drive->name, irq_off); | |||
| 2753 | #ifdef CONFIG_BLK_DEV_CMD640 | |||
| 2754 | #ifdef CMD640_DUMP_REGS | |||
| 2755 | if (HWIF(drive)((ide_hwif_t *)((drive)->hwif))->chipset == ide_cmd640) { | |||
| 2756 | printk("%s: Hmmm.. probably a driver problem.\n", drive->name); | |||
| 2757 | CMD640_DUMP_REGS; | |||
| 2758 | } | |||
| 2759 | #endif /* CMD640_DUMP_REGS */ | |||
| 2760 | #endif /* CONFIG_BLK_DEV_CMD640 */ | |||
| 2761 | } | |||
| 2762 | } | |||
| 2763 | return rc; | |||
| 2764 | } | |||
| 2765 | ||||
| 2766 | /* | |||
| 2767 | * do_probe() has the difficult job of finding a drive if it exists, | |||
| 2768 | * without getting hung up if it doesn't exist, without trampling on | |||
| 2769 | * ethernet cards, and without leaving any IRQs dangling to haunt us later. | |||
| 2770 | * | |||
| 2771 | * If a drive is "known" to exist (from CMOS or kernel parameters), | |||
| 2772 | * but does not respond right away, the probe will "hang in there" | |||
| 2773 | * for the maximum wait time (about 30 seconds), otherwise it will | |||
| 2774 | * exit much more quickly. | |||
| 2775 | * | |||
| 2776 | * Returns: 0 device was identified | |||
| 2777 | * 1 device timed-out (no response to identify request) | |||
| 2778 | * 2 device aborted the command (refused to identify itself) | |||
| 2779 | * 3 bad status from device (possible for ATAPI drives) | |||
| 2780 | * 4 probe was not attempted because failure was obvious | |||
| 2781 | */ | |||
| 2782 | static int do_probe (ide_drive_t *drive, byte cmd) | |||
| 2783 | { | |||
| 2784 | int rc; | |||
| 2785 | ide_hwif_t *hwif = HWIF(drive)((ide_hwif_t *)((drive)->hwif)); | |||
| 2786 | unsigned long timeout; | |||
| 2787 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 2788 | if (drive->present) { /* avoid waiting for inappropriate probes */ | |||
| 2789 | if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY0xEC)) | |||
| 2790 | return 4; | |||
| 2791 | } | |||
| 2792 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 2793 | #ifdef DEBUG | |||
| 2794 | printk("probing for %s: present=%d, media=%d, probetype=%s\n", | |||
| 2795 | drive->name, drive->present, drive->media, | |||
| 2796 | (cmd == WIN_IDENTIFY0xEC) ? "ATA" : "ATAPI"); | |||
| 2797 | #endif | |||
| 2798 | SELECT_DRIVE(hwif,drive)((__builtin_constant_p(((hwif->io_base+(6)))) && ( (hwif->io_base+(6))) < 256) ? __outbc_p((((drive)->select .all)),((hwif->io_base+(6)))) : __outb_p((((drive)->select .all)),((hwif->io_base+(6)))));; | |||
| 2799 | delay_50ms(); | |||
| 2800 | if (IN_BYTE(IDE_SELECT_REG)(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(6))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(6))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(6)))) != drive->select.all && !drive->present) { | |||
| 2801 | OUT_BYTE(0xa0,IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((0xa0)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6))))) : __outb_p(((0xa0) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6)))))); /* exit with drive0 selected */ | |||
| 2802 | delay_50ms(); /* allow BUSY_STAT to assert & clear */ | |||
| 2803 | return 3; /* no i/f present: avoid killing ethernet cards */ | |||
| 2804 | } | |||
| 2805 | ||||
| 2806 | if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT)((((byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)-> hwif))->io_base+(7)))) && ((((ide_hwif_t *)((drive )->hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&((0x40)|(0x80) ))==(0x40)) | |||
| 2807 | || drive->present || cmd == WIN_PIDENTIFY0xA1) | |||
| 2808 | { | |||
| 2809 | if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ | |||
| 2810 | rc = try_to_identify(drive,cmd); /* failed: try again */ | |||
| 2811 | if (rc == 1 && cmd == WIN_PIDENTIFY0xA1 && drive->autotune != 2) { | |||
| 2812 | printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))); | |||
| 2813 | delay_50ms(); | |||
| 2814 | OUT_BYTE (drive->select.all, IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((drive->select .all)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6)) ))) : __outb_p(((drive->select.all)),(((((ide_hwif_t *)((drive )->hwif))->io_base+(6)))))); | |||
| 2815 | delay_50ms(); | |||
| 2816 | OUT_BYTE(WIN_SRST, IDE_COMMAND_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(7))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) < 256) ? __outbc_p(((0x08)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) : __outb_p(((0x08) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))); | |||
| 2817 | timeout = jiffies; | |||
| 2818 | while ((GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))) & BUSY_STAT0x80) && jiffies < timeout + WAIT_WORSTCASE(30*100)) | |||
| 2819 | delay_50ms(); | |||
| 2820 | rc = try_to_identify(drive, cmd); | |||
| 2821 | } | |||
| 2822 | if (rc == 1) | |||
| 2823 | printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))); | |||
| 2824 | (void) GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); /* ensure drive irq is clear */ | |||
| 2825 | } else { | |||
| 2826 | rc = 3; /* not present or maybe ATAPI */ | |||
| 2827 | } | |||
| 2828 | if (drive->select.b.unit != 0) { | |||
| 2829 | OUT_BYTE(0xa0,IDE_SELECT_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(6))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(6)))) < 256) ? __outbc_p(((0xa0)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6))))) : __outb_p(((0xa0) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(6)))))); /* exit with drive0 selected */ | |||
| 2830 | delay_50ms(); | |||
| 2831 | (void) GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))); /* ensure drive irq is clear */ | |||
| 2832 | } | |||
| 2833 | return rc; | |||
| 2834 | } | |||
| 2835 | ||||
| 2836 | static void enable_nest (ide_drive_t *drive) | |||
| 2837 | { | |||
| 2838 | unsigned long timeout; | |||
| 2839 | ||||
| 2840 | printk("%s: enabling %s -- ", HWIF(drive)((ide_hwif_t *)((drive)->hwif))->name, drive->id->model); | |||
| 2841 | SELECT_DRIVE(HWIF(drive), drive)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif))-> io_base+(6)))) && ((((ide_hwif_t *)((drive)->hwif) )->io_base+(6))) < 256) ? __outbc_p((((drive)->select .all)),((((ide_hwif_t *)((drive)->hwif))->io_base+(6))) ) : __outb_p((((drive)->select.all)),((((ide_hwif_t *)((drive )->hwif))->io_base+(6)))));; | |||
| 2842 | delay_50ms(); | |||
| 2843 | OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG)((__builtin_constant_p((((((ide_hwif_t *)((drive)->hwif))-> io_base+(7))))) && (((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) < 256) ? __outbc_p(((0xf0)),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))) : __outb_p(((0xf0) ),(((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))); | |||
| 2844 | timeout = jiffies + WAIT_WORSTCASE(30*100); | |||
| 2845 | do { | |||
| 2846 | if (jiffies > timeout) { | |||
| 2847 | printk("failed (timeout)\n"); | |||
| 2848 | return; | |||
| 2849 | } | |||
| 2850 | delay_50ms(); | |||
| 2851 | } while (GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))) & BUSY_STAT0x80); | |||
| 2852 | delay_50ms(); | |||
| 2853 | if (!OK_STAT(GET_STAT(), 0, BAD_STAT)((((byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)-> hwif))->io_base+(7)))) && ((((ide_hwif_t *)((drive )->hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7)))))&((0)|(((0x80 | 0x01) | 0x08))))==(0))) | |||
| 2854 | printk("failed (status = 0x%02x)\n", GET_STAT()(byte)((__builtin_constant_p(((((ide_hwif_t *)((drive)->hwif ))->io_base+(7)))) && ((((ide_hwif_t *)((drive)-> hwif))->io_base+(7))) < 256) ? __inbc_p((((ide_hwif_t * )((drive)->hwif))->io_base+(7))) : __inb_p((((ide_hwif_t *)((drive)->hwif))->io_base+(7))))); | |||
| 2855 | else | |||
| 2856 | printk("success\n"); | |||
| 2857 | if (do_probe(drive, WIN_IDENTIFY0xEC) >= 2) { /* if !(success||timed-out) */ | |||
| 2858 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 2859 | (void) do_probe(drive, WIN_PIDENTIFY0xA1); /* look for ATAPI device */ | |||
| 2860 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 2861 | } | |||
| 2862 | } | |||
| 2863 | ||||
| 2864 | /* | |||
| 2865 | * probe_for_drive() tests for existence of a given drive using do_probe(). | |||
| 2866 | * | |||
| 2867 | * Returns: 0 no device was found | |||
| 2868 | * 1 device was found (note: drive->present might still be 0) | |||
| 2869 | */ | |||
| 2870 | static inlineinline __attribute__((always_inline)) byte probe_for_drive (ide_drive_t *drive) | |||
| 2871 | { | |||
| 2872 | if (drive->noprobe) /* skip probing? */ | |||
| 2873 | return drive->present; | |||
| 2874 | if (do_probe(drive, WIN_IDENTIFY0xEC) >= 2) { /* if !(success||timed-out) */ | |||
| 2875 | #ifdef CONFIG_BLK_DEV_IDEATAPI1 | |||
| 2876 | (void) do_probe(drive, WIN_PIDENTIFY0xA1); /* look for ATAPI device */ | |||
| 2877 | #endif /* CONFIG_BLK_DEV_IDEATAPI */ | |||
| 2878 | } | |||
| 2879 | if (drive->id && strstr((char *)drive->id->model, "E X A B Y T E N E S T")) | |||
| 2880 | enable_nest(drive); | |||
| 2881 | if (!drive->present) | |||
| 2882 | return 0; /* drive not found */ | |||
| 2883 | if (drive->id == NULL((void *) 0)) { /* identification failed? */ | |||
| 2884 | if (drive->media == ide_disk) { | |||
| 2885 | printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", | |||
| 2886 | drive->name, drive->cyl, drive->head, drive->sect); | |||
| 2887 | } | |||
| 2888 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 2889 | else if (drive->media == ide_cdrom) { | |||
| 2890 | printk("%s: ATAPI cdrom (?)\n", drive->name); | |||
| 2891 | } | |||
| 2892 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 2893 | else { | |||
| 2894 | drive->present = 0; /* nuke it */ | |||
| 2895 | } | |||
| 2896 | } | |||
| 2897 | return 1; /* drive was found */ | |||
| 2898 | } | |||
| 2899 | ||||
| 2900 | /* | |||
| 2901 | * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc | |||
| 2902 | * controller that is BIOS compatible with ST-506, and thus showing up in our | |||
| 2903 | * BIOS table, but not register compatible, and therefore not present in CMOS. | |||
| 2904 | * | |||
| 2905 | * Furthermore, we will assume that our ST-506 drives <if any> are the primary | |||
| 2906 | * drives in the system -- the ones reflected as drive 1 or 2. The first | |||
| 2907 | * drive is stored in the high nibble of CMOS byte 0x12, the second in the low | |||
| 2908 | * nibble. This will be either a 4 bit drive type or 0xf indicating use byte | |||
| 2909 | * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value | |||
| 2910 | * means we have an AT controller hard disk for that drive. | |||
| 2911 | * | |||
| 2912 | * Of course, there is no guarantee that either drive is actually on the | |||
| 2913 | * "primary" IDE interface, but we don't bother trying to sort that out here. | |||
| 2914 | * If a drive is not actually on the primary interface, then these parameters | |||
| 2915 | * will be ignored. This results in the user having to supply the logical | |||
| 2916 | * drive geometry as a boot parameter for each drive not on the primary i/f. | |||
| 2917 | * | |||
| 2918 | * The only "perfect" way to handle this would be to modify the setup.[cS] code | |||
| 2919 | * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info | |||
| 2920 | * for us during initialization. I have the necessary docs -- any takers? -ml | |||
| 2921 | */ | |||
| 2922 | static void probe_cmos_for_drives (ide_hwif_t *hwif) | |||
| 2923 | { | |||
| 2924 | #ifdef __i386__1 | |||
| 2925 | extern struct drive_info_struct drive_info; | |||
| 2926 | byte cmos_disks, *BIOS = (byte *) &drive_info; | |||
| 2927 | int unit; | |||
| 2928 | ||||
| 2929 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 2930 | if (hwif->is_promise2) | |||
| 2931 | return; | |||
| 2932 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 2933 | outb_p(0x12,0x70)((__builtin_constant_p((0x70)) && (0x70) < 256) ? __outbc_p ((0x12),(0x70)) : __outb_p((0x12),(0x70))); /* specify CMOS address 0x12 */ | |||
| 2934 | cmos_disks = inb_p(0x71)((__builtin_constant_p((0x71)) && (0x71) < 256) ? __inbc_p (0x71) : __inb_p(0x71)); /* read the data from 0x12 */ | |||
| 2935 | /* Extract drive geometry from CMOS+BIOS if not already setup */ | |||
| 2936 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 2937 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 2938 | if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) { | |||
| 2939 | unsigned short cyl = *(unsigned short *)BIOS; | |||
| 2940 | unsigned char head = *(BIOS+2); | |||
| 2941 | unsigned char sect = *(BIOS+14); | |||
| 2942 | unsigned char ctl = *(BIOS+8); | |||
| 2943 | if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { | |||
| 2944 | drive->cyl = drive->bios_cyl = cyl; | |||
| 2945 | drive->head = drive->bios_head = head; | |||
| 2946 | drive->sect = drive->bios_sect = sect; | |||
| 2947 | drive->ctl = ctl; | |||
| 2948 | drive->present = 1; | |||
| 2949 | printk("hd%d: got CHS=%d/%d/%d CTL=%x from BIOS\n", | |||
| 2950 | unit, cyl, head, sect, ctl); | |||
| 2951 | ||||
| 2952 | } else { | |||
| 2953 | printk("hd%d: CHS=%d/%d/%d CTL=%x from BIOS ignored\n", | |||
| 2954 | unit, cyl, head, sect, ctl); | |||
| 2955 | } | |||
| 2956 | } | |||
| 2957 | BIOS += 16; | |||
| 2958 | } | |||
| 2959 | #endif | |||
| 2960 | } | |||
| 2961 | ||||
| 2962 | /* | |||
| 2963 | * This routine only knows how to look for drive units 0 and 1 | |||
| 2964 | * on an interface, so any setting of MAX_DRIVES > 2 won't work here. | |||
| 2965 | */ | |||
| 2966 | static void probe_hwif (ide_hwif_t *hwif) | |||
| 2967 | { | |||
| 2968 | unsigned int unit; | |||
| 2969 | ||||
| 2970 | if (hwif->noprobe) | |||
| 2971 | return; | |||
| 2972 | if (hwif->io_base == HD_DATA0x1f0) | |||
| 2973 | probe_cmos_for_drives (hwif); | |||
| 2974 | #if CONFIG_BLK_DEV_PROMISE | |||
| 2975 | if (!hwif->is_promise2 && | |||
| 2976 | (check_region(hwif->io_base,8) || check_region(hwif->ctl_port,1))) { | |||
| 2977 | #else | |||
| 2978 | if (check_region(hwif->io_base,8) || check_region(hwif->ctl_port,1)) { | |||
| 2979 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 2980 | int msgout = 0; | |||
| 2981 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 2982 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 2983 | if (drive->present) { | |||
| 2984 | drive->present = 0; | |||
| 2985 | printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name); | |||
| 2986 | msgout = 1; | |||
| 2987 | } | |||
| 2988 | } | |||
| 2989 | if (!msgout) | |||
| 2990 | printk("%s: ports already in use, skipping probe\n", hwif->name); | |||
| 2991 | } else { | |||
| 2992 | unsigned long flags; | |||
| 2993 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 2994 | ||||
| 2995 | sti()__asm__ __volatile__ ("sti": : :"memory"); /* needed for jiffies and irq probing */ | |||
| 2996 | /* | |||
| 2997 | * Second drive should only exist if first drive was found, | |||
| 2998 | * but a lot of cdrom drives are configured as single slaves. | |||
| 2999 | */ | |||
| 3000 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 3001 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 3002 | (void) probe_for_drive (drive); | |||
| 3003 | if (drive->present && drive->media == ide_disk) { | |||
| 3004 | if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { | |||
| 3005 | printk("%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", | |||
| 3006 | drive->name, drive->head); | |||
| 3007 | drive->present = 0; | |||
| 3008 | } | |||
| 3009 | } | |||
| 3010 | if (drive->present && !hwif->present) { | |||
| 3011 | hwif->present = 1; | |||
| 3012 | request_region(hwif->io_base, 8, hwif->name); | |||
| 3013 | request_region(hwif->ctl_port, 1, hwif->name); | |||
| 3014 | } | |||
| 3015 | } | |||
| 3016 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3017 | for (unit = 0; unit < MAX_DRIVES2; ++unit) { | |||
| 3018 | ide_drive_t *drive = &hwif->drives[unit]; | |||
| 3019 | if (drive->present && drive->media != ide_tape) { | |||
| 3020 | ide_tuneproc_t *tuneproc = HWIF(drive)((ide_hwif_t *)((drive)->hwif))->tuneproc; | |||
| 3021 | if (tuneproc != NULL((void *) 0) && drive->autotune == 1) | |||
| 3022 | tuneproc(drive, 255); /* auto-tune PIO mode */ | |||
| 3023 | } | |||
| 3024 | } | |||
| 3025 | } | |||
| 3026 | } | |||
| 3027 | ||||
| 3028 | /* | |||
| 3029 | * stridx() returns the offset of c within s, | |||
| 3030 | * or -1 if c is '\0' or not found within s. | |||
| 3031 | */ | |||
| 3032 | static int stridx (const char *s, char c) | |||
| 3033 | { | |||
| 3034 | char *i = strchr(s, c); | |||
| 3035 | return (i && c) ? i - s : -1; | |||
| 3036 | } | |||
| 3037 | ||||
| 3038 | /* | |||
| 3039 | * match_parm() does parsing for ide_setup(): | |||
| 3040 | * | |||
| 3041 | * 1. the first char of s must be '='. | |||
| 3042 | * 2. if the remainder matches one of the supplied keywords, | |||
| 3043 | * the index (1 based) of the keyword is negated and returned. | |||
| 3044 | * 3. if the remainder is a series of no more than max_vals numbers | |||
| 3045 | * separated by commas, the numbers are saved in vals[] and a | |||
| 3046 | * count of how many were saved is returned. Base10 is assumed, | |||
| 3047 | * and base16 is allowed when prefixed with "0x". | |||
| 3048 | * 4. otherwise, zero is returned. | |||
| 3049 | */ | |||
| 3050 | static int match_parm (char *s, const char *keywords[], int vals[], int max_vals) | |||
| 3051 | { | |||
| 3052 | static const char *decimal = "0123456789"; | |||
| 3053 | static const char *hex = "0123456789abcdef"; | |||
| 3054 | int i, n; | |||
| 3055 | ||||
| 3056 | if (*s++ == '=') { | |||
| 3057 | /* | |||
| 3058 | * Try matching against the supplied keywords, | |||
| 3059 | * and return -(index+1) if we match one | |||
| 3060 | */ | |||
| 3061 | if (keywords != NULL((void *) 0)) { | |||
| 3062 | for (i = 0; *keywords != NULL((void *) 0); ++i) { | |||
| 3063 | if (!strcmp(s, *keywords++)) | |||
| 3064 | return -(i+1); | |||
| 3065 | } | |||
| 3066 | } | |||
| 3067 | /* | |||
| 3068 | * Look for a series of no more than "max_vals" | |||
| 3069 | * numeric values separated by commas, in base10, | |||
| 3070 | * or base16 when prefixed with "0x". | |||
| 3071 | * Return a count of how many were found. | |||
| 3072 | */ | |||
| 3073 | for (n = 0; (i = stridx(decimal, *s)) >= 0;) { | |||
| 3074 | vals[n] = i; | |||
| 3075 | while ((i = stridx(decimal, *++s)) >= 0) | |||
| 3076 | vals[n] = (vals[n] * 10) + i; | |||
| 3077 | if (*s == 'x' && !vals[n]) { | |||
| 3078 | while ((i = stridx(hex, *++s)) >= 0) | |||
| 3079 | vals[n] = (vals[n] * 0x10) + i; | |||
| 3080 | } | |||
| 3081 | if (++n == max_vals) | |||
| 3082 | break; | |||
| 3083 | if (*s == ',') | |||
| 3084 | ++s; | |||
| 3085 | } | |||
| 3086 | if (!*s) | |||
| 3087 | return n; | |||
| 3088 | } | |||
| 3089 | return 0; /* zero = nothing matched */ | |||
| 3090 | } | |||
| 3091 | ||||
| 3092 | /* | |||
| 3093 | * ide_setup() gets called VERY EARLY during initialization, | |||
| 3094 | * to handle kernel "command line" strings beginning with "hdx=" | |||
| 3095 | * or "ide". Here is the complete set currently supported: | |||
| 3096 | * | |||
| 3097 | * "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". | |||
| 3098 | * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". | |||
| 3099 | * | |||
| 3100 | * "hdx=noprobe" : drive may be present, but do not probe for it | |||
| 3101 | * "hdx=none" : drive is NOT present, ignore cmos and do not probe | |||
| 3102 | * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive | |||
| 3103 | * "hdx=cdrom" : drive is present, and is a cdrom drive | |||
| 3104 | * "hdx=cyl,head,sect" : disk drive is present, with specified geometry | |||
| 3105 | * "hdx=autotune" : driver will attempt to tune interface speed | |||
| 3106 | * to the fastest PIO mode supported, | |||
| 3107 | * if possible for this drive only. | |||
| 3108 | * Not fully supported by all chipset types, | |||
| 3109 | * and quite likely to cause trouble with | |||
| 3110 | * older/odd IDE drives. | |||
| 3111 | * | |||
| 3112 | * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz, | |||
| 3113 | * where "xx" is between 20 and 66 inclusive, | |||
| 3114 | * used when tuning chipset PIO modes. | |||
| 3115 | * For PCI bus, 25 is correct for a P75 system, | |||
| 3116 | * 30 is correct for P90,P120,P180 systems, | |||
| 3117 | * and 33 is used for P100,P133,P166 systems. | |||
| 3118 | * If in doubt, use idebus=33 for PCI. | |||
| 3119 | * As for VLB, it is safest to not specify it. | |||
| 3120 | * | |||
| 3121 | * "idex=noprobe" : do not attempt to access/use this interface | |||
| 3122 | * "idex=base" : probe for an interface at the addr specified, | |||
| 3123 | * where "base" is usually 0x1f0 or 0x170 | |||
| 3124 | * and "ctl" is assumed to be "base"+0x206 | |||
| 3125 | * "idex=base,ctl" : specify both base and ctl | |||
| 3126 | * "idex=base,ctl,irq" : specify base, ctl, and irq number | |||
| 3127 | * "idex=autotune" : driver will attempt to tune interface speed | |||
| 3128 | * to the fastest PIO mode supported, | |||
| 3129 | * for all drives on this interface. | |||
| 3130 | * Not fully supported by all chipset types, | |||
| 3131 | * and quite likely to cause trouble with | |||
| 3132 | * older/odd IDE drives. | |||
| 3133 | * "idex=noautotune" : driver will NOT attempt to tune interface speed | |||
| 3134 | * This is the default for most chipsets, | |||
| 3135 | * except the cmd640. | |||
| 3136 | * "idex=serialize" : do not overlap operations on idex and ide(x^1) | |||
| 3137 | * | |||
| 3138 | * The following are valid ONLY on ide0, | |||
| 3139 | * and the defaults for the base,ctl ports must not be altered. | |||
| 3140 | * | |||
| 3141 | * "ide0=dtc2278" : probe/support DTC2278 interface | |||
| 3142 | * "ide0=ht6560b" : probe/support HT6560B interface | |||
| 3143 | * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip | |||
| 3144 | * (not for PCI -- automatically detected) | |||
| 3145 | * "ide0=qd6580" : probe/support qd6580 interface | |||
| 3146 | * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) | |||
| 3147 | * "ide0=umc8672" : probe/support umc8672 chipsets | |||
| 3148 | */ | |||
| 3149 | void ide_setup (char *s) | |||
| 3150 | { | |||
| 3151 | int i, vals[3]; | |||
| 3152 | ide_hwif_t *hwif; | |||
| 3153 | ide_drive_t *drive; | |||
| 3154 | unsigned int hw, unit; | |||
| 3155 | const char max_drive = 'a' + ((MAX_HWIFS4 * MAX_DRIVES2) - 1); | |||
| 3156 | const char max_hwif = '0' + (MAX_HWIFS4 - 1); | |||
| 3157 | ||||
| 3158 | printk("ide_setup: %s", s); | |||
| 3159 | init_ide_data (); | |||
| 3160 | ||||
| 3161 | /* | |||
| 3162 | * Look for drive options: "hdx=" | |||
| 3163 | */ | |||
| 3164 | if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { | |||
| 3165 | const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", | |||
| 3166 | "serialize", "autotune", "noautotune", | |||
| 3167 | "slow", "ide-scsi", NULL((void *) 0)}; | |||
| 3168 | unit = s[2] - 'a'; | |||
| 3169 | hw = unit / MAX_DRIVES2; | |||
| 3170 | unit = unit % MAX_DRIVES2; | |||
| 3171 | hwif = &ide_hwifs[hw]; | |||
| 3172 | drive = &hwif->drives[unit]; | |||
| 3173 | switch (match_parm(&s[3], hd_words, vals, 3)) { | |||
| 3174 | case -1: /* "none" */ | |||
| 3175 | drive->nobios = 1; /* drop into "noprobe" */ | |||
| 3176 | case -2: /* "noprobe" */ | |||
| 3177 | drive->noprobe = 1; | |||
| 3178 | goto done; | |||
| 3179 | case -3: /* "nowerr" */ | |||
| 3180 | drive->bad_wstat = BAD_R_STAT(0x80 | 0x01); | |||
| 3181 | hwif->noprobe = 0; | |||
| 3182 | goto done; | |||
| 3183 | case -4: /* "cdrom" */ | |||
| 3184 | drive->present = 1; | |||
| 3185 | drive->media = ide_cdrom; | |||
| 3186 | hwif->noprobe = 0; | |||
| 3187 | goto done; | |||
| 3188 | case -5: /* "serialize" */ | |||
| 3189 | printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); | |||
| 3190 | goto do_serialize; | |||
| 3191 | case -6: /* "autotune" */ | |||
| 3192 | drive->autotune = 1; | |||
| 3193 | goto done; | |||
| 3194 | case -7: /* "noautotune" */ | |||
| 3195 | drive->autotune = 2; | |||
| 3196 | goto done; | |||
| 3197 | case -8: /* "slow" */ | |||
| 3198 | drive->slow = 1; | |||
| 3199 | goto done; | |||
| 3200 | case -9: /* "ide-scsi" */ | |||
| 3201 | drive->ide_scsi = 1; | |||
| 3202 | goto done; | |||
| 3203 | case 3: /* cyl,head,sect */ | |||
| 3204 | drive->media = ide_disk; | |||
| 3205 | drive->cyl = drive->bios_cyl = vals[0]; | |||
| 3206 | drive->head = drive->bios_head = vals[1]; | |||
| 3207 | drive->sect = drive->bios_sect = vals[2]; | |||
| 3208 | drive->present = 1; | |||
| 3209 | drive->forced_geom = 1; | |||
| 3210 | hwif->noprobe = 0; | |||
| 3211 | goto done; | |||
| 3212 | default: | |||
| 3213 | goto bad_option; | |||
| 3214 | } | |||
| 3215 | } | |||
| 3216 | ||||
| 3217 | if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') | |||
| 3218 | goto bad_option; | |||
| 3219 | /* | |||
| 3220 | * Look for bus speed option: "idebus=" | |||
| 3221 | */ | |||
| 3222 | if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') { | |||
| 3223 | if (match_parm(&s[6], NULL((void *) 0), vals, 1) != 1) | |||
| 3224 | goto bad_option; | |||
| 3225 | if (vals[0] >= 20 && vals[0] <= 66) | |||
| 3226 | idebus_parameter = vals[0]; | |||
| 3227 | else | |||
| 3228 | printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); | |||
| 3229 | goto done; | |||
| 3230 | } | |||
| 3231 | /* | |||
| 3232 | * Look for interface options: "idex=" | |||
| 3233 | */ | |||
| 3234 | if (s[3] >= '0' && s[3] <= max_hwif) { | |||
| 3235 | /* | |||
| 3236 | * Be VERY CAREFUL changing this: note hardcoded indexes below | |||
| 3237 | */ | |||
| 3238 | const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", | |||
| 3239 | "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL((void *) 0)}; | |||
| 3240 | hw = s[3] - '0'; | |||
| 3241 | hwif = &ide_hwifs[hw]; | |||
| 3242 | i = match_parm(&s[4], ide_words, vals, 3); | |||
| 3243 | ||||
| 3244 | /* | |||
| 3245 | * Cryptic check to ensure chipset not already set for hwif: | |||
| 3246 | */ | |||
| 3247 | if (i > 0 || i <= -5) { | |||
| 3248 | if (hwif->chipset != ide_unknown) | |||
| 3249 | goto bad_option; | |||
| 3250 | if (i <= -5) { | |||
| 3251 | if (ide_hwifs[1].chipset != ide_unknown) | |||
| 3252 | goto bad_option; | |||
| 3253 | /* | |||
| 3254 | * Interface keywords work only for ide0: | |||
| 3255 | */ | |||
| 3256 | if (hw != 0) | |||
| 3257 | goto bad_hwif; | |||
| 3258 | } | |||
| 3259 | } | |||
| 3260 | ||||
| 3261 | switch (i) { | |||
| 3262 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 3263 | case -11: /* "dc4030" */ | |||
| 3264 | { | |||
| 3265 | setup_dc4030(hwif); | |||
| 3266 | goto done; | |||
| 3267 | } | |||
| 3268 | #endif /* CONFIG_BLK_DEV_PROMISE */ | |||
| 3269 | #ifdef CONFIG_BLK_DEV_ALI14XX | |||
| 3270 | case -10: /* "ali14xx" */ | |||
| 3271 | { | |||
| 3272 | extern void init_ali14xx (void); | |||
| 3273 | init_ali14xx(); | |||
| 3274 | goto done; | |||
| 3275 | } | |||
| 3276 | #endif /* CONFIG_BLK_DEV_ALI14XX */ | |||
| 3277 | #ifdef CONFIG_BLK_DEV_UMC8672 | |||
| 3278 | case -9: /* "umc8672" */ | |||
| 3279 | { | |||
| 3280 | extern void init_umc8672 (void); | |||
| 3281 | init_umc8672(); | |||
| 3282 | goto done; | |||
| 3283 | } | |||
| 3284 | #endif /* CONFIG_BLK_DEV_UMC8672 */ | |||
| 3285 | #ifdef CONFIG_BLK_DEV_DTC2278 | |||
| 3286 | case -8: /* "dtc2278" */ | |||
| 3287 | { | |||
| 3288 | extern void init_dtc2278 (void); | |||
| 3289 | init_dtc2278(); | |||
| 3290 | goto done; | |||
| 3291 | } | |||
| 3292 | #endif /* CONFIG_BLK_DEV_DTC2278 */ | |||
| 3293 | #ifdef CONFIG_BLK_DEV_CMD640 | |||
| 3294 | case -7: /* "cmd640_vlb" */ | |||
| 3295 | { | |||
| 3296 | extern int cmd640_vlb; /* flag for cmd640.c */ | |||
| 3297 | cmd640_vlb = 1; | |||
| 3298 | goto done; | |||
| 3299 | } | |||
| 3300 | #endif /* CONFIG_BLK_DEV_CMD640 */ | |||
| 3301 | #ifdef CONFIG_BLK_DEV_HT6560B | |||
| 3302 | case -6: /* "ht6560b" */ | |||
| 3303 | { | |||
| 3304 | extern void init_ht6560b (void); | |||
| 3305 | init_ht6560b(); | |||
| 3306 | goto done; | |||
| 3307 | } | |||
| 3308 | #endif /* CONFIG_BLK_DEV_HT6560B */ | |||
| 3309 | #if CONFIG_BLK_DEV_QD6580 | |||
| 3310 | case -5: /* "qd6580" (has secondary i/f) */ | |||
| 3311 | { | |||
| 3312 | extern void init_qd6580 (void); | |||
| 3313 | init_qd6580(); | |||
| 3314 | goto done; | |||
| 3315 | } | |||
| 3316 | #endif /* CONFIG_BLK_DEV_QD6580 */ | |||
| 3317 | case -4: /* "noautotune" */ | |||
| 3318 | hwif->drives[0].autotune = 2; | |||
| 3319 | hwif->drives[1].autotune = 2; | |||
| 3320 | goto done; | |||
| 3321 | case -3: /* "autotune" */ | |||
| 3322 | hwif->drives[0].autotune = 1; | |||
| 3323 | hwif->drives[1].autotune = 1; | |||
| 3324 | goto done; | |||
| 3325 | case -2: /* "serialize" */ | |||
| 3326 | do_serialize: | |||
| 3327 | ide_hwifs[hw].serialized = 1; /* serialize */ | |||
| 3328 | ide_hwifs[hw^1].serialized = 1; /* with mate */ | |||
| 3329 | goto done; | |||
| 3330 | ||||
| 3331 | case -1: /* "noprobe" */ | |||
| 3332 | hwif->noprobe = 1; | |||
| 3333 | goto done; | |||
| 3334 | ||||
| 3335 | case 1: /* base */ | |||
| 3336 | vals[1] = vals[0] + 0x206; /* default ctl */ | |||
| 3337 | case 2: /* base,ctl */ | |||
| 3338 | vals[2] = 0; /* default irq = probe for it */ | |||
| 3339 | case 3: /* base,ctl,irq */ | |||
| 3340 | hwif->io_base = vals[0]; | |||
| 3341 | hwif->ctl_port = vals[1]; | |||
| 3342 | hwif->irq = vals[2]; | |||
| 3343 | hwif->noprobe = 0; | |||
| 3344 | hwif->chipset = ide_generic; | |||
| 3345 | goto done; | |||
| 3346 | ||||
| 3347 | case 0: goto bad_option; | |||
| 3348 | default: | |||
| 3349 | printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); | |||
| 3350 | return; | |||
| 3351 | } | |||
| 3352 | } | |||
| 3353 | bad_option: | |||
| 3354 | printk(" -- BAD OPTION\n"); | |||
| 3355 | return; | |||
| 3356 | bad_hwif: | |||
| 3357 | printk("-- NOT SUPPORTED ON ide%d", hw); | |||
| 3358 | done: | |||
| 3359 | printk("\n"); | |||
| 3360 | } | |||
| 3361 | ||||
| 3362 | /* | |||
| 3363 | * This routine is called from the partition-table code in genhd.c | |||
| 3364 | * to "convert" a drive to a logical geometry with fewer than 1024 cyls. | |||
| 3365 | * | |||
| 3366 | * The second parameter, "xparm", determines exactly how the translation | |||
| 3367 | * will be handled: | |||
| 3368 | * 0 = convert to CHS with fewer than 1024 cyls | |||
| 3369 | * using the same method as Ontrack DiskManager. | |||
| 3370 | * 1 = same as "0", plus offset everything by 63 sectors. | |||
| 3371 | * -1 = similar to "0", plus redirect sector 0 to sector 1. | |||
| 3372 | * >1 = convert to a CHS geometry with "xparm" heads. | |||
| 3373 | * | |||
| 3374 | * Returns 0 if the translation was not possible, if the device was not | |||
| 3375 | * an IDE disk drive, or if a geometry was "forced" on the commandline. | |||
| 3376 | * Returns 1 if the geometry translation was successful. | |||
| 3377 | */ | |||
| 3378 | ||||
| 3379 | int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg) | |||
| 3380 | { | |||
| 3381 | ide_drive_t *drive; | |||
| 3382 | static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0}; | |||
| 3383 | const byte *heads = head_vals; | |||
| 3384 | unsigned long tracks; | |||
| 3385 | ||||
| 3386 | drive = get_info_ptr(i_rdev); | |||
| 3387 | if (!drive) | |||
| 3388 | return 0; | |||
| 3389 | ||||
| 3390 | if (drive->forced_geom) | |||
| 3391 | return 0; | |||
| 3392 | ||||
| 3393 | if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) | |||
| 3394 | return 0; /* we already have a translation */ | |||
| 3395 | ||||
| 3396 | printk("%s ", msg); | |||
| 3397 | ||||
| 3398 | if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) { | |||
| 3399 | return 0; /* small disk: no translation needed */ | |||
| 3400 | } | |||
| 3401 | ||||
| 3402 | if (drive->id) { | |||
| 3403 | drive->cyl = drive->id->cyls; | |||
| 3404 | drive->head = drive->id->heads; | |||
| 3405 | drive->sect = drive->id->sectors; | |||
| 3406 | } | |||
| 3407 | drive->bios_cyl = drive->cyl; | |||
| 3408 | drive->bios_head = drive->head; | |||
| 3409 | drive->bios_sect = drive->sect; | |||
| 3410 | drive->special.b.set_geometry = 1; | |||
| 3411 | ||||
| 3412 | tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63; | |||
| 3413 | drive->bios_sect = 63; | |||
| 3414 | if (xparm > 1) { | |||
| 3415 | drive->bios_head = xparm; | |||
| 3416 | drive->bios_cyl = tracks / drive->bios_head; | |||
| 3417 | } else { | |||
| 3418 | while (drive->bios_cyl >= 1024) { | |||
| 3419 | drive->bios_head = *heads; | |||
| 3420 | drive->bios_cyl = tracks / drive->bios_head; | |||
| 3421 | if (0 == *++heads) | |||
| 3422 | break; | |||
| 3423 | } | |||
| 3424 | #if FAKE_FDISK_FOR_EZDRIVE1 | |||
| 3425 | if (xparm == -1) { | |||
| 3426 | drive->remap_0_to_1 = 1; | |||
| 3427 | msg = "0->1"; | |||
| 3428 | } else | |||
| 3429 | #endif /* FAKE_FDISK_FOR_EZDRIVE */ | |||
| 3430 | if (xparm == 1) { | |||
| 3431 | drive->sect0 = 63; | |||
| 3432 | drive->bios_cyl = (tracks - 1) / drive->bios_head; | |||
| 3433 | msg = "+63"; | |||
| 3434 | } | |||
| 3435 | printk("[remap %s] ", msg); | |||
| 3436 | } | |||
| 3437 | drive->part[0].nr_sects = current_capacity(drive); | |||
| 3438 | printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect); | |||
| 3439 | return 1; | |||
| 3440 | } | |||
| 3441 | ||||
| 3442 | #if MAX_HWIFS4 > 1 | |||
| 3443 | /* | |||
| 3444 | * save_match() is used to simplify logic in init_irq() below. | |||
| 3445 | * | |||
| 3446 | * A loophole here is that we may not know about a particular | |||
| 3447 | * hwif's irq until after that hwif is actually probed/initialized.. | |||
| 3448 | * This could be a problem for the case where an hwif is on a | |||
| 3449 | * dual interface that requires serialization (eg. cmd640) and another | |||
| 3450 | * hwif using one of the same irqs is initialized beforehand. | |||
| 3451 | * | |||
| 3452 | * This routine detects and reports such situations, but does not fix them. | |||
| 3453 | */ | |||
| 3454 | static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) | |||
| 3455 | { | |||
| 3456 | ide_hwif_t *m = *match; | |||
| 3457 | ||||
| 3458 | if (m && m->hwgroup && m->hwgroup != new->hwgroup) { | |||
| 3459 | if (!new->hwgroup) | |||
| 3460 | return; | |||
| 3461 | printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name); | |||
| 3462 | } | |||
| 3463 | if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ | |||
| 3464 | *match = new; | |||
| 3465 | } | |||
| 3466 | #endif /* MAX_HWIFS > 1 */ | |||
| 3467 | ||||
| 3468 | /* | |||
| 3469 | * This routine sets up the irq for an ide interface, and creates a new | |||
| 3470 | * hwgroup for the irq/hwif if none was previously assigned. | |||
| 3471 | * | |||
| 3472 | * Much of the code is for correctly detecting/handling irq sharing | |||
| 3473 | * and irq serialization situations. This is somewhat complex because | |||
| 3474 | * it handles static as well as dynamic (PCMCIA) IDE interfaces. | |||
| 3475 | * | |||
| 3476 | * The SA_INTERRUPT in sa_flags means ide_intr() is always entered with | |||
| 3477 | * interrupts completely disabled. This can be bad for interrupt latency, | |||
| 3478 | * but anything else has led to problems on some machines. We re-enable | |||
| 3479 | * interrupts as much as we can safely do in most places. | |||
| 3480 | */ | |||
| 3481 | static int init_irq (ide_hwif_t *hwif) | |||
| 3482 | { | |||
| 3483 | unsigned long flags; | |||
| 3484 | #if MAX_HWIFS4 > 1 | |||
| 3485 | unsigned int index; | |||
| 3486 | #endif /* MAX_HWIFS > 1 */ | |||
| 3487 | ide_hwgroup_t *hwgroup; | |||
| 3488 | ide_hwif_t *match = NULL((void *) 0); | |||
| 3489 | ||||
| 3490 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 3491 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 3492 | ||||
| 3493 | hwif->hwgroup = NULL((void *) 0); | |||
| 3494 | #if MAX_HWIFS4 > 1 | |||
| 3495 | /* | |||
| 3496 | * Group up with any other hwifs that share our irq(s). | |||
| 3497 | */ | |||
| 3498 | for (index = 0; index < MAX_HWIFS4; index++) { | |||
| 3499 | ide_hwif_t *h = &ide_hwifs[index]; | |||
| 3500 | if (h->hwgroup) { /* scan only initialized hwif's */ | |||
| 3501 | if (hwif->irq == h->irq) { | |||
| 3502 | hwif->sharing_irq = h->sharing_irq = 1; | |||
| 3503 | save_match(hwif, h, &match); | |||
| 3504 | } | |||
| 3505 | if (hwif->serialized) { | |||
| 3506 | ide_hwif_t *mate = &ide_hwifs[hwif->index^1]; | |||
| 3507 | if (index == mate->index || h->irq == mate->irq) | |||
| 3508 | save_match(hwif, h, &match); | |||
| 3509 | } | |||
| 3510 | if (h->serialized) { | |||
| 3511 | ide_hwif_t *mate = &ide_hwifs[h->index^1]; | |||
| 3512 | if (hwif->irq == mate->irq) | |||
| 3513 | save_match(hwif, h, &match); | |||
| 3514 | } | |||
| 3515 | } | |||
| 3516 | } | |||
| 3517 | #endif /* MAX_HWIFS > 1 */ | |||
| 3518 | /* | |||
| 3519 | * If we are still without a hwgroup, then form a new one | |||
| 3520 | */ | |||
| 3521 | if (match) { | |||
| 3522 | hwgroup = match->hwgroup; | |||
| 3523 | } else { | |||
| 3524 | hwgroup = kmalloclinux_kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL0x03); | |||
| 3525 | hwgroup->hwif = hwgroup->next_hwif = hwif->next = hwif; | |||
| 3526 | hwgroup->rq = NULL((void *) 0); | |||
| 3527 | hwgroup->handler = NULL((void *) 0); | |||
| 3528 | if (hwif->drives[0].present) | |||
| 3529 | hwgroup->drive = &hwif->drives[0]; | |||
| 3530 | else | |||
| 3531 | hwgroup->drive = &hwif->drives[1]; | |||
| 3532 | hwgroup->poll_timeout = 0; | |||
| 3533 | hwgroup->active = 0; | |||
| 3534 | init_timer(&hwgroup->timer); | |||
| 3535 | hwgroup->timer.function = &timer_expiry; | |||
| 3536 | hwgroup->timer.data = (unsigned long) hwgroup; | |||
| 3537 | } | |||
| 3538 | ||||
| 3539 | /* | |||
| 3540 | * Allocate the irq, if not already obtained for another hwif | |||
| 3541 | */ | |||
| 3542 | if (!match || match->irq != hwif->irq) { | |||
| 3543 | if (request_irq(hwif->irq, ide_intr, SA_INTERRUPT0x20000000, hwif->name, hwgroup)) { | |||
| 3544 | if (!match) | |||
| 3545 | kfreelinux_kfree(hwgroup); | |||
| 3546 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3547 | return 1; | |||
| 3548 | } | |||
| 3549 | } | |||
| 3550 | ||||
| 3551 | /* | |||
| 3552 | * Everything is okay, so link us into the hwgroup | |||
| 3553 | */ | |||
| 3554 | hwif->hwgroup = hwgroup; | |||
| 3555 | hwif->next = hwgroup->hwif->next; | |||
| 3556 | hwgroup->hwif->next = hwif; | |||
| 3557 | ||||
| 3558 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); /* safe now that hwif->hwgroup is set up */ | |||
| 3559 | ||||
| 3560 | printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, | |||
| 3561 | hwif->io_base, hwif->io_base+7, hwif->ctl_port, hwif->irq); | |||
| 3562 | if (match) | |||
| 3563 | printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name); | |||
| 3564 | printk("\n"); | |||
| 3565 | return 0; | |||
| 3566 | } | |||
| 3567 | ||||
| 3568 | static struct file_operations ide_fops = { | |||
| 3569 | NULL((void *) 0), /* lseek - default */ | |||
| 3570 | block_read, /* read - general block-dev read */ | |||
| 3571 | block_write, /* write - general block-dev write */ | |||
| 3572 | NULL((void *) 0), /* readdir - bad */ | |||
| 3573 | NULL((void *) 0), /* select */ | |||
| 3574 | ide_ioctl, /* ioctl */ | |||
| 3575 | NULL((void *) 0), /* mmap */ | |||
| 3576 | ide_open, /* open */ | |||
| 3577 | ide_release, /* release */ | |||
| 3578 | block_fsync /* fsync */ | |||
| 3579 | ,NULL((void *) 0), /* fasync */ | |||
| 3580 | ide_check_media_change, /* check_media_change */ | |||
| 3581 | revalidate_disk /* revalidate */ | |||
| 3582 | }; | |||
| 3583 | ||||
| 3584 | #ifdef CONFIG_PCI1 | |||
| 3585 | #if defined(CONFIG_BLK_DEV_RZ10001) || defined(CONFIG_BLK_DEV_TRITON1) | |||
| 3586 | ||||
| 3587 | typedef void (ide_pci_init_proc_t)(byte, byte); | |||
| 3588 | ||||
| 3589 | /* | |||
| 3590 | * ide_probe_pci() scans PCI for a specific vendor/device function, | |||
| 3591 | * and invokes the supplied init routine for each instance detected. | |||
| 3592 | */ | |||
| 3593 | static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj) | |||
| 3594 | { | |||
| 3595 | unsigned long flags; | |||
| 3596 | unsigned index; | |||
| 3597 | byte fn, bus; | |||
| 3598 | ||||
| 3599 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 3600 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 3601 | for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) { | |||
| 3602 | init (bus, fn + func_adj); | |||
| 3603 | } | |||
| 3604 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3605 | } | |||
| 3606 | ||||
| 3607 | #endif /* defined(CONFIG_BLK_DEV_RZ1000) || defined(CONFIG_BLK_DEV_TRITON) */ | |||
| 3608 | ||||
| 3609 | static void ide_probe_promise_20246(void) | |||
| 3610 | { | |||
| 3611 | byte fn, bus; | |||
| 3612 | unsigned short io[6], count = 0; | |||
| 3613 | unsigned int reg, tmp, i; | |||
| 3614 | ide_hwif_t *hwif; | |||
| 3615 | ||||
| 3616 | memset(io, 0, 6 * sizeof(unsigned short))(__builtin_constant_p(0) ? (__builtin_constant_p((6 * sizeof( unsigned short))) ? __constant_c_and_count_memset(((io)),((0x01010101UL *(unsigned char)(0))),((6 * sizeof(unsigned short)))) : __constant_c_memset (((io)),((0x01010101UL*(unsigned char)(0))),((6 * sizeof(unsigned short))))) : (__builtin_constant_p((6 * sizeof(unsigned short ))) ? __memset_generic((((io))),(((0))),(((6 * sizeof(unsigned short))))) : __memset_generic(((io)),((0)),((6 * sizeof(unsigned short)))))); | |||
| 3617 | if (pcibios_find_device(PCI_VENDOR_ID_PROMISE0x105a, PCI_DEVICE_ID_PROMISE_202460x4d33, 0, &bus, &fn)) | |||
| 3618 | return; | |||
| 3619 | printk("ide: Promise Technology IDE Ultra-DMA 33 on PCI bus %d function %d\n", bus, fn); | |||
| 3620 | for (reg = PCI_BASE_ADDRESS_00x10; reg <= PCI_BASE_ADDRESS_50x24; reg += 4) { | |||
| 3621 | pcibios_read_config_dword(bus, fn, reg, &tmp); | |||
| 3622 | if (tmp & PCI_BASE_ADDRESS_SPACE_IO0x01) | |||
| 3623 | io[count++] = tmp & PCI_BASE_ADDRESS_IO_MASK(~0x03); | |||
| 3624 | } | |||
| 3625 | for (i = 2; i < 4; i++) { | |||
| 3626 | hwif = ide_hwifs + i; | |||
| 3627 | if (hwif->chipset == ide_generic) { | |||
| 3628 | printk("ide%d: overridden with command line parameter\n", i); | |||
| 3629 | return; | |||
| 3630 | } | |||
| 3631 | tmp = (i - 2) * 2; | |||
| 3632 | if (!io[tmp] || !io[tmp + 1]) { | |||
| 3633 | printk("ide%d: invalid port address %x, %x -- aborting\n", i, io[tmp], io[tmp + 1]); | |||
| 3634 | return; | |||
| 3635 | } | |||
| 3636 | hwif->io_base = io[tmp]; | |||
| 3637 | hwif->ctl_port = io[tmp + 1] + 2; | |||
| 3638 | hwif->noprobe = 0; | |||
| 3639 | } | |||
| 3640 | } | |||
| 3641 | ||||
| 3642 | #endif /* CONFIG_PCI */ | |||
| 3643 | ||||
| 3644 | /* | |||
| 3645 | * ide_init_pci() finds/initializes "known" PCI IDE interfaces | |||
| 3646 | * | |||
| 3647 | * This routine should ideally be using pcibios_find_class() to find | |||
| 3648 | * all IDE interfaces, but that function causes some systems to "go weird". | |||
| 3649 | */ | |||
| 3650 | static void probe_for_hwifs (void) | |||
| 3651 | { | |||
| 3652 | #ifdef CONFIG_PCI1 | |||
| 3653 | /* | |||
| 3654 | * Find/initialize PCI IDE interfaces | |||
| 3655 | */ | |||
| 3656 | if (pcibios_present()) { | |||
| 3657 | #ifdef CONFIG_BLK_DEV_RZ10001 | |||
| 3658 | ide_pci_init_proc_t init_rz1000; | |||
| 3659 | ide_probe_pci (PCI_VENDOR_ID_PCTECH0x1042, PCI_DEVICE_ID_PCTECH_RZ10000x1000, &init_rz1000, 0); | |||
| 3660 | ide_probe_pci (PCI_VENDOR_ID_PCTECH0x1042, PCI_DEVICE_ID_PCTECH_RZ10010x1001, &init_rz1000, 0); | |||
| 3661 | #endif /* CONFIG_BLK_DEV_RZ1000 */ | |||
| 3662 | #ifdef CONFIG_BLK_DEV_TRITON1 | |||
| 3663 | /* | |||
| 3664 | * Apparently the BIOS32 services on Intel motherboards are | |||
| 3665 | * buggy and won't find the PCI_DEVICE_ID_INTEL_82371_1 for us. | |||
| 3666 | * So instead, we search for PCI_DEVICE_ID_INTEL_82371_0, | |||
| 3667 | * and then add 1. | |||
| 3668 | */ | |||
| 3669 | ide_probe_pci (PCI_VENDOR_ID_INTEL0x8086, PCI_DEVICE_ID_INTEL_82371_00x122e, &ide_init_triton, 1); | |||
| 3670 | ide_probe_pci (PCI_VENDOR_ID_INTEL0x8086, PCI_DEVICE_ID_INTEL_82371SB_10x7010, &ide_init_triton, 0); | |||
| 3671 | ide_probe_pci (PCI_VENDOR_ID_INTEL0x8086, PCI_DEVICE_ID_INTEL_82371AB0x7111, &ide_init_triton, 0); | |||
| 3672 | ide_probe_pci (PCI_VENDOR_ID_SI0x1039, PCI_DEVICE_ID_SI_55130x5513, &ide_init_triton, 0); | |||
| 3673 | ide_probe_pci (PCI_VENDOR_ID_VIA0x1106, PCI_DEVICE_ID_VIA_82C586_10x0571, &ide_init_triton, 0); | |||
| 3674 | ide_probe_pci (PCI_VENDOR_ID_AL0x10b9, PCI_DEVICE_ID_AL_M52290x5229, &ide_init_triton, 0); | |||
| 3675 | #endif /* CONFIG_BLK_DEV_TRITON */ | |||
| 3676 | ide_probe_promise_20246(); | |||
| 3677 | } | |||
| 3678 | #endif /* CONFIG_PCI */ | |||
| 3679 | #ifdef CONFIG_BLK_DEV_CMD640 | |||
| 3680 | { | |||
| 3681 | extern void ide_probe_for_cmd640x (void); | |||
| 3682 | ide_probe_for_cmd640x(); | |||
| 3683 | } | |||
| 3684 | #endif | |||
| 3685 | #ifdef CONFIG_BLK_DEV_PROMISE | |||
| 3686 | init_dc4030(); | |||
| 3687 | #endif | |||
| 3688 | ahci_probe_pci(); | |||
| 3689 | } | |||
| 3690 | ||||
| 3691 | static int hwif_init (int h) | |||
| 3692 | { | |||
| 3693 | ide_hwif_t *hwif = &ide_hwifs[h]; | |||
| 3694 | void (*rfn)(void); | |||
| 3695 | ||||
| 3696 | if (!hwif->present) | |||
| 3697 | return 0; | |||
| 3698 | if (!hwif->irq) { | |||
| 3699 | if (!(hwif->irq = default_irqs[h])) { | |||
| 3700 | printk("%s: DISABLED, NO IRQ\n", hwif->name); | |||
| 3701 | return (hwif->present = 0); | |||
| 3702 | } | |||
| 3703 | } | |||
| 3704 | #ifdef CONFIG_BLK_DEV_HD | |||
| 3705 | if (hwif->irq == HD_IRQ14 && hwif->io_base != HD_DATA0x1f0) { | |||
| 3706 | printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); | |||
| 3707 | return (hwif->present = 0); | |||
| 3708 | } | |||
| 3709 | #endif /* CONFIG_BLK_DEV_HD */ | |||
| 3710 | ||||
| 3711 | hwif->present = 0; /* we set it back to 1 if all is ok below */ | |||
| 3712 | switch (hwif->major) { | |||
| 3713 | case IDE0_MAJOR3: rfn = &do_ide0_request; break; | |||
| 3714 | #if MAX_HWIFS4 > 1 | |||
| 3715 | case IDE1_MAJOR22: rfn = &do_ide1_request; break; | |||
| 3716 | #endif | |||
| 3717 | #if MAX_HWIFS4 > 2 | |||
| 3718 | case IDE2_MAJOR33: rfn = &do_ide2_request; break; | |||
| 3719 | #endif | |||
| 3720 | #if MAX_HWIFS4 > 3 | |||
| 3721 | case IDE3_MAJOR34: rfn = &do_ide3_request; break; | |||
| 3722 | #endif | |||
| 3723 | default: | |||
| 3724 | printk("%s: request_fn NOT DEFINED\n", hwif->name); | |||
| 3725 | return (hwif->present = 0); | |||
| 3726 | } | |||
| 3727 | if (register_blkdev (hwif->major, hwif->name, &ide_fops)) { | |||
| 3728 | printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); | |||
| 3729 | } else if (init_irq (hwif)) { | |||
| 3730 | printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq); | |||
| 3731 | (void) unregister_blkdev (hwif->major, hwif->name); | |||
| 3732 | } else { | |||
| 3733 | init_gendisk(hwif); | |||
| 3734 | blk_dev[hwif->major].request_fn = rfn; | |||
| 3735 | read_ahead[hwif->major] = 8; /* (4kB) */ | |||
| 3736 | hwif->present = 1; /* success */ | |||
| 3737 | } | |||
| 3738 | return hwif->present; | |||
| 3739 | } | |||
| 3740 | ||||
| 3741 | /* | |||
| 3742 | * This is gets invoked once during initialization, to set *everything* up | |||
| 3743 | */ | |||
| 3744 | int ide_init (void) | |||
| 3745 | { | |||
| 3746 | int index; | |||
| 3747 | ||||
| 3748 | init_ide_data (); | |||
| 3749 | /* | |||
| 3750 | * Probe for special "known" interface chipsets | |||
| 3751 | */ | |||
| 3752 | probe_for_hwifs (); | |||
| 3753 | ||||
| 3754 | /* | |||
| 3755 | * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports | |||
| 3756 | */ | |||
| 3757 | for (index = 0; index < MAX_HWIFS4; ++index) | |||
| 3758 | probe_hwif (&ide_hwifs[index]); | |||
| 3759 | for (index = 0; index < MAX_HWIFS4; ++index) | |||
| 3760 | hwif_init (index); | |||
| 3761 | ||||
| 3762 | #ifdef CONFIG_BLK_DEV_IDETAPE | |||
| 3763 | idetape_register_chrdev(); /* Register character device interface to the ide tape */ | |||
| 3764 | #endif /* CONFIG_BLK_DEV_IDETAPE */ | |||
| 3765 | ||||
| 3766 | return 0; | |||
| 3767 | } | |||
| 3768 | ||||
| 3769 | #ifdef CONFIG_BLK_DEV_IDE_PCMCIA | |||
| 3770 | int ide_register(int io_base, int ctl_port, int irq) | |||
| 3771 | { | |||
| 3772 | int index, i, rc = -1; | |||
| 3773 | ide_hwif_t *hwif; | |||
| 3774 | ide_drive_t *drive; | |||
| 3775 | unsigned long flags; | |||
| 3776 | ||||
| 3777 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 3778 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 3779 | for (index = 0; index < MAX_HWIFS4; ++index) { | |||
| 3780 | hwif = &ide_hwifs[index]; | |||
| 3781 | if (hwif->present) { | |||
| 3782 | if (hwif->io_base == io_base || hwif->ctl_port == ctl_port) | |||
| 3783 | break; /* this ide port already exists */ | |||
| 3784 | } else { | |||
| 3785 | hwif->io_base = io_base; | |||
| 3786 | hwif->ctl_port = ctl_port; | |||
| 3787 | hwif->irq = irq; | |||
| 3788 | hwif->noprobe = 0; | |||
| 3789 | probe_hwif(hwif); | |||
| 3790 | if (!hwif_init(index)) | |||
| 3791 | break; | |||
| 3792 | for (i = 0; i < hwif->gd->nr_real; i++) { | |||
| 3793 | drive = &hwif->drives[i]; | |||
| 3794 | revalidate_disk(MKDEV(hwif->major, i<<PARTN_BITS)(((hwif->major) << 8) | (i<<6))); | |||
| 3795 | #ifdef CONFIG_BLK_DEV_IDECD1 | |||
| 3796 | if (drive->present && drive->media == ide_cdrom) | |||
| 3797 | ide_cdrom_setup(drive); | |||
| 3798 | #endif /* CONFIG_BLK_DEV_IDECD */ | |||
| 3799 | } | |||
| 3800 | rc = index; | |||
| 3801 | break; | |||
| 3802 | } | |||
| 3803 | } | |||
| 3804 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3805 | return rc; | |||
| 3806 | } | |||
| 3807 | ||||
| 3808 | void ide_unregister (unsigned int index) | |||
| 3809 | { | |||
| 3810 | struct gendisk *gd, **gdp; | |||
| 3811 | ide_hwif_t *hwif, *g; | |||
| 3812 | ide_hwgroup_t *hwgroup; | |||
| 3813 | int irq_count = 0; | |||
| 3814 | unsigned long flags; | |||
| 3815 | ||||
| 3816 | if (index >= MAX_HWIFS4) | |||
| 3817 | return; | |||
| 3818 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); | |||
| 3819 | cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 3820 | hwif = &ide_hwifs[index]; | |||
| 3821 | if (!hwif->present || hwif->drives[0].busy || hwif->drives[1].busy) { | |||
| 3822 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3823 | return; | |||
| 3824 | } | |||
| 3825 | hwif->present = 0; | |||
| 3826 | hwgroup = hwif->hwgroup; | |||
| 3827 | ||||
| 3828 | /* | |||
| 3829 | * free the irq if we were the only hwif using it | |||
| 3830 | */ | |||
| 3831 | g = hwgroup->hwif; | |||
| 3832 | do { | |||
| 3833 | if (g->irq == hwif->irq) | |||
| 3834 | ++irq_count; | |||
| 3835 | g = g->next; | |||
| 3836 | } while (g != hwgroup->hwif); | |||
| 3837 | if (irq_count == 1) | |||
| 3838 | free_irq(hwif->irq, hwgroup); | |||
| 3839 | ||||
| 3840 | /* | |||
| 3841 | * Note that we only release the standard ports, | |||
| 3842 | * and do not even try to handle any extra ports | |||
| 3843 | * allocated for weird IDE interface chipsets. | |||
| 3844 | */ | |||
| 3845 | release_region(hwif->io_base, 8); | |||
| 3846 | release_region(hwif->ctl_port, 1); | |||
| 3847 | ||||
| 3848 | /* | |||
| 3849 | * Remove us from the hwgroup, and free | |||
| 3850 | * the hwgroup if we were the only member | |||
| 3851 | */ | |||
| 3852 | while (hwgroup->hwif->next != hwif) | |||
| 3853 | hwgroup->hwif = hwgroup->hwif->next; | |||
| 3854 | hwgroup->hwif->next = hwif->next; | |||
| 3855 | if (hwgroup->hwif == hwif) | |||
| 3856 | hwgroup->hwif = hwif->next; | |||
| 3857 | if (hwgroup->next_hwif == hwif) | |||
| 3858 | hwgroup->next_hwif = hwif->next; | |||
| 3859 | if (hwgroup->hwif == hwif) | |||
| 3860 | kfreelinux_kfree(hwgroup); | |||
| 3861 | ||||
| 3862 | /* | |||
| 3863 | * Remove us from the kernel's knowledge | |||
| 3864 | */ | |||
| 3865 | unregister_blkdev(hwif->major, hwif->name); | |||
| 3866 | kfreelinux_kfree(blksize_size[hwif->major]); | |||
| 3867 | blk_dev[hwif->major].request_fn = NULL((void *) 0); | |||
| 3868 | blksize_size[hwif->major] = NULL((void *) 0); | |||
| 3869 | for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) | |||
| 3870 | if (*gdp == hwif->gd) | |||
| 3871 | break; | |||
| 3872 | if (*gdp == NULL((void *) 0)) | |||
| 3873 | printk("gd not in disk chain!\n"); | |||
| 3874 | else { | |||
| 3875 | gd = *gdp; *gdp = gd->next; | |||
| 3876 | kfreelinux_kfree(gd->sizes); | |||
| 3877 | kfreelinux_kfree(gd->part); | |||
| 3878 | kfreelinux_kfree(gd); | |||
| 3879 | } | |||
| 3880 | init_hwif_data (index); /* restore hwif data to pristine status */ | |||
| 3881 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||
| 3882 | } | |||
| 3883 | #endif /* CONFIG_BLK_DEV_IDE_PCMCIA */ |