📄 ide.h
字号:
#ifndef _IDE_H#define _IDE_H/* * linux/drivers/block/ide.h * * Copyright (C) 1994-1998 Linus Torvalds & authors */#include <linux/config.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/hdreg.h>#include <linux/blkdev.h>#include <linux/proc_fs.h>#include <asm/ide.h>/* * This is the multiple IDE interface driver, as evolved from hd.c. * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15). * There can be up to two drives per interface, as per the ATA-2 spec. * * Primary i/f: ide0: major=3; (hda) minor=0; (hdb) minor=64 * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64 * Tertiary i/f: ide2: major=33; (hde) minor=0; (hdf) minor=64 * Quaternary i/f: ide3: major=34; (hdg) minor=0; (hdh) minor=64 *//****************************************************************************** * IDE driver configuration options (play with these as desired): * * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary */#undef REALLY_FAST_IO /* define if ide ports are perfect */#define INITIAL_MULT_COUNT 0 /* off=0; on=2,4,8,16,32, etc.. */#ifndef SUPPORT_SLOW_DATA_PORTS /* 1 to support slow data ports */#define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */#endif#ifndef SUPPORT_VLB_SYNC /* 1 to support weird 32-bit chips */#define SUPPORT_VLB_SYNC 1 /* 0 to reduce kernel size */#endif#ifndef DISK_RECOVERY_TIME /* off=0; on=access_delay_time */#define DISK_RECOVERY_TIME 0 /* for hardware that needs it */#endif#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */#define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */#endif#ifndef FAKE_FDISK_FOR_EZDRIVE /* 1 to help linux fdisk with EZDRIVE */#define FAKE_FDISK_FOR_EZDRIVE 1 /* 0 to reduce kernel size */#endif#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */#define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */#endif#ifdef CONFIG_BLK_DEV_CMD640#if 0 /* change to 1 when debugging cmd640 problems */void cmd640_dump_regs (void);#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */#endif#endif /* CONFIG_BLK_DEV_CMD640 *//* * IDE_DRIVE_CMD is used to implement many features of the hdparm utility */#define IDE_DRIVE_CMD 99 /* (magic) undef to reduce kernel size*//* * "No user-serviceable parts" beyond this point :) *****************************************************************************/typedef unsigned char byte; /* used everywhere *//* * Probably not wise to fiddle with these */#define ERROR_MAX 8 /* Max read/write errors per sector */#define ERROR_RESET 3 /* Reset controller every 4th retry */#define ERROR_RECAL 1 /* Recalibrate every 2nd retry *//* * Ensure that various configuration flags have compatible settings */#ifdef REALLY_SLOW_IO#undef REALLY_FAST_IO#endif#define HWIF(drive) ((ide_hwif_t *)((drive)->hwif))#define HWGROUP(drive) ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))/* * Definitions for accessing IDE controller registers */#define IDE_NR_PORTS (10)#define IDE_DATA_OFFSET (0)#define IDE_ERROR_OFFSET (1)#define IDE_NSECTOR_OFFSET (2)#define IDE_SECTOR_OFFSET (3)#define IDE_LCYL_OFFSET (4)#define IDE_HCYL_OFFSET (5)#define IDE_SELECT_OFFSET (6)#define IDE_STATUS_OFFSET (7)#define IDE_CONTROL_OFFSET (8)#define IDE_IRQ_OFFSET (9)#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET#define IDE_DATA_REG (HWIF(drive)->io_ports[IDE_DATA_OFFSET])#define IDE_ERROR_REG (HWIF(drive)->io_ports[IDE_ERROR_OFFSET])#define IDE_NSECTOR_REG (HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])#define IDE_SECTOR_REG (HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])#define IDE_LCYL_REG (HWIF(drive)->io_ports[IDE_LCYL_OFFSET])#define IDE_HCYL_REG (HWIF(drive)->io_ports[IDE_HCYL_OFFSET])#define IDE_SELECT_REG (HWIF(drive)->io_ports[IDE_SELECT_OFFSET])#define IDE_STATUS_REG (HWIF(drive)->io_ports[IDE_STATUS_OFFSET])#define IDE_CONTROL_REG (HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])#define IDE_IRQ_REG (HWIF(drive)->io_ports[IDE_IRQ_OFFSET])#define IDE_FEATURE_REG IDE_ERROR_REG#define IDE_COMMAND_REG IDE_STATUS_REG#define IDE_ALTSTATUS_REG IDE_CONTROL_REG#define IDE_IREASON_REG IDE_NSECTOR_REG#define IDE_BCOUNTL_REG IDE_LCYL_REG#define IDE_BCOUNTH_REG IDE_HCYL_REG#ifdef REALLY_FAST_IO#define OUT_BYTE(b,p) outb((b),(p))#define IN_BYTE(p) (byte)inb(p)#else#define OUT_BYTE(b,p) outb_p((b),(p))#define IN_BYTE(p) (byte)inb_p(p)#endif /* REALLY_FAST_IO */#define GET_ERR() IN_BYTE(IDE_ERROR_REG)#define GET_STAT() IN_BYTE(IDE_STATUS_REG)#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))#define BAD_R_STAT (BUSY_STAT | ERR_STAT)#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)#define BAD_STAT (BAD_R_STAT | DRQ_STAT)#define DRIVE_READY (READY_STAT | SEEK_STAT)#define DATA_READY (DRQ_STAT)/* * Some more useful definitions */#define IDE_MAJOR_NAME "ide" /* the same for all i/f; see also genhd.c */#define MAJOR_NAME IDE_MAJOR_NAME#define PARTN_BITS 6 /* number of minor dev bits for partitions */#define PARTN_MASK ((1<<PARTN_BITS)-1) /* a useful bit mask */#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */#define SECTOR_WORDS (512 / 4) /* number of 32bit words per sector */#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))#define IDE_MIN(a,b) ((a)<(b) ? (a):(b))#define IDE_MAX(a,b) ((a)>(b) ? (a):(b))/* * Timeouts for various operations: */#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */#ifdef CONFIG_APM#define WAIT_READY (5*HZ) /* 5sec - some laptops are very slow */#else#define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */#endif /* CONFIG_APM */#define WAIT_PIDENTIFY (10*HZ) /* 10sec - should be less than 3ms (?) if all ATAPI CD is closed at boot */#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */#define SELECT_DRIVE(hwif,drive) \{ \ if (hwif->selectproc) \ hwif->selectproc(drive); \ OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \}/* * Now for the data we need to maintain per-drive: ide_drive_t */#define ide_scsi 0x21#define ide_disk 0x20#define ide_optical 0x7#define ide_cdrom 0x5#define ide_tape 0x1#define ide_floppy 0x0typedef union { unsigned all : 8; /* all of the bits together */ struct { unsigned set_geometry : 1; /* respecify drive geometry */ unsigned recalibrate : 1; /* seek to cyl 0 */ unsigned set_multmode : 1; /* set multmode count */ unsigned set_tune : 1; /* tune interface for drive */ unsigned reserved : 4; /* unused */ } b; } special_t;typedef struct ide_drive_s { struct request *queue; /* request queue */ struct ide_drive_s *next; /* circular list of hwgroup drives */ unsigned long sleep; /* sleep until this time */ unsigned long service_start; /* time we started last request */ unsigned long service_time; /* service time of last request */ special_t special; /* special action flags */ byte keep_settings; /* restore settings after drive reset */ byte using_dma; /* disk is using dma for read/write */ byte waiting_for_dma; /* dma currently in progress */ byte unmask; /* flag: okay to unmask other irqs */ byte slow; /* flag: slow data port */ byte bswap; /* flag: byte swap data */ byte dsc_overlap; /* flag: DSC overlap */ byte nice1; /* flag: give potential excess bandwidth */ unsigned present : 1; /* drive is physically present */ unsigned noprobe : 1; /* from: hdx=noprobe */ unsigned busy : 1; /* currently doing revalidate_disk() */ unsigned removable : 1; /* 1 if need to do check_media_change */ unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */ unsigned no_unmask : 1; /* disallow setting unmask bit */ unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */ unsigned nobios : 1; /* flag: do not probe bios for drive */ unsigned revalidate : 1; /* request revalidation */ unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */ unsigned nice0 : 1; /* flag: give obvious excess bandwidth */ unsigned nice2 : 1; /* flag: give a share in our own bandwidth */ unsigned doorlocking : 1; /* flag: for removable only: door lock/unlock works */ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */#if FAKE_FDISK_FOR_EZDRIVE unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */#endif /* FAKE_FDISK_FOR_EZDRIVE */ byte media; /* disk, cdrom, tape, floppy, ... */ select_t select; /* basic drive/head select reg value */ byte ctl; /* "normal" value for IDE_CONTROL_REG */ byte ready_stat; /* min status value for drive ready */ byte mult_count; /* current multiple sector setting */ byte mult_req; /* requested multiple sector setting */ byte tune_req; /* requested drive tuning setting */ byte io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ byte bad_wstat; /* used for ignoring WRERR_STAT */ byte nowerr; /* used for ignoring WRERR_STAT */ byte sect0; /* offset of first sector for DM6:DDO */ byte usage; /* current "open()" count for drive */ byte head; /* "real" number of heads */ byte sect; /* "real" sectors per track */ byte bios_head; /* BIOS/fdisk/LILO number of heads */ byte bios_sect; /* BIOS/fdisk/LILO sectors per track */ unsigned short bios_cyl; /* BIOS/fdisk/LILO number of cyls */ unsigned short cyl; /* "real" number of cyls */ unsigned int drive_data; /* for use by tuneproc/selectproc as needed */ void *hwif; /* actually (ide_hwif_t *) */ struct wait_queue *wqueue; /* used to wait for drive in open() */ struct hd_driveid *id; /* drive model identification info */ struct hd_struct *part; /* drive partition table */ char name[4]; /* drive name, such as "hda" */ void *driver; /* (ide_driver_t *) */ void *driver_data; /* extra driver data */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ void *settings; /* /proc/ide/ drive settings */ char driver_req[10]; /* requests specific driver */ } ide_drive_t;/* * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive. * * The caller is assumed to have selected the drive and programmed the drive's * sector address using CHS or LBA. All that remains is to prepare for DMA * and then issue the actual read/write DMA/PIO command to the drive. * * Returns 0 if all went well. * Returns 1 if DMA read/write could not be started, in which case the caller * should either try again later, or revert to PIO for the current request. */typedef enum { ide_dma_read, ide_dma_write, ide_dma_begin, ide_dma_end, ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly, ide_dma_test_irq } ide_dma_action_t;typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);/* * An ide_tuneproc_t() is used to set the speed of an IDE interface * to a particular PIO mode. The "byte" parameter is used * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255 * indicates that the interface driver should "auto-tune" the PIO mode * according to the drive capabilities in drive->id; * * Not all interface types support tuning, and not all of those * support all possible PIO settings. They may silently ignore * or round values as they see fit. */typedef void (ide_tuneproc_t)(ide_drive_t *, byte);/* * This is used to provide support for strange interfaces */typedef void (ide_selectproc_t) (ide_drive_t *);/* * hwif_chipset_t is used to keep track of the specific hardware * chipset used by each IDE interface, if known. */typedef enum { ide_unknown, ide_generic, ide_pci, ide_cmd640, ide_dtc2278, ide_ali14xx, ide_qd6580, ide_umc8672, ide_ht6560b, ide_pdc4030, ide_rz1000, ide_trm290, ide_cmd646, ide_4drives } hwif_chipset_t;typedef struct ide_pci_devid_s { unsigned short vid; unsigned short did;} ide_pci_devid_t;#define IDE_PCI_DEVID_NULL ((ide_pci_devid_t){0,0})#define IDE_PCI_DEVID_EQ(a,b) (a.vid == b.vid && a.did == b.did)typedef struct hwif_s { struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ void *hwgroup; /* actually (ide_hwgroup_t *) */ ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */ ide_drive_t drives[MAX_DRIVES]; /* drive info */ struct gendisk *gd; /* gendisk structure */ ide_tuneproc_t *tuneproc; /* routine to tune PIO mode for drives */ ide_selectproc_t *selectproc; /* tweaks hardware to select drive */ ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */ unsigned long *dmatable; /* dma physical region descriptor table */ struct hwif_s *mate; /* other hwif from same PCI chip */ unsigned long dma_base; /* base addr for dma ports */ unsigned dma_extra; /* extra addr for dma ports */ unsigned long config_data; /* for use by chipset-specific code */ unsigned long select_data; /* for use by chipset-specific code */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ int irq; /* our irq number */ byte major; /* our major number */ char name[6]; /* name of interface, eg. "ide0" */ byte index; /* 0 for ide0; 1 for ide1; ... */ hwif_chipset_t chipset; /* sub-module for tuning.. */ unsigned noprobe : 1; /* don't probe for this interface */ unsigned present : 1; /* this interface exists */ unsigned serialized : 1; /* serialized operation with mate hwif */ unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */ unsigned reset : 1; /* reset after probe */ unsigned autodma : 1; /* automatically try to enable DMA at boot */ byte channel; /* for dual-port chips: 0=primary, 1=secondary */ struct pci_dev *pci_dev; /* for pci chipsets */ ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */#if (DISK_RECOVERY_TIME > 0) unsigned long last_time; /* time when previous rq was done */#endif } ide_hwif_t;/* * internal ide interrupt handler type */typedef void (ide_handler_t)(ide_drive_t *);typedef struct hwgroup_s { spinlock_t spinlock; /* protects "busy" and "handler" */ ide_handler_t *handler;/* irq handler, if active */ int busy; /* BOOL: protects all fields below */ ide_drive_t *drive; /* current drive */ ide_hwif_t *hwif; /* ptr to current hwif in linked-list */ struct request *rq; /* current request */ struct timer_list timer; /* failsafe timer */ struct request wrq; /* local copy of current write rq */ unsigned long poll_timeout; /* timeout value during long polls */ } ide_hwgroup_t;/* * configurable drive settings */#define TYPE_INT 0#define TYPE_INTA 1#define TYPE_BYTE 2#define TYPE_SHORT 3#define SETTING_READ (1 << 0)#define SETTING_WRITE (1 << 1)#define SETTING_RW (SETTING_READ | SETTING_WRITE)typedef int (ide_procset_t)(ide_drive_t *, int);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -