summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/floppy.c44
-rw-r--r--drivers/block/ide-cd.c114
-rw-r--r--drivers/block/ide-cd.h4
-rw-r--r--drivers/block/ide-disk.c16
-rw-r--r--drivers/block/ide-pci.c13
-rw-r--r--drivers/block/ide.c14
-rw-r--r--drivers/block/ll_rw_blk.c9
-rw-r--r--drivers/block/md.c9
-rw-r--r--drivers/block/raid5.c5
-rw-r--r--drivers/block/rd.c41
-rw-r--r--drivers/char/ChangeLog8
-rw-r--r--drivers/char/Config.in5
-rw-r--r--drivers/char/apm_bios.c8
-rw-r--r--drivers/char/esp.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c3
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c6
-rw-r--r--drivers/char/ftape/zftape/zftape-read.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-write.c4
-rw-r--r--drivers/char/lp_m68k.c6
-rw-r--r--drivers/char/misc.c9
-rw-r--r--drivers/char/n_tty.c7
-rw-r--r--drivers/char/rtc.c57
-rw-r--r--drivers/char/serial.c4
-rw-r--r--drivers/char/tty_io.c51
-rw-r--r--drivers/char/tty_ioctl.c7
-rw-r--r--drivers/misc/parport_init.c1
-rw-r--r--drivers/misc/parport_share.c10
-rw-r--r--drivers/net/Config.in5
-rw-r--r--drivers/net/Makefile13
-rw-r--r--drivers/net/Space.c5
-rw-r--r--drivers/net/de4x5.c301
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/hp100.c4642
-rw-r--r--drivers/net/hp100.h2
-rw-r--r--drivers/net/ipddp.c71
-rw-r--r--drivers/net/ipddp.h1
-rw-r--r--drivers/net/ppp.c11
-rw-r--r--drivers/net/seeq8005.c1
-rw-r--r--drivers/net/slip.c6
-rw-r--r--drivers/net/tulip.c4
-rw-r--r--drivers/scsi/ncr53c8xx.c2
-rw-r--r--drivers/scsi/ppa.c6
-rw-r--r--drivers/scsi/scsi.c71
-rw-r--r--drivers/scsi/scsi_error.c5
-rw-r--r--drivers/scsi/scsi_obsolete.c9
-rw-r--r--drivers/scsi/scsi_queue.c5
-rw-r--r--drivers/scsi/sd.c7
-rw-r--r--drivers/scsi/wd7000.c1552
-rw-r--r--drivers/scsi/wd7000.h50
-rw-r--r--drivers/sound/Config.in2
-rw-r--r--drivers/sound/Makefile42
-rw-r--r--drivers/sound/ad1848.c113
-rw-r--r--drivers/sound/audio.c1
-rw-r--r--drivers/sound/bin2hex.c19
-rw-r--r--drivers/sound/cs4232.c17
-rw-r--r--drivers/sound/dev_table.c3
-rw-r--r--drivers/sound/dmabuf.c35
-rw-r--r--drivers/sound/gus_card.c11
-rw-r--r--drivers/sound/hex2hex.c17
-rw-r--r--drivers/sound/maui.c25
-rw-r--r--drivers/sound/midibuf.c1
-rw-r--r--drivers/sound/mpu401.c1778
-rw-r--r--drivers/sound/opl3.c78
-rw-r--r--drivers/sound/pas2_card.c4
-rw-r--r--drivers/sound/pss.c797
-rw-r--r--drivers/sound/sb_audio.c16
-rw-r--r--drivers/sound/sb_card.c22
-rw-r--r--drivers/sound/sb_common.c32
-rw-r--r--drivers/sound/sound_calls.h6
-rw-r--r--drivers/sound/sound_timer.c8
-rw-r--r--drivers/sound/soundcard.c22
-rw-r--r--drivers/sound/uart401.c337
-rw-r--r--drivers/sound/uart6850.c9
-rw-r--r--drivers/sound/v_midi.c11
-rw-r--r--drivers/video/fbcon.c14
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);