diff options
Diffstat (limited to 'drivers/block')
35 files changed, 1458 insertions, 512 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 02bfe7dcd..a4920df2a 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -33,6 +33,7 @@ else bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA + bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO fi @@ -41,11 +42,13 @@ else if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 + bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586 + bool ' CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646 fi fi fi if [ "$CONFIG_PPC" = "y" ]; then - bool ' WInbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 + bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 fi fi if [ "$CONFIG_PMAC" = "y" ]; then @@ -74,7 +77,7 @@ else fi fi if [ "$CONFIG_MCA" = "y" ]; then - bool 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2 + tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2 fi if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM @@ -91,7 +94,9 @@ fi comment 'Additional Block Devices' tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -tristate 'Network block device support' CONFIG_BLK_DEV_NBD +if [ "$CONFIG_NET" = "y" ]; then + tristate 'Network block device support' CONFIG_BLK_DEV_NBD +fi bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then tristate ' Linear (append) mode' CONFIG_MD_LINEAR diff --git a/drivers/block/Makefile b/drivers/block/Makefile index fa943cc48..6d48ecb98 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -87,10 +87,10 @@ else endif ifeq ($(CONFIG_BLK_DEV_LOOP),y) -L_OBJS += loop.o +LX_OBJS += loop.o else ifeq ($(CONFIG_BLK_DEV_LOOP),m) - M_OBJS += loop.o + MX_OBJS += loop.o endif endif @@ -154,6 +154,10 @@ ifeq ($(CONFIG_BLK_DEV_NS87415),y) IDE_OBJS += ns87415.o endif +ifeq ($(CONFIG_BLK_DEV_VIA82C586),y) +IDE_OBJS += via82c586.o +endif + ifeq ($(CONFIG_BLK_DEV_CMD646),y) IDE_OBJS += cmd646.o endif diff --git a/drivers/block/README.fd b/drivers/block/README.fd index b750c89cf..3e3e8f346 100644 --- a/drivers/block/README.fd +++ b/drivers/block/README.fd @@ -102,12 +102,12 @@ isn't, use the old method using environment variables. Tells the floppy driver that a workable DMA channel is available (the default). -floppy=nofifo + floppy=nofifo Disables the FIFO entirely. This is needed if you get "Bus master arbitration error" messages from your Ethernet card (or from other devices) while accessing the floppy. -floppy=fifo + floppy=fifo Enables the FIFO (default) floppy=<threshold>,fifo_depth @@ -189,6 +189,13 @@ floppy=fifo floppy=<nr>,dma Sets the floppy DMA channel to <nr> instead of 2 + floppy=slow + Use PS/2 stepping rate: + " PS/2 floppies have much slower step rates than regular floppies. + It's been recommended that take about 1/4 of the default speed + in some more extreme cases." + + Supporting utilities and additional documentation: ================================================== diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index f49f186a8..9d6c4fb00 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c @@ -3,7 +3,7 @@ * * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> * - * Some parts are based on hd.c by Linus Thorvalds + * Some parts are based on hd.c by Linus Torvalds * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -1343,7 +1343,7 @@ static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd ) if (acsi_wait_for_noIRQ( 20 ) && acsicmd_nodma( modesense_cmd, 0 ) && acsi_wait_for_IRQ( 3*HZ ) && - acsi_getstatus() == 0); + acsi_getstatus() == 0) break; } if (page == 4) { diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index a7631741e..cc97d18dd 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -114,7 +114,7 @@ #define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */ #define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */ -static long int fd_def_df0 = 0; /* default for df0 if it doesn't identify */ +static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ MODULE_PARM(fd_def_df0,"l"); @@ -1859,20 +1859,6 @@ __initfunc(int amiga_floppy_init(void)) blksize_size[MAJOR_NR] = floppy_blocksizes; blk_size[MAJOR_NR] = floppy_sizes; - - #if 0 /* Doesn't seem to be correct */ - if (fd_def_df0==0) { - if ((amiga.model == AMI_3000) || (amiga.model == AMI_3000T) || - (amiga.model == AMI_3000PLUS) || (amiga.model == AMI_4000)) - fd_def_df0=FD_HD_3; - else - fd_def_df0=FD_DD_3; - } - #else - /* Now we hope that every HD drive will identify itself correctly */ - fd_def_df0 = FD_DD_3; - #endif - for (i = 0; i < 128; i++) mfmdecode[i]=255; for (i = 0; i < 16; i++) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index e555aa9d9..1a40d6009 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -102,6 +102,10 @@ * failures. */ +/* + * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives. + */ + #define FLOPPY_SANITY_CHECK #undef FLOPPY_SILENT_DCL_CLEAR @@ -149,6 +153,13 @@ static int irqdma_allocated = 0; #include <linux/interrupt.h> #include <linux/init.h> +/* + * PS/2 floppies have much slower step rates than regular floppies. + * It's been recommended that take about 1/4 of the default speed + * in some more extreme cases. + */ +static int slow_floppy = 0; + #include <asm/dma.h> #include <asm/irq.h> #include <asm/system.h> @@ -348,7 +359,7 @@ static struct { 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/ {{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0, - 0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ + 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ {{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/ @@ -1045,6 +1056,7 @@ static void floppy_enable_hlt(void) static void setup_DMA(void) { unsigned long flags; + unsigned long f; #ifdef FLOPPY_SANITY_CHECK if (raw_cmd->length == 0){ @@ -1066,17 +1078,20 @@ static void setup_DMA(void) } #endif INT_OFF; + f=claim_dma_lock(); fd_disable_dma(FLOPPY_DMA); #ifdef fd_dma_setup if(fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, (raw_cmd->flags & FD_RAW_READ)? DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) { + release_dma_lock(f); INT_ON; cont->done(0); FDCS->reset=1; return; } + release_dma_lock(f); #else fd_clear_dma_ff(FLOPPY_DMA); dma_cache_wback_inv((unsigned long)raw_cmd->kernel_data, @@ -1088,6 +1103,7 @@ static void setup_DMA(void) fd_set_dma_count(FLOPPY_DMA, raw_cmd->length); virtual_dma_port = FDCS->address; fd_enable_dma(FLOPPY_DMA); + release_dma_lock(f); #endif INT_ON; floppy_disable_hlt(); @@ -1302,6 +1318,9 @@ static void fdc_specify(void) /* Convert step rate from microseconds to milliseconds and 4 bits */ srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR; + if( slow_floppy ) { + srt = srt / 4; + } SUPBOUND(srt, 0xf); INFBOUND(srt, 0); @@ -1687,11 +1706,15 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) { void (*handler)(void) = DEVICE_INTR; int do_print; + unsigned long f; lasthandler = handler; interruptjiffies = jiffies; + f=claim_dma_lock(); fd_disable_dma(FLOPPY_DMA); + release_dma_lock(f); + floppy_enable_hlt(); CLEAR_INTR; if (fdc >= N_FDC || FDCS->address == -1){ @@ -1719,12 +1742,14 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(do_print) print_result("unexpected interrupt", inr); if (inr == 0){ + int max_sensei = 4; do { output_byte(FD_SENSEI); inr = result(); if(do_print) print_result("sensei", inr); - } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2); + max_sensei--; + } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei); } if (handler) { int cpu = smp_processor_id(); @@ -1772,13 +1797,18 @@ static void reset_interrupt(void) */ static void reset_fdc(void) { + unsigned long flags; + SET_INTR(reset_interrupt); FDCS->reset = 0; reset_fdc_info(0); /* Pseudo-DMA may intercept 'reset finished' interrupt. */ /* Irrelevant for systems with true DMA (i386). */ + + flags=claim_dma_lock(); fd_disable_dma(FLOPPY_DMA); + release_dma_lock(flags); if (FDCS->version >= FDC_82072A) fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS); @@ -1837,12 +1867,18 @@ static void show_floppy(void) static void floppy_shutdown(void) { + unsigned long flags; + if (!initialising) show_floppy(); cancel_activity(); floppy_enable_hlt(); + + flags=claim_dma_lock(); fd_disable_dma(FLOPPY_DMA); + release_dma_lock(flags); + /* avoid dma going to a random drive after shutdown */ if (!initialising) @@ -1890,6 +1926,8 @@ static int start_motor(void (*function)(void) ) static void floppy_ready(void) { + unsigned long flags; + CHECK_RESET; if (start_motor(floppy_ready)) return; if (fdc_dtr()) return; @@ -1908,8 +1946,12 @@ static void floppy_ready(void) #ifdef fd_chose_dma_mode if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) + { + flags=claim_dma_lock(); fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length); + release_dma_lock(flags); + } #endif if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){ @@ -2886,7 +2928,8 @@ static void process_fd_request(void) static void do_fd_request(void) { if(usage_count == 0) { - printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd); + printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); + printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd); return; } if (fdc_busy){ @@ -3012,7 +3055,12 @@ static void raw_cmd_done(int flag) raw_cmd->reply[i] = reply_buffer[i]; if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) + { + unsigned long flags; + flags=claim_dma_lock(); raw_cmd->length = fd_get_dma_residue(FLOPPY_DMA); + release_dma_lock(flags); + } if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) && (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) @@ -4017,6 +4065,7 @@ static struct param_table { { "usefifo", 0, &no_fifo, 0, 0 }, { "cmos", set_cmos, 0, 0, 0 }, + { "slow", 0, &slow_floppy, 1, 0 }, { "unexpected_interrupts", 0, &print_unex, 1, 0 }, { "no_unexpected_interrupts", 0, &print_unex, 0, 0 }, @@ -4027,7 +4076,7 @@ __initfunc(void floppy_setup(char *str, int *ints)) { int i; int param; - if (str) + if (str) { for (i=0; i< ARRAY_SIZE(config_params); i++){ if (strcmp(str,config_params[i].name) == 0){ if (ints[0]) @@ -4045,6 +4094,7 @@ __initfunc(void floppy_setup(char *str, int *ints)) return; } } + } if (str) { DPRINT("unknown floppy option [%s]\n", str); @@ -4107,6 +4157,8 @@ __initfunc(int floppy_init(void)) #endif if (floppy_grab_irq_and_dma()){ + del_timer(&fd_timeout); + blk_dev[MAJOR_NR].request_fn = NULL; unregister_blkdev(MAJOR_NR,"fd"); del_timer(&fd_timeout); return -EBUSY; @@ -4116,7 +4168,9 @@ __initfunc(int floppy_init(void)) for (drive = 0; drive < N_DRIVE; drive++) { CLEARSTRUCT(UDRS); CLEARSTRUCT(UDRWE); - UDRS->flags = FD_VERIFY | FD_DISK_NEWCHANGE | FD_DISK_CHANGED; + USETF(FD_DISK_NEWCHANGE); + USETF(FD_DISK_CHANGED); + USETF(FD_VERIFY); UDRS->fd_device = -1; floppy_track_buffer = NULL; max_buffer_sectors = 0; @@ -4131,6 +4185,9 @@ __initfunc(int floppy_init(void)) continue; FDCS->rawcmd = 2; if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){ + /* free ioports reserved by floppy_grab_irq_and_dma() */ + release_region(FDCS->address, 6); + release_region(FDCS->address+7, 1); FDCS->address = -1; FDCS->version = FDC_NONE; continue; @@ -4138,6 +4195,9 @@ __initfunc(int floppy_init(void)) /* Try to determine the floppy controller type */ FDCS->version = get_fdc_version(); if (FDCS->version == FDC_NONE){ + /* free ioports reserved by floppy_grab_irq_and_dma() */ + release_region(FDCS->address, 6); + release_region(FDCS->address+7, 1); FDCS->address = -1; continue; } @@ -4156,8 +4216,15 @@ __initfunc(int floppy_init(void)) current_drive = 0; floppy_release_irq_and_dma(); initialising=0; - if (have_no_fdc) { + if (have_no_fdc) + { DPRINT("no floppy controllers found\n"); + floppy_tq.routine = (void *)(void *) empty; + mark_bh(IMMEDIATE_BH); + schedule(); + if (usage_count) + floppy_release_irq_and_dma(); + blk_dev[MAJOR_NR].request_fn = NULL; unregister_blkdev(MAJOR_NR,"fd"); } return have_no_fdc; diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index c1b1e4e06..7fb8430ee 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -16,6 +16,8 @@ * More flexible handling of extended partitions - aeb, 950831 * * Check partition table on IDE disks for common CHS translations + * + * Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl} */ #include <linux/config.h> @@ -59,6 +61,10 @@ extern int blk_dev_init(void); extern int scsi_dev_init(void); extern int net_dev_init(void); +#ifdef CONFIG_PPC +extern void note_bootable_part(kdev_t dev, int part); +#endif + /* * disk_name() is used by genhd.c and md.c. * It formats the devicename of the indicated disk @@ -69,7 +75,7 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) { unsigned int part; const char *maj = hd->major_name; - char unit = (minor >> hd->minor_shift) + 'a'; + int unit = (minor >> hd->minor_shift) + 'a'; /* * IDE devices use multiple major numbers, but the drives @@ -77,6 +83,10 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) * This requires special handling here. */ switch (hd->major) { + case IDE5_MAJOR: + unit += 2; + case IDE4_MAJOR: + unit += 2; case IDE3_MAJOR: unit += 2; case IDE2_MAJOR: @@ -85,8 +95,19 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) unit += 2; case IDE0_MAJOR: maj = "hd"; + break; } part = minor & ((1 << hd->minor_shift) - 1); + if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) { + unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16; + if (unit > 'z') { + unit -= 'z' + 1; + sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26); + if (part) + sprintf(buf + 4, "%d", part); + return buf; + } + } if (part) sprintf(buf, "%s%c%d", maj, unit, part); else @@ -421,8 +442,8 @@ check_table: && (q->end_sector & 63) == 63) { unsigned int heads = q->end_head + 1; if (heads == 32 || heads == 64 || - heads == 128 || heads == 255 || - heads == 240) { + heads == 128 || heads == 240 || + heads == 255) { (void) ide_xlate_1024(dev, heads, " [PTBL]"); break; } @@ -845,7 +866,7 @@ static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec) int blk, blocks_in_map; int dev_bsize, dev_pos, pos; unsigned secsize; -#ifdef CONFIG_PMAC +#ifdef CONFIG_PPC int first_bootable = 1; #endif struct mac_partition *part; @@ -899,18 +920,18 @@ static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec) fsec + be32_to_cpu(part->start_block) * (secsize/512), be32_to_cpu(part->block_count) * (secsize/512)); -#ifdef CONFIG_PMAC +#ifdef CONFIG_PPC /* * If this is the first bootable partition, tell the * setup code, in case it wants to make this the root. */ - if (first_bootable + if ( (_machine == _MACH_Pmac) && first_bootable && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) && strcasecmp(part->processor, "powerpc") == 0) { note_bootable_part(dev, blk); first_bootable = 0; } -#endif /* CONFIG_PMAC */ +#endif /* CONFIG_PPC */ ++current_minor; } diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 34ac359d2..2231f5693 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -1,8 +1,9 @@ -#define VERBOSE_IDE_CD_ERRORS 1 +#define VERBOSE_IDE_CD_ERRORS 1 /* * linux/drivers/block/ide-cd.c * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> + * Copyright (C) 1998 Jens Axboe and Chris Zwilling * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. @@ -218,9 +219,16 @@ * since the .pdf version doesn't seem to work... * -- Updated the TODO list to something more current. * + * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess, + * patch thanks to "Eddie C. Dost" <ecd@skynet.be> + * + * 4.50 Oct 19, 1998 -- New maintainers! + * Jens Axboe <axboe@image.dk> + * Chris Zwilling <chris@cloudnet.com> + * *************************************************************************/ -#define IDECD_VERSION "4.14" +#define IDECD_VERSION "4.50" #include <linux/module.h> #include <linux/types.h> @@ -1287,8 +1295,7 @@ static void cdrom_sleep (int time) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + time; - schedule (); + schedule_timeout(time); } static @@ -2597,6 +2604,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) return 0; } else { + int was_locked; + if ( #if ! STANDARD_ATAPI CDROM_STATE_FLAGS (drive)->sanyo_slot == 0 && @@ -2605,6 +2614,10 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) return -ENOMEDIUM; } + was_locked = CDROM_STATE_FLAGS (drive)->door_locked; + if (was_locked) + (void) cdrom_lockdoor (drive, 0, NULL); + stat = cdrom_load_unload (drive, slot, NULL); cdrom_saw_media_change (drive); if (stat) @@ -2618,10 +2631,12 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) stat = cdrom_read_toc (drive, &my_reqbuf); if (stat) return stat; - return slot; } - else - return stat; + + if (was_locked) + (void) cdrom_lockdoor (drive, 1, NULL); + + return slot; } } diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h index fbb2f859e..e72777fdd 100644 --- a/drivers/block/ide-cd.h +++ b/drivers/block/ide-cd.h @@ -4,8 +4,11 @@ * linux/drivers/block/ide_modes.h * * Copyright (C) 1996 Erik Andersen + * Copyright (C) 1998 Jens Axboe and Chris Zwilling */ +#include <asm/byteorder.h> + /* Turn this on to have the driver print out the meanings of the ATAPI error codes. This will use up additional kernel-space memory, though. */ @@ -148,13 +151,29 @@ struct ide_cd_state_flags { struct atapi_request_sense { +#if defined(__BIG_ENDIAN_BITFIELD) + unsigned char valid : 1; + unsigned char error_code : 7; +#elif defined(__LITTLE_ENDIAN_BITFIELD) unsigned char error_code : 7; unsigned char valid : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte reserved1; +#if defined(__BIG_ENDIAN_BITFIELD) + unsigned char reserved3 : 2; + unsigned char ili : 1; + unsigned char reserved2 : 1; + unsigned char sense_key : 4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) unsigned char sense_key : 4; unsigned char reserved2 : 1; unsigned char ili : 1; unsigned char reserved3 : 2; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte info[4]; byte sense_len; byte command_info[4]; @@ -190,8 +209,15 @@ struct atapi_toc_header { struct atapi_toc_entry { byte reserved1; - unsigned control : 4; - unsigned adr : 4; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 adr : 4; + __u8 control : 4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 control : 4; + __u8 adr : 4; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte track; byte reserved2; union { @@ -218,8 +244,15 @@ struct atapi_cdrom_subchnl { u_short acdsc_length; u_char acdsc_format; +#if defined(__BIG_ENDIAN_BITFIELD) + u_char acdsc_ctrl: 4; + u_char acdsc_adr: 4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) u_char acdsc_adr: 4; u_char acdsc_ctrl: 4; +#else +#error "Please fix <asm/byteorder.h>" +#endif u_char acdsc_trk; u_char acdsc_ind; union { @@ -243,79 +276,182 @@ typedef enum { struct atapi_capabilities_page { - unsigned page_code : 6; - unsigned reserved1 : 1; - unsigned parameters_saveable : 1; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 parameters_saveable : 1; + __u8 reserved1 : 1; + __u8 page_code : 6; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 page_code : 6; + __u8 reserved1 : 1; + __u8 parameters_saveable : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte page_length; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved2 : 5; + /* Drive supports reading CD-R discs with addressing method 2 */ + __u8 method2 : 1; /* reserved in 1.2 */ + /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ + __u8 cd_rw_read : 1; /* reserved in 1.2 */ /* Drive supports read from CD-R discs (orange book, part II) */ - unsigned cd_r_read : 1; /* reserved in 1.2 */ - /* Drive supports read from CD-R/W (CD-E) discs (orange book, part III) */ - unsigned cd_rw_read : 1; /* reserved in 1.2 */ + __u8 cd_r_read : 1; /* reserved in 1.2 */ +#elif defined(__LITTLE_ENDIAN_BITFIELD) + /* Drive supports read from CD-R discs (orange book, part II) */ + __u8 cd_r_read : 1; /* reserved in 1.2 */ + /* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */ + __u8 cd_rw_read : 1; /* reserved in 1.2 */ /* Drive supports reading CD-R discs with addressing method 2 */ - unsigned method2 : 1; /* reserved in 1.2 */ - unsigned reserved2 : 5; + __u8 method2 : 1; /* reserved in 1.2 */ + __u8 reserved2 : 5; +#else +#error "Please fix <asm/byteorder.h>" +#endif +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved3 : 6; + /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ + __u8 cd_rw_write : 1; /* reserved in 1.2 */ /* Drive supports write to CD-R discs (orange book, part II) */ - unsigned cd_r_write : 1; /* reserved in 1.2 */ - /* Drive supports write to CD-R/W (CD-E) discs (orange book, part III) */ - unsigned cd_rw_write : 1; /* reserved in 1.2 */ - unsigned reserved3 : 6; + __u8 cd_r_write : 1; /* reserved in 1.2 */ +#elif defined(__LITTLE_ENDIAN_BITFIELD) + + /* Drive can write to CD-R discs (orange book, part II) */ + __u8 cd_r_write : 1; /* reserved in 1.2 */ + /* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */ + __u8 cd_rw_write : 1; /* reserved in 1.2 */ + __u8 reserved3 : 6; +#else +#error "Please fix <asm/byteorder.h>" +#endif +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved4 : 1; + /* Drive can read multisession discs. */ + __u8 multisession : 1; + /* Drive can read mode 2, form 2 data. */ + __u8 mode2_form2 : 1; + /* Drive can read mode 2, form 1 (XA) data. */ + __u8 mode2_form1 : 1; + /* Drive supports digital output on port 2. */ + __u8 digport2 : 1; + /* Drive supports digital output on port 1. */ + __u8 digport1 : 1; + /* Drive can deliver a composite audio/video data stream. */ + __u8 composite : 1; /* Drive supports audio play operations. */ - unsigned audio_play : 1; + __u8 audio_play : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + /* Drive supports audio play operations. */ + __u8 audio_play : 1; /* Drive can deliver a composite audio/video data stream. */ - unsigned composite : 1; + __u8 composite : 1; /* Drive supports digital output on port 1. */ - unsigned digport1 : 1; + __u8 digport1 : 1; /* Drive supports digital output on port 2. */ - unsigned digport2 : 1; + __u8 digport2 : 1; /* Drive can read mode 2, form 1 (XA) data. */ - unsigned mode2_form1 : 1; + __u8 mode2_form1 : 1; /* Drive can read mode 2, form 2 data. */ - unsigned mode2_form2 : 1; + __u8 mode2_form2 : 1; /* Drive can read multisession discs. */ - unsigned multisession : 1; - unsigned reserved4 : 1; + __u8 multisession : 1; + __u8 reserved4 : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved5 : 1; + /* Drive can return Media Catalog Number (UPC) info. */ + __u8 upc : 1; + /* Drive can return International Standard Recording Code info. */ + __u8 isrc : 1; + /* Drive supports C2 error pointers. */ + __u8 c2_pointers : 1; + /* R-W data will be returned deinterleaved and error corrected. */ + __u8 rw_corr : 1; + /* Subchannel reads can return combined R-W information. */ + __u8 rw_supported : 1; + /* Drive can continue a read cdda operation from a loss of streaming.*/ + __u8 cdda_accurate : 1; + /* Drive can read Red Book audio data. */ + __u8 cdda : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) /* Drive can read Red Book audio data. */ - unsigned cdda : 1; + __u8 cdda : 1; /* Drive can continue a read cdda operation from a loss of streaming.*/ - unsigned cdda_accurate : 1; + __u8 cdda_accurate : 1; /* Subchannel reads can return combined R-W information. */ - unsigned rw_supported : 1; + __u8 rw_supported : 1; /* R-W data will be returned deinterleaved and error corrected. */ - unsigned rw_corr : 1; + __u8 rw_corr : 1; /* Drive supports C2 error pointers. */ - unsigned c2_pointers : 1; + __u8 c2_pointers : 1; /* Drive can return International Standard Recording Code info. */ - unsigned isrc : 1; + __u8 isrc : 1; /* Drive can return Media Catalog Number (UPC) info. */ - unsigned upc : 1; - unsigned reserved5 : 1; + __u8 upc : 1; + __u8 reserved5 : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif + +#if defined(__BIG_ENDIAN_BITFIELD) + /* Drive mechanism types. */ + mechtype_t mechtype : 3; + __u8 reserved6 : 1; + /* Drive can eject a disc or changer cartridge. */ + __u8 eject : 1; + /* State of prevent/allow jumper. */ + __u8 prevent_jumper : 1; + /* Present state of door lock. */ + __u8 lock_state : 1; + /* Drive can lock the door. */ + __u8 lock : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) /* Drive can lock the door. */ - unsigned lock : 1; + __u8 lock : 1; /* Present state of door lock. */ - unsigned lock_state : 1; + __u8 lock_state : 1; /* State of prevent/allow jumper. */ - unsigned prevent_jumper : 1; + __u8 prevent_jumper : 1; /* Drive can eject a disc or changer cartridge. */ - unsigned eject : 1; - unsigned reserved6 : 1; + __u8 eject : 1; + __u8 reserved6 : 1; /* Drive mechanism types. */ mechtype_t mechtype : 3; +#else +#error "Please fix <asm/byteorder.h>" +#endif + +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved7 : 4; + /* Drive supports software slot selection. */ + __u8 sss : 1; /* reserved in 1.2 */ + /* Changer can report exact contents of slots. */ + __u8 disc_present : 1; /* reserved in 1.2 */ + /* Audio for each channel can be muted independently. */ + __u8 separate_mute : 1; + /* Audio level for each channel can be controlled independently. */ + __u8 separate_volume : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) /* Audio level for each channel can be controlled independently. */ - unsigned separate_volume : 1; + __u8 separate_volume : 1; /* Audio for each channel can be muted independently. */ - unsigned separate_mute : 1; + __u8 separate_mute : 1; /* Changer can report exact contents of slots. */ - unsigned disc_present : 1; /* reserved in 1.2 */ + __u8 disc_present : 1; /* reserved in 1.2 */ /* Drive supports software slot selection. */ - unsigned sss : 1; /* reserved in 1.2 */ - unsigned reserved7 : 4; + __u8 sss : 1; /* reserved in 1.2 */ + __u8 reserved7 : 4; +#else +#error "Please fix <asm/byteorder.h>" +#endif /* Note: the following four fields are returned in big-endian form. */ /* Maximum speed (in kB/s). */ @@ -333,23 +469,46 @@ struct atapi_capabilities_page { struct atapi_mechstat_header { - unsigned curslot : 5; - unsigned changer_state : 2; - unsigned fault : 1; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 fault : 1; + __u8 changer_state : 2; + __u8 curslot : 5; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 curslot : 5; + __u8 changer_state : 2; + __u8 fault : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif - unsigned reserved1 : 5; - unsigned mech_state : 3; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 mech_state : 3; + __u8 reserved1 : 5; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 reserved1 : 5; + __u8 mech_state : 3; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte curlba[3]; byte nslots; - unsigned short slot_tablelen; + __u8 short slot_tablelen; }; struct atapi_slot { - unsigned change : 1; - unsigned reserved1 : 6; - unsigned disc_present : 1; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 disc_present : 1; + __u8 reserved1 : 6; + __u8 change : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 change : 1; + __u8 reserved1 : 6; + __u8 disc_present : 1; +#else +#error "Please fix <asm/byteorder.h>" +#endif byte reserved2[3]; }; diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index c4672208e..2062f5cdf 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -19,6 +19,7 @@ * Version 1.05 add capacity support for ATA3 >= 8GB * Version 1.06 get boot-up messages to show full cyl count * Version 1.07 disable door-locking if it fails + * Version 1.07a fixed mult_count enables */ #define IDEDISK_VERSION "1.07" @@ -724,20 +725,24 @@ static void idedisk_setup (ide_drive_t *drive) drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2, drive->bios_cyl, drive->bios_head, drive->bios_sect); if (drive->using_dma) { - if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) - printk(", UDMA"); - else + if ((id->field_valid & 4) && + (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { + printk(", UDMA"); /* UDMA BIOS-enabled! */ + } else if (id->field_valid & 4) { + printk(", (U)DMA"); /* Can be BIOS-enabled! */ + } else { printk(", DMA"); + } } printk("\n"); drive->mult_count = 0; if (id->max_multsect) { - drive->mult_req = INITIAL_MULT_COUNT; - if (drive->mult_req > id->max_multsect) - drive->mult_req = id->max_multsect; - if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) - drive->special.b.set_multmode = 1; + id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; + id->multsect_valid = id->multsect ? 1 : 0; + drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT; + drive->special.b.set_multmode = drive->mult_req ? 1 : 0; } + drive->no_io_32bit = id->dword_io ? 1 : 0; } int idedisk_init (void) diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c index 93cc2cc1c..058d93b85 100644 --- a/drivers/block/ide-dma.c +++ b/drivers/block/ide-dma.c @@ -62,6 +62,13 @@ * for supplying a Promise UDMA board & WD UDMA drive for this work! * * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports. + * + * ACARD ATP850UF Chipset "Modified SCSI Class" with other names + * AEC6210 U/UF + * SIIG's UltraIDE Pro CN-2449 + * TTI HPT343 Chipset "Modified SCSI Class" but reports as an + * unknown storage device. + * NEW check_drive_lists(ide_drive_t *drive, int good_bad) */ #include <linux/config.h> #include <linux/types.h> @@ -85,9 +92,19 @@ const char *good_dma_drives[] = {"Micropolis 2112A", "CONNER CTMA 4000", "ST34342A", /* for Sun Ultra */ + "WDC AC2340F", /* DMA mode1 */ + "WDC AC2340H", /* DMA mode1 */ NULL}; /* + * bad_dma_drives() lists the model names (from "hdparm -i") + * of drives which supposedly support (U)DMA but which are + * known to corrupt data with this interface under Linux. + */ +const char *bad_dma_drives[] = {"WDC AC22100H", + NULL}; + +/* * Our Physical Region Descriptor (PRD) table should be large enough * to handle the biggest I/O request we are likely to see. Since requests * can have no more than 256 sectors, and since the typical blocksize is @@ -204,27 +221,57 @@ int ide_build_dmatable (ide_drive_t *drive) return count; } -static int config_drive_for_dma (ide_drive_t *drive) +/* + * For both Blacklisted and Whitelisted drives. + * This is setup to be called as an extern for future support + * to other special driver code. + */ +int check_drive_lists (ide_drive_t *drive, int good_bad) { const char **list; struct hd_driveid *id = drive->id; + + if (good_bad) { + /* Consult the list of known "good" drives */ + list = good_dma_drives; + while (*list) { + if (!strcmp(*list++,id->model)) + return 1; + } + } else { + /* Consult the list of known "bad" drives */ + list = bad_dma_drives; + while (*list) { + if (!strcmp(*list++,id->model)) { + printk("%s: (U)DMA capability is broken for %s\n", + drive->name, id->model); + return 1; + } + } + } + return 0; +} + +static int config_drive_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); if (id && (id->capability & 1) && hwif->autodma) { + /* Consult the list of known "bad" drives */ + if (check_drive_lists(drive, BAD_DMA_DRIVE)) + return hwif->dmaproc(ide_dma_off, drive); /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ if (id->field_valid & 4) /* UltraDMA */ if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) return hwif->dmaproc(ide_dma_on, drive); /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ if (id->field_valid & 2) /* regular DMA */ - if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) + if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) return hwif->dmaproc(ide_dma_on, drive); /* Consult the list of known "good" drives */ - list = good_dma_drives; - while (*list) { - if (!strcmp(*list++,id->model)) - return hwif->dmaproc(ide_dma_on, drive); - } + if (check_drive_lists(drive, GOOD_DMA_DRIVE)) + return hwif->dmaproc(ide_dma_on, drive); } return hwif->dmaproc(ide_dma_off_quietly, drive); } @@ -297,6 +344,21 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) } } +/* + * Needed for allowing full modular support of ide-driver + */ +int ide_release_dma (ide_hwif_t *hwif) +{ + if (hwif->dmatable) { + clear_page((unsigned long)hwif->dmatable); /* clear PRD 1st */ + free_page((unsigned long)hwif->dmatable); /* free PRD 2nd */ + } + if ((hwif->dma_extra) && (hwif->channel == 0)) + release_region((hwif->dma_base + 16), hwif->dma_extra); + release_region(hwif->dma_base, 8); + return 1; +} + __initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)) { static unsigned long dmatable = 0; @@ -354,9 +416,10 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c } } if (dma_base) { - if (extra) /* PDC20246 */ + if (extra) /* PDC20246 & HPT343 */ request_region(dma_base+16, extra, name); dma_base += hwif->channel ? 8 : 0; + hwif->dma_extra = extra; if (inb(dma_base+2) & 0x80) { printk("%s: simplex device: DMA disabled\n", name); dma_base = 0; diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c index 3c6d0c006..e5d48249d 100644 --- a/drivers/block/ide-floppy.c +++ b/drivers/block/ide-floppy.c @@ -121,10 +121,19 @@ typedef struct idefloppy_packet_command_s { * Removable Block Access Capabilities Page */ typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned page_code :6; /* Page code - Should be 0x1b */ unsigned reserved1_6 :1; /* Reserved */ unsigned ps :1; /* Should be 0 */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned ps :1; /* Should be 0 */ + unsigned reserved1_6 :1; /* Reserved */ + unsigned page_code :6; /* Page code - Should be 0x1b */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 page_length; /* Page Length - Should be 0xa */ +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned reserved2 :6; unsigned srfp :1; /* Supports reporting progress of format */ unsigned sflp :1; /* System floppy type device */ @@ -132,6 +141,17 @@ typedef struct { unsigned reserved3 :3; unsigned sml :1; /* Single / Multiple lun supported */ unsigned ncd :1; /* Non cd optical device */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned sflp :1; /* System floppy type device */ + unsigned srfp :1; /* Supports reporting progress of format */ + unsigned reserved2 :6; + unsigned ncd :1; /* Non cd optical device */ + unsigned sml :1; /* Single / Multiple lun supported */ + unsigned reserved3 :3; + unsigned tlun :3; /* Total logical units supported by the device */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 reserved[8]; } idefloppy_capabilities_page_t; @@ -139,9 +159,17 @@ typedef struct { * Flexible disk page. */ typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned page_code :6; /* Page code - Should be 0x5 */ unsigned reserved1_6 :1; /* Reserved */ unsigned ps :1; /* The device is capable of saving the page */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned ps :1; /* The device is capable of saving the page */ + unsigned reserved1_6 :1; /* Reserved */ + unsigned page_code :6; /* Page code - Should be 0x5 */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 page_length; /* Page Length - Should be 0x1e */ u16 transfer_rate; /* In kilobits per second */ u8 heads, sectors; /* Number of heads, Number of sectors per track */ @@ -164,8 +192,15 @@ typedef struct { typedef struct { u32 blocks; /* Number of blocks */ +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned dc :2; /* Descriptor Code */ unsigned reserved :6; +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned reserved :6; + unsigned dc :2; /* Descriptor Code */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 length_msb; /* Block Length (MSB)*/ u16 length; /* Block Length */ } idefloppy_capacity_descriptor_t; @@ -271,6 +306,7 @@ typedef struct { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned check :1; /* Error occurred */ unsigned idx :1; /* Reserved */ unsigned corr :1; /* Correctable error occurred */ @@ -279,6 +315,18 @@ typedef union { unsigned reserved5 :1; /* Reserved */ unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ unsigned bsy :1; /* The device has access to the command block */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned bsy :1; /* The device has access to the command block */ + unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ + unsigned reserved5 :1; /* Reserved */ + unsigned dsc :1; /* Media access command finished */ + unsigned drq :1; /* Data is request by the device */ + unsigned corr :1; /* Correctable error occurred */ + unsigned idx :1; /* Reserved */ + unsigned check :1; /* Error occurred */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_status_reg_t; @@ -288,11 +336,21 @@ typedef union { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned ili :1; /* Illegal Length Indication */ unsigned eom :1; /* End Of Media Detected */ unsigned abrt :1; /* Aborted command - As defined by ATA */ unsigned mcr :1; /* Media Change Requested - As defined by ATA */ unsigned sense_key :4; /* Sense key of the last failed packet command */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned sense_key :4; /* Sense key of the last failed packet command */ + unsigned mcr :1; /* Media Change Requested - As defined by ATA */ + unsigned abrt :1; /* Aborted command - As defined by ATA */ + unsigned eom :1; /* End Of Media Detected */ + unsigned ili :1; /* Illegal Length Indication */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_error_reg_t; @@ -302,10 +360,19 @@ typedef union { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned dma :1; /* Using DMA or PIO */ unsigned reserved321 :3; /* Reserved */ unsigned reserved654 :3; /* Reserved (Tag Type) */ unsigned reserved7 :1; /* Reserved */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned reserved7 :1; /* Reserved */ + unsigned reserved654 :3; /* Reserved (Tag Type) */ + unsigned reserved321 :3; /* Reserved */ + unsigned dma :1; /* Using DMA or PIO */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_feature_reg_t; @@ -315,8 +382,15 @@ typedef union { typedef union { unsigned all :16; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned low :8; /* LSB */ unsigned high :8; /* MSB */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned high :8; /* MSB */ + unsigned low :8; /* LSB */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_bcount_reg_t; @@ -326,9 +400,17 @@ typedef union { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned cod :1; /* Information transferred is command (1) or data (0) */ unsigned io :1; /* The device requests us to read (1) or write (0) */ unsigned reserved :6; /* Reserved */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned reserved :6; /* Reserved */ + unsigned io :1; /* The device requests us to read (1) or write (0) */ + unsigned cod :1; /* Information transferred is command (1) or data (0) */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_ireason_reg_t; @@ -338,12 +420,23 @@ typedef union { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned sam_lun :3; /* Logical unit number */ unsigned reserved3 :1; /* Reserved */ unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ unsigned one5 :1; /* Should be set to 1 */ unsigned reserved6 :1; /* Reserved */ unsigned one7 :1; /* Should be set to 1 */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned one7 :1; /* Should be set to 1 */ + unsigned reserved6 :1; /* Reserved */ + unsigned one5 :1; /* Should be set to 1 */ + unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ + unsigned reserved3 :1; /* Reserved */ + unsigned sam_lun :3; /* Logical unit number */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_drivesel_reg_t; @@ -353,11 +446,21 @@ typedef union { typedef union { unsigned all :8; struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned zero0 :1; /* Should be set to zero */ unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ unsigned one3 :1; /* Should be set to 1 */ unsigned reserved4567 :4; /* Reserved */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned reserved4567 :4; /* Reserved */ + unsigned one3 :1; /* Should be set to 1 */ + unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ + unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ + unsigned zero0 :1; /* Should be set to zero */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } b; } idefloppy_control_reg_t; @@ -366,6 +469,7 @@ typedef union { * the ATAPI IDENTIFY DEVICE command. */ struct idefloppy_id_gcw { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned packet_size :2; /* Packet Size */ unsigned reserved234 :3; /* Reserved */ unsigned drq_type :2; /* Command packet DRQ type */ @@ -373,12 +477,24 @@ struct idefloppy_id_gcw { unsigned device_type :5; /* Device type */ unsigned reserved13 :1; /* Reserved */ unsigned protocol :2; /* Protocol type */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned protocol :2; /* Protocol type */ + unsigned reserved13 :1; /* Reserved */ + unsigned device_type :5; /* Device type */ + unsigned removable :1; /* Removable media */ + unsigned drq_type :2; /* Command packet DRQ type */ + unsigned reserved234 :3; /* Reserved */ + unsigned packet_size :2; /* Packet Size */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif }; /* * INQUIRY packet command - Data Format */ typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned device_type :5; /* Peripheral Device Type */ unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ unsigned reserved1_6t0 :7; /* Reserved */ @@ -390,6 +506,21 @@ typedef struct { unsigned reserved3_45 :2; /* Reserved */ unsigned reserved3_6 :1; /* TrmIOP - Reserved */ unsigned reserved3_7 :1; /* AENC - Reserved */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ + unsigned device_type :5; /* Peripheral Device Type */ + unsigned rmb :1; /* Removable Medium Bit */ + unsigned reserved1_6t0 :7; /* Reserved */ + unsigned iso_version :2; /* ISO Version */ + unsigned ecma_version :3; /* ECMA Version */ + unsigned ansi_version :3; /* ANSI Version */ + unsigned reserved3_7 :1; /* AENC - Reserved */ + unsigned reserved3_6 :1; /* TrmIOP - Reserved */ + unsigned reserved3_45 :2; /* Reserved */ + unsigned response_format :4; /* Response Data Format */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 additional_length; /* Additional Length (total_length-4) */ u8 rsv5, rsv6, rsv7; /* Reserved */ u8 vendor_id[8]; /* Vendor Identification */ @@ -404,6 +535,7 @@ typedef struct { * REQUEST SENSE packet command result - Data Format. */ typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned error_code :7; /* Current error (0x70) */ unsigned valid :1; /* The information field conforms to SFF-8070i */ u8 reserved1 :8; /* Reserved */ @@ -411,6 +543,17 @@ typedef struct { unsigned reserved2_4 :1; /* Reserved */ unsigned ili :1; /* Incorrect Length Indicator */ unsigned reserved2_67 :2; +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned valid :1; /* The information field conforms to SFF-8070i */ + unsigned error_code :7; /* Current error (0x70) */ + u8 reserved1 :8; /* Reserved */ + unsigned reserved2_67 :2; + unsigned ili :1; /* Incorrect Length Indicator */ + unsigned reserved2_4 :1; /* Reserved */ + unsigned sense_key :4; /* Sense Key */ +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u32 information __attribute__ ((packed)); u8 asl; /* Additional sense length (n-7) */ u32 command_specific; /* Additional command specific information */ @@ -433,8 +576,15 @@ typedef struct { typedef struct { u16 mode_data_length; /* Length of the following data transfer */ u8 medium_type; /* Medium Type */ +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned reserved3 :7; unsigned wp :1; /* Write protect */ +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned wp :1; /* Write protect */ + unsigned reserved3 :7; +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif u8 reserved[4]; } idefloppy_mode_parameter_header_t; @@ -718,7 +868,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive) if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error, ",drive->name); + printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); #endif /* IDEFLOPPY_DEBUG_LOG */ rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { @@ -907,6 +1057,7 @@ static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc) pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD; pc->c[7] = 255; pc->c[8] = 255; + pc->request_transfer = 255; } /* @@ -1371,7 +1522,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) if (gcw.drq_type == 1) set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 && - strcmp(drive->id->fw_rev, "21.D") == 0) { + ((strcmp(drive->id->fw_rev, "21.D") == 0) || + (strcmp(drive->id->fw_rev, "23.D") == 0))) { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c index 1122757cb..88b0dc631 100644 --- a/drivers/block/ide-pci.c +++ b/drivers/block/ide-pci.c @@ -42,8 +42,10 @@ #define DEVID_NS87410 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410}) #define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415}) #define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565}) -#define DEVID_AEC6210 ((ide_pci_devid_t){0x1191, 0x0005}) +#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) #define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) +#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) +#define DEVID_HPT343 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) #define IDE_IGNORE ((void *)-1) @@ -93,6 +95,13 @@ extern void ide_init_rz1000(ide_hwif_t *); #define INIT_RZ1000 IDE_IGNORE #endif +#ifdef CONFIG_BLK_DEV_VIA82C586 +extern void ide_init_via82c586(ide_hwif_t *); +#define INIT_VIA82C586 &ide_init_via82c586 +#else +#define INIT_VIA82C586 NULL +#endif + typedef struct ide_pci_enablebit_s { byte reg; /* byte pci reg holding the enable-bit */ byte mask; /* mask to isolate the enable-bit */ @@ -104,35 +113,82 @@ typedef struct ide_pci_device_s { const char *name; void (*init_hwif)(ide_hwif_t *hwif); ide_pci_enablebit_t enablebits[2]; + byte bootable; + unsigned int extra; } ide_pci_device_t; static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} }, - {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} }, - {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} }, - {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} }, - {DEVID_VP_IDE, "VP_IDE", NULL, {{0x40,0x02,0x02}, {0x40,0x01,0x01}} }, - {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}} }, - {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}} }, - {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} }, - {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}} }, - {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} }, - {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}} }, - {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }, - {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}} }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }}; + {DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIXb, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VP_IDE, "VP_IDE", INIT_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_PDC20246,"PDC20246", NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {DEVID_RZ1000, "RZ1000", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_RZ1001, "RZ1001", INIT_RZ1000, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD640, "CMD640", IDE_IGNORE, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87410, "NS87410", NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {DEVID_SIS5513, "SIS5513", NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", INIT_CMD646, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_HT6565, "HT6565", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621, "OPTI621", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621X,"OPTI621X", INIT_OPTI621, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + +/* + * This allows offboard ide-pci cards the enable a BIOS, verify interrupt + * settings of split-mirror pci-config space, place chipset into init-mode, + * and/or preserve an interrupt if the card is not native ide support. + */ +__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name)) +{ + unsigned int addressbios = 0; + + pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addressbios); + + switch(dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP850UF: + case PCI_DEVICE_ID_PROMISE_20246: + pci_write_config_byte(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_ENABLE); + printk("%s: ROM enabled ", name); + + if (!addressbios) { + printk("but no address\n"); + } else { + printk("at 0x%08x\n", addressbios); + } + + if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) { + unsigned char irq1 = 0, irq2 = 0; + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq1); + pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */ + if (irq1 != irq2) { + printk("%s: IRQ1 %d IRQ2 %d\n", + name, irq1, irq2); + pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1); /* 0xbc */ + } + } + return dev->irq; + case PCI_DEVICE_ID_TTI_HPT343: + return dev->irq; + default: + break; + } + return 0; +} /* * Match a PCI IDE port against an entry in ide_hwifs[], * based on io_base port if possible. */ -__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char *name)) +__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)) { int h; ide_hwif_t *hwif; @@ -168,11 +224,22 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, const char * Give preference to claiming other slots before claiming ide0/ide1, * just in case there's another interface yet-to-be-scanned * which uses ports 1f0/170 (the ide0/ide1 defaults). + * + * Unless there is a bootable card that does not use the standard + * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. */ - for (h = 2; h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ + if (bootable) { + for (h = 0; h < MAX_HWIFS; ++h) { + hwif = &ide_hwifs[h]; + if (hwif->chipset == ide_unknown) + return hwif; /* pick an unused entry */ + } + } else { + for (h = 2; h < MAX_HWIFS; ++h) { + hwif = ide_hwifs + h; + if (hwif->chipset == ide_unknown) + return hwif; /* pick an unused entry */ + } } for (h = 0; h < 2; ++h) { hwif = ide_hwifs + h; @@ -263,7 +330,7 @@ check_if_enabled: pciirq = dev->irq; if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { printk("%s: not 100%% native mode: will probe irqs later\n", d->name); - pciirq = 0; + pciirq = ide_special_settings(dev, d->name); } else if (tried_config) { printk("%s: will probe irqs later\n", d->name); pciirq = 0; @@ -298,7 +365,7 @@ check_if_enabled: ctl = port ? 0x374 : 0x3f4; /* use default value */ if (!base) base = port ? 0x170 : 0x1f0; /* use default value */ - if ((hwif = ide_match_hwif(base, d->name)) == NULL) + if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL) continue; /* no room in ide_hwifs[] */ if (hwif->io_ports[IDE_DATA_OFFSET] != base) { ide_init_hwif_ports(hwif->io_ports, base, NULL); @@ -314,6 +381,10 @@ check_if_enabled: if (mate) { hwif->mate = mate; mate->mate = hwif; + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) { + hwif->serialized = 1; + mate->serialized = 1; + } } #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513)) @@ -321,9 +392,10 @@ check_if_enabled: if (autodma) hwif->autodma = 1; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0; - unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name); + unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { /* * Set up BM-DMA capability (PnP BIOS should have done this) diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c index cb8b13e06..f504cb9c2 100644 --- a/drivers/block/ide-pmac.c +++ b/drivers/block/ide-pmac.c @@ -25,10 +25,13 @@ #include <asm/dbdma.h> #include <asm/ide.h> #include <asm/mediabay.h> +#include <asm/feature.h> #include "ide.h" ide_ioreg_t pmac_ide_regbase[MAX_HWIFS]; int pmac_ide_irq[MAX_HWIFS]; +int pmac_ide_count; +struct device_node *pmac_ide_node[MAX_HWIFS]; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #define MAX_DCMDS 256 /* allow up to 256 DBDMA commands per xfer */ @@ -45,15 +48,18 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr); void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) { - int i; + int i, r; *p = 0; if (base == 0) return; - if (base == mb_cd_base && !check_media_bay(MB_CD)) { - mb_cd_index = -1; + /* we check only for -EINVAL meaning that we have found a matching + bay but with the wrong device type */ + + r = check_media_bay_by_base(base, MB_CD); + if (r == -EINVAL) return; - } + for (i = 0; i < 8; ++i) *p++ = base + i * 0x10; *p = base + 0x160; @@ -93,8 +99,8 @@ pmac_ide_probe(void)) /* Move removable devices such as the media-bay CDROM on the PB3400 to the end of the list. */ for (; p != NULL; p = p->next) { - if (p->parent && p->parent->name - && strcasecmp(p->parent->name, "media-bay") == 0) { + if (p->parent && p->parent->type + && strcasecmp(p->parent->type, "media-bay") == 0) { *rp = p; rp = &p->next; } else { @@ -111,7 +117,13 @@ pmac_ide_probe(void)) np->full_name); continue; } + base = (unsigned long) ioremap(np->addrs[0].address, 0x200); + + /* XXX This is bogus. Should be fixed in the registry by checking + the kind of host interrupt controller, a bit like gatwick + fixes in irq.c + */ if (np->n_intrs == 0) { printk("ide: no intrs for device %s, using 13\n", np->full_name); @@ -121,13 +133,13 @@ pmac_ide_probe(void)) } pmac_ide_regbase[i] = base; pmac_ide_irq[i] = irq; + pmac_ide_node[i] = np; if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { - mb_cd_index = i; - mb_cd_base = base; - mb_cd_irq = irq; - } + media_bay_set_ide_infos(np->parent,base,irq,i); + } else + feature_set(np, FEATURE_IDE_enable); hwif = &ide_hwifs[i]; pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq); @@ -143,6 +155,7 @@ pmac_ide_probe(void)) ++i; } + pmac_ide_count = i; } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 14b6bf323..bcaa40221 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -78,8 +78,18 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ - drive->present = 1; printk("%s: %s, ", drive->name, id->model); + drive->present = 1; + + /* + * Prevent long system lockup probing later for non-existant + * slave drive if the hwif is actually a Kodak CompactFlash card. + */ + if (!strcmp(id->model, "KODAK ATA_FLASH")) { + ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit]; + mate->present = 0; + mate->noprobe = 1; + } /* * Check for an ATAPI device @@ -273,6 +283,18 @@ static int do_probe (ide_drive_t *drive, byte cmd) { if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ rc = try_to_identify(drive,cmd); /* failed: try again */ + if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { + unsigned long timeout; + printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT()); + delay_50ms(); + OUT_BYTE (drive->select.all, IDE_SELECT_REG); + delay_50ms(); + OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); + timeout = jiffies; + while ((GET_STAT() & BUSY_STAT) && jiffies < timeout + WAIT_WORSTCASE) + delay_50ms(); + rc = try_to_identify(drive, cmd); + } if (rc == 1) printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); (void) GET_STAT(); /* ensure drive irq is clear */ diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c index 61e084366..f99fe7d41 100644 --- a/drivers/block/ide-tape.c +++ b/drivers/block/ide-tape.c @@ -45,7 +45,7 @@ * flag, can be configured by issuing an ioctl to the block device interface, * as any other ide device. * - * Our own ide-tape ioctl's can can be issued to either the block device or + * Our own ide-tape ioctl's can be issued to either the block device or * the character device interface. * * Maximal throughput with minimal bus load will usually be achieved in the @@ -276,7 +276,7 @@ * loop which checks if the pipeline is empty, and if it is, we * increase the maximum number of stages as necessary until we * reach the optimum value which just manages to keep the tape - * busy with with minimum allocated memory or until we reach + * busy with minimum allocated memory or until we reach * IDETAPE_MAX_PIPELINE_STAGES. * * Concerning (2): diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 9213f5274..23a554398 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1104,6 +1104,10 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags if (sleep) { if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) sleep = jiffies + WAIT_MIN_SLEEP; +#if 1 + if (hwgroup->timer.next || hwgroup->timer.prev) + printk("ide_set_handler: timer already active\n"); +#endif mod_timer(&hwgroup->timer, sleep); } else { /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */ @@ -1253,7 +1257,7 @@ void ide_timer_expiry (unsigned long data) } hwgroup->busy = 1; /* should already be "1" */ hwgroup->handler = NULL; - del_timer(&hwgroup->timer); + del_timer(&hwgroup->timer); /* Is this needed?? */ if (hwgroup->poll_timeout != 0) { /* polling in progress? */ spin_unlock_irqrestore(&hwgroup->spinlock, flags); handler(drive); @@ -1265,6 +1269,10 @@ void ide_timer_expiry (unsigned long data) if (drive->waiting_for_dma) { (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); printk("%s: timeout waiting for DMA\n", drive->name); + /* + * need something here for HX PIIX3 UDMA and HPT343.......AMH + * irq timeout: status=0x58 { DriveReady SeekComplete DataRequest } + */ } spin_unlock_irqrestore(&hwgroup->spinlock, flags); ide_error(drive, "irq timeout", GET_STAT()); @@ -1426,9 +1434,9 @@ void ide_init_drive_cmd (struct request *rq) * This function issues a special IDE device request * onto the request queue. * - * If action is ide_wait, then then 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_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 @@ -1729,6 +1737,11 @@ void ide_unregister (unsigned int index) else hwgroup->hwif = HWIF(hwgroup->drive); +#ifdef CONFIG_BLK_DEV_IDEDMA + if (hwif->dma_base) + (void) ide_release_dma(hwif); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + /* * Remove us from the kernel's knowledge */ @@ -2990,8 +3003,13 @@ void cleanup_module (void) { int index; - for (index = 0; index < MAX_HWIFS; ++index) + for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); +#ifdef CONFIG_BLK_DEV_IDEDMA + if (ide_hwifs[index].dma_base) + (void) ide_release_dma(&ide_hwifs[index]); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + } #ifdef CONFIG_PROC_FS proc_ide_destroy(); #endif diff --git a/drivers/block/ide.h b/drivers/block/ide.h index 1da4ff371..0919ca710 100644 --- a/drivers/block/ide.h +++ b/drivers/block/ide.h @@ -332,6 +332,7 @@ typedef struct hwif_s { 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 */ @@ -615,9 +616,9 @@ typedef enum * This function issues a special IDE device request * onto the request queue. * - * If action is ide_wait, then then 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_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 @@ -729,13 +730,25 @@ 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); 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 diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 158b5e975..35403ce59 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -93,8 +93,8 @@ int * blksize_size[MAX_BLKDEV] = { NULL, NULL, }; * then 512 bytes is assumed. * else * sector_size is hardsect_size[MAJOR][MINOR] - * This is currently set by some scsi device and read by the msdos fs driver - * This might be a some uses later. + * This is currently set by some scsi devices and read by the msdos fs driver. + * Other uses may appear later. */ int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, }; @@ -297,8 +297,8 @@ void add_request(struct blk_dev_struct * dev, struct request * req) int queue_new_request = 0; switch (MAJOR(req->rq_dev)) { - case SCSI_DISK_MAJOR: - disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4; + case SCSI_DISK0_MAJOR: + disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4; if (disk_index < 4) drive_stat_acct(req->cmd, req->nr_sectors, disk_index); break; @@ -331,10 +331,16 @@ void add_request(struct blk_dev_struct * dev, struct request * req) goto out; } for ( ; tmp->next ; tmp = tmp->next) { - if ((IN_ORDER(tmp,req) || - !IN_ORDER(tmp,tmp->next)) && - IN_ORDER(req,tmp->next)) - break; + const int after_current = IN_ORDER(tmp,req); + const int before_next = IN_ORDER(req,tmp->next); + + if (!IN_ORDER(tmp,tmp->next)) { + if (after_current || before_next) + break; + } else { + if (after_current && before_next) + break; + } } req->next = tmp->next; tmp->next = req; @@ -479,7 +485,14 @@ void make_request(int major,int rw, struct buffer_head * bh) break; /* fall through */ - case SCSI_DISK_MAJOR: + case SCSI_DISK0_MAJOR: + case SCSI_DISK1_MAJOR: + case SCSI_DISK2_MAJOR: + case SCSI_DISK3_MAJOR: + case SCSI_DISK4_MAJOR: + case SCSI_DISK5_MAJOR: + case SCSI_DISK6_MAJOR: + case SCSI_DISK7_MAJOR: case SCSI_CDROM_MAJOR: do { @@ -842,7 +855,7 @@ __initfunc(int blk_dev_init(void)) #ifdef CONFIG_BLK_DEV_FD floppy_init(); #else -#if !defined(CONFIG_SGI) && !defined (__mc68000__) && !defined(CONFIG_PMAC) +#if !defined(CONFIG_SGI) && !defined (__mc68000__) && !defined(CONFIG_PMAC) \ && !defined(__sparc__) && !defined(CONFIG_APUS) outb_p(0xc, 0x3f2); #endif diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 5a936899f..f635dd6c0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -15,30 +15,34 @@ * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997 * * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998 + * + * Loadable modules and other fixes by AK, 1998 + * + * Make real block number available to downstream transfer functions, enables + * CBC (and relatives) mode encryption requiring unique IVs per data block. + * Reed H. Petty, rhp@draper.net + * + * Still To Fix: + * - Advisory locking is ignored here. + * - Should use an own CAP_* category instead of CAP_SYS_ADMIN + * - Should use the underlying filesystems/devices read function if possible + * to support read ahead (and for write) */ #include <linux/module.h> -#include <linux/config.h> #include <linux/sched.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/major.h> + #include <linux/init.h> #include <asm/uaccess.h> -#ifdef CONFIG_BLK_DEV_LOOP_DES -# /*nodep*/ include <linux/des.h> -#endif - -#ifdef CONFIG_BLK_DEV_LOOP_IDEA -# /*nodep*/ include <linux/idea.h> -#endif - -#include <linux/loop.h> /* must follow des.h */ +#include <linux/loop.h> #define MAJOR_NR LOOP_MAJOR @@ -63,12 +67,11 @@ static int loop_blksizes[MAX_LOOP]; backing file (can happen if the backing file is sparse) */ static int create_missing_block(struct loop_device *lo, int block, int blksize); - /* * Transfer functions */ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) + char *loop_buf, int size, int real_block) { if (cmd == READ) memcpy(loop_buf, raw_buf, size); @@ -78,7 +81,7 @@ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, } static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) + char *loop_buf, int size, int real_block) { char *in, *out, *key; int i, keysize; @@ -97,80 +100,38 @@ static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, return 0; } -#ifdef DES_AVAILABLE -static int transfer_des(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) +static int none_status(struct loop_device *lo, struct loop_info *info) { - unsigned long tmp[2]; - unsigned long x0,x1,p0,p1; + return 0; +} - if (size & 7) +static int xor_status(struct loop_device *lo, struct loop_info *info) +{ + if (info->lo_encrypt_key_size < 0) return -EINVAL; - x0 = lo->lo_des_init[0]; - x1 = lo->lo_des_init[1]; - while (size) { - if (cmd == READ) { - tmp[0] = (p0 = ((unsigned long *) raw_buf)[0])^x0; - tmp[1] = (p1 = ((unsigned long *) raw_buf)[1])^x1; - des_ecb_encrypt((des_cblock *) tmp,(des_cblock *) - loop_buf,lo->lo_des_key,DES_ENCRYPT); - x0 = p0^((unsigned long *) loop_buf)[0]; - x1 = p1^((unsigned long *) loop_buf)[1]; - } - else { - p0 = ((unsigned long *) loop_buf)[0]; - p1 = ((unsigned long *) loop_buf)[1]; - des_ecb_encrypt((des_cblock *) loop_buf,(des_cblock *) - raw_buf,lo->lo_des_key,DES_DECRYPT); - ((unsigned long *) raw_buf)[0] ^= x0; - ((unsigned long *) raw_buf)[1] ^= x1; - x0 = p0^((unsigned long *) raw_buf)[0]; - x1 = p1^((unsigned long *) raw_buf)[1]; - } - size -= 8; - raw_buf += 8; - loop_buf += 8; - } return 0; } -#endif - -#ifdef IDEA_AVAILABLE -extern void idea_encrypt_block(idea_key,char *,char *,int); - -static int transfer_idea(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) -{ - if (cmd==READ) { - idea_encrypt_block(lo->lo_idea_en_key,raw_buf,loop_buf,size); - } - else { - idea_encrypt_block(lo->lo_idea_de_key,loop_buf,raw_buf,size); - } - return 0; -} -#endif - -static transfer_proc_t xfer_funcs[MAX_LOOP] = { - transfer_none, /* LO_CRYPT_NONE */ - transfer_xor, /* LO_CRYPT_XOR */ -#ifdef DES_AVAILABLE - transfer_des, /* LO_CRYPT_DES */ -#else - NULL, /* LO_CRYPT_DES */ -#endif -#ifdef IDEA_AVAILABLE /* LO_CRYPT_IDEA */ - transfer_idea -#else - NULL -#endif +struct loop_func_table none_funcs = { + number: LO_CRYPT_NONE, + transfer: transfer_none, + init: none_status +}; + +struct loop_func_table xor_funcs = { + number: LO_CRYPT_XOR, + transfer: transfer_xor, + init: xor_status +}; + +/* xfer_funcs[0] is special - its release function is never called */ +struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { + &none_funcs, + &xor_funcs }; - #define MAX_DISK_SIZE 1024*1024*1024 - static void figure_loop_size(struct loop_device *lo) { int size; @@ -288,7 +249,7 @@ repeat: } if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset, - dest_addr, size)) { + dest_addr, size, real_block)) { printk(KERN_ERR "loop: transfer error block %d\n", block); brelse(bh); goto error_out_lock; @@ -326,6 +287,7 @@ static int create_missing_block(struct loop_device *lo, int block, int blksize) char zero_buf[1] = { 0 }; ssize_t retval; mm_segment_t old_fs; + struct inode *inode; file = lo->lo_backing_file; if (file == NULL) { @@ -350,15 +312,18 @@ static int create_missing_block(struct loop_device *lo, int block, int blksize) } if (file->f_op->write == NULL) { - printk(KERN_WARNING "loop: cannot create block - no write file op\n"); + printk(KERN_WARNING "loop: cannot create block - file not writeable\n"); return FALSE; } old_fs = get_fs(); set_fs(get_ds()); + inode = file->f_dentry->d_inode; + down(&inode->i_sem); retval = file->f_op->write(file, zero_buf, 1, &file->f_pos); - + up(&inode->i_sem); + set_fs(old_fs); if (retval < 0) { @@ -426,9 +391,9 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) lo->lo_backing_file->f_op = file->f_op; lo->lo_backing_file->private_data = file->private_data; - error = get_write_access(inode); /* cannot fail */ + error = get_write_access(inode); if (error) { - fput(lo->lo_backing_file); + put_filp(lo->lo_backing_file); lo->lo_backing_file = NULL; } } @@ -444,9 +409,9 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) set_device_ro(dev, 0); } - lo->lo_dentry = file->f_dentry; - lo->lo_dentry->d_count++; + lo->lo_dentry = dget(file->f_dentry); lo->transfer = NULL; + lo->ioctl = NULL; figure_loop_size(lo); out_putf: @@ -457,6 +422,36 @@ out: return error; } +static int loop_release_xfer(struct loop_device *lo) +{ + int err = 0; + if (lo->lo_encrypt_type) { + struct loop_func_table *xfer= xfer_funcs[lo->lo_encrypt_type]; + if (xfer && xfer->release) + err = xfer->release(lo); + if (xfer && xfer->unlock) + xfer->unlock(lo); + lo->lo_encrypt_type = 0; + } + return err; +} + +static int loop_init_xfer(struct loop_device *lo, int type,struct loop_info *i) +{ + int err = 0; + if (type) { + struct loop_func_table *xfer = xfer_funcs[type]; + if (xfer->init) + err = xfer->init(lo, i); + if (!err) { + lo->lo_encrypt_type = type; + if (xfer->lock) + xfer->lock(lo); + } + } + return err; +} + static int loop_clr_fd(struct loop_device *lo, kdev_t dev) { struct dentry *dentry = lo->lo_dentry; @@ -477,6 +472,9 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev) dput(dentry); } + loop_release_xfer(lo); + lo->transfer = NULL; + lo->ioctl = NULL; lo->lo_device = 0; lo->lo_encrypt_type = 0; lo->lo_offset = 0; @@ -491,60 +489,41 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev) static int loop_set_status(struct loop_device *lo, struct loop_info *arg) { - struct loop_info info; + struct loop_info info; int err; + unsigned int type; + if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && + !capable(CAP_SYS_ADMIN)) + return -EPERM; if (!lo->lo_dentry) return -ENXIO; - if (!arg) - return -EINVAL; - err = verify_area(VERIFY_READ, arg, sizeof(info)); - if (err) - return err; - copy_from_user(&info, arg, sizeof(info)); + if (copy_from_user(&info, arg, sizeof (struct loop_info))) + return -EFAULT; if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; - switch (info.lo_encrypt_type) { - case LO_CRYPT_NONE: - break; - case LO_CRYPT_XOR: - if (info.lo_encrypt_key_size < 0) - return -EINVAL; - break; -#ifdef DES_AVAILABLE - case LO_CRYPT_DES: - if (info.lo_encrypt_key_size != 8) - return -EINVAL; - des_set_key((des_cblock *) lo->lo_encrypt_key, - lo->lo_des_key); - memcpy(lo->lo_des_init,info.lo_init,8); - break; -#endif -#ifdef IDEA_AVAILABLE - case LO_CRYPT_IDEA: - { - uint16 tmpkey[8]; - - if (info.lo_encrypt_key_size != IDEAKEYSIZE) - return -EINVAL; - /* create key in lo-> from info.lo_encrypt_key */ - memcpy(tmpkey,info.lo_encrypt_key,sizeof(tmpkey)); - en_key_idea(tmpkey,lo->lo_idea_en_key); - de_key_idea(lo->lo_idea_en_key,lo->lo_idea_de_key); - break; - } -#endif - default: + type = info.lo_encrypt_type; + if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; - } + err = loop_release_xfer(lo); + if (!err) + err = loop_init_xfer(lo, type, &info); + if (err) + return err; + lo->lo_offset = info.lo_offset; strncpy(lo->lo_name, info.lo_name, LO_NAME_SIZE); - lo->lo_encrypt_type = info.lo_encrypt_type; - lo->transfer = xfer_funcs[lo->lo_encrypt_type]; + + lo->transfer = xfer_funcs[type]->transfer; + lo->ioctl = xfer_funcs[type]->ioctl; lo->lo_encrypt_key_size = info.lo_encrypt_key_size; - if (info.lo_encrypt_key_size) - memcpy(lo->lo_encrypt_key, info.lo_encrypt_key, + lo->lo_init[0] = info.lo_init[0]; + lo->lo_init[1] = info.lo_init[1]; + if (info.lo_encrypt_key_size) { + memcpy(lo->lo_encrypt_key, info.lo_encrypt_key, info.lo_encrypt_key_size); + lo->lo_key_owner = current->uid; + } figure_loop_size(lo); return 0; } @@ -552,15 +531,11 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg) static int loop_get_status(struct loop_device *lo, struct loop_info *arg) { struct loop_info info; - int err; - + if (!lo->lo_dentry) return -ENXIO; if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE, arg, sizeof(info)); - if (err) - return err; memset(&info, 0, sizeof(info)); info.lo_number = lo->lo_number; info.lo_device = kdev_t_to_nr(lo->lo_dentry->d_inode->i_dev); @@ -575,8 +550,7 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg) memcpy(info.lo_encrypt_key, lo->lo_encrypt_key, lo->lo_encrypt_key_size); } - copy_to_user(arg, &info, sizeof(info)); - return 0; + return copy_to_user(arg, &info, sizeof(info)) ? -EFAULT : 0; } static int lo_ioctl(struct inode * inode, struct file * file, @@ -611,7 +585,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, return -EINVAL; return put_user(loop_sizes[lo->lo_number] << 1, (long *) arg); default: - return -EINVAL; + return lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } return 0; } @@ -619,7 +593,8 @@ static int lo_ioctl(struct inode * inode, struct file * file, static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo; - int dev; + int dev, type; + if (!inode) return -EINVAL; @@ -628,9 +603,14 @@ static int lo_open(struct inode *inode, struct file *file) return -ENODEV; } dev = MINOR(inode->i_rdev); - if (dev >= MAX_LOOP) + if (dev >= MAX_LOOP) { return -ENODEV; + } lo = &loop_dev[dev]; + + type = lo->lo_encrypt_type; + if (type && xfer_funcs[type] && xfer_funcs[type]->lock) + xfer_funcs[type]->lock(lo); lo->lo_refcnt++; MOD_INC_USE_COUNT; return 0; @@ -639,7 +619,7 @@ static int lo_open(struct inode *inode, struct file *file) static int lo_release(struct inode *inode, struct file *file) { struct loop_device *lo; - int dev; + int dev, err; if (!inode) return 0; @@ -650,15 +630,18 @@ static int lo_release(struct inode *inode, struct file *file) dev = MINOR(inode->i_rdev); if (dev >= MAX_LOOP) return 0; - fsync_dev(inode->i_rdev); + err = fsync_dev(inode->i_rdev); lo = &loop_dev[dev]; if (lo->lo_refcnt <= 0) printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt); else { - lo->lo_refcnt--; + int type = lo->lo_encrypt_type; + --lo->lo_refcnt; + if (xfer_funcs[type] && xfer_funcs[type]->unlock) + xfer_funcs[type]->unlock(lo); MOD_DEC_USE_COUNT; } - return 0; + return err; } static struct file_operations lo_fops = { @@ -681,8 +664,37 @@ static struct file_operations lo_fops = { #define loop_init init_module #endif -__initfunc(int -loop_init( void )) { +int loop_register_transfer(struct loop_func_table *funcs) +{ + if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number]) + return -EINVAL; + xfer_funcs[funcs->number] = funcs; + return 0; +} + +int loop_unregister_transfer(int number) +{ + struct loop_device *lo; + + if ((unsigned)number >= MAX_LO_CRYPT) + return -EINVAL; + for (lo = &loop_dev[0]; lo < &loop_dev[MAX_LOOP]; lo++) { + int type = lo->lo_encrypt_type; + if (type == number) { + xfer_funcs[type]->release(lo); + lo->transfer = NULL; + lo->lo_encrypt_type = 0; + } + } + xfer_funcs[number] = NULL; + return 0; +} + +EXPORT_SYMBOL(loop_register_transfer); +EXPORT_SYMBOL(loop_unregister_transfer); + +int __init loop_init(void) +{ int i; if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) { @@ -692,12 +704,6 @@ loop_init( void )) { } #ifndef MODULE printk(KERN_INFO "loop: registered device at major %d\n", MAJOR_NR); -#ifdef DES_AVAILABLE - printk(KERN_INFO "loop: DES encryption available\n"); -#endif -#ifdef IDEA_AVAILABLE - printk(KERN_INFO "loop: IDEA encryption available\n"); -#endif #endif blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; @@ -714,9 +720,9 @@ loop_init( void )) { } #ifdef MODULE -void -cleanup_module( void ) { - if (unregister_blkdev(MAJOR_NR, "loop") != 0) - printk(KERN_WARNING "loop: cleanup_module failed\n"); +void cleanup_module(void) +{ + if (unregister_blkdev(MAJOR_NR, "loop") != 0) + printk(KERN_WARNING "loop: cannot unregister blkdev\n"); } #endif diff --git a/drivers/block/md.c b/drivers/block/md.c index b6cf3d34e..77090708e 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -696,7 +696,6 @@ static int md_ioctl (struct inode *inode, struct file *file, RO_IOCTLS(inode->i_rdev,arg); default: - printk ("Unknown md_ioctl %d\n", cmd); return -EINVAL; } @@ -1140,8 +1139,7 @@ int md_do_sync(struct md_dev *mddev) while (blocksize*j/(jiffies-starttime+1)*HZ/1024 > SPEED_LIMIT) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies+1; - schedule(); + schedule_timeout(1); } /* diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c index d065606c7..dbce52137 100644 --- a/drivers/block/ns87415.c +++ b/drivers/block/ns87415.c @@ -31,7 +31,7 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) { ide_hwif_t *hwif = HWIF(drive); - unsigned int bit, new, *old = (unsigned int *) hwif->select_data; + unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data; struct pci_dev *dev = hwif->pci_dev; unsigned long flags; @@ -39,24 +39,20 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) __cli(); /* local CPU only */ new = *old; - /* adjust IRQ enable bit */ + /* Adjust IRQ enable bit */ bit = 1 << (8 + hwif->channel); new = drive->present ? (new & ~bit) : (new | bit); - /* select PIO or DMA */ - bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); - new = use_dma ? (new | bit) : (new & ~bit); + /* Select PIO or DMA, DMA may only be selected for one drive/channel. */ + bit = 1 << (20 + drive->select.b.unit + (hwif->channel << 1)); + other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1)); + new = use_dma ? ((new & ~other) | bit) : (new & ~bit); if (new != *old) { - if (use_dma) { - bit = (1 << (5 + drive->select.b.unit)); - outb((inb(hwif->dma_base+2) & 0x60) | bit, - hwif->dma_base+2); - } - *old = new; (void) pci_write_config_dword(dev, 0x40, new); } + __restore_flags(flags); /* local CPU only */ } @@ -74,8 +70,8 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive) case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; dma_stat = inb(hwif->dma_base+2); - outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */ - outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ + outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ return (dma_stat & 7) != 4; /* verify good DMA status */ case ide_dma_write: case ide_dma_read: @@ -94,6 +90,10 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) struct pci_dev *dev = hwif->pci_dev; unsigned int ctrl, using_inta; byte progif; +#ifdef __sparc_v9__ + int timeout; + byte stat; +#endif /* * We cannot probe for IRQ: both ports share common IRQ on INTA. @@ -126,22 +126,6 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) pci_write_config_byte(dev, 0x55, 0xee); #ifdef __sparc_v9__ -{ - int timeout; - byte stat; - /* - * Put reasonable values in the timing registers - * for DMA2 mode performance. - */ - pci_write_config_byte(dev, 0x44, 0xfe); - pci_write_config_byte(dev, 0x45, 0xfe); - pci_write_config_byte(dev, 0x48, 0xfe); - pci_write_config_byte(dev, 0x49, 0xfe); - pci_write_config_byte(dev, 0x4c, 0xfe); - pci_write_config_byte(dev, 0x4d, 0xfe); - pci_write_config_byte(dev, 0x50, 0xfe); - pci_write_config_byte(dev, 0x51, 0xfe); - /* * XXX: Reset the device, if we don't it will not respond * to SELECT_DRIVE() properly during first probe_hwif(). @@ -156,9 +140,11 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) if (stat == 0xff) break; } while ((stat & BUSY_STAT) && --timeout); -} #endif } + + outb(0x60, hwif->dma_base + 2); + if (!using_inta) hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ else if (!hwif->irq && hwif->mate && hwif->mate->irq) diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c index f965fb9da..680f9e592 100644 --- a/drivers/block/paride/frpw.c +++ b/drivers/block/paride/frpw.c @@ -12,10 +12,11 @@ 1.01 GRG 1998.05.06 init_proto, release_proto fix chip detect added EPP-16 and EPP-32 + 1.02 GRG 1998.09.23 added hard reset to initialisation process */ -#define FRPW_VERSION "1.01" +#define FRPW_VERSION "1.02" #include <linux/module.h> #include <linux/delay.h> @@ -184,6 +185,9 @@ static int frpw_test_pnp ( PIA *pi ) { int olddelay, a, b; + w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */ + mdelay(1500); + olddelay = pi->delay; pi->delay = 10; diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo new file mode 100644 index 000000000..b952fde92 --- /dev/null +++ b/drivers/block/paride/jumbo @@ -0,0 +1,70 @@ +#!/bin/sh +# +# This script can be used to build "jumbo" modules that contain the +# base PARIDE support, one protocol module and one high-level driver. +# +echo -n "High level driver [pcd] : " +read X +HLD=${X:-pcd} +# +echo -n "Protocol module [bpck] : " +read X +PROTO=${X:-bpck} +# +echo -n "Use MODVERSIONS [y] ? " +read X +UMODV=${X:-y} +# +echo -n "For SMP kernel [n] ? " +read X +USMP=${X:-n} +# +echo -n "Support PARPORT [n] ? " +read X +UPARP=${X:-n} +# +echo +# +case $USMP in + y* | Y* ) FSMP="-D__SMP__" + ;; + *) FSMP="" + ;; +esac +# +MODI="-include ../../../include/linux/modversions.h" +# +case $UMODV in + y* | Y* ) FMODV="-DMODVERSIONS $MODI" + ;; + *) FMODV="" + ;; +esac +# +case $UPARP in + y* | Y* ) FPARP="-DCONFIG_PARPORT" + ;; + *) FPARP="" + ;; +esac +# +TARG=$HLD-$PROTO.o +FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]` +FK="-D__KERNEL__ -I ../../../include" +FLCH=-D_LINUX_CONFIG_H +# +echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c +cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c +# +echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c +cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c +# +echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c +cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c +# +echo ld -r -o $TARG Jp.o Jb.o Jd.o +ld -r -o $TARG Jp.o Jb.o Jd.o +# +# +rm Jp.o Jb.o Jd.o +# diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c index 89457cc80..78477593e 100644 --- a/drivers/block/paride/on26.c +++ b/drivers/block/paride/on26.c @@ -10,10 +10,11 @@ /* Changes: 1.01 GRG 1998.05.06 init_proto, release_proto + 1.02 GRG 1998.09.23 updates for the -E rev chip */ -#define ON26_VERSION "1.01" +#define ON26_VERSION "1.02" #include <linux/module.h> #include <linux/delay.h> @@ -91,8 +92,8 @@ static void on26_write_regr( PIA *pi, int cont, int regr, int val ) } } -#define CCP(x) w0(0xff);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ - w0(0x87);w0(0x78);w0(x);w2(4); +#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\ + w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff); static void on26_connect ( PIA *pi ) @@ -102,7 +103,6 @@ static void on26_connect ( PIA *pi ) pi->saved_r2 = r2(); CCP(0x20); - w2(0xcd); w2(0xcc); w0(0xff); x = 8; if (pi->mode) x = 9; w0(2); P1; w0(8); P2; @@ -114,11 +114,62 @@ static void on26_disconnect ( PIA *pi ) { if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); } else { w0(4); P1; w0(4); P1; } CCP(0x30); - w2(0xcd); w2(0xcc); w0(0xff); w0(pi->saved_r0); w2(pi->saved_r2); } +static int on26_test_port( PIA *pi) /* hard reset */ + +{ int i, m, d; + + pi->saved_r0 = r0(); + pi->saved_r2 = r2(); + + d = pi->delay; + m = pi->mode; + pi->delay = 5; + pi->mode = 0; + + w2(0xc); + + CCP(0x30); CCP(0); + + w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff); + i = ((r1() & 0xf0) << 4); w0(0x87); + i |= (r1() & 0xf0); w0(0x78); + w0(0x20);w2(4);w2(5); + i |= ((r1() & 0xf0) >> 4); + w2(4);w0(0xff); + + if (i == 0xb5f) { + + w0(2); P1; w0(0); P2; + w0(3); P1; w0(0); P2; + w0(2); P1; w0(8); P2; udelay(100); + w0(2); P1; w0(0xa); P2; udelay(100); + w0(2); P1; w0(8); P2; udelay(1000); + + on26_write_regr(pi,0,6,0xa0); + + for (i=0;i<100;i++) { + if (!(on26_read_regr(pi,0,7) & 0x80)) break; + udelay(100000); + } + + w0(4); P1; w0(4); P1; + } + + CCP(0x30); + + pi->delay = d; + pi->mode = m; + w0(pi->saved_r0); + w2(pi->saved_r2); + + return 5; +} + + static void on26_read_block( PIA *pi, char * buf, int count ) { int k, a, b; @@ -240,7 +291,7 @@ struct pi_protocol on26 = {"on26",0,5,2,1,1, on26_read_block, on26_connect, on26_disconnect, - 0, + on26_test_port, 0, 0, on26_log_adapter, diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 4a083abbf..6366afa6b 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -96,10 +96,11 @@ pcd_completion, use HZ in loop timing 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard 1.06 GRG 1998.08.19 Added audio ioctl support + 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support */ -#define PCD_VERSION "1.06" +#define PCD_VERSION "1.07" #define PCD_MAJOR 46 #define PCD_NAME "pcd" #define PCD_UNITS 4 @@ -191,7 +192,7 @@ MODULE_PARM(drive3,"1-6i"); #define PCD_TMO 800 /* timeout in jiffies */ #define PCD_DELAY 50 /* spin delay in uS */ #define PCD_READY_TMO 20 /* in seconds */ -#define PCD_RESET_TMO 30 /* in tenths of a second */ +#define PCD_RESET_TMO 100 /* in tenths of a second */ #define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) @@ -365,6 +366,12 @@ int init_module(void) { int err; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pcd_init(); return err; @@ -552,8 +559,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position) static void pcd_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pcd_reset( int unit ) diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 69274fe48..3518a59d6 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -110,10 +110,11 @@ Added slave support 1.03 GRG 1998.06.16 Eliminate an Ugh. 1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing + 1.05 GRG 1998.09.24 Added jumbo support */ -#define PD_VERSION "1.04" +#define PD_VERSION "1.05" #define PD_MAJOR 45 #define PD_NAME "pd" #define PD_UNITS 4 @@ -611,6 +612,12 @@ int init_module(void) { int err, unit; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pd_init(); if (err) return err; diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index a2f1f1da9..255352f0a 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -109,10 +109,11 @@ up transfer size. 1.02 GRG 1998.06.16 Eliminated an Ugh 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging + 1.04 GRG 1998.09.24 Added jumbo support */ -#define PF_VERSION "1.03" +#define PF_VERSION "1.04" #define PF_MAJOR 47 #define PF_NAME "pf" #define PF_UNITS 4 @@ -509,6 +510,12 @@ int init_module(void) { int err; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pf_init(); return err; @@ -653,8 +660,7 @@ static void pf_eject( int unit ) static void pf_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index fd001008d..1563a2afc 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -34,10 +34,10 @@ To use this device, you must have the following device special files defined: - /dev/pg0 b 97 0 - /dev/pg1 b 97 1 - /dev/pg2 b 97 2 - /dev/pg3 b 97 3 + /dev/pg0 c 97 0 + /dev/pg1 c 97 1 + /dev/pg2 c 97 2 + /dev/pg3 c 97 3 (You'll need to change the 97 to something else if you use the 'major' parameter to install the driver on a different @@ -117,9 +117,11 @@ /* Changes: 1.01 GRG 1998.06.16 Bug fixes + 1.02 GRG 1998.09.24 Added jumbo support + */ -#define PG_VERSION "1.01" +#define PG_VERSION "1.02" #define PG_MAJOR 97 #define PG_NAME "pg" #define PG_UNITS 4 @@ -324,6 +326,12 @@ int init_module(void) { int err; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pg_init(); return err; @@ -349,8 +357,7 @@ void cleanup_module(void) static void pg_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pg_wait( int unit, int go, int stop, int tmo, char * msg ) diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 44c4dadfb..1a09c84b0 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -100,10 +100,11 @@ 1.02 GRG 1998.06.16 Eliminate an Ugh. 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing, extra debugging - + 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support + */ -#define PT_VERSION "1.03" +#define PT_VERSION "1.04" #define PT_MAJOR 96 #define PT_NAME "pt" #define PT_UNITS 4 @@ -328,6 +329,12 @@ int init_module(void) { int err; +#ifdef PARIDE_JUMBO + { extern paride_init(); + paride_init(); + } +#endif + err = pt_init(); return err; @@ -457,8 +464,7 @@ static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) static void pt_sleep( int cs ) { current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + cs; - schedule(); + schedule_timeout(cs); } static int pt_poll_dsc( int unit, int pause, int tmo, char *msg ) @@ -584,8 +590,8 @@ static int pt_identify( int unit ) char *ms[2] = {"master","slave"}; char mf[10], id[18]; char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0}; - char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0}; - char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0}; + char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0}; + char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0}; char buf[36]; s = pt_atapi(unit,id_cmd,36,buf,"identify"); diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index e56616a77..4e165bbd0 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -109,20 +109,16 @@ u_int dma_arb_level; /* DMA arbitration level */ static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL; int no_int_yet; -static int access_count[MAX_HD] = -{0,}; -static char ps2esdi_valid[MAX_HD] = -{0,}; -static int ps2esdi_sizes[MAX_HD << 6] = -{0,}; -static int ps2esdi_blocksizes[MAX_HD << 6] = -{0,}; +static int access_count[MAX_HD] = {0,}; +static char ps2esdi_valid[MAX_HD] = {0,}; +static int ps2esdi_sizes[MAX_HD << 6] = {0,}; +static int ps2esdi_blocksizes[MAX_HD << 6] = {0,}; static int ps2esdi_drives = 0; static struct hd_struct ps2esdi[MAX_HD << 6]; static u_short io_base; -static struct timer_list esdi_timer = -{NULL, NULL, 0, 0L, ps2esdi_reset_timer}; +static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer}; static int reset_status; +static int ps2esdi_slot = -1; int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ struct ps2esdi_i_struct { @@ -198,6 +194,51 @@ __initfunc(int ps2esdi_init(void)) } /* ps2esdi_init */ +#ifdef MODULE + +int cyl[2] = {-1,-1}; +int head[2] = {-1, -1}; +int sect[2] = {-1, -1}; + +MODULE_PARM(tp720esdi, "i"); +MODULE_PARM(cyl, "i"); +MODULE_PARM(head, "i"); +MODULE_PARM(track, "i"); + +int init_module(void) { + int drive; + + for(drive = 0; drive <= 1; drive++) { + struct ps2_esdi_i_struct *info = &ps2esdi_info[drive]; + + if (cyl[drive] != -1) { + info->cyl = info->lzone = cyl[drive]; + info->wpcom = 0; + } + if (head[drive] != -1) { + info->head = head[drive]; + info->ctl = (head[drive] > 8 ? 8 : 0); + } + if (sect[drive] != -1) info->sect = sect[drive]; + } + return ps2esdi_init(); +} + +void +cleanup_module(void) +{ + if(ps2esdi_slot) + { + mca_mark_as_unused(ps2esdi_slot); + mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); + } + release_region(io_base, 4); + free_dma(dma_arb_level); + free_irq(PS2ESDI_IRQ, NULL) + unregister_blkdev(MAJOR_NR, "ed"); +} +#endif /* MODULE */ + /* handles boot time command line parameters */ __initfunc(void tp720_setup(char *str, int *ints)) { @@ -289,6 +330,8 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored)) return; } + ps2esdi_slot = slot; + mca_mark_as_used(slot); mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); /* Found the slot - read the POS register 2 to get the necessary @@ -383,6 +426,9 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored)) } for (i = 0; i < (MAX_HD << 6); i++) ps2esdi_blocksizes[i] = 1024; + + request_dma(dma_arb_level, "ed"); + request_region(io_base, 4, "ed"); blksize_size[MAJOR_NR] = ps2esdi_blocksizes; } /* ps2esdi_geninit */ @@ -511,7 +557,7 @@ static void reset_ctrl(void) printk("%s: hard reset...\n", DEVICE_NAME); outb_p(CTRL_HARD_RESET, ESDI_CONTROL); expire = jiffies + 200; - while (jiffies < expire); + while (time_before(jiffies, expire)); outb_p(1, ESDI_CONTROL); } /* hard reset */ @@ -588,7 +634,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk) outb(CTRL_ENABLE_INTR, ESDI_CONTROL); /* do not write to the controller, if it is busy */ - for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) & + for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) & STATUS_BUSY);); #if 0 @@ -611,7 +657,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk) for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { status = inb(ESDI_STATUS); for (j = jiffies + ESDI_STAT_TIMEOUT; - (j > jiffies) && (status & STATUS_BUSY) && + time_after(j, jiffies) && (status & STATUS_BUSY) && (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { #if 0 diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c index 39b62fddd..6c1d12cb9 100644 --- a/drivers/block/sl82c105.c +++ b/drivers/block/sl82c105.c @@ -14,11 +14,6 @@ #include "ide.h" #include "ide_modes.h" -unsigned int chrp_ide_irq = 0; -int chrp_ide_ports_known = 0; -ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; -ide_ioreg_t chrp_idedma_regbase; - void ide_init_sl82c105(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; @@ -37,37 +32,3 @@ void ide_init_sl82c105(ide_hwif_t *hwif) printk("IDE control/status register: %08x\n",t32); pci_write_config_dword(dev, 0x40, 0x10ff08a1); } - -/* nobody ever calls these.. ?? -mlord - * - * Yes somebody certainly does, check asm-ppc/ide.h for the place. -DaveM - */ -void chrp_ide_probe(void) { - - struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); - - chrp_ide_ports_known = 1; - - if(pdev) { - chrp_ide_regbase[0]=pdev->base_address[0] & - PCI_BASE_ADDRESS_IO_MASK; - chrp_ide_regbase[1]=pdev->base_address[2] & - PCI_BASE_ADDRESS_IO_MASK; - chrp_idedma_regbase=pdev->base_address[4] & - PCI_BASE_ADDRESS_IO_MASK; - chrp_ide_irq=pdev->irq; - } -} - - -void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq) -{ - ide_ioreg_t port = base; - int i = 8; - - while (i--) - *p++ = port++; - *p++ = port; - if (irq != NULL) - *irq = chrp_ide_irq; -} diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index bacb3df98..247db08d6 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -22,12 +22,15 @@ #include <asm/prom.h> #include <asm/uaccess.h> #include <asm/mediabay.h> +#include <asm/feature.h> #define MAJOR_NR FLOPPY_MAJOR #include <linux/blk.h> -static int floppy_blocksizes[2] = {512}; -static int floppy_sizes[2] = {2880}; +static int floppy_blocksizes[2] = {512,512}; +static int floppy_sizes[2] = {2880,2880}; + +#define MAX_FLOPPIES 2 enum swim_state { idle, @@ -139,11 +142,12 @@ struct floppy_state { int ejected; struct wait_queue *wait; int wanted; - int in_media_bay; + struct device_node* media_bay; /* NULL when not in bay */ char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; }; -static struct floppy_state floppy_states[1]; +static struct floppy_state floppy_states[MAX_FLOPPIES]; +static int floppy_count = 0; static unsigned short write_preamble[] = { 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */ @@ -175,7 +179,7 @@ static void scan_timeout(unsigned long data); static void seek_timeout(unsigned long data); static void xfer_timeout(unsigned long data); static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs); +/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible); static void release_drive(struct floppy_state *fs); @@ -190,6 +194,7 @@ static ssize_t floppy_write(struct file *filp, const char *buf, size_t count, loff_t *ppos); static int floppy_check_change(kdev_t dev); static int floppy_revalidate(kdev_t dev); +static int swim3_add_device(struct device_node *swims); int swim3_init(void); #define IOCTL_MODE_BIT 8 @@ -212,11 +217,11 @@ static void swim3_action(struct floppy_state *fs, int action) volatile struct swim3 *sw = fs->swim3; swim3_select(fs, action); - udelay(1); + udelay(10); sw->select |= LSTRB; eieio(); - udelay(2); + udelay(20); sw->select &= ~LSTRB; eieio(); - udelay(1); + udelay(10); out_8(&sw->select, RELAX); } @@ -226,7 +231,7 @@ static int swim3_readbit(struct floppy_state *fs, int bit) int stat; swim3_select(fs, bit); - udelay(1); + udelay(10); stat = in_8(&sw->status); out_8(&sw->select, RELAX); return (stat & DATA) == 0; @@ -234,13 +239,19 @@ static int swim3_readbit(struct floppy_state *fs, int bit) static void do_fd_request(void) { - start_request(&floppy_states[0]); + int i; + for(i=0;i<floppy_count;i++) + { + if (floppy_states[i].media_bay && + check_media_bay(floppy_states[i].media_bay, MB_FD)) + continue; + start_request(&floppy_states[i]); + } sti(); } static void start_request(struct floppy_state *fs) { - int drive; unsigned long x; if (fs->state == idle && fs->wanted) { @@ -261,11 +272,6 @@ static void start_request(struct floppy_state *fs) CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors); #endif - drive = MINOR(CURRENT->rq_dev); - if (drive != 0) { - end_request(0); - continue; - } if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { end_request(0); continue; @@ -438,7 +444,7 @@ static void act(struct floppy_state *fs) case settling: /* wait for SEEK_COMPLETE to become true */ swim3_select(fs, SEEK_COMPLETE); - udelay(1); + udelay(10); out_8(&sw->intr_enable, ERROR | DATA_CHANGED); in_8(&sw->intr); /* clear DATA_CHANGED */ if (in_8(&sw->status) & DATA) { @@ -560,7 +566,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) err = in_8(&sw->error); intr = in_8(&sw->intr); #if 0 - printk(KERN_DEBUG "swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err); + printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err); #endif if ((intr & ERROR) && fs->state != do_transfer) printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", @@ -685,9 +691,11 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } +/* static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) { } +*/ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible) @@ -740,8 +748,7 @@ static int fd_eject(struct floppy_state *fs) break; } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } fs->ejected = 1; release_drive(fs); @@ -756,12 +763,20 @@ static int floppy_ioctl(struct inode *inode, struct file *filp, { struct floppy_state *fs; int err; + int devnum = MINOR(inode->i_rdev); + if (devnum >= floppy_count) + return -ENODEV; + if (((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT))) || ((cmd & 0x80) && !suser())) return -EPERM; - fs = &floppy_states[0]; + fs = &floppy_states[devnum]; + + if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + return -ENXIO; + switch (cmd) { case FDEJECT: if (fs->ref_count != 1) @@ -781,19 +796,21 @@ static int floppy_open(struct inode *inode, struct file *filp) struct floppy_state *fs; volatile struct swim3 *sw; int n, err; + int devnum = MINOR(inode->i_rdev); - if (MINOR(inode->i_rdev) != 0) + if (devnum >= floppy_count) return -ENODEV; - fs = &floppy_states[0]; + + fs = &floppy_states[devnum]; sw = fs->swim3; err = 0; if (fs->ref_count == 0) { - if (fs->in_media_bay && !check_media_bay(MB_FD)) + if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) return -ENXIO; out_8(&sw->mode, 0x95); out_8(&sw->control_bic, 0xff); out_8(&sw->reg5, 0x28); - udelay(1); + udelay(10); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); swim3_action(fs, MOTOR_ON); @@ -807,8 +824,7 @@ static int floppy_open(struct inode *inode, struct file *filp) break; } current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0)) @@ -858,9 +874,11 @@ static int floppy_release(struct inode *inode, struct file *filp) { struct floppy_state *fs; volatile struct swim3 *sw; + int devnum = MINOR(inode->i_rdev); + + if (devnum >= floppy_count) + return -ENODEV; - if (MINOR(inode->i_rdev) != 0) - return -ENXIO; /* * If filp is NULL, we're being called from blkdev_release * or after a failed mount attempt. In the former case the @@ -870,7 +888,7 @@ static int floppy_release(struct inode *inode, struct file *filp) if (filp && (filp->f_mode & (2 | OPEN_WRITE_BIT))) block_fsync (filp, filp->f_dentry); - fs = &floppy_states[0]; + fs = &floppy_states[devnum]; sw = fs->swim3; if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); @@ -882,10 +900,12 @@ static int floppy_release(struct inode *inode, struct file *filp) static int floppy_check_change(kdev_t dev) { struct floppy_state *fs; + int devnum = MINOR(dev); - if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count)) return 0; - fs = &floppy_states[0]; + + fs = &floppy_states[devnum]; return fs->ejected; } @@ -894,10 +914,16 @@ static int floppy_revalidate(kdev_t dev) struct floppy_state *fs; volatile struct swim3 *sw; int ret, n; + int devnum = MINOR(dev); - if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + if (MAJOR(dev) != MAJOR_NR || (devnum >= floppy_count)) return 0; - fs = &floppy_states[0]; + + fs = &floppy_states[devnum]; + + if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + return -ENXIO; + sw = fs->swim3; grab_drive(fs, revalidating, 0); out_8(&sw->intr_enable, 0); @@ -911,8 +937,7 @@ static int floppy_revalidate(kdev_t dev) if (signal_pending(current)) break; current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 1; - schedule(); + schedule_timeout(1); } ret = swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0; @@ -932,10 +957,12 @@ static ssize_t floppy_read(struct file *filp, char *buf, { struct inode *inode = filp->f_dentry->d_inode; struct floppy_state *fs; + int devnum = MINOR(inode->i_rdev); - if (MINOR(inode->i_rdev) != 0) + if (devnum >= floppy_count) return -ENODEV; - fs = &floppy_states[0]; + + fs = &floppy_states[devnum]; if (fs->ejected) return -ENXIO; return block_read(filp, buf, count, ppos); @@ -946,10 +973,12 @@ static ssize_t floppy_write(struct file * filp, const char * buf, { struct inode * inode = filp->f_dentry->d_inode; struct floppy_state *fs; + int devnum = MINOR(inode->i_rdev); - if (MINOR(inode->i_rdev) != 0) + if (devnum >= floppy_count) return -ENODEV; - fs = &floppy_states[0]; + + fs = &floppy_states[devnum]; if (fs->ejected) return -ENXIO; return block_write(filp, buf, count, ppos); @@ -978,50 +1007,72 @@ static struct file_operations floppy_fops = { int swim3_init(void) { - struct device_node *swims; - struct floppy_state *fs = &floppy_states[0]; - int is_3400 = 0; - - if (find_devices("media-bay") != NULL) { - /* assume this is a PB3400 */ - swims = find_devices("floppy"); - is_3400 = 1; - } else { - swims = find_devices("swim3"); + struct device_node *swim; + + swim = find_devices("floppy"); + while (swim && (floppy_count < MAX_FLOPPIES)) + { + swim3_add_device(swim); + swim = swim->next; } - if (swims == NULL) - return 0; + swim = find_devices("swim3"); + while (swim && (floppy_count < MAX_FLOPPIES)) + { + swim3_add_device(swim); + swim = swim->next; + } - if (swims->next != NULL) - printk(KERN_ERR "Warning: only using first SWIM3 floppy controller\n"); - if (swims->n_addrs != 2 || swims->n_intrs != 2) { - printk(KERN_ERR "swim3: expecting 2 addrs and 2 intrs! (%d, %d)\n", - swims->n_addrs, swims->n_intrs); + if (floppy_count > 0) + { + if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + printk(KERN_ERR "Unable to get major %d for floppy\n", + MAJOR_NR); + return -EBUSY; + } + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + blksize_size[MAJOR_NR] = floppy_blocksizes; + blk_size[MAJOR_NR] = floppy_sizes; + } + + return 0; +} + +static int swim3_add_device(struct device_node *swim) +{ + struct device_node *mediabay; + struct floppy_state *fs = &floppy_states[floppy_count]; + + if (swim->n_addrs < 2) + { + printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n", + swim->n_addrs, swim->n_intrs); return -EINVAL; } - if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { - printk(KERN_ERR "Unable to get major %d for floppy\n", - MAJOR_NR); - return -EBUSY; + if (swim->n_intrs < 2) + { + printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n", + swim->n_addrs, swim->n_intrs); + return -EINVAL; } - blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; - blksize_size[MAJOR_NR] = floppy_blocksizes; - blk_size[MAJOR_NR] = floppy_sizes; + mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? swim->parent : NULL; + if (mediabay == NULL) + feature_set(swim, FEATURE_SWIM3_enable); + memset(fs, 0, sizeof(*fs)); fs->state = idle; - fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address; - fs->dma = (struct dbdma_regs *) swims->addrs[1].address; - fs->swim3_intr = swims->intrs[0].line; - fs->dma_intr = swims->intrs[1].line; + fs->swim3 = (volatile struct swim3 *) ioremap(swim->addrs[0].address, 0x200); + fs->dma = (struct dbdma_regs *) ioremap(swim->addrs[1].address, 0x200); + fs->swim3_intr = swim->intrs[0].line; + fs->dma_intr = swim->intrs[1].line; fs->cur_cyl = -1; fs->cur_sector = -1; fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; - fs->in_media_bay = is_3400; + fs->media_bay = mediabay; fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); @@ -1029,19 +1080,26 @@ int swim3_init(void) if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr); + feature_clear(swim, FEATURE_SWIM3_enable); return -EBUSY; } +/* if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", fs->dma_intr); + feature_clear(swim, FEATURE_SWIM3_enable); return -EBUSY; } +*/ init_timer(&fs->timeout); do_floppy = NULL; - printk(KERN_INFO "fd0: SWIM3 floppy controller\n"); + printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, + mediabay ? "in media bay" : ""); + floppy_count++; + return 0; } diff --git a/drivers/block/via82c586.c b/drivers/block/via82c586.c new file mode 100644 index 000000000..28bf80c76 --- /dev/null +++ b/drivers/block/via82c586.c @@ -0,0 +1,86 @@ +/* + * linux/drivers/block/via82c586.c Version 0.01 Aug 16, 1998 + * + * Copyright (C) 1998 Michel Aubry + * Copyright (C) 1998 Andre Hedrick + * + * The VIA MVP-3 is reported OK with UDMA. + * + * VIA chips also have a single FIFO, with the same 64 bytes deep buffer (16 levels + * of 4 bytes each). + * However, VIA chips can have the buffer split either 8:8 levels, 16:0 levels or + * 0:16 levels between both channels. One could think of using this feature, as even + * if no level of FIFO is given to a given channel, one can always reach ATAPI drives + * through it, or, if one channel is unused, configuration defaults to an even split + * FIFO levels. + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/timer.h> +#include <linux/mm.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <linux/blkdev.h> +#include <linux/hdreg.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <asm/io.h> +#include "ide.h" + +/* + * Set VIA Chipset Timings for (U)DMA modes enabled. + * + * VIA Apollo chipset has complete support for + * setting up the timing parameters. + */ +static void set_via_timings (ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + byte post = hwif->channel ? 0xc0 : 0x30; + byte flush = hwif->channel ? 0xa0 : 0x50; + byte via_config = 0; + int rc = 0, errors = 0; + + printk("%s: VIA Bus-Master ", hwif->name); + + if (!hwif->dma_base) { + printk(" ERROR, NO DMA_BASE\n"); + return; + } + + /* setting IDE read prefetch buffer and IDE post write buffer. + * (This feature allows prefetched reads and post writes). + */ + if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) { + errors++; + goto via_error; + } + if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) { + errors++; + goto via_error; + } + + /* setting Channel read and End-of-sector FIFO flush. + * (This feature ensures that FIFO flush is enabled: + * - for read DMA when interrupt asserts the given channel. + * - at the end of each sector for the given channel.) + */ + if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) { + errors++; + goto via_error; + } + if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) { + errors++; + goto via_error; + } + +via_error: + printk("(U)DMA Timing Config %s\n", errors ? "ERROR" : "Success"); +} + +void ide_init_via82c586 (ide_hwif_t *hwif) +{ + set_via_timings(hwif); +} + diff --git a/drivers/block/xd.c b/drivers/block/xd.c index ccbcc0a97..2ea4bf393 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -108,9 +108,7 @@ static XD_SIGNATURE xd_sigs[] __initdata = { { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */ { 0x000B,"CRD18A Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */ { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */ - { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */ { 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */ - { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */ { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */ { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */ { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */ @@ -533,6 +531,8 @@ static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) /* xd_setup_dma: set up the DMA controller for a data transfer */ static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count) { + unsigned long f; + if (nodma) return (PIO_MODE); if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) { @@ -541,11 +541,15 @@ static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count) #endif /* DEBUG_OTHER */ return (PIO_MODE); } + + f=claim_dma_lock(); disable_dma(xd_dma); clear_dma_ff(xd_dma); set_dma_mode(xd_dma,mode); set_dma_addr(xd_dma,(u_int) buffer); set_dma_count(xd_dma,count); + + release_dma_lock(f); return (DMA_MODE); /* use DMA and INT */ } @@ -583,7 +587,7 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t int success; xdc_busy = 1; - while ((success = ((inb(port) & mask) != flags)) && (jiffies < expiry)) { + while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) { xd_timer.expires = jiffies; cli(); add_timer(&xd_timer); @@ -597,13 +601,22 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t static inline u_int xd_wait_for_IRQ (void) { + unsigned long flags; xd_watchdog_int.expires = jiffies + 8 * HZ; add_timer(&xd_watchdog_int); + + flags=claim_dma_lock(); enable_dma(xd_dma); + release_dma_lock(flags); + sleep_on(&xd_wait_int); del_timer(&xd_watchdog_int); xdc_busy = 0; + + flags=claim_dma_lock(); disable_dma(xd_dma); + release_dma_lock(flags); + if (xd_error) { printk("xd: missed IRQ - command aborted\n"); xd_error = 0; @@ -1154,7 +1167,7 @@ int init_module(void) for (i = 4; i > 0; i--) if(((xd[i] = xd[i-1]) >= 0) && !count) count = i; - if((xd[0] = count)); + if((xd[0] = count)) xd_setup(NULL, xd); xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 }); if (!xd_drives) { |