patch-2.3.1 linux/include/linux/ide.h

Next file: linux/include/linux/if_pppvar.h
Previous file: linux/include/linux/hfs_sysdep.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.0/linux/include/linux/ide.h linux/include/linux/ide.h
@@ -0,0 +1,821 @@
+#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/hdsmart.h>
+#include <linux/blkdev.h>
+#include <linux/proc_fs.h>
+#include <asm/hdreg.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]); \
+}
+
+/*
+ * Check for an interrupt and acknowledge the interrupt status
+ */
+struct hwif_s;
+typedef int (ide_ack_intr_t)(struct hwif_s *);
+
+/*
+ * Structure to hold all information about the location of this port
+ */
+typedef struct hw_regs_s {
+	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
+	int		irq;			/* our irq number */
+	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
+	void		*priv;			/* interface specific data */
+} hw_regs_t;
+
+/*
+ * Register new hardware with ide
+ */
+int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp);
+
+/*
+ * Set up hw_regs_t structure before calling ide_register_hw (optional)
+ */
+void ide_setup_ports(	hw_regs_t *hw,
+			ide_ioreg_t base,
+			int *offsets,
+			ide_ioreg_t ctrl,
+			ide_ioreg_t intr,
+			ide_ack_intr_t *ack_intr,
+			int irq);
+
+#include <asm/ide.h>
+
+/*
+ * 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	0x0
+
+typedef 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 *) */
+	wait_queue_head_t 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 */
+#if 1
+	struct thresholds_s	*smart_thresholds;
+	struct values_s		*smart_values;
+#else
+	thresholds_t		smart_thresholds;
+	values_t		smart_values;
+#endif
+	} 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_bad_drive,			ide_dma_good_drive
+	} 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_cy82c693,	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 */
+	hw_regs_t	hw;		/* Hardware info */
+	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);
+typedef struct ide_settings_s {
+	char			*name;
+	int			rw;
+	int			read_ioctl;
+	int			write_ioctl;
+	int			data_type;
+	int			min;
+	int			max;
+	int			mul_factor;
+	int			div_factor;
+	void			*data;
+	ide_procset_t		*set;
+	int			auto_remove;
+	struct ide_settings_s	*next;
+} ide_settings_t;
+
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_remove_setting(ide_drive_t *drive, char *name);
+ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
+int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
+int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
+void ide_add_generic_settings(ide_drive_t *drive);
+
+/*
+ * /proc/ide interface
+ */
+typedef struct {
+	const char	*name;
+	mode_t		mode;
+	read_proc_t	*read_proc;
+	write_proc_t	*write_proc;
+} ide_proc_entry_t;
+
+#ifdef CONFIG_PROC_FS
+void proc_ide_create(void);
+void proc_ide_destroy(void);
+void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
+void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
+read_proc_t proc_ide_read_capacity;
+read_proc_t proc_ide_read_geometry;
+
+/*
+ * Standard exit stuff:
+ */
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
+{					\
+	len -= off;			\
+	if (len < count) {		\
+		*eof = 1;		\
+		if (len <= 0)		\
+			return 0;	\
+	} else				\
+		len = count;		\
+	*start = page + off;		\
+	return len;			\
+}
+#else
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
+#endif
+
+/*
+ * Subdrivers support.
+ */
+#define IDE_SUBDRIVER_VERSION	1
+
+typedef int	(ide_cleanup_proc)(ide_drive_t *);
+typedef void 	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
+typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
+typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
+typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef int	(ide_check_media_change_proc)(ide_drive_t *);
+typedef void	(ide_pre_reset_proc)(ide_drive_t *);
+typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
+typedef void	(ide_special_proc)(ide_drive_t *);
+typedef void	(ide_setting_proc)(ide_drive_t *);
+
+typedef struct ide_driver_s {
+	const char			*name;
+	const char			*version;
+	byte				media;
+	unsigned busy			: 1;
+	unsigned supports_dma		: 1;
+	unsigned supports_dsc_overlap	: 1;
+	ide_cleanup_proc		*cleanup;
+	ide_do_request_proc		*do_request;
+	ide_end_request_proc		*end_request;
+	ide_ioctl_proc			*ioctl;
+	ide_open_proc			*open;
+	ide_release_proc		*release;
+	ide_check_media_change_proc	*media_change;
+	ide_pre_reset_proc		*pre_reset;
+	ide_capacity_proc		*capacity;
+	ide_special_proc		*special;
+	ide_proc_entry_t		*proc;
+	} ide_driver_t;
+
+#define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
+
+/*
+ * IDE modules.
+ */
+#define IDE_CHIPSET_MODULE		0	/* not supported yet */
+#define IDE_PROBE_MODULE		1
+#define IDE_DRIVER_MODULE		2
+
+typedef int	(ide_module_init_proc)(void);
+
+typedef struct ide_module_s {
+	int				type;
+	ide_module_init_proc		*init;
+	void				*info;
+	struct ide_module_s		*next;
+} ide_module_t;
+
+/*
+ * ide_hwifs[] is the master data structure used to keep track
+ * of just about everything in ide.c.  Whenever possible, routines
+ * should be using pointers to a drive (ide_drive_t *) or
+ * pointers to a hwif (ide_hwif_t *), rather than indexing this
+ * structure directly (the allocation/layout may change!).
+ *
+ */
+#ifndef _IDE_C
+extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
+extern  ide_module_t	*ide_modules;
+#endif
+
+/*
+ * We need blk.h, but we replace its end_request by our own version.
+ */
+#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
+#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
+#include <linux/blk.h>
+
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
+
+/*
+ * This is used for (nearly) all data transfers from/to the IDE interface
+ */
+void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
+/*
+ * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
+ */
+void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+
+/*
+ * This is used on exit from the driver, to designate the next irq handler
+ * and also to start the safety timer.
+ */
+void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
+
+/*
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * ide_error() takes action based on the error returned by the controller.
+ * The calling function must return afterwards, to restart the request.
+ */
+void ide_error (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * Issue a simple drive command
+ * The drive must be selected beforehand.
+ */
+void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
+
+/*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
+void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+
+/*
+ * This routine busy-waits for the drive status to be not "busy".
+ * It then checks the status for all of the "good" bits and none
+ * of the "bad" bits, and if all is okay it returns 0.  All other
+ * cases return 1 after invoking ide_error() -- caller should return.
+ *
+ */
+int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
+
+/*
+ * This routine is called from the partition-table code in genhd.c
+ * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
+ *
+ * The second parameter, "xparm", determines exactly how the translation
+ * will be handled:
+ *		 0 = convert to CHS with fewer than 1024 cyls
+ *			using the same method as Ontrack DiskManager.
+ *		 1 = same as "0", plus offset everything by 63 sectors.
+ *		-1 = similar to "0", plus redirect sector 0 to sector 1.
+ *		>1 = convert to a CHS geometry with "xparm" heads.
+ *
+ * Returns 0 if the translation was not possible, if the device was not
+ * an IDE disk drive, or if a geometry was "forced" on the commandline.
+ * Returns 1 if the geometry translation was successful.
+ */
+int ide_xlate_1024 (kdev_t, int, const char *);
+
+/*
+ * Start a reset operation for an IDE interface.
+ * The caller should return immediately after invoking this.
+ */
+void ide_do_reset (ide_drive_t *);
+
+/*
+ * This function is intended to be used prior to invoking ide_do_drive_cmd().
+ */
+void ide_init_drive_cmd (struct request *rq);
+
+/*
+ * "action" parameter type for ide_do_drive_cmd() below.
+ */
+typedef enum
+	{ide_wait,	/* insert rq at end of list, and wait for it */
+	 ide_next,	/* insert rq immediately after current request */
+	 ide_preempt,	/* insert rq in front of current request */
+	 ide_end}	/* insert rq at end of list, but don't wait for it */
+ ide_action_t;
+
+/*
+ * This function issues a special IDE device request
+ * onto the request queue.
+ *
+ * If action is ide_wait, then the rq is queued at the end of the
+ * request queue, and the function sleeps until it has been processed.
+ * This is for use when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then the rq is queued at the head of
+ * the request queue, displacing the currently-being-processed
+ * request and this function returns immediately without waiting
+ * for the new rq to be completed.  This is VERY DANGEROUS, and is
+ * intended for careful use by the ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_next, then the rq is queued immediately after
+ * the currently-being-processed-request (if any), and the function
+ * returns without waiting for the new rq to be completed.  As above,
+ * This is VERY DANGEROUS, and is intended for careful use by the
+ * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code.
+ */
+int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
+
+/*
+ * Clean up after success/failure of an explicit drive cmd.
+ * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
+ */
+void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
+
+/*
+ * Issue ATA command and wait for completion.
+ */
+int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
+
+void ide_delay_50ms (void);
+
+/*
+ * ide_system_bus_speed() returns what we think is the system VESA/PCI
+ * bus speed (in MHz).  This is used for calculating interface PIO timings.
+ * The default is 40 for known PCI systems, 50 otherwise.
+ * The "idebus=xx" parameter can be used to override this value.
+ */
+int ide_system_bus_speed (void);
+
+/*
+ * ide_multwrite() transfers a block of up to mcount sectors of data
+ * to a drive as part of a disk multwrite operation.
+ */
+void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
+
+/*
+ * ide_stall_queue() can be used by a drive to give excess bandwidth back
+ * to the hwgroup by sleeping for timeout jiffies.
+ */
+void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
+
+/*
+ * ide_get_queue() returns the queue which corresponds to a given device.
+ */
+struct request **ide_get_queue (kdev_t dev);
+
+/*
+ * CompactFlash cards and their brethern pretend to be removable hard disks,
+ * but they never have a slave unit, and they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting appropriate config bits.
+ */
+int drive_is_flashcard (ide_drive_t *drive);
+
+int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
+void ide_timer_expiry (unsigned long data);
+void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
+void ide_geninit (struct gendisk *gd);
+void do_ide0_request (void);
+#if MAX_HWIFS > 1
+void do_ide1_request (void);
+#endif
+#if MAX_HWIFS > 2
+void do_ide2_request (void);
+#endif
+#if MAX_HWIFS > 3
+void do_ide3_request (void);
+#endif
+#if MAX_HWIFS > 4
+void do_ide4_request (void);
+#endif
+#if MAX_HWIFS > 5
+void do_ide5_request (void);
+#endif
+#if MAX_HWIFS > 6
+void do_ide6_request (void);
+#endif
+#if MAX_HWIFS > 7
+void do_ide7_request (void);
+#endif
+void ide_init_subdrivers (void);
+
+#ifndef _IDE_C
+extern struct file_operations ide_fops[];
+#endif
+
+#ifdef _IDE_C
+#ifdef CONFIG_BLK_DEV_IDE
+int ideprobe_init (void);
+#endif /* CONFIG_BLK_DEV_IDE */
+#ifdef CONFIG_BLK_DEV_IDEDISK
+int idedisk_init (void);
+#endif /* CONFIG_BLK_DEV_IDEDISK */
+#ifdef CONFIG_BLK_DEV_IDECD
+int ide_cdrom_init (void);
+#endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDETAPE
+int idetape_init (void);
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+int idefloppy_init (void);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+int idescsi_init (void);
+#endif /* CONFIG_BLK_DEV_IDESCSI */
+#endif /* _IDE_C */
+
+int ide_register_module (ide_module_t *module);
+void ide_unregister_module (ide_module_t *module);
+ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
+int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
+int ide_unregister_subdriver (ide_drive_t *drive);
+int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
+
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ON_BOARD		1
+#define NEVER_BOARD		0
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define OFF_BOARD		ON_BOARD
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+#  define OFF_BOARD		NEVER_BOARD
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+unsigned long ide_find_free_region (unsigned short size) __init;
+void ide_scan_pcibus (void) __init;
+#endif
+#ifdef CONFIG_BLK_DEV_IDEDMA
+#define BAD_DMA_DRIVE		0
+#define GOOD_DMA_DRIVE		1
+int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func);
+void ide_dma_intr  (ide_drive_t *drive);
+int check_drive_lists (ide_drive_t *drive, int good_bad);
+int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+int ide_release_dma (ide_hwif_t *hwif);
+void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
+unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
+#endif
+
+/* This is too ugly to live! */
+#ifdef CONFIG_BLK_DEV_PDC4030
+#include "pdc4030.h"
+#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
+#else
+#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
+
+#endif /* _IDE_H */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)