diff options
Diffstat (limited to 'drivers')
75 files changed, 5666 insertions, 4988 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 8823e4c97..088980ead 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -534,6 +534,8 @@ static struct floppy_struct *_floppy = floppy_type; static unsigned char current_drive = 0; static long current_count_sectors = 0; static unsigned char sector_t; /* sector in track */ +static unsigned char in_sector_offset; /* offset within physical sector, + * expressed in units of 512 bytes */ #ifndef fd_eject #define fd_eject(x) -EINVAL @@ -2252,7 +2254,7 @@ static void request_done(int uptodate) /* Interrupt handler evaluating the result of the r/w operation */ static void rw_interrupt(void) { - int nr_sectors, ssize, eoc; + int nr_sectors, ssize, eoc, heads; if (!DRS->first_read_date) DRS->first_read_date = jiffies; @@ -2264,23 +2266,32 @@ static void rw_interrupt(void) eoc = 1; else eoc = 0; - nr_sectors = ((R_TRACK-TRACK)*_floppy->head+R_HEAD-HEAD) * - _floppy->sect + ((R_SECTOR-SECTOR+eoc) << SIZECODE >> 2) - - (sector_t % _floppy->sect) % ssize; + + if(COMMAND & 0x80) + heads = 2; + else + heads = 1; + + nr_sectors = (((R_TRACK-TRACK) * heads + + R_HEAD-HEAD) * SECT_PER_TRACK + + R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; #ifdef FLOPPY_SANITY_CHECK - if (nr_sectors > current_count_sectors + ssize - - (current_count_sectors + sector_t) % ssize + - sector_t % ssize){ + if (nr_sectors / ssize > + (in_sector_offset + current_count_sectors + ssize - 1)/ssize) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); printk("rh=%d h=%d\n", R_HEAD, HEAD); printk("rt=%d t=%d\n", R_TRACK, TRACK); - printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, - sector_t, ssize); + printk("heads=%d eoc=%d\n", heads, eoc); + printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, + sector_t, ssize); + printk("in_sector_offset=%d\n", in_sector_offset); } #endif + + nr_sectors -= in_sector_offset; INFBOUND(nr_sectors,0); SUPBOUND(current_count_sectors, nr_sectors); @@ -2473,7 +2484,7 @@ static inline int check_dma_crossing(char *start, * does not work with MT, hence we can only transfer one head at * a time */ -static int virtualdmabug_workaround() { +static void virtualdmabug_workaround(void) { int hard_sectors, end_sector; if(CT(COMMAND) == FD_WRITE) { COMMAND &= ~0x80; /* switch off multiple track mode */ @@ -2484,7 +2495,7 @@ static int virtualdmabug_workaround() { if(end_sector > SECT_PER_TRACK) { printk("too many sectors %d > %d\n", end_sector, SECT_PER_TRACK); - return 0; + return; } #endif SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points @@ -2595,7 +2606,8 @@ static int make_raw_rw_request(void) max_sector = _floppy->sect; } - aligned_sector_t = sector_t - (sector_t % _floppy->sect) % ssize; + in_sector_offset = (sector_t % _floppy->sect) % ssize; + aligned_sector_t = sector_t - in_sector_offset; max_size = CURRENT->nr_sectors; if ((raw_cmd->track == buffer_track) && (current_drive == buffer_drive) && @@ -2605,7 +2617,7 @@ static int make_raw_rw_request(void) copy_buffer(1, max_sector, buffer_max); return 1; } - } else if (aligned_sector_t != sector_t || CURRENT->nr_sectors < ssize){ + } else if (in_sector_offset || CURRENT->nr_sectors < ssize){ if (CT(COMMAND) == FD_WRITE){ if (sector_t + CURRENT->nr_sectors > ssize && sector_t + CURRENT->nr_sectors < ssize + ssize) @@ -2677,7 +2689,7 @@ static int make_raw_rw_request(void) sector_t > buffer_max || sector_t < buffer_min || ((CT(COMMAND) == FD_READ || - (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize))&& + (!in_sector_offset && CURRENT->nr_sectors >= ssize))&& max_sector > 2 * max_buffer_sectors + buffer_min && max_size + sector_t > 2 * max_buffer_sectors + buffer_min) /* not enough space */){ @@ -2694,7 +2706,7 @@ static int make_raw_rw_request(void) * is either aligned or the data already in the buffer * (buffer will be overwritten) */ #ifdef FLOPPY_SANITY_CHECK - if (sector_t != aligned_sector_t && buffer_track == -1) + if (in_sector_offset && buffer_track == -1) DPRINT("internal error offset !=0 on write\n"); #endif buffer_track = raw_cmd->track; @@ -2705,7 +2717,7 @@ static int make_raw_rw_request(void) 2*max_buffer_sectors+buffer_min-aligned_sector_t); /* round up current_count_sectors to get dma xfer size */ - raw_cmd->length = sector_t+current_count_sectors-aligned_sector_t; + raw_cmd->length = in_sector_offset+current_count_sectors; raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1; raw_cmd->length <<= 9; #ifdef FLOPPY_SANITY_CHECK diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 24f00c950..27b7d4c70 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -26,7 +26,6 @@ * (If you are using a cd changer, you may get errors in the kernel * logs that are completly expected. Don't complain to me about this, * unless you have a patch to fix it. I am working on it...) - * -Implement ide_cdrom_select_speed using the generic cdrom interface * -Fix ide_cdrom_reset so that it works (it does nothing right now) * -Query the drive to find what features are available before trying to * use them (like trying to close the tray in drives that can't). @@ -189,10 +188,19 @@ * malloc'ed but never free'd when closing the device. * -- Cleaned up the global namespace a bit by making more * functions static that should already have been. + * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl + * based on a patch for 2.0.33 by Jelle Foks + * <jelle@scintilla.utwente.nl>, a patch for 2.0.33 + * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI + * version, and my own efforts. -erik + * -- Fixed a stupid bug which egcs was kind enough to + * inform me of where "Illegal mode for this track" + * was never returned due to a comparison on data + * types of limited range. * *************************************************************************/ -#define IDECD_VERSION "4.10" +#define IDECD_VERSION "4.11" #include <linux/module.h> #include <linux/types.h> @@ -271,8 +279,7 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, printk (" Error code: 0x%02x\n", reqbuf->error_code); - if (reqbuf->sense_key >= 0 && - reqbuf->sense_key < ARY_LEN (sense_key_texts)) + if ( reqbuf->sense_key < ARY_LEN (sense_key_texts)) s = sense_key_texts[reqbuf->sense_key]; else s = "(bad sense key)"; @@ -285,7 +292,7 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, s = buf; } else { int lo, hi; - int key = (reqbuf->asc << 8); + unsigned short key = (reqbuf->asc << 8); if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) ) key |= reqbuf->ascq; @@ -496,7 +503,7 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat, } else if (sense_key == UNIT_ATTENTION) { /* Check for media change. */ cdrom_saw_media_change (drive); - printk ("%s: media changed\n", drive->name); + /*printk("%s: media changed\n",drive->name);*/ return 0; } else { /* Otherwise, print an error. */ @@ -1518,7 +1525,6 @@ cdrom_startstop (ide_drive_t *drive, int startflag, return cdrom_queue_packet_command (drive, &pc); } - static int cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity, struct atapi_request_sense *reqbuf) @@ -1721,7 +1727,6 @@ cdrom_mode_sense (ide_drive_t *drive, int pageno, int modeflag, return cdrom_queue_packet_command (drive, &pc); } - static int cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen, struct atapi_request_sense *reqbuf) @@ -1742,6 +1747,43 @@ cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen, } +/* Note that this takes speed in kbytes/second, so don't try requesting + silly speeds like 2 here. Common speeds include: + 176 kbytes/second -- 1x + 353 kbytes/second -- 2x + 387 kbytes/second -- 2.2x + 528 kbytes/second -- 3x + 706 kbytes/second -- 4x + 1400 kbytes/second -- 8x + 2800 kbytes/second -- 16x + ATAPI 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 +cdrom_select_speed (ide_drive_t *drive, int speed, + struct atapi_request_sense *reqbuf) +{ + struct packet_command pc; + memset (&pc, 0, sizeof (pc)); + pc.sense_data = reqbuf; + + if (speed < 1) + speed = 0xffff; /* set to max */ + else + speed *= 177; /* Nx to kbytes/s */ + + pc.c[0] = SET_CD_SPEED; + /* Read Drive speed in kbytes/second MSB */ + pc.c[2] = (speed >> 8) & 0xff; + /* Read Drive speed in kbytes/second LSB */ + pc.c[3] = speed & 0xff; + /* Write Drive speed in kbytes/second MSB */ + //pc.c[4] = (speed >> 8) & 0xff; + /* Write Drive speed in kbytes/second LSB */ + //pc.c[5] = speed & 0xff; + + return cdrom_queue_packet_command (drive, &pc); +} + static int cdrom_play_lba_range_1 (ide_drive_t *drive, int lba_start, int lba_end, struct atapi_request_sense *reqbuf) @@ -2429,6 +2471,44 @@ int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) return cdrom_lockdoor (drive, lock, NULL); } +static +int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed) +{ + int stat, attempts = 3; + struct { + char pad[8]; + struct atapi_capabilities_page cap; + } buf; + ide_drive_t *drive = (ide_drive_t*) cdi->handle; + struct atapi_request_sense reqbuf; + stat=cdrom_select_speed (drive, speed, &reqbuf); + if (stat<0) + return stat; + + /* Now that that is done, update the speed fields */ + do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ + if (attempts-- <= 0) + return 0; + stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0, + (char *)&buf, sizeof (buf), NULL); + } while (stat); + + /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ + if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { + CDROM_STATE_FLAGS (drive)->current_speed = + (((unsigned int)buf.cap.curspeed) + (176/2)) / 176; + CDROM_CONFIG_FLAGS (drive)->max_speed = + (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176; + } else { + CDROM_STATE_FLAGS (drive)->current_speed = + (ntohs(buf.cap.curspeed) + (176/2)) / 176; + CDROM_CONFIG_FLAGS (drive)->max_speed = + (ntohs(buf.cap.maxspeed) + (176/2)) / 176; + } + cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed; + return 0; +} + static int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) @@ -2668,14 +2748,14 @@ struct cdrom_device_ops ide_cdrom_dops = { ide_cdrom_check_media_change_real, /* media_changed */ ide_cdrom_tray_move, /* tray_move */ ide_cdrom_lock_door, /* lock_door */ - NULL, /* select_speed */ + ide_cdrom_select_speed, /* select_speed */ ide_cdrom_select_disc, /* select_disc */ ide_cdrom_get_last_session, /* get_last_session */ ide_cdrom_get_mcn, /* get_mcn */ ide_cdrom_reset, /* reset */ ide_cdrom_audio_ioctl, /* audio_ioctl */ ide_cdrom_dev_ioctl, /* dev_ioctl */ - CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK + CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */ @@ -2691,7 +2771,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) devinfo->dev = MKDEV (HWIF(drive)->major, minor); devinfo->ops = &ide_cdrom_dops; devinfo->mask = 0; - *(int *)&devinfo->speed = CDROM_CONFIG_FLAGS (drive)->max_speed; + *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed; *(int *)&devinfo->capacity = nslots; devinfo->handle = (void *) drive; strcpy(devinfo->name, drive->name); @@ -2750,11 +2830,15 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { - CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176; + CDROM_STATE_FLAGS (drive)->current_speed = + (((unsigned int)buf.cap.curspeed) + (176/2)) / 176; + CDROM_CONFIG_FLAGS (drive)->max_speed = + (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176; } else { - CDROM_STATE_FLAGS (drive)->current_speed = (ntohs(buf.cap.curspeed) + (176/2)) / 176; - CDROM_CONFIG_FLAGS (drive)->max_speed = (ntohs(buf.cap.maxspeed) + (176/2)) / 176; + CDROM_STATE_FLAGS (drive)->current_speed = + (ntohs(buf.cap.curspeed) + (176/2)) / 176; + CDROM_CONFIG_FLAGS (drive)->max_speed = + (ntohs(buf.cap.maxspeed) + (176/2)) / 176; } printk ("%s: ATAPI %dX CDROM", diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h index 53e38e1b1..140c4ccb6 100644 --- a/drivers/block/ide-cd.h +++ b/drivers/block/ide-cd.h @@ -71,7 +71,7 @@ #define MODE_SENSE_10 0x5a #define MODE_SELECT_10 0x55 #define READ_CD 0xbe - +#define SET_CD_SPEED 0xbb #define LOAD_UNLOAD 0xa6 #define MECHANISM_STATUS 0xbd @@ -431,7 +431,7 @@ char *sense_key_texts[16] = { with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */ struct { - short asc_ascq; + unsigned short asc_ascq; char *text; } sense_data_texts[] = { { 0x0000, "No additional sense information" }, diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index 4ad8bf606..8c72c791d 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -16,9 +16,11 @@ * Version 1.02 remove ", LBA" from drive identification msgs * Version 1.03 fix display of id->buf_size for big-endian * Version 1.04 add /proc configurable settings and S.M.A.R.T support + * Version 1.05 add capacity support for ATA3 >= 8GB + * Version 1.06 get boot-up messages to show full cyl count */ -#define IDEDISK_VERSION "1.04" +#define IDEDISK_VERSION "1.06" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -83,6 +85,11 @@ static int lba_capacity_is_ok (struct hd_driveid *id) unsigned long chs_sects = id->cyls * id->heads * id->sectors; unsigned long _10_percent = chs_sects / 10; + /* very large drives (8GB+) may lie about the number of cylinders */ + if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) { + 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 */ @@ -439,6 +446,7 @@ static unsigned long idedisk_capacity (ide_drive_t *drive) /* Determine capacity, and use LBA if the drive properly supports it */ if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) { if (id->lba_capacity >= capacity) { + drive->cyl = id->lba_capacity / (drive->head * drive->sect); capacity = id->lba_capacity; drive->select.b.lba = 1; } @@ -698,6 +706,10 @@ static void idedisk_setup (ide_drive_t *drive) drive->head = id->heads; drive->sect = id->sectors; } + + /* calculate drive capacity, and select LBA if possible */ + (void) idedisk_capacity (drive); + /* Correct the number of cyls if the bios value is too small */ if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) { if (drive->cyl > drive->bios_cyl) @@ -706,8 +718,6 @@ static void idedisk_setup (ide_drive_t *drive) /* fix byte-ordering of buffer size field */ id->buf_size = le16_to_cpu(id->buf_size); - (void) idedisk_capacity (drive); /* initialize LBA selection */ - printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d", drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2, drive->bios_cyl, drive->bios_head, drive->bios_sect); diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c index d8fa6edf5..9e8fd5127 100644 --- a/drivers/block/ide-pci.c +++ b/drivers/block/ide-pci.c @@ -24,7 +24,8 @@ #include "ide.h" -#define DEVID_PIIX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) +#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}) +#define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) #define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) #define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) @@ -87,7 +88,8 @@ typedef struct ide_pci_device_s { } ide_pci_device_t; static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIX, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}} }, + {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}} }, @@ -360,6 +362,13 @@ static inline void ide_scan_pci_device (unsigned int bus, unsigned int fn) || IDE_PCI_DEVID_EQ(devid, IDE_PCI_DEVID_NULL) || pcibios_read_config_dword(bus, fn, 0x08, &ccode)) return; + /* + * workaround Intel Advanced/ZP with bios <= 1.04; + * these appear in some Dell Dimension XPS's + */ + if (!hedt && IDE_PCI_DEVID_EQ(devid, DEVID_PIIXa)) + hedt = 0x80; + for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); if (d->init_hwif == IDE_IGNORE) printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 7ec27d45d..e10578508 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -134,9 +134,9 @@ #include "ide.h" #include "ide_modes.h" -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif /* CONFIG_KERNELD */ +#ifdef CONFIG_KMOD +#include <linux/kmod.h> +#endif /* CONFIG_KMOD */ static const byte ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; @@ -1505,10 +1505,10 @@ static void ide_init_module (int type) module = module->next; } revalidate_drives(); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (!found && type == IDE_PROBE_MODULE) (void) request_module("ide-probe"); -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ } static int ide_open(struct inode * inode, struct file * filp) @@ -1521,7 +1521,7 @@ static int ide_open(struct inode * inode, struct file * filp) MOD_INC_USE_COUNT; if (drive->driver == NULL) ide_init_module(IDE_DRIVER_MODULE); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (drive->driver == NULL) { if (drive->media == ide_disk) (void) request_module("ide-disk"); @@ -1532,7 +1532,7 @@ static int ide_open(struct inode * inode, struct file * filp) if (drive->media == ide_floppy) (void) request_module("ide-floppy"); } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ while (drive->busy) sleep_on(&drive->wqueue); drive->usage++; diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 01cf3923a..9f0db3b23 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -24,9 +24,6 @@ #include <linux/module.h> -#define ATOMIC_ON() do { } while (0) -#define ATOMIC_OFF() do { } while (0) - /* * The request-struct contains all necessary data * to load a nr of sectors into memory @@ -419,8 +416,6 @@ void make_request(int major,int rw, struct buffer_head * bh) * not to schedule or do something nonatomic */ spin_lock_irqsave(&io_request_lock,flags); - ATOMIC_ON(); - req = *get_queue(bh->b_rdev); if (!req) { /* MD and loop can't handle plugging without deadlocking */ @@ -480,7 +475,6 @@ void make_request(int major,int rw, struct buffer_head * bh) continue; mark_buffer_clean(bh); - ATOMIC_OFF(); spin_unlock_irqrestore(&io_request_lock,flags); return; @@ -490,7 +484,6 @@ void make_request(int major,int rw, struct buffer_head * bh) /* find an unused request. */ req = get_request(max_req, bh->b_rdev); - ATOMIC_OFF(); spin_unlock_irqrestore(&io_request_lock,flags); /* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */ @@ -665,9 +658,7 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf) } else { unsigned long flags; spin_lock_irqsave(&io_request_lock,flags); - ATOMIC_ON(); req[j] = get_request(max_req, rdev); - ATOMIC_OFF(); spin_unlock_irqrestore(&io_request_lock,flags); if (req[j] == NULL) break; diff --git a/drivers/block/md.c b/drivers/block/md.c index 4feeb0ce9..4d0ccf401 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -12,6 +12,9 @@ RAID-1/RAID-5 extensions by: Ingo Molnar, Miguel de Icaza, Gadi Oxman + + Changes for kmod by: + Cyrus Durgin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -43,8 +46,8 @@ #include <linux/blkdev.h> #include <linux/genhd.h> #include <linux/smp_lock.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #include <linux/errno.h> #include <linux/init.h> @@ -431,7 +434,7 @@ static int do_md_run (int minor, int repart) } if (!pers[pnum]) { -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD char module_name[80]; sprintf (module_name, "md-personality-%d", pnum); request_module (module_name); diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c index 6fefac06d..2b0e97450 100644 --- a/drivers/block/raid5.c +++ b/drivers/block/raid5.c @@ -837,8 +837,11 @@ static void add_stripe_bh (struct stripe_head *sh, struct buffer_head *bh, int d struct raid5_data *raid_conf = sh->raid_conf; struct buffer_head *bh_req; - if (sh->bh_new[dd_idx]) + if (sh->bh_new[dd_idx]) { printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); + printk("forcing oops.\n"); + *(int*)0=0; + } set_bit(BH_Lock, &bh->b_state); diff --git a/drivers/block/rd.c b/drivers/block/rd.c index de17158a7..a133b70cc 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -35,6 +35,9 @@ * * 4/25/96 : Made ramdisk size a parameter (default is now 4MB) * - Chad Page + * + * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98 + * */ #include <linux/config.h> @@ -344,7 +347,6 @@ identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; int nblocks = -1; - int max_blocks; unsigned char *buf; buf = kmalloc(size, GFP_KERNEL); @@ -423,17 +425,6 @@ done: fp->f_op->llseek(fp, start_block * BLOCK_SIZE, 0); fp->f_pos = start_block * BLOCK_SIZE; - if ((nblocks > 0) && blk_size[MAJOR(device)]) { - max_blocks = blk_size[MAJOR(device)][MINOR(device)]; - max_blocks -= start_block; - if (nblocks > max_blocks) { - printk(KERN_NOTICE - "RAMDISK: Restricting filesystem size " - "from %d to %d blocks.\n", - nblocks, max_blocks); - nblocks = max_blocks; - } - } kfree(buf); return nblocks; } @@ -451,6 +442,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) int nblocks, i; char *buf; unsigned short rotate = 0; + unsigned short devblocks = 0; char rotator[4] = { '|' , '/' , '-' , '\\' }; ram_device = MKDEV(MAJOR_NR, 0); @@ -508,8 +500,31 @@ __initfunc(static void rd_load_image(kdev_t device,int offset)) goto done; } - printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks); + if (blk_size[MAJOR(device)]) + devblocks = blk_size[MAJOR(device)][MINOR(device)]; + + if (devblocks == 0) { + printk(KERN_ERR "RAMDISK: could not determine device size\n"); + goto done; + } + + printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%d disk(s)] into ram disk... ", nblocks, nblocks/devblocks+1); for (i=0; i < nblocks; i++) { + if (i && (i % devblocks == 0)) { + printk("done.\n"); + rotate = 0; + invalidate_buffers(device); + if (infile.f_op->release) + infile.f_op->release(&inode, &infile); + printk("Please insert disk #%d and press ENTER\n", i/devblocks+1); + wait_for_keypress(); + if (blkdev_open(&inode, &infile) != 0) { + printk("Error opening disk.\n"); + goto done; + } + infile.f_pos = 0; + printk("Loading disk #%d... ", i/devblocks+1); + } infile.f_op->read(&infile, buf, BLOCK_SIZE, &infile.f_pos); outfile.f_op->write(&outfile, buf, BLOCK_SIZE, &outfile.f_pos); if (!(i % 16)) { diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog index 56e762e71..95d6741c5 100644 --- a/drivers/char/ChangeLog +++ b/drivers/char/ChangeLog @@ -1,3 +1,11 @@ +Thu Feb 19 14:24:08 1998 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * tty_io.c (tty_name): Remove the non-reentrant (and non-SMP safe) + version of tty_name, and rename the reentrant _tty_name + function to be tty_name. + (tty_open): Add a warning message stating callout devices + are deprecated. + Mon Dec 1 08:24:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu> * tty_io.c (tty_get_baud_rate): Print a warning syslog if the diff --git a/drivers/char/Config.in b/drivers/char/Config.in index ffb6287a7..e17a220e6 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -110,11 +110,6 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC -if [ "$CONFIG_RTC" = "y" ]; then - if [ "$ARCH" = "alpha" ]; then - bool ' ARC console time' CONFIG_RTC_ARC y - fi -fi if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then bool 'Tadpole ANA H8 Support' CONFIG_H8 fi diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c index b425ab694..94f13f8fd 100644 --- a/drivers/char/apm_bios.c +++ b/drivers/char/apm_bios.c @@ -1203,17 +1203,17 @@ __initfunc(void apm_bios_init(void)) * even though they are called in protected mode. */ set_base(gdt[APM_40 >> 3], - 0xc0000000 + ((unsigned long)0x40 << 4)); + __va((unsigned long)0x40 << 4)); set_limit(gdt[APM_40 >> 3], 4096 - (0x40 << 4)); apm_bios_entry.offset = apm_bios_info.offset; apm_bios_entry.segment = APM_CS; set_base(gdt[APM_CS >> 3], - 0xc0000000 + ((unsigned long)apm_bios_info.cseg << 4)); + __va((unsigned long)apm_bios_info.cseg << 4)); set_base(gdt[APM_CS_16 >> 3], - 0xc0000000 + ((unsigned long)apm_bios_info.cseg_16 << 4)); + __va((unsigned long)apm_bios_info.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], - 0xc0000000 + ((unsigned long)apm_bios_info.dseg << 4)); + __va((unsigned long)apm_bios_info.dseg << 4)); if (apm_bios_info.version == 0x100) { set_limit(gdt[APM_CS >> 3], 64 * 1024); set_limit(gdt[APM_CS_16 >> 3], 64 * 1024); diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 089ce7b2d..2ea9cb86f 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1384,7 +1384,7 @@ static void rs_throttle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), + printk("throttle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif @@ -1406,7 +1406,7 @@ static void rs_unthrottle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + printk("unthrottle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c index 19d10c95b..3b80c207f 100644 --- a/drivers/char/ftape/zftape/zftape-ctl.c +++ b/drivers/char/ftape/zftape/zftape-ctl.c @@ -29,9 +29,6 @@ #include <linux/mm.h> #define __NO_VERSION__ #include <linux/module.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif #include <linux/fcntl.h> #include <linux/zftape.h> diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c index 0c8a6f9eb..78a857ace 100644 --- a/drivers/char/ftape/zftape/zftape-init.c +++ b/drivers/char/ftape/zftape/zftape-init.c @@ -30,8 +30,8 @@ #include <linux/signal.h> #include <linux/major.h> #include <linux/malloc.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #include <linux/fcntl.h> #include <linux/wrapper.h> @@ -391,7 +391,7 @@ struct zft_cmpr_ops *zft_cmpr_unregister(void) int zft_cmpr_lock(int try_to_load) { if (zft_cmpr_ops == NULL) { -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (try_to_load) { request_module("zft-compressor"); if (zft_cmpr_ops == NULL) { diff --git a/drivers/char/ftape/zftape/zftape-read.c b/drivers/char/ftape/zftape/zftape-read.c index c7d319fac..91ed51423 100644 --- a/drivers/char/ftape/zftape/zftape-read.c +++ b/drivers/char/ftape/zftape/zftape-read.c @@ -24,12 +24,8 @@ * for the QIC-117 floppy-tape driver for Linux. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/mm.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif #include <linux/zftape.h> diff --git a/drivers/char/ftape/zftape/zftape-write.c b/drivers/char/ftape/zftape/zftape-write.c index 46f1ecc09..03b126f49 100644 --- a/drivers/char/ftape/zftape/zftape-write.c +++ b/drivers/char/ftape/zftape/zftape-write.c @@ -24,12 +24,8 @@ * for the QIC-117 floppy-tape driver for Linux. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/mm.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif #include <linux/zftape.h> diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c index a36903c7a..4a000e9aa 100644 --- a/drivers/char/lp_m68k.c +++ b/drivers/char/lp_m68k.c @@ -43,8 +43,8 @@ #include <linux/string.h> #include <linux/init.h> #include <asm/irq.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #ifdef CONFIG_AMIGA @@ -365,7 +365,7 @@ static int lp_open(struct inode *inode, struct file *file) if (dev >= MAX_LP) return -ENODEV; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (!lp_table[dev]) { char modname[30]; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 665b9ec9d..b3b283015 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -26,6 +26,9 @@ * Idea by Jacques Gelinas <jack@solucorp.qc.ca>, * adapted by Bjorn Ekwall <bj0rn@blox.se> * corrected by Alan Cox <alan@lxorguk.ukuu.org.uk> + * + * Changes for kmod (from kerneld): + Cyrus Durgin <cider@speakeasy.org> */ #include <linux/config.h> @@ -46,8 +49,8 @@ #include <linux/tty.h> #include <linux/selection.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif /* @@ -109,7 +112,7 @@ static int misc_open(struct inode * inode, struct file * file) while ((c != &misc_list) && (c->minor != minor)) c = c->next; if (c == &misc_list) { -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD char modname[20]; sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor); request_module(modname); diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 3d2f2b18c..a434cf405 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -420,7 +420,7 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty) tty->num_overrun++; if (tty->overrun_time < (jiffies - HZ)) { - printk("%s: %d input overrun(s)\n", _tty_name(tty, buf), + printk("%s: %d input overrun(s)\n", tty_name(tty, buf), tty->num_overrun); tty->overrun_time = jiffies; tty->num_overrun = 0; @@ -656,6 +656,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, const unsigned char *p; char *f, flags = TTY_NORMAL; int i; + char buf[64]; if (!tty->read_buf) return; @@ -693,8 +694,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, n_tty_receive_overrun(tty); break; default: - printk("%s: unknown flag %d\n", tty_name(tty), - flags); + printk("%s: unknown flag %d\n", + tty_name(tty, buf), flags); break; } } diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 26d15d182..9edca1683 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -48,7 +48,6 @@ * this driver.) */ -#include <linux/config.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> @@ -63,13 +62,6 @@ #include <asm/uaccess.h> #include <asm/system.h> -/* Adjust starting epoch if ARC console time is being used */ -#ifdef CONFIG_RTC_ARC -#define ARCFUDGE 20 -#else -#define ARCFUDGE 0 -#endif - /* * We sponge a minor off of the misc major. No need slurping * up another valuable major dev number for this. If you add @@ -126,12 +118,8 @@ unsigned char days_in_mo[] = * so that there is no possibility of conflicting with the * set_rtc_mmss() call that happens during some timer interrupts. * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) - * - * On Alpha we won't get any interrupts anyway, as they all end up - * in the system timer code. */ -#ifndef __alpha__ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* @@ -152,11 +140,9 @@ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) add_timer(&rtc_irq_timer); } } -#endif /* * Now all the various file operations that we export. - * They are all useless on Alpha... *sigh*. */ static long long rtc_llseek(struct file *file, loff_t offset, int origin) @@ -167,9 +153,6 @@ static long long rtc_llseek(struct file *file, loff_t offset, int origin) static ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) { -#ifdef __alpha__ - return -EIO; -#else struct wait_queue wait = { current, NULL }; unsigned long data; ssize_t retval; @@ -201,7 +184,6 @@ static ssize_t rtc_read(struct file *file, char *buf, remove_wait_queue(&rtc_wait, &wait); return retval; -#endif } static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, @@ -212,7 +194,6 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, struct rtc_time wtime; switch (cmd) { -#ifndef __alpha__ case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ { mask_rtc_irq_bit(RTC_AIE); @@ -260,7 +241,6 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, set_rtc_irq_bit(RTC_UIE); return 0; } -#endif case RTC_ALM_READ: /* Read the present alarm time */ { /* @@ -335,7 +315,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, sizeof(struct rtc_time))) return -EFAULT; - yrs = rtc_tm.tm_year + 1900 + ARCFUDGE; + yrs = rtc_tm.tm_year + 1900; mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ day = rtc_tm.tm_mday; hrs = rtc_tm.tm_hour; @@ -400,7 +380,6 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { return put_user(rtc_freq, (unsigned long *)arg); } -#ifndef __alpha__ case RTC_IRQP_SET: /* Set periodic IRQ rate. */ { int tmp = 0; @@ -437,7 +416,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, restore_flags(flags); return 0; } -#else /* __alpha__ */ +#ifdef __alpha__ case RTC_EPOCH_READ: /* Read the epoch. */ { return put_user (epoch, (unsigned long *)arg); @@ -467,18 +446,15 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * We enforce only one user at a time here with the open/close. * Also clear the previous interrupt data on an open, and clean * up things on a close. - * On Alpha we just open, for we don't mess with interrups anyway. */ static int rtc_open(struct inode *inode, struct file *file) { -#ifndef __alpha__ if(rtc_status & RTC_IS_OPEN) return -EBUSY; rtc_status |= RTC_IS_OPEN; rtc_irq_data = 0; -#endif return 0; } @@ -489,7 +465,6 @@ static int rtc_release(struct inode *inode, struct file *file) * in use, and clear the data. */ -#ifndef __alpha__ unsigned char tmp; unsigned long flags; @@ -510,11 +485,9 @@ static int rtc_release(struct inode *inode, struct file *file) rtc_irq_data = 0; rtc_status &= ~RTC_IS_OPEN; -#endif return 0; } -#ifndef __alpha__ static unsigned int rtc_poll(struct file *file, poll_table *wait) { poll_wait(file, &rtc_wait, wait); @@ -522,7 +495,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait) return POLLIN | POLLRDNORM; return 0; } -#endif /* * The various file operations we support. @@ -533,11 +505,7 @@ static struct file_operations rtc_fops = { rtc_read, NULL, /* No write */ NULL, /* No readdir */ -#ifdef __alpha__ - NULL, /* No select on Alpha */ -#else rtc_poll, -#endif rtc_ioctl, NULL, /* No mmap */ rtc_open, @@ -560,14 +528,12 @@ __initfunc(int rtc_init(void)) char *guess = NULL; #endif printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); -#ifndef __alpha__ if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL)) { /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); return -EIO; } -#endif misc_register(&rtc_dev); /* Check region? Naaah! Just snarf it up. */ request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); @@ -599,8 +565,8 @@ __initfunc(int rtc_init(void)) guess = "Digital UNIX"; } if (guess) - printk("rtc: %s epoch (%ld) detected\n", guess, epoch); -#else + printk("rtc: %s epoch (%lu) detected\n", guess, epoch); +#endif init_timer(&rtc_irq_timer); rtc_irq_timer.function = rtc_dropped_irq; rtc_wait = NULL; @@ -610,7 +576,6 @@ __initfunc(int rtc_init(void)) CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT); restore_flags(flags); rtc_freq = 1024; -#endif return 0; } @@ -626,7 +591,6 @@ __initfunc(int rtc_init(void)) * for something that requires a steady > 1KHz signal anyways.) */ -#ifndef __alpha__ void rtc_dropped_irq(unsigned long data) { unsigned long flags; @@ -643,7 +607,6 @@ void rtc_dropped_irq(unsigned long data) rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ restore_flags(flags); } -#endif /* * Info exported via "/proc/rtc". @@ -672,9 +635,10 @@ int get_rtc_status(char *buf) */ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", + "rtc_date\t: %04d-%02d-%02d\n" + "rtc_epoch\t: %04lu\n", tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); get_rtc_alm_time(&tm); @@ -788,12 +752,9 @@ void get_rtc_time(struct rtc_time *rtc_tm) * Account for differences between how the RTC uses the values * and how they are defined in a struct rtc_time; */ - if ((rtc_tm->tm_year += epoch - 1900) <= 69) + if ((rtc_tm->tm_year += (epoch - 1900)) <= 69) rtc_tm->tm_year += 100; - /* if ARCFUDGE == 0, the optimizer should do away with this */ - rtc_tm->tm_year -= ARCFUDGE; - rtc_tm->tm_mon--; } @@ -832,7 +793,6 @@ void get_rtc_alm_time(struct rtc_time *alm_tm) * meddles with the interrupt enable/disable bits. */ -#ifndef __alpha__ void mask_rtc_irq_bit(unsigned char bit) { unsigned char val; @@ -862,4 +822,3 @@ void set_rtc_irq_bit(unsigned char bit) rtc_irq_data = 0; restore_flags(flags); } -#endif diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 7af575780..b81a8eb8f 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -1745,7 +1745,7 @@ static void rs_throttle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), + printk("throttle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif @@ -1769,7 +1769,7 @@ static void rs_unthrottle(struct tty_struct * tty) #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + printk("unthrottle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index dcc38830f..5d100bba4 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -87,8 +87,8 @@ #include <linux/vt_kern.h> #include <linux/selection.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) @@ -127,11 +127,9 @@ static int tty_fasync(struct file * filp, int on); #endif /* - * These two routines return the name of tty. tty_name() should NOT - * be used in interrupt drivers, since it's not re-entrant. Use - * _tty_name() instead. + * This routine returns the name of tty. */ -char *_tty_name(struct tty_struct *tty, char *buf) +char *tty_name(struct tty_struct *tty, char *buf) { if (tty) sprintf(buf, "%s%d", tty->driver.name, @@ -142,13 +140,6 @@ char *_tty_name(struct tty_struct *tty, char *buf) return buf; } -char *tty_name(struct tty_struct *tty) -{ - static char buf[64]; - - return(_tty_name(tty, buf)); -} - inline int tty_paranoia_check(struct tty_struct *tty, kdev_t device, const char *routine) { @@ -213,11 +204,13 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval = 0; struct tty_ldisc o_ldisc; + char buf[64]; if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) return -EINVAL; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD /* Eduardo Blanco <ejbs@cs.cs.com.uy> */ + /* Cyrus Durgin <cider@speakeasy.org> */ if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) { char modname [20]; sprintf(modname, "tty-ldisc-%d", ldisc); @@ -254,7 +247,7 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (r < 0) panic("Couldn't open N_TTY ldisc for " "%s --- error %d.", - tty_name(tty), r); + tty_name(tty, buf), r); } } } @@ -455,7 +448,9 @@ void do_tty_hangup(void *data) void tty_hangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP - printk("%s hangup...\n", tty_name(tty)); + char buf[64]; + + printk("%s hangup...\n", tty_name(tty, buf)); #endif queue_task(&tty->tq_hangup, &tq_timer); } @@ -463,7 +458,9 @@ void tty_hangup(struct tty_struct * tty) void tty_vhangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP - printk("%s vhangup...\n", tty_name(tty)); + char buf[64]; + + printk("%s vhangup...\n", tty_name(tty, buf)); #endif do_tty_hangup((void *) tty); } @@ -950,6 +947,7 @@ static void release_dev(struct file * filp) struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; int idx; + char buf[64]; tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev")) @@ -990,7 +988,7 @@ static void release_dev(struct file * filp) #endif #ifdef TTY_DEBUG_HANGUP - printk("release_dev of %s (tty count=%d)...", tty_name(tty), + printk("release_dev of %s (tty count=%d)...", tty_name(tty, buf), tty->count); #endif @@ -1068,7 +1066,7 @@ static void release_dev(struct file * filp) break; printk("release_dev: %s: read/write wait queue active!\n", - tty_name(tty)); + tty_name(tty, buf)); schedule(); } @@ -1084,13 +1082,13 @@ static void release_dev(struct file * filp) if (pty_master) { if (--o_tty->count < 0) { printk("release_dev: bad pty slave count (%d) for %s\n", - o_tty->count, tty_name(o_tty)); + o_tty->count, tty_name(o_tty, buf)); o_tty->count = 0; } } if (--tty->count < 0) { printk("release_dev: bad tty->count (%d) for %s\n", - tty->count, tty_name(tty)); + tty->count, tty_name(tty, buf)); tty->count = 0; } @@ -1178,6 +1176,7 @@ static int tty_open(struct inode * inode, struct file * filp) int noctty, retval; kdev_t device; unsigned short saved_flags; + char buf[64]; saved_flags = filp->f_flags; retry_open: @@ -1245,7 +1244,7 @@ init_dev_done: tty->driver.subtype == PTY_TYPE_MASTER) noctty = 1; #ifdef TTY_DEBUG_HANGUP - printk("opening %s...", tty_name(tty)); + printk("opening %s...", tty_name(tty, buf)); #endif if (tty->driver.open) retval = tty->driver.open(tty, filp); @@ -1258,7 +1257,8 @@ init_dev_done: if (retval) { #ifdef TTY_DEBUG_HANGUP - printk("error %d in opening %s...", retval, tty_name(tty)); + printk("error %d in opening %s...", retval, + tty_name(tty, buf)); #endif release_dev(filp); @@ -1282,6 +1282,11 @@ init_dev_done: tty->session = current->session; tty->pgrp = current->pgrp; } + if ((tty->driver.type == TTY_DRIVER_TYPE_SERIAL) && + (tty->driver.subtype == SERIAL_TYPE_CALLOUT)) { + printk("Warning, %s opened, is a deprecated tty " + "callout device\n", tty_name(tty, buf)); + } return 0; } diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 21c09384e..735a955fc 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -45,7 +45,9 @@ void tty_wait_until_sent(struct tty_struct * tty, int timeout) struct wait_queue wait = { current, NULL }; #ifdef TTY_DEBUG_WAIT_UNTIL_SENT - printk("%s wait until sent...\n", tty_name(tty)); + char buf[64]; + + printk("%s wait until sent...\n", tty_name(tty, buf)); #endif if (!tty->driver.chars_in_buffer) return; @@ -57,7 +59,8 @@ void tty_wait_until_sent(struct tty_struct * tty, int timeout) current->timeout = (unsigned) -1; do { #ifdef TTY_DEBUG_WAIT_UNTIL_SENT - printk("waiting %s...(%d)\n", tty_name(tty), tty->driver.chars_in_buffer(tty)); + printk("waiting %s...(%d)\n", tty_name(tty, buf), + tty->driver.chars_in_buffer(tty)); #endif current->state = TASK_INTERRUPTIBLE; if (signal_pending(current)) diff --git a/drivers/misc/parport_init.c b/drivers/misc/parport_init.c index 3fc222ff9..31753dc1a 100644 --- a/drivers/misc/parport_init.c +++ b/drivers/misc/parport_init.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/malloc.h> #include <linux/init.h> -#include <linux/kerneld.h> #ifndef MODULE static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 }; diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c index 91fb8b0dc..bc39b351c 100644 --- a/drivers/misc/parport_share.c +++ b/drivers/misc/parport_share.c @@ -1,4 +1,4 @@ -/* $Id: parport_share.c,v 1.9 1998/03/16 23:44:45 ralf Exp $ +/* $Id: parport_share.c,v 1.10 1998/03/18 06:32:19 ralf Exp $ * Parallel-port resource manager code. * * Authors: David Campbell <campbell@tirian.che.curtin.edu.au> @@ -28,8 +28,8 @@ #include <asm/spinlock.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #undef PARPORT_PARANOID @@ -44,14 +44,14 @@ void (*parport_probe_hook)(struct parport *port) = NULL; /* Return a list of all the ports we know about. */ struct parport *parport_enumerate(void) { -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (portlist == NULL) { request_module("parport_lowlevel"); #ifdef CONFIG_PNP_PARPORT_MODULE request_module("parport_probe"); #endif /* CONFIG_PNP_PARPORT_MODULE */ } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ return portlist; } diff --git a/drivers/net/Config.in b/drivers/net/Config.in index ea97a5bc1..c3bcd09c5 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -49,10 +49,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then tristate 'WD80*3 support' CONFIG_WD80x3 if [ "$CONFIG_MCA" = "y" ]; then - tristate 'SMC Ultra MCA support' CONFIG_ULTRA - else - tristate 'SMC Ultra support' CONFIG_ULTRA + tristate 'SMC Ultra MCA support' CONFIG_ULTRAMCA fi + tristate 'SMC Ultra support' CONFIG_ULTRA tristate 'SMC Ultra32 EISA support' CONFIG_ULTRA32 tristate 'SMC 9194 support' CONFIG_SMC9194 fi diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5856b0f35..8d3f1f40b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -158,9 +158,6 @@ endif ifeq ($(CONFIG_ULTRA),y) L_OBJS += smc-ultra.o CONFIG_8390_BUILTIN = y - ifeq ($(CONFIG_MCA),y) - L_OBJS += smc-mca.o - endif else ifeq ($(CONFIG_ULTRA),m) CONFIG_8390_MODULE = y @@ -168,6 +165,16 @@ else endif endif +ifeq ($(CONFIG_ULTRAMCA),y) +L_OBJS += smc-mca.o +CONFIG_8390_BUILTIN = y +else + ifeq ($(CONFIG_ULTRAMCA),m) + CONFIG_8390_MODULE = y + M_OBJS += smc-mca.o + endif +endif + ifeq ($(CONFIG_ULTRA32),y) L_OBJS += smc-ultra32.o CONFIG_8390_BUILTIN = y diff --git a/drivers/net/Space.c b/drivers/net/Space.c index e5a98378b..9d880aa4d 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -43,6 +43,7 @@ extern int tulip_probe(struct device *dev); extern int hp100_probe(struct device *dev); extern int ultra_probe(struct device *dev); +extern int ultra32_probe(struct device *dev); extern int ultramca_probe(struct device *dev); extern int wd_probe(struct device *dev); extern int el2_probe(struct device *dev); @@ -135,13 +136,13 @@ __initfunc(static int ethif_probe(struct device *dev)) #endif #if defined(CONFIG_ULTRA) && ultra_probe(dev) -#if defined(CONFIG_MCA) +#endif +#if defined(CONFIG_ULTRAMCA) && ultramca_probe(dev) #endif #if defined(CONFIG_ULTRA32) && ultra32_probe(dev) #endif -#endif #if defined(CONFIG_SMC9194) && smc_init(dev) #endif diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c index ed2652b96..6bd5be8b7 100644 --- a/drivers/net/de4x5.c +++ b/drivers/net/de4x5.c @@ -213,7 +213,7 @@ insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'. - For a compiled in driver, somewhere in this file, place e.g. + For a compiled in driver, at or above line 526, place e.g. #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP" Yes, I know full duplex isn't permissible on BNC or AUI; they're just @@ -371,11 +371,14 @@ 0.533 9-Jan-98 Fix more 64 bit bugs reported by <jal@cs.brown.edu>. 0.534 24-Jan-98 Fix last (?) endian bug from <Geert.Uytterhoeven@cs.kuleuven.ac.be> + 0.535 21-Feb-98 Fix Ethernet Address PROM reset bug for DC21040. + 0.536 21-Mar-98 Change pci_probe() to use the pci_dev structure. + **Incompatible with 2.0.x from here.** ========================================================================= */ -static const char *version = "de4x5.c:V0.534 1998/1/24 davies@maniac.ultranet.com\n"; +static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com\n"; #include <linux/module.h> @@ -390,11 +393,15 @@ static const char *version = "de4x5.c:V0.534 1998/1/24 davies@maniac.ultranet.co #include <linux/bios32.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/init.h> +#include <linux/version.h> + #include <asm/bitops.h> #include <asm/io.h> #include <asm/dma.h> #include <asm/byteorder.h> #include <asm/unaligned.h> +#include <asm/uaccess.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -408,31 +415,6 @@ static const char *version = "de4x5.c:V0.534 1998/1/24 davies@maniac.ultranet.co #include "de4x5.h" #define c_char const char - -#include <linux/version.h> -#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) -# define __initfunc(__arginit) __arginit -# define test_and_set_bit set_bit -# define net_device_stats enet_statistics -# define copy_to_user(a,b,c) memcpy_tofs(a,b,c) -# define copy_from_user(a,b,c) memcpy_fromfs(a,b,c) -# define le16_to_cpu(a) cpu_to_le16(a) -# define le32_to_cpu(a) cpu_to_le32(a) -# ifdef __powerpc__ -# define cpu_to_le16(a) ((((a) & 0x00ffU) << 8) | (((a) & 0xff00U) >> 8)) -# define cpu_to_le32(a) ((((a) & 0x000000ffU) << 24) |\ - (((a) & 0x0000ff00U) << 8) |\ - (((a) & 0x00ff0000U) >> 8) |\ - (((a) & 0xff000000U) >> 24)) -# else -# define cpu_to_le16(a) (a) -# define cpu_to_le32(a) (a) -# endif /* __powerpc__ */ -# include <asm/segment.h> -#else -# include <asm/uaccess.h> -# include <linux/init.h> -#endif /* LINUX_VERSION_CODE */ #define TWIDDLE(a) (u_short)le16_to_cpu(get_unaligned((u_short *)(a))) /* @@ -538,8 +520,8 @@ static int de4x5_debug = (DEBUG_MEDIA | DEBUG_VERSION); ** insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'. ** ** For a compiled in driver, place e.g. -** #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP" -** somewhere in this file above this point. +** #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP" +** here */ #ifdef DE4X5_PARM static char *args = DE4X5_PARM; @@ -592,6 +574,12 @@ struct parameters { #define DE4X5_NAME_LENGTH 8 /* +** Ethernet PROM defines for DC21040 +*/ +#define PROBE_LENGTH 32 +#define ETH_PROM_SIG 0xAA5500FFUL + +/* ** PCI Bus defines */ #define PCI_MAX_BUS_NUM 8 @@ -912,6 +900,7 @@ static int test_tp(struct device *dev, s32 msec); static int EISA_signature(char *name, s32 eisa_id); static int PCI_signature(char *name, struct bus_type *lp); static void DevicePresent(u_long iobase); +static void enet_addr_rst(u_long aprom_addr); static int de4x5_bad_srom(struct bus_type *lp); static short srom_rd(u_long address, u_char offset); static void srom_latch(u_int command, u_long address); @@ -981,11 +970,9 @@ static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)); static int count_adapters(void); static int loading_module = 1; -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) MODULE_PARM(de4x5_debug, "i"); MODULE_PARM(dec_only, "i"); MODULE_PARM(args, "s"); -#endif /* LINUX_VERSION_CODE */ # else static int loading_module = 0; #endif /* MODULE */ @@ -1507,9 +1494,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev) cli(); test_and_set_bit(0, (void*)&dev->tbusy); load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb); -#if LINUX_VERSION_CODE >= ((2 << 16) | (1 << 8)) lp->stats.tx_bytes += skb->len; -#endif outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */ lp->tx_new = (++lp->tx_new) % lp->txRingSize; @@ -1559,9 +1544,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs) printk("%s: Re-entering the interrupt handler.\n", dev->name); DISABLE_IRQs; /* Ensure non re-entrancy */ -#if LINUX_VERSION_CODE >= ((2 << 16) | (1 << 8)) synchronize_irq(); -#endif dev->interrupt = MASK_INTERRUPTS; for (limit=0; limit<8; limit++) { @@ -1659,9 +1642,7 @@ de4x5_rx(struct device *dev) /* Update stats */ lp->stats.rx_packets++; -#if LINUX_VERSION_CODE >= ((2 << 16) | (1 << 8)) lp->stats.rx_bytes += pkt_len; -#endif de4x5_local_stats(dev, skb->data, pkt_len); } } @@ -2042,7 +2023,7 @@ eisa_probe(struct device *dev, u_long ioaddr)) outl(0x00006000, PCI_CFLT); outl(iobase, PCI_CBIO); - DevicePresent(DE4X5_APROM); + DevicePresent(EISA_APROM); if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) { dev->irq = irq; if ((status = de4x5_hw_init(dev, iobase)) == 0) { @@ -2081,11 +2062,12 @@ eisa_probe(struct device *dev, u_long ioaddr)) __initfunc(static void pci_probe(struct device *dev, u_long ioaddr)) { - u_char pb, pbus, dev_num, dnum, dev_fn, timer, tirq; - u_short dev_id, vendor, index, status; - u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE; + u_char pb, pbus, dev_num, dnum, dev_fn, timer; + u_short vendor, index, status; + u_int irq = 0, device, class = DE4X5_CLASS_CODE; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ struct bus_type *lp = &bus; + struct pci_dev *pdev; if (lastPCI == NO_MORE_PCI) return; @@ -2109,96 +2091,77 @@ pci_probe(struct device *dev, u_long ioaddr)) (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND); index++) { dev_num = PCI_SLOT(dev_fn); - if ((!pbus && !dnum) || ((pbus == pb) && (dnum == dev_num))) { -#ifdef __sparc_v9__ - struct pci_dev *pdev; - for (pdev = pci_devices; pdev; pdev = pdev->next) { - if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break; - } -#endif - device = 0; - pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id); - device = dev_id; - device <<= 8; - if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) { - continue; - } - - /* Search for an SROM on this bus */ - if (lp->bus_num != pb) { - lp->bus_num = pb; - srom_search(index); - } + if ((pbus || dnum) && ((pbus != pb) || (dnum != dev_num))) continue; + for (pdev = pci_devices; pdev; pdev = pdev->next) { + if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break; + } - /* Get the chip configuration revision register */ - pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv); + vendor = pdev->vendor; + device = pdev->device << 8; + if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; - /* Set the device number information */ - lp->device = dev_num; + /* Search for an SROM on this bus */ + if (lp->bus_num != pb) { lp->bus_num = pb; + srom_search(index); + } + + /* Get the chip configuration revision register */ + pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv); + + /* Set the device number information */ + lp->device = dev_num; + lp->bus_num = pb; - /* Set the chipset information */ - if (is_DC2114x) device |= (cfrv & CFRV_RN); - lp->chipset = device; + /* Set the chipset information */ + if (is_DC2114x) device |= (cfrv & CFRV_RN); + lp->chipset = device; - /* Get the board I/O address (64 bits on sparc64) */ -#ifndef __sparc_v9__ - pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp); - iobase = tmp; -#else - iobase = pdev->base_address[0]; -#endif - iobase &= CBIO_MASK; + /* Get the board I/O address (64 bits on sparc64) */ + iobase = pdev->base_address[0] & CBIO_MASK; - /* Fetch the IRQ to be used */ -#ifndef __sparc_v9__ - pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq); - irq = tirq; -#else - irq = pdev->irq; -#endif - if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; + /* Fetch the IRQ to be used */ + irq = pdev->irq; + if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; - /* Check if I/O accesses and Bus Mastering are enabled */ - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); + /* Check if I/O accesses and Bus Mastering are enabled */ + pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); #ifdef __powerpc__ - if (!(status & PCI_COMMAND_IO)) { - status |= PCI_COMMAND_IO; - pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - } + if (!(status & PCI_COMMAND_IO)) { + status |= PCI_COMMAND_IO; + pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); + pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); + } #endif /* __powerpc__ */ - if (!(status & PCI_COMMAND_IO)) continue; + if (!(status & PCI_COMMAND_IO)) continue; - if (!(status & PCI_COMMAND_MASTER)) { - status |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); - } - if (!(status & PCI_COMMAND_MASTER)) continue; + if (!(status & PCI_COMMAND_MASTER)) { + status |= PCI_COMMAND_MASTER; + pcibios_write_config_word(pb, PCI_DEVICE, PCI_COMMAND, status); + pcibios_read_config_word(pb, PCI_DEVICE, PCI_COMMAND, &status); + } + if (!(status & PCI_COMMAND_MASTER)) continue; - /* Check the latency timer for values >= 0x60 */ - pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer); - if (timer < 0x60) { - pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60); - } + /* Check the latency timer for values >= 0x60 */ + pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer); + if (timer < 0x60) { + pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60); + } - DevicePresent(DE4X5_APROM); - if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { - dev->irq = irq; - if ((status = de4x5_hw_init(dev, iobase)) == 0) { - num_de4x5s++; - if (loading_module) { - link_modules(lastModule, dev); - lastPCI = index; - } - return; + DevicePresent(DE4X5_APROM); + if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) { + dev->irq = irq; + if ((status = de4x5_hw_init(dev, iobase)) == 0) { + num_de4x5s++; + if (loading_module) { + link_modules(lastModule, dev); + lastPCI = index; } - } else if (ioaddr != 0) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, - iobase); + return; } + } else if (ioaddr != 0) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, + iobase); } } @@ -2216,12 +2179,13 @@ pci_probe(struct device *dev, u_long ioaddr)) __initfunc(static void srom_search(int index)) { - u_char pb, dev_fn, tirq; - u_short dev_id, dev_num, vendor, status; - u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE; + u_char pb, dev_fn; + u_short dev_num, vendor, status; + u_int irq = 0, device, class = DE4X5_CLASS_CODE; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ int i, j; struct bus_type *lp = &bus; + struct pci_dev *pdev; for (; (pcibios_find_class(class, index, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND); @@ -2229,20 +2193,13 @@ srom_search(int index)) if (lp->bus_num != pb) return; dev_num = PCI_SLOT(dev_fn); -#ifdef __sparc_v9__ - struct pci_dev *pdev; for (pdev = pci_devices; pdev; pdev = pdev->next) { if ((pdev->bus->number == pb) && (pdev->devfn == dev_fn)) break; } -#endif - device = 0; - pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id); - device = dev_id; - device <<= 8; - if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) { - continue; - } + + vendor = pdev->vendor; + device = pdev->device << 8; + if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue; /* Get the chip configuration revision register */ pcibios_read_config_dword(pb, PCI_DEVICE, PCI_REVISION_ID, &cfrv); @@ -2256,21 +2213,10 @@ srom_search(int index)) lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ -#ifndef __sparc_v9__ - pcibios_read_config_dword(pb, PCI_DEVICE, PCI_BASE_ADDRESS_0, &tmp); - iobase = tmp; -#else - iobase = pdev->base_address[0]; -#endif - iobase &= CBIO_MASK; + iobase = pdev->base_address[0] & CBIO_MASK; /* Fetch the IRQ to be used */ -#ifndef __sparc_v9__ - pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq); - irq = tirq; -#else irq = pdev->irq; -#endif if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; /* Check if I/O accesses are enabled */ @@ -3982,7 +3928,11 @@ DevicePresent(u_long aprom_addr) struct bus_type *lp = &bus; if (lp->chipset == DC21040) { - outl(0, aprom_addr); /* Reset Ethernet Address ROM Pointer */ + if (lp->bus == EISA) { + enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */ + } else { + outl(0, aprom_addr); /* Reset Ethernet Address ROM Pointer */ + } } else { /* Read new srom */ u_short tmp, *p = (short *)((char *)&lp->srom + SROM_HWADD); for (i=0; i<(ETH_ALEN>>1); i++) { @@ -4006,6 +3956,45 @@ DevicePresent(u_long aprom_addr) } /* +** Since the write on the Enet PROM register doesn't seem to reset the PROM +** pointer correctly (at least on my DE425 EISA card), this routine should do +** it...from depca.c. +*/ +static void +enet_addr_rst(u_long aprom_addr) +{ + union { + struct { + u32 a; + u32 b; + } llsig; + char Sig[sizeof(u32) << 1]; + } dev; + short sigLength=0; + s8 data; + int i, j; + + dev.llsig.a = ETH_PROM_SIG; + dev.llsig.b = ETH_PROM_SIG; + sigLength = sizeof(u32) << 1; + + for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) { + data = inb(aprom_addr); + if (dev.Sig[j] == data) { /* track signature */ + j++; + } else { /* lost signature; begin search again */ + if (data == dev.Sig[0]) { /* rare case.... */ + j=1; + } else { + j=0; + } + } + } + + return; +} + +/* ** For the bad status case and no SROM, then add one to the previous ** address. However, need to add one backwards in case we have 0xff ** as one or more of the bytes. Only the last 3 bytes should be checked @@ -5665,9 +5654,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd) #define LP(a) ((struct de4x5_private *)(a)) static struct device *mdev = NULL; static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) MODULE_PARM(io, "i"); -#endif /* LINUX_VERSION_CODE */ int init_module(void) @@ -5730,16 +5717,18 @@ unlink_modules(struct device *p) static int count_adapters(void) { - int i, j; + int i, j=0; char name[DE4X5_STRLEN]; - u_char pb, dev_fn, dev_num; - u_short dev_id, vendor; + u_char pb, dev_fn; + u_short vendor; u_int class = DE4X5_CLASS_CODE; u_int device; + struct pci_dev *pdev; + #ifndef __sparc_v9__ u_long iobase = 0x1000; - for (j=0, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) { + for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) { if (EISA_signature(name, EISA_ID)) j++; } #endif @@ -5748,12 +5737,12 @@ count_adapters(void) for (i=0; (pcibios_find_class(class, i, &pb, &dev_fn)!= PCIBIOS_DEVICE_NOT_FOUND); i++) { - dev_num = PCI_SLOT(dev_fn); - device = 0; - pcibios_read_config_word(pb, PCI_DEVICE, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pb, PCI_DEVICE, PCI_DEVICE_ID, &dev_id); - device = dev_id; - device <<= 8; + for (pdev = pci_devices; pdev; pdev = pdev->next) { + if ((pdev->bus->number==pb) && (pdev->devfn==dev_fn)) break; + } + + vendor = pdev->vendor; + device = pdev->device << 8; if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++; } diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 9a33ea3a4..156a07ba2 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -1348,7 +1348,7 @@ speedo_rx(struct device *dev) #if (LINUX_VERSION_CODE >= VERSION(1,3,44)) if (! rx_in_place) { skb_reserve(skb, 2); /* 16 byte align the data fields */ -#if defined(__i386) && notyet +#if defined(__i386__) && notyet /* Packet is in one chunk -- we can copy + cksum. */ eth_io_copy_and_sum(skb, bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), pkt_len, 0); diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index cb6b1bb69..0f1bdd3c7 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1,51 +1,77 @@ /* - ** hp100.c - ** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters - ** - ** $Id: hp100.c,v 1.14 1997/11/16 13:57:28 alan Exp $ - ** - ** Based on the HP100 driver written by Jaroslav Kysela <perex@jcu.cz> - ** Extended for new busmaster capable chipsets by - ** Siegfried "Frieder" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de> - ** - ** Maintained by: Jaroslav Kysela <perex@jcu.cz> - ** - ** This driver has only been tested with - ** -- HP J2585B 10/100 Mbit/s PCI Busmaster - ** -- HP J2585A 10/100 Mbit/s PCI - ** -- HP J2970 10 Mbit/s PCI Combo 10base-T/BNC - ** -- HP J2973 10 Mbit/s PCI 10base-T - ** -- HP J2573 10/100 ISA - ** -- Compex ReadyLink ENET100-VG4 10/100 Mbit/s PCI / EISA - ** - ** but it should also work with the other CASCADE based adapters. - ** - ** TODO: - ** - J2573 seems to hang sometimes when in shared memory mode. - ** - Mode for Priority TX - ** - Check PCI registers, performance might be improved? - ** - To reduce interrupt load in busmaster, one could switch off - ** the interrupts that are used to refill the queues whenever the - ** queues are filled up to more than a certain threshold. - ** - ** - ** This source/code is public free; you can distribute it and/or modify - ** it under terms of the GNU General Public License (published by the - ** Free Software Foundation) either version two of this License, or any - ** later version. - ** - */ - -#define HP100_DEFAULT_PRIORITY_TX 0 +** hp100.c +** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters +** +** $Id: hp100.c,v 1.56 1998/03/04 15:23:59 perex Exp perex $ +** +** Based on the HP100 driver written by Jaroslav Kysela <perex@jcu.cz> +** Extended for new busmaster capable chipsets by +** Siegfried "Frieder" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de> +** +** Maintained by: Jaroslav Kysela <perex@jcu.cz> +** +** This driver has only been tested with +** -- HP J2585B 10/100 Mbit/s PCI Busmaster +** -- HP J2585A 10/100 Mbit/s PCI +** -- HP J2970 10 Mbit/s PCI Combo 10base-T/BNC +** -- HP J2973 10 Mbit/s PCI 10base-T +** -- HP J2573 10/100 ISA +** -- Compex ReadyLink ENET100-VG4 10/100 Mbit/s PCI / EISA +** -- Compex FreedomLine 100/VG 10/100 Mbit/s ISA / EISA / PCI +** +** but it should also work with the other CASCADE based adapters. +** +** TODO: +** - J2573 seems to hang sometimes when in shared memory mode. +** - Mode for Priority TX +** - Check PCI registers, performance might be improved? +** - To reduce interrupt load in busmaster, one could switch off +** the interrupts that are used to refill the queues whenever the +** queues are filled up to more than a certain threshold. +** - some updates for EISA version of card +** +** +** This source/code is public free; you can distribute it and/or modify +** it under terms of the GNU General Public License (published by the +** Free Software Foundation) either version two of this License, or any +** later version. +** +** 1.55 -> 1.56 +** - removed printk in misc. interrupt and update statistics to allow +** monitoring of card status +** - timing changes in xmit routines, relogin to 100VG hub added when +** driver does reset +** - included fix for Compex FreedomLine PCI adapter +** +** 1.54 -> 1.55 +** - fixed bad initialization in init_module +** - added Compex FreedomLine adapter +** - some fixes in card initialization +** +** 1.53 -> 1.54 +** - added hardware multicast filter support (doesn't work) +** - little changes in hp100_sense_lan routine +** - added support for Coax and AUI (J2970) +** - fix for multiple cards and hp100_mode parameter (insmod) +** - fix for shared IRQ +** +** 1.52 -> 1.53 +** - fixed bug in multicast support +** +*/ + +#define HP100_DEFAULT_PRIORITY_TX 0 #undef HP100_DEBUG -#undef HP100_DEBUG_B /* Trace */ -#undef HP100_DEBUG_BM /* Debug busmaster code (PDL stuff) */ +#undef HP100_DEBUG_B /* Trace */ +#undef HP100_DEBUG_BM /* Debug busmaster code (PDL stuff) */ -#undef HP100_DEBUG_TRAINING /* Debug login-to-hub procedure */ -#undef HP100_DEBUG_TX -#undef HP100_DEBUG_IRQ -#undef HP100_DEBUG_RX +#undef HP100_DEBUG_TRAINING /* Debug login-to-hub procedure */ +#undef HP100_DEBUG_TX +#undef HP100_DEBUG_IRQ +#undef HP100_DEBUG_RX + +#undef HP100_MULTICAST_FILTER /* Need to be debugged... */ #include <linux/version.h> #include <linux/module.h> @@ -58,7 +84,6 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/bios32.h> -#include <linux/init.h> #include <asm/bitops.h> #include <asm/io.h> @@ -67,7 +92,7 @@ #include <linux/skbuff.h> #include <linux/types.h> -#include <linux/config.h> /* for CONFIG_PCI */ +#include <linux/config.h> /* for CONFIG_PCI */ #include <linux/delay.h> #if LINUX_VERSION_CODE < 0x020100 @@ -79,6 +104,12 @@ typedef struct enet_statistics hp100_stats_t; typedef struct net_device_stats hp100_stats_t; #endif +#ifndef __initfunc +#define __initfunc(__initarg) __initarg +#else +#include <linux/init.h> +#endif + #include "hp100.h" /* @@ -98,8 +129,14 @@ typedef struct net_device_stats hp100_stats_t; #ifndef PCI_DEVICE_ID_COMPEX_ENET100VG4 #define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112 #endif +#ifndef PCI_VENDOR_ID_COMPEX2 +#define PCI_VENDOR_ID_COMPEX2 0x101a +#endif +#ifndef PCI_DEVICE_ID_COMPEX2_100VG +#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005 +#endif -#define HP100_REGION_SIZE 0x20 /* for ioports */ +#define HP100_REGION_SIZE 0x20 /* for ioports */ #define HP100_MAX_PACKET_SIZE (1536+4) #define HP100_MIN_PACKET_SIZE 60 @@ -119,135 +156,167 @@ typedef struct net_device_stats hp100_stats_t; */ struct hp100_eisa_id { - u_int id; - const char *name; - u_char bus; + u_int id; + const char *name; + u_char bus; +}; + +struct hp100_pci_id { + u_short vendor; + u_short device; }; struct hp100_private { - struct hp100_eisa_id *id; - u_short chip; - u_short soft_model; - u_int memory_size; - u_short rx_ratio; /* 1 - 99 */ - u_short priority_tx; /* != 0 - priority tx */ - u_short mode; /* PIO, Shared Mem or Busmaster */ - u_char bus; - u_char pci_bus; - u_char pci_device_fn; - short mem_mapped; /* memory mapped access */ - u_int *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ - u_int *mem_ptr_phys; /* physical memory mapped area */ - short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */ - int hub_status; /* was login to hub successful? */ - u_char mac1_mode; - u_char mac2_mode; - hp100_stats_t stats; - - /* Rings for busmaster mode: */ - hp100_ring_t *rxrhead; /* Head (oldest) index into rxring */ - hp100_ring_t *rxrtail; /* Tail (newest) index into rxring */ - hp100_ring_t *txrhead; /* Head (oldest) index into txring */ - hp100_ring_t *txrtail; /* Tail (newest) index into txring */ - - hp100_ring_t rxring[MAX_RX_PDL]; - hp100_ring_t txring[MAX_TX_PDL]; - - u_int *page_vaddr; /* Virtual address of allocated page */ - u_int *page_vaddr_algn; /* Aligned virtual address of allocated page */ - int rxrcommit; /* # Rx PDLs commited to adapter */ - int txrcommit; /* # Tx PDLs commited to adapter */ + struct hp100_eisa_id *id; + u_short chip; + u_short soft_model; + u_int memory_size; + u_int virt_memory_size; + u_short rx_ratio; /* 1 - 99 */ + u_short priority_tx; /* != 0 - priority tx */ + u_short mode; /* PIO, Shared Mem or Busmaster */ + u_char bus; + u_char pci_bus; + u_char pci_device_fn; + short mem_mapped; /* memory mapped access */ + u_int *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ + u_int *mem_ptr_phys; /* physical memory mapped area */ + short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */ + int hub_status; /* was login to hub successful? */ + u_char mac1_mode; + u_char mac2_mode; + u_char hash_bytes[ 8 ]; + hp100_stats_t stats; + + /* Rings for busmaster mode: */ + hp100_ring_t *rxrhead; /* Head (oldest) index into rxring */ + hp100_ring_t *rxrtail; /* Tail (newest) index into rxring */ + hp100_ring_t *txrhead; /* Head (oldest) index into txring */ + hp100_ring_t *txrtail; /* Tail (newest) index into txring */ + + hp100_ring_t rxring[ MAX_RX_PDL ]; + hp100_ring_t txring[ MAX_TX_PDL ]; + + u_int *page_vaddr; /* Virtual address of allocated page */ + u_int *page_vaddr_algn; /* Aligned virtual address of allocated page */ + int rxrcommit; /* # Rx PDLs commited to adapter */ + int txrcommit; /* # Tx PDLs commited to adapter */ }; /* * variables */ -static struct hp100_eisa_id hp100_eisa_ids[] = -{ +static struct hp100_eisa_id hp100_eisa_ids[] = { /* 10/100 EISA card with revision A Cascade chip */ - {0x80F1F022, "HP J2577 rev A", HP100_BUS_EISA}, + { 0x80F1F022, "HP J2577 rev A", HP100_BUS_EISA }, /* 10/100 ISA card with revision A Cascade chip */ - {0x50F1F022, "HP J2573 rev A", HP100_BUS_ISA}, + { 0x50F1F022, "HP J2573 rev A", HP100_BUS_ISA }, /* 10 only EISA card with Cascade chip */ - {0x2019F022, "HP 27248B", HP100_BUS_EISA}, + { 0x2019F022, "HP 27248B", HP100_BUS_EISA }, /* 10/100 EISA card with Cascade chip */ - {0x4019F022, "HP J2577", HP100_BUS_EISA}, + { 0x4019F022, "HP J2577", HP100_BUS_EISA }, /* 10/100 ISA card with Cascade chip */ - {0x5019F022, "HP J2573", HP100_BUS_ISA}, + { 0x5019F022, "HP J2573", HP100_BUS_ISA }, /* 10/100 PCI card - old J2585A */ - {0x1030103c, "HP J2585A", HP100_BUS_PCI}, + { 0x1030103c, "HP J2585A", HP100_BUS_PCI }, /* 10/100 PCI card - new J2585B - master capable */ - {0x1041103c, "HP J2585B", HP100_BUS_PCI}, + { 0x1041103c, "HP J2585B", HP100_BUS_PCI }, /* 10 Mbit Combo Adapter */ - {0x1042103c, "HP J2970", HP100_BUS_PCI}, + { 0x1042103c, "HP J2970", HP100_BUS_PCI }, /* 10 Mbit 10baseT Adapter */ - {0x1040103c, "HP J2973", HP100_BUS_PCI}, + { 0x1040103c, "HP J2973", HP100_BUS_PCI }, /* 10/100 EISA card from Compex */ - {0x0103180e, "ReadyLink ENET100-VG4", HP100_BUS_EISA}, - + { 0x0103180e, "ReadyLink ENET100-VG4", HP100_BUS_EISA }, + + /* 10/100 EISA card from Compex - FreedomLine (sq5bpf) */ + /* Note: plhbrod@mbox.vol.cz reported that same ID have ISA */ + /* version of adapter, too... */ + { 0x0104180e, "FreedomLine 100/VG", HP100_BUS_EISA }, + + /* 10/100 PCI card from Compex - FreedomLine + * + * I think this card doesn't like aic7178 scsi controller, but + * I haven't tested this much. It works fine on diskless machines. + * Jacek Lipkowski <sq5bpf@acid.ch.pw.edu.pl> + */ + { 0x021211f6, "FreedomLine 100/VG", HP100_BUS_PCI }, + /* 10/100 PCI card from Compex (J2585A compatible) */ - {0x011211f6, "ReadyLink ENET100-VG4", HP100_BUS_PCI} + { 0x011211f6, "ReadyLink ENET100-VG4", HP100_BUS_PCI } + }; +#define HP100_EISA_IDS_SIZE (sizeof(hp100_eisa_ids)/sizeof(struct hp100_eisa_id)) + +static struct hp100_pci_id hp100_pci_ids[] = { + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A }, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B }, + { PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4 }, + { PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG } +}; + +#define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id)) + static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; static int hp100_mode = 1; #ifdef LINUX_2_1 -MODULE_PARM(hp100_rx_ratio, "1i"); -MODULE_PARM(hp100_priority_tx, "1i"); -MODULE_PARM(hp100_mode, "1i"); +MODULE_PARM( hp100_rx_ratio, "1i" ); +MODULE_PARM( hp100_priority_tx, "1i" ); +MODULE_PARM( hp100_mode, "1i" ); #endif /* * prototypes */ -static int hp100_probe1(struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn); -static int hp100_open(struct device *dev); -static int hp100_close(struct device *dev); -static int hp100_start_xmit(struct sk_buff *skb, struct device *dev); -static int hp100_start_xmit_bm(struct sk_buff *skb, struct device *dev); -static void hp100_rx(struct device *dev); -static hp100_stats_t *hp100_get_stats(struct device *dev); -static void hp100_update_stats(struct device *dev); -static void hp100_clear_stats(int ioaddr); -static void hp100_set_multicast_list(struct device *dev); -static void hp100_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void hp100_start_interface(struct device *dev); -static void hp100_stop_interface(struct device *dev); -static void hp100_load_eeprom(struct device *dev); -static int hp100_sense_lan(struct device *dev); -static int hp100_login_to_vg_hub(struct device *dev, u_short force_relogin); -static int hp100_down_vg_link(struct device *dev); -static void hp100_cascade_reset(struct device *dev, u_short enable); -static void hp100_BM_shutdown(struct device *dev); -static void hp100_mmuinit(struct device *dev); -static void hp100_init_pdls(struct device *dev); -static int hp100_init_rxpdl(register hp100_ring_t * ringptr, register u_int * pdlptr); -static int hp100_init_txpdl(register hp100_ring_t * ringptr, register u_int * pdlptr); -static void hp100_rxfill(struct device *dev); -static void hp100_hwinit(struct device *dev); -static void hp100_clean_txring(struct device *dev); +static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ); +static int hp100_open( struct device *dev ); +static int hp100_close( struct device *dev ); +static int hp100_start_xmit( struct sk_buff *skb, struct device *dev ); +static int hp100_start_xmit_bm (struct sk_buff *skb, struct device *dev ); +static void hp100_rx( struct device *dev ); +static hp100_stats_t *hp100_get_stats( struct device *dev ); +static void hp100_misc_interrupt( struct device *dev ); +static void hp100_update_stats( struct device *dev ); +static void hp100_clear_stats( int ioaddr ); +static void hp100_set_multicast_list( struct device *dev); +static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ); +static void hp100_start_interface( struct device *dev ); +static void hp100_stop_interface( struct device *dev ); +static void hp100_load_eeprom( struct device *dev, u_short ioaddr ); +static int hp100_sense_lan( struct device *dev ); +static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin ); +static int hp100_down_vg_link( struct device *dev ); +static void hp100_cascade_reset( struct device *dev, u_short enable ); +static void hp100_BM_shutdown( struct device *dev ); +static void hp100_mmuinit( struct device *dev ); +static void hp100_init_pdls( struct device *dev ); +static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr); +static int hp100_init_txpdl( struct device *dev, register hp100_ring_t *ringptr, register u_int *pdlptr); +static void hp100_rxfill( struct device *dev ); +static void hp100_hwinit( struct device *dev ); +static void hp100_clean_txring( struct device *dev ); #ifdef HP100_DEBUG -static void hp100_RegisterDump(struct device *dev); +static void hp100_RegisterDump( struct device *dev ); #endif /* TODO: This function should not really be needed in a good design... */ -static void wait(void) +static void wait( void ) { - udelay(1000); + udelay( 1000 ); } /* @@ -255,863 +324,984 @@ static void wait(void) * These functions should - if possible - avoid doing write operations * since this could cause problems when the card is not installed. */ - -__initfunc(int hp100_probe(struct device *dev)) + +__initfunc(int hp100_probe( struct device *dev )) { - int base_addr = dev ? dev->base_addr : 0; - int ioaddr = 0; + int base_addr = dev ? dev -> base_addr : 0; + int ioaddr = 0; #ifdef CONFIG_PCI - int pci_start_index = 0; + int pci_start_index = 0; #endif #ifdef HP100_DEBUG_B - hp100_outw(0x4200, TRACE); - printk("hp100: probe\n"); -#endif - - if (base_addr > 0xff) { /* Check a single specified location. */ - if (check_region(base_addr, HP100_REGION_SIZE)) - return -EINVAL; - if (base_addr < 0x400) - return hp100_probe1(dev, base_addr, HP100_BUS_ISA, 0, 0); - else - return hp100_probe1(dev, base_addr, HP100_BUS_EISA, 0, 0); - } else + hp100_outw( 0x4200, TRACE ); + printk( "hp100: %s: probe\n", dev->name ); +#endif + + if ( base_addr > 0xff ) /* Check a single specified location. */ + { + if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL; + if ( base_addr < 0x400 ) + return hp100_probe1( dev, base_addr, HP100_BUS_ISA, 0, 0 ); + if ( EISA_bus && base_addr >= 0x1c38 && ( (base_addr - 0x1c38) & 0x3ff ) == 0 ) + return hp100_probe1( dev, base_addr, HP100_BUS_EISA, 0, 0 ); +#ifdef CONFIG_PCI + printk( "hp100: %s: You may specify card # in i/o address parameter for PCI bus...", dev->name ); + return hp100_probe1( dev, base_addr, HP100_BUS_PCI, 0, 0 ); +#else + return -ENODEV; +#endif + } + else #ifdef CONFIG_PCI - if (base_addr > 0 && base_addr < 8 + 1) - pci_start_index = 0x100 | (base_addr - 1); - else + if ( base_addr > 0 && base_addr < 8 + 1 ) + pci_start_index = 0x100 | ( base_addr - 1 ); + else #endif - if (base_addr != 0) - return -ENXIO; + if ( base_addr != 0 ) return -ENXIO; - /* at first - scan PCI bus(es) */ + /* at first - scan PCI bus(es) */ #ifdef CONFIG_PCI - if (pcibios_present()) { - int pci_index; + if ( pcibios_present() ) + { + int pci_index; #ifdef HP100_DEBUG_PCI - printk("hp100: PCI BIOS is present, checking for devices..\n"); -#endif - for (pci_index = pci_start_index & 7; pci_index < 8; pci_index++) { - u_char pci_bus, pci_device_fn; - u_short pci_command; - - if ((pcibios_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, - pci_index, &pci_bus, - &pci_device_fn) != 0) && - (pcibios_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, - pci_index, &pci_bus, - &pci_device_fn) != 0) && - (pcibios_find_device(PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, - pci_index, &pci_bus, - &pci_device_fn) != 0)) - break; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &ioaddr); - - ioaddr &= ~3; /* remove I/O space marker in bit 0. */ - - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - if (!(pci_command & PCI_COMMAND_MASTER)) { -#ifdef HP100_DEBUG - printk("hp100: PCI Master Bit has not been set. Setting...\n"); + printk( "hp100: %s: PCI BIOS is present, checking for devices..\n", dev->name ); #endif - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, pci_command); - } -#ifdef HP100_DEBUG - printk("hp100: PCI adapter found at 0x%x\n", ioaddr); -#endif - if (hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pci_bus, pci_device_fn) == 0) - return 0; - } - } - if (pci_start_index > 0) - return -ENODEV; -#endif /* CONFIG_PCI */ - - /* Second: Probe all EISA possible port regions (if EISA bus present) */ - for (ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400) { - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - if (hp100_probe1(dev, ioaddr, HP100_BUS_EISA, 0, 0) == 0) - return 0; - } + for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ ) + { + u_char pci_bus, pci_device_fn; + u_short pci_command; + int pci_id_index; - /* Third Probe all ISA possible port regions */ - for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) { - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - if (hp100_probe1(dev, ioaddr, HP100_BUS_ISA, 0, 0) == 0) - return 0; - } + for ( pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; pci_id_index++ ) + if ( pcibios_find_device( hp100_pci_ids[ pci_id_index ].vendor, + hp100_pci_ids[ pci_id_index ].device, + pci_index, &pci_bus, + &pci_device_fn ) == 0 ) goto __pci_found; + break; - return -ENODEV; + __pci_found: + pcibios_read_config_dword( pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &ioaddr ); + + ioaddr &= ~3; /* remove I/O space marker in bit 0. */ + + if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; + + pcibios_read_config_word( pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command ); + if ( !( pci_command & PCI_COMMAND_IO ) ) + { +#ifdef HP100_DEBUG + printk( "hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name ); +#endif + pci_command |= PCI_COMMAND_IO; + pcibios_write_config_word( pci_bus, pci_device_fn, + PCI_COMMAND, pci_command ); + } + if ( !( pci_command & PCI_COMMAND_MASTER ) ) + { +#ifdef HP100_DEBUG + printk( "hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name ); +#endif + pci_command |= PCI_COMMAND_MASTER; + pcibios_write_config_word( pci_bus, pci_device_fn, + PCI_COMMAND, pci_command ); + } +#ifdef HP100_DEBUG + printk( "hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr ); +#endif + if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI, pci_bus, pci_device_fn ) == 0 ) + return 0; + } + } + if ( pci_start_index > 0 ) return -ENODEV; +#endif /* CONFIG_PCI */ + + /* Second: Probe all EISA possible port regions (if EISA bus present) */ + for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 ) + { + if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; + if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA, 0, 0 ) == 0 ) return 0; + } + + /* Third Probe all ISA possible port regions */ + for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 ) + { + if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; + if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA, 0, 0 ) == 0 ) return 0; + } + + return -ENODEV; } - -__initfunc(static int hp100_probe1(struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn)) + +__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn )) { - int i; - - u_char uc, uc_1; - u_int eisa_id; - u_int chip; - u_int memory_size = 0; - short mem_mapped; - u_int *mem_ptr_phys, *mem_ptr_virt; - struct hp100_private *lp; - struct hp100_eisa_id *eid; + int i; + + u_char uc, uc_1; + u_int eisa_id; + u_int chip; + u_int memory_size = 0, virt_memory_size = 0; + u_short local_mode, lsw; + short mem_mapped; + u_int *mem_ptr_phys, *mem_ptr_virt; + struct hp100_private *lp; + struct hp100_eisa_id *eid; #ifdef HP100_DEBUG_B - hp100_outw(0x4201, TRACE); - printk("hp100: probe1\n"); + hp100_outw( 0x4201, TRACE ); + printk("hp100: %s: probe1\n",dev->name); #endif - if (dev == NULL) { + if ( dev == NULL ) + { #ifdef HP100_DEBUG - printk("hp100_probe1: dev == NULL ?\n"); -#endif - return EIO; + printk( "hp100_probe1: %s: dev == NULL ?\n", dev->name ); +#endif + return EIO; + } + + if ( hp100_inw( HW_ID ) != HP100_HW_ID_CASCADE ) + { + return -ENODEV; + } + else + { + chip = hp100_inw( PAGING ) & HP100_CHIPID_MASK; +#ifdef HP100_DEBUG + if ( chip == HP100_CHIPID_SHASTA ) + printk("hp100: %s: Shasta Chip detected. (This is a pre 802.12 chip)\n", dev->name); + else if ( chip == HP100_CHIPID_RAINIER ) + printk("hp100: %s: Rainier Chip detected. (This is a pre 802.12 chip)\n", dev->name); + else if ( chip == HP100_CHIPID_LASSEN ) + printk("hp100: %s: Lassen Chip detected.\n", dev->name); + else + printk("hp100: %s: Warning: Unknown CASCADE chip (id=0x%.4x).\n",dev->name,chip); +#endif + } + + dev->base_addr = ioaddr; + + hp100_page( ID_MAC_ADDR ); + for ( i = uc = eisa_id = 0; i < 4; i++ ) + { + eisa_id >>= 8; + uc_1 = hp100_inb( BOARD_ID + i ); + eisa_id |= uc_1 << 24; + uc += uc_1; + } + uc += hp100_inb( BOARD_ID + 4 ); + + if ( uc != 0xff ) /* bad checksum? */ + { + printk("hp100_probe: %s: bad EISA ID checksum at base port 0x%x\n", dev->name, ioaddr ); + return -ENODEV; + } + + for ( i=0; i < HP100_EISA_IDS_SIZE; i++) + if ( hp100_eisa_ids[ i ].id == eisa_id ) + break; + if ( i >= HP100_EISA_IDS_SIZE ) { + for ( i = 0; i < HP100_EISA_IDS_SIZE; i++) + if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) ) + break; + if ( i >= HP100_EISA_IDS_SIZE ) { + printk( "hp100_probe: %s: card at port 0x%x isn't known (id = 0x%x)\n", dev -> name, ioaddr, eisa_id ); + return -ENODEV; + } + } + eid = &hp100_eisa_ids[ i ]; + if ( ( eid->id & 0x0f000000 ) < ( eisa_id & 0x0f000000 ) ) + { + printk( "hp100_probe: %s: newer version of card %s at port 0x%x - unsupported\n", + dev->name, eid->name, ioaddr ); + return -ENODEV; + } + + for ( i = uc = 0; i < 7; i++ ) + uc += hp100_inb( LAN_ADDR + i ); + if ( uc != 0xff ) + { + printk("hp100_probe: %s: bad lan address checksum (card %s at port 0x%x)\n", + dev->name, eid->name, ioaddr ); + return -EIO; + } + + /* Make sure, that all registers are correctly updated... */ + + hp100_load_eeprom( dev, ioaddr ); + wait(); + + /* + * Determine driver operation mode + * + * Use the variable "hp100_mode" upon insmod or as kernel parameter to + * force driver modes: + * hp100_mode=1 -> default, use busmaster mode if configured. + * hp100_mode=2 -> enable shared memory mode + * hp100_mode=3 -> force use of i/o mapped mode. + * hp100_mode=4 -> same as 1, but re-set the enable bit on the card. + */ + + /* + * LSW values: + * 0x2278 -> J2585B, PnP shared memory mode + * 0x2270 -> J2585B, shared memory mode, 0xdc000 + * 0xa23c -> J2585B, I/O mapped mode + * 0x2240 -> EISA COMPEX, BusMaster (Shasta Chip) + * 0x2220 -> EISA HP, I/O (Shasta Chip) + * 0x2260 -> EISA HP, BusMaster (Shasta Chip) + */ + +#if 0 + local_mode = 0x2270; + hp100_outw(0xfefe,OPTION_LSW); + hp100_outw(local_mode|HP100_SET_LB|HP100_SET_HB,OPTION_LSW); +#endif + + /* hp100_mode value maybe used in future by another card */ + local_mode=hp100_mode; + if ( local_mode < 1 || local_mode > 4 ) + local_mode = 1; /* default */ +#ifdef HP100_DEBUG + printk( "hp100: %s: original LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) ); +#endif + + if(local_mode==3) + { + hp100_outw(HP100_MEM_EN|HP100_RESET_LB, OPTION_LSW); + hp100_outw(HP100_IO_EN|HP100_SET_LB, OPTION_LSW); + hp100_outw(HP100_BM_WRITE|HP100_BM_READ|HP100_RESET_HB, OPTION_LSW); + printk("hp100: %s: IO mapped mode forced.\n", dev->name); + } + else if(local_mode==2) + { + hp100_outw(HP100_MEM_EN|HP100_SET_LB, OPTION_LSW); + hp100_outw(HP100_IO_EN |HP100_SET_LB, OPTION_LSW); + hp100_outw(HP100_BM_WRITE|HP100_BM_READ|HP100_RESET_HB, OPTION_LSW); + printk("hp100: %s: Shared memory mode requested.\n", dev->name); + } + else if(local_mode==4) + { + if(chip==HP100_CHIPID_LASSEN) + { + hp100_outw(HP100_BM_WRITE| + HP100_BM_READ | HP100_SET_HB, OPTION_LSW); + hp100_outw(HP100_IO_EN | + HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW); + printk("hp100: %s: Busmaster mode requested.\n",dev->name); } - if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) { - return -ENODEV; - } else { - chip = hp100_inw(PAGING) & HP100_CHIPID_MASK; + local_mode=1; + } + + if(local_mode==1) /* default behaviour */ + { + lsw = hp100_inw(OPTION_LSW); + + if ( (lsw & HP100_IO_EN) && + (~lsw & HP100_MEM_EN) && + (~lsw & (HP100_BM_WRITE|HP100_BM_READ)) ) + { #ifdef HP100_DEBUG - if (chip == HP100_CHIPID_SHASTA) - printk("hp100: Shasta Chip detected. (This is a pre 802.12 chip)\n"); - else if (chip == HP100_CHIPID_RAINIER) - printk("hp100: Rainier Chip detected. (This is a pre 802.12 chip)\n"); - else if (chip == HP100_CHIPID_LASSEN) - printk("hp100: Lassen Chip detected.\n"); - else - printk("hp100: Warning: Unknown CASCADE chip (id=0x%.4x).\n", chip); + printk("hp100: %s: IO_EN bit is set on card.\n",dev->name); #endif + local_mode=3; } - - dev->base_addr = ioaddr; - - hp100_page(ID_MAC_ADDR); - for (i = uc = eisa_id = 0; i < 4; i++) { - eisa_id >>= 8; - uc_1 = hp100_inb(BOARD_ID + i); - eisa_id |= uc_1 << 24; - uc += uc_1; + else if ( chip == HP100_CHIPID_LASSEN && + ( lsw & (HP100_BM_WRITE|HP100_BM_READ) ) == + (HP100_BM_WRITE|HP100_BM_READ) ) + { + printk("hp100: %s: Busmaster mode enabled.\n",dev->name); + hp100_outw(HP100_MEM_EN|HP100_IO_EN|HP100_RESET_LB, OPTION_LSW); } - uc += hp100_inb(BOARD_ID + 4); - - if (uc != 0xff) { /* bad checksum? */ - printk("hp100_probe: bad EISA ID checksum at base port 0x%x\n", ioaddr); - return -ENODEV; - } - for (i = 0; i < sizeof(hp100_eisa_ids) / sizeof(struct hp100_eisa_id); i++) - if ((hp100_eisa_ids[i].id & 0xf0ffffff) == (eisa_id & 0xf0ffffff)) - break; - if (i >= sizeof(hp100_eisa_ids) / sizeof(struct hp100_eisa_id)) { - printk("hp100_probe1: card at port 0x%x isn't known (id = 0x%x)\n", ioaddr, eisa_id); - return -ENODEV; - } - eid = &hp100_eisa_ids[i]; - if ((eid->id & 0x0f000000) < (eisa_id & 0x0f000000)) { - printk("hp100_probe1: newer version of card %s at port 0x%x - unsupported\n", - eid->name, ioaddr); - return -ENODEV; - } - for (i = uc = 0; i < 7; i++) - uc += hp100_inb(LAN_ADDR + i); - if (uc != 0xff) { - printk("hp100_probe1: bad lan address checksum (card %s at port 0x%x)\n", - eid->name, ioaddr); - return -EIO; - } - /* Determine driver operation mode - - * Use the variable "hp100_mode" upon insmod or as kernel parameter to - * force driver modes: - * hp100_mode=1 -> default, use busmaster mode if configured. - * hp100_mode=2 -> enable shared memory mode - * hp100_mode=3 -> force use of i/o mapped mode. - * hp100_mode=4 -> same as 1, but re-set the enable bit on the card. - */ - - if (hp100_mode == 3) { - hp100_outw(HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW); - hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); - hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); - printk("hp100: IO mapped mode forced.\n"); - } else if (hp100_mode == 2) { - hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW); - hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); - hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); - printk("hp100: Shared memory mode requested.\n"); - } else if (hp100_mode == 4) { - if (chip == HP100_CHIPID_LASSEN) { - hp100_outw(HP100_BM_WRITE | - HP100_BM_READ | HP100_SET_HB, OPTION_LSW); - hp100_outw(HP100_IO_EN | - HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW); - printk("hp100: Busmaster mode requested.\n"); - } - hp100_mode = 1; - } - if (hp100_mode == 1) { /* default behaviour */ - if ((hp100_inw(OPTION_LSW) & HP100_IO_EN) && - (~hp100_inw(OPTION_LSW) & HP100_MEM_EN) && - (~hp100_inw(OPTION_LSW) & (HP100_BM_WRITE | HP100_BM_READ)) - ) { -#ifdef HP100_DEBUG - printk("hp100: IO_EN bit is set on card.\n"); -#endif - hp100_mode = 3; - } else if ((chip == HP100_CHIPID_LASSEN) && - ((hp100_inw(OPTION_LSW) & (HP100_BM_WRITE | HP100_BM_READ)) == - (HP100_BM_WRITE | HP100_BM_READ))) { - printk("hp100: Busmaster mode enabled.\n"); - hp100_outw(HP100_MEM_EN | HP100_IO_EN | HP100_RESET_LB, OPTION_LSW); - } else { + else + { #ifdef HP100_DEBUG - printk("hp100: Card not configured for BM or BM not supported with this card. Trying shared memory mode.\n"); + printk("hp100: %s: Card not configured for BM or BM not supported with this card.\n", dev->name ); + printk("hp100: %s: Trying shared memory mode.\n", dev->name); #endif - /* In this case, try shared memory mode */ - hp100_mode = 2; - hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW); - /* hp100_outw(HP100_IO_EN|HP100_RESET_LB, OPTION_LSW); */ - } + /* In this case, try shared memory mode */ + local_mode=2; + hp100_outw(HP100_MEM_EN|HP100_SET_LB, OPTION_LSW); + /* hp100_outw(HP100_IO_EN|HP100_RESET_LB, OPTION_LSW); */ } - /* Check for shared memory on the card, eventually remap it */ - hp100_page(HW_MAP); - mem_mapped = ((hp100_inw(OPTION_LSW) & (HP100_MEM_EN)) != 0); - mem_ptr_phys = mem_ptr_virt = NULL; - memory_size = (8192 << ((hp100_inb(SRAM) >> 5) & 0x07)); - - /* For memory mapped or busmaster mode, we want the memory address */ - if (mem_mapped || (hp100_mode == 1)) { - mem_ptr_phys = (u_int *) (hp100_inw(MEM_MAP_LSW) | - (hp100_inw(MEM_MAP_MSW) << 16)); - (u_int) mem_ptr_phys &= ~0x1fff; /* 8k alignment */ - - if (bus == HP100_BUS_ISA && ((u_long) mem_ptr_phys & ~0xfffff) != 0) { - printk("hp100: Can only use programmed i/o mode.\n"); - mem_ptr_phys = NULL; - mem_mapped = 0; - hp100_mode = 3; /* Use programmed i/o */ - } - /* We do not need access to shared memory in busmaster mode */ - /* However in slave mode we need to remap high (>1GB) card memory */ - if (hp100_mode != 1) { /* = not busmaster */ - if (bus == HP100_BUS_PCI) { - /* We try with smaller memory sizes, if ioremap fails */ - for (; memory_size > 16383; memory_size = memory_size / 2) { - if ((mem_ptr_virt = ioremap((u_long) mem_ptr_phys, memory_size)) == NULL) { + } + #ifdef HP100_DEBUG - printk("hp100: ioremap for 0x%x bytes high PCI memory at 0x%lx failed\n", memory_size, (u_long) mem_ptr_phys); + printk( "hp100: %s: new LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) ); +#endif + + /* Check for shared memory on the card, eventually remap it */ + hp100_page( HW_MAP ); + mem_mapped = (( hp100_inw( OPTION_LSW ) & ( HP100_MEM_EN ) ) != 0); + mem_ptr_phys = mem_ptr_virt = NULL; + memory_size = (8192<<( (hp100_inb(SRAM)>>5)&0x07)); + virt_memory_size = 0; + + /* For memory mapped or busmaster mode, we want the memory address */ + if ( mem_mapped || (local_mode==1)) + { + mem_ptr_phys = (u_int *)( hp100_inw( MEM_MAP_LSW ) | + ( hp100_inw( MEM_MAP_MSW ) << 16 ) ); + (u_int)mem_ptr_phys &= ~0x1fff; /* 8k alignment */ + + if ( bus == HP100_BUS_ISA && ( (u_long)mem_ptr_phys & ~0xfffff ) != 0 ) + { + printk("hp100: %s: Can only use programmed i/o mode.\n", dev->name); + mem_ptr_phys = NULL; + mem_mapped = 0; + local_mode=3; /* Use programmed i/o */ + } + + /* We do not need access to shared memory in busmaster mode */ + /* However in slave mode we need to remap high (>1GB) card memory */ + if(local_mode!=1) /* = not busmaster */ + { + if ( bus == HP100_BUS_PCI && mem_ptr_phys >= (u_int *)0x100000 ) + { + /* We try with smaller memory sizes, if ioremap fails */ + for(virt_memory_size = memory_size; virt_memory_size>16383; virt_memory_size>>=1) + { + if((mem_ptr_virt=ioremap((u_long)mem_ptr_phys,virt_memory_size))==NULL) + { +#ifdef HP100_DEBUG + printk( "hp100: %s: ioremap for 0x%x bytes high PCI memory at 0x%lx failed\n", dev->name, virt_memory_size, (u_long)mem_ptr_phys ); #endif - } else { + } + else + { #ifdef HP100_DEBUG - printk("hp100: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", memory_size, (u_long) mem_ptr_phys, (u_long) mem_ptr_virt); -#endif - break; - } - } - - if (mem_ptr_virt == NULL) { /* all ioremap tries failed */ - printk("hp100: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n"); - hp100_mode = 3; - memory_size = (8192 << ((hp100_inb(SRAM) >> 5) & 0x07)); - } - } + printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, virt_memory_size, (u_long)mem_ptr_phys, (u_long)mem_ptr_virt); +#endif + break; + } } + + if(mem_ptr_virt==NULL) /* all ioremap tries failed */ + { + printk("hp100: %s: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n", dev->name); + local_mode=3; + virt_memory_size = 0; + } + } } - if (hp100_mode == 3) { /* io mapped forced */ - mem_mapped = 0; - mem_ptr_phys = mem_ptr_virt = NULL; - printk("hp100: Using (slow) programmed i/o mode.\n"); - } - /* Initialise the "private" data structure for this card. */ - if ((dev->priv = kmalloc(sizeof(struct hp100_private), GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct hp100_private)); - - lp = (struct hp100_private *) dev->priv; - lp->id = eid; - lp->chip = chip; - lp->mode = hp100_mode; - lp->pci_bus = pci_bus; - lp->bus = bus; - lp->pci_device_fn = pci_device_fn; - lp->priority_tx = hp100_priority_tx; - lp->rx_ratio = hp100_rx_ratio; - lp->mem_ptr_phys = mem_ptr_phys; - lp->mem_ptr_virt = mem_ptr_virt; - hp100_page(ID_MAC_ADDR); - lp->soft_model = hp100_inb(SOFT_MODEL); - lp->mac1_mode = HP100_MAC1MODE3; - lp->mac2_mode = HP100_MAC2MODE3; - - dev->base_addr = ioaddr; - - lp->memory_size = memory_size; - lp->rx_ratio = hp100_rx_ratio; /* can be conf'd with insmod */ - - /* memory region for programmed i/o */ - request_region(dev->base_addr, HP100_REGION_SIZE, eid->name); - - dev->open = hp100_open; - dev->stop = hp100_close; - - if (lp->mode == 1) /* busmaster */ - dev->hard_start_xmit = hp100_start_xmit_bm; - else - dev->hard_start_xmit = hp100_start_xmit; - - dev->get_stats = hp100_get_stats; - dev->set_multicast_list = &hp100_set_multicast_list; - - /* Ask the card for which IRQ line it is configured */ - hp100_page(HW_MAP); - dev->irq = hp100_inb(IRQ_CHANNEL) & HP100_IRQMASK; - if (dev->irq == 2) - dev->irq = 9; - - if (lp->mode == 1) /* busmaster */ - dev->dma = 4; - - /* Ask the card for its MAC address and store it for later use. */ - hp100_page(ID_MAC_ADDR); - for (i = uc = 0; i < 6; i++) - dev->dev_addr[i] = hp100_inb(LAN_ADDR + i); - - /* Reset statistics (counters) */ - hp100_clear_stats(ioaddr); - - ether_setup(dev); - - /* If busmaster mode is wanted, a dma-capable memory area is needed for - * the rx and tx PDLs - * PCI cards can access the whole PC memory. Therefore GFP_DMA is not - * needed for the allocation of the memory area. - */ - - /* TODO: We do not need this with old cards, where PDLs are stored - * in the cards shared memory area. But currently, busmaster has been - * implemented/tested only with the lassen chip anyway... */ - if (lp->mode == 1) { /* busmaster */ - /* Get physically continous memory for TX & RX PDLs */ - if ((lp->page_vaddr = kmalloc(MAX_RINGSIZE + 0x0f, GFP_KERNEL)) == NULL) - return -ENOMEM; - lp->page_vaddr_algn = ((u_int *) (((u_int) (lp->page_vaddr) + 0x0f) & ~0x0f)); - memset(lp->page_vaddr, 0, MAX_RINGSIZE + 0x0f); + + } + + if(local_mode==3) /* io mapped forced */ + { + mem_mapped = 0; + mem_ptr_phys = mem_ptr_virt = NULL; + printk("hp100: %s: Using (slow) programmed i/o mode.\n", dev->name); + } + + /* Initialise the "private" data structure for this card. */ + if ( (dev->priv=kmalloc(sizeof(struct hp100_private), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset( dev->priv, 0, sizeof(struct hp100_private) ); + + lp = (struct hp100_private *)dev->priv; + lp->id = eid; + lp->chip = chip; + lp->mode = local_mode; + lp->pci_bus = pci_bus; + lp->bus = bus; + lp->pci_device_fn = pci_device_fn; + lp->priority_tx = hp100_priority_tx; + lp->rx_ratio = hp100_rx_ratio; + lp->mem_ptr_phys = mem_ptr_phys; + lp->mem_ptr_virt = mem_ptr_virt; + hp100_page( ID_MAC_ADDR ); + lp->soft_model = hp100_inb( SOFT_MODEL ); + lp->mac1_mode = HP100_MAC1MODE3; + lp->mac2_mode = HP100_MAC2MODE3; + memset( &lp->hash_bytes, 0x00, 8 ); + + dev->base_addr = ioaddr; + + lp->memory_size = memory_size; + lp->virt_memory_size = virt_memory_size; + lp->rx_ratio = hp100_rx_ratio; /* can be conf'd with insmod */ + + /* memory region for programmed i/o */ + request_region( dev->base_addr, HP100_REGION_SIZE, eid->name ); + + dev->open = hp100_open; + dev->stop = hp100_close; + + if (lp->mode==1) /* busmaster */ + dev->hard_start_xmit = hp100_start_xmit_bm; + else + dev->hard_start_xmit = hp100_start_xmit; + + dev->get_stats = hp100_get_stats; + dev->set_multicast_list = &hp100_set_multicast_list; + + /* Ask the card for which IRQ line it is configured */ + hp100_page( HW_MAP ); + dev->irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQMASK; + if ( dev->irq == 2 ) + dev->irq = 9; + + if(lp->mode==1) /* busmaster */ + dev->dma=4; + + /* Ask the card for its MAC address and store it for later use. */ + hp100_page( ID_MAC_ADDR ); + for ( i = uc = 0; i < 6; i++ ) + dev->dev_addr[ i ] = hp100_inb( LAN_ADDR + i ); + + /* Reset statistics (counters) */ + hp100_clear_stats( ioaddr ); + + ether_setup( dev ); + + /* If busmaster mode is wanted, a dma-capable memory area is needed for + * the rx and tx PDLs + * PCI cards can access the whole PC memory. Therefore GFP_DMA is not + * needed for the allocation of the memory area. + */ + + /* TODO: We do not need this with old cards, where PDLs are stored + * in the cards shared memory area. But currently, busmaster has been + * implemented/tested only with the lassen chip anyway... */ + if(lp->mode==1) /* busmaster */ + { + /* Get physically continous memory for TX & RX PDLs */ + if ( (lp->page_vaddr=kmalloc(MAX_RINGSIZE+0x0f,GFP_KERNEL) ) == NULL) + return -ENOMEM; + lp->page_vaddr_algn=((u_int *) ( ((u_int)(lp->page_vaddr)+0x0f) &~0x0f)); + memset(lp->page_vaddr, 0, MAX_RINGSIZE+0x0f); #ifdef HP100_DEBUG_BM - printk("hp100: Reserved DMA memory from 0x%x to 0x%x\n", - (u_int) lp->page_vaddr_algn, - (u_int) lp->page_vaddr_algn + MAX_RINGSIZE); -#endif - lp->rxrcommit = lp->txrcommit = 0; - lp->rxrhead = lp->rxrtail = &(lp->rxring[0]); - lp->txrhead = lp->txrtail = &(lp->txring[0]); - } - /* Initialise the card. */ - /* (I'm not really sure if it's a good idea to do this during probing, but - * like this it's assured that the lan connection type can be sensed - * correctly) - */ - hp100_hwinit(dev); - - /* Try to find out which kind of LAN the card is connected to. */ - lp->lan_type = hp100_sense_lan(dev); - - /* Print out a message what about what we think we have probed. */ - printk("hp100: %s: %s at 0x%x, IRQ %d, ", - dev->name, lp->id->name, ioaddr, dev->irq); - switch (bus) { - case HP100_BUS_EISA: - printk("EISA"); - break; - case HP100_BUS_PCI: - printk("PCI"); - break; - default: - printk("ISA"); - break; - } - printk(" bus, %dk SRAM (rx/tx %d%%).\n", - lp->memory_size >> 10, lp->rx_ratio); - - if (lp->mode == 2) { /* memory mapped */ - printk("%s: Memory area at 0x%lx-0x%lx", - dev->name, (u_long) mem_ptr_phys, (u_long) mem_ptr_phys + (u_long) lp->memory_size); - if (mem_ptr_virt) - printk(" (virtual base 0x%lx)", (u_long) mem_ptr_virt); - printk(".\n"); - - /* Set for info when doing ifconfig */ - dev->mem_start = (u_long) mem_ptr_phys; - dev->mem_end = (u_long) mem_ptr_phys + (u_long) lp->memory_size; - } - printk("%s: ", dev->name); - if (lp->lan_type != HP100_LAN_ERR) - printk("Adapter is attached to "); - switch (lp->lan_type) { - case HP100_LAN_100: - printk("100Mb/s Voice Grade AnyLAN network.\n"); - break; - case HP100_LAN_10: - printk("10Mb/s network.\n"); - break; - default: - printk("Warning! Link down.\n"); - } - return 0; + printk("hp100: %s: Reserved DMA memory from 0x%x to 0x%x\n", + dev->name, + (u_int)lp->page_vaddr_algn, + (u_int)lp->page_vaddr_algn+MAX_RINGSIZE); +#endif + lp->rxrcommit = lp->txrcommit = 0; + lp->rxrhead = lp->rxrtail = &(lp->rxring[0]); + lp->txrhead = lp->txrtail = &(lp->txring[0]); + } + + /* Initialise the card. */ + /* (I'm not really sure if it's a good idea to do this during probing, but + * like this it's assured that the lan connection type can be sensed + * correctly) + */ + hp100_hwinit( dev ); + + /* Try to find out which kind of LAN the card is connected to. */ + lp->lan_type = hp100_sense_lan( dev ); + + /* Print out a message what about what we think we have probed. */ + printk( "hp100: %s: %s at 0x%x, IRQ %d, ", + dev->name, lp->id->name, ioaddr, dev->irq ); + switch ( bus ) { + case HP100_BUS_EISA: printk( "EISA" ); break; + case HP100_BUS_PCI: printk( "PCI" ); break; + default: printk( "ISA" ); break; + } + printk( " bus, %dk SRAM (rx/tx %d%%).\n", + lp->memory_size >> 10, lp->rx_ratio ); + + if ( lp->mode==2 ) /* memory mapped */ + { + printk( "hp100: %s: Memory area at 0x%lx-0x%lx", + dev->name,(u_long)mem_ptr_phys, + ((u_long)mem_ptr_phys+(mem_ptr_phys>(u_int *)0x100000?(u_long)lp->memory_size:16*1024))-1 ); + if ( mem_ptr_virt ) + printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt ); + printk( ".\n" ); + + /* Set for info when doing ifconfig */ + dev->mem_start = (u_long)mem_ptr_phys; + dev->mem_end = (u_long)mem_ptr_phys+(u_long)lp->memory_size; + } + printk( "hp100: %s: ", dev->name ); + if ( lp->lan_type != HP100_LAN_ERR ) + printk( "Adapter is attached to " ); + switch ( lp->lan_type ) { + case HP100_LAN_100: + printk( "100Mb/s Voice Grade AnyLAN network.\n" ); + break; + case HP100_LAN_10: + printk( "10Mb/s network.\n" ); + break; + default: + printk( "Warning! Link down.\n" ); + } + + return 0; } - + /* This procedure puts the card into a stable init state */ -static void hp100_hwinit(struct device *dev) +static void hp100_hwinit( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4202, TRACE); - printk("hp100: hwinit\n"); -#endif - - /* Initialise the card. -------------------------------------------- */ - - /* Clear all pending Ints and disable Ints */ - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* clear all pending ints */ - - hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); - hp100_outw(HP100_TRI_INT | HP100_SET_HB, OPTION_LSW); - - if (lp->mode == 1) { - hp100_BM_shutdown(dev); /* disables BM, puts cascade in reset */ - wait(); - } else { - hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); - hp100_cascade_reset(dev, TRUE); - hp100_page(MAC_CTRL); - hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); - } - - /* Initiate EEPROM reload */ - hp100_load_eeprom(dev); - - wait(); - - /* Go into reset again. */ - hp100_cascade_reset(dev, TRUE); - - /* Set Option Registers to a safe state */ - hp100_outw(HP100_DEBUG_EN | - HP100_RX_HDR | - HP100_EE_EN | - HP100_BM_WRITE | - HP100_BM_READ | HP100_RESET_HB | - HP100_FAKE_INT | - HP100_INT_EN | - HP100_MEM_EN | - HP100_IO_EN | HP100_RESET_LB, OPTION_LSW); - - hp100_outw(HP100_TRI_INT | - HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW); - - hp100_outb(HP100_PRIORITY_TX | - HP100_ADV_NXT_PKT | - HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW); - - /* TODO: Configure MMU for Ram Test. */ - /* TODO: Ram Test. */ - - /* Re-check if adapter is still at same i/o location */ - /* (If the base i/o in eeprom has been changed but the */ - /* registers had not been changed, a reload of the eeprom */ - /* would move the adapter to the address stored in eeprom */ - - /* TODO: Code to implement. */ - - /* Until here it was code from HWdiscover procedure. */ - /* Next comes code from mmuinit procedure of SCO BM driver which is - * called from HWconfigure in the SCO driver. */ - - /* Initialise MMU, eventually switch on Busmaster Mode, initialise - * multicast filter... - */ - hp100_mmuinit(dev); - - /* We don't turn the interrupts on here - this is done by start_interface. */ - wait(); /* TODO: Do we really need this? */ - - /* Enable Hardware (e.g. unreset) */ - hp100_cascade_reset(dev, FALSE); - - /* ------- initialisation complete ----------- */ - - /* Finally try to log in the Hub if there may be a VG connection. */ - if (lp->lan_type != HP100_LAN_10) - hp100_login_to_vg_hub(dev, FALSE); /* relogin */ + hp100_outw( 0x4202, TRACE ); + printk("hp100: %s: hwinit\n", dev->name); +#endif + + /* Initialise the card. -------------------------------------------- */ + + /* Clear all pending Ints and disable Ints */ + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* clear all pending ints */ + + hp100_outw( HP100_INT_EN | HP100_RESET_LB, OPTION_LSW ); + hp100_outw( HP100_TRI_INT | HP100_SET_HB, OPTION_LSW ); + + if(lp->mode==1) + { + hp100_BM_shutdown( dev ); /* disables BM, puts cascade in reset */ + wait(); + } + else + { + hp100_outw( HP100_INT_EN | HP100_RESET_LB, OPTION_LSW ); + hp100_cascade_reset( dev, TRUE ); + hp100_page( MAC_CTRL ); + hp100_andb( ~(HP100_RX_EN|HP100_TX_EN), MAC_CFG_1); + } + + /* Initiate EEPROM reload */ + hp100_load_eeprom( dev, 0 ); + + wait(); + + /* Go into reset again. */ + hp100_cascade_reset( dev, TRUE ); + + /* Set Option Registers to a safe state */ + hp100_outw( HP100_DEBUG_EN | + HP100_RX_HDR | + HP100_EE_EN | + HP100_BM_WRITE | + HP100_BM_READ | HP100_RESET_HB | + HP100_FAKE_INT | + HP100_INT_EN | + HP100_MEM_EN | + HP100_IO_EN | HP100_RESET_LB, OPTION_LSW); + + hp100_outw( HP100_TRI_INT | + HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW ); + + hp100_outb( HP100_PRIORITY_TX | + HP100_ADV_NXT_PKT | + HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW ); + + /* TODO: Configure MMU for Ram Test. */ + /* TODO: Ram Test. */ + + /* Re-check if adapter is still at same i/o location */ + /* (If the base i/o in eeprom has been changed but the */ + /* registers had not been changed, a reload of the eeprom */ + /* would move the adapter to the address stored in eeprom */ + + /* TODO: Code to implement. */ + + /* Until here it was code from HWdiscover procedure. */ + /* Next comes code from mmuinit procedure of SCO BM driver which is + * called from HWconfigure in the SCO driver. */ + + /* Initialise MMU, eventually switch on Busmaster Mode, initialise + * multicast filter... + */ + hp100_mmuinit( dev ); + + /* We don't turn the interrupts on here - this is done by start_interface. */ + wait(); /* TODO: Do we really need this? */ + + /* Enable Hardware (e.g. unreset) */ + hp100_cascade_reset( dev, FALSE ); + + /* ------- initialisation complete ----------- */ + + /* Finally try to log in the Hub if there may be a VG connection. */ + if( lp->lan_type != HP100_LAN_10 ) + hp100_login_to_vg_hub( dev, FALSE ); /* relogin */ } - + /* * mmuinit - Reinitialise Cascade MMU and MAC settings. * Note: Must already be in reset and leaves card in reset. */ -static void hp100_mmuinit(struct device *dev) +static void hp100_mmuinit( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - int i; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + int i; #ifdef HP100_DEBUG_B - hp100_outw(0x4203, TRACE); - printk("hp100: mmuinit\n"); + hp100_outw( 0x4203, TRACE ); + printk("hp100: %s: mmuinit\n",dev->name); #endif #ifdef HP100_DEBUG - if (0 != (hp100_inw(OPTION_LSW) & HP100_HW_RST)) { - printk("hp100: Not in reset when entering mmuinit. Fix me.\n"); - return; - } -#endif - - /* Make sure IRQs are masked off and ack'ed. */ - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */ - - /* - * Enable Hardware - * - Clear Debug En, Rx Hdr Pipe, EE En, I/O En, Fake Int and Intr En - * - Set Tri-State Int, Bus Master Rd/Wr, and Mem Map Disable - * - Clear Priority, Advance Pkt and Xmit Cmd - */ - - hp100_outw(HP100_DEBUG_EN | - HP100_RX_HDR | - HP100_EE_EN | HP100_RESET_HB | - HP100_IO_EN | - HP100_FAKE_INT | - HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); - - hp100_outw(HP100_TRI_INT | HP100_SET_HB, OPTION_LSW); - - if (lp->mode == 1) { /* busmaster */ - hp100_outw(HP100_BM_WRITE | - HP100_BM_READ | - HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW); - } else if (lp->mode == 2) { /* memory mapped */ - hp100_outw(HP100_BM_WRITE | - HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); - hp100_outw(HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW); - hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW); - hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); - } else if (lp->mode == 3) { /* i/o mapped mode */ - hp100_outw(HP100_MMAP_DIS | HP100_SET_HB | - HP100_IO_EN | HP100_SET_LB, OPTION_LSW); - } - hp100_page(HW_MAP); - hp100_outb(0, EARLYRXCFG); - hp100_outw(0, EARLYTXCFG); - - /* - * Enable Bus Master mode - */ - if (lp->mode == 1) { /* busmaster */ - /* Experimental: Set some PCI configuration bits */ - hp100_page(HW_MAP); - hp100_andb(~HP100_PDL_USE3, MODECTRL1); /* BM engine read maximum */ - hp100_andb(~HP100_TX_DUALQ, MODECTRL1); /* No Queue for Priority TX */ - - /* PCI Bus failures should result in a Misc. Interrupt */ - hp100_orb(HP100_EN_BUS_FAIL, MODECTRL2); - - hp100_outw(HP100_BM_READ | HP100_BM_WRITE | HP100_SET_HB, OPTION_LSW); - hp100_page(HW_MAP); - /* Use Burst Mode and switch on PAGE_CK */ - hp100_orb(HP100_BM_BURST_RD | - HP100_BM_BURST_WR, BM); - if ((lp->chip == HP100_CHIPID_RAINIER) || (lp->chip == HP100_CHIPID_SHASTA)) - hp100_orb(HP100_BM_PAGE_CK, BM); - hp100_orb(HP100_BM_MASTER, BM); - } else { /* not busmaster */ - hp100_page(HW_MAP); - hp100_andb(~HP100_BM_MASTER, BM); - } - - /* - * Divide card memory into regions for Rx, Tx and, if non-ETR chip, PDLs - */ - hp100_page(MMU_CFG); - if (lp->mode == 1) { /* only needed for Busmaster */ - int xmit_stop, recv_stop; - - if ((lp->chip == HP100_CHIPID_RAINIER) || (lp->chip == HP100_CHIPID_SHASTA)) { - int pdl_stop; - - /* - * Each pdl is 508 bytes long. (63 frags * 4 bytes for address and - * 4 bytes for for header). We will leave NUM_RXPDLS * 508 (rounded - * to the next higher 1k boundary) bytes for the rx-pdl's - * Note: For non-etr chips the transmit stop register must be - * programmed on a 1k boundary, i.e. bits 9:0 must be zero. - */ - pdl_stop = lp->memory_size; - xmit_stop = (pdl_stop - 508 * (MAX_RX_PDL) - 16) & ~(0x03ff); - recv_stop = (xmit_stop * (lp->rx_ratio) / 100) & ~(0x03ff); - hp100_outw((pdl_stop >> 4) - 1, PDL_MEM_STOP); + if( 0!=(hp100_inw(OPTION_LSW)&HP100_HW_RST) ) + { + printk("hp100: %s: Not in reset when entering mmuinit. Fix me.\n",dev->name); + return; + } +#endif + + /* Make sure IRQs are masked off and ack'ed. */ + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* ack IRQ */ + + /* + * Enable Hardware + * - Clear Debug En, Rx Hdr Pipe, EE En, I/O En, Fake Int and Intr En + * - Set Tri-State Int, Bus Master Rd/Wr, and Mem Map Disable + * - Clear Priority, Advance Pkt and Xmit Cmd + */ + + hp100_outw( HP100_DEBUG_EN | + HP100_RX_HDR | + HP100_EE_EN | HP100_RESET_HB | + HP100_IO_EN | + HP100_FAKE_INT | + HP100_INT_EN | HP100_RESET_LB, OPTION_LSW ); + + hp100_outw( HP100_TRI_INT | HP100_SET_HB, OPTION_LSW); + + if(lp->mode==1) /* busmaster */ + { + hp100_outw( HP100_BM_WRITE | + HP100_BM_READ | + HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW ); + } + else if(lp->mode==2) /* memory mapped */ + { + hp100_outw( HP100_BM_WRITE | + HP100_BM_READ | HP100_RESET_HB, OPTION_LSW ); + hp100_outw( HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW ); + hp100_outw( HP100_MEM_EN | HP100_SET_LB, OPTION_LSW ); + hp100_outw( HP100_IO_EN | HP100_SET_LB, OPTION_LSW ); + } + else if( lp->mode==3 ) /* i/o mapped mode */ + { + hp100_outw( HP100_MMAP_DIS | HP100_SET_HB | + HP100_IO_EN | HP100_SET_LB, OPTION_LSW ); + } + + hp100_page( HW_MAP ); + hp100_outb( 0, EARLYRXCFG ); + hp100_outw( 0, EARLYTXCFG ); + + /* + * Enable Bus Master mode + */ + if(lp->mode==1) /* busmaster */ + { + /* Experimental: Set some PCI configuration bits */ + hp100_page( HW_MAP ); + hp100_andb( ~HP100_PDL_USE3, MODECTRL1 ); /* BM engine read maximum */ + hp100_andb( ~HP100_TX_DUALQ, MODECTRL1 ); /* No Queue for Priority TX */ + + /* PCI Bus failures should result in a Misc. Interrupt */ + hp100_orb( HP100_EN_BUS_FAIL, MODECTRL2); + + hp100_outw( HP100_BM_READ | HP100_BM_WRITE | HP100_SET_HB, OPTION_LSW ); + hp100_page( HW_MAP ); + /* Use Burst Mode and switch on PAGE_CK */ + hp100_orb( HP100_BM_BURST_RD | + HP100_BM_BURST_WR, BM); + if((lp->chip==HP100_CHIPID_RAINIER)||(lp->chip==HP100_CHIPID_SHASTA)) + hp100_orb( HP100_BM_PAGE_CK, BM ); + hp100_orb( HP100_BM_MASTER, BM ); + } + else /* not busmaster */ + { + hp100_page(HW_MAP); + hp100_andb(~HP100_BM_MASTER, BM ); + } + + /* + * Divide card memory into regions for Rx, Tx and, if non-ETR chip, PDLs + */ + hp100_page( MMU_CFG ); + if(lp->mode==1) /* only needed for Busmaster */ + { + int xmit_stop, recv_stop; + + if((lp->chip==HP100_CHIPID_RAINIER)||(lp->chip==HP100_CHIPID_SHASTA)) + { + int pdl_stop; + + /* + * Each pdl is 508 bytes long. (63 frags * 4 bytes for address and + * 4 bytes for for header). We will leave NUM_RXPDLS * 508 (rounded + * to the next higher 1k boundary) bytes for the rx-pdl's + * Note: For non-etr chips the transmit stop register must be + * programmed on a 1k boundary, i.e. bits 9:0 must be zero. + */ + pdl_stop = lp->memory_size; + xmit_stop = ( pdl_stop-508*(MAX_RX_PDL)-16 )& ~(0x03ff); + recv_stop = ( xmit_stop * (lp->rx_ratio)/100 ) &~(0x03ff); + hp100_outw( (pdl_stop>>4)-1, PDL_MEM_STOP ); #ifdef HP100_DEBUG_BM - printk("hp100: PDL_STOP = 0x%x\n", pdl_stop); + printk("hp100: %s: PDL_STOP = 0x%x\n", dev->name, pdl_stop); #endif - } else { /* ETR chip (Lassen) in busmaster mode */ - xmit_stop = (lp->memory_size) - 1; - recv_stop = ((lp->memory_size * lp->rx_ratio) / 100) & ~(0x03ff); - } + } + else /* ETR chip (Lassen) in busmaster mode */ + { + xmit_stop = ( lp->memory_size ) - 1; + recv_stop = ( ( lp->memory_size * lp->rx_ratio ) / 100 ) & ~(0x03ff); + } - hp100_outw(xmit_stop >> 4, TX_MEM_STOP); - hp100_outw(recv_stop >> 4, RX_MEM_STOP); + hp100_outw( xmit_stop>>4 , TX_MEM_STOP ); + hp100_outw( recv_stop>>4 , RX_MEM_STOP ); #ifdef HP100_DEBUG_BM - printk("hp100: TX_STOP = 0x%x\n", xmit_stop >> 4); - printk("hp100: RX_STOP = 0x%x\n", recv_stop >> 4); -#endif - } else { /* Slave modes (memory mapped and programmed io) */ - hp100_outw((((lp->memory_size * lp->rx_ratio) / 100) >> 4), RX_MEM_STOP); - hp100_outw(((lp->memory_size - 1) >> 4), TX_MEM_STOP); + printk("hp100: %s: TX_STOP = 0x%x\n",dev->name,xmit_stop>>4); + printk("hp100: %s: RX_STOP = 0x%x\n",dev->name,recv_stop>>4); +#endif + } + else /* Slave modes (memory mapped and programmed io) */ + { + hp100_outw( (((lp->memory_size*lp->rx_ratio)/100)>>4), RX_MEM_STOP ); + hp100_outw( ((lp->memory_size - 1 )>>4), TX_MEM_STOP ); #ifdef HP100_DEBUG - printk("hp100: TX_MEM_STOP: 0x%x\n", hp100_inw(TX_MEM_STOP)); - printk("hp100: RX_MEM_STOP: 0x%x\n", hp100_inw(RX_MEM_STOP)); -#endif - } - - /* Write MAC address into page 1 */ - hp100_page(MAC_ADDRESS); - for (i = 0; i < 6; i++) - hp100_outb(dev->dev_addr[i], MAC_ADDR + i); - - /* Zero the multicast hash registers */ - for (i = 0; i < 8; i++) - hp100_outb(0x0, HASH_BYTE0 + i); - - /* Set up MAC defaults */ - hp100_page(MAC_CTRL); - - /* Go to LAN Page and zero all filter bits */ - /* Zero accept error, accept multicast, accept broadcast and accept */ - /* all directed packet bits */ - hp100_andb(~(HP100_RX_EN | - HP100_TX_EN | - HP100_ACC_ERRORED | - HP100_ACC_MC | - HP100_ACC_BC | - HP100_ACC_PHY), MAC_CFG_1); - - hp100_outb(0x00, MAC_CFG_2); - - /* Zero the frame format bit. This works around a training bug in the */ - /* new hubs. */ - hp100_outb(0x00, VG_LAN_CFG_2); /* (use 802.3) */ - - if (lp->priority_tx) - hp100_outb(HP100_PRIORITY_TX | HP100_SET_LB, OPTION_MSW); - else - hp100_outb(HP100_PRIORITY_TX | HP100_RESET_LB, OPTION_MSW); - - hp100_outb(HP100_ADV_NXT_PKT | - HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW); - - /* If busmaster, initialize the PDLs */ - if (lp->mode == 1) - hp100_init_pdls(dev); - - /* Go to performance page and initalize isr and imr registers */ - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */ + printk("hp100: %s: TX_MEM_STOP: 0x%x\n", dev->name,hp100_inw(TX_MEM_STOP)); + printk("hp100: %s: RX_MEM_STOP: 0x%x\n", dev->name,hp100_inw(RX_MEM_STOP)); +#endif + } + + /* Write MAC address into page 1 */ + hp100_page( MAC_ADDRESS ); + for ( i = 0; i < 6; i++ ) + hp100_outb( dev->dev_addr[ i ], MAC_ADDR + i ); + + /* Zero the multicast hash registers */ + for ( i = 0; i < 8; i++ ) + hp100_outb( 0x0, HASH_BYTE0 + i ); + + /* Set up MAC defaults */ + hp100_page( MAC_CTRL ); + + /* Go to LAN Page and zero all filter bits */ + /* Zero accept error, accept multicast, accept broadcast and accept */ + /* all directed packet bits */ + hp100_andb( ~(HP100_RX_EN| + HP100_TX_EN| + HP100_ACC_ERRORED| + HP100_ACC_MC| + HP100_ACC_BC| + HP100_ACC_PHY), MAC_CFG_1 ); + + hp100_outb( 0x00, MAC_CFG_2 ); + + /* Zero the frame format bit. This works around a training bug in the */ + /* new hubs. */ + hp100_outb( 0x00, VG_LAN_CFG_2); /* (use 802.3) */ + + if(lp->priority_tx) + hp100_outb( HP100_PRIORITY_TX | HP100_SET_LB, OPTION_MSW ); + else + hp100_outb( HP100_PRIORITY_TX | HP100_RESET_LB, OPTION_MSW ); + + hp100_outb( HP100_ADV_NXT_PKT | + HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW ); + + /* If busmaster, initialize the PDLs */ + if(lp->mode==1) + hp100_init_pdls( dev ); + + /* Go to performance page and initalize isr and imr registers */ + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* ack IRQ */ } - + /* * open/close functions */ -static int hp100_open(struct device *dev) +static int hp100_open( struct device *dev ) { - struct hp100_private *lp = (struct hp100_private *) dev->priv; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - int ioaddr = dev->base_addr; + int ioaddr=dev->base_addr; #endif #ifdef HP100_DEBUG_B - hp100_outw(0x4204, TRACE); - printk("hp100: open\n"); -#endif - - /* New: if bus is PCI or EISA, interrupts might be shared interrupts */ - if ((lp->bus == HP100_BUS_PCI) || (lp->bus == HP100_BUS_EISA)) { - if (request_irq(dev->irq, hp100_interrupt, SA_SHIRQ, lp->id->name, dev)) { - printk("%s: unable to get IRQ %d\n", dev->name, dev->irq); - return -EAGAIN; - } - } else if (request_irq(dev->irq, hp100_interrupt, SA_INTERRUPT, lp->id->name, dev)) { - printk("%s: unable to get IRQ %d\n", dev->name, dev->irq); - return -EAGAIN; - } - MOD_INC_USE_COUNT; - - dev->tbusy = 0; - dev->trans_start = jiffies; - dev->interrupt = 0; - dev->start = 1; - - lp->lan_type = hp100_sense_lan(dev); - lp->mac1_mode = HP100_MAC1MODE3; - lp->mac2_mode = HP100_MAC2MODE3; - - hp100_stop_interface(dev); - - hp100_hwinit(dev); - - hp100_start_interface(dev); /* sets mac modes, enables interrupts */ - - return 0; + hp100_outw( 0x4204, TRACE ); + printk("hp100: %s: open\n",dev->name); +#endif + + /* New: if bus is PCI or EISA, interrupts might be shared interrupts */ + if ( request_irq(dev->irq, hp100_interrupt, + lp->bus==HP100_BUS_PCI||lp->bus==HP100_BUS_EISA?SA_SHIRQ:SA_INTERRUPT, + lp->id->name, dev)) + { + printk( "hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq ); + return -EAGAIN; + } + + MOD_INC_USE_COUNT; + + dev->tbusy = 0; + dev->trans_start = jiffies; + dev->interrupt = 0; + dev->start = 1; + + lp->lan_type = hp100_sense_lan( dev ); + lp->mac1_mode = HP100_MAC1MODE3; + lp->mac2_mode = HP100_MAC2MODE3; + memset( &lp->hash_bytes, 0x00, 8 ); + + hp100_stop_interface( dev ); + + hp100_hwinit( dev ); + + hp100_start_interface( dev ); /* sets mac modes, enables interrupts */ + + return 0; } - + /* The close function is called when the interface is to be brought down */ -static int hp100_close(struct device *dev) +static int hp100_close( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4205, TRACE); - printk("hp100:close\n"); + hp100_outw( 0x4205, TRACE ); + printk("hp100: %s: close\n", dev->name); #endif - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all IRQs */ + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all IRQs */ + + hp100_stop_interface( dev ); + + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status=hp100_login_to_vg_hub( dev, FALSE ); - hp100_stop_interface(dev); + dev->tbusy = 1; + dev->start = 0; - if (lp->lan_type == HP100_LAN_100) - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); + free_irq( dev->irq, dev ); - dev->tbusy = 1; - dev->start = 0; +#ifdef HP100_DEBUG + printk( "hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) ); +#endif - if ((lp->bus == HP100_BUS_PCI) || (lp->bus == HP100_BUS_EISA)) - free_irq(dev->irq, dev); - else - free_irq(dev->irq, NULL); - MOD_DEC_USE_COUNT; - return 0; + MOD_DEC_USE_COUNT; + return 0; } - + /* * Configure the PDL Rx rings and LAN */ -static void hp100_init_pdls(struct device *dev) +static void hp100_init_pdls( struct device *dev ) { - struct hp100_private *lp = (struct hp100_private *) dev->priv; - hp100_ring_t *ringptr; - u_int *pageptr; - int i; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + hp100_ring_t *ringptr; + u_int *pageptr; + int i; #ifdef HP100_DEBUG_B - int ioaddr = dev->base_addr; + int ioaddr = dev->base_addr; #endif #ifdef HP100_DEBUG_B - hp100_outw(0x4206, TRACE); - printk("hp100: init pdls\n"); -#endif - - if (0 == lp->page_vaddr_algn) - printk("hp100: Warning: lp->page_vaddr_algn not initialised!\n"); - else { - /* pageptr shall point into the DMA accessible memory region */ - /* we use this pointer to status the upper limit of allocated */ - /* memory in the allocated page. */ - /* note: align the pointers to the pci cache line size */ - memset(lp->page_vaddr_algn, 0, MAX_RINGSIZE); /* Zero Rx/Tx ring page */ - pageptr = lp->page_vaddr_algn; - - lp->rxrcommit = 0; - ringptr = lp->rxrhead = lp->rxrtail = &(lp->rxring[0]); - - /* Initialise Rx Ring */ - for (i = MAX_RX_PDL - 1; i >= 0; i--) { - lp->rxring[i].next = ringptr; - ringptr = &(lp->rxring[i]); - pageptr += hp100_init_rxpdl(ringptr, pageptr); - } - - /* Initialise Tx Ring */ - lp->txrcommit = 0; - ringptr = lp->txrhead = lp->txrtail = &(lp->txring[0]); - for (i = MAX_TX_PDL - 1; i >= 0; i--) { - lp->txring[i].next = ringptr; - ringptr = &(lp->txring[i]); - pageptr += hp100_init_txpdl(ringptr, pageptr); - } - } + hp100_outw( 0x4206, TRACE ); + printk("hp100: %s: init pdls\n", dev->name); +#endif + + if(0==lp->page_vaddr_algn) + printk("hp100: %s: Warning: lp->page_vaddr_algn not initialised!\n",dev->name); + else + { + /* pageptr shall point into the DMA accessible memory region */ + /* we use this pointer to status the upper limit of allocated */ + /* memory in the allocated page. */ + /* note: align the pointers to the pci cache line size */ + memset(lp->page_vaddr_algn, 0, MAX_RINGSIZE); /* Zero Rx/Tx ring page */ + pageptr=lp->page_vaddr_algn; + + lp->rxrcommit =0; + ringptr = lp->rxrhead = lp-> rxrtail = &(lp->rxring[0]); + + /* Initialise Rx Ring */ + for (i=MAX_RX_PDL-1; i>=0; i--) + { + lp->rxring[i].next = ringptr; + ringptr=&(lp->rxring[i]); + pageptr+=hp100_init_rxpdl(dev, ringptr, pageptr); + } + + /* Initialise Tx Ring */ + lp->txrcommit = 0; + ringptr = lp->txrhead = lp->txrtail = &(lp->txring[0]); + for (i=MAX_TX_PDL-1; i>=0; i--) + { + lp->txring[i].next = ringptr; + ringptr=&(lp->txring[i]); + pageptr+=hp100_init_txpdl(dev, ringptr, pageptr); + } + } } - + /* These functions "format" the entries in the pdl structure */ /* They return how much memory the fragments need. */ -static int hp100_init_rxpdl(register hp100_ring_t * ringptr, register u32 * pdlptr) +static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr ) { - /* pdlptr is starting adress for this pdl */ + /* pdlptr is starting adress for this pdl */ - if (0 != (((unsigned) pdlptr) & 0xf)) - printk("hp100: Init rxpdl: Unaligned pdlptr 0x%x.\n", (unsigned) pdlptr); + if( 0!=( ((unsigned)pdlptr) & 0xf) ) + printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr); - ringptr->pdl = pdlptr + 1; - ringptr->pdl_paddr = virt_to_bus(pdlptr + 1); - ringptr->skb = (void *) NULL; + ringptr->pdl = pdlptr+1; + ringptr->pdl_paddr = virt_to_bus(pdlptr+1); + ringptr->skb = (void *) NULL; - /* - * Write address and length of first PDL Fragment (which is used for - * storing the RX-Header - * We use the 4 bytes _before_ the PDH in the pdl memory area to - * store this information. (PDH is at offset 0x04) - */ - /* Note that pdlptr+1 and not pdlptr is the pointer to the PDH */ + /* + * Write address and length of first PDL Fragment (which is used for + * storing the RX-Header + * We use the 4 bytes _before_ the PDH in the pdl memory area to + * store this information. (PDH is at offset 0x04) + */ + /* Note that pdlptr+1 and not pdlptr is the pointer to the PDH */ - *(pdlptr + 2) = (u_int) virt_to_bus(pdlptr); /* Address Frag 1 */ - *(pdlptr + 3) = 4; /* Length Frag 1 */ + *(pdlptr+2) =(u_int) virt_to_bus(pdlptr); /* Address Frag 1 */ + *(pdlptr+3) = 4; /* Length Frag 1 */ - return ((((MAX_RX_FRAG * 2 + 2) + 3) / 4) * 4); + return( ( ((MAX_RX_FRAG*2+2)+3) /4)*4 ); } -static int hp100_init_txpdl(register hp100_ring_t * ringptr, register u32 * pdlptr) +static int hp100_init_txpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr ) { - if (0 != (((unsigned) pdlptr) & 0xf)) - printk("hp100: Init txpdl: Unaligned pdlptr 0x%x.\n", (unsigned) pdlptr); - - ringptr->pdl = pdlptr; /* +1; */ - ringptr->pdl_paddr = virt_to_bus(pdlptr); /* +1 */ - ringptr->skb = (void *) NULL; - - return ((((MAX_TX_FRAG * 2 + 2) + 3) / 4) * 4); + if( 0!=( ((unsigned)pdlptr) & 0xf) ) + printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned) pdlptr); + + ringptr->pdl = pdlptr; /* +1; */ + ringptr->pdl_paddr = virt_to_bus(pdlptr); /* +1 */ + ringptr->skb = (void *) NULL; + + return((((MAX_TX_FRAG*2+2)+3)/4)*4); } - + /* * hp100_build_rx_pdl allocates an skb_buff of maximum size plus two bytes * for possible odd word alignment rounding up to next dword and set PDL @@ -1119,77 +1309,80 @@ static int hp100_init_txpdl(register hp100_ring_t * ringptr, register u32 * pdlp * Returns: 0 if unable to allocate skb_buff * 1 if successful */ -int hp100_build_rx_pdl(hp100_ring_t * ringptr, struct device *dev) +int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct device *dev ) { #ifdef HP100_DEBUG_B - int ioaddr = dev->base_addr; + int ioaddr = dev->base_addr; #endif #ifdef HP100_DEBUG_BM - u_int *p; + u_int *p; #endif #ifdef HP100_DEBUG_B - hp100_outw(0x4207, TRACE); - printk("hp100: build rx pdl\n"); -#endif - - /* Allocate skb buffer of maximum size */ - /* Note: This depends on the alloc_skb functions allocating more - * space than requested, i.e. aligning to 16bytes */ - - ringptr->skb = dev_alloc_skb(((MAX_ETHER_SIZE + 2 + 3) / 4) * 4); - - if (NULL != ringptr->skb) { - /* - * Reserve 2 bytes at the head of the buffer to land the IP header - * on a long word boundary (According to the Network Driver section - * in the Linux KHG, this should help to increase performance.) - */ - skb_reserve(ringptr->skb, 2); - - ringptr->skb->dev = dev; - ringptr->skb->data = (u_char *) skb_put(ringptr->skb, MAX_ETHER_SIZE); - - /* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */ - /* Note: 1st Fragment is used for the 4 byte packet status - * (receive header). Its PDL entries are set up by init_rxpdl. So - * here we only have to set up the PDL fragment entries for the data - * part. Those 4 bytes will be stored in the DMA memory region - * directly before the PDL. - */ + hp100_outw( 0x4207, TRACE ); + printk("hp100: %s: build rx pdl\n", dev->name); +#endif + + /* Allocate skb buffer of maximum size */ + /* Note: This depends on the alloc_skb functions allocating more + * space than requested, i.e. aligning to 16bytes */ + + ringptr->skb = dev_alloc_skb( ((MAX_ETHER_SIZE+2+3)/4)*4 ); + + if(NULL!=ringptr->skb) + { + /* + * Reserve 2 bytes at the head of the buffer to land the IP header + * on a long word boundary (According to the Network Driver section + * in the Linux KHG, this should help to increase performance.) + */ + skb_reserve(ringptr->skb, 2); + + ringptr->skb->dev=dev; + ringptr->skb->data=(u_char *)skb_put(ringptr->skb, MAX_ETHER_SIZE ); + + /* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */ + /* Note: 1st Fragment is used for the 4 byte packet status + * (receive header). Its PDL entries are set up by init_rxpdl. So + * here we only have to set up the PDL fragment entries for the data + * part. Those 4 bytes will be stored in the DMA memory region + * directly before the PDL. + */ #ifdef HP100_DEBUG_BM - printk("hp100: build_rx_pdl: PDH@0x%x, skb->data (len %d) at 0x%x\n", - (u_int) ringptr->pdl, - ((MAX_ETHER_SIZE + 2 + 3) / 4) * 4, - (unsigned int) ringptr->skb->data); + printk("hp100: %s: build_rx_pdl: PDH@0x%x, skb->data (len %d) at 0x%x\n", + dev->name, + (u_int) ringptr->pdl, + ((MAX_ETHER_SIZE+2+3)/4)*4, + (unsigned int) ringptr->skb->data); #endif - ringptr->pdl[0] = 0x00020000; /* Write PDH */ - ringptr->pdl[3] = ((u_int) virt_to_bus(ringptr->skb->data)); - ringptr->pdl[4] = MAX_ETHER_SIZE; /* Length of Data */ - + ringptr->pdl[0] = 0x00020000; /* Write PDH */ + ringptr->pdl[3] = ((u_int)virt_to_bus(ringptr->skb->data)); + ringptr->pdl[4] = MAX_ETHER_SIZE; /* Length of Data */ + #ifdef HP100_DEBUG_BM - for (p = (ringptr->pdl); p < (ringptr->pdl + 5); p++) - printk("Adr 0x%.8x = 0x%.8x\n", (u_int) p, (u_int) * p); -#endif - return (1); - } - /* else: */ - /* alloc_skb failed (no memory) -> still can receive the header - * fragment into PDL memory. make PDL safe by clearing msgptr and - * making the PDL only 1 fragment (i.e. the 4 byte packet status) - */ + for(p=(ringptr->pdl); p<(ringptr->pdl+5); p++) + printk("hp100: %s: Adr 0x%.8x = 0x%.8x\n",dev->name,(u_int) p,(u_int) *p ); +#endif + return(1); + } + /* else: */ + /* alloc_skb failed (no memory) -> still can receive the header + * fragment into PDL memory. make PDL safe by clearing msgptr and + * making the PDL only 1 fragment (i.e. the 4 byte packet status) + */ #ifdef HP100_DEBUG_BM - printk("hp100: build_rx_pdl: PDH@0x%x, No space for skb.\n", - (u_int) ringptr->pdl); + printk("hp100: %s: build_rx_pdl: PDH@0x%x, No space for skb.\n", + dev->name, + (u_int) ringptr->pdl); #endif - ringptr->pdl[0] = 0x00010000; /* PDH: Count=1 Fragment */ + ringptr->pdl[0]=0x00010000; /* PDH: Count=1 Fragment */ - return (0); + return(0); } - + /* * hp100_rxfill - attempt to fill the Rx Ring will empty skb's * @@ -1200,246 +1393,279 @@ int hp100_build_rx_pdl(hp100_ring_t * ringptr, struct device *dev) * b. Put the physical address of the buffer into the PDL. * c. Output physical address of PDL to adapter. */ -static void hp100_rxfill(struct device *dev) +static void hp100_rxfill( struct device *dev ) { - int ioaddr = dev->base_addr; + int ioaddr=dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - hp100_ring_t *ringptr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + hp100_ring_t *ringptr; #ifdef HP100_DEBUG_B - hp100_outw(0x4208, TRACE); - printk("hp100: rxfill\n"); -#endif - - hp100_page(PERFORMANCE); - - while (lp->rxrcommit < MAX_RX_PDL) { - /* - ** Attempt to get a buffer and build a Rx PDL. - */ - ringptr = lp->rxrtail; - if (0 == hp100_build_rx_pdl(ringptr, dev)) { - return; /* None available, return */ - } - /* Hand this PDL over to the card */ - /* Note: This needs performance page selected! */ + hp100_outw( 0x4208, TRACE ); + printk("hp100: %s: rxfill\n",dev->name); +#endif + + hp100_page( PERFORMANCE ); + + while (lp->rxrcommit < MAX_RX_PDL) + { + /* + ** Attempt to get a buffer and build a Rx PDL. + */ + ringptr = lp->rxrtail; + if (0 == hp100_build_rx_pdl( ringptr, dev )) + { + return; /* None available, return */ + } + + /* Hand this PDL over to the card */ + /* Note: This needs performance page selected! */ #ifdef HP100_DEBUG_BM - printk("hp100: rxfill: Hand to card: pdl #%d @0x%x phys:0x%x, buffer: 0x%x\n", - lp->rxrcommit, - (u_int) ringptr->pdl, - (u_int) ringptr->pdl_paddr, - (u_int) ringptr->pdl[3]); -#endif - - hp100_outl((u32) ringptr->pdl_paddr, RX_PDA); - - lp->rxrcommit += 1; - lp->rxrtail = ringptr->next; - } + printk("hp100: %s: rxfill: Hand to card: pdl #%d @0x%x phys:0x%x, buffer: 0x%x\n", + dev->name, + lp->rxrcommit, + (u_int)ringptr->pdl, + (u_int)ringptr->pdl_paddr, + (u_int)ringptr->pdl[3]); +#endif + + hp100_outl( (u32)ringptr->pdl_paddr, RX_PDA); + + lp->rxrcommit += 1; + lp->rxrtail = ringptr->next; + } } - + /* * BM_shutdown - shutdown bus mastering and leave chip in reset state */ -static void hp100_BM_shutdown(struct device *dev) +static void hp100_BM_shutdown( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - unsigned long time; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + unsigned long time; #ifdef HP100_DEBUG_B - hp100_outw(0x4209, TRACE); - printk("hp100: bm shutdown\n"); -#endif - - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* Ack all ints */ - - /* Ensure Interrupts are off */ - hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); - - /* Disable all MAC activity */ - hp100_page(MAC_CTRL); - hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); /* stop rx/tx */ - - /* If cascade MMU is not already in reset */ - if (0 != (hp100_inw(OPTION_LSW) & HP100_HW_RST)) { - /* Wait 1.3ms (10Mb max packet time) to ensure MAC is idle so - * MMU pointers will not be reset out from underneath - */ - hp100_page(MAC_CTRL); - for (time = 0; time < 5000; time++) { - if ((hp100_inb(MAC_CFG_1) & (HP100_TX_IDLE | HP100_RX_IDLE)) == - (HP100_TX_IDLE | HP100_RX_IDLE)) - break; - } - - /* Shutdown algorithm depends on the generation of Cascade */ - if (lp->chip == HP100_CHIPID_LASSEN) { /* ETR shutdown/reset */ - /* Disable Busmaster mode and wait for bit to go to zero. */ - hp100_page(HW_MAP); - hp100_andb(~HP100_BM_MASTER, BM); - /* 100 ms timeout */ - for (time = 0; time < 32000; time++) { - if (0 == (hp100_inb(BM) & HP100_BM_MASTER)) - break; - } - } else { /* Shasta or Rainier Shutdown/Reset */ - /* To ensure all bus master inloading activity has ceased, - * wait for no Rx PDAs or no Rx packets on card. - */ - hp100_page(PERFORMANCE); - /* 100 ms timeout */ - for (time = 0; time < 10000; time++) { - /* RX_PDL: PDLs not executed. */ - /* RX_PKT_CNT: RX'd packets on card. */ - if ((hp100_inb(RX_PDL) == 0) && - (hp100_inb(RX_PKT_CNT) == 0)) - break; - } - - if (time >= 10000) - printk("hp100: BM shutdown error.\n"); - - /* To ensure all bus master outloading activity has ceased, - * wait until the Tx PDA count goes to zero or no more Tx space - * available in the Tx region of the card. - */ - /* 100 ms timeout */ - for (time = 0; time < 10000; time++) { - if ((0 == hp100_inb(TX_PKT_CNT)) && - (0 != (hp100_inb(TX_MEM_FREE) & HP100_AUTO_COMPARE))) - break; - } - - /* Disable Busmaster mode */ - hp100_page(HW_MAP); - hp100_andb(~HP100_BM_MASTER, BM); - } /* end of shutdown procedure for non-etr parts */ - - hp100_cascade_reset(dev, TRUE); - } - hp100_page(PERFORMANCE); - hp100_outw(HP100_BM_READ | HP100_BM_WRITE | HP100_RESET_HB, OPTION_LSW); - /* Busmaster mode should be shut down now. */ + hp100_outw( 0x4209, TRACE ); + printk("hp100: %s: bm shutdown\n",dev->name); +#endif + + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* Ack all ints */ + + /* Ensure Interrupts are off */ + hp100_outw( HP100_INT_EN | HP100_RESET_LB , OPTION_LSW ); + + /* Disable all MAC activity */ + hp100_page( MAC_CTRL ); + hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */ + + /* If cascade MMU is not already in reset */ + if (0 != (hp100_inw(OPTION_LSW)&HP100_HW_RST) ) + { + /* Wait 1.3ms (10Mb max packet time) to ensure MAC is idle so + * MMU pointers will not be reset out from underneath + */ + hp100_page( MAC_CTRL ); + for(time=0; time<5000; time++) + { + if( (hp100_inb(MAC_CFG_1)&(HP100_TX_IDLE|HP100_RX_IDLE))== + (HP100_TX_IDLE|HP100_RX_IDLE) ) break; + } + + /* Shutdown algorithm depends on the generation of Cascade */ + if( lp->chip==HP100_CHIPID_LASSEN ) + { /* ETR shutdown/reset */ + /* Disable Busmaster mode and wait for bit to go to zero. */ + hp100_page(HW_MAP); + hp100_andb( ~HP100_BM_MASTER, BM ); + /* 100 ms timeout */ + for(time=0; time<32000; time++) + { + if ( 0 == (hp100_inb( BM ) & HP100_BM_MASTER) ) break; + } + } + else + { /* Shasta or Rainier Shutdown/Reset */ + /* To ensure all bus master inloading activity has ceased, + * wait for no Rx PDAs or no Rx packets on card. + */ + hp100_page( PERFORMANCE ); + /* 100 ms timeout */ + for(time=0; time<10000; time++) + { + /* RX_PDL: PDLs not executed. */ + /* RX_PKT_CNT: RX'd packets on card. */ + if ( (hp100_inb( RX_PDL ) == 0) && + (hp100_inb( RX_PKT_CNT ) == 0) ) break; + } + + if(time>=10000) + printk("hp100: %s: BM shutdown error.\n", dev->name); + + /* To ensure all bus master outloading activity has ceased, + * wait until the Tx PDA count goes to zero or no more Tx space + * available in the Tx region of the card. + */ + /* 100 ms timeout */ + for(time=0; time<10000; time++) { + if ( (0 == hp100_inb( TX_PKT_CNT )) && + (0 != (hp100_inb( TX_MEM_FREE )&HP100_AUTO_COMPARE))) break; + } + + /* Disable Busmaster mode */ + hp100_page(HW_MAP); + hp100_andb( ~HP100_BM_MASTER, BM ); + } /* end of shutdown procedure for non-etr parts */ + + hp100_cascade_reset( dev, TRUE ); + } + hp100_page( PERFORMANCE ); + /* hp100_outw( HP100_BM_READ | HP100_BM_WRITE | HP100_RESET_HB, OPTION_LSW ); */ + /* Busmaster mode should be shut down now. */ } - + /* * transmit functions */ /* tx function for busmaster mode */ -static int hp100_start_xmit_bm(struct sk_buff *skb, struct device *dev) +static int hp100_start_xmit_bm( struct sk_buff *skb, struct device *dev ) { - int i, ok_flag; - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - hp100_ring_t *ringptr; + unsigned long flags; + int i, ok_flag; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + hp100_ring_t *ringptr; #ifdef HP100_DEBUG_B - hp100_outw(0x4210, TRACE); - printk("hp100: start_xmit_bm\n"); -#endif - - /* Get Tx ring tail pointer */ - if (lp->txrtail->next == lp->txrhead) { - /* No memory. */ + hp100_outw( 0x4210, TRACE ); + printk("hp100: %s: start_xmit_bm\n",dev->name); +#endif + + if ( skb==NULL ) + { +#ifndef LINUX_2_1 + dev_tint( dev ); +#endif + return 0; + } + + if ( skb->len <= 0 ) return 0; + + /* Get Tx ring tail pointer */ + if( lp->txrtail->next==lp->txrhead ) + { + /* No memory. */ #ifdef HP100_DEBUG - printk("hp100: start_xmit_bm: No TX PDL available.\n"); -#endif - /* not waited long enough since last tx? */ - if (jiffies - dev->trans_start < HZ / 10) - return -EAGAIN; - - if (lp->lan_type < 0) { /* no LAN type detected yet? */ - hp100_stop_interface(dev); - if ((lp->lan_type = hp100_sense_lan(dev)) < 0) { - printk("%s: no connection found - check wire\n", dev->name); - hp100_start_interface(dev); /* 10Mb/s RX pkts maybe handled */ - return -EIO; - } - if (lp->lan_type == HP100_LAN_100) - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); /* relogin */ - hp100_start_interface(dev); - } - if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) - /* we have a 100Mb/s adapter but it isn't connected to hub */ - { - printk("%s: login to 100Mb/s hub retry\n", dev->name); - hp100_stop_interface(dev); - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); - hp100_start_interface(dev); - } else { - hp100_ints_off(); - i = hp100_sense_lan(dev); - hp100_page(PERFORMANCE); - hp100_ints_on(); - if (i == HP100_LAN_ERR) - printk("%s: link down detected\n", dev->name); - else if (lp->lan_type != i) { /* cable change! */ - /* it's very hard - all network setting must be changed!!! */ - printk("%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name); - lp->lan_type = i; - hp100_stop_interface(dev); - if (lp->lan_type == HP100_LAN_100) - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); - hp100_start_interface(dev); - } else { - printk("%s: interface reset\n", dev->name); - hp100_stop_interface(dev); - hp100_start_interface(dev); - } - } - - dev->trans_start = jiffies; - return -EAGAIN; + printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name); +#endif + /* not waited long enough since last tx? */ + if ( jiffies - dev->trans_start < HZ ) return -EAGAIN; + + if ( lp->lan_type < 0 ) /* no LAN type detected yet? */ + { + hp100_stop_interface( dev ); + if ( ( lp->lan_type = hp100_sense_lan( dev ) ) < 0 ) + { + printk( "hp100: %s: no connection found - check wire\n", dev->name ); + hp100_start_interface( dev ); /* 10Mb/s RX pkts maybe handled */ + return -EIO; + } + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); /* relogin */ + hp100_start_interface( dev ); } - /* - * we have to turn int's off before modifying this, otherwise - * a tx_pdl_cleanup could occur at the same time - */ - cli(); - ringptr = lp->txrtail; - lp->txrtail = ringptr->next; - - /* Check whether packet has minimal packet size */ - ok_flag = skb->len >= HP100_MIN_PACKET_SIZE; - i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE; - - ringptr->skb = skb; - ringptr->pdl[0] = ((1 << 16) | i); /* PDH: 1 Fragment & length */ - ringptr->pdl[1] = (u32) virt_to_bus(skb->data); /* 1st Frag: Adr. of data */ - if (lp->chip == HP100_CHIPID_SHASTA) { - /* TODO:Could someone who has the EISA card please check if this works? */ - ringptr->pdl[2] = i; - } else { /* Lassen */ - /* In the PDL, don't use the padded size but the real packet size: */ - ringptr->pdl[2] = skb->len; /* 1st Frag: Length of frag */ + + if ( lp->lan_type == HP100_LAN_100 && lp->hub_status < 0 ) + /* we have a 100Mb/s adapter but it isn't connected to hub */ + { + printk( "hp100: %s: login to 100Mb/s hub retry\n", dev->name ); + hp100_stop_interface( dev ); + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + } + else + { + hp100_ints_off(); + i = hp100_sense_lan( dev ); + hp100_ints_on(); + if ( i == HP100_LAN_ERR ) + printk( "hp100: %s: link down detected\n", dev->name ); + else + if ( lp->lan_type != i ) /* cable change! */ + { + /* it's very hard - all network setting must be changed!!! */ + printk( "hp100: %s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name ); + lp->lan_type = i; + hp100_stop_interface( dev ); + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + } + else + { + printk( "hp100: %s: interface reset\n", dev->name ); + hp100_stop_interface( dev ); + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + } } - /* Hand this PDL to the card. */ - hp100_outl(ringptr->pdl_paddr, TX_PDA_L); /* Low Prio. Queue */ - - lp->txrcommit++; - sti(); - - /* Update statistics */ - lp->stats.tx_packets++; + dev->trans_start = jiffies; + return -EAGAIN; + } + + /* + * we have to turn int's off before modifying this, otherwise + * a tx_pdl_cleanup could occur at the same time + */ + save_flags( flags ); + cli(); + ringptr=lp->txrtail; + lp->txrtail=ringptr->next; + + /* Check whether packet has minimal packet size */ + ok_flag = skb->len >= HP100_MIN_PACKET_SIZE; + i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE; + + ringptr->skb=skb; + ringptr->pdl[0]=((1<<16) | i); /* PDH: 1 Fragment & length */ + ringptr->pdl[1]=(u32)virt_to_bus(skb->data); /* 1st Frag: Adr. of data */ + if(lp->chip==HP100_CHIPID_SHASTA) + { + /* TODO:Could someone who has the EISA card please check if this works? */ + ringptr->pdl[2]=i; + } + else /* Lassen */ + { + /* In the PDL, don't use the padded size but the real packet size: */ + ringptr->pdl[2]=skb->len; /* 1st Frag: Length of frag */ + } + + /* Hand this PDL to the card. */ + hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */ + + lp->txrcommit++; + restore_flags( flags ); + + /* Update statistics */ + lp->stats.tx_packets++; #ifdef LINUX_2_1 - lp->stats.tx_bytes += skb->len; + lp->stats.tx_bytes += skb->len; #endif - dev->trans_start = jiffies; - - return 0; + dev->trans_start = jiffies; + + return 0; } - + /* clean_txring checks if packets have been sent by the card by reading * the TX_PDL register from the performance page and comparing it to the * number of commited packets. It then frees the skb's of the packets that @@ -1447,168 +1673,209 @@ static int hp100_start_xmit_bm(struct sk_buff *skb, struct device *dev) * * Needs the PERFORMANCE page selected. */ -static void hp100_clean_txring(struct device *dev) +static void hp100_clean_txring( struct device *dev ) { - struct hp100_private *lp = (struct hp100_private *) dev->priv; - int ioaddr = dev->base_addr; - int donecount; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + int ioaddr = dev->base_addr; + int donecount; #ifdef HP100_DEBUG_B - hp100_outw(0x4211, TRACE); - printk("hp100: clean txring\n"); + hp100_outw( 0x4211, TRACE ); + printk("hp100: %s: clean txring\n", dev->name); #endif - /* How many PDLs have been transmitted? */ - donecount = (lp->txrcommit) - hp100_inb(TX_PDL); + /* How many PDLs have been transmitted? */ + donecount=(lp->txrcommit)-hp100_inb(TX_PDL); #ifdef HP100_DEBUG - if (donecount > MAX_TX_PDL) - printk("hp100: Warning: More PDLs transmitted than commited to card???\n"); + if(donecount>MAX_TX_PDL) + printk("hp100: %s: Warning: More PDLs transmitted than commited to card???\n",dev->name); #endif - for (; 0 != donecount; donecount--) { + for( ; 0!=donecount; donecount-- ) + { #ifdef HP100_DEBUG_BM - printk("hp100: Free skb: data @0x%.8x txrcommit=0x%x TXPDL=0x%x, done=0x%x\n", - (u_int) lp->txrhead->skb->data, - lp->txrcommit, - hp100_inb(TX_PDL), - donecount); -#endif - dev_kfree_skb(lp->txrhead->skb); - lp->txrhead->skb = (void *) NULL; - lp->txrhead = lp->txrhead->next; - lp->txrcommit--; - } + printk("hp100: %s: Free skb: data @0x%.8x txrcommit=0x%x TXPDL=0x%x, done=0x%x\n", + dev->name, + (u_int) lp->txrhead->skb->data, + lp->txrcommit, + hp100_inb(TX_PDL), + donecount); +#endif +#ifdef LINUX_2_1 + dev_kfree_skb( lp->txrhead->skb ); +#else + dev_kfree_skb( lp->txrhead->skb, FREE_WRITE ); +#endif + lp->txrhead->skb=(void *)NULL; + lp->txrhead=lp->txrhead->next; + lp->txrcommit--; + } } - + /* tx function for slave modes */ -static int hp100_start_xmit(struct sk_buff *skb, struct device *dev) +static int hp100_start_xmit( struct sk_buff *skb, struct device *dev ) { - int i, ok_flag; - int ioaddr = dev->base_addr; - u_short val; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + int i, ok_flag; + int ioaddr = dev->base_addr; + u_short val; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4212, TRACE); - printk("hp100: start_xmit\n"); -#endif - - if (lp->lan_type < 0) { /* no LAN type detected yet? */ - hp100_stop_interface(dev); - if ((lp->lan_type = hp100_sense_lan(dev)) < 0) { - printk("%s: no connection found - check wire\n", dev->name); - hp100_start_interface(dev); /* 10Mb/s RX packets maybe handled */ - return -EIO; - } - if (lp->lan_type == HP100_LAN_100) - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); /* relogin */ - hp100_start_interface(dev); - } - /* If there is not enough free memory on the card... */ - i = hp100_inl(TX_MEM_FREE) & 0x7fffffff; - if (!(((i / 2) - 539) > (skb->len + 16) && (hp100_inb(TX_PKT_CNT) < 255))) { + hp100_outw( 0x4212, TRACE ); + printk("hp100: %s: start_xmit\n", dev->name); +#endif + + if ( skb==NULL ) + { +#ifndef LINUX_2_1 + dev_tint( dev ); +#endif + return 0; + } + + if ( skb->len <= 0 ) return 0; + + if ( lp->lan_type < 0 ) /* no LAN type detected yet? */ + { + hp100_stop_interface( dev ); + if ( ( lp->lan_type = hp100_sense_lan( dev ) ) < 0 ) + { + printk( "hp100: %s: no connection found - check wire\n", dev->name ); + hp100_start_interface( dev ); /* 10Mb/s RX packets maybe handled */ + return -EIO; + } + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); /* relogin */ + hp100_start_interface( dev ); + } + + /* If there is not enough free memory on the card... */ + i=hp100_inl(TX_MEM_FREE)&0x7fffffff; + if ( !(((i/2)-539)>(skb->len+16) && (hp100_inb(TX_PKT_CNT)<255)) ) + { #ifdef HP100_DEBUG - printk("hp100_start_xmit: tx free mem = 0x%x\n", i); + printk( "hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i ); #endif - /* not waited long enough since last failed tx try? */ - if (jiffies - dev->trans_start < HZ / 2) { + /* not waited long enough since last failed tx try? */ + if ( jiffies - dev->trans_start < HZ ) + { #ifdef HP100_DEBUG - printk("hp100: trans_start timing problem\n"); + printk("hp100: %s: trans_start timing problem\n", dev->name); #endif - return -EAGAIN; - } - if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) - /* we have a 100Mb/s adapter but it isn't connected to hub */ - { - printk("%s: login to 100Mb/s hub retry\n", dev->name); - hp100_stop_interface(dev); - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); - hp100_start_interface(dev); - } else { - hp100_ints_off(); - i = hp100_sense_lan(dev); - hp100_page(PERFORMANCE); - hp100_ints_on(); - if (i == HP100_LAN_ERR) - printk("%s: link down detected\n", dev->name); - else if (lp->lan_type != i) { /* cable change! */ - /* it's very hard - all network setting must be changed!!! */ - printk("%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name); - lp->lan_type = i; - hp100_stop_interface(dev); - if (lp->lan_type == HP100_LAN_100) - lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); - hp100_start_interface(dev); - } else { - printk("%s: interface reset\n", dev->name); - hp100_stop_interface(dev); - hp100_start_interface(dev); - udelay(1000); - } - } - dev->trans_start = jiffies; - return -EAGAIN; + return -EAGAIN; } - for (i = 0; i < 6000 && (hp100_inb(OPTION_MSW) & HP100_TX_CMD); i++) { + if ( lp->lan_type == HP100_LAN_100 && lp->hub_status < 0 ) + /* we have a 100Mb/s adapter but it isn't connected to hub */ + { + printk( "hp100: %s: login to 100Mb/s hub retry\n", dev->name ); + hp100_stop_interface( dev ); + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + } + else + { + hp100_ints_off(); + i = hp100_sense_lan( dev ); + hp100_ints_on(); + if ( i == HP100_LAN_ERR ) + printk( "hp100: %s: link down detected\n", dev->name ); + else + if ( lp->lan_type != i ) /* cable change! */ + { + /* it's very hard - all network setting must be changed!!! */ + printk( "hp100: %s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name ); + lp->lan_type = i; + hp100_stop_interface( dev ); + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + } + else + { + printk( "hp100: %s: interface reset\n", dev->name ); + hp100_stop_interface( dev ); + if ( lp->lan_type == HP100_LAN_100 ) + lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); + hp100_start_interface( dev ); + udelay(1000); + } + } + dev->trans_start = jiffies; + return -EAGAIN; + } + + for ( i=0; i<6000 && ( hp100_inb( OPTION_MSW ) & HP100_TX_CMD ); i++ ) + { #ifdef HP100_DEBUG_TX - printk("hp100_start_xmit: busy\n"); -#endif - } - - hp100_ints_off(); - val = hp100_inw(IRQ_STATUS); - /* Ack / clear the interrupt TX_COMPLETE interrupt - this interrupt is set - * when the current packet being transmitted on the wire is completed. */ - hp100_outw(HP100_TX_COMPLETE, IRQ_STATUS); + printk( "hp100: %s: start_xmit: busy\n", dev->name ); +#endif + } + + hp100_ints_off(); + val = hp100_inw( IRQ_STATUS ); + /* Ack / clear the interrupt TX_COMPLETE interrupt - this interrupt is set + * when the current packet being transmitted on the wire is completed. */ + hp100_outw( HP100_TX_COMPLETE, IRQ_STATUS ); #ifdef HP100_DEBUG_TX - printk("hp100_start_xmit: irq_status=0x%.4x, irqmask=0x%.4x, len=%d\n", val, hp100_inw(IRQ_MASK), (int) skb->len); -#endif - - ok_flag = skb->len >= HP100_MIN_PACKET_SIZE; - i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE; - - hp100_outw(i, DATA32); /* tell card the total packet length */ - hp100_outw(i, FRAGMENT_LEN); /* and first/only fragment length */ - - if (lp->mode == 2) { /* memory mapped */ - if (lp->mem_ptr_virt) { /* high pci memory was remapped */ - /* Note: The J2585B needs alignment to 32bits here! */ - memcpy(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3); - if (!ok_flag) - memset(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len); - } else { - memcpy_toio(lp->mem_ptr_phys, skb->data, skb->len); - if (!ok_flag) - memset_io(lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len); - } - } else { /* programmed i/o */ - outsl(ioaddr + HP100_REG_DATA32, skb->data, (skb->len + 3) >> 2); - if (!ok_flag) - for (i = (skb->len + 3) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4) - hp100_outl(0, DATA32); + printk("hp100: %s: start_xmit: irq_status=0x%.4x, irqmask=0x%.4x, len=%d\n",dev->name,val,hp100_inw(IRQ_MASK),(int)skb->len ); +#endif + + ok_flag = skb->len >= HP100_MIN_PACKET_SIZE; + i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE; + + hp100_outw( i, DATA32 ); /* tell card the total packet length */ + hp100_outw( i, FRAGMENT_LEN ); /* and first/only fragment length */ + + if ( lp->mode==2 ) /* memory mapped */ + { + if ( lp->mem_ptr_virt ) /* high pci memory was remapped */ + { + /* Note: The J2585B needs alignment to 32bits here! */ + memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 ); + if ( !ok_flag ) + memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len ); } - - hp100_outb(HP100_TX_CMD | HP100_SET_LB, OPTION_MSW); /* send packet */ - - lp->stats.tx_packets++; + else + { + /* Note: The J2585B needs alignment to 32bits here! */ + memcpy_toio( lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3 ); + if ( !ok_flag ) + memset_io( lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len ); + } + } + else /* programmed i/o */ + { + outsl( ioaddr + HP100_REG_DATA32, skb->data, ( skb->len + 3 ) >> 2 ); + if ( !ok_flag ) + for ( i = ( skb->len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 ) + hp100_outl( 0, DATA32 ); + } + + hp100_outb( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */ + + lp->stats.tx_packets++; #ifdef LINUX_2_1 - lp->stats.tx_bytes += skb->len; + lp->stats.tx_bytes += skb->len; #endif - dev->trans_start = jiffies; - hp100_ints_on(); - - dev_kfree_skb(skb); - + dev->trans_start=jiffies; + hp100_ints_on(); + +#ifdef LINUX_2_1 + dev_kfree_skb( skb ); +#else + dev_kfree_skb( skb, FREE_WRITE ); +#endif + #ifdef HP100_DEBUG_TX - printk("hp100_start_xmit: end\n"); + printk( "hp100: %s: start_xmit: end\n", dev->name ); #endif - - return 0; + + return 0; } - + /* * Receive Function (Non-Busmaster mode) * Called when an "Receive Packet" interrupt occurs, i.e. the receive @@ -1618,981 +1885,1163 @@ static int hp100_start_xmit(struct sk_buff *skb, struct device *dev) * and netif_rx. */ -static void hp100_rx(struct device *dev) +static void hp100_rx( struct device *dev ) { - int packets, pkt_len; - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - u_int header; - struct sk_buff *skb; + int packets, pkt_len; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + u_int header; + struct sk_buff *skb; #ifdef DEBUG_B - hp100_outw(0x4213, TRACE); - printk("hp100: rx\n"); + hp100_outw( 0x4213, TRACE ); + printk("hp100: %s: rx\n", dev->name); #endif - /* First get indication of received lan packet */ - /* RX_PKT_CND indicates the number of packets which have been fully */ - /* received onto the card but have not been fully transfered of the card */ - packets = hp100_inb(RX_PKT_CNT); + /* First get indication of received lan packet */ + /* RX_PKT_CND indicates the number of packets which have been fully */ + /* received onto the card but have not been fully transfered of the card */ + packets = hp100_inb( RX_PKT_CNT ); #ifdef HP100_DEBUG_RX - if (packets > 1) - printk("hp100_rx: waiting packets = %d\n", packets); + if ( packets > 1 ) + printk( "hp100: %s: rx: waiting packets = %d\n", dev->name,packets ); #endif - while (packets-- > 0) { - /* If ADV_NXT_PKT is still set, we have to wait until the card has */ - /* really advanced to the next packet. */ - for (pkt_len = 0; pkt_len < 6000 && (hp100_inb(OPTION_MSW) & HP100_ADV_NXT_PKT); - pkt_len++) { + while ( packets-- > 0 ) + { + /* If ADV_NXT_PKT is still set, we have to wait until the card has */ + /* really advanced to the next packet. */ + for (pkt_len=0; pkt_len<6000 &&(hp100_inb(OPTION_MSW)&HP100_ADV_NXT_PKT); + pkt_len++ ) + { #ifdef HP100_DEBUG_RX - printk("hp100_rx: busy, remaining packets = %d\n", packets); -#endif - } - - /* First we get the header, which contains information about the */ - /* actual length of the received packet. */ - if (lp->mode == 2) { /* memory mapped mode */ - if (lp->mem_ptr_virt) /* if memory was remapped */ - header = *(__u32 *) lp->mem_ptr_virt; - else - header = readl(lp->mem_ptr_phys); - } else /* programmed i/o */ - header = hp100_inl(DATA32); - - pkt_len = header & HP100_PKT_LEN_MASK; + printk( "hp100: %s: rx: busy, remaining packets = %d\n", dev->name, packets ); +#endif + } + + /* First we get the header, which contains information about the */ + /* actual length of the received packet. */ + if( lp->mode==2 ) /* memory mapped mode */ + { + if ( lp->mem_ptr_virt ) /* if memory was remapped */ + header = *(__u32 *)lp->mem_ptr_virt; + else + header = readl( lp->mem_ptr_phys ); + } + else /* programmed i/o */ + header = hp100_inl( DATA32 ); + + pkt_len = ((header & HP100_PKT_LEN_MASK) + 3) & ~3; #ifdef HP100_DEBUG_RX - printk("hp100_rx: new packet - length=%d, errors=0x%x, dest=0x%x\n", - header & HP100_PKT_LEN_MASK, (header >> 16) & 0xfff8, - (header >> 16) & 7); -#endif - - /* Now we allocate the skb and transfer the data into it. */ - /* NOTE! This (and the skb_put() below) depends on the skb-functions - * allocating more than asked (notably, aligning the request up to - * the next 16-byte length). - */ - skb = dev_alloc_skb(pkt_len); - if (skb == NULL) { /* Not enough memory->drop packet */ + printk( "hp100: %s: rx: new packet - length=%d, errors=0x%x, dest=0x%x\n", + dev->name, + header & HP100_PKT_LEN_MASK, (header>>16)&0xfff8, + (header>>16)&7); +#endif + + /* Now we allocate the skb and transfer the data into it. */ + skb = dev_alloc_skb( pkt_len ); + if ( skb == NULL ) /* Not enough memory->drop packet */ + { #ifdef HP100_DEBUG - printk("hp100_rx: couldn't allocate a sk_buff of size %d\n", pkt_len); + printk( "hp100: %s: rx: couldn't allocate a sk_buff of size %d\n", dev->name, pkt_len ); #endif - lp->stats.rx_dropped++; - } else { /* skb successfully allocated */ - u_char *ptr; - - skb->dev = dev; - - /* ptr to start of the sk_buff data area */ - ptr = (u_char *) skb_put(skb, pkt_len); - - /* Now transfer the data from the card into that area */ - if (lp->mode == 2) { - if (lp->mem_ptr_virt) - memcpy(ptr, lp->mem_ptr_virt, (pkt_len + 3) & ~3); - /* Note alignment to 32bit transfers */ - else - memcpy_fromio(ptr, lp->mem_ptr_phys, (pkt_len + 3) & ~3); - } else /* io mapped */ - insl(ioaddr + HP100_REG_DATA32, ptr, (pkt_len + 3) >> 2); - - skb->protocol = eth_type_trans(skb, dev); - - netif_rx(skb); - lp->stats.rx_packets++; + lp->stats.rx_dropped++; + } + else /* skb successfully allocated */ + { + u_char *ptr; + + skb->dev = dev; + + /* ptr to start of the sk_buff data area */ + ptr = (u_char *)skb_put( skb, pkt_len ); + + /* Now transfer the data from the card into that area */ + if ( lp->mode==2 ) + { + if ( lp->mem_ptr_virt ) + memcpy( ptr, lp->mem_ptr_virt, pkt_len ); + /* Note alignment to 32bit transfers */ + else + memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len ); + } + else /* io mapped */ + insl( ioaddr + HP100_REG_DATA32, ptr, pkt_len >> 2 ); + + skb->protocol = eth_type_trans( skb, dev ); + + netif_rx( skb ); + lp->stats.rx_packets++; #ifdef LINUX_2_1 - lp->stats.rx_bytes += skb->len; + lp->stats.rx_bytes += skb->len; #endif - + #ifdef HP100_DEBUG_RX - printk("rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], - ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11]); + printk( "hp100: %s: rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + dev->name, + ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ], ptr[ 4 ], ptr[ 5 ], + ptr[ 6 ], ptr[ 7 ], ptr[ 8 ], ptr[ 9 ], ptr[ 10 ], ptr[ 11 ] ); #endif - } - - /* Indicate the card that we have got the packet */ - hp100_outb(HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW); - - switch (header & 0x00070000) { - case (HP100_MULTI_ADDR_HASH << 16): - case (HP100_MULTI_ADDR_NO_HASH << 16): - lp->stats.multicast++; - break; - } - } /* end of while(there are packets) loop */ + } + + /* Indicate the card that we have got the packet */ + hp100_outb( HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW ); + + switch ( header & 0x00070000 ) { + case (HP100_MULTI_ADDR_HASH<<16): + case (HP100_MULTI_ADDR_NO_HASH<<16): + lp->stats.multicast++; break; + } + } /* end of while(there are packets) loop */ #ifdef HP100_DEBUG_RX - printk("hp100_rx: end\n"); + printk( "hp100_rx: %s: end\n", dev->name ); #endif } - + /* * Receive Function for Busmaster Mode */ -static void hp100_rx_bm(struct device *dev) +static void hp100_rx_bm( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - hp100_ring_t *ptr; - u_int header; - int pkt_len; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + hp100_ring_t *ptr; + u_int header; + int pkt_len; #ifdef HP100_DEBUG_B - hp100_outw(0x4214, TRACE); - printk("hp100: rx_bm\n"); + hp100_outw( 0x4214, TRACE ); + printk("hp100: %s: rx_bm\n", dev->name); #endif #ifdef HP100_DEBUG - if (0 == lp->rxrcommit) { - printk("hp100: rx_bm called although no PDLs were committed to adapter?\n"); - return; - } else - /* RX_PKT_CNT states how many PDLs are currently formatted and available to - * the cards BM engine */ - if ((hp100_inw(RX_PKT_CNT) & 0x00ff) >= lp->rxrcommit) { - printk("hp100: More packets received than commited? RX_PKT_CNT=0x%x, commit=0x%x\n", hp100_inw(RX_PKT_CNT) & 0x00ff, lp->rxrcommit); - return; - } -#endif - - while ((lp->rxrcommit > hp100_inb(RX_PDL))) { - /* - * The packet was received into the pdl pointed to by lp->rxrhead ( - * the oldest pdl in the ring - */ - - /* First we get the header, which contains information about the */ - /* actual length of the received packet. */ - - ptr = lp->rxrhead; - - header = *(ptr->pdl - 1); - pkt_len = (header & HP100_PKT_LEN_MASK); + if(0==lp->rxrcommit) + { + printk("hp100: %s: rx_bm called although no PDLs were committed to adapter?\n", dev->name); + return; + } + else + + /* RX_PKT_CNT states how many PDLs are currently formatted and available to + * the cards BM engine */ + if( (hp100_inw(RX_PKT_CNT)&0x00ff) >= lp->rxrcommit) + { + printk("hp100: %s: More packets received than commited? RX_PKT_CNT=0x%x, commit=0x%x\n", dev->name, hp100_inw(RX_PKT_CNT)&0x00ff, lp->rxrcommit); + return; + } +#endif + + while( (lp->rxrcommit > hp100_inb(RX_PDL)) ) + { + /* + * The packet was received into the pdl pointed to by lp->rxrhead ( + * the oldest pdl in the ring + */ + + /* First we get the header, which contains information about the */ + /* actual length of the received packet. */ + + ptr=lp->rxrhead; + + header = *(ptr->pdl-1); + pkt_len = (header & HP100_PKT_LEN_MASK); #ifdef HP100_DEBUG_BM - printk("hp100: rx_bm: header@0x%x=0x%x length=%d, errors=0x%x, dest=0x%x\n", - (u_int) (ptr->pdl - 1), (u_int) header, - pkt_len, - (header >> 16) & 0xfff8, - (header >> 16) & 7); - printk("hp100: RX_PDL_COUNT:0x%x TX_PDL_COUNT:0x%x, RX_PKT_CNT=0x%x PDH=0x%x, Data@0x%x len=0x%x\n", - hp100_inb(RX_PDL), - hp100_inb(TX_PDL), - hp100_inb(RX_PKT_CNT), - (u_int) * (ptr->pdl), - (u_int) * (ptr->pdl + 3), - (u_int) * (ptr->pdl + 4)); -#endif - - if ((pkt_len >= MIN_ETHER_SIZE) && - (pkt_len <= MAX_ETHER_SIZE)) { - if (ptr->skb == NULL) { - printk("hp100: rx_bm: skb null\n"); - /* can happen if we only allocated room for the pdh due to memory shortage. */ - lp->stats.rx_dropped++; - } else { - skb_trim(ptr->skb, pkt_len); /* Shorten it */ - ptr->skb->protocol = eth_type_trans(ptr->skb, dev); - - netif_rx(ptr->skb); /* Up and away... */ - - lp->stats.rx_packets++; + printk( "hp100: %s: rx_bm: header@0x%x=0x%x length=%d, errors=0x%x, dest=0x%x\n", + dev->name, + (u_int) (ptr->pdl-1),(u_int) header, + pkt_len, + (header>>16)&0xfff8, + (header>>16)&7); + printk( "hp100: %s: RX_PDL_COUNT:0x%x TX_PDL_COUNT:0x%x, RX_PKT_CNT=0x%x PDH=0x%x, Data@0x%x len=0x%x\n", + dev->name, + hp100_inb( RX_PDL ), + hp100_inb( TX_PDL ), + hp100_inb( RX_PKT_CNT ), + (u_int) *(ptr->pdl), + (u_int) *(ptr->pdl+3), + (u_int) *(ptr->pdl+4)); +#endif + + if( (pkt_len>=MIN_ETHER_SIZE) && + (pkt_len<=MAX_ETHER_SIZE) ) + { + if(ptr->skb==NULL) + { + printk("hp100: %s: rx_bm: skb null\n", dev->name); + /* can happen if we only allocated room for the pdh due to memory shortage. */ + lp->stats.rx_dropped++; + } + else + { + skb_trim( ptr->skb, pkt_len ); /* Shorten it */ + ptr->skb->protocol = eth_type_trans( ptr->skb, dev ); + + netif_rx( ptr->skb ); /* Up and away... */ + + lp->stats.rx_packets++; #ifdef LINUX_2_1 - lp->stats.rx_bytes += ptr->skb->len; -#endif - } - - switch (header & 0x00070000) { - case (HP100_MULTI_ADDR_HASH << 16): - case (HP100_MULTI_ADDR_NO_HASH << 16): - lp->stats.multicast++; - break; - } - } else { + lp->stats.rx_bytes += ptr->skb->len; +#endif + } + + switch ( header & 0x00070000 ) { + case (HP100_MULTI_ADDR_HASH<<16): + case (HP100_MULTI_ADDR_NO_HASH<<16): + lp->stats.multicast++; break; + } + } + else + { #ifdef HP100_DEBUG - printk("hp100: rx_bm: Received bad packet (length=%d)\n", pkt_len); + printk("hp100: %s: rx_bm: Received bad packet (length=%d)\n",dev->name,pkt_len); #endif - if (ptr->skb != NULL) - dev_kfree_skb(ptr->skb); - lp->stats.rx_errors++; - } - - lp->rxrhead = lp->rxrhead->next; - - /* Allocate a new rx PDL (so lp->rxrcommit stays the same) */ - if (0 == hp100_build_rx_pdl(lp->rxrtail, dev)) { - /* No space for skb, header can still be received. */ -#ifdef HP100_DEBUG - printk("hp100: rx_bm: No space for new PDL.\n"); + if(ptr->skb!=NULL) +#ifdef LINUX_2_1 + dev_kfree_skb( ptr->skb ); +#else + dev_kfree_skb( ptr->skb, FREE_READ ); #endif - return; - } else { /* successfully allocated new PDL - put it in ringlist at tail. */ - hp100_outl((u32) lp->rxrtail->pdl_paddr, RX_PDA); - lp->rxrtail = lp->rxrtail->next; - } + lp->stats.rx_errors++; + } + + lp->rxrhead=lp->rxrhead->next; + /* Allocate a new rx PDL (so lp->rxrcommit stays the same) */ + if (0 == hp100_build_rx_pdl( lp->rxrtail, dev )) + { + /* No space for skb, header can still be received. */ +#ifdef HP100_DEBUG + printk("hp100: %s: rx_bm: No space for new PDL.\n", dev->name); +#endif + return; + } + else + { /* successfully allocated new PDL - put it in ringlist at tail. */ + hp100_outl((u32)lp->rxrtail->pdl_paddr, RX_PDA); + lp->rxrtail=lp->rxrtail->next; } + + } } - + /* * statistics */ -static hp100_stats_t *hp100_get_stats(struct device *dev) +static hp100_stats_t *hp100_get_stats( struct device *dev ) { - int ioaddr = dev->base_addr; + int ioaddr = dev->base_addr; #ifdef HP100_DEBUG_B - hp100_outw(0x4215, TRACE); + hp100_outw( 0x4215, TRACE ); #endif - hp100_ints_off(); - hp100_update_stats(dev); - hp100_ints_on(); - return &((struct hp100_private *) dev->priv)->stats; + hp100_ints_off(); + hp100_update_stats( dev ); + hp100_ints_on(); + return &((struct hp100_private *)dev->priv)->stats; } -static void hp100_update_stats(struct device *dev) +static void hp100_update_stats( struct device *dev ) { - int ioaddr = dev->base_addr; - u_short val; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + int ioaddr = dev->base_addr; + u_short val; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4216, TRACE); - printk("hp100: update-stats\n"); -#endif - - /* Note: Statistics counters clear when read. */ - hp100_page(MAC_CTRL); - val = hp100_inw(DROPPED) & 0x0fff; - lp->stats.rx_errors += val; - lp->stats.rx_over_errors += val; - val = hp100_inb(CRC); - lp->stats.rx_errors += val; - lp->stats.rx_crc_errors += val; - val = hp100_inb(ABORT); - lp->stats.tx_errors += val; - lp->stats.tx_aborted_errors += val; - hp100_page(PERFORMANCE); + hp100_outw( 0x4216, TRACE ); + printk("hp100: %s: update-stats\n", dev->name); +#endif + + /* Note: Statistics counters clear when read. */ + hp100_page( MAC_CTRL ); + val = hp100_inw( DROPPED ) & 0x0fff; + lp->stats.rx_errors += val; + lp->stats.rx_over_errors += val; + val = hp100_inb( CRC ); + lp->stats.rx_errors += val; + lp->stats.rx_crc_errors += val; + val = hp100_inb( ABORT ); + lp->stats.tx_errors += val; + lp->stats.tx_aborted_errors += val; + hp100_page( PERFORMANCE ); } -static void hp100_clear_stats(int ioaddr) +static void hp100_misc_interrupt( struct device *dev ) { + struct hp100_private *lp = (struct hp100_private *)dev->priv; + #ifdef HP100_DEBUG_B - hp100_outw(0x4217, TRACE); - printk("hp100: clear_stats\n"); + hp100_outw( 0x4216, TRACE ); + printk("hp100: %s: misc_interrupt\n", dev->name); #endif - cli(); - hp100_page(MAC_CTRL); /* get all statistics bytes */ - hp100_inw(DROPPED); - hp100_inb(CRC); - hp100_inb(ABORT); - hp100_page(PERFORMANCE); - sti(); + /* Note: Statistics counters clear when read. */ + lp->stats.rx_errors++; + lp->stats.tx_errors++; +} + +static void hp100_clear_stats( int ioaddr ) +{ + unsigned long flags; + +#ifdef HP100_DEBUG_B + hp100_outw( 0x4217, TRACE ); + printk("hp100: %s: clear_stats\n", dev->name); +#endif + + save_flags( flags ); + cli(); + hp100_page( MAC_CTRL ); /* get all statistics bytes */ + hp100_inw( DROPPED ); + hp100_inb( CRC ); + hp100_inb( ABORT ); + hp100_page( PERFORMANCE ); + restore_flags( flags ); } - + /* * multicast setup */ /* * Set or clear the multicast filter for this adapter. - * TODO: Currently when in multicast mode, card accepts all multicast packets - * for all MC addresses. Should better use the list on the card. */ - -static void hp100_set_multicast_list(struct device *dev) + +static void hp100_set_multicast_list( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + unsigned long flags; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4218, TRACE); - printk("hp100: set_mc_list\n"); -#endif - - cli(); - hp100_ints_off(); - hp100_page(MAC_CTRL); - hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); /* stop rx/tx */ - - if (dev->flags & IFF_PROMISC) { - lp->mac2_mode = HP100_MAC2MODE6; /* promiscuous mode = get all good */ - lp->mac1_mode = HP100_MAC1MODE6; /* packets on the net */ - } else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { - lp->mac2_mode = HP100_MAC2MODE5; /* multicast mode = get packets for */ - lp->mac1_mode = HP100_MAC1MODE5; /* me, broadcasts and all multicasts */ - } else { - lp->mac2_mode = HP100_MAC2MODE3; /* normal mode = get packets for me */ - lp->mac1_mode = HP100_MAC1MODE3; /* and broadcasts */ - } - - if (((hp100_inb(MAC_CFG_1) & 0x0f) != lp->mac1_mode) || - (hp100_inb(MAC_CFG_2) != lp->mac2_mode)) { - hp100_outb(lp->mac2_mode, MAC_CFG_2); - hp100_andb(HP100_MAC1MODEMASK, MAC_CFG_1); /* clear mac1 mode bits */ - hp100_orb(lp->mac1_mode, MAC_CFG_1); /* and set the new mode */ - - if (lp->lan_type == HP100_LAN_100) { + hp100_outw( 0x4218, TRACE ); + printk("hp100: %s: set_mc_list\n", dev->name); +#endif + + save_flags( flags ); + cli(); + hp100_ints_off(); + hp100_page( MAC_CTRL ); + hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */ + + if ( dev->flags & IFF_PROMISC ) + { + lp->mac2_mode = HP100_MAC2MODE6; /* promiscuous mode = get all good */ + lp->mac1_mode = HP100_MAC1MODE6; /* packets on the net */ + memset( &lp->hash_bytes, 0xff, 8 ); + } + else if ( dev->mc_count || (dev->flags&IFF_ALLMULTI) ) + { + lp->mac2_mode = HP100_MAC2MODE5; /* multicast mode = get packets for */ + lp->mac1_mode = HP100_MAC1MODE5; /* me, broadcasts and all multicasts */ +#ifdef HP100_MULTICAST_FILTER /* doesn't work!!! */ + if ( dev -> flags & IFF_ALLMULTI ) + { + /* set hash filter to receive all multicast packets */ + memset( &lp->hash_bytes, 0xff, 8 ); + } + else + { + int i, j, idx; + u_char *addrs; + struct dev_mc_list *dmi; + + memset( &lp->hash_bytes, 0x00, 8 ); +#ifdef HP100_DEBUG + printk("hp100: %s: computing hash filter - mc_count = %i\n", dev -> name, dev -> mc_count ); +#endif + for ( i = 0, dmi = dev -> mc_list; i < dev -> mc_count; i++, dmi = dmi -> next ) + { + addrs = dmi -> dmi_addr; + if ( ( *addrs & 0x01 ) == 0x01 ) /* multicast address? */ + { +#ifdef HP100_DEBUG + printk("hp100: %s: multicast = %02x:%02x:%02x:%02x:%02x:%02x, ", + dev -> name, + addrs[ 0 ], addrs[ 1 ], addrs[ 2 ], + addrs[ 3 ], addrs[ 4 ], addrs[ 5 ] ); +#endif + for ( j = idx = 0; j < 6; j++ ) + { + idx ^= *addrs++ & 0x3f; + printk( ":%02x:", idx ); + } #ifdef HP100_DEBUG - printk("hp100: 100VG MAC settings have changed - relogin.\n"); + printk("idx = %i\n", idx ); #endif - lp->hub_status = hp100_login_to_vg_hub(dev, TRUE); /* force a relogin to the hub */ - } - } - hp100_page(MAC_CTRL); - hp100_orb(HP100_RX_EN | HP100_RX_IDLE | /* enable rx */ - HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1); /* enable tx */ - - hp100_page(PERFORMANCE); - hp100_ints_on(); - sti(); + lp->hash_bytes[ idx >> 3 ] |= ( 1 << ( idx & 7 ) ); + } + } + } +#else + memset( &lp->hash_bytes, 0xff, 8 ); +#endif + } + else + { + lp->mac2_mode = HP100_MAC2MODE3; /* normal mode = get packets for me */ + lp->mac1_mode = HP100_MAC1MODE3; /* and broadcasts */ + memset( &lp->hash_bytes, 0x00, 8 ); + } + + if ( ( (hp100_inb(MAC_CFG_1) & 0x0f)!=lp->mac1_mode ) || + ( hp100_inb(MAC_CFG_2)!=lp->mac2_mode ) ) + { + int i; + + hp100_outb( lp->mac2_mode, MAC_CFG_2 ); + hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 ); /* clear mac1 mode bits */ + hp100_orb( lp->mac1_mode, MAC_CFG_1 ); /* and set the new mode */ + + hp100_page( MAC_ADDRESS ); + for ( i = 0; i < 8; i++ ) + hp100_outb( lp->hash_bytes[ i ], HASH_BYTE0 + i ); +#ifdef HP100_DEBUG + printk("hp100: %s: mac1 = 0x%x, mac2 = 0x%x, multicast hash = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, lp->mac1_mode, lp->mac2_mode, + lp->hash_bytes[ 0 ], lp->hash_bytes[ 1 ], + lp->hash_bytes[ 2 ], lp->hash_bytes[ 3 ], + lp->hash_bytes[ 4 ], lp->hash_bytes[ 5 ], + lp->hash_bytes[ 6 ], lp->hash_bytes[ 7 ] + ); +#endif + + if(lp->lan_type==HP100_LAN_100) + { +#ifdef HP100_DEBUG + printk("hp100: %s: 100VG MAC settings have changed - relogin.\n", dev->name); +#endif + lp->hub_status=hp100_login_to_vg_hub( dev, TRUE ); /* force a relogin to the hub */ + } + } + else + { + int i; + u_char old_hash_bytes[ 8 ]; + + hp100_page( MAC_ADDRESS ); + for ( i = 0; i < 8; i++ ) + old_hash_bytes[ i ] = hp100_inb( HASH_BYTE0 + i ); + if ( memcmp( old_hash_bytes, &lp->hash_bytes, 8 ) ) + { + for ( i = 0; i < 8; i++ ) + hp100_outb( lp->hash_bytes[ i ], HASH_BYTE0 + i ); +#ifdef HP100_DEBUG + printk("hp100: %s: multicast hash = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, + lp->hash_bytes[ 0 ], lp->hash_bytes[ 1 ], + lp->hash_bytes[ 2 ], lp->hash_bytes[ 3 ], + lp->hash_bytes[ 4 ], lp->hash_bytes[ 5 ], + lp->hash_bytes[ 6 ], lp->hash_bytes[ 7 ] + ); +#endif + + if(lp->lan_type==HP100_LAN_100) + { +#ifdef HP100_DEBUG + printk("hp100: %s: 100VG MAC settings have changed - relogin.\n", dev->name); +#endif + lp->hub_status=hp100_login_to_vg_hub( dev, TRUE ); /* force a relogin to the hub */ + } + } + } + + hp100_page( MAC_CTRL ); + hp100_orb( HP100_RX_EN | HP100_RX_IDLE | /* enable rx */ + HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 ); /* enable tx */ + + hp100_page( PERFORMANCE ); + hp100_ints_on(); + restore_flags( flags ); } - + /* * hardware interrupt handling */ -static void hp100_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs ) { - struct device *dev = dev_id; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + struct device *dev = (struct device *)dev_id; + struct hp100_private *lp = (struct hp100_private *)dev->priv; - int ioaddr; - u_int val; + int ioaddr; + u_int val; - if (dev == NULL) - return; - ioaddr = dev->base_addr; + if ( dev == NULL ) return; + ioaddr = dev->base_addr; - if (dev->interrupt) - printk("%s: re-entering the interrupt handler\n", dev->name); - hp100_ints_off(); - dev->interrupt = 1; /* mark that we are inside the handler */ + if ( dev->interrupt ) + printk( "hp100: %s: re-entering the interrupt handler\n", dev->name ); + hp100_ints_off(); + dev->interrupt = 1; /* mark that we are inside the handler */ #ifdef HP100_DEBUG_B - hp100_outw(0x4219, TRACE); + hp100_outw( 0x4219, TRACE ); #endif - /* hp100_page( PERFORMANCE ); */ - val = hp100_inw(IRQ_STATUS); + /* hp100_page( PERFORMANCE ); */ + val = hp100_inw( IRQ_STATUS ); #ifdef HP100_DEBUG_IRQ - printk("hp100: mode=%x,IRQ_STAT=0x%.4x,RXPKTCNT=0x%.2x RXPDL=0x%.2x TXPKTCNT=0x%.2x TXPDL=0x%.2x\n", - lp->mode, - (u_int) val, - hp100_inb(RX_PKT_CNT), - hp100_inb(RX_PDL), - hp100_inb(TX_PKT_CNT), - hp100_inb(TX_PDL) - ); -#endif - - if (val == 0) { /* might be a shared interrupt */ - dev->interrupt = 0; - hp100_ints_on(); - return; + printk( "hp100: %s: mode=%x,IRQ_STAT=0x%.4x,RXPKTCNT=0x%.2x RXPDL=0x%.2x TXPKTCNT=0x%.2x TXPDL=0x%.2x\n", + dev->name, + lp->mode, + (u_int)val, + hp100_inb( RX_PKT_CNT ), + hp100_inb( RX_PDL ), + hp100_inb( TX_PKT_CNT ), + hp100_inb( TX_PDL ) + ); +#endif + + if(val==0) /* might be a shared interrupt */ + { + dev->interrupt=0; + hp100_ints_on(); + return; + } + /* We're only interested in those interrupts we really enabled. */ + /* val &= hp100_inw( IRQ_MASK ); */ + + /* + * RX_PDL_FILL_COMPL is set whenever a RX_PDL has been executed. A RX_PDL + * is considered executed whenever the RX_PDL data structure is no longer + * needed. + */ + if ( val & HP100_RX_PDL_FILL_COMPL ) + { + if(lp->mode==1) + hp100_rx_bm( dev ); + else + { + printk("hp100: %s: rx_pdl_fill_compl interrupt although not busmaster?\n", dev->name); } - /* We're only interested in those interrupts we really enabled. */ - /* val &= hp100_inw( IRQ_MASK ); */ - - /* - * RX_PDL_FILL_COMPL is set whenever a RX_PDL has been executed. A RX_PDL - * is considered executed whenever the RX_PDL data structure is no longer - * needed. - */ - if (val & HP100_RX_PDL_FILL_COMPL) { - if (lp->mode == 1) - hp100_rx_bm(dev); - else - printk("hp100: rx_pdl_fill_compl interrupt although not busmaster?\n"); + } + + /* + * The RX_PACKET interrupt is set, when the receive packet counter is + * non zero. We use this interrupt for receiving in slave mode. In + * busmaster mode, we use it to make sure we did not miss any rx_pdl_fill + * interrupts. If rx_pdl_fill_compl is not set and rx_packet is set, then + * we somehow have missed a rx_pdl_fill_compl interrupt. + */ + + if ( val & HP100_RX_PACKET ) /* Receive Packet Counter is non zero */ + { + if(lp->mode!=1) /* non busmaster */ + hp100_rx( dev ); + else if ( !(val & HP100_RX_PDL_FILL_COMPL )) + { + /* Shouldnt happen - maybe we missed a RX_PDL_FILL Interrupt? */ + hp100_rx_bm( dev ); } - /* - * The RX_PACKET interrupt is set, when the receive packet counter is - * non zero. We use this interrupt for receiving in slave mode. In - * busmaster mode, we use it to make sure we did not miss any rx_pdl_fill - * interrupts. If rx_pdl_fill_compl is not set and rx_packet is set, then - * we somehow have missed a rx_pdl_fill_compl interrupt. - */ - - if (val & HP100_RX_PACKET) { /* Receive Packet Counter is non zero */ - if (lp->mode != 1) /* non busmaster */ - hp100_rx(dev); - else if (!(val & HP100_RX_PDL_FILL_COMPL)) { - /* Shouldnt happen - maybe we missed a RX_PDL_FILL Interrupt? */ - hp100_rx_bm(dev); - } - } - /* - * Ack. that we have noticed the interrupt and thereby allow next one. - * Note that this is now done after the slave rx function, since first - * acknowledging and then setting ADV_NXT_PKT caused an extra interrupt - * on the J2573. - */ - hp100_outw(val, IRQ_STATUS); - - /* - * RX_ERROR is set when a packet is dropped due to no memory resources on - * the card or when a RCV_ERR occurs. - * TX_ERROR is set when a TX_ABORT condition occurs in the MAC->exists - * only in the 802.3 MAC and happens when 16 collisions occur during a TX - */ - if (val & (HP100_TX_ERROR | HP100_RX_ERROR)) { + } + + /* + * Ack. that we have noticed the interrupt and thereby allow next one. + * Note that this is now done after the slave rx function, since first + * acknowledging and then setting ADV_NXT_PKT caused an extra interrupt + * on the J2573. + */ + hp100_outw( val, IRQ_STATUS ); + + /* + * RX_ERROR is set when a packet is dropped due to no memory resources on + * the card or when a RCV_ERR occurs. + * TX_ERROR is set when a TX_ABORT condition occurs in the MAC->exists + * only in the 802.3 MAC and happens when 16 collisions occur during a TX + */ + if ( val & ( HP100_TX_ERROR | HP100_RX_ERROR ) ) + { #ifdef HP100_DEBUG_IRQ - printk("hp100: TX/RX Error IRQ\n"); + printk("hp100: %s: TX/RX Error IRQ\n", dev->name); #endif - hp100_update_stats(dev); - if (lp->mode == 1) { - hp100_rxfill(dev); - hp100_clean_txring(dev); - } + hp100_update_stats( dev ); + if(lp->mode==1) + { + hp100_rxfill( dev ); + hp100_clean_txring( dev ); } - /* - * RX_PDA_ZERO is set when the PDA count goes from non-zero to zero. - */ - if ((lp->mode == 1) && (val & (HP100_RX_PDA_ZERO))) - hp100_rxfill(dev); - - /* - * HP100_TX_COMPLETE interrupt occurs when packet transmitted on wire - * is completed - */ - if ((lp->mode == 1) && (val & (HP100_TX_COMPLETE))) - hp100_clean_txring(dev); - - /* - * MISC_ERROR is set when either the LAN link goes down or a detected - * bus error occurs. - */ - if (val & HP100_MISC_ERROR) { /* New for J2585B */ - printk("hp100: Misc. Error Interrupt - Check cabling.\n"); - if (lp->mode == 1) { - hp100_clean_txring(dev); - hp100_rxfill(dev); - } + } + + /* + * RX_PDA_ZERO is set when the PDA count goes from non-zero to zero. + */ + if ( (lp->mode==1)&&(val &(HP100_RX_PDA_ZERO)) ) + hp100_rxfill( dev ); + + /* + * HP100_TX_COMPLETE interrupt occurs when packet transmitted on wire + * is completed + */ + if ( (lp->mode==1) && ( val & ( HP100_TX_COMPLETE )) ) + hp100_clean_txring( dev ); + + /* + * MISC_ERROR is set when either the LAN link goes down or a detected + * bus error occurs. + */ + if ( val & HP100_MISC_ERROR ) /* New for J2585B */ + { +#ifdef HP100_DEBUG_IRQ + printk("hp100: %s: Misc. Error Interrupt - Check cabling.\n", dev->name); +#endif + if(lp->mode==1) + { + hp100_clean_txring( dev ); + hp100_rxfill( dev ); } - dev->interrupt = 0; - hp100_ints_on(); + hp100_misc_interrupt( dev ); + } + + dev->interrupt = 0; + hp100_ints_on(); } - + /* * some misc functions */ -static void hp100_start_interface(struct device *dev) +static void hp100_start_interface( struct device *dev ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + unsigned long flags; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4220, TRACE); - printk("hp100: hp100_start_interface %s\n", dev->name); -#endif - - cli(); - - /* Ensure the adapter does not want to request an interrupt when */ - /* enabling the IRQ line to be active on the bus (i.e. not tri-stated) */ - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* ack all IRQs */ - hp100_outw(HP100_FAKE_INT | HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); - /* Un Tri-state int. TODO: Check if shared interrupts can be realised? */ - hp100_outw(HP100_TRI_INT | HP100_RESET_HB, OPTION_LSW); - - if (lp->mode == 1) { - /* Make sure BM bit is set... */ - hp100_page(HW_MAP); - hp100_orb(HP100_BM_MASTER, BM); - hp100_rxfill(dev); - } else if (lp->mode == 2) { - /* Enable memory mapping. Note: Don't do this when busmaster. */ - hp100_outw(HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW); - } - hp100_page(PERFORMANCE); - hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ - hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */ - - /* enable a few interrupts: */ - if (lp->mode == 1) { /* busmaster mode */ - hp100_outw(HP100_RX_PDL_FILL_COMPL | - HP100_RX_PDA_ZERO | - HP100_RX_ERROR | - /* HP100_RX_PACKET | */ - /* HP100_RX_EARLY_INT | */ HP100_SET_HB | - /* HP100_TX_PDA_ZERO | */ - HP100_TX_COMPLETE | - /* HP100_MISC_ERROR | */ - HP100_TX_ERROR | HP100_SET_LB, IRQ_MASK); - } else { - hp100_outw(HP100_RX_PACKET | - HP100_RX_ERROR | HP100_SET_HB | - HP100_TX_ERROR | HP100_SET_LB, IRQ_MASK); - } - - /* Enable MAC Tx and RX, set MAC modes, ... */ - /* Note: This function also turns on the interrupts. */ - hp100_set_multicast_list(dev); + hp100_outw( 0x4220, TRACE ); + printk("hp100: %s: hp100_start_interface\n",dev->name); +#endif + + save_flags( flags ); + cli(); + + /* Ensure the adapter does not want to request an interrupt when */ + /* enabling the IRQ line to be active on the bus (i.e. not tri-stated) */ + hp100_page( PERFORMANCE ); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* ack all IRQs */ + hp100_outw( HP100_FAKE_INT|HP100_INT_EN|HP100_RESET_LB, OPTION_LSW); + /* Un Tri-state int. TODO: Check if shared interrupts can be realised? */ + hp100_outw( HP100_TRI_INT | HP100_RESET_HB, OPTION_LSW ); + + if(lp->mode==1) + { + /* Make sure BM bit is set... */ + hp100_page(HW_MAP); + hp100_orb( HP100_BM_MASTER, BM ); + hp100_rxfill( dev ); + } + else if(lp->mode==2) + { + /* Enable memory mapping. Note: Don't do this when busmaster. */ + hp100_outw( HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW ); + } + + hp100_page(PERFORMANCE); + hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ + hp100_outw( 0xffff, IRQ_STATUS ); /* ack IRQ */ + + /* enable a few interrupts: */ + if(lp->mode==1) /* busmaster mode */ + { + hp100_outw( HP100_RX_PDL_FILL_COMPL | + HP100_RX_PDA_ZERO | + HP100_RX_ERROR | + /* HP100_RX_PACKET | */ + /* HP100_RX_EARLY_INT | */ HP100_SET_HB | + /* HP100_TX_PDA_ZERO | */ + HP100_TX_COMPLETE | + /* HP100_MISC_ERROR | */ + HP100_TX_ERROR | HP100_SET_LB, IRQ_MASK ); + } + else + { + hp100_outw( HP100_RX_PACKET | + HP100_RX_ERROR | HP100_SET_HB | + HP100_TX_ERROR | HP100_SET_LB , IRQ_MASK ); + } + + /* Enable MAC Tx and RX, set MAC modes, ... */ + hp100_set_multicast_list( dev ); + + restore_flags( flags ); } - -static void hp100_stop_interface(struct device *dev) + +static void hp100_stop_interface( struct device *dev ) { - struct hp100_private *lp = (struct hp100_private *) dev->priv; - int ioaddr = dev->base_addr; - u_int val; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + int ioaddr = dev->base_addr; + u_int val; #ifdef HP100_DEBUG_B - printk("hp100: hp100_stop_interface %s\n", dev->name); - hp100_outw(0x4221, TRACE); -#endif - - if (lp->mode == 1) - hp100_BM_shutdown(dev); - else { - /* Note: MMAP_DIS will be reenabled by start_interface */ - hp100_outw(HP100_INT_EN | HP100_RESET_LB | - HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW); - val = hp100_inw(OPTION_LSW); - - hp100_page(MAC_CTRL); - hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); - - if (!(val & HP100_HW_RST)) - return; /* If reset, imm. return ... */ - /* ... else: busy wait until idle */ - for (val = 0; val < 6000; val++) - if ((hp100_inb(MAC_CFG_1) & (HP100_TX_IDLE | HP100_RX_IDLE)) == - (HP100_TX_IDLE | HP100_RX_IDLE)) { - hp100_page(PERFORMANCE); - return; - } - printk("%s: hp100_stop_interface - timeout\n", dev->name); - hp100_page(PERFORMANCE); - } + printk("hp100: %s: hp100_stop_interface\n",dev->name); + hp100_outw( 0x4221, TRACE ); +#endif + + if (lp->mode==1) + hp100_BM_shutdown( dev ); + else + { + /* Note: MMAP_DIS will be reenabled by start_interface */ + hp100_outw( HP100_INT_EN | HP100_RESET_LB | + HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW ); + val = hp100_inw( OPTION_LSW ); + + hp100_page( MAC_CTRL ); + hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); + + if ( !(val & HP100_HW_RST) ) return; /* If reset, imm. return ... */ + /* ... else: busy wait until idle */ + for ( val = 0; val < 6000; val++ ) + if ( ( hp100_inb( MAC_CFG_1 ) & (HP100_TX_IDLE | HP100_RX_IDLE) ) == + (HP100_TX_IDLE | HP100_RX_IDLE) ) + { + hp100_page(PERFORMANCE); + return; + } + printk( "hp100: %s: hp100_stop_interface - timeout\n", dev->name ); + hp100_page(PERFORMANCE); + } } - -static void hp100_load_eeprom(struct device *dev) + +static void hp100_load_eeprom( struct device *dev, u_short probe_ioaddr ) { - int i; - int ioaddr = dev->base_addr; + int i; + int ioaddr = probe_ioaddr > 0 ? probe_ioaddr : dev->base_addr; #ifdef HP100_DEBUG_B - hp100_outw(0x4222, TRACE); + hp100_outw( 0x4222, TRACE ); #endif - hp100_page(EEPROM_CTRL); - hp100_andw(~HP100_EEPROM_LOAD, EEPROM_CTRL); - hp100_orw(HP100_EEPROM_LOAD, EEPROM_CTRL); - for (i = 0; i < 10000; i++) - if (!(hp100_inb(OPTION_MSW) & HP100_EE_LOAD)) - return; - printk("%s: hp100_load_eeprom - timeout\n", dev->name); + hp100_page( EEPROM_CTRL ); + hp100_andw( ~HP100_EEPROM_LOAD, EEPROM_CTRL ); + hp100_orw( HP100_EEPROM_LOAD, EEPROM_CTRL ); + for ( i = 0; i < 10000; i++ ) + if ( !( hp100_inb( OPTION_MSW ) & HP100_EE_LOAD ) ) return; + printk( "hp100: %s: hp100_load_eeprom - timeout\n", dev->name ); } - + /* Sense connection status. * return values: LAN_10 - Connected to 10Mbit/s network * LAN_100 - Connected to 100Mbit/s network * LAN_ERR - not connected or 100Mbit/s Hub down */ -static int hp100_sense_lan(struct device *dev) +static int hp100_sense_lan( struct device *dev ) { - int ioaddr = dev->base_addr; - u_short val_VG, val_10; - struct hp100_private *lp = (struct hp100_private *) dev->priv; + int ioaddr = dev->base_addr; + u_short val_VG, val_10; + struct hp100_private *lp = (struct hp100_private *)dev->priv; #ifdef HP100_DEBUG_B - hp100_outw(0x4223, TRACE); -#endif - - hp100_page(MAC_CTRL); - /* Enable Auto Selection */ - /* hp100_orb( HP100_VG_RESET|HP100_LINK_CMD|HP100_VG_SEL, VG_LAN_CFG_1 ); */ - /* hp100_orb( HP100_DOT3_MAC,10_LAN_CFG_2); */ - /* hp100_orb( HP100_AUTO_MODE,MAC_CFG_3); */ - /* Now we have to wait a while... */ - /* for(i=0; i<5000; i++) */ - /* { */ - val_10 = hp100_inb(10_LAN_CFG_1); - val_VG = hp100_inb(VG_LAN_CFG_1); - /* } */ + hp100_outw( 0x4223, TRACE ); +#endif + + hp100_page( MAC_CTRL ); + val_10 = hp100_inb( 10_LAN_CFG_1 ); + val_VG = hp100_inb( VG_LAN_CFG_1 ); + hp100_page( PERFORMANCE ); #ifdef HP100_DEBUG - printk("hp100_sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", val_VG, val_10); -#endif - if (val_10 & HP100_LINK_BEAT_ST) - return HP100_LAN_10; - if ((lp->id->id == 0x02019F022) || - (lp->id->id == 0x01042103c) || - (lp->id->id == 0x01040103c)) { - hp100_page(PERFORMANCE); - return HP100_LAN_ERR; /* Those cards don't have a 100 Mbit connector */ - } - /* for ( i = 0; i < 2500; i++ ) */ - /* { */ - val_VG = hp100_inb(VG_LAN_CFG_1); - hp100_page(PERFORMANCE); - - if (val_VG & HP100_LINK_CABLE_ST) /* Can hear the HUBs tone. */ - return HP100_LAN_100; - /* } */ - return HP100_LAN_ERR; + printk( "hp100: %s: sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", dev->name, val_VG, val_10 ); +#endif + + if ( val_10 & HP100_LINK_BEAT_ST ) /* 10Mb connection is active */ + return HP100_LAN_10; + + if ( val_10 & HP100_AUI_ST ) /* have we BNC or AUI onboard? */ + { + val_10 |= HP100_AUI_SEL | HP100_LOW_TH; + hp100_page( MAC_CTRL ); + hp100_outb( val_10, 10_LAN_CFG_1 ); + hp100_page( PERFORMANCE ); + return HP100_LAN_10; + } + + if ( (lp->id->id == 0x02019F022) || + (lp->id->id == 0x01042103c) || + (lp->id->id == 0x01040103c) ) + return HP100_LAN_ERR; /* Those cards don't have a 100 Mbit connector */ + + if ( val_VG & HP100_LINK_CABLE_ST ) /* Can hear the HUBs tone. */ + return HP100_LAN_100; + return HP100_LAN_ERR; } - -static int hp100_down_vg_link(struct device *dev) + +static int hp100_down_vg_link( struct device *dev ) { - struct hp100_private *lp = (struct hp100_private *) dev->priv; - int ioaddr = dev->base_addr; - unsigned long time; - long savelan, newlan; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + int ioaddr = dev->base_addr; + unsigned long time; + long savelan, newlan; #ifdef HP100_DEBUG_B - hp100_outw(0x4224, TRACE); - printk("hp100: down_vg_link\n"); + hp100_outw( 0x4224, TRACE ); + printk("hp100: %s: down_vg_link\n", dev->name); #endif - hp100_page(MAC_CTRL); - time = jiffies + (HZ / 4); - do { - if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) - break; - } while (time > jiffies); + hp100_page( MAC_CTRL ); + time=jiffies+(HZ/4); + do{ + if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break; + } while (time>jiffies); - if (jiffies >= time) /* no signal->no logout */ - return 0; + if ( jiffies >= time ) /* no signal->no logout */ + return 0; - /* Drop the VG Link by clearing the link up cmd and load addr. */ + /* Drop the VG Link by clearing the link up cmd and load addr.*/ - hp100_andb(~(HP100_LOAD_ADDR | HP100_LINK_CMD), VG_LAN_CFG_1); - hp100_orb(HP100_VG_SEL, VG_LAN_CFG_1); + hp100_andb( ~( HP100_LOAD_ADDR| HP100_LINK_CMD), VG_LAN_CFG_1); + hp100_orb( HP100_VG_SEL, VG_LAN_CFG_1); - /* Conditionally stall for >250ms on Link-Up Status (to go down) */ - time = jiffies + (HZ / 2); - do { - if (!(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST)) - break; - } while (time > jiffies); + /* Conditionally stall for >250ms on Link-Up Status (to go down) */ + time=jiffies+(HZ/2); + do{ + if ( !(hp100_inb( VG_LAN_CFG_1) & HP100_LINK_UP_ST) ) break; + } while(time>jiffies); #ifdef HP100_DEBUG - if (jiffies >= time) - printk("hp100_down_vg_link: Link does not go down?\n"); -#endif - - /* To prevent condition where Rev 1 VG MAC and old hubs do not complete */ - /* logout under traffic (even though all the status bits are cleared), */ - /* do this workaround to get the Rev 1 MAC in its idle state */ - if (lp->chip == HP100_CHIPID_LASSEN) { - /* Reset VG MAC to insure it leaves the logoff state even if */ - /* the Hub is still emitting tones */ - hp100_andb(~HP100_VG_RESET, VG_LAN_CFG_1); - udelay(1500); /* wait for >1ms */ - hp100_orb(HP100_VG_RESET, VG_LAN_CFG_1); /* Release Reset */ - udelay(1500); - } - /* New: For lassen, switch to 10 Mbps mac briefly to clear training ACK */ - /* to get the VG mac to full reset. This is not req.d with later chips */ - /* Note: It will take the between 1 and 2 seconds for the VG mac to be */ - /* selected again! This will be left to the connect hub function to */ - /* perform if desired. */ - if (lp->chip == HP100_CHIPID_LASSEN) { - /* Have to write to 10 and 100VG control registers simultaneously */ - savelan = newlan = hp100_inl(10_LAN_CFG_1); /* read 10+100 LAN_CFG regs */ - newlan &= ~(HP100_VG_SEL << 16); - newlan |= (HP100_DOT3_MAC) << 8; - hp100_andb(~HP100_AUTO_MODE, MAC_CFG_3); /* Autosel off */ - hp100_outl(newlan, 10_LAN_CFG_1); - - /* Conditionally stall for 5sec on VG selected. */ - time = jiffies + (HZ * 5); - do { - if (!(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST)) - break; - } while (time > jiffies); - - hp100_orb(HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */ - hp100_outl(savelan, 10_LAN_CFG_1); - } - time = jiffies + (3 * HZ); /* Timeout 3s */ - do { - if ((hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) == 0) - break; - } while (time > jiffies); - - if (time <= jiffies) { + if (jiffies>=time) + printk("hp100: %s: down_vg_link: Link does not go down?\n", dev->name); +#endif + + /* To prevent condition where Rev 1 VG MAC and old hubs do not complete */ + /* logout under traffic (even though all the status bits are cleared), */ + /* do this workaround to get the Rev 1 MAC in its idle state */ + if ( lp->chip==HP100_CHIPID_LASSEN ) + { + /* Reset VG MAC to insure it leaves the logoff state even if */ + /* the Hub is still emitting tones */ + hp100_andb(~HP100_VG_RESET, VG_LAN_CFG_1); + udelay(1500); /* wait for >1ms */ + hp100_orb(HP100_VG_RESET, VG_LAN_CFG_1); /* Release Reset */ + udelay(1500); + } + + /* New: For lassen, switch to 10 Mbps mac briefly to clear training ACK */ + /* to get the VG mac to full reset. This is not req.d with later chips */ + /* Note: It will take the between 1 and 2 seconds for the VG mac to be */ + /* selected again! This will be left to the connect hub function to */ + /* perform if desired. */ + if (lp->chip==HP100_CHIPID_LASSEN) + { + /* Have to write to 10 and 100VG control registers simultaneously */ + savelan=newlan=hp100_inl(10_LAN_CFG_1); /* read 10+100 LAN_CFG regs */ + newlan &= ~(HP100_VG_SEL<<16); + newlan |= (HP100_DOT3_MAC)<<8; + hp100_andb( ~HP100_AUTO_MODE, MAC_CFG_3); /* Autosel off */ + hp100_outl(newlan, 10_LAN_CFG_1); + + /* Conditionally stall for 5sec on VG selected. */ + time=jiffies+(HZ*5); + do{ + if( !(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST) ) break; + } while(time>jiffies); + + hp100_orb( HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */ + hp100_outl(savelan, 10_LAN_CFG_1); + } + + time=jiffies+(3*HZ); /* Timeout 3s */ + do { + if ( (hp100_inb( VG_LAN_CFG_1 )&HP100_LINK_CABLE_ST) == 0) break; + } while (time>jiffies); + + if(time<=jiffies) + { #ifdef HP100_DEBUG - printk("hp100_down_vg_link: timeout\n"); -#endif - return -EIO; - } - time = jiffies + (2 * HZ); /* This seems to take a while.... */ - do { - } while (time > jiffies); - - return 0; + printk( "hp100: %s: down_vg_link: timeout\n", dev->name ); +#endif + return -EIO; + } + + time=jiffies+(2*HZ); /* This seems to take a while.... */ + do {} while (time>jiffies); + + return 0; } - -static int hp100_login_to_vg_hub(struct device *dev, u_short force_relogin) + +static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - u_short val = 0; - unsigned long time; - int startst; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + u_short val=0; + unsigned long time; + int startst; #ifdef HP100_DEBUG_B - hp100_outw(0x4225, TRACE); - printk("hp100: login_to_vg_hub\n"); -#endif - - /* Initiate a login sequence iff VG MAC is enabled and either Load Address - * bit is zero or the force relogin flag is set (e.g. due to MAC address or - * promiscuous mode change) - */ - hp100_page(MAC_CTRL); - startst = hp100_inb(VG_LAN_CFG_1); - if ((force_relogin == TRUE) || (hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST)) { + hp100_outw( 0x4225, TRACE ); + printk("hp100: %s: login_to_vg_hub\n", dev->name); +#endif + + /* Initiate a login sequence iff VG MAC is enabled and either Load Address + * bit is zero or the force relogin flag is set (e.g. due to MAC address or + * promiscuous mode change) + */ + hp100_page( MAC_CTRL ); + startst=hp100_inb( VG_LAN_CFG_1 ); + if((force_relogin==TRUE)||(hp100_inb( MAC_CFG_4 )&HP100_MAC_SEL_ST)) + { #ifdef HP100_DEBUG_TRAINING - printk("hp100: Start training\n"); + printk("hp100: %s: Start training\n", dev->name); #endif - /* Ensure VG Reset bit is 1 (i.e., do not reset) */ - hp100_orb(HP100_VG_RESET, VG_LAN_CFG_1); + /* Ensure VG Reset bit is 1 (i.e., do not reset)*/ + hp100_orb( HP100_VG_RESET , VG_LAN_CFG_1 ); - /* If Lassen AND auto-select-mode AND VG tones were sensed on */ - /* entry then temporarily put them into force 100Mbit mode */ - if ((lp->chip == HP100_CHIPID_LASSEN) && (startst & HP100_LINK_CABLE_ST)) - hp100_andb(~HP100_DOT3_MAC, 10_LAN_CFG_2); - - /* Drop the VG link by zeroing Link Up Command and Load Address */ - hp100_andb(~(HP100_LINK_CMD /* |HP100_LOAD_ADDR */ ), VG_LAN_CFG_1); + /* If Lassen AND auto-select-mode AND VG tones were sensed on */ + /* entry then temporarily put them into force 100Mbit mode */ + if((lp->chip==HP100_CHIPID_LASSEN)&&( startst & HP100_LINK_CABLE_ST ) ) + hp100_andb( ~HP100_DOT3_MAC, 10_LAN_CFG_2 ); + + /* Drop the VG link by zeroing Link Up Command and Load Address */ + hp100_andb( ~(HP100_LINK_CMD/* |HP100_LOAD_ADDR */), VG_LAN_CFG_1); #ifdef HP100_DEBUG_TRAINING - printk("hp100: Bring down the link\n"); -#endif - - /* Wait for link to drop */ - time = jiffies + (HZ / 10); - do { - if (~(hp100_inb(VG_LAN_CFG_1) & HP100_LINK_UP_ST)) - break; - } while (time > jiffies); - - /* Start an addressed training and optionally request promiscuous port */ - if ((dev->flags) & IFF_PROMISC) { - hp100_orb(HP100_PROM_MODE, VG_LAN_CFG_2); - if (lp->chip == HP100_CHIPID_LASSEN) - hp100_orw(HP100_MACRQ_PROMSC, TRAIN_REQUEST); - } else { - hp100_andb(~HP100_PROM_MODE, VG_LAN_CFG_2); - /* For ETR parts we need to reset the prom. bit in the training - * register, otherwise promiscious mode won't be disabled. - */ - if (lp->chip == HP100_CHIPID_LASSEN) { - hp100_andw(~HP100_MACRQ_PROMSC, TRAIN_REQUEST); - } - } - - /* With ETR parts, frame format request bits can be set. */ - if (lp->chip == HP100_CHIPID_LASSEN) - hp100_orb(HP100_MACRQ_FRAMEFMT_EITHER, TRAIN_REQUEST); - - hp100_orb(HP100_LINK_CMD | HP100_LOAD_ADDR | HP100_VG_RESET, VG_LAN_CFG_1); + printk("hp100: %s: Bring down the link\n", dev->name); +#endif - /* Note: Next wait could be omitted for Hood and earlier chips under */ - /* certain circumstances */ - /* TODO: check if hood/earlier and skip wait. */ + /* Wait for link to drop */ + time = jiffies + (HZ/10); + do { + if (~(hp100_inb( VG_LAN_CFG_1 )& HP100_LINK_UP_ST) ) break; + } while (time>jiffies); - /* Wait for either short timeout for VG tones or long for login */ - /* Wait for the card hardware to signalise link cable status ok... */ - hp100_page(MAC_CTRL); - time = jiffies + (1 * HZ); /* 1 sec timeout for cable st */ - do { - if (hp100_inb(VG_LAN_CFG_1) & HP100_LINK_CABLE_ST) - break; - } while (jiffies < time); + /* Start an addressed training and optionally request promiscuous port */ + if ( (dev->flags) & IFF_PROMISC ) + { + hp100_orb( HP100_PROM_MODE, VG_LAN_CFG_2); + if(lp->chip==HP100_CHIPID_LASSEN) + hp100_orw( HP100_MACRQ_PROMSC, TRAIN_REQUEST ); + } + else + { + hp100_andb( ~HP100_PROM_MODE, VG_LAN_CFG_2); + /* For ETR parts we need to reset the prom. bit in the training + * register, otherwise promiscious mode won't be disabled. + */ + if(lp->chip==HP100_CHIPID_LASSEN) + { + hp100_andw( ~HP100_MACRQ_PROMSC, TRAIN_REQUEST ); + } + } - if (jiffies >= time) { + /* With ETR parts, frame format request bits can be set. */ + if(lp->chip==HP100_CHIPID_LASSEN) + hp100_orb( HP100_MACRQ_FRAMEFMT_EITHER, TRAIN_REQUEST); + + hp100_orb( HP100_LINK_CMD|HP100_LOAD_ADDR|HP100_VG_RESET, VG_LAN_CFG_1); + + /* Note: Next wait could be omitted for Hood and earlier chips under */ + /* certain circumstances */ + /* TODO: check if hood/earlier and skip wait. */ + + /* Wait for either short timeout for VG tones or long for login */ + /* Wait for the card hardware to signalise link cable status ok... */ + hp100_page( MAC_CTRL ); + time = jiffies + ( 1*HZ ); /* 1 sec timeout for cable st */ + do { + if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break; + } while ( jiffies < time ); + + if ( jiffies >= time ) + { #ifdef HP100_DEBUG_TRAINING - printk("hp100: Link cable status not ok? Training aborted.\n"); -#endif - } else { + printk( "hp100: %s: Link cable status not ok? Training aborted.\n", dev->name ); +#endif + } + else + { #ifdef HP100_DEBUG_TRAINING - printk("hp100: HUB tones detected. Trying to train.\n"); + printk( "hp100: %s: HUB tones detected. Trying to train.\n", dev->name); #endif - time = jiffies + (2 * HZ); /* again a timeout */ - do { - val = hp100_inb(VG_LAN_CFG_1); - if ((val & (HP100_LINK_UP_ST))) { + time = jiffies + ( 2*HZ ); /* again a timeout */ + do { + val = hp100_inb( VG_LAN_CFG_1 ); + if ( (val & ( HP100_LINK_UP_ST )) ) + { #ifdef HP100_DEBUG_TRAINING - printk("hp100: Passed training.\n"); + printk( "hp100: %s: Passed training.\n", dev->name); #endif - break; - } - } while (time > jiffies); - } - - /* If LINK_UP_ST is set, then we are logged into the hub. */ - if ((jiffies <= time) && (val & HP100_LINK_UP_ST)) { + break; + } + } while ( time > jiffies ); + } + + /* If LINK_UP_ST is set, then we are logged into the hub. */ + if ( (jiffies<=time) && (val & HP100_LINK_UP_ST) ) + { #ifdef HP100_DEBUG_TRAINING - printk("hp100: Successfully logged into the HUB.\n"); - if (lp->chip == HP100_CHIPID_LASSEN) { - val = hp100_inw(TRAIN_ALLOW); - printk("hp100: Card supports 100VG MAC Version \"%s\" ", - (hp100_inw(TRAIN_REQUEST) & HP100_CARD_MACVER) ? "802.12" : "Pre"); - printk("Driver will use MAC Version \"%s\"\n", - (val & HP100_HUB_MACVER) ? "802.12" : "Pre"); - printk("hp100: Frame format is %s.\n", (val & HP100_MALLOW_FRAMEFMT) ? "802.5" : "802.3"); - } -#endif - } else { - /* If LINK_UP_ST is not set, login was not successful */ - printk("hp100/%s: Problem logging into the HUB.\n", dev->name); - if (lp->chip == HP100_CHIPID_LASSEN) { - /* Check allowed Register to find out why there is a problem. */ - val = hp100_inw(TRAIN_ALLOW); /* wont work on non-ETR card */ + printk( "hp100: %s: Successfully logged into the HUB.\n", dev->name); + if(lp->chip==HP100_CHIPID_LASSEN) + { + val = hp100_inw(TRAIN_ALLOW); + printk( "hp100: %s: Card supports 100VG MAC Version \"%s\" ", + dev->name,(hp100_inw(TRAIN_REQUEST)&HP100_CARD_MACVER) ? "802.12" : "Pre"); + printk( "Driver will use MAC Version \"%s\"\n", + ( val & HP100_HUB_MACVER) ? "802.12" : "Pre" ); + printk( "hp100: %s: Frame format is %s.\n",dev->name,(val&HP100_MALLOW_FRAMEFMT)?"802.5":"802.3"); + } +#endif + } + else + { + /* If LINK_UP_ST is not set, login was not successful */ + printk("hp100: %s: Problem logging into the HUB.\n",dev->name); + if(lp->chip==HP100_CHIPID_LASSEN) + { + /* Check allowed Register to find out why there is a problem. */ + val = hp100_inw( TRAIN_ALLOW ); /* wont work on non-ETR card */ #ifdef HP100_DEBUG_TRAINING - printk("hp100: MAC Configuration requested: 0x%04x, HUB allowed: 0x%04x\n", hp100_inw(TRAIN_REQUEST), val); -#endif - if (val & HP100_MALLOW_ACCDENIED) - printk("hp100: HUB access denied.\n"); - if (val & HP100_MALLOW_CONFIGURE) - printk("hp100: MAC Configuration is incompatible with the Network.\n"); - if (val & HP100_MALLOW_DUPADDR) - printk("hp100: Duplicate MAC Address on the Network.\n"); - } - } - - /* If we have put the chip into forced 100 Mbit mode earlier, go back */ - /* to auto-select mode */ - - if ((lp->chip == HP100_CHIPID_LASSEN) && (startst & HP100_LINK_CABLE_ST)) { - hp100_page(MAC_CTRL); - hp100_orb(HP100_DOT3_MAC, 10_LAN_CFG_2); - } - val = hp100_inb(VG_LAN_CFG_1); - - /* Clear the MISC_ERROR Interrupt, which might be generated when doing the relogin */ - hp100_page(PERFORMANCE); - hp100_outw(HP100_MISC_ERROR, IRQ_STATUS); - - if (val & HP100_LINK_UP_ST) - return (0); /* login was ok */ - else { - printk("hp100: Training failed.\n"); - hp100_down_vg_link(dev); - return -EIO; - } - } - /* no forced relogin & already link there->no training. */ - return -EIO; + printk("hp100: %s: MAC Configuration requested: 0x%04x, HUB allowed: 0x%04x\n", dev->name, hp100_inw(TRAIN_REQUEST), val); +#endif + if ( val & HP100_MALLOW_ACCDENIED ) + printk("hp100: %s: HUB access denied.\n", dev->name); + if ( val & HP100_MALLOW_CONFIGURE ) + printk("hp100: %s: MAC Configuration is incompatible with the Network.\n", dev->name); + if ( val & HP100_MALLOW_DUPADDR ) + printk("hp100: %s: Duplicate MAC Address on the Network.\n", dev->name); + } + } + + /* If we have put the chip into forced 100 Mbit mode earlier, go back */ + /* to auto-select mode */ + + if( (lp->chip==HP100_CHIPID_LASSEN)&&(startst & HP100_LINK_CABLE_ST) ) + { + hp100_page( MAC_CTRL ); + hp100_orb( HP100_DOT3_MAC, 10_LAN_CFG_2 ); + } + + val=hp100_inb(VG_LAN_CFG_1); + + /* Clear the MISC_ERROR Interrupt, which might be generated when doing the relogin */ + hp100_page(PERFORMANCE); + hp100_outw( HP100_MISC_ERROR, IRQ_STATUS); + + if (val&HP100_LINK_UP_ST) + return(0); /* login was ok */ + else + { + printk("hp100: %s: Training failed.\n", dev->name); + hp100_down_vg_link( dev ); + return -EIO; + } + } + /* no forced relogin & already link there->no training. */ + return -EIO; } - -static void hp100_cascade_reset(struct device *dev, u_short enable) + +static void hp100_cascade_reset( struct device *dev, u_short enable ) { - int ioaddr = dev->base_addr; - struct hp100_private *lp = (struct hp100_private *) dev->priv; - int i; + int ioaddr = dev->base_addr; + struct hp100_private *lp = (struct hp100_private *)dev->priv; + int i; #ifdef HP100_DEBUG_B - hp100_outw(0x4226, TRACE); - printk("hp100: cascade_reset\n"); -#endif - - if (enable == TRUE) { - hp100_outw(HP100_HW_RST | HP100_RESET_LB, OPTION_LSW); - if (lp->chip == HP100_CHIPID_LASSEN) { - /* Lassen requires a PCI transmit fifo reset */ - hp100_page(HW_MAP); - hp100_andb(~HP100_PCI_RESET, PCICTRL2); - hp100_orb(HP100_PCI_RESET, PCICTRL2); - /* Wait for min. 300 ns */ - /* we cant use jiffies here, because it may be */ - /* that we have disabled the timer... */ - for (i = 0; i < 0xffff; i++); - hp100_andb(~HP100_PCI_RESET, PCICTRL2); - hp100_page(PERFORMANCE); - } - } else { /* bring out of reset */ - hp100_outw(HP100_HW_RST | HP100_SET_LB, OPTION_LSW); - for (i = 0; i < 0xffff; i++); - hp100_page(PERFORMANCE); - } + hp100_outw( 0x4226, TRACE ); + printk("hp100: %s: cascade_reset\n", dev->name); +#endif + + if (enable==TRUE) + { + hp100_outw( HP100_HW_RST | HP100_RESET_LB, OPTION_LSW ); + if(lp->chip==HP100_CHIPID_LASSEN) + { + /* Lassen requires a PCI transmit fifo reset */ + hp100_page( HW_MAP ); + hp100_andb( ~HP100_PCI_RESET, PCICTRL2 ); + hp100_orb( HP100_PCI_RESET, PCICTRL2 ); + /* Wait for min. 300 ns */ + /* we cant use jiffies here, because it may be */ + /* that we have disabled the timer... */ + for (i=0; i<0xffff; i++); + hp100_andb( ~HP100_PCI_RESET, PCICTRL2 ); + hp100_page( PERFORMANCE ); + } + } + else + { /* bring out of reset */ + hp100_outw(HP100_HW_RST|HP100_SET_LB, OPTION_LSW); + for (i=0; i<0xffff; i++ ); + hp100_page(PERFORMANCE); + } } -#ifdef HP100_DEBUG -void hp100_RegisterDump(struct device *dev) +#ifdef HP100_DEBUG +void hp100_RegisterDump( struct device *dev ) { - int ioaddr = dev->base_addr; - int Page; - int Register; - - /* Dump common registers */ - printk("hp100: Cascade Register Dump\n"); - printk("hardware id #1: 0x%.2x\n", hp100_inb(HW_ID)); - printk("hardware id #2/paging: 0x%.2x\n", hp100_inb(PAGING)); - printk("option #1: 0x%.4x\n", hp100_inw(OPTION_LSW)); - printk("option #2: 0x%.4x\n", hp100_inw(OPTION_MSW)); - - /* Dump paged registers */ - for (Page = 0; Page < 8; Page++) { - /* Dump registers */ - printk("page: 0x%.2x\n", Page); - outw(Page, ioaddr + 0x02); - for (Register = 0x8; Register < 0x22; Register += 2) { - /* Display Register contents except data port */ - if (((Register != 0x10) && (Register != 0x12)) || (Page > 0)) { - printk("0x%.2x = 0x%.4x\n", Register, inw(ioaddr + Register)); - } - } + int ioaddr=dev->base_addr; + int Page; + int Register; + + /* Dump common registers */ + printk("hp100: %s: Cascade Register Dump\n", dev->name); + printk("hardware id #1: 0x%.2x\n",hp100_inb(HW_ID)); + printk("hardware id #2/paging: 0x%.2x\n",hp100_inb(PAGING)); + printk("option #1: 0x%.4x\n",hp100_inw(OPTION_LSW)); + printk("option #2: 0x%.4x\n",hp100_inw(OPTION_MSW)); + + /* Dump paged registers */ + for (Page = 0; Page < 8; Page++) + { + /* Dump registers */ + printk("page: 0x%.2x\n",Page); + outw( Page, ioaddr+0x02); + for (Register = 0x8; Register < 0x22; Register += 2) + { + /* Display Register contents except data port */ + if (((Register != 0x10) && (Register != 0x12)) || (Page > 0)) + { + printk("0x%.2x = 0x%.4x\n",Register,inw(ioaddr+Register)); + } } - hp100_page(PERFORMANCE); + } + hp100_page(PERFORMANCE); } #endif - + /* * module section */ - + #ifdef MODULE /* Parameters set by insmod */ -int hp100_port[5] = -{0, -1, -1, -1, -1}; +int hp100_port[5] = { 0, -1, -1, -1, -1 }; #ifdef LINUX_2_1 MODULE_PARM(hp100_port, "1-5i"); #endif #ifdef LINUX_2_1 -char hp100_name[5][IFNAMSIZ] = -{"", "", "", "", ""}; +char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" }; MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ)); #else -static char devname[5][IFNAMSIZ] = -{"", "", "", "", ""}; -static char *hp100_name[5] = -{devname[0], devname[1], - devname[2], devname[3], - devname[4]}; +static char devname[5][IFNAMSIZ] = { "", "", "", "", "" }; +static char *hp100_name[5] = { devname[0], devname[1], + devname[2], devname[3], + devname[4] }; #endif /* List of devices */ -static struct device *hp100_devlist[5] = -{NULL, NULL, NULL, NULL, NULL}; +static struct device *hp100_devlist[5] = { NULL, NULL, NULL, NULL, NULL }; /* * Note: if you have more than five 100vg cards in your pc, feel free to @@ -2606,61 +3055,64 @@ static struct device *hp100_devlist[5] = * option hp100 hp100_port=0x280 hp100_name=eth239 */ -int init_module(void) +int init_module( void ) { - int i; - int ret = 0; - - if (hp100_port == 0 && !EISA_bus && !pcibios_present()) - printk("HP100: You should not use auto-probing with insmod!\n"); - - /* Loop on all possible base addresses */ - i = -1; - while ((hp100_port[++i] != -1) && (i < 5)) { - /* Create device and set basics args */ - hp100_devlist[i] = kmalloc(sizeof(struct device), GFP_KERNEL); - memset(hp100_devlist[i], 0x00, sizeof(struct device)); - hp100_devlist[i]->name = hp100_name[i]; - hp100_devlist[i]->base_addr = hp100_port[i]; - hp100_devlist[i]->init = &hp100_probe; - - /* Try to create the device */ - if (register_netdev(hp100_devlist[i]) != 0) { - /* DeAllocate everything */ - /* Note: if dev->priv is mallocated, there is no way to fail */ - kfree_s(hp100_devlist[i], sizeof(struct device)); - hp100_devlist[i] = (struct device *) NULL; - ret = -EIO; - } - } /* Loop over all devices */ + int i, cards; + + if (hp100_port == 0 && !EISA_bus && !pcibios_present()) + printk("hp100: You should not use auto-probing with insmod!\n"); + + /* Loop on all possible base addresses */ + i = -1; cards = 0; + while((hp100_port[++i] != -1) && (i < 5)) + { + /* Create device and set basics args */ + hp100_devlist[i] = kmalloc(sizeof(struct device), GFP_KERNEL); + memset(hp100_devlist[i], 0x00, sizeof(struct device)); + hp100_devlist[i]->name = hp100_name[i]; + hp100_devlist[i]->base_addr = hp100_port[i]; + hp100_devlist[i]->init = &hp100_probe; + + /* Try to create the device */ + if(register_netdev(hp100_devlist[i]) != 0) + { + /* DeAllocate everything */ + /* Note: if dev->priv is mallocated, there is no way to fail */ + kfree_s(hp100_devlist[i], sizeof(struct device)); + hp100_devlist[i] = (struct device *) NULL; + } + else + cards++; + } /* Loop over all devices */ - return ret; + return cards > 0 ? 0 : -ENODEV; } -void cleanup_module(void) +void cleanup_module( void ) { - int i; - - /* TODO: Check if all skb's are released/freed. */ - for (i = 0; i < 5; i++) - if (hp100_devlist[i] != (struct device *) NULL) { - unregister_netdev(hp100_devlist[i]); - release_region(hp100_devlist[i]->base_addr, HP100_REGION_SIZE); - if (((struct hp100_private *) hp100_devlist[i]->priv)->mode == 1) /* busmaster */ - kfree_s(((struct hp100_private *) hp100_devlist[i]->priv)->page_vaddr, MAX_RINGSIZE + 0x0f); - if (((struct hp100_private *) hp100_devlist[i]->priv)->mem_ptr_virt) - iounmap(((struct hp100_private *) hp100_devlist[i]->priv)->mem_ptr_virt); - kfree_s(hp100_devlist[i]->priv, sizeof(struct hp100_private)); - hp100_devlist[i]->priv = NULL; - kfree_s(hp100_devlist[i], sizeof(struct device)); - hp100_devlist[i] = (struct device *) NULL; - } + int i; + + /* TODO: Check if all skb's are released/freed. */ + for(i = 0; i < 5; i++) + if(hp100_devlist[i] != (struct device *) NULL) + { + unregister_netdev( hp100_devlist[i] ); + release_region( hp100_devlist[i]->base_addr, HP100_REGION_SIZE ); + if( ((struct hp100_private *)hp100_devlist[i]->priv)->mode==1 ) /* busmaster */ + kfree_s( ((struct hp100_private *)hp100_devlist[i]->priv)->page_vaddr, MAX_RINGSIZE+0x0f); + if ( ((struct hp100_private *)hp100_devlist[i]->priv) -> mem_ptr_virt ) + iounmap( ((struct hp100_private *)hp100_devlist[i]->priv) -> mem_ptr_virt ); + kfree_s( hp100_devlist[i]->priv, sizeof( struct hp100_private ) ); + hp100_devlist[i]->priv = NULL; + kfree_s(hp100_devlist[i], sizeof(struct device)); + hp100_devlist[i] = (struct device *) NULL; + } } -#endif /* MODULE */ - +#endif /* MODULE */ + /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp100.c" diff --git a/drivers/net/hp100.h b/drivers/net/hp100.h index c1c62e6bb..436dd3700 100644 --- a/drivers/net/hp100.h +++ b/drivers/net/hp100.h @@ -1,7 +1,7 @@ /* * hp100.h: Hewlett Packard HP10/100VG ANY LAN ethernet driver for Linux. * - * $Id: hp100.h,v 1.4 1997/05/26 21:09:19 davem Exp $ + * $Id: hp100.h,v 1.51 1997/04/08 14:26:42 floeff Exp floeff $ * * Authors: Jaroslav Kysela, <perex@pf.jcu.cz> * Siegfried Loeffler <floeff@tunix.mathematik.uni-stuttgart.de> diff --git a/drivers/net/ipddp.c b/drivers/net/ipddp.c index 141349576..16e52bd98 100644 --- a/drivers/net/ipddp.c +++ b/drivers/net/ipddp.c @@ -83,9 +83,6 @@ static unsigned int ipddp_debug = IPDDP_DEBUG; /* Index to functions, as function prototypes. */ static int ipddp_xmit(struct sk_buff *skb, struct device *dev); static struct net_device_stats *ipddp_get_stats(struct device *dev); -static int ipddp_rebuild_header(struct sk_buff *skb); -static int ipddp_hard_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len); static int ipddp_create(struct ipddp_route *new_rt); static int ipddp_delete(struct ipddp_route *rt); static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt); @@ -119,10 +116,10 @@ int ipddp_init(struct device *dev) /* Let the user now what mode we are in */ if(ipddp_mode == IPDDP_ENCAP) - printk("%s: Appletalk-IP Encapsulation mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", + printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", dev->name); if(ipddp_mode == IPDDP_DECAP) - printk("%s: Appletalk-IP Decapsulation mode by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n", + printk("%s: Appletalk-IP Decap. mode by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n", dev->name); /* Fill in the device structure with ethernet-generic values. */ @@ -140,8 +137,6 @@ int ipddp_init(struct device *dev) dev->stop = ipddp_close; dev->get_stats = ipddp_get_stats; dev->do_ioctl = ipddp_ioctl; - dev->hard_header = ipddp_hard_header; /* see ip_output.c */ - dev->rebuild_header = ipddp_rebuild_header; dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */ dev->mtu = 585; @@ -158,24 +153,6 @@ int ipddp_init(struct device *dev) } /* - * Transmit LLAP/ELAP frame using aarp_send_ddp. - */ -static int ipddp_xmit(struct sk_buff *skb, struct device *dev) -{ - /* Retrieve the saved address hint */ - struct at_addr *at = (struct at_addr *)skb->data; - skb_pull(skb,4); - - ((struct net_device_stats *) dev->priv)->tx_packets++; - ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len; - - if(aarp_send_ddp(skb->dev, skb, at, NULL) < 0) - dev_kfree_skb(skb); - - return 0; -} - -/* * Get the current statistics. This may be called with the card open or closed. */ static struct net_device_stats *ipddp_get_stats(struct device *dev) @@ -184,19 +161,15 @@ static struct net_device_stats *ipddp_get_stats(struct device *dev) } /* - * Now the packet really wants to go out. On entry skb->data points to the - * ddpehdr we reserved earlier. skb->h.raw will be the higher level header. + * Transmit LLAP/ELAP frame using aarp_send_ddp. */ -static int ipddp_rebuild_header(struct sk_buff *skb) +static int ipddp_xmit(struct sk_buff *skb, struct device *dev) { u32 paddr = ((struct rtable*)skb->dst)->rt_gateway; struct ddpehdr *ddp; - struct at_addr at; struct ipddp_route *rt; struct at_addr *our_addr; - /* Wow! I'll eat my hat if this routine is really called. --ANK */ - /* * Find appropriate route to use, based only on IP number. */ @@ -205,25 +178,21 @@ static int ipddp_rebuild_header(struct sk_buff *skb) if(rt->ip == paddr) break; } - if(rt == NULL) - { - printk("%s: unreachable dst %s\n", cardname, in_ntoa(paddr)); - return -ENETUNREACH; - } + return 0; our_addr = atalk_find_dev_addr(rt->dev); if(ipddp_mode == IPDDP_DECAP) /* * Pull off the excess room that should not be there. - * This is the case for Localtalk, this may not hold - * true for Ethertalk, etc. + * This is due to a hard-header problem. This is the + * quick fix for now though, till it breaks. */ - skb_pull(skb, 31-(sizeof(struct ddpehdr)+1)); + skb_pull(skb, 35-(sizeof(struct ddpehdr)+1)); /* Create the Extended DDP header */ - ddp = (struct ddpehdr *) (skb->data+4); + ddp = (struct ddpehdr *)skb->data; ddp->deh_len = skb->len; ddp->deh_hops = 1; ddp->deh_pad = 0; @@ -231,7 +200,7 @@ static int ipddp_rebuild_header(struct sk_buff *skb) /* * For Localtalk we need aarp_send_ddp to strip the - * Ext DDP header and place a Shrt DDP header on it. + * long DDP header and place a shot DDP header on it. */ if(rt->dev->type == ARPHRD_LOCALTLK) { @@ -248,24 +217,16 @@ static int ipddp_rebuild_header(struct sk_buff *skb) ddp->deh_dport = 72; ddp->deh_sport = 72; - *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ - *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* fix up length field */ + *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ + *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* fix up length field */ - /* Hide it at the start of the buffer, we pull it out in ipddp_xmit */ - at = rt->at; - memcpy(skb->data,(void *)&at,sizeof(at)); - - skb->dev = rt->dev; /* set skb->dev to appropriate device */ skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ - return 0; -} + ((struct net_device_stats *) dev->priv)->tx_packets++; + ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len; -static int ipddp_hard_header(struct sk_buff *skb, struct device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) -{ - /* Push down the header space and the type byte */ - skb_push(skb, sizeof(struct ddpehdr)+1+4); + if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0) + dev_kfree_skb(skb); return 0; } diff --git a/drivers/net/ipddp.h b/drivers/net/ipddp.h index 31178934b..076373b81 100644 --- a/drivers/net/ipddp.h +++ b/drivers/net/ipddp.h @@ -10,7 +10,6 @@ #define SIOCADDIPDDPRT (SIOCDEVPRIVATE) #define SIOCDELIPDDPRT (SIOCDEVPRIVATE+1) #define SIOCFINDIPDDPRT (SIOCDEVPRIVATE+2) -#define SIOCPRINTIPDDPRT (SIOCDEVPRIVATE+3) struct ipddp_route { diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 9380f32f8..de70cd001 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -3,6 +3,7 @@ * Michael Callahan <callahan@maths.ox.ac.uk> * Al Longyear <longyear@netcom.com> * Paul Mackerras <Paul.Mackerras@cs.anu.edu.au> + * Cyrus Durgin <cider@speakeasy.org> (changes for kmod) * * Dynamic PPP devices by Jim Freeman <jfree@caldera.com>. * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se> @@ -50,7 +51,7 @@ /* $Id: ppp.c,v 1.14 1997/11/27 06:04:45 paulus Exp $ */ -#include <linux/config.h> /* for CONFIG_KERNELD */ +#include <linux/config.h> /* for CONFIG_KMOD */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -94,8 +95,8 @@ typedef struct sk_buff sk_buff; #include <linux/if_pppvar.h> #include <linux/ppp-comp.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #ifndef PPP_IPX @@ -2190,14 +2191,14 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) restore_flags(flags); cp = find_compressor (ccp_option[0]); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (cp == NULL) { char modname[32]; sprintf(modname, "ppp-compress-%d", ccp_option[0]); request_module(modname); cp = find_compressor(ccp_option[0]); } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ if (cp == NULL) goto out_no_comp; diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index d036fabb3..6dbaec6d2 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -43,6 +43,7 @@ static const char *version = #include <linux/init.h> #include <asm/system.h> #include <asm/bitops.h> +#include <asm/delay.h> #include <asm/io.h> #include <asm/dma.h> #include <linux/errno.h> diff --git a/drivers/net/slip.c b/drivers/net/slip.c index fe464965e..489f0a39e 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -181,12 +181,14 @@ sl_alloc_bufs(struct slip *sl, int mtu) sl->xleft = 0; rbuff = xchg(&sl->rbuff, rbuff); xbuff = xchg(&sl->xbuff, xbuff); -#ifdef CONFIG_SLIP_MODE_SLIP6 +#ifdef SL_INCLUDE_CSLIP cbuff = xchg(&sl->cbuff, cbuff); slcomp = xchg(&sl->slcomp, slcomp); +#ifdef CONFIG_SLIP_MODE_SLIP6 sl->xdata = 0; sl->xbits = 0; #endif +#endif end_bh_atomic(); err = 0; @@ -1134,7 +1136,7 @@ slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) it breaks my old poor gcc on alpha --ANK */ tmp = strlen(sl->dev->name) + 1; - if (copy_to_user(arg, sl->dev->name, tmp) < 0) + if (copy_to_user(arg, sl->dev->name, tmp)) return -EFAULT; return 0; diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c index f4484e225..035c47a5c 100644 --- a/drivers/net/tulip.c +++ b/drivers/net/tulip.c @@ -636,7 +636,7 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq, for (i = 0; i < 5; i++) dev->dev_addr[i] = last_phys_addr[i]; dev->dev_addr[i] = last_phys_addr[i] + 1; -#if defined(__i386) /* This BIOS bug doesn't exist on Alphas. */ +#if defined(__i386__) /* This BIOS bug doesn't exist on Alphas. */ irq = last_irq; #endif } @@ -1094,7 +1094,7 @@ tulip_open(struct device *dev) outl(0x00200000 | 0xE000, ioaddr + CSR0); #elif defined(__powerpc__) outl(0x00200080 | 0x8000, ioaddr + CSR0); -#elif defined(__i386) +#elif defined(__i386__) #if defined(MODULE) /* When a module we don't have 'x86' to check. */ outl(0x00200000 | 0x4800, ioaddr + CSR0); diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 2dc9c8a66..7956db9d1 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -9470,7 +9470,7 @@ printk("ncr53c8xx_pci_init() #1: bus == %d, device_fn == %d\n", bus, device_fn); /* * Try to fix up PCI config according to wished features. */ -#if defined(__i386) && !defined(MODULE) +#if defined(__i386__) && !defined(MODULE) if ((driver_setup.pci_fix_up & 1) && (chip->features & FE_CLSE) && cache_line_size == 0) { #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75) diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 3c2f083bd..ebdcb560c 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -50,8 +50,8 @@ NULL, /* cur_cmd */ \ #include "ppa.h" #include <linux/parport.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #ifndef PARPORT_MODULES #define PARPORT_MODULES "parport_pc" #endif @@ -130,7 +130,7 @@ int ppa_detect(Scsi_Host_Template * host) nhosts = 0; try_again = 0; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (!pb) { request_module(PARPORT_MODULES); pb = parport_enumerate(); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 4876ad297..90bb6e2d4 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -23,10 +23,13 @@ * Added request_module("scsi_hostadapter") for kerneld: * (Put an "alias scsi_hostadapter your_hostadapter" in /etc/conf.modules) * Bjorn Ekwall <bj0rn@blox.se> + * (changed to kmod) * * Major improvements to the timeout, abort, and reset processing, * as well as performance modifications for large queue depths by * Leonard N. Zubkoff <lnz@dandelion.com> + * + * Converted cli() code to spinlocks, Ingo Molnar */ #include <linux/config.h> @@ -57,8 +60,8 @@ #include "hosts.h" #include "constants.h" -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #undef USE_STATIC_SCSI_MEMORY @@ -350,8 +353,8 @@ scsi_make_blocked_list(void) * (DB, 4 Feb 1995) */ - save_flags(flags); - cli(); + + spin_lock_irqsave(&io_request_lock, flags); host_active = NULL; for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) { @@ -383,7 +386,7 @@ scsi_make_blocked_list(void) sh[index]->host_no); } - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static void scan_scsis_done (Scsi_Cmnd * SCpnt) @@ -1134,21 +1137,21 @@ Scsi_Cmnd * scsi_allocate_device (struct request ** reqp, Scsi_Device * device, SCpnt = found; } - save_flags(flags); - cli(); + __save_flags(flags); + __cli(); /* See if this request has already been queued by an interrupt routine */ if (req && (req->rq_status == RQ_INACTIVE || req->rq_dev != dev)) { - restore_flags(flags); + __restore_flags(flags); return NULL; } if (!SCpnt || SCpnt->request.rq_status != RQ_INACTIVE) /* Might have changed */ { if (wait && SCwait && SCwait->request.rq_status != RQ_INACTIVE){ sleep_on(&device->device_wait); - restore_flags(flags); + __restore_flags(flags); } else { - restore_flags(flags); + __restore_flags(flags); if (!wait) return NULL; if (!SCwait) { printk("Attempt to allocate device channel %d," @@ -1198,7 +1201,7 @@ Scsi_Cmnd * scsi_allocate_device (struct request ** reqp, Scsi_Device * device, * to complete */ } atomic_inc(&SCpnt->host->host_active); - restore_flags(flags); + __restore_flags(flags); SCSI_LOG_MLQUEUE(5, printk("Activating command for device %d (%d)\n", SCpnt->target, atomic_read(&SCpnt->host->host_active))); @@ -1295,8 +1298,7 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt) host = SCpnt->host; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); /* Assign a unique nonzero serial_number. */ if (++serial_number == 0) serial_number = 1; SCpnt->serial_number = serial_number; @@ -1306,6 +1308,8 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt) * we can avoid the drive not being ready. */ timeout = host->last_reset + MIN_RESET_DELAY; + spin_unlock(&io_request_lock); + if (jiffies < timeout) { int ticks_remaining = timeout - jiffies; /* @@ -1317,11 +1321,11 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt) * interrupt handler (assuming there is one irq-level per * host). */ - sti(); + __sti(); while (--ticks_remaining >= 0) udelay(1000000/HZ); host->last_reset = jiffies - MIN_RESET_DELAY; } - restore_flags(flags); + __restore_flags(flags); /* this possibly puts us back into __cli() */ if( host->hostt->use_new_eh_code ) { @@ -1452,21 +1456,20 @@ SCSI_LOG_MLQUEUE(4, * ourselves. */ - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); SCpnt->pid = scsi_pid++; while (SCSI_BLOCK((Scsi_Device *) NULL, host)) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); SCSI_SLEEP(&host->host_wait, SCSI_BLOCK((Scsi_Device *) NULL, host)); - cli(); + spin_lock_irqsave(&io_request_lock, flags); } if (host->block) host_active = host; host->host_busy++; device->device_busy++; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); /* * Our own function scsi_done (which marks the host as not busy, disables @@ -1820,8 +1823,7 @@ void *scsi_malloc(unsigned int len) if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE) return NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); nbits = len >> 9; mask = (1 << nbits) - 1; @@ -1829,7 +1831,7 @@ void *scsi_malloc(unsigned int len) for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){ if ((dma_malloc_freelist[i] & (mask << j)) == 0){ dma_malloc_freelist[i] |= (mask << j); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); scsi_dma_free_sectors -= nbits; #ifdef DEBUG SCSI_LOG_MLQUEUE(3,printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9))); @@ -1838,7 +1840,7 @@ void *scsi_malloc(unsigned int len) return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); } } - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return NULL; /* Nope. No more */ } @@ -1872,19 +1874,20 @@ int scsi_free(void *obj, unsigned int len) if ((mask << sector) >= (1 << SECTORS_PER_PAGE)) panic ("scsi_free:Bad memory alignment"); - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector)){ + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG printk("scsi_free(obj=%p, len=%d) called from %08lx\n", obj, len, ret); #endif panic("scsi_free:Trying to free unused memory"); + spin_lock_irqsave(&io_request_lock, flags); } scsi_dma_free_sectors += nbits; dma_malloc_freelist[page] &= ~(mask << sector); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } } @@ -2548,8 +2551,7 @@ static void resize_dma_pool(void) /* When we dick with the actual DMA list, we need to * protect things */ - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if (dma_malloc_freelist) { size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); @@ -2569,7 +2571,7 @@ static void resize_dma_pool(void) dma_malloc_pages = new_dma_malloc_pages; dma_sectors = new_dma_sectors; scsi_need_isa_buffer = new_need_isa_buffer; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG_INIT printk("resize_dma_pool: dma free sectors = %d\n", scsi_dma_free_sectors); @@ -2808,11 +2810,10 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) { online_status = SDpnt->online; SDpnt->online = FALSE; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if(SCpnt->request.rq_status != RQ_INACTIVE) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); printk("SCSI device not inactive - state=%d, id=%d\n", SCpnt->request.rq_status, SCpnt->target); for(SDpnt1 = shpnt->host_queue; SDpnt1; @@ -2833,7 +2834,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) */ SCpnt->state = SCSI_STATE_DISCONNECTING; SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */ - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } } } @@ -3118,7 +3119,7 @@ int scsi_register_module(int module_type, void * ptr) /* Load upper level device handler of some kind */ case MODULE_SCSI_DEV: -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (scsi_hosts == NULL) request_module("scsi_hostadapter"); #endif diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f5e19c547..70adb0040 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -8,7 +8,6 @@ * */ -#include <linux/config.h> #define __NO_VERSION__ #include <linux/module.h> @@ -38,10 +37,6 @@ #define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif - #ifdef DEBUG #define SENSE_TIMEOUT SCSI_TIMEOUT #define ABORT_TIMEOUT SCSI_TIMEOUT diff --git a/drivers/scsi/scsi_obsolete.c b/drivers/scsi/scsi_obsolete.c index 077b73063..daede4a56 100644 --- a/drivers/scsi/scsi_obsolete.c +++ b/drivers/scsi/scsi_obsolete.c @@ -20,10 +20,6 @@ * Native multichannel, wide scsi, /proc/scsi and hot plugging * support added by Michael Neuffer <mike@i-connect.net> * - * Added request_module("scsi_hostadapter") for kerneld: - * (Put an "alias scsi_hostadapter your_hostadapter" in /etc/conf.modules) - * Bjorn Ekwall <bj0rn@blox.se> - * * Major improvements to the timeout, abort, and reset processing, * as well as performance modifications for large queue depths by * Leonard N. Zubkoff <lnz@dandelion.com> @@ -47,7 +43,6 @@ * driver uses the new code this *ENTIRE* file will be nuked. */ -#include <linux/config.h> /* for CONFIG_KERNELD */ #define __NO_VERSION__ #include <linux/module.h> @@ -70,10 +65,6 @@ #include "hosts.h" #include "constants.h" -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif - #undef USE_STATIC_SCSI_MEMORY /* diff --git a/drivers/scsi/scsi_queue.c b/drivers/scsi/scsi_queue.c index b9e2a4feb..3c29353f9 100644 --- a/drivers/scsi/scsi_queue.c +++ b/drivers/scsi/scsi_queue.c @@ -10,7 +10,6 @@ * we attempt to remove commands from the queue and retry them. */ -#include <linux/config.h> #define __NO_VERSION__ #include <linux/module.h> @@ -38,10 +37,6 @@ #include "hosts.h" #include "constants.h" -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> -#endif - /* * TODO: * 1) Prevent multiple traversals of list to look for commands to diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c29194b70..5f0668eb6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1598,15 +1598,14 @@ int revalidate_scsidisk(kdev_t dev, int maxusage){ target = DEVICE_NR(dev); gdev = &GENDISK_STRUCT; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); printk("Device busy for revalidation (usage=%d)\n", USAGE); return -EBUSY; } DEVICE_BUSY = 1; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); max_p = gdev->max_p; start = target << gdev->minor_shift; diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index f8c899535..1b915e3ed 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -127,6 +127,19 @@ * * Thanks to Roger Scott for driver debugging. * + * 06/07/1997 + * + * Added support for /proc file system (/proc/scsi/wd7000/[0...] files). + * Now, driver can handle hard disks with capacity >1GB. + * + * 01/15/1998 + * + * Added support for BUS_ON and BUS_OFF parameters in config line. + * Miscellaneous cleanup. + * + * 03/01/1998 + * + * WD7000 driver now work on kernels >= 2.1.x */ #ifdef MODULE @@ -143,24 +156,29 @@ #include <asm/system.h> #include <asm/dma.h> #include <asm/io.h> -#include <asm/irq.h> #include <linux/ioport.h> #include <linux/proc_fs.h> #include <linux/blk.h> +#include <linux/version.h> #include "scsi.h" #include "hosts.h" #include "sd.h" +#include <scsi/scsicam.h> #define ANY2SCSI_INLINE /* undef this to use old macros */ -#undef DEBUG +#undef WD7000_DEBUG /* general debug */ #include "wd7000.h" +#include <linux/stat.h> -#include<linux/stat.h> -struct proc_dir_entry proc_scsi_wd7000 = { - PROC_SCSI_7000FASST, 6, "wd7000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 +struct proc_dir_entry proc_scsi_wd7000 = +{ + PROC_SCSI_7000FASST, + 6, + "wd7000", + S_IFDIR | S_IRUGO | S_IXUGO, + 2 }; @@ -186,52 +204,48 @@ struct proc_dir_entry proc_scsi_wd7000 = { * WD7000-specific mailbox structure * */ -typedef volatile struct mailbox{ - unchar status; - unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ +typedef volatile struct mailbox { + unchar status; + unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */ } Mailbox; /* * This structure should contain all per-adapter global data. I.e., any * new global per-adapter data should put in here. - * */ typedef struct adapter { - struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ - int iobase; /* This adapter's I/O base address */ - int irq; /* This adapter's IRQ level */ - int dma; /* This adapter's DMA channel */ - struct { /* This adapter's mailboxes */ - Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ - Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ - } mb; - int next_ogmb; /* to reduce contention at mailboxes */ - unchar control; /* shadows CONTROL port value */ - unchar rev1, rev2; /* filled in by wd7000_revision */ + struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */ + int iobase; /* This adapter's I/O base address */ + int irq; /* This adapter's IRQ level */ + int dma; /* This adapter's DMA channel */ + int int_counter; /* This adapter's interrupt counter */ + int bus_on; /* This adapter's BUS_ON time */ + int bus_off; /* This adapter's BUS_OFF time */ + struct { /* This adapter's mailboxes */ + Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */ + Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */ + } mb; + int next_ogmb; /* to reduce contention at mailboxes */ + unchar control; /* shadows CONTROL port value */ + unchar rev1, rev2; /* filled in by wd7000_revision */ } Adapter; /* - * The following is set up by wd7000_detect, and used thereafter by - * wd7000_intr_handle to map the irq level to the corresponding Adapter. - * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be - * changed to pick up the IRQ level correctly. - */ -static Adapter *irq2host[NR_IRQS] = {NULL}; - -/* * (linear) base address for ROM BIOS */ -static const long wd7000_biosaddr[] = { - 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, - 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000 +static const long wd7000_biosaddr[] = +{ + 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000 }; #define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long)) -static const unsigned short wd7000_iobase[] = { - 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, - 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, - 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, - 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8 +static const unsigned short wd7000_iobase[] = +{ + 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, + 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, + 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, + 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8 }; #define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short)) @@ -240,24 +254,48 @@ static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; static const short wd7000_dma[] = { 5, 6, 7 }; #define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short)) - + +/* + * possible irq range + */ +#define IRQ_MIN 3 +#define IRQ_MAX 15 +#define IRQS (IRQ_MAX - IRQ_MIN + 1) + +/* + * The following is set up by wd7000_detect, and used thereafter by + * wd7000_intr_handle to map the irq level to the corresponding Adapter. + * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be + * changed to pick up the IRQ level correctly. + */ +static struct Scsi_Host *wd7000_host[IRQS]; + +#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ +#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ + /* * Standard Adapter Configurations - used by wd7000_detect */ typedef struct { - int irq; /* IRQ level */ - int dma; /* DMA channel */ - unsigned iobase; /* I/O base address */ + short irq; /* IRQ level */ + short dma; /* DMA channel */ + unsigned iobase; /* I/O base address */ + short bus_on; /* Time that WD7000 spends on the AT-bus when */ + /* transferring data. BIOS default is 8000ns. */ + short bus_off; /* Time that WD7000 spends OFF THE BUS after */ + /* while it is transferring data. */ + /* BIOS default is 1875ns */ } Config; /* * Add here your configuration... */ -static const Config configs[] = { - { 15, 6, 0x350 }, /* defaults for single adapter */ - { 11, 5, 0x320 }, /* defaults for second adapter */ - { 7, 6, 0x350 }, /* My configuration (Zaga) */ - { -1, -1, 0x0 } /* Empty slot */ +static Config configs[] = +{ + { 15, 6, 0x350, BUS_ON, BUS_OFF }, /* defaults for single adapter */ + { 11, 5, 0x320, BUS_ON, BUS_OFF }, /* defaults for second adapter */ + { 7, 6, 0x350, BUS_ON, BUS_OFF }, /* My configuration (Zaga) */ + { -1, -1, 0x0, BUS_ON, BUS_OFF } /* Empty slot */ }; #define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) @@ -267,13 +305,14 @@ static const Config configs[] = { * added for the Future Domain version. */ typedef struct signature { - const void *sig; /* String to look for */ - unsigned ofs; /* offset from BIOS base address */ - unsigned len; /* length of string */ + const char *sig; /* String to look for */ + unsigned long ofs; /* offset from BIOS base address */ + unsigned len; /* length of string */ } Signature; -static const Signature signatures[] = { - { "SSTBIOS", 0x0000d, 7 } /* "SSTBIOS" @ offset 0x0000d */ +static const Signature signatures[] = +{ + {"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */ }; #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) @@ -282,22 +321,23 @@ static const Signature signatures[] = { * I/O Port Offsets and Bit Definitions * 4 addresses are used. Those not defined here are reserved. */ -#define ASC_STAT 0 /* Status, Read */ -#define ASC_COMMAND 0 /* Command, Write */ +#define ASC_STAT 0 /* Status, Read */ +#define ASC_COMMAND 0 /* Command, Write */ #define ASC_INTR_STAT 1 /* Interrupt Status, Read */ -#define ASC_INTR_ACK 1 /* Acknowledge, Write */ -#define ASC_CONTROL 2 /* Control, Write */ +#define ASC_INTR_ACK 1 /* Acknowledge, Write */ +#define ASC_CONTROL 2 /* Control, Write */ /* * ASC Status Port */ -#define INT_IM 0x80 /* Interrupt Image Flag */ -#define CMD_RDY 0x40 /* Command Port Ready */ -#define CMD_REJ 0x20 /* Command Port Byte Rejected */ -#define ASC_INIT 0x10 /* ASC Initialized Flag */ +#define INT_IM 0x80 /* Interrupt Image Flag */ +#define CMD_RDY 0x40 /* Command Port Ready */ +#define CMD_REJ 0x20 /* Command Port Byte Rejected */ +#define ASC_INIT 0x10 /* ASC Initialized Flag */ #define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */ -/* COMMAND opcodes +/* + * COMMAND opcodes * * Unfortunately, I have no idea how to properly use some of these commands, * as the OEM manual does not make it clear. I have not been able to use @@ -305,39 +345,38 @@ static const Signature signatures[] = { * discernible effect whatsoever. I think they may be related to certain * ICB commands, but again, the OEM manual doesn't make that clear. */ -#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */ -#define INITIALIZATION 1 /* initialization (10 bytes) */ -#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */ -#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */ -#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */ -#define SOFT_RESET 5 /* SCSI bus soft reset */ -#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */ -#define START_OGMB 0x80 /* start command in OGMB (n) */ +#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */ +#define INITIALIZATION 1 /* initialization (10 bytes) */ +#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */ +#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */ +#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */ +#define SOFT_RESET 5 /* SCSI bus soft reset */ +#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */ +#define START_OGMB 0x80 /* start command in OGMB (n) */ #define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */ - /* where (n) = lower 6 bits */ -/* For INITIALIZATION: + /* where (n) = lower 6 bits */ +/* + * For INITIALIZATION: */ typedef struct initCmd { - unchar op; /* command opcode (= 1) */ - unchar ID; /* Adapter's SCSI ID */ - unchar bus_on; /* Bus on time, x 125ns (see below) */ - unchar bus_off; /* Bus off time, "" "" */ - unchar rsvd; /* Reserved */ - unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ - unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ - unchar icmbs; /* Number of incoming MBs, "" "" */ + unchar op; /* command opcode (= 1) */ + unchar ID; /* Adapter's SCSI ID */ + unchar bus_on; /* Bus on time, x 125ns (see below) */ + unchar bus_off; /* Bus off time, "" "" */ + unchar rsvd; /* Reserved */ + unchar mailboxes[3]; /* Address of Mailboxes, MSB first */ + unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */ + unchar icmbs; /* Number of incoming MBs, "" "" */ } InitCmd; -#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */ -#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */ - -/* Interrupt Status Port - also returns diagnostic codes at ASC reset +/* + * Interrupt Status Port - also returns diagnostic codes at ASC reset * * if msb is zero, the lower bits are diagnostic status * Diagnostics: - * 01 No diagnostic error occurred - * 02 RAM failure - * 03 FIFO R/W failed + * 01 No diagnostic error occurred + * 02 RAM failure + * 03 FIFO R/W failed * 04 SBIC register read/write failed * 05 Initialization D-FF failed * 06 Host IRQ D-FF failed @@ -346,19 +385,20 @@ typedef struct initCmd { * 10NNNNNN outgoing mailbox NNNNNN is free * 11NNNNNN incoming mailbox NNNNNN needs service */ -#define MB_INTR 0xC0 /* Mailbox Service possible/required */ -#define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ -#define MB_MASK 0x3f /* mask for mailbox number */ +#define MB_INTR 0xC0 /* Mailbox Service possible/required */ +#define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */ +#define MB_MASK 0x3f /* mask for mailbox number */ -/* CONTROL port bits +/* + * CONTROL port bits */ -#define INT_EN 0x08 /* Interrupt Enable */ -#define DMA_EN 0x04 /* DMA Enable */ -#define SCSI_RES 0x02 /* SCSI Reset */ -#define ASC_RES 0x01 /* ASC Reset */ +#define INT_EN 0x08 /* Interrupt Enable */ +#define DMA_EN 0x04 /* DMA Enable */ +#define SCSI_RES 0x02 /* SCSI Reset */ +#define ASC_RES 0x01 /* ASC Reset */ /* - * Driver data structures: + * Driver data structures: * - mb and scbs are required for interfacing with the host adapter. * An SCB has extra fields not visible to the adapter; mb's * _cannot_ do this, since the adapter assumes they are contiguous in @@ -387,28 +427,28 @@ typedef struct initCmd { */ typedef struct sgb { unchar len[3]; - unchar ptr[3]; /* Also SCSI-style - MSB first */ + unchar ptr[3]; /* Also SCSI-style - MSB first */ } Sgb; -typedef struct scb { /* Command Control Block 5.4.1 */ - unchar op; /* Command Control Block Operation Code */ - unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ - /* Outbound data transfer, length is checked*/ - /* Inbound data transfer, length is checked */ - /* Logical Unit Number */ - unchar cdb[12]; /* SCSI Command Block */ - volatile unchar status; /* SCSI Return Status */ - volatile unchar vue; /* Vendor Unique Error Code */ - unchar maxlen[3]; /* Maximum Data Transfer Length */ - unchar dataptr[3]; /* SCSI Data Block Pointer */ - unchar linkptr[3]; /* Next Command Link Pointer */ - unchar direc; /* Transfer Direction */ - unchar reserved2[6]; /* SCSI Command Descriptor Block */ - /* end of hardware SCB */ - Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ - Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ - Adapter *host; /* host adapter */ - struct scb *next; /* for lists of scbs */ +typedef struct scb { /* Command Control Block 5.4.1 */ + unchar op; /* Command Control Block Operation Code */ + unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ + /* Outbound data transfer, length is checked */ + /* Inbound data transfer, length is checked */ + /* Logical Unit Number */ + unchar cdb[12]; /* SCSI Command Block */ + volatile unchar status; /* SCSI Return Status */ + volatile unchar vue; /* Vendor Unique Error Code */ + unchar maxlen[3]; /* Maximum Data Transfer Length */ + unchar dataptr[3]; /* SCSI Data Block Pointer */ + unchar linkptr[3]; /* Next Command Link Pointer */ + unchar direc; /* Transfer Direction */ + unchar reserved2[6]; /* SCSI Command Descriptor Block */ + /* end of hardware SCB */ + Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */ + Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */ + Adapter *host; /* host adapter */ + struct scb *next; /* for lists of scbs */ } Scb; /* @@ -422,110 +462,110 @@ typedef struct scb { /* Command Control Block 5.4.1 */ * (notably, get/set unsolicited interrupt status) in my copy of the OEM * manual, and others are ambiguous/hard to follow. */ -#define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */ -#define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */ -#define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */ -#define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */ -#define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */ -#define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */ -#define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */ - /* 0x87 is reserved */ -#define ICB_OP_READ_INIT 0x88 /* read initialization bytes */ -#define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */ -#define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */ -#define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */ -#define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */ -#define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */ -#define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */ -#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ +#define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */ +#define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */ +#define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */ +#define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */ +#define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */ +#define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */ +#define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */ + /* 0x87 is reserved */ +#define ICB_OP_READ_INIT 0x88 /* read initialization bytes */ +#define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */ +#define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */ +#define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */ +#define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */ +#define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */ +#define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */ +#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */ typedef struct icbRecvCmd { - unchar op; - unchar IDlun; /* Initiator SCSI ID/lun */ - unchar len[3]; /* command buffer length */ - unchar ptr[3]; /* command buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + unchar IDlun; /* Initiator SCSI ID/lun */ + unchar len[3]; /* command buffer length */ + unchar ptr[3]; /* command buffer address */ + unchar rsvd[7]; /* reserved */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbRecvCmd; typedef struct icbSendStat { - unchar op; - unchar IDlun; /* Target SCSI ID/lun */ - unchar stat; /* (outgoing) completion status byte 1 */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + unchar IDlun; /* Target SCSI ID/lun */ + unchar stat; /* (outgoing) completion status byte 1 */ + unchar rsvd[12]; /* reserved */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbSendStat; typedef struct icbRevLvl { - unchar op; - volatile unchar primary; /* primary revision level (returned) */ - volatile unchar secondary; /* secondary revision level (returned) */ - unchar rsvd[12]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + volatile unchar primary; /* primary revision level (returned) */ + volatile unchar secondary; /* secondary revision level (returned) */ + unchar rsvd[12]; /* reserved */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbRevLvl; -typedef struct icbUnsMask { /* I'm totally guessing here */ - unchar op; - volatile unchar mask[14]; /* mask bits */ -#if 0 - unchar rsvd[12]; /* reserved */ +typedef struct icbUnsMask { /* I'm totally guessing here */ + unchar op; + volatile unchar mask[14]; /* mask bits */ +#ifdef 0 + unchar rsvd[12]; /* reserved */ #endif - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbUnsMask; typedef struct icbDiag { - unchar op; - unchar type; /* diagnostics type code (0-3) */ - unchar len[3]; /* buffer length */ - unchar ptr[3]; /* buffer address */ - unchar rsvd[7]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + unchar type; /* diagnostics type code (0-3) */ + unchar len[3]; /* buffer length */ + unchar ptr[3]; /* buffer address */ + unchar rsvd[7]; /* reserved */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbDiag; -#define ICB_DIAG_POWERUP 0 /* Power-up diags only */ -#define ICB_DIAG_WALKING 1 /* walking 1's pattern */ -#define ICB_DIAG_DMA 2 /* DMA - system memory diags */ -#define ICB_DIAG_FULL 3 /* do both 1 & 2 */ +#define ICB_DIAG_POWERUP 0 /* Power-up diags only */ +#define ICB_DIAG_WALKING 1 /* walking 1's pattern */ +#define ICB_DIAG_DMA 2 /* DMA - system memory diags */ +#define ICB_DIAG_FULL 3 /* do both 1 & 2 */ typedef struct icbParms { - unchar op; - unchar rsvd1; /* reserved */ - unchar len[3]; /* parms buffer length */ - unchar ptr[3]; /* parms buffer address */ - unchar idx[2]; /* index (MSB-LSB) */ - unchar rsvd2[5]; /* reserved */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + unchar rsvd1; /* reserved */ + unchar len[3]; /* parms buffer length */ + unchar ptr[3]; /* parms buffer address */ + unchar idx[2]; /* index (MSB-LSB) */ + unchar rsvd2[5]; /* reserved */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbParms; typedef struct icbAny { - unchar op; - unchar data[14]; /* format-specific data */ - volatile unchar vue; /* vendor-unique error code */ - volatile unchar status; /* returned (icmb) status */ - volatile unchar phase; /* used by interrupt handler */ + unchar op; + unchar data[14]; /* format-specific data */ + volatile unchar vue; /* vendor-unique error code */ + volatile unchar status; /* returned (icmb) status */ + volatile unchar phase; /* used by interrupt handler */ } IcbAny; typedef union icb { - unchar op; /* ICB opcode */ - IcbRecvCmd recv_cmd; /* format for receive command */ - IcbSendStat send_stat; /* format for send status */ - IcbRevLvl rev_lvl; /* format for get revision level */ - IcbDiag diag; /* format for execute diagnostics */ - IcbParms eparms; /* format for get/set exec parms */ - IcbAny icb; /* generic format */ - unchar data[18]; + unchar op; /* ICB opcode */ + IcbRecvCmd recv_cmd; /* format for receive command */ + IcbSendStat send_stat; /* format for send status */ + IcbRevLvl rev_lvl; /* format for get revision level */ + IcbDiag diag; /* format for execute diagnostics */ + IcbParms eparms; /* format for get/set exec parms */ + IcbAny icb; /* generic format */ + unchar data[18]; } Icb; @@ -536,27 +576,34 @@ typedef union icb { * structure is not part of the Adapter structure. */ static Scb scbs[MAX_SCBS]; -static Scb *scbfree = NULL; /* free list */ -static int freescbs = MAX_SCBS; /* free list counter */ - -/* - * - */ -static short wd7000_setupIRQ[NUM_CONFIGS]; -static short wd7000_setupDMA[NUM_CONFIGS]; -static short wd7000_setupIO[NUM_CONFIGS]; -static short wd7000_card_num = 0; +static Scb *scbfree = NULL; /* free list */ +static int freescbs = MAX_SCBS; /* free list counter */ /* * END of data/declarations - code follows. */ +static void setup_error (char *mesg, int *ints) +{ + if (ints[0] == 3) + printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> %s\n", + ints[1], ints[2], ints[3], mesg); + else if (ints[0] == 4) + printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d\" -> %s\n", + ints[1], ints[2], ints[3], ints[4], mesg); + else + printk ("wd7000_setup: \"wd7000=%d,%d,0x%x,%d,%d\" -> %s\n", + ints[1], ints[2], ints[3], ints[4], ints[5], mesg); +} /* * Note: You can now set these options from the kernel's "command line". * The syntax is: * - * wd7000=IRQ,DMA,IO + * wd7000=<IRQ>,<DMA>,<IO>[,<BUS_ON>[,<BUS_OFF>]] + * + * , where BUS_ON and BUS_OFF are in nanoseconds. BIOS default values + * are 8000ns for BUS_ON and 1875ns for BUS_OFF. * eg: * wd7000=7,6,0x350 * @@ -565,82 +612,99 @@ static short wd7000_card_num = 0; */ void wd7000_setup (char *str, int *ints) { + static short wd7000_card_num = 0; short i, j; if (wd7000_card_num >= NUM_CONFIGS) { - printk ("wd7000_setup: Too many \"wd7000=\" configurations in " - "command line!\n"); - - return; + printk ("wd7000_setup: Too many \"wd7000=\" configurations in " + "command line!\n"); + return; } - if (ints[0] != 3) + if ((ints[0] < 3) || (ints[0] > 5)) printk ("wd7000_setup: Error in command line! " - "Usage: wd7000=IRQ,DMA,IO\n"); + "Usage: wd7000=<IRQ>,<DMA>,IO>[,<BUS_ON>[,<BUS_OFF>]]\n"); else { for (i = 0; i < NUM_IRQS; i++) if (ints[1] == wd7000_irq[i]) break; if (i == NUM_IRQS) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "invalid IRQ.\n", ints[1], ints[2], ints[3]); + setup_error ("invalid IRQ.", ints); return; } else - wd7000_setupIRQ[wd7000_card_num] = ints[1]; + configs[wd7000_card_num].irq = ints[1]; for (i = 0; i < NUM_DMAS; i++) if (ints[2] == wd7000_dma[i]) break; if (i == NUM_DMAS) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "invalid DMA channel.\n", ints[1], ints[2], ints[3]); + setup_error ("invalid DMA channel.", ints); return; } else - wd7000_setupDMA[wd7000_card_num] = ints[2]; + configs[wd7000_card_num].dma = ints[2]; for (i = 0; i < NUM_IOPORTS; i++) if (ints[3] == wd7000_iobase[i]) break; if (i == NUM_IOPORTS) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "invalid I/O base address.\n", ints[1], ints[2], ints[3]); + setup_error ("invalid I/O base address.", ints); return; } else - wd7000_setupIO[wd7000_card_num] = ints[3]; + configs[wd7000_card_num].iobase = ints[3]; + + if (ints[0] > 3) { + if ((ints[4] < 500) || (ints[4] > 31875)) { + setup_error ("BUS_ON value is out of range (500 to 31875 nanoseconds)!", + ints); + configs[wd7000_card_num].bus_on = BUS_ON; + } + else + configs[wd7000_card_num].bus_on = ints[4] / 125.0; + } + else + configs[wd7000_card_num].bus_on = BUS_ON; + + if (ints[0] > 4) { + if ((ints[5] < 500) || (ints[5] > 31875)) { + setup_error ("BUS_OFF value is out of range (500 to 31875 nanoseconds)!", + ints); + configs[wd7000_card_num].bus_off = BUS_OFF; + } + else + configs[wd7000_card_num].bus_off = ints[5] / 125.0; + } + else + configs[wd7000_card_num].bus_off = BUS_OFF; if (wd7000_card_num) for (i = 0; i < (wd7000_card_num - 1); i++) - for (j = i + 1; j < wd7000_card_num; j++) - if (wd7000_setupIRQ[i] == wd7000_setupIRQ[j]) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "duplicated IRQ!\n", - ints[1], ints[2], ints[3]); - return; - } - else if (wd7000_setupDMA[i] == wd7000_setupDMA[j]) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "duplicated DMA channel!\n", - ints[1], ints[2], ints[3]); - return; - } - else if (wd7000_setupIO[i] == wd7000_setupIO[j]) { - printk ("wd7000_setup: \"wd7000=%d,%d,0x%x\" -> " - "duplicated I/O base address!\n", - ints[1], ints[2], ints[3]); - return; - } - -#ifdef DEBUG - printk ("wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x\n", - wd7000_setupIRQ[wd7000_card_num], - wd7000_setupDMA[wd7000_card_num], - wd7000_setupIO[wd7000_card_num]); + for (j = i + 1; j < wd7000_card_num; j++) + if (configs[i].irq == configs[j].irq) { + setup_error ("duplicated IRQ!", ints); + return; + } + else if (configs[i].dma == configs[j].dma) { + setup_error ("duplicated DMA channel!", ints); + return; + } + else if (configs[i].iobase == configs[j].iobase) { + setup_error ("duplicated I/O base address!", ints); + return; + } + +#ifdef WD7000_DEBUG + printk ("wd7000_setup: IRQ=%d, DMA=%d, I/O=0x%x, BUS_ON=%dns, BUS_OFF=%dns\n", + configs[wd7000_card_num].irq, + configs[wd7000_card_num].dma, + configs[wd7000_card_num].iobase, + configs[wd7000_card_num].bus_on * 125, + configs[wd7000_card_num].bus_off * 125); #endif wd7000_card_num++; @@ -650,21 +714,20 @@ void wd7000_setup (char *str, int *ints) #ifdef ANY2SCSI_INLINE /* - Since they're used a lot, I've redone the following from the macros - formerly in wd7000.h, hopefully to speed them up by getting rid of - all the shifting (it may not matter; GCC might have done as well anyway). - - xany2scsi and xscsi2int were not being used, and are no longer defined. - (They were simply 4-byte versions of these routines). -*/ - -typedef union { /* let's cheat... */ - int i; - unchar u[sizeof(int)]; /* the sizeof(int) makes it more portable */ + * Since they're used a lot, I've redone the following from the macros + * formerly in wd7000.h, hopefully to speed them up by getting rid of + * all the shifting (it may not matter; GCC might have done as well anyway). + * + * xany2scsi and xscsi2int were not being used, and are no longer defined. + * (They were simply 4-byte versions of these routines). + */ +typedef union { /* let's cheat... */ + int i; + unchar u[sizeof (int)]; /* the sizeof(int) makes it more portable */ } i_u; -static inline void any2scsi( unchar *scsi, int any ) +static inline void any2scsi (unchar * scsi, int any) { *scsi++ = ((i_u) any).u[2]; *scsi++ = ((i_u) any).u[1]; @@ -672,49 +735,50 @@ static inline void any2scsi( unchar *scsi, int any ) } -static inline int scsi2int( unchar *scsi ) +static inline int scsi2int (unchar * scsi) { i_u result; - result.i = 0; /* clears unused bytes */ - *(result.u+2) = *scsi++; - *(result.u+1) = *scsi++; - *(result.u) = *scsi++; - return result.i; + result.i = 0; /* clears unused bytes */ + result.u[2] = *scsi++; + result.u[1] = *scsi++; + result.u[0] = *scsi++; + + return (result.i); } #else /* - These are the old ones - I've just moved them here... -*/ + * These are the old ones - I've just moved them here... + */ #undef any2scsi -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16); \ -(up)[1] = ((unsigned long)(p)) >> 8; \ -(up)[2] = ((unsigned long)(p)); +#define any2scsi(up, p) (up)[0] = (((unsigned long) (p)) >> 16); \ + (up)[1] = ((unsigned long) (p)) >> 8; \ + (up)[2] = ((unsigned long) (p)); #undef scsi2int -#define scsi2int(up) ( (((unsigned long)*(up)) << 16) + \ - (((unsigned long)(up)[1]) << 8) + ((unsigned long)(up)[2]) ) +#define scsi2int(up) ( (((unsigned long) *(up)) << 16) + \ + (((unsigned long) (up)[1]) << 8) + \ + ((unsigned long) (up)[2]) ) #endif - -static inline void wd7000_enable_intr(Adapter *host) + +static inline void wd7000_enable_intr (Adapter *host) { host->control |= INT_EN; - outb(host->control, host->iobase+ASC_CONTROL); + outb (host->control, host->iobase + ASC_CONTROL); } -static inline void wd7000_enable_dma(Adapter *host) +static inline void wd7000_enable_dma (Adapter *host) { host->control |= DMA_EN; - outb(host->control,host->iobase+ASC_CONTROL); - set_dma_mode(host->dma, DMA_MODE_CASCADE); - enable_dma(host->dma); + outb (host->control, host->iobase + ASC_CONTROL); + set_dma_mode (host->dma, DMA_MODE_CASCADE); + enable_dma (host->dma); } -#define WAITnexttimeout 200 /* 2 seconds */ +#define WAITnexttimeout 200 /* 2 seconds */ static inline short WAIT (unsigned port, unsigned mask, unsigned allof, unsigned noneof) { @@ -722,7 +786,7 @@ static inline short WAIT (unsigned port, unsigned mask, unsigned allof, unsigned register unsigned long WAITtimeout = jiffies + WAITnexttimeout; while (jiffies <= WAITtimeout) { - WAITbits = inb (port) & mask; + WAITbits = inb (port) & mask; if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0)) return (0); @@ -732,31 +796,32 @@ static inline short WAIT (unsigned port, unsigned mask, unsigned allof, unsigned } -static inline void delay( unsigned how_long ) +static inline void delay (unsigned how_long) { - register unsigned long time = jiffies + how_long; + register unsigned long time = jiffies + how_long; - while (jiffies < time); + while (jiffies < time); } -static inline int command_out(Adapter *host, unchar *cmd, int len) +static inline int command_out (Adapter * host, unchar * cmd, int len) { - if (! WAIT (host->iobase+ASC_STAT,ASC_STATMASK,CMD_RDY,0)) { - while (len--) { - do { - outb(*cmd, host->iobase+ASC_COMMAND); - WAIT(host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0); - } while (inb(host->iobase+ASC_STAT) & CMD_REJ); + if (!WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { + while (len--) { + do { + outb (*cmd, host->iobase + ASC_COMMAND); + WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0); + } while (inb (host->iobase + ASC_STAT) & CMD_REJ); cmd++; } - return 1; + return (1); } - printk("wd7000 command_out: WAIT failed(%d)\n", len+1); - return 0; + printk ("wd7000 command_out: WAIT failed(%d)\n", len + 1); + + return (0); } @@ -770,7 +835,7 @@ static inline int command_out(Adapter *host, unchar *cmd, int len) * the satisfiability of a request is not dependent on the size of the * request. */ -static inline Scb *alloc_scbs(int needed) +static inline Scb *alloc_scbs (int needed) { register Scb *scb, *p; register unsigned long flags; @@ -779,84 +844,89 @@ static inline Scb *alloc_scbs(int needed) static int busy = 0; int i; - if (needed <= 0) return NULL; /* sanity check */ + if (needed <= 0) + return (NULL); /* sanity check */ - save_flags(flags); - cli(); - while (busy) { /* someone else is allocating */ - sti(); /* Yes this is really needed here */ - now = jiffies; while (jiffies == now) /* wait a jiffy */; - cli(); + save_flags (flags); + cli (); + while (busy) { /* someone else is allocating */ + sti (); /* Yes this is really needed here */ + for (now = jiffies; now == jiffies; ); /* wait a jiffy */ + cli (); } - busy = 1; /* not busy now; it's our turn */ + busy = 1; /* not busy now; it's our turn */ - while (freescbs < needed) { + while (freescbs < needed) { timeout = jiffies + WAITnexttimeout; do { - sti(); /* Yes this is really needed here */ - now = jiffies; - while (jiffies == now); /* wait a jiffy */ - cli(); - } while (freescbs < needed && jiffies <= timeout); + sti (); /* Yes this is really needed here */ + for (now = jiffies; now == jiffies; ); /* wait a jiffy */ + cli (); + } while (freescbs < needed && jiffies <= timeout); /* * If we get here with enough free Scbs, we can take them. * Otherwise, we timed out and didn't get enough. */ - if (freescbs < needed) { + if (freescbs < needed) { busy = 0; - panic("wd7000: can't get enough free SCBs.\n"); - restore_flags(flags); - return NULL; + panic ("wd7000: can't get enough free SCBs.\n"); + restore_flags (flags); + return (NULL); } } - scb = scbfree; freescbs -= needed; - for (i = 0; i < needed; i++) { p = scbfree; scbfree = p->next; } + scb = scbfree; + freescbs -= needed; + for (i = 0; i < needed; i++) { + p = scbfree; + scbfree = p->next; + } p->next = NULL; - - busy = 0; /* we're done */ + busy = 0; /* we're done */ - restore_flags(flags); + restore_flags (flags); - return scb; + return (scb); } -static inline void free_scb( Scb *scb ) +static inline void free_scb (Scb *scb) { register unsigned long flags; - save_flags(flags); - cli(); + save_flags (flags); + cli (); - memset(scb, 0, sizeof(Scb)); - scb->next = scbfree; scbfree = scb; + memset (scb, 0, sizeof (Scb)); + scb->next = scbfree; + scbfree = scb; freescbs++; - restore_flags(flags); + restore_flags (flags); } -static inline void init_scbs(void) +static inline void init_scbs (void) { int i; unsigned long flags; - save_flags(flags); - cli(); + save_flags (flags); + cli (); scbfree = &(scbs[0]); - memset(scbs, 0, sizeof(scbs)); - for (i = 0; i < MAX_SCBS-1; i++) { - scbs[i].next = &(scbs[i+1]); scbs[i].SCpnt = NULL; + memset (scbs, 0, sizeof (scbs)); + for (i = 0; i < MAX_SCBS - 1; i++) { + scbs[i].next = &(scbs[i + 1]); + scbs[i].SCpnt = NULL; } - scbs[MAX_SCBS-1].next = NULL; - scbs[MAX_SCBS-1].SCpnt = NULL; + scbs[MAX_SCBS - 1].next = NULL; + scbs[MAX_SCBS - 1].SCpnt = NULL; + + restore_flags (flags); +} - restore_flags(flags); -} - -static int mail_out( Adapter *host, Scb *scbptr ) +static int mail_out (Adapter *host, Scb *scbptr) /* * Note: this can also be used for ICBs; just cast to the parm type. */ @@ -866,30 +936,35 @@ static int mail_out( Adapter *host, Scb *scbptr ) unchar start_ogmb; Mailbox *ogmbs = host->mb.ogmb; int *next_ogmb = &(host->next_ogmb); -#ifdef DEBUG - printk("wd7000 mail_out: 0x%06lx",(long) scbptr); + +#ifdef WD7000_DEBUG + printk ("wd7000_mail_out: 0x%06lx", (long) scbptr); #endif + /* We first look for a free outgoing mailbox */ - save_flags(flags); - cli(); + save_flags (flags); + cli (); ogmb = *next_ogmb; for (i = 0; i < OGMB_CNT; i++) { - if (ogmbs[ogmb].status == 0) { -#ifdef DEBUG - printk(" using OGMB 0x%x",ogmb); + if (ogmbs[ogmb].status == 0) { +#ifdef WD7000_DEBUG + printk (" using OGMB 0x%x", ogmb); #endif ogmbs[ogmb].status = 1; - any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); + any2scsi ((unchar *) ogmbs[ogmb].scbptr, (int) scbptr); - *next_ogmb = (ogmb+1) % OGMB_CNT; + *next_ogmb = (ogmb + 1) % OGMB_CNT; break; - } else + } + else ogmb = (++ogmb) % OGMB_CNT; } - restore_flags(flags); -#ifdef DEBUG - printk(", scb is 0x%06lx",(long) scbptr); + restore_flags (flags); + +#ifdef WD7000_DEBUG + printk (", scb is 0x%06lx", (long) scbptr); #endif + if (i >= OGMB_CNT) { /* * Alternatively, we might issue the "interrupt on free OGMB", @@ -899,171 +974,182 @@ static int mail_out( Adapter *host, Scb *scbptr ) * that marks OGMB's free, waiting even with interrupts off * should work, since they are freed very quickly in most cases. */ - #ifdef DEBUG - printk(", no free OGMBs.\n"); +#ifdef WD7000_DEBUG + printk (", no free OGMBs.\n"); #endif - return 0; + return (0); } - wd7000_enable_intr(host); + wd7000_enable_intr (host); start_ogmb = START_OGMB | ogmb; - command_out( host, &start_ogmb, 1 ); -#ifdef DEBUG - printk(", awaiting interrupt.\n"); + command_out (host, &start_ogmb, 1); + +#ifdef WD7000_DEBUG + printk (", awaiting interrupt.\n"); #endif - return 1; + + return (1); } -int make_code(unsigned hosterr, unsigned scsierr) -{ -#ifdef DEBUG +int make_code (unsigned hosterr, unsigned scsierr) +{ +#ifdef WD7000_DEBUG int in_error = hosterr; #endif - switch ((hosterr>>8)&0xff){ - case 0: /* Reserved */ - hosterr = DID_ERROR; - break; - case 1: /* Command Complete, no errors */ - hosterr = DID_OK; - break; - case 2: /* Command complete, error logged in scb status (scsierr) */ - hosterr = DID_OK; - break; - case 4: /* Command failed to complete - timeout */ - hosterr = DID_TIME_OUT; - break; - case 5: /* Command terminated; Bus reset by external device */ - hosterr = DID_RESET; - break; - case 6: /* Unexpected Command Received w/ host as target */ - hosterr = DID_BAD_TARGET; - break; + switch ((hosterr >> 8) & 0xff) { + case 0: /* Reserved */ + hosterr = DID_ERROR; + break; + case 1: /* Command Complete, no errors */ + hosterr = DID_OK; + break; + case 2: /* Command complete, error logged in scb status (scsierr) */ + hosterr = DID_OK; + break; + case 4: /* Command failed to complete - timeout */ + hosterr = DID_TIME_OUT; + break; + case 5: /* Command terminated; Bus reset by external device */ + hosterr = DID_RESET; + break; + case 6: /* Unexpected Command Received w/ host as target */ + hosterr = DID_BAD_TARGET; + break; case 80: /* Unexpected Reselection */ case 81: /* Unexpected Selection */ - hosterr = DID_BAD_INTR; - break; + hosterr = DID_BAD_INTR; + break; case 82: /* Abort Command Message */ - hosterr = DID_ABORT; - break; + hosterr = DID_ABORT; + break; case 83: /* SCSI Bus Software Reset */ case 84: /* SCSI Bus Hardware Reset */ - hosterr = DID_RESET; - break; + hosterr = DID_RESET; + break; default: /* Reserved */ - hosterr = DID_ERROR; - break; - } -#ifdef DEBUG - if (scsierr||hosterr) - printk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", - scsierr,in_error,hosterr); + hosterr = DID_ERROR; + } +#ifdef WD7000_DEBUG + if (scsierr || hosterr) + printk ("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n", + scsierr, in_error, hosterr); #endif - return scsierr | (hosterr << 16); + return (scsierr | (hosterr << 16)); } -static void wd7000_scsi_done(Scsi_Cmnd * SCpnt) +static void wd7000_scsi_done (Scsi_Cmnd *SCpnt) { -#ifdef DEBUG +#ifdef WD7000_DEBUG printk ("wd7000_scsi_done: 0x%06lx\n", (long) SCpnt); #endif + SCpnt->SCp.phase = 0; } -#define wd7000_intr_ack(host) outb(0,host->iobase+ASC_INTR_ACK) +#define wd7000_intr_ack(host) outb (0, host->iobase + ASC_INTR_ACK) -void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs * regs) +void wd7000_intr_handle (int irq, void *dev_id, struct pt_regs *regs) { register int flag, icmb, errstatus, icmb_status; register int host_error, scsi_error; - register Scb *scb; /* for SCSI commands */ - register IcbAny *icb; /* for host commands */ + register Scb *scb; /* for SCSI commands */ + register IcbAny *icb; /* for host commands */ register Scsi_Cmnd *SCpnt; - Adapter *host = irq2host[irq]; /* This MUST be set!!! */ + Adapter *host = (Adapter *) wd7000_host[irq - IRQ_MIN]->hostdata; /* This MUST be set!!! */ Mailbox *icmbs = host->mb.icmb; -#ifdef DEBUG - printk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host); + host->int_counter++; + +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host); #endif - flag = inb(host->iobase+ASC_INTR_STAT); -#ifdef DEBUG - printk("wd7000_intr_handle: intr stat = 0x%02x\n",flag); + flag = inb (host->iobase + ASC_INTR_STAT); + +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: intr stat = 0x%02x\n", flag); #endif - if (!(inb(host->iobase+ASC_STAT) & INT_IM)) { + if (!(inb (host->iobase + ASC_STAT) & INT_IM)) { /* NB: these are _very_ possible if IRQ 15 is being used, since - it's the "garbage collector" on the 2nd 8259 PIC. Specifically, - any interrupt signal into the 8259 which can't be identified - comes out as 7 from the 8259, which is 15 to the host. Thus, it - is a good thing the WD7000 has an interrupt status port, so we - can sort these out. Otherwise, electrical noise and other such - problems would be indistinguishable from valid interrupts... - */ -#ifdef DEBUG - printk("wd7000_intr_handle: phantom interrupt...\n"); + * it's the "garbage collector" on the 2nd 8259 PIC. Specifically, + * any interrupt signal into the 8259 which can't be identified + * comes out as 7 from the 8259, which is 15 to the host. Thus, it + * is a good thing the WD7000 has an interrupt status port, so we + * can sort these out. Otherwise, electrical noise and other such + * problems would be indistinguishable from valid interrupts... + */ +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: phantom interrupt...\n"); #endif - wd7000_intr_ack(host); - return; + wd7000_intr_ack (host); + return; } - if (flag & MB_INTR) { + if (flag & MB_INTR) { /* The interrupt is for a mailbox */ if (!(flag & IMB_INTR)) { -#ifdef DEBUG - printk("wd7000_intr_handle: free outgoing mailbox\n"); +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: free outgoing mailbox\n"); #endif /* * If sleep_on() and the "interrupt on free OGMB" command are * used in mail_out(), wake_up() should correspondingly be called * here. For now, we don't need to do anything special. */ - wd7000_intr_ack(host); + wd7000_intr_ack (host); return; - } else { + } + else { /* The interrupt is for an incoming mailbox */ icmb = flag & MB_MASK; icmb_status = icmbs[icmb].status; - if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ -#ifdef DEBUG - printk("wd7000_intr_handle: unsolicited interrupt 0x%02xh\n", - icmb_status); + if (icmb_status & 0x80) { /* unsolicited - result in ICMB */ +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: unsolicited interrupt 0x%02x\n", + icmb_status); #endif - wd7000_intr_ack(host); + wd7000_intr_ack (host); return; } - scb = (struct scb *) scsi2int((unchar *)icmbs[icmb].scbptr); + /* Aaaargh! (Zaga) */ + scb = (struct scb *) (scsi2int ((unchar *) icmbs[icmb].scbptr) | PAGE_OFFSET); icmbs[icmb].status = 0; - if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */ + if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */ SCpnt = scb->SCpnt; - if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ + if (--(SCpnt->SCp.phase) <= 0) { /* all scbs are done */ host_error = scb->vue | (icmb_status << 8); scsi_error = scb->status; - errstatus = make_code(host_error,scsi_error); + errstatus = make_code (host_error, scsi_error); SCpnt->result = errstatus; - free_scb(scb); + free_scb (scb); - SCpnt->scsi_done(SCpnt); + SCpnt->scsi_done (SCpnt); } - } else { /* an ICB is done */ + } + else { /* an ICB is done */ icb = (IcbAny *) scb; icb->status = icmb_status; - icb->phase = 0; + icb->phase = 0; } - } /* incoming mailbox */ + } /* incoming mailbox */ } - wd7000_intr_ack(host); - return; + wd7000_intr_ack (host); + +#ifdef WD7000_DEBUG + printk ("wd7000_intr_handle: return from interrupt handler\n"); +#endif } -int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +int wd7000_queuecommand (Scsi_Cmnd *SCpnt, void (*done) (Scsi_Cmnd *)) { register Scb *scb; register Sgb *sgb; @@ -1076,94 +1162,105 @@ int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); SCpnt->scsi_done = done; SCpnt->SCp.phase = 1; - scb = alloc_scbs(1); + scb = alloc_scbs (1); scb->idlun = idlun; - memcpy(scb->cdb, cdb, cdblen); + memcpy (scb->cdb, cdb, cdblen); scb->direc = 0x40; /* Disable direction check */ - scb->SCpnt = SCpnt; /* so we can find stuff later */ + scb->SCpnt = SCpnt; /* so we can find stuff later */ SCpnt->host_scribble = (unchar *) scb; scb->host = host; - if (SCpnt->use_sg) { + if (SCpnt->use_sg) { struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; unsigned i; - if (SCpnt->host->sg_tablesize == SG_NONE) { - panic("wd7000_queuecommand: scatter/gather not supported.\n"); + if (SCpnt->host->sg_tablesize == SG_NONE) { + panic ("wd7000_queuecommand: scatter/gather not supported.\n"); } -#ifdef DEBUG - printk("Using scatter/gather with %d elements.\n",SCpnt->use_sg); +#ifdef WD7000_DEBUG + printk ("Using scatter/gather with %d elements.\n", SCpnt->use_sg); #endif sgb = scb->sgb; - scb->op = 1; - any2scsi(scb->dataptr, (int) sgb); - any2scsi(scb->maxlen, SCpnt->use_sg * sizeof (Sgb) ); + scb->op = 1; + any2scsi (scb->dataptr, (int) sgb); + any2scsi (scb->maxlen, SCpnt->use_sg * sizeof (Sgb)); - for (i = 0; i < SCpnt->use_sg; i++) { - any2scsi(sgb[i].ptr, (int) sg[i].address); - any2scsi(sgb[i].len, sg[i].length); + for (i = 0; i < SCpnt->use_sg; i++) { + any2scsi (sgb[i].ptr, (int) sg[i].address); + any2scsi (sgb[i].len, sg[i].length); } - } else { + } + else { scb->op = 0; - any2scsi(scb->dataptr, (int) SCpnt->request_buffer); - any2scsi(scb->maxlen, SCpnt->request_bufflen); + any2scsi (scb->dataptr, (int) SCpnt->request_buffer); + any2scsi (scb->maxlen, SCpnt->request_bufflen); } - while (!mail_out(host, scb)) /* keep trying */; - return 1; + while (!mail_out (host, scb)); /* keep trying */ + + return (1); } -int wd7000_command(Scsi_Cmnd *SCpnt) +int wd7000_command (Scsi_Cmnd *SCpnt) { - wd7000_queuecommand(SCpnt, wd7000_scsi_done); + wd7000_queuecommand (SCpnt, wd7000_scsi_done); - while (SCpnt->SCp.phase > 0) barrier(); /* phase counts scbs down to 0 */ + while (SCpnt->SCp.phase > 0) + barrier (); /* phase counts scbs down to 0 */ - return SCpnt->result; + return (SCpnt->result); } -int wd7000_diagnostics( Adapter *host, int code ) +int wd7000_diagnostics (Adapter *host, int code) { static IcbDiag icb = {ICB_OP_DIAGNOSTICS}; static unchar buf[256]; unsigned long timeout; icb.type = code; - any2scsi(icb.len, sizeof(buf)); - any2scsi(icb.ptr, (int) &buf); + any2scsi (icb.len, sizeof (buf)); + any2scsi (icb.ptr, (int) &buf); icb.phase = 1; /* * This routine is only called at init, so there should be OGMBs * available. I'm assuming so here. If this is going to * fail, I can just let the timeout catch the failure. */ - mail_out(host, (struct scb *) &icb); - timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ + mail_out (host, (struct scb *) &icb); + timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */ while (icb.phase && jiffies < timeout) - barrier(); /* wait for completion */ + barrier (); /* wait for completion */ - if (icb.phase) { - printk("wd7000_diagnostics: timed out.\n"); - return 0; + if (icb.phase) { + printk ("wd7000_diagnostics: timed out.\n"); + return (0); } - if (make_code(icb.vue|(icb.status << 8),0)) { - printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", - icb.vue, icb.status); - return 0; + if (make_code (icb.vue | (icb.status << 8), 0)) { + printk ("wd7000_diagnostics: failed (0x%02x,0x%02x)\n", + icb.vue, icb.status); + return (0); } - return 1; + return (1); } -int wd7000_init( Adapter *host ) +int wd7000_init (Adapter *host) { - InitCmd init_cmd = { - INITIALIZATION, 7, BUS_ON, BUS_OFF, 0, {0,0,0}, OGMB_CNT, ICMB_CNT + InitCmd init_cmd = + { + INITIALIZATION, + 7, + host->bus_on, + host->bus_off, + 0, + { 0, 0, 0 }, + OGMB_CNT, + ICMB_CNT }; int diag; @@ -1171,84 +1268,78 @@ int wd7000_init( Adapter *host ) * Reset the adapter - only. The SCSI bus was initialized at power-up, * and we need to do this just so we control the mailboxes, etc. */ - outb(ASC_RES, host->iobase+ASC_CONTROL); - delay(1); /* reset pulse: this is 10ms, only need 25us */ - outb(0,host->iobase+ASC_CONTROL); - host->control = 0; /* this must always shadow ASC_CONTROL */ - - if (WAIT (host->iobase+ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { - printk ("wd7000_init: WAIT timed out.\n"); - return 0; /* 0 = not ok */ + outb (ASC_RES, host->iobase + ASC_CONTROL); + delay (1); /* reset pulse: this is 10ms, only need 25us */ + outb (0, host->iobase + ASC_CONTROL); + host->control = 0; /* this must always shadow ASC_CONTROL */ + + if (WAIT (host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { + printk ("wd7000_init: WAIT timed out.\n"); + return (0); /* 0 = not ok */ } - if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1) { - printk("wd7000_init: "); - - switch (diag) { - case 2: - printk("RAM failure.\n"); - break; - case 3: - printk("FIFO R/W failed\n"); - break; - case 4: - printk("SBIC register R/W failed\n"); - break; - case 5: - printk("Initialization D-FF failed.\n"); - break; - case 6: - printk("Host IRQ D-FF failed.\n"); - break; - case 7: - printk("ROM checksum error.\n"); - break; - default: - printk("diagnostic code 0x%02Xh received.\n", diag); + if ((diag = inb (host->iobase + ASC_INTR_STAT)) != 1) { + printk ("wd7000_init: "); + + switch (diag) { + case 2: printk ("RAM failure.\n"); + break; + case 3: printk ("FIFO R/W failed\n"); + break; + case 4: printk ("SBIC register R/W failed\n"); + break; + case 5: printk ("Initialization D-FF failed.\n"); + break; + case 6: printk ("Host IRQ D-FF failed.\n"); + break; + case 7: printk ("ROM checksum error.\n"); + break; + default: printk ("diagnostic code 0x%02Xh received.\n", diag); } - return 0; + return (0); } - + /* Clear mailboxes */ - memset(&(host->mb), 0, sizeof(host->mb)); + memset (&(host->mb), 0, sizeof (host->mb)); /* Execute init command */ - any2scsi((unchar *) &(init_cmd.mailboxes), (int) &(host->mb)); - if (!command_out(host, (unchar *) &init_cmd, sizeof(init_cmd))) { - printk("wd7000_init: adapter initialization failed.\n"); - return 0; + any2scsi ((unchar *) & (init_cmd.mailboxes), (int) &(host->mb)); + if (!command_out (host, (unchar *) &init_cmd, sizeof (init_cmd))) { + printk ("wd7000_init: adapter initialization failed.\n"); + return (0); } - if (WAIT (host->iobase+ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) { - printk ("wd7000_init: WAIT timed out.\n"); - return 0; + if (WAIT (host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) { + printk ("wd7000_init: WAIT timed out.\n"); + return (0); } - if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000", NULL)) { - printk("wd7000_init: can't get IRQ %d.\n", host->irq); - return 0; + if (request_irq (host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000", NULL)) { + printk ("wd7000_init: can't get IRQ %d.\n", host->irq); + return (0); } - if (request_dma(host->dma,"wd7000")) { - printk("wd7000_init: can't get DMA channel %d.\n", host->dma); - free_irq(host->irq, NULL); - return 0; + if (request_dma (host->dma, "wd7000")) { + printk ("wd7000_init: can't get DMA channel %d.\n", host->dma); + free_irq (host->irq, NULL); + return (0); } - wd7000_enable_dma(host); - wd7000_enable_intr(host); + wd7000_enable_dma (host); + wd7000_enable_intr (host); - if (!wd7000_diagnostics(host,ICB_DIAG_FULL)) { - free_dma(host->dma); - free_irq(host->irq, NULL); - return 0; + if (!wd7000_diagnostics (host, ICB_DIAG_FULL)) { + free_dma (host->dma); + free_irq (host->irq, NULL); + return (0); } - return 1; + return (1); } -void wd7000_revision(Adapter *host) +void wd7000_revision (Adapter *host) { - static IcbRevLvl icb = {ICB_OP_GET_REVISION}; + static IcbRevLvl icb = + {ICB_OP_GET_REVISION}; icb.phase = 1; /* @@ -1257,14 +1348,160 @@ void wd7000_revision(Adapter *host) * the only damage will be that the revision will show up as 0.0, * which in turn means that scatter/gather will be disabled. */ - mail_out(host, (struct scb *) &icb); + mail_out (host, (struct scb *) &icb); while (icb.phase) - barrier(); /* wait for completion */ + barrier (); /* wait for completion */ host->rev1 = icb.primary; host->rev2 = icb.secondary; } +#undef SPRINTF +#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } + +int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host) +{ + unsigned long flags; + + save_flags (flags); + cli (); + +#ifdef WD7000_DEBUG + printk ("Buffer = <%.*s>, length = %d\n", length, buffer, length); +#endif + + /* + * Currently this is a no-op + */ + printk ("Sorry, this function is currently out of order...\n"); + + restore_flags (flags); + + return (length); +} + + +int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout) +{ + struct Scsi_Host *host = NULL; + Scsi_Device *scd; + Adapter *adapter; + unsigned long flags; + char *pos = buffer; + short i; + +#ifdef WD7000_DEBUG + Mailbox *ogmbs, *icmbs; + short count; +#endif + + /* + * Find the specified host board. + */ + for (i = 0; i < IRQS; i++) + if (wd7000_host[i] && (wd7000_host[i]->host_no == hostno)) { + host = wd7000_host[i]; + + break; + } + + /* + * Host not found! + */ + if (! host) + return (-ESRCH); + + /* + * Has data been written to the file ? + */ + if (inout) + return (wd7000_set_info (buffer, length, host)); + + adapter = (Adapter *) host->hostdata; + + save_flags (flags); + cli (); + + SPRINTF ("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", hostno, adapter->rev1, adapter->rev2); + SPRINTF (" IO base: 0x%x\n", adapter->iobase); + SPRINTF (" IRQ: %d\n", adapter->irq); + SPRINTF (" DMA channel: %d\n", adapter->dma); + SPRINTF (" Interrupts: %d\n", adapter->int_counter); + SPRINTF (" BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125); + SPRINTF (" BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125); + +#ifdef WD7000_DEBUG + ogmbs = adapter->mb.ogmb; + icmbs = adapter->mb.icmb; + + SPRINTF ("\nControl port value: 0x%x\n", adapter->control); + SPRINTF ("Incoming mailbox:\n"); + SPRINTF (" size: %d\n", ICMB_CNT); + SPRINTF (" queued messages: "); + + for (i = count = 0; i < ICMB_CNT; i++) + if (icmbs[i].status) { + count++; + SPRINTF ("0x%x ", i); + } + + SPRINTF (count ? "\n" : "none\n"); + + SPRINTF ("Outgoing mailbox:\n"); + SPRINTF (" size: %d\n", OGMB_CNT); + SPRINTF (" next message: 0x%x\n", adapter->next_ogmb); + SPRINTF (" queued messages: "); + + for (i = count = 0; i < OGMB_CNT; i++) + if (ogmbs[i].status) { + count++; + SPRINTF ("0x%x ", i); + } + + SPRINTF (count ? "\n" : "none\n"); +#endif + + /* + * Display driver information for each device attached to the board. + */ + scd = host->host_queue; + + SPRINTF ("\nAttached devices: %s\n", scd ? "" : "none"); + + for ( ; scd; scd = scd->next) + if (scd->host->host_no == hostno) { + SPRINTF (" [Channel: %02d, Id: %02d, Lun: %02d] ", + scd->channel, scd->id, scd->lun); + SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? + scsi_device_types[(short) scd->type] : "Unknown device"); + + for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) + SPRINTF ("%c", scd->vendor[i]); + SPRINTF (" "); + + for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) + SPRINTF ("%c", scd->model[i]); + SPRINTF ("\n"); + } + + SPRINTF ("\n"); + + restore_flags (flags); + + /* + * Calculate start of next buffer, and return value. + */ + *start = buffer + offset; + + if ((pos - buffer) < offset) + return (0); + else if ((pos - buffer - offset) < length) + return (pos - buffer - offset); + else + return (length); +} + + /* * Returns the number of adapters this driver is supporting. * @@ -1277,84 +1514,102 @@ void wd7000_revision(Adapter *host) */ int wd7000_detect (Scsi_Host_Template *tpnt) { - short present = 0, biosaddr_ptr, cfg_ptr, sig_ptr, i, pass; + short present = 0, biosaddr_ptr, sig_ptr, i, pass; short biosptr[NUM_CONFIGS]; unsigned iobase; Adapter *host = NULL; struct Scsi_Host *sh; - for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1); +#ifdef WD7000_DEBUG + printk ("wd7000_detect: started\n"); +#endif + + for (i = 0; i < IRQS; wd7000_host[i++] = NULL) ; + for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1) ; tpnt->proc_dir = &proc_scsi_wd7000; + tpnt->proc_info = &wd7000_proc_info; /* * Set up SCB free list, which is shared by all adapters */ init_scbs (); - for (pass = 0, cfg_ptr = 0; pass < NUM_CONFIGS; pass++) { - for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++) + for (pass = 0; pass < NUM_CONFIGS; pass++) { + /* + * First, search for BIOS SIGNATURE... + */ + for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++) for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) { - for (i = 0; i < pass; i++) - if (biosptr[i] == biosaddr_ptr) - break; - - if ((i == pass) && - check_signature(wd7000_biosaddr[biosaddr_ptr] + - signatures[sig_ptr].ofs, - signatures[sig_ptr].sig, - signatures[sig_ptr].len)) - goto bios_matched; - } + for (i = 0; i < pass; i++) + if (biosptr[i] == biosaddr_ptr) + break; -bios_matched: + if (i == pass) { +#if (LINUX_VERSION_CODE < 0x020100) +#else + void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] + + signatures[sig_ptr].ofs, + signatures[sig_ptr].len); +#endif + short bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, + signatures[sig_ptr].len); + +#if (LINUX_VERSION_CODE < 0x020100) +#else + iounmap (biosaddr); +#endif -#ifdef DEBUG + if (! bios_match) + goto bios_matched; + } + } + + bios_matched: + /* + * BIOS SIGNATURE has been found. + */ +#ifdef WD7000_DEBUG printk ("wd7000_detect: pass %d\n", pass + 1); - if (biosaddr_ptr == NUM_ADDRS) + if (biosaddr_ptr == NUM_ADDRS) printk ("WD-7000 SST BIOS not detected...\n"); else printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n", - wd7000_biosaddr[biosaddr_ptr]); + wd7000_biosaddr[biosaddr_ptr]); #endif - if (wd7000_card_num) - iobase = wd7000_setupIO[wd7000_card_num - 1]; - else { - if (configs[cfg_ptr++].irq < 0) - continue; + if (configs[pass].irq < 0) + continue; - iobase = configs[cfg_ptr - 1].iobase; - } + iobase = configs[pass].iobase; -#ifdef DEBUG - printk ("wd7000_detect: check IO 0x%x region...\n", iobase); +#ifdef WD7000_DEBUG + printk ("wd7000_detect: check IO 0x%x region...\n", iobase); #endif - if (! check_region (iobase, 4)) { + if (!check_region (iobase, 4)) { -#ifdef DEBUG - printk ("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); +#ifdef WD7000_DEBUG + printk ("wd7000_detect: ASC reset (IO 0x%x) ...", iobase); #endif - - /* - * ASC reset... - */ - outb (ASC_RES, iobase + ASC_CONTROL); - delay (1); - outb (0, iobase + ASC_CONTROL); - - if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) -#ifdef DEBUG - { - printk ("failed!\n"); - continue; - } - else - printk ("ok!\n"); + /* + * ASC reset... + */ + outb (ASC_RES, iobase + ASC_CONTROL); + delay (1); + outb (0, iobase + ASC_CONTROL); + + if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) +#ifdef WD7000_DEBUG + { + printk ("failed!\n"); + continue; + } + else + printk ("ok!\n"); #else - continue; + continue; #endif if (inb (iobase + ASC_INTR_STAT) == 1) { @@ -1368,33 +1623,27 @@ bios_matched: sh = scsi_register (tpnt, sizeof (Adapter)); host = (Adapter *) sh->hostdata; -#ifdef DEBUG - printk ("wd7000_detect: adapter allocated at 0x%x\n", - (int) host); +#ifdef WD7000_DEBUG + printk ("wd7000_detect: adapter allocated at 0x%x\n", (int) host); #endif memset (host, 0, sizeof (Adapter)); - if (wd7000_card_num) { - host->irq = wd7000_setupIRQ[--wd7000_card_num]; - host->dma = wd7000_setupDMA[wd7000_card_num]; - } - else { - host->irq = configs[cfg_ptr - 1].irq; - host->dma = configs[cfg_ptr - 1].dma; - } - - host->sh = sh; - host->iobase = iobase; - irq2host[host->irq] = host; + host->irq = configs[pass].irq; + host->dma = configs[pass].dma; + host->iobase = iobase; + host->int_counter = 0; + host->bus_on = configs[pass].bus_on; + host->bus_off = configs[pass].bus_off; + host->sh = wd7000_host[host->irq - IRQ_MIN] = sh; -#ifdef DEBUG +#ifdef WD7000_DEBUG printk ("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma); #endif - if (! wd7000_init (host)) { /* Initialization failed */ + if (!wd7000_init (host)) { /* Initialization failed */ scsi_unregister (sh); continue; @@ -1403,7 +1652,7 @@ bios_matched: /* * OK from here - we'll use this adapter/configuration. */ - wd7000_revision (host); /* important for scatter/gather */ + wd7000_revision (host); /* important for scatter/gather */ /* * Register our ports. @@ -1411,34 +1660,34 @@ bios_matched: request_region (host->iobase, 4, "wd7000"); /* - * For boards before rev 6.0, scatter/gather - * isn't supported. + * For boards before rev 6.0, scatter/gather isn't supported. */ if (host->rev1 < 6) sh->sg_tablesize = SG_NONE; - present++; /* count it */ + present++; /* count it */ if (biosaddr_ptr != NUM_ADDRS) biosptr[pass] = biosaddr_ptr; printk ("Western Digital WD-7000 (rev %d.%d) ", host->rev1, host->rev2); - printk ("using IO 0x%x, IRQ %d, DMA %d.\n", + printk ("using IO 0x%x, IRQ %d, DMA %d.\n", host->iobase, host->irq, host->dma); + printk (" BUS_ON time: %dns, BUS_OFF time: %dns\n", + host->bus_on * 125, host->bus_off * 125); } } -#ifdef DEBUG +#ifdef WD7000_DEBUG else - printk ("wd7000_detect: IO 0x%x region already allocated!\n", - iobase); + printk ("wd7000_detect: IO 0x%x region already allocated!\n", iobase); #endif } - if (! present) - printk ("Failed initialization of WD-7000 SCSI card!\n"); + if (!present) + printk ("Failed initialization of WD-7000 SCSI card!\n"); return (present); } @@ -1447,42 +1696,81 @@ bios_matched: /* * I have absolutely NO idea how to do an abort with the WD7000... */ -int wd7000_abort(Scsi_Cmnd * SCpnt) +int wd7000_abort (Scsi_Cmnd *SCpnt) { Adapter *host = (Adapter *) SCpnt->host->hostdata; - if (inb(host->iobase+ASC_STAT) & INT_IM) { - printk("wd7000_abort: lost interrupt\n"); - wd7000_intr_handle(host->irq, NULL, NULL); - return SCSI_ABORT_SUCCESS; + if (inb (host->iobase + ASC_STAT) & INT_IM) { + printk ("wd7000_abort: lost interrupt\n"); + wd7000_intr_handle (host->irq, NULL, NULL); + + return (SCSI_ABORT_SUCCESS); } - return SCSI_ABORT_SNOOZE; + return (SCSI_ABORT_SNOOZE); } /* * I also have no idea how to do a reset... */ -int wd7000_reset(Scsi_Cmnd * SCpnt, unsigned int ignored) +int wd7000_reset (Scsi_Cmnd *SCpnt, unsigned int unused) { - return SCSI_RESET_PUNT; + return (SCSI_RESET_PUNT); } /* - * This was borrowed directly from aha1542.c, but my disks are organized - * this way, so I think it will work OK. Someone who is ambitious can - * borrow a newer or more complete version from another driver. + * This was borrowed directly from aha1542.c. (Zaga) */ -int wd7000_biosparam(Disk * disk, kdev_t dev, int* ip) +int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip) { - int size = disk->capacity; - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; -/* if (ip[2] >= 1024) ip[2] = 1024; */ - return 0; +#ifdef WD7000_DEBUG + printk ("wd7000_biosparam: dev=%s, size=%d, ", kdevname (dev), disk->capacity); +#endif + + /* + * try default translation + */ + ip[0] = 64; + ip[1] = 32; + ip[2] = disk->capacity / (64 * 32); + + /* + * for disks >1GB do some guessing + */ + if (ip[2] >= 1024) { + int info[3]; + + /* + * try to figure out the geometry from the partition table + */ + if ((scsicam_bios_param (disk, dev, info) < 0) || + !(((info[0] == 64) && (info[1] == 32)) || + ((info[0] == 255) && (info[1] == 63)))) { + printk ("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" + " using extended translation.\n"); + + ip[0] = 255; + ip[1] = 63; + ip[2] = disk->capacity / (255 * 63); + } + else { + ip[0] = info[0]; + ip[1] = info[1]; + ip[2] = info[2]; + + if (info[0] == 255) + printk ("wd7000_biosparam: current partition table is using extended translation.\n"); + } + } + +#ifdef WD7000_DEBUG + printk ("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); + printk ("WARNING: check, if the bios geometry is correct.\n"); +#endif + + return (0); } #ifdef MODULE diff --git a/drivers/scsi/wd7000.h b/drivers/scsi/wd7000.h index 8835e5f50..73679c24a 100644 --- a/drivers/scsi/wd7000.h +++ b/drivers/scsi/wd7000.h @@ -8,17 +8,23 @@ * This file has been reduced to only the definitions needed for the * WD7000 host structure. * + * Revision by Miroslav Zagorac <zaga@fly.cc.fer.hr> Jun 1997. */ #include <linux/types.h> #include <linux/kdev_t.h> -int wd7000_detect(Scsi_Host_Template *); -int wd7000_command(Scsi_Cmnd *); -int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int wd7000_abort(Scsi_Cmnd *); -int wd7000_reset(Scsi_Cmnd *, unsigned int); -int wd7000_biosparam(Disk *, kdev_t, int *); +extern struct proc_dir_entry proc_scsi_wd7000; + + +int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host); +int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); +int wd7000_detect (Scsi_Host_Template *); +int wd7000_command (Scsi_Cmnd *); +int wd7000_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int wd7000_abort (Scsi_Cmnd *); +int wd7000_reset (Scsi_Cmnd *, unsigned int); +int wd7000_biosparam (Disk *, kdev_t, int *); #ifndef NULL #define NULL 0L @@ -38,18 +44,22 @@ int wd7000_biosparam(Disk *, kdev_t, int *); #define WD7000_Q 16 #define WD7000_SG 16 -#define WD7000 { \ - name: "Western Digital WD-7000", \ - detect: wd7000_detect, \ - command: wd7000_command, \ - queuecommand: wd7000_queuecommand, \ - abort: wd7000_abort, \ - reset: wd7000_reset, \ - bios_param: wd7000_biosparam, \ - can_queue: WD7000_Q, \ - this_id: 7, \ - sg_tablesize: WD7000_SG, \ - cmd_per_lun: 1, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING} +#define WD7000 { \ + proc_dir: &proc_scsi_wd7000, \ + proc_info: wd7000_proc_info, \ + name: "Western Digital WD-7000", \ + detect: wd7000_detect, \ + command: wd7000_command, \ + queuecommand: wd7000_queuecommand, \ + abort: wd7000_abort, \ + reset: wd7000_reset, \ + bios_param: wd7000_biosparam, \ + can_queue: WD7000_Q, \ + this_id: 7, \ + sg_tablesize: WD7000_SG, \ + cmd_per_lun: 1, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 0 \ +} #endif diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index 7ef5f8dd4..d4678da82 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -6,6 +6,8 @@ fi dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND if [ "$CONFIG_SB" = "y" ]; then + bool 'Is the card a Soundman Games ?' CONFIG_SM_GAMES + bool 'Are you using the IBM Mwave "emulation" of SB ?' CONFIG_SB_MWAVE hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220 int 'Sound Blaster IRQ Check from manual of the card' CONFIG_SB_IRQ 7 int 'Sound Blaster DMA 0, 1 or 3' CONFIG_SB_DMA 1 diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index e8ec0b12d..6b09e336b 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -117,22 +117,6 @@ else endif endif -ifeq ($(CONFIG_MPU401),y) -LX_OBJS += mpu401.o -else - ifeq ($(CONFIG_MPU401),m) - MX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),y) - LX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),m) - MX_OBJS += mpu401.o - endif - endif - endif -endif - ifeq ($(CONFIG_UART401),y) LX_OBJS += uart401.o else @@ -159,9 +143,31 @@ endif ifeq ($(CONFIG_SSCAPE),y) L_OBJS += sscape.o +LX_OBJS += ad1848.o +CONFIG_MPU401 = y else ifeq ($(CONFIG_SSCAPE),m) M_OBJS += sscape.o + MX_OBJS += ad1848.o + ifneq ($(CONFIG_MPU401),y) + CONFIG_MPU401 = m + endif + endif +endif + +ifeq ($(CONFIG_MPU401),y) +LX_OBJS += mpu401.o +else + ifeq ($(CONFIG_MPU401),m) + MX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),y) + LX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),m) + MX_OBJS += mpu401.o + endif + endif endif endif @@ -265,7 +271,7 @@ CONFIG_MAUI_BOOT_FILE := $(patsubst "%", %, $(CONFIG_MAUI_BOOT_FILE)) maui.o: maui_boot.h maui_boot.h: $(CONFIG_MAUI_BOOT_FILE) bin2hex - bin2hex maui_os < "$(CONFIG_MAUI_BOOT_FILE)" > $@ + bin2hex -i maui_os < "$(CONFIG_MAUI_BOOT_FILE)" > $@ @ ( \ echo 'ifeq ($(strip $(CONFIG_MAUI_BOOT_FILE)),$$(strip $$(CONFIG_MAUI_BOOT_FILE)))'; \ echo 'FILES_BOOT_UP_TO_DATE += $@'; \ @@ -297,7 +303,7 @@ CONFIG_TRIX_BOOT_FILE := $(patsubst "%", %, $(CONFIG_TRIX_BOOT_FILE)) trix.o: trix_boot.h trix_boot.h: $(CONFIG_TRIX_BOOT_FILE) hex2hex - hex2hex trix_boot < "$(CONFIG_TRIX_BOOT_FILE)" > $@ + hex2hex -i trix_boot < "$(CONFIG_TRIX_BOOT_FILE)" > $@ @ ( \ echo 'ifeq ($(strip $(CONFIG_TRIX_BOOT_FILE)),$$(strip $$(CONFIG_TRIX_BOOT_FILE)))'; \ echo 'FILES_BOOT_UP_TO_DATE += $@'; \ diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index 6fdec35ec..d839ed208 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -23,6 +23,12 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * general sleep/wakeup clean up. + * Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free + * of irqs. Use dev_id. + * + * Status: + * Tested. Believed fully functional. */ #include <linux/config.h> @@ -144,9 +150,9 @@ static void ad1848_tmr_reprogram(int dev); static int ad_read(ad1848_info * devc, int reg) { - unsigned long flags; - int x; - int timeout = 900000; + unsigned long flags; + int x; + int timeout = 900000; while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ timeout--; @@ -163,11 +169,10 @@ static int ad_read(ad1848_info * devc, int reg) static void ad_write(ad1848_info * devc, int reg, int data) { - unsigned long flags; - int timeout = 900000; + unsigned long flags; + int timeout = 900000; - while (timeout > 0 && - inb(devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb(devc->base) == 0x80) /* Are we initializing */ timeout--; save_flags(flags); @@ -180,7 +185,7 @@ static void ad_write(ad1848_info * devc, int reg, int data) static void wait_for_calibration(ad1848_info * devc) { - int timeout = 0; + int timeout = 0; /* * Wait until the auto calibration process has finished. @@ -1751,7 +1756,11 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt else devc->audio_flags |= DMA_DUPLEX; } - + + portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); + if(portc==NULL) + return -1; + if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name, &ad1848_audio_driver, @@ -1762,12 +1771,11 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt dma_playback, dma_capture)) < 0) { + kfree(portc); + portc=NULL; return -1; } - portc = (ad1848_port_info *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(ad1848_port_info))); - sound_mem_sizes[sound_nblocks] = sizeof(ad1848_port_info); - if (sound_nblocks < 1024) - sound_nblocks++;; + audio_devs[my_dev]->portc = portc; memset((char *) portc, 0, sizeof(*portc)); @@ -1777,23 +1785,21 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt if (irq > 0) { - irq2dev[irq] = devc->dev_no = my_dev; - if (snd_set_irq_handler(devc->irq, adintr, - devc->name, - NULL) < 0) + devc->dev_no = my_dev; + if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) { - printk(KERN_WARNING "ad1848: IRQ in use\n"); + printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); } if (devc->model != MD_1848 && devc->model != MD_C930) { - int x; - unsigned char tmp = ad_read(devc, 16); + int x; + unsigned char tmp = ad_read(devc, 16); devc->timer_ticks = 0; ad_write(devc, 21, 0x00); /* Timer MSB */ ad_write(devc, 20, 0x10); /* Timer LSB */ - +#ifndef __SMP__ ad_write(devc, 16, tmp | 0x40); /* Enable timer */ for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ @@ -1805,6 +1811,9 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt DDB(printk("Interrupt test OK\n")); devc->irq_ok = 1; } +#else + devc->irq_ok=1; +#endif } else devc->irq_ok = 1; /* Couldn't test. assume it's OK */ @@ -1840,7 +1849,7 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt void ad1848_control(int cmd, int arg) { - ad1848_info *devc; + ad1848_info *devc; if (nr_ad1848_devs < 1) return; @@ -1850,7 +1859,7 @@ void ad1848_control(int cmd, int arg) switch (cmd) { case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ - if (devc->model != MD_1845) + if (devc->model != MD_1845) return; ad_enter_MCE(devc); ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); @@ -1859,8 +1868,8 @@ void ad1848_control(int cmd, int arg) case AD1848_MIXER_REROUTE: { - int o = (arg >> 8) & 0xff; - int n = arg & 0xff; + int o = (arg >> 8) & 0xff; + int n = arg & 0xff; if (n == SOUND_MIXER_NONE) { /* Just hide this control */ @@ -1906,12 +1915,14 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if (devc != NULL) { + if(audio_devs[dev]->portc!=NULL) + kfree(audio_devs[dev]->portc); release_region(devc->base, 4); if (!share_dma) { if (irq > 0) - snd_release_irq(devc->irq); + free_irq(devc->irq, NULL); sound_free_dma(audio_devs[dev]->dmap_out->dma); @@ -1926,35 +1937,15 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int void adintr(int irq, void *dev_id, struct pt_regs *dummy) { - unsigned char status; - ad1848_info *devc; - int dev; - int alt_stat = 0xff; - unsigned char c930_stat = 0; - int cnt = 0; - - if (irq < 0 || irq > 15) - { - dev = -1; - } - else - dev = irq2dev[irq]; - - if (dev < 0 || dev >= num_audiodevs) - { - for (irq = 0; irq < 17; irq++) - if (irq2dev[irq] != -1) - break; - - if (irq > 15) - { - /* printk("ad1848.c: Bogus interrupt %d\n", irq); */ - return; - } - dev = irq2dev[irq]; - devc = (ad1848_info *) audio_devs[dev]->devc; - } else - devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned char status; + ad1848_info *devc; + int dev; + int alt_stat = 0xff; + unsigned char c930_stat = 0; + int cnt = 0; + + dev = (int)dev_id; + devc = (ad1848_info *) audio_devs[dev]->devc; interrupt_again: /* Jump back here if int status doesn't reset */ @@ -2542,12 +2533,12 @@ EXPORT_SYMBOL(unload_ms_sound); #ifdef MODULE -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(dma, "i"); -MODULE_PARM(dma2, "i"); -MODULE_PARM(type, "i"); -MODULE_PARM(deskpro_xl, "i"); +MODULE_PARM(io, "i"); /* I/O for a raw AD1848 card */ +MODULE_PARM(irq, "i"); /* IRQ to use */ +MODULE_PARM(dma, "i"); /* First DMA channel */ +MODULE_PARM(dma2, "i"); /* Second DMA channel */ +MODULE_PARM(type, "i"); /* Card type */ +MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */ int io = -1; int irq = -1; diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index b27b1999a..9c9ccf095 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -21,7 +21,6 @@ #include <linux/config.h> #include <linux/stddef.h> -#include <linux/kerneld.h> #include "sound_config.h" diff --git a/drivers/sound/bin2hex.c b/drivers/sound/bin2hex.c index 351dd24e0..fc49c99d9 100644 --- a/drivers/sound/bin2hex.c +++ b/drivers/sound/bin2hex.c @@ -2,12 +2,27 @@ int main( int argc, const char * argv [] ) { - const char * varname = argv[1]; + const char * varname; int i = 0; int c; + int id = 0; + if(argv[1] && strcmp(argv[1],"-i")==0) + { + argv++; + argc--; + id=1; + } + + if(argc==1) + { + fprintf(stderr, "bin2hex: [-i] firmware\n"); + exit(1); + } + + varname = argv[1]; printf( "/* automatically generated by bin2hex */\n" ); - printf( "static unsigned char %s [] =\n{\n", varname ); + printf( "static unsigned char %s [] %s =\n{\n", varname , id?"__initdata":""); while ( ( c = getchar( ) ) != EOF ) { diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index c8732dfe4..fdb5b738c 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -12,7 +12,14 @@ * CS4232 * CS4236 * CS4236B + * + * Note: You will need a PnP config setup to initialise some CS4232 boards + * anyway. + * + * Changes + * Alan Cox Modularisation, Basic cleanups. */ + /* * Copyright (C) by Hannu Savolainen 1993-1997 * @@ -20,6 +27,7 @@ * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ + #include <linux/config.h> #include <linux/module.h> @@ -99,6 +107,8 @@ int probe_cs4232(struct address_info *hw_config) * just one CS4232 compatible device can exist on the system. Also this * method conflicts with possible PnP support in the OS. For this reason * driver is just a temporary kludge. + * + * Also the Cirrus/Crystal method doesnt always work. Try ISAPnP first ;) */ /* @@ -106,8 +116,8 @@ int probe_cs4232(struct address_info *hw_config) * first time. */ - for (n = 0; n < 4; n++) { - + for (n = 0; n < 4; n++) + { /* * Wake up the card by sending a 32 byte Crystal key to the key port. */ @@ -298,8 +308,7 @@ struct address_info cfg; * loaded ready. */ -int -init_module(void) +int init_module(void) { if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) { diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 666d7765e..7f3957bfd 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -148,9 +148,6 @@ void sound_unload_drivers(void) } } - for (i=0;i<num_audiodevs;i++) - DMAbuf_deinit(i); - if (trace_init) printk(KERN_DEBUG "Sound unload complete\n"); } diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index 151e20449..db6a02d05 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -104,7 +104,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap) dmap->raw_buf_phys = virt_to_bus(start_addr); for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - set_bit(PG_reserved, &mem_map[i].flags);; + set_bit(PG_reserved, &mem_map[i].flags); return 0; } @@ -115,8 +115,6 @@ static void sound_free_dmap(struct dma_buffparms *dmap) if (dmap->raw_buf == NULL) return; - if (dmap->mapping_flags & DMA_MAP_MAPPED) - return; /* Don't free mmapped buffer. Will use it next time */ for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); start_addr = (unsigned long) dmap->raw_buf; @@ -127,6 +125,8 @@ static void sound_free_dmap(struct dma_buffparms *dmap) free_pages((unsigned long) dmap->raw_buf, sz); dmap->raw_buf = NULL; + /* Remember the buffer is deleted so we dont Oops later */ + dmap->fragment_size = 0; } @@ -206,6 +206,7 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; disable_dma(dmap->dma); + sound_free_dmap(dmap); } @@ -832,12 +833,12 @@ int DMAbuf_move_wrpointer(int dev, int l) dmap->user_counter += l; dmap->flags |= DMA_DIRTY; - if (dmap->user_counter >= dmap->max_byte_counter) { + if (dmap->byte_counter >= dmap->max_byte_counter) { /* Wrap the byte counters */ - long decr = dmap->user_counter; - dmap->user_counter = (dmap->user_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->user_counter; - dmap->byte_counter -= decr; + long decr = dmap->byte_counter; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); + decr -= dmap->byte_counter; + dmap->user_counter -= decr; } end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; @@ -928,7 +929,7 @@ static void do_outputintr(int dev, int dummy) dmap->byte_counter += dmap->bytes_in_use; if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); decr -= dmap->byte_counter; dmap->user_counter -= decr; } @@ -952,7 +953,7 @@ static void do_outputintr(int dev, int dummy) dmap->byte_counter += dmap->bytes_in_use; if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); decr -= dmap->byte_counter; dmap->user_counter -= decr; } @@ -1211,18 +1212,4 @@ unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) return poll_input(file, dev, wait) | poll_output(file, dev, wait); } -void DMAbuf_deinit(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - /* This routine is called when driver is being unloaded */ - if (!adev) - return; -#ifdef RUNTIME_DMA_ALLOC - sound_free_dmap(adev->dmap_out); - - if (adev->flags & DMA_DUPLEX) - sound_free_dmap(adev->dmap_in); -#endif -} - #endif diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index 0f4f769eb..92e6dbab6 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -30,7 +30,7 @@ int gus_pnp_flag = 0; void attach_gus_card(struct address_info *hw_config) { - snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp); + snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp, hw_config); gus_wave_init(hw_config); @@ -101,7 +101,7 @@ void unload_gus(struct address_info *hw_config) release_region(hw_config->io_base, 16); release_region(hw_config->io_base + 0x100, 12); /* 0x10c-> is MAX */ - snd_release_irq(hw_config->irq); + snd_release_irq(hw_config->irq, hw_config); sound_free_dma(hw_config->dma); @@ -111,14 +111,15 @@ void unload_gus(struct address_info *hw_config) void gusintr(int irq, void *dev_id, struct pt_regs *dummy) { - unsigned char src; - extern int gus_timer_enabled; + unsigned char src; + extern int gus_timer_enabled; + struct address_info *hw_config=dev_id; sti(); #ifdef CONFIG_GUSMAX if (have_gus_max) - adintr(irq, NULL, NULL); + adintr(irq, (void *)hw_config->slots[3], NULL); #endif while (1) diff --git a/drivers/sound/hex2hex.c b/drivers/sound/hex2hex.c index 19753bfc2..4b182625b 100644 --- a/drivers/sound/hex2hex.c +++ b/drivers/sound/hex2hex.c @@ -66,14 +66,27 @@ int loadhex(FILE *inf, unsigned char *buf) int main( int argc, const char * argv [] ) { - const char * varline = argv[1]; + const char * varline; int i,l; + int id=0; + if(argv[1] && strcmp(argv[1], "-i")==0) + { + argv++; + argc--; + id=1; + } + if(argv[1]==NULL) + { + fprintf(stderr,"hex2hex: [-i] filename\n"); + exit(1); + } + varline = argv[1; l = loadhex(stdin, buf); printf("/*\n *\t Computer generated file. Do not edit.\n */\n"); printf("static int %s_len = %d;\n", varline, l); - printf("static unsigned char %s[] = {\n", varline); + printf("static unsigned char %s[] %s = {\n", varline, id?"__initdata":""); for (i=0;i<l;i++) { diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c index 5cd620dbf..a7d37039c 100644 --- a/drivers/sound/maui.c +++ b/drivers/sound/maui.c @@ -9,7 +9,15 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * Alan Cox General clean up, use kernel IRQ + * system + * + * Status: + * Untested */ + #include <linux/config.h> #include <linux/module.h> @@ -327,7 +335,7 @@ int probe_maui(struct address_info *hw_config) maui_base = hw_config->io_base; maui_osp = hw_config->osp; - if (snd_set_irq_handler(hw_config->irq, mauiintr, "Maui", maui_osp) < 0) + if (request_irq(hw_config->irq, mauiintr, 0, "Maui", NULL) < 0) return 0; /* @@ -342,26 +350,26 @@ int probe_maui(struct address_info *hw_config) maui_read() == -1 || maui_read() == -1) if (!maui_init(hw_config->irq)) { - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } } if (!maui_write(0xCF)) /* Report hardware version */ { printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n"); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) { printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n"); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } if (tmp1 == 0xff || tmp2 == 0xff) { - snd_release_irq(hw_config->irq); - return 0; + free_irq(hw_config->irq, NULL); + return 0; } if (trace_init) printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2); @@ -439,7 +447,7 @@ void unload_maui(struct address_info *hw_config) if (irq < 0) irq = -irq; if (irq > 0) - snd_release_irq(irq); + free_irq(irq, NULL); } #ifdef MODULE @@ -452,8 +460,7 @@ static int fw_load = 0; struct address_info cfg; /* - * Install a CS4232 based card. Need to have ad1848 and mpu401 - * loaded ready. + * Install a Maui card. Needs mpu401 loaded already. */ int init_module(void) diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c index 0c024a454..09dea3a34 100644 --- a/drivers/sound/midibuf.c +++ b/drivers/sound/midibuf.c @@ -15,7 +15,6 @@ */ #include <linux/config.h> #include <linux/stddef.h> -#include <linux/kerneld.h> #define MIDIBUF_C diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index 9ae597404..ce92010fc 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -9,10 +9,12 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, use normal request_irq, use dev_id */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ + #include <linux/config.h> #include <linux/module.h> @@ -32,30 +34,30 @@ static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; #endif struct mpu_config - { - int base; /* +{ + int base; /* * I/O base */ - int irq; - int opened; /* - * Open mode - */ - int devno; - int synthno; - int uart_mode; - int initialized; - int mode; + int irq; + int opened; /* + * Open mode + */ + int devno; + int synthno; + int uart_mode; + int initialized; + int mode; #define MODE_MIDI 1 #define MODE_SYNTH 2 - unsigned char version, revision; - unsigned int capabilities; + unsigned char version, revision; + unsigned int capabilities; #define MPU_CAP_INTLG 0x10000000 #define MPU_CAP_SYNC 0x00000010 #define MPU_CAP_FSK 0x00000020 #define MPU_CAP_CLS 0x00000040 #define MPU_CAP_SMPTE 0x00000080 #define MPU_CAP_2PORT 0x00000001 - int timer_flag; + int timer_flag; #define MBUF_MAX 10 #define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ @@ -75,28 +77,27 @@ struct mpu_config #define COMDPORT(base) (base+1) #define STATPORT(base) (base+1) -static int -mpu401_status(struct mpu_config *devc) +static int mpu401_status(struct mpu_config *devc) { return inb(STATPORT(devc->base)); } + #define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) -static void -write_command(struct mpu_config *devc, unsigned char cmd) + +static void write_command(struct mpu_config *devc, unsigned char cmd) { - outb((cmd), COMDPORT(devc->base)); + outb(cmd, COMDPORT(devc->base)); } -static int -read_data(struct mpu_config *devc) + +static int read_data(struct mpu_config *devc) { return inb(DATAPORT(devc->base)); } -static void -write_data(struct mpu_config *devc, unsigned char byte) +static void write_data(struct mpu_config *devc, unsigned char byte) { - outb((byte), DATAPORT(devc->base)); + outb(byte, DATAPORT(devc->base)); } #define OUTPUT_READY 0x40 @@ -107,22 +108,27 @@ write_data(struct mpu_config *devc, unsigned char byte) static struct mpu_config dev_conf[MAX_MIDI_DEV] = { - {0}}; + {0} +}; -static int n_mpu_devs = 0; -static volatile int irq2dev[17] = -{-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int n_mpu_devs = 0; -static int reset_mpu401(struct mpu_config *devc); -static void set_uart_mode(int dev, struct mpu_config *devc, int arg); +static int reset_mpu401(struct mpu_config *devc); +static void set_uart_mode(int dev, struct mpu_config *devc, int arg); -static int mpu_timer_init(int midi_dev); -static void mpu_timer_interrupt(void); -static void timer_ext_event(struct mpu_config *devc, int event, int parm); +static int mpu_timer_init(int midi_dev); +static void mpu_timer_interrupt(void); +static void timer_ext_event(struct mpu_config *devc, int event, int parm); -static struct synth_info mpu_synth_info_proto = -{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT}; +static struct synth_info mpu_synth_info_proto = { + "MPU-401 MIDI interface", + 0, + SYNTH_TYPE_MIDI, + MIDI_TYPE_MPU401, + 0, 128, + 0, 128, + SYNTH_CAP_INPUT +}; static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; @@ -158,10 +164,10 @@ static unsigned char len_tab[] = /* # of data bytes following a status #else #define STORE(cmd) \ { \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ + int len; \ + unsigned char obuf[8]; \ + cmd; \ + seq_input_event(obuf, len); \ } #endif @@ -169,242 +175,242 @@ static unsigned char len_tab[] = /* # of data bytes following a status #define _seqbufptr 0 #define _SEQ_ADVBUF(x) len=x -static int -mpu_input_scanner(struct mpu_config *devc, unsigned char midic) +static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) { switch (devc->m_state) - { - case ST_INIT: - switch (midic) - { - case 0xf8: - /* Timer overflow */ - break; - - case 0xfc: - printk("<all end>"); - break; - - case 0xfd: - if (devc->timer_flag) - mpu_timer_interrupt(); - break; - - case 0xfe: - return MPU_ACK; - break; - - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - printk("<Trk data rq #%d>", midic & 0x0f); - break; - - case 0xf9: - printk("<conductor rq>"); - break; - - case 0xff: - devc->m_state = ST_SYSMSG; - break; - - default: - if (midic <= 0xef) - { - /* printk( "mpu time: %d ", midic); */ - devc->m_state = ST_TIMED; - } else - printk("<MPU: Unknown event %02x> ", midic); - } - break; - - case ST_TIMED: - { - int msg = ((int) (midic & 0xf0) >> 4); - - devc->m_state = ST_DATABYTE; - - if (msg < 8) /* Data byte */ - { - /* printk( "midi msg (running status) "); */ - msg = ((int) (devc->last_status & 0xf0) >> 4); - msg -= 8; - devc->m_left = len_tab[msg] - 1; - - devc->m_ptr = 2; - devc->m_buf[0] = devc->last_status; - devc->m_buf[1] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } else if (msg == 0xf) /* MPU MARK */ - { - devc->m_state = ST_INIT; - - switch (midic) - { - case 0xf8: - /* printk( "NOP "); */ - break; - - case 0xf9: - /* printk( "meas end "); */ - break; - - case 0xfc: - /* printk( "data end "); */ - break; - - default: - printk("Unknown MPU mark %02x\n", midic); - } - } else - { - devc->last_status = midic; - /* printk( "midi msg "); */ - msg -= 8; - devc->m_left = len_tab[msg]; - - devc->m_ptr = 1; - devc->m_buf[0] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - } - break; - - case ST_SYSMSG: - switch (midic) - { - case 0xf0: - printk("<SYX>"); - devc->m_state = ST_SYSEX; - break; - - case 0xf1: - devc->m_state = ST_MTC; - break; - - case 0xf2: - devc->m_state = ST_SONGPOS; - devc->m_ptr = 0; - break; - - case 0xf3: - devc->m_state = ST_SONGSEL; - break; - - case 0xf6: - /* printk( "tune_request\n"); */ - devc->m_state = ST_INIT; - - /* - * Real time messages - */ - case 0xf8: - /* midi clock */ - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CLOCK, 0); - break; - - case 0xfA: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_START, 0); - break; - - case 0xFB: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CONTINUE, 0); - break; - - case 0xFC: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_STOP, 0); - break; - - case 0xFE: - /* active sensing */ - devc->m_state = ST_INIT; - break; - - case 0xff: - /* printk( "midi hard reset"); */ - devc->m_state = ST_INIT; - break; - - default: - printk("unknown MIDI sysmsg %0x\n", midic); - devc->m_state = ST_INIT; - } - break; - - case ST_MTC: - devc->m_state = ST_INIT; - printk("MTC frame %x02\n", midic); - break; - - case ST_SYSEX: - if (midic == 0xf7) - { - printk("<EOX>"); - devc->m_state = ST_INIT; - } else - printk("%02x ", midic); - break; - - case ST_SONGPOS: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if (devc->m_ptr == 2) - { - devc->m_state = ST_INIT; - devc->m_ptr = 0; - timer_ext_event(devc, TMR_SPP, - ((devc->m_buf[1] & 0x7f) << 7) | - (devc->m_buf[0] & 0x7f)); - } - break; - - case ST_DATABYTE: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if ((--devc->m_left) <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - break; - - default: - printk("Bad state %d ", devc->m_state); - devc->m_state = ST_INIT; - } + { + case ST_INIT: + switch (midic) + { + case 0xf8: + /* Timer overflow */ + break; + + case 0xfc: + printk("<all end>"); + break; + + case 0xfd: + if (devc->timer_flag) + mpu_timer_interrupt(); + break; + + case 0xfe: + return MPU_ACK; + + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + printk("<Trk data rq #%d>", midic & 0x0f); + break; + + case 0xf9: + printk("<conductor rq>"); + break; + + case 0xff: + devc->m_state = ST_SYSMSG; + break; + + default: + if (midic <= 0xef) + { + /* printk( "mpu time: %d ", midic); */ + devc->m_state = ST_TIMED; + } + else + printk("<MPU: Unknown event %02x> ", midic); + } + break; + + case ST_TIMED: + { + int msg = ((int) (midic & 0xf0) >> 4); + + devc->m_state = ST_DATABYTE; + + if (msg < 8) /* Data byte */ + { + /* printk( "midi msg (running status) "); */ + msg = ((int) (devc->last_status & 0xf0) >> 4); + msg -= 8; + devc->m_left = len_tab[msg] - 1; + + devc->m_ptr = 2; + devc->m_buf[0] = devc->last_status; + devc->m_buf[1] = midic; + + if (devc->m_left <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + } + else if (msg == 0xf) /* MPU MARK */ + { + devc->m_state = ST_INIT; + + switch (midic) + { + case 0xf8: + /* printk( "NOP "); */ + break; + + case 0xf9: + /* printk( "meas end "); */ + break; + + case 0xfc: + /* printk( "data end "); */ + break; + + default: + printk("Unknown MPU mark %02x\n", midic); + } + } + else + { + devc->last_status = midic; + /* printk( "midi msg "); */ + msg -= 8; + devc->m_left = len_tab[msg]; + + devc->m_ptr = 1; + devc->m_buf[0] = midic; + + if (devc->m_left <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + } + } + break; + + case ST_SYSMSG: + switch (midic) + { + case 0xf0: + printk("<SYX>"); + devc->m_state = ST_SYSEX; + break; + + case 0xf1: + devc->m_state = ST_MTC; + break; + + case 0xf2: + devc->m_state = ST_SONGPOS; + devc->m_ptr = 0; + break; + + case 0xf3: + devc->m_state = ST_SONGSEL; + break; + + case 0xf6: + /* printk( "tune_request\n"); */ + devc->m_state = ST_INIT; + + /* + * Real time messages + */ + case 0xf8: + /* midi clock */ + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_CLOCK, 0); + break; + + case 0xfA: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_START, 0); + break; + + case 0xFB: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_CONTINUE, 0); + break; + + case 0xFC: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_STOP, 0); + break; + + case 0xFE: + /* active sensing */ + devc->m_state = ST_INIT; + break; + + case 0xff: + /* printk( "midi hard reset"); */ + devc->m_state = ST_INIT; + break; + + default: + printk("unknown MIDI sysmsg %0x\n", midic); + devc->m_state = ST_INIT; + } + break; + + case ST_MTC: + devc->m_state = ST_INIT; + printk("MTC frame %x02\n", midic); + break; + + case ST_SYSEX: + if (midic == 0xf7) + { + printk("<EOX>"); + devc->m_state = ST_INIT; + } + else + printk("%02x ", midic); + break; + + case ST_SONGPOS: + BUFTEST(devc); + devc->m_buf[devc->m_ptr++] = midic; + if (devc->m_ptr == 2) + { + devc->m_state = ST_INIT; + devc->m_ptr = 0; + timer_ext_event(devc, TMR_SPP, + ((devc->m_buf[1] & 0x7f) << 7) | + (devc->m_buf[0] & 0x7f)); + } + break; + case ST_DATABYTE: + BUFTEST(devc); + devc->m_buf[devc->m_ptr++] = midic; + if ((--devc->m_left) <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + break; + + default: + printk("Bad state %d ", devc->m_state); + devc->m_state = ST_INIT; + } return 1; } -static void -mpu401_input_loop(struct mpu_config *devc) +static void mpu401_input_loop(struct mpu_config *devc) { - unsigned long flags; - int busy; - int n; + unsigned long flags; + int busy; + int n; save_flags(flags); cli(); @@ -418,72 +424,45 @@ mpu401_input_loop(struct mpu_config *devc) n = 50; while (input_avail(devc) && n-- > 0) - { - unsigned char c = read_data(devc); - - if (devc->mode == MODE_SYNTH) - { - mpu_input_scanner(devc, c); - } else if (devc->opened & OPEN_READ && devc->inputintr != NULL) - devc->inputintr(devc->devno, c); - } + { + unsigned char c = read_data(devc); + if (devc->mode == MODE_SYNTH) + { + mpu_input_scanner(devc, c); + } + else if (devc->opened & OPEN_READ && devc->inputintr != NULL) + devc->inputintr(devc->devno, c); + } devc->m_busy = 0; } -void -mpuintr(int irq, void *dev_id, struct pt_regs *dummy) +void mpuintr(int irq, void *dev_id, struct pt_regs *dummy) { struct mpu_config *devc; - int dev; + int dev = (int) dev_id; sti(); - -/* - * FreeBSD (and some others) pass unit number to the interrupt handler. - * In this case we have to scan the table for first handler. - */ - - if (irq < 1 || irq > 15) - { - dev = -1; - } else - dev = irq2dev[irq]; - - if (dev == -1) - { - int origirq = irq; - - for (irq = 0; irq <= 16; irq++) - if (irq2dev[irq] != -1) - break; - if (irq > 15) - { - printk("MPU-401: Bogus interrupt #%d?\n", origirq); - return; - } - dev = irq2dev[irq]; - devc = &dev_conf[dev]; - } else - devc = &dev_conf[dev]; + devc = &dev_conf[dev]; if (input_avail(devc)) + { if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) mpu401_input_loop(devc); else - { - /* Dummy read (just to acknowledge the interrupt) */ - read_data(devc); - } + { + /* Dummy read (just to acknowledge the interrupt) */ + read_data(devc); + } + } } -static int -mpu401_open(int dev, int mode, +static int mpu401_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) { - int err; + int err; struct mpu_config *devc; if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) @@ -492,36 +471,34 @@ mpu401_open(int dev, int mode, devc = &dev_conf[dev]; if (devc->opened) - { - printk("MPU-401: Midi busy\n"); return -EBUSY; - } /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. + * Verify that the device is really running. + * Some devices (such as Ensoniq SoundScape don't + * work before the on board processor (OBP) is initialized + * by downloading its microcode. */ if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk("MPU-401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - irq2dev[devc->irq] = dev; + { + if (mpu401_status(devc) == 0xff) /* Bus float */ + { + printk(KERN_ERR "mpu401: Device not initialized properly\n"); + return -EIO; + } + reset_mpu401(devc); + } if (midi_devs[dev]->coproc) + { if ((err = midi_devs[dev]->coproc-> open(midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0) - { - printk("MPU-401: Can't access coprocessor device\n"); - - return err; - } + { + printk("MPU-401: Can't access coprocessor device\n"); + return err; + } + } + set_uart_mode(dev, devc, 1); devc->mode = MODE_MIDI; devc->synthno = 0; @@ -534,19 +511,16 @@ mpu401_open(int dev, int mode, return 0; } -static void -mpu401_close(int dev) +static void mpu401_close(int dev) { struct mpu_config *devc; devc = &dev_conf[dev]; - if (devc->uart_mode) reset_mpu401(devc); /* * This disables the UART mode */ devc->mode = 0; - devc->inputintr = NULL; if (midi_devs[dev]->coproc) @@ -554,11 +528,10 @@ mpu401_close(int dev) devc->opened = 0; } -static int -mpu401_out(int dev, unsigned char midi_byte) +static int mpu401_out(int dev, unsigned char midi_byte) { - int timeout; - unsigned long flags; + int timeout; + unsigned long flags; struct mpu_config *devc; @@ -574,21 +547,20 @@ mpu401_out(int dev, unsigned char midi_byte) save_flags(flags); cli(); if (!output_ready(devc)) - { - printk("MPU-401: Send data timeout\n"); - restore_flags(flags); - return 0; - } + { + printk(KERN_WARNING "mpu401: Send data timeout\n"); + restore_flags(flags); + return 0; + } write_data(devc, midi_byte); restore_flags(flags); return 1; } -static int -mpu401_command(int dev, mpu_command_rec * cmd) +static int mpu401_command(int dev, mpu_command_rec * cmd) { - int i, timeout, ok; - int ret = 0; + int i, timeout, ok; + int ret = 0; unsigned long flags; struct mpu_config *devc; @@ -597,10 +569,10 @@ mpu401_command(int dev, mpu_command_rec * cmd) if (devc->uart_mode) /* * Not possible in UART mode */ - { - printk("MPU-401 commands not possible in the UART mode\n"); - return -EINVAL; - } + { + printk(KERN_WARNING "mpu401: commands not possible in the UART mode\n"); + return -EINVAL; + } /* * Test for input since pending input seems to block the output. */ @@ -613,83 +585,87 @@ mpu401_command(int dev, mpu_command_rec * cmd) */ timeout = 50000; - retry: +retry: if (timeout-- <= 0) - { - printk("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd); - return -EIO; - } + { + printk(KERN_WARNING "mpu401: Command (0x%x) timeout\n", (int) cmd->cmd); + return -EIO; + } save_flags(flags); cli(); if (!output_ready(devc)) - { + { restore_flags(flags); goto retry; - } + } write_command(devc, cmd->cmd); ok = 0; for (timeout = 50000; timeout > 0 && !ok; timeout--) + { if (input_avail(devc)) - { - if (devc->opened && devc->mode == MODE_SYNTH) - { - if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) - ok = 1; - } else - { /* Device is not currently open. Use simpler method */ - if (read_data(devc) == MPU_ACK) - ok = 1; - } - } + { + if (devc->opened && devc->mode == MODE_SYNTH) + { + if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) + ok = 1; + } + else + { + /* Device is not currently open. Use simpler method */ + if (read_data(devc) == MPU_ACK) + ok = 1; + } + } + } if (!ok) - { - restore_flags(flags); - /* printk( "MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */ - return -EIO; - } + { + restore_flags(flags); + return -EIO; + } if (cmd->nr_args) + { for (i = 0; i < cmd->nr_args; i++) - { - for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); - - if (!mpu401_out(dev, cmd->data[i])) - { - restore_flags(flags); - printk("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return -EIO; - } - } + { + for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); + + if (!mpu401_out(dev, cmd->data[i])) + { + restore_flags(flags); + printk(KERN_WARNING "mpu401: Command (0x%x), parm send failed.\n", (int) cmd->cmd); + return -EIO; + } + } + } ret = 0; cmd->data[0] = 0; if (cmd->nr_returns) + { for (i = 0; i < cmd->nr_returns; i++) - { - ok = 0; - for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail(devc)) - { - cmd->data[i] = read_data(devc); - ok = 1; - } - if (!ok) - { - restore_flags(flags); - /* printk( "MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */ - return -EIO; - } - } + { + ok = 0; + for (timeout = 5000; timeout > 0 && !ok; timeout--) + if (input_avail(devc)) + { + cmd->data[i] = read_data(devc); + ok = 1; + } + if (!ok) + { + restore_flags(flags); + return -EIO; + } + } + } restore_flags(flags); - return ret; } -static int -mpu_cmd(int dev, int cmd, int data) +static int mpu_cmd(int dev, int cmd, int data) { - int ret; + int ret; static mpu_command_rec rec; @@ -699,14 +675,11 @@ mpu_cmd(int dev, int cmd, int data) rec.data[0] = data & 0xff; if ((ret = mpu401_command(dev, &rec)) < 0) - { - return ret; - } + return ret; return (unsigned char) rec.data[0]; } -static int -mpu401_prefix_cmd(int dev, unsigned char status) +static int mpu401_prefix_cmd(int dev, unsigned char status) { struct mpu_config *devc = &dev_conf[dev]; @@ -714,37 +687,29 @@ mpu401_prefix_cmd(int dev, unsigned char status) return 1; if (status < 0xf0) - { - if (mpu_cmd(dev, 0xD0, 0) < 0) - { - return 0; - } - return 1; - } + { + if (mpu_cmd(dev, 0xD0, 0) < 0) + return 0; + return 1; + } switch (status) - { - case 0xF0: - if (mpu_cmd(dev, 0xDF, 0) < 0) - { - return 0; - } - return 1; - break; - - default: - return 0; - } + { + case 0xF0: + if (mpu_cmd(dev, 0xDF, 0) < 0) + return 0; + return 1; + default: + return 0; + } } -static int -mpu401_start_read(int dev) +static int mpu401_start_read(int dev) { return 0; } -static int -mpu401_end_read(int dev) +static int mpu401_end_read(int dev) { return 0; } @@ -756,49 +721,47 @@ static int mpu401_ioctl(int dev, unsigned cmd, caddr_t arg) int val, ret; devc = &dev_conf[dev]; - switch (cmd) { - case SNDCTL_MIDI_MPUMODE: - if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ - printk("MPU-401: Intelligent mode not supported by the HW\n"); + switch (cmd) + { + case SNDCTL_MIDI_MPUMODE: + if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ + printk(KERN_WARNING "mpu401: Intelligent mode not supported by the HW\n"); + return -EINVAL; + } + if (get_user(val, (int *)arg)) + return -EFAULT; + set_uart_mode(dev, devc, !val); + return 0; + + case SNDCTL_MIDI_MPUCMD: + if (copy_from_user(&rec, arg, sizeof(rec))) + return -EFAULT; + if ((ret = mpu401_command(dev, &rec)) < 0) + return ret; + if (copy_to_user(arg, &rec, sizeof(rec))) + return -EFAULT; + return 0; + + default: return -EINVAL; - } - if (__get_user(val, (int *)arg)) - return -EFAULT; - set_uart_mode(dev, devc, !val); - return 0; - - case SNDCTL_MIDI_MPUCMD: - if (__copy_from_user(&rec, arg, sizeof(rec))) - return -EFAULT; - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - if (__copy_to_user(arg, &rec, sizeof(rec))) - return -EFAULT; - return 0; - - default: - return -EINVAL; } } -static void -mpu401_kick(int dev) +static void mpu401_kick(int dev) { } -static int -mpu401_buffer_status(int dev) +static int mpu401_buffer_status(int dev) { return 0; /* * No data in buffers */ } -static int -mpu_synth_ioctl(int dev, +static int mpu_synth_ioctl(int dev, unsigned int cmd, caddr_t arg) { - int midi_dev; + int midi_dev; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; @@ -809,88 +772,77 @@ mpu_synth_ioctl(int dev, devc = &dev_conf[midi_dev]; switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - memcpy((&((char *) arg)[0]), (char *) &mpu_synth_info[midi_dev], sizeof(struct synth_info)); + { - return 0; - break; + case SNDCTL_SYNTH_INFO: + memcpy((&((char *) arg)[0]), (char *) &mpu_synth_info[midi_dev], sizeof(struct synth_info)); + return 0; - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - break; + case SNDCTL_SYNTH_MEMAVL: + return 0x7fffffff; - default: - return -EINVAL; - } + default: + return -EINVAL; + } } -static int -mpu_synth_open(int dev, int mode) +static int mpu_synth_open(int dev, int mode) { - int midi_dev, err; + int midi_dev, err; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) - { - return -ENXIO; - } + return -ENXIO; + devc = &dev_conf[midi_dev]; /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. + * Verify that the device is really running. + * Some devices (such as Ensoniq SoundScape don't + * work before the on board processor (OBP) is initialized + * by downloading its microcode. */ if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk("MPU-401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } + { + if (mpu401_status(devc) == 0xff) /* Bus float */ + { + printk(KERN_ERR "mpu401: Device not initialized properly\n"); + return -EIO; + } + reset_mpu401(devc); + } if (devc->opened) - { - printk("MPU-401: Midi busy\n"); - return -EBUSY; - } + return -EBUSY; devc->mode = MODE_SYNTH; devc->synthno = dev; devc->inputintr = NULL; - irq2dev[devc->irq] = midi_dev; if (midi_devs[midi_dev]->coproc) if ((err = midi_devs[midi_dev]->coproc-> open(midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0) - { - printk("MPU-401: Can't access coprocessor device\n"); - - return err; - } + { + printk(KERN_WARNING "mpu401: Can't access coprocessor device\n"); + return err; + } devc->opened = mode; reset_mpu401(devc); if (mode & OPEN_READ) - { - mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ - mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ - mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ - } + { + mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ + mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ + mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ + } return 0; } -static void -mpu_synth_close(int dev) -{ - int midi_dev; +static void mpu_synth_close(int dev) +{ + int midi_dev; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; @@ -958,55 +910,52 @@ static struct midi_operations mpu401_midi_proto = static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; -static void -mpu401_chk_version(int n, struct mpu_config *devc) +static void mpu401_chk_version(int n, struct mpu_config *devc) { - int tmp; - unsigned long flags; + int tmp; + unsigned long flags; devc->version = devc->revision = 0; save_flags(flags); cli(); if ((tmp = mpu_cmd(n, 0xAC, 0)) < 0) - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } devc->version = tmp; if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) - { - devc->version = 0; - restore_flags(flags); - return; - } + { + devc->version = 0; + restore_flags(flags); + return; + } devc->revision = tmp; - restore_flags(flags); } -void -attach_mpu401(struct address_info *hw_config) +void attach_mpu401(struct address_info *hw_config) { - unsigned long flags; - char revision_char; + unsigned long flags; + char revision_char; - int m; + int m; struct mpu_config *devc; hw_config->slots[1] = -1; m = sound_alloc_mididev(); if (m == -1) - { - printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); - return; - } + { + printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); + return; + } devc = &dev_conf[m]; devc->base = hw_config->io_base; devc->osp = hw_config->osp; @@ -1024,35 +973,36 @@ attach_mpu401(struct address_info *hw_config) devc->irq = hw_config->irq; if (devc->irq < 0) - { - devc->irq *= -1; - devc->shared_irq = 1; - } - irq2dev[devc->irq] = m; + { + devc->irq *= -1; + devc->shared_irq = 1; + } if (!hw_config->always_detect) - { - /* Verify the hardware again */ - if (!reset_mpu401(devc)) - { - printk(KERN_WARNING "mpu401: Device didn't respond\n"); - sound_unload_mididev(m); - return; - } - if (!devc->shared_irq) - if (snd_set_irq_handler(devc->irq, mpuintr, "mpu401", devc->osp) < 0) - { - printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); - sound_unload_mididev(m); - return; - } - save_flags(flags); - cli(); - mpu401_chk_version(m, devc); - if (devc->version == 0) - mpu401_chk_version(m, devc); - restore_flags(flags); - } + { + /* Verify the hardware again */ + if (!reset_mpu401(devc)) + { + printk(KERN_WARNING "mpu401: Device didn't respond\n"); + sound_unload_mididev(m); + return; + } + if (!devc->shared_irq) + { + if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0) + { + printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); + sound_unload_mididev(m); + return; + } + } + save_flags(flags); + cli(); + mpu401_chk_version(m, devc); + if (devc->version == 0) + mpu401_chk_version(m, devc); + restore_flags(flags); + } request_region(hw_config->io_base, 2, "mpu401"); if (devc->version != 0) @@ -1061,36 +1011,32 @@ attach_mpu401(struct address_info *hw_config) devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ - mpu401_synth_operations[m] = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (mpu401_synth_operations[m] == NULL) - { - sound_unload_mididev(m); - printk(KERN_ERR "mpu401: Can't allocate memory\n"); - return; - } + { + sound_unload_mididev(m); + printk(KERN_ERR "mpu401: Can't allocate memory\n"); + return; + } if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &std_midi_synth, + { + memcpy((char *) mpu401_synth_operations[m], + (char *) &std_midi_synth, sizeof(struct synth_operations)); - } else - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &mpu401_synth_proto, + } + else + { + memcpy((char *) mpu401_synth_operations[m], + (char *) &mpu401_synth_proto, sizeof(struct synth_operations)); - } + } memcpy((char *) &mpu401_midi_operations[m], (char *) &mpu401_midi_proto, sizeof(struct midi_operations)); - mpu401_midi_operations[m].converter = - mpu401_synth_operations[m]; + mpu401_midi_operations[m].converter = mpu401_synth_operations[m]; memcpy((char *) &mpu_synth_info[m], (char *) &mpu_synth_info_proto, @@ -1099,37 +1045,36 @@ attach_mpu401(struct address_info *hw_config) n_mpu_devs++; if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ - { - int ports = (devc->revision & 0x08) ? 32 : 16; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | - MPU_CAP_CLS | MPU_CAP_2PORT; - - revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - sprintf(mpu_synth_info[m].name, - "MQX-%d%c MIDI Interface #%d", - ports, - revision_char, - n_mpu_devs); - } else - { - - revision_char = devc->revision ? devc->revision + '@' : ' '; - if ((int) devc->revision > ('Z' - '@')) - revision_char = '+'; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - - if (hw_config->name) - sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); - else - sprintf(mpu_synth_info[m].name, - "MPU-401 %d.%d%c Midi interface #%d", - (int) (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char, - n_mpu_devs); - } + { + int ports = (devc->revision & 0x08) ? 32 : 16; + + devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | + MPU_CAP_CLS | MPU_CAP_2PORT; + + revision_char = (devc->revision == 0x7f) ? 'M' : ' '; + sprintf(mpu_synth_info[m].name, "MQX-%d%c MIDI Interface #%d", + ports, + revision_char, + n_mpu_devs); + } + else + { + revision_char = devc->revision ? devc->revision + '@' : ' '; + if ((int) devc->revision > ('Z' - '@')) + revision_char = '+'; + + devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; + + if (hw_config->name) + sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); + else + sprintf(mpu_synth_info[m].name, + "MPU-401 %d.%d%c Midi interface #%d", + (int) (devc->version & 0xf0) >> 4, + devc->version & 0x0f, + revision_char, + n_mpu_devs); + } strcpy(mpu401_midi_operations[m].info.name, mpu_synth_info[m].name); @@ -1137,24 +1082,21 @@ attach_mpu401(struct address_info *hw_config) conf_printf(mpu_synth_info[m].name, hw_config); mpu401_synth_operations[m]->midi_dev = devc->devno = m; - mpu401_synth_operations[devc->devno]->info = - &mpu_synth_info[devc->devno]; + mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ hw_config->slots[2] = mpu_timer_init(m); - irq2dev[devc->irq] = m; midi_devs[m] = &mpu401_midi_operations[devc->devno]; hw_config->slots[1] = m; sequencer_init(); } -static int -reset_mpu401(struct mpu_config *devc) +static int reset_mpu401(struct mpu_config *devc) { - unsigned long flags; - int ok, timeout, n; - int timeout_limit; + unsigned long flags; + int ok, timeout, n; + int timeout_limit; /* * Send the RESET command. Try again if no success at the first time. @@ -1167,30 +1109,30 @@ reset_mpu401(struct mpu_config *devc) devc->initialized = 1; for (n = 0; n < 2 && !ok; n++) - { - for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) + { + for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) ok = output_ready(devc); - write_command(devc, MPU_RESET); /* + write_command(devc, MPU_RESET); /* * Send MPU-401 RESET Command */ - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ - for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) - { - save_flags(flags); - cli(); - if (input_avail(devc)) - if (read_data(devc) == MPU_ACK) - ok = 1; - restore_flags(flags); - } + for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) + { + save_flags(flags); + cli(); + if (input_avail(devc)) + if (read_data(devc) == MPU_ACK) + ok = 1; + restore_flags(flags); + } - } + } devc->m_state = ST_INIT; devc->m_ptr = 0; @@ -1201,43 +1143,37 @@ reset_mpu401(struct mpu_config *devc) return ok; } -static void -set_uart_mode(int dev, struct mpu_config *devc, int arg) +static void set_uart_mode(int dev, struct mpu_config *devc, int arg) { if (!arg && (devc->capabilities & MPU_CAP_INTLG)) - { - return; - } + return; if ((devc->uart_mode == 0) == (arg == 0)) - { - return; /* Already set */ - } + return; /* Already set */ reset_mpu401(devc); /* This exits the uart mode */ if (arg) - { - if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) - { - printk("MPU%d: Can't enter UART mode\n", devc->devno); - devc->uart_mode = 0; - return; - } - } + { + if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) + { + printk(KERN_ERR "mpu401: Can't enter UART mode\n"); + devc->uart_mode = 0; + return; + } + } devc->uart_mode = arg; } -int -probe_mpu401(struct address_info *hw_config) +int probe_mpu401(struct address_info *hw_config) { - int ok = 0; + int ok = 0; struct mpu_config tmp_devc; if (check_region(hw_config->io_base, 2)) - { - printk("\n\nmpu401.c: I/O port %x already in use\n\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "mpu401: I/O port %x already in use\n\n", hw_config->io_base); + return 0; + } tmp_devc.base = hw_config->io_base; tmp_devc.irq = hw_config->irq; tmp_devc.initialized = 0; @@ -1248,27 +1184,32 @@ probe_mpu401(struct address_info *hw_config) return 1; if (inb(hw_config->io_base + 1) == 0xff) - { - DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); - return 0; /* Just bus float? */ - } + { + DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); + return 0; /* Just bus float? */ + } ok = reset_mpu401(&tmp_devc); if (!ok) - { - DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); - } + { + DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); + } return ok; } -void -unload_mpu401(struct address_info *hw_config) +void unload_mpu401(struct address_info *hw_config) { + void *p; + int n=hw_config->slots[1]; + release_region(hw_config->io_base, 2); if (hw_config->always_detect == 0 && hw_config->irq > 0) - snd_release_irq(hw_config->irq); - sound_unload_mididev(hw_config->slots[1]); + free_irq(hw_config->irq, (void *)n); + p=mpu401_synth_operations[n]; + sound_unload_mididev(n); sound_unload_timerdev(hw_config->slots[2]); + if(p) + kfree(p); } /***************************************************** @@ -1285,23 +1226,20 @@ static volatile unsigned long curr_ticks, curr_clocks; static unsigned long prev_event_time; static int metronome_mode; -static unsigned long -clocks2ticks(unsigned long clocks) +static unsigned long clocks2ticks(unsigned long clocks) { /* - * The MPU-401 supports just a limited set of possible timebase values. - * Since the applications require more choices, the driver has to - * program the HW to do its best and to convert between the HW and - * actual timebases. + * The MPU-401 supports just a limited set of possible timebase values. + * Since the applications require more choices, the driver has to + * program the HW to do its best and to convert between the HW and + * actual timebases. */ - return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; } -static void -set_timebase(int midi_dev, int val) +static void set_timebase(int midi_dev, int val) { - int hw_val; + int hw_val; if (val < 48) val = 48; @@ -1314,19 +1252,18 @@ set_timebase(int midi_dev, int val) hw_val = max_timebase; if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) - { - printk("MPU: Can't set HW timebase to %d\n", hw_val * 24); - return; - } + { + printk(KERN_WARNING "mpu401: Can't set HW timebase to %d\n", hw_val * 24); + return; + } hw_timebase = hw_val * 24; curr_timebase = val; } -static void -tmr_reset(void) +static void tmr_reset(void) { - unsigned long flags; + unsigned long flags; save_flags(flags); cli(); @@ -1336,8 +1273,7 @@ tmr_reset(void) restore_flags(flags); } -static void -set_timer_mode(int midi_dev) +static void set_timer_mode(int midi_dev) { if (timer_mode & TMR_MODE_CLS) mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ @@ -1345,31 +1281,31 @@ set_timer_mode(int midi_dev) mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ if (timer_mode & TMR_INTERNAL) - { + { mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */ - } else - { - if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) - { - mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ - mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ - } else if (timer_mode & TMR_MODE_FSK) - mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ - } + } + else + { + if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) + { + mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ + mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ + } + else if (timer_mode & TMR_MODE_FSK) + mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ + } } -static void -stop_metronome(int midi_dev) +static void stop_metronome(int midi_dev) { mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ } -static void -setup_metronome(int midi_dev) +static void setup_metronome(int midi_dev) { - int numerator, denominator; - int clks_per_click, num_32nds_per_beat; - int beats_per_measure; + int numerator, denominator; + int clks_per_click, num_32nds_per_beat; + int beats_per_measure; numerator = ((unsigned) metronome_mode >> 24) & 0xff; denominator = ((unsigned) metronome_mode >> 16) & 0xff; @@ -1380,15 +1316,14 @@ setup_metronome(int midi_dev) if (!metronome_mode) mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ else - { - mpu_cmd(midi_dev, 0xE4, clks_per_click); - mpu_cmd(midi_dev, 0xE6, beats_per_measure); - mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ - } + { + mpu_cmd(midi_dev, 0xE4, clks_per_click); + mpu_cmd(midi_dev, 0xE6, beats_per_measure); + mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ + } } -static int -mpu_start_timer(int midi_dev) +static int mpu_start_timer(int midi_dev) { tmr_reset(); set_timer_mode(midi_dev); @@ -1397,25 +1332,24 @@ mpu_start_timer(int midi_dev) return TIMER_NOT_ARMED; /* Already running */ if (timer_mode & TMR_INTERNAL) - { - mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ - tmr_running = 1; - return TIMER_NOT_ARMED; - } else - { - mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ - mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ - mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ - mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ - } - + { + mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ + tmr_running = 1; + return TIMER_NOT_ARMED; + } + else + { + mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ + mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ + mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ + mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ + } return TIMER_ARMED; } -static int -mpu_timer_open(int dev, int mode) +static int mpu_timer_open(int dev, int mode) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; if (timer_open) return -EBUSY; @@ -1435,10 +1369,9 @@ mpu_timer_open(int dev, int mode) return 0; } -static void -mpu_timer_close(int dev) +static void mpu_timer_close(int dev) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; timer_open = tmr_running = 0; mpu_cmd(midi_dev, 0x15, 0); /* Stop all */ @@ -1447,86 +1380,80 @@ mpu_timer_close(int dev) stop_metronome(midi_dev); } -static int -mpu_timer_event(int dev, unsigned char *event) +static int mpu_timer_event(int dev, unsigned char *event) { - unsigned char command = event[1]; - unsigned long parm = *(unsigned int *) &event[4]; - int midi_dev = sound_timer_devs[dev]->devlink; + unsigned char command = event[1]; + unsigned long parm = *(unsigned int *) &event[4]; + int midi_dev = sound_timer_devs[dev]->devlink; switch (command) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - if (tmr_running) - break; - return mpu_start_timer(midi_dev); - break; - - case TMR_STOP: - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - tmr_running = 0; - break; - - case TMR_CONTINUE: - if (tmr_running) - break; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - setup_metronome(midi_dev); - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - - if (mpu_cmd(midi_dev, 0xE0, parm) < 0) - printk("MPU: Can't set tempo to %d\n", (int) parm); - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input(event, 8); - break; - - case TMR_TIMESIG: - if (metronome_mode) /* Metronome enabled */ - { - metronome_mode = parm; - setup_metronome(midi_dev); - } - break; - - default:; - } + { + case TMR_WAIT_REL: + parm += prev_event_time; + case TMR_WAIT_ABS: + if (parm > 0) + { + long time; + + if (parm <= curr_ticks) /* It's the time */ + return TIMER_NOT_ARMED; + time = parm; + next_event_time = prev_event_time = time; + + return TIMER_ARMED; + } + break; + + case TMR_START: + if (tmr_running) + break; + return mpu_start_timer(midi_dev); + + case TMR_STOP: + mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ + stop_metronome(midi_dev); + tmr_running = 0; + break; + case TMR_CONTINUE: + if (tmr_running) + break; + mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ + setup_metronome(midi_dev); + tmr_running = 1; + break; + + case TMR_TEMPO: + if (parm) + { + if (parm < 8) + parm = 8; + if (parm > 250) + parm = 250; + if (mpu_cmd(midi_dev, 0xE0, parm) < 0) + printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) parm); + curr_tempo = parm; + } + break; + + case TMR_ECHO: + seq_copy_to_input(event, 8); + break; + + case TMR_TIMESIG: + if (metronome_mode) /* Metronome enabled */ + { + metronome_mode = parm; + setup_metronome(midi_dev); + } + break; + + default: + } return TIMER_NOT_ARMED; } -static unsigned long -mpu_timer_get_time(int dev) +static unsigned long mpu_timer_get_time(int dev) { if (!timer_open) return 0; @@ -1534,128 +1461,115 @@ mpu_timer_get_time(int dev) return curr_ticks; } -static int -mpu_timer_ioctl(int dev, - unsigned int command, caddr_t arg) +static int mpu_timer_ioctl(int dev, unsigned int command, caddr_t arg) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; switch (command) - { - case SNDCTL_TMR_SOURCE: - { - int parm; - - parm = *(int *) arg; - parm &= timer_caps; - - if (parm != 0) - { - timer_mode = parm; - - if (timer_mode & TMR_MODE_CLS) - mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ - } - return (*(int *) arg = timer_mode); - } - break; - - case SNDCTL_TMR_START: - mpu_start_timer(midi_dev); - return 0; - break; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - return 0; - break; - - case SNDCTL_TMR_CONTINUE: - if (tmr_running) - return 0; - tmr_running = 1; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - return 0; - break; - - case SNDCTL_TMR_TIMEBASE: - { - int val; - - val = *(int *) arg; - if (val) - set_timebase(midi_dev, val); - - return (*(int *) arg = curr_timebase); - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val; - int ret; - - val = *(int *) arg; - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) - { - printk("MPU: Can't set tempo to %d\n", (int) val); - return ret; - } - curr_tempo = val; - } - return (*(int *) arg = curr_tempo); - } - break; - - case SNDCTL_SEQ_CTRLRATE: - { - int val; - - val = *(int *) arg; - if (val != 0) /* Can't change */ - return -EINVAL; - - return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60); - } - break; - - case SNDCTL_SEQ_GETTIME: - return (*(int *) arg = curr_ticks); - break; - - case SNDCTL_TMR_METRONOME: - metronome_mode = *(int *) arg; - setup_metronome(midi_dev); - return 0; - break; - - default:; - } + { + case SNDCTL_TMR_SOURCE: + { + int parm; + + parm = *(int *) arg; + parm &= timer_caps; + if (parm != 0) + { + timer_mode = parm; + + if (timer_mode & TMR_MODE_CLS) + mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ + else if (timer_mode & TMR_MODE_SMPTE) + mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ + } + return (*(int *) arg = timer_mode); + } + break; + + case SNDCTL_TMR_START: + mpu_start_timer(midi_dev); + return 0; + + case SNDCTL_TMR_STOP: + tmr_running = 0; + mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ + stop_metronome(midi_dev); + return 0; + + case SNDCTL_TMR_CONTINUE: + if (tmr_running) + return 0; + tmr_running = 1; + mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ + return 0; + + case SNDCTL_TMR_TIMEBASE: + { + int val; + + val = *(int *) arg; + if (val) + set_timebase(midi_dev, val); + return (*(int *) arg = curr_timebase); + } + break; + + case SNDCTL_TMR_TEMPO: + { + int val; + int ret; + + val = *(int *) arg; + + if (val) + { + if (val < 8) + val = 8; + if (val > 250) + val = 250; + if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) + { + printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) val); + return ret; + } + curr_tempo = val; + } + return (*(int *) arg = curr_tempo); + } + break; + + case SNDCTL_SEQ_CTRLRATE: + { + int val; + + val = *(int *) arg; + if (val != 0) /* Can't change */ + return -EINVAL; + return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60); + } + break; + + case SNDCTL_SEQ_GETTIME: + return (*(int *) arg = curr_ticks); + + case SNDCTL_TMR_METRONOME: + metronome_mode = *(int *) arg; + setup_metronome(midi_dev); + return 0; + + default: + } return -EINVAL; } -static void -mpu_timer_arm(int dev, long time) +static void mpu_timer_arm(int dev, long time) { if (time < 0) time = curr_ticks + 1; else if (time <= curr_ticks) /* It's the time */ return; - next_event_time = prev_event_time = time; - return; } @@ -1672,10 +1586,8 @@ static struct sound_timer_operations mpu_timer = mpu_timer_arm }; -static void -mpu_timer_interrupt(void) +static void mpu_timer_interrupt(void) { - if (!timer_open) return; @@ -1686,10 +1598,10 @@ mpu_timer_interrupt(void) curr_ticks = clocks2ticks(curr_clocks); if (curr_ticks >= next_event_time) - { - next_event_time = (unsigned long) -1; - sequencer_timer(0); - } + { + next_event_time = (unsigned long) -1; + sequencer_timer(0); + } } static void timer_ext_event(struct mpu_config *devc, int event, int parm) @@ -1706,8 +1618,9 @@ static void timer_ext_event(struct mpu_config *devc, int event, int parm) break; case TMR_START: - printk("Ext MIDI start\n"); + printk("Ext MIDI start\n"); if (!tmr_running) + { if (timer_mode & TMR_EXTERNAL) { tmr_running = 1; @@ -1715,6 +1628,7 @@ static void timer_ext_event(struct mpu_config *devc, int event, int parm) next_event_time = 0; STORE(SEQ_START_TIMER()); } + } break; case TMR_STOP: diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c index 36734c2e7..cd768801f 100644 --- a/drivers/sound/opl3.c +++ b/drivers/sound/opl3.c @@ -2,25 +2,30 @@ * sound/opl3.c * * A low level driver for Yamaha YM3812 and OPL-3 -chips - */ -/* + * +* * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * + * Changes + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, fixed sound_mem allocs. + * + * Status + * Believed to work. Badly needs rewriting a bit to support multiple + * OPL3 devices. */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ + #include <linux/config.h> #include <linux/module.h> #include <linux/delay.h> /* * Major improvements to the FM handling 30AUG92 by Rob Hooft, - */ -/* * hooft@chem.ruu.nl */ @@ -109,32 +114,32 @@ static int opl3_ioctl(int dev, unsigned int cmd, caddr_t arg) struct sbi_instrument ins; switch (cmd) { - case SNDCTL_FM_LOAD_INSTR: - printk(KERN_WARNING "Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); - if (__copy_from_user(&ins, arg, sizeof(ins))) - return -EFAULT; - if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { - printk("FM Error: Invalid instrument number %d\n", ins.channel); - return -EINVAL; - } - return store_instr(ins.channel, &ins); + case SNDCTL_FM_LOAD_INSTR: + printk(KERN_WARNING "Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); + if (copy_from_user(&ins, arg, sizeof(ins))) + return -EFAULT; + if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { + printk(KERN_WARNING "FM Error: Invalid instrument number %d\n", ins.channel); + return -EINVAL; + } + return store_instr(ins.channel, &ins); - case SNDCTL_SYNTH_INFO: - devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; - if (__copy_to_user(arg, &devc->fm_info, sizeof(devc->fm_info))) - return -EFAULT; - return 0; + case SNDCTL_SYNTH_INFO: + devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; + if (copy_to_user(arg, &devc->fm_info, sizeof(devc->fm_info))) + return -EFAULT; + return 0; - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; + case SNDCTL_SYNTH_MEMAVL: + return 0x7fffffff; - case SNDCTL_FM_4OP_ENABLE: - if (devc->model == 2) - enter_4op_mode(); - return 0; + case SNDCTL_FM_4OP_ENABLE: + if (devc->model == 2) + enter_4op_mode(); + return 0; - default: - return -EINVAL; + default: + return -EINVAL; } } @@ -151,8 +156,8 @@ int opl3_detect(int ioaddr, int *osp) * Note2! The chip is initialized if detected. */ - unsigned char stat1, signature; - int i; + unsigned char stat1, signature; + int i; if (devc != NULL) { @@ -160,10 +165,7 @@ int opl3_detect(int ioaddr, int *osp) return 0; } - devc = (struct opl_devinfo *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(*devc))); - sound_mem_sizes[sound_nblocks] = sizeof(*devc); - if (sound_nblocks < 1024) - sound_nblocks++;; + devc = (struct opl_devinfo *)kmalloc(sizeof(*devc), GFP_KERNEL); if (devc == NULL) { @@ -333,7 +335,7 @@ static char fm_volume_table[128] = static void calc_vol(unsigned char *regbyte, int volume, int main_vol) { - int level = (~*regbyte & 0x3f); + int level = (~*regbyte & 0x3f); if (main_vol > 127) main_vol = 127; @@ -814,7 +816,8 @@ static int opl3_load_patch(int dev, int format, const char *addr, return -EINVAL; } - copy_from_user(&((char *) &ins)[offs], &(addr)[offs], sizeof(ins) - offs); + if(copy_from_user(&((char *) &ins)[offs], &(addr)[offs], sizeof(ins) - offs)) + return -EFAULT; if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { @@ -1199,6 +1202,7 @@ void cleanup_module(void) { if (devc) { + kfree(devc); devc = NULL; sound_unload_synthdev(me); } diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index 656034d54..bf95b84d5 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -164,7 +164,7 @@ static int config_pas_hw(struct address_info *hw_config) } else { - if (snd_set_irq_handler(pas_irq, pasintr, "PAS16", hw_config->osp) < 0) + if (request_irq(pas_irq, pasintr, "PAS16", 0, NULL) < 0) ok = 0; } } @@ -355,7 +355,7 @@ void unload_pas(struct address_info *hw_config) { sound_free_dma(hw_config->dma); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); } #ifdef MODULE diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c index 9d62dd485..7a0a2e66e 100644 --- a/drivers/sound/pss.c +++ b/drivers/sound/pss.c @@ -11,7 +11,8 @@ * for more info. */ /* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, clean up. */ #include <linux/config.h> #include <linux/module.h> @@ -62,12 +63,12 @@ static int pss_synthLen = 0; #endif typedef struct pss_confdata - { - int base; - int irq; - int dma; - int *osp; - } +{ + int base; + int irq; + int dma; + int *osp; +} pss_confdata; @@ -77,12 +78,11 @@ static pss_confdata *devc = &pss_data; static int pss_initialized = 0; static int nonstandard_microcode = 0; -static void -pss_write(int data) +static void pss_write(int data) { - int i, limit; + int i, limit; - limit = jiffies + 10; /* The timeout is 0.1 seconds */ + limit = jiffies + HZ/10; /* The timeout is 0.1 seconds */ /* * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes * called while interrupts are disabled. This means that the timer is @@ -92,21 +92,20 @@ pss_write(int data) */ for (i = 0; i < 5000000 && jiffies < limit; i++) - { - if (inw(devc->base + PSS_STATUS) & PSS_WRITE_EMPTY) - { - outw(devc->base + PSS_DATA, data); - return; - } - } - printk("PSS: DSP Command (%04x) Timeout.\n", data); + { + if (inw(devc->base + PSS_STATUS) & PSS_WRITE_EMPTY) + { + outw(devc->base + PSS_DATA, data); + return; + } + } + printk(KERN_ERR "PSS: DSP Command (%04x) Timeout.\n", data); } -int -probe_pss(struct address_info *hw_config) +int probe_pss(struct address_info *hw_config) { - unsigned short id; - int irq, dma; + unsigned short id; + int irq, dma; devc->base = hw_config->io_base; irq = devc->irq = hw_config->irq; @@ -129,8 +128,7 @@ probe_pss(struct address_info *hw_config) return 1; } -static int -set_irq(pss_confdata * devc, int dev, int irq) +static int set_irq(pss_confdata * devc, int dev, int irq) { static unsigned short irq_bits[16] = { @@ -148,16 +146,15 @@ set_irq(pss_confdata * devc, int dev, int irq) tmp = inw(REG(dev)) & ~0x38; /* Load confreg, mask IRQ bits out */ if ((bits = irq_bits[irq]) == 0 && irq != 0) - { - printk("PSS: Invalid IRQ %d\n", irq); - return 0; - } + { + printk(KERN_ERR "PSS: Invalid IRQ %d\n", irq); + return 0; + } outw(tmp | bits, REG(dev)); return 1; } -static int -set_io_base(pss_confdata * devc, int dev, int base) +static int set_io_base(pss_confdata * devc, int dev, int base) { unsigned short tmp = inw(REG(dev)) & 0x003f; unsigned short bits = (base & 0x0ffc) << 4; @@ -167,8 +164,7 @@ set_io_base(pss_confdata * devc, int dev, int base) return 1; } -static int -set_dma(pss_confdata * devc, int dev, int dma) +static int set_dma(pss_confdata * devc, int dev, int dma) { static unsigned short dma_bits[8] = { @@ -184,150 +180,139 @@ set_dma(pss_confdata * devc, int dev, int dma) tmp = inw(REG(dev)) & ~0x07; /* Load confreg, mask DMA bits out */ if ((bits = dma_bits[dma]) == 0 && dma != 4) - { - printk("PSS: Invalid DMA %d\n", dma); + { + printk(KERN_ERR "PSS: Invalid DMA %d\n", dma); return 0; - } + } outw(tmp | bits, REG(dev)); return 1; } -static int -pss_reset_dsp(pss_confdata * devc) +static int pss_reset_dsp(pss_confdata * devc) { - unsigned long i, limit = jiffies + 10; + unsigned long i, limit = jiffies + HZ/10; outw(0x2000, REG(PSS_CONTROL)); - - for (i = 0; i < 32768 && jiffies < limit; i++) + for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) inw(REG(PSS_CONTROL)); - outw(0x0000, REG(PSS_CONTROL)); - return 1; } -static int -pss_put_dspword(pss_confdata * devc, unsigned short word) +static int pss_put_dspword(pss_confdata * devc, unsigned short word) { - int i, val; + int i, val; for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_WRITE_EMPTY) - { - outw(word, REG(PSS_DATA)); - return 1; - } - } + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_WRITE_EMPTY) + { + outw(word, REG(PSS_DATA)); + return 1; + } + } return 0; } -static int -pss_get_dspword(pss_confdata * devc, unsigned short *word) +static int pss_get_dspword(pss_confdata * devc, unsigned short *word) { - int i, val; + int i, val; for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - { - *word = inw(REG(PSS_DATA)); - return 1; - } - } - + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_READ_FULL) + { + *word = inw(REG(PSS_DATA)); + return 1; + } + } return 0; } -static int -pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) +static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) { - int i, limit, val, count; + int i, limit, val, count; if (flags & CPF_FIRST) - { + { /*_____ Warn DSP software that a boot is coming */ - outw(0x00fe, REG(PSS_DATA)); - - limit = jiffies + 10; + outw(0x00fe, REG(PSS_DATA)); - for (i = 0; i < 32768 && jiffies < limit; i++) - if (inw(REG(PSS_DATA)) == 0x5500) - break; - - outw(*block++, REG(PSS_DATA)); + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && jiffies < limit; i++) + if (inw(REG(PSS_DATA)) == 0x5500) + break; - pss_reset_dsp(devc); - } + outw(*block++, REG(PSS_DATA)); + pss_reset_dsp(devc); + } count = 1; while (1) - { - int j; + { + int j; - for (j = 0; j < 327670; j++) - { + for (j = 0; j < 327670; j++) + { /*_____ Wait for BG to appear */ - if (inw(REG(PSS_STATUS)) & PSS_FLAG3) - break; - } - - if (j == 327670) - { - /* It's ok we timed out when the file was empty */ - if (count >= size && flags & CPF_LAST) - break; - else - { - printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size); - return 0; - } - } + if (inw(REG(PSS_STATUS)) & PSS_FLAG3) + break; + } + + if (j == 327670) + { + /* It's ok we timed out when the file was empty */ + if (count >= size && flags & CPF_LAST) + break; + else + { + printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size); + return 0; + } + } /*_____ Send the next byte */ - outw(*block++, REG(PSS_DATA)); - count++; - } + outw(*block++, REG(PSS_DATA)); + count++; + } if (flags & CPF_LAST) - { + { /*_____ Why */ - outw(0, REG(PSS_DATA)); - - limit = jiffies + 10; - for (i = 0; i < 32768 && jiffies < limit; i++) - val = inw(REG(PSS_STATUS)); - - limit = jiffies + 10; - for (i = 0; i < 32768 && jiffies < limit; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & 0x4000) - break; - } - - /* now read the version */ - for (i = 0; i < 32000; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - break; - } - if (i == 32000) - return 0; - - val = inw(REG(PSS_DATA)); - /* printk( "<PSS: microcode version %d.%d loaded>", val/16, val % 16); */ - } + outw(0, REG(PSS_DATA)); + + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && (limit - jiffies >= 0); i++) + val = inw(REG(PSS_STATUS)); + + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + { + val = inw(REG(PSS_STATUS)); + if (val & 0x4000) + break; + } + + /* now read the version */ + for (i = 0; i < 32000; i++) + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_READ_FULL) + break; + } + if (i == 32000) + return 0; + + val = inw(REG(PSS_DATA)); + /* printk( "<PSS: microcode version %d.%d loaded>", val/16, val % 16); */ + } return 1; } -void -attach_pss(struct address_info *hw_config) +void attach_pss(struct address_info *hw_config) { unsigned short id; - char tmp[100]; + char tmp[100]; devc->base = hw_config->io_base; devc->irq = hw_config->irq; @@ -350,20 +335,20 @@ attach_pss(struct address_info *hw_config) #if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES if (sound_alloc_dma(hw_config->dma, "PSS")) - { - printk("pss.c: Can't allocate DMA channel\n"); - return; - } + { + printk("pss.c: Can't allocate DMA channel.\n"); + return; + } if (!set_irq(devc, CONF_PSS, devc->irq)) - { - printk("PSS: IRQ error\n"); - return; - } + { + printk("PSS: IRQ allocation error.\n"); + return; + } if (!set_dma(devc, CONF_PSS, devc->dma)) - { - printk("PSS: DRQ error\n"); - return; - } + { + printk(KERN_ERR "PSS: DMA allocation error\n"); + return; + } #endif pss_initialized = 1; @@ -371,8 +356,7 @@ attach_pss(struct address_info *hw_config) conf_printf(tmp, hw_config); } -static void -pss_init_speaker(void) +static void pss_init_speaker(void) { /* Don't ask what are these commands. I really don't know */ pss_write(0x0010); @@ -387,53 +371,52 @@ pss_init_speaker(void) pss_write(0x0800 | 0x00ce); /* Stereo switch? */ } -int -probe_pss_mpu(struct address_info *hw_config) +int probe_pss_mpu(struct address_info *hw_config) { - int timeout; + int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 2)) - { - printk("PSS: MPU I/O port conflict\n"); - return 0; - } + { + printk("PSS: MPU I/O port conflict\n"); + return 0; + } if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) - { - printk("PSS: MIDI base error.\n"); + { + printk("PSS: MIDI base could not be set.\n"); return 0; - } + } if (!set_irq(devc, CONF_MIDI, hw_config->irq)) - { - printk("PSS: MIDI IRQ error.\n"); + { + printk("PSS: MIDI IRQ allocation error.\n"); return 0; - } + } if (!pss_synthLen) - { - printk("PSS: Can't enable MPU. MIDI synth microcode not available.\n"); - return 0; - } + { + printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n"); + return 0; + } if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - return 0; - } + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + return 0; + } pss_init_speaker(); -/* - * Finally wait until the DSP algorithm has initialized itself and - * deactivates receive interrupt. - */ + /* + * Finally wait until the DSP algorithm has initialized itself and + * deactivates receive interrupt. + */ for (timeout = 900000; timeout > 0; timeout--) - { - if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ - inb(hw_config->io_base); /* Discard it */ - else - break; /* No more input */ - } + { + if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ + inb(hw_config->io_base); /* Discard it */ + else + break; /* No more input */ + } #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) return probe_mpu401(hw_config); @@ -442,62 +425,56 @@ probe_pss_mpu(struct address_info *hw_config) #endif } -static int -pss_coproc_open(void *dev_info, int sub_device) +static int pss_coproc_open(void *dev_info, int sub_device) { switch (sub_device) - { - case COPR_MIDI: - - if (pss_synthLen == 0) - { - printk("PSS: MIDI synth microcode not available.\n"); - return -EIO; - } - if (nonstandard_microcode) - if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - return -EIO; - } - nonstandard_microcode = 0; - break; - - default:; - } + { + case COPR_MIDI: + if (pss_synthLen == 0) + { + printk(KERN_ERR "PSS: MIDI synth microcode not available.\n"); + return -EIO; + } + if (nonstandard_microcode) + if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + return -EIO; + } + nonstandard_microcode = 0; + break; + + default: + } return 0; } -static void -pss_coproc_close(void *dev_info, int sub_device) +static void pss_coproc_close(void *dev_info, int sub_device) { return; } -static void -pss_coproc_reset(void *dev_info) +static void pss_coproc_reset(void *dev_info) { if (pss_synthLen) if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - } + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + } nonstandard_microcode = 0; } -static int -download_boot_block(void *dev_info, copr_buffer * buf) +static int download_boot_block(void *dev_info, copr_buffer * buf) { if (buf->len <= 0 || buf->len > sizeof(buf->data)) return -EINVAL; if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) - { - printk("PSS: Unable to load microcode block to DSP.\n"); - return -EIO; - } + { + printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n"); + return -EIO; + } nonstandard_microcode = 1; /* The MIDI microcode has been overwritten */ - return 0; } @@ -512,169 +489,170 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, caddr_t arg, int l int i, err; /* printk( "PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ - switch (cmd) { - case SNDCTL_COPR_RESET: - pss_coproc_reset(dev_info); - return 0; + switch (cmd) + { + case SNDCTL_COPR_RESET: + pss_coproc_reset(dev_info); + return 0; - case SNDCTL_COPR_LOAD: - buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); - if (buf == NULL) - return -ENOSPC; - if (__copy_from_user(buf, arg, sizeof(copr_buffer))) { + case SNDCTL_COPR_LOAD: + buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); + if (buf == NULL) + return -ENOSPC; + if (copy_from_user(buf, arg, sizeof(copr_buffer))) { + vfree(buf); + return -EFAULT; + } + err = download_boot_block(dev_info, buf); vfree(buf); - return -EFAULT; - } - err = download_boot_block(dev_info, buf); - vfree(buf); - return err; + return err; - case SNDCTL_COPR_SENDMSG: - mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); - if (mbuf == NULL) - return -ENOSPC; - if (__copy_from_user(mbuf, arg, sizeof(copr_msg))) { - vfree(mbuf); - return -EFAULT; - } - data = (unsigned short *)(mbuf->data); - save_flags(flags); - cli(); - for (i = 0; i < mbuf->len; i++) { - if (!pss_put_dspword(devc, *data++)) { - restore_flags(flags); - mbuf->len = i; /* feed back number of WORDs sent */ - err = __copy_to_user(arg, mbuf, sizeof(copr_msg)); + case SNDCTL_COPR_SENDMSG: + mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); + if (mbuf == NULL) + return -ENOSPC; + if (copy_from_user(mbuf, arg, sizeof(copr_msg))) { vfree(mbuf); - return err ? -EFAULT : -EIO; + return -EFAULT; } - } - restore_flags(flags); - vfree(mbuf); - return 0; - - case SNDCTL_COPR_RCVMSG: - err = 0; - mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); - if (mbuf == NULL) - return -ENOSPC; - data = (unsigned short *)mbuf->data; - save_flags(flags); - cli(); - for (i = 0; i < mbuf->len; i++) { - mbuf->len = i; /* feed back number of WORDs read */ - if (!pss_get_dspword(devc, data++)) { - if (i == 0) - err = -EIO; - break; + data = (unsigned short *)(mbuf->data); + save_flags(flags); + cli(); + for (i = 0; i < mbuf->len; i++) { + if (!pss_put_dspword(devc, *data++)) { + restore_flags(flags); + mbuf->len = i; /* feed back number of WORDs sent */ + err = copy_to_user(arg, mbuf, sizeof(copr_msg)); + vfree(mbuf); + return err ? -EFAULT : -EIO; + } } - } - restore_flags(flags); - if (__copy_to_user(arg, mbuf, sizeof(copr_msg))) - err = -EFAULT; - vfree(mbuf); - return err; - - case SNDCTL_COPR_RDATA: - if (__copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - save_flags(flags); - cli(); - if (!pss_put_dspword(devc, 0x00d0)) { - restore_flags(flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { restore_flags(flags); - return -EIO; - } - if (!pss_get_dspword(devc, &tmp)) { + vfree(mbuf); + return 0; + + case SNDCTL_COPR_RCVMSG: + err = 0; + mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); + if (mbuf == NULL) + return -ENOSPC; + data = (unsigned short *)mbuf->data; + save_flags(flags); + cli(); + for (i = 0; i < mbuf->len; i++) { + mbuf->len = i; /* feed back number of WORDs read */ + if (!pss_get_dspword(devc, data++)) { + if (i == 0) + err = -EIO; + break; + } + } restore_flags(flags); - return -EIO; - } - dbuf.parm1 = tmp; - restore_flags(flags); - if (__copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; + if (copy_to_user(arg, mbuf, sizeof(copr_msg))) + err = -EFAULT; + vfree(mbuf); + return err; - case SNDCTL_COPR_WDATA: - if (__copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - save_flags(flags); - cli(); - if (!pss_put_dspword(devc, 0x00d1)) { - restore_flags(flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) { - restore_flags(flags); - return -EIO; - } - tmp = (unsigned int)dbuf.parm2 & 0xffff; - if (!pss_put_dspword(devc, tmp)) { + case SNDCTL_COPR_RDATA: + if (copy_from_user(&dbuf, arg, sizeof(dbuf))) + return -EFAULT; + save_flags(flags); + cli(); + if (!pss_put_dspword(devc, 0x00d0)) { + restore_flags(flags); + return -EIO; + } + if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { + restore_flags(flags); + return -EIO; + } + if (!pss_get_dspword(devc, &tmp)) { + restore_flags(flags); + return -EIO; + } + dbuf.parm1 = tmp; restore_flags(flags); - return -EIO; - } - restore_flags(flags); - return 0; + if (copy_to_user(arg, &dbuf, sizeof(dbuf))) + return -EFAULT; + return 0; - case SNDCTL_COPR_WCODE: - if (__copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - save_flags(flags); - cli(); - if (!pss_put_dspword(devc, 0x00d3)) { - restore_flags(flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { - restore_flags(flags); - return -EIO; - } - tmp = (unsigned int)dbuf.parm2 & 0x00ff; - if (!pss_put_dspword(devc, tmp)) { - restore_flags(flags); - return -EIO; - } - tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff; - if (!pss_put_dspword(devc, tmp)) { + case SNDCTL_COPR_WDATA: + if (copy_from_user(&dbuf, arg, sizeof(dbuf))) + return -EFAULT; + save_flags(flags); + cli(); + if (!pss_put_dspword(devc, 0x00d1)) { + restore_flags(flags); + return -EIO; + } + if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) { + restore_flags(flags); + return -EIO; + } + tmp = (unsigned int)dbuf.parm2 & 0xffff; + if (!pss_put_dspword(devc, tmp)) { + restore_flags(flags); + return -EIO; + } restore_flags(flags); - return -EIO; - } - restore_flags(flags); - return 0; + return 0; - case SNDCTL_COPR_RCODE: - if (__copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - save_flags(flags); - cli(); - if (!pss_put_dspword(devc, 0x00d2)) { - restore_flags(flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { - restore_flags(flags); - return -EIO; - } - if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */ + case SNDCTL_COPR_WCODE: + if (copy_from_user(&dbuf, arg, sizeof(dbuf))) + return -EFAULT; + save_flags(flags); + cli(); + if (!pss_put_dspword(devc, 0x00d3)) { + restore_flags(flags); + return -EIO; + } + if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { + restore_flags(flags); + return -EIO; + } + tmp = (unsigned int)dbuf.parm2 & 0x00ff; + if (!pss_put_dspword(devc, tmp)) { + restore_flags(flags); + return -EIO; + } + tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff; + if (!pss_put_dspword(devc, tmp)) { + restore_flags(flags); + return -EIO; + } restore_flags(flags); - return -EIO; - } - dbuf.parm1 = tmp << 8; - if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */ + return 0; + + case SNDCTL_COPR_RCODE: + if (copy_from_user(&dbuf, arg, sizeof(dbuf))) + return -EFAULT; + save_flags(flags); + cli(); + if (!pss_put_dspword(devc, 0x00d2)) { + restore_flags(flags); + return -EIO; + } + if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { + restore_flags(flags); + return -EIO; + } + if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */ + restore_flags(flags); + return -EIO; + } + dbuf.parm1 = tmp << 8; + if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */ + restore_flags(flags); + return -EIO; + } + dbuf.parm1 |= tmp & 0x00ff; restore_flags(flags); - return -EIO; - } - dbuf.parm1 |= tmp & 0x00ff; - restore_flags(flags); - if (__copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; + if (copy_to_user(arg, &dbuf, sizeof(dbuf))) + return -EFAULT; + return 0; - default: - return -EINVAL; + default: + return -EINVAL; } return -EINVAL; } @@ -689,52 +667,47 @@ static coproc_operations pss_coproc_operations = &pss_data }; -void -attach_pss_mpu(struct address_info *hw_config) +void attach_pss_mpu(struct address_info *hw_config) { #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) - { - attach_mpu401(hw_config); /* Slot 1 */ - - if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ - midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; - } + attach_mpu401(hw_config); /* Slot 1 */ + if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ + midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; #endif } -int -probe_pss_mss(struct address_info *hw_config) +int probe_pss_mss(struct address_info *hw_config) { - volatile int timeout; + volatile int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 8)) - { - printk("PSS: WSS I/O port conflict\n"); + { + printk(KERN_ERR "PSS: WSS I/O port conflicts.\n"); return 0; - } + } if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) - { - printk("PSS: WSS base error.\n"); - return 0; - } + { + printk("PSS: WSS base not settable.\n"); + return 0; + } if (!set_irq(devc, CONF_WSS, hw_config->irq)) - { - printk("PSS: WSS IRQ error.\n"); - return 0; - } + { + printk("PSS: WSS IRQ allocation error.\n"); + return 0; + } if (!set_dma(devc, CONF_WSS, hw_config->dma)) - { - printk("PSS: WSS DRQ error\n"); - return 0; - } + { + printk(KERN_ERR "PSS: WSS DMA allocation error\n"); + return 0; + } /* - * For some reason the card returns 0xff in the WSS status register - * immediately after boot. Probably MIDI+SB emulation algorithm - * downloaded to the ADSP2115 spends some time initializing the card. - * Let's try to wait until it finishes this task. + * For some reason the card returns 0xff in the WSS status register + * immediately after boot. Probably MIDI+SB emulation algorithm + * downloaded to the ADSP2115 spends some time initializing the card. + * Let's try to wait until it finishes this task. */ for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + 3) & 0x3f) != 0x04; @@ -748,8 +721,7 @@ probe_pss_mss(struct address_info *hw_config) return probe_ms_sound(hw_config); } -void -attach_pss_mss(struct address_info *hw_config) +void attach_pss_mss(struct address_info *hw_config) { attach_ms_sound(hw_config); /* Slot 0 */ @@ -757,34 +729,31 @@ attach_pss_mss(struct address_info *hw_config) audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations; } -void -unload_pss(struct address_info *hw_config) +void unload_pss(struct address_info *hw_config) { } -void -unload_pss_mpu(struct address_info *hw_config) +void unload_pss_mpu(struct address_info *hw_config) { #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) unload_mpu401(hw_config); #endif } -void -unload_pss_mss(struct address_info *hw_config) +void unload_pss_mss(struct address_info *hw_config) { unload_ms_sound(hw_config); } #ifdef MODULE -int pss_io = 0x220; +int pss_io = -1; -int mss_io = 0x530; -int mss_irq = 11; -int mss_dma = 1; +int mss_io = -1; +int mss_irq = -1; +int mss_dma = -1; -int mpu_io = 0x330; +int mpu_io = -1; int mpu_irq = -1; struct address_info cfgpss = { 0 /* pss_io */, 0, -1, -1 }; @@ -798,22 +767,20 @@ MODULE_PARM(mss_dma, "i"); MODULE_PARM(mpu_io, "i"); MODULE_PARM(mpu_irq, "i"); -static int fw_load = 0; -static int pssmpu = 0, pssmss = 0; +static int fw_load = 0; +static int pssmpu = 0, pssmss = 0; /* * Load a PSS sound card module */ -int -init_module(void) +int init_module(void) { -#if 0 - if (pss_io == -1 || irq == -1 || dma == -1) { - printk("pss: dma, irq and io must be set.\n"); - return -EINVAL; + if (pss_io == -1 || mss_io == -1 || mss_irq == -1 || mss_dma == -1) { + printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n"); + return -EINVAL; } -#endif + cfgpss.io_base = pss_io; cfgmss.io_base = mss_io; @@ -823,7 +790,8 @@ init_module(void) cfgmpu.io_base = mpu_io; cfgmpu.irq = mpu_irq; - if (!pss_synth) { + if (!pss_synth) + { fw_load = 1; pss_synthLen = mod_firmware_load("/etc/sound/pss_synth", (void *) &pss_synth); } @@ -845,8 +813,7 @@ init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (fw_load && pss_synth) kfree(pss_synth); diff --git a/drivers/sound/sb_audio.c b/drivers/sound/sb_audio.c index 9a0fe3c79..bf3a8dbef 100644 --- a/drivers/sound/sb_audio.c +++ b/drivers/sound/sb_audio.c @@ -1151,14 +1151,14 @@ void sb_audio_init(sb_devc * devc, char *name) } if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - name, - driver, - sizeof(struct audio_driver), - audio_flags, - format_mask, - devc, - devc->dma8, - devc->dma8)) < 0) + name, + driver, + sizeof(struct audio_driver), + audio_flags, + format_mask, + devc, + devc->dma8, + devc->dma8)) < 0) { printk(KERN_ERR "sb: unable to install audio.\n"); return; diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index fddf74b79..941422c3f 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -69,6 +69,7 @@ int trix = 0; /* Set trix=1 to load this as support for trix */ int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ int sm_games = 0; /* Mixer - see sb_mixer.c */ int acer = 0; /* Do acer notebook init */ +int mwave_bug = 0; /* Using the dreadful mwave sb emulation */ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); @@ -80,10 +81,11 @@ MODULE_PARM(mad16, "i"); MODULE_PARM(trix, "i"); MODULE_PARM(pas2, "i"); MODULE_PARM(sm_games, "i"); +MODULE_PARM(mwave_bug, "i"); -static int sbmpu = 0; +static int sbmpu = 0; -void *smw_free = NULL; +void *smw_free = NULL; int init_module(void) { @@ -119,8 +121,7 @@ int init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (smw_free) kfree(smw_free); @@ -133,19 +134,20 @@ cleanup_module(void) #else -#ifdef SM_GAMES +#ifdef CONFIG_SM_GAMES int sm_games = 1; - #else int sm_games = 0; - #endif -#ifdef SB_ACER +#ifdef CONFIG_SB_ACER int acer = 1; - #else int acer = 0; - +#endif +#ifdef CONFIG_SB_MWAVE +int mwave_bug = 1; +#else +int mwave_bug = 0; #endif #endif #endif diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index 0f3e1e6aa..fcdcfcf2c 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -28,7 +28,6 @@ static sb_devc *detected_devc = NULL; /* For communication from probe to init */ static sb_devc *last_devc = NULL; /* For MPU401 initialization */ -static sb_devc *irq2devc[16] = {NULL}; static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6 }; @@ -123,15 +122,9 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy) int status; unsigned char src = 0xff; - sb_devc *devc = irq2devc[irq]; + sb_devc *devc = dev_id; - if (devc == NULL || devc->irq != irq) - { - DEB(printk("sbintr: Bogus interrupt IRQ%d\n", irq)); - return; - } devc->irq_ok = 1; - if (devc->model == MDL_SB16) { src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */ @@ -710,6 +703,7 @@ void sb_dsp_init(struct address_info *hw_config) sb_devc *devc; char name[100]; extern int sb_be_quiet; + extern int mwave_bug; /* * Check if we had detected a SB device earlier @@ -743,21 +737,19 @@ void sb_dsp_init(struct address_info *hw_config) if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0) { /* IRQ setup */ - if (snd_set_irq_handler(hw_config->irq, sbintr, "soundblaster", devc->osp) < 0) + if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0) { printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq); sound_unload_audiodev(devc->dev); return; } - irq2devc[hw_config->irq] = devc; devc->irq_ok = 0; if (devc->major == 4) if (!sb16_set_irq_hw(devc, devc->irq)) /* Unsupported IRQ */ { - snd_release_irq(devc->irq); + free_irq(devc->irq, devc); sound_unload_audiodev(devc->dev); - irq2devc[hw_config->irq] = NULL; return; } if ((devc->type == 0 || devc->type == MDL_ESS) && @@ -777,7 +769,7 @@ void sb_dsp_init(struct address_info *hw_config) /* Skip IRQ detection if SMP (doesn't work) */ devc->irq_ok = 1; #else - if (devc->major == 4 && devc->minor <= 11) /* Won't work */ + if ((devc->major == 4 && devc->minor <= 11 ) || mwave_bug ) /* Won't work */ devc->irq_ok = 1; else { @@ -883,6 +875,7 @@ void sb_dsp_init(struct address_info *hw_config) } } hw_config->card_subtype = devc->model; + hw_config->slots[0]=devc->dev; last_devc = devc; /* For SB MPU detection */ if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0) @@ -915,15 +908,8 @@ void sb_dsp_disable_recording(int io_base) void sb_dsp_unload(struct address_info *hw_config) { sb_devc *devc; - int irq = hw_config->irq; - if (irq < 0) - irq *= -1; - - if (irq > 2 && irq < 16) - devc = irq2devc[irq]; - else - devc = NULL; + devc = audio_devs[hw_config->slots[0]]->devc; if (devc && devc->base == hw_config->io_base) { @@ -937,12 +923,12 @@ void sb_dsp_unload(struct address_info *hw_config) } if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && devc->irq > 0) { - snd_release_irq(devc->irq); - irq2devc[devc->irq] = NULL; + free_irq(devc->irq, devc); sound_unload_mixerdev(devc->my_mixerdev); sound_unload_mididev(devc->my_mididev); sound_unload_audiodev(devc->my_dev); } + kfree(devc); } else release_region(hw_config->io_base, 16); diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index aed677c89..416737f65 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -11,7 +11,6 @@ int DMAbuf_start_output(int dev, int buff_no, int l); int DMAbuf_move_wrpointer(int dev, int l); /* int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); */ void DMAbuf_init(int dev, int dma1, int dma2); -void DMAbuf_deinit(int dev); int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); int DMAbuf_open_dma (int dev); void DMAbuf_close_dma (int dev); @@ -84,8 +83,9 @@ void MIDIbuf_init(void); /* From soundcard.c */ void request_sound_timer (int count); void sound_stop_timer(void); -int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp); -void snd_release_irq(int vect); +/* These two are about to die.. */ +int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp, void *dev_id); +void snd_release_irq(int vect, void *ptr); void sound_dma_malloc(int dev); void sound_dma_free(int dev); void conf_printf(char *name, struct address_info *hw_config); diff --git a/drivers/sound/sound_timer.c b/drivers/sound/sound_timer.c index 8a519e7e2..986668316 100644 --- a/drivers/sound/sound_timer.c +++ b/drivers/sound/sound_timer.c @@ -47,6 +47,14 @@ void reprogram_timer(void) { unsigned long usecs_per_tick; + /* + * The user is changing the timer rate before setting a timer + * slap, bad bad not allowed. + */ + + if(!tmr) + return; + usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); /* diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index e23e5486e..fe3622a73 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -26,7 +26,7 @@ #include <linux/fcntl.h> #include <linux/ctype.h> #include <linux/stddef.h> -#include <linux/kerneld.h> +#include <linux/kmod.h> #ifdef __KERNEL__ #include <asm/io.h> #include <asm/segment.h> @@ -439,7 +439,7 @@ static int sound_open(struct inode *inode, struct file *file) case SND_DEV_CTL: dev >>= 4; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { char modname[20]; sprintf(modname, "mixer%d", dev); @@ -555,14 +555,14 @@ static int sound_mixer_ioctl(int mixdev, unsigned int cmd, caddr_t arg) { if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) return -ENXIO; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD /* Try to load the mixer... */ if (mixer_devs[mixdev] == NULL) { char modname[20]; sprintf(modname, "mixer%d", mixdev); request_module(modname); } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ if (mixdev >= num_mixers || !mixer_devs[mixdev]) return -ENXIO; if (cmd == SOUND_MIXER_INFO) @@ -801,7 +801,7 @@ free_all_irqs(void) if (irqs & (1ul << i)) { printk(KERN_WARNING "Sound warning: IRQ%d was left allocated - fixed.\n", i); - snd_release_irq(i); + snd_release_irq(i, NULL); } } irqs = 0; @@ -895,14 +895,14 @@ void cleanup_module(void) } #endif -int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp) +int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp, void *dev_id) { - int retcode; - unsigned long flags; + int retcode; + unsigned long flags; save_flags(flags); cli(); - retcode = request_irq(interrupt_level, iproc, 0, name, NULL); + retcode = request_irq(interrupt_level, iproc, 0, name, dev_id); if (retcode < 0) { @@ -915,13 +915,13 @@ int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct return retcode; } -void snd_release_irq(int vect) +void snd_release_irq(int vect, void *dev_id) { if (!(irqs & (1ul << vect))) return; irqs &= ~(1ul << vect); - free_irq(vect, NULL); + free_irq(vect, dev_id); } int sound_alloc_dma(int chn, char *deviceID) diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c index 7293e9047..2e7ed2a27 100644 --- a/drivers/sound/uart401.c +++ b/drivers/sound/uart401.c @@ -9,7 +9,15 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * Alan Cox Reformatted, removed sound_mem usage, use normal Linux + * interrupt allocation. + * + * Status: + * Untested */ + #include <linux/config.h> #include <linux/module.h> @@ -19,45 +27,43 @@ #if (defined(CONFIG_UART401)||defined(CONFIG_MIDI)) || defined(MODULE) typedef struct uart401_devc - { - int base; - int irq; - int *osp; - void (*midi_input_intr) (int dev, unsigned char data); - int opened, disabled; - volatile unsigned char input_byte; - int my_dev; - int share_irq; - } +{ + int base; + int irq; + int *osp; + void (*midi_input_intr) (int dev, unsigned char data); + int opened, disabled; + volatile unsigned char input_byte; + int my_dev; + int share_irq; +} uart401_devc; static uart401_devc *detected_devc = NULL; -static uart401_devc *irq2devc[16] = -{NULL}; #define DATAPORT (devc->base) #define COMDPORT (devc->base+1) #define STATPORT (devc->base+1) -static int -uart401_status(uart401_devc * devc) +static int uart401_status(uart401_devc * devc) { return inb(STATPORT); } + #define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) -static void -uart401_cmd(uart401_devc * devc, unsigned char cmd) + +static void uart401_cmd(uart401_devc * devc, unsigned char cmd) { outb((cmd), COMDPORT); } -static int -uart401_read(uart401_devc * devc) + +static int uart401_read(uart401_devc * devc) { return inb(DATAPORT); } -static void -uart401_write(uart401_devc * devc, unsigned char byte) + +static void uart401_write(uart401_devc * devc, unsigned char byte) { outb((byte), DATAPORT); } @@ -71,30 +77,26 @@ uart401_write(uart401_devc * devc, unsigned char byte) static int reset_uart401(uart401_devc * devc); static void enter_uart_mode(uart401_devc * devc); -static void -uart401_input_loop(uart401_devc * devc) +static void uart401_input_loop(uart401_devc * devc) { while (input_avail(devc)) - { - unsigned char c = uart401_read(devc); - - if (c == MPU_ACK) - devc->input_byte = c; - else if (devc->opened & OPEN_READ && devc->midi_input_intr) - devc->midi_input_intr(devc->my_dev, c); - } + { + unsigned char c = uart401_read(devc); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr(devc->my_dev, c); + } } -void -uart401intr(int irq, void *dev_id, struct pt_regs *dummy) +void uart401intr(int irq, void *dev_id, struct pt_regs *dummy) { - uart401_devc *devc; + uart401_devc *devc = dev_id; if (irq < 1 || irq > 15) return; - devc = irq2devc[irq]; - if (devc == NULL) return; @@ -108,12 +110,12 @@ uart401_open(int dev, int mode, void (*output) (int dev) ) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; if (devc->opened) - { - return -EBUSY; - } + { + return -EBUSY; + } while (input_avail(devc)) uart401_read(devc); @@ -125,21 +127,19 @@ uart401_open(int dev, int mode, return 0; } -static void -uart401_close(int dev) +static void uart401_close(int dev) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; reset_uart401(devc); devc->opened = 0; } -static int -uart401_out(int dev, unsigned char midi_byte) +static int uart401_out(int dev, unsigned char midi_byte) { - int timeout; - unsigned long flags; - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + int timeout; + unsigned long flags; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; if (devc->disabled) return 1; @@ -163,36 +163,32 @@ uart401_out(int dev, unsigned char midi_byte) for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); if (!output_ready(devc)) - { - printk("MPU-401: Timeout - Device not responding\n"); + { + printk(KERN_WARNING "uart401: Timeout - Device not responding\n"); devc->disabled = 1; reset_uart401(devc); enter_uart_mode(devc); return 1; - } + } uart401_write(devc, midi_byte); return 1; } -static int -uart401_start_read(int dev) +static int uart401_start_read(int dev) { return 0; } -static int -uart401_end_read(int dev) +static int uart401_end_read(int dev) { return 0; } -static void -uart401_kick(int dev) +static void uart401_kick(int dev) { } -static int -uart401_buffer_status(int dev) +static int uart401_buffer_status(int dev) { return 0; } @@ -203,7 +199,9 @@ uart401_buffer_status(int dev) static struct midi_operations uart401_operations = { - {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401}, + { + "MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401 + }, &std_midi_synth, {0}, uart401_open, @@ -218,11 +216,10 @@ static struct midi_operations uart401_operations = NULL }; -static void -enter_uart_mode(uart401_devc * devc) +static void enter_uart_mode(uart401_devc * devc) { - int ok, timeout; - unsigned long flags; + int ok, timeout; + unsigned long flags; save_flags(flags); cli(); @@ -242,11 +239,10 @@ enter_uart_mode(uart401_devc * devc) restore_flags(flags); } -void -attach_uart401(struct address_info *hw_config) +void attach_uart401(struct address_info *hw_config) { - uart401_devc *devc; - char *name = "MPU-401 (UART) MIDI"; + uart401_devc *devc; + char *name = "MPU-401 (UART) MIDI"; if (hw_config->name) name = hw_config->name; @@ -255,80 +251,75 @@ attach_uart401(struct address_info *hw_config) return; - devc = (uart401_devc *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(uart401_devc))); - sound_mem_sizes[sound_nblocks] = sizeof(uart401_devc); - if (sound_nblocks < 1024) - sound_nblocks++;; + devc = (uart401_devc *) kmalloc(sizeof(uart401_devc), GFP_KERNEL); if (devc == NULL) - { - printk(KERN_WARNING "uart401: Can't allocate memory\n"); - return; - } + { + printk(KERN_WARNING "uart401: Can't allocate memory\n"); + return; + } memcpy((char *) devc, (char *) detected_devc, sizeof(uart401_devc)); detected_devc = NULL; devc->irq = hw_config->irq; if (devc->irq < 0) - { - devc->share_irq = 1; - devc->irq *= -1; - } else + { + devc->share_irq = 1; + devc->irq *= -1; + } + else devc->share_irq = 0; if (devc->irq < 1 || devc->irq > 15) + { + kfree(devc); return; + } if (!devc->share_irq) - if (snd_set_irq_handler(devc->irq, uart401intr, "MPU-401 UART", devc->osp) < 0) - { - printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq); - devc->share_irq = 1; - } - irq2devc[devc->irq] = devc; + { + if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) + { + printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq); + devc->share_irq = 1; + } + } devc->my_dev = sound_alloc_mididev(); request_region(hw_config->io_base, 4, "MPU-401 UART"); enter_uart_mode(devc); if (devc->my_dev == -1) - { - printk(KERN_INFO "uart401: Too many midi devices detected\n"); - return; - } + { + printk(KERN_INFO "uart401: Too many midi devices detected\n"); + kfree(devc); + return; + } conf_printf(name, hw_config); std_midi_synth.midi_dev = devc->my_dev; - - - midi_devs[devc->my_dev] = (struct midi_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct midi_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct midi_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + midi_devs[devc->my_dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL); if (midi_devs[devc->my_dev] == NULL) - { - printk("uart401: Failed to allocate memory\n"); - sound_unload_mididev(devc->my_dev); - return; - } + { + printk(KERN_ERR "uart401: Failed to allocate memory\n"); + sound_unload_mididev(devc->my_dev); + kfree(devc); + devc=NULL; + return; + } memcpy((char *) midi_devs[devc->my_dev], (char *) &uart401_operations, sizeof(struct midi_operations)); midi_devs[devc->my_dev]->devc = devc; - - - midi_devs[devc->my_dev]->converter = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations); - - if (sound_nblocks < 1024) - sound_nblocks++; - + midi_devs[devc->my_dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (midi_devs[devc->my_dev]->converter == NULL) - { - printk(KERN_WARNING "uart401: Failed to allocate memory\n"); - sound_unload_mididev(devc->my_dev); - return; - } + { + printk(KERN_WARNING "uart401: Failed to allocate memory\n"); + sound_unload_mididev(devc->my_dev); + kfree(midi_devs[devc->my_dev]); + kfree(devc); + devc=NULL; + return; + } memcpy((char *) midi_devs[devc->my_dev]->converter, (char *) &std_midi_synth, sizeof(struct synth_operations)); @@ -339,10 +330,9 @@ attach_uart401(struct address_info *hw_config) devc->opened = 0; } -static int -reset_uart401(uart401_devc * devc) +static int reset_uart401(uart401_devc * devc) { - int ok, timeout, n; + int ok, timeout, n; /* * Send the RESET command. Try again if no success at the first time. @@ -351,31 +341,33 @@ reset_uart401(uart401_devc * devc) ok = 0; for (n = 0; n < 2 && !ok; n++) - { - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - devc->input_byte = 0; - uart401_cmd(devc, MPU_RESET); - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (devc->input_byte == MPU_ACK) /* Interrupt */ - ok = 1; - else if (input_avail(devc)) - if (uart401_read(devc) == MPU_ACK) - ok = 1; - - } + { + for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); + devc->input_byte = 0; + uart401_cmd(devc, MPU_RESET); + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + { + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail(devc)) + { + if (uart401_read(devc) == MPU_ACK) + ok = 1; + } + } + } if (ok) - { - DEB(printk("Reset UART401 OK\n")); - } else + { + DEB(printk("Reset UART401 OK\n")); + } + else DDB(printk("Reset UART401 failed - No hardware detected.\n")); if (ok) @@ -386,14 +378,12 @@ reset_uart401(uart401_devc * devc) return ok; } -int -probe_uart401(struct address_info *hw_config) +int probe_uart401(struct address_info *hw_config) { - int ok = 0; - unsigned long flags; - + int ok = 0; + unsigned long flags; static uart401_devc hw_info; - uart401_devc *devc = &hw_info; + uart401_devc *devc = &hw_info; DDB(printk("Entered probe_uart401()\n")); @@ -422,21 +412,10 @@ probe_uart401(struct address_info *hw_config) return ok; } -void -unload_uart401(struct address_info *hw_config) +void unload_uart401(struct address_info *hw_config) { - uart401_devc *devc; - - int irq = hw_config->irq; - - if (irq < 0) - { - irq *= -1; - } - if (irq < 1 || irq > 15) - return; - - devc = irq2devc[irq]; + uart401_devc *devc; + devc = midi_devs[hw_config->slots[4]]->devc; if (devc == NULL) return; @@ -444,47 +423,47 @@ unload_uart401(struct address_info *hw_config) release_region(hw_config->io_base, 4); if (!devc->share_irq) - snd_release_irq(devc->irq); - + free_irq(devc->irq, devc); + sound_unload_mididev(hw_config->slots[4]); if (devc) + { + kfree(midi_devs[devc->my_dev]->converter); + kfree(midi_devs[devc->my_dev]); + kfree(devc); devc = NULL; - sound_unload_mididev(hw_config->slots[4]); + } } #ifdef MODULE -int io = -1; -int irq = -1; +int io = -1; +int irq = -1; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); struct address_info hw; -int -init_module(void) +int init_module(void) { /* Can be loaded either for module use or to provide functions to others */ if (io != -1 && irq != -1) - { - printk("MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); - hw.irq = irq; - hw.io_base = io; - if (probe_uart401(&hw) == 0) - return -ENODEV; - attach_uart401(&hw); - } + { + printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); + hw.irq = irq; + hw.io_base = io; + if (probe_uart401(&hw) == 0) + return -ENODEV; + attach_uart401(&hw); + } SOUND_LOCK; return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (io != -1 && irq != -1) - { - unload_uart401(&hw); - } + unload_uart401(&hw); /* FREE SYMTAB */ SOUND_LOCK_END; } diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c index 932be1846..b26e75a89 100644 --- a/drivers/sound/uart6850.c +++ b/drivers/sound/uart6850.c @@ -10,6 +10,11 @@ * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver. * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2. * + * Alan Cox: Updated for new modular code. Removed snd_* irq handling. Now + * uses native linux resources + * + * Status: Testing required + * */ #include <linux/config.h> #include <linux/module.h> @@ -297,7 +302,7 @@ int probe_uart6850(struct address_info *hw_config) uart6850_base = hw_config->io_base; uart6850_irq = hw_config->irq; - if (snd_set_irq_handler(uart6850_irq, m6850intr, "MIDI6850", uart6850_osp) < 0) + if (request_irq(uart6850_irq, m6850intr, 0, "MIDI6850", NULL) < 0) return 0; ok = reset_uart6850(); @@ -307,7 +312,7 @@ int probe_uart6850(struct address_info *hw_config) void unload_uart6850(struct address_info *hw_config) { - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); sound_unload_mididev(hw_config->slots[4]); } diff --git a/drivers/sound/v_midi.c b/drivers/sound/v_midi.c index 12c221a68..4820d5f36 100644 --- a/drivers/sound/v_midi.c +++ b/drivers/sound/v_midi.c @@ -2,15 +2,22 @@ * sound/v_midi.c * * The low level driver for the Sound Blaster DS chips. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1996 * * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. * ?? + * + * Changes + * Alan Cox Modularisation, changed memory allocations + * + * Status + * Untested */ + #include <linux/config.h> #include <linux/module.h> diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 1341d3196..872d77928 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -74,8 +74,8 @@ #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/init.h> -#ifdef CONFIG_KERNELD -#include <linux/kerneld.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> #endif #include <asm/irq.h> @@ -196,7 +196,7 @@ static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx, static struct display_switch *probe_list(struct display_switch *dispsw, struct display *disp); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD static void request_driver(struct display *disp, int is_accel); #endif static struct display_switch *fbcon_get_driver(struct display *disp); @@ -1368,7 +1368,7 @@ static struct display_switch *probe_list(struct display_switch *dispsw, } -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD static void request_driver(struct display *disp, int is_accel) { char modname[30]; @@ -1400,7 +1400,7 @@ static void request_driver(struct display *disp, int is_accel) len += sprintf(modname+len, "-%d", disp->var.accel); request_module(modname); } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ static struct display_switch *fbcon_get_driver(struct display *disp) @@ -1410,7 +1410,7 @@ static struct display_switch *fbcon_get_driver(struct display *disp) if (disp->var.accel != FB_ACCEL_NONE) { /* First try an accelerated driver */ dispsw = probe_list(accel_drivers, disp); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (!dispsw) { request_driver(disp, 1); dispsw = probe_list(accel_drivers, disp); @@ -1422,7 +1422,7 @@ static struct display_switch *fbcon_get_driver(struct display *disp) /* Then try an unaccelerated driver */ dispsw = probe_list(drivers, disp); -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (!dispsw) { request_driver(disp, 0); dispsw = probe_list(drivers, disp); |