diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /drivers/block | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Config.in | 16 | ||||
-rw-r--r-- | drivers/block/Makefile | 4 | ||||
-rw-r--r-- | drivers/block/cmd646.c | 9 | ||||
-rw-r--r-- | drivers/block/floppy.c | 48 | ||||
-rw-r--r-- | drivers/block/genhd.c | 103 | ||||
-rw-r--r-- | drivers/block/hd.c | 3 | ||||
-rw-r--r-- | drivers/block/ide-cd.c | 80 | ||||
-rw-r--r-- | drivers/block/ide-cd.h | 31 | ||||
-rw-r--r-- | drivers/block/ide-disk.c | 31 | ||||
-rw-r--r-- | drivers/block/ide-pmac.c | 66 | ||||
-rw-r--r-- | drivers/block/ide-probe.c | 73 | ||||
-rw-r--r-- | drivers/block/ide.c | 36 | ||||
-rw-r--r-- | drivers/block/ide.h | 8 | ||||
-rw-r--r-- | drivers/block/ide_modes.h | 2 | ||||
-rw-r--r-- | drivers/block/ll_rw_blk.c | 7 | ||||
-rw-r--r-- | drivers/block/nbd.c | 36 | ||||
-rw-r--r-- | drivers/block/ns87415.c | 6 | ||||
-rw-r--r-- | drivers/block/rd.c | 123 | ||||
-rw-r--r-- | drivers/block/sl82c105.c | 4 | ||||
-rw-r--r-- | drivers/block/swim3.c | 119 |
20 files changed, 574 insertions, 231 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index de2ca9c88..390aa708c 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -51,13 +51,15 @@ else bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 fi fi - if [ "$CONFIG_PMAC" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDE_PMAC y - bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC - if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDEDMA y - bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO - fi + if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then + bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC + if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then + bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC + if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then + define_bool CONFIG_BLK_DEV_IDEDMA y + bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO + fi + fi fi bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 6d48ecb98..79f3a9547 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -220,6 +220,10 @@ endif ifeq ($(CONFIG_BLK_DEV_PS2),y) L_OBJS += ps2esdi.o +else + ifeq ($(CONFIG_BLK_DEV_PS2),m) + M_OBJS += ps2esdi.o + endif endif ifeq ($(CONFIG_BLK_DEV_XD),y) diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c index fe2eb10a2..57b593131 100644 --- a/drivers/block/cmd646.c +++ b/drivers/block/cmd646.c @@ -1,4 +1,4 @@ -/* $Id: cmd646.c,v 1.10 1998/08/03 15:28:42 davem Exp $ +/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $ * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because * there the "BIOS" has done all of the following already. @@ -219,8 +219,11 @@ __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif)) hwif->chipset = ide_cmd646; - /* Set a good latency timer value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 240); + /* Set a good latency timer and cache line size value. */ + (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); +#ifdef __sparc_v9__ + (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); +#endif /* Setup interrupts. */ (void) pci_read_config_byte(dev, 0x71, &mrdmode); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 4c18a79dd..2b3f38895 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3594,7 +3594,7 @@ static void config_types(void) /* read drive info out of physical CMOS */ drive=0; if (!UDP->cmos) - UDP->cmos= FLOPPY0_TYPE; + UDP->cmos = FLOPPY0_TYPE; drive=1; if (!UDP->cmos && FLOPPY1_TYPE) UDP->cmos = FLOPPY1_TYPE; @@ -3603,26 +3603,31 @@ static void config_types(void) /* additional physical CMOS drive detection should go here */ for (drive=0; drive < N_DRIVE; drive++){ - if (UDP->cmos >= 16) - UDP->cmos = 0; - if (UDP->cmos >= 0 && UDP->cmos <= NUMBER(default_drive_params)) - memcpy((char *) UDP, - (char *) (&default_drive_params[(int)UDP->cmos].params), - sizeof(struct floppy_drive_params)); - if (UDP->cmos){ - if (first) - printk(KERN_INFO "Floppy drive(s): "); - else - printk(", "); - first=0; - if (UDP->cmos > 0){ + unsigned int type = UDP->cmos; + struct floppy_drive_params *params; + const char *name = NULL; + static char temparea[32]; + + if (type < NUMBER(default_drive_params)) { + params = &default_drive_params[type].params; + if (type) { + name = default_drive_params[type].name; allowed_drive_mask |= 1 << drive; - printk("fd%d is %s", drive, - default_drive_params[(int)UDP->cmos].name); - } else - printk("fd%d is unknown type %d",drive, - UDP->cmos); + } + } else { + params = &default_drive_params[0].params; + sprintf(temparea, "unknown type %d (usb?)", type); + name = temparea; } + if (name) { + const char * prepend = ","; + if (first) { + prepend = KERN_INFO "Floppy drive(s):"; + first = 0; + } + printk("%s fd%d is %s", prepend, drive, name); + } + *UDP = *params; } if (!first) printk("\n"); @@ -4022,11 +4027,6 @@ __initfunc(static void set_cmos(int *ints, int dummy, int dummy2)) } if (current_drive >= 4 && !FDC2) FDC2 = 0x370; - if (ints[2] <= 0 || - (ints[2] >= NUMBER(default_drive_params) && ints[2] != 16)){ - DPRINT("bad CMOS code %d\n", ints[2]); - return; - } DP->cmos = ints[2]; DPRINT("setting CMOS code to %d\n", ints[2]); } diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index edb8a41cc..729c59929 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -130,6 +130,14 @@ static inline int is_extended_partition(struct partition *p) SYS_IND(p) == LINUX_EXTENDED_PARTITION); } +static int sector_partition_scale(kdev_t dev) +{ + if (hardsect_size[MAJOR(dev)] != NULL) + return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512); + else + return (1); +} + static unsigned int get_ptable_blocksize(kdev_t dev) { int ret = 1024; @@ -149,6 +157,7 @@ static unsigned int get_ptable_blocksize(kdev_t dev) * the natural blocksize for the device so that we don't have to try * and read partial sectors. Anything smaller should be just fine. */ + switch( blksize_size[MAJOR(dev)][MINOR(dev)] ) { case 2048: @@ -196,6 +205,7 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) struct partition *p; unsigned long first_sector, first_size, this_sector, this_size; int mask = (1 << hd->minor_shift) - 1; + int sector_size = sector_partition_scale(dev); int i; first_sector = hd->part[MINOR(dev)].start_sect; @@ -233,22 +243,22 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) * First process the data partition(s) */ for (i=0; i<4; i++, p++) { - if (!NR_SECTS(p) || is_extended_partition(p)) - continue; - - /* Check the 3rd and 4th entries - - these sometimes contain random garbage */ - if (i >= 2 - && START_SECT(p) + NR_SECTS(p) > this_size - && (this_sector + START_SECT(p) < first_sector || - this_sector + START_SECT(p) + NR_SECTS(p) > - first_sector + first_size)) - continue; - - add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p)); - current_minor++; - if ((current_minor & mask) == 0) - goto done; + if (!NR_SECTS(p) || is_extended_partition(p)) + continue; + + /* Check the 3rd and 4th entries - + these sometimes contain random garbage */ + if (i >= 2 + && START_SECT(p) + NR_SECTS(p) > this_size + && (this_sector + START_SECT(p) < first_sector || + this_sector + START_SECT(p) + NR_SECTS(p) > + first_sector + first_size)) + continue; + + add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); + current_minor++; + if ((current_minor & mask) == 0) + goto done; } /* * Next, process the (first) extended partition, if present. @@ -262,20 +272,21 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) */ p -= 4; for (i=0; i<4; i++, p++) - if(NR_SECTS(p) && is_extended_partition(p)) - break; + if(NR_SECTS(p) && is_extended_partition(p)) + break; if (i == 4) - goto done; /* nothing left to do */ + goto done; /* nothing left to do */ - hd->part[current_minor].nr_sects = NR_SECTS(p); - hd->part[current_minor].start_sect = first_sector + START_SECT(p); - this_sector = first_sector + START_SECT(p); + hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */ + hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size; + this_sector = first_sector + START_SECT(p) * sector_size; dev = MKDEV(hd->major, current_minor); brelse(bh); } done: brelse(bh); } + #ifdef CONFIG_SOLARIS_X86_PARTITION static void solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) { @@ -317,11 +328,13 @@ solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) { #endif #ifdef CONFIG_BSD_DISKLABEL -static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p) +static void check_and_add_bsd_partition(struct gendisk *hd, + struct bsd_partition *bsd_p, kdev_t dev) { struct hd_struct *lin_p; /* check relative position of partitions. */ - for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) { + for (lin_p = hd->part + 1 + MINOR(dev); + lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) { /* no relationship -> try again */ if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset || lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size) @@ -383,7 +396,7 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, break; if (p->p_fstype != BSD_FS_UNUSED) - check_and_add_bsd_partition(hd, p); + check_and_add_bsd_partition(hd, p, dev); } brelse(bh); @@ -436,6 +449,7 @@ static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s struct partition *p; unsigned char *data; int mask = (1 << hd->minor_shift) - 1; + int sector_size = sector_partition_scale(dev); #ifdef CONFIG_BSD_DISKLABEL /* no bsd disklabel as a default */ kdev_t bsd_kdev = 0; @@ -538,7 +552,7 @@ check_table: for (i=1 ; i<=4 ; minor++,i++,p++) { if (!NR_SECTS(p)) continue; - add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p)); + add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); if (is_extended_partition(p)) { printk(" <"); /* @@ -795,7 +809,7 @@ static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec struct sgi_partition *p; #define SGI_LABEL_MAGIC 0x0be5a941 - if(!(bh = bread(dev, 0, 1024))) { + if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition table\n", kdevname(dev)); return -1; } @@ -863,12 +877,20 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) int nr_sects; int blk; int part, res; + int old_blocksize; + int blocksize; - set_blocksize(dev,512); + old_blocksize = get_ptable_blocksize(dev); + if (hardsect_size[MAJOR(dev)] != NULL) + blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)]; + else + blocksize = 512; + + set_blocksize(dev,blocksize); res = 0; for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { - if(!(bh = bread(dev,blk,512))) { + if(!(bh = bread(dev,blk,blocksize))) { printk("Dev %s: unable to read RDB block %d\n", kdevname(dev),blk); goto rdb_done; @@ -876,16 +898,25 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { rdb = (struct RigidDiskBlock *)bh->b_data; if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { - printk("Dev %s: RDB in block %d has bad checksum\n", - kdevname(dev),blk); - brelse(bh); - continue; + /* Try again with 0xdc..0xdf zeroed, Windows might have + * trashed it. + */ + *(u32 *)(&bh->b_data[0xdc]) = 0; + if (checksum_block((u32 *)bh->b_data, + htonl(rdb->rdb_SummedLongs) & 0x7F)) { + brelse(bh); + printk("Dev %s: RDB in block %d has bad checksum\n", + kdevname(dev),blk); + continue; + } + printk("Warning: Trashed word at 0xd0 in block %d " + "ignored in checksum calculation\n",blk); } printk(" RDSK"); blk = htonl(rdb->rdb_PartitionList); brelse(bh); for (part = 1; blk > 0 && part <= 16; part++) { - if (!(bh = bread(dev,blk,512))) { + if (!(bh = bread(dev,blk,blocksize))) { printk("Dev %s: unable to read partition block %d\n", kdevname(dev),blk); goto rdb_done; @@ -918,7 +949,7 @@ amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) } rdb_done: - set_blocksize(dev,BLOCK_SIZE); + set_blocksize(dev,old_blocksize); return res; } #endif /* CONFIG_AMIGA_PARTITION */ @@ -1099,7 +1130,7 @@ static int atari_partition (struct gendisk *hd, kdev_t dev, partsect = extensect = pi->st; while (1) { - xbh = bread (dev, partsect / 2, 1024); + xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev)); if (!xbh) { printk (" block %ld read failed\n", partsect); diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 5674e3070..203c2d609 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -744,11 +744,12 @@ static void hd_geninit(struct gendisk *ignored) */ - if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) + if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) { if (cmos_disks & 0x0f) NR_HD = 2; else NR_HD = 1; + } } #endif /* __i386__ */ for (drive=0 ; drive < NR_HD ; drive++) { diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 2e1f9ba76..7e07eda65 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -33,6 +33,7 @@ * boot * -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen * of Pioneer Denmark for providing me with a drive for testing. + * -Implement Features and Profiles. * * * ---------------------------------- @@ -230,9 +231,23 @@ * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk> * - Detect DVD-ROM/RAM drives * + * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar + * drive in transfer size limit. + * - Fix the I/O error when doing eject without a medium + * loaded on some drives. + * - CDROMREADMODE2 is now implemented through + * CDROMREADRAW, since many drives don't support + * MODE2 (even though ATAPI 2.6 says they must). + * - Added ignore parameter to ide-cd (as a module), eg + * insmod ide-cd ignore='hda hdb' + * Useful when using ide-cd in conjunction with + * ide-scsi. TODO: non-modular way of doing the + * same. + * + * *************************************************************************/ -#define IDECD_VERSION "4.52" +#define IDECD_VERSION "4.53" #include <linux/module.h> #include <linux/types.h> @@ -252,7 +267,6 @@ #include "ide.h" #include "ide-cd.h" - /**************************************************************************** * Generic packet command support and error handling routines. */ @@ -1527,6 +1541,10 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag, CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; stat = 0; } + + /* no medium, that's alright. */ + if (stat != 0 && reqbuf->sense_key == NOT_READY && reqbuf->asc == 0x3a) + stat = 0; if (stat == 0) CDROM_STATE_FLAGS (drive)->door_locked = lockflag; @@ -1806,7 +1824,6 @@ cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen, return cdrom_queue_packet_command (drive, &pc); } - /* ATAPI cdrom drives are free to select the speed you request or any slower rate :-( Requesting too fast a speed will _not_ produce an error. */ static int @@ -2092,22 +2109,17 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, if (cmd == CDROMREADMODE1) { blocksize = CD_FRAMESIZE; format = 2; - } else if (cmd == CDROMREADMODE2) { - blocksize = CD_FRAMESIZE_RAW0; - format = 3; - } else { + } else { /* for RAW and MODE2. */ blocksize = CD_FRAMESIZE_RAW; format = 0; } - stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize); - if (stat) return stat; + + copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT); - copy_from_user (&msf, (void *)arg, sizeof (msf)); + lba = msf_to_lba(msf.cdmsf_min0, + msf.cdmsf_sec0, + msf.cdmsf_frame0); - lba = msf_to_lba (msf.cdmsf_min0, - msf.cdmsf_sec0, - msf.cdmsf_frame0); - /* Make sure the TOC is up to date. */ stat = cdrom_read_toc (drive, NULL); if (stat) return stat; @@ -2117,14 +2129,21 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, if (lba < 0 || lba >= toc->capacity) return -EINVAL; - buf = (char *) kmalloc (CD_FRAMESIZE_RAW, GFP_KERNEL); + buf = (char *) kmalloc (blocksize, GFP_KERNEL); if (buf == NULL) return -ENOMEM; stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize, NULL); - if (stat == 0) - copy_to_user ((char *)arg, buf, blocksize); + + if (stat == 0) { + if (cmd == CDROMREADMODE2) { + /* For Mode2, skip the Sync, Header, and Subheader */ + copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT); + } else { + copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT); + } + } kfree (buf); return stat; @@ -2486,14 +2505,12 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, static int ide_cdrom_reset (struct cdrom_device_info *cdi) { - ide_drive_t *drive = (ide_drive_t*) cdi->handle; struct request req; ide_init_drive_cmd (&req); req.cmd = RESET_DRIVE_COMMAND; return ide_do_drive_cmd (drive, &req, ide_wait); - } @@ -2501,9 +2518,10 @@ static int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) { ide_drive_t *drive = (ide_drive_t*) cdi->handle; + struct atapi_request_sense rq; if (position) { - int stat = cdrom_lockdoor (drive, 0, NULL); + int stat = cdrom_lockdoor (drive, 0, &rq); if (stat) return stat; } @@ -2980,12 +2998,14 @@ int ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->no_eject = 1; CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; - /* limit transfer size per interrupt. currently only one Samsung - drive needs this. */ + /* limit transfer size per interrupt. */ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0; - if (drive->id != NULL) - if (strcmp (drive->id->model, "SAMSUNG CD-ROM SCR-2432") == 0) + if (drive->id != NULL) { + if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; + else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) + CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; + } #if ! STANDARD_ATAPI /* by default Sanyo 3 CD changer support is turned off and @@ -3155,7 +3175,13 @@ static ide_module_t ide_cdrom_module = { NULL }; +/* options */ +char *ignore = NULL; + #ifdef MODULE +MODULE_PARM(ignore, "s"); +MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); + int init_module (void) { return ide_cdrom_init(); @@ -3183,6 +3209,12 @@ int ide_cdrom_init (void) MOD_INC_USE_COUNT; while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) { + /* skip drives that we were told to ignore */ + if (ignore != NULL) + if (strstr(ignore, drive->name)) { + printk("ide-cd: ignoring drive %s\n", drive->name); + continue; + } info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); if (info == NULL) { printk ("%s: Can't allocate a cdrom structure\n", drive->name); diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h index 289b656ba..553013b9d 100644 --- a/drivers/block/ide-cd.h +++ b/drivers/block/ide-cd.h @@ -85,6 +85,9 @@ #define MECHANISM_STATUS 0xbd #define READ_CD 0xbe +/* DVD Opcodes */ +#define DVD_GET_PERFORMANCE 0xac + /* Page codes for mode sense/set */ @@ -331,13 +334,13 @@ struct atapi_capabilities_page { #if defined(__BIG_ENDIAN_BITFIELD) __u8 reserved3 : 2; - /* Drive can fake writes */ - __u8 test_write : 1; - __u8 reserved3a : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; /* Drive can write DVD-RAM discs */ __u8 dvd_ram_write : 1; + /* Drive can write DVD-R discs */ + __u8 dvd_r_write : 1; + __u8 reserved3a : 1; + /* Drive can fake writes */ + __u8 test_write : 1; /* 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) */ @@ -347,20 +350,20 @@ struct atapi_capabilities_page { __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 */ - /* Drive can write DVD-RAM discs */ - __u8 dvd_ram_write : 1; - /* Drive can write DVD-R discs */ - __u8 dvd_r_write : 1; - __u8 reserved3a : 1; /* Drive can fake writes */ __u8 test_write : 1; + __u8 reserved3a : 1; + /* Drive can write DVD-R discs */ + __u8 dvd_r_write : 1; + /* Drive can write DVD-RAM discs */ + __u8 dvd_ram_write : 1; __u8 reserved3 : 2; #else #error "Please fix <asm/byteorder.h>" #endif #if defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved4 : 4; + __u8 reserved4 : 1; /* Drive can read multisession discs. */ __u8 multisession : 1; /* Drive can read mode 2, form 2 data. */ @@ -562,7 +565,7 @@ struct cdrom_info { /* Sector buffer. If a read request wants only the first part of a cdrom block, we cache the rest of the block here, - in the expectation that that data is going to be wanted soon. + in the expectation that the data is going to be wanted soon. SECTOR_BUFFERED is the number of the first buffered sector, and NSECTORS_BUFFERED is the number of sectors in the buffer. Before the buffer is allocated, we should have @@ -656,6 +659,7 @@ const struct { { PLAY_CD, "Play CD" }, { MECHANISM_STATUS, "Mechanism Status" }, { READ_CD, "Read CD" }, + { DVD_GET_PERFORMANCE, "Get Performance" }, }; @@ -776,7 +780,8 @@ const struct { { 0x6400, "Illegal mode for this track or incompatible medium" }, - { 0xb900, "Play operation oborted (sic)" }, + /* Following error is misspelled in ATAPI 2.6 */ + { 0xb900, "Play operation oborted [sic]" }, { 0xbf00, "Loss of streaming" }, }; diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index f84ac8f14..14ad6269e 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -101,20 +101,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id) id->cyls = lba_sects / (16 * 63); /* correct cyls */ return 1; /* lba_capacity is our only option */ } - /* - * This is a split test for drives less than 8 Gig only. - * Drives less than 8GB sometimes declare that they have 15 heads. - * This is an accounting trick (0-15) == (1-16), just an initial - * zero point difference. - */ - if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) && - ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) { - if (id->heads == 15) - id->cyls = lba_sects / (15 * 63); /* correct cyls */ - if (id->heads == 16) - id->cyls = lba_sects / (16 * 63); /* correct cyls */ - return 1; /* lba_capacity is our only option */ - } /* perform a rough sanity check on lba_sects: within 10% is "okay" */ if ((lba_sects - chs_sects) < _10_percent) { return 1; /* lba_capacity is good */ @@ -684,10 +670,15 @@ static void idedisk_setup (ide_drive_t *drive) if (id == NULL) return; - /* check for removable disks (eg. SYQUEST), ignore 'WD' drives */ - if (id->config & (1<<7)) { /* removable disk ? */ + /* + * CompactFlash cards and their brethern look just like hard drives + * to us, but they are removable and don't have a doorlock mechanism. + */ + if (drive->removable && !drive_is_flashcard(drive)) { + /* + * Removable disks (eg. SYQUEST); ignore 'WD' drives + */ if (id->model[0] != 'W' || id->model[1] != 'D') { - drive->removable = 1; drive->doorlocking = 1; } } @@ -818,12 +809,6 @@ int idedisk_init (void) MOD_INC_USE_COUNT; while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) { - - /* SunDisk drives: ignore "second" drive; can mess up non-Sun systems! FIXME */ - struct hd_driveid *id = drive->id; - if (id && id->model[0] == 'S' && id->model[1] == 'u' && drive->select.b.unit) - continue; - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); continue; diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c index f504cb9c2..d8d353d87 100644 --- a/drivers/block/ide-pmac.c +++ b/drivers/block/ide-pmac.c @@ -20,13 +20,19 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/init.h> +#include <linux/delay.h> #include <asm/prom.h> #include <asm/io.h> #include <asm/dbdma.h> #include <asm/ide.h> #include <asm/mediabay.h> #include <asm/feature.h> +#ifdef CONFIG_PMAC_PBOOK +#include <asm/adb.h> +#include <asm/pmu.h> +#endif #include "ide.h" +#include "ide_modes.h" ide_ioreg_t pmac_ide_regbase[MAX_HWIFS]; int pmac_ide_irq[MAX_HWIFS]; @@ -41,6 +47,13 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive); static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ +#ifdef CONFIG_PMAC_PBOOK +static int idepmac_notify(struct notifier_block *, unsigned long, void *); +struct notifier_block idepmac_sleep_notifier = { + idepmac_notify +}; +#endif /* CONFIG_PMAC_PBOOK */ + /* * N.B. this can't be an initfunc, because the media-bay task can * call ide_[un]register at any time. @@ -74,6 +87,23 @@ pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) } } +void pmac_ide_tuneproc(ide_drive_t *drive, byte pio) +{ + ide_pio_data_t d; + + if (_machine != _MACH_Pmac) + return; + pio = ide_get_best_pio_mode(drive, pio, 4, &d); + switch (pio) { + case 4: + out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x211025); + break; + default: + out_le32((unsigned *)(IDE_DATA_REG + 0x200), 0x2f8526); + break; + } +} + __initfunc(void pmac_ide_probe(void)) { @@ -145,9 +175,10 @@ pmac_ide_probe(void)) pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq); hwif->chipset = ide_generic; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; + hwif->tuneproc = pmac_ide_tuneproc; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - if (np->n_addrs >= 2 && np->n_intrs >= 2) { + if (np->n_addrs >= 2) { /* has a DBDMA controller channel */ pmac_ide_setup_dma(np, hwif); } @@ -156,6 +187,10 @@ pmac_ide_probe(void)) ++i; } pmac_ide_count = i; + +#ifdef CONFIG_PMAC_PBOOK + notifier_chain_register(&sleep_notifier_list, &idepmac_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC @@ -311,5 +346,32 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } return 0; } - #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + +#ifdef CONFIG_PMAC_PBOOK +static int idepmac_notify(struct notifier_block *this, + unsigned long code, void *p) +{ + int i, timeout; + + switch (code) { + case PBOOK_SLEEP: + /* do anything here?? */ + break; + case PBOOK_WAKE: + /* wait for the controller(s) to become ready */ + timeout = 5000; + for (i = 0; i < pmac_ide_count; ++i) { + unsigned long base = pmac_ide_regbase[i]; + if (check_media_bay_by_base(base, MB_CD) == -EINVAL) + continue; + while ((inb(base + 0x70) & BUSY_STAT) && timeout) { + mdelay(1); + --timeout; + } + } + break; + } + return NOTIFY_DONE; +} +#endif /* CONFIG_PMAC_PBOOK */ diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 8e0c54dc1..1d13043e8 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-probe.c Version 1.03 Dec 5, 1997 + * linux/drivers/block/ide-probe.c Version 1.04 March 10, 1999 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -17,6 +17,7 @@ * Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot * by Andrea Arcangeli * Version 1.03 fix for (hwif->chipset == ide_4drives) + * Version 1.04 fixed buggy treatments of known flash memory cards */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -84,16 +85,6 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) 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 */ if (cmd == WIN_PIDENTIFY) { @@ -124,6 +115,10 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) case ide_tape: printk ("TAPE"); break; + case ide_optical: + printk ("OPTICAL"); + drive->removable = 1; + break; default: printk("UNKNOWN (type %d)", type); break; @@ -133,6 +128,20 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) return; } + /* + * Not an ATAPI device: looks like a "regular" hard disk + */ + if (id->config & (1<<7)) + drive->removable = 1; + /* + * Prevent long system lockup probing later for non-existant + * slave drive if the hwif is actually a flash memory card of some variety: + */ + if (drive_is_flashcard(drive)) { + ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit]; + mate->present = 0; + mate->noprobe = 1; + } drive->media = ide_disk; printk("ATA DISK drive\n"); return; @@ -720,17 +729,39 @@ static int hwif_init (ide_hwif_t *hwif) } if (register_blkdev (hwif->major, hwif->name, ide_fops)) { printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); - } else if (init_irq (hwif)) { - printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq); - (void) unregister_blkdev (hwif->major, hwif->name); - } else { - init_gendisk(hwif); - blk_dev[hwif->major].data = hwif; - blk_dev[hwif->major].request_fn = rfn; - blk_dev[hwif->major].queue = ide_get_queue; - read_ahead[hwif->major] = 8; /* (4kB) */ - hwif->present = 1; /* success */ + return (hwif->present = 0); + } + + if (init_irq (hwif)) { + int i = hwif->irq; + /* + * It failed to initialise. Find the default IRQ for + * this port and try that. + */ + if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) + { + printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); + (void) unregister_blkdev (hwif->major, hwif->name); + return (hwif->present = 0); + } + if(init_irq (hwif)) + { + printk("%s: probed IRQ %d and default IRQ %d failed.\n", + hwif->name, i, hwif->irq); + (void) unregister_blkdev (hwif->major, hwif->name); + return (hwif->present = 0); + } + printk("%s: probed IRQ %d failed, using default.\n", + hwif->name, hwif->irq); } + + init_gendisk(hwif); + blk_dev[hwif->major].data = hwif; + blk_dev[hwif->major].request_fn = rfn; + blk_dev[hwif->major].queue = ide_get_queue; + read_ahead[hwif->major] = 8; /* (4kB) */ + hwif->present = 1; /* success */ + #if (DEBUG_SPINLOCK > 0) { static int done = 0; diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 456ca470f..2e703455d 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -254,6 +254,33 @@ static void init_ide_data (void) } /* + * CompactFlash cards and their brethern pretend to be removable hard disks, except: + * (1) they never have a slave unit, and + * (2) they don't have doorlock mechanisms. + * This test catches them, and is invoked elsewhere when setting appropriate config bits. + * + * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD) devices, + * so in linux 2.3.x we should change this to just treat all PCMCIA drives this way, + * and get rid of the model-name tests below (too big of an interface change for 2.2.x). + * At that time, we might also consider parameterizing the timeouts and retries, + * since these are MUCH faster than mechanical drives. -M.Lord + */ +int drive_is_flashcard (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + + if (drive->removable && id != NULL) { + if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ + || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ + || !strncmp(id->model, "SunDisk SDCFB", 13)) /* SunDisk */ + { + return 1; /* yes, it is a flash memory card */ + } + } + return 0; /* no, it is not a flash memory card */ +} + +/* * ide_system_bus_speed() returns what we think is the system VESA/PCI * bus speed (in MHz). This is used for calculating interface PIO timings. * The default is 40 for known PCI systems, 50 otherwise. @@ -786,7 +813,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat) ide_end_drive_cmd(drive, stat, err); return; } - if (stat & BUSY_STAT) { /* other bits are useless when BUSY */ + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { if (drive->media == ide_disk && (stat & ERR_STAT)) { @@ -2068,6 +2095,12 @@ static int ide_ioctl (struct inode *inode, struct file *file, (unsigned long *) &loc->start)) return -EFAULT; return 0; } + case BLKSSZGET: + /* Block size of media */ + return put_user(blksize_size[HWIF(drive)->major] + [minor&PARTN_MASK], + (int *)arg); + case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); @@ -2957,6 +2990,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); /* * Probe module */ +EXPORT_SYMBOL(drive_is_flashcard); EXPORT_SYMBOL(ide_timer_expiry); EXPORT_SYMBOL(ide_intr); EXPORT_SYMBOL(ide_geninit); diff --git a/drivers/block/ide.h b/drivers/block/ide.h index 7c0b2555b..2ca3266ec 100644 --- a/drivers/block/ide.h +++ b/drivers/block/ide.h @@ -182,6 +182,7 @@ typedef unsigned char byte; /* used everywhere */ #define ide_scsi 0x21 #define ide_disk 0x20 +#define ide_optical 0x7 #define ide_cdrom 0x5 #define ide_tape 0x1 #define ide_floppy 0x0 @@ -677,6 +678,13 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout); */ struct request **ide_get_queue (kdev_t dev); +/* + * CompactFlash cards and their brethern pretend to be removable hard disks, + * but they never have a slave unit, and they don't have doorlock mechanisms. + * This test catches them, and is invoked elsewhere when setting appropriate config bits. + */ +int drive_is_flashcard (ide_drive_t *drive); + int ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags); void ide_timer_expiry (unsigned long data); void ide_intr (int irq, void *dev_id, struct pt_regs *regs); diff --git a/drivers/block/ide_modes.h b/drivers/block/ide_modes.h index 21679622c..49a4997e3 100644 --- a/drivers/block/ide_modes.h +++ b/drivers/block/ide_modes.h @@ -15,7 +15,7 @@ * breaking the fragile cmd640.c support. */ -#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) +#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC) /* * Standard (generic) timings for PIO modes, from ATA2 specification. diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 695fcb361..bc2ed2cac 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -392,8 +392,10 @@ void make_request(int major,int rw, struct buffer_head * bh) lock_buffer(bh); - if (blk_size[major]) - if (blk_size[major][MINOR(bh->b_rdev)] < (sector + count)>>1) { + if (blk_size[major]) { + unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; + + if (maxsector < count || maxsector - count < sector) { bh->b_state &= (1 << BH_Lock); /* This may well happen - the kernel calls bread() without checking the size of the device, e.g., @@ -406,6 +408,7 @@ void make_request(int major,int rw, struct buffer_head * bh) blk_size[major][MINOR(bh->b_rdev)]); goto end_io; } + } rw_ahead = 0; /* normal case; gets changed below for READA/WRITEA */ switch (rw) { diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8b316d116..ca4e93ed0 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -17,6 +17,7 @@ * 97-4-11 Making protocol independent of endianity etc. * 97-9-13 Cosmetic changes * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines + * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl> * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -45,8 +46,9 @@ #define LO_MAGIC 0x68797548 static int nbd_blksizes[MAX_NBD]; +static int nbd_blksize_bits[MAX_NBD]; static int nbd_sizes[MAX_NBD]; -static int nbd_bytesizes[MAX_NBD]; +static u64 nbd_bytesizes[MAX_NBD]; static struct nbd_device nbd_dev[MAX_NBD]; @@ -149,7 +151,7 @@ void nbd_send_req(struct socket *sock, struct request *req) DEBUG("NBD: sending control, "); request.magic = htonl(NBD_REQUEST_MAGIC); request.type = htonl(req->cmd); - request.from = cpu_to_be64( (u64) req->sector * (u64) 512); + request.from = cpu_to_be64( (u64) req->sector << 9); request.len = htonl(req->current_nr_sectors << 9); memcpy(request.handle, &req, sizeof(req)); @@ -340,7 +342,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct nbd_device *lo; - int dev, error; + int dev, error, temp; /* Anyone capable of this syscall can do *real bad* things */ @@ -355,6 +357,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, lo = &nbd_dev[dev]; switch (cmd) { case NBD_CLEAR_SOCK: + nbd_clear_que(lo); if (lo->head || lo->tail) { printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n"); return -EBUSY; @@ -380,14 +383,25 @@ static int nbd_ioctl(struct inode *inode, struct file *file, } return error; case NBD_SET_BLKSIZE: - if ((arg & 511) || (arg > PAGE_SIZE)) + if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE)) return -EINVAL; nbd_blksizes[dev] = arg; - nbd_sizes[dev] = arg/nbd_blksizes[dev]; + temp = arg >> 9; + nbd_blksize_bits[dev] = 9; + while (temp > 1) { + nbd_blksize_bits[dev]++; + temp >>= 1; + } + nbd_sizes[dev] = nbd_bytesizes[dev] >> nbd_blksize_bits[dev]; + nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev]; return 0; case NBD_SET_SIZE: - nbd_bytesizes[dev] = arg; - nbd_sizes[dev] = arg/nbd_blksizes[dev]; + nbd_sizes[dev] = arg >> nbd_blksize_bits[dev]; + nbd_bytesizes[dev] = nbd_sizes[dev] << nbd_blksize_bits[dev]; + return 0; + case NBD_SET_SIZE_BLOCKS: + nbd_sizes[dev] = arg; + nbd_bytesizes[dev] = arg << nbd_blksize_bits[dev]; return 0; case NBD_DO_IT: if (!lo->file) @@ -404,7 +418,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, return 0; #endif case BLKGETSIZE: - return put_user(nbd_bytesizes[dev]/512, (long *) arg); + return put_user(nbd_bytesizes[dev] >> 9, (long *) arg); } return -EINVAL; } @@ -420,6 +434,7 @@ static int nbd_release(struct inode *inode, struct file *file) if (dev >= MAX_NBD) return -ENODEV; fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); lo = &nbd_dev[dev]; if (lo->refcnt <= 0) printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt); @@ -478,8 +493,9 @@ int nbd_init(void) nbd_dev[i].magic = LO_MAGIC; nbd_dev[i].flags = 0; nbd_blksizes[i] = 1024; - nbd_bytesizes[i] = 0x7fffffff; - nbd_sizes[i] = nbd_bytesizes[i]/nbd_blksizes[i]; + nbd_blksize_bits[i] = 10; + nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */ + nbd_sizes[i] = nbd_bytesizes[i] >> nbd_blksize_bits[i]; } return 0; } diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c index dbce52137..3275c0171 100644 --- a/drivers/block/ns87415.c +++ b/drivers/block/ns87415.c @@ -95,6 +95,12 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) byte stat; #endif + /* Set a good latency timer and cache line size value. */ + (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); +#ifdef __sparc_v9__ + (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10); +#endif + /* * We cannot probe for IRQ: both ports share common IRQ on INTA. * Also, leave IRQ masked during drive probing, to prevent infinite diff --git a/drivers/block/rd.c b/drivers/block/rd.c index dd1933a47..13a4307a8 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -33,11 +33,13 @@ * * Added initrd: Werner Almesberger & Hans Lermen, Feb '96 * -* 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) + * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) * - Chad Page * * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98 * + * Make block size and block size shift for RAM disks a global macro + * and set blk_size for -ENOSPC, Werner Fink <werner@suse.de>, Apr '99 */ #include <linux/config.h> @@ -47,6 +49,7 @@ #include <linux/romfs_fs.h> #include <linux/fs.h> #include <linux/kernel.h> +#include <linux/hdreg.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/mman.h> @@ -70,6 +73,15 @@ extern void wait_for_keypress(void); #define MAJOR_NR RAMDISK_MAJOR #include <linux/blk.h> +/* + * We use a block size of 512 bytes in comparision to BLOCK_SIZE + * defined in include/linux/blk.h. This because of the finer + * granularity for filling up a RAM disk. + */ +#define RDBLK_SIZE_BITS 9 +#define RDBLK_SIZE (1<<RDBLK_SIZE_BITS) + + /* The RAM disk size is now a parameter */ #define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ @@ -89,8 +101,10 @@ static int initrd_users = 0; /* Various static variables go here. Most are used only in the RAM disk code. */ -static int rd_length[NUM_RAMDISKS]; -static int rd_blocksizes[NUM_RAMDISKS]; +static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */ +static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */ +static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */ +static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ /* * Parameters for the boot-loading of the RAM disk. These are set by @@ -120,9 +134,12 @@ int initrd_below_start_ok = 0; static void rd_request(void) { unsigned int minor; - int offset, len; + unsigned long offset, len; repeat: + if (!CURRENT) + return; + INIT_REQUEST; minor = MINOR(CURRENT->rq_dev); @@ -132,14 +149,20 @@ repeat: goto repeat; } - offset = CURRENT->sector << 9; - len = CURRENT->current_nr_sectors << 9; + offset = CURRENT->sector << RDBLK_SIZE_BITS; + len = CURRENT->current_nr_sectors << RDBLK_SIZE_BITS; if ((offset + len) > rd_length[minor]) { end_request(0); goto repeat; } + if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) { + printk(KERN_INFO "RAMDISK: bad command: %d\n", CURRENT->cmd); + end_request(0); + goto repeat; + } + /* * If we're reading, fill the buffer with 0's. This is okay since * we're using protected buffers which should never get freed... @@ -158,28 +181,31 @@ repeat: static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int err; - + unsigned int minor; + if (!inode || !inode->i_rdev) return -EINVAL; + minor = MINOR(inode->i_rdev); + switch (cmd) { case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; invalidate_buffers(inode->i_rdev); break; + case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE, (long *) arg, - sizeof(long)); - if (err) - return err; - put_user(rd_length[MINOR(inode->i_rdev)] / 512, - (long *) arg); - return 0; - + return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg); + + case BLKSSZGET: /* Block size of media */ + if (!arg) return -EINVAL; + return put_user(rd_blocksizes[minor], (int *)arg); + + RO_IOCTLS(inode->i_rdev, arg); + default: - break; + return -EINVAL; }; return 0; @@ -267,7 +293,7 @@ static struct file_operations fd_fops = { rd_open, /* open */ NULL, /* flush */ rd_release, /* module needs to decrement use count */ - block_fsync /* fsync */ + block_fsync /* fsync */ }; /* This is the registration and initialization section of the RAM disk driver */ @@ -283,11 +309,16 @@ __initfunc(int rd_init(void)) blk_dev[MAJOR_NR].request_fn = &rd_request; for (i = 0; i < NUM_RAMDISKS; i++) { - rd_length[i] = (rd_size * 1024); - rd_blocksizes[i] = 1024; + /* rd_size is given in kB */ + rd_length[i] = (rd_size << BLOCK_SIZE_BITS); + rd_hardsec[i] = RDBLK_SIZE; + rd_blocksizes[i] = BLOCK_SIZE; + rd_kbsize[i] = (rd_length[i] >> BLOCK_SIZE_BITS); } - blksize_size[MAJOR_NR] = rd_blocksizes; + hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */ + blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */ + blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */ printk("RAM disk driver initialized: %d RAM disks of %dK size\n", NUM_RAMDISKS, rd_size); @@ -299,6 +330,9 @@ __initfunc(int rd_init(void)) #ifdef MODULE +MODULE_PARM (rd_size, "1i"); +MODULE_PARM_DESC(rd_size, "Size of each RAM disk."); + int init_module(void) { int error = rd_init(); @@ -429,7 +463,7 @@ done: /* * This routine loads in the RAM disk image. */ -__initfunc(static void rd_load_image(kdev_t device,int offset)) +__initfunc(static void rd_load_image(kdev_t device, int offset, int unit)) { struct inode inode, out_inode; struct file infile, outfile; @@ -442,7 +476,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) unsigned short devblocks = 0; char rotator[4] = { '|' , '/' , '-' , '\\' }; - ram_device = MKDEV(MAJOR_NR, 0); + ram_device = MKDEV(MAJOR_NR, unit); memset(&infile, 0, sizeof(infile)); memset(&inode, 0, sizeof(inode)); @@ -482,9 +516,9 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) goto done; } - if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) { + if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) { printk("RAMDISK: image too big! (%d/%d blocks)\n", - nblocks, rd_length[0] >> BLOCK_SIZE_BITS); + nblocks, rd_length[unit] >> RDBLK_SIZE_BITS); goto done; } @@ -540,7 +574,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) successful_load: invalidate_buffers(device); - ROOT_DEV = MKDEV(MAJOR_NR,0); + ROOT_DEV = MKDEV(MAJOR_NR, unit); done: if (infile.f_op->release) @@ -549,12 +583,21 @@ done: } -__initfunc(void rd_load(void)) +__initfunc(static void rd_load_disk(int n)) { +#ifdef CONFIG_BLK_DEV_INITRD + extern kdev_t real_root_dev; +#endif + if (rd_doload == 0) return; - - if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return; + + if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR +#ifdef CONFIG_BLK_DEV_INITRD + && MAJOR(real_root_dev) != FLOPPY_MAJOR +#endif + ) + return; if (rd_prompt) { #ifdef CONFIG_BLK_DEV_FD @@ -565,15 +608,24 @@ __initfunc(void rd_load(void)) wait_for_keypress(); } - rd_load_image(ROOT_DEV,rd_image_start); + rd_load_image(ROOT_DEV,rd_image_start, n); } +__initfunc(void rd_load(void)) +{ + rd_load_disk(0); +} + +__initfunc(void rd_load_secondary(void)) +{ + rd_load_disk(1); +} #ifdef CONFIG_BLK_DEV_INITRD __initfunc(void initrd_load(void)) { - rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0); + rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0,0); } #endif @@ -697,7 +749,14 @@ __initfunc(static int crd_load(struct file * fp, struct file *outfp)) { int result; - + + insize = 0; /* valid bytes in inbuf */ + inptr = 0; /* index of next byte to be processed in inbuf */ + outcnt = 0; /* bytes in output buffer */ + exit_code = 0; + bytes_out = 0; + crc = (ulg)0xffffffffL; /* shift register contents */ + crd_infp = fp; crd_outfp = outfp; inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c index 6c1d12cb9..7fca7d5d9 100644 --- a/drivers/block/sl82c105.c +++ b/drivers/block/sl82c105.c @@ -1,3 +1,4 @@ +#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/timer.h> @@ -19,7 +20,6 @@ void ide_init_sl82c105(ide_hwif_t *hwif) struct pci_dev *dev = hwif->pci_dev; unsigned short t16; unsigned int t32; - pci_read_config_word(dev, PCI_COMMAND, &t16); printk("SL82C105 command word: %x\n",t16); t16 |= PCI_COMMAND_IO; @@ -28,7 +28,9 @@ void ide_init_sl82c105(ide_hwif_t *hwif) pci_read_config_dword(dev, 0x44, &t32); printk("IDE timing: %08x, resetting to PIO0 timing\n",t32); pci_write_config_dword(dev, 0x44, 0x03e4); +#ifndef CONFIG_MBX pci_read_config_dword(dev, 0x40, &t32); printk("IDE control/status register: %08x\n",t32); pci_write_config_dword(dev, 0x40, 0x10ff08a1); +#endif /* CONFIG_MBX */ } diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 247db08d6..246405aff 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -10,6 +10,12 @@ * 2 of the License, or (at your option) any later version. */ +/* + * TODO: + * handle 2 drives + * handle GCR disks + */ + #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -52,18 +58,18 @@ enum swim_state { */ struct swim3 { REG(data); - REG(usecs); /* counts down at 1MHz */ + REG(timer); /* counts down at 1MHz */ REG(error); REG(mode); REG(select); /* controls CA0, CA1, CA2 and LSTRB signals */ - REG(reg5); + REG(setup); REG(control); /* writing bits clears them */ REG(status); /* writing bits sets them in control */ REG(intr); REG(nseek); /* # tracks to seek */ REG(ctrack); /* current track number */ REG(csect); /* current sector number */ - REG(ssize); /* sector size code?? */ + REG(gap3); /* size of gap 3 in track format */ REG(sector); /* sector # to read or write */ REG(nsect); /* # sectors to read or write */ REG(intr_enable); @@ -78,21 +84,46 @@ struct swim3 { /* Bits in control register */ #define DO_SEEK 0x80 +#define FORMAT 0x40 #define SELECT 0x20 #define WRITE_SECTORS 0x10 -#define SCAN_TRACK 0x08 +#define DO_ACTION 0x08 +#define DRIVE2_ENABLE 0x04 #define DRIVE_ENABLE 0x02 #define INTR_ENABLE 0x01 /* Bits in status register */ +#define FIFO_1BYTE 0x80 +#define FIFO_2BYTE 0x40 +#define ERROR 0x20 #define DATA 0x08 +#define RDDATA 0x04 +#define INTR_PENDING 0x02 +#define MARK_BYTE 0x01 /* Bits in intr and intr_enable registers */ -#define ERROR 0x20 +#define ERROR_INTR 0x20 #define DATA_CHANGED 0x10 #define TRANSFER_DONE 0x08 #define SEEN_SECTOR 0x04 #define SEEK_DONE 0x02 +#define TIMER_DONE 0x01 + +/* Bits in error register */ +#define ERR_DATA_CRC 0x80 +#define ERR_ADDR_CRC 0x40 +#define ERR_OVERRUN 0x04 +#define ERR_UNDERRUN 0x01 + +/* Bits in setup register */ +#define S_SW_RESET 0x80 +#define S_GCR_WRITE 0x40 +#define S_IBM_DRIVE 0x20 +#define S_TEST_MODE 0x10 +#define S_FCLK_DIV2 0x08 +#define S_GCR 0x04 +#define S_COPY_PROT 0x02 +#define S_INV_WDATA 0x01 /* Select values for swim3_action */ #define SEEK_POSITIVE 0 @@ -100,14 +131,18 @@ struct swim3 { #define STEP 1 #define MOTOR_ON 2 #define MOTOR_OFF 6 +#define INDEX 3 #define EJECT 7 +#define SETMFM 9 +#define SETGCR 13 /* Select values for swim3_select and swim3_readbit */ #define STEP_DIR 0 #define STEPPING 1 #define MOTOR_ON 2 -#define RELAX 3 +#define RELAX 3 /* also eject in progress */ #define READ_DATA_0 4 +#define TWOMEG_DRIVE 5 #define SINGLE_SIDED 6 #define DRIVE_PRESENT 7 #define DISK_IN 8 @@ -115,7 +150,25 @@ struct swim3 { #define TRACK_ZERO 10 #define TACHO 11 #define READ_DATA_1 12 +#define MFM_MODE 13 #define SEEK_COMPLETE 14 +#define ONEMEG_MEDIA 15 + +/* Definitions of values used in writing and formatting */ +#define DATA_ESCAPE 0x99 +#define GCR_SYNC_EXC 0x3f +#define GCR_SYNC_CONV 0x80 +#define GCR_FIRST_MARK 0xd5 +#define GCR_SECOND_MARK 0xaa +#define GCR_ADDR_MARK "\xd5\xaa\x00" +#define GCR_DATA_MARK "\xd5\xaa\x0b" +#define GCR_SLIP_BYTE "\x27\xaa" +#define GCR_SELF_SYNC "\x3f\xbf\x1e\x34\x3c\x3f" + +#define DATA_99 "\x99\x99" +#define MFM_ADDR_MARK "\x99\xa1\x99\xa1\x99\xa1\x99\xfe" +#define MFM_INDEX_MARK "\x99\xc2\x99\xc2\x99\xc2\x99\xfc" +#define MFM_GAP_LEN 12 struct floppy_state { enum swim_state state; @@ -153,7 +206,7 @@ static unsigned short write_preamble[] = { 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */ 0, 0, 0, 0, 0, 0, /* sync field */ 0x99a1, 0x99a1, 0x99a1, 0x99fb, /* data address mark */ - 0x990f /* init CRC generator */ + 0x990f /* no escape for 512 bytes */ }; static unsigned short write_postamble[] = { @@ -217,11 +270,11 @@ static void swim3_action(struct floppy_state *fs, int action) volatile struct swim3 *sw = fs->swim3; swim3_select(fs, action); - udelay(10); - sw->select |= LSTRB; eieio(); - udelay(20); - sw->select &= ~LSTRB; eieio(); - udelay(10); + udelay(1); + out_8(&sw->select, sw->select | LSTRB); + udelay(2); + out_8(&sw->select, sw->select & ~LSTRB); + udelay(1); out_8(&sw->select, RELAX); } @@ -328,9 +381,9 @@ static inline void scan_track(struct floppy_state *fs) swim3_select(fs, READ_DATA_0); xx = sw->intr; /* clear SEEN_SECTOR bit */ - out_8(&sw->control_bis, SCAN_TRACK); + out_8(&sw->control_bis, DO_ACTION); /* enable intr when track found */ - out_8(&sw->intr_enable, ERROR | SEEN_SECTOR); + out_8(&sw->intr_enable, ERROR_INTR | SEEN_SECTOR); set_timeout(fs, HZ, scan_timeout); /* enable timeout */ } @@ -349,7 +402,7 @@ static inline void seek_track(struct floppy_state *fs, int n) swim3_select(fs, STEP); out_8(&sw->control_bis, DO_SEEK); /* enable intr when seek finished */ - out_8(&sw->intr_enable, ERROR | SEEK_DONE); + out_8(&sw->intr_enable, ERROR_INTR | SEEK_DONE); set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */ } @@ -384,7 +437,7 @@ static inline void setup_transfer(struct floppy_state *fs) swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); out_8(&sw->sector, fs->req_sector); out_8(&sw->nsect, n); - out_8(&sw->ssize, 0); + out_8(&sw->gap3, 0); st_le32(&dr->cmdptr, virt_to_bus(cp)); if (CURRENT->cmd == WRITE) { /* Set up 3 dma commands: write preamble, data, postamble */ @@ -400,9 +453,9 @@ static inline void setup_transfer(struct floppy_state *fs) out_le16(&cp->command, DBDMA_STOP); out_le32(&dr->control, (RUN << 16) | RUN); out_8(&sw->control_bis, - (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK); + (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | DO_ACTION); /* enable intr when transfer complete */ - out_8(&sw->intr_enable, ERROR | TRANSFER_DONE); + out_8(&sw->intr_enable, ERROR_INTR | TRANSFER_DONE); set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */ } @@ -445,7 +498,7 @@ static void act(struct floppy_state *fs) /* wait for SEEK_COMPLETE to become true */ swim3_select(fs, SEEK_COMPLETE); udelay(10); - out_8(&sw->intr_enable, ERROR | DATA_CHANGED); + out_8(&sw->intr_enable, ERROR_INTR | DATA_CHANGED); in_8(&sw->intr); /* clear DATA_CHANGED */ if (in_8(&sw->status) & DATA) { /* seek_complete is not yet true */ @@ -487,7 +540,7 @@ static void scan_timeout(unsigned long data) volatile struct swim3 *sw = fs->swim3; fs->timeout_pending = 0; - out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->control_bic, DO_ACTION); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); fs->cur_cyl = -1; @@ -537,7 +590,7 @@ static void xfer_timeout(unsigned long data) fs->timeout_pending = 0; st_le32(&dr->control, RUN << 16); out_8(&sw->intr_enable, 0); - out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); if (CURRENT->cmd == WRITE) ++cp; @@ -568,13 +621,13 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if 0 printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err); #endif - if ((intr & ERROR) && fs->state != do_transfer) + if ((intr & ERROR_INTR) && fs->state != do_transfer) printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", fs->state, CURRENT->cmd, intr, err); switch (fs->state) { case locating: if (intr & SEEN_SECTOR) { - out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->control_bic, DO_ACTION); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); del_timer(&fs->timeout); @@ -622,13 +675,13 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) act(fs); break; case do_transfer: - if ((intr & (ERROR | TRANSFER_DONE)) == 0) + if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0) break; dr = fs->dma; cp = fs->dma_cmd; st_le32(&dr->control, RUN << 16); out_8(&sw->intr_enable, 0); - out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); del_timer(&fs->timeout); fs->timeout_pending = 0; @@ -636,7 +689,7 @@ static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++cp; stat = ld_le16(&cp->xfer_status); resid = ld_le16(&cp->res_count); - if (intr & ERROR) { + if (intr & ERROR_INTR) { n = fs->scount - 1 - resid / 512; if (n > 0) { CURRENT->sector += n; @@ -800,6 +853,8 @@ static int floppy_open(struct inode *inode, struct file *filp) if (devnum >= floppy_count) return -ENODEV; + if (filp == 0) + return -EIO; fs = &floppy_states[devnum]; sw = fs->swim3; @@ -809,7 +864,7 @@ static int floppy_open(struct inode *inode, struct file *filp) return -ENXIO; out_8(&sw->mode, 0x95); out_8(&sw->control_bic, 0xff); - out_8(&sw->reg5, 0x28); + out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); udelay(10); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); @@ -834,14 +889,14 @@ static int floppy_open(struct inode *inode, struct file *filp) } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL) return -EBUSY; - if (err == 0 && filp && (filp->f_flags & O_NDELAY) == 0 + if (err == 0 && (filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) { check_disk_change(inode->i_rdev); if (fs->ejected) err = -ENXIO; } - if (err == 0 && filp && (filp->f_flags & (O_WRONLY | O_RDWR))) { + if (err == 0 && (filp->f_mode & 2)) { if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) @@ -977,10 +1032,14 @@ static ssize_t floppy_write(struct file * filp, const char * buf, if (devnum >= floppy_count) return -ENODEV; - + check_disk_change(inode->i_rdev); fs = &floppy_states[devnum]; if (fs->ejected) return -ENXIO; + if (fs->write_prot < 0) + fs->write_prot = swim3_readbit(fs, WRITE_PROT); + if (fs->write_prot) + return -EROFS; return block_write(filp, buf, count, ppos); } |