diff options
Diffstat (limited to 'drivers')
473 files changed, 28793 insertions, 25189 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index a9e4c5f..f0878b2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -66,6 +66,7 @@ obj-y += i2c/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/ +obj-$(CONFIG_WATCHDOG) += char/watchdog/ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ diff --git a/drivers/acorn/README b/drivers/acorn/README deleted file mode 100644 index d399c09..0000000 --- a/drivers/acorn/README +++ /dev/null @@ -1 +0,0 @@ -Drivers for the ACORN "podule" ARM specific bus. diff --git a/drivers/acorn/block/Kconfig b/drivers/acorn/block/Kconfig deleted file mode 100644 index a0ff25e..0000000 --- a/drivers/acorn/block/Kconfig +++ /dev/null @@ -1,36 +0,0 @@ -# -# Block device driver configuration -# - -menu "Acorn-specific block devices" - depends on ARCH_ARC || ARCH_A5K - -config BLK_DEV_FD1772 - tristate "Old Archimedes floppy (1772) support" - depends on ARCH_ARC || ARCH_A5K - help - Support the floppy drive on the Acorn Archimedes (A300, A4x0, A540, - R140 and R260) series of computers; it supports only 720K floppies - at the moment. If you don't have one of these machines just answer - N. - -config BLK_DEV_MFM - tristate "MFM harddisk support" - depends on ARCH_ARC || ARCH_A5K - help - Support the MFM hard drives on the Acorn Archimedes both - on-board the A4x0 motherboards and via the Acorn MFM podules. - Drives up to 64MB are supported. If you haven't got one of these - machines or drives just say N. - -config BLK_DEV_MFM_AUTODETECT - bool "Autodetect hard drive geometry" - depends on BLK_DEV_MFM - help - If you answer Y, the MFM code will attempt to automatically detect - the cylinders/heads/sectors count on your hard drive. WARNING: This - sometimes doesn't work and it also does some dodgy stuff which - potentially might damage your drive. - -endmenu - diff --git a/drivers/acorn/block/Makefile b/drivers/acorn/block/Makefile deleted file mode 100644 index 38a9afe..0000000 --- a/drivers/acorn/block/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the Acorn block device drivers. -# - -fd1772_mod-objs := fd1772.o fd1772dma.o -mfmhd_mod-objs := mfmhd.o mfm.o - -obj-$(CONFIG_BLK_DEV_FD1772) += fd1772_mod.o -obj-$(CONFIG_BLK_DEV_MFM) += mfmhd_mod.o diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c deleted file mode 100644 index 423ed08..0000000 --- a/drivers/acorn/block/fd1772.c +++ /dev/null @@ -1,1604 +0,0 @@ -/* - * linux/kernel/arch/arm/drivers/block/fd1772.c - * Based on ataflop.c in the m68k Linux - * Copyright (C) 1993 Greg Harp - * Atari Support by Bjoern Brauel, Roman Hodek - * Archimedes Support by Dave Gilbert (linux@treblig.org) - * - * Big cleanup Sep 11..14 1994 Roman Hodek: - * - Driver now works interrupt driven - * - Support for two drives; should work, but I cannot test that :-( - * - Reading is done in whole tracks and buffered to speed up things - * - Disk change detection and drive deselecting after motor-off - * similar to TOS - * - Autodetection of disk format (DD/HD); untested yet, because I - * don't have an HD drive :-( - * - * Fixes Nov 13 1994 Martin Schaller: - * - Autodetection works now - * - Support for 5 1/4" disks - * - Removed drive type (unknown on atari) - * - Do seeks with 8 Mhz - * - * Changes by Andreas Schwab: - * - After errors in multiple read mode try again reading single sectors - * (Feb 1995): - * - Clean up error handling - * - Set blk_size for proper size checking - * - Initialize track register when testing presence of floppy - * - Implement some ioctl's - * - * Changes by Torsten Lang: - * - When probing the floppies we should add the FDC1772CMDADD_H flag since - * the FDC1772 will otherwise wait forever when no disk is inserted... - * - * Things left to do: - * - Formatting - * - Maybe a better strategy for disk change detection (does anyone - * know one?) - * - There are some strange problems left: The strangest one is - * that, at least on my TT (4+4MB), the first 2 Bytes of the last - * page of the TT-Ram (!) change their contents (some bits get - * set) while a floppy DMA is going on. But there are no accesses - * to these memory locations from the kernel... (I tested that by - * making the page read-only). I cannot explain what's going on... - * - Sometimes the drive-change-detection stops to work. The - * function is still called, but the WP bit always reads as 0... - * Maybe a problem with the status reg mode or a timing problem. - * Note 10/12/94: The change detection now seems to work reliably. - * There is no proof, but I've seen no hang for a long time... - * - * ARCHIMEDES changes: (gilbertd@cs.man.ac.uk) - * 26/12/95 - Changed all names starting with FDC to FDC1772 - * Removed all references to clock speed of FDC - we're stuck with 8MHz - * Modified disk_type structure to remove HD formats - * - * 7/ 1/96 - Wrote FIQ code, removed most remaining atariisms - * - * 13/ 1/96 - Well I think its read a single sector; but there is a problem - * fd_rwsec_done which is called in FIQ mode starts another transfer - * off (in fd_rwsec) while still in FIQ mode. Because its still in - * FIQ mode it can't service the DMA and loses data. So need to - * heavily restructure. - * 14/ 1/96 - Found that the definitions of the register numbers of the - * FDC were multiplied by 2 in the header for the 16bit words - * of the atari so half the writes were going in the wrong place. - * Also realised that the FIQ entry didn't make any attempt to - * preserve registers or return correctly; now in assembler. - * - * 11/ 2/96 - Hmm - doesn't work on real machine. Auto detect doesn't - * and hacking that past seems to wait forever - check motor - * being turned on. - * - * 17/ 2/96 - still having problems - forcing track to -1 when selecting - * new drives seems to allow it to read first few sectors - * but then we get solid hangs at apparently random places - * which change depending what is happening. - * - * 9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35 - * A lot of fiddling in DMA stuff. Having problems with it - * constnatly thinking its timeing out. Ah - its timeout - * was set to (6*HZ) rather than jiffies+(6*HZ). Now giving - * duff data! - * - * 5/ 4/96 - Made it use the new IOC_ macros rather than *ioc - * Hmm - giving unexpected FIQ and then timeouts - * 18/ 8/96 - Ran through indent -kr -i8 - * Some changes to disc change detect; don't know how well it - * works. - * 24/ 8/96 - Put all the track buffering code back in from the atari - * code - I wonder if it will still work... No :-) - * Still works if I turn off track buffering. - * 25/ 8/96 - Changed the timer expires that I'd added back to be - * jiffies + ....; and it all sprang to life! Got 2.8K/sec - * off a cp -r of a 679K disc (showed 94% cpu usage!) - * (PC gets 14.3K/sec - 0% CPU!) Hmm - hard drive corrupt! - * Also perhaps that compile was with cache off. - * changed cli in fd_readtrack_check to cliIF - * changed vmallocs to kmalloc (whats the difference!!) - * Removed the busy wait loop in do_fd_request and replaced - * by a routine on tq_immediate; only 11% cpu on a dd off the - * raw disc - but the speed is the same. - * 1/ 9/96 - Idea (failed!) - set the 'disable spin-up sequence' - * when we read the track if we know the motor is on; didn't - * help - perhaps we have to do it in stepping as well. - * Nope. Still doesn't help. - * Hmm - what seems to be happening is that fd_readtrack_check - * is never getting called. Its job is to terminate the read - * just after we think we should have got the data; otherwise - * the fdc takes 1 second to timeout; which is what's happening - * Now I can see 'readtrack_timer' being set (which should do the - * call); but it never seems to be called - hmm! - * OK - I've moved the check to my tq_immediate code - - * and it WORKS! 13.95K/second at 19% CPU. - * I wish I knew why that timer didn't work..... - * - * 16/11/96 - Fiddled and frigged for 2.0.18 - * - * DAG 30/01/99 - Started frobbing for 2.2.1 - * DAG 20/06/99 - A little more frobbing: - * Included include/asm/uaccess.h for get_user/put_user - * - * DAG 1/09/00 - Dusted off for 2.4.0-test7 - * MAX_SECTORS was name clashing so it is now FD1772_... - * Minor parameter, name layouts for 2.4.x differences - */ - -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/fcntl.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/timer.h> -#include <linux/workqueue.h> -#include <linux/fd.h> -#include <linux/fd1772.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/mm.h> -#include <linux/bitops.h> - -#include <asm/arch/oldlatches.h> -#include <asm/dma.h> -#include <asm/hardware.h> -#include <asm/hardware/ioc.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mach-types.h> -#include <asm/pgtable.h> -#include <asm/system.h> -#include <asm/uaccess.h> - - -/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with - * little additional rework in this file). But I'm not yet sure if - * some other code depends on the number of floppies... (It is defined - * in a public header!) - */ -#if 0 -#undef FD_MAX_UNITS -#define FD_MAX_UNITS 2 -#endif - -/* Ditto worries for Arc - DAG */ -#define FD_MAX_UNITS 4 -#define TRACKBUFFER 0 -/*#define DEBUG*/ - -#ifdef DEBUG -#define DPRINT(a) printk a -#else -#define DPRINT(a) -#endif - -static struct request_queue *floppy_queue; - -#define MAJOR_NR FLOPPY_MAJOR -#define FLOPPY_DMA 0 -#define DEVICE_NAME "floppy" -#define QUEUE (floppy_queue) -#define CURRENT elv_next_request(floppy_queue) - -/* Disk types: DD */ -static struct archy_disk_type { - const char *name; - unsigned spt; /* sectors per track */ - unsigned blocks; /* total number of blocks */ - unsigned stretch; /* track doubling ? */ -} disk_type[] = { - - { "d360", 9, 720, 0 }, /* 360kB diskette */ - { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */ - { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */ - /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors - - DAG - can't see how type detect can distinguish this - from 720K until it reads block 4 by which time its too late! */ -}; - -#define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type)) - -/* - * Maximum disk size (in kilobytes). This default is used whenever the - * current disk size is unknown. - */ -#define MAX_DISK_SIZE 720 - -static struct gendisk *disks[FD_MAX_UNIT]; - -/* current info on each unit */ -static struct archy_floppy_struct { - int connected; /* !=0 : drive is connected */ - int autoprobe; /* !=0 : do autoprobe */ - - struct archy_disk_type *disktype; /* current type of disk */ - - int track; /* current head position or -1 - * if unknown */ - unsigned int steprate; /* steprate setting */ - unsigned int wpstat; /* current state of WP signal - * (for disk change detection) */ -} unit[FD_MAX_UNITS]; - -/* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which - is an assembler routine */ -extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */ -extern volatile int fdc1772_comendstatus; -extern volatile int fdc1772_fdc_int_done; - -#define FDC1772BASE ((0x210000>>2)|0x80000000) - -#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2)) - -/* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather - than the #def below - well simple - the #def won't compile - and I - don't understand why (__outwc not defined) */ -/* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility - with the ST version of fd1772.h */ -/*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */ -void FDC1772_WRITE(int reg, unsigned char val) -{ - if (reg == FDC1772REG_CMD) { - DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies)); - if (fdc1772_fdc_int_done) { - DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n")); - fdc1772_fdc_int_done = 0; - }; - }; - outb(val, (reg / 2) + FDC1772BASE); -}; - -#define FD1772_MAX_SECTORS 22 - -unsigned char *DMABuffer; /* buffer for writes */ -/*static unsigned long PhysDMABuffer; *//* physical address */ -/* DAG: On Arc we just go straight for the DMA buffer */ -#define PhysDMABuffer DMABuffer - -#ifdef TRACKBUFFER -unsigned char *TrackBuffer; /* buffer for reads */ -#define PhysTrackBuffer TrackBuffer /* physical address */ -static int BufferDrive, BufferSide, BufferTrack; -static int read_track; /* non-zero if we are reading whole tracks */ - -#define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512) -#define IS_BUFFERED(drive,side,track) \ - (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track)) -#endif - -/* - * These are global variables, as that's the easiest way to give - * information to interrupts. They are the data used for the current - * request. - */ -static int SelectedDrive = 0; -static int ReqCmd, ReqBlock; -static int ReqSide, ReqTrack, ReqSector, ReqCnt; -static int HeadSettleFlag = 0; -static unsigned char *ReqData, *ReqBuffer; -static int MotorOn = 0, MotorOffTrys; - -/* Synchronization of FDC1772 access. */ -static volatile int fdc_busy = 0; -static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); - - -/* long req'd for set_bit --RR */ -static unsigned long changed_floppies = 0xff, fake_change = 0; -#define CHECK_CHANGE_DELAY HZ/2 - -/* DAG - increased to 30*HZ - not sure if this is the correct thing to do */ -#define FD_MOTOR_OFF_DELAY (10*HZ) -#define FD_MOTOR_OFF_MAXTRY (10*20) - -#define FLOPPY_TIMEOUT (6*HZ) -#define RECALIBRATE_ERRORS 4 /* After this many errors the drive - * will be recalibrated. */ -#define MAX_ERRORS 8 /* After this many errors the driver - * will give up. */ - -#define START_MOTOR_OFF_TIMER(delay) \ - do { \ - motor_off_timer.expires = jiffies + (delay); \ - add_timer( &motor_off_timer ); \ - MotorOffTrys = 0; \ - } while(0) - -#define START_CHECK_CHANGE_TIMER(delay) \ - do { \ - mod_timer(&fd_timer, jiffies + (delay)); \ - } while(0) - -#define START_TIMEOUT() \ - do { \ - mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \ - } while(0) - -#define STOP_TIMEOUT() \ - do { \ - del_timer( &timeout_timer ); \ - } while(0) - -#define ENABLE_IRQ() enable_irq(FIQ_FD1772+64); - -#define DISABLE_IRQ() disable_irq(FIQ_FD1772+64); - -static void fd1772_checkint(void); - -DECLARE_WORK(fd1772_tq, (void *)fd1772_checkint, NULL); -/* - * The driver is trying to determine the correct media format - * while Probing is set. fd_rwsec_done() clears it after a - * successful access. - */ -static int Probing = 0; - -/* This flag is set when a dummy seek is necessary to make the WP - * status bit accessible. - */ -static int NeedSeek = 0; - - -/***************************** Prototypes *****************************/ - -static void fd_select_side(int side); -static void fd_select_drive(int drive); -static void fd_deselect(void); -static void fd_motor_off_timer(unsigned long dummy); -static void check_change(unsigned long dummy); -static void floppy_irqconsequencehandler(void); -static void fd_error(void); -static void do_fd_action(int drive); -static void fd_calibrate(void); -static void fd_calibrate_done(int status); -static void fd_seek(void); -static void fd_seek_done(int status); -static void fd_rwsec(void); -#ifdef TRACKBUFFER -static void fd_readtrack_check( unsigned long dummy ); -#endif -static void fd_rwsec_done(int status); -static void fd_times_out(unsigned long dummy); -static void finish_fdc(void); -static void finish_fdc_done(int dummy); -static void floppy_off(unsigned int nr); -static void setup_req_params(int drive); -static void redo_fd_request(void); -static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int - cmd, unsigned long param); -static void fd_probe(int drive); -static int fd_test_drive_present(int drive); -static void config_types(void); -static int floppy_open(struct inode *inode, struct file *filp); -static int floppy_release(struct inode *inode, struct file *filp); -static void do_fd_request(request_queue_t *); - -/************************* End of Prototypes **************************/ - -static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0); - -#ifdef TRACKBUFFER -static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0); -#endif - -static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0); - -static DEFINE_TIMER(fd_timer, check_change, 0, 0); - -/* DAG: Haven't got a clue what this is? */ -int stdma_islocked(void) -{ - return 0; -}; - -/* Select the side to use. */ - -static void fd_select_side(int side) -{ - oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL); -} - - -/* Select a drive, update the FDC1772's track register - */ - -static void fd_select_drive(int drive) -{ -#ifdef DEBUG - printk("fd_select_drive:%d\n", drive); -#endif - /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */ - oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0); - - if (drive == SelectedDrive) - return; - - oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive)); - - /* restore track register to saved value */ - FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track); - udelay(25); - - SelectedDrive = drive; -} - - -/* Deselect both drives. */ - -static void fd_deselect(void) -{ - unsigned long flags; - - DPRINT(("fd_deselect\n")); - - oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE); - - SelectedDrive = -1; -} - - -/* This timer function deselects the drives when the FDC1772 switched the - * motor off. The deselection cannot happen earlier because the FDC1772 - * counts the index signals, which arrive only if one drive is selected. - */ - -static void fd_motor_off_timer(unsigned long dummy) -{ - unsigned long flags; - unsigned char status; - int delay; - - del_timer(&motor_off_timer); - - if (SelectedDrive < 0) - /* no drive selected, needn't deselect anyone */ - return; - - save_flags(flags); - cli(); - - if (fdc_busy) /* was stdma_islocked */ - goto retry; - - status = FDC1772_READ(FDC1772REG_STATUS); - - if (!(status & 0x80)) { - /* - * motor already turned off by FDC1772 -> deselect drives - * In actual fact its this deselection which turns the motor - * off on the Arc, since the motor control is actually on - * Latch A - */ - DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n")); - fd_deselect(); - MotorOn = 0; - restore_flags(flags); - return; - } - /* not yet off, try again */ - -retry: - restore_flags(flags); - /* Test again later; if tested too often, it seems there is no disk - * in the drive and the FDC1772 will leave the motor on forever (or, - * at least until a disk is inserted). So we'll test only twice - * per second from then on... - */ - delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ? - (++MotorOffTrys, HZ / 20) : HZ / 2; - START_MOTOR_OFF_TIMER(delay); -} - - -/* This function is repeatedly called to detect disk changes (as good - * as possible) and keep track of the current state of the write protection. - */ - -static void check_change(unsigned long dummy) -{ - static int drive = 0; - - unsigned long flags; - int stat; - - if (fdc_busy) - return; /* Don't start poking about if the fdc is busy */ - - return; /* let's just forget it for the mo DAG */ - - if (++drive > 1 || !unit[drive].connected) - drive = 0; - - save_flags(flags); - cli(); - - if (!stdma_islocked()) { - stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT); - - /* The idea here is that if the write protect line has changed then - the disc must have changed */ - if (stat != unit[drive].wpstat) { - DPRINT(("wpstat[%d] = %d\n", drive, stat)); - unit[drive].wpstat = stat; - set_bit(drive, &changed_floppies); - } - } - restore_flags(flags); - - START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY); -} - - -/* Handling of the Head Settling Flag: This flag should be set after each - * seek operation, because we don't use seeks with verify. - */ - -static inline void set_head_settle_flag(void) -{ - HeadSettleFlag = FDC1772CMDADD_E; -} - -static inline int get_head_settle_flag(void) -{ - int tmp = HeadSettleFlag; - HeadSettleFlag = 0; - return (tmp); -} - - - - -/* General Interrupt Handling */ - -static inline void copy_buffer(void *from, void *to) -{ - ulong *p1 = (ulong *) from, *p2 = (ulong *) to; - int cnt; - - for (cnt = 512 / 4; cnt; cnt--) - *p2++ = *p1++; -} - -static void (*FloppyIRQHandler) (int status) = NULL; - -static void floppy_irqconsequencehandler(void) -{ - unsigned char status; - void (*handler) (int); - - fdc1772_fdc_int_done = 0; - - handler = FloppyIRQHandler; - FloppyIRQHandler = NULL; - - if (handler) { - nop(); - status = (unsigned char) fdc1772_comendstatus; - DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler)); - handler(status); - } else { - DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus)); - } - DPRINT(("FDC1772 irq: end of floppy_irq\n")); -} - - -/* Error handling: If some error happened, retry some times, then - * recalibrate, then try again, and fail after MAX_ERRORS. - */ - -static void fd_error(void) -{ - printk("FDC1772: fd_error\n"); - /*panic("fd1772: fd_error"); *//* DAG tmp */ - if (!CURRENT) - return; - CURRENT->errors++; - if (CURRENT->errors >= MAX_ERRORS) { - printk("fd%d: too many errors.\n", SelectedDrive); - end_request(CURRENT, 0); - } else if (CURRENT->errors == RECALIBRATE_ERRORS) { - printk("fd%d: recalibrating\n", SelectedDrive); - if (SelectedDrive != -1) - unit[SelectedDrive].track = -1; - } - redo_fd_request(); -} - - - -#define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0) - - -/* do_fd_action() is the general procedure for a fd request: All - * required parameter settings (drive select, side select, track - * position) are checked and set if needed. For each of these - * parameters and the actual reading or writing exist two functions: - * one that starts the setting (or skips it if possible) and one - * callback for the "done" interrupt. Each done func calls the next - * set function to propagate the request down to fd_rwsec_done(). - */ - -static void do_fd_action(int drive) -{ - struct request *req; - DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track)); - -#ifdef TRACKBUFFER -repeat: - - if (IS_BUFFERED( drive, ReqSide, ReqTrack )) { - req = CURRENT; - if (ReqCmd == READ) { - copy_buffer( SECTOR_BUFFER(ReqSector), ReqData ); - if (++ReqCnt < req->current_nr_sectors) { - /* read next sector */ - setup_req_params( drive ); - goto repeat; - } else { - /* all sectors finished */ - req->nr_sectors -= req->current_nr_sectors; - req->sector += req->current_nr_sectors; - end_request(req, 1); - redo_fd_request(); - return; - } - } else { - /* cmd == WRITE, pay attention to track buffer - * consistency! */ - copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) ); - } - } -#endif - - if (SelectedDrive != drive) { - /*unit[drive].track = -1; DAG */ - fd_select_drive(drive); - }; - - - if (unit[drive].track == -1) - fd_calibrate(); - else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch) - fd_seek(); - else - fd_rwsec(); -} - - -/* Seek to track 0 if the current track is unknown */ - -static void fd_calibrate(void) -{ - DPRINT(("fd_calibrate\n")); - if (unit[SelectedDrive].track >= 0) { - fd_calibrate_done(0); - return; - } - DPRINT(("fd_calibrate (after track compare)\n")); - SET_IRQ_HANDLER(fd_calibrate_done); - /* we can't verify, since the speed may be incorrect */ - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate); - - NeedSeek = 1; - MotorOn = 1; - START_TIMEOUT(); - /* wait for IRQ */ -} - - -static void fd_calibrate_done(int status) -{ - DPRINT(("fd_calibrate_done()\n")); - STOP_TIMEOUT(); - - /* set the correct speed now */ - if (status & FDC1772STAT_RECNF) { - printk("fd%d: restore failed\n", SelectedDrive); - fd_error(); - } else { - unit[SelectedDrive].track = 0; - fd_seek(); - } -} - - -/* Seek the drive to the requested track. The drive must have been - * calibrated at some point before this. - */ - -static void fd_seek(void) -{ - unsigned long flags; - DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack, - unit[SelectedDrive].track)); - if (unit[SelectedDrive].track == ReqTrack << - unit[SelectedDrive].disktype->stretch) { - fd_seek_done(0); - return; - } - FDC1772_WRITE(FDC1772REG_DATA, ReqTrack << - unit[SelectedDrive].disktype->stretch); - udelay(25); - save_flags(flags); - clf(); - SET_IRQ_HANDLER(fd_seek_done); - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate | - /* DAG */ - (MotorOn?FDC1772CMDADD_H:0)); - - restore_flags(flags); - MotorOn = 1; - set_head_settle_flag(); - START_TIMEOUT(); - /* wait for IRQ */ -} - - -static void fd_seek_done(int status) -{ - DPRINT(("fd_seek_done()\n")); - STOP_TIMEOUT(); - - /* set the correct speed */ - if (status & FDC1772STAT_RECNF) { - printk("fd%d: seek error (to track %d)\n", - SelectedDrive, ReqTrack); - /* we don't know exactly which track we are on now! */ - unit[SelectedDrive].track = -1; - fd_error(); - } else { - unit[SelectedDrive].track = ReqTrack << - unit[SelectedDrive].disktype->stretch; - NeedSeek = 0; - fd_rwsec(); - } -} - - -/* This does the actual reading/writing after positioning the head - * over the correct track. - */ - -#ifdef TRACKBUFFER -static int MultReadInProgress = 0; -#endif - - -static void fd_rwsec(void) -{ - unsigned long paddr, flags; - unsigned int rwflag, old_motoron; - unsigned int track; - - DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r')); - if (ReqCmd == WRITE) { - /*cache_push( (unsigned long)ReqData, 512 ); */ - paddr = (unsigned long) ReqData; - rwflag = 0x100; - } else { - paddr = (unsigned long) PhysDMABuffer; -#ifdef TRACKBUFFER - if (read_track) - paddr = (unsigned long)PhysTrackBuffer; -#endif - rwflag = 0; - } - - DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag, - ReqSector, FDC1772_READ(FDC1772REG_TRACK))); - fd_select_side(ReqSide); - - /*DPRINT(("fd_rwsec() before start sector \n")); */ - /* Start sector of this operation */ -#ifdef TRACKBUFFER - FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 ); -#else - FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector ); -#endif - - /* Cheat for track if stretch != 0 */ - if (unit[SelectedDrive].disktype->stretch) { - track = FDC1772_READ(FDC1772REG_TRACK); - FDC1772_WRITE(FDC1772REG_TRACK, track >> - unit[SelectedDrive].disktype->stretch); - } - udelay(25); - - DPRINT(("fd_rwsec() before setup DMA \n")); - /* Setup DMA - Heavily modified by DAG */ - save_flags(flags); - clf(); - disable_dma(FLOPPY_DMA); - set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ); - set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */ -#ifdef TRACKBUFFER - set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512); -#else - set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */ -#endif - SET_IRQ_HANDLER(fd_rwsec_done); - /* Turn on dma int */ - enable_dma(FLOPPY_DMA); - /* Now give it something to do */ - FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) : -#ifdef TRACKBUFFER - (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) | - /* Hmm - the idea here is to stop the FDC spinning the disc - up when we know that we already still have it spinning */ - (MotorOn?FDC1772CMDADD_H:0)) -#else - FDC1772CMD_RDSEC -#endif - )); - - restore_flags(flags); - DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags)); - /*sti(); *//* DAG - Hmm */ - /* Hmm - should do something DAG */ - old_motoron = MotorOn; - MotorOn = 1; - NeedSeek = 1; - - /* wait for interrupt */ - -#ifdef TRACKBUFFER - if (read_track) { - /* - * If reading a whole track, wait about one disk rotation and - * then check if all sectors are read. The FDC will even - * search for the first non-existant sector and need 1 sec to - * recognise that it isn't present :-( - */ - /* 1 rot. + 5 rot.s if motor was off */ - mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ)); - DPRINT(("Setting readtrack_timer to %d @ %d\n", - readtrack_timer.expires,jiffies)); - MultReadInProgress = 1; - } -#endif - - /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */ - START_TIMEOUT(); - /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */ -} - - -#ifdef TRACKBUFFER - -static void fd_readtrack_check(unsigned long dummy) -{ - unsigned long flags, addr; - extern unsigned char *fdc1772_dataaddr; - - DPRINT(("fd_readtrack_check @ %d\n",jiffies)); - - save_flags(flags); - clf(); - - del_timer( &readtrack_timer ); - - if (!MultReadInProgress) { - /* This prevents a race condition that could arise if the - * interrupt is triggered while the calling of this timer - * callback function takes place. The IRQ function then has - * already cleared 'MultReadInProgress' when control flow - * gets here. - */ - restore_flags(flags); - return; - } - - /* get the current DMA address */ - addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */ - DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer)); - - if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) { - /* already read enough data, force an FDC interrupt to stop - * the read operation - */ - SET_IRQ_HANDLER( NULL ); - restore_flags(flags); - DPRINT(("fd_readtrack_check(): done\n")); - FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI ); - udelay(25); - - /* No error until now -- the FDC would have interrupted - * otherwise! - */ - fd_rwsec_done( 0 ); - } else { - /* not yet finished, wait another tenth rotation */ - restore_flags(flags); - DPRINT(("fd_readtrack_check(): not yet finished\n")); - readtrack_timer.expires = jiffies + HZ/5/10; - add_timer( &readtrack_timer ); - } -} - -#endif - -static void fd_rwsec_done(int status) -{ - unsigned int track; - - DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies)); - -#ifdef TRACKBUFFER - if (read_track && !MultReadInProgress) - return; - - MultReadInProgress = 0; - - STOP_TIMEOUT(); - - if (read_track) - del_timer( &readtrack_timer ); -#endif - - - /* Correct the track if stretch != 0 */ - if (unit[SelectedDrive].disktype->stretch) { - track = FDC1772_READ(FDC1772REG_TRACK); - FDC1772_WRITE(FDC1772REG_TRACK, track << - unit[SelectedDrive].disktype->stretch); - } - if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) { - printk("fd%d: is write protected\n", SelectedDrive); - goto err_end; - } - if ((status & FDC1772STAT_RECNF) -#ifdef TRACKBUFFER - /* RECNF is no error after a multiple read when the FDC - * searched for a non-existant sector! - */ - && !(read_track && - FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt) -#endif - ) { - if (Probing) { - if (unit[SelectedDrive].disktype > disk_type) { - /* try another disk type */ - unit[SelectedDrive].disktype--; - set_capacity(disks[SelectedDrive], - unit[SelectedDrive].disktype->blocks); - } else - Probing = 0; - } else { - /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ - if (unit[SelectedDrive].autoprobe) { - unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1; - set_capacity(disks[SelectedDrive], - unit[SelectedDrive].disktype->blocks); - Probing = 1; - } - } - if (Probing) { - setup_req_params(SelectedDrive); -#ifdef TRACKBUFFER - BufferDrive = -1; -#endif - do_fd_action(SelectedDrive); - return; - } - printk("fd%d: sector %d not found (side %d, track %d)\n", - SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack); - goto err_end; - } - if (status & FDC1772STAT_CRC) { - printk("fd%d: CRC error (side %d, track %d, sector %d)\n", - SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR)); - goto err_end; - } - if (status & FDC1772STAT_LOST) { - printk("fd%d: lost data (side %d, track %d, sector %d)\n", - SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR)); - goto err_end; - } - Probing = 0; - - if (ReqCmd == READ) { -#ifdef TRACKBUFFER - if (!read_track) { - /*cache_clear (PhysDMABuffer, 512);*/ - copy_buffer (DMABuffer, ReqData); - } else { - /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/ - BufferDrive = SelectedDrive; - BufferSide = ReqSide; - BufferTrack = ReqTrack; - copy_buffer (SECTOR_BUFFER (ReqSector), ReqData); - } -#else - /*cache_clear( PhysDMABuffer, 512 ); */ - copy_buffer(DMABuffer, ReqData); -#endif - } - if (++ReqCnt < CURRENT->current_nr_sectors) { - /* read next sector */ - setup_req_params(SelectedDrive); - do_fd_action(SelectedDrive); - } else { - /* all sectors finished */ - CURRENT->nr_sectors -= CURRENT->current_nr_sectors; - CURRENT->sector += CURRENT->current_nr_sectors; - end_request(CURRENT, 1); - redo_fd_request(); - } - return; - -err_end: -#ifdef TRACKBUFFER - BufferDrive = -1; -#endif - - fd_error(); -} - - -static void fd_times_out(unsigned long dummy) -{ - SET_IRQ_HANDLER(NULL); - /* If the timeout occurred while the readtrack_check timer was - * active, we need to cancel it, else bad things will happen */ - del_timer( &readtrack_timer ); - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); - udelay(25); - - printk("floppy timeout\n"); - STOP_TIMEOUT(); /* hmm - should we do this ? */ - fd_error(); -} - - -/* The (noop) seek operation here is needed to make the WP bit in the - * FDC1772 status register accessible for check_change. If the last disk - * operation would have been a RDSEC, this bit would always read as 0 - * no matter what :-( To save time, the seek goes to the track we're - * already on. - */ - -static void finish_fdc(void) -{ - /* DAG - just try without this dummy seek! */ - finish_fdc_done(0); - return; - - if (!NeedSeek) { - finish_fdc_done(0); - } else { - DPRINT(("finish_fdc: dummy seek started\n")); - FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track); - SET_IRQ_HANDLER(finish_fdc_done); - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK); - MotorOn = 1; - START_TIMEOUT(); - /* we must wait for the IRQ here, because the ST-DMA is - * released immediately afterwards and the interrupt may be - * delivered to the wrong driver. - */ - } -} - - -static void finish_fdc_done(int dummy) -{ - unsigned long flags; - - DPRINT(("finish_fdc_done entered\n")); - STOP_TIMEOUT(); - NeedSeek = 0; - - if (timer_pending(&fd_timer) && - time_after(jiffies + 5, fd_timer.expires)) - /* If the check for a disk change is done too early after this - * last seek command, the WP bit still reads wrong :-(( - */ - mod_timer(&fd_timer, jiffies + 5); - else { - /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ - }; - del_timer(&motor_off_timer); - START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY); - - save_flags(flags); - cli(); - /* stdma_release(); - not sure if I should do something DAG */ - fdc_busy = 0; - wake_up(&fdc_wait); - restore_flags(flags); - - DPRINT(("finish_fdc() finished\n")); -} - - -/* Prevent "aliased" accesses. */ -static int fd_ref[4]; -static int fd_device[4]; - -/* dummy for blk.h */ -static void floppy_off(unsigned int nr) -{ -} - - -/* On the old arcs write protect depends on the particular model - of machine. On the A310, R140, and A440 there is a disc changed - detect, however on the A4x0/1 range there is not. There - is nothing to tell you which machine your on. - At the moment I'm just marking changed always. I've - left the Atari's 'change on write protect change' code in this - part (but nothing sets it). - RiscOS apparently checks the disc serial number etc. to detect changes - - but if it sees a disc change line go high (?) it flips to using - it. Well maybe I'll add that in the future (!?) -*/ -static int check_floppy_change(struct gendisk *disk) -{ - struct archy_floppy_struct *p = disk->private_data; - unsigned int drive = p - unit; - - if (test_bit(drive, &fake_change)) { - /* simulated change (e.g. after formatting) */ - return 1; - } - if (test_bit(drive, &changed_floppies)) { - /* surely changed (the WP signal changed at least once) */ - return 1; - } - if (p->wpstat) { - /* WP is on -> could be changed: to be sure, buffers should be - * invalidated... - */ - return 1; - } - return 1; /* DAG - was 0 */ -} - -static int floppy_revalidate(struct gendisk *disk) -{ - struct archy_floppy_struct *p = disk->private_data; - unsigned int drive = p - unit; - - if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change) - || unit[drive].disktype == 0) { -#ifdef TRACKBUFFER - BufferDrive = -1; -#endif - clear_bit(drive, &fake_change); - clear_bit(drive, &changed_floppies); - p->disktype = 0; - } - return 0; -} - -/* This sets up the global variables describing the current request. */ - -static void setup_req_params(int drive) -{ - int block = ReqBlock + ReqCnt; - - ReqTrack = block / unit[drive].disktype->spt; - ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1; - ReqSide = ReqTrack & 1; - ReqTrack >>= 1; - ReqData = ReqBuffer + 512 * ReqCnt; - -#ifdef TRACKBUFFER - read_track = (ReqCmd == READ && CURRENT->errors == 0); -#endif - - DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide, - ReqTrack, ReqSector, (unsigned long) ReqData)); -} - - -static void redo_fd_request(void) -{ - int drive, type; - struct archy_floppy_struct *floppy; - - DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n", - CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "", - CURRENT ? CURRENT->sector : 0)); - -repeat: - - if (!CURRENT) - goto the_end; - - floppy = CURRENT->rq_disk->private_data; - drive = floppy - unit; - type = fd_device[drive]; - - if (!floppy->connected) { - /* drive not connected */ - printk("Unknown Device: fd%d\n", drive); - end_request(CURRENT, 0); - goto repeat; - } - if (type == 0) { - if (!floppy->disktype) { - Probing = 1; - floppy->disktype = disk_type + NUM_DISK_TYPES - 1; - set_capacity(disks[drive], floppy->disktype->blocks); - floppy->autoprobe = 1; - } - } else { - /* user supplied disk type */ - --type; - if (type >= NUM_DISK_TYPES) { - printk("fd%d: invalid disk format", drive); - end_request(CURRENT, 0); - goto repeat; - } - floppy->disktype = &disk_type[type]; - set_capacity(disks[drive], floppy->disktype->blocks); - floppy->autoprobe = 0; - } - - if (CURRENT->sector + 1 > floppy->disktype->blocks) { - end_request(CURRENT, 0); - goto repeat; - } - /* stop deselect timer */ - del_timer(&motor_off_timer); - - ReqCnt = 0; - ReqCmd = rq_data_dir(CURRENT); - ReqBlock = CURRENT->sector; - ReqBuffer = CURRENT->buffer; - setup_req_params(drive); - do_fd_action(drive); - - return; - -the_end: - finish_fdc(); -} - -static void fd1772_checkint(void) -{ - extern int fdc1772_bytestogo; - - /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/ - if (fdc1772_fdc_int_done) - floppy_irqconsequencehandler(); - if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0); - if (fdc_busy) { - schedule_work(&fd1772_tq); - } -} - -static void do_fd_request(request_queue_t* q) -{ - unsigned long flags; - - DPRINT(("do_fd_request for pid %d\n", current->pid)); - if (fdc_busy) return; - save_flags(flags); - cli(); - wait_event(fdc_wait, !fdc_busy); - fdc_busy = 1; - ENABLE_IRQ(); - restore_flags(flags); - - fdc1772_fdc_int_done = 0; - - redo_fd_request(); - - schedule_work(&fd1772_tq); -} - - -static int invalidate_drive(struct block_device *bdev) -{ - struct archy_floppy_struct *p = bdev->bd_disk->private_data; - /* invalidate the buffer track to force a reread */ -#ifdef TRACKBUFFER - BufferDrive = -1; -#endif - - set_bit(p - unit, &fake_change); - return 0; -} - -static int fd_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long param) -{ - struct block_device *bdev = inode->i_bdev; - - switch (cmd) { - case FDFMTEND: - case FDFLUSH: - invalidate_drive(bdev); - check_disk_change(bdev); - case FDFMTBEG: - return 0; - default: - return -EINVAL; - } -} - - -/* Initialize the 'unit' variable for drive 'drive' */ - -static void fd_probe(int drive) -{ - unit[drive].connected = 0; - unit[drive].disktype = NULL; - - if (!fd_test_drive_present(drive)) - return; - - unit[drive].connected = 1; - unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */ - unit[drive].steprate = FDC1772STEP_6; - MotorOn = 1; /* from probe restore operation! */ -} - - -/* This function tests the physical presence of a floppy drive (not - * whether a disk is inserted). This is done by issuing a restore - * command, waiting max. 2 seconds (that should be enough to move the - * head across the whole disk) and looking at the state of the "TR00" - * signal. This should now be raised if there is a drive connected - * (and there is no hardware failure :-) Otherwise, the drive is - * declared absent. - */ - -static int fd_test_drive_present(int drive) -{ - unsigned long timeout; - unsigned char status; - int ok; - - printk("fd_test_drive_present %d\n", drive); - if (drive > 1) - return (0); - return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */ - fd_select_drive(drive); - - /* disable interrupt temporarily */ - DISABLE_IRQ(); - FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */ - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6); - - /*printk("fd_test_drive_present: Going into timeout loop\n"); */ - for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) { - /* What does this piece of atariism do? - query for an interrupt? */ - /* if (!(mfp.par_dt_reg & 0x20)) - break; */ - /* Well this is my nearest guess - quit when we get an FDC interrupt */ - if (ioc_readb(IOC_FIQSTAT) & 2) - break; - } - - /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */ - status = FDC1772_READ(FDC1772REG_STATUS); - ok = (status & FDC1772STAT_TR00) != 0; - - /*printk("fd_test_drive_present: ok=%d\n",ok); */ - /* force interrupt to abort restore operation (FDC1772 would try - * about 50 seconds!) */ - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); - udelay(500); - status = FDC1772_READ(FDC1772REG_STATUS); - udelay(20); - /*printk("fd_test_drive_present: just before OK code %d\n",ok); */ - - if (ok) { - /* dummy seek command to make WP bit accessible */ - FDC1772_WRITE(FDC1772REG_DATA, 0); - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK); - printk("fd_test_drive_present: just before wait for int\n"); - /* DAG: Guess means wait for interrupt */ - while (!(ioc_readb(IOC_FIQSTAT) & 2)); - printk("fd_test_drive_present: just after wait for int\n"); - status = FDC1772_READ(FDC1772REG_STATUS); - } - printk("fd_test_drive_present: just before ENABLE_IRQ\n"); - ENABLE_IRQ(); - printk("fd_test_drive_present: about to return\n"); - return (ok); -} - - -/* Look how many and which kind of drives are connected. If there are - * floppies, additionally start the disk-change and motor-off timers. - */ - -static void config_types(void) -{ - int drive, cnt = 0; - - printk("Probing floppy drive(s):\n"); - for (drive = 0; drive < FD_MAX_UNITS; drive++) { - fd_probe(drive); - if (unit[drive].connected) { - printk("fd%d\n", drive); - ++cnt; - } - } - - if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) { - /* If FDC1772 is still busy from probing, give it another FORCI - * command to abort the operation. If this isn't done, the FDC1772 - * will interrupt later and its IRQ line stays low, because - * the status register isn't read. And this will block any - * interrupts on this IRQ line :-( - */ - FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); - udelay(500); - FDC1772_READ(FDC1772REG_STATUS); - udelay(20); - } - if (cnt > 0) { - START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY); - if (cnt == 1) - fd_select_drive(0); - /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ - } -} - -/* - * floppy_open check for aliasing (/dev/fd0 can be the same as - * /dev/PS0 etc), and disallows simultaneous access to the same - * drive with different device numbers. - */ - -static int floppy_open(struct inode *inode, struct file *filp) -{ - int drive = iminor(inode) & 3; - int type = iminor(inode) >> 2; - int old_dev = fd_device[drive]; - - if (fd_ref[drive] && old_dev != type) - return -EBUSY; - - if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL)) - return -EBUSY; - - if (filp->f_flags & O_EXCL) - fd_ref[drive] = -1; - else - fd_ref[drive]++; - - fd_device[drive] = type; - - if (filp->f_flags & O_NDELAY) - return 0; - - if (filp->f_mode & 3) { - check_disk_change(inode->i_bdev); - if (filp->f_mode & 2) { - if (unit[drive].wpstat) { - floppy_release(inode, filp); - return -EROFS; - } - } - } - return 0; -} - - -static int floppy_release(struct inode *inode, struct file *filp) -{ - int drive = iminor(inode) & 3; - - if (fd_ref[drive] < 0) - fd_ref[drive] = 0; - else if (!fd_ref[drive]--) { - printk("floppy_release with fd_ref == 0"); - fd_ref[drive] = 0; - } - - return 0; -} - -static struct block_device_operations floppy_fops = -{ - .open = floppy_open, - .release = floppy_release, - .ioctl = fd_ioctl, - .media_changed = check_floppy_change, - .revalidate_disk= floppy_revalidate, -}; - -static struct kobject *floppy_find(dev_t dev, int *part, void *data) -{ - int drive = *part & 3; - if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS) - return NULL; - *part = 0; - return get_disk(disks[drive]); -} - -int fd1772_init(void) -{ - static DEFINE_SPINLOCK(lock); - int i, err = -ENOMEM; - - if (!machine_is_archimedes()) - return 0; - - for (i = 0; i < FD_MAX_UNITS; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto err_disk; - } - - err = register_blkdev(MAJOR_NR, "fd"); - if (err) - goto err_disk; - - err = -EBUSY; - if (request_dma(FLOPPY_DMA, "fd1772")) { - printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA); - goto err_blkdev; - }; - - if (request_dma(FIQ_FD1772, "fd1772 end")) { - printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772); - goto err_dma1; - }; - - /* initialize variables */ - SelectedDrive = -1; -#ifdef TRACKBUFFER - BufferDrive = BufferSide = BufferTrack = -1; - /* Atari uses 512 - I want to eventually cope with 1K sectors */ - DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL); - TrackBuffer = DMABuffer + 512; -#else - /* Allocate memory for the DMAbuffer - on the Atari this takes it - out of some special memory... */ - DMABuffer = kmalloc(2048); /* Copes with pretty large sectors */ -#endif - err = -ENOMEM; - if (!DMAbuffer) - goto err_dma2; - - enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */ - - floppy_queue = blk_init_queue(do_fd_request, &lock); - if (!floppy_queue) - goto err_queue; - - for (i = 0; i < FD_MAX_UNITS; i++) { - unit[i].track = -1; - disks[i]->major = MAJOR_NR; - disks[i]->first_minor = 0; - disks[i]->fops = &floppy_fops; - sprintf(disks[i]->disk_name, "fd%d", i); - disks[i]->private_data = &unit[i]; - disks[i]->queue = floppy_queue; - set_capacity(disks[i], MAX_DISK_SIZE * 2); - } - blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE, - floppy_find, NULL, NULL); - - for (i = 0; i < FD_MAX_UNITS; i++) - add_disk(disks[i]); - - config_types(); - - return 0; - - err_queue: - kfree(DMAbuffer); - err_dma2: - free_dma(FIQ_FD1772); - - err_dma1: - free_dma(FLOPPY_DMA); - - err_blkdev: - unregister_blkdev(MAJOR_NR, "fd"); - - err_disk: - while (i--) - put_disk(disks[i]); - return err; -} diff --git a/drivers/acorn/block/fd1772dma.S b/drivers/acorn/block/fd1772dma.S deleted file mode 100644 index 7964435..0000000 --- a/drivers/acorn/block/fd1772dma.S +++ /dev/null @@ -1,100 +0,0 @@ -#include <asm/hardware.h> - -@ Code for DMA with the 1772 fdc -.text - - - .global fdc1772_dataaddr -fdc1772_fiqdata: -@ Number of bytes left to DMA - .global fdc1772_bytestogo -fdc1772_bytestogo: - .word 0 -@ Place to put/get data from in DMA - .global fdc1772_dataaddr -fdc1772_dataaddr: - .word 0 - - .global fdc1772_fdc_int_done -fdc1772_fdc_int_done: - .word 0 - .global fdc1772_comendstatus -fdc1772_comendstatus: - .word 0 - -@ We hang this off DMA channel 1 - .global fdc1772_comendhandler -fdc1772_comendhandler: - mov r8,#IOC_BASE - ldrb r9,[r8,#0x34] @ IOC FIQ status - tst r9,#2 - subeqs pc,r14,#4 @ should I leave a space here - orr r9,r8,#0x10000 @ FDC base - adr r8,fdc1772_fdc_int_done - ldrb r10,[r9,#0] @ FDC status - mov r9,#1 @ Got a FIQ flag - stmia r8,{r9,r10} - subs pc,r14,#4 - - - .global fdc1772_dma_read -fdc1772_dma_read: - mov r8,#IOC_BASE - ldrb r9,[r8,#0x34] @ IOC FIQ status - tst r9,#1 - beq fdc1772_dma_read_notours - orr r8,r8,#0x10000 @ FDC base - ldrb r10,[r8,#0xc] @ Read from FDC data reg (also clears interrupt) - ldmia r11,{r8,r9} - subs r8,r8,#1 @ One less byte to go - @ If there was somewhere for this data to go then store it and update pointers - strplb r10,[r9],#1 @ Store the data and increment the pointer - stmplia r11,{r8,r9} @ Update count/pointers - @ Handle any other interrupts if there are any -fdc1772_dma_read_notours: - @ Cant branch because this code has been copied down to the FIQ vector - ldr pc,[pc,#-4] - .word fdc1772_comendhandler - .global fdc1772_dma_read_end -fdc1772_dma_read_end: - - .global fdc1772_dma_write -fdc1772_dma_write: - mov r8,#IOC_BASE - ldrb r9,[r8,#0x34] @ IOC FIQ status - tst r9,#1 - beq fdc1772_dma_write_notours - orr r8,r8,#0x10000 @ FDC base - ldmia r11,{r9,r10} - subs r9,r9,#1 @ One less byte to go - @ If there really is some data then get it, store it and update count - ldrplb r12,[r10],#1 - strplb r12,[r8,#0xc] @ write it to FDC data reg - stmplia r11,{r9,r10} @ Update count and pointer - should clear interrupt - @ Handle any other interrupts -fdc1772_dma_write_notours: - @ Cant branch because this code has been copied down to the FIQ vector - ldr pc,[pc,#-4] - .word fdc1772_comendhandler - - .global fdc1772_dma_write_end -fdc1772_dma_write_end: - - -@ Setup the FIQ R11 to point to the data and store the count, address -@ for this dma -@ R0=count -@ R1=address - .global fdc1772_setupdma -fdc1772_setupdma: - @ The big job is flipping in and out of FIQ mode - adr r2,fdc1772_fiqdata @ This is what we really came here for - stmia r2,{r0,r1} - mov r3, pc - teqp pc,#0x0c000001 @ Disable FIQs, IRQs and switch to FIQ mode - mov r0,r0 @ NOP - mov r11,r2 - teqp r3,#0 @ Normal mode - mov r0,r0 @ NOP - mov pc,r14 - diff --git a/drivers/acorn/block/mfm.S b/drivers/acorn/block/mfm.S deleted file mode 100644 index c90cbd4..0000000 --- a/drivers/acorn/block/mfm.S +++ /dev/null @@ -1,162 +0,0 @@ -@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400 Acorn Archimedes -@ motherboard and on ST506 expansion podules. -@ (c) David Alan Gilbert (linux@treblig.org) 1996-1999 - -#include <asm/assembler.h> - -hdc63463_irqdata: -@ Controller base address - .global hdc63463_baseaddress -hdc63463_baseaddress: - .word 0 - - .global hdc63463_irqpolladdress -hdc63463_irqpolladdress: - .word 0 - - .global hdc63463_irqpollmask -hdc63463_irqpollmask: - .word 0 - -@ where to read/write data from the kernel data space - .global hdc63463_dataptr -hdc63463_dataptr: - .word 0 - -@ Number of bytes left to transfer - .global hdc63463_dataleft -hdc63463_dataleft: - .word 0 - -@ ------------------------------------------------------------------------- -@ hdc63463_writedma: DMA from host to controller -@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask -@ r3=data ptr, r4=data left, r5,r6=temporary - .global hdc63463_writedma -hdc63463_writedma: - stmfd sp!,{r4-r7} - adr r5,hdc63463_irqdata - ldmia r5,{r0,r1,r2,r3,r4} - -writedma_again: - - @ test number of remaining bytes to transfer - cmp r4,#0 - beq writedma_end - bmi writedma_end - - @ Check the hdc is interrupting - ldrb r5,[r1,#0] - tst r5,r2 - beq writedma_end - - @ Transfer a block of upto 256 bytes - cmp r4,#256 - movlt r7,r4 - movge r7,#256 - - @ Check the hdc is still busy and command has not ended and no errors - ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status - @ think we should continue DMA until it drops busy - perhaps this was - @ the main problem with corrected errors causing a hang - @tst r5,#0x3c00 @ Test for things which should be off - @bne writedma_end - and r5,r5,#0x8000 @ This is test for things which should be on: Busy - cmp r5,#0x8000 - bne writedma_end - - @ Bytes remaining at end - sub r4,r4,r7 - - @ HDC Write register location - add r0,r0,#32+8 - -writedma_loop: - @ OK - pretty sure we should be doing this - - ldr r5,[r3],#4 @ Get a word to be written - @ get bottom half to be sent first - mov r6,r5,lsl#16 @ Separate the first 2 bytes - orr r2,r6,r6,lsr #16 @ Duplicate them in the bottom half of the word - @ now the top half - mov r6,r5,lsr#16 @ Get 2nd 2 bytes - orr r6,r6,r6,lsl#16 @ Duplicate - @str r6,[r0] @ to hdc - stmia r0,{r2,r6} - subs r7,r7,#4 @ Dec. number of bytes left - bne writedma_loop - - @ If we were too slow we had better go through again - DAG - took out with new interrupt routine - @ sub r0,r0,#32+8 - @ adr r2,hdc63463_irqdata - @ ldr r2,[r2,#8] - @ b writedma_again - -writedma_end: - adr r5,hdc63463_irqdata+12 - stmia r5,{r3,r4} - ldmfd sp!,{r4-r7} - RETINSTR(mov,pc,lr) - -@ ------------------------------------------------------------------------- -@ hdc63463_readdma: DMA from controller to host -@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask -@ r3=data ptr, r4=data left, r5,r6=temporary - .global hdc63463_readdma -hdc63463_readdma: - stmfd sp!,{r4-r7} - adr r5,hdc63463_irqdata - ldmia r5,{r0,r1,r2,r3,r4} - -readdma_again: - @ test number of remaining bytes to transfer - cmp r4,#0 - beq readdma_end - bmi readdma_end - - @ Check the hdc is interrupting - ldrb r5,[r1,#0] - tst r5,r2 - beq readdma_end - - @ Check the hdc is still busy and command has not ended and no errors - ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status - @ think we should continue DMA until it drops busy - perhaps this was - @ the main problem with corrected errors causing a hang - @tst r5,#0x3c00 @ Test for things which should be off - @bne readdma_end - and r5,r5,#0x8000 @ This is test for things which should be on: Busy - cmp r5,#0x8000 - bne readdma_end - - @ Transfer a block of upto 256 bytes - cmp r4,#256 - movlt r7,r4 - movge r7,#256 - - @ Bytes remaining at end - sub r4,r4,r7 - - @ Set a pointer to the data register in the HDC - add r0,r0,#8 -readdma_loop: - @ OK - pretty sure we should be doing this - ldmia r0,{r5,r6} - mov r5,r5,lsl#16 - mov r6,r6,lsl#16 - orr r6,r6,r5,lsr #16 - str r6,[r3],#4 - subs r7,r7,#4 @ Decrement bytes to go - bne readdma_loop - - @ Try reading multiple blocks - if this was fast enough then I do not think - @ this should help - NO taken out DAG - new interrupt handler has - @ non-consecutive memory blocks - @ sub r0,r0,#8 - @ b readdma_again - -readdma_end: - adr r5,hdc63463_irqdata+12 - stmia r5,{r3,r4} - ldmfd sp!,{r4-r7} - RETINSTR(mov,pc,lr) diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c deleted file mode 100644 index d85520f..0000000 --- a/drivers/acorn/block/mfmhd.c +++ /dev/null @@ -1,1385 +0,0 @@ -/* - * linux/drivers/acorn/block/mfmhd.c - * - * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk) - * - * MFM hard drive code [experimental] - */ - -/* - * Change list: - * - * 3/2/96:DAG: Started a change list :-) - * Set the hardsect_size pointers up since we are running 256 byte - * sectors - * Added DMA code, put it into the rw_intr - * Moved RCAL out of generic interrupt code - don't want to do it - * while DMA'ing - its now in individual handlers. - * Took interrupt handlers off task queue lists and called - * directly - not sure of implications. - * - * 18/2/96:DAG: Well its reading OK I think, well enough for image file code - * to find the image file; but now I've discovered that I actually - * have to put some code in for image files. - * - * Added stuff for image files; seems to work, but I've not - * got a multisegment image file (I don't think!). - * Put in a hack (yep a real hack) for multiple cylinder reads. - * Not convinced its working. - * - * 5/4/96:DAG: Added asm/hardware.h and use IOC_ macros - * Rewrote dma code in mfm.S (again!) - now takes a word at a time - * from main RAM for speed; still doesn't feel speedy! - * - * 20/4/96:DAG: After rewriting mfm.S a heck of a lot of times and speeding - * things up, I've finally figured out why its so damn slow. - * Linux is only reading a block at a time, and so you never - * get more than 1K per disc revoloution ~=60K/second. - * - * 27/4/96:DAG: On Russell's advice I change ll_rw_blk.c to ask it to - * join adjacent blocks together. Everything falls flat on its - * face. - * Four hours of debugging later; I hadn't realised that - * ll_rw_blk would be so generous as to join blocks whose - * results aren't going into consecutive buffers. - * - * OK; severe rehacking of mfm_rw_interrupt; now end_request's - * as soon as its DMA'd each request. Odd thing is that - * we are sometimes getting interrupts where we are not transferring - * any data; why? Is that what happens when you miss? I doubt - * it; are we too fast? No - its just at command ends. Got 240K/s - * better than before, but RiscOS hits 480K/s - * - * 25/6/96:RMK: Fixed init code to allow the MFM podule to work. Increased the - * number of errors for my Miniscribe drive (8425). - * - * 30/6/96:DAG: Russell suggested that a check drive 0 might turn the LEDs off - * - so in request_done just before it clears Busy it sends a - * check drive 0 - and the LEDs go off!!!! - * - * Added test for mainboard controller. - Removes need for separate - * define. - * - * 13/7/96:DAG: Changed hardware sectore size to 512 in attempt to make - * IM drivers work. - * 21/7/96:DAG: Took out old image file stuff (accessing it now produces an IO - * error.) - * - * 17/8/96:DAG: Ran through indent -kr -i8; evil - all my nice 2 character indents - * gone :-( Hand modified afterwards. - * Took out last remains of the older image map system. - * - * 22/9/96:DAG: Changed mfm.S so it will carry on DMA'ing til; BSY is dropped - * Changed mfm_rw_intr so that it doesn't follow the error - * code until BSY is dropped. Nope - still broke. Problem - * may revolve around when it reads the results for the error - * number? - * - *16/11/96:DAG: Modified for 2.0.18; request_irq changed - * - *17/12/96:RMK: Various cleanups, reorganisation, and the changes for new IO system. - * Improved probe for onboard MFM chip - it was hanging on my A5k. - * Added autodetect CHS code such that we don't rely on the presence - * of an ADFS boot block. Added ioport resource manager calls so - * that we don't clash with already-running hardware (eg. RiscPC Ether - * card slots if someone tries this)! - * - * 17/1/97:RMK: Upgraded to 2.1 kernels. - * - * 4/3/98:RMK: Changed major number to 21. - * - * 27/6/98:RMK: Changed asm/delay.h to linux/delay.h for mdelay(). - */ - -/* - * Possible enhancements: - * Multi-thread the code so that it is possible that while one drive - * is seeking, the other one can be reading data/seeking as well. - * This would be a performance boost with dual drive systems. - */ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/errno.h> -#include <linux/genhd.h> -#include <linux/major.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/blkpg.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/dma.h> -#include <asm/hardware.h> -#include <asm/ecard.h> -#include <asm/hardware/ioc.h> - -static void (*do_mfm)(void) = NULL; -static struct request_queue *mfm_queue; -static DEFINE_SPINLOCK(mfm_lock); - -#define MAJOR_NR MFM_ACORN_MAJOR -#define QUEUE (mfm_queue) -#define CURRENT elv_next_request(mfm_queue) - -/* - * Configuration section - * - * This is the maximum number of drives that we accept - */ -#define MFM_MAXDRIVES 2 -/* - * Linux I/O address of onboard MFM controller or 0 to disable this - */ -#define ONBOARD_MFM_ADDRESS ((0x002d0000 >> 2) | 0x80000000) -/* - * Uncomment this to enable debugging in the MFM driver... - */ -#ifndef DEBUG -/*#define DEBUG */ -#endif -/* - * End of configuration - */ - - -/* - * This structure contains all information to do with a particular physical - * device. - */ -struct mfm_info { - unsigned char sectors; - unsigned char heads; - unsigned short cylinders; - unsigned short lowcurrent; - unsigned short precomp; -#define NO_TRACK -1 -#define NEED_1_RECAL -2 -#define NEED_2_RECAL -3 - int cylinder; - struct { - char recal; - char report; - char abort; - } errors; -} mfm_info[MFM_MAXDRIVES]; - -#define MFM_DRV_INFO mfm_info[raw_cmd.dev] - -/* Stuff from the assembly routines */ -extern unsigned int hdc63463_baseaddress; /* Controller base address */ -extern unsigned int hdc63463_irqpolladdress; /* Address to read to test for int */ -extern unsigned int hdc63463_irqpollmask; /* Mask for irq register */ -extern unsigned int hdc63463_dataptr; /* Pointer to kernel data space to DMA */ -extern int hdc63463_dataleft; /* Number of bytes left to transfer */ - - - - -static int lastspecifieddrive; -static unsigned Busy; - -static unsigned int PartFragRead; /* The number of sectors which have been read - during a partial read split over two - cylinders. If 0 it means a partial - read did not occur. */ - -static unsigned int PartFragRead_RestartBlock; /* Where to restart on a split access */ -static unsigned int PartFragRead_SectorsLeft; /* Where to restart on a split access */ - -static int Sectors256LeftInCurrent; /* i.e. 256 byte sectors left in current */ -static int SectorsLeftInRequest; /* i.e. blocks left in the thing mfm_request was called for */ -static int Copy_Sector; /* The 256 byte sector we are currently at - fragments need to know - where to take over */ -static char *Copy_buffer; - - -static void mfm_seek(void); -static void mfm_rerequest(void); -static void mfm_request(void); -static void mfm_specify (void); -static void issue_request(unsigned int block, unsigned int nsect, - struct request *req); - -static unsigned int mfm_addr; /* Controller address */ -static unsigned int mfm_IRQPollLoc; /* Address to read for IRQ information */ -static unsigned int mfm_irqenable; /* Podule IRQ enable location */ -static unsigned char mfm_irq; /* Interrupt number */ -static int mfm_drives = 0; /* drives available */ -static int mfm_status = 0; /* interrupt status */ -static int *errors; - -static struct rawcmd { - unsigned int dev; - unsigned int cylinder; - unsigned int head; - unsigned int sector; - unsigned int cmdtype; - unsigned int cmdcode; - unsigned char cmddata[16]; - unsigned int cmdlen; -} raw_cmd; - -static unsigned char result[16]; - -static struct cont { - void (*interrupt) (void); /* interrupt handler */ - void (*error) (void); /* error handler */ - void (*redo) (void); /* redo handler */ - void (*done) (int st); /* done handler */ -} *cont = NULL; - -#if 0 -static struct tq_struct mfm_tq = {0, 0, (void (*)(void *)) NULL, 0}; -#endif - -int number_mfm_drives = 1; - -/* ------------------------------------------------------------------------------------------ */ -/* - * From the HD63463 data sheet from Hitachi Ltd. - */ - -#define MFM_COMMAND (mfm_addr + 0) -#define MFM_DATAOUT (mfm_addr + 1) -#define MFM_STATUS (mfm_addr + 8) -#define MFM_DATAIN (mfm_addr + 9) - -#define CMD_ABT 0xF0 /* Abort */ -#define CMD_SPC 0xE8 /* Specify */ -#define CMD_TST 0xE0 /* Test */ -#define CMD_RCLB 0xC8 /* Recalibrate */ -#define CMD_SEK 0xC0 /* Seek */ -#define CMD_WFS 0xAB /* Write Format Skew */ -#define CMD_WFM 0xA3 /* Write Format */ -#define CMD_MTB 0x90 /* Memory to buffer */ -#define CMD_CMPD 0x88 /* Compare data */ -#define CMD_WD 0x87 /* Write data */ -#define CMD_RED 0x70 /* Read erroneous data */ -#define CMD_RIS 0x68 /* Read ID skew */ -#define CMD_FID 0x61 /* Find ID */ -#define CMD_RID 0x60 /* Read ID */ -#define CMD_BTM 0x50 /* Buffer to memory */ -#define CMD_CKD 0x48 /* Check data */ -#define CMD_RD 0x40 /* Read data */ -#define CMD_OPBW 0x38 /* Open buffer write */ -#define CMD_OPBR 0x30 /* Open buffer read */ -#define CMD_CKV 0x28 /* Check drive */ -#define CMD_CKE 0x20 /* Check ECC */ -#define CMD_POD 0x18 /* Polling disable */ -#define CMD_POL 0x10 /* Polling enable */ -#define CMD_RCAL 0x08 /* Recall */ - -#define STAT_BSY 0x8000 /* Busy */ -#define STAT_CPR 0x4000 /* Command Parameter Rejection */ -#define STAT_CED 0x2000 /* Command end */ -#define STAT_SED 0x1000 /* Seek end */ -#define STAT_DER 0x0800 /* Drive error */ -#define STAT_ABN 0x0400 /* Abnormal end */ -#define STAT_POL 0x0200 /* Polling */ - -/* ------------------------------------------------------------------------------------------ */ -#ifdef DEBUG -static void console_printf(const char *fmt,...) -{ - static char buffer[2048]; /* Arbitary! */ - extern void console_print(const char *); - unsigned long flags; - va_list ap; - - local_irq_save(flags); - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - console_print(buffer); - va_end(fmt); - - local_irq_restore(flags); -}; /* console_printf */ - -#define DBG(x...) console_printf(x) -#else -#define DBG(x...) -#endif - -static void print_status(void) -{ - char *error; - static char *errors[] = { - "no error", - "command aborted", - "invalid command", - "parameter error", - "not initialised", - "rejected TEST", - "no useld", - "write fault", - "not ready", - "no scp", - "in seek", - "invalid NCA", - "invalid step rate", - "seek error", - "over run", - "invalid PHA", - "data field EEC error", - "data field CRC error", - "error corrected", - "data field fatal error", - "no data am", - "not hit", - "ID field CRC error", - "time over", - "no ID am", - "not writable" - }; - if (result[1] < 0x65) - error = errors[result[1] >> 2]; - else - error = "unknown"; - printk("("); - if (mfm_status & STAT_BSY) printk("BSY "); - if (mfm_status & STAT_CPR) printk("CPR "); - if (mfm_status & STAT_CED) printk("CED "); - if (mfm_status & STAT_SED) printk("SED "); - if (mfm_status & STAT_DER) printk("DER "); - if (mfm_status & STAT_ABN) printk("ABN "); - if (mfm_status & STAT_POL) printk("POL "); - printk(") SSB = %X (%s)\n", result[1], error); - -} - -/* ------------------------------------------------------------------------------------- */ - -static void issue_command(int command, unsigned char *cmdb, int len) -{ - int status; -#ifdef DEBUG - int i; - console_printf("issue_command: %02X: ", command); - for (i = 0; i < len; i++) - console_printf("%02X ", cmdb[i]); - console_printf("\n"); -#endif - - do { - status = inw(MFM_STATUS); - } while (status & (STAT_BSY | STAT_POL)); - DBG("issue_command: status after pol/bsy loop: %02X:\n ", status >> 8); - - if (status & (STAT_CPR | STAT_CED | STAT_SED | STAT_DER | STAT_ABN)) { - outw(CMD_RCAL, MFM_COMMAND); - while (inw(MFM_STATUS) & STAT_BSY); - } - status = inw(MFM_STATUS); - DBG("issue_command: status before parameter issue: %02X:\n ", status >> 8); - - while (len > 0) { - outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT); - len -= 2; - cmdb += 2; - } - status = inw(MFM_STATUS); - DBG("issue_command: status before command issue: %02X:\n ", status >> 8); - - outw(command, MFM_COMMAND); - status = inw(MFM_STATUS); - DBG("issue_command: status immediately after command issue: %02X:\n ", status >> 8); -} - -static void wait_for_completion(void) -{ - while ((mfm_status = inw(MFM_STATUS)) & STAT_BSY); -} - -static void wait_for_command_end(void) -{ - int i; - - while (!((mfm_status = inw(MFM_STATUS)) & STAT_CED)); - - for (i = 0; i < 16;) { - int in; - in = inw(MFM_DATAIN); - result[i++] = in >> 8; - result[i++] = in; - } - outw (CMD_RCAL, MFM_COMMAND); -} - -/* ------------------------------------------------------------------------------------- */ - -static void mfm_rw_intr(void) -{ - int old_status; /* Holds status on entry, we read to see if the command just finished */ -#ifdef DEBUG - console_printf("mfm_rw_intr...dataleft=%d\n", hdc63463_dataleft); - print_status(); -#endif - - /* Now don't handle the error until BSY drops */ - if ((mfm_status & (STAT_DER | STAT_ABN)) && ((mfm_status&STAT_BSY)==0)) { - /* Something has gone wrong - let's try that again */ - outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ - if (cont) { - DBG("mfm_rw_intr: DER/ABN err\n"); - cont->error(); - cont->redo(); - }; - return; - }; - - /* OK so what ever happened it's not an error, now I reckon we are left between - a choice of command end or some data which is ready to be collected */ - /* I think we have to transfer data while the interrupt line is on and its - not any other type of interrupt */ - if (rq_data_dir(CURRENT) == WRITE) { - extern void hdc63463_writedma(void); - if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) { - printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n"); - if (cont) { - cont->error(); - cont->redo(); - }; - return; - }; - hdc63463_writedma(); - } else { - extern void hdc63463_readdma(void); - if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) { - printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n"); - if (cont) { - cont->error(); - cont->redo(); - }; - return; - }; - DBG("Going to try read dma..............status=0x%x, buffer=%p\n", mfm_status, hdc63463_dataptr); - hdc63463_readdma(); - }; /* Read */ - - if (hdc63463_dataptr != ((unsigned int) Copy_buffer + 256)) { - /* If we didn't actually manage to get any data on this interrupt - but why? We got the interrupt */ - /* Ah - well looking at the status its just when we get command end; so no problem */ - /*console_printf("mfm: dataptr mismatch. dataptr=0x%08x Copy_buffer+256=0x%08p\n", - hdc63463_dataptr,Copy_buffer+256); - print_status(); */ - } else { - Sectors256LeftInCurrent--; - Copy_buffer += 256; - Copy_Sector++; - - /* We have come to the end of this request */ - if (!Sectors256LeftInCurrent) { - DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n", - CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors); - - CURRENT->nr_sectors -= CURRENT->current_nr_sectors; - CURRENT->sector += CURRENT->current_nr_sectors; - SectorsLeftInRequest -= CURRENT->current_nr_sectors; - - end_request(CURRENT, 1); - if (SectorsLeftInRequest) { - hdc63463_dataptr = (unsigned int) CURRENT->buffer; - Copy_buffer = CURRENT->buffer; - Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2; - errors = &(CURRENT->errors); - /* These should match the present calculations of the next logical sector - on the device - Copy_Sector=CURRENT->sector*2; */ - - if (Copy_Sector != CURRENT->sector * 2) -#ifdef DEBUG - /*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n", - Copy_Sector, CURRENT->sector * 2); -#else - printk("mfm: Copy_Sector mismatch! Eek!\n"); -#endif - }; /* CURRENT */ - }; /* Sectors256LeftInCurrent */ - }; - - old_status = mfm_status; - mfm_status = inw(MFM_STATUS); - if (mfm_status & (STAT_DER | STAT_ABN)) { - /* Something has gone wrong - let's try that again */ - if (cont) { - DBG("mfm_rw_intr: DER/ABN error\n"); - cont->error(); - cont->redo(); - }; - return; - }; - - /* If this code wasn't entered due to command_end but there is - now a command end we must read the command results out. If it was - entered like this then mfm_interrupt_handler would have done the - job. */ - if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) && - ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) { - int len = 0; - while (len < 16) { - int in; - in = inw(MFM_DATAIN); - result[len++] = in >> 8; - result[len++] = in; - }; - }; /* Result read */ - - /*console_printf ("mfm_rw_intr nearexit [%02X]\n", __raw_readb(mfm_IRQPollLoc)); */ - - /* If end of command move on */ - if (mfm_status & (STAT_CED)) { - outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ - /* End of command - trigger the next command */ - if (cont) { - cont->done(1); - } - DBG("mfm_rw_intr: returned from cont->done\n"); - } else { - /* Its going to generate another interrupt */ - do_mfm = mfm_rw_intr; - }; -} - -static void mfm_setup_rw(void) -{ - DBG("setting up for rw...\n"); - - do_mfm = mfm_rw_intr; - issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen); -} - -static void mfm_recal_intr(void) -{ -#ifdef DEBUG - console_printf("recal intr - status = "); - print_status(); -#endif - outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ - if (mfm_status & (STAT_DER | STAT_ABN)) { - printk("recal failed\n"); - MFM_DRV_INFO.cylinder = NEED_2_RECAL; - if (cont) { - cont->error(); - cont->redo(); - } - return; - } - /* Thats seek end - we are finished */ - if (mfm_status & STAT_SED) { - issue_command(CMD_POD, NULL, 0); - MFM_DRV_INFO.cylinder = 0; - mfm_seek(); - return; - } - /* Command end without seek end (see data sheet p.20) for parallel seek - - we have to send a POL command to wait for the seek */ - if (mfm_status & STAT_CED) { - do_mfm = mfm_recal_intr; - issue_command(CMD_POL, NULL, 0); - return; - } - printk("recal: unknown status\n"); -} - -static void mfm_seek_intr(void) -{ -#ifdef DEBUG - console_printf("seek intr - status = "); - print_status(); -#endif - outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ - if (mfm_status & (STAT_DER | STAT_ABN)) { - printk("seek failed\n"); - MFM_DRV_INFO.cylinder = NEED_2_RECAL; - if (cont) { - cont->error(); - cont->redo(); - } - return; - } - if (mfm_status & STAT_SED) { - issue_command(CMD_POD, NULL, 0); - MFM_DRV_INFO.cylinder = raw_cmd.cylinder; - mfm_seek(); - return; - } - if (mfm_status & STAT_CED) { - do_mfm = mfm_seek_intr; - issue_command(CMD_POL, NULL, 0); - return; - } - printk("seek: unknown status\n"); -} - -/* IDEA2 seems to work better - its what RiscOS sets my - * disc to - on its SECOND call to specify! - */ -#define IDEA2 -#ifndef IDEA2 -#define SPEC_SL 0x16 -#define SPEC_SH 0xa9 /* Step pulse high=21, Record Length=001 (256 bytes) */ -#else -#define SPEC_SL 0x00 /* OM2 - SL - step pulse low */ -#define SPEC_SH 0x21 /* Step pulse high=4, Record Length=001 (256 bytes) */ -#endif - -static void mfm_setupspecify (int drive, unsigned char *cmdb) -{ - cmdb[0] = 0x1f; /* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */ - cmdb[1] = 0xc3; /* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */ - cmdb[2] = SPEC_SL; /* OM2 - SL - step pulse low */ - cmdb[3] = (number_mfm_drives == 1) ? 0x02 : 0x06; /* 1 or 2 drives */ - cmdb[4] = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */ - cmdb[5] = mfm_info[drive].cylinders - 1; /* low part of number of cylinders */ - cmdb[6] = mfm_info[drive].heads - 1; /* Number of heads */ - cmdb[7] = mfm_info[drive].sectors - 1; /* Number of sectors */ - cmdb[8] = SPEC_SH; - cmdb[9] = 0x0a; /* gap length 1 */ - cmdb[10] = 0x0d; /* gap length 2 */ - cmdb[11] = 0x0c; /* gap length 3 */ - cmdb[12] = (mfm_info[drive].precomp - 1) >> 8; /* pre comp cylinder */ - cmdb[13] = mfm_info[drive].precomp - 1; - cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8; /* Low current cylinder */ - cmdb[15] = mfm_info[drive].lowcurrent - 1; -} - -static void mfm_specify (void) -{ - unsigned char cmdb[16]; - - DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive); - mfm_setupspecify (raw_cmd.dev, cmdb); - - issue_command (CMD_SPC, cmdb, 16); - /* Ensure that we will do another specify if we move to the other drive */ - lastspecifieddrive = raw_cmd.dev; - wait_for_completion(); -} - -static void mfm_seek(void) -{ - unsigned char cmdb[4]; - - DBG("seeking...\n"); - if (MFM_DRV_INFO.cylinder < 0) { - do_mfm = mfm_recal_intr; - DBG("mfm_seek: about to call specify\n"); - mfm_specify (); /* DAG added this */ - - cmdb[0] = raw_cmd.dev + 1; - cmdb[1] = 0; - - issue_command(CMD_RCLB, cmdb, 2); - return; - } - if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) { - cmdb[0] = raw_cmd.dev + 1; - cmdb[1] = 0; /* raw_cmd.head; DAG: My data sheet says this should be 0 */ - cmdb[2] = raw_cmd.cylinder >> 8; - cmdb[3] = raw_cmd.cylinder; - - do_mfm = mfm_seek_intr; - issue_command(CMD_SEK, cmdb, 4); - } else - mfm_setup_rw(); -} - -static void mfm_initialise(void) -{ - DBG("init...\n"); - mfm_seek(); -} - -static void request_done(int uptodate) -{ - DBG("mfm:request_done\n"); - if (uptodate) { - unsigned char block[2] = {0, 0}; - - /* Apparently worked - let's check bytes left to DMA */ - if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) { - printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256); - end_request(CURRENT, 0); - Busy = 0; - }; - /* Potentially this means that we've done; but we might be doing - a partial access, (over two cylinders) or we may have a number - of fragments in an image file. First let's deal with partial accesss - */ - if (PartFragRead) { - /* Yep - a partial access */ - - /* and issue the remainder */ - issue_request(PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT); - return; - } - - /* ah well - perhaps there is another fragment to go */ - - /* Increment pointers/counts to start of next fragment */ - if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n"); - - /* No - its the end of the line */ - /* end_request's should have happened at the end of sector DMAs */ - /* Turns Drive LEDs off - may slow it down? */ - if (!elv_next_request(QUEUE)) - issue_command(CMD_CKV, block, 2); - - Busy = 0; - DBG("request_done: About to mfm_request\n"); - /* Next one please */ - mfm_request(); /* Moved from mfm_rw_intr */ - DBG("request_done: returned from mfm_request\n"); - } else { - printk("mfm:request_done: update=0\n"); - end_request(CURRENT, 0); - Busy = 0; - } -} - -static void error_handler(void) -{ - printk("error detected... status = "); - print_status(); - (*errors)++; - if (*errors > MFM_DRV_INFO.errors.abort) - cont->done(0); - if (*errors > MFM_DRV_INFO.errors.recal) - MFM_DRV_INFO.cylinder = NEED_2_RECAL; -} - -static void rw_interrupt(void) -{ - printk("rw_interrupt\n"); -} - -static struct cont rw_cont = -{ - rw_interrupt, - error_handler, - mfm_rerequest, - request_done -}; - -/* - * Actually gets round to issuing the request - note everything at this - * point is in 256 byte sectors not Linux 512 byte blocks - */ -static void issue_request(unsigned int block, unsigned int nsect, - struct request *req) -{ - struct gendisk *disk = req->rq_disk; - struct mfm_info *p = disk->private_data; - int track, start_head, start_sector; - int sectors_to_next_cyl; - dev = p - mfm_info; - - track = block / p->sectors; - start_sector = block % p->sectors; - start_head = track % p->heads; - - /* First get the number of whole tracks which are free before the next - track */ - sectors_to_next_cyl = (p->heads - (start_head + 1)) * p->sectors; - /* Then add in the number of sectors left on this track */ - sectors_to_next_cyl += (p->sectors - start_sector); - - DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", p->sectors, track); - - raw_cmd.dev = dev; - raw_cmd.sector = start_sector; - raw_cmd.head = start_head; - raw_cmd.cylinder = track / p->heads; - raw_cmd.cmdtype = CURRENT->cmd; - raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD; - raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */ - raw_cmd.cmddata[1] = raw_cmd.head; - raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8; - raw_cmd.cmddata[3] = raw_cmd.cylinder; - raw_cmd.cmddata[4] = raw_cmd.head; - raw_cmd.cmddata[5] = raw_cmd.sector; - - /* Was == and worked - how the heck??? */ - if (lastspecifieddrive != raw_cmd.dev) - mfm_specify (); - - if (nsect <= sectors_to_next_cyl) { - raw_cmd.cmddata[6] = nsect >> 8; - raw_cmd.cmddata[7] = nsect; - PartFragRead = 0; /* All in one */ - PartFragRead_SectorsLeft = 0; /* Must set this - used in DMA calcs */ - } else { - raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8; - raw_cmd.cmddata[7] = sectors_to_next_cyl; - PartFragRead = sectors_to_next_cyl; /* only do this many this time */ - PartFragRead_RestartBlock = block + sectors_to_next_cyl; /* Where to restart from */ - PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl; - } - raw_cmd.cmdlen = 8; - - /* Setup DMA pointers */ - hdc63463_dataptr = (unsigned int) Copy_buffer; - hdc63463_dataleft = nsect * 256; /* Better way? */ - - DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n", - raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ", - raw_cmd.cylinder, - raw_cmd.head, - raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT); - - cont = &rw_cont; - errors = &(CURRENT->errors); -#if 0 - mfm_tq.routine = (void (*)(void *)) mfm_initialise; - queue_task(&mfm_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -#else - mfm_initialise(); -#endif -} /* issue_request */ - -/* - * Called when an error has just happened - need to trick mfm_request - * into thinking we weren't busy - * - * Turn off ints - mfm_request expects them this way - */ -static void mfm_rerequest(void) -{ - DBG("mfm_rerequest\n"); - cli(); - Busy = 0; - mfm_request(); -} - -static struct gendisk *mfm_gendisk[2]; - -static void mfm_request(void) -{ - DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy); - - /* If we are still processing then return; we will get called again */ - if (Busy) { - /* Again seems to be common in 1.3.45 */ - /*DBG*/printk("mfm_request: Exiting due to busy\n"); - return; - } - Busy = 1; - - while (1) { - unsigned int block, nsect; - struct gendisk *disk; - - DBG("mfm_request: loop start\n"); - sti(); - - DBG("mfm_request: before !CURRENT\n"); - - if (!CURRENT) { - printk("mfm_request: Exiting due to empty queue (pre)\n"); - do_mfm = NULL; - Busy = 0; - return; - } - - DBG("mfm_request: before arg extraction\n"); - - disk = CURRENT->rq_disk; - block = CURRENT->sector; - nsect = CURRENT->nr_sectors; - if (block >= get_capacity(disk) || - block+nsect > get_capacity(disk)) { - printk("%s: bad access: block=%d, count=%d, nr_sects=%ld\n", - disk->disk_name, block, nsect, get_capacity(disk)); - printk("mfm: continue 1\n"); - end_request(CURRENT, 0); - Busy = 0; - continue; - } - - /* DAG: Linux doesn't cope with this - even though it has an array telling - it the hardware block size - silly */ - block <<= 1; /* Now in 256 byte sectors */ - nsect <<= 1; /* Ditto */ - - SectorsLeftInRequest = nsect >> 1; - Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2; - Copy_buffer = CURRENT->buffer; - Copy_Sector = CURRENT->sector << 1; - - DBG("mfm_request: block after offset=%d\n", block); - - issue_request(block, nsect, CURRENT); - - break; - } - DBG("mfm_request: Dropping out bottom\n"); -} - -static void do_mfm_request(request_queue_t *q) -{ - DBG("do_mfm_request: about to mfm_request\n"); - mfm_request(); -} - -static void mfm_interrupt_handler(int unused, void *dev_id) -{ - void (*handler) (void) = do_mfm; - - do_mfm = NULL; - - DBG("mfm_interrupt_handler (handler=0x%p)\n", handler); - - mfm_status = inw(MFM_STATUS); - - /* If CPR (Command Parameter Reject) and not busy it means that the command - has some return message to give us */ - if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) { - int len = 0; - while (len < 16) { - int in; - in = inw(MFM_DATAIN); - result[len++] = in >> 8; - result[len++] = in; - } - } - if (handler) { - handler(); - return; - } - outw (CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */ - printk ("mfm: unexpected interrupt - status = "); - print_status (); - while (1); -} - - - - - -/* - * Tell the user about the drive if we decided it exists. - */ -static void mfm_geometry(int drive) -{ - struct mfm_info *p = mfm_info + drive; - struct gendisk *disk = mfm_gendisk[drive]; - disk->private_data = p; - if (p->cylinders) - printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", - disk->disk_name, - p->cylinders * p->heads * p->sectors / 4096, - p->cylinders, p->heads, p->sectors, - p->lowcurrent, p->precomp); - set_capacity(disk, p->cylinders * p->heads * p->sectors / 2); -} - -#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT -/* - * Attempt to detect a drive and find its geometry. The drive has already been - * specified... - * - * We first recalibrate the disk, then try to probe sectors, heads and then - * cylinders. NOTE! the cylinder probe may break drives. The xd disk driver - * does something along these lines, so I assume that most drives are up to - * this mistreatment... - */ -static int mfm_detectdrive (int drive) -{ - unsigned int mingeo[3], maxgeo[3]; - unsigned int attribute, need_recal = 1; - unsigned char cmdb[8]; - - memset (mingeo, 0, sizeof (mingeo)); - maxgeo[0] = mfm_info[drive].sectors; - maxgeo[1] = mfm_info[drive].heads; - maxgeo[2] = mfm_info[drive].cylinders; - - cmdb[0] = drive + 1; - cmdb[6] = 0; - cmdb[7] = 1; - for (attribute = 0; attribute < 3; attribute++) { - while (mingeo[attribute] != maxgeo[attribute]) { - unsigned int variable; - - variable = (maxgeo[attribute] + mingeo[attribute]) >> 1; - cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0; - - if (need_recal) { - int tries = 5; - - do { - issue_command (CMD_RCLB, cmdb, 2); - wait_for_completion (); - wait_for_command_end (); - if (result[1] == 0x20) - break; - } while (result[1] && --tries); - if (result[1]) { - outw (CMD_RCAL, MFM_COMMAND); - return 0; - } - need_recal = 0; - } - - switch (attribute) { - case 0: - cmdb[5] = variable; - issue_command (CMD_CMPD, cmdb, 8); - break; - case 1: - cmdb[1] = variable; - cmdb[4] = variable; - issue_command (CMD_CMPD, cmdb, 8); - break; - case 2: - cmdb[2] = variable >> 8; - cmdb[3] = variable; - issue_command (CMD_SEK, cmdb, 4); - break; - } - wait_for_completion (); - wait_for_command_end (); - - switch (result[1]) { - case 0x00: - case 0x50: - mingeo[attribute] = variable + 1; - break; - - case 0x20: - outw (CMD_RCAL, MFM_COMMAND); - return 0; - - case 0x24: - need_recal = 1; - default: - maxgeo[attribute] = variable; - break; - } - } - } - mfm_info[drive].cylinders = mingeo[2]; - mfm_info[drive].lowcurrent = mingeo[2]; - mfm_info[drive].precomp = mingeo[2] / 2; - mfm_info[drive].heads = mingeo[1]; - mfm_info[drive].sectors = mingeo[0]; - outw (CMD_RCAL, MFM_COMMAND); - return 1; -} -#endif - -/* - * Initialise all drive information for this controller. - */ -static int mfm_initdrives(void) -{ - int drive; - - if (number_mfm_drives > MFM_MAXDRIVES) { - number_mfm_drives = MFM_MAXDRIVES; - printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n"); - } - - for (drive = 0; drive < number_mfm_drives; drive++) { - mfm_info[drive].lowcurrent = 1; - mfm_info[drive].precomp = 1; - mfm_info[drive].cylinder = -1; - mfm_info[drive].errors.recal = 0; - mfm_info[drive].errors.report = 0; - mfm_info[drive].errors.abort = 4; - -#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT - mfm_info[drive].cylinders = 1024; - mfm_info[drive].heads = 8; - mfm_info[drive].sectors = 64; - { - unsigned char cmdb[16]; - - mfm_setupspecify (drive, cmdb); - cmdb[1] &= ~0x81; - issue_command (CMD_SPC, cmdb, 16); - wait_for_completion (); - if (!mfm_detectdrive (drive)) { - mfm_info[drive].cylinders = 0; - mfm_info[drive].heads = 0; - mfm_info[drive].sectors = 0; - } - cmdb[0] = cmdb[1] = 0; - issue_command (CMD_CKV, cmdb, 2); - } -#else - mfm_info[drive].cylinders = 1; /* its going to have to figure it out from the partition info */ - mfm_info[drive].heads = 4; - mfm_info[drive].sectors = 32; -#endif - } - return number_mfm_drives; -} - - - -/* - * The 'front' end of the mfm driver follows... - */ - -static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct mfm_info *p = bdev->bd_disk->private_data; - - geo->heads = p->heads; - geo->sectors = p->sectors; - geo->cylinders = p->cylinders; - return 0; -} - -/* - * This is to handle various kernel command line parameters - * specific to this driver. - */ -void mfm_setup(char *str, int *ints) -{ - return; -} - -/* - * Set the CHS from the ADFS boot block if it is present. This is not ideal - * since if there are any non-ADFS partitions on the disk, this won't work! - * Hence, I want to get rid of this... - */ -void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, - unsigned char heads, unsigned int secsize) -{ - struct mfm_info *p = bdev->bd_disk->private_data; - int drive = p - mfm_info; - unsigned long disksize = bdev->bd_inode->i_size; - - if (p->cylinders == 1) { - p->sectors = secsptrack; - p->heads = heads; - p->cylinders = discsize / (secsptrack * heads * secsize); - - if ((heads < 1) || (p->cylinders > 1024)) { - printk("%s: Insane disc shape! Setting to 512/4/32\n", - bdev->bd_disk->disk_name); - - /* These values are fairly arbitary, but are there so that if your - * lucky you can pick apart your disc to find out what is going on - - * I reckon these figures won't hurt MOST drives - */ - p->sectors = 32; - p->heads = 4; - p->cylinders = 512; - } - if (raw_cmd.dev == drive) - mfm_specify (); - mfm_geometry (drive); - } -} - -static struct block_device_operations mfm_fops = -{ - .owner = THIS_MODULE, - .getgeo = mfm_getgeo, -}; - -/* - * See if there is a controller at the address presently at mfm_addr - * - * We check to see if the controller is busy - if it is, we abort it first, - * and check that the chip is no longer busy after at least 180 clock cycles. - * We then issue a command and check that the BSY or CPR bits are set. - */ -static int mfm_probecontroller (unsigned int mfm_addr) -{ - if (inw (MFM_STATUS) & STAT_BSY) { - outw (CMD_ABT, MFM_COMMAND); - udelay (50); - if (inw (MFM_STATUS) & STAT_BSY) - return 0; - } - - if (inw (MFM_STATUS) & STAT_CED) - outw (CMD_RCAL, MFM_COMMAND); - - outw (CMD_SEK, MFM_COMMAND); - - if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) { - unsigned int count = 2000; - while (inw (MFM_STATUS) & STAT_BSY) { - udelay (500); - if (!--count) - return 0; - } - - outw (CMD_RCAL, MFM_COMMAND); - } - return 1; -} - -static int mfm_do_init(unsigned char irqmask) -{ - int i, ret; - - printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq); - - ret = -EBUSY; - if (!request_region (mfm_addr, 10, "mfm")) - goto out1; - - ret = register_blkdev(MAJOR_NR, "mfm"); - if (ret) - goto out2; - - /* Stuff for the assembler routines to get to */ - hdc63463_baseaddress = ioaddr(mfm_addr); - hdc63463_irqpolladdress = mfm_IRQPollLoc; - hdc63463_irqpollmask = irqmask; - - mfm_queue = blk_init_queue(do_mfm_request, &mfm_lock); - if (!mfm_queue) - goto out2a; - - Busy = 0; - lastspecifieddrive = -1; - - mfm_drives = mfm_initdrives(); - if (!mfm_drives) { - ret = -ENODEV; - goto out3; - } - - for (i = 0; i < mfm_drives; i++) { - struct gendisk *disk = alloc_disk(64); - if (!disk) - goto Enomem; - disk->major = MAJOR_NR; - disk->first_minor = i << 6; - disk->fops = &mfm_fops; - sprintf(disk->disk_name, "mfm%c", 'a'+i); - mfm_gendisk[i] = disk; - } - - printk("mfm: detected %d hard drive%s\n", mfm_drives, - mfm_drives == 1 ? "" : "s"); - ret = request_irq(mfm_irq, mfm_interrupt_handler, IRQF_DISABLED, "MFM harddisk", NULL); - if (ret) { - printk("mfm: unable to get IRQ%d\n", mfm_irq); - goto out4; - } - - if (mfm_irqenable) - outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */ - - for (i = 0; i < mfm_drives; i++) { - mfm_geometry(i); - mfm_gendisk[i]->queue = mfm_queue; - add_disk(mfm_gendisk[i]); - } - return 0; - -out4: - for (i = 0; i < mfm_drives; i++) - put_disk(mfm_gendisk[i]); -out3: - blk_cleanup_queue(mfm_queue); -out2a: - unregister_blkdev(MAJOR_NR, "mfm"); -out2: - release_region(mfm_addr, 10); -out1: - return ret; -Enomem: - while (i--) - put_disk(mfm_gendisk[i]); - goto out3; -} - -static void mfm_do_exit(void) -{ - int i; - - free_irq(mfm_irq, NULL); - for (i = 0; i < mfm_drives; i++) { - del_gendisk(mfm_gendisk[i]); - put_disk(mfm_gendisk[i]); - } - blk_cleanup_queue(mfm_queue); - unregister_blkdev(MAJOR_NR, "mfm"); - if (mfm_addr) - release_region(mfm_addr, 10); -} - -static int __devinit mfm_probe(struct expansion_card *ec, struct ecard_id *id) -{ - if (mfm_addr) - return -EBUSY; - - mfm_addr = ecard_address(ec, ECARD_IOC, ECARD_MEDIUM) + 0x800; - mfm_IRQPollLoc = ioaddr(mfm_addr + 0x400); - mfm_irqenable = mfm_IRQPollLoc; - mfm_irq = ec->irq; - - return mfm_do_init(0x08); -} - -static void __devexit mfm_remove(struct expansion_card *ec) -{ - outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ - mfm_do_exit(); -} - -static const struct ecard_id mfm_cids[] = { - { MANU_ACORN, PROD_ACORN_MFM }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver mfm_driver = { - .probe = mfm_probe, - .remove = __devexit(mfm_remove), - .id_table = mfm_cids, - .drv = { - .name = "mfm", - }, -}; - -/* - * Look for a MFM controller - first check the motherboard, then the podules - * The podules have an extra interrupt enable that needs to be played with - * - * The HDC is accessed at MEDIUM IOC speeds. - */ -static int __init mfm_init (void) -{ - unsigned char irqmask; - - if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) { - mfm_addr = ONBOARD_MFM_ADDRESS; - mfm_IRQPollLoc = IOC_IRQSTATB; - mfm_irqenable = 0; - mfm_irq = IRQ_HARDDISK; - return mfm_do_init(0x08); /* IL3 pin */ - } else { - return ecard_register_driver(&mfm_driver); - } -} - -static void __exit mfm_exit(void) -{ - if (mfm_addr == ONBOARD_MFM_ADDRESS) - mfm_do_exit(); - else - ecard_unregister_driver(&mfm_driver); -} - -module_init(mfm_init) -module_exit(mfm_exit) -MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 408b451..f1372de 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -43,50 +43,30 @@ menuconfig ACPI if ACPI config ACPI_SLEEP - bool "Sleep States" - depends on X86 && (!SMP || SUSPEND_SMP) - default y - ---help--- - This option adds support for ACPI suspend states. - - With this option, you will be able to put the system "to sleep". - Sleep states are low power states for the system and devices. All - of the system operating state is saved to either memory or disk - (depending on the state), to allow the system to resume operation - quickly at your request. - - Although this option sounds really nifty, barely any of the device - drivers have been converted to the new driver model and hence few - have proper power management support. - - This option is not recommended for anyone except those doing driver - power management development. - -config ACPI_SLEEP_PROC_FS bool - depends on ACPI_SLEEP && PROC_FS + depends on PM_SLEEP default y -config ACPI_SLEEP_PROC_SLEEP - bool "/proc/acpi/sleep (deprecated)" - depends on ACPI_SLEEP_PROC_FS - default n - ---help--- - Create /proc/acpi/sleep - Deprecated by /sys/power/state - config ACPI_PROCFS - bool "Procfs interface (deprecated)" - default y + bool "Deprecated /proc/acpi files" + depends on PROC_FS ---help--- - The Procfs interface for ACPI is made optional for backward compatibility. - As the same functions are duplicated in the sysfs interface - and this proc interface will be removed some time later, - it's marked as deprecated. - ( /proc/acpi/debug_layer && debug_level are deprecated by - /sys/module/acpi/parameters/debug_layer && debug_level. - /proc/acpi/info is deprecated by - /sys/module/acpi/parameters/acpica_version ) + For backwards compatibility, this option allows + depricated /proc/acpi/ files to exist, even when + they have been replaced by functions in /sys. + The deprecated files (and their replacements) include: + + /proc/acpi/sleep (/sys/power/state) + /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) + /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) + /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) + /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) + /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) + + This option has no effect on /proc/acpi/ files + and functions which do not yet exist in /sys. + + Say N to delete /proc/acpi/ files that have moved to /sys/ config ACPI_AC tristate "AC Adapter" diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 37c7dc4..d8b3509 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -34,7 +34,6 @@ #define ACPI_AC_COMPONENT 0x00020000 #define ACPI_AC_CLASS "ac_adapter" -#define ACPI_AC_HID "ACPI0003" #define ACPI_AC_DEVICE_NAME "AC Adapter" #define ACPI_AC_FILE_STATE "state" #define ACPI_AC_NOTIFY_STATUS 0x80 @@ -56,10 +55,16 @@ static int acpi_ac_add(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device, int type); static int acpi_ac_open_fs(struct inode *inode, struct file *file); +const static struct acpi_device_id ac_device_ids[] = { + {"ACPI0003", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, ac_device_ids); + static struct acpi_driver acpi_ac_driver = { .name = "ac", .class = ACPI_AC_CLASS, - .ids = ACPI_AC_HID, + .ids = ac_device_ids, .ops = { .add = acpi_ac_add, .remove = acpi_ac_remove, diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index e65628a..5f1127a 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -53,10 +53,16 @@ static int acpi_memory_device_add(struct acpi_device *device); static int acpi_memory_device_remove(struct acpi_device *device, int type); static int acpi_memory_device_start(struct acpi_device *device); +static const struct acpi_device_id memory_device_ids[] = { + {ACPI_MEMORY_DEVICE_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, memory_device_ids); + static struct acpi_driver acpi_memory_device_driver = { .name = "acpi_memhotplug", .class = ACPI_MEMORY_DEVICE_CLASS, - .ids = ACPI_MEMORY_DEVICE_HID, + .ids = memory_device_ids, .ops = { .add = acpi_memory_device_add, .remove = acpi_memory_device_remove, diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index 3cd79ca..9c4bd22 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -56,7 +56,6 @@ #define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver" #define ACPI_HOTK_CLASS "hotkey" #define ACPI_HOTK_DEVICE_NAME "Hotkey" -#define ACPI_HOTK_HID "ATK0100" /* * Some events we use, same for all Asus @@ -426,14 +425,20 @@ static struct acpi_table_header *asus_info; static struct asus_hotk *hotk; /* - * The hotkey driver declaration + * The hotkey driver and autoloading declaration */ static int asus_hotk_add(struct acpi_device *device); static int asus_hotk_remove(struct acpi_device *device, int type); +static const struct acpi_device_id asus_device_ids[] = { + {"ATK0100", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, asus_device_ids); + static struct acpi_driver asus_hotk_driver = { .name = "asus_acpi", .class = ACPI_HOTK_CLASS, - .ids = ACPI_HOTK_HID, + .ids = asus_device_ids, .ops = { .add = asus_hotk_add, .remove = asus_hotk_remove, diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index cad932d..8165103 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -41,7 +41,6 @@ #define ACPI_BATTERY_COMPONENT 0x00040000 #define ACPI_BATTERY_CLASS "battery" -#define ACPI_BATTERY_HID "PNP0C0A" #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 @@ -74,10 +73,16 @@ static int acpi_battery_add(struct acpi_device *device); static int acpi_battery_remove(struct acpi_device *device, int type); static int acpi_battery_resume(struct acpi_device *device); +static const struct acpi_device_id battery_device_ids[] = { + {"PNP0C0A", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, battery_device_ids); + static struct acpi_driver acpi_battery_driver = { .name = "battery", .class = ACPI_BATTERY_CLASS, - .ids = ACPI_BATTERY_HID, + .ids = battery_device_ids, .ops = { .add = acpi_battery_add, .resume = acpi_battery_resume, diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb4110b..5405813 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -66,6 +66,16 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI Button Driver"); MODULE_LICENSE("GPL"); +static const struct acpi_device_id button_device_ids[] = { + {ACPI_BUTTON_HID_LID, 0}, + {ACPI_BUTTON_HID_SLEEP, 0}, + {ACPI_BUTTON_HID_SLEEPF, 0}, + {ACPI_BUTTON_HID_POWER, 0}, + {ACPI_BUTTON_HID_POWERF, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, button_device_ids); + static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); static int acpi_button_info_open_fs(struct inode *inode, struct file *file); @@ -74,7 +84,7 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = "button", .class = ACPI_BUTTON_CLASS, - .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E", + .ids = button_device_ids, .ops = { .add = acpi_button_add, .remove = acpi_button_remove, diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 0dd3bf7..3c25ec7 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -52,10 +52,18 @@ MODULE_LICENSE("GPL"); static int acpi_container_add(struct acpi_device *device); static int acpi_container_remove(struct acpi_device *device, int type); +static const struct acpi_device_id container_device_ids[] = { + {"ACPI0004", 0}, + {"PNP0A05", 0}, + {"PNP0A06", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, container_device_ids); + static struct acpi_driver acpi_container_driver = { .name = "container", .class = ACPI_CONTAINER_CLASS, - .ids = "ACPI0004,PNP0A05,PNP0A06", + .ids = container_device_ids, .ops = { .add = acpi_container_add, .remove = acpi_container_remove, diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 10e8510..469f3f5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -41,7 +41,6 @@ #include <acpi/actypes.h> #define ACPI_EC_CLASS "embedded_controller" -#define ACPI_EC_HID "PNP0C09" #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" @@ -82,10 +81,15 @@ static int acpi_ec_start(struct acpi_device *device); static int acpi_ec_stop(struct acpi_device *device, int type); static int acpi_ec_add(struct acpi_device *device); +static const struct acpi_device_id ec_device_ids[] = { + {"PNP0C09", 0}, + {"", 0}, +}; + static struct acpi_driver acpi_ec_driver = { .name = "ec", .class = ACPI_EC_CLASS, - .ids = ACPI_EC_HID, + .ids = ec_device_ids, .ops = { .add = acpi_ec_add, .remove = acpi_ec_remove, diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 23ee7bc..b1aaa0e 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -378,7 +378,7 @@ static u8 acpi_ev_match_pci_root_bridge(char *id) static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) { acpi_status status; - struct acpi_device_id hid; + struct acpica_device_id hid; struct acpi_compatible_id_list *cid; acpi_native_uint i; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index ec655c5..c81f6bd 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -50,10 +50,16 @@ static int acpi_fan_remove(struct acpi_device *device, int type); static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); static int acpi_fan_resume(struct acpi_device *device); +static const struct acpi_device_id fan_device_ids[] = { + {"PNP0C0B", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, fan_device_ids); + static struct acpi_driver acpi_fan_driver = { .name = "fan", .class = ACPI_FAN_CLASS, - .ids = "PNP0C0B", + .ids = fan_device_ids, .ops = { .add = acpi_fan_add, .remove = acpi_fan_remove, diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index be4f289..ab65b2c 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -440,7 +440,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, acpi_status status; struct acpi_namespace_node *node; u32 flags; - struct acpi_device_id hid; + struct acpica_device_id hid; struct acpi_compatible_id_list *cid; acpi_native_uint i; diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 3448edd..c9f526e 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -46,7 +46,6 @@ #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" -#define ACPI_PCI_LINK_HID "PNP0C0F" #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" #define ACPI_PCI_LINK_FILE_INFO "info" #define ACPI_PCI_LINK_FILE_STATUS "state" @@ -54,10 +53,16 @@ ACPI_MODULE_NAME("pci_link"); static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); +static struct acpi_device_id link_device_ids[] = { + {"PNP0C0F", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, link_device_ids); + static struct acpi_driver acpi_pci_link_driver = { .name = "pci_link", .class = ACPI_PCI_LINK_CLASS, - .ids = ACPI_PCI_LINK_HID, + .ids = link_device_ids, .ops = { .add = acpi_pci_link_add, .remove = acpi_pci_link_remove, diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ad4145a..f14ff1f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -38,16 +38,21 @@ #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" -#define ACPI_PCI_ROOT_HID "PNP0A03" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); +static struct acpi_device_id root_device_ids[] = { + {"PNP0A03", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, root_device_ids); + static struct acpi_driver acpi_pci_root_driver = { .name = "pci_root", .class = ACPI_PCI_ROOT_CLASS, - .ids = ACPI_PCI_ROOT_HID, + .ids = root_device_ids, .ops = { .add = acpi_pci_root_add, .remove = acpi_pci_root_remove, diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 4ffecd1..57b9a29 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -59,10 +59,16 @@ static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); +static struct acpi_device_id power_device_ids[] = { + {ACPI_POWER_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, power_device_ids); + static struct acpi_driver acpi_power_driver = { .name = "power", .class = ACPI_POWER_CLASS, - .ids = ACPI_POWER_HID, + .ids = power_device_ids, .ops = { .add = acpi_power_add, .remove = acpi_power_remove, diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 81aceb5..4984223 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -88,10 +88,16 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); +static const struct acpi_device_id processor_device_ids[] = { + {ACPI_PROCESSOR_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, processor_device_ids); + static struct acpi_driver acpi_processor_driver = { .name = "processor", .class = ACPI_PROCESSOR_CLASS, - .ids = ACPI_PROCESSOR_HID, + .ids = processor_device_ids, .ops = { .add = acpi_processor_add, .remove = acpi_processor_remove, diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 3f55d1f..0b8204e 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -47,6 +47,9 @@ ACPI_MODULE_NAME("processor_throttling"); static int acpi_processor_get_throttling(struct acpi_processor *pr); int acpi_processor_set_throttling(struct acpi_processor *pr, int state); +/* + * _TPC - Throttling Present Capabilities + */ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; @@ -55,8 +58,10 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) if (!pr) return -EINVAL; status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); + } return -ENODEV; } pr->throttling_platform_limit = (int)tpc; @@ -68,9 +73,9 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr) return acpi_processor_get_platform_limit(pr); } -/* -------------------------------------------------------------------------- - _PTC, _TSS, _TSD support - -------------------------------------------------------------------------- */ +/* + * _PTC - Processor Throttling Control (and status) register location + */ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) { int result = 0; @@ -81,7 +86,9 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); + if (status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); + } return -ENODEV; } @@ -132,6 +139,10 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) return result; } + +/* + * _TSS - Throttling Supported States + */ static int acpi_processor_get_throttling_states(struct acpi_processor *pr) { int result = 0; @@ -144,7 +155,9 @@ static int acpi_processor_get_throttling_states(struct acpi_processor *pr) status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); + if (status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); + } return -ENODEV; } @@ -201,6 +214,10 @@ static int acpi_processor_get_throttling_states(struct acpi_processor *pr) return result; } + +/* + * _TSD - T-State Dependencies + */ static int acpi_processor_get_tsd(struct acpi_processor *pr) { int result = 0; @@ -213,6 +230,9 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSD")); + } return -ENODEV; } @@ -525,9 +545,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) int result = 0; int step = 0; int i = 0; - int no_ptc = 0; - int no_tss = 0; - int no_tsd = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", @@ -538,12 +555,14 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) if (!pr) return -EINVAL; - /* TBD: Support ACPI 2.0 objects */ - no_ptc = acpi_processor_get_throttling_control(pr); - no_tss = acpi_processor_get_throttling_states(pr); - no_tsd = acpi_processor_get_tsd(pr); - - if (no_ptc || no_tss) { + /* + * Evaluate _PTC, _TSS and _TPC + * They must all be present or none of them can be used. + */ + if (acpi_processor_get_throttling_control(pr) || + acpi_processor_get_throttling_states(pr) || + acpi_processor_get_platform_limit(pr)) + { pr->throttling.acpi_processor_get_throttling = &acpi_processor_get_throttling_fadt; pr->throttling.acpi_processor_set_throttling = @@ -555,6 +574,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) &acpi_processor_set_throttling_ptc; } + acpi_processor_get_tsd(pr); + if (!pr->throttling.address) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); return 0; @@ -658,18 +679,20 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, pr->throttling.state_count - 1); seq_puts(seq, "states:\n"); - if (acpi_processor_get_throttling == acpi_processor_get_throttling_fadt) + if (pr->throttling.acpi_processor_get_throttling == + acpi_processor_get_throttling_fadt) { for (i = 0; i < pr->throttling.state_count; i++) seq_printf(seq, " %cT%d: %02d%%\n", (i == pr->throttling.state ? '*' : ' '), i, (pr->throttling.states[i].performance ? pr-> throttling.states[i].performance / 10 : 0)); - else + } else { for (i = 0; i < pr->throttling.state_count; i++) seq_printf(seq, " %cT%d: %02d%%\n", (i == pr->throttling.state ? '*' : ' '), i, (int)pr->throttling.states_tss[i]. freqpercentage); + } end: return 0; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 974d00c..7d8e78e 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -38,7 +38,6 @@ #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" -#define ACPI_SBS_HID "ACPI0002" #define ACPI_SBS_DEVICE_NAME "Smart Battery System" #define ACPI_SBS_FILE_INFO "info" #define ACPI_SBS_FILE_STATE "state" @@ -124,10 +123,17 @@ static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_remove(struct acpi_device *device, int type); static int acpi_sbs_resume(struct acpi_device *device); +static const struct acpi_device_id sbs_device_ids[] = { + {"ACPI0001", 0}, + {"ACPI0005", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, sbs_device_ids); + static struct acpi_driver acpi_sbs_driver = { .name = "sbs", .class = ACPI_SBS_CLASS, - .ids = "ACPI0001,ACPI0005", + .ids = sbs_device_ids, .ops = { .add = acpi_sbs_add, .remove = acpi_sbs_remove, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 6b3b8a5..be74347 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -16,7 +16,7 @@ ACPI_MODULE_NAME("scan"); extern struct acpi_device *acpi_root; #define ACPI_BUS_CLASS "system_bus" -#define ACPI_BUS_HID "ACPI_BUS" +#define ACPI_BUS_HID "LNXSYBUS" #define ACPI_BUS_DEVICE_NAME "System Bus" static LIST_HEAD(acpi_device_list); @@ -29,6 +29,62 @@ struct acpi_device_bus_id{ unsigned int instance_no; struct list_head node; }; + +/* + * Creates hid/cid(s) string needed for modalias and uevent + * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: + * char *modalias: "acpi:IBM0001:ACPI0001" +*/ +int create_modalias(struct acpi_device *acpi_dev, char *modalias, int size){ + + int len; + + if (!acpi_dev->flags.hardware_id) + return -ENODEV; + + len = snprintf(modalias, size, "acpi:%s:", + acpi_dev->pnp.hardware_id); + if (len < 0 || len >= size) + return -EINVAL; + size -= len; + + if (acpi_dev->flags.compatible_ids) { + struct acpi_compatible_id_list *cid_list; + int i; + int count; + + cid_list = acpi_dev->pnp.cid_list; + for (i = 0; i < cid_list->count; i++) { + count = snprintf(&modalias[len], size, "%s:", + cid_list->id[i].value); + if (count < 0 || count >= size) { + printk(KERN_ERR "acpi: %s cid[%i] exceeds event buffer size", + acpi_dev->pnp.device_name, i); + break; + } + len += count; + size -= count; + } + } + + modalias[len] = '\0'; + return len; +} + +static ssize_t +acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); + int len; + + /* Device has no HID and no CID or string is >1024 */ + len = create_modalias(acpi_dev, buf, 1024); + if (len <= 0) + return 0; + buf[len++] = '\n'; + return len; +} +static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); + static int acpi_eject_operation(acpi_handle handle, int lockable) { struct acpi_object_list arg_list; @@ -154,6 +210,12 @@ static int acpi_device_setup_files(struct acpi_device *dev) goto end; } + if (dev->flags.hardware_id || dev->flags.compatible_ids){ + result = device_create_file(&dev->dev, &dev_attr_modalias); + if(result) + goto end; + } + /* * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. @@ -178,6 +240,9 @@ static void acpi_device_remove_files(struct acpi_device *dev) if (ACPI_SUCCESS(status)) device_remove_file(&dev->dev, &dev_attr_eject); + if (dev->flags.hardware_id || dev->flags.compatible_ids) + device_remove_file(&dev->dev, &dev_attr_modalias); + if(dev->flags.hardware_id) device_remove_file(&dev->dev, &dev_attr_hid); if(dev->handle) @@ -186,6 +251,37 @@ static void acpi_device_remove_files(struct acpi_device *dev) /* -------------------------------------------------------------------------- ACPI Bus operations -------------------------------------------------------------------------- */ + +int acpi_match_device_ids(struct acpi_device *device, + const struct acpi_device_id *ids) +{ + const struct acpi_device_id *id; + + if (device->flags.hardware_id) { + for (id = ids; id->id[0]; id++) { + if (!strcmp((char*)id->id, device->pnp.hardware_id)) + return 0; + } + } + + if (device->flags.compatible_ids) { + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + int i; + + for (id = ids; id->id[0]; id++) { + /* compare multiple _CID entries against driver ids */ + for (i = 0; i < cid_list->count; i++) { + if (!strcmp((char*)id->id, + cid_list->id[i].value)) + return 0; + } + } + } + + return -ENOENT; +} +EXPORT_SYMBOL(acpi_match_device_ids); + static void acpi_device_release(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -219,37 +315,19 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_ids(acpi_dev, acpi_drv->ids); + return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) + char *buffer, int buffer_size) { struct acpi_device *acpi_dev = to_acpi_device(dev); - int i = 0, length = 0, ret = 0; - - if (acpi_dev->flags.hardware_id) - ret = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "HWID=%s", acpi_dev->pnp.hardware_id); - if (ret) - return -ENOMEM; - if (acpi_dev->flags.compatible_ids) { - int j; - struct acpi_compatible_id_list *cid_list; - cid_list = acpi_dev->pnp.cid_list; - - for (j = 0; j < cid_list->count; j++) { - ret = add_uevent_var(envp, num_envp, &i, buffer, - buffer_size, &length, "COMPTID=%s", - cid_list->id[j].value); - if (ret) - return -ENOMEM; - } + strcpy(buffer, "MODALIAS="); + if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { + envp[0] = buffer; + envp[1] = NULL; } - - envp[i] = NULL; return 0; } @@ -543,25 +621,6 @@ void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) return; } -int acpi_match_ids(struct acpi_device *device, char *ids) -{ - if (device->flags.hardware_id) - if (strstr(ids, device->pnp.hardware_id)) - return 0; - - if (device->flags.compatible_ids) { - struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; - int i; - - /* compare multiple _CID entries against driver ids */ - for (i = 0; i < cid_list->count; i++) { - if (strstr(ids, cid_list->id[i].value)) - return 0; - } - } - return -ENOENT; -} - static int acpi_bus_get_perf_flags(struct acpi_device *device) { device->performance.state = ACPI_STATE_UNKNOWN; @@ -624,6 +683,13 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; + struct acpi_device_id button_device_ids[] = { + {"PNP0C0D", 0}, + {"PNP0C0C", 0}, + {"PNP0C0E", 0}, + {"", 0}, + }; + /* _PRW */ status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); @@ -643,7 +709,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) device->wakeup.flags.valid = 1; /* Power button, Lid switch always enable wakeup */ - if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E")) + if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; end: diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile index d6c0177..195a4f6 100644 --- a/drivers/acpi/sleep/Makefile +++ b/drivers/acpi/sleep/Makefile @@ -1,5 +1,5 @@ obj-y := poweroff.o wakeup.o obj-$(CONFIG_ACPI_SLEEP) += main.o -obj-$(CONFIG_ACPI_SLEEP_PROC_FS) += proc.o +obj-$(CONFIG_ACPI_SLEEP) += proc.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 3279e72..e8cff5d 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -21,6 +21,9 @@ u8 sleep_states[ACPI_S_STATE_COUNT]; +static u32 acpi_target_sleep_state = ACPI_STATE_S0; + +#ifdef CONFIG_SUSPEND static struct pm_ops acpi_pm_ops; extern void do_suspend_lowlevel(void); @@ -35,34 +38,49 @@ static u32 acpi_suspend_states[] = { static int init_8259A_after_S1; /** + * acpi_pm_set_target - Set the target system sleep state to the state + * associated with given @pm_state, if supported. + */ + +static int acpi_pm_set_target(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + int error = 0; + + if (sleep_states[acpi_state]) { + acpi_target_sleep_state = acpi_state; + } else { + printk(KERN_ERR "ACPI does not support this state: %d\n", + pm_state); + error = -ENOSYS; + } + return error; +} + +/** * acpi_pm_prepare - Do preliminary suspend work. - * @pm_state: suspend state we're entering. + * @pm_state: ignored * - * Make sure we support the state. If we do, and we need it, set the - * firmware waking vector and do arch-specific nastiness to get the - * wakeup code to the waking vector. + * If necessary, set the firmware waking vector and do arch-specific + * nastiness to get the wakeup code to the waking vector. */ -extern int acpi_sleep_prepare(u32 acpi_state); -extern void acpi_power_off(void); - static int acpi_pm_prepare(suspend_state_t pm_state) { - u32 acpi_state = acpi_suspend_states[pm_state]; + int error = acpi_sleep_prepare(acpi_target_sleep_state); - if (!sleep_states[acpi_state]) { - printk("acpi_pm_prepare does not support %d \n", pm_state); - return -EPERM; - } - return acpi_sleep_prepare(acpi_state); + if (error) + acpi_target_sleep_state = ACPI_STATE_S0; + + return error; } /** * acpi_pm_enter - Actually enter a sleep state. - * @pm_state: State we're entering. + * @pm_state: ignored * - * Flush caches and go to sleep. For STR or STD, we have to call - * arch-specific assembly, which in turn call acpi_enter_sleep_state(). + * Flush caches and go to sleep. For STR we have to call arch-specific + * assembly, which in turn call acpi_enter_sleep_state(). * It's unfortunate, but it works. Please fix if you're feeling frisky. */ @@ -70,31 +88,31 @@ static int acpi_pm_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; unsigned long flags = 0; - u32 acpi_state = acpi_suspend_states[pm_state]; + u32 acpi_state = acpi_target_sleep_state; ACPI_FLUSH_CPU_CACHE(); /* Do arch specific saving of state. */ - if (pm_state > PM_SUSPEND_STANDBY) { + if (acpi_state == ACPI_STATE_S3) { int error = acpi_save_state_mem(); - if (error) + + if (error) { + acpi_target_sleep_state = ACPI_STATE_S0; return error; + } } local_irq_save(flags); acpi_enable_wakeup_device(acpi_state); - switch (pm_state) { - case PM_SUSPEND_STANDBY: + switch (acpi_state) { + case ACPI_STATE_S1: barrier(); status = acpi_enter_sleep_state(acpi_state); break; - case PM_SUSPEND_MEM: + case ACPI_STATE_S3: do_suspend_lowlevel(); break; - - default: - return -EINVAL; } /* ACPI 3.0 specs (P62) says that it's the responsabilty @@ -107,12 +125,8 @@ static int acpi_pm_enter(suspend_state_t pm_state) local_irq_restore(flags); printk(KERN_DEBUG "Back to C!\n"); - /* restore processor state - * We should only be here if we're coming back from STR or STD. - * And, in the case of the latter, the memory image should have already - * been loaded from disk. - */ - if (pm_state > PM_SUSPEND_STANDBY) + /* restore processor state */ + if (acpi_state == ACPI_STATE_S3) acpi_restore_state_mem(); return ACPI_SUCCESS(status) ? 0 : -EFAULT; @@ -120,7 +134,7 @@ static int acpi_pm_enter(suspend_state_t pm_state) /** * acpi_pm_finish - Finish up suspend sequence. - * @pm_state: State we're coming out of. + * @pm_state: ignored * * This is called after we wake back up (or if entering the sleep state * failed). @@ -128,7 +142,7 @@ static int acpi_pm_enter(suspend_state_t pm_state) static int acpi_pm_finish(suspend_state_t pm_state) { - u32 acpi_state = acpi_suspend_states[pm_state]; + u32 acpi_state = acpi_target_sleep_state; acpi_leave_sleep_state(acpi_state); acpi_disable_wakeup_device(acpi_state); @@ -136,28 +150,17 @@ static int acpi_pm_finish(suspend_state_t pm_state) /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); + acpi_target_sleep_state = ACPI_STATE_S0; + +#ifdef CONFIG_X86 if (init_8259A_after_S1) { printk("Broken toshiba laptop -> kicking interrupts\n"); init_8259A(0); } +#endif return 0; } -int acpi_suspend(u32 acpi_state) -{ - suspend_state_t states[] = { - [1] = PM_SUSPEND_STANDBY, - [3] = PM_SUSPEND_MEM, - [5] = PM_SUSPEND_MAX - }; - - if (acpi_state < 6 && states[acpi_state]) - return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); - return -EINVAL; -} - static int acpi_pm_state_valid(suspend_state_t pm_state) { u32 acpi_state; @@ -176,12 +179,34 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) static struct pm_ops acpi_pm_ops = { .valid = acpi_pm_state_valid, + .set_target = acpi_pm_set_target, .prepare = acpi_pm_prepare, .enter = acpi_pm_enter, .finish = acpi_pm_finish, }; -#ifdef CONFIG_SOFTWARE_SUSPEND +/* + * Toshiba fails to preserve interrupts over S1, reinitialization + * of 8259 is needed after S1 resume. + */ +static int __init init_ints_after_s1(struct dmi_system_id *d) +{ + printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); + init_8259A_after_S1 = 1; + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_ints_after_s1, + .ident = "Toshiba Satellite 4030cdt", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, + }, + {}, +}; +#endif /* CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION static int acpi_hibernation_prepare(void) { return acpi_sleep_prepare(ACPI_STATE_S4); @@ -233,41 +258,114 @@ static struct hibernation_ops acpi_hibernation_ops = { .pre_restore = acpi_hibernation_pre_restore, .restore_cleanup = acpi_hibernation_restore_cleanup, }; -#endif /* CONFIG_SOFTWARE_SUSPEND */ +#endif /* CONFIG_HIBERNATION */ -/* - * Toshiba fails to preserve interrupts over S1, reinitialization - * of 8259 is needed after S1 resume. - */ -static int __init init_ints_after_s1(struct dmi_system_id *d) +int acpi_suspend(u32 acpi_state) { - printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); - init_8259A_after_S1 = 1; - return 0; + suspend_state_t states[] = { + [1] = PM_SUSPEND_STANDBY, + [3] = PM_SUSPEND_MEM, + [5] = PM_SUSPEND_MAX + }; + + if (acpi_state < 6 && states[acpi_state]) + return pm_suspend(states[acpi_state]); + if (acpi_state == 4) + return hibernate(); + return -EINVAL; } -static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - { - .callback = init_ints_after_s1, - .ident = "Toshiba Satellite 4030cdt", - .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, - }, - {}, -}; +/** + * acpi_pm_device_sleep_state - return preferred power state of ACPI device + * in the system sleep state given by %acpi_target_sleep_state + * @dev: device to examine + * @wake: if set, the device should be able to wake up the system + * @d_min_p: used to store the upper limit of allowed states range + * Return value: preferred power state of the device on success, -ENODEV on + * failure (ie. if there's no 'struct acpi_device' for @dev) + * + * Find the lowest power (highest number) ACPI device power state that + * device @dev can be in while the system is in the sleep state represented + * by %acpi_target_sleep_state. If @wake is nonzero, the device should be + * able to wake up the system from this sleep state. If @d_min_p is set, + * the highest power (lowest number) device power state of @dev allowed + * in this system sleep state is stored at the location pointed to by it. + * + * The caller must ensure that @dev is valid before using this function. + * The caller is also responsible for figuring out if the device is + * supposed to be able to wake up the system and passing this information + * via @wake. + */ + +int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + struct acpi_device *adev; + char acpi_method[] = "_SxD"; + unsigned long d_min, d_max; + + if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { + printk(KERN_ERR "ACPI handle has no context!\n"); + return -ENODEV; + } + + acpi_method[2] = '0' + acpi_target_sleep_state; + /* + * If the sleep state is S0, we will return D3, but if the device has + * _S0W, we will use the value from _S0W + */ + d_min = ACPI_STATE_D0; + d_max = ACPI_STATE_D3; + + /* + * If present, _SxD methods return the minimum D-state (highest power + * state) we can use for the corresponding S-states. Otherwise, the + * minimum D-state is D0 (ACPI 3.x). + * + * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer + * provided -- that's our fault recovery, we ignore retval. + */ + if (acpi_target_sleep_state > ACPI_STATE_S0) + acpi_evaluate_integer(handle, acpi_method, NULL, &d_min); + + /* + * If _PRW says we can wake up the system from the target sleep state, + * the D-state returned by _SxD is sufficient for that (we assume a + * wakeup-aware driver if wake is set). Still, if _SxW exists + * (ACPI 3.x), it should return the maximum (lowest power) D-state that + * can wake the system. _S0W may be valid, too. + */ + if (acpi_target_sleep_state == ACPI_STATE_S0 || + (wake && adev->wakeup.state.enabled && + adev->wakeup.sleep_state <= acpi_target_sleep_state)) { + acpi_method[3] = 'W'; + acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); + /* Sanity check */ + if (d_max < d_min) + d_min = d_max; + } + + if (d_min_p) + *d_min_p = d_min; + return d_max; +} int __init acpi_sleep_init(void) { + acpi_status status; + u8 type_a, type_b; +#ifdef CONFIG_SUSPEND int i = 0; dmi_check_system(acpisleep_dmi_table); +#endif if (acpi_disabled) return 0; +#ifdef CONFIG_SUSPEND printk(KERN_INFO PREFIX "(supports"); - for (i = 0; i < ACPI_S_STATE_COUNT; i++) { - acpi_status status; - u8 type_a, type_b; + for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) { status = acpi_get_sleep_type_data(i, &type_a, &type_b); if (ACPI_SUCCESS(status)) { sleep_states[i] = 1; @@ -277,10 +375,14 @@ int __init acpi_sleep_init(void) printk(")\n"); pm_set_ops(&acpi_pm_ops); +#endif -#ifdef CONFIG_SOFTWARE_SUSPEND - if (sleep_states[ACPI_STATE_S4]) +#ifdef CONFIG_HIBERNATION + status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { hibernation_set_ops(&acpi_hibernation_ops); + sleep_states[ACPI_STATE_S4] = 1; + } #else sleep_states[ACPI_STATE_S4] = 0; #endif diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 61f1822..66b62b0 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -14,8 +14,16 @@ #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT + +/* + * this file provides support for: + * /proc/acpi/sleep + * /proc/acpi/alarm + * /proc/acpi/wakeup + */ + ACPI_MODULE_NAME("sleep") -#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP +#ifdef CONFIG_ACPI_PROCFS_SLEEP static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset) { int i; @@ -58,7 +66,7 @@ acpi_system_write_sleep(struct file *file, goto Done; } state = simple_strtoul(str, NULL, 0); -#ifdef CONFIG_SOFTWARE_SUSPEND +#ifdef CONFIG_HIBERNATION if (state == 4) { error = hibernate(); goto Done; @@ -68,9 +76,9 @@ acpi_system_write_sleep(struct file *file, Done: return error ? error : count; } -#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */ +#endif /* CONFIG_ACPI_PROCFS_SLEEP */ -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) +#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86) /* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */ #else #define HAVE_ACPI_LEGACY_ALARM @@ -463,7 +471,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = { .release = single_release, }; -#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP +#ifdef CONFIG_ACPI_PROCFS_SLEEP static const struct file_operations acpi_system_sleep_fops = { .open = acpi_system_sleep_open_fs, .read = seq_read, @@ -471,7 +479,7 @@ static const struct file_operations acpi_system_sleep_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif /* CONFIG_ACPI_SLEEP_PROC_SLEEP */ +#endif /* CONFIG_ACPI_PROCFS_SLEEP */ #ifdef HAVE_ACPI_LEGACY_ALARM static const struct file_operations acpi_system_alarm_fops = { @@ -498,14 +506,14 @@ static int __init acpi_sleep_proc_init(void) if (acpi_disabled) return 0; -#ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP +#ifdef CONFIG_ACPI_PROCFS_SLEEP /* 'sleep' [R/W] */ entry = create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR, acpi_root_dir); if (entry) entry->proc_fops = &acpi_system_sleep_fops; -#endif +#endif /* CONFIG_ACPI_PROCFS */ #ifdef HAVE_ACPI_LEGACY_ALARM /* 'alarm' [R/W] */ diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index f3e7039..ff1f850 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h @@ -6,3 +6,5 @@ extern void acpi_enable_wakeup_device_prep(u8 sleep_state); extern void acpi_enable_wakeup_device(u8 sleep_state); extern void acpi_disable_wakeup_device(u8 sleep_state); extern void acpi_gpe_sleep_prepare(u32 sleep_state); + +extern int acpi_sleep_prepare(u32 acpi_state); diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index fab8f26..97c27dd 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -17,7 +17,6 @@ ACPI_MODULE_NAME("wakeup_devices") extern struct list_head acpi_wakeup_device_list; extern spinlock_t acpi_device_lock; -#ifdef CONFIG_ACPI_SLEEP /** * acpi_enable_wakeup_device_prep - prepare wakeup devices * @sleep_state: ACPI state @@ -180,7 +179,6 @@ static int __init acpi_wakeup_device_init(void) } late_initcall(acpi_wakeup_device_init); -#endif /* * Disable all wakeup GPEs before entering requested sleep state. diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 58f1338..5a62de1 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -92,10 +92,16 @@ static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, size_t, loff_t *); +static const struct acpi_device_id thermal_device_ids[] = { + {ACPI_THERMAL_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, thermal_device_ids); + static struct acpi_driver acpi_thermal_driver = { .name = "thermal", .class = ACPI_THERMAL_CLASS, - .ids = ACPI_THERMAL_HID, + .ids = thermal_device_ids, .ops = { .add = acpi_thermal_add, .remove = acpi_thermal_remove, diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index f112af4..0042b7e 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -407,7 +407,7 @@ acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length) acpi_status acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpi_device_id *hid) + struct acpica_device_id *hid) { union acpi_operand_object *obj_desc; acpi_status status; @@ -609,7 +609,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpi_device_id *uid) + struct acpica_device_id *uid) { union acpi_operand_object *obj_desc; acpi_status status; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 04ea697..d987019 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -74,10 +74,16 @@ MODULE_LICENSE("GPL"); static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); +static const struct acpi_device_id video_device_ids[] = { + {ACPI_VIDEO_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, video_device_ids); + static struct acpi_driver acpi_video_bus = { .name = "video", .class = ACPI_VIDEO_CLASS, - .ids = ACPI_VIDEO_HID, + .ids = video_device_ids, .ops = { .add = acpi_video_bus_add, .remove = acpi_video_bus_remove, diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d9fa329..ad07086 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -91,6 +91,7 @@ #include <linux/device.h> #include <scsi/scsi_host.h> #include <linux/libata.h> +#include <linux/dmi.h> #define DRV_NAME "ata_piix" #define DRV_VERSION "2.11" @@ -140,6 +141,9 @@ enum { RV = -3, /* reserved */ PIIX_AHCI_DEVICE = 6, + + /* host->flags bits */ + PIIX_HOST_BROKEN_SUSPEND = (1 << 24), }; struct piix_map_db { @@ -159,6 +163,10 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev); static int ich_pata_cable_detect(struct ata_port *ap); +#ifdef CONFIG_PM +static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int piix_pci_device_resume(struct pci_dev *pdev); +#endif static unsigned int in_module_init = 1; @@ -255,8 +263,8 @@ static struct pci_driver piix_pci_driver = { .probe = piix_init_one, .remove = ata_pci_remove_one, #ifdef CONFIG_PM - .suspend = ata_pci_device_suspend, - .resume = ata_pci_device_resume, + .suspend = piix_pci_device_suspend, + .resume = piix_pci_device_resume, #endif }; @@ -881,6 +889,107 @@ static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev) do_pata_set_dmamode(ap, adev, 1); } +#ifdef CONFIG_PM +static struct dmi_system_id piix_broken_suspend_dmi_table[] = { + { + .ident = "TECRA M5", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M5"), + }, + }, + { + .ident = "Satellite U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U200"), + }, + }, + { + .ident = "Satellite U205", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U205"), + }, + }, + { + .ident = "Portege M500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M500"), + }, + }, + { } +}; + +static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + unsigned long flags; + int rc = 0; + + rc = ata_host_suspend(host, mesg); + if (rc) + return rc; + + /* Some braindamaged ACPI suspend implementations expect the + * controller to be awake on entry; otherwise, it burns cpu + * cycles and power trying to do something to the sleeping + * beauty. + */ + if (dmi_check_system(piix_broken_suspend_dmi_table) && + mesg.event == PM_EVENT_SUSPEND) { + pci_save_state(pdev); + + /* mark its power state as "unknown", since we don't + * know if e.g. the BIOS will change its device state + * when we suspend. + */ + if (pdev->current_state == PCI_D0) + pdev->current_state = PCI_UNKNOWN; + + /* tell resume that it's waking up from broken suspend */ + spin_lock_irqsave(&host->lock, flags); + host->flags |= PIIX_HOST_BROKEN_SUSPEND; + spin_unlock_irqrestore(&host->lock, flags); + } else + ata_pci_device_do_suspend(pdev, mesg); + + return 0; +} + +static int piix_pci_device_resume(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + unsigned long flags; + int rc; + + if (host->flags & PIIX_HOST_BROKEN_SUSPEND) { + spin_lock_irqsave(&host->lock, flags); + host->flags &= ~PIIX_HOST_BROKEN_SUSPEND; + spin_unlock_irqrestore(&host->lock, flags); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + /* PCI device wasn't disabled during suspend. Use + * __pci_reenable_device() to avoid affecting the + * enable count. + */ + rc = __pci_reenable_device(pdev); + if (rc) + dev_printk(KERN_ERR, &pdev->dev, "failed to enable " + "device after resume (%d)\n", rc); + } else + rc = ata_pci_device_do_resume(pdev); + + if (rc == 0) + ata_host_resume(host); + + return rc; +} +#endif + #define AHCI_PCI_BAR 5 #define AHCI_GLOBAL_CTL 0x04 #define AHCI_ENABLE (1 << 31) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 12ac0b5..e836476 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -768,7 +768,7 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, * Decrement max hw segments accordingly. */ if (dev->class == ATA_DEV_ATAPI) { - request_queue_t *q = sdev->request_queue; + struct request_queue *q = sdev->request_queue; blk_queue_max_hw_segments(q, q->max_hw_segments - 1); } diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 0104367..e8a28e9 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -45,7 +45,7 @@ static struct dmi_system_id cable_dmi_table[] = { .ident = "HP Pavilion N5430", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"), + DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), }, }, { } diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index b0af65a..84d9c55 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -26,7 +26,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.6" +#define DRV_VERSION "0.6.7" struct hpt_clock { u8 xfer_speed; @@ -1103,17 +1103,17 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* Select the DPLL clock. */ pci_write_config_byte(dev, 0x5b, 0x21); - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); + pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); for(adjust = 0; adjust < 8; adjust++) { if (hpt37x_calibrate_dpll(dev)) break; /* See if it'll settle at a fractionally different clock */ - if ((adjust & 3) == 3) { - f_low --; - f_high ++; - } - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); + if (adjust & 1) + f_low -= adjust >> 1; + else + f_high += adjust >> 1; + pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); } if (adjust == 8) { printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n"); diff --git a/drivers/base/core.c b/drivers/base/core.c index 3599ab2..e6738bc 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -24,8 +24,6 @@ #include "base.h" #include "power/power.h" -extern const char *kobject_actions[]; - int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL; @@ -680,8 +678,7 @@ static int device_add_class_symlinks(struct device *dev) if (error) goto out_subsys; } - /* only bus-device parents get a "device"-link */ - if (dev->parent && dev->parent->bus) { + if (dev->parent) { error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); if (error) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index fe7ef33..4054507 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -53,7 +53,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, ret = count; return ret; } -static SYSDEV_ATTR(online, 0600, show_online, store_online); +static SYSDEV_ATTR(online, 0644, show_online, store_online); static void __devinit register_cpu_control(struct cpu *cpu) { diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 53f0ee6..b24efd4 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -232,6 +232,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) /** * firmware_data_write - write method for firmware * @kobj: kobject for the device + * @bin_attr: bin_attr structure * @buffer: buffer being written * @offset: buffer offset for write in total data store area * @count: buffer size diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 966a5e2..9caeaea 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,5 +1,5 @@ obj-y := shutdown.o -obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o +obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 591a0dd..8ba0830 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -5,7 +5,7 @@ extern void device_shutdown(void); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP /* * main.c @@ -62,7 +62,7 @@ extern int resume_device(struct device *); */ extern int suspend_device(struct device *, pm_message_t); -#else /* CONFIG_PM */ +#else /* CONFIG_PM_SLEEP */ static inline int device_pm_add(struct device * dev) diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index a47ee1b..56e8eaa 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -44,7 +44,5 @@ void device_shutdown(void) dev->driver->shutdown(dev); } } - - sysdev_shutdown(); } diff --git a/drivers/block/Makefile b/drivers/block/Makefile index a7a0990..014e721 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -31,4 +31,4 @@ obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o -obj-$(CONFIG_LGUEST_GUEST) += lguest_blk.o +obj-$(CONFIG_LGUEST_BLOCK) += lguest_blk.o diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 6ce8b89..c9751b2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1422,7 +1422,7 @@ static void redo_fd_request(void) goto repeat; } -static void do_fd_request(request_queue_t * q) +static void do_fd_request(struct request_queue * q) { redo_fd_request(); } diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 1d84668..ba07f76 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -138,7 +138,7 @@ struct aoedev { u16 maxbcnt; struct work_struct work;/* disk create work struct */ struct gendisk *gd; - request_queue_t blkq; + struct request_queue blkq; struct hd_geometry geo; sector_t ssize; struct timer_list timer; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 4f59827..007faaf 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -125,7 +125,7 @@ aoeblk_release(struct inode *inode, struct file *filp) } static int -aoeblk_make_request(request_queue_t *q, struct bio *bio) +aoeblk_make_request(struct request_queue *q, struct bio *bio) { struct aoedev *d; struct buf *buf; diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 14d6b94..94268c7 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1466,7 +1466,7 @@ repeat: } -void do_fd_request(request_queue_t * q) +void do_fd_request(struct request_queue * q) { unsigned long flags; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index a2d6612..a11b2bd 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -139,7 +139,7 @@ static struct board_type products[] = { static ctlr_info_t *hba[MAX_CTLR]; -static void do_cciss_request(request_queue_t *q); +static void do_cciss_request(struct request_queue *q); static irqreturn_t do_cciss_intr(int irq, void *dev_id); static int cciss_open(struct inode *inode, struct file *filep); static int cciss_release(struct inode *inode, struct file *filep); @@ -1584,7 +1584,7 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, */ if (h->gendisk[0] != disk) { if (disk) { - request_queue_t *q = disk->queue; + struct request_queue *q = disk->queue; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); if (q) { @@ -2511,7 +2511,7 @@ after_error_processing: /* * Get a request and submit it to the controller. */ -static void do_cciss_request(request_queue_t *q) +static void do_cciss_request(struct request_queue *q) { ctlr_info_t *h = q->queuedata; CommandList_struct *c; @@ -3227,12 +3227,15 @@ static int alloc_cciss_hba(void) for (i = 0; i < MAX_CTLR; i++) { if (!hba[i]) { ctlr_info_t *p; + p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); if (!p) goto Enomem; p->gendisk[0] = alloc_disk(1 << NWD_SHIFT); - if (!p->gendisk[0]) + if (!p->gendisk[0]) { + kfree(p); goto Enomem; + } hba[i] = p; return i; } @@ -3380,7 +3383,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, do { drive_info_struct *drv = &(hba[i]->drv[j]); struct gendisk *disk = hba[i]->gendisk[j]; - request_queue_t *q; + struct request_queue *q; /* Check if the disk was allocated already */ if (!disk){ @@ -3523,7 +3526,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) for (j = 0; j < CISS_MAX_LUN; j++) { struct gendisk *disk = hba[i]->gendisk[j]; if (disk) { - request_queue_t *q = disk->queue; + struct request_queue *q = disk->queue; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index b94cd1c..be4e3477d 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -161,7 +161,7 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io); -static void do_ida_request(request_queue_t *q); +static void do_ida_request(struct request_queue *q); static void start_io(ctlr_info_t *h); static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c); @@ -391,7 +391,7 @@ static void __devexit cpqarray_remove_one_eisa (int i) /* pdev is NULL for eisa */ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) { - request_queue_t *q; + struct request_queue *q; int j; /* @@ -886,7 +886,7 @@ static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c) * are in here (either via the dummy do_ida_request functions or by being * called from the interrupt handler */ -static void do_ida_request(request_queue_t *q) +static void do_ida_request(struct request_queue *q) { ctlr_info_t *h = q->queuedata; cmdlist_t *c; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index fe08804..085b779 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -251,7 +251,7 @@ static int irqdma_allocated; static struct request *current_req; static struct request_queue *floppy_queue; -static void do_fd_request(request_queue_t * q); +static void do_fd_request(struct request_queue * q); #ifndef fd_get_dma_residue #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) @@ -2981,7 +2981,7 @@ static void process_fd_request(void) schedule_bh(redo_fd_request); } -static void do_fd_request(request_queue_t * q) +static void do_fd_request(struct request_queue * q) { if (max_buffer_sectors == 0) { printk("VFS: do_fd_request called on non-open device\n"); diff --git a/drivers/block/lguest_blk.c b/drivers/block/lguest_blk.c index 1634c2d..93e3c40 100644 --- a/drivers/block/lguest_blk.c +++ b/drivers/block/lguest_blk.c @@ -1,6 +1,12 @@ -/* A simple block driver for lguest. +/*D:400 + * The Guest block driver * - * Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation + * This is a simple block driver, which appears as /dev/lgba, lgbb, lgbc etc. + * The mechanism is simple: we place the information about the request in the + * device page, then use SEND_DMA (containing the data for a write, or an empty + * "ping" DMA for a read). + :*/ +/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation * * 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 @@ -25,27 +31,50 @@ static char next_block_index = 'a'; +/*D:420 Here is the structure which holds all the information we need about + * each Guest block device. + * + * I'm sure at this stage, you're wondering "hey, where was the adventure I was + * promised?" and thinking "Rusty sucks, I shall say nasty things about him on + * my blog". I think Real adventures have boring bits, too, and you're in the + * middle of one. But it gets better. Just not quite yet. */ struct blockdev { + /* The block queue infrastructure wants a spinlock: it is held while it + * calls our block request function. We grab it in our interrupt + * handler so the responses don't mess with new requests. */ spinlock_t lock; - /* The disk structure for the kernel. */ + /* The disk structure registered with kernel. */ struct gendisk *disk; - /* The major number for this disk. */ + /* The major device number for this disk, and the interrupt. We only + * really keep them here for completeness; we'd need them if we + * supported device unplugging. */ int major; int irq; + /* The physical address of this device's memory page */ unsigned long phys_addr; - /* The mapped block page. */ + /* The mapped memory page for convenient acces. */ struct lguest_block_page *lb_page; - /* We only have a single request outstanding at a time. */ + /* We only have a single request outstanding at a time: this is it. */ struct lguest_dma dma; struct request *req; }; -/* Jens gave me this nice helper to end all chunks of a request. */ +/*D:495 We originally used end_request() throughout the driver, but it turns + * out that end_request() is deprecated, and doesn't actually end the request + * (which seems like a good reason to deprecate it!). It simply ends the first + * bio. So if we had 3 bios in a "struct request" we would do all 3, + * end_request(), do 2, end_request(), do 1 and end_request(): twice as much + * work as we needed to do. + * + * This reinforced to me that I do not understand the block layer. + * + * Nonetheless, Jens Axboe gave me this nice helper to end all chunks of a + * request. This improved disk speed by 130%. */ static void end_entire_request(struct request *req, int uptodate) { if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) @@ -55,30 +84,62 @@ static void end_entire_request(struct request *req, int uptodate) end_that_request_last(req, uptodate); } +/* I'm told there are only two stories in the world worth telling: love and + * hate. So there used to be a love scene here like this: + * + * Launcher: We could make beautiful I/O together, you and I. + * Guest: My, that's a big disk! + * + * Unfortunately, it was just too raunchy for our otherwise-gentle tale. */ + +/*D:490 This is the interrupt handler, called when a block read or write has + * been completed for us. */ static irqreturn_t lgb_irq(int irq, void *_bd) { + /* We handed our "struct blockdev" as the argument to request_irq(), so + * it is passed through to us here. This tells us which device we're + * dealing with in case we have more than one. */ struct blockdev *bd = _bd; unsigned long flags; + /* We weren't doing anything? Strange, but could happen if we shared + * interrupts (we don't!). */ if (!bd->req) { pr_debug("No work!\n"); return IRQ_NONE; } + /* Not done yet? That's equally strange. */ if (!bd->lb_page->result) { pr_debug("No result!\n"); return IRQ_NONE; } + /* We have to grab the lock before ending the request. */ spin_lock_irqsave(&bd->lock, flags); + /* "result" is 1 for success, 2 for failure: end_entire_request() wants + * to know whether this succeeded or not. */ end_entire_request(bd->req, bd->lb_page->result == 1); + /* Clear out request, it's done. */ bd->req = NULL; + /* Reset incoming DMA for next time. */ bd->dma.used_len = 0; + /* Ready for more reads or writes */ blk_start_queue(bd->disk->queue); spin_unlock_irqrestore(&bd->lock, flags); + + /* The interrupt was for us, we dealt with it. */ return IRQ_HANDLED; } +/*D:480 The block layer's "struct request" contains a number of "struct bio"s, + * each of which contains "struct bio_vec"s, each of which contains a page, an + * offset and a length. + * + * Fortunately there are iterators to help us walk through the "struct + * request". Even more fortunately, there were plenty of places to steal the + * code from. We pack the "struct request" into our "struct lguest_dma" and + * return the total length. */ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) { unsigned int i = 0, idx, len = 0; @@ -87,8 +148,13 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) rq_for_each_bio(bio, req) { struct bio_vec *bvec; bio_for_each_segment(bvec, bio, idx) { + /* We told the block layer not to give us too many. */ BUG_ON(i == LGUEST_MAX_DMA_SECTIONS); + /* If we had a zero-length segment, it would look like + * the end of the data referred to by the "struct + * lguest_dma", so make sure that doesn't happen. */ BUG_ON(!bvec->bv_len); + /* Convert page & offset to a physical address */ dma->addr[i] = page_to_phys(bvec->bv_page) + bvec->bv_offset; dma->len[i] = bvec->bv_len; @@ -96,26 +162,39 @@ static unsigned int req_to_dma(struct request *req, struct lguest_dma *dma) i++; } } + /* If the array isn't full, we mark the end with a 0 length */ if (i < LGUEST_MAX_DMA_SECTIONS) dma->len[i] = 0; return len; } +/* This creates an empty DMA, useful for prodding the Host without sending data + * (ie. when we want to do a read) */ static void empty_dma(struct lguest_dma *dma) { dma->len[0] = 0; } +/*D:470 Setting up a request is fairly easy: */ static void setup_req(struct blockdev *bd, int type, struct request *req, struct lguest_dma *dma) { + /* The type is 1 (write) or 0 (read). */ bd->lb_page->type = type; + /* The sector on disk where the read or write starts. */ bd->lb_page->sector = req->sector; + /* The result is initialized to 0 (unfinished). */ bd->lb_page->result = 0; + /* The current request (so we can end it in the interrupt handler). */ bd->req = req; + /* The number of bytes: returned as a side-effect of req_to_dma(), + * which packs the block layer's "struct request" into our "struct + * lguest_dma" */ bd->lb_page->bytes = req_to_dma(req, dma); } +/*D:450 Write is pretty straightforward: we pack the request into a "struct + * lguest_dma", then use SEND_DMA to send the request. */ static void do_write(struct blockdev *bd, struct request *req) { struct lguest_dma send; @@ -126,6 +205,9 @@ static void do_write(struct blockdev *bd, struct request *req) lguest_send_dma(bd->phys_addr, &send); } +/* Read is similar to write, except we pack the request into our receive + * "struct lguest_dma" and send through an empty DMA just to tell the Host that + * there's a request pending. */ static void do_read(struct blockdev *bd, struct request *req) { struct lguest_dma ping; @@ -137,21 +219,30 @@ static void do_read(struct blockdev *bd, struct request *req) lguest_send_dma(bd->phys_addr, &ping); } -static void do_lgb_request(request_queue_t *q) +/*D:440 This where requests come in: we get handed the request queue and are + * expected to pull a "struct request" off it until we've finished them or + * we're waiting for a reply: */ +static void do_lgb_request(struct request_queue *q) { struct blockdev *bd; struct request *req; again: + /* This sometimes returns NULL even on the very first time around. I + * wonder if it's something to do with letting elves handle the request + * queue... */ req = elv_next_request(q); if (!req) return; + /* We attached the struct blockdev to the disk: get it back */ bd = req->rq_disk->private_data; - /* Sometimes we get repeated requests after blk_stop_queue. */ + /* Sometimes we get repeated requests after blk_stop_queue(), but we + * can only handle one at a time. */ if (bd->req) return; + /* We only do reads and writes: no tricky business! */ if (!blk_fs_request(req)) { pr_debug("Got non-command 0x%08x\n", req->cmd_type); req->errors++; @@ -164,20 +255,31 @@ again: else do_read(bd, req); - /* Wait for interrupt to tell us it's done. */ + /* We've put out the request, so stop any more coming in until we get + * an interrupt, which takes us to lgb_irq() to re-enable the queue. */ blk_stop_queue(q); } +/*D:430 This is the "struct block_device_operations" we attach to the disk at + * the end of lguestblk_probe(). It doesn't seem to want much. */ static struct block_device_operations lguestblk_fops = { .owner = THIS_MODULE, }; +/*D:425 Setting up a disk device seems to involve a lot of code. I'm not sure + * quite why. I do know that the IDE code sent two or three of the maintainers + * insane, perhaps this is the fringe of the same disease? + * + * As in the console code, the probe function gets handed the generic + * lguest_device from lguest_bus.c: */ static int lguestblk_probe(struct lguest_device *lgdev) { struct blockdev *bd; int err; int irqflags = IRQF_SHARED; + /* First we allocate our own "struct blockdev" and initialize the easy + * fields. */ bd = kmalloc(sizeof(*bd), GFP_KERNEL); if (!bd) return -ENOMEM; @@ -187,59 +289,100 @@ static int lguestblk_probe(struct lguest_device *lgdev) bd->req = NULL; bd->dma.used_len = 0; bd->dma.len[0] = 0; + /* The descriptor in the lguest_devices array provided by the Host + * gives the Guest the physical page number of the device's page. */ bd->phys_addr = (lguest_devices[lgdev->index].pfn << PAGE_SHIFT); + /* We use lguest_map() to get a pointer to the device page */ bd->lb_page = lguest_map(bd->phys_addr, 1); if (!bd->lb_page) { err = -ENOMEM; goto out_free_bd; } + /* We need a major device number: 0 means "assign one dynamically". */ bd->major = register_blkdev(0, "lguestblk"); if (bd->major < 0) { err = bd->major; goto out_unmap; } + /* This allocates a "struct gendisk" where we pack all the information + * about the disk which the rest of Linux sees. We ask for one minor + * number; I do wonder if we should be asking for more. */ bd->disk = alloc_disk(1); if (!bd->disk) { err = -ENOMEM; goto out_unregister_blkdev; } + /* Every disk needs a queue for requests to come in: we set up the + * queue with a callback function (the core of our driver) and the lock + * to use. */ bd->disk->queue = blk_init_queue(do_lgb_request, &bd->lock); if (!bd->disk->queue) { err = -ENOMEM; goto out_put_disk; } - /* We can only handle a certain number of sg entries */ + /* We can only handle a certain number of pointers in our SEND_DMA + * call, so we set that with blk_queue_max_hw_segments(). This is not + * to be confused with blk_queue_max_phys_segments() of course! I + * know, who could possibly confuse the two? + * + * Well, it's simple to tell them apart: this one seems to work and the + * other one didn't. */ blk_queue_max_hw_segments(bd->disk->queue, LGUEST_MAX_DMA_SECTIONS); - /* Buffers must not cross page boundaries */ + + /* Due to technical limitations of our Host (and simple coding) we + * can't have a single buffer which crosses a page boundary. Tell it + * here. This means that our maximum request size is 16 + * (LGUEST_MAX_DMA_SECTIONS) pages. */ blk_queue_segment_boundary(bd->disk->queue, PAGE_SIZE-1); + /* We name our disk: this becomes the device name when udev does its + * magic thing and creates the device node, such as /dev/lgba. + * next_block_index is a global which starts at 'a'. Unfortunately + * this simple increment logic means that the 27th disk will be called + * "/dev/lgb{". In that case, I recommend having at least 29 disks, so + * your /dev directory will be balanced. */ sprintf(bd->disk->disk_name, "lgb%c", next_block_index++); + + /* We look to the device descriptor again to see if this device's + * interrupts are expected to be random. If they are, we tell the irq + * subsystem. At the moment this bit is always set. */ if (lguest_devices[lgdev->index].features & LGUEST_DEVICE_F_RANDOMNESS) irqflags |= IRQF_SAMPLE_RANDOM; + + /* Now we have the name and irqflags, we can request the interrupt; we + * give it the "struct blockdev" we have set up to pass to lgb_irq() + * when there is an interrupt. */ err = request_irq(bd->irq, lgb_irq, irqflags, bd->disk->disk_name, bd); if (err) goto out_cleanup_queue; + /* We bind our one-entry DMA pool to the key for this block device so + * the Host can reply to our requests. The key is equal to the + * physical address of the device's page, which is conveniently + * unique. */ err = lguest_bind_dma(bd->phys_addr, &bd->dma, 1, bd->irq); if (err) goto out_free_irq; + /* We finish our disk initialization and add the disk to the system. */ bd->disk->major = bd->major; bd->disk->first_minor = 0; bd->disk->private_data = bd; bd->disk->fops = &lguestblk_fops; - /* This is initialized to the disk size by the other end. */ + /* This is initialized to the disk size by the Launcher. */ set_capacity(bd->disk, bd->lb_page->num_sectors); add_disk(bd->disk); printk(KERN_INFO "%s: device %i at major %d\n", bd->disk->disk_name, lgdev->index, bd->major); + /* We don't need to keep the "struct blockdev" around, but if we ever + * implemented device removal, we'd need this. */ lgdev->private = bd; return 0; @@ -258,6 +401,8 @@ out_free_bd: return err; } +/*D:410 The boilerplate code for registering the lguest block driver is just + * like the console: */ static struct lguest_driver lguestblk_drv = { .name = "lguestblk", .owner = THIS_MODULE, diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e425daa..9f015fc 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -529,7 +529,7 @@ static struct bio *loop_get_bio(struct loop_device *lo) return bio; } -static int loop_make_request(request_queue_t *q, struct bio *old_bio) +static int loop_make_request(struct request_queue *q, struct bio *old_bio) { struct loop_device *lo = q->queuedata; int rw = bio_rw(old_bio); @@ -558,7 +558,7 @@ out: /* * kick off io on the underlying address space */ -static void loop_unplug(request_queue_t *q) +static void loop_unplug(struct request_queue *q) { struct loop_device *lo = q->queuedata; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index c129510..be92c65 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -100,7 +100,7 @@ static const char *nbdcmd_to_ascii(int cmd) static void nbd_end_request(struct request *req) { int uptodate = (req->errors == 0) ? 1 : 0; - request_queue_t *q = req->q; + struct request_queue *q = req->q; unsigned long flags; dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name, @@ -410,7 +410,7 @@ static void nbd_clear_que(struct nbd_device *lo) * { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); } */ -static void do_nbd_request(request_queue_t * q) +static void do_nbd_request(struct request_queue * q) { struct request *req; diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 1eeb8f2..b8a994a 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -183,7 +183,7 @@ static int pcd_packet(struct cdrom_device_info *cdi, static int pcd_detect(void); static void pcd_probe_capabilities(void); static void do_pcd_read_drq(void); -static void do_pcd_request(request_queue_t * q); +static void do_pcd_request(struct request_queue * q); static void do_pcd_read(void); struct pcd_unit { @@ -713,7 +713,7 @@ static int pcd_detect(void) /* I/O request processing */ static struct request_queue *pcd_queue; -static void do_pcd_request(request_queue_t * q) +static void do_pcd_request(struct request_queue * q) { if (pcd_busy) return; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 31e0148..df819f8 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -698,7 +698,7 @@ static enum action pd_identify(struct pd_unit *disk) /* end of io request engine */ -static void do_pd_request(request_queue_t * q) +static void do_pd_request(struct request_queue * q) { if (pd_req) return; diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 5826508..ceffa60 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -202,7 +202,7 @@ module_param_array(drive3, int, NULL, 0); #define ATAPI_WRITE_10 0x2a static int pf_open(struct inode *inode, struct file *file); -static void do_pf_request(request_queue_t * q); +static void do_pf_request(struct request_queue * q); static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -760,7 +760,7 @@ static void pf_end_request(int uptodate) } } -static void do_pf_request(request_queue_t * q) +static void do_pf_request(struct request_queue * q) { if (pf_busy) return; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 31be33e..fadbfd8 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -752,7 +752,7 @@ static inline struct bio *pkt_get_list_first(struct bio **list_head, struct bio */ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc) { - request_queue_t *q = bdev_get_queue(pd->bdev); + struct request_queue *q = bdev_get_queue(pd->bdev); struct request *rq; int ret = 0; @@ -979,7 +979,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) * Special care is needed if the underlying block device has a small * max_phys_segments value. */ -static int pkt_set_segment_merging(struct pktcdvd_device *pd, request_queue_t *q) +static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) { if ((pd->settings.size << 9) / CD_FRAMESIZE <= q->max_phys_segments) { /* @@ -2314,7 +2314,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) { int ret; long lba; - request_queue_t *q; + struct request_queue *q; /* * We need to re-open the cdrom device without O_NONBLOCK to be able @@ -2477,7 +2477,7 @@ static int pkt_end_io_read_cloned(struct bio *bio, unsigned int bytes_done, int return 0; } -static int pkt_make_request(request_queue_t *q, struct bio *bio) +static int pkt_make_request(struct request_queue *q, struct bio *bio) { struct pktcdvd_device *pd; char b[BDEVNAME_SIZE]; @@ -2626,7 +2626,7 @@ end_io: -static int pkt_merge_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *bvec) +static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *bvec) { struct pktcdvd_device *pd = q->queuedata; sector_t zone = ZONE(bio->bi_sector, pd); @@ -2647,7 +2647,7 @@ static int pkt_merge_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *b static void pkt_init_queue(struct pktcdvd_device *pd) { - request_queue_t *q = pd->disk->queue; + struct request_queue *q = pd->disk->queue; blk_queue_make_request(q, pkt_make_request); blk_queue_hardsect_size(q, CD_FRAMESIZE); diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 688a4fb..3c796e2 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -64,7 +64,7 @@ static void reset_ctrl(void); static int ps2esdi_geninit(void); -static void do_ps2esdi_request(request_queue_t * q); +static void do_ps2esdi_request(struct request_queue * q); static void ps2esdi_readwrite(int cmd, struct request *req); @@ -473,7 +473,7 @@ static void __init ps2esdi_get_device_cfg(void) } /* strategy routine that handles most of the IO requests */ -static void do_ps2esdi_request(request_queue_t * q) +static void do_ps2esdi_request(struct request_queue * q) { struct request *req; /* since, this routine is called with interrupts cleared - they diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 170fb33..aa8b890 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -190,7 +190,7 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, } static void ps3disk_do_request(struct ps3_storage_device *dev, - request_queue_t *q) + struct request_queue *q) { struct request *req; @@ -211,7 +211,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, } } -static void ps3disk_request(request_queue_t *q) +static void ps3disk_request(struct request_queue *q) { struct ps3_storage_device *dev = q->queuedata; struct ps3disk_private *priv = dev->sbd.core.driver_data; @@ -404,7 +404,7 @@ static int ps3disk_identify(struct ps3_storage_device *dev) return 0; } -static void ps3disk_prepare_flush(request_queue_t *q, struct request *req) +static void ps3disk_prepare_flush(struct request_queue *q, struct request *req) { struct ps3_storage_device *dev = q->queuedata; @@ -414,7 +414,7 @@ static void ps3disk_prepare_flush(request_queue_t *q, struct request *req) req->cmd_type = REQ_TYPE_FLUSH; } -static int ps3disk_issue_flush(request_queue_t *q, struct gendisk *gendisk, +static int ps3disk_issue_flush(struct request_queue *q, struct gendisk *gendisk, sector_t *sector) { struct ps3_storage_device *dev = q->queuedata; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index a1512da..65150b5 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -264,7 +264,7 @@ static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector, * 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Added devfs support * */ -static int rd_make_request(request_queue_t *q, struct bio *bio) +static int rd_make_request(struct request_queue *q, struct bio *bio) { struct block_device *bdev = bio->bi_bdev; struct address_space * mapping = bdev->bd_inode->i_mapping; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index d50b823..4dff492 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -444,7 +444,7 @@ out: return err; } -static void do_vdc_request(request_queue_t *q) +static void do_vdc_request(struct request_queue *q) { while (1) { struct request *req = elv_next_request(q); diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 1a65979..b4e462f 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -225,7 +225,7 @@ static unsigned short write_postamble[] = { static void swim3_select(struct floppy_state *fs, int sel); static void swim3_action(struct floppy_state *fs, int action); static int swim3_readbit(struct floppy_state *fs, int bit); -static void do_fd_request(request_queue_t * q); +static void do_fd_request(struct request_queue * q); static void start_request(struct floppy_state *fs); static void set_timeout(struct floppy_state *fs, int nticks, void (*proc)(unsigned long)); @@ -290,7 +290,7 @@ static int swim3_readbit(struct floppy_state *fs, int bit) return (stat & DATA) == 0; } -static void do_fd_request(request_queue_t * q) +static void do_fd_request(struct request_queue * q) { int i; for(i=0;i<floppy_count;i++) diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 949ae93..402209f 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -278,7 +278,7 @@ struct carm_host { unsigned int state; u32 fw_ver; - request_queue_t *oob_q; + struct request_queue *oob_q; unsigned int n_oob; unsigned int hw_sg_used; @@ -287,7 +287,7 @@ struct carm_host { unsigned int wait_q_prod; unsigned int wait_q_cons; - request_queue_t *wait_q[CARM_MAX_WAIT_Q]; + struct request_queue *wait_q[CARM_MAX_WAIT_Q]; unsigned int n_msgs; u64 msg_alloc; @@ -756,7 +756,7 @@ static inline void carm_end_request_queued(struct carm_host *host, assert(rc == 0); } -static inline void carm_push_q (struct carm_host *host, request_queue_t *q) +static inline void carm_push_q (struct carm_host *host, struct request_queue *q) { unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q; @@ -768,7 +768,7 @@ static inline void carm_push_q (struct carm_host *host, request_queue_t *q) BUG_ON(host->wait_q_prod == host->wait_q_cons); /* overrun */ } -static inline request_queue_t *carm_pop_q(struct carm_host *host) +static inline struct request_queue *carm_pop_q(struct carm_host *host) { unsigned int idx; @@ -783,7 +783,7 @@ static inline request_queue_t *carm_pop_q(struct carm_host *host) static inline void carm_round_robin(struct carm_host *host) { - request_queue_t *q = carm_pop_q(host); + struct request_queue *q = carm_pop_q(host); if (q) { blk_start_queue(q); VPRINTK("STARTED QUEUE %p\n", q); @@ -802,7 +802,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq, } } -static void carm_oob_rq_fn(request_queue_t *q) +static void carm_oob_rq_fn(struct request_queue *q) { struct carm_host *host = q->queuedata; struct carm_request *crq; @@ -833,7 +833,7 @@ static void carm_oob_rq_fn(request_queue_t *q) } } -static void carm_rq_fn(request_queue_t *q) +static void carm_rq_fn(struct request_queue *q) { struct carm_port *port = q->queuedata; struct carm_host *host = port->host; @@ -1494,7 +1494,7 @@ static int carm_init_disks(struct carm_host *host) for (i = 0; i < CARM_MAX_PORTS; i++) { struct gendisk *disk; - request_queue_t *q; + struct request_queue *q; struct carm_port *port; port = &host->port[i]; @@ -1538,7 +1538,7 @@ static void carm_free_disks(struct carm_host *host) for (i = 0; i < CARM_MAX_PORTS; i++) { struct gendisk *disk = host->port[i].disk; if (disk) { - request_queue_t *q = disk->queue; + struct request_queue *q = disk->queue; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); @@ -1571,7 +1571,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) struct carm_host *host; unsigned int pci_dac; int rc; - request_queue_t *q; + struct request_queue *q; unsigned int i; if (!printed_version++) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 8b13d7d..c57dd2b 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -503,7 +503,7 @@ static void ub_cleanup(struct ub_dev *sc) { struct list_head *p; struct ub_lun *lun; - request_queue_t *q; + struct request_queue *q; while (!list_empty(&sc->luns)) { p = sc->luns.next; @@ -619,7 +619,7 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc) * The request function is our main entry point */ -static void ub_request_fn(request_queue_t *q) +static void ub_request_fn(struct request_queue *q) { struct ub_lun *lun = q->queuedata; struct request *rq; @@ -2273,7 +2273,7 @@ err_core: static int ub_probe_lun(struct ub_dev *sc, int lnum) { struct ub_lun *lun; - request_queue_t *q; + struct request_queue *q; struct gendisk *disk; int rc; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index dec74bd..6b7c02d 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -114,7 +114,7 @@ struct cardinfo { */ struct bio *bio, *currentbio, **biotail; - request_queue_t *queue; + struct request_queue *queue; struct mm_page { dma_addr_t page_dma; @@ -357,7 +357,7 @@ static inline void reset_page(struct mm_page *page) page->biotail = & page->bio; } -static void mm_unplug_device(request_queue_t *q) +static void mm_unplug_device(struct request_queue *q) { struct cardinfo *card = q->queuedata; unsigned long flags; @@ -541,7 +541,7 @@ static void process_page(unsigned long data) -- mm_make_request ----------------------------------------------------------------------------------- */ -static int mm_make_request(request_queue_t *q, struct bio *bio) +static int mm_make_request(struct request_queue *q, struct bio *bio) { struct cardinfo *card = q->queuedata; pr_debug("mm_make_request %llu %u\n", diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index dae3991..85916e2 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -400,7 +400,7 @@ error_ret: /* * This is the external request processing routine */ -static void do_viodasd_request(request_queue_t *q) +static void do_viodasd_request(struct request_queue *q) { struct request *req; diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 0d97b7e..624d30f 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -298,7 +298,7 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address) } /* do_xd_request: handle an incoming request */ -static void do_xd_request (request_queue_t * q) +static void do_xd_request (struct request_queue * q) { struct request *req; diff --git a/drivers/block/xd.h b/drivers/block/xd.h index 82e090f..cffd44a 100644 --- a/drivers/block/xd.h +++ b/drivers/block/xd.h @@ -104,7 +104,7 @@ static int xd_manual_geo_init (char *command); static u_char xd_detect (u_char *controller, unsigned int *address); static u_char xd_initdrives (void (*init_drive)(u_char drive)); -static void do_xd_request (request_queue_t * q); +static void do_xd_request (struct request_queue * q); static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg); static int xd_readwrite (u_char operation,XD_INFO *disk,char *buffer,u_int block,u_int count); static void xd_recalibrate (u_char drive); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6746c29..964e516 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -241,7 +241,7 @@ static inline void flush_requests(struct blkfront_info *info) * do_blkif_request * read a block; request is in a request queue */ -static void do_blkif_request(request_queue_t *rq) +static void do_blkif_request(struct request_queue *rq) { struct blkfront_info *info = NULL; struct request *req; @@ -287,7 +287,7 @@ wait: static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { - request_queue_t *rq; + struct request_queue *rq; rq = blk_init_queue(do_blkif_request, &blkif_io_lock); if (rq == NULL) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 732ec63..cb27e88 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -458,7 +458,7 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace) } /* Get the next read/write request; ending requests that we don't handle */ -struct request *ace_get_next_request(request_queue_t * q) +struct request *ace_get_next_request(struct request_queue * q) { struct request *req; @@ -825,7 +825,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id) /* --------------------------------------------------------------------- * Block ops */ -static void ace_request(request_queue_t * q) +static void ace_request(struct request_queue * q) { struct request *req; struct ace_device *ace; diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index e40fa98..2d5853c 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(z2ram_lock); static struct block_device_operations z2_fops; static struct gendisk *z2ram_gendisk; -static void do_z2_request(request_queue_t *q) +static void do_z2_request(struct request_queue *q) { struct request *req; while ((req = elv_next_request(q)) != NULL) { diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 499019b..67ee3d4 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2094,7 +2094,7 @@ out: static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, int lba, int nframes) { - request_queue_t *q = cdi->disk->queue; + struct request_queue *q = cdi->disk->queue; struct request *rq; struct bio *bio; unsigned int len; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 44cd7b2..e51550d 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -398,7 +398,7 @@ static void viocd_end_request(struct request *req, int uptodate) static int rwreq; -static void do_viocd_request(request_queue_t *q) +static void do_viocd_request(struct request_queue *q) { struct request *req; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index c8dfd18..b391776 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -130,6 +130,7 @@ config ROCKETPORT config CYCLADES tristate "Cyclades async mux support" depends on SERIAL_NONSTANDARD && (PCI || ISA) + select FW_LOADER ---help--- This driver supports Cyclades Z and Y multiserial boards. You would need something like this to connect more than two modems to @@ -726,7 +727,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC64 && (!SPARC32 || PCI) && !FRV && !ARM && !SUPERH && !S390 + depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -750,6 +751,28 @@ config RTC To compile this driver as a module, choose M here: the module will be called rtc. +config JS_RTC + tristate "Enhanced Real Time Clock Support" + depends on SPARC32 && PCI + ---help--- + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you + will get access to the real time clock (or hardware clock) built + into your computer. + + Every PC has such a clock built in. It can be used to generate + signals from as low as 1Hz up to 8192Hz, and can also be used + as a 24 hour alarm. It reports status information via the file + /proc/driver/rtc and its behaviour is set by various ioctls on + /dev/rtc. + + If you think you have a use for such a device (such as periodic data + sampling), then say Y here, and read <file:Documentation/rtc.txt> + for details. + + To compile this driver as a module, choose M here: the + module will be called js-rtc. + config SGI_DS1286 tristate "SGI DS1286 RTC support" depends on SGI_IP22 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 8fecaf4..d68ddbe 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -97,7 +97,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o -obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ obj-$(CONFIG_DRM) += drm/ @@ -109,6 +108,9 @@ obj-$(CONFIG_TCG_TPM) += tpm/ obj-$(CONFIG_PS3_FLASH) += ps3flash.o +obj-$(CONFIG_JS_RTC) += js-rtc.o +js-rtc-y = rtc.o + # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index a9f9c48..713533d 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -50,7 +50,7 @@ config AGP_ATI config AGP_AMD tristate "AMD Irongate, 761, and 762 chipset support" - depends on AGP && X86_32 + depends on AGP && (X86_32 || ALPHA) help This option gives you AGP support for the GLX component of X on AMD Irongate, 761, and 762 chipsets. diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 780e59e..da7513d 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -123,21 +123,16 @@ static int ati_create_gatt_pages(int nr_tables) for (i = 0; i < nr_tables; i++) { entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); + tables[i] = entry; if (entry == NULL) { - while (i > 0) { - kfree(tables[i-1]); - i--; - } - kfree(tables); retval = -ENOMEM; break; } - tables[i] = entry; retval = ati_create_page_map(entry); if (retval != 0) break; } - ati_generic_private.num_tables = nr_tables; + ati_generic_private.num_tables = i; ati_generic_private.gatt_pages = tables; if (retval != 0) diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c index fcb4b1b..ecd4248 100644 --- a/drivers/char/agp/compat_ioctl.c +++ b/drivers/char/agp/compat_ioctl.c @@ -28,6 +28,7 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/fs.h> #include <linux/agpgart.h> #include <asm/uaccess.h> #include "agp.h" diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index c7ed617..7791e98 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -37,6 +37,7 @@ #include <linux/agpgart.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/sched.h> #include <asm/uaccess.h> #include <asm/pgtable.h> diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index d535c40..3db4f40 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1170,7 +1170,6 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) map_page_into_agp(page); get_page(page); - SetPageLocked(page); atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); } @@ -1187,7 +1186,6 @@ void agp_generic_destroy_page(void *addr) page = virt_to_page(addr); unmap_page_from_agp(page); put_page(page); - unlock_page(page); free_page((unsigned long)addr); atomic_dec(&agp_bridge->current_memory_agp); } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a124060..294cdbf 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -20,7 +20,9 @@ #define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 #define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00 #define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02 +#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10 #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 +#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 @@ -33,7 +35,8 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ @@ -213,7 +216,6 @@ static void *i8xx_alloc_pages(void) } global_flush_tlb(); get_page(page); - SetPageLocked(page); atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); } @@ -229,7 +231,6 @@ static void i8xx_destroy_pages(void *addr) change_page_attr(page, 4, PAGE_KERNEL); global_flush_tlb(); put_page(page); - unlock_page(page); __free_pages(page, 2); atomic_dec(&agp_bridge->current_memory_agp); } @@ -527,6 +528,7 @@ static void intel_i830_init_gtt_entries(void) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB || IS_I965 || IS_G33) gtt_entries = MB(48) - KB(size); else @@ -538,6 +540,7 @@ static void intel_i830_init_gtt_entries(void) agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB || IS_I965 || IS_G33) gtt_entries = MB(64) - KB(size); else @@ -1848,9 +1851,9 @@ static const struct intel_driver_description { NULL, &intel_915_driver }, { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G", NULL, &intel_915_driver }, - { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM", + { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM", NULL, &intel_915_driver }, - { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME", + { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME", NULL, &intel_915_driver }, { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ", NULL, &intel_i965_driver }, @@ -1860,9 +1863,9 @@ static const struct intel_driver_description { NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM", + { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE", + { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL }, { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL }, @@ -2051,11 +2054,13 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82915GM_HB), ID(PCI_DEVICE_ID_INTEL_82945G_HB), ID(PCI_DEVICE_ID_INTEL_82945GM_HB), + ID(PCI_DEVICE_ID_INTEL_82945GME_HB), ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), ID(PCI_DEVICE_ID_INTEL_82965G_1_HB), ID(PCI_DEVICE_ID_INTEL_82965Q_HB), ID(PCI_DEVICE_ID_INTEL_82965G_HB), ID(PCI_DEVICE_ID_INTEL_82965GM_HB), + ID(PCI_DEVICE_ID_INTEL_82965GME_HB), ID(PCI_DEVICE_ID_INTEL_G33_HB), ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB), diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index cda608c..98cf8ab 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -51,7 +51,6 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge) return NULL; get_page(page); - SetPageLocked(page); atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); } diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index ba0e74a..77bf4aa 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -73,7 +73,7 @@ static struct clocksource clocksource_hpet = { .name = "hpet", .rating = 250, .read = read_hpet, - .mask = 0xffffffffffffffff, + .mask = CLOCKSOURCE_MASK(64), .mult = 0, /*to be caluclated*/ .shift = 10, .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -1007,9 +1007,15 @@ static int hpet_acpi_remove(struct acpi_device *device, int type) return -EINVAL; } +static const struct acpi_device_id hpet_device_ids[] = { + {"PNP0103", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, hpet_device_ids); + static struct acpi_driver hpet_acpi_driver = { .name = "hpet", - .ids = "PNP0103", + .ids = hpet_device_ids, .ops = { .add = hpet_acpi_add, .remove = hpet_acpi_remove, diff --git a/drivers/char/hvc_lguest.c b/drivers/char/hvc_lguest.c index e7b889e..feeccba 100644 --- a/drivers/char/hvc_lguest.c +++ b/drivers/char/hvc_lguest.c @@ -1,6 +1,22 @@ -/* Simple console for lguest. +/*D:300 + * The Guest console driver * - * Copyright (C) 2006 Rusty Russell, IBM Corporation + * This is a trivial console driver: we use lguest's DMA mechanism to send + * bytes out, and register a DMA buffer to receive bytes in. It is assumed to + * be present and available from the very beginning of boot. + * + * Writing console drivers is one of the few remaining Dark Arts in Linux. + * Fortunately for us, the path of virtual consoles has been well-trodden by + * the PowerPC folks, who wrote "hvc_console.c" to generically support any + * virtual console. We use that infrastructure which only requires us to write + * the basic put_chars and get_chars functions and call the right register + * functions. + :*/ + +/*M:002 The console can be flooded: while the Guest is processing input the + * Host can send more. Buffering in the Host could alleviate this, but it is a + * difficult problem in general. :*/ +/* Copyright (C) 2006 Rusty Russell, IBM Corporation * * 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 @@ -21,49 +37,81 @@ #include <linux/lguest_bus.h> #include "hvc_console.h" +/*D:340 This is our single console input buffer, with associated "struct + * lguest_dma" referring to it. Note the 0-terminated length array, and the + * use of physical address for the buffer itself. */ static char inbuf[256]; static struct lguest_dma cons_input = { .used_len = 0, .addr[0] = __pa(inbuf), .len[0] = sizeof(inbuf), .len[1] = 0 }; +/*D:310 The put_chars() callback is pretty straightforward. + * + * First we put the pointer and length in a "struct lguest_dma": we only have + * one pointer, so we set the second length to 0. Then we use SEND_DMA to send + * the data to (Host) buffers attached to the console key. Usually a device's + * key is a physical address within the device's memory, but because the + * console device doesn't have any associated physical memory, we use the + * LGUEST_CONSOLE_DMA_KEY constant (aka 0). */ static int put_chars(u32 vtermno, const char *buf, int count) { struct lguest_dma dma; - /* FIXME: what if it's over a page boundary? */ + /* FIXME: DMA buffers in a "struct lguest_dma" are not allowed + * to go over page boundaries. This never seems to happen, + * but if it did we'd need to fix this code. */ dma.len[0] = count; dma.len[1] = 0; dma.addr[0] = __pa(buf); lguest_send_dma(LGUEST_CONSOLE_DMA_KEY, &dma); + /* We're expected to return the amount of data we wrote: all of it. */ return count; } +/*D:350 get_chars() is the callback from the hvc_console infrastructure when + * an interrupt is received. + * + * Firstly we see if our buffer has been filled: if not, we return. The rest + * of the code deals with the fact that the hvc_console() infrastructure only + * asks us for 16 bytes at a time. We keep a "cons_offset" variable for + * partially-read buffers. */ static int get_chars(u32 vtermno, char *buf, int count) { static int cons_offset; + /* Nothing left to see here... */ if (!cons_input.used_len) return 0; + /* You want more than we have to give? Well, try wanting less! */ if (cons_input.used_len - cons_offset < count) count = cons_input.used_len - cons_offset; + /* Copy across to their buffer and increment offset. */ memcpy(buf, inbuf + cons_offset, count); cons_offset += count; + + /* Finished? Zero offset, and reset cons_input so Host will use it + * again. */ if (cons_offset == cons_input.used_len) { cons_offset = 0; cons_input.used_len = 0; } return count; } +/*:*/ static struct hv_ops lguest_cons = { .get_chars = get_chars, .put_chars = put_chars, }; +/*D:320 Console drivers are initialized very early so boot messages can go + * out. At this stage, the console is output-only. Our driver checks we're a + * Guest, and if so hands hvc_instantiate() the console number (0), priority + * (0), and the struct hv_ops containing the put_chars() function. */ static int __init cons_init(void) { if (strcmp(paravirt_ops.name, "lguest") != 0) @@ -73,21 +121,46 @@ static int __init cons_init(void) } console_initcall(cons_init); +/*D:370 To set up and manage our virtual console, we call hvc_alloc() and + * stash the result in the private pointer of the "struct lguest_device". + * Since we never remove the console device we never need this pointer again, + * but using ->private is considered good form, and you never know who's going + * to copy your driver. + * + * Once the console is set up, we bind our input buffer ready for input. */ static int lguestcons_probe(struct lguest_device *lgdev) { int err; + /* The first argument of hvc_alloc() is the virtual console number, so + * we use zero. The second argument is the interrupt number. + * + * The third argument is a "struct hv_ops" containing the put_chars() + * and get_chars() pointers. The final argument is the output buffer + * size: we use 256 and expect the Host to have room for us to send + * that much. */ lgdev->private = hvc_alloc(0, lgdev_irq(lgdev), &lguest_cons, 256); if (IS_ERR(lgdev->private)) return PTR_ERR(lgdev->private); + /* We bind a single DMA buffer at key LGUEST_CONSOLE_DMA_KEY. + * "cons_input" is that statically-initialized global DMA buffer we saw + * above, and we also give the interrupt we want. */ err = lguest_bind_dma(LGUEST_CONSOLE_DMA_KEY, &cons_input, 1, lgdev_irq(lgdev)); if (err) printk("lguest console: failed to bind buffer.\n"); return err; } +/* Note the use of lgdev_irq() for the interrupt number. We tell hvc_alloc() + * to expect input when this interrupt is triggered, and then tell + * lguest_bind_dma() that is the interrupt to send us when input comes in. */ +/*D:360 From now on the console driver follows standard Guest driver form: + * register_lguest_driver() registers the device type and probe function, and + * the probe function sets up the device. + * + * The standard "struct lguest_driver": */ static struct lguest_driver lguestcons_drv = { .name = "lguestcons", .owner = THIS_MODULE, @@ -95,6 +168,7 @@ static struct lguest_driver lguestcons_drv = { .probe = lguestcons_probe, }; +/* The standard init function */ static int __init hvc_lguest_init(void) { return register_lguest_driver(&lguestcons_drv); diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 6005b52..8d74b8745e 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -500,7 +500,6 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) { int i, j, box; int err = 0; - int status = 0; static int loaded; i2eBordStrPtr pB = NULL; int rc = -1; @@ -588,6 +587,8 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) case PCI: #ifdef CONFIG_PCI { + int status; + pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); if (pci_dev_i != NULL) { diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4edfdda..96d2f9e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2050,6 +2050,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) info->si_type = SI_BT; break; default: + kfree(info); return; } diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 6e55cfb..e60a74c 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -25,6 +25,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/mmtimer.h> #include <linux/miscdevice.h> #include <linux/posix-timers.h> diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index c716ef0..c08a415 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -38,6 +38,7 @@ #include <linux/miscdevice.h> #include <linux/spinlock.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/vmalloc.h> #include <linux/string.h> #include <linux/slab.h> diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 372a37e..bbb7f12 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1,5 +1,5 @@ /* - * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $ + * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $ * * Device driver for Microgate SyncLink GT serial adapters. * @@ -93,7 +93,7 @@ * module identification */ static char *driver_name = "SyncLink GT"; -static char *driver_version = "$Revision: 4.36 $"; +static char *driver_version = "$Revision: 4.50 $"; static char *tty_driver_name = "synclink_gt"; static char *tty_dev_prefix = "ttySLG"; MODULE_LICENSE("GPL"); @@ -477,6 +477,7 @@ static void tx_set_idle(struct slgt_info *info); static unsigned int free_tbuf_count(struct slgt_info *info); static void reset_tbufs(struct slgt_info *info); static void tdma_reset(struct slgt_info *info); +static void tdma_start(struct slgt_info *info); static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); static void get_signals(struct slgt_info *info); @@ -904,6 +905,8 @@ start: spin_lock_irqsave(&info->lock,flags); if (!info->tx_active) tx_start(info); + else + tdma_start(info); spin_unlock_irqrestore(&info->lock,flags); } @@ -3871,44 +3874,58 @@ static void tx_start(struct slgt_info *info) slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); /* clear tx idle and underrun status bits */ wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); - - if (!(rd_reg32(info, TDCSR) & BIT0)) { - /* tx DMA stopped, restart tx DMA */ - tdma_reset(info); - /* set 1st descriptor address */ - wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - switch(info->params.mode) { - case MGSL_MODE_RAW: - case MGSL_MODE_MONOSYNC: - case MGSL_MODE_BISYNC: - wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ - break; - default: - wr_reg32(info, TDCSR, BIT0); /* DMA enable */ - } - } - if (info->params.mode == MGSL_MODE_HDLC) mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); } else { - tdma_reset(info); - /* set 1st descriptor address */ - wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - slgt_irq_off(info, IRQ_TXDATA); slgt_irq_on(info, IRQ_TXIDLE); /* clear tx idle status bit */ wr_reg16(info, SSR, IRQ_TXIDLE); - - /* enable tx DMA */ - wr_reg32(info, TDCSR, BIT0); } - + tdma_start(info); info->tx_active = 1; } } +/* + * start transmit DMA if inactive and there are unsent buffers + */ +static void tdma_start(struct slgt_info *info) +{ + unsigned int i; + + if (rd_reg32(info, TDCSR) & BIT0) + return; + + /* transmit DMA inactive, check for unsent buffers */ + i = info->tbuf_start; + while (!desc_count(info->tbufs[i])) { + if (++i == info->tbuf_count) + i = 0; + if (i == info->tbuf_current) + return; + } + info->tbuf_start = i; + + /* there are unsent buffers, start transmit DMA */ + + /* reset needed if previous error condition */ + tdma_reset(info); + + /* set 1st descriptor address */ + wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); + switch(info->params.mode) { + case MGSL_MODE_RAW: + case MGSL_MODE_MONOSYNC: + case MGSL_MODE_BISYNC: + wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ + break; + default: + wr_reg32(info, TDCSR, BIT0); /* DMA enable */ + } +} + static void tx_stop(struct slgt_info *info) { unsigned short val; @@ -4642,8 +4659,8 @@ static unsigned int free_tbuf_count(struct slgt_info *info) i=0; } while (i != info->tbuf_current); - /* last buffer with zero count may be in use, assume it is */ - if (count) + /* if tx DMA active, last zero count buffer is in use */ + if (count && (rd_reg32(info, TDCSR) & BIT0)) --count; return count; diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 16fb231..37bddc1 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -55,6 +55,8 @@ config SOFT_WATCHDOG To compile this driver as a module, choose M here: the module will be called softdog. +# ALPHA Architecture + # ARM Architecture config AT91RM9200_WATCHDOG @@ -189,7 +191,7 @@ config PNX4008_WATCHDOG config IOP_WATCHDOG tristate "IOP Watchdog" - depends on WATCHDOG && PLAT_IOP + depends on PLAT_IOP select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X) help Say Y here if to include support for the watchdog timer @@ -203,15 +205,48 @@ config IOP_WATCHDOG operating as an Root Complex and/or Central Resource, the PCI-X and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER. +config DAVINCI_WATCHDOG + tristate "DaVinci watchdog" + depends on ARCH_DAVINCI + help + Say Y here if to include support for the watchdog timer + in the DaVinci DM644x/DM646x processors. + To compile this driver as a module, choose M here: the + module will be called davinci_wdt. + + NOTE: once enabled, this timer cannot be disabled. + Say N if you are unsure. + +# ARM26 Architecture + # AVR32 Architecture config AT32AP700X_WDT tristate "AT32AP700x watchdog" - depends on WATCHDOG && CPU_AT32AP7000 + depends on CPU_AT32AP7000 help Watchdog timer embedded into AT32AP700x devices. This will reboot your system when the timeout is reached. +# BLACKFIN Architecture + +config BFIN_WDT + tristate "Blackfin On-Chip Watchdog Timer" + depends on BLACKFIN + ---help--- + If you say yes here you will get support for the Blackfin On-Chip + Watchdog Timer. If you have one of these processors and wish to + have watchdog support enabled, say Y, otherwise say N. + + To compile this driver as a module, choose M here: the + module will be called bfin_wdt. + +# CRIS Architecture + +# FRV Architecture + +# H8300 Architecture + # X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT @@ -540,37 +575,11 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. -# PowerPC Architecture +# M32R Architecture -config 8xx_WDT - tristate "MPC8xx Watchdog Timer" - depends on 8xx +# M68K Architecture -config 83xx_WDT - tristate "MPC83xx Watchdog Timer" - depends on PPC_83xx - -config MV64X60_WDT - tristate "MV64X60 (Marvell Discovery) Watchdog Timer" - depends on MV64X60 - -config BOOKE_WDT - bool "PowerPC Book-E Watchdog Timer" - depends on BOOKE || 4xx - ---help--- - Please see Documentation/watchdog/watchdog-api.txt for - more information. - -# PPC64 Architecture - -config WATCHDOG_RTAS - tristate "RTAS watchdog" - depends on PPC_RTAS - help - This driver adds watchdog support for the RTAS watchdog. - - To compile this driver as a module, choose M here. The module - will be called wdrtas. +# M68KNOMMU Architecture # MIPS Architecture @@ -600,6 +609,44 @@ config WDT_RM9K_GPI To compile this driver as a module, choose M here: the module will be called rm9k_wdt. +# PARISC Architecture + +# POWERPC Architecture + +config MPC5200_WDT + tristate "MPC5200 Watchdog Timer" + depends on PPC_MPC52xx + +config 8xx_WDT + tristate "MPC8xx Watchdog Timer" + depends on 8xx + +config 83xx_WDT + tristate "MPC83xx Watchdog Timer" + depends on PPC_83xx + +config MV64X60_WDT + tristate "MV64X60 (Marvell Discovery) Watchdog Timer" + depends on MV64X60 + +config BOOKE_WDT + bool "PowerPC Book-E Watchdog Timer" + depends on BOOKE || 4xx + ---help--- + Please see Documentation/watchdog/watchdog-api.txt for + more information. + +# PPC64 Architecture + +config WATCHDOG_RTAS + tristate "RTAS watchdog" + depends on PPC_RTAS + help + This driver adds watchdog support for the RTAS watchdog. + + To compile this driver as a module, choose M here. The module + will be called wdrtas. + # S390 Architecture config ZVM_WATCHDOG @@ -614,7 +661,7 @@ config ZVM_WATCHDOG To compile this driver as a module, choose M here. The module will be called vmwatchdog. -# SUPERH Architecture +# SUPERH (sh + sh64) Architecture config SH_WDT tristate "SuperH Watchdog" @@ -641,6 +688,8 @@ config SH_WDT_MMAP If you say Y here, user applications will be able to mmap the WDT/CPG registers. +# SPARC Architecture + # SPARC64 Architecture config WATCHDOG_CP1XXX @@ -665,6 +714,10 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. +# V850 Architecture + +# XTENSA Architecture + # # ISA-based Watchdog Cards # diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index bdb9d5e..389f8b1 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -22,6 +22,8 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o # USB-based Watchdog Cards obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o +# ALPHA Architecture + # ARM Architecture obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o @@ -36,10 +38,22 @@ obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o +obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o + +# ARM26 Architecture # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o +# BLACKFIN Architecture +obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o + +# CRIS Architecture + +# FRV Architecture + +# H8300 Architecture + # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o @@ -66,8 +80,22 @@ obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o -# PowerPC Architecture +# M32R Architecture + +# M68K Architecture + +# M68KNOMMU Architecture + +# MIPS Architecture +obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o +obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o + +# PARISC Architecture + +# POWERPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o +obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o @@ -75,17 +103,18 @@ obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o # PPC64 Architecture obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o -# MIPS Architecture -obj-$(CONFIG_INDYDOG) += indydog.o -obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o -obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o - # S390 Architecture -# SUPERH Architecture +# SUPERH (sh + sh64) Architecture obj-$(CONFIG_SH_WDT) += shwdt.o +# SPARC Architecture + # SPARC64 Architecture +# V850 Architecture + +# XTENSA Architecture + # Architecture Independant obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o diff --git a/drivers/char/watchdog/bfin_wdt.c b/drivers/char/watchdog/bfin_wdt.c new file mode 100644 index 0000000..309d279 --- /dev/null +++ b/drivers/char/watchdog/bfin_wdt.c @@ -0,0 +1,490 @@ +/* + * Blackfin On-Chip Watchdog Driver + * Supports BF53[123]/BF53[467]/BF54[2489]/BF561 + * + * Originally based on softdog.c + * Copyright 2006-2007 Analog Devices Inc. + * Copyright 2006-2007 Michele d'Amico + * Copyright 1996 Alan Cox <alan@redhat.com> + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/timer.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/fs.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/blackfin.h> +#include <asm/uaccess.h> + +#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) +#define stampit() stamp("here i am") + +#define WATCHDOG_NAME "bfin-wdt" +#define PFX WATCHDOG_NAME ": " + +/* The BF561 has two watchdogs (one per core), but since Linux + * only runs on core A, we'll just work with that one. + */ +#ifdef BF561_FAMILY +# define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL() +# define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT() +# define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT() +# define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x) +# define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x) +# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x) +#endif + +/* Bit in SWRST that indicates boot caused by watchdog */ +#define SWRST_RESET_WDOG 0x4000 + +/* Bit in WDOG_CTL that indicates watchdog has expired (WDR0) */ +#define WDOG_EXPIRED 0x8000 + +/* Masks for WDEV field in WDOG_CTL register */ +#define ICTL_RESET 0x0 +#define ICTL_NMI 0x2 +#define ICTL_GPI 0x4 +#define ICTL_NONE 0x6 +#define ICTL_MASK 0x6 + +/* Masks for WDEN field in WDOG_CTL register */ +#define WDEN_MASK 0x0FF0 +#define WDEN_ENABLE 0x0000 +#define WDEN_DISABLE 0x0AD0 + +/* some defaults */ +#define WATCHDOG_TIMEOUT 20 + +static unsigned int timeout = WATCHDOG_TIMEOUT; +static int nowayout = WATCHDOG_NOWAYOUT; +static struct watchdog_info bfin_wdt_info; +static unsigned long open_check; +static char expect_close; +static spinlock_t bfin_wdt_spinlock = SPIN_LOCK_UNLOCKED; + +/** + * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive + * + * The Userspace watchdog got a KeepAlive: schedule the next timeout. + */ +static int bfin_wdt_keepalive(void) +{ + stampit(); + bfin_write_WDOG_STAT(0); + return 0; +} + +/** + * bfin_wdt_stop - Stop the Watchdog + * + * Stops the on-chip watchdog. + */ +static int bfin_wdt_stop(void) +{ + stampit(); + bfin_write_WDOG_CTL(WDEN_DISABLE); + return 0; +} + +/** + * bfin_wdt_start - Start the Watchdog + * + * Starts the on-chip watchdog. Automatically loads WDOG_CNT + * into WDOG_STAT for us. + */ +static int bfin_wdt_start(void) +{ + stampit(); + bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET); + return 0; +} + +/** + * bfin_wdt_running - Check Watchdog status + * + * See if the watchdog is running. + */ +static int bfin_wdt_running(void) +{ + stampit(); + return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE); +} + +/** + * bfin_wdt_set_timeout - Set the Userspace Watchdog timeout + * @t: new timeout value (in seconds) + * + * Translate the specified timeout in seconds into System Clock + * terms which is what the on-chip Watchdog requires. + */ +static int bfin_wdt_set_timeout(unsigned long t) +{ + u32 cnt; + unsigned long flags; + + stampit(); + + cnt = t * get_sclk(); + if (cnt < get_sclk()) { + printk(KERN_WARNING PFX "timeout value is too large\n"); + return -EINVAL; + } + + spin_lock_irqsave(&bfin_wdt_spinlock, flags); + { + int run = bfin_wdt_running(); + bfin_wdt_stop(); + bfin_write_WDOG_CNT(cnt); + if (run) bfin_wdt_start(); + } + spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); + + timeout = t; + + return 0; +} + +/** + * bfin_wdt_open - Open the Device + * @inode: inode of device + * @file: file handle of device + * + * Watchdog device is opened and started. + */ +static int bfin_wdt_open(struct inode *inode, struct file *file) +{ + stampit(); + + if (test_and_set_bit(0, &open_check)) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); + + bfin_wdt_keepalive(); + bfin_wdt_start(); + + return nonseekable_open(inode, file); +} + +/** + * bfin_wdt_close - Close the Device + * @inode: inode of device + * @file: file handle of device + * + * Watchdog device is closed and stopped. + */ +static int bfin_wdt_release(struct inode *inode, struct file *file) +{ + stampit(); + + if (expect_close == 42) { + bfin_wdt_stop(); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + bfin_wdt_keepalive(); + } + + expect_close = 0; + clear_bit(0, &open_check); + + return 0; +} + +/** + * bfin_wdt_write - Write to Device + * @file: file handle of device + * @buf: buffer to write + * @count: length of buffer + * @ppos: offset + * + * Pings the watchdog on write. + */ +static ssize_t bfin_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + stampit(); + + if (len) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + bfin_wdt_keepalive(); + } + + return len; +} + +/** + * bfin_wdt_ioctl - Query Device + * @inode: inode of device + * @file: file handle of device + * @cmd: watchdog command + * @arg: argument + * + * Query basic information from the device or ping it, as outlined by the + * watchdog API. + */ +static int bfin_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + + stampit(); + + switch (cmd) { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) + return -EFAULT; + else + return 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); + + case WDIOC_KEEPALIVE: + bfin_wdt_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: { + int new_timeout; + + if (get_user(new_timeout, p)) + return -EFAULT; + + if (bfin_wdt_set_timeout(new_timeout)) + return -EINVAL; + } + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + case WDIOC_SETOPTIONS: { + unsigned long flags; + int options, ret = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + spin_lock_irqsave(&bfin_wdt_spinlock, flags); + + if (options & WDIOS_DISABLECARD) { + bfin_wdt_stop(); + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + bfin_wdt_start(); + ret = 0; + } + + spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); + + return ret; + } + } +} + +/** + * bfin_wdt_notify_sys - Notifier Handler + * @this: notifier block + * @code: notifier event + * @unused: unused + * + * Handles specific events, such as turning off the watchdog during a + * shutdown event. + */ +static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + stampit(); + + if (code == SYS_DOWN || code == SYS_HALT) + bfin_wdt_stop(); + + return NOTIFY_DONE; +} + +#ifdef CONFIG_PM +static int state_before_suspend; + +/** + * bfin_wdt_suspend - suspend the watchdog + * @pdev: device being suspended + * @state: requested suspend state + * + * Remember if the watchdog was running and stop it. + * TODO: is this even right? Doesn't seem to be any + * standard in the watchdog world ... + */ +static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state) +{ + stampit(); + + state_before_suspend = bfin_wdt_running(); + bfin_wdt_stop(); + + return 0; +} + +/** + * bfin_wdt_resume - resume the watchdog + * @pdev: device being resumed + * + * If the watchdog was running, turn it back on. + */ +static int bfin_wdt_resume(struct platform_device *pdev) +{ + stampit(); + + if (state_before_suspend) { + bfin_wdt_set_timeout(timeout); + bfin_wdt_start(); + } + + return 0; +} +#else +# define bfin_wdt_suspend NULL +# define bfin_wdt_resume NULL +#endif + +static struct platform_device bfin_wdt_device = { + .name = WATCHDOG_NAME, + .id = -1, +}; + +static struct platform_driver bfin_wdt_driver = { + .driver = { + .name = WATCHDOG_NAME, + .owner = THIS_MODULE, + }, + .suspend = bfin_wdt_suspend, + .resume = bfin_wdt_resume, +}; + +static struct file_operations bfin_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = bfin_wdt_write, + .ioctl = bfin_wdt_ioctl, + .open = bfin_wdt_open, + .release = bfin_wdt_release, +}; + +static struct miscdevice bfin_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &bfin_wdt_fops, +}; + +static struct watchdog_info bfin_wdt_info = { + .identity = "Blackfin Watchdog", + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, +}; + +static struct notifier_block bfin_wdt_notifier = { + .notifier_call = bfin_wdt_notify_sys, +}; + +/** + * bfin_wdt_init - Initialize module + * + * Registers the device and notifier handler. Actual device + * initialization is handled by bfin_wdt_open(). + */ +static int __init bfin_wdt_init(void) +{ + int ret; + + stampit(); + + /* Check that the timeout value is within range */ + if (bfin_wdt_set_timeout(timeout)) + return -EINVAL; + + /* Since this is an on-chip device and needs no board-specific + * resources, we'll handle all the platform device stuff here. + */ + ret = platform_device_register(&bfin_wdt_device); + if (ret) + return ret; + + ret = platform_driver_probe(&bfin_wdt_driver, NULL); + if (ret) + return ret; + + ret = register_reboot_notifier(&bfin_wdt_notifier); + if (ret) { + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); + return ret; + } + + ret = misc_register(&bfin_wdt_miscdev); + if (ret) { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&bfin_wdt_notifier); + return ret; + } + + printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", + timeout, nowayout); + + return 0; +} + +/** + * bfin_wdt_exit - Deinitialize module + * + * Unregisters the device and notifier handler. Actual device + * deinitialization is handled by bfin_wdt_close(). + */ +static void __exit bfin_wdt_exit(void) +{ + misc_deregister(&bfin_wdt_miscdev); + unregister_reboot_notifier(&bfin_wdt_notifier); +} + +module_init(bfin_wdt_init); +module_exit(bfin_wdt_exit); + +MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>"); +MODULE_DESCRIPTION("Blackfin Watchdog Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index 0f5c77d..d362f5b 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c @@ -144,7 +144,7 @@ static int booke_wdt_open (struct inode *inode, struct file *file) booke_wdt_period); } - return 0; + return nonseekable_open(inode, file); } static const struct file_operations booke_wdt_fops = { diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index d0d45a8..5941ca6 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c @@ -162,6 +162,10 @@ static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cm if ( copy_to_user(argp, &value, sizeof(int)) ) return -EFAULT; break; + case WDIOC_GETBOOTSTATUS: + if ( copy_to_user(argp, &value, sizeof(int)) ) + return -EFAULT; + break; case WDIOC_GETSUPPORT: if ( copy_to_user(argp, &ident, sizeof(ident)) ) return -EFAULT; diff --git a/drivers/char/watchdog/davinci_wdt.c b/drivers/char/watchdog/davinci_wdt.c new file mode 100644 index 0000000..19db530 --- /dev/null +++ b/drivers/char/watchdog/davinci_wdt.c @@ -0,0 +1,281 @@ +/* + * drivers/char/watchdog/davinci_wdt.c + * + * Watchdog driver for DaVinci DM644x/DM646x processors + * + * Copyright (C) 2006 Texas Instruments. + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#include <asm/hardware.h> +#include <asm/uaccess.h> +#include <asm/io.h> + +#define MODULE_NAME "DAVINCI-WDT: " + +#define DEFAULT_HEARTBEAT 60 +#define MAX_HEARTBEAT 600 /* really the max margin is 264/27MHz*/ + +/* Timer register set definition */ +#define PID12 (0x0) +#define EMUMGT (0x4) +#define TIM12 (0x10) +#define TIM34 (0x14) +#define PRD12 (0x18) +#define PRD34 (0x1C) +#define TCR (0x20) +#define TGCR (0x24) +#define WDTCR (0x28) + +/* TCR bit definitions */ +#define ENAMODE12_DISABLED (0 << 6) +#define ENAMODE12_ONESHOT (1 << 6) +#define ENAMODE12_PERIODIC (2 << 6) + +/* TGCR bit definitions */ +#define TIM12RS_UNRESET (1 << 0) +#define TIM34RS_UNRESET (1 << 1) +#define TIMMODE_64BIT_WDOG (2 << 2) + +/* WDTCR bit definitions */ +#define WDEN (1 << 14) +#define WDFLAG (1 << 15) +#define WDKEY_SEQ0 (0xa5c6 << 16) +#define WDKEY_SEQ1 (0xda7e << 16) + +static int heartbeat = DEFAULT_HEARTBEAT; + +static spinlock_t io_lock; +static unsigned long wdt_status; +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 +#define WDT_REGION_INITED 2 +#define WDT_DEVICE_INITED 3 + +static struct resource *wdt_mem; +static void __iomem *wdt_base; + +static void wdt_service(void) +{ + spin_lock(&io_lock); + + /* put watchdog in service state */ + davinci_writel(WDKEY_SEQ0, wdt_base + WDTCR); + /* put watchdog in active state */ + davinci_writel(WDKEY_SEQ1, wdt_base + WDTCR); + + spin_unlock(&io_lock); +} + +static void wdt_enable(void) +{ + u32 tgcr; + u32 timer_margin; + + spin_lock(&io_lock); + + /* disable, internal clock source */ + davinci_writel(0, wdt_base + TCR); + /* reset timer, set mode to 64-bit watchdog, and unreset */ + davinci_writel(0, wdt_base + TGCR); + tgcr = TIMMODE_64BIT_WDOG | TIM12RS_UNRESET | TIM34RS_UNRESET; + davinci_writel(tgcr, wdt_base + TGCR); + /* clear counter regs */ + davinci_writel(0, wdt_base + TIM12); + davinci_writel(0, wdt_base + TIM34); + /* set timeout period */ + timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) & 0xffffffff); + davinci_writel(timer_margin, wdt_base + PRD12); + timer_margin = (((u64)heartbeat * CLOCK_TICK_RATE) >> 32); + davinci_writel(timer_margin, wdt_base + PRD34); + /* enable run continuously */ + davinci_writel(ENAMODE12_PERIODIC, wdt_base + TCR); + /* Once the WDT is in pre-active state write to + * TIM12, TIM34, PRD12, PRD34, TCR, TGCR, WDTCR are + * write protected (except for the WDKEY field) + */ + /* put watchdog in pre-active state */ + davinci_writel(WDKEY_SEQ0 | WDEN, wdt_base + WDTCR); + /* put watchdog in active state */ + davinci_writel(WDKEY_SEQ1 | WDEN, wdt_base + WDTCR); + + spin_unlock(&io_lock); +} + +static int davinci_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) + return -EBUSY; + + wdt_enable(); + + return nonseekable_open(inode, file); +} + +static ssize_t +davinci_wdt_write(struct file *file, const char *data, size_t len, + loff_t *ppos) +{ + if (len) + wdt_service(); + + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING, + .identity = "DaVinci Watchdog", +}; + +static int +davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + wdt_service(); + ret = 0; + break; + } + return ret; +} + +static int davinci_wdt_release(struct inode *inode, struct file *file) +{ + wdt_service(); + clear_bit(WDT_IN_USE, &wdt_status); + + return 0; +} + +static const struct file_operations davinci_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = davinci_wdt_write, + .ioctl = davinci_wdt_ioctl, + .open = davinci_wdt_open, + .release = davinci_wdt_release, +}; + +static struct miscdevice davinci_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &davinci_wdt_fops, +}; + +static int davinci_wdt_probe(struct platform_device *pdev) +{ + int ret = 0, size; + struct resource *res; + + spin_lock_init(&io_lock); + + if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) + heartbeat = DEFAULT_HEARTBEAT; + + printk(KERN_INFO MODULE_NAME + "DaVinci Watchdog Timer: heartbeat %d sec\n", heartbeat); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + printk(KERN_INFO MODULE_NAME + "failed to get memory region resource\n"); + return -ENOENT; + } + + size = res->end - res->start + 1; + wdt_mem = request_mem_region(res->start, size, pdev->name); + + if (wdt_mem == NULL) { + printk(KERN_INFO MODULE_NAME "failed to get memory region\n"); + return -ENOENT; + } + wdt_base = (void __iomem *)(res->start); + + ret = misc_register(&davinci_wdt_miscdev); + if (ret < 0) { + printk(KERN_ERR MODULE_NAME "cannot register misc device\n"); + release_resource(wdt_mem); + kfree(wdt_mem); + } else { + set_bit(WDT_DEVICE_INITED, &wdt_status); + } + + return ret; +} + +static int davinci_wdt_remove(struct platform_device *pdev) +{ + misc_deregister(&davinci_wdt_miscdev); + if (wdt_mem) { + release_resource(wdt_mem); + kfree(wdt_mem); + wdt_mem = NULL; + } + return 0; +} + +static struct platform_driver platform_wdt_driver = { + .driver = { + .name = "watchdog", + }, + .probe = davinci_wdt_probe, + .remove = davinci_wdt_remove, +}; + +static int __init davinci_wdt_init(void) +{ + return platform_driver_register(&platform_wdt_driver); +} + +static void __exit davinci_wdt_exit(void) +{ + return platform_driver_unregister(&platform_wdt_driver); +} + +module_init(davinci_wdt_init); +module_exit(davinci_wdt_exit); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("DaVinci Watchdog Driver"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, + "Watchdog heartbeat period in seconds from 1 to " + __MODULE_STRING(MAX_HEARTBEAT) ", default " + __MODULE_STRING(DEFAULT_HEARTBEAT)); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index eac4f9b..cd5a565 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -39,7 +39,12 @@ * 82801HR (ICH8R) : document number 313056-002, 313057-004, * 82801HH (ICH8DH) : document number 313056-002, 313057-004, * 82801HO (ICH8DO) : document number 313056-002, 313057-004, - * 6300ESB (6300ESB) : document number 300641-003 + * 82801IB (ICH9) : document number 316972-001, 316973-001, + * 82801IR (ICH9R) : document number 316972-001, 316973-001, + * 82801IH (ICH9DH) : document number 316972-001, 316973-001, + * 6300ESB (6300ESB) : document number 300641-003, 300884-010, + * 631xESB (631xESB) : document number 313082-001, 313075-005, + * 632xESB (632xESB) : document number 313082-001, 313075-005 */ /* @@ -48,8 +53,8 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" -#define DRV_VERSION "1.01" -#define DRV_RELDATE "21-Jan-2007" +#define DRV_VERSION "1.02" +#define DRV_RELDATE "26-Jul-2007" #define PFX DRV_NAME ": " /* Includes */ @@ -92,6 +97,10 @@ enum iTCO_chipsets { TCO_ICH8, /* ICH8 & ICH8R */ TCO_ICH8DH, /* ICH8DH */ TCO_ICH8DO, /* ICH8DO */ + TCO_ICH9, /* ICH9 */ + TCO_ICH9R, /* ICH9R */ + TCO_ICH9DH, /* ICH9DH */ + TCO_631XESB, /* 631xESB/632xESB */ }; static struct { @@ -118,6 +127,10 @@ static struct { {"ICH8 or ICH8R", 2}, {"ICH8DH", 2}, {"ICH8DO", 2}, + {"ICH9", 2}, + {"ICH9R", 2}, + {"ICH9DH", 2}, + {"631xESB/632xESB", 2}, {NULL,0} }; @@ -148,6 +161,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, + { PCI_VENDOR_ID_INTEL, 0x2918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9 }, + { PCI_VENDOR_ID_INTEL, 0x2916, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9R }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH9DH }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, + { PCI_VENDOR_ID_INTEL, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_631XESB }, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index a0d2716..6d35bb1 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -321,6 +321,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, break; case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index db2ccb8..1adf1d5 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -215,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, return -EFAULT; } break; + case WDIOC_GETBOOTSTATUS: + if (copy_to_user(p, &status, sizeof(int))) { + return -EFAULT; + } + break; case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) { return -EFAULT; diff --git a/drivers/char/watchdog/mpc5200_wdt.c b/drivers/char/watchdog/mpc5200_wdt.c new file mode 100644 index 0000000..564143d --- /dev/null +++ b/drivers/char/watchdog/mpc5200_wdt.c @@ -0,0 +1,286 @@ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/io.h> +#include <linux/spinlock.h> +#include <asm/of_platform.h> +#include <asm/uaccess.h> +#include <asm/mpc52xx.h> + + +#define GPT_MODE_WDT (1<<15) +#define GPT_MODE_CE (1<<12) +#define GPT_MODE_MS_TIMER (0x4) + + +struct mpc5200_wdt { + unsigned count; /* timer ticks before watchdog kicks in */ + long ipb_freq; + struct miscdevice miscdev; + struct resource mem; + struct mpc52xx_gpt __iomem *regs; + spinlock_t io_lock; +}; + +/* is_active stores wether or not the /dev/watchdog device is opened */ +static unsigned long is_active; + +/* misc devices don't provide a way, to get back to 'dev' or 'miscdev' from + * file operations, which sucks. But there can be max 1 watchdog anyway, so... + */ +static struct mpc5200_wdt *wdt_global; + + +/* helper to calculate timeout in timer counts */ +static void mpc5200_wdt_set_timeout(struct mpc5200_wdt *wdt, int timeout) +{ + /* use biggest prescaler of 64k */ + wdt->count = (wdt->ipb_freq + 0xffff) / 0x10000 * timeout; + + if (wdt->count > 0xffff) + wdt->count = 0xffff; +} +/* return timeout in seconds (calculated from timer count) */ +static int mpc5200_wdt_get_timeout(struct mpc5200_wdt *wdt) +{ + return wdt->count * 0x10000 / wdt->ipb_freq; +} + + +/* watchdog operations */ +static int mpc5200_wdt_start(struct mpc5200_wdt *wdt) +{ + spin_lock(&wdt->io_lock); + /* disable */ + out_be32(&wdt->regs->mode, 0); + /* set timeout, with maximum prescaler */ + out_be32(&wdt->regs->count, 0x0 | wdt->count); + /* enable watchdog */ + out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER); + spin_unlock(&wdt->io_lock); + + return 0; +} +static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt) +{ + spin_lock(&wdt->io_lock); + /* writing A5 to OCPW resets the watchdog */ + out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode))); + spin_unlock(&wdt->io_lock); + return 0; +} +static int mpc5200_wdt_stop(struct mpc5200_wdt *wdt) +{ + spin_lock(&wdt->io_lock); + /* disable */ + out_be32(&wdt->regs->mode, 0); + spin_unlock(&wdt->io_lock); + return 0; +} + + +/* file operations */ +static ssize_t mpc5200_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + struct mpc5200_wdt *wdt = file->private_data; + mpc5200_wdt_ping(wdt); + return 0; +} +static struct watchdog_info mpc5200_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "mpc5200 watchdog on GPT0", +}; +static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct mpc5200_wdt *wdt = file->private_data; + int __user *data = (int __user *)arg; + int timeout; + int ret = 0; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user(data, &mpc5200_wdt_info, + sizeof(mpc5200_wdt_info)); + if (ret) + ret = -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, data); + break; + + case WDIOC_KEEPALIVE: + mpc5200_wdt_ping(wdt); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(timeout, data); + if (ret) + break; + mpc5200_wdt_set_timeout(wdt, timeout); + mpc5200_wdt_start(wdt); + /* fall through and return the timeout */ + + case WDIOC_GETTIMEOUT: + timeout = mpc5200_wdt_get_timeout(wdt); + ret = put_user(timeout, data); + break; + + default: + ret = -ENOTTY; + } + return ret; +} +static int mpc5200_wdt_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &is_active)) + return -EBUSY; + + /* Set and activate the watchdog */ + mpc5200_wdt_set_timeout(wdt_global, 30); + mpc5200_wdt_start(wdt_global); + file->private_data = wdt_global; + return nonseekable_open(inode, file); +} +static int mpc5200_wdt_release(struct inode *inode, struct file *file) +{ +#if WATCHDOG_NOWAYOUT == 0 + struct mpc5200_wdt *wdt = file->private_data; + mpc5200_wdt_stop(wdt); + wdt->count = 0; /* == disabled */ +#endif + clear_bit(0, &is_active); + return 0; +} + +static struct file_operations mpc5200_wdt_fops = { + .owner = THIS_MODULE, + .write = mpc5200_wdt_write, + .ioctl = mpc5200_wdt_ioctl, + .open = mpc5200_wdt_open, + .release = mpc5200_wdt_release, +}; + +/* module operations */ +static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match) +{ + struct mpc5200_wdt *wdt; + int err; + const void *has_wdt; + int size; + + has_wdt = of_get_property(op->node, "has-wdt", NULL); + if (!has_wdt) + return -ENODEV; + + wdt = kzalloc(sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; + + wdt->ipb_freq = mpc52xx_find_ipb_freq(op->node); + + err = of_address_to_resource(op->node, 0, &wdt->mem); + if (err) + goto out_free; + size = wdt->mem.end - wdt->mem.start + 1; + if (!request_mem_region(wdt->mem.start, size, "mpc5200_wdt")) { + err = -ENODEV; + goto out_free; + } + wdt->regs = ioremap(wdt->mem.start, size); + if (!wdt->regs) { + err = -ENODEV; + goto out_release; + } + + dev_set_drvdata(&op->dev, wdt); + spin_lock_init(&wdt->io_lock); + + wdt->miscdev = (struct miscdevice) { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mpc5200_wdt_fops, + .parent = &op->dev, + }; + wdt_global = wdt; + err = misc_register(&wdt->miscdev); + if (!err) + return 0; + + iounmap(wdt->regs); + out_release: + release_mem_region(wdt->mem.start, size); + out_free: + kfree(wdt); + return err; +} + +static int mpc5200_wdt_remove(struct of_device *op) +{ + struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); + + mpc5200_wdt_stop(wdt); + misc_deregister(&wdt->miscdev); + iounmap(wdt->regs); + release_mem_region(wdt->mem.start, wdt->mem.end - wdt->mem.start + 1); + kfree(wdt); + + return 0; +} +static int mpc5200_wdt_suspend(struct of_device *op, pm_message_t state) +{ + struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); + mpc5200_wdt_stop(wdt); + return 0; +} +static int mpc5200_wdt_resume(struct of_device *op) +{ + struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); + if (wdt->count) + mpc5200_wdt_start(wdt); + return 0; +} +static int mpc5200_wdt_shutdown(struct of_device *op) +{ + struct mpc5200_wdt *wdt = dev_get_drvdata(&op->dev); + mpc5200_wdt_stop(wdt); + return 0; +} + +static struct of_device_id mpc5200_wdt_match[] = { + { .compatible = "mpc5200-gpt", }, + {}, +}; +static struct of_platform_driver mpc5200_wdt_driver = { + .owner = THIS_MODULE, + .name = "mpc5200-gpt-wdt", + .match_table = mpc5200_wdt_match, + .probe = mpc5200_wdt_probe, + .remove = mpc5200_wdt_remove, + .suspend = mpc5200_wdt_suspend, + .resume = mpc5200_wdt_resume, + .shutdown = mpc5200_wdt_shutdown, +}; + + +static int __init mpc5200_wdt_init(void) +{ + return of_register_platform_driver(&mpc5200_wdt_driver); +} + +static void __exit mpc5200_wdt_exit(void) +{ + of_unregister_platform_driver(&mpc5200_wdt_driver); +} + +module_init(mpc5200_wdt_init); +module_exit(mpc5200_wdt_exit); + +MODULE_AUTHOR("Domen Puncer <domen.puncer@telargo.com>"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c index 18ca752..a0bf95f 100644 --- a/drivers/char/watchdog/mpc83xx_wdt.c +++ b/drivers/char/watchdog/mpc83xx_wdt.c @@ -119,6 +119,9 @@ static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); case WDIOC_KEEPALIVE: mpc83xx_wdt_keepalive(); return 0; diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c index 8aaed10..85b5734 100644 --- a/drivers/char/watchdog/mpc8xx_wdt.c +++ b/drivers/char/watchdog/mpc8xx_wdt.c @@ -57,7 +57,7 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file) m8xx_wdt_reset(); mpc8xx_wdt_handler_disable(); - return 0; + return nonseekable_open(inode, file); } static int mpc8xx_wdt_release(struct inode *inode, struct file *file) diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c index 419ab44..dcfd401 100644 --- a/drivers/char/watchdog/mtx-1_wdt.c +++ b/drivers/char/watchdog/mtx-1_wdt.c @@ -143,6 +143,7 @@ static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int c mtx1_wdt_reset(); break; case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: if ( copy_to_user(argp, &value, sizeof(int)) ) return -EFAULT; break; diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index b887cdb..0365c31 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c @@ -23,61 +23,101 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> -#include <asm/mv64x60.h> +#include <linux/mv643xx.h> #include <asm/uaccess.h> #include <asm/io.h> -/* MV64x60 WDC (config) register access definitions */ -#define MV64x60_WDC_CTL1_MASK (3 << 24) -#define MV64x60_WDC_CTL1(val) ((val & 3) << 24) -#define MV64x60_WDC_CTL2_MASK (3 << 26) -#define MV64x60_WDC_CTL2(val) ((val & 3) << 26) +#define MV64x60_WDT_WDC_OFFSET 0 + +/* + * The watchdog configuration register contains a pair of 2-bit fields, + * 1. a reload field, bits 27-26, which triggers a reload of + * the countdown register, and + * 2. an enable field, bits 25-24, which toggles between + * enabling and disabling the watchdog timer. + * Bit 31 is a read-only field which indicates whether the + * watchdog timer is currently enabled. + * + * The low 24 bits contain the timer reload value. + */ +#define MV64x60_WDC_ENABLE_SHIFT 24 +#define MV64x60_WDC_SERVICE_SHIFT 26 +#define MV64x60_WDC_ENABLED_SHIFT 31 + +#define MV64x60_WDC_ENABLED_TRUE 1 +#define MV64x60_WDC_ENABLED_FALSE 0 /* Flags bits */ #define MV64x60_WDOG_FLAG_OPENED 0 -#define MV64x60_WDOG_FLAG_ENABLED 1 static unsigned long wdt_flags; static int wdt_status; -static void __iomem *mv64x60_regs; +static void __iomem *mv64x60_wdt_regs; static int mv64x60_wdt_timeout; +static int mv64x60_wdt_count; +static unsigned int bus_clk; +static char expect_close; +static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static void mv64x60_wdt_reg_write(u32 val) +static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) { - /* Allow write only to CTL1 / CTL2 fields, retaining values in - * other fields. - */ - u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); - data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); - data |= val; - writel(data, mv64x60_regs + MV64x60_WDT_WDC); + u32 data; + u32 enabled; + int ret = 0; + + spin_lock(&mv64x60_wdt_spinlock); + data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1; + + /* only toggle the requested field if enabled state matches predicate */ + if ((enabled ^ enabled_predicate) == 0) { + /* We write a 1, then a 2 -- to the appropriate field */ + data = (1 << field_shift) | mv64x60_wdt_count; + writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + + data = (2 << field_shift) | mv64x60_wdt_count; + writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); + ret = 1; + } + spin_unlock(&mv64x60_wdt_spinlock); + + return ret; } static void mv64x60_wdt_service(void) { - /* Write 01 followed by 10 to CTL2 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); + mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, + MV64x60_WDC_SERVICE_SHIFT); +} + +static void mv64x60_wdt_handler_enable(void) +{ + if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE, + MV64x60_WDC_ENABLE_SHIFT)) { + mv64x60_wdt_service(); + printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); + } } static void mv64x60_wdt_handler_disable(void) { - if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { - /* Write 01 followed by 10 to CTL1 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); + if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, + MV64x60_WDC_ENABLE_SHIFT)) printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); - } } -static void mv64x60_wdt_handler_enable(void) +static void mv64x60_wdt_set_timeout(unsigned int timeout) { - if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { - /* Write 01 followed by 10 to CTL1 */ - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); - mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); - printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); - } + /* maximum bus cycle count is 0xFFFFFFFF */ + if (timeout > 0xFFFFFFFF / bus_clk) + timeout = 0xFFFFFFFF / bus_clk; + + mv64x60_wdt_count = timeout * bus_clk >> 8; + mv64x60_wdt_timeout = timeout; } static int mv64x60_wdt_open(struct inode *inode, struct file *file) @@ -85,21 +125,24 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) return -EBUSY; - mv64x60_wdt_service(); - mv64x60_wdt_handler_enable(); + if (nowayout) + __module_get(THIS_MODULE); - nonseekable_open(inode, file); + mv64x60_wdt_handler_enable(); - return 0; + return nonseekable_open(inode, file); } static int mv64x60_wdt_release(struct inode *inode, struct file *file) { - mv64x60_wdt_service(); - -#if !defined(CONFIG_WATCHDOG_NOWAYOUT) - mv64x60_wdt_handler_disable(); -#endif + if (expect_close == 42) + mv64x60_wdt_handler_disable(); + else { + printk(KERN_CRIT + "mv64x60_wdt: unexpected close, not stopping timer!\n"); + mv64x60_wdt_service(); + } + expect_close = 0; clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); @@ -109,8 +152,22 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { - if (len) + if (len) { + if (!nowayout) { + size_t i; + + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } mv64x60_wdt_service(); + } return len; } @@ -119,9 +176,12 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int timeout; + int options; void __user *argp = (void __user *)arg; static struct watchdog_info info = { - .options = WDIOF_KEEPALIVEPING, + .options = WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, .firmware_version = 0, .identity = "MV64x60 watchdog", }; @@ -143,7 +203,15 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, return -EOPNOTSUPP; case WDIOC_SETOPTIONS: - return -EOPNOTSUPP; + if (get_user(options, (int __user *)argp)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) + mv64x60_wdt_handler_disable(); + + if (options & WDIOS_ENABLECARD) + mv64x60_wdt_handler_enable(); + break; case WDIOC_KEEPALIVE: mv64x60_wdt_service(); @@ -151,11 +219,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, break; case WDIOC_SETTIMEOUT: - return -EOPNOTSUPP; + if (get_user(timeout, (int __user *)argp)) + return -EFAULT; + mv64x60_wdt_set_timeout(timeout); + /* Fall through */ case WDIOC_GETTIMEOUT: - timeout = mv64x60_wdt_timeout * HZ; - if (put_user(timeout, (int __user *)argp)) + if (put_user(mv64x60_wdt_timeout, (int __user *)argp)) return -EFAULT; break; @@ -184,18 +254,33 @@ static struct miscdevice mv64x60_wdt_miscdev = { static int __devinit mv64x60_wdt_probe(struct platform_device *dev) { struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data; - int bus_clk = 133; + struct resource *r; + int timeout = 10; - mv64x60_wdt_timeout = 10; + bus_clk = 133; /* in MHz */ if (pdata) { - mv64x60_wdt_timeout = pdata->timeout; + timeout = pdata->timeout; bus_clk = pdata->bus_clk; } - mv64x60_regs = mv64x60_get_bridge_vbase(); + /* Since bus_clk is truncated MHz, actual frequency could be + * up to 1MHz higher. Round up, since it's better to time out + * too late than too soon. + */ + bus_clk++; + bus_clk *= 1000000; /* convert to Hz */ + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; - writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, - mv64x60_regs + MV64x60_WDT_WDC); + mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1); + if (mv64x60_wdt_regs == NULL) + return -ENOMEM; + + mv64x60_wdt_set_timeout(timeout); + + mv64x60_wdt_handler_disable(); /* in case timer was already running */ return misc_register(&mv64x60_wdt_miscdev); } @@ -204,9 +289,10 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev) { misc_deregister(&mv64x60_wdt_miscdev); - mv64x60_wdt_service(); mv64x60_wdt_handler_disable(); + iounmap(mv64x60_wdt_regs); + return 0; } @@ -219,40 +305,16 @@ static struct platform_driver mv64x60_wdt_driver = { }, }; -static struct platform_device *mv64x60_wdt_dev; - static int __init mv64x60_wdt_init(void) { - int ret; - printk(KERN_INFO "MV64x60 watchdog driver\n"); - mv64x60_wdt_dev = platform_device_alloc(MV64x60_WDT_NAME, -1); - if (!mv64x60_wdt_dev) { - ret = -ENOMEM; - goto out; - } - - ret = platform_device_add(mv64x60_wdt_dev); - if (ret) { - platform_device_put(mv64x60_wdt_dev); - goto out; - } - - ret = platform_driver_register(&mv64x60_wdt_driver); - if (ret) { - platform_device_unregister(mv64x60_wdt_dev); - goto out; - } - - out: - return ret; + return platform_driver_register(&mv64x60_wdt_driver); } static void __exit mv64x60_wdt_exit(void) { platform_driver_unregister(&mv64x60_wdt_driver); - platform_device_unregister(mv64x60_wdt_dev); } module_init(mv64x60_wdt_init); diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index b36fa8d..719b066 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c @@ -142,7 +142,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_set_timeout(); omap_wdt_enable(); - return 0; + return nonseekable_open(inode, file); } static int omap_wdt_release(struct inode *inode, struct file *file) @@ -197,7 +197,7 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { default: - return -ENOIOCTLCMD; + return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)); diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 50430bc..5d1c15f 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -52,10 +52,10 @@ #include <asm/arch/map.h> -#undef S3C24XX_VA_WATCHDOG -#define S3C24XX_VA_WATCHDOG (0) +#undef S3C_VA_WATCHDOG +#define S3C_VA_WATCHDOG (0) -#include <asm/arch/regs-watchdog.h> +#include <asm/plat-s3c/regs-watchdog.h> #define PFX "s3c2410-wdt: " diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 33c1137..3475f47 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -45,7 +45,6 @@ static int boot_status; */ static int sa1100dog_open(struct inode *inode, struct file *file) { - nonseekable_open(inode, file); if (test_and_set_bit(1,&sa1100wdt_users)) return -EBUSY; @@ -54,7 +53,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file) OSSR = OSSR_M3; OWER = OWER_WME; OIER |= OIER_E3; - return 0; + return nonseekable_open(inode, file); } /* diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c index b628203..e4f3cb6 100644 --- a/drivers/char/watchdog/sbc60xxwdt.c +++ b/drivers/char/watchdog/sbc60xxwdt.c @@ -191,8 +191,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { - nonseekable_open(inode, file); - /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; @@ -202,7 +200,7 @@ static int fop_open(struct inode * inode, struct file * file) /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 2f7ba7a..9670d47 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -150,8 +150,6 @@ static inline int sc1200wdt_status(void) static int sc1200wdt_open(struct inode *inode, struct file *file) { - nonseekable_open(inode, file); - /* allow one at a time */ if (down_trylock(&open_sem)) return -EBUSY; @@ -162,7 +160,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file) sc1200wdt_start(); printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout); - return 0; + return nonseekable_open(inode, file); } diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 2676a43..e8594c6 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -248,8 +248,6 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou static int fop_open(struct inode * inode, struct file * file) { - nonseekable_open(inode, file); - /* Just in case we're already talking to someone... */ if(test_and_set_bit(0, &wdt_is_open)) return -EBUSY; @@ -258,7 +256,7 @@ static int fop_open(struct inode * inode, struct file * file) /* Good, fire up the show */ wdt_startup(); - return 0; + return nonseekable_open(inode, file); } static int fop_close(struct inode * inode, struct file * file) diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b46e7f4..df33b3b 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c @@ -4,7 +4,7 @@ * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> * added support for W83627THF. * - * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> + * (c) Copyright 2003,2007 Pádraig Brady <P@draigBrady.com> * * Based on advantechwdt.c which is based on wdt.c. * Original copyright messages: @@ -42,7 +42,7 @@ #include <asm/uaccess.h> #include <asm/system.h> -#define WATCHDOG_NAME "w83627hf/thf WDT" +#define WATCHDOG_NAME "w83627hf/thf/hg WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ @@ -57,7 +57,7 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)"); static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); @@ -78,9 +78,9 @@ w83627hf_select_wd_register(void) outb_p(0x87, WDT_EFER); /* Enter extended function mode */ outb_p(0x87, WDT_EFER); /* Again according to manual */ - outb(0x20, WDT_EFER); /* check chip version */ + outb(0x20, WDT_EFER); /* check chip version */ c = inb(WDT_EFDR); - if (c == 0x82) { /* W83627THF */ + if (c == 0x82) { /* W83627THF */ outb_p(0x2b, WDT_EFER); /* select GPIO3 */ c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ outb_p(0x2b, WDT_EFER); @@ -114,11 +114,17 @@ w83627hf_init(void) printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ } + outb_p(0xF5, WDT_EFER); /* Select CRF5 */ t=inb_p(WDT_EFDR); /* read CRF5 */ t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ outb_p(t, WDT_EFDR); /* Write back to CRF5 */ + outb_p(0xF7, WDT_EFER); /* Select CRF7 */ + t=inb_p(WDT_EFDR); /* read CRF7 */ + t&=~0xC0; /* disable keyboard & mouse turning off watchdog */ + outb_p(t, WDT_EFDR); /* Write back to CRF7 */ + w83627hf_unselect_wd_register(); } @@ -126,7 +132,7 @@ static void wdt_ctrl(int timeout) { spin_lock(&io_lock); - + w83627hf_select_wd_register(); outb_p(0xF6, WDT_EFER); /* Select CRF6 */ @@ -154,7 +160,7 @@ wdt_disable(void) static int wdt_set_heartbeat(int t) { - if ((t < 1) || (t > 63)) + if ((t < 1) || (t > 255)) return -EINVAL; timeout = t; @@ -324,11 +330,11 @@ wdt_init(void) spin_lock_init(&io_lock); - printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n"); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); - printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", + printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", WATCHDOG_TIMEOUT); } diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c index d637555..e763d72 100644 --- a/drivers/dma/iovlock.c +++ b/drivers/dma/iovlock.c @@ -143,29 +143,6 @@ void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) kfree(pinned_list); } -static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct - iovec *iov, unsigned char *kdata, size_t len) -{ - dma_cookie_t dma_cookie = 0; - - while (len > 0) { - if (iov->iov_len) { - int copy = min_t(unsigned int, iov->iov_len, len); - dma_cookie = dma_async_memcpy_buf_to_buf( - chan, - iov->iov_base, - kdata, - copy); - kdata += copy; - len -= copy; - iov->iov_len -= copy; - iov->iov_base += copy; - } - iov++; - } - - return dma_cookie; -} /* * We have already pinned down the pages we will be using in the iovecs. @@ -187,10 +164,6 @@ dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, if (!chan) return memcpy_toiovec(iov, kdata, len); - /* -> kernel copies (e.g. smbfs) */ - if (!pinned_list) - return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len); - iovec_idx = 0; while (iovec_idx < pinned_list->nr_iovecs) { struct dma_page_list *page_list; diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 1724c41..98b6b4f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -8,7 +8,7 @@ menuconfig EDAC bool "EDAC - error detection and reporting (EXPERIMENTAL)" depends on HAS_IOMEM depends on EXPERIMENTAL - depends on X86 || MIPS || PPC + depends on X86 || PPC help EDAC is designed to report errors in the core system. These are low-level errors that are reported in the CPU or @@ -126,7 +126,7 @@ config EDAC_I5000 config EDAC_PASEMI tristate "PA Semi PWRficient" depends on EDAC_MM_EDAC && PCI - depends on PPC + depends on PPC_PASEMI help Support for error detection and correction on PA Semi PWRficient. diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4471be3..063a1bf 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -214,6 +214,13 @@ void edac_mc_free(struct mem_ctl_info *mci) } EXPORT_SYMBOL_GPL(edac_mc_free); + +/* + * find_mci_by_dev + * + * scan list of controllers looking for the one that manages + * the 'dev' device + */ static struct mem_ctl_info *find_mci_by_dev(struct device *dev) { struct mem_ctl_info *mci; @@ -268,12 +275,6 @@ static void edac_mc_workq_function(struct work_struct *work_req) if (edac_mc_assert_error_check_and_clear() && (mci->edac_check != NULL)) mci->edac_check(mci); - /* - * FIXME: temp place holder for PCI checks, - * goes away when we break out PCI - */ - edac_pci_do_parity_check(); - mutex_unlock(&mem_ctls_mutex); /* Reschedule */ @@ -314,36 +315,55 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) { int status; - /* if not running POLL, leave now */ - if (mci->op_state == OP_RUNNING_POLL) { - status = cancel_delayed_work(&mci->work); - if (status == 0) { - debugf0("%s() not canceled, flush the queue\n", - __func__); + status = cancel_delayed_work(&mci->work); + if (status == 0) { + debugf0("%s() not canceled, flush the queue\n", + __func__); - /* workq instance might be running, wait for it */ - flush_workqueue(edac_workqueue); - } + /* workq instance might be running, wait for it */ + flush_workqueue(edac_workqueue); } } /* - * edac_reset_delay_period + * edac_mc_reset_delay_period(unsigned long value) + * + * user space has updated our poll period value, need to + * reset our workq delays */ -static void edac_reset_delay_period(struct mem_ctl_info *mci, unsigned long value) +void edac_mc_reset_delay_period(int value) { - /* cancel the current workq request */ - edac_mc_workq_teardown(mci); + struct mem_ctl_info *mci; + struct list_head *item; - /* lock the list of devices for the new setup */ mutex_lock(&mem_ctls_mutex); - /* restart the workq request, with new delay value */ - edac_mc_workq_setup(mci, value); + /* scan the list and turn off all workq timers, doing so under lock + */ + list_for_each(item, &mc_devices) { + mci = list_entry(item, struct mem_ctl_info, link); + + if (mci->op_state == OP_RUNNING_POLL) + cancel_delayed_work(&mci->work); + } + + mutex_unlock(&mem_ctls_mutex); + + + /* re-walk the list, and reset the poll delay */ + mutex_lock(&mem_ctls_mutex); + + list_for_each(item, &mc_devices) { + mci = list_entry(item, struct mem_ctl_info, link); + + edac_mc_workq_setup(mci, (unsigned long) value); + } mutex_unlock(&mem_ctls_mutex); } + + /* Return 0 on success, 1 on failure. * Before calling this function, caller must * assign a unique value to mci->mc_idx. diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index cd090b0..4a0576b 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -122,6 +122,23 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) return count; } +/* + * mc poll_msec time value + */ +static ssize_t poll_msec_int_store(void *ptr, const char *buffer, size_t count) +{ + int *value = (int *)ptr; + + if (isdigit(*buffer)) { + *value = simple_strtoul(buffer, NULL, 0); + + /* notify edac_mc engine to reset the poll period */ + edac_mc_reset_delay_period(*value); + } + + return count; +} + /* EDAC sysfs CSROW data structures and methods */ @@ -704,7 +721,7 @@ MEMCTRL_ATTR(edac_mc_log_ce, S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store); MEMCTRL_ATTR(edac_mc_poll_msec, - S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store); + S_IRUGO | S_IWUSR, memctrl_int_show, poll_msec_int_store); /* Base Attributes of the memory ECC object */ static struct memctrl_dev_attribute *memctrl_attr[] = { diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index a2134df..cbc419c 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -52,6 +52,8 @@ extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev); extern void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev, unsigned long value); +extern void edac_mc_reset_delay_period(int value); + extern void *edac_align_ptr(void *ptr, unsigned size); /* @@ -64,6 +66,10 @@ extern int edac_sysfs_pci_setup(void); extern void edac_sysfs_pci_teardown(void); extern int edac_pci_get_check_errors(void); extern int edac_pci_get_poll_msec(void); +extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci); +extern void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg); +extern void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, + const char *msg); #else /* CONFIG_PCI */ /* pre-process these away */ #define edac_pci_do_parity_check() @@ -72,6 +78,8 @@ extern int edac_pci_get_poll_msec(void); #define edac_sysfs_pci_teardown() #define edac_pci_get_check_errors() #define edac_pci_get_poll_msec() +#define edac_pci_handle_pe() +#define edac_pci_handle_npe() #endif /* CONFIG_PCI */ #endif /* __EDAC_MODULE_H__ */ diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index d9cd5e0..5dee9f5 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -31,20 +31,12 @@ static DEFINE_MUTEX(edac_pci_ctls_mutex); static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list); -static inline void edac_lock_pci_list(void) -{ - mutex_lock(&edac_pci_ctls_mutex); -} - -static inline void edac_unlock_pci_list(void) -{ - mutex_unlock(&edac_pci_ctls_mutex); -} - /* - * The alloc() and free() functions for the 'edac_pci' control info - * structure. The chip driver will allocate one of these for each - * edac_pci it is going to control/register with the EDAC CORE. + * edac_pci_alloc_ctl_info + * + * The alloc() function for the 'edac_pci' control info + * structure. The chip driver will allocate one of these for each + * edac_pci it is going to control/register with the EDAC CORE. */ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, const char *edac_pci_name) @@ -53,47 +45,59 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, void *pvt; unsigned int size; + debugf1("%s()\n", __func__); + pci = (struct edac_pci_ctl_info *)0; pvt = edac_align_ptr(&pci[1], sz_pvt); size = ((unsigned long)pvt) + sz_pvt; - if ((pci = kzalloc(size, GFP_KERNEL)) == NULL) + /* Alloc the needed control struct memory */ + pci = kzalloc(size, GFP_KERNEL); + if (pci == NULL) return NULL; + /* Now much private space */ pvt = sz_pvt ? ((char *)pci) + ((unsigned long)pvt) : NULL; pci->pvt_info = pvt; - pci->op_state = OP_ALLOC; snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name); return pci; } - EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); /* * edac_pci_free_ctl_info() - * frees the memory allocated by edac_pci_alloc_ctl_info() function + * + * Last action on the pci control structure. + * + * call the remove sysfs informaton, which will unregister + * this control struct's kobj. When that kobj's ref count + * goes to zero, its release function will be call and then + * kfree() the memory. */ void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) { - kfree(pci); -} + debugf1("%s()\n", __func__); + edac_pci_remove_sysfs(pci); +} EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info); /* * find_edac_pci_by_dev() * scans the edac_pci list for a specific 'struct device *' + * + * return NULL if not found, or return control struct pointer */ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) { struct edac_pci_ctl_info *pci; struct list_head *item; - debugf3("%s()\n", __func__); + debugf1("%s()\n", __func__); list_for_each(item, &edac_pci_list) { pci = list_entry(item, struct edac_pci_ctl_info, link); @@ -118,10 +122,13 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) struct list_head *item, *insert_before; struct edac_pci_ctl_info *rover; + debugf1("%s()\n", __func__); + insert_before = &edac_pci_list; /* Determine if already on the list */ - if (unlikely((rover = find_edac_pci_by_dev(pci->dev)) != NULL)) + rover = find_edac_pci_by_dev(pci->dev); + if (unlikely(rover != NULL)) goto fail0; /* Insert in ascending order by 'pci_idx', so find position */ @@ -157,6 +164,8 @@ fail1: /* * complete_edac_pci_list_del + * + * RCU completion callback to indicate item is deleted */ static void complete_edac_pci_list_del(struct rcu_head *head) { @@ -169,6 +178,8 @@ static void complete_edac_pci_list_del(struct rcu_head *head) /* * del_edac_pci_from_global_list + * + * remove the PCI control struct from the global list */ static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) { @@ -207,35 +218,52 @@ struct edac_pci_ctl_info *edac_pci_find(int idx) return NULL; } - EXPORT_SYMBOL_GPL(edac_pci_find); /* * edac_pci_workq_function() - * performs the operation scheduled by a workq request + * + * periodic function that performs the operation + * scheduled by a workq request, for a given PCI control struct */ static void edac_pci_workq_function(struct work_struct *work_req) { struct delayed_work *d_work = (struct delayed_work *)work_req; struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); + int msec; + unsigned long delay; - edac_lock_pci_list(); + debugf3("%s() checking\n", __func__); - if ((pci->op_state == OP_RUNNING_POLL) && - (pci->edac_check != NULL) && (edac_pci_get_check_errors())) - pci->edac_check(pci); + mutex_lock(&edac_pci_ctls_mutex); - edac_unlock_pci_list(); + if (pci->op_state == OP_RUNNING_POLL) { + /* we might be in POLL mode, but there may NOT be a poll func + */ + if ((pci->edac_check != NULL) && edac_pci_get_check_errors()) + pci->edac_check(pci); + + /* if we are on a one second period, then use round */ + msec = edac_pci_get_poll_msec(); + if (msec == 1000) + delay = round_jiffies(msecs_to_jiffies(msec)); + else + delay = msecs_to_jiffies(msec); + + /* Reschedule only if we are in POLL mode */ + queue_delayed_work(edac_workqueue, &pci->work, delay); + } - /* Reschedule */ - queue_delayed_work(edac_workqueue, &pci->work, - msecs_to_jiffies(edac_pci_get_poll_msec())); + mutex_unlock(&edac_pci_ctls_mutex); } /* * edac_pci_workq_setup() * initialize a workq item for this edac_pci instance * passing in the new delay period in msec + * + * locking model: + * called when 'edac_pci_ctls_mutex' is locked */ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, unsigned int msec) @@ -255,6 +283,8 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { int status; + debugf0("%s()\n", __func__); + status = cancel_delayed_work(&pci->work); if (status == 0) flush_workqueue(edac_workqueue); @@ -262,19 +292,25 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) /* * edac_pci_reset_delay_period + * + * called with a new period value for the workq period + * a) stop current workq timer + * b) restart workq timer with new value */ void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value) { - edac_lock_pci_list(); + debugf0("%s()\n", __func__); edac_pci_workq_teardown(pci); + /* need to lock for the setup */ + mutex_lock(&edac_pci_ctls_mutex); + edac_pci_workq_setup(pci, value); - edac_unlock_pci_list(); + mutex_unlock(&edac_pci_ctls_mutex); } - EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); /* @@ -294,14 +330,13 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) debugf0("%s()\n", __func__); pci->pci_idx = edac_idx; + pci->start_time = jiffies; - edac_lock_pci_list(); + mutex_lock(&edac_pci_ctls_mutex); if (add_edac_pci_to_global_list(pci)) goto fail0; - pci->start_time = jiffies; - if (edac_pci_create_sysfs(pci)) { edac_pci_printk(pci, KERN_WARNING, "failed to create sysfs pci\n"); @@ -323,16 +358,16 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) pci->ctl_name, dev_name(pci), edac_op_state_to_string(pci->op_state)); - edac_unlock_pci_list(); + mutex_unlock(&edac_pci_ctls_mutex); return 0; + /* error unwind stack */ fail1: del_edac_pci_from_global_list(pci); fail0: - edac_unlock_pci_list(); + mutex_unlock(&edac_pci_ctls_mutex); return 1; } - EXPORT_SYMBOL_GPL(edac_pci_add_device); /* @@ -354,22 +389,25 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) debugf0("%s()\n", __func__); - edac_lock_pci_list(); + mutex_lock(&edac_pci_ctls_mutex); - if ((pci = find_edac_pci_by_dev(dev)) == NULL) { - edac_unlock_pci_list(); + /* ensure the control struct is on the global list + * if not, then leave + */ + pci = find_edac_pci_by_dev(dev); + if (pci == NULL) { + mutex_unlock(&edac_pci_ctls_mutex); return NULL; } pci->op_state = OP_OFFLINE; - edac_pci_workq_teardown(pci); - - edac_pci_remove_sysfs(pci); - del_edac_pci_from_global_list(pci); - edac_unlock_pci_list(); + mutex_unlock(&edac_pci_ctls_mutex); + + /* stop the workq timer */ + edac_pci_workq_teardown(pci); edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", @@ -377,14 +415,20 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) return pci; } - EXPORT_SYMBOL_GPL(edac_pci_del_device); +/* + * edac_pci_generic_check + * + * a Generic parity check API + */ void edac_pci_generic_check(struct edac_pci_ctl_info *pci) { + debugf4("%s()\n", __func__); edac_pci_do_parity_check(); } +/* free running instance index counter */ static int edac_pci_idx; #define EDAC_PCI_GENCTL_NAME "EDAC PCI controller" @@ -392,6 +436,17 @@ struct edac_pci_gen_data { int edac_idx; }; +/* + * edac_pci_create_generic_ctl + * + * A generic constructor for a PCI parity polling device + * Some systems have more than one domain of PCI busses. + * For systems with one domain, then this API will + * provide for a generic poller. + * + * This routine calls the edac_pci_alloc_ctl_info() for + * the generic device, with default values + */ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, const char *mod_name) { @@ -421,13 +476,18 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, return pci; } - EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); +/* + * edac_pci_release_generic_ctl + * + * The release function of a generic EDAC PCI polling device + */ void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) { + debugf0("%s() pci mod=%s\n", __func__, pci->mod_name); + edac_pci_del_device(pci->dev); edac_pci_free_ctl_info(pci); } - EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index fac94ca..69f5ddd 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -13,22 +13,25 @@ #include "edac_core.h" #include "edac_module.h" +/* Turn off this whole feature if PCI is not configured */ #ifdef CONFIG_PCI #define EDAC_PCI_SYMLINK "device" -static int check_pci_errors; /* default YES check PCI parity */ -static int edac_pci_panic_on_pe; /* default no panic on PCI Parity */ -static int edac_pci_log_pe = 1; /* log PCI parity errors */ +/* data variables exported via sysfs */ +static int check_pci_errors; /* default NO check PCI parity */ +static int edac_pci_panic_on_pe; /* default NO panic on PCI Parity */ +static int edac_pci_log_pe = 1; /* log PCI parity errors */ static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */ +static int edac_pci_poll_msec = 1000; /* one second workq period */ + static atomic_t pci_parity_count = ATOMIC_INIT(0); static atomic_t pci_nonparity_count = ATOMIC_INIT(0); -static int edac_pci_poll_msec = 1000; -static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */ -static struct completion edac_pci_kobj_complete; +static struct kobject edac_pci_top_main_kobj; static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); +/* getter functions for the data variables */ int edac_pci_get_check_errors(void) { return check_pci_errors; @@ -74,17 +77,22 @@ static void edac_pci_instance_release(struct kobject *kobj) { struct edac_pci_ctl_info *pci; - debugf1("%s()\n", __func__); + debugf0("%s()\n", __func__); + /* Form pointer to containing struct, the pci control struct */ pci = to_instance(kobj); - complete(&pci->kobj_complete); + + /* decrement reference count on top main kobj */ + kobject_put(&edac_pci_top_main_kobj); + + kfree(pci); /* Free the control struct */ } /* instance specific attribute structure */ struct instance_attribute { struct attribute attr; - ssize_t(*show) (struct edac_pci_ctl_info *, char *); - ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t); + ssize_t(*show) (struct edac_pci_ctl_info *, char *); + ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t); }; /* Function to 'show' fields from the edac_pci 'instance' structure */ @@ -112,6 +120,7 @@ static ssize_t edac_pci_instance_store(struct kobject *kobj, return -EIO; } +/* fs_ops table */ static struct sysfs_ops pci_instance_ops = { .show = edac_pci_instance_show, .store = edac_pci_instance_store @@ -134,48 +143,82 @@ static struct instance_attribute *pci_instance_attr[] = { NULL }; -/* the ktype for pci instance */ +/* the ktype for a pci instance */ static struct kobj_type ktype_pci_instance = { .release = edac_pci_instance_release, .sysfs_ops = &pci_instance_ops, .default_attrs = (struct attribute **)pci_instance_attr, }; +/* + * edac_pci_create_instance_kobj + * + * construct one EDAC PCI instance's kobject for use + */ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) { + struct kobject *main_kobj; int err; - pci->kobj.parent = &edac_pci_kobj; + debugf0("%s()\n", __func__); + + /* Set the parent and the instance's ktype */ + pci->kobj.parent = &edac_pci_top_main_kobj; pci->kobj.ktype = &ktype_pci_instance; err = kobject_set_name(&pci->kobj, "pci%d", idx); if (err) return err; + /* First bump the ref count on the top main kobj, which will + * track the number of PCI instances we have, and thus nest + * properly on keeping the module loaded + */ + main_kobj = kobject_get(&edac_pci_top_main_kobj); + if (!main_kobj) { + err = -ENODEV; + goto error_out; + } + + /* And now register this new kobject under the main kobj */ err = kobject_register(&pci->kobj); if (err != 0) { debugf2("%s() failed to register instance pci%d\n", __func__, idx); - return err; + kobject_put(&edac_pci_top_main_kobj); + goto error_out; } debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); return 0; + + /* Error unwind statck */ +error_out: + return err; } -static void -edac_pci_delete_instance_kobj(struct edac_pci_ctl_info *pci, int idx) +/* + * edac_pci_unregister_sysfs_instance_kobj + * + * unregister the kobj for the EDAC PCI instance + */ +void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci) { - init_completion(&pci->kobj_complete); + debugf0("%s()\n", __func__); + + /* Unregister the instance kobject and allow its release + * function release the main reference count and then + * kfree the memory + */ kobject_unregister(&pci->kobj); - wait_for_completion(&pci->kobj_complete); } /***************************** EDAC PCI sysfs root **********************/ #define to_edacpci(k) container_of(k, struct edac_pci_ctl_info, kobj) #define to_edacpci_attr(a) container_of(a, struct edac_pci_attr, attr) +/* simple show/store functions for attributes */ static ssize_t edac_pci_int_show(void *ptr, char *buffer) { int *value = ptr; @@ -267,118 +310,189 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { NULL, }; -/* No memory to release */ -static void edac_pci_release(struct kobject *kobj) +/* + * edac_pci_release_main_kobj + * + * This release function is called when the reference count to the + * passed kobj goes to zero. + * + * This kobj is the 'main' kobject that EDAC PCI instances + * link to, and thus provide for proper nesting counts + */ +static void edac_pci_release_main_kobj(struct kobject *kobj) { - struct edac_pci_ctl_info *pci; - pci = to_edacpci(kobj); + debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); - debugf1("%s()\n", __func__); - complete(&pci->kobj_complete); + /* last reference to top EDAC PCI kobject has been removed, + * NOW release our ref count on the core module + */ + module_put(THIS_MODULE); } -static struct kobj_type ktype_edac_pci = { - .release = edac_pci_release, +/* ktype struct for the EDAC PCI main kobj */ +static struct kobj_type ktype_edac_pci_main_kobj = { + .release = edac_pci_release_main_kobj, .sysfs_ops = &edac_pci_sysfs_ops, .default_attrs = (struct attribute **)edac_pci_attr, }; /** - * edac_sysfs_pci_setup() + * edac_pci_main_kobj_setup() * * setup the sysfs for EDAC PCI attributes * assumes edac_class has already been initialized */ -int edac_pci_register_main_kobj(void) +int edac_pci_main_kobj_setup(void) { int err; struct sysdev_class *edac_class; - debugf1("%s()\n", __func__); + debugf0("%s()\n", __func__); + + /* check and count if we have already created the main kobject */ + if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) + return 0; + /* First time, so create the main kobject and its + * controls and atributes + */ edac_class = edac_get_edac_class(); if (edac_class == NULL) { debugf1("%s() no edac_class\n", __func__); - return -ENODEV; + err = -ENODEV; + goto decrement_count_fail; } - edac_pci_kobj.ktype = &ktype_edac_pci; + /* Need the kobject hook ups, and name setting */ + edac_pci_top_main_kobj.ktype = &ktype_edac_pci_main_kobj; + edac_pci_top_main_kobj.parent = &edac_class->kset.kobj; - edac_pci_kobj.parent = &edac_class->kset.kobj; - - err = kobject_set_name(&edac_pci_kobj, "pci"); + err = kobject_set_name(&edac_pci_top_main_kobj, "pci"); if (err) - return err; + goto decrement_count_fail; + + /* Bump the reference count on this module to ensure the + * modules isn't unloaded until we deconstruct the top + * level main kobj for EDAC PCI + */ + if (!try_module_get(THIS_MODULE)) { + debugf1("%s() try_module_get() failed\n", __func__); + err = -ENODEV; + goto decrement_count_fail; + } /* Instanstiate the pci object */ /* FIXME: maybe new sysdev_create_subdir() */ - err = kobject_register(&edac_pci_kobj); - + err = kobject_register(&edac_pci_top_main_kobj); if (err) { debugf1("Failed to register '.../edac/pci'\n"); - return err; + goto kobject_register_fail; } + /* At this point, to 'release' the top level kobject + * for EDAC PCI, then edac_pci_main_kobj_teardown() + * must be used, for resources to be cleaned up properly + */ debugf1("Registered '.../edac/pci' kobject\n"); return 0; + + /* Error unwind statck */ +kobject_register_fail: + module_put(THIS_MODULE); + +decrement_count_fail: + /* if are on this error exit, nothing to tear down */ + atomic_dec(&edac_pci_sysfs_refcount); + + return err; } /* - * edac_pci_unregister_main_kobj() + * edac_pci_main_kobj_teardown() * - * perform the sysfs teardown for the PCI attributes + * if no longer linked (needed) remove the top level EDAC PCI + * kobject with its controls and attributes */ -void edac_pci_unregister_main_kobj(void) +static void edac_pci_main_kobj_teardown(void) { debugf0("%s()\n", __func__); - init_completion(&edac_pci_kobj_complete); - kobject_unregister(&edac_pci_kobj); - wait_for_completion(&edac_pci_kobj_complete); + + /* Decrement the count and only if no more controller instances + * are connected perform the unregisteration of the top level + * main kobj + */ + if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { + debugf0("%s() called kobject_unregister on main kobj\n", + __func__); + kobject_unregister(&edac_pci_top_main_kobj); + } } +/* + * + * edac_pci_create_sysfs + * + * Create the controls/attributes for the specified EDAC PCI device + */ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) { int err; struct kobject *edac_kobj = &pci->kobj; - if (atomic_inc_return(&edac_pci_sysfs_refcount) == 1) { - err = edac_pci_register_main_kobj(); - if (err) { - atomic_dec(&edac_pci_sysfs_refcount); - return err; - } - } + debugf0("%s() idx=%d\n", __func__, pci->pci_idx); - err = edac_pci_create_instance_kobj(pci, pci->pci_idx); - if (err) { - if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) - edac_pci_unregister_main_kobj(); - } + /* create the top main EDAC PCI kobject, IF needed */ + err = edac_pci_main_kobj_setup(); + if (err) + return err; - debugf0("%s() idx=%d\n", __func__, pci->pci_idx); + /* Create this instance's kobject under the MAIN kobject */ + err = edac_pci_create_instance_kobj(pci, pci->pci_idx); + if (err) + goto unregister_cleanup; err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) { debugf0("%s() sysfs_create_link() returned err= %d\n", __func__, err); - return err; + goto symlink_fail; } return 0; + + /* Error unwind stack */ +symlink_fail: + edac_pci_unregister_sysfs_instance_kobj(pci); + +unregister_cleanup: + edac_pci_main_kobj_teardown(); + + return err; } +/* + * edac_pci_remove_sysfs + * + * remove the controls and attributes for this EDAC PCI device + */ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) { - debugf0("%s()\n", __func__); - - edac_pci_delete_instance_kobj(pci, pci->pci_idx); + debugf0("%s() index=%d\n", __func__, pci->pci_idx); + /* Remove the symlink */ sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); - if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) - edac_pci_unregister_main_kobj(); + /* remove this PCI instance's sysfs entries */ + edac_pci_unregister_sysfs_instance_kobj(pci); + + /* Call the main unregister function, which will determine + * if this 'pci' is the last instance. + * If it is, the main kobject will be unregistered as a result + */ + debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__); + edac_pci_main_kobj_teardown(); } /************************ PCI error handling *************************/ @@ -414,13 +528,14 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) return status; } -typedef void (*pci_parity_check_fn_t) (struct pci_dev * dev); /* Clear any PCI parity errors logged by this device. */ static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; + debugf0("%s()\n", __func__); + get_pci_parity_status(dev, 0); /* read the device TYPE, looking for bridges */ @@ -433,17 +548,28 @@ static void edac_pci_dev_parity_clear(struct pci_dev *dev) /* * PCI Parity polling * + * Fucntion to retrieve the current parity status + * and decode it + * */ static void edac_pci_dev_parity_test(struct pci_dev *dev) { + unsigned long flags; u16 status; u8 header_type; - /* read the STATUS register on this device - */ + /* stop any interrupts until we can acquire the status */ + local_irq_save(flags); + + /* read the STATUS register on this device */ status = get_pci_parity_status(dev, 0); - debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); + /* read the device TYPE, looking for bridges */ + pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); + + local_irq_restore(flags); + + debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); /* check the status reg for errors */ if (status) { @@ -471,16 +597,14 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) } } - /* read the device TYPE, looking for bridges */ - pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); - debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id); + debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* On bridges, need to examine secondary status register */ status = get_pci_parity_status(dev, 1); - debugf2("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); + debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); /* check the secondary status reg for errors */ if (status) { @@ -510,9 +634,12 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) } } +/* reduce some complexity in definition of the iterator */ +typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); + /* * pci_dev parity list iterator - * Scan the PCI device list for one iteration, looking for SERRORs + * Scan the PCI device list for one pass, looking for SERRORs * Master Parity ERRORS or Parity ERRORs on primary or secondary devices */ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) @@ -535,22 +662,22 @@ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) */ void edac_pci_do_parity_check(void) { - unsigned long flags; int before_count; debugf3("%s()\n", __func__); + /* if policy has PCI check off, leave now */ if (!check_pci_errors) return; before_count = atomic_read(&pci_parity_count); /* scan all PCI devices looking for a Parity Error on devices and - * bridges + * bridges. + * The iterator calls pci_get_device() which might sleep, thus + * we cannot disable interrupts in this scan. */ - local_irq_save(flags); edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); - local_irq_restore(flags); /* Only if operator has selected panic on PCI Error */ if (edac_pci_get_panic_on_pe()) { @@ -560,6 +687,12 @@ void edac_pci_do_parity_check(void) } } +/* + * edac_pci_clear_parity_errors + * + * function to perform an iteration over the PCI devices + * and clearn their current status + */ void edac_pci_clear_parity_errors(void) { /* Clear any PCI bus parity errors that devices initially have logged @@ -567,6 +700,12 @@ void edac_pci_clear_parity_errors(void) */ edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); } + +/* + * edac_pci_handle_pe + * + * Called to handle a PARITY ERROR event + */ void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg) { @@ -584,9 +723,14 @@ void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg) */ edac_pci_do_parity_check(); } - EXPORT_SYMBOL_GPL(edac_pci_handle_pe); + +/* + * edac_pci_handle_npe + * + * Called to handle a NON-PARITY ERROR event + */ void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg) { @@ -604,7 +748,6 @@ void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg) */ edac_pci_do_parity_check(); } - EXPORT_SYMBOL_GPL(edac_pci_handle_npe); /* diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 0ecfdc4..e895f9f 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -275,7 +275,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) unsigned char *c0dra = dra, *c1dra = &dra[I3000_RANKS_PER_CHANNEL / 2]; unsigned char *c0drb = drb, *c1drb = &drb[I3000_RANKS_PER_CHANNEL]; unsigned long mchbar; - void *window; + void __iomem *window; debugf0("MC: %s()\n", __func__); diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index dbdca6f..192953b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -520,6 +520,16 @@ config SENSORS_SMSC47B397 This driver can also be built as a module. If so, the module will be called smsc47b397. +config SENSORS_THMC50 + tristate "Texas Instruments THMC50 / Analog Devices ADM1022" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for Texas Instruments THMC50 + sensor chips and clones: the Analog Devices ADM1022. + + This driver can also be built as a module. If so, the module + will be called thmc50. + config SENSORS_VIA686A tristate "VIA686A" depends on PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 59f81fa..d04f900 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o +obj-$(CONFIG_SENSORS_THMC50) += thmc50.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VT1211) += vt1211.o obj-$(CONFIG_SENSORS_VT8231) += vt8231.o diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index a003d10..cdd8b6d 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -691,8 +691,9 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, /* Sensor settings are stored 1 byte per offset with the bytes placed add consecutive offsets. */ -int abituguru3_read_increment_offset(struct abituguru3_data *data, u8 bank, - u8 offset, u8 count, u8 *buf, int offset_count) +static int abituguru3_read_increment_offset(struct abituguru3_data *data, + u8 bank, u8 offset, u8 count, + u8 *buf, int offset_count) { int i, x; diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index 6db9737..a112a03 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c @@ -23,7 +23,6 @@ #include <linux/types.h> #include <linux/errno.h> #include <linux/init.h> -#include <linux/module.h> #include <asm/pmac_pfunc.h> #include <asm/of_platform.h> diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index fd1281f..941729a 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -79,11 +79,15 @@ /* * Temperature sensors keys (sp78 - 2 bytes). - * First set for Macbook(Pro), second for Macmini. */ static const char* temperature_sensors_sets[][13] = { +/* Set 0: Macbook Pro */ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, +/* Set 1: Macbook set */ + { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S", + "Th1H", "Ts0P", NULL }, +/* Set 2: Macmini set */ { "TC0D", "TC0P", NULL } }; @@ -1150,10 +1154,10 @@ static void applesmc_release_accelerometer(void) static __initdata struct dmi_match_data applesmc_dmi_data[] = { /* MacBook Pro: accelerometer, backlight and temperature set 0 */ { .accelerometer = 1, .light = 1, .temperature_set = 0 }, -/* MacBook: accelerometer and temperature set 0 */ - { .accelerometer = 1, .light = 0, .temperature_set = 0 }, -/* MacBook: temperature set 1 */ - { .accelerometer = 0, .light = 0, .temperature_set = 1 } +/* MacBook: accelerometer and temperature set 1 */ + { .accelerometer = 1, .light = 0, .temperature_set = 1 }, +/* MacMini: temperature set 2 */ + { .accelerometer = 0, .light = 0, .temperature_set = 2 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index be3aaa5..e9cbc72 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -750,7 +750,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, res = (data->alarms >> DME1737_BIT_ALARM_TEMP[ix]) & 0x01; break; case SYS_TEMP_FAULT: - res = (data->temp[ix] == 0x0800); + res = (((u16)data->temp[ix] & 0xff00) == 0x8000); break; default: res = 0; diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index 1971775..b34b546 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -441,6 +441,8 @@ static struct fscher_data *fscher_update_device(struct device *dev) data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL); data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE); + data->global_control = fscher_read_value(client, + FSCHER_REG_CONTROL); data->last_updated = jiffies; data->valid = 1; @@ -599,7 +601,7 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; mutex_lock(&data->update_lock); - data->global_control &= ~v; + data->global_control = v; fscher_write_value(client, reg, v); mutex_unlock(&data->update_lock); return count; diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index eff6036..d75dba9 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -252,7 +252,7 @@ struct it87_data { static int it87_probe(struct platform_device *pdev); -static int it87_remove(struct platform_device *pdev); +static int __devexit it87_remove(struct platform_device *pdev); static int it87_read_value(struct it87_data *data, u8 reg); static void it87_write_value(struct it87_data *data, u8 reg, u8 value); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 9fb572f..565c4e6 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -864,7 +864,7 @@ static int __init lm78_isa_found(unsigned short address) /* Determine the chip type */ outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET); val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val == 0x00 /* LM78 */ + if (val == 0x00 || val == 0x20 /* LM78 */ || val == 0x40 /* LM78-J */ || (val & 0xfe) == 0xc0) /* LM79 */ found = 1; diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 48833ff..af541d6 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -585,7 +585,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) * those of the man_id register. */ if (chip_id == man_id - && (address == 0x4F || address == 0x4D) + && (address == 0x4C || address == 0x4D) && (reg_config1 & 0x1F) == (man_id & 0x0F) && reg_convrate <= 0x09) { kind = max6657; diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 23edf4f..d84f8bf 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -234,7 +234,7 @@ struct lm93_data { struct { u8 min; u8 max; - } temp_lim[3]; + } temp_lim[4]; /* vin1 - vin16: low and high limits */ struct { diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index cb72526c..f57c75d 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -220,7 +220,7 @@ struct pc87360_data { */ static int pc87360_probe(struct platform_device *pdev); -static int pc87360_remove(struct platform_device *pdev); +static int __devexit pc87360_remove(struct platform_device *pdev); static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, u8 reg); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 83321b2..92956eb 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -187,7 +187,7 @@ struct sis5595_data { static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ static int sis5595_probe(struct platform_device *pdev); -static int sis5595_remove(struct platform_device *pdev); +static int __devexit sis5595_remove(struct platform_device *pdev); static int sis5595_read_value(struct sis5595_data *data, u8 reg); static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value); diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 1de2f2b..338ee4f 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -134,7 +134,7 @@ struct smsc47m1_sio_data { static int smsc47m1_probe(struct platform_device *pdev); -static int smsc47m1_remove(struct platform_device *pdev); +static int __devexit smsc47m1_remove(struct platform_device *pdev); static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, int init); diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c new file mode 100644 index 0000000..9395b52 --- /dev/null +++ b/drivers/hwmon/thmc50.c @@ -0,0 +1,440 @@ +/* + thmc50.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> + Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and + Philip Edelbrock <phil@netroedge.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> + +MODULE_LICENSE("GPL"); + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_2(thmc50, adm1022); +I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs " + "to enable 3rd temperature (ADM1022 only)"); + +/* Many THMC50 constants specified below */ + +/* The THMC50 registers */ +#define THMC50_REG_CONF 0x40 +#define THMC50_REG_COMPANY_ID 0x3E +#define THMC50_REG_DIE_CODE 0x3F +#define THMC50_REG_ANALOG_OUT 0x19 + +const static u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; +const static u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; +const static u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; + +#define THMC50_REG_CONF_nFANOFF 0x20 + +/* Each client has this additional data */ +struct thmc50_data { + struct i2c_client client; + struct class_device *class_dev; + + struct mutex update_lock; + enum chips type; + unsigned long last_updated; /* In jiffies */ + char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ + char valid; /* !=0 if following fields are valid */ + + /* Register values */ + s8 temp_input[3]; + s8 temp_max[3]; + s8 temp_min[3]; + u8 analog_out; +}; + +static int thmc50_attach_adapter(struct i2c_adapter *adapter); +static int thmc50_detach_client(struct i2c_client *client); +static void thmc50_init_client(struct i2c_client *client); +static struct thmc50_data *thmc50_update_device(struct device *dev); + +static struct i2c_driver thmc50_driver = { + .driver = { + .name = "thmc50", + }, + .attach_adapter = thmc50_attach_adapter, + .detach_client = thmc50_detach_client, +}; + +static ssize_t show_analog_out(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct thmc50_data *data = thmc50_update_device(dev); + return sprintf(buf, "%d\n", data->analog_out); +} + +static ssize_t set_analog_out(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct thmc50_data *data = i2c_get_clientdata(client); + int tmp = simple_strtoul(buf, NULL, 10); + int config; + + mutex_lock(&data->update_lock); + data->analog_out = SENSORS_LIMIT(tmp, 0, 255); + i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, + data->analog_out); + + config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + if (data->analog_out == 0) + config &= ~THMC50_REG_CONF_nFANOFF; + else + config |= THMC50_REG_CONF_nFANOFF; + i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); + + mutex_unlock(&data->update_lock); + return count; +} + +/* There is only one PWM mode = DC */ +static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "0\n"); +} + +/* Temperatures */ +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct thmc50_data *data = thmc50_update_device(dev); + return sprintf(buf, "%d\n", data->temp_input[nr] * 1000); +} + +static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct thmc50_data *data = thmc50_update_device(dev); + return sprintf(buf, "%d\n", data->temp_min[nr] * 1000); +} + +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct thmc50_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->temp_min[nr] = SENSORS_LIMIT(val / 1000, -128, 127); + i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MIN[nr], + data->temp_min[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct thmc50_data *data = thmc50_update_device(dev); + return sprintf(buf, "%d\n", data->temp_max[nr] * 1000); +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct thmc50_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->temp_max[nr] = SENSORS_LIMIT(val / 1000, -128, 127); + i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MAX[nr], + data->temp_max[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +#define temp_reg(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ + NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, offset - 1); + +temp_reg(1); +temp_reg(2); +temp_reg(3); + +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_analog_out, + set_analog_out, 0); +static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); + +static struct attribute *thmc50_attributes[] = { + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + NULL +}; + +static const struct attribute_group thmc50_group = { + .attrs = thmc50_attributes, +}; + +/* for ADM1022 3rd temperature mode */ +static struct attribute *adm1022_attributes[] = { + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group adm1022_group = { + .attrs = adm1022_attributes, +}; + +static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) +{ + unsigned company; + unsigned revision; + unsigned config; + struct i2c_client *client; + struct thmc50_data *data; + struct device *dev; + int err = 0; + const char *type_name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + pr_debug("thmc50: detect failed, " + "smbus byte data not supported!\n"); + goto exit; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access thmc50 registers. */ + if (!(data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL))) { + pr_debug("thmc50: detect failed, kzalloc failed!\n"); + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &thmc50_driver; + dev = &client->dev; + + pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", + client->addr, i2c_adapter_id(client->adapter)); + + /* Now, we do the remaining detection. */ + company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID); + revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE); + config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + + if (kind == 0) + kind = thmc50; + else if (kind < 0) { + err = -ENODEV; + if (revision >= 0xc0 && ((config & 0x10) == 0)) { + if (company == 0x49) { + kind = thmc50; + err = 0; + } else if (company == 0x41) { + kind = adm1022; + err = 0; + } + } + } + if (err == -ENODEV) { + pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); + goto exit_free; + } + pr_debug("thmc50: Detected %s (version %x, revision %x)\n", + type_name, (revision >> 4) - 0xc, revision & 0xf); + data->type = kind; + + if (kind == thmc50) + type_name = "thmc50"; + else if (kind == adm1022) { + int id = i2c_adapter_id(client->adapter); + int i; + + type_name = "adm1022"; + data->has_temp3 = (config >> 7) & 1; /* config MSB */ + for (i = 0; i + 1 < adm1022_temp3_num; i += 2) + if (adm1022_temp3[i] == id && + adm1022_temp3[i + 1] == address) { + /* enable 2nd remote temp */ + data->has_temp3 = 1; + break; + } + } + + /* Fill in the remaining client fields & put it into the global list */ + strlcpy(client->name, type_name, I2C_NAME_SIZE); + mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + thmc50_init_client(client); + + /* Register sysfs hooks */ + if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group))) + goto exit_detach; + + /* Register ADM1022 sysfs hooks */ + if (data->type == adm1022) + if ((err = sysfs_create_group(&client->dev.kobj, + &adm1022_group))) + goto exit_remove_sysfs_thmc50; + + /* Register a new directory entry with module sensors */ + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_remove_sysfs; + } + + return 0; + +exit_remove_sysfs: + if (data->type == adm1022) + sysfs_remove_group(&client->dev.kobj, &adm1022_group); +exit_remove_sysfs_thmc50: + sysfs_remove_group(&client->dev.kobj, &thmc50_group); +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int thmc50_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, thmc50_detect); +} + +static int thmc50_detach_client(struct i2c_client *client) +{ + struct thmc50_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + sysfs_remove_group(&client->dev.kobj, &thmc50_group); + if (data->type == adm1022) + sysfs_remove_group(&client->dev.kobj, &adm1022_group); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + + return 0; +} + +static void thmc50_init_client(struct i2c_client *client) +{ + struct thmc50_data *data = i2c_get_clientdata(client); + int config; + + data->analog_out = i2c_smbus_read_byte_data(client, + THMC50_REG_ANALOG_OUT); + /* set up to at least 1 */ + if (data->analog_out == 0) { + data->analog_out = 1; + i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, + data->analog_out); + } + config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + config |= 0x1; /* start the chip if it is in standby mode */ + if (data->has_temp3) + config |= 0x80; /* enable 2nd remote temp */ + i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); +} + +static struct thmc50_data *thmc50_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct thmc50_data *data = i2c_get_clientdata(client); + int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + timeout) + || !data->valid) { + + int temps = data->has_temp3 ? 3 : 2; + int i; + for (i = 0; i < temps; i++) { + data->temp_input[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MIN[i]); + } + data->analog_out = + i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init sm_thmc50_init(void) +{ + return i2c_add_driver(&thmc50_driver); +} + +static void __exit sm_thmc50_exit(void) +{ + i2c_del_driver(&thmc50_driver); +} + +MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); +MODULE_DESCRIPTION("THMC50 driver"); + +module_init(sm_thmc50_init); +module_exit(sm_thmc50_exit); diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 24a6851..696c8a2 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -314,7 +314,7 @@ struct via686a_data { static struct pci_dev *s_bridge; /* pointer to the (only) via686a */ static int via686a_probe(struct platform_device *pdev); -static int via686a_remove(struct platform_device *pdev); +static int __devexit via686a_remove(struct platform_device *pdev); static inline int via686a_read_value(struct via686a_data *data, u8 reg) { diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index c604972..3e63eaf 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -167,7 +167,7 @@ struct vt8231_data { static struct pci_dev *s_bridge; static int vt8231_probe(struct platform_device *pdev); -static int vt8231_remove(struct platform_device *pdev); +static int __devexit vt8231_remove(struct platform_device *pdev); static struct vt8231_data *vt8231_update_device(struct device *dev); static void vt8231_init_device(struct vt8231_data *data); @@ -751,7 +751,7 @@ exit_release: return err; } -static int vt8231_remove(struct platform_device *pdev) +static int __devexit vt8231_remove(struct platform_device *pdev) { struct vt8231_data *data = platform_get_drvdata(pdev); int i; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 1ce7817..7a4a15f 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -387,7 +387,7 @@ struct w83627hf_sio_data { static int w83627hf_probe(struct platform_device *pdev); -static int w83627hf_remove(struct platform_device *pdev); +static int __devexit w83627hf_remove(struct platform_device *pdev); static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index da16478..1842f52 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -92,9 +92,9 @@ config I2C_AU1550 config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" - depends on BF534 || BF536 || BF537 + depends on BF534 || BF536 || BF537 || BF54x help - This is the TWI I2C device driver for Blackfin 534/536/537. + This is the TWI I2C device driver for Blackfin 534/536/537/54x. This driver can also be built as a module. If so, the module will be called i2c-bfin-twi. diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c index 5879f0f..9e94542 100644 --- a/drivers/i2c/chips/ds1682.c +++ b/drivers/i2c/chips/ds1682.c @@ -75,7 +75,8 @@ static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr, /* Special case: the 32 bit regs are time values with 1/4s * resolution, scale them up to milliseconds */ if (sattr->nr == 4) - return sprintf(buf, "%llu\n", ((u64) le32_to_cpu(val)) * 250); + return sprintf(buf, "%llu\n", + ((unsigned long long)le32_to_cpu(val)) * 250); /* Format the output string and return # of bytes */ return sprintf(buf, "%li\n", (long)le32_to_cpu(val)); diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 3c3f2eb..503ffec 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -352,7 +352,7 @@ static void tps65010_interrupt(struct tps65010 *tps) /* REVISIT: this might need its own workqueue * plus tweaks including deadlock avoidance ... * also needs to get error handling and probably - * an #ifdef CONFIG_SOFTWARE_SUSPEND + * an #ifdef CONFIG_HIBERNATION */ hibernate(); #endif diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b1a9b81..e049f65 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -833,7 +833,7 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ depends on BLK_DEV_IDE_AU1XXX config IDE_ARM - def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) + def_bool ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) config BLK_DEV_IDE_ICSIDE tristate "ICS IDE interface support" diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index a3d6744..bce2bec 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -1,5 +1,5 @@ /* - * ARM/ARM26 default IDE host driver + * ARM default IDE host driver * * Copyright (C) 2004 Bartlomiej Zolnierkiewicz * Based on code by: Russell King, Ian Molton and Alexander Schulz. @@ -14,12 +14,6 @@ #include <asm/mach-types.h> #include <asm/irq.h> -#ifdef CONFIG_ARM26 -# define IDE_ARM_HOST (machine_is_a5k()) -#else -# define IDE_ARM_HOST (1) -#endif - #ifdef CONFIG_ARCH_CLPS7500 # include <asm/arch/hardware.h> # @@ -32,12 +26,10 @@ void __init ide_arm_init(void) { - if (IDE_ARM_HOST) { - hw_regs_t hw; + hw_regs_t hw; - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); - hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, 1, NULL); - } + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); + hw.irq = IDE_ARM_IRQ; + ide_register_hw(&hw, 1, NULL); } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 1486eb2..ca84352 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3071,7 +3071,7 @@ static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } /* * standard prep_rq_fn that builds 10 byte cmds */ -static int ide_cdrom_prep_fs(request_queue_t *q, struct request *rq) +static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) { int hard_sect = queue_hardsect_size(q); long block = (long)rq->hard_sector / (hard_sect >> 9); @@ -3137,7 +3137,7 @@ static int ide_cdrom_prep_pc(struct request *rq) return BLKPREP_OK; } -static int ide_cdrom_prep_fn(request_queue_t *q, struct request *rq) +static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) { if (blk_fs_request(rq)) return ide_cdrom_prep_fs(q, rq); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index b1304a7..5ce4216 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -679,7 +679,7 @@ static ide_proc_entry_t idedisk_proc[] = { }; #endif /* CONFIG_IDE_PROC_FS */ -static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) +static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) { ide_drive_t *drive = q->queuedata; @@ -697,7 +697,7 @@ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) rq->buffer = rq->cmd; } -static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, +static int idedisk_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { ide_drive_t *drive = q->queuedata; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 484c50e..aa9f5f0 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1327,7 +1327,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) /* * Passes the stuff to ide_do_request */ -void do_ide_request(request_queue_t *q) +void do_ide_request(struct request_queue *q) { ide_drive_t *drive = q->queuedata; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5a4c5ea..3a2a9a3 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -945,7 +945,7 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) */ static int ide_init_queue(ide_drive_t *drive) { - request_queue_t *q; + struct request_queue *q; ide_hwif_t *hwif = HWIF(drive); int max_sectors = 256; int max_sg_entries = PRD_ENTRIES; diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 8f2db8d..8e05d88 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -652,7 +652,7 @@ repeat: } } -static void do_hd_request (request_queue_t * q) +static void do_hd_request (struct request_queue * q) { disable_irq(HD_IRQ); hd_request(); diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index f668d23..bf19ddf 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -551,8 +551,8 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) unsigned long dma_base = pci_resource_start(dev, 1); unsigned long ctl_size = pci_resource_len(dev, 0); unsigned long dma_size = pci_resource_len(dev, 1); - void *ctl_addr; - void *dma_addr; + void __iomem *ctl_addr; + void __iomem *dma_addr; int i; for (i = 0; i < MAX_HWIFS; i++) { diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 336e5ff..cadf047 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2677,7 +2677,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, struct raw1394_iso_packets32 __user *arg) { compat_uptr_t infos32; - void *infos; + void __user *infos; long err = -EFAULT; struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets)); diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c index 420c138..01d0786 100644 --- a/drivers/infiniband/hw/amso1100/c2_qp.c +++ b/drivers/infiniband/hw/amso1100/c2_qp.c @@ -506,6 +506,7 @@ int c2_alloc_qp(struct c2_dev *c2dev, qp->send_sgl_depth = qp_attrs->cap.max_send_sge; qp->rdma_write_sgl_depth = qp_attrs->cap.max_send_sge; qp->recv_sgl_depth = qp_attrs->cap.max_recv_sge; + init_waitqueue_head(&qp->wait); /* Initialize the SQ MQ */ q_size = be32_to_cpu(reply->sq_depth); diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 3725aa8..b5e9603 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -322,6 +322,7 @@ extern int ehca_static_rate; extern int ehca_port_act_time; extern int ehca_use_hp_mr; extern int ehca_scaling_code; +extern int ehca_mr_largepage; struct ipzu_queue_resp { u32 qe_size; /* queue entry size */ diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 71c0799..ee06d8b 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -116,7 +116,7 @@ static void print_error_data(struct ehca_shca *shca, void *data, } default: ehca_err(&shca->ib_device, - "Unknown errror type: %lx on %s.", + "Unknown error type: %lx on %s.", type, shca->ib_device.name); break; } diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c index c1b868b..d97eda3 100644 --- a/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -40,10 +40,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <rdma/ib_umem.h> - #include <asm/current.h> +#include <rdma/ib_umem.h> + #include "ehca_iverbs.h" #include "ehca_mrmw.h" #include "hcp_if.h" @@ -64,8 +64,6 @@ enum ehca_mr_pgsize { EHCA_MR_PGSIZE16M = 0x1000000L }; -extern int ehca_mr_largepage; - static u32 ehca_encode_hwpage_size(u32 pgsize) { u32 idx = 0; diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c index 3dafd7f..43bcf08 100644 --- a/drivers/infiniband/hw/ehca/ehca_pd.c +++ b/drivers/infiniband/hw/ehca/ehca_pd.c @@ -88,7 +88,6 @@ int ehca_dealloc_pd(struct ib_pd *pd) u32 cur_pid = current->tgid; struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); int i, leftovers = 0; - extern struct kmem_cache *small_qp_cache; struct ipz_small_queue_page *page, *tmp; if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c index fdbfebe..24f4541 100644 --- a/drivers/infiniband/hw/ehca/hcp_if.c +++ b/drivers/infiniband/hw/ehca/hcp_if.c @@ -758,7 +758,6 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, const u64 logical_address_of_page, const u64 count) { - extern int ehca_debug_level; u64 ret; if (unlikely(ehca_debug_level >= 2)) { diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h index c6937a0..a801274 100644 --- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h +++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h @@ -54,6 +54,8 @@ struct ehca_pd; struct ipz_small_queue_page; +extern struct kmem_cache *small_qp_cache; + /* struct generic ehca page */ struct ipz_page { u8 entries[EHCA_PAGESIZE]; diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h index b4b786d..6ad822c 100644 --- a/drivers/infiniband/hw/ipath/ipath_common.h +++ b/drivers/infiniband/hw/ipath/ipath_common.h @@ -100,8 +100,7 @@ struct infinipath_stats { __u64 sps_hwerrs; /* number of times IB link changed state unexpectedly */ __u64 sps_iblink; - /* kernel receive interrupts that didn't read intstat */ - __u64 sps_fastrcvint; + __u64 sps_unused; /* was fastrcvint, no longer implemented */ /* number of kernel (port0) packets received */ __u64 sps_port0pkts; /* number of "ethernet" packets sent by driver */ diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index a698f19..cf25cda 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c @@ -44,6 +44,7 @@ #include <linux/io.h> #include <linux/pci.h> #include <linux/vmalloc.h> +#include <linux/fs.h> #include <asm/uaccess.h> #include "ipath_kernel.h" diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 09c5fd8..6ccba36 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -740,7 +740,7 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, * pioavail updates to memory to stop. */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - sendorig & ~IPATH_S_PIOBUFAVAILUPD); + sendorig & ~INFINIPATH_S_PIOBUFAVAILUPD); sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); @@ -1614,7 +1614,7 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd) * it's safer to always do it. * PIOAvail bits are updated by the chip as if normal send had happened. */ -void ipath_cancel_sends(struct ipath_devdata *dd) +void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl) { ipath_dbg("Cancelling all in-progress send buffers\n"); dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */ @@ -1627,6 +1627,9 @@ void ipath_cancel_sends(struct ipath_devdata *dd) ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); ipath_disarm_piobufs(dd, 0, (unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k)); + if (restore_sendctrl) /* else done by caller later */ + ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, + dd->ipath_sendctrl); /* and again, be sure all have hit the chip */ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); @@ -1655,7 +1658,7 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) /* flush all queued sends when going to DOWN or INIT, to be sure that * they don't block MAD packets */ if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) - ipath_cancel_sends(dd); + ipath_cancel_sends(dd, 1); ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, dd->ipath_ibcctrl | which); @@ -2000,7 +2003,7 @@ void ipath_shutdown_device(struct ipath_devdata *dd) ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE << INFINIPATH_IBCC_LINKINITCMD_SHIFT); - ipath_cancel_sends(dd); + ipath_cancel_sends(dd, 0); /* disable IBC */ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index 9868ccd..5b6ac9a 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c @@ -321,6 +321,8 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = { << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) static int ipath_pe_txe_recover(struct ipath_devdata *); +static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *, + u32, unsigned long); /** * ipath_pe_handle_hwerrors - display hardware errors. @@ -555,8 +557,11 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name, ipath_dev_err(dd, "Unsupported InfiniPath hardware revision %u.%u!\n", dd->ipath_majrev, dd->ipath_minrev); ret = 1; - } else + } else { ret = 0; + if (dd->ipath_minrev >= 2) + dd->ipath_f_put_tid = ipath_pe_put_tid_2; + } return ret; } @@ -1220,7 +1225,7 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port) port * dd->ipath_rcvtidcnt * sizeof(*tidbase)); for (i = 0; i < dd->ipath_rcvtidcnt; i++) - ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED, + dd->ipath_f_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED, tidinv); tidbase = (u64 __iomem *) @@ -1229,7 +1234,7 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port) port * dd->ipath_rcvegrcnt * sizeof(*tidbase)); for (i = 0; i < dd->ipath_rcvegrcnt; i++) - ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER, + dd->ipath_f_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER, tidinv); } @@ -1395,10 +1400,11 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd) dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes; dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes; dd->ipath_f_clear_tids = ipath_pe_clear_tids; - if (dd->ipath_minrev >= 2) - dd->ipath_f_put_tid = ipath_pe_put_tid_2; - else - dd->ipath_f_put_tid = ipath_pe_put_tid; + /* + * this may get changed after we read the chip revision, + * but we start with the safe version for all revs + */ + dd->ipath_f_put_tid = ipath_pe_put_tid; dd->ipath_f_cleanup = ipath_setup_pe_cleanup; dd->ipath_f_setextled = ipath_setup_pe_setextled; dd->ipath_f_get_base_info = ipath_pe_get_base_info; diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 49951d5..9dd0bac 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c @@ -782,7 +782,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) * Follows early_init because some chips have to initialize * PIO buffers in early_init to avoid false parity errors. */ - ipath_cancel_sends(dd); + ipath_cancel_sends(dd, 0); /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be * done after early_init */ @@ -851,13 +851,14 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, dd->ipath_hwerrmask); - dd->ipath_maskederrs = dd->ipath_ignorederrs; /* clear all */ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL); /* enable errors that are masked, at least this first time. */ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, ~dd->ipath_maskederrs); - /* clear any interrups up to this point (ints still not enabled) */ + dd->ipath_errormask = ipath_read_kreg64(dd, + dd->ipath_kregs->kr_errormask); + /* clear any interrupts up to this point (ints still not enabled) */ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); /* diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 1fd91c5..b29fe7e 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c @@ -303,7 +303,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, * Flush all queued sends when link went to DOWN or INIT, * to be sure that they don't block SMA and other MAD packets */ - ipath_cancel_sends(dd); + ipath_cancel_sends(dd, 1); } else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || lstate == IPATH_IBSTATE_ACTIVE) { @@ -517,10 +517,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint); - /* - * don't report errors that are masked (includes those always - * ignored) - */ + /* don't report errors that are masked */ errs &= ~dd->ipath_maskederrs; /* do these first, they are most important */ @@ -566,19 +563,19 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) * ones on this particular interrupt, which also isn't great */ dd->ipath_maskederrs |= dd->ipath_lasterror | errs; + dd->ipath_errormask &= ~dd->ipath_maskederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - ~dd->ipath_maskederrs); + dd->ipath_errormask); s_iserr = ipath_decode_err(msg, sizeof msg, - (dd->ipath_maskederrs & ~dd-> - ipath_ignorederrs)); + dd->ipath_maskederrs); - if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & + if (dd->ipath_maskederrs & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS)) ipath_dev_err(dd, "Temporarily disabling " "error(s) %llx reporting; too frequent (%s)\n", - (unsigned long long) (dd->ipath_maskederrs & - ~dd->ipath_ignorederrs), msg); + (unsigned long long)dd->ipath_maskederrs, + msg); else { /* * rcvegrfull and rcvhdrqfull are "normal", @@ -793,19 +790,22 @@ void ipath_clear_freeze(struct ipath_devdata *dd) /* disable error interrupts, to avoid confusion */ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL); + /* also disable interrupts; errormask is sometimes overwriten */ + ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL); + /* * clear all sends, because they have may been * completed by usercode while in freeze mode, and * therefore would not be sent, and eventually * might cause the process to run out of bufs */ - ipath_cancel_sends(dd); + ipath_cancel_sends(dd, 0); ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control); /* ensure pio avail updates continue */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl & ~IPATH_S_PIOBUFAVAILUPD); + dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD); ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl); @@ -817,7 +817,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd) for (i = 0; i < dd->ipath_pioavregs; i++) { /* deal with 6110 chip bug */ im = i > 3 ? ((i&1) ? i-1 : i+1) : i; - val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64))); + val = ipath_read_kreg64(dd, (0x1000/sizeof(u64))+im); dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i] = le64_to_cpu(val); } @@ -832,7 +832,8 @@ void ipath_clear_freeze(struct ipath_devdata *dd) ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, E_SPKT_ERRS_IGNORE); ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - ~dd->ipath_maskederrs); + dd->ipath_errormask); + ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, -1LL); ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); } @@ -1002,7 +1003,6 @@ irqreturn_t ipath_intr(int irq, void *data) u32 istat, chk0rcv = 0; ipath_err_t estat = 0; irqreturn_t ret; - u32 oldhead, curtail; static unsigned unexpected = 0; static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) | (1U<<INFINIPATH_I_RCVURG_SHIFT); @@ -1035,36 +1035,6 @@ irqreturn_t ipath_intr(int irq, void *data) goto bail; } - /* - * We try to avoid reading the interrupt status register, since - * that's a PIO read, and stalls the processor for up to about - * ~0.25 usec. The idea is that if we processed a port0 packet, - * we blindly clear the port 0 receive interrupt bits, and nothing - * else, then return. If other interrupts are pending, the chip - * will re-interrupt us as soon as we write the intclear register. - * We then won't process any more kernel packets (if not the 2nd - * time, then the 3rd or 4th) and we'll then handle the other - * interrupts. We clear the interrupts first so that we don't - * lose intr for later packets that arrive while we are processing. - */ - oldhead = dd->ipath_port0head; - curtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr); - if (oldhead != curtail) { - if (dd->ipath_flags & IPATH_GPIO_INTR) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear, - (u64) (1 << IPATH_GPIO_PORT0_BIT)); - istat = port0rbits | INFINIPATH_I_GPIO; - } - else - istat = port0rbits; - ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat); - ipath_kreceive(dd); - if (oldhead != dd->ipath_port0head) { - ipath_stats.sps_fastrcvint++; - goto done; - } - } - istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus); if (unlikely(!istat)) { @@ -1225,7 +1195,6 @@ irqreturn_t ipath_intr(int irq, void *data) handle_layer_pioavail(dd); } -done: ret = IRQ_HANDLED; bail: diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index ace63ef..7a7966f 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -261,18 +261,10 @@ struct ipath_devdata { * limiting of hwerror reporting */ ipath_err_t ipath_lasthwerror; - /* - * errors masked because they occur too fast, also includes errors - * that are always ignored (ipath_ignorederrs) - */ + /* errors masked because they occur too fast */ ipath_err_t ipath_maskederrs; /* time in jiffies at which to re-enable maskederrs */ unsigned long ipath_unmasktime; - /* - * errors always ignored (masked), at least for a given - * chip/device, because they are wrong or not useful - */ - ipath_err_t ipath_ignorederrs; /* count of egrfull errors, combined for all ports */ u64 ipath_last_tidfull; /* for ipath_qcheck() */ @@ -436,6 +428,7 @@ struct ipath_devdata { u64 ipath_lastibcstat; /* hwerrmask shadow */ ipath_err_t ipath_hwerrmask; + ipath_err_t ipath_errormask; /* errormask shadow */ /* interrupt config reg shadow */ u64 ipath_intconfig; /* kr_sendpiobufbase value */ @@ -683,7 +676,7 @@ int ipath_unordered_wc(void); void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first, unsigned cnt); -void ipath_cancel_sends(struct ipath_devdata *); +void ipath_cancel_sends(struct ipath_devdata *, int); int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *); void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *); diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c index 73ed17d..bae4f56 100644 --- a/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/drivers/infiniband/hw/ipath/ipath_stats.c @@ -196,6 +196,45 @@ static void ipath_qcheck(struct ipath_devdata *dd) } } +static void ipath_chk_errormask(struct ipath_devdata *dd) +{ + static u32 fixed; + u32 ctrl; + unsigned long errormask; + unsigned long hwerrs; + + if (!dd->ipath_errormask || !(dd->ipath_flags & IPATH_INITTED)) + return; + + errormask = ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask); + + if (errormask == dd->ipath_errormask) + return; + fixed++; + + hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus); + ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); + + ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, + dd->ipath_errormask); + + if ((hwerrs & dd->ipath_hwerrmask) || + (ctrl & INFINIPATH_C_FREEZEMODE)) { + /* force re-interrupt of pending events, just in case */ + ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL); + ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, 0ULL); + ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); + dev_info(&dd->pcidev->dev, + "errormask fixed(%u) %lx -> %lx, ctrl %x hwerr %lx\n", + fixed, errormask, (unsigned long)dd->ipath_errormask, + ctrl, hwerrs); + } else + ipath_dbg("errormask fixed(%u) %lx -> %lx, no freeze\n", + fixed, errormask, + (unsigned long)dd->ipath_errormask); +} + + /** * ipath_get_faststats - get word counters from chip before they overflow * @opaque - contains a pointer to the infinipath device ipath_devdata @@ -251,14 +290,13 @@ void ipath_get_faststats(unsigned long opaque) dd->ipath_lasterror = 0; if (dd->ipath_lasthwerror) dd->ipath_lasthwerror = 0; - if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) + if (dd->ipath_maskederrs && time_after(jiffies, dd->ipath_unmasktime)) { char ebuf[256]; int iserr; iserr = ipath_decode_err(ebuf, sizeof ebuf, - (dd->ipath_maskederrs & ~dd-> - ipath_ignorederrs)); - if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & + dd->ipath_maskederrs); + if (dd->ipath_maskederrs & ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS )) ipath_dev_err(dd, "Re-enabling masked errors " @@ -278,9 +316,12 @@ void ipath_get_faststats(unsigned long opaque) ipath_cdbg(ERRPKT, "Re-enabling packet" " problem interrupt (%s)\n", ebuf); } - dd->ipath_maskederrs = dd->ipath_ignorederrs; + + /* re-enable masked errors */ + dd->ipath_errormask |= dd->ipath_maskederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, - ~dd->ipath_maskederrs); + dd->ipath_errormask); + dd->ipath_maskederrs = 0; } /* limit qfull messages to ~one per minute per port */ @@ -294,6 +335,7 @@ void ipath_get_faststats(unsigned long opaque) } } + ipath_chk_errormask(dd); done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); } diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index f6315df..ba0428d 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1209,7 +1209,6 @@ static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg, memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn); dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey); - } static void set_data_seg(struct mlx4_wqe_data_seg *dseg, diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 5db3143..bad8dac 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -548,6 +548,7 @@ iscsi_iser_ep_disconnect(__u64 ep_handle) } static struct scsi_host_template iscsi_iser_sht = { + .module = THIS_MODULE, .name = "iSCSI Initiator over iSER, v." DRV_VER, .queuecommand = iscsi_queuecommand, .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ab4b2d9..f1c3d6c 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -186,7 +186,7 @@ struct input_event_compat { #elif defined(CONFIG_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) #elif defined(CONFIG_MIPS) -# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR) +# define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR) #else # define COMPAT_TEST test_thread_flag(TIF_32BIT) #endif diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 0acc3a1..e43e92f 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -31,7 +31,6 @@ #define ACPI_ATLAS_NAME "Atlas ACPI" #define ACPI_ATLAS_CLASS "Atlas" -#define ACPI_ATLAS_BUTTON_HID "ASIM0000" static struct input_dev *input_dev; @@ -130,10 +129,16 @@ static int atlas_acpi_button_remove(struct acpi_device *device, int type) return status; } +static const struct acpi_device_id atlas_device_ids[] = { + {"ASIM0000", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, atlas_device_ids); + static struct acpi_driver atlas_acpi_driver = { .name = ACPI_ATLAS_NAME, .class = ACPI_ATLAS_CLASS, - .ids = ACPI_ATLAS_BUTTON_HID, + .ids = atlas_device_ids, .ops = { .add = atlas_acpi_button_add, .remove = atlas_acpi_button_remove, diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index adef447..5ce632c 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -21,7 +21,7 @@ if SERIO config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y - depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K + depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BFIN ---help--- i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index be77ee6..559a0d0 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -70,6 +70,8 @@ put_info_buffer(char *cp) wake_up_interruptible(&(rd_queue)); } /* put_info_buffer */ +#ifdef CONFIG_PROC_FS + /**********************************/ /* deflection device read routine */ /**********************************/ @@ -253,8 +255,6 @@ isdn_divert_ioctl(struct inode *inode, struct file *file, return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; } /* isdn_divert_ioctl */ - -#ifdef CONFIG_PROC_FS static const struct file_operations isdn_fops = { .owner = THIS_MODULE, diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index bcbe683..9685609 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -297,9 +297,6 @@ static struct kvm *kvm_create_vm(void) kvm_io_bus_init(&kvm->pio_bus); spin_lock_init(&kvm->lock); INIT_LIST_HEAD(&kvm->active_mmu_pages); - spin_lock(&kvm_lock); - list_add(&kvm->vm_list, &vm_list); - spin_unlock(&kvm_lock); kvm_io_bus_init(&kvm->mmio_bus); for (i = 0; i < KVM_MAX_VCPUS; ++i) { struct kvm_vcpu *vcpu = &kvm->vcpus[i]; @@ -309,6 +306,9 @@ static struct kvm *kvm_create_vm(void) vcpu->kvm = kvm; vcpu->mmu.root_hpa = INVALID_PAGE; } + spin_lock(&kvm_lock); + list_add(&kvm->vm_list, &vm_list); + spin_unlock(&kvm_lock); return kvm; } @@ -1070,18 +1070,16 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, return 0; mark_page_dirty(vcpu->kvm, gpa >> PAGE_SHIFT); virt = kmap_atomic(page, KM_USER0); - if (memcmp(virt + offset_in_page(gpa), val, bytes)) { - kvm_mmu_pte_write(vcpu, gpa, virt + offset, val, bytes); - memcpy(virt + offset_in_page(gpa), val, bytes); - } + kvm_mmu_pte_write(vcpu, gpa, virt + offset, val, bytes); + memcpy(virt + offset_in_page(gpa), val, bytes); kunmap_atomic(virt, KM_USER0); return 1; } -static int emulator_write_emulated(unsigned long addr, - const void *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) +static int emulator_write_emulated_onepage(unsigned long addr, + const void *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) { struct kvm_vcpu *vcpu = ctxt->vcpu; struct kvm_io_device *mmio_dev; @@ -1113,6 +1111,26 @@ static int emulator_write_emulated(unsigned long addr, return X86EMUL_CONTINUE; } +static int emulator_write_emulated(unsigned long addr, + const void *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + /* Crossing a page boundary? */ + if (((addr + bytes - 1) ^ addr) & PAGE_MASK) { + int rc, now; + + now = -addr & ~PAGE_MASK; + rc = emulator_write_emulated_onepage(addr, val, now, ctxt); + if (rc != X86EMUL_CONTINUE) + return rc; + addr += now; + val += now; + bytes -= now; + } + return emulator_write_emulated_onepage(addr, val, bytes, ctxt); +} + static int emulator_cmpxchg_emulated(unsigned long addr, const void *old, const void *new, @@ -2414,9 +2432,9 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu) break; } } - if (entry && (entry->edx & EFER_NX) && !(efer & EFER_NX)) { + if (entry && (entry->edx & (1 << 20)) && !(efer & EFER_NX)) { entry->edx &= ~(1 << 20); - printk(KERN_INFO ": guest NX capability removed\n"); + printk(KERN_INFO "kvm: guest NX capability removed\n"); } } diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 1b800fc..1f979cb 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -1178,6 +1178,8 @@ pop_instruction: twobyte_insn: switch (b) { case 0x01: /* lgdt, lidt, lmsw */ + /* Disable writeback. */ + no_wb = 1; switch (modrm_reg) { u16 size; unsigned long address; diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig index 43d901f..888205c 100644 --- a/drivers/lguest/Kconfig +++ b/drivers/lguest/Kconfig @@ -1,6 +1,6 @@ config LGUEST tristate "Linux hypervisor example code" - depends on X86 && PARAVIRT && NET && EXPERIMENTAL && !X86_PAE + depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE select LGUEST_GUEST select HVC_DRIVER ---help--- @@ -18,3 +18,11 @@ config LGUEST_GUEST The guest needs code built-in, even if the host has lguest support as a module. The drivers are tiny, so we build them in too. + +config LGUEST_NET + tristate + depends on LGUEST_GUEST && NET + +config LGUEST_BLOCK + tristate + depends on LGUEST_GUEST && BLOCK diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile index 55382c7..e504747 100644 --- a/drivers/lguest/Makefile +++ b/drivers/lguest/Makefile @@ -5,3 +5,15 @@ obj-$(CONFIG_LGUEST_GUEST) += lguest.o lguest_asm.o lguest_bus.o obj-$(CONFIG_LGUEST) += lg.o lg-y := core.o hypercalls.o page_tables.o interrupts_and_traps.o \ segments.o io.o lguest_user.o switcher.o + +Preparation Preparation!: PREFIX=P +Guest: PREFIX=G +Drivers: PREFIX=D +Launcher: PREFIX=L +Host: PREFIX=H +Switcher: PREFIX=S +Mastery: PREFIX=M +Beer: + @for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}" +Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery: + @sh ../../Documentation/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'` diff --git a/drivers/lguest/README b/drivers/lguest/README new file mode 100644 index 0000000..b7db39a --- /dev/null +++ b/drivers/lguest/README @@ -0,0 +1,47 @@ +Welcome, friend reader, to lguest. + +Lguest is an adventure, with you, the reader, as Hero. I can't think of many +5000-line projects which offer both such capability and glimpses of future +potential; it is an exciting time to be delving into the source! + +But be warned; this is an arduous journey of several hours or more! And as we +know, all true Heroes are driven by a Noble Goal. Thus I offer a Beer (or +equivalent) to anyone I meet who has completed this documentation. + +So get comfortable and keep your wits about you (both quick and humorous). +Along your way to the Noble Goal, you will also gain masterly insight into +lguest, and hypervisors and x86 virtualization in general. + +Our Quest is in seven parts: (best read with C highlighting turned on) + +I) Preparation + - In which our potential hero is flown quickly over the landscape for a + taste of its scope. Suitable for the armchair coders and other such + persons of faint constitution. + +II) Guest + - Where we encounter the first tantalising wisps of code, and come to + understand the details of the life of a Guest kernel. + +III) Drivers + - Whereby the Guest finds its voice and become useful, and our + understanding of the Guest is completed. + +IV) Launcher + - Where we trace back to the creation of the Guest, and thus begin our + understanding of the Host. + +V) Host + - Where we master the Host code, through a long and tortuous journey. + Indeed, it is here that our hero is tested in the Bit of Despair. + +VI) Switcher + - Where our understanding of the intertwined nature of Guests and Hosts + is completed. + +VII) Mastery + - Where our fully fledged hero grapples with the Great Question: + "What next?" + +make Preparation! +Rusty Russell. diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index ce909ec..0a46e88 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -1,5 +1,8 @@ -/* World's simplest hypervisor, to test paravirt_ops and show - * unbelievers that virtualization is the future. Plus, it's fun! */ +/*P:400 This contains run_guest() which actually calls into the Host<->Guest + * Switcher and analyzes the return, such as determining if the Guest wants the + * Host to do something. This file also contains useful helper routines, and a + * couple of non-obvious setup and teardown pieces which were implemented after + * days of debugging pain. :*/ #include <linux/module.h> #include <linux/stringify.h> #include <linux/stddef.h> @@ -61,11 +64,33 @@ static struct lguest_pages *lguest_pages(unsigned int cpu) (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]); } +/*H:010 We need to set up the Switcher at a high virtual address. Remember the + * Switcher is a few hundred bytes of assembler code which actually changes the + * CPU to run the Guest, and then changes back to the Host when a trap or + * interrupt happens. + * + * The Switcher code must be at the same virtual address in the Guest as the + * Host since it will be running as the switchover occurs. + * + * Trying to map memory at a particular address is an unusual thing to do, so + * it's not a simple one-liner. We also set up the per-cpu parts of the + * Switcher here. + */ static __init int map_switcher(void) { int i, err; struct page **pagep; + /* + * Map the Switcher in to high memory. + * + * It turns out that if we choose the address 0xFFC00000 (4MB under the + * top virtual address), it makes setting up the page tables really + * easy. + */ + + /* We allocate an array of "struct page"s. map_vm_area() wants the + * pages in this form, rather than just an array of pointers. */ switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES, GFP_KERNEL); if (!switcher_page) { @@ -73,6 +98,8 @@ static __init int map_switcher(void) goto out; } + /* Now we actually allocate the pages. The Guest will see these pages, + * so we make sure they're zeroed. */ for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) { unsigned long addr = get_zeroed_page(GFP_KERNEL); if (!addr) { @@ -82,6 +109,9 @@ static __init int map_switcher(void) switcher_page[i] = virt_to_page(addr); } + /* Now we reserve the "virtual memory area" we want: 0xFFC00000 + * (SWITCHER_ADDR). We might not get it in theory, but in practice + * it's worked so far. */ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, VM_ALLOC, SWITCHER_ADDR, VMALLOC_END); if (!switcher_vma) { @@ -90,49 +120,105 @@ static __init int map_switcher(void) goto free_pages; } + /* This code actually sets up the pages we've allocated to appear at + * SWITCHER_ADDR. map_vm_area() takes the vma we allocated above, the + * kind of pages we're mapping (kernel pages), and a pointer to our + * array of struct pages. It increments that pointer, but we don't + * care. */ pagep = switcher_page; err = map_vm_area(switcher_vma, PAGE_KERNEL, &pagep); if (err) { printk("lguest: map_vm_area failed: %i\n", err); goto free_vma; } + + /* Now the switcher is mapped at the right address, we can't fail! + * Copy in the compiled-in Switcher code (from switcher.S). */ memcpy(switcher_vma->addr, start_switcher_text, end_switcher_text - start_switcher_text); - /* Fix up IDT entries to point into copied text. */ + /* Most of the switcher.S doesn't care that it's been moved; on Intel, + * jumps are relative, and it doesn't access any references to external + * code or data. + * + * The only exception is the interrupt handlers in switcher.S: their + * addresses are placed in a table (default_idt_entries), so we need to + * update the table with the new addresses. switcher_offset() is a + * convenience function which returns the distance between the builtin + * switcher code and the high-mapped copy we just made. */ for (i = 0; i < IDT_ENTRIES; i++) default_idt_entries[i] += switcher_offset(); + /* + * Set up the Switcher's per-cpu areas. + * + * Each CPU gets two pages of its own within the high-mapped region + * (aka. "struct lguest_pages"). Much of this can be initialized now, + * but some depends on what Guest we are running (which is set up in + * copy_in_guest_info()). + */ for_each_possible_cpu(i) { + /* lguest_pages() returns this CPU's two pages. */ struct lguest_pages *pages = lguest_pages(i); + /* This is a convenience pointer to make the code fit one + * statement to a line. */ struct lguest_ro_state *state = &pages->state; - /* These fields are static: rest done in copy_in_guest_info */ + /* The Global Descriptor Table: the Host has a different one + * for each CPU. We keep a descriptor for the GDT which says + * where it is and how big it is (the size is actually the last + * byte, not the size, hence the "-1"). */ state->host_gdt_desc.size = GDT_SIZE-1; state->host_gdt_desc.address = (long)get_cpu_gdt_table(i); + + /* All CPUs on the Host use the same Interrupt Descriptor + * Table, so we just use store_idt(), which gets this CPU's IDT + * descriptor. */ store_idt(&state->host_idt_desc); + + /* The descriptors for the Guest's GDT and IDT can be filled + * out now, too. We copy the GDT & IDT into ->guest_gdt and + * ->guest_idt before actually running the Guest. */ state->guest_idt_desc.size = sizeof(state->guest_idt)-1; state->guest_idt_desc.address = (long)&state->guest_idt; state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1; state->guest_gdt_desc.address = (long)&state->guest_gdt; + + /* We know where we want the stack to be when the Guest enters + * the switcher: in pages->regs. The stack grows upwards, so + * we start it at the end of that structure. */ state->guest_tss.esp0 = (long)(&pages->regs + 1); + /* And this is the GDT entry to use for the stack: we keep a + * couple of special LGUEST entries. */ state->guest_tss.ss0 = LGUEST_DS; - /* No I/O for you! */ + + /* x86 can have a finegrained bitmap which indicates what I/O + * ports the process can use. We set it to the end of our + * structure, meaning "none". */ state->guest_tss.io_bitmap_base = sizeof(state->guest_tss); + + /* Some GDT entries are the same across all Guests, so we can + * set them up now. */ setup_default_gdt_entries(state); + /* Most IDT entries are the same for all Guests, too.*/ setup_default_idt_entries(state, default_idt_entries); - /* Setup LGUEST segments on all cpus */ + /* The Host needs to be able to use the LGUEST segments on this + * CPU, too, so put them in the Host GDT. */ get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT; get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT; } - /* Initialize entry point into switcher. */ + /* In the Switcher, we want the %cs segment register to use the + * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so + * it will be undisturbed when we switch. To change %cs and jump we + * need this structure to feed to Intel's "lcall" instruction. */ lguest_entry.offset = (long)switch_to_guest + switcher_offset(); lguest_entry.segment = LGUEST_CS; printk(KERN_INFO "lguest: mapped switcher at %p\n", switcher_vma->addr); + /* And we succeeded... */ return 0; free_vma: @@ -146,35 +232,58 @@ free_some_pages: out: return err; } +/*:*/ +/* Cleaning up the mapping when the module is unloaded is almost... + * too easy. */ static void unmap_switcher(void) { unsigned int i; + /* vunmap() undoes *both* map_vm_area() and __get_vm_area(). */ vunmap(switcher_vma->addr); + /* Now we just need to free the pages we copied the switcher into */ for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) __free_pages(switcher_page[i], 0); } -/* IN/OUT insns: enough to get us past boot-time probing. */ +/*H:130 Our Guest is usually so well behaved; it never tries to do things it + * isn't allowed to. Unfortunately, "struct paravirt_ops" isn't quite + * complete, because it doesn't contain replacements for the Intel I/O + * instructions. As a result, the Guest sometimes fumbles across one during + * the boot process as it probes for various things which are usually attached + * to a PC. + * + * When the Guest uses one of these instructions, we get trap #13 (General + * Protection Fault) and come here. We see if it's one of those troublesome + * instructions and skip over it. We return true if we did. */ static int emulate_insn(struct lguest *lg) { u8 insn; unsigned int insnlen = 0, in = 0, shift = 0; + /* The eip contains the *virtual* address of the Guest's instruction: + * guest_pa just subtracts the Guest's page_offset. */ unsigned long physaddr = guest_pa(lg, lg->regs->eip); - /* This only works for addresses in linear mapping... */ + /* The guest_pa() function only works for Guest kernel addresses, but + * that's all we're trying to do anyway. */ if (lg->regs->eip < lg->page_offset) return 0; + + /* Decoding x86 instructions is icky. */ lgread(lg, &insn, physaddr, 1); - /* Operand size prefix means it's actually for ax. */ + /* 0x66 is an "operand prefix". It means it's using the upper 16 bits + of the eax register. */ if (insn == 0x66) { shift = 16; + /* The instruction is 1 byte so far, read the next byte. */ insnlen = 1; lgread(lg, &insn, physaddr + insnlen, 1); } + /* We can ignore the lower bit for the moment and decode the 4 opcodes + * we need to emulate. */ switch (insn & 0xFE) { case 0xE4: /* in <next byte>,%al */ insnlen += 2; @@ -191,9 +300,13 @@ static int emulate_insn(struct lguest *lg) insnlen += 1; break; default: + /* OK, we don't know what this is, can't emulate. */ return 0; } + /* If it was an "IN" instruction, they expect the result to be read + * into %eax, so we change %eax. We always return all-ones, which + * traditionally means "there's nothing there". */ if (in) { /* Lower bit tells is whether it's a 16 or 32 bit access */ if (insn & 0x1) @@ -201,28 +314,46 @@ static int emulate_insn(struct lguest *lg) else lg->regs->eax |= (0xFFFF << shift); } + /* Finally, we've "done" the instruction, so move past it. */ lg->regs->eip += insnlen; + /* Success! */ return 1; } - +/*:*/ + +/*L:305 + * Dealing With Guest Memory. + * + * When the Guest gives us (what it thinks is) a physical address, we can use + * the normal copy_from_user() & copy_to_user() on that address: remember, + * Guest physical == Launcher virtual. + * + * But we can't trust the Guest: it might be trying to access the Launcher + * code. We have to check that the range is below the pfn_limit the Launcher + * gave us. We have to make sure that addr + len doesn't give us a false + * positive by overflowing, too. */ int lguest_address_ok(const struct lguest *lg, unsigned long addr, unsigned long len) { return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); } -/* Just like get_user, but don't let guest access lguest binary. */ +/* This is a convenient routine to get a 32-bit value from the Guest (a very + * common operation). Here we can see how useful the kill_lguest() routine we + * met in the Launcher can be: we return a random value (0) instead of needing + * to return an error. */ u32 lgread_u32(struct lguest *lg, unsigned long addr) { u32 val = 0; - /* Don't let them access lguest binary */ + /* Don't let them access lguest binary. */ if (!lguest_address_ok(lg, addr, sizeof(val)) || get_user(val, (u32 __user *)addr) != 0) kill_guest(lg, "bad read address %#lx", addr); return val; } +/* Same thing for writing a value. */ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) { if (!lguest_address_ok(lg, addr, sizeof(val)) @@ -230,6 +361,9 @@ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val) kill_guest(lg, "bad write address %#lx", addr); } +/* This routine is more generic, and copies a range of Guest bytes into a + * buffer. If the copy_from_user() fails, we fill the buffer with zeroes, so + * the caller doesn't end up using uninitialized kernel memory. */ void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) { if (!lguest_address_ok(lg, addr, bytes) @@ -240,6 +374,7 @@ void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes) } } +/* Similarly, our generic routine to copy into a range of Guest bytes. */ void lgwrite(struct lguest *lg, unsigned long addr, const void *b, unsigned bytes) { @@ -247,6 +382,7 @@ void lgwrite(struct lguest *lg, unsigned long addr, const void *b, || copy_to_user((void __user *)addr, b, bytes) != 0) kill_guest(lg, "bad write address %#lx len %u", addr, bytes); } +/* (end of memory access helper routines) :*/ static void set_ts(void) { @@ -257,54 +393,108 @@ static void set_ts(void) write_cr0(cr0|8); } +/*S:010 + * We are getting close to the Switcher. + * + * Remember that each CPU has two pages which are visible to the Guest when it + * runs on that CPU. This has to contain the state for that Guest: we copy the + * state in just before we run the Guest. + * + * Each Guest has "changed" flags which indicate what has changed in the Guest + * since it last ran. We saw this set in interrupts_and_traps.c and + * segments.c. + */ static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages) { + /* Copying all this data can be quite expensive. We usually run the + * same Guest we ran last time (and that Guest hasn't run anywhere else + * meanwhile). If that's not the case, we pretend everything in the + * Guest has changed. */ if (__get_cpu_var(last_guest) != lg || lg->last_pages != pages) { __get_cpu_var(last_guest) = lg; lg->last_pages = pages; lg->changed = CHANGED_ALL; } - /* These are pretty cheap, so we do them unconditionally. */ + /* These copies are pretty cheap, so we do them unconditionally: */ + /* Save the current Host top-level page directory. */ pages->state.host_cr3 = __pa(current->mm->pgd); + /* Set up the Guest's page tables to see this CPU's pages (and no + * other CPU's pages). */ map_switcher_in_guest(lg, pages); + /* Set up the two "TSS" members which tell the CPU what stack to use + * for traps which do directly into the Guest (ie. traps at privilege + * level 1). */ pages->state.guest_tss.esp1 = lg->esp1; pages->state.guest_tss.ss1 = lg->ss1; - /* Copy direct trap entries. */ + /* Copy direct-to-Guest trap entries. */ if (lg->changed & CHANGED_IDT) copy_traps(lg, pages->state.guest_idt, default_idt_entries); - /* Copy all GDT entries but the TSS. */ + /* Copy all GDT entries which the Guest can change. */ if (lg->changed & CHANGED_GDT) copy_gdt(lg, pages->state.guest_gdt); /* If only the TLS entries have changed, copy them. */ else if (lg->changed & CHANGED_GDT_TLS) copy_gdt_tls(lg, pages->state.guest_gdt); + /* Mark the Guest as unchanged for next time. */ lg->changed = 0; } +/* Finally: the code to actually call into the Switcher to run the Guest. */ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) { + /* This is a dummy value we need for GCC's sake. */ unsigned int clobber; + /* Copy the guest-specific information into this CPU's "struct + * lguest_pages". */ copy_in_guest_info(lg, pages); - /* Put eflags on stack, lcall does rest: suitable for iret return. */ + /* Now: we push the "eflags" register on the stack, then do an "lcall". + * This is how we change from using the kernel code segment to using + * the dedicated lguest code segment, as well as jumping into the + * Switcher. + * + * The lcall also pushes the old code segment (KERNEL_CS) onto the + * stack, then the address of this call. This stack layout happens to + * exactly match the stack of an interrupt... */ asm volatile("pushf; lcall *lguest_entry" + /* This is how we tell GCC that %eax ("a") and %ebx ("b") + * are changed by this routine. The "=" means output. */ : "=a"(clobber), "=b"(clobber) + /* %eax contains the pages pointer. ("0" refers to the + * 0-th argument above, ie "a"). %ebx contains the + * physical address of the Guest's top-level page + * directory. */ : "0"(pages), "1"(__pa(lg->pgdirs[lg->pgdidx].pgdir)) + /* We tell gcc that all these registers could change, + * which means we don't have to save and restore them in + * the Switcher. */ : "memory", "%edx", "%ecx", "%edi", "%esi"); } +/*:*/ +/*H:030 Let's jump straight to the the main loop which runs the Guest. + * Remember, this is called by the Launcher reading /dev/lguest, and we keep + * going around and around until something interesting happens. */ int run_guest(struct lguest *lg, unsigned long __user *user) { + /* We stop running once the Guest is dead. */ while (!lg->dead) { + /* We need to initialize this, otherwise gcc complains. It's + * not (yet) clever enough to see that it's initialized when we + * need it. */ unsigned int cr2 = 0; /* Damn gcc */ - /* Hypercalls first: we might have been out to userspace */ + /* First we run any hypercalls the Guest wants done: either in + * the hypercall ring in "struct lguest_data", or directly by + * using int 31 (LGUEST_TRAP_ENTRY). */ do_hypercalls(lg); + /* It's possible the Guest did a SEND_DMA hypercall to the + * Launcher, in which case we return from the read() now. */ if (lg->dma_is_pending) { if (put_user(lg->pending_dma, user) || put_user(lg->pending_key, user+1)) @@ -312,6 +502,7 @@ int run_guest(struct lguest *lg, unsigned long __user *user) return sizeof(unsigned long)*2; } + /* Check for signals */ if (signal_pending(current)) return -ERESTARTSYS; @@ -319,77 +510,154 @@ int run_guest(struct lguest *lg, unsigned long __user *user) if (lg->break_out) return -EAGAIN; + /* Check if there are any interrupts which can be delivered + * now: if so, this sets up the hander to be executed when we + * next run the Guest. */ maybe_do_interrupt(lg); + /* All long-lived kernel loops need to check with this horrible + * thing called the freezer. If the Host is trying to suspend, + * it stops us. */ try_to_freeze(); + /* Just make absolutely sure the Guest is still alive. One of + * those hypercalls could have been fatal, for example. */ if (lg->dead) break; + /* If the Guest asked to be stopped, we sleep. The Guest's + * clock timer or LHCALL_BREAK from the Waker will wake us. */ if (lg->halted) { set_current_state(TASK_INTERRUPTIBLE); schedule(); continue; } + /* OK, now we're ready to jump into the Guest. First we put up + * the "Do Not Disturb" sign: */ local_irq_disable(); - /* Even if *we* don't want FPU trap, guest might... */ + /* Remember the awfully-named TS bit? If the Guest has asked + * to set it we set it now, so we can trap and pass that trap + * to the Guest if it uses the FPU. */ if (lg->ts) set_ts(); - /* Don't let Guest do SYSENTER: we can't handle it. */ + /* SYSENTER is an optimized way of doing system calls. We + * can't allow it because it always jumps to privilege level 0. + * A normal Guest won't try it because we don't advertise it in + * CPUID, but a malicious Guest (or malicious Guest userspace + * program) could, so we tell the CPU to disable it before + * running the Guest. */ if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); + /* Now we actually run the Guest. It will pop back out when + * something interesting happens, and we can examine its + * registers to see what it was doing. */ run_guest_once(lg, lguest_pages(raw_smp_processor_id())); - /* Save cr2 now if we page-faulted. */ + /* The "regs" pointer contains two extra entries which are not + * really registers: a trap number which says what interrupt or + * trap made the switcher code come back, and an error code + * which some traps set. */ + + /* If the Guest page faulted, then the cr2 register will tell + * us the bad virtual address. We have to grab this now, + * because once we re-enable interrupts an interrupt could + * fault and thus overwrite cr2, or we could even move off to a + * different CPU. */ if (lg->regs->trapnum == 14) cr2 = read_cr2(); + /* Similarly, if we took a trap because the Guest used the FPU, + * we have to restore the FPU it expects to see. */ else if (lg->regs->trapnum == 7) math_state_restore(); + /* Restore SYSENTER if it's supposed to be on. */ if (boot_cpu_has(X86_FEATURE_SEP)) wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); + + /* Now we're ready to be interrupted or moved to other CPUs */ local_irq_enable(); + /* OK, so what happened? */ switch (lg->regs->trapnum) { case 13: /* We've intercepted a GPF. */ + /* Check if this was one of those annoying IN or OUT + * instructions which we need to emulate. If so, we + * just go back into the Guest after we've done it. */ if (lg->regs->errcode == 0) { if (emulate_insn(lg)) continue; } break; case 14: /* We've intercepted a page fault. */ + /* The Guest accessed a virtual address that wasn't + * mapped. This happens a lot: we don't actually set + * up most of the page tables for the Guest at all when + * we start: as it runs it asks for more and more, and + * we set them up as required. In this case, we don't + * even tell the Guest that the fault happened. + * + * The errcode tells whether this was a read or a + * write, and whether kernel or userspace code. */ if (demand_page(lg, cr2, lg->regs->errcode)) continue; - /* If lguest_data is NULL, this won't hurt. */ + /* OK, it's really not there (or not OK): the Guest + * needs to know. We write out the cr2 value so it + * knows where the fault occurred. + * + * Note that if the Guest were really messed up, this + * could happen before it's done the INITIALIZE + * hypercall, so lg->lguest_data will be NULL, so + * &lg->lguest_data->cr2 will be address 8. Writing + * into that address won't hurt the Host at all, + * though. */ if (put_user(cr2, &lg->lguest_data->cr2)) kill_guest(lg, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ - /* If they don't want to know, just absorb it. */ + /* If the Guest doesn't want to know, we already + * restored the Floating Point Unit, so we just + * continue without telling it. */ if (!lg->ts) continue; break; - case 32 ... 255: /* Real interrupt, fall thru */ + case 32 ... 255: + /* These values mean a real interrupt occurred, in + * which case the Host handler has already been run. + * We just do a friendly check if another process + * should now be run, then fall through to loop + * around: */ cond_resched(); case LGUEST_TRAP_ENTRY: /* Handled at top of loop */ continue; } + /* If we get here, it's a trap the Guest wants to know + * about. */ if (deliver_trap(lg, lg->regs->trapnum)) continue; + /* If the Guest doesn't have a handler (either it hasn't + * registered any yet, or it's one of the faults we don't let + * it handle), it dies with a cryptic error message. */ kill_guest(lg, "unhandled trap %li at %#lx (%#lx)", lg->regs->trapnum, lg->regs->eip, lg->regs->trapnum == 14 ? cr2 : lg->regs->errcode); } + /* The Guest is dead => "No such file or directory" */ return -ENOENT; } +/* Now we can look at each of the routines this calls, in increasing order of + * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(), + * deliver_trap() and demand_page(). After all those, we'll be ready to + * examine the Switcher, and our philosophical understanding of the Host/Guest + * duality will be complete. :*/ + int find_free_guest(void) { unsigned int i; @@ -407,55 +675,96 @@ static void adjust_pge(void *on) write_cr4(read_cr4() & ~X86_CR4_PGE); } +/*H:000 + * Welcome to the Host! + * + * By this point your brain has been tickled by the Guest code and numbed by + * the Launcher code; prepare for it to be stretched by the Host code. This is + * the heart. Let's begin at the initialization routine for the Host's lg + * module. + */ static int __init init(void) { int err; + /* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */ if (paravirt_enabled()) { printk("lguest is afraid of %s\n", paravirt_ops.name); return -EPERM; } + /* First we put the Switcher up in very high virtual memory. */ err = map_switcher(); if (err) return err; + /* Now we set up the pagetable implementation for the Guests. */ err = init_pagetables(switcher_page, SHARED_SWITCHER_PAGES); if (err) { unmap_switcher(); return err; } + + /* The I/O subsystem needs some things initialized. */ lguest_io_init(); + /* /dev/lguest needs to be registered. */ err = lguest_device_init(); if (err) { free_pagetables(); unmap_switcher(); return err; } + + /* Finally, we need to turn off "Page Global Enable". PGE is an + * optimization where page table entries are specially marked to show + * they never change. The Host kernel marks all the kernel pages this + * way because it's always present, even when userspace is running. + * + * Lguest breaks this: unbeknownst to the rest of the Host kernel, we + * switch to the Guest kernel. If you don't disable this on all CPUs, + * you'll get really weird bugs that you'll chase for two days. + * + * I used to turn PGE off every time we switched to the Guest and back + * on when we return, but that slowed the Switcher down noticibly. */ + + /* We don't need the complexity of CPUs coming and going while we're + * doing this. */ lock_cpu_hotplug(); if (cpu_has_pge) { /* We have a broader idea of "global". */ + /* Remember that this was originally set (for cleanup). */ cpu_had_pge = 1; + /* adjust_pge is a helper function which sets or unsets the PGE + * bit on its CPU, depending on the argument (0 == unset). */ on_each_cpu(adjust_pge, (void *)0, 0, 1); + /* Turn off the feature in the global feature set. */ clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability); } unlock_cpu_hotplug(); + + /* All good! */ return 0; } +/* Cleaning up is just the same code, backwards. With a little French. */ static void __exit fini(void) { lguest_device_remove(); free_pagetables(); unmap_switcher(); + + /* If we had PGE before we started, turn it back on now. */ lock_cpu_hotplug(); if (cpu_had_pge) { set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability); + /* adjust_pge's argument "1" means set PGE. */ on_each_cpu(adjust_pge, (void *)1, 0, 1); } unlock_cpu_hotplug(); } +/* The Host side of lguest can be a module. This is a nice way for people to + * play with it. */ module_init(init); module_exit(fini); MODULE_LICENSE("GPL"); diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index ea52ca4..db6caac 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -1,5 +1,10 @@ -/* Actual hypercalls, which allow guests to actually do something. - Copyright (C) 2006 Rusty Russell IBM Corporation +/*P:500 Just as userspace programs request kernel operations through a system + * call, the Guest requests Host operations through a "hypercall". You might + * notice this nomenclature doesn't really follow any logic, but the name has + * been around for long enough that we're stuck with it. As you'd expect, this + * code is basically a one big switch statement. :*/ + +/* Copyright (C) 2006 Rusty Russell IBM Corporation 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 @@ -23,37 +28,55 @@ #include <irq_vectors.h> #include "lg.h" +/*H:120 This is the core hypercall routine: where the Guest gets what it + * wants. Or gets killed. Or, in the case of LHCALL_CRASH, both. + * + * Remember from the Guest: %eax == which call to make, and the arguments are + * packed into %edx, %ebx and %ecx if needed. */ static void do_hcall(struct lguest *lg, struct lguest_regs *regs) { switch (regs->eax) { case LHCALL_FLUSH_ASYNC: + /* This call does nothing, except by breaking out of the Guest + * it makes us process all the asynchronous hypercalls. */ break; case LHCALL_LGUEST_INIT: + /* You can't get here unless you're already initialized. Don't + * do that. */ kill_guest(lg, "already have lguest_data"); break; case LHCALL_CRASH: { + /* Crash is such a trivial hypercall that we do it in four + * lines right here. */ char msg[128]; + /* If the lgread fails, it will call kill_guest() itself; the + * kill_guest() with the message will be ignored. */ lgread(lg, msg, regs->edx, sizeof(msg)); msg[sizeof(msg)-1] = '\0'; kill_guest(lg, "CRASH: %s", msg); break; } case LHCALL_FLUSH_TLB: + /* FLUSH_TLB comes in two flavors, depending on the + * argument: */ if (regs->edx) guest_pagetable_clear_all(lg); else guest_pagetable_flush_user(lg); break; - case LHCALL_GET_WALLCLOCK: { - struct timespec ts; - ktime_get_real_ts(&ts); - regs->eax = ts.tv_sec; - break; - } case LHCALL_BIND_DMA: + /* BIND_DMA really wants four arguments, but it's the only call + * which does. So the Guest packs the number of buffers and + * the interrupt number into the final argument, and we decode + * it here. This can legitimately fail, since we currently + * place a limit on the number of DMA pools a Guest can have. + * So we return true or false from this call. */ regs->eax = bind_dma(lg, regs->edx, regs->ebx, regs->ecx >> 8, regs->ecx & 0xFF); break; + + /* All these calls simply pass the arguments through to the right + * routines. */ case LHCALL_SEND_DMA: send_dma(lg, regs->edx, regs->ebx); break; @@ -81,10 +104,13 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs) case LHCALL_SET_CLOCKEVENT: guest_set_clockevent(lg, regs->edx); break; + case LHCALL_TS: + /* This sets the TS flag, as we saw used in run_guest(). */ lg->ts = regs->edx; break; case LHCALL_HALT: + /* Similarly, this sets the halted flag for run_guest(). */ lg->halted = 1; break; default: @@ -92,25 +118,42 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs) } } -/* We always do queued calls before actual hypercall. */ +/* Asynchronous hypercalls are easy: we just look in the array in the Guest's + * "struct lguest_data" and see if there are any new ones marked "ready". + * + * We are careful to do these in order: obviously we respect the order the + * Guest put them in the ring, but we also promise the Guest that they will + * happen before any normal hypercall (which is why we check this before + * checking for a normal hcall). */ static void do_async_hcalls(struct lguest *lg) { unsigned int i; u8 st[LHCALL_RING_SIZE]; + /* For simplicity, we copy the entire call status array in at once. */ if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st))) return; + + /* We process "struct lguest_data"s hcalls[] ring once. */ for (i = 0; i < ARRAY_SIZE(st); i++) { struct lguest_regs regs; + /* We remember where we were up to from last time. This makes + * sure that the hypercalls are done in the order the Guest + * places them in the ring. */ unsigned int n = lg->next_hcall; + /* 0xFF means there's no call here (yet). */ if (st[n] == 0xFF) break; + /* OK, we have hypercall. Increment the "next_hcall" cursor, + * and wrap back to 0 if we reach the end. */ if (++lg->next_hcall == LHCALL_RING_SIZE) lg->next_hcall = 0; + /* We copy the hypercall arguments into a fake register + * structure. This makes life simple for do_hcall(). */ if (get_user(regs.eax, &lg->lguest_data->hcalls[n].eax) || get_user(regs.edx, &lg->lguest_data->hcalls[n].edx) || get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx) @@ -119,74 +162,139 @@ static void do_async_hcalls(struct lguest *lg) break; } + /* Do the hypercall, same as a normal one. */ do_hcall(lg, ®s); + + /* Mark the hypercall done. */ if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) { kill_guest(lg, "Writing result for async hypercall"); break; } + /* Stop doing hypercalls if we've just done a DMA to the + * Launcher: it needs to service this first. */ if (lg->dma_is_pending) break; } } +/* Last of all, we look at what happens first of all. The very first time the + * Guest makes a hypercall, we end up here to set things up: */ static void initialize(struct lguest *lg) { u32 tsc_speed; + /* You can't do anything until you're initialized. The Guest knows the + * rules, so we're unforgiving here. */ if (lg->regs->eax != LHCALL_LGUEST_INIT) { kill_guest(lg, "hypercall %li before LGUEST_INIT", lg->regs->eax); return; } - /* We only tell the guest to use the TSC if it's reliable. */ + /* We insist that the Time Stamp Counter exist and doesn't change with + * cpu frequency. Some devious chip manufacturers decided that TSC + * changes could be handled in software. I decided that time going + * backwards might be good for benchmarks, but it's bad for users. + * + * We also insist that the TSC be stable: the kernel detects unreliable + * TSCs for its own purposes, and we use that here. */ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable()) tsc_speed = tsc_khz; else tsc_speed = 0; + /* The pointer to the Guest's "struct lguest_data" is the only + * argument. */ lg->lguest_data = (struct lguest_data __user *)lg->regs->edx; - /* We check here so we can simply copy_to_user/from_user */ + /* If we check the address they gave is OK now, we can simply + * copy_to_user/from_user from now on rather than using lgread/lgwrite. + * I put this in to show that I'm not immune to writing stupid + * optimizations. */ if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) { kill_guest(lg, "bad guest page %p", lg->lguest_data); return; } + /* The Guest tells us where we're not to deliver interrupts by putting + * the range of addresses into "struct lguest_data". */ if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start) || get_user(lg->noirq_end, &lg->lguest_data->noirq_end) - /* We reserve the top pgd entry. */ + /* We tell the Guest that it can't use the top 4MB of virtual + * addresses used by the Switcher. */ || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem) || put_user(tsc_speed, &lg->lguest_data->tsc_khz) + /* We also give the Guest a unique id, as used in lguest_net.c. */ || put_user(lg->guestid, &lg->lguest_data->guestid)) kill_guest(lg, "bad guest page %p", lg->lguest_data); - /* This is the one case where the above accesses might have - * been the first write to a Guest page. This may have caused - * a copy-on-write fault, but the Guest might be referring to - * the old (read-only) page. */ + /* We write the current time into the Guest's data page once now. */ + write_timestamp(lg); + + /* This is the one case where the above accesses might have been the + * first write to a Guest page. This may have caused a copy-on-write + * fault, but the Guest might be referring to the old (read-only) + * page. */ guest_pagetable_clear_all(lg); } +/* Now we've examined the hypercall code; our Guest can make requests. There + * is one other way we can do things for the Guest, as we see in + * emulate_insn(). */ -/* Even if we go out to userspace and come back, we don't want to do - * the hypercall again. */ +/*H:110 Tricky point: we mark the hypercall as "done" once we've done it. + * Normally we don't need to do this: the Guest will run again and update the + * trap number before we come back around the run_guest() loop to + * do_hypercalls(). + * + * However, if we are signalled or the Guest sends DMA to the Launcher, that + * loop will exit without running the Guest. When it comes back it would try + * to re-run the hypercall. */ static void clear_hcall(struct lguest *lg) { lg->regs->trapnum = 255; } +/*H:100 + * Hypercalls + * + * Remember from the Guest, hypercalls come in two flavors: normal and + * asynchronous. This file handles both of types. + */ void do_hypercalls(struct lguest *lg) { + /* Not initialized yet? */ if (unlikely(!lg->lguest_data)) { + /* Did the Guest make a hypercall? We might have come back for + * some other reason (an interrupt, a different trap). */ if (lg->regs->trapnum == LGUEST_TRAP_ENTRY) { + /* Set up the "struct lguest_data" */ initialize(lg); + /* The hypercall is done. */ clear_hcall(lg); } return; } + /* The Guest has initialized. + * + * Look in the hypercall ring for the async hypercalls: */ do_async_hcalls(lg); + + /* If we stopped reading the hypercall ring because the Guest did a + * SEND_DMA to the Launcher, we want to return now. Otherwise if the + * Guest asked us to do a hypercall, we do it. */ if (!lg->dma_is_pending && lg->regs->trapnum == LGUEST_TRAP_ENTRY) { do_hcall(lg, lg->regs); + /* The hypercall is done. */ clear_hcall(lg); } } + +/* This routine supplies the Guest with time: it's used for wallclock time at + * initial boot and as a rough time source if the TSC isn't available. */ +void write_timestamp(struct lguest *lg) +{ + struct timespec now; + ktime_get_real_ts(&now); + if (put_user(now, &lg->lguest_data->time)) + kill_guest(lg, "Writing timestamp"); +} diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index bee029b..49787e9 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -1,100 +1,160 @@ +/*P:800 Interrupts (traps) are complicated enough to earn their own file. + * There are three classes of interrupts: + * + * 1) Real hardware interrupts which occur while we're running the Guest, + * 2) Interrupts for virtual devices attached to the Guest, and + * 3) Traps and faults from the Guest. + * + * Real hardware interrupts must be delivered to the Host, not the Guest. + * Virtual interrupts must be delivered to the Guest, but we make them look + * just like real hardware would deliver them. Traps from the Guest can be set + * up to go directly back into the Guest, but sometimes the Host wants to see + * them first, so we also have a way of "reflecting" them into the Guest as if + * they had been delivered to it directly. :*/ #include <linux/uaccess.h> #include "lg.h" +/* The address of the interrupt handler is split into two bits: */ static unsigned long idt_address(u32 lo, u32 hi) { return (lo & 0x0000FFFF) | (hi & 0xFFFF0000); } +/* The "type" of the interrupt handler is a 4 bit field: we only support a + * couple of types. */ static int idt_type(u32 lo, u32 hi) { return (hi >> 8) & 0xF; } +/* An IDT entry can't be used unless the "present" bit is set. */ static int idt_present(u32 lo, u32 hi) { return (hi & 0x8000); } +/* We need a helper to "push" a value onto the Guest's stack, since that's a + * big part of what delivering an interrupt does. */ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val) { + /* Stack grows upwards: move stack then write value. */ *gstack -= 4; lgwrite_u32(lg, *gstack, val); } +/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or + * trap. The mechanics of delivering traps and interrupts to the Guest are the + * same, except some traps have an "error code" which gets pushed onto the + * stack as well: the caller tells us if this is one. + * + * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this + * interrupt or trap. It's split into two parts for traditional reasons: gcc + * on i386 used to be frightened by 64 bit numbers. + * + * We set up the stack just like the CPU does for a real interrupt, so it's + * identical for the Guest (and the standard "iret" instruction will undo + * it). */ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err) { unsigned long gstack; u32 eflags, ss, irq_enable; - /* If they want a ring change, we use new stack and push old ss/esp */ + /* There are two cases for interrupts: one where the Guest is already + * in the kernel, and a more complex one where the Guest is in + * userspace. We check the privilege level to find out. */ if ((lg->regs->ss&0x3) != GUEST_PL) { + /* The Guest told us their kernel stack with the SET_STACK + * hypercall: both the virtual address and the segment */ gstack = guest_pa(lg, lg->esp1); ss = lg->ss1; + /* We push the old stack segment and pointer onto the new + * stack: when the Guest does an "iret" back from the interrupt + * handler the CPU will notice they're dropping privilege + * levels and expect these here. */ push_guest_stack(lg, &gstack, lg->regs->ss); push_guest_stack(lg, &gstack, lg->regs->esp); } else { + /* We're staying on the same Guest (kernel) stack. */ gstack = guest_pa(lg, lg->regs->esp); ss = lg->regs->ss; } - /* We use IF bit in eflags to indicate whether irqs were enabled - (it's always 1, since irqs are enabled when guest is running). */ + /* Remember that we never let the Guest actually disable interrupts, so + * the "Interrupt Flag" bit is always set. We copy that bit from the + * Guest's "irq_enabled" field into the eflags word: the Guest copies + * it back in "lguest_iret". */ eflags = lg->regs->eflags; if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0 && !(irq_enable & X86_EFLAGS_IF)) eflags &= ~X86_EFLAGS_IF; + /* An interrupt is expected to push three things on the stack: the old + * "eflags" word, the old code segment, and the old instruction + * pointer. */ push_guest_stack(lg, &gstack, eflags); push_guest_stack(lg, &gstack, lg->regs->cs); push_guest_stack(lg, &gstack, lg->regs->eip); + /* For the six traps which supply an error code, we push that, too. */ if (has_err) push_guest_stack(lg, &gstack, lg->regs->errcode); - /* Change the real stack so switcher returns to trap handler */ + /* Now we've pushed all the old state, we change the stack, the code + * segment and the address to execute. */ lg->regs->ss = ss; lg->regs->esp = gstack + lg->page_offset; lg->regs->cs = (__KERNEL_CS|GUEST_PL); lg->regs->eip = idt_address(lo, hi); - /* Disable interrupts for an interrupt gate. */ + /* There are two kinds of interrupt handlers: 0xE is an "interrupt + * gate" which expects interrupts to be disabled on entry. */ if (idt_type(lo, hi) == 0xE) if (put_user(0, &lg->lguest_data->irq_enabled)) kill_guest(lg, "Disabling interrupts"); } +/*H:200 + * Virtual Interrupts. + * + * maybe_do_interrupt() gets called before every entry to the Guest, to see if + * we should divert the Guest to running an interrupt handler. */ void maybe_do_interrupt(struct lguest *lg) { unsigned int irq; DECLARE_BITMAP(blk, LGUEST_IRQS); struct desc_struct *idt; + /* If the Guest hasn't even initialized yet, we can do nothing. */ if (!lg->lguest_data) return; - /* Mask out any interrupts they have blocked. */ + /* Take our "irqs_pending" array and remove any interrupts the Guest + * wants blocked: the result ends up in "blk". */ if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts, sizeof(blk))) return; bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS); + /* Find the first interrupt. */ irq = find_first_bit(blk, LGUEST_IRQS); + /* None? Nothing to do */ if (irq >= LGUEST_IRQS) return; + /* They may be in the middle of an iret, where they asked us never to + * deliver interrupts. */ if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end) return; - /* If they're halted, we re-enable interrupts. */ + /* If they're halted, interrupts restart them. */ if (lg->halted) { /* Re-enable interrupts. */ if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled)) kill_guest(lg, "Re-enabling interrupts"); lg->halted = 0; } else { - /* Maybe they have interrupts disabled? */ + /* Otherwise we check if they have interrupts disabled. */ u32 irq_enabled; if (get_user(irq_enabled, &lg->lguest_data->irq_enabled)) irq_enabled = 0; @@ -102,112 +162,218 @@ void maybe_do_interrupt(struct lguest *lg) return; } + /* Look at the IDT entry the Guest gave us for this interrupt. The + * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip + * over them. */ idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq]; + /* If they don't have a handler (yet?), we just ignore it */ if (idt_present(idt->a, idt->b)) { + /* OK, mark it no longer pending and deliver it. */ clear_bit(irq, lg->irqs_pending); + /* set_guest_interrupt() takes the interrupt descriptor and a + * flag to say whether this interrupt pushes an error code onto + * the stack as well: virtual interrupts never do. */ set_guest_interrupt(lg, idt->a, idt->b, 0); } + + /* Every time we deliver an interrupt, we update the timestamp in the + * Guest's lguest_data struct. It would be better for the Guest if we + * did this more often, but it can actually be quite slow: doing it + * here is a compromise which means at least it gets updated every + * timer interrupt. */ + write_timestamp(lg); } +/*H:220 Now we've got the routines to deliver interrupts, delivering traps + * like page fault is easy. The only trick is that Intel decided that some + * traps should have error codes: */ static int has_err(unsigned int trap) { return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); } +/* deliver_trap() returns true if it could deliver the trap. */ int deliver_trap(struct lguest *lg, unsigned int num) { u32 lo = lg->idt[num].a, hi = lg->idt[num].b; + /* Early on the Guest hasn't set the IDT entries (or maybe it put a + * bogus one in): if we fail here, the Guest will be killed. */ if (!idt_present(lo, hi)) return 0; set_guest_interrupt(lg, lo, hi, has_err(num)); return 1; } +/*H:250 Here's the hard part: returning to the Host every time a trap happens + * and then calling deliver_trap() and re-entering the Guest is slow. + * Particularly because Guest userspace system calls are traps (trap 128). + * + * So we'd like to set up the IDT to tell the CPU to deliver traps directly + * into the Guest. This is possible, but the complexities cause the size of + * this file to double! However, 150 lines of code is worth writing for taking + * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all + * the other hypervisors would tease it. + * + * This routine determines if a trap can be delivered directly. */ static int direct_trap(const struct lguest *lg, const struct desc_struct *trap, unsigned int num) { - /* Hardware interrupts don't go to guest (except syscall). */ + /* Hardware interrupts don't go to the Guest at all (except system + * call). */ if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR) return 0; - /* We intercept page fault (demand shadow paging & cr2 saving) - protection fault (in/out emulation) and device not - available (TS handling), and hypercall */ + /* The Host needs to see page faults (for shadow paging and to save the + * fault address), general protection faults (in/out emulation) and + * device not available (TS handling), and of course, the hypercall + * trap. */ if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY) return 0; - /* Interrupt gates (0xE) or not present (0x0) can't go direct. */ + /* Only trap gates (type 15) can go direct to the Guest. Interrupt + * gates (type 14) disable interrupts as they are entered, which we + * never let the Guest do. Not present entries (type 0x0) also can't + * go direct, of course 8) */ return idt_type(trap->a, trap->b) == 0xF; } - +/*:*/ + +/*M:005 The Guest has the ability to turn its interrupt gates into trap gates, + * if it is careful. The Host will let trap gates can go directly to the + * Guest, but the Guest needs the interrupts atomically disabled for an + * interrupt gate. It can do this by pointing the trap gate at instructions + * within noirq_start and noirq_end, where it can safely disable interrupts. */ + +/*M:006 The Guests do not use the sysenter (fast system call) instruction, + * because it's hardcoded to enter privilege level 0 and so can't go direct. + * It's about twice as fast as the older "int 0x80" system call, so it might + * still be worthwhile to handle it in the Switcher and lcall down to the + * Guest. The sysenter semantics are hairy tho: search for that keyword in + * entry.S :*/ + +/*H:260 When we make traps go directly into the Guest, we need to make sure + * the kernel stack is valid (ie. mapped in the page tables). Otherwise, the + * CPU trying to deliver the trap will fault while trying to push the interrupt + * words on the stack: this is called a double fault, and it forces us to kill + * the Guest. + * + * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */ void pin_stack_pages(struct lguest *lg) { unsigned int i; + /* Depending on the CONFIG_4KSTACKS option, the Guest can have one or + * two pages of stack space. */ for (i = 0; i < lg->stack_pages; i++) + /* The stack grows *upwards*, hence the subtraction */ pin_page(lg, lg->esp1 - i * PAGE_SIZE); } +/* Direct traps also mean that we need to know whenever the Guest wants to use + * a different kernel stack, so we can change the IDT entries to use that + * stack. The IDT entries expect a virtual address, so unlike most addresses + * the Guest gives us, the "esp" (stack pointer) value here is virtual, not + * physical. + * + * In Linux each process has its own kernel stack, so this happens a lot: we + * change stacks on each context switch. */ void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages) { - /* You cannot have a stack segment with priv level 0. */ + /* You are not allowd have a stack segment with privilege level 0: bad + * Guest! */ if ((seg & 0x3) != GUEST_PL) kill_guest(lg, "bad stack segment %i", seg); + /* We only expect one or two stack pages. */ if (pages > 2) kill_guest(lg, "bad stack pages %u", pages); + /* Save where the stack is, and how many pages */ lg->ss1 = seg; lg->esp1 = esp; lg->stack_pages = pages; + /* Make sure the new stack pages are mapped */ pin_stack_pages(lg); } -/* Set up trap in IDT. */ +/* All this reference to mapping stacks leads us neatly into the other complex + * part of the Host: page table handling. */ + +/*H:235 This is the routine which actually checks the Guest's IDT entry and + * transfers it into our entry in "struct lguest": */ static void set_trap(struct lguest *lg, struct desc_struct *trap, unsigned int num, u32 lo, u32 hi) { u8 type = idt_type(lo, hi); + /* We zero-out a not-present entry */ if (!idt_present(lo, hi)) { trap->a = trap->b = 0; return; } + /* We only support interrupt and trap gates. */ if (type != 0xE && type != 0xF) kill_guest(lg, "bad IDT type %i", type); + /* We only copy the handler address, present bit, privilege level and + * type. The privilege level controls where the trap can be triggered + * manually with an "int" instruction. This is usually GUEST_PL, + * except for system calls which userspace can use. */ trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF); trap->b = (hi&0xFFFFEF00); } +/*H:230 While we're here, dealing with delivering traps and interrupts to the + * Guest, we might as well complete the picture: how the Guest tells us where + * it wants them to go. This would be simple, except making traps fast + * requires some tricks. + * + * We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the + * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi) { - /* Guest never handles: NMI, doublefault, hypercall, spurious irq. */ + /* Guest never handles: NMI, doublefault, spurious interrupt or + * hypercall. We ignore when it tries to set them. */ if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY) return; + /* Mark the IDT as changed: next time the Guest runs we'll know we have + * to copy this again. */ lg->changed |= CHANGED_IDT; + + /* The IDT which we keep in "struct lguest" only contains 32 entries + * for the traps and LGUEST_IRQS (32) entries for interrupts. We + * ignore attempts to set handlers for higher interrupt numbers, except + * for the system call "interrupt" at 128: we have a special IDT entry + * for that. */ if (num < ARRAY_SIZE(lg->idt)) set_trap(lg, &lg->idt[num], num, lo, hi); else if (num == SYSCALL_VECTOR) set_trap(lg, &lg->syscall_idt, num, lo, hi); } +/* The default entry for each interrupt points into the Switcher routines which + * simply return to the Host. The run_guest() loop will then call + * deliver_trap() to bounce it back into the Guest. */ static void default_idt_entry(struct desc_struct *idt, int trap, const unsigned long handler) { + /* A present interrupt gate. */ u32 flags = 0x8e00; - /* They can't "int" into any of them except hypercall. */ + /* Set the privilege level on the entry for the hypercall: this allows + * the Guest to use the "int" instruction to trigger it. */ if (trap == LGUEST_TRAP_ENTRY) flags |= (GUEST_PL << 13); + /* Now pack it into the IDT entry in its weird format. */ idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); idt->b = (handler&0xFFFF0000) | flags; } +/* When the Guest first starts, we put default entries into the IDT. */ void setup_default_idt_entries(struct lguest_ro_state *state, const unsigned long *def) { @@ -217,19 +383,25 @@ void setup_default_idt_entries(struct lguest_ro_state *state, default_idt_entry(&state->guest_idt[i], i, def[i]); } +/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead + * we copy them into the IDT which we've set up for Guests on this CPU, just + * before we run the Guest. This routine does that copy. */ void copy_traps(const struct lguest *lg, struct desc_struct *idt, const unsigned long *def) { unsigned int i; - /* All hardware interrupts are same whatever the guest: only the - * traps might be different. */ + /* We can simply copy the direct traps, otherwise we use the default + * ones in the Switcher: they will return to the Host. */ for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) { if (direct_trap(lg, &lg->idt[i], i)) idt[i] = lg->idt[i]; else default_idt_entry(&idt[i], i, def[i]); } + + /* Don't forget the system call trap! The IDT entries for other + * interupts never change, so no need to copy them. */ i = SYSCALL_VECTOR; if (direct_trap(lg, &lg->syscall_idt, i)) idt[i] = lg->syscall_idt; diff --git a/drivers/lguest/io.c b/drivers/lguest/io.c index c8eb792..ea68613 100644 --- a/drivers/lguest/io.c +++ b/drivers/lguest/io.c @@ -1,5 +1,9 @@ -/* Simple I/O model for guests, based on shared memory. - * Copyright (C) 2006 Rusty Russell IBM Corporation +/*P:300 The I/O mechanism in lguest is simple yet flexible, allowing the Guest + * to talk to the Launcher or directly to another Guest. It uses familiar + * concepts of DMA and interrupts, plus some neat code stolen from + * futexes... :*/ + +/* Copyright (C) 2006 Rusty Russell IBM Corporation * * 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 @@ -23,8 +27,36 @@ #include <linux/uaccess.h> #include "lg.h" +/*L:300 + * I/O + * + * Getting data in and out of the Guest is quite an art. There are numerous + * ways to do it, and they all suck differently. We try to keep things fairly + * close to "real" hardware so our Guest's drivers don't look like an alien + * visitation in the middle of the Linux code, and yet make sure that Guests + * can talk directly to other Guests, not just the Launcher. + * + * To do this, the Guest gives us a key when it binds or sends DMA buffers. + * The key corresponds to a "physical" address inside the Guest (ie. a virtual + * address inside the Launcher process). We don't, however, use this key + * directly. + * + * We want Guests which share memory to be able to DMA to each other: two + * Launchers can mmap memory the same file, then the Guests can communicate. + * Fortunately, the futex code provides us with a way to get a "union + * futex_key" corresponding to the memory lying at a virtual address: if the + * two processes share memory, the "union futex_key" for that memory will match + * even if the memory is mapped at different addresses in each. So we always + * convert the keys to "union futex_key"s to compare them. + * + * Before we dive into this though, we need to look at another set of helper + * routines used throughout the Host kernel code to access Guest memory. + :*/ static struct list_head dma_hash[61]; +/* An unfortunate side effect of the Linux double-linked list implementation is + * that there's no good way to statically initialize an array of linked + * lists. */ void lguest_io_init(void) { unsigned int i; @@ -56,6 +88,19 @@ kill: return 0; } +/*L:330 This is our hash function, using the wonderful Jenkins hash. + * + * The futex key is a union with three parts: an unsigned long word, a pointer, + * and an int "offset". We could use jhash_2words() which takes three u32s. + * (Ok, the hash functions are great: the naming sucks though). + * + * It's nice to be portable to 64-bit platforms, so we use the more generic + * jhash2(), which takes an array of u32, the number of u32s, and an initial + * u32 to roll in. This is uglier, but breaks down to almost the same code on + * 32-bit platforms like this one. + * + * We want a position in the array, so we modulo ARRAY_SIZE(dma_hash) (ie. 61). + */ static unsigned int hash(const union futex_key *key) { return jhash2((u32*)&key->both.word, @@ -64,6 +109,9 @@ static unsigned int hash(const union futex_key *key) % ARRAY_SIZE(dma_hash); } +/* This is a convenience routine to compare two keys. It's a much bemoaned C + * weakness that it doesn't allow '==' on structures or unions, so we have to + * open-code it like this. */ static inline int key_eq(const union futex_key *a, const union futex_key *b) { return (a->both.word == b->both.word @@ -71,22 +119,36 @@ static inline int key_eq(const union futex_key *a, const union futex_key *b) && a->both.offset == b->both.offset); } -/* Must hold read lock on dmainfo owner's current->mm->mmap_sem */ +/*L:360 OK, when we need to actually free up a Guest's DMA array we do several + * things, so we have a convenient function to do it. + * + * The caller must hold a read lock on dmainfo owner's current->mm->mmap_sem + * for the drop_futex_key_refs(). */ static void unlink_dma(struct lguest_dma_info *dmainfo) { + /* You locked this too, right? */ BUG_ON(!mutex_is_locked(&lguest_lock)); + /* This is how we know that the entry is free. */ dmainfo->interrupt = 0; + /* Remove it from the hash table. */ list_del(&dmainfo->list); + /* Drop the references we were holding (to the inode or mm). */ drop_futex_key_refs(&dmainfo->key); } +/*L:350 This is the routine which we call when the Guest asks to unregister a + * DMA array attached to a given key. Returns true if the array was found. */ static int unbind_dma(struct lguest *lg, const union futex_key *key, unsigned long dmas) { int i, ret = 0; + /* We don't bother with the hash table, just look through all this + * Guest's DMA arrays. */ for (i = 0; i < LGUEST_MAX_DMA; i++) { + /* In theory it could have more than one array on the same key, + * or one array on multiple keys, so we check both */ if (key_eq(key, &lg->dma[i].key) && dmas == lg->dma[i].dmas) { unlink_dma(&lg->dma[i]); ret = 1; @@ -96,51 +158,91 @@ static int unbind_dma(struct lguest *lg, return ret; } +/*L:340 BIND_DMA: this is the hypercall which sets up an array of "struct + * lguest_dma" for receiving I/O. + * + * The Guest wants to bind an array of "struct lguest_dma"s to a particular key + * to receive input. This only happens when the Guest is setting up a new + * device, so it doesn't have to be very fast. + * + * It returns 1 on a successful registration (it can fail if we hit the limit + * of registrations for this Guest). + */ int bind_dma(struct lguest *lg, unsigned long ukey, unsigned long dmas, u16 numdmas, u8 interrupt) { unsigned int i; int ret = 0; union futex_key key; + /* Futex code needs the mmap_sem. */ struct rw_semaphore *fshared = ¤t->mm->mmap_sem; + /* Invalid interrupt? (We could kill the guest here). */ if (interrupt >= LGUEST_IRQS) return 0; + /* We need to grab the Big Lguest Lock, because other Guests may be + * trying to look through this Guest's DMAs to send something while + * we're doing this. */ mutex_lock(&lguest_lock); down_read(fshared); if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { kill_guest(lg, "bad dma key %#lx", ukey); goto unlock; } + + /* We want to keep this key valid once we drop mmap_sem, so we have to + * hold a reference. */ get_futex_key_refs(&key); + /* If the Guest specified an interrupt of 0, that means they want to + * unregister this array of "struct lguest_dma"s. */ if (interrupt == 0) ret = unbind_dma(lg, &key, dmas); else { + /* Look through this Guest's dma array for an unused entry. */ for (i = 0; i < LGUEST_MAX_DMA; i++) { + /* If the interrupt is non-zero, the entry is already + * used. */ if (lg->dma[i].interrupt) continue; + /* OK, a free one! Fill on our details. */ lg->dma[i].dmas = dmas; lg->dma[i].num_dmas = numdmas; lg->dma[i].next_dma = 0; lg->dma[i].key = key; lg->dma[i].guestid = lg->guestid; lg->dma[i].interrupt = interrupt; + + /* Now we add it to the hash table: the position + * depends on the futex key that we got. */ list_add(&lg->dma[i].list, &dma_hash[hash(&key)]); + /* Success! */ ret = 1; goto unlock; } } + /* If we didn't find a slot to put the key in, drop the reference + * again. */ drop_futex_key_refs(&key); unlock: + /* Unlock and out. */ up_read(fshared); mutex_unlock(&lguest_lock); return ret; } -/* lgread from another guest */ +/*L:385 Note that our routines to access a different Guest's memory are called + * lgread_other() and lgwrite_other(): these names emphasize that they are only + * used when the Guest is *not* the current Guest. + * + * The interface for copying from another process's memory is called + * access_process_vm(), with a final argument of 0 for a read, and 1 for a + * write. + * + * We need lgread_other() to read the destination Guest's "struct lguest_dma" + * array. */ static int lgread_other(struct lguest *lg, void *buf, u32 addr, unsigned bytes) { @@ -153,7 +255,8 @@ static int lgread_other(struct lguest *lg, return 1; } -/* lgwrite to another guest */ +/* "lgwrite()" to another Guest: used to update the destination "used_len" once + * we've transferred data into the buffer. */ static int lgwrite_other(struct lguest *lg, u32 addr, const void *buf, unsigned bytes) { @@ -166,6 +269,15 @@ static int lgwrite_other(struct lguest *lg, u32 addr, return 1; } +/*L:400 This is the generic engine which copies from a source "struct + * lguest_dma" from this Guest into another Guest's "struct lguest_dma". The + * destination Guest's pages have already been mapped, as contained in the + * pages array. + * + * If you're wondering if there's a nice "copy from one process to another" + * routine, so was I. But Linux isn't really set up to copy between two + * unrelated processes, so we have to write it ourselves. + */ static u32 copy_data(struct lguest *srclg, const struct lguest_dma *src, const struct lguest_dma *dst, @@ -174,33 +286,59 @@ static u32 copy_data(struct lguest *srclg, unsigned int totlen, si, di, srcoff, dstoff; void *maddr = NULL; + /* We return the total length transferred. */ totlen = 0; + + /* We keep indexes into the source and destination "struct lguest_dma", + * and an offset within each region. */ si = di = 0; srcoff = dstoff = 0; + + /* We loop until the source or destination is exhausted. */ while (si < LGUEST_MAX_DMA_SECTIONS && src->len[si] && di < LGUEST_MAX_DMA_SECTIONS && dst->len[di]) { + /* We can only transfer the rest of the src buffer, or as much + * as will fit into the destination buffer. */ u32 len = min(src->len[si] - srcoff, dst->len[di] - dstoff); + /* For systems using "highmem" we need to use kmap() to access + * the page we want. We often use the same page over and over, + * so rather than kmap() it on every loop, we set the maddr + * pointer to NULL when we need to move to the next + * destination page. */ if (!maddr) maddr = kmap(pages[di]); - /* FIXME: This is not completely portable, since - archs do different things for copy_to_user_page. */ + /* Copy directly from (this Guest's) source address to the + * destination Guest's kmap()ed buffer. Note that maddr points + * to the start of the page: we need to add the offset of the + * destination address and offset within the buffer. */ + + /* FIXME: This is not completely portable. I looked at + * copy_to_user_page(), and some arch's seem to need special + * flushes. x86 is fine. */ if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE, (void __user *)src->addr[si], len) != 0) { + /* If a copy failed, it's the source's fault. */ kill_guest(srclg, "bad address in sending DMA"); totlen = 0; break; } + /* Increment the total and src & dst offsets */ totlen += len; srcoff += len; dstoff += len; + + /* Presumably we reached the end of the src or dest buffers: */ if (srcoff == src->len[si]) { + /* Move to the next buffer at offset 0 */ si++; srcoff = 0; } if (dstoff == dst->len[di]) { + /* We need to unmap that destination page and reset + * maddr ready for the next one. */ kunmap(pages[di]); maddr = NULL; di++; @@ -208,13 +346,15 @@ static u32 copy_data(struct lguest *srclg, } } + /* If we still had a page mapped at the end, unmap now. */ if (maddr) kunmap(pages[di]); return totlen; } -/* Src is us, ie. current. */ +/*L:390 This is how we transfer a "struct lguest_dma" from the source Guest + * (the current Guest which called SEND_DMA) to another Guest. */ static u32 do_dma(struct lguest *srclg, const struct lguest_dma *src, struct lguest *dstlg, const struct lguest_dma *dst) { @@ -222,23 +362,31 @@ static u32 do_dma(struct lguest *srclg, const struct lguest_dma *src, u32 ret; struct page *pages[LGUEST_MAX_DMA_SECTIONS]; + /* We check that both source and destination "struct lguest_dma"s are + * within the bounds of the source and destination Guests */ if (!check_dma_list(dstlg, dst) || !check_dma_list(srclg, src)) return 0; - /* First get the destination pages */ + /* We need to map the pages which correspond to each parts of + * destination buffer. */ for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) { if (dst->len[i] == 0) break; + /* get_user_pages() is a complicated function, especially since + * we only want a single page. But it works, and returns the + * number of pages. Note that we're holding the destination's + * mmap_sem, as get_user_pages() requires. */ if (get_user_pages(dstlg->tsk, dstlg->mm, dst->addr[i], 1, 1, 1, pages+i, NULL) != 1) { + /* This means the destination gave us a bogus buffer */ kill_guest(dstlg, "Error mapping DMA pages"); ret = 0; goto drop_pages; } } - /* Now copy until we run out of src or dst. */ + /* Now copy the data until we run out of src or dst. */ ret = copy_data(srclg, src, dst, pages); drop_pages: @@ -247,6 +395,11 @@ drop_pages: return ret; } +/*L:380 Transferring data from one Guest to another is not as simple as I'd + * like. We've found the "struct lguest_dma_info" bound to the same address as + * the send, we need to copy into it. + * + * This function returns true if the destination array was empty. */ static int dma_transfer(struct lguest *srclg, unsigned long udma, struct lguest_dma_info *dst) @@ -255,15 +408,23 @@ static int dma_transfer(struct lguest *srclg, struct lguest *dstlg; u32 i, dma = 0; + /* From the "struct lguest_dma_info" we found in the hash, grab the + * Guest. */ dstlg = &lguests[dst->guestid]; - /* Get our dma list. */ + /* Read in the source "struct lguest_dma" handed to SEND_DMA. */ lgread(srclg, &src_dma, udma, sizeof(src_dma)); - /* We can't deadlock against them dmaing to us, because this - * is all under the lguest_lock. */ + /* We need the destination's mmap_sem, and we already hold the source's + * mmap_sem for the futex key lookup. Normally this would suggest that + * we could deadlock if the destination Guest was trying to send to + * this source Guest at the same time, which is another reason that all + * I/O is done under the big lguest_lock. */ down_read(&dstlg->mm->mmap_sem); + /* Look through the destination DMA array for an available buffer. */ for (i = 0; i < dst->num_dmas; i++) { + /* We keep a "next_dma" pointer which often helps us avoid + * looking at lots of previously-filled entries. */ dma = (dst->next_dma + i) % dst->num_dmas; if (!lgread_other(dstlg, &dst_dma, dst->dmas + dma * sizeof(struct lguest_dma), @@ -273,30 +434,46 @@ static int dma_transfer(struct lguest *srclg, if (!dst_dma.used_len) break; } + + /* If we found a buffer, we do the actual data copy. */ if (i != dst->num_dmas) { unsigned long used_lenp; unsigned int ret; ret = do_dma(srclg, &src_dma, dstlg, &dst_dma); - /* Put used length in src. */ + /* Put used length in the source "struct lguest_dma"'s used_len + * field. It's a little tricky to figure out where that is, + * though. */ lgwrite_u32(srclg, udma+offsetof(struct lguest_dma, used_len), ret); + /* Tranferring 0 bytes is OK if the source buffer was empty. */ if (ret == 0 && src_dma.len[0] != 0) goto fail; - /* Make sure destination sees contents before length. */ + /* The destination Guest might be running on a different CPU: + * we have to make sure that it will see the "used_len" field + * change to non-zero *after* it sees the data we copied into + * the buffer. Hence a write memory barrier. */ wmb(); + /* Figuring out where the destination's used_len field for this + * "struct lguest_dma" in the array is also a little ugly. */ used_lenp = dst->dmas + dma * sizeof(struct lguest_dma) + offsetof(struct lguest_dma, used_len); lgwrite_other(dstlg, used_lenp, &ret, sizeof(ret)); + /* Move the cursor for next time. */ dst->next_dma++; } up_read(&dstlg->mm->mmap_sem); - /* Do this last so dst doesn't simply sleep on lock. */ + /* We trigger the destination interrupt, even if the destination was + * empty and we didn't transfer anything: this gives them a chance to + * wake up and refill. */ set_bit(dst->interrupt, dstlg->irqs_pending); + /* Wake up the destination process. */ wake_up_process(dstlg->tsk); + /* If we passed the last "struct lguest_dma", the receive had no + * buffers left. */ return i == dst->num_dmas; fail: @@ -304,6 +481,8 @@ fail: return 0; } +/*L:370 This is the counter-side to the BIND_DMA hypercall; the SEND_DMA + * hypercall. We find out who's listening, and send to them. */ void send_dma(struct lguest *lg, unsigned long ukey, unsigned long udma) { union futex_key key; @@ -313,31 +492,43 @@ void send_dma(struct lguest *lg, unsigned long ukey, unsigned long udma) again: mutex_lock(&lguest_lock); down_read(fshared); + /* Get the futex key for the key the Guest gave us */ if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { kill_guest(lg, "bad sending DMA key"); goto unlock; } - /* Shared mapping? Look for other guests... */ + /* Since the key must be a multiple of 4, the futex key uses the lower + * bit of the "offset" field (which would always be 0) to indicate a + * mapping which is shared with other processes (ie. Guests). */ if (key.shared.offset & 1) { struct lguest_dma_info *i; + /* Look through the hash for other Guests. */ list_for_each_entry(i, &dma_hash[hash(&key)], list) { + /* Don't send to ourselves. */ if (i->guestid == lg->guestid) continue; if (!key_eq(&key, &i->key)) continue; + /* If dma_transfer() tells us the destination has no + * available buffers, we increment "empty". */ empty += dma_transfer(lg, udma, i); break; } + /* If the destination is empty, we release our locks and + * give the destination Guest a brief chance to restock. */ if (empty == 1) { /* Give any recipients one chance to restock. */ up_read(¤t->mm->mmap_sem); mutex_unlock(&lguest_lock); + /* Next time, we won't try again. */ empty++; goto again; } } else { - /* Private mapping: tell our userspace. */ + /* Private mapping: Guest is sending to its Launcher. We set + * the "dma_is_pending" flag so that the main loop will exit + * and the Launcher's read() from /dev/lguest will return. */ lg->dma_is_pending = 1; lg->pending_dma = udma; lg->pending_key = ukey; @@ -346,6 +537,7 @@ unlock: up_read(fshared); mutex_unlock(&lguest_lock); } +/*:*/ void release_all_dma(struct lguest *lg) { @@ -361,7 +553,18 @@ void release_all_dma(struct lguest *lg) up_read(&lg->mm->mmap_sem); } -/* Userspace wants a dma buffer from this guest. */ +/*M:007 We only return a single DMA buffer to the Launcher, but it would be + * more efficient to return a pointer to the entire array of DMA buffers, which + * it can cache and choose one whenever it wants. + * + * Currently the Launcher uses a write to /dev/lguest, and the return value is + * the address of the DMA structure with the interrupt number placed in + * dma->used_len. If we wanted to return the entire array, we need to return + * the address, array size and interrupt number: this seems to require an + * ioctl(). :*/ + +/*L:320 This routine looks for a DMA buffer registered by the Guest on the + * given key (using the BIND_DMA hypercall). */ unsigned long get_dma_buffer(struct lguest *lg, unsigned long ukey, unsigned long *interrupt) { @@ -370,15 +573,29 @@ unsigned long get_dma_buffer(struct lguest *lg, struct lguest_dma_info *i; struct rw_semaphore *fshared = ¤t->mm->mmap_sem; + /* Take the Big Lguest Lock to stop other Guests sending this Guest DMA + * at the same time. */ mutex_lock(&lguest_lock); + /* To match between Guests sharing the same underlying memory we steal + * code from the futex infrastructure. This requires that we hold the + * "mmap_sem" for our process (the Launcher), and pass it to the futex + * code. */ down_read(fshared); + + /* This can fail if it's not a valid address, or if the address is not + * divisible by 4 (the futex code needs that, we don't really). */ if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) { kill_guest(lg, "bad registered DMA buffer"); goto unlock; } + /* Search the hash table for matching entries (the Launcher can only + * send to its own Guest for the moment, so the entry must be for this + * Guest) */ list_for_each_entry(i, &dma_hash[hash(&key)], list) { if (key_eq(&key, &i->key) && i->guestid == lg->guestid) { unsigned int j; + /* Look through the registered DMA array for an + * available buffer. */ for (j = 0; j < i->num_dmas; j++) { struct lguest_dma dma; @@ -387,6 +604,8 @@ unsigned long get_dma_buffer(struct lguest *lg, if (dma.used_len == 0) break; } + /* Store the interrupt the Guest wants when the buffer + * is used. */ *interrupt = i->interrupt; break; } @@ -396,4 +615,12 @@ unlock: mutex_unlock(&lguest_lock); return ret; } +/*:*/ +/*L:410 This really has completed the Launcher. Not only have we now finished + * the longest chapter in our journey, but this also means we are over halfway + * through! + * + * Enough prevaricating around the bush: it is time for us to dive into the + * core of the Host, in "make Host". + */ diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 3e2ddfb..64f0abe 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -58,9 +58,18 @@ struct lguest_dma_info u8 interrupt; /* 0 when not registered */ }; -/* We have separate types for the guest's ptes & pgds and the shadow ptes & - * pgds. Since this host might use three-level pagetables and the guest and - * shadow pagetables don't, we can't use the normal pte_t/pgd_t. */ +/*H:310 The page-table code owes a great debt of gratitude to Andi Kleen. He + * reviewed the original code which used "u32" for all page table entries, and + * insisted that it would be far clearer with explicit typing. I thought it + * was overkill, but he was right: it is much clearer than it was before. + * + * We have separate types for the Guest's ptes & pgds and the shadow ptes & + * pgds. There's already a Linux type for these (pte_t and pgd_t) but they + * change depending on kernel config options (PAE). */ + +/* Each entry is identical: lower 12 bits of flags and upper 20 bits for the + * "page frame number" (0 == first physical page, etc). They are different + * types so the compiler will warn us if we mix them improperly. */ typedef union { struct { unsigned flags:12, pfn:20; }; struct { unsigned long val; } raw; @@ -77,8 +86,12 @@ typedef union { struct { unsigned flags:12, pfn:20; }; struct { unsigned long val; } raw; } gpte_t; + +/* We have two convenient macros to convert a "raw" value as handed to us by + * the Guest into the correct Guest PGD or PTE type. */ #define mkgpte(_val) ((gpte_t){.raw.val = _val}) #define mkgpgd(_val) ((gpgd_t){.raw.val = _val}) +/*:*/ struct pgdir { @@ -243,7 +256,32 @@ unsigned long get_dma_buffer(struct lguest *lg, unsigned long key, /* hypercalls.c: */ void do_hypercalls(struct lguest *lg); - +void write_timestamp(struct lguest *lg); + +/*L:035 + * Let's step aside for the moment, to study one important routine that's used + * widely in the Host code. + * + * There are many cases where the Guest does something invalid, like pass crap + * to a hypercall. Since only the Guest kernel can make hypercalls, it's quite + * acceptable to simply terminate the Guest and give the Launcher a nicely + * formatted reason. It's also simpler for the Guest itself, which doesn't + * need to check most hypercalls for "success"; if you're still running, it + * succeeded. + * + * Once this is called, the Guest will never run again, so most Host code can + * call this then continue as if nothing had happened. This means many + * functions don't have to explicitly return an error code, which keeps the + * code simple. + * + * It also means that this can be called more than once: only the first one is + * remembered. The only trick is that we still need to kill the Guest even if + * we can't allocate memory to store the reason. Linux has a neat way of + * packing error codes into invalid pointers, so we use that here. + * + * Like any macro which uses an "if", it is safely wrapped in a run-once "do { + * } while(0)". + */ #define kill_guest(lg, fmt...) \ do { \ if (!(lg)->dead) { \ @@ -252,6 +290,7 @@ do { \ (lg)->dead = ERR_PTR(-ENOMEM); \ } \ } while(0) +/* (End of aside) :*/ static inline unsigned long guest_pa(struct lguest *lg, unsigned long vaddr) { diff --git a/drivers/lguest/lguest.c b/drivers/lguest/lguest.c index 18dade0..1bc1546 100644 --- a/drivers/lguest/lguest.c +++ b/drivers/lguest/lguest.c @@ -1,6 +1,32 @@ -/* - * Lguest specific paravirt-ops implementation +/*P:010 + * A hypervisor allows multiple Operating Systems to run on a single machine. + * To quote David Wheeler: "Any problem in computer science can be solved with + * another layer of indirection." + * + * We keep things simple in two ways. First, we start with a normal Linux + * kernel and insert a module (lg.ko) which allows us to run other Linux + * kernels the same way we'd run processes. We call the first kernel the Host, + * and the others the Guests. The program which sets up and configures Guests + * (such as the example in Documentation/lguest/lguest.c) is called the + * Launcher. + * + * Secondly, we only run specially modified Guests, not normal kernels. When + * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets + * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows + * how to be a Guest. This means that you can use the same kernel you boot + * normally (ie. as a Host) as a Guest. * + * These Guests know that they cannot do privileged operations, such as disable + * interrupts, and that they have to ask the Host to do such things explicitly. + * This file consists of all the replacements for such low-level native + * hardware operations: these special Guest versions call the Host. + * + * So how does the kernel know it's a Guest? The Guest starts at a special + * entry point marked with a magic string, which sets up a few things then + * calls here. We replace the native functions in "struct paravirt_ops" + * with our Guest versions, then boot like normal. :*/ + +/* * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation. * * This program is free software; you can redistribute it and/or modify @@ -40,6 +66,12 @@ #include <asm/mce.h> #include <asm/io.h> +/*G:010 Welcome to the Guest! + * + * The Guest in our tale is a simple creature: identical to the Host but + * behaving in simplified but equivalent ways. In particular, the Guest is the + * same kernel as the Host (or at least, built from the same source code). :*/ + /* Declarations for definitions in lguest_guest.S */ extern char lguest_noirq_start[], lguest_noirq_end[]; extern const char lgstart_cli[], lgend_cli[]; @@ -58,7 +90,26 @@ struct lguest_data lguest_data = { struct lguest_device_desc *lguest_devices; static cycle_t clock_base; -static enum paravirt_lazy_mode lazy_mode; +/*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first + * real optimization trick! + * + * When lazy_mode is set, it means we're allowed to defer all hypercalls and do + * them as a batch when lazy_mode is eventually turned off. Because hypercalls + * are reasonably expensive, batching them up makes sense. For example, a + * large mmap might update dozens of page table entries: that code calls + * lguest_lazy_mode(PARAVIRT_LAZY_MMU), does the dozen updates, then calls + * lguest_lazy_mode(PARAVIRT_LAZY_NONE). + * + * So, when we're in lazy mode, we call async_hypercall() to store the call for + * future processing. When lazy mode is turned off we issue a hypercall to + * flush the stored calls. + * + * There's also a hack where "mode" is set to "PARAVIRT_LAZY_FLUSH" which + * indicates we're to flush any outstanding calls immediately. This is used + * when an interrupt handler does a kmap_atomic(): the page table changes must + * happen immediately even if we're in the middle of a batch. Usually we're + * not, though, so there's nothing to do. */ +static enum paravirt_lazy_mode lazy_mode; /* Note: not SMP-safe! */ static void lguest_lazy_mode(enum paravirt_lazy_mode mode) { if (mode == PARAVIRT_LAZY_FLUSH) { @@ -82,6 +133,16 @@ static void lazy_hcall(unsigned long call, async_hcall(call, arg1, arg2, arg3); } +/* async_hcall() is pretty simple: I'm quite proud of it really. We have a + * ring buffer of stored hypercalls which the Host will run though next time we + * do a normal hypercall. Each entry in the ring has 4 slots for the hypercall + * arguments, and a "hcall_status" word which is 0 if the call is ready to go, + * and 255 once the Host has finished with it. + * + * If we come around to a slot which hasn't been finished, then the table is + * full and we just make the hypercall directly. This has the nice side + * effect of causing the Host to run all the stored calls in the ring buffer + * which empties it for next time! */ void async_hcall(unsigned long call, unsigned long arg1, unsigned long arg2, unsigned long arg3) { @@ -89,6 +150,9 @@ void async_hcall(unsigned long call, static unsigned int next_call; unsigned long flags; + /* Disable interrupts if not already disabled: we don't want an + * interrupt handler making a hypercall while we're already doing + * one! */ local_irq_save(flags); if (lguest_data.hcall_status[next_call] != 0xFF) { /* Table full, so do normal hcall which will flush table. */ @@ -98,7 +162,7 @@ void async_hcall(unsigned long call, lguest_data.hcalls[next_call].edx = arg1; lguest_data.hcalls[next_call].ebx = arg2; lguest_data.hcalls[next_call].ecx = arg3; - /* Make sure host sees arguments before "valid" flag. */ + /* Arguments must all be written before we mark it to go */ wmb(); lguest_data.hcall_status[next_call] = 0; if (++next_call == LHCALL_RING_SIZE) @@ -106,9 +170,14 @@ void async_hcall(unsigned long call, } local_irq_restore(flags); } +/*:*/ +/* Wrappers for the SEND_DMA and BIND_DMA hypercalls. This is mainly because + * Jeff Garzik complained that __pa() should never appear in drivers, and this + * helps remove most of them. But also, it wraps some ugliness. */ void lguest_send_dma(unsigned long key, struct lguest_dma *dma) { + /* The hcall might not write this if something goes wrong */ dma->used_len = 0; hcall(LHCALL_SEND_DMA, key, __pa(dma), 0); } @@ -116,11 +185,16 @@ void lguest_send_dma(unsigned long key, struct lguest_dma *dma) int lguest_bind_dma(unsigned long key, struct lguest_dma *dmas, unsigned int num, u8 irq) { + /* This is the only hypercall which actually wants 5 arguments, and we + * only support 4. Fortunately the interrupt number is always less + * than 256, so we can pack it with the number of dmas in the final + * argument. */ if (!hcall(LHCALL_BIND_DMA, key, __pa(dmas), (num << 8) | irq)) return -ENOMEM; return 0; } +/* Unbinding is the same hypercall as binding, but with 0 num & irq. */ void lguest_unbind_dma(unsigned long key, struct lguest_dma *dmas) { hcall(LHCALL_BIND_DMA, key, __pa(dmas), 0); @@ -138,35 +212,73 @@ void lguest_unmap(void *addr) iounmap((__force void __iomem *)addr); } +/*G:033 + * Here are our first native-instruction replacements: four functions for + * interrupt control. + * + * The simplest way of implementing these would be to have "turn interrupts + * off" and "turn interrupts on" hypercalls. Unfortunately, this is too slow: + * these are by far the most commonly called functions of those we override. + * + * So instead we keep an "irq_enabled" field inside our "struct lguest_data", + * which the Guest can update with a single instruction. The Host knows to + * check there when it wants to deliver an interrupt. + */ + +/* save_flags() is expected to return the processor state (ie. "eflags"). The + * eflags word contains all kind of stuff, but in practice Linux only cares + * about the interrupt flag. Our "save_flags()" just returns that. */ static unsigned long save_fl(void) { return lguest_data.irq_enabled; } +/* "restore_flags" just sets the flags back to the value given. */ static void restore_fl(unsigned long flags) { - /* FIXME: Check if interrupt pending... */ lguest_data.irq_enabled = flags; } +/* Interrupts go off... */ static void irq_disable(void) { lguest_data.irq_enabled = 0; } +/* Interrupts go on... */ static void irq_enable(void) { - /* FIXME: Check if interrupt pending... */ lguest_data.irq_enabled = X86_EFLAGS_IF; } - +/*:*/ +/*M:003 Note that we don't check for outstanding interrupts when we re-enable + * them (or when we unmask an interrupt). This seems to work for the moment, + * since interrupts are rare and we'll just get the interrupt on the next timer + * tick, but when we turn on CONFIG_NO_HZ, we should revisit this. One way + * would be to put the "irq_enabled" field in a page by itself, and have the + * Host write-protect it when an interrupt comes in when irqs are disabled. + * There will then be a page fault as soon as interrupts are re-enabled. :*/ + +/*G:034 + * The Interrupt Descriptor Table (IDT). + * + * The IDT tells the processor what to do when an interrupt comes in. Each + * entry in the table is a 64-bit descriptor: this holds the privilege level, + * address of the handler, and... well, who cares? The Guest just asks the + * Host to make the change anyway, because the Host controls the real IDT. + */ static void lguest_write_idt_entry(struct desc_struct *dt, int entrynum, u32 low, u32 high) { + /* Keep the local copy up to date. */ write_dt_entry(dt, entrynum, low, high); + /* Tell Host about this new entry. */ hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, low, high); } +/* Changing to a different IDT is very rare: we keep the IDT up-to-date every + * time it is written, so we can simply loop through all entries and tell the + * Host about them. */ static void lguest_load_idt(const struct Xgt_desc_struct *desc) { unsigned int i; @@ -176,12 +288,29 @@ static void lguest_load_idt(const struct Xgt_desc_struct *desc) hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b); } +/* + * The Global Descriptor Table. + * + * The Intel architecture defines another table, called the Global Descriptor + * Table (GDT). You tell the CPU where it is (and its size) using the "lgdt" + * instruction, and then several other instructions refer to entries in the + * table. There are three entries which the Switcher needs, so the Host simply + * controls the entire thing and the Guest asks it to make changes using the + * LOAD_GDT hypercall. + * + * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY + * hypercall and use that repeatedly to load a new IDT. I don't think it + * really matters, but wouldn't it be nice if they were the same? + */ static void lguest_load_gdt(const struct Xgt_desc_struct *desc) { BUG_ON((desc->size+1)/8 != GDT_ENTRIES); hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0); } +/* For a single GDT entry which changes, we do the lazy thing: alter our GDT, + * then tell the Host to reload the entire thing. This operation is so rare + * that this naive implementation is reasonable. */ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum, u32 low, u32 high) { @@ -189,19 +318,58 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, hcall(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES, 0); } +/* OK, I lied. There are three "thread local storage" GDT entries which change + * on every context switch (these three entries are how glibc implements + * __thread variables). So we have a hypercall specifically for this case. */ static void lguest_load_tls(struct thread_struct *t, unsigned int cpu) { lazy_hcall(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu, 0); } +/*:*/ +/*G:038 That's enough excitement for now, back to ploughing through each of + * the paravirt_ops (we're about 1/3 of the way through). + * + * This is the Local Descriptor Table, another weird Intel thingy. Linux only + * uses this for some strange applications like Wine. We don't do anything + * here, so they'll get an informative and friendly Segmentation Fault. */ static void lguest_set_ldt(const void *addr, unsigned entries) { } +/* This loads a GDT entry into the "Task Register": that entry points to a + * structure called the Task State Segment. Some comments scattered though the + * kernel code indicate that this used for task switching in ages past, along + * with blood sacrifice and astrology. + * + * Now there's nothing interesting in here that we don't get told elsewhere. + * But the native version uses the "ltr" instruction, which makes the Host + * complain to the Guest about a Segmentation Fault and it'll oops. So we + * override the native version with a do-nothing version. */ static void lguest_load_tr_desc(void) { } +/* The "cpuid" instruction is a way of querying both the CPU identity + * (manufacturer, model, etc) and its features. It was introduced before the + * Pentium in 1993 and keeps getting extended by both Intel and AMD. As you + * might imagine, after a decade and a half this treatment, it is now a giant + * ball of hair. Its entry in the current Intel manual runs to 28 pages. + * + * This instruction even it has its own Wikipedia entry. The Wikipedia entry + * has been translated into 4 languages. I am not making this up! + * + * We could get funky here and identify ourselves as "GenuineLguest", but + * instead we just use the real "cpuid" instruction. Then I pretty much turned + * off feature bits until the Guest booted. (Don't say that: you'll damage + * lguest sales!) Shut up, inner voice! (Hey, just pointing out that this is + * hardly future proof.) Noone's listening! They don't like you anyway, + * parenthetic weirdo! + * + * Replacing the cpuid so we can turn features off is great for the kernel, but + * anyone (including userspace) can just use the raw "cpuid" instruction and + * the Host won't even notice since it isn't privileged. So we try not to get + * too worked up about it. */ static void lguest_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { @@ -214,21 +382,43 @@ static void lguest_cpuid(unsigned int *eax, unsigned int *ebx, *ecx &= 0x00002201; /* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, FPU. */ *edx &= 0x07808101; - /* Host wants to know when we flush kernel pages: set PGE. */ + /* The Host can do a nice optimization if it knows that the + * kernel mappings (addresses above 0xC0000000 or whatever + * PAGE_OFFSET is set to) haven't changed. But Linux calls + * flush_tlb_user() for both user and kernel mappings unless + * the Page Global Enable (PGE) feature bit is set. */ *edx |= 0x00002000; break; case 0x80000000: /* Futureproof this a little: if they ask how much extended - * processor information, limit it to known fields. */ + * processor information there is, limit it to known fields. */ if (*eax > 0x80000008) *eax = 0x80000008; break; } } +/* Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4. + * I assume there's a cr1, but it hasn't bothered us yet, so we'll not bother + * it. The Host needs to know when the Guest wants to change them, so we have + * a whole series of functions like read_cr0() and write_cr0(). + * + * We start with CR0. CR0 allows you to turn on and off all kinds of basic + * features, but Linux only really cares about one: the horrifically-named Task + * Switched (TS) bit at bit 3 (ie. 8) + * + * What does the TS bit do? Well, it causes the CPU to trap (interrupt 7) if + * the floating point unit is used. Which allows us to restore FPU state + * lazily after a task switch, and Linux uses that gratefully, but wouldn't a + * name like "FPUTRAP bit" be a little less cryptic? + * + * We store cr0 (and cr3) locally, because the Host never changes it. The + * Guest sometimes wants to read it and we'd prefer not to bother the Host + * unnecessarily. */ static unsigned long current_cr0, current_cr3; static void lguest_write_cr0(unsigned long val) { + /* 8 == TS bit. */ lazy_hcall(LHCALL_TS, val & 8, 0, 0); current_cr0 = val; } @@ -238,17 +428,25 @@ static unsigned long lguest_read_cr0(void) return current_cr0; } +/* Intel provided a special instruction to clear the TS bit for people too cool + * to use write_cr0() to do it. This "clts" instruction is faster, because all + * the vowels have been optimized out. */ static void lguest_clts(void) { lazy_hcall(LHCALL_TS, 0, 0, 0); current_cr0 &= ~8U; } +/* CR2 is the virtual address of the last page fault, which the Guest only ever + * reads. The Host kindly writes this into our "struct lguest_data", so we + * just read it out of there. */ static unsigned long lguest_read_cr2(void) { return lguest_data.cr2; } +/* CR3 is the current toplevel pagetable page: the principle is the same as + * cr0. Keep a local copy, and tell the Host when it changes. */ static void lguest_write_cr3(unsigned long cr3) { lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0); @@ -260,7 +458,7 @@ static unsigned long lguest_read_cr3(void) return current_cr3; } -/* Used to enable/disable PGE, but we don't care. */ +/* CR4 is used to enable and disable PGE, but we don't care. */ static unsigned long lguest_read_cr4(void) { return 0; @@ -270,6 +468,59 @@ static void lguest_write_cr4(unsigned long val) { } +/* + * Page Table Handling. + * + * Now would be a good time to take a rest and grab a coffee or similarly + * relaxing stimulant. The easy parts are behind us, and the trek gradually + * winds uphill from here. + * + * Quick refresher: memory is divided into "pages" of 4096 bytes each. The CPU + * maps virtual addresses to physical addresses using "page tables". We could + * use one huge index of 1 million entries: each address is 4 bytes, so that's + * 1024 pages just to hold the page tables. But since most virtual addresses + * are unused, we use a two level index which saves space. The CR3 register + * contains the physical address of the top level "page directory" page, which + * contains physical addresses of up to 1024 second-level pages. Each of these + * second level pages contains up to 1024 physical addresses of actual pages, + * or Page Table Entries (PTEs). + * + * Here's a diagram, where arrows indicate physical addresses: + * + * CR3 ---> +---------+ + * | --------->+---------+ + * | | | PADDR1 | + * Top-level | | PADDR2 | + * (PMD) page | | | + * | | Lower-level | + * | | (PTE) page | + * | | | | + * .... .... + * + * So to convert a virtual address to a physical address, we look up the top + * level, which points us to the second level, which gives us the physical + * address of that page. If the top level entry was not present, or the second + * level entry was not present, then the virtual address is invalid (we + * say "the page was not mapped"). + * + * Put another way, a 32-bit virtual address is divided up like so: + * + * 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + * |<---- 10 bits ---->|<---- 10 bits ---->|<------ 12 bits ------>| + * Index into top Index into second Offset within page + * page directory page pagetable page + * + * The kernel spends a lot of time changing both the top-level page directory + * and lower-level pagetable pages. The Guest doesn't know physical addresses, + * so while it maintains these page tables exactly like normal, it also needs + * to keep the Host informed whenever it makes a change: the Host will create + * the real page tables based on the Guests'. + */ + +/* The Guest calls this to set a second-level entry (pte), ie. to map a page + * into a process' address space. We set the entry then tell the Host the + * toplevel and address this corresponds to. The Guest uses one pagetable per + * process, so we need to tell the Host which one we're changing (mm->pgd). */ static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { @@ -277,7 +528,9 @@ static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr, lazy_hcall(LHCALL_SET_PTE, __pa(mm->pgd), addr, pteval.pte_low); } -/* We only support two-level pagetables at the moment. */ +/* The Guest calls this to set a top-level entry. Again, we set the entry then + * tell the Host which top-level page we changed, and the index of the entry we + * changed. */ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) { *pmdp = pmdval; @@ -285,7 +538,15 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) (__pa(pmdp)&(PAGE_SIZE-1))/4, 0); } -/* FIXME: Eliminate all callers of this. */ +/* There are a couple of legacy places where the kernel sets a PTE, but we + * don't know the top level any more. This is useless for us, since we don't + * know which pagetable is changing or what address, so we just tell the Host + * to forget all of them. Fortunately, this is very rare. + * + * ... except in early boot when the kernel sets up the initial pagetables, + * which makes booting astonishingly slow. So we don't even tell the Host + * anything changed until we've done the first page table switch. + */ static void lguest_set_pte(pte_t *ptep, pte_t pteval) { *ptep = pteval; @@ -294,22 +555,51 @@ static void lguest_set_pte(pte_t *ptep, pte_t pteval) lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0); } +/* Unfortunately for Lguest, the paravirt_ops for page tables were based on + * native page table operations. On native hardware you can set a new page + * table entry whenever you want, but if you want to remove one you have to do + * a TLB flush (a TLB is a little cache of page table entries kept by the CPU). + * + * So the lguest_set_pte_at() and lguest_set_pmd() functions above are only + * called when a valid entry is written, not when it's removed (ie. marked not + * present). Instead, this is where we come when the Guest wants to remove a + * page table entry: we tell the Host to set that entry to 0 (ie. the present + * bit is zero). */ static void lguest_flush_tlb_single(unsigned long addr) { - /* Simply set it to zero, and it will fault back in. */ + /* Simply set it to zero: if it was not, it will fault back in. */ lazy_hcall(LHCALL_SET_PTE, current_cr3, addr, 0); } +/* This is what happens after the Guest has removed a large number of entries. + * This tells the Host that any of the page table entries for userspace might + * have changed, ie. virtual addresses below PAGE_OFFSET. */ static void lguest_flush_tlb_user(void) { lazy_hcall(LHCALL_FLUSH_TLB, 0, 0, 0); } +/* This is called when the kernel page tables have changed. That's not very + * common (unless the Guest is using highmem, which makes the Guest extremely + * slow), so it's worth separating this from the user flushing above. */ static void lguest_flush_tlb_kernel(void) { lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0); } +/* + * The Unadvanced Programmable Interrupt Controller. + * + * This is an attempt to implement the simplest possible interrupt controller. + * I spent some time looking though routines like set_irq_chip_and_handler, + * set_irq_chip_and_handler_name, set_irq_chip_data and set_phasers_to_stun and + * I *think* this is as simple as it gets. + * + * We can tell the Host what interrupts we want blocked ready for using the + * lguest_data.interrupts bitmap, so disabling (aka "masking") them is as + * simple as setting a bit. We don't actually "ack" interrupts as such, we + * just mask and unmask them. I wonder if we should be cleverer? + */ static void disable_lguest_irq(unsigned int irq) { set_bit(irq, lguest_data.blocked_interrupts); @@ -318,9 +608,9 @@ static void disable_lguest_irq(unsigned int irq) static void enable_lguest_irq(unsigned int irq) { clear_bit(irq, lguest_data.blocked_interrupts); - /* FIXME: If it's pending? */ } +/* This structure describes the lguest IRQ controller. */ static struct irq_chip lguest_irq_controller = { .name = "lguest", .mask = disable_lguest_irq, @@ -328,6 +618,10 @@ static struct irq_chip lguest_irq_controller = { .unmask = enable_lguest_irq, }; +/* This sets up the Interrupt Descriptor Table (IDT) entry for each hardware + * interrupt (except 128, which is used for system calls), and then tells the + * Linux infrastructure that each interrupt is controlled by our level-based + * lguest interrupt controller. */ static void __init lguest_init_IRQ(void) { unsigned int i; @@ -340,20 +634,51 @@ static void __init lguest_init_IRQ(void) handle_level_irq); } } + /* This call is required to set up for 4k stacks, where we have + * separate stacks for hard and soft interrupts. */ irq_ctx_init(smp_processor_id()); } +/* + * Time. + * + * It would be far better for everyone if the Guest had its own clock, but + * until then the Host gives us the time on every interrupt. + */ static unsigned long lguest_get_wallclock(void) { - return hcall(LHCALL_GET_WALLCLOCK, 0, 0, 0); + return lguest_data.time.tv_sec; } static cycle_t lguest_clock_read(void) { + unsigned long sec, nsec; + + /* If the Host tells the TSC speed, we can trust that. */ if (lguest_data.tsc_khz) return native_read_tsc(); - else - return jiffies; + + /* If we can't use the TSC, we read the time value written by the Host. + * Since it's in two parts (seconds and nanoseconds), we risk reading + * it just as it's changing from 99 & 0.999999999 to 100 and 0, and + * getting 99 and 0. As Linux tends to come apart under the stress of + * time travel, we must be careful: */ + do { + /* First we read the seconds part. */ + sec = lguest_data.time.tv_sec; + /* This read memory barrier tells the compiler and the CPU that + * this can't be reordered: we have to complete the above + * before going on. */ + rmb(); + /* Now we read the nanoseconds part. */ + nsec = lguest_data.time.tv_nsec; + /* Make sure we've done that. */ + rmb(); + /* Now if the seconds part has changed, try again. */ + } while (unlikely(lguest_data.time.tv_sec != sec)); + + /* Our non-TSC clock is in real nanoseconds. */ + return sec*1000000000ULL + nsec; } /* This is what we tell the kernel is our clocksource. */ @@ -361,8 +686,11 @@ static struct clocksource lguest_clock = { .name = "lguest", .rating = 400, .read = lguest_clock_read, + .mask = CLOCKSOURCE_MASK(64), + .mult = 1, }; +/* The "scheduler clock" is just our real clock, adjusted to start at zero */ static unsigned long long lguest_sched_clock(void) { return cyc2ns(&lguest_clock, lguest_clock_read() - clock_base); @@ -428,34 +756,55 @@ static void lguest_time_irq(unsigned int irq, struct irq_desc *desc) local_irq_restore(flags); } +/* At some point in the boot process, we get asked to set up our timing + * infrastructure. The kernel doesn't expect timer interrupts before this, but + * we cleverly initialized the "blocked_interrupts" field of "struct + * lguest_data" so that timer interrupts were blocked until now. */ static void lguest_time_init(void) { + /* Set up the timer interrupt (0) to go to our simple timer routine */ set_irq_handler(0, lguest_time_irq); - /* We use the TSC if the Host tells us we can, otherwise a dumb - * jiffies-based clock. */ + /* Our clock structure look like arch/i386/kernel/tsc.c if we can use + * the TSC, otherwise it's a dumb nanosecond-resolution clock. Either + * way, the "rating" is initialized so high that it's always chosen + * over any other clocksource. */ if (lguest_data.tsc_khz) { lguest_clock.shift = 22; lguest_clock.mult = clocksource_khz2mult(lguest_data.tsc_khz, lguest_clock.shift); - lguest_clock.mask = CLOCKSOURCE_MASK(64); lguest_clock.flags = CLOCK_SOURCE_IS_CONTINUOUS; - } else { - /* To understand this, start at kernel/time/jiffies.c... */ - lguest_clock.shift = 8; - lguest_clock.mult = (((u64)NSEC_PER_SEC<<8)/ACTHZ) << 8; - lguest_clock.mask = CLOCKSOURCE_MASK(32); } clock_base = lguest_clock_read(); clocksource_register(&lguest_clock); - /* We can't set cpumask in the initializer: damn C limitations! */ + /* Now we've set up our clock, we can use it as the scheduler clock */ + paravirt_ops.sched_clock = lguest_sched_clock; + + /* We can't set cpumask in the initializer: damn C limitations! Set it + * here and register our timer device. */ lguest_clockevent.cpumask = cpumask_of_cpu(0); clockevents_register_device(&lguest_clockevent); + /* Finally, we unblock the timer interrupt. */ enable_lguest_irq(0); } +/* + * Miscellaneous bits and pieces. + * + * Here is an oddball collection of functions which the Guest needs for things + * to work. They're pretty simple. + */ + +/* The Guest needs to tell the host what stack it expects traps to use. For + * native hardware, this is part of the Task State Segment mentioned above in + * lguest_load_tr_desc(), but to help hypervisors there's this special call. + * + * We tell the Host the segment we want to use (__KERNEL_DS is the kernel data + * segment), the privilege level (we're privilege level 1, the Host is 0 and + * will not tolerate us trying to use that), the stack pointer, and the number + * of pages in the stack. */ static void lguest_load_esp0(struct tss_struct *tss, struct thread_struct *thread) { @@ -463,15 +812,31 @@ static void lguest_load_esp0(struct tss_struct *tss, THREAD_SIZE/PAGE_SIZE); } +/* Let's just say, I wouldn't do debugging under a Guest. */ static void lguest_set_debugreg(int regno, unsigned long value) { /* FIXME: Implement */ } +/* There are times when the kernel wants to make sure that no memory writes are + * caught in the cache (that they've all reached real hardware devices). This + * doesn't matter for the Guest which has virtual hardware. + * + * On the Pentium 4 and above, cpuid() indicates that the Cache Line Flush + * (clflush) instruction is available and the kernel uses that. Otherwise, it + * uses the older "Write Back and Invalidate Cache" (wbinvd) instruction. + * Unlike clflush, wbinvd can only be run at privilege level 0. So we can + * ignore clflush, but replace wbinvd. + */ static void lguest_wbinvd(void) { } +/* If the Guest expects to have an Advanced Programmable Interrupt Controller, + * we play dumb by ignoring writes and returning 0 for reads. So it's no + * longer Programmable nor Controlling anything, and I don't think 8 lines of + * code qualifies for Advanced. It will also never interrupt anything. It + * does, however, allow us to get through the Linux boot code. */ #ifdef CONFIG_X86_LOCAL_APIC static void lguest_apic_write(unsigned long reg, unsigned long v) { @@ -483,19 +848,32 @@ static unsigned long lguest_apic_read(unsigned long reg) } #endif +/* STOP! Until an interrupt comes in. */ static void lguest_safe_halt(void) { hcall(LHCALL_HALT, 0, 0, 0); } +/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a + * message out when we're crashing as well as elegant termination like powering + * off. + * + * Note that the Host always prefers that the Guest speak in physical addresses + * rather than virtual addresses, so we use __pa() here. */ static void lguest_power_off(void) { hcall(LHCALL_CRASH, __pa("Power down"), 0, 0); } +/* + * Panicing. + * + * Don't. But if you did, this is what happens. + */ static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) { hcall(LHCALL_CRASH, __pa(p), 0, 0); + /* The hcall won't return, but to keep gcc happy, we're "done". */ return NOTIFY_DONE; } @@ -503,15 +881,45 @@ static struct notifier_block paniced = { .notifier_call = lguest_panic }; +/* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { - /* We do this here because lockcheck barfs if before start_kernel */ + /* We do this here and not earlier because lockcheck barfs if we do it + * before start_kernel() */ atomic_notifier_chain_register(&panic_notifier_list, &paniced); + /* The Linux bootloader header contains an "e820" memory map: the + * Launcher populated the first entry with our memory limit. */ add_memory_region(E820_MAP->addr, E820_MAP->size, E820_MAP->type); + + /* This string is for the boot messages. */ return "LGUEST"; } +/*G:050 + * Patching (Powerfully Placating Performance Pedants) + * + * We have already seen that "struct paravirt_ops" lets us replace simple + * native instructions with calls to the appropriate back end all throughout + * the kernel. This allows the same kernel to run as a Guest and as a native + * kernel, but it's slow because of all the indirect branches. + * + * Remember that David Wheeler quote about "Any problem in computer science can + * be solved with another layer of indirection"? The rest of that quote is + * "... But that usually will create another problem." This is the first of + * those problems. + * + * Our current solution is to allow the paravirt back end to optionally patch + * over the indirect calls to replace them with something more efficient. We + * patch the four most commonly called functions: disable interrupts, enable + * interrupts, restore interrupts and save interrupts. We usually have 10 + * bytes to patch into: the Guest versions of these operations are small enough + * that we can fit comfortably. + * + * First we need assembly templates of each of the patchable Guest operations, + * and these are in lguest_asm.S. */ + +/*G:060 We construct a table from the assembler templates: */ static const struct lguest_insns { const char *start, *end; @@ -521,35 +929,52 @@ static const struct lguest_insns [PARAVIRT_PATCH(restore_fl)] = { lgstart_popf, lgend_popf }, [PARAVIRT_PATCH(save_fl)] = { lgstart_pushf, lgend_pushf }, }; + +/* Now our patch routine is fairly simple (based on the native one in + * paravirt.c). If we have a replacement, we copy it in and return how much of + * the available space we used. */ static unsigned lguest_patch(u8 type, u16 clobber, void *insns, unsigned len) { unsigned int insn_len; - /* Don't touch it if we don't have a replacement */ + /* Don't do anything special if we don't have a replacement */ if (type >= ARRAY_SIZE(lguest_insns) || !lguest_insns[type].start) return paravirt_patch_default(type, clobber, insns, len); insn_len = lguest_insns[type].end - lguest_insns[type].start; - /* Similarly if we can't fit replacement. */ + /* Similarly if we can't fit replacement (shouldn't happen, but let's + * be thorough). */ if (len < insn_len) return paravirt_patch_default(type, clobber, insns, len); + /* Copy in our instructions. */ memcpy(insns, lguest_insns[type].start, insn_len); return insn_len; } +/*G:030 Once we get to lguest_init(), we know we're a Guest. The paravirt_ops + * structure in the kernel provides a single point for (almost) every routine + * we have to override to avoid privileged instructions. */ __init void lguest_init(void *boot) { - /* Copy boot parameters first. */ + /* Copy boot parameters first: the Launcher put the physical location + * in %esi, and head.S converted that to a virtual address and handed + * it to us. */ memcpy(&boot_params, boot, PARAM_SIZE); + /* The boot parameters also tell us where the command-line is: save + * that, too. */ memcpy(boot_command_line, __va(boot_params.hdr.cmd_line_ptr), COMMAND_LINE_SIZE); + /* We're under lguest, paravirt is enabled, and we're running at + * privilege level 1, not 0 as normal. */ paravirt_ops.name = "lguest"; paravirt_ops.paravirt_enabled = 1; paravirt_ops.kernel_rpl = 1; + /* We set up all the lguest overrides for sensitive operations. These + * are detailed with the operations themselves. */ paravirt_ops.save_fl = save_fl; paravirt_ops.restore_fl = restore_fl; paravirt_ops.irq_disable = irq_disable; @@ -592,21 +1017,50 @@ __init void lguest_init(void *boot) paravirt_ops.time_init = lguest_time_init; paravirt_ops.set_lazy_mode = lguest_lazy_mode; paravirt_ops.wbinvd = lguest_wbinvd; - paravirt_ops.sched_clock = lguest_sched_clock; - + /* Now is a good time to look at the implementations of these functions + * before returning to the rest of lguest_init(). */ + + /*G:070 Now we've seen all the paravirt_ops, we return to + * lguest_init() where the rest of the fairly chaotic boot setup + * occurs. + * + * The Host expects our first hypercall to tell it where our "struct + * lguest_data" is, so we do that first. */ hcall(LHCALL_LGUEST_INIT, __pa(&lguest_data), 0, 0); - /* We use top of mem for initial pagetables. */ + /* The native boot code sets up initial page tables immediately after + * the kernel itself, and sets init_pg_tables_end so they're not + * clobbered. The Launcher places our initial pagetables somewhere at + * the top of our physical memory, so we don't need extra space: set + * init_pg_tables_end to the end of the kernel. */ init_pg_tables_end = __pa(pg0); + /* Load the %fs segment register (the per-cpu segment register) with + * the normal data segment to get through booting. */ asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory"); + /* Clear the part of the kernel data which is expected to be zero. + * Normally it will be anyway, but if we're loading from a bzImage with + * CONFIG_RELOCATALE=y, the relocations will be sitting here. */ + memset(__bss_start, 0, __bss_stop - __bss_start); + + /* The Host uses the top of the Guest's virtual address space for the + * Host<->Guest Switcher, and it tells us how much it needs in + * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */ reserve_top_address(lguest_data.reserve_mem); + /* If we don't initialize the lock dependency checker now, it crashes + * paravirt_disable_iospace. */ lockdep_init(); + /* The IDE code spends about 3 seconds probing for disks: if we reserve + * all the I/O ports up front it can't get them and so doesn't probe. + * Other device drivers are similar (but less severe). This cuts the + * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. */ paravirt_disable_iospace(); + /* This is messy CPU setup stuff which the native boot code does before + * start_kernel, so we have to do, too: */ cpu_detect(&new_cpu_data); /* head.S usually sets up the first capability word, so do it here. */ new_cpu_data.x86_capability[0] = cpuid_edx(1); @@ -617,14 +1071,27 @@ __init void lguest_init(void *boot) #ifdef CONFIG_X86_MCE mce_disabled = 1; #endif - #ifdef CONFIG_ACPI acpi_disabled = 1; acpi_ht = 0; #endif + /* We set the perferred console to "hvc". This is the "hypervisor + * virtual console" driver written by the PowerPC people, which we also + * adapted for lguest's use. */ add_preferred_console("hvc", 0, NULL); + /* Last of all, we set the power management poweroff hook to point to + * the Guest routine to power off. */ pm_power_off = lguest_power_off; + + /* Now we're set up, call start_kernel() in init/main.c and we proceed + * to boot as normal. It never returns. */ start_kernel(); } +/* + * This marks the end of stage II of our journey, The Guest. + * + * It is now time for us to explore the nooks and crannies of the three Guest + * devices and complete our understanding of the Guest in "make Drivers". + */ diff --git a/drivers/lguest/lguest_asm.S b/drivers/lguest/lguest_asm.S index a3dbf22..f182c6a 100644 --- a/drivers/lguest/lguest_asm.S +++ b/drivers/lguest/lguest_asm.S @@ -4,15 +4,15 @@ #include <asm/thread_info.h> #include <asm/processor-flags.h> -/* - * This is where we begin: we have a magic signature which the launcher looks - * for. The plan is that the Linux boot protocol will be extended with a +/*G:020 This is where we begin: we have a magic signature which the launcher + * looks for. The plan is that the Linux boot protocol will be extended with a * "platform type" field which will guide us here from the normal entry point, - * but for the moment this suffices. We pass the virtual address of the boot - * info to lguest_init(). + * but for the moment this suffices. The normal boot code uses %esi for the + * boot header, so we do too. We convert it to a virtual address by adding + * PAGE_OFFSET, and hand it to lguest_init() as its argument (ie. %eax). * - * We put it in .init.text will be discarded after boot. - */ + * The .section line puts this code in .init.text so it will be discarded after + * boot. */ .section .init.text, "ax", @progbits .ascii "GenuineLguest" /* Set up initial stack. */ @@ -21,7 +21,9 @@ addl $__PAGE_OFFSET, %eax jmp lguest_init -/* The templates for inline patching. */ +/*G:055 We create a macro which puts the assembler code between lgstart_ and + * lgend_ markers. These templates end up in the .init.text section, so they + * are discarded after boot. */ #define LGUEST_PATCH(name, insns...) \ lgstart_##name: insns; lgend_##name:; \ .globl lgstart_##name; .globl lgend_##name @@ -30,24 +32,61 @@ LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled) LGUEST_PATCH(sti, movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled) LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled) LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax) +/*:*/ .text /* These demark the EIP range where host should never deliver interrupts. */ .global lguest_noirq_start .global lguest_noirq_end -/* - * We move eflags word to lguest_data.irq_enabled to restore interrupt state. - * For page faults, gpfs and virtual interrupts, the hypervisor has saved - * eflags manually, otherwise it was delivered directly and so eflags reflects - * the real machine IF state, ie. interrupts on. Since the kernel always dies - * if it takes such a trap with interrupts disabled anyway, turning interrupts - * back on unconditionally here is OK. - */ +/*M:004 When the Host reflects a trap or injects an interrupt into the Guest, + * it sets the eflags interrupt bit on the stack based on + * lguest_data.irq_enabled, so the Guest iret logic does the right thing when + * restoring it. However, when the Host sets the Guest up for direct traps, + * such as system calls, the processor is the one to push eflags onto the + * stack, and the interrupt bit will be 1 (in reality, interrupts are always + * enabled in the Guest). + * + * This turns out to be harmless: the only trap which should happen under Linux + * with interrupts disabled is Page Fault (due to our lazy mapping of vmalloc + * regions), which has to be reflected through the Host anyway. If another + * trap *does* go off when interrupts are disabled, the Guest will panic, and + * we'll never get to this iret! :*/ + +/*G:045 There is one final paravirt_op that the Guest implements, and glancing + * at it you can see why I left it to last. It's *cool*! It's in *assembler*! + * + * The "iret" instruction is used to return from an interrupt or trap. The + * stack looks like this: + * old address + * old code segment & privilege level + * old processor flags ("eflags") + * + * The "iret" instruction pops those values off the stack and restores them all + * at once. The only problem is that eflags includes the Interrupt Flag which + * the Guest can't change: the CPU will simply ignore it when we do an "iret". + * So we have to copy eflags from the stack to lguest_data.irq_enabled before + * we do the "iret". + * + * There are two problems with this: firstly, we need to use a register to do + * the copy and secondly, the whole thing needs to be atomic. The first + * problem is easy to solve: push %eax on the stack so we can use it, and then + * restore it at the end just before the real "iret". + * + * The second is harder: copying eflags to lguest_data.irq_enabled will turn + * interrupts on before we're finished, so we could be interrupted before we + * return to userspace or wherever. Our solution to this is to surround the + * code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the + * Host that it is *never* to interrupt us there, even if interrupts seem to be + * enabled. */ ENTRY(lguest_iret) pushl %eax movl 12(%esp), %eax lguest_noirq_start: + /* Note the %ss: segment prefix here. Normal data accesses use the + * "ds" segment, but that will have already been restored for whatever + * we're returning to (such as userspace): we can't trust it. The %ss: + * prefix makes sure we use the stack segment, which is still valid. */ movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled popl %eax iret diff --git a/drivers/lguest/lguest_bus.c b/drivers/lguest/lguest_bus.c index 18d6ab2..55a7940 100644 --- a/drivers/lguest/lguest_bus.c +++ b/drivers/lguest/lguest_bus.c @@ -1,3 +1,6 @@ +/*P:050 Lguest guests use a very simple bus for devices. It's a simple array + * of device descriptors contained just above the top of normal memory. The + * lguest bus is 80% tedious boilerplate code. :*/ #include <linux/init.h> #include <linux/bootmem.h> #include <linux/lguest_bus.h> @@ -43,6 +46,10 @@ static struct device_attribute lguest_dev_attrs[] = { __ATTR_NULL }; +/*D:130 The generic bus infrastructure requires a function which says whether a + * device matches a driver. For us, it is simple: "struct lguest_driver" + * contains a "device_type" field which indicates what type of device it can + * handle, so we just cast the args and compare: */ static int lguest_dev_match(struct device *_dev, struct device_driver *_drv) { struct lguest_device *dev = container_of(_dev,struct lguest_device,dev); @@ -50,6 +57,7 @@ static int lguest_dev_match(struct device *_dev, struct device_driver *_drv) return (drv->device_type == lguest_devices[dev->index].type); } +/*:*/ struct lguest_bus { struct bus_type bus; @@ -68,11 +76,24 @@ static struct lguest_bus lguest_bus = { } }; +/*D:140 This is the callback which occurs once the bus infrastructure matches + * up a device and driver, ie. in response to add_lguest_device() calling + * device_register(), or register_lguest_driver() calling driver_register(). + * + * At the moment it's always the latter: the devices are added first, since + * scan_devices() is called from a "core_initcall", and the drivers themselves + * called later as a normal "initcall". But it would work the other way too. + * + * So now we have the happy couple, we add the status bit to indicate that we + * found a driver. If the driver truly loves the device, it will return + * happiness from its probe function (ok, perhaps this wasn't my greatest + * analogy), and we set the final "driver ok" bit so the Host sees it's all + * green. */ static int lguest_dev_probe(struct device *_dev) { int ret; - struct lguest_device *dev = container_of(_dev,struct lguest_device,dev); - struct lguest_driver *drv = container_of(dev->dev.driver, + struct lguest_device*dev = container_of(_dev,struct lguest_device,dev); + struct lguest_driver*drv = container_of(dev->dev.driver, struct lguest_driver, drv); lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER; @@ -82,6 +103,10 @@ static int lguest_dev_probe(struct device *_dev) return ret; } +/* The last part of the bus infrastructure is the function lguest drivers use + * to register themselves. Firstly, we do nothing if there's no lguest bus + * (ie. this is not a Guest), otherwise we fill in the embedded generic "struct + * driver" fields and call the generic driver_register(). */ int register_lguest_driver(struct lguest_driver *drv) { if (!lguest_devices) @@ -94,12 +119,36 @@ int register_lguest_driver(struct lguest_driver *drv) return driver_register(&drv->drv); } + +/* At the moment we build all the drivers into the kernel because they're so + * simple: 8144 bytes for all three of them as I type this. And as the console + * really needs to be built in, it's actually only 3527 bytes for the network + * and block drivers. + * + * If they get complex it will make sense for them to be modularized, so we + * need to explicitly export the symbol. + * + * I don't think non-GPL modules make sense, so it's a GPL-only export. + */ EXPORT_SYMBOL_GPL(register_lguest_driver); +/*D:120 This is the core of the lguest bus: actually adding a new device. + * It's a separate function because it's neater that way, and because an + * earlier version of the code supported hotplug and unplug. They were removed + * early on because they were never used. + * + * As Andrew Tridgell says, "Untested code is buggy code". + * + * It's worth reading this carefully: we start with an index into the array of + * "struct lguest_device_desc"s indicating the device which is new: */ static void add_lguest_device(unsigned int index) { struct lguest_device *new; + /* Each "struct lguest_device_desc" has a "status" field, which the + * Guest updates as the device is probed. In the worst case, the Host + * can look at these bits to tell what part of device setup failed, + * even if the console isn't available. */ lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE; new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL); if (!new) { @@ -108,12 +157,17 @@ static void add_lguest_device(unsigned int index) return; } + /* The "struct lguest_device" setup is pretty straight-forward example + * code. */ new->index = index; new->private = NULL; memset(&new->dev, 0, sizeof(new->dev)); new->dev.parent = &lguest_bus.dev; new->dev.bus = &lguest_bus.bus; sprintf(new->dev.bus_id, "%u", index); + + /* device_register() causes the bus infrastructure to look for a + * matching driver. */ if (device_register(&new->dev) != 0) { printk(KERN_EMERG "Cannot register lguest device %u\n", index); lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED; @@ -121,6 +175,9 @@ static void add_lguest_device(unsigned int index) } } +/*D:110 scan_devices() simply iterates through the device array. The type 0 + * is reserved to mean "no device", and anything else means we have found a + * device: add it. */ static void scan_devices(void) { unsigned int i; @@ -130,12 +187,23 @@ static void scan_devices(void) add_lguest_device(i); } +/*D:100 Fairly early in boot, lguest_bus_init() is called to set up the lguest + * bus. We check that we are a Guest by checking paravirt_ops.name: there are + * other ways of checking, but this seems most obvious to me. + * + * So we can access the array of "struct lguest_device_desc"s easily, we map + * that memory and store the pointer in the global "lguest_devices". Then we + * register the bus with the core. Doing two registrations seems clunky to me, + * but it seems to be the correct sysfs incantation. + * + * Finally we call scan_devices() which adds all the devices found in the + * "struct lguest_device_desc" array. */ static int __init lguest_bus_init(void) { if (strcmp(paravirt_ops.name, "lguest") != 0) return 0; - /* Devices are in page above top of "normal" mem. */ + /* Devices are in a single page above top of "normal" mem */ lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1); if (bus_register(&lguest_bus.bus) != 0 @@ -145,4 +213,5 @@ static int __init lguest_bus_init(void) scan_devices(); return 0; } +/* Do this after core stuff, before devices. */ postcore_initcall(lguest_bus_init); diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index e90d7a7..80d1b58 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -1,36 +1,70 @@ -/* Userspace control of the guest, via /dev/lguest. */ +/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher + * controls and communicates with the Guest. For example, the first write will + * tell us the memory size, pagetable, entry point and kernel address offset. + * A read will run the Guest until a signal is pending (-EINTR), or the Guest + * does a DMA out to the Launcher. Writes are also used to get a DMA buffer + * registered by the Guest and to send the Guest an interrupt. :*/ #include <linux/uaccess.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include "lg.h" +/*L:030 setup_regs() doesn't really belong in this file, but it gives us an + * early glimpse deeper into the Host so it's worth having here. + * + * Most of the Guest's registers are left alone: we used get_zeroed_page() to + * allocate the structure, so they will be 0. */ static void setup_regs(struct lguest_regs *regs, unsigned long start) { - /* Write out stack in format lguest expects, so we can switch to it. */ + /* There are four "segment" registers which the Guest needs to boot: + * The "code segment" register (cs) refers to the kernel code segment + * __KERNEL_CS, and the "data", "extra" and "stack" segment registers + * refer to the kernel data segment __KERNEL_DS. + * + * The privilege level is packed into the lower bits. The Guest runs + * at privilege level 1 (GUEST_PL).*/ regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL; regs->cs = __KERNEL_CS|GUEST_PL; - regs->eflags = 0x202; /* Interrupts enabled. */ + + /* The "eflags" register contains miscellaneous flags. Bit 1 (0x002) + * is supposed to always be "1". Bit 9 (0x200) controls whether + * interrupts are enabled. We always leave interrupts enabled while + * running the Guest. */ + regs->eflags = 0x202; + + /* The "Extended Instruction Pointer" register says where the Guest is + * running. */ regs->eip = start; - /* esi points to our boot information (physical address 0) */ + + /* %esi points to our boot information, at physical address 0, so don't + * touch it. */ } -/* + addr */ +/*L:310 To send DMA into the Guest, the Launcher needs to be able to ask for a + * DMA buffer. This is done by writing LHREQ_GETDMA and the key to + * /dev/lguest. */ static long user_get_dma(struct lguest *lg, const u32 __user *input) { unsigned long key, udma, irq; + /* Fetch the key they wrote to us. */ if (get_user(key, input) != 0) return -EFAULT; + /* Look for a free Guest DMA buffer bound to that key. */ udma = get_dma_buffer(lg, key, &irq); if (!udma) return -ENOENT; - /* We put irq number in udma->used_len. */ + /* We need to tell the Launcher what interrupt the Guest expects after + * the buffer is filled. We stash it in udma->used_len. */ lgwrite_u32(lg, udma + offsetof(struct lguest_dma, used_len), irq); + + /* The (guest-physical) address of the DMA buffer is returned from + * the write(). */ return udma; } -/* To force the Guest to stop running and return to the Launcher, the +/*L:315 To force the Guest to stop running and return to the Launcher, the * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */ static int break_guest_out(struct lguest *lg, const u32 __user *input) @@ -54,7 +88,8 @@ static int break_guest_out(struct lguest *lg, const u32 __user *input) } } -/* + irq */ +/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt + * number to /dev/lguest. */ static int user_send_irq(struct lguest *lg, const u32 __user *input) { u32 irq; @@ -63,14 +98,19 @@ static int user_send_irq(struct lguest *lg, const u32 __user *input) return -EFAULT; if (irq >= LGUEST_IRQS) return -EINVAL; + /* Next time the Guest runs, the core code will see if it can deliver + * this interrupt. */ set_bit(irq, lg->irqs_pending); return 0; } +/*L:040 Once our Guest is initialized, the Launcher makes it run by reading + * from /dev/lguest. */ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) { struct lguest *lg = file->private_data; + /* You must write LHREQ_INITIALIZE first! */ if (!lg) return -EINVAL; @@ -78,27 +118,52 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) if (current != lg->tsk) return -EPERM; + /* If the guest is already dead, we indicate why */ if (lg->dead) { size_t len; + /* lg->dead either contains an error code, or a string. */ if (IS_ERR(lg->dead)) return PTR_ERR(lg->dead); + /* We can only return as much as the buffer they read with. */ len = min(size, strlen(lg->dead)+1); if (copy_to_user(user, lg->dead, len) != 0) return -EFAULT; return len; } + /* If we returned from read() last time because the Guest sent DMA, + * clear the flag. */ if (lg->dma_is_pending) lg->dma_is_pending = 0; + /* Run the Guest until something interesting happens. */ return run_guest(lg, (unsigned long __user *)user); } -/* Take: pfnlimit, pgdir, start, pageoffset. */ +/*L:020 The initialization write supplies 4 32-bit values (in addition to the + * 32-bit LHREQ_INITIALIZE value). These are: + * + * pfnlimit: The highest (Guest-physical) page number the Guest should be + * allowed to access. The Launcher has to live in Guest memory, so it sets + * this to ensure the Guest can't reach it. + * + * pgdir: The (Guest-physical) address of the top of the initial Guest + * pagetables (which are set up by the Launcher). + * + * start: The first instruction to execute ("eip" in x86-speak). + * + * page_offset: The PAGE_OFFSET constant in the Guest kernel. We should + * probably wean the code off this, but it's a very useful constant! Any + * address above this is within the Guest kernel, and any kernel address can + * quickly converted from physical to virtual by adding PAGE_OFFSET. It's + * 0xC0000000 (3G) by default, but it's configurable at kernel build time. + */ static int initialize(struct file *file, const u32 __user *input) { + /* "struct lguest" contains everything we (the Host) know about a + * Guest. */ struct lguest *lg; int err, i; u32 args[4]; @@ -106,7 +171,7 @@ static int initialize(struct file *file, const u32 __user *input) /* We grab the Big Lguest lock, which protects the global array * "lguests" and multiple simultaneous initializations. */ mutex_lock(&lguest_lock); - + /* You can't initialize twice! Close the device and start again... */ if (file->private_data) { err = -EBUSY; goto unlock; @@ -117,37 +182,70 @@ static int initialize(struct file *file, const u32 __user *input) goto unlock; } + /* Find an unused guest. */ i = find_free_guest(); if (i < 0) { err = -ENOSPC; goto unlock; } + /* OK, we have an index into the "lguest" array: "lg" is a convenient + * pointer. */ lg = &lguests[i]; + + /* Populate the easy fields of our "struct lguest" */ lg->guestid = i; lg->pfn_limit = args[0]; lg->page_offset = args[3]; + + /* We need a complete page for the Guest registers: they are accessible + * to the Guest and we can only grant it access to whole pages. */ lg->regs_page = get_zeroed_page(GFP_KERNEL); if (!lg->regs_page) { err = -ENOMEM; goto release_guest; } + /* We actually put the registers at the bottom of the page. */ lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs); + /* Initialize the Guest's shadow page tables, using the toplevel + * address the Launcher gave us. This allocates memory, so can + * fail. */ err = init_guest_pagetable(lg, args[1]); if (err) goto free_regs; + /* Now we initialize the Guest's registers, handing it the start + * address. */ setup_regs(lg->regs, args[2]); + + /* There are a couple of GDT entries the Guest expects when first + * booting. */ setup_guest_gdt(lg); + + /* The timer for lguest's clock needs initialization. */ init_clockdev(lg); + + /* We keep a pointer to the Launcher task (ie. current task) for when + * other Guests want to wake this one (inter-Guest I/O). */ lg->tsk = current; + /* We need to keep a pointer to the Launcher's memory map, because if + * the Launcher dies we need to clean it up. If we don't keep a + * reference, it is destroyed before close() is called. */ lg->mm = get_task_mm(lg->tsk); + + /* Initialize the queue for the waker to wait on */ init_waitqueue_head(&lg->break_wq); + + /* We remember which CPU's pages this Guest used last, for optimization + * when the same Guest runs on the same CPU twice. */ lg->last_pages = NULL; + + /* We keep our "struct lguest" in the file's private_data. */ file->private_data = lg; mutex_unlock(&lguest_lock); + /* And because this is a write() call, we return the length used. */ return sizeof(args); free_regs: @@ -159,9 +257,15 @@ unlock: return err; } +/*L:010 The first operation the Launcher does must be a write. All writes + * start with a 32 bit number: for the first write this must be + * LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use + * writes of other values to get DMA buffers and send interrupts. */ static ssize_t write(struct file *file, const char __user *input, size_t size, loff_t *off) { + /* Once the guest is initialized, we hold the "struct lguest" in the + * file private data. */ struct lguest *lg = file->private_data; u32 req; @@ -169,8 +273,11 @@ static ssize_t write(struct file *file, const char __user *input, return -EFAULT; input += sizeof(req); + /* If you haven't initialized, you must do that first. */ if (req != LHREQ_INITIALIZE && !lg) return -EINVAL; + + /* Once the Guest is dead, all you can do is read() why it died. */ if (lg && lg->dead) return -ENOENT; @@ -192,33 +299,72 @@ static ssize_t write(struct file *file, const char __user *input, } } +/*L:060 The final piece of interface code is the close() routine. It reverses + * everything done in initialize(). This is usually called because the + * Launcher exited. + * + * Note that the close routine returns 0 or a negative error number: it can't + * really fail, but it can whine. I blame Sun for this wart, and K&R C for + * letting them do it. :*/ static int close(struct inode *inode, struct file *file) { struct lguest *lg = file->private_data; + /* If we never successfully initialized, there's nothing to clean up */ if (!lg) return 0; + /* We need the big lock, to protect from inter-guest I/O and other + * Launchers initializing guests. */ mutex_lock(&lguest_lock); /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */ hrtimer_cancel(&lg->hrt); + /* Free any DMA buffers the Guest had bound. */ release_all_dma(lg); + /* Free up the shadow page tables for the Guest. */ free_guest_pagetable(lg); + /* Now all the memory cleanups are done, it's safe to release the + * Launcher's memory management structure. */ mmput(lg->mm); + /* If lg->dead doesn't contain an error code it will be NULL or a + * kmalloc()ed string, either of which is ok to hand to kfree(). */ if (!IS_ERR(lg->dead)) kfree(lg->dead); + /* We can free up the register page we allocated. */ free_page(lg->regs_page); + /* We clear the entire structure, which also marks it as free for the + * next user. */ memset(lg, 0, sizeof(*lg)); + /* Release lock and exit. */ mutex_unlock(&lguest_lock); + return 0; } +/*L:000 + * Welcome to our journey through the Launcher! + * + * The Launcher is the Host userspace program which sets up, runs and services + * the Guest. In fact, many comments in the Drivers which refer to "the Host" + * doing things are inaccurate: the Launcher does all the device handling for + * the Guest. The Guest can't tell what's done by the the Launcher and what by + * the Host. + * + * Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we + * shall see more of that later. + * + * We begin our understanding with the Host kernel interface which the Launcher + * uses: reading and writing a character device called /dev/lguest. All the + * work happens in the read(), write() and close() routines: */ static struct file_operations lguest_fops = { .owner = THIS_MODULE, .release = close, .write = write, .read = read, }; + +/* This is a textbook example of a "misc" character device. Populate a "struct + * miscdevice" and register it with misc_register(). */ static struct miscdevice lguest_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "lguest", diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 1b0ba09..b7a924a 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -1,5 +1,11 @@ -/* Shadow page table operations. - * Copyright (C) Rusty Russell IBM Corporation 2006. +/*P:700 The pagetable code, on the other hand, still shows the scars of + * previous encounters. It's functional, and as neat as it can be in the + * circumstances, but be wary, for these things are subtle and break easily. + * The Guest provides a virtual to physical mapping, but we can neither trust + * it nor use it: we verify and convert it here to point the hardware to the + * actual Guest pages when running the Guest. :*/ + +/* Copyright (C) Rusty Russell IBM Corporation 2006. * GPL v2 and any later version */ #include <linux/mm.h> #include <linux/types.h> @@ -9,38 +15,96 @@ #include <asm/tlbflush.h> #include "lg.h" +/*M:008 We hold reference to pages, which prevents them from being swapped. + * It'd be nice to have a callback in the "struct mm_struct" when Linux wants + * to swap out. If we had this, and a shrinker callback to trim PTE pages, we + * could probably consider launching Guests as non-root. :*/ + +/*H:300 + * The Page Table Code + * + * We use two-level page tables for the Guest. If you're not entirely + * comfortable with virtual addresses, physical addresses and page tables then + * I recommend you review lguest.c's "Page Table Handling" (with diagrams!). + * + * The Guest keeps page tables, but we maintain the actual ones here: these are + * called "shadow" page tables. Which is a very Guest-centric name: these are + * the real page tables the CPU uses, although we keep them up to date to + * reflect the Guest's. (See what I mean about weird naming? Since when do + * shadows reflect anything?) + * + * Anyway, this is the most complicated part of the Host code. There are seven + * parts to this: + * (i) Setting up a page table entry for the Guest when it faults, + * (ii) Setting up the page table entry for the Guest stack, + * (iii) Setting up a page table entry when the Guest tells us it has changed, + * (iv) Switching page tables, + * (v) Flushing (thowing away) page tables, + * (vi) Mapping the Switcher when the Guest is about to run, + * (vii) Setting up the page tables initially. + :*/ + +/* Pages a 4k long, and each page table entry is 4 bytes long, giving us 1024 + * (or 2^10) entries per page. */ #define PTES_PER_PAGE_SHIFT 10 #define PTES_PER_PAGE (1 << PTES_PER_PAGE_SHIFT) + +/* 1024 entries in a page table page maps 1024 pages: 4MB. The Switcher is + * conveniently placed at the top 4MB, so it uses a separate, complete PTE + * page. */ #define SWITCHER_PGD_INDEX (PTES_PER_PAGE - 1) +/* We actually need a separate PTE page for each CPU. Remember that after the + * Switcher code itself comes two pages for each CPU, and we don't want this + * CPU's guest to see the pages of any other CPU. */ static DEFINE_PER_CPU(spte_t *, switcher_pte_pages); #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu) +/*H:320 With our shadow and Guest types established, we need to deal with + * them: the page table code is curly enough to need helper functions to keep + * it clear and clean. + * + * The first helper takes a virtual address, and says which entry in the top + * level page table deals with that address. Since each top level entry deals + * with 4M, this effectively divides by 4M. */ static unsigned vaddr_to_pgd_index(unsigned long vaddr) { return vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT); } -/* These access the shadow versions (ie. the ones used by the CPU). */ +/* There are two functions which return pointers to the shadow (aka "real") + * page tables. + * + * spgd_addr() takes the virtual address and returns a pointer to the top-level + * page directory entry for that address. Since we keep track of several page + * tables, the "i" argument tells us which one we're interested in (it's + * usually the current one). */ static spgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr) { unsigned int index = vaddr_to_pgd_index(vaddr); + /* We kill any Guest trying to touch the Switcher addresses. */ if (index >= SWITCHER_PGD_INDEX) { kill_guest(lg, "attempt to access switcher pages"); index = 0; } + /* Return a pointer index'th pgd entry for the i'th page table. */ return &lg->pgdirs[i].pgdir[index]; } +/* This routine then takes the PGD entry given above, which contains the + * address of the PTE page. It then returns a pointer to the PTE entry for the + * given address. */ static spte_t *spte_addr(struct lguest *lg, spgd_t spgd, unsigned long vaddr) { spte_t *page = __va(spgd.pfn << PAGE_SHIFT); + /* You should never call this if the PGD entry wasn't valid */ BUG_ON(!(spgd.flags & _PAGE_PRESENT)); return &page[(vaddr >> PAGE_SHIFT) % PTES_PER_PAGE]; } -/* These access the guest versions. */ +/* These two functions just like the above two, except they access the Guest + * page tables. Hence they return a Guest address. */ static unsigned long gpgd_addr(struct lguest *lg, unsigned long vaddr) { unsigned int index = vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT); @@ -55,12 +119,24 @@ static unsigned long gpte_addr(struct lguest *lg, return gpage + ((vaddr>>PAGE_SHIFT) % PTES_PER_PAGE) * sizeof(gpte_t); } -/* Do a virtual -> physical mapping on a user page. */ +/*H:350 This routine takes a page number given by the Guest and converts it to + * an actual, physical page number. It can fail for several reasons: the + * virtual address might not be mapped by the Launcher, the write flag is set + * and the page is read-only, or the write flag was set and the page was + * shared so had to be copied, but we ran out of memory. + * + * This holds a reference to the page, so release_pte() is careful to + * put that back. */ static unsigned long get_pfn(unsigned long virtpfn, int write) { struct page *page; + /* This value indicates failure. */ unsigned long ret = -1UL; + /* get_user_pages() is a complex interface: it gets the "struct + * vm_area_struct" and "struct page" assocated with a range of pages. + * It also needs the task's mmap_sem held, and is not very quick. + * It returns the number of pages it got. */ down_read(¤t->mm->mmap_sem); if (get_user_pages(current, current->mm, virtpfn << PAGE_SHIFT, 1, write, 1, &page, NULL) == 1) @@ -69,28 +145,47 @@ static unsigned long get_pfn(unsigned long virtpfn, int write) return ret; } +/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table + * entry can be a little tricky. The flags are (almost) the same, but the + * Guest PTE contains a virtual page number: the CPU needs the real page + * number. */ static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write) { spte_t spte; unsigned long pfn; - /* We ignore the global flag. */ + /* The Guest sets the global flag, because it thinks that it is using + * PGE. We only told it to use PGE so it would tell us whether it was + * flushing a kernel mapping or a userspace mapping. We don't actually + * use the global bit, so throw it away. */ spte.flags = (gpte.flags & ~_PAGE_GLOBAL); + + /* We need a temporary "unsigned long" variable to hold the answer from + * get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't + * fit in spte.pfn. get_pfn() finds the real physical number of the + * page, given the virtual number. */ pfn = get_pfn(gpte.pfn, write); if (pfn == -1UL) { kill_guest(lg, "failed to get page %u", gpte.pfn); - /* Must not put_page() bogus page on cleanup. */ + /* When we destroy the Guest, we'll go through the shadow page + * tables and release_pte() them. Make sure we don't think + * this one is valid! */ spte.flags = 0; } + /* Now we assign the page number, and our shadow PTE is complete. */ spte.pfn = pfn; return spte; } +/*H:460 And to complete the chain, release_pte() looks like this: */ static void release_pte(spte_t pte) { + /* Remember that get_user_pages() took a reference to the page, in + * get_pfn()? We have to put it back now. */ if (pte.flags & _PAGE_PRESENT) put_page(pfn_to_page(pte.pfn)); } +/*:*/ static void check_gpte(struct lguest *lg, gpte_t gpte) { @@ -104,11 +199,16 @@ static void check_gpgd(struct lguest *lg, gpgd_t gpgd) kill_guest(lg, "bad page directory entry"); } -/* FIXME: We hold reference to pages, which prevents them from being - swapped. It'd be nice to have a callback when Linux wants to swap out. */ - -/* We fault pages in, which allows us to update accessed/dirty bits. - * Return true if we got page. */ +/*H:330 + * (i) Setting up a page table entry for the Guest when it faults + * + * We saw this call in run_guest(): when we see a page fault in the Guest, we + * come here. That's because we only set up the shadow page tables lazily as + * they're needed, so we get page faults all the time and quietly fix them up + * and return to the Guest without it knowing. + * + * If we fixed up the fault (ie. we mapped the address), this routine returns + * true. */ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) { gpgd_t gpgd; @@ -117,106 +217,161 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode) gpte_t gpte; spte_t *spte; + /* First step: get the top-level Guest page table entry. */ gpgd = mkgpgd(lgread_u32(lg, gpgd_addr(lg, vaddr))); + /* Toplevel not present? We can't map it in. */ if (!(gpgd.flags & _PAGE_PRESENT)) return 0; + /* Now look at the matching shadow entry. */ spgd = spgd_addr(lg, lg->pgdidx, vaddr); if (!(spgd->flags & _PAGE_PRESENT)) { - /* Get a page of PTEs for them. */ + /* No shadow entry: allocate a new shadow PTE page. */ unsigned long ptepage = get_zeroed_page(GFP_KERNEL); - /* FIXME: Steal from self in this case? */ + /* This is not really the Guest's fault, but killing it is + * simple for this corner case. */ if (!ptepage) { kill_guest(lg, "out of memory allocating pte page"); return 0; } + /* We check that the Guest pgd is OK. */ check_gpgd(lg, gpgd); + /* And we copy the flags to the shadow PGD entry. The page + * number in the shadow PGD is the page we just allocated. */ spgd->raw.val = (__pa(ptepage) | gpgd.flags); } + /* OK, now we look at the lower level in the Guest page table: keep its + * address, because we might update it later. */ gpte_ptr = gpte_addr(lg, gpgd, vaddr); gpte = mkgpte(lgread_u32(lg, gpte_ptr)); - /* No page? */ + /* If this page isn't in the Guest page tables, we can't page it in. */ if (!(gpte.flags & _PAGE_PRESENT)) return 0; - /* Write to read-only page? */ + /* Check they're not trying to write to a page the Guest wants + * read-only (bit 2 of errcode == write). */ if ((errcode & 2) && !(gpte.flags & _PAGE_RW)) return 0; - /* User access to a non-user page? */ + /* User access to a kernel page? (bit 3 == user access) */ if ((errcode & 4) && !(gpte.flags & _PAGE_USER)) return 0; + /* Check that the Guest PTE flags are OK, and the page number is below + * the pfn_limit (ie. not mapping the Launcher binary). */ check_gpte(lg, gpte); + /* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */ gpte.flags |= _PAGE_ACCESSED; if (errcode & 2) gpte.flags |= _PAGE_DIRTY; - /* We're done with the old pte. */ + /* Get the pointer to the shadow PTE entry we're going to set. */ spte = spte_addr(lg, *spgd, vaddr); + /* If there was a valid shadow PTE entry here before, we release it. + * This can happen with a write to a previously read-only entry. */ release_pte(*spte); - /* We don't make it writable if this isn't a write: later - * write will fault so we can set dirty bit in guest. */ + /* If this is a write, we insist that the Guest page is writable (the + * final arg to gpte_to_spte()). */ if (gpte.flags & _PAGE_DIRTY) *spte = gpte_to_spte(lg, gpte, 1); else { + /* If this is a read, don't set the "writable" bit in the page + * table entry, even if the Guest says it's writable. That way + * we come back here when a write does actually ocur, so we can + * update the Guest's _PAGE_DIRTY flag. */ gpte_t ro_gpte = gpte; ro_gpte.flags &= ~_PAGE_RW; *spte = gpte_to_spte(lg, ro_gpte, 0); } - /* Now we update dirty/accessed on guest. */ + /* Finally, we write the Guest PTE entry back: we've set the + * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */ lgwrite_u32(lg, gpte_ptr, gpte.raw.val); + + /* We succeeded in mapping the page! */ return 1; } -/* This is much faster than the full demand_page logic. */ +/*H:360 (ii) Setting up the page table entry for the Guest stack. + * + * Remember pin_stack_pages() which makes sure the stack is mapped? It could + * simply call demand_page(), but as we've seen that logic is quite long, and + * usually the stack pages are already mapped anyway, so it's not required. + * + * This is a quick version which answers the question: is this virtual address + * mapped by the shadow page tables, and is it writable? */ static int page_writable(struct lguest *lg, unsigned long vaddr) { spgd_t *spgd; unsigned long flags; + /* Look at the top level entry: is it present? */ spgd = spgd_addr(lg, lg->pgdidx, vaddr); if (!(spgd->flags & _PAGE_PRESENT)) return 0; + /* Check the flags on the pte entry itself: it must be present and + * writable. */ flags = spte_addr(lg, *spgd, vaddr)->flags; return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW); } +/* So, when pin_stack_pages() asks us to pin a page, we check if it's already + * in the page tables, and if not, we call demand_page() with error code 2 + * (meaning "write"). */ void pin_page(struct lguest *lg, unsigned long vaddr) { if (!page_writable(lg, vaddr) && !demand_page(lg, vaddr, 2)) kill_guest(lg, "bad stack page %#lx", vaddr); } +/*H:450 If we chase down the release_pgd() code, it looks like this: */ static void release_pgd(struct lguest *lg, spgd_t *spgd) { + /* If the entry's not present, there's nothing to release. */ if (spgd->flags & _PAGE_PRESENT) { unsigned int i; + /* Converting the pfn to find the actual PTE page is easy: turn + * the page number into a physical address, then convert to a + * virtual address (easy for kernel pages like this one). */ spte_t *ptepage = __va(spgd->pfn << PAGE_SHIFT); + /* For each entry in the page, we might need to release it. */ for (i = 0; i < PTES_PER_PAGE; i++) release_pte(ptepage[i]); + /* Now we can free the page of PTEs */ free_page((long)ptepage); + /* And zero out the PGD entry we we never release it twice. */ spgd->raw.val = 0; } } +/*H:440 (v) Flushing (thowing away) page tables, + * + * We saw flush_user_mappings() called when we re-used a top-level pgdir page. + * It simply releases every PTE page from 0 up to the kernel address. */ static void flush_user_mappings(struct lguest *lg, int idx) { unsigned int i; + /* Release every pgd entry up to the kernel's address. */ for (i = 0; i < vaddr_to_pgd_index(lg->page_offset); i++) release_pgd(lg, lg->pgdirs[idx].pgdir + i); } +/* The Guest also has a hypercall to do this manually: it's used when a large + * number of mappings have been changed. */ void guest_pagetable_flush_user(struct lguest *lg) { + /* Drop the userspace part of the current page table. */ flush_user_mappings(lg, lg->pgdidx); } +/*:*/ +/* We keep several page tables. This is a simple routine to find the page + * table (if any) corresponding to this top-level address the Guest has given + * us. */ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable) { unsigned int i; @@ -226,21 +381,30 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable) return i; } +/*H:435 And this is us, creating the new page directory. If we really do + * allocate a new one (and so the kernel parts are not there), we set + * blank_pgdir. */ static unsigned int new_pgdir(struct lguest *lg, unsigned long cr3, int *blank_pgdir) { unsigned int next; + /* We pick one entry at random to throw out. Choosing the Least + * Recently Used might be better, but this is easy. */ next = random32() % ARRAY_SIZE(lg->pgdirs); + /* If it's never been allocated at all before, try now. */ if (!lg->pgdirs[next].pgdir) { lg->pgdirs[next].pgdir = (spgd_t *)get_zeroed_page(GFP_KERNEL); + /* If the allocation fails, just keep using the one we have */ if (!lg->pgdirs[next].pgdir) next = lg->pgdidx; else - /* There are no mappings: you'll need to re-pin */ + /* This is a blank page, so there are no kernel + * mappings: caller must map the stack! */ *blank_pgdir = 1; } + /* Record which Guest toplevel this shadows. */ lg->pgdirs[next].cr3 = cr3; /* Release all the non-kernel mappings. */ flush_user_mappings(lg, next); @@ -248,82 +412,161 @@ static unsigned int new_pgdir(struct lguest *lg, return next; } +/*H:430 (iv) Switching page tables + * + * This is what happens when the Guest changes page tables (ie. changes the + * top-level pgdir). This happens on almost every context switch. */ void guest_new_pagetable(struct lguest *lg, unsigned long pgtable) { int newpgdir, repin = 0; + /* Look to see if we have this one already. */ newpgdir = find_pgdir(lg, pgtable); + /* If not, we allocate or mug an existing one: if it's a fresh one, + * repin gets set to 1. */ if (newpgdir == ARRAY_SIZE(lg->pgdirs)) newpgdir = new_pgdir(lg, pgtable, &repin); + /* Change the current pgd index to the new one. */ lg->pgdidx = newpgdir; + /* If it was completely blank, we map in the Guest kernel stack */ if (repin) pin_stack_pages(lg); } +/*H:470 Finally, a routine which throws away everything: all PGD entries in all + * the shadow page tables. This is used when we destroy the Guest. */ static void release_all_pagetables(struct lguest *lg) { unsigned int i, j; + /* Every shadow pagetable this Guest has */ for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++) if (lg->pgdirs[i].pgdir) + /* Every PGD entry except the Switcher at the top */ for (j = 0; j < SWITCHER_PGD_INDEX; j++) release_pgd(lg, lg->pgdirs[i].pgdir + j); } +/* We also throw away everything when a Guest tells us it's changed a kernel + * mapping. Since kernel mappings are in every page table, it's easiest to + * throw them all away. This is amazingly slow, but thankfully rare. */ void guest_pagetable_clear_all(struct lguest *lg) { release_all_pagetables(lg); + /* We need the Guest kernel stack mapped again. */ pin_stack_pages(lg); } +/*H:420 This is the routine which actually sets the page table entry for then + * "idx"'th shadow page table. + * + * Normally, we can just throw out the old entry and replace it with 0: if they + * use it demand_page() will put the new entry in. We need to do this anyway: + * The Guest expects _PAGE_ACCESSED to be set on its PTE the first time a page + * is read from, and _PAGE_DIRTY when it's written to. + * + * But Avi Kivity pointed out that most Operating Systems (Linux included) set + * these bits on PTEs immediately anyway. This is done to save the CPU from + * having to update them, but it helps us the same way: if they set + * _PAGE_ACCESSED then we can put a read-only PTE entry in immediately, and if + * they set _PAGE_DIRTY then we can put a writable PTE entry in immediately. + */ static void do_set_pte(struct lguest *lg, int idx, unsigned long vaddr, gpte_t gpte) { + /* Look up the matching shadow page directot entry. */ spgd_t *spgd = spgd_addr(lg, idx, vaddr); + + /* If the top level isn't present, there's no entry to update. */ if (spgd->flags & _PAGE_PRESENT) { + /* Otherwise, we start by releasing the existing entry. */ spte_t *spte = spte_addr(lg, *spgd, vaddr); release_pte(*spte); + + /* If they're setting this entry as dirty or accessed, we might + * as well put that entry they've given us in now. This shaves + * 10% off a copy-on-write micro-benchmark. */ if (gpte.flags & (_PAGE_DIRTY | _PAGE_ACCESSED)) { check_gpte(lg, gpte); *spte = gpte_to_spte(lg, gpte, gpte.flags&_PAGE_DIRTY); } else + /* Otherwise we can demand_page() it in later. */ spte->raw.val = 0; } } +/*H:410 Updating a PTE entry is a little trickier. + * + * We keep track of several different page tables (the Guest uses one for each + * process, so it makes sense to cache at least a few). Each of these have + * identical kernel parts: ie. every mapping above PAGE_OFFSET is the same for + * all processes. So when the page table above that address changes, we update + * all the page tables, not just the current one. This is rare. + * + * The benefit is that when we have to track a new page table, we can copy keep + * all the kernel mappings. This speeds up context switch immensely. */ void guest_set_pte(struct lguest *lg, unsigned long cr3, unsigned long vaddr, gpte_t gpte) { - /* Kernel mappings must be changed on all top levels. */ + /* Kernel mappings must be changed on all top levels. Slow, but + * doesn't happen often. */ if (vaddr >= lg->page_offset) { unsigned int i; for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++) if (lg->pgdirs[i].pgdir) do_set_pte(lg, i, vaddr, gpte); } else { + /* Is this page table one we have a shadow for? */ int pgdir = find_pgdir(lg, cr3); if (pgdir != ARRAY_SIZE(lg->pgdirs)) + /* If so, do the update. */ do_set_pte(lg, pgdir, vaddr, gpte); } } +/*H:400 + * (iii) Setting up a page table entry when the Guest tells us it has changed. + * + * Just like we did in interrupts_and_traps.c, it makes sense for us to deal + * with the other side of page tables while we're here: what happens when the + * Guest asks for a page table to be updated? + * + * We already saw that demand_page() will fill in the shadow page tables when + * needed, so we can simply remove shadow page table entries whenever the Guest + * tells us they've changed. When the Guest tries to use the new entry it will + * fault and demand_page() will fix it up. + * + * So with that in mind here's our code to to update a (top-level) PGD entry: + */ void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 idx) { int pgdir; + /* The kernel seems to try to initialize this early on: we ignore its + * attempts to map over the Switcher. */ if (idx >= SWITCHER_PGD_INDEX) return; + /* If they're talking about a page table we have a shadow for... */ pgdir = find_pgdir(lg, cr3); if (pgdir < ARRAY_SIZE(lg->pgdirs)) + /* ... throw it away. */ release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx); } +/*H:500 (vii) Setting up the page tables initially. + * + * When a Guest is first created, the Launcher tells us where the toplevel of + * its first page table is. We set some things up here: */ int init_guest_pagetable(struct lguest *lg, unsigned long pgtable) { - /* We assume this in flush_user_mappings, so check now */ + /* In flush_user_mappings() we loop from 0 to + * "vaddr_to_pgd_index(lg->page_offset)". This assumes it won't hit + * the Switcher mappings, so check that now. */ if (vaddr_to_pgd_index(lg->page_offset) >= SWITCHER_PGD_INDEX) return -EINVAL; + /* We start on the first shadow page table, and give it a blank PGD + * page. */ lg->pgdidx = 0; lg->pgdirs[lg->pgdidx].cr3 = pgtable; lg->pgdirs[lg->pgdidx].pgdir = (spgd_t*)get_zeroed_page(GFP_KERNEL); @@ -332,33 +575,48 @@ int init_guest_pagetable(struct lguest *lg, unsigned long pgtable) return 0; } +/* When a Guest dies, our cleanup is fairly simple. */ void free_guest_pagetable(struct lguest *lg) { unsigned int i; + /* Throw away all page table pages. */ release_all_pagetables(lg); + /* Now free the top levels: free_page() can handle 0 just fine. */ for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++) free_page((long)lg->pgdirs[i].pgdir); } -/* Caller must be preempt-safe */ +/*H:480 (vi) Mapping the Switcher when the Guest is about to run. + * + * The Switcher and the two pages for this CPU need to be available to the + * Guest (and not the pages for other CPUs). We have the appropriate PTE pages + * for each CPU already set up, we just need to hook them in. */ void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages) { spte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); spgd_t switcher_pgd; spte_t regs_pte; - /* Since switcher less that 4MB, we simply mug top pte page. */ + /* Make the last PGD entry for this Guest point to the Switcher's PTE + * page for this CPU (with appropriate flags). */ switcher_pgd.pfn = __pa(switcher_pte_page) >> PAGE_SHIFT; switcher_pgd.flags = _PAGE_KERNEL; lg->pgdirs[lg->pgdidx].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd; - /* Map our regs page over stack page. */ + /* We also change the Switcher PTE page. When we're running the Guest, + * we want the Guest's "regs" page to appear where the first Switcher + * page for this CPU is. This is an optimization: when the Switcher + * saves the Guest registers, it saves them into the first page of this + * CPU's "struct lguest_pages": if we make sure the Guest's register + * page is already mapped there, we don't have to copy them out + * again. */ regs_pte.pfn = __pa(lg->regs_page) >> PAGE_SHIFT; regs_pte.flags = _PAGE_KERNEL; switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTES_PER_PAGE] = regs_pte; } +/*:*/ static void free_switcher_pte_pages(void) { @@ -368,6 +626,10 @@ static void free_switcher_pte_pages(void) free_page((long)switcher_pte_page(i)); } +/*H:520 Setting up the Switcher PTE page for given CPU is fairly easy, given + * the CPU number and the "struct page"s for the Switcher code itself. + * + * Currently the Switcher is less than a page long, so "pages" is always 1. */ static __init void populate_switcher_pte_page(unsigned int cpu, struct page *switcher_page[], unsigned int pages) @@ -375,21 +637,26 @@ static __init void populate_switcher_pte_page(unsigned int cpu, unsigned int i; spte_t *pte = switcher_pte_page(cpu); + /* The first entries are easy: they map the Switcher code. */ for (i = 0; i < pages; i++) { pte[i].pfn = page_to_pfn(switcher_page[i]); pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED; } - /* We only map this CPU's pages, so guest can't see others. */ + /* The only other thing we map is this CPU's pair of pages. */ i = pages + cpu*2; - /* First page (regs) is rw, second (state) is ro. */ + /* First page (Guest registers) is writable from the Guest */ pte[i].pfn = page_to_pfn(switcher_page[i]); pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW; + /* The second page contains the "struct lguest_ro_state", and is + * read-only. */ pte[i+1].pfn = page_to_pfn(switcher_page[i+1]); pte[i+1].flags = _PAGE_PRESENT|_PAGE_ACCESSED; } +/*H:510 At boot or module load time, init_pagetables() allocates and populates + * the Switcher PTE page for each CPU. */ __init int init_pagetables(struct page **switcher_page, unsigned int pages) { unsigned int i; @@ -404,7 +671,9 @@ __init int init_pagetables(struct page **switcher_page, unsigned int pages) } return 0; } +/*:*/ +/* Cleaning up simply involves freeing the PTE page for each CPU. */ void free_pagetables(void) { free_switcher_pte_pages(); diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index 1b2cfe8..f675a41 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c @@ -1,16 +1,68 @@ +/*P:600 The x86 architecture has segments, which involve a table of descriptors + * which can be used to do funky things with virtual address interpretation. + * We originally used to use segments so the Guest couldn't alter the + * Guest<->Host Switcher, and then we had to trim Guest segments, and restore + * for userspace per-thread segments, but trim again for on userspace->kernel + * transitions... This nightmarish creation was contained within this file, + * where we knew not to tread without heavy armament and a change of underwear. + * + * In these modern times, the segment handling code consists of simple sanity + * checks, and the worst you'll experience reading this code is butterfly-rash + * from frolicking through its parklike serenity. :*/ #include "lg.h" +/*H:600 + * We've almost completed the Host; there's just one file to go! + * + * Segments & The Global Descriptor Table + * + * (That title sounds like a bad Nerdcore group. Not to suggest that there are + * any good Nerdcore groups, but in high school a friend of mine had a band + * called Joe Fish and the Chips, so there are definitely worse band names). + * + * To refresh: the GDT is a table of 8-byte values describing segments. Once + * set up, these segments can be loaded into one of the 6 "segment registers". + * + * GDT entries are passed around as "struct desc_struct"s, which like IDT + * entries are split into two 32-bit members, "a" and "b". One day, someone + * will clean that up, and be declared a Hero. (No pressure, I'm just saying). + * + * Anyway, the GDT entry contains a base (the start address of the segment), a + * limit (the size of the segment - 1), and some flags. Sounds simple, and it + * would be, except those zany Intel engineers decided that it was too boring + * to put the base at one end, the limit at the other, and the flags in + * between. They decided to shotgun the bits at random throughout the 8 bytes, + * like so: + * + * 0 16 40 48 52 56 63 + * [ limit part 1 ][ base part 1 ][ flags ][li][fl][base ] + * mit ags part 2 + * part 2 + * + * As a result, this file contains a certain amount of magic numeracy. Let's + * begin. + */ + +/* Is the descriptor the Guest wants us to put in OK? + * + * The flag which Intel says must be zero: must be zero. The descriptor must + * be present, (this is actually checked earlier but is here for thorougness), + * and the descriptor type must be 1 (a memory segment). */ static int desc_ok(const struct desc_struct *gdt) { - /* MBZ=0, P=1, DT=1 */ return ((gdt->b & 0x00209000) == 0x00009000); } +/* Is the segment present? (Otherwise it can't be used by the Guest). */ static int segment_present(const struct desc_struct *gdt) { return gdt->b & 0x8000; } +/* There are several entries we don't let the Guest set. The TSS entry is the + * "Task State Segment" which controls all kinds of delicate things. The + * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the + * the Guest can't be trusted to deal with double faults. */ static int ignored_gdt(unsigned int num) { return (num == GDT_ENTRY_TSS @@ -19,9 +71,18 @@ static int ignored_gdt(unsigned int num) || num == GDT_ENTRY_DOUBLEFAULT_TSS); } -/* We don't allow removal of CS, DS or SS; it doesn't make sense. */ +/* If the Guest asks us to remove an entry from the GDT, we have to be careful. + * If one of the segment registers is pointing at that entry the Switcher will + * crash when it tries to reload the segment registers for the Guest. + * + * It doesn't make much sense for the Guest to try to remove its own code, data + * or stack segments while they're in use: assume that's a Guest bug. If it's + * one of the lesser segment registers using the removed entry, we simply set + * that register to 0 (unusable). */ static void check_segment_use(struct lguest *lg, unsigned int desc) { + /* GDT entries are 8 bytes long, so we divide to get the index and + * ignore the bottom bits. */ if (lg->regs->gs / 8 == desc) lg->regs->gs = 0; if (lg->regs->fs / 8 == desc) @@ -33,13 +94,21 @@ static void check_segment_use(struct lguest *lg, unsigned int desc) || lg->regs->ss / 8 == desc) kill_guest(lg, "Removed live GDT entry %u", desc); } - +/*:*/ +/*M:009 We wouldn't need to check for removal of in-use segments if we handled + * faults in the Switcher. However, it's probably not a worthwhile + * optimization. :*/ + +/*H:610 Once the GDT has been changed, we look through the changed entries and + * see if they're OK. If not, we'll call kill_guest() and the Guest will never + * get to use the invalid entries. */ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) { unsigned int i; for (i = start; i < end; i++) { - /* We never copy these ones to real gdt */ + /* We never copy these ones to real GDT, so we don't care what + * they say */ if (ignored_gdt(i)) continue; @@ -53,41 +122,57 @@ static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end) if (!desc_ok(&lg->gdt[i])) kill_guest(lg, "Bad GDT descriptor %i", i); - /* DPL 0 presumably means "for use by guest". */ + /* Segment descriptors contain a privilege level: the Guest is + * sometimes careless and leaves this as 0, even though it's + * running at privilege level 1. If so, we fix it here. */ if ((lg->gdt[i].b & 0x00006000) == 0) lg->gdt[i].b |= (GUEST_PL << 13); - /* Set accessed bit, since gdt isn't writable. */ + /* Each descriptor has an "accessed" bit. If we don't set it + * now, the CPU will try to set it when the Guest first loads + * that entry into a segment register. But the GDT isn't + * writable by the Guest, so bad things can happen. */ lg->gdt[i].b |= 0x00000100; } } +/* This routine is called at boot or modprobe time for each CPU to set up the + * "constant" GDT entries for Guests running on that CPU. */ void setup_default_gdt_entries(struct lguest_ro_state *state) { struct desc_struct *gdt = state->guest_gdt; unsigned long tss = (unsigned long)&state->guest_tss; - /* Hypervisor segments. */ + /* The hypervisor segments are full 0-4G segments, privilege level 0 */ gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT; gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT; - /* This is the one which we *cannot* copy from guest, since tss - is depended on this lguest_ro_state, ie. this cpu. */ + /* The TSS segment refers to the TSS entry for this CPU, so we cannot + * copy it from the Guest. Forgive the magic flags */ gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16); gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000) | ((tss >> 16) & 0x000000FF); } +/* This routine is called before the Guest is run for the first time. */ void setup_guest_gdt(struct lguest *lg) { + /* Start with full 0-4G segments... */ lg->gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT; lg->gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT; + /* ...except the Guest is allowed to use them, so set the privilege + * level appropriately in the flags. */ lg->gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13); lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13); } -/* This is a fast version for the common case where only the three TLS entries - * have changed. */ +/* Like the IDT, we never simply use the GDT the Guest gives us. We set up the + * GDTs for each CPU, then we copy across the entries each time we want to run + * a different Guest on that CPU. */ + +/* A partial GDT load, for the three "thead-local storage" entries. Otherwise + * it's just like load_guest_gdt(). So much, in fact, it would probably be + * neater to have a single hypercall to cover both. */ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) { unsigned int i; @@ -96,22 +181,31 @@ void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt) gdt[i] = lg->gdt[i]; } +/* This is the full version */ void copy_gdt(const struct lguest *lg, struct desc_struct *gdt) { unsigned int i; + /* The default entries from setup_default_gdt_entries() are not + * replaced. See ignored_gdt() above. */ for (i = 0; i < GDT_ENTRIES; i++) if (!ignored_gdt(i)) gdt[i] = lg->gdt[i]; } +/* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num) { + /* We assume the Guest has the same number of GDT entries as the + * Host, otherwise we'd have to dynamically allocate the Guest GDT. */ if (num > ARRAY_SIZE(lg->gdt)) kill_guest(lg, "too many gdt entries %i", num); + /* We read the whole thing in, then fix it up. */ lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0])); fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt)); + /* Mark that the GDT changed so the core knows it has to copy it again, + * even if the Guest is run on the same CPU. */ lg->changed |= CHANGED_GDT; } @@ -123,3 +217,13 @@ void guest_load_tls(struct lguest *lg, unsigned long gtls) fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); lg->changed |= CHANGED_GDT_TLS; } + +/* + * With this, we have finished the Host. + * + * Five of the seven parts of our task are complete. You have made it through + * the Bit of Despair (I think that's somewhere in the page table code, + * myself). + * + * Next, we examine "make Switcher". It's short, but intense. + */ diff --git a/drivers/lguest/switcher.S b/drivers/lguest/switcher.S index eadd4cc..d418179 100644 --- a/drivers/lguest/switcher.S +++ b/drivers/lguest/switcher.S @@ -1,45 +1,136 @@ -/* This code sits at 0xFFC00000 to do the low-level guest<->host switch. +/*P:900 This is the Switcher: code which sits at 0xFFC00000 to do the low-level + * Guest<->Host switch. It is as simple as it can be made, but it's naturally + * very specific to x86. + * + * You have now completed Preparation. If this has whet your appetite; if you + * are feeling invigorated and refreshed then the next, more challenging stage + * can be found in "make Guest". :*/ - There is are two pages above us for this CPU (struct lguest_pages). - The second page (struct lguest_ro_state) becomes read-only after the - context switch. The first page (the stack for traps) remains writable, - but while we're in here, the guest cannot be running. -*/ +/*S:100 + * Welcome to the Switcher itself! + * + * This file contains the low-level code which changes the CPU to run the Guest + * code, and returns to the Host when something happens. Understand this, and + * you understand the heart of our journey. + * + * Because this is in assembler rather than C, our tale switches from prose to + * verse. First I tried limericks: + * + * There once was an eax reg, + * To which our pointer was fed, + * It needed an add, + * Which asm-offsets.h had + * But this limerick is hurting my head. + * + * Next I tried haikus, but fitting the required reference to the seasons in + * every stanza was quickly becoming tiresome: + * + * The %eax reg + * Holds "struct lguest_pages" now: + * Cherry blossoms fall. + * + * Then I started with Heroic Verse, but the rhyming requirement leeched away + * the content density and led to some uniquely awful oblique rhymes: + * + * These constants are coming from struct offsets + * For use within the asm switcher text. + * + * Finally, I settled for something between heroic hexameter, and normal prose + * with inappropriate linebreaks. Anyway, it aint no Shakespeare. + */ + +// Not all kernel headers work from assembler +// But these ones are needed: the ENTRY() define +// And constants extracted from struct offsets +// To avoid magic numbers and breakage: +// Should they change the compiler can't save us +// Down here in the depths of assembler code. #include <linux/linkage.h> #include <asm/asm-offsets.h> #include "lg.h" +// We mark the start of the code to copy +// It's placed in .text tho it's never run here +// You'll see the trick macro at the end +// Which interleaves data and text to effect. .text ENTRY(start_switcher_text) -/* %eax points to lguest pages for this CPU. %ebx contains cr3 value. - All normal registers can be clobbered! */ +// When we reach switch_to_guest we have just left +// The safe and comforting shores of C code +// %eax has the "struct lguest_pages" to use +// Where we save state and still see it from the Guest +// And %ebx holds the Guest shadow pagetable: +// Once set we have truly left Host behind. ENTRY(switch_to_guest) - /* Save host segments on host stack. */ + // We told gcc all its regs could fade, + // Clobbered by our journey into the Guest + // We could have saved them, if we tried + // But time is our master and cycles count. + + // Segment registers must be saved for the Host + // We push them on the Host stack for later pushl %es pushl %ds pushl %gs pushl %fs - /* With CONFIG_FRAME_POINTER, gcc doesn't let us clobber this! */ + // But the compiler is fickle, and heeds + // No warning of %ebp clobbers + // When frame pointers are used. That register + // Must be saved and restored or chaos strikes. pushl %ebp - /* Save host stack. */ + // The Host's stack is done, now save it away + // In our "struct lguest_pages" at offset + // Distilled into asm-offsets.h movl %esp, LGUEST_PAGES_host_sp(%eax) - /* Switch to guest stack: if we get NMI we expect to be there. */ + + // All saved and there's now five steps before us: + // Stack, GDT, IDT, TSS + // And last of all the page tables are flipped. + + // Yet beware that our stack pointer must be + // Always valid lest an NMI hits + // %edx does the duty here as we juggle + // %eax is lguest_pages: our stack lies within. movl %eax, %edx addl $LGUEST_PAGES_regs, %edx movl %edx, %esp - /* Switch to guest's GDT, IDT. */ + + // The Guest's GDT we so carefully + // Placed in the "struct lguest_pages" before lgdt LGUEST_PAGES_guest_gdt_desc(%eax) + + // The Guest's IDT we did partially + // Move to the "struct lguest_pages" as well. lidt LGUEST_PAGES_guest_idt_desc(%eax) - /* Switch to guest's TSS while GDT still writable. */ + + // The TSS entry which controls traps + // Must be loaded up with "ltr" now: + // For after we switch over our page tables + // It (as the rest) will be writable no more. + // (The GDT entry TSS needs + // Changes type when we load it: damn Intel!) movl $(GDT_ENTRY_TSS*8), %edx ltr %dx - /* Set host's TSS GDT entry to available (clear byte 5 bit 2). */ + + // Look back now, before we take this last step! + // The Host's TSS entry was also marked used; + // Let's clear it again, ere we return. + // The GDT descriptor of the Host + // Points to the table after two "size" bytes movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx + // Clear the type field of "used" (byte 5, bit 2) andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx) - /* Switch to guest page tables: lguest_pages->state now read-only. */ + + // Once our page table's switched, the Guest is live! + // The Host fades as we run this final step. + // Our "struct lguest_pages" is now read-only. movl %ebx, %cr3 - /* Restore guest regs */ + + // The page table change did one tricky thing: + // The Guest's register page has been mapped + // Writable onto our %esp (stack) -- + // We can simply pop off all Guest regs. popl %ebx popl %ecx popl %edx @@ -51,12 +142,27 @@ ENTRY(switch_to_guest) popl %fs popl %ds popl %es - /* Skip error code and trap number */ + + // Near the base of the stack lurk two strange fields + // Which we fill as we exit the Guest + // These are the trap number and its error + // We can simply step past them on our way. addl $8, %esp + + // The last five stack slots hold return address + // And everything needed to change privilege + // Into the Guest privilege level of 1, + // And the stack where the Guest had last left it. + // Interrupts are turned back on: we are Guest. iret +// There are two paths where we switch to the Host +// So we put the routine in a macro. +// We are on our way home, back to the Host +// Interrupted out of the Guest, we come here. #define SWITCH_TO_HOST \ - /* Save guest state */ \ + /* We save the Guest state: all registers first \ + * Laid out just as "struct lguest_regs" defines */ \ pushl %es; \ pushl %ds; \ pushl %fs; \ @@ -68,58 +174,119 @@ ENTRY(switch_to_guest) pushl %edx; \ pushl %ecx; \ pushl %ebx; \ - /* Load lguest ds segment for convenience. */ \ + /* Our stack and our code are using segments \ + * Set in the TSS and IDT \ + * Yet if we were to touch data we'd use \ + * Whatever data segment the Guest had. \ + * Load the lguest ds segment for now. */ \ movl $(LGUEST_DS), %eax; \ movl %eax, %ds; \ - /* Figure out where we are, based on stack (at top of regs). */ \ + /* So where are we? Which CPU, which struct? \ + * The stack is our clue: our TSS sets \ + * It at the end of "struct lguest_pages" \ + * And we then pushed and pushed and pushed Guest regs: \ + * Now stack points atop the "struct lguest_regs". \ + * Subtract that offset, and we find our struct. */ \ movl %esp, %eax; \ subl $LGUEST_PAGES_regs, %eax; \ - /* Put trap number in %ebx before we switch cr3 and lose it. */ \ + /* Save our trap number: the switch will obscure it \ + * (The Guest regs are not mapped here in the Host) \ + * %ebx holds it safe for deliver_to_host */ \ movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \ - /* Switch to host page tables (host GDT, IDT and stack are in host \ - mem, so need this first) */ \ + /* The Host GDT, IDT and stack! \ + * All these lie safely hidden from the Guest: \ + * We must return to the Host page tables \ + * (Hence that was saved in struct lguest_pages) */ \ movl LGUEST_PAGES_host_cr3(%eax), %edx; \ movl %edx, %cr3; \ - /* Set guest's TSS to available (clear byte 5 bit 2). */ \ + /* As before, when we looked back at the Host \ + * As we left and marked TSS unused \ + * So must we now for the Guest left behind. */ \ andb $0xFD, (LGUEST_PAGES_guest_gdt+GDT_ENTRY_TSS*8+5)(%eax); \ - /* Switch to host's GDT & IDT. */ \ + /* Switch to Host's GDT, IDT. */ \ lgdt LGUEST_PAGES_host_gdt_desc(%eax); \ lidt LGUEST_PAGES_host_idt_desc(%eax); \ - /* Switch to host's stack. */ \ + /* Restore the Host's stack where it's saved regs lie */ \ movl LGUEST_PAGES_host_sp(%eax), %esp; \ - /* Switch to host's TSS */ \ + /* Last the TSS: our Host is complete */ \ movl $(GDT_ENTRY_TSS*8), %edx; \ ltr %dx; \ + /* Restore now the regs saved right at the first. */ \ popl %ebp; \ popl %fs; \ popl %gs; \ popl %ds; \ popl %es -/* Return to run_guest_once. */ +// Here's where we come when the Guest has just trapped: +// (Which trap we'll see has been pushed on the stack). +// We need only switch back, and the Host will decode +// Why we came home, and what needs to be done. return_to_host: SWITCH_TO_HOST iret +// An interrupt, with some cause external +// Has ajerked us rudely from the Guest's code +// Again we must return home to the Host deliver_to_host: SWITCH_TO_HOST - /* Decode IDT and jump to hosts' irq handler. When that does iret, it - * will return to run_guest_once. This is a feature. */ + // But now we must go home via that place + // Where that interrupt was supposed to go + // Had we not been ensconced, running the Guest. + // Here we see the cleverness of our stack: + // The Host stack is formed like an interrupt + // With EIP, CS and EFLAGS layered. + // Interrupt handlers end with "iret" + // And that will take us home at long long last. + + // But first we must find the handler to call! + // The IDT descriptor for the Host + // Has two bytes for size, and four for address: + // %edx will hold it for us for now. movl (LGUEST_PAGES_host_idt_desc+2)(%eax), %edx + // We now know the table address we need, + // And saved the trap's number inside %ebx. + // Yet the pointer to the handler is smeared + // Across the bits of the table entry. + // What oracle can tell us how to extract + // From such a convoluted encoding? + // I consulted gcc, and it gave + // These instructions, which I gladly credit: leal (%edx,%ebx,8), %eax movzwl (%eax),%edx movl 4(%eax), %eax xorw %ax, %ax orl %eax, %edx + // Now the address of the handler's in %edx + // We call it now: its "iret" takes us home. jmp *%edx -/* Real hardware interrupts are delivered straight to the host. Others - cause us to return to run_guest_once so it can decide what to do. Note - that some of these are overridden by the guest to deliver directly, and - never enter here (see load_guest_idt_entry). */ +// Every interrupt can come to us here +// But we must truly tell each apart. +// They number two hundred and fifty six +// And each must land in a different spot, +// Push its number on stack, and join the stream. + +// And worse, a mere six of the traps stand apart +// And push on their stack an addition: +// An error number, thirty two bits long +// So we punish the other two fifty +// And make them push a zero so they match. + +// Yet two fifty six entries is long +// And all will look most the same as the last +// So we create a macro which can make +// As many entries as we need to fill. + +// Note the change to .data then .text: +// We plant the address of each entry +// Into a (data) table for the Host +// To know where each Guest interrupt should go. .macro IRQ_STUB N TARGET .data; .long 1f; .text; 1: - /* Make an error number for most traps, which don't have one. */ + // Trap eight, ten through fourteen and seventeen + // Supply an error number. Else zero. .if (\N <> 8) && (\N < 10 || \N > 14) && (\N <> 17) pushl $0 .endif @@ -128,6 +295,8 @@ deliver_to_host: ALIGN .endm +// This macro creates numerous entries +// Using GAS macros which out-power C's. .macro IRQ_STUBS FIRST LAST TARGET irq=\FIRST .rept \LAST-\FIRST+1 @@ -136,24 +305,43 @@ deliver_to_host: .endr .endm -/* We intercept every interrupt, because we may need to switch back to - * host. Unfortunately we can't tell them apart except by entry - * point, so we need 256 entry points. - */ +// Here's the marker for our pointer table +// Laid in the data section just before +// Each macro places the address of code +// Forming an array: each one points to text +// Which handles interrupt in its turn. .data .global default_idt_entries default_idt_entries: .text - IRQ_STUBS 0 1 return_to_host /* First two traps */ - IRQ_STUB 2 handle_nmi /* NMI */ - IRQ_STUBS 3 31 return_to_host /* Rest of traps */ - IRQ_STUBS 32 127 deliver_to_host /* Real interrupts */ - IRQ_STUB 128 return_to_host /* System call (overridden) */ - IRQ_STUBS 129 255 deliver_to_host /* Other real interrupts */ - -/* We ignore NMI and return. */ + // The first two traps go straight back to the Host + IRQ_STUBS 0 1 return_to_host + // We'll say nothing, yet, about NMI + IRQ_STUB 2 handle_nmi + // Other traps also return to the Host + IRQ_STUBS 3 31 return_to_host + // All interrupts go via their handlers + IRQ_STUBS 32 127 deliver_to_host + // 'Cept system calls coming from userspace + // Are to go to the Guest, never the Host. + IRQ_STUB 128 return_to_host + IRQ_STUBS 129 255 deliver_to_host + +// The NMI, what a fabulous beast +// Which swoops in and stops us no matter that +// We're suspended between heaven and hell, +// (Or more likely between the Host and Guest) +// When in it comes! We are dazed and confused +// So we do the simplest thing which one can. +// Though we've pushed the trap number and zero +// We discard them, return, and hope we live. handle_nmi: addl $8, %esp iret +// We are done; all that's left is Mastery +// And "make Mastery" is a journey long +// Designed to make your fingers itch to code. + +// Here ends the text, the file and poem. ENTRY(end_switcher_text) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2fc199b..2bcde57 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -526,7 +526,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) { - request_queue_t *q = bdev_get_queue(bdev); + struct request_queue *q = bdev_get_queue(bdev); struct io_restrictions *rs = &ti->limits; /* @@ -979,7 +979,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits) devices = dm_table_get_devices(t); for (d = devices->next; d != devices; d = d->next) { struct dm_dev *dd = list_entry(d, struct dm_dev, list); - request_queue_t *q = bdev_get_queue(dd->bdev); + struct request_queue *q = bdev_get_queue(dd->bdev); r |= bdi_congested(&q->backing_dev_info, bdi_bits); } @@ -992,7 +992,7 @@ void dm_table_unplug_all(struct dm_table *t) for (d = devices->next; d != devices; d = d->next) { struct dm_dev *dd = list_entry(d, struct dm_dev, list); - request_queue_t *q = bdev_get_queue(dd->bdev); + struct request_queue *q = bdev_get_queue(dd->bdev); if (q->unplug_fn) q->unplug_fn(q); @@ -1011,7 +1011,7 @@ int dm_table_flush_all(struct dm_table *t) for (d = devices->next; d != devices; d = d->next) { struct dm_dev *dd = list_entry(d, struct dm_dev, list); - request_queue_t *q = bdev_get_queue(dd->bdev); + struct request_queue *q = bdev_get_queue(dd->bdev); int err; if (!q->issue_flush_fn) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 846614e..141ff9f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -80,7 +80,7 @@ struct mapped_device { unsigned long flags; - request_queue_t *queue; + struct request_queue *queue; struct gendisk *disk; char name[16]; @@ -792,7 +792,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) * The request function that just remaps the bio built up by * dm_merge_bvec. */ -static int dm_request(request_queue_t *q, struct bio *bio) +static int dm_request(struct request_queue *q, struct bio *bio) { int r; int rw = bio_data_dir(bio); @@ -844,7 +844,7 @@ static int dm_request(request_queue_t *q, struct bio *bio) return 0; } -static int dm_flush_all(request_queue_t *q, struct gendisk *disk, +static int dm_flush_all(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { struct mapped_device *md = q->queuedata; @@ -859,7 +859,7 @@ static int dm_flush_all(request_queue_t *q, struct gendisk *disk, return ret; } -static void dm_unplug_all(request_queue_t *q) +static void dm_unplug_all(struct request_queue *q) { struct mapped_device *md = q->queuedata; struct dm_table *map = dm_get_table(md); @@ -1110,7 +1110,7 @@ static void __set_size(struct mapped_device *md, sector_t size) static int __bind(struct mapped_device *md, struct dm_table *t) { - request_queue_t *q = md->queue; + struct request_queue *q = md->queue; sector_t size; size = dm_table_get_size(t); diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 4ebd0f2..cb059cf 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -167,7 +167,7 @@ static void add_sector(conf_t *conf, sector_t start, int mode) conf->nfaults = n+1; } -static int make_request(request_queue_t *q, struct bio *bio) +static int make_request(struct request_queue *q, struct bio *bio) { mddev_t *mddev = q->queuedata; conf_t *conf = (conf_t*)mddev->private; diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 1927410..17f795c 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -55,7 +55,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) * * Return amount of bytes we can take at this offset */ -static int linear_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) +static int linear_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec) { mddev_t *mddev = q->queuedata; dev_info_t *dev0; @@ -79,20 +79,20 @@ static int linear_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio return maxsectors << 9; } -static void linear_unplug(request_queue_t *q) +static void linear_unplug(struct request_queue *q) { mddev_t *mddev = q->queuedata; linear_conf_t *conf = mddev_to_conf(mddev); int i; for (i=0; i < mddev->raid_disks; i++) { - request_queue_t *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); + struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); } } -static int linear_issue_flush(request_queue_t *q, struct gendisk *disk, +static int linear_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -101,7 +101,7 @@ static int linear_issue_flush(request_queue_t *q, struct gendisk *disk, for (i=0; i < mddev->raid_disks && ret == 0; i++) { struct block_device *bdev = conf->disks[i].rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -118,7 +118,7 @@ static int linear_congested(void *data, int bits) int i, ret = 0; for (i = 0; i < mddev->raid_disks && !ret ; i++) { - request_queue_t *q = bdev_get_queue(conf->disks[i].rdev->bdev); + struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); ret |= bdi_congested(&q->backing_dev_info, bits); } return ret; @@ -330,7 +330,7 @@ static int linear_stop (mddev_t *mddev) return 0; } -static int linear_make_request (request_queue_t *q, struct bio *bio) +static int linear_make_request (struct request_queue *q, struct bio *bio) { const int rw = bio_data_dir(bio); mddev_t *mddev = q->queuedata; diff --git a/drivers/md/md.c b/drivers/md/md.c index 65ddc88..f883b7e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -211,7 +211,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); ) -static int md_fail_request (request_queue_t *q, struct bio *bio) +static int md_fail_request (struct request_queue *q, struct bio *bio) { bio_io_error(bio, bio->bi_size); return 0; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 14da37f..1e2af43 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -125,7 +125,7 @@ static void unplug_slaves(mddev_t *mddev) mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + struct request_queue *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); @@ -140,13 +140,13 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_unlock(); } -static void multipath_unplug(request_queue_t *q) +static void multipath_unplug(struct request_queue *q) { unplug_slaves(q->queuedata); } -static int multipath_make_request (request_queue_t *q, struct bio * bio) +static int multipath_make_request (struct request_queue *q, struct bio * bio) { mddev_t *mddev = q->queuedata; multipath_conf_t *conf = mddev_to_conf(mddev); @@ -199,7 +199,7 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) seq_printf (seq, "]"); } -static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, +static int multipath_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -211,7 +211,7 @@ static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -238,7 +238,7 @@ static int multipath_congested(void *data, int bits) for (i = 0; i < mddev->raid_disks ; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { - request_queue_t *q = bdev_get_queue(rdev->bdev); + struct request_queue *q = bdev_get_queue(rdev->bdev); ret |= bdi_congested(&q->backing_dev_info, bits); /* Just like multipath_map, we just check the diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 2c404f7..b8216bc 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -25,7 +25,7 @@ #define MD_DRIVER #define MD_PERSONALITY -static void raid0_unplug(request_queue_t *q) +static void raid0_unplug(struct request_queue *q) { mddev_t *mddev = q->queuedata; raid0_conf_t *conf = mddev_to_conf(mddev); @@ -33,14 +33,14 @@ static void raid0_unplug(request_queue_t *q) int i; for (i=0; i<mddev->raid_disks; i++) { - request_queue_t *r_queue = bdev_get_queue(devlist[i]->bdev); + struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev); if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); } } -static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk, +static int raid0_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -50,7 +50,7 @@ static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk, for (i=0; i<mddev->raid_disks && ret == 0; i++) { struct block_device *bdev = devlist[i]->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -68,7 +68,7 @@ static int raid0_congested(void *data, int bits) int i, ret = 0; for (i = 0; i < mddev->raid_disks && !ret ; i++) { - request_queue_t *q = bdev_get_queue(devlist[i]->bdev); + struct request_queue *q = bdev_get_queue(devlist[i]->bdev); ret |= bdi_congested(&q->backing_dev_info, bits); } @@ -268,7 +268,7 @@ static int create_strip_zones (mddev_t *mddev) * * Return amount of bytes we can accept at this offset */ -static int raid0_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) +static int raid0_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec) { mddev_t *mddev = q->queuedata; sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); @@ -408,7 +408,7 @@ static int raid0_stop (mddev_t *mddev) return 0; } -static int raid0_make_request (request_queue_t *q, struct bio *bio) +static int raid0_make_request (struct request_queue *q, struct bio *bio) { mddev_t *mddev = q->queuedata; unsigned int sect_in_chunk, chunksize_bits, chunk_size, chunk_sects; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 00c78b7..650991b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -552,7 +552,7 @@ static void unplug_slaves(mddev_t *mddev) for (i=0; i<mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + struct request_queue *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); @@ -567,7 +567,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_unlock(); } -static void raid1_unplug(request_queue_t *q) +static void raid1_unplug(struct request_queue *q) { mddev_t *mddev = q->queuedata; @@ -575,7 +575,7 @@ static void raid1_unplug(request_queue_t *q) md_wakeup_thread(mddev->thread); } -static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, +static int raid1_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -587,7 +587,7 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -615,7 +615,7 @@ static int raid1_congested(void *data, int bits) for (i = 0; i < mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { - request_queue_t *q = bdev_get_queue(rdev->bdev); + struct request_queue *q = bdev_get_queue(rdev->bdev); /* Note the '|| 1' - when read_balance prefers * non-congested targets, it can be removed @@ -765,7 +765,7 @@ do_sync_io: return NULL; } -static int make_request(request_queue_t *q, struct bio * bio) +static int make_request(struct request_queue *q, struct bio * bio) { mddev_t *mddev = q->queuedata; conf_t *conf = mddev_to_conf(mddev); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a95ada1..4e53792 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -453,7 +453,7 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev) * If near_copies == raid_disk, there are no striping issues, * but in that case, the function isn't called at all. */ -static int raid10_mergeable_bvec(request_queue_t *q, struct bio *bio, +static int raid10_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *bio_vec) { mddev_t *mddev = q->queuedata; @@ -595,7 +595,7 @@ static void unplug_slaves(mddev_t *mddev) for (i=0; i<mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + struct request_queue *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); @@ -610,7 +610,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_unlock(); } -static void raid10_unplug(request_queue_t *q) +static void raid10_unplug(struct request_queue *q) { mddev_t *mddev = q->queuedata; @@ -618,7 +618,7 @@ static void raid10_unplug(request_queue_t *q) md_wakeup_thread(mddev->thread); } -static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, +static int raid10_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -630,7 +630,7 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -658,7 +658,7 @@ static int raid10_congested(void *data, int bits) for (i = 0; i < mddev->raid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { - request_queue_t *q = bdev_get_queue(rdev->bdev); + struct request_queue *q = bdev_get_queue(rdev->bdev); ret |= bdi_congested(&q->backing_dev_info, bits); } @@ -772,7 +772,7 @@ static void unfreeze_array(conf_t *conf) spin_unlock_irq(&conf->resync_lock); } -static int make_request(request_queue_t *q, struct bio * bio) +static int make_request(struct request_queue *q, struct bio * bio) { mddev_t *mddev = q->queuedata; conf_t *conf = mddev_to_conf(mddev); @@ -917,6 +917,13 @@ static int make_request(request_queue_t *q, struct bio * bio) bio_list_add(&bl, mbio); } + if (unlikely(!atomic_read(&r10_bio->remaining))) { + /* the array is dead */ + md_write_end(mddev); + raid_end_bio_io(r10_bio); + return 0; + } + bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0); spin_lock_irqsave(&conf->device_lock, flags); bio_list_merge(&conf->pending_bio_list, &bl); @@ -1557,7 +1564,6 @@ static void raid10d(mddev_t *mddev) bio = r10_bio->devs[r10_bio->read_slot].bio; r10_bio->devs[r10_bio->read_slot].bio = mddev->ro ? IO_BLOCKED : NULL; - bio_put(bio); mirror = read_balance(conf, r10_bio); if (mirror == -1) { printk(KERN_ALERT "raid10: %s: unrecoverable I/O" @@ -1565,8 +1571,10 @@ static void raid10d(mddev_t *mddev) bdevname(bio->bi_bdev,b), (unsigned long long)r10_bio->sector); raid_end_bio_io(r10_bio); + bio_put(bio); } else { const int do_sync = bio_sync(r10_bio->master_bio); + bio_put(bio); rdev = conf->mirrors[mirror].rdev; if (printk_ratelimit()) printk(KERN_ERR "raid10: %s: redirecting sector %llu to" diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d90ee14..2aff4be 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -289,7 +289,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, in } static void unplug_slaves(mddev_t *mddev); -static void raid5_unplug_device(request_queue_t *q); +static void raid5_unplug_device(struct request_queue *q); static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks, int pd_idx, int noblock) @@ -3182,7 +3182,7 @@ static void unplug_slaves(mddev_t *mddev) for (i=0; i<mddev->raid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + struct request_queue *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); @@ -3197,7 +3197,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_unlock(); } -static void raid5_unplug_device(request_queue_t *q) +static void raid5_unplug_device(struct request_queue *q) { mddev_t *mddev = q->queuedata; raid5_conf_t *conf = mddev_to_conf(mddev); @@ -3216,7 +3216,7 @@ static void raid5_unplug_device(request_queue_t *q) unplug_slaves(mddev); } -static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, +static int raid5_issue_flush(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { mddev_t *mddev = q->queuedata; @@ -3228,7 +3228,7 @@ static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); + struct request_queue *r_queue = bdev_get_queue(bdev); if (!r_queue->issue_flush_fn) ret = -EOPNOTSUPP; @@ -3267,7 +3267,7 @@ static int raid5_congested(void *data, int bits) /* We want read requests to align with chunks where possible, * but write requests don't need to. */ -static int raid5_mergeable_bvec(request_queue_t *q, struct bio *bio, struct bio_vec *biovec) +static int raid5_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec) { mddev_t *mddev = q->queuedata; sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); @@ -3377,7 +3377,7 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error) static int bio_fits_rdev(struct bio *bi) { - request_queue_t *q = bdev_get_queue(bi->bi_bdev); + struct request_queue *q = bdev_get_queue(bi->bi_bdev); if ((bi->bi_size>>9) > q->max_sectors) return 0; @@ -3396,7 +3396,7 @@ static int bio_fits_rdev(struct bio *bi) } -static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) +static int chunk_aligned_read(struct request_queue *q, struct bio * raid_bio) { mddev_t *mddev = q->queuedata; raid5_conf_t *conf = mddev_to_conf(mddev); @@ -3466,7 +3466,7 @@ static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) } -static int make_request(request_queue_t *q, struct bio * bi) +static int make_request(struct request_queue *q, struct bio * bi) { mddev_t *mddev = q->queuedata; raid5_conf_t *conf = mddev_to_conf(mddev); diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index 7195c94..b1a9c4c 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c @@ -29,8 +29,6 @@ struct af9005_fe_state { struct dvb_usb_device *d; - struct dvb_frontend *tuner; - fe_status_t stat; /* retraining parameters */ @@ -345,8 +343,8 @@ static int af9005_reset_pre_viterbi(struct dvb_frontend *fe) 1 & 0xff); if (ret) return ret; - af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, - 1 >> 8); + ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, + 1 >> 8); if (ret) return ret; /* reset pre viterbi error count */ @@ -447,7 +445,7 @@ static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat) u8 temp; int ret; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; *stat = 0; @@ -493,7 +491,7 @@ static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat) static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber) { struct af9005_fe_state *state = fe->demodulator_priv; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; af9005_fe_refresh_state(fe); *ber = state->ber; @@ -503,7 +501,7 @@ static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber) static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) { struct af9005_fe_state *state = fe->demodulator_priv; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; af9005_fe_refresh_state(fe); *unc = state->unc; @@ -517,7 +515,7 @@ static int af9005_fe_read_signal_strength(struct dvb_frontend *fe, int ret; u8 if_gain, rf_gain; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; ret = af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain, @@ -881,10 +879,8 @@ static int af9005_fe_init(struct dvb_frontend *fe) af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, reg_ofdm_rst_pos, reg_ofdm_rst_len, 1))) return ret; - if ((ret = - af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, - reg_ofdm_rst_pos, reg_ofdm_rst_len, 0))) - return ret; + ret = af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, + reg_ofdm_rst_pos, reg_ofdm_rst_len, 0); if (ret) return ret; @@ -1041,7 +1037,7 @@ static int af9005_fe_init(struct dvb_frontend *fe) return ret; /* attach tuner and init */ - if (state->tuner == NULL) { + if (fe->ops.tuner_ops.release == NULL) { /* read tuner and board id from eeprom */ ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2); if (ret) { @@ -1058,20 +1054,16 @@ static int af9005_fe_init(struct dvb_frontend *fe) return ret; } if1 = (u16) (buf[0] << 8) + buf[1]; - state->tuner = - dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap, - &af9005_mt2060_config, if1); - if (state->tuner == NULL) { + if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap, + &af9005_mt2060_config, if1) == NULL) { deb_info("MT2060 attach failed\n"); return -ENODEV; } break; case 3: /* QT1010 */ case 9: /* QT1010B */ - state->tuner = - dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap, - &af9005_qt1010_config); - if (state->tuner == NULL) { + if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap, + &af9005_qt1010_config) ==NULL) { deb_info("QT1010 attach failed\n"); return -ENODEV; } @@ -1080,7 +1072,7 @@ static int af9005_fe_init(struct dvb_frontend *fe) err("Unsupported tuner type %d", buf[0]); return -ENODEV; } - ret = state->tuner->ops.tuner_ops.init(state->tuner); + ret = fe->ops.tuner_ops.init(fe); if (ret) return ret; } @@ -1118,7 +1110,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe, deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency, fep->u.ofdm.bandwidth); - if (state->tuner == NULL) { + if (fe->ops.tuner_ops.release == NULL) { err("Tuner not attached"); return -ENODEV; } @@ -1199,7 +1191,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe, return ret; /* set tuner */ deb_info("set tuner\n"); - ret = state->tuner->ops.tuner_ops.set_params(state->tuner, fep); + ret = fe->ops.tuner_ops.set_params(fe, fep); if (ret) return ret; @@ -1435,12 +1427,6 @@ static void af9005_fe_release(struct dvb_frontend *fe) { struct af9005_fe_state *state = (struct af9005_fe_state *)fe->demodulator_priv; - if (state->tuner != NULL && state->tuner->ops.tuner_ops.release != NULL) { - state->tuner->ops.tuner_ops.release(state->tuner); -#ifdef CONFIG_DVB_CORE_ATTACH - symbol_put_addr(state->tuner->ops.tuner_ops.release); -#endif - } kfree(state); } @@ -1458,7 +1444,6 @@ struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d) deb_info("attaching frontend af9005\n"); state->d = d; - state->tuner = NULL; state->opened = 0; memcpy(&state->frontend.ops, &af9005_fe_ops, diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 0c0b947..ca99e43 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -501,7 +501,7 @@ static struct dvb_pll_desc dvb_pll_opera1 = { /* Philips FCV1236D */ -struct dvb_pll_desc dvb_pll_fcv1236d = { +static struct dvb_pll_desc dvb_pll_fcv1236d = { /* Bit_0: RF Input select * Bit_1: 0=digital, 1=analog */ diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9dcbffd..e204e7b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -509,7 +509,7 @@ config VIDEO_VINO config VIDEO_STRADIS tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && !PPC64 + depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS help Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video driver for PCI. There is a product page at @@ -520,7 +520,7 @@ config VIDEO_ZORAN_ZR36060 config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && !PPC64 + depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 387cb21..f671500 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -33,6 +33,7 @@ #include <linux/pci.h> #include <linux/vmalloc.h> #include <linux/firmware.h> +#include <net/checksum.h> #include <asm/io.h> @@ -45,7 +46,7 @@ static void boot_msp34xx(struct bttv *btv, int pin); static void boot_bt832(struct bttv *btv); static void hauppauge_eeprom(struct bttv *btv); static void avermedia_eeprom(struct bttv *btv); -static void osprey_eeprom(struct bttv *btv); +static void osprey_eeprom(struct bttv *btv, const u8 ee[256]); static void modtec_eeprom(struct bttv *btv); static void init_PXC200(struct bttv *btv); static void init_RTV24(struct bttv *btv); @@ -2843,13 +2844,28 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, }, /* ---- card 0x8c ---------------------------------- */ + /* Has four Bt878 chips behind a PCI bridge, each chip has: + one external BNC composite input (mux 2) + three internal composite inputs (unknown muxes) + an 18-bit stereo A/D (CS5331A), which has: + one external stereo unblanced (RCA) audio connection + one (or 3?) internal stereo balanced (XLR) audio connection + input is selected via gpio to a 14052B mux + (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300) + gain is controlled via an X9221A chip on the I2C bus @0x28 + sample rate is controlled via gpio to an MK1413S + (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3) + There is neither a tuner nor an svideo input. */ [BTTV_BOARD_OSPREY440] = { .name = "Osprey 440", - .video_inputs = 1, - .audio_inputs = 1, + .video_inputs = 4, + .audio_inputs = 2, /* this is meaningless */ .tuner = UNSET, - .svhs = 1, - .muxsel = { 2 }, + .svhs = UNSET, + .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */ + .gpiomask = 0x303, + .gpiomute = 0x000, /* int + 32kHz */ + .gpiomux = { 0, 0, 0x000, 0x100}, .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -3453,11 +3469,12 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_OSPREY2xx: case BTTV_BOARD_OSPREY2x0_SVID: case BTTV_BOARD_OSPREY2x0: + case BTTV_BOARD_OSPREY440: case BTTV_BOARD_OSPREY500: case BTTV_BOARD_OSPREY540: case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); + osprey_eeprom(btv, eeprom_data); break; case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); @@ -3748,106 +3765,119 @@ static int __devinit pvr_boot(struct bttv *btv) /* ----------------------------------------------------------------------- */ /* some osprey specific stuff */ -static void __devinit osprey_eeprom(struct bttv *btv) +static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) { - int i = 0; - unsigned char *ee = eeprom_data; - unsigned long serial = 0; - - if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i = 0; i < 21; i++) - checksum += ee[i]; - if (checksum != ee[21]) - return; - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - for (i = 12; i < 21; i++) - serial *= 10, serial += ee[i] - '0'; - } + int i; + u32 serial = 0; + int cardid = -1; + + /* This code will nevery actually get called in this case.... */ + if (btv->c.type == BTTV_BOARD_UNKNOWN) { + /* this might be an antique... check for MMAC label in eeprom */ + if (!strncmp(ee, "MMAC", 4)) { + u8 checksum = 0; + for (i = 0; i < 21; i++) + checksum += ee[i]; + if (checksum != ee[21]) + return; + cardid = BTTV_BOARD_OSPREY1x0_848; + for (i = 12; i < 21; i++) + serial *= 10, serial += ee[i] - '0'; + } } else { - unsigned short type; - int offset = 4*16; - - for (; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for (i = 0; i < 14; i++) - checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) - return; - - /* found a valid descriptor */ - type = (ee[offset+4]<<8) | (ee[offset+5]); - - switch(type) { - /* 848 based */ - case 0x0004: - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - break; - case 0x0005: - btv->c.type = BTTV_BOARD_OSPREY101_848; - break; - - /* 878 based */ - case 0x0012: - case 0x0013: - btv->c.type = BTTV_BOARD_OSPREY1x0; - break; - case 0x0014: - case 0x0015: - btv->c.type = BTTV_BOARD_OSPREY1x1; - break; - case 0x0016: - case 0x0017: - case 0x0020: - btv->c.type = BTTV_BOARD_OSPREY1x1_SVID; - break; - case 0x0018: - case 0x0019: - case 0x001E: - case 0x001F: - btv->c.type = BTTV_BOARD_OSPREY2xx; - break; - case 0x001A: - case 0x001B: - btv->c.type = BTTV_BOARD_OSPREY2x0_SVID; - break; - case 0x0040: - btv->c.type = BTTV_BOARD_OSPREY500; - break; - case 0x0050: - case 0x0056: - btv->c.type = BTTV_BOARD_OSPREY540; - /* bttv_osprey_540_init(btv); */ - break; - case 0x0060: - case 0x0070: - case 0x00A0: - btv->c.type = BTTV_BOARD_OSPREY2x0; - /* enable output on select control lines */ - gpio_inout(0xffffff,0x000303); - break; - default: - /* unknown...leave generic, but get serial # */ - break; - } - serial = (ee[offset+6] << 24) - | (ee[offset+7] << 16) - | (ee[offset+8] << 8) - | (ee[offset+9]); - } - - printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", - btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); + unsigned short type; + + for (i = 4*16; i < 8*16; i += 16) { + u16 checksum = ip_compute_csum(ee + i, 16); + + if ((checksum&0xff) + (checksum>>8) == 0xff) + break; + } + if (i >= 8*16) + return; + ee += i; + + /* found a valid descriptor */ + type = be16_to_cpup((u16*)(ee+4)); + + switch(type) { + /* 848 based */ + case 0x0004: + cardid = BTTV_BOARD_OSPREY1x0_848; + break; + case 0x0005: + cardid = BTTV_BOARD_OSPREY101_848; + break; + + /* 878 based */ + case 0x0012: + case 0x0013: + cardid = BTTV_BOARD_OSPREY1x0; + break; + case 0x0014: + case 0x0015: + cardid = BTTV_BOARD_OSPREY1x1; + break; + case 0x0016: + case 0x0017: + case 0x0020: + cardid = BTTV_BOARD_OSPREY1x1_SVID; + break; + case 0x0018: + case 0x0019: + case 0x001E: + case 0x001F: + cardid = BTTV_BOARD_OSPREY2xx; + break; + case 0x001A: + case 0x001B: + cardid = BTTV_BOARD_OSPREY2x0_SVID; + break; + case 0x0040: + cardid = BTTV_BOARD_OSPREY500; + break; + case 0x0050: + case 0x0056: + cardid = BTTV_BOARD_OSPREY540; + /* bttv_osprey_540_init(btv); */ + break; + case 0x0060: + case 0x0070: + case 0x00A0: + cardid = BTTV_BOARD_OSPREY2x0; + /* enable output on select control lines */ + gpio_inout(0xffffff,0x000303); + break; + case 0x00D8: + cardid = BTTV_BOARD_OSPREY440; + break; + default: + /* unknown...leave generic, but get serial # */ + printk(KERN_INFO "bttv%d: " + "osprey eeprom: unknown card type 0x%04x\n", + btv->c.nr, type); + break; + } + serial = be32_to_cpup((u32*)(ee+6)); + } + + printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n", + btv->c.nr, cardid, + cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial); + + if (cardid<0 || btv->c.type == cardid) + return; + + /* card type isn't set correctly */ + if (card[btv->c.nr] < bttv_num_tvcards) { + printk(KERN_WARNING "bttv%d: osprey eeprom: " + "Not overriding user specified card type\n", btv->c.nr); + } else { + printk(KERN_INFO "bttv%d: osprey eeprom: " + "Changing card type from %d to %d\n", btv->c.nr, + btv->c.type, cardid); + btv->c.type = cardid; + } } /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 91b588d..8abb34a 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -417,6 +417,7 @@ struct ivtv_mailbox_data { #define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ #define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ #define IVTV_F_I_PIO 19 /* PIO in progress */ +#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 8e97a93..5dd519c 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -757,6 +757,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) itv->output_mode = OUT_NONE; itv->speed = 0; + clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); ivtv_release_stream(s); } @@ -799,7 +800,16 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ivtv_unmute(itv); ivtv_release_stream(s); } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { + struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; + ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); + + /* If all output streams are closed, and if the user doesn't have + IVTV_DEC_STREAM_TYPE_VOUT open, then disable VBI on TV-out. */ + if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { + /* disable VBI on TV-out */ + ivtv_disable_vbi(itv); + } } else { ivtv_stop_capture(id, 0); } diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index d0feabf..425eb10 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -72,8 +72,8 @@ retry: dst++; src++; } - release_firmware(fw); IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); + release_firmware(fw); return size; } IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 4773453..047624b 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -285,6 +285,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) return -EBUSY; + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + /* forces ivtv_set_speed to be called */ + itv->speed = 0; + } return ivtv_start_decoding(id, vc->play.speed); } @@ -309,6 +313,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (atomic_read(&itv->decoding) > 0) { ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); + set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); } break; @@ -317,8 +322,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (try) break; if (itv->output_mode != OUT_MPG) return -EBUSY; - if (atomic_read(&itv->decoding) > 0) { - ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 0); + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + int speed = itv->speed; + itv->speed = 0; + return ivtv_start_decoding(id, speed); } break; diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 814a673..5e3b679 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c @@ -40,6 +40,7 @@ #define API_HIGH_VOL (1 << 5) /* High volume command (i.e. called during encoding or decoding) */ #define API_NO_WAIT_MB (1 << 4) /* Command may not wait for a free mailbox */ #define API_NO_WAIT_RES (1 << 5) /* Command may not wait for the result */ +#define API_NO_POLL (1 << 6) /* Avoid pointless polling */ struct ivtv_api_info { int flags; /* Flags, see above */ @@ -51,7 +52,7 @@ struct ivtv_api_info { static const struct ivtv_api_info api_info[256] = { /* MPEG encoder API */ API_ENTRY(CX2341X_ENC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT), + API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT | API_NO_POLL), API_ENTRY(CX2341X_ENC_STOP_CAPTURE, API_RESULT), API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, API_CACHE), API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, API_CACHE), @@ -96,7 +97,7 @@ static const struct ivtv_api_info api_info[256] = { /* MPEG decoder API */ API_ENTRY(CX2341X_DEC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT), + API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT | API_NO_POLL), API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, API_RESULT), API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, API_RESULT), API_ENTRY(CX2341X_DEC_STEP_VIDEO, API_RESULT), @@ -290,6 +291,13 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) /* Get results */ then = jiffies; + if (!(flags & API_NO_POLL)) { + /* First try to poll, then switch to delays */ + for (i = 0; i < 100; i++) { + if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE) + break; + } + } while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { if (jiffies - then > api_timeout) { IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); @@ -301,7 +309,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) if (flags & API_NO_WAIT_RES) mdelay(1); else - ivtv_msleep_timeout(10, 0); + ivtv_msleep_timeout(1, 0); } if (jiffies - then > msecs_to_jiffies(100)) IVTV_DEBUG_WARN("%s took %u jiffies\n", diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 322b347..51df3f8 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -603,10 +603,6 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); - /* disable VBI signals, if the MPEG stream contains VBI data, - then that data will be processed automatically for you. */ - ivtv_disable_vbi(itv); - /* set audio mode to left/stereo for dual/stereo mode. */ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); @@ -639,7 +635,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) } if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, itv->params.width, itv->params.height, itv->params.audio_properties)) { - IVTV_DEBUG_WARN("COULDN'T INITIALIZE DECODER SOURCE\n"); + IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); } return 0; } @@ -909,11 +905,6 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) clear_bit(IVTV_F_S_STREAMING, &s->s_flags); ivtv_flush_queues(s); - if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { - /* disable VBI on TV-out */ - ivtv_disable_vbi(itv); - } - /* decrement decoding */ atomic_dec(&itv->decoding); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 868b688..e3371f9 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -517,6 +517,7 @@ static int vidioc_g_register (struct file *file, void *priv, __FUNCTION__, errCode); return errCode; } + reg->val = errCode; return 0; } @@ -531,8 +532,8 @@ static int vidioc_s_register (struct file *file, void *priv, if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* NT100x has a 8-bit register space */ - reg->val = (u8)usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (reg->val < 0) { + errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + if (errCode < 0) { err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode); return errCode; diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 8fb4a34..937c4a6 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -240,11 +240,16 @@ enum gpcs_type { struct zoran_format { char *name; +#ifdef CONFIG_VIDEO_V4L1_COMPAT int palette; +#endif +#ifdef CONFIG_VIDEO_V4L2 __u32 fourcc; int colorspace; +#endif int depth; __u32 flags; + __u32 vfespfr; }; /* flags */ #define ZORAN_FORMAT_COMPRESSED 1<<0 diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index b075276..ba2f4ed 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -429,8 +429,6 @@ zr36057_set_vfe (struct zoran *zr, reg |= (HorDcm << ZR36057_VFESPFR_HorDcm); reg |= (VerDcm << ZR36057_VFESPFR_VerDcm); reg |= (DispMode << ZR36057_VFESPFR_DispMode); - if (format->palette != VIDEO_PALETTE_YUV422 && format->palette != VIDEO_PALETTE_YUYV) - reg |= ZR36057_VFESPFR_LittleEndian; /* RJ: I don't know, why the following has to be the opposite * of the corresponding ZR36060 setting, but only this way * we get the correct colors when uncompressing to the screen */ @@ -439,36 +437,6 @@ zr36057_set_vfe (struct zoran *zr, if (zr->norm != VIDEO_MODE_NTSC) reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang reg |= ZR36057_VFESPFR_TopField; - switch (format->palette) { - - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_YUV422: - reg |= ZR36057_VFESPFR_YUV422; - break; - - case VIDEO_PALETTE_RGB555: - reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB565: - reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB24: - reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24; - break; - - case VIDEO_PALETTE_RGB32: - reg |= ZR36057_VFESPFR_RGB888; - break; - - default: - dprintk(1, - KERN_INFO "%s: set_vfe() - unknown color_fmt=%x\n", - ZR_DEVNAME(zr), format->palette); - return; - - } if (HorDcm >= 48) { reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ } else if (HorDcm >= 32) { @@ -476,6 +444,7 @@ zr36057_set_vfe (struct zoran *zr, } else if (HorDcm >= 16) { reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ } + reg |= format->vfespfr; btwrite(reg, ZR36057_VFESPFR); /* display configuration */ @@ -651,11 +620,17 @@ zr36057_set_memgrab (struct zoran *zr, int mode) { if (mode) { - if (btread(ZR36057_VSSFGR) & - (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab)) + /* We only check SnapShot and not FrameGrab here. SnapShot==1 + * means a capture is already in progress, but FrameGrab==1 + * doesn't necessary mean that. It's more correct to say a 1 + * to 0 transition indicates a capture completed. If a + * capture is pending when capturing is tuned off, FrameGrab + * will be stuck at 1 until capturing is turned back on. + */ + if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) dprintk(1, KERN_WARNING - "%s: zr36057_set_memgrab(1) with SnapShot or FrameGrab on!?\n", + "%s: zr36057_set_memgrab(1) with SnapShot on!?\n", ZR_DEVNAME(zr)); /* switch on VSync interrupts */ @@ -672,11 +647,12 @@ zr36057_set_memgrab (struct zoran *zr, zr->v4l_memgrab_active = 1; } else { - zr->v4l_memgrab_active = 0; - /* switch off VSync interrupts */ btand(~zr->card.vsync_int, ZR36057_ICR); // SW + zr->v4l_memgrab_active = 0; + zr->v4l_grab_frame = NO_GRAB_ACTIVE; + /* reenable grabbing to screen if it was running */ if (zr->v4l_overlay_active) { zr36057_overlay(zr, 1); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 17118a4..72a037b 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -99,88 +99,103 @@ #include <asm/byteorder.h> -const struct zoran_format zoran_formats[] = { - { - .name = "15-bit RGB", - .palette = VIDEO_PALETTE_RGB555, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_RGB555, +#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT) +#define ZFMT(pal, fcc, cs) \ + .palette = (pal), .fourcc = (fcc), .colorspace = (cs) +#elif defined(CONFIG_VIDEO_V4L2) +#define ZFMT(pal, fcc, cs) \ + .fourcc = (fcc), .colorspace = (cs) #else - .fourcc = V4L2_PIX_FMT_RGB555X, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, +#define ZFMT(pal, fcc, cs) \ + .palette = (pal) #endif + +const struct zoran_format zoran_formats[] = { + { + .name = "15-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB555, + V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB), .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif| + ZR36057_VFESPFR_LittleEndian, }, { - .name = "16-bit RGB", - .palette = VIDEO_PALETTE_RGB565, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_RGB565, -#else - .fourcc = V4L2_PIX_FMT_RGB565X, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + .name = "15-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB), + .depth = 15, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif, + }, { + .name = "16-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB565, + V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif| + ZR36057_VFESPFR_LittleEndian, + }, { + .name = "16-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), + .depth = 16, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif, }, { .name = "24-bit RGB", - .palette = VIDEO_PALETTE_RGB24, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_BGR24, -#else - .fourcc = V4L2_PIX_FMT_RGB24, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + ZFMT(VIDEO_PALETTE_RGB24, + V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB), .depth = 24, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24, }, { - .name = "32-bit RGB", - .palette = VIDEO_PALETTE_RGB32, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_BGR32, -#else - .fourcc = V4L2_PIX_FMT_RGB32, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + .name = "32-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB32, + V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB), + .depth = 32, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian, + }, { + .name = "32-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB), .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888, }, { .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUV422, -#ifdef CONFIG_VIDEO_V4L2 - .fourcc = V4L2_PIX_FMT_YUYV, - .colorspace = V4L2_COLORSPACE_SMPTE170M, -#endif + ZFMT(VIDEO_PALETTE_YUV422, + V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M), + .depth = 16, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_YUV422, + }, { + .name = "4:2:2, packed, UYVY", + ZFMT(VIDEO_PALETTE_UYVY, + V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M), .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian, }, { .name = "Hardware-encoded Motion-JPEG", - .palette = -1, -#ifdef CONFIG_VIDEO_V4L2 - .fourcc = V4L2_PIX_FMT_MJPEG, - .colorspace = V4L2_COLORSPACE_SMPTE170M, -#endif + ZFMT(-1, + V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M), .depth = 0, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_PLAYBACK | ZORAN_FORMAT_COMPRESSED, } }; -static const int zoran_num_formats = - (sizeof(zoran_formats) / sizeof(struct zoran_format)); +#define NUM_FORMATS ARRAY_SIZE(zoran_formats) // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined @@ -768,13 +783,13 @@ v4l_grab (struct file *file, struct zoran *zr = fh->zr; int res = 0, i; - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { if (zoran_formats[i].palette == mp->format && zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE && !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)) break; } - if (i == zoran_num_formats || zoran_formats[i].depth == 0) { + if (i == NUM_FORMATS || zoran_formats[i].depth == 0) { dprintk(1, KERN_ERR "%s: v4l_grab() - wrong bytes-per-pixel format\n", @@ -1173,10 +1188,14 @@ zoran_close_end_session (struct file *file) /* v4l capture */ if (fh->v4l_buffers.active != ZORAN_FREE) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); } /* v4l buffers */ @@ -2107,7 +2126,7 @@ zoran_do_ioctl (struct inode *inode, vpict->colour, vpict->contrast, vpict->depth, vpict->palette); - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { const struct zoran_format *fmt = &zoran_formats[i]; if (fmt->palette != -1 && @@ -2116,7 +2135,7 @@ zoran_do_ioctl (struct inode *inode, fmt->depth == vpict->depth) break; } - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOCSPICT - Invalid palette %d\n", @@ -2220,10 +2239,10 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vbuf->base, vbuf->width, vbuf->height, vbuf->depth, vbuf->bytesperline); - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].depth == vbuf->depth) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOCSFBUF - invalid fbuf depth %d\n", @@ -2672,14 +2691,14 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { if (zoran_formats[i].flags & flag) num++; if (num == fmt->index) break; } if (fmt->index < 0 /* late, but not too late */ || - i == zoran_num_formats) + i == NUM_FORMATS) return -EINVAL; memset(fmt, 0, sizeof(*fmt)); @@ -2737,7 +2756,8 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.pix.height = fh->v4l_settings.height; fmt->fmt.pix.sizeimage = - fh->v4l_buffers.buffer_size; + fh->v4l_settings.bytesperline * + fh->v4l_settings.height; fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc; fmt->fmt.pix.colorspace = @@ -2941,11 +2961,11 @@ zoran_do_ioctl (struct inode *inode, sfmtjpg_unlock_and_return: mutex_unlock(&zr->resource_lock); } else { - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n", @@ -2984,8 +3004,9 @@ zoran_do_ioctl (struct inode *inode, /* tell the user the * results/missing stuff */ - fmt->fmt.pix.sizeimage = fh->v4l_buffers.buffer_size /*zr->gbpl * zr->gheight */ - ; + fmt->fmt.pix.sizeimage = + fh->v4l_settings.height * + fh->v4l_settings.bytesperline; if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) fmt->fmt.pix.field = @@ -3053,10 +3074,10 @@ zoran_do_ioctl (struct inode *inode, fb->fmt.bytesperline, fb->fmt.pixelformat, (char *) &printformat); - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].fourcc == fb->fmt.pixelformat) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", @@ -3439,8 +3460,13 @@ zoran_do_ioctl (struct inode *inode, goto strmoff_unlock_and_return; /* unload capture */ - if (zr->v4l_memgrab_active) + if (zr->v4l_memgrab_active) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); + spin_unlock_irqrestore(&zr->spinlock, flags); + } for (i = 0; i < fh->v4l_buffers.num_buffers; i++) zr->v4l_buffers.buffer[i].state = @@ -3704,11 +3730,11 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n", ZR_DEVNAME(zr), (unsigned long long)*std); - if (*std == V4L2_STD_PAL) + if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) norm = VIDEO_MODE_PAL; - else if (*std == V4L2_STD_NTSC) + else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) norm = VIDEO_MODE_NTSC; - else if (*std == V4L2_STD_SECAM) + else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) norm = VIDEO_MODE_SECAM; else if (*std == V4L2_STD_ALL) norm = VIDEO_MODE_AUTO; @@ -4149,11 +4175,11 @@ zoran_do_ioctl (struct inode *inode, V4L2_BUF_TYPE_VIDEO_CAPTURE) { int i; - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { res = -EINVAL; goto tryfmt_unlock_and_return; } @@ -4213,8 +4239,8 @@ zoran_poll (struct file *file, { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - wait_queue_head_t *queue = NULL; int res = 0, frame; + unsigned long flags; /* we should check whether buffers are ready to be synced on * (w/o waits - O_NONBLOCK) here @@ -4228,51 +4254,58 @@ zoran_poll (struct file *file, switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: - if (fh->v4l_buffers.active == ZORAN_FREE || - zr->v4l_pend_head == zr->v4l_pend_tail) { - dprintk(1, - "%s: zoran_poll() - no buffers queued\n", - ZR_DEVNAME(zr)); - res = POLLNVAL; - goto poll_unlock_and_return; - } - queue = &zr->v4l_capq; - frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; - poll_wait(file, queue, wait); - if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) + poll_wait(file, &zr->v4l_capq, wait); + frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; + + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", + ZR_DEVNAME(zr), __FUNCTION__, + "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail, + "UPMD"[zr->v4l_buffers.buffer[frame].state], + zr->v4l_pend_tail, zr->v4l_pend_head); + /* Process is the one capturing? */ + if (fh->v4l_buffers.active != ZORAN_FREE && + /* Buffer ready to DQBUF? */ + zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) res = POLLIN | POLLRDNORM; + spin_unlock_irqrestore(&zr->spinlock, flags); + break; case ZORAN_MAP_MODE_JPG_REC: case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE || - zr->jpg_que_head == zr->jpg_que_tail) { - dprintk(1, - "%s: zoran_poll() - no buffers queued\n", - ZR_DEVNAME(zr)); - res = POLLNVAL; - goto poll_unlock_and_return; - } - queue = &zr->jpg_capq; + poll_wait(file, &zr->jpg_capq, wait); frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - poll_wait(file, queue, wait); - if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { + + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", + ZR_DEVNAME(zr), __FUNCTION__, + "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail, + "UPMD"[zr->jpg_buffers.buffer[frame].state], + zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); + if (fh->jpg_buffers.active != ZORAN_FREE && + zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) res = POLLIN | POLLRDNORM; else res = POLLOUT | POLLWRNORM; } + spin_unlock_irqrestore(&zr->spinlock, flags); + break; default: dprintk(1, + KERN_ERR "%s: zoran_poll() - internal error, unknown map_mode=%d\n", ZR_DEVNAME(zr), fh->map_mode); res = POLLNVAL; - goto poll_unlock_and_return; } -poll_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; @@ -4368,11 +4401,15 @@ zoran_vm_close (struct vm_area_struct *vma) mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); } //v4l_fbuffer_free(file); fh->v4l_buffers.allocated = 0; diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 4494e0f..f55cc03 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -102,4 +102,18 @@ config FUSION_LAN If unsure whether you really want or need this, say N. +config FUSION_LOGGING + bool "Fusion MPT logging facility" + depends on FUSION + ---help--- + This turns on a logging facility that can be used to debug a number + of Fusion MPT related problems. + + The debug level can be programmed on the fly via SysFS (hex values) + + echo [level] > /sys/class/scsi_host/host#/debug_level + + There are various debug levels that an be found in the source: + file:drivers/message/fusion/mptdebug.h + endmenu diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 6003b46..95c9532 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -1,39 +1,8 @@ # Fusion MPT drivers; recognized debug defines... -# MPT general: -#EXTRA_CFLAGS += -DMPT_DEBUG -#EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME -#EXTRA_CFLAGS += -DMPT_DEBUG_SG -#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS -#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS -#EXTRA_CFLAGS += -DMPT_DEBUG_INIT -#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT -#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL -#EXTRA_CFLAGS += -DMPT_DEBUG_DV -#EXTRA_CFLAGS += -DMPT_DEBUG_TM -#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY -# -# driver/module specifics... -# -# For mptbase: -#CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE -#CFLAGS_mptbase.o += -DMPT_DEBUG_CONFIG -#CFLAGS_mptbase.o += -DMPT_DEBUG_DL -#CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ -#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET -# -# For mptscsih: -#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI -# -# For mptctl: -#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL -# -# For mptfc: -#CFLAGS_mptfc.o += -DMPT_DEBUG_FC - -# For mptsas: -#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS -#CFLAGS_mptsas.o += -DMPT_DEBUG_SAS_WIDE +# enable verbose logging +# CONFIG_FUSION_LOGGING needs to be enabled in Kconfig +#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 04f75e2..e866dac 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -87,6 +87,10 @@ static int mpt_channel_mapping; module_param(mpt_channel_mapping, int, 0); MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)"); +static int mpt_debug_level; +module_param(mpt_debug_level, int, 0); +MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)"); + #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT 20000 @@ -179,9 +183,7 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); -#ifdef MPT_DEBUG_REPLY static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); -#endif static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); @@ -229,7 +231,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) int req_idx = 0; int cb_idx; - dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { @@ -312,9 +314,9 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); - DBG_DUMP_REPLY_FRAME(mr) + DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr) /* Check/log IOC log info */ @@ -329,10 +331,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) mpt_sas_log_info(ioc, log_info); } -#ifdef MPT_DEBUG_REPLY if (ioc_stat & MPI_IOCSTATUS_MASK) mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); -#endif /* Check for (valid) IO callback! */ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || @@ -414,17 +414,17 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) int freereq = 1; u8 func; - dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply() called\n", ioc->name)); - -#if defined(MPT_DEBUG_MSG_FRAME) - if (!(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { - dmfprintk((KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); - DBG_DUMP_REQUEST_FRAME_HDR(mf) + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name)); +#ifdef CONFIG_FUSION_LOGGING + if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) && + !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { + dmfprintk(ioc, printk(KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); + DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf) } #endif func = reply->u.hdr.Function; - dmfprintk((MYIOC_s_INFO_FMT "mpt_base_reply, Function=%02Xh\n", + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n", ioc->name, func)); if (func == MPI_FUNCTION_EVENT_NOTIFICATION) { @@ -435,7 +435,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) results = ProcessEventNotification(ioc, pEvReply, &evHandlers); if (results != evHandlers) { /* CHECKME! Any special handling needed here? */ - devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", + devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", ioc->name, evHandlers, results)); } @@ -446,7 +446,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { freereq = 0; } else { - devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", + devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", ioc->name, pEvReply)); } @@ -455,13 +455,13 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) #endif } else if (func == MPI_FUNCTION_EVENT_ACK) { - dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n", ioc->name)); } else if (func == MPI_FUNCTION_CONFIG) { CONFIGPARMS *pCfg; unsigned long flags; - dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n", + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n", ioc->name, mf, reply)); pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *))); @@ -484,7 +484,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) u16 status; status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; - dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", + dcprintk(ioc, printk(KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", status, le32_to_cpu(pReply->IOCLogInfo))); pCfg->status = status; @@ -789,7 +789,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth); #endif - dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", + dmfprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", ioc->name, handle, ioc->id, mf)); return mf; } @@ -820,27 +820,10 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; -#ifdef MPT_DEBUG_MSG_FRAME - { - u32 *m = mf->u.frame.hwhdr.__hdr; - int ii, n; - - printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", - ioc->name, m); - n = ioc->req_sz/4 - 1; - while (m[n] == 0) - n--; - for (ii=0; ii<=n; ii++) { - if (ii && ((ii%8)==0)) - printk("\n" KERN_INFO " "); - printk(" %08x", le32_to_cpu(m[ii])); - } - printk("\n"); - } -#endif + DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf); mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; - dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr); } @@ -955,7 +938,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; - dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", + dhsprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -1066,7 +1049,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) host_page_buffer_sz, &ioc->HostPageBuffer_dma)) != NULL) { - dinitprintk((MYIOC_s_INFO_FMT + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", ioc->name, ioc->HostPageBuffer, (u32)ioc->HostPageBuffer_dma, @@ -1410,31 +1393,37 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) struct proc_dir_entry *dent, *ent; #endif + ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); + if (ioc == NULL) { + printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); + return -ENOMEM; + } + + ioc->debug_level = mpt_debug_level; + if (mpt_debug_level) + printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level); + if (pci_enable_device(pdev)) return r; - dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n")); + dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk((KERN_INFO MYNAM + dprintk(ioc, printk(KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return r; } - if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) - dprintk((KERN_INFO MYNAM + if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { + dprintk(ioc, printk(KERN_INFO MYNAM ": Using 64 bit consistent mask\n")); - else - dprintk((KERN_INFO MYNAM + } else { + dprintk(ioc, printk(KERN_INFO MYNAM ": Not using 64 bit consistent mask\n")); - - ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); - if (ioc == NULL) { - printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); - return -ENOMEM; } + ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; @@ -1502,9 +1491,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) return -EINVAL; } ioc->memmap = mem; - dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); - dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", + dinitprintk(ioc, printk(KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", &ioc->facts, &ioc->pfacts[0])); ioc->mem_phys = mem_phys; @@ -1830,6 +1819,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int ret = 0; int reset_alt_ioc_active = 0; int irq_allocated = 0; + u8 *a; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); @@ -1858,7 +1848,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ - dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + dprintk(ioc, printk(KERN_INFO MYNAM + ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; @@ -1891,7 +1882,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (ii == 5) { - dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); ret = -2; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); @@ -1899,13 +1890,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (alt_ioc_ready) { if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { - dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); /* Retry - alt IOC was initialized once */ rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); } if (rc) { - dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { @@ -1938,7 +1931,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ioc->pci_irq = ioc->pcidev->irq; pci_set_master(ioc->pcidev); /* ?? */ pci_set_drvdata(ioc->pcidev, ioc); - dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + dprintk(ioc, printk(KERN_INFO MYNAM ": %s installed at interrupt " "%d\n", ioc->name, ioc->pcidev->irq)); } } @@ -1976,7 +1969,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ if (ioc->upload_fw) { - ddlprintk((MYIOC_s_INFO_FMT + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "firmware upload required!\n", ioc->name)); /* Controller is not operational, cannot do upload @@ -1992,7 +1985,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * chips (mpt_adapter_disable, * mpt_diag_reset) */ - ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + ": mpt_upload: alt_%s has cached_fw=%p \n", ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); ioc->alt_ioc->cached_fw = NULL; } @@ -2012,7 +2006,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ - dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + dinitprintk(ioc, printk(KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; @@ -2064,13 +2058,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * (LANPage1_t stuff) */ (void) GetLanConfigPages(ioc); -#ifdef MPT_DEBUG - { - u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; - dprintk((MYIOC_s_INFO_FMT "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - ioc->name, a[5], a[4], a[3], a[2], a[1], a[0] )); - } -#endif + a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "LanAddr = %02X:%02X:%02X:" + "%02X:%02X:%02X\n", + ioc->name, a[5], a[4], + a[3], a[2], a[1], a[0] )); + } } else { /* Get NVRAM and adapter maximums from SPP 0 and 2 @@ -2107,15 +2101,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) rc = handlers = 0; for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if ((ret == 0) && MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", - ioc->name, ii)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Calling IOC post_reset handler #%d\n", + ioc->name, ii)); rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET); handlers++; } if (alt_ioc_ready && MptResetHandlers[ii]) { - drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); + drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Calling alt-%s post_reset handler #%d\n", + ioc->name, ioc->alt_ioc->name, ii)); rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } @@ -2153,7 +2149,7 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) unsigned int func = PCI_FUNC(pdev->devfn); MPT_ADAPTER *ioc_srch; - dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x," + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x," " searching for devfn match on %x or %x\n", ioc->name, pci_name(pdev), pdev->bus->number, pdev->devfn, func-1, func+1)); @@ -2178,7 +2174,7 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) ioc_srch->name, ioc_srch->alt_ioc->name); break; } - dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", + dprintk(ioc, printk(KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; @@ -2199,7 +2195,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) int ret; if (ioc->cached_fw != NULL) { - ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); + ddlprintk(ioc, printk(KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", ret); @@ -2214,7 +2210,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->alloc != NULL) { sz = ioc->alloc_sz; - dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n", + dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n", ioc->name, ioc->alloc, ioc->alloc_sz)); pci_free_consistent(ioc->pcidev, sz, ioc->alloc, ioc->alloc_dma); @@ -2256,7 +2252,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; - pci_free_consistent(ioc->pcidev, sz, + pci_free_consistent(ioc->pcidev, sz, ioc->spi_data.pIocPg4, ioc->spi_data.IocPg4_dma); ioc->spi_data.pIocPg4 = NULL; @@ -2279,7 +2275,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) ": %s: host page buffers free failed (%d)!\n", __FUNCTION__, ret); } - dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", + dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, ioc->HostPageBuffer, @@ -2325,7 +2321,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) #if defined(CONFIG_MTRR) && 0 if (ioc->mtrr_reg > 0) { mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); } #endif @@ -2333,7 +2329,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) list_del(&ioc->list); sz_last = ioc->alloc_total; - dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", + dprintk(ioc, printk(KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); if (ioc->alt_ioc) @@ -2413,7 +2409,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) /* Get current [raw] IOC state */ ioc_state = mpt_GetIocState(ioc, 0); - dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); + dhsprintk(ioc, printk(KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); /* * Check to see if IOC got left/stuck in doorbell handshake @@ -2444,7 +2440,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Hmmm... Did it get left operational? */ if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { - dinitprintk((MYIOC_s_INFO_FMT "IOC operational unexpected\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n", ioc->name)); /* Check WhoInit. @@ -2453,7 +2449,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Else, fall through to KickStart case */ whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; - dinitprintk((KERN_INFO MYNAM + dinitprintk(ioc, printk(KERN_INFO MYNAM ": whoinit 0x%x statefault %d force %d\n", whoinit, statefault, force)); if (whoinit == MPI_WHOINIT_PCI_PEER) @@ -2589,7 +2585,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get IocFacts request req_sz=%d reply_sz=%d\n", ioc->name, req_sz, reply_sz)); @@ -2691,8 +2687,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) sz = sz >> 1; } ioc->NBShiftFactor = shiftFactor; - dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", - ioc->name, vv, shiftFactor, r)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", + ioc->name, vv, shiftFactor, r)); if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* @@ -2704,9 +2701,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) ioc->reply_sz = MPT_REPLY_FRAME_SIZE; ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); - dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); - dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n", ioc->name, ioc->req_sz, ioc->req_depth)); /* Get port facts! */ @@ -2765,7 +2762,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) get_pfacts.PortNumber = portnum; /* Assert: All other get_pfacts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n", ioc->name, portnum)); /* No non-zero fields in the get_pfacts request are greater than @@ -2841,12 +2838,12 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ioc->upload_fw = 1; else ioc->upload_fw = 0; - ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n", ioc->name, ioc->upload_fw, ioc->facts.Flags)); ioc_init.MaxDevices = (U8)ioc->devices_per_bus; ioc_init.MaxBuses = (U8)ioc->number_of_buses; - dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", ioc->name, ioc->facts.MsgVersion)); if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { // set MsgVersion and HeaderVersion host driver was built with @@ -2877,7 +2874,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ioc->facts.MaxDevices = ioc_init.MaxDevices; ioc->facts.MaxBuses = ioc_init.MaxBuses; - dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, @@ -2891,7 +2888,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) * since we don't even look at its contents. */ - dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n", ioc->name, &ioc_init)); if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) { @@ -2922,7 +2919,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); count++; } - dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", ioc->name, count)); ioc->aen_event_read_flag=0; @@ -2962,7 +2959,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* port_enable.MsgFlags = 0; */ /* port_enable.MsgContext = 0; */ - dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n", ioc->name, portnum, &port_enable)); /* RAID FW may take a long time to enable @@ -3015,7 +3012,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; - dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + dinitprintk(ioc, printk(KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); @@ -3059,7 +3056,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_alloc_fw_memory(ioc, sz); - dinitprintk((KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", + dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); if (ioc->cached_fw == NULL) { @@ -3091,14 +3088,14 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dinitprintk((KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n", + dinitprintk(ioc, printk(KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n", prequest, sgeoffset)); - DBG_DUMP_FW_REQUEST_FRAME(prequest) + DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest) ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); - dinitprintk((KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); cmdStatus = -EFAULT; if (ii == 0) { @@ -3113,13 +3110,13 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) cmdStatus = 0; } } - dinitprintk((MYIOC_s_INFO_FMT ": do_upload cmdStatus=%d \n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", ioc->name, cmdStatus)); if (cmdStatus) { - ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n", ioc->name)); mpt_free_fw_memory(ioc); } @@ -3154,7 +3151,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) u32 load_addr; u32 ioc_state=0; - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); @@ -3179,7 +3176,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) for (count = 0; count < 30; count ++) { diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { - ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n", ioc->name, count)); break; } @@ -3192,7 +3189,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) } if ( count == 30 ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! " + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! " "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", ioc->name, diag0val)); return -3; @@ -3218,10 +3215,10 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) pci_enable_io_access(ioc->pcidev); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress); - ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n", ioc->name, pFwHeader->LoadStartAddress)); - ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n", ioc->name, fwSize*4, ptrFw)); while (fwSize--) { CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); @@ -3236,7 +3233,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) fwSize = (pExtImage->ImageSize + 3) >> 2; ptrFw = (u32 *)pExtImage; - ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); @@ -3247,11 +3244,11 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) } /* Write the IopResetVectorRegAddr */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr); /* Write the IopResetVectorValue */ - ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue); /* Clear the internal flash bad bit - autoincrementing register, @@ -3285,11 +3282,11 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) pci_disable_io_access(ioc->pcidev); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, " + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, " "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", ioc->name, diag0val)); diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n", ioc->name, diag0val)); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); @@ -3300,7 +3297,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) ioc_state = mpt_GetIocState(ioc, 0); if ( (GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { - ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n", ioc->name, ioc_state)); return -EFAULT; } @@ -3308,17 +3305,20 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) for (count=0; count<HZ*20; count++) { if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", - ioc->name, count, ioc_state)); + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "downloadboot successful! (count=%d) IocState=%x\n", + ioc->name, count, ioc_state)); if (ioc->bus_type == SAS) { return 0; } if ((SendIocInit(ioc, sleepFlag)) != 0) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "downloadboot: SendIocInit failed\n", ioc->name)); return -EFAULT; } - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n", + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "downloadboot: SendIocInit successful\n", ioc->name)); return 0; } @@ -3328,8 +3328,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) mdelay (10); } } - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n", - ioc->name, ioc_state)); + ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "downloadboot failed! IocState=%x\n",ioc->name, ioc_state)); return -EFAULT; } @@ -3366,7 +3366,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) u32 ioc_state=0; int cnt,cntdn; - dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); + dinitprintk(ioc, printk(KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); if (ioc->bus_type == SPI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. @@ -3384,14 +3384,14 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) if (hard_reset_done < 0) return hard_reset_done; - dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n", ioc->name)); cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */ for (cnt=0; cnt<cntdn; cnt++) { ioc_state = mpt_GetIocState(ioc, 1); if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) { - dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n", ioc->name, cnt)); return hard_reset_done; } @@ -3434,15 +3434,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) u32 doorbell; int hard_reset_done = 0; int count = 0; -#ifdef MPT_DEBUG u32 diag1val = 0; -#endif /* Clear any existing interrupts */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { - drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " + drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " "address=%p\n", ioc->name, __FUNCTION__, &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07); @@ -3455,7 +3453,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); doorbell &= MPI_IOC_STATE_MASK; - drsprintk((MYIOC_s_INFO_FMT + drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "looking for READY STATE: doorbell=%x" " count=%d\n", ioc->name, doorbell, count)); @@ -3475,12 +3473,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* Use "Diagnostic reset" method! (only thing available!) */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n", + if (ioc->debug_level & MPT_DEBUG) { + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); -#endif + } /* Do the reset if we are told to ignore the reset history * or if the reset history is 0 @@ -3514,16 +3512,16 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n", ioc->name, diag0val)); } -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n", + if (ioc->debug_level & MPT_DEBUG) { + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); -#endif + } /* * Disable the ARM (Bug fix) * @@ -3537,7 +3535,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); hard_reset_done = 1; - dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n", ioc->name)); /* @@ -3552,12 +3550,14 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptResetHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", - ioc->name, ii)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Calling IOC pre_reset handler #%d\n", + ioc->name, ii)); r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET); if (ioc->alt_ioc) { - dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Calling alt-%s pre_reset handler #%d\n", + ioc->name, ioc->alt_ioc->name, ii)); r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET); } } @@ -3580,7 +3580,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) break; } - dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n", iocp->name, diag0val, count)); /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { @@ -3621,12 +3621,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) } diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif + if (ioc->debug_level & MPT_DEBUG) { + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n", + ioc->name, diag0val, diag1val)); + } /* Clear RESET_HISTORY bit! Place board in the * diagnostic mode to update the diag register. @@ -3680,12 +3680,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) return -3; } -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n", + if (ioc->debug_level & MPT_DEBUG) { + if (ioc->alt_ioc) + diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); -#endif + } /* * Reset flag that says we've enabled event notification @@ -3717,7 +3717,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) u32 state; int cntdn, count; - drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n", + drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n", ioc->name, reset_type)); CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) @@ -3782,14 +3782,14 @@ initChainBuffers(MPT_ADAPTER *ioc) return -1; ioc->ReqToChain = (int *) mem; - dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n", ioc->name, mem, sz)); mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) return -1; ioc->RequestNB = (int *) mem; - dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n", ioc->name, mem, sz)); } for (ii = 0; ii < ioc->req_depth; ii++) { @@ -3819,7 +3819,7 @@ initChainBuffers(MPT_ADAPTER *ioc) numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); } - dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", ioc->name, num_sge, numSGE)); if ( numSGE > MPT_SCSI_SG_DEPTH ) @@ -3832,7 +3832,7 @@ initChainBuffers(MPT_ADAPTER *ioc) } num_chain++; - dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n", ioc->name, numSGE, num_sge, num_chain)); if (ioc->bus_type == SPI) @@ -3849,7 +3849,7 @@ initChainBuffers(MPT_ADAPTER *ioc) return -1; ioc->ChainToChain = (int *) mem; - dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n", ioc->name, mem, sz)); } else { mem = (u8 *) ioc->ChainToChain; @@ -3885,22 +3885,22 @@ PrimeIocFifos(MPT_ADAPTER *ioc) return -1; total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); - dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); - dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n", ioc->name, reply_sz, reply_sz)); sz = (ioc->req_sz * ioc->req_depth); - dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n", ioc->name, ioc->req_sz, ioc->req_depth)); - dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n", ioc->name, sz, sz)); total_size += sz; sz = num_chain * ioc->req_sz; /* chain buffer pool size */ - dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n", ioc->name, ioc->req_sz, num_chain)); - dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n", ioc->name, sz, sz, num_chain)); total_size += sz; @@ -3911,7 +3911,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) goto out_fail; } - dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n", ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size)); memset(mem, 0, total_size); @@ -3922,7 +3922,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->reply_frames = (MPT_FRAME_HDR *) mem; ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); - dinitprintk((KERN_INFO MYNAM ": %s ReplyBuffers @ %p[%p]\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n", ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); alloc_dma += reply_sz; @@ -3933,7 +3933,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->req_frames = (MPT_FRAME_HDR *) mem; ioc->req_frames_dma = alloc_dma; - dinitprintk((KERN_INFO MYNAM ": %s RequestBuffers @ %p[%p]\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n", ioc->name, mem, (void *)(ulong)alloc_dma)); ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); @@ -3947,7 +3947,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma, sz, MTRR_TYPE_WRCOMB, 1); - dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n", ioc->name, ioc->req_frames_dma, sz)); #endif @@ -3959,7 +3959,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->ChainBuffer = mem; ioc->ChainBufferDMA = alloc_dma; - dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n", ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); /* Initialize the free chain Q. @@ -4004,7 +4004,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF); ioc->alloc_total += sz; - dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n", ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma)); } @@ -4012,7 +4012,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) /* Post Reply frames to FIFO */ alloc_dma = ioc->alloc_dma; - dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n", ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); for (i = 0; i < ioc->reply_depth; i++) { @@ -4093,7 +4093,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) failcnt++; - dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n", ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); /* Read doorbell and check for active bit */ @@ -4128,10 +4128,10 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, failcnt++; } - dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req)); - DBG_DUMP_REQUEST_FRAME_HDR(req) + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req)); + DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req) - dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n", ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : "")); /* @@ -4140,7 +4140,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0) failcnt++; - dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n", ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : "")); /* @@ -4196,7 +4196,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } if (cntdn) { - dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n", ioc->name, count)); return count; } @@ -4245,7 +4245,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } if (cntdn) { - dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n", ioc->name, count, howlong)); return count; } @@ -4297,7 +4297,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } } - dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); @@ -4333,10 +4333,10 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } #endif - dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name)); - DBG_DUMP_REPLY_FRAME(mptReply) + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name)); + DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply) - dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", ioc->name, t, u16cnt/2)); return u16cnt/2; } @@ -4761,7 +4761,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.nvram = (int *) mem; - dprintk((MYIOC_s_INFO_FMT "SCSI device NVRAM settings @ %p, sz=%d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n", ioc->name, ioc->spi_data.nvram, sz)); } @@ -4797,7 +4797,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.minSyncFactor = MPT_ASYNC; ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN; rc = 1; - ddvprintk((MYIOC_s_INFO_FMT "Unable to read PortPage0 minSyncFactor=%x\n", + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Unable to read PortPage0 minSyncFactor=%x\n", ioc->name, ioc->spi_data.minSyncFactor)); } else { /* Save the Port Page 0 data @@ -4808,7 +4809,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; - ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", + ddvprintk(ioc, printk(KERN_INFO MYNAM + " :%s noQas due to Capabilities=%x\n", ioc->name, pPP0->Capabilities)); } ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; @@ -4817,7 +4819,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.maxSyncOffset = (u8) (data >> 16); data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK; ioc->spi_data.minSyncFactor = (u8) (data >> 8); - ddvprintk((MYIOC_s_INFO_FMT "PortPage0 minSyncFactor=%x\n", + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "PortPage0 minSyncFactor=%x\n", ioc->name, ioc->spi_data.minSyncFactor)); } else { ioc->spi_data.maxSyncOffset = 0; @@ -4833,7 +4836,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if (ioc->spi_data.minSyncFactor < MPT_ULTRA) { ioc->spi_data.minSyncFactor = MPT_ULTRA; - ddvprintk((MYIOC_s_INFO_FMT "HVD or SE detected, minSyncFactor=%x\n", + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "HVD or SE detected, minSyncFactor=%x\n", ioc->name, ioc->spi_data.minSyncFactor)); } } @@ -4949,10 +4953,10 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion; ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength; - dcprintk((MYIOC_s_INFO_FMT "Headers: 0: version %d length %d\n", + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n", ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length)); - dcprintk((MYIOC_s_INFO_FMT "Headers: 1: version %d length %d\n", + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n", ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length)); return 0; } @@ -5361,12 +5365,12 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) cfg.physAddr = ioc1_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; if (mpt_config(ioc, &cfg) == 0) { - + tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING; if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) { tmp = le32_to_cpu(pIoc1->CoalescingTimeout); - dprintk((MYIOC_s_INFO_FMT "Coalescing Enabled Timeout = %d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n", ioc->name, tmp)); if (tmp > MPT_COALESCING_TIMEOUT) { @@ -5377,26 +5381,29 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) cfg.dir = 1; cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; if (mpt_config(ioc, &cfg) == 0) { - dprintk((MYIOC_s_INFO_FMT "Reset Current Coalescing Timeout to = %d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n", ioc->name, MPT_COALESCING_TIMEOUT)); cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; if (mpt_config(ioc, &cfg) == 0) { - dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout to = %d\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Reset NVRAM Coalescing Timeout to = %d\n", ioc->name, MPT_COALESCING_TIMEOUT)); } else { - dprintk((MYIOC_s_INFO_FMT "Reset NVRAM Coalescing Timeout Failed\n", - ioc->name)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Reset NVRAM Coalescing Timeout Failed\n", + ioc->name)); } } else { - dprintk((MYIOC_s_WARN_FMT "Reset of Current Coalescing Timeout Failed!\n", - ioc->name)); + dprintk(ioc, printk(MYIOC_s_WARN_FMT + "Reset of Current Coalescing Timeout Failed!\n", + ioc->name)); } } } else { - dprintk((MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name)); + dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name)); } } @@ -5461,13 +5468,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); if (evnp == NULL) { - devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", + devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", ioc->name)); return 0; } memset(evnp, 0, sizeof(*evnp)); - devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->ChainOffset = 0; @@ -5491,12 +5498,12 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) EventAck_t *pAck; if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", ioc->name,__FUNCTION__)); return -1; } - devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name)); + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name)); pAck->Function = MPI_FUNCTION_EVENT_ACK; pAck->ChainOffset = 0; @@ -5541,7 +5548,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) */ in_isr = in_interrupt(); if (in_isr) { - dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", + dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", ioc->name)); return -EPERM; } @@ -5549,7 +5556,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Get and Populate a free Frame */ if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { - dcprintk((MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", + dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", ioc->name)); return -EAGAIN; } @@ -5594,13 +5601,13 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { flagsLength |= pExtHdr->ExtPageLength * 4; - dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action)); } else { flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; - dcprintk((MYIOC_s_INFO_FMT "Sending Config request type %d, page %d and action %d\n", + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); } @@ -5650,7 +5657,7 @@ mpt_timer_expired(unsigned long data) { MPT_ADAPTER *ioc = (MPT_ADAPTER *) data; - dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired! \n", ioc->name)); + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name)); /* Perform a FW reload */ if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) @@ -5660,7 +5667,7 @@ mpt_timer_expired(unsigned long data) * Hard reset clean-up will wake up * process and free all resources. */ - dcprintk((MYIOC_s_WARN_FMT "mpt_timer_expired complete!\n", ioc->name)); + dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name)); return; } @@ -5679,7 +5686,7 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) CONFIGPARMS *pCfg; unsigned long flags; - dprintk((KERN_WARNING MYNAM + dprintk(ioc, printk(KERN_DEBUG MYNAM ": IOC %s_reset routed to MPT base driver!\n", reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); @@ -6050,7 +6057,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) int rc; unsigned long flags; - dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); #ifdef MFCNT printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name); printk("MF count 0x%x !\n", ioc->mfcnt); @@ -6082,11 +6089,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptResetHandlers[ii]) { - dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n", ioc->name, ii)); r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET); if (ioc->alt_ioc) { - dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET); } @@ -6108,7 +6115,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) ioc->alt_ioc->diagPending = 0; spin_unlock_irqrestore(&ioc->diagLock, flags); - dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); return rc; } @@ -6509,16 +6516,18 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } EventDescriptionStr(event, evData0, evStr); - devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n", + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n", ioc->name, event, evStr)); -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS) - printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); +#ifdef CONFIG_FUSION_LOGGING + devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM + ": Event data:\n")); for (ii = 0; ii < evDataLen; ii++) - printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); - printk("\n"); + devtverboseprintk(ioc, printk(" %08x", + le32_to_cpu(pEventReply->Data[ii]))); + devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); #endif /* @@ -6573,7 +6582,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptEvHandlers[ii]) { - devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n", ioc->name, ii)); r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; @@ -6585,10 +6594,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * If needed, send (a single) EventAck. */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { - devtverboseprintk((MYIOC_s_WARN_FMT + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "EventAck required\n",ioc->name)); if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n", ioc->name, ii)); } } @@ -6935,7 +6944,6 @@ union loginfo_type { sas_loginfo.dw.code, sas_loginfo.dw.subcode); } -#ifdef MPT_DEBUG_REPLY /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_iocstatus_info_config - IOCSTATUS information for config pages @@ -7240,7 +7248,6 @@ mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc); } -#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ EXPORT_SYMBOL(mpt_attach); @@ -7305,11 +7312,7 @@ fusion_init(void) /* Register for hard reset handling callbacks. */ - if (mpt_reset_register(mpt_base_index, mpt_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM ": Register for IOC reset notification\n")); - } else { - /* FIXME! */ - } + mpt_reset_register(mpt_base_index, mpt_ioc_reset); #ifdef CONFIG_PROC_FS (void) procmpt_create(); @@ -7328,8 +7331,6 @@ static void __exit fusion_exit(void) { - dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n")); - mpt_reset_deregister(mpt_base_index); #ifdef CONFIG_PROC_FS diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 98eb9c6..15ff226 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -186,6 +186,7 @@ * MPT drivers. NOTE: Users of these macro defs must * themselves define their own MYNAM. */ +#define MYIOC_s_DEBUG_FMT KERN_DEBUG MYNAM ": %s: " #define MYIOC_s_INFO_FMT KERN_INFO MYNAM ": %s: " #define MYIOC_s_NOTE_FMT KERN_NOTICE MYNAM ": %s: " #define MYIOC_s_WARN_FMT KERN_WARNING MYNAM ": %s: WARNING - " @@ -543,6 +544,7 @@ typedef struct _MPT_ADAPTER char board_tracer[16]; u16 nvdata_version_persistent; u16 nvdata_version_default; + int debug_level; u8 io_missing_delay; u8 device_missing_delay; SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ @@ -718,171 +720,7 @@ typedef struct _mpt_sge { /* * Funky (private) macros... */ -#ifdef MPT_DEBUG -#define dprintk(x) printk x -#else -#define dprintk(x) -#endif - -#ifdef MPT_DEBUG_INIT -#define dinitprintk(x) printk x -#define DBG_DUMP_FW_REQUEST_FRAME(mfp) \ - { int i, n = 10; \ - u32 *m = (u32 *)(mfp); \ - printk(KERN_INFO " "); \ - for (i=0; i<n; i++) \ - printk(" %08x", le32_to_cpu(m[i])); \ - printk("\n"); \ - } -#else -#define dinitprintk(x) -#define DBG_DUMP_FW_REQUEST_FRAME(mfp) -#endif - -#ifdef MPT_DEBUG_EXIT -#define dexitprintk(x) printk x -#else -#define dexitprintk(x) -#endif - -#if defined MPT_DEBUG_FAIL || defined (MPT_DEBUG_SG) -#define dfailprintk(x) printk x -#else -#define dfailprintk(x) -#endif - -#ifdef MPT_DEBUG_HANDSHAKE -#define dhsprintk(x) printk x -#else -#define dhsprintk(x) -#endif - -#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS) -#define devtprintk(x) printk x -#else -#define devtprintk(x) -#endif - -#ifdef MPT_DEBUG_VERBOSE_EVENTS -#define devtverboseprintk(x) printk x -#else -#define devtverboseprintk(x) -#endif - -#ifdef MPT_DEBUG_RESET -#define drsprintk(x) printk x -#else -#define drsprintk(x) -#endif - -//#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#if defined(MPT_DEBUG_MSG_FRAME) -#define dmfprintk(x) printk x -#define DBG_DUMP_REQUEST_FRAME(mfp) \ - { int i, n = 24; \ - u32 *m = (u32 *)(mfp); \ - for (i=0; i<n; i++) { \ - if (i && ((i%8)==0)) \ - printk("\n"); \ - printk("%08x ", le32_to_cpu(m[i])); \ - } \ - printk("\n"); \ - } -#else -#define dmfprintk(x) -#define DBG_DUMP_REQUEST_FRAME(mfp) -#endif - -#ifdef MPT_DEBUG_IRQ -#define dirqprintk(x) printk x -#else -#define dirqprintk(x) -#endif - -#ifdef MPT_DEBUG_SG -#define dsgprintk(x) printk x -#else -#define dsgprintk(x) -#endif - -#if defined(MPT_DEBUG_DL) || defined(MPT_DEBUG) -#define ddlprintk(x) printk x -#else -#define ddlprintk(x) -#endif - -#ifdef MPT_DEBUG_DV -#define ddvprintk(x) printk x -#else -#define ddvprintk(x) -#endif - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) -#define ddvtprintk(x) printk x -#else -#define ddvtprintk(x) -#endif - -#ifdef MPT_DEBUG_IOCTL -#define dctlprintk(x) printk x -#else -#define dctlprintk(x) -#endif - -#ifdef MPT_DEBUG_REPLY -#define dreplyprintk(x) printk x -#else -#define dreplyprintk(x) -#endif - -#ifdef DMPT_DEBUG_FC -#define dfcprintk(x) printk x -#else -#define dfcprintk(x) -#endif - -#ifdef MPT_DEBUG_TM -#define dtmprintk(x) printk x -#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \ - { u32 *m = (u32 *)(mfp); \ - int i, n = 13; \ - printk("TM_REQUEST:\n"); \ - for (i=0; i<n; i++) { \ - if (i && ((i%8)==0)) \ - printk("\n"); \ - printk("%08x ", le32_to_cpu(m[i])); \ - } \ - printk("\n"); \ - } -#define DBG_DUMP_TM_REPLY_FRAME(mfp) \ - { u32 *m = (u32 *)(mfp); \ - int i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16; \ - printk("TM_REPLY MessageLength=%d:\n", n); \ - for (i=0; i<n; i++) { \ - if (i && ((i%8)==0)) \ - printk("\n"); \ - printk(" %08x", le32_to_cpu(m[i])); \ - } \ - printk("\n"); \ - } -#else -#define dtmprintk(x) -#define DBG_DUMP_TM_REQUEST_FRAME(mfp) -#define DBG_DUMP_TM_REPLY_FRAME(mfp) -#endif - -#if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG) -#define dcprintk(x) printk x -#else -#define dcprintk(x) -#endif - -#if defined(MPT_DEBUG_SCSI) || defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#define dsprintk(x) printk x -#else -#define dsprintk(x) -#endif - +#include "mptdebug.h" #define MPT_INDEX_2_MFPTR(ioc,idx) \ (MPT_FRAME_HDR*)( (u8*)(ioc)->req_frames + (ioc)->req_sz * (idx) ) @@ -893,36 +731,6 @@ typedef struct _mpt_sge { #define MPT_INDEX_2_RFPTR(ioc,idx) \ (MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) ) -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) -#define DBG_DUMP_REPLY_FRAME(mfp) \ - { u32 *m = (u32 *)(mfp); \ - int i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16; \ - printk(KERN_INFO " "); \ - for (i=0; i<n; i++) \ - printk(" %08x", le32_to_cpu(m[i])); \ - printk("\n"); \ - } -#define DBG_DUMP_REQUEST_FRAME_HDR(mfp) \ - { int i, n = 3; \ - u32 *m = (u32 *)(mfp); \ - printk(KERN_INFO " "); \ - for (i=0; i<n; i++) \ - printk(" %08x", le32_to_cpu(m[i])); \ - printk("\n"); \ - } -#else -#define DBG_DUMP_REPLY_FRAME(mfp) -#define DBG_DUMP_REQUEST_FRAME_HDR(mfp) -#endif - -// debug sas wide ports -#ifdef MPT_DEBUG_SAS_WIDE -#define dsaswideprintk(x) printk x -#else -#define dsaswideprintk(x) -#endif - - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #define SCSI_STD_SENSE_BYTES 18 diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 58e6c31..89695e7 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -181,7 +181,7 @@ static inline int mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) { int rc = 0; - dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); +// dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); if (nonblock) { if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) @@ -190,7 +190,7 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) rc = -ERESTARTSYS; } - dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); +// dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down return %d\n", rc)); return rc; } @@ -209,18 +209,19 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) u16 iocStatus; u8 cmd; - dctlprintk(("mptctl_reply()!\n")); if (req) cmd = req->u.hdr.Function; else return 1; + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tcompleting mpi function (0x%02X), req=%p, " + "reply=%p\n", ioc->name, req->u.hdr.Function, req, reply)); if (ioc->ioctl) { if (reply==NULL) { - dctlprintk(("mptctl_reply() NULL Reply " - "Function=%x!\n", cmd)); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_reply() NULL Reply " + "Function=%x!\n", ioc->name, cmd)); ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; ioc->ioctl->reset &= ~MPTCTL_RESET_OK; @@ -233,14 +234,9 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) } - dctlprintk(("mptctl_reply() with req=%p " - "reply=%p Function=%x!\n", req, reply, cmd)); - /* Copy the reply frame (which much exist * for non-SCSI I/O) to the IOC structure. */ - dctlprintk(("Copying Reply Frame @%p to ioc%d!\n", - reply, ioc->id)); memcpy(ioc->ioctl->ReplyFrame, reply, min(ioc->reply_sz, 4*reply->u.reply.MsgLength)); ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID; @@ -252,8 +248,24 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) if (iocStatus == MPI_IOCSTATUS_SUCCESS) ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; + if (iocStatus || reply->u.reply.IOCLogInfo) + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tiocstatus (0x%04X), " + "loginfo (0x%08X)\n", ioc->name, + iocStatus, + le32_to_cpu(reply->u.reply.IOCLogInfo))); + if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { + + if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState) + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "\tscsi_status (0x%02x), scsi_state (0x%02x), " + "tag = (0x%04x), transfer_count (0x%08x)\n", ioc->name, + reply->u.sreply.SCSIStatus, + reply->u.sreply.SCSIState, + le16_to_cpu(reply->u.sreply.TaskTag), + le32_to_cpu(reply->u.sreply.TransferCount))); + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || @@ -298,8 +310,8 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) { int rc = 1; - dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n", - ioctl->ioc->id)); + dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n", + ioctl->ioc->name, ioctl->ioc->id)); if (ioctl == NULL) return; @@ -311,7 +323,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) /* Issue a reset for this device. * The IOC is not responding. */ - dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", + dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", ioctl->ioc->name)); mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP); } @@ -350,14 +362,14 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) /* Send request */ if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc)) == NULL) { - dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", + dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt, no msg frames!!\n", ioctl->ioc->name)); mptctl_free_tm_flags(ioctl->ioc); return -ENOMEM; } - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", + dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", ioctl->ioc->name, mf)); pScsiTm = (SCSITaskMgmt_t *) mf; @@ -377,15 +389,15 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) pScsiTm->Reserved2[ii] = 0; pScsiTm->TaskMsgContext = 0; - dtmprintk((MYIOC_s_INFO_FMT + dtmprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name)); - DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); + DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf); ioctl->wait_done=0; if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); goto mptctl_bus_reset_done; @@ -456,7 +468,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_IOCTL *ioctl = ioc->ioctl; - dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n", + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": IOC %s_reset routed to IOCTL driver!\n",ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); @@ -487,7 +499,8 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) event = le32_to_cpu(pEvReply->Event) & 0xFF; - dctlprintk(("%s() called\n", __FUNCTION__)); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s() called\n", + ioc->name, __FUNCTION__)); if(async_queue == NULL) return 1; @@ -497,8 +510,10 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) */ if (event == 0x21 ) { ioc->aen_event_read_flag=1; - dctlprintk(("Raised SIGIO to application\n")); - devtverboseprintk(("Raised SIGIO to application\n")); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Raised SIGIO to application\n", + ioc->name)); + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Raised SIGIO to application\n", ioc->name)); kill_fasync(&async_queue, SIGIO, POLL_IN); return 1; } @@ -515,8 +530,10 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) */ if (ioc->events && (ioc->eventTypes & ( 1 << event))) { ioc->aen_event_read_flag=1; - dctlprintk(("Raised SIGIO to application\n")); - devtverboseprintk(("Raised SIGIO to application\n")); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Raised SIGIO to application\n", ioc->name)); + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Raised SIGIO to application\n", ioc->name)); kill_fasync(&async_queue, SIGIO, POLL_IN); } return 1; @@ -530,14 +547,12 @@ mptctl_fasync(int fd, struct file *filep, int mode) list_for_each_entry(ioc, &ioc_list, list) ioc->aen_event_read_flag=0; - dctlprintk(("%s() called\n", __FUNCTION__)); return fasync_helper(fd, filep, mode, &async_queue); } static int mptctl_release(struct inode *inode, struct file *filep) { - dctlprintk(("%s() called\n", __FUNCTION__)); return fasync_helper(-1, filep, 0, &async_queue); } @@ -558,8 +573,6 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int ret; MPT_ADAPTER *iocp = NULL; - dctlprintk(("mptctl_ioctl() called\n")); - if (copy_from_user(&khdr, uhdr, sizeof(khdr))) { printk(KERN_ERR "%s::mptctl_ioctl() @%d - " "Unable to copy mpt_ioctl_header data @ %p\n", @@ -574,13 +587,13 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) iocnumX = khdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnumX)); + printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnumX); return -ENODEV; } if (!iocp->active) { - printk(KERN_ERR "%s::mptctl_ioctl() @%d - Controller disabled.\n", + printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - Controller disabled.\n", __FILE__, __LINE__); return -EFAULT; } @@ -612,8 +625,6 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) return ret; - dctlprintk((MYIOC_s_INFO_FMT ": mptctl_ioctl()\n", iocp->name)); - if (cmd == MPTFWDOWNLOAD) ret = mptctl_fw_download(arg); else if (cmd == MPTCOMMAND) @@ -648,8 +659,6 @@ static int mptctl_do_reset(unsigned long arg) struct mpt_ioctl_diag_reset krinfo; MPT_ADAPTER *iocp; - dctlprintk((KERN_INFO "mptctl_do_reset called.\n")); - if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) { printk(KERN_ERR "%s@%d::mptctl_do_reset - " "Unable to copy mpt_ioctl_diag_reset struct @ %p\n", @@ -658,11 +667,14 @@ static int mptctl_do_reset(unsigned long arg) } if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) { - dctlprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n", - __FILE__, __LINE__, krinfo.hdr.iocnum)); + printk(KERN_DEBUG "%s@%d::mptctl_do_reset - ioc%d not found!\n", + __FILE__, __LINE__, krinfo.hdr.iocnum); return -ENODEV; /* (-6) No such device or address */ } + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n", + iocp->name)); + if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) { printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n", __FILE__, __LINE__); @@ -695,7 +707,6 @@ mptctl_fw_download(unsigned long arg) struct mpt_fw_xfer __user *ufwdl = (void __user *) arg; struct mpt_fw_xfer kfwdl; - dctlprintk((KERN_INFO "mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) { printk(KERN_ERR "%s@%d::_ioctl_fwdl - " "Unable to copy mpt_fw_xfer struct @ %p\n", @@ -744,15 +755,8 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) u16 iocstat; pFWDownloadReply_t ReplyMsg = NULL; - dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); - - dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf)); - dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen)); - dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc)); - if (mpt_verify_adapter(ioc, &iocp) < 0) { - dctlprintk(("ioctl_fwdl - ioc%d not found!\n", - ioc)); + printk(KERN_DEBUG "ioctl_fwdl - ioc%d not found!\n", ioc); return -ENODEV; /* (-6) No such device or address */ } else { @@ -761,6 +765,16 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) return -EAGAIN; } + + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT + "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id)); + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.bufp = %p\n", + iocp->name, ufwbuf)); + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n", + iocp->name, (int)fwlen)); + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc = %04xh\n", + iocp->name, ioc)); + dlmsg = (FWDownload_t*) mf; ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; sgOut = (char *) (ptsge + 1); @@ -829,7 +843,8 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) goto fwdl_out; } - dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: sgl buffer = %p, sgfrags = %d\n", + iocp->name, sgl, numfrags)); /* * Parse SG list, copying sgl itself, @@ -865,15 +880,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) sgOut += (sizeof(dma_addr_t) + sizeof(u32)); } -#ifdef MPT_DEBUG - { - u32 *m = (u32 *)mf; - printk(KERN_INFO MYNAM ": F/W download request:\n" KERN_INFO " "); - for (i=0; i < 7+numfrags*2; i++) - printk(" %08x", le32_to_cpu(m[i])); - printk("\n"); - } -#endif + DBG_DUMP_FW_DOWNLOAD(iocp, (u32 *)mf, numfrags); /* * Finally, perform firmware download. @@ -1049,13 +1056,11 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, *frags = numfrags; *blp = buflist; - dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " - "%d SG frags generated!\n", - numfrags)); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: kbuf_alloc_2_sgl() - " + "%d SG frags generated!\n", ioc->name, numfrags)); - dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " - "last (big) alloc_sz=%d\n", - alloc_sz)); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: kbuf_alloc_2_sgl() - " + "last (big) alloc_sz=%d\n", ioc->name, alloc_sz)); return sglbuf; @@ -1139,7 +1144,8 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTE pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sgl, sgl_dma); kfree(buflist); - dctlprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n)); + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: Free'd 1 SGL buf + %d kbufs!\n", + ioc->name, n)); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1166,7 +1172,6 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) struct scsi_device *sdev; VirtDevice *vdev; - dctlprintk((": mptctl_getiocinfo called.\n")); /* Add of PCI INFO results in unaligned access for * IA64 and Sparc. Reset long to int. Return no PCI * data for obsolete format. @@ -1199,8 +1204,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); kfree(karg); return -ENODEV; } @@ -1214,6 +1219,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) return -EFAULT; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_getiocinfo called.\n", + ioc->name)); + /* Fill in the data and return the structure to the calling * program */ @@ -1320,7 +1328,6 @@ mptctl_gettargetinfo (unsigned long arg) u8 port; struct scsi_device *sdev; - dctlprintk(("mptctl_gettargetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to read in mpt_ioctl_targetinfo struct @ %p\n", @@ -1330,11 +1337,13 @@ mptctl_gettargetinfo (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n", + ioc->name)); /* Get the port number and set the maximum number of bytes * in the returned structure. * Ignore the port setting. @@ -1434,7 +1443,6 @@ mptctl_readtest (unsigned long arg) MPT_ADAPTER *ioc; int iocnum; - dctlprintk(("mptctl_readtest called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to read in mpt_ioctl_test struct @ %p\n", @@ -1444,11 +1452,13 @@ mptctl_readtest (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_readtest() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n", + ioc->name)); /* Fill in the data and return the structure to the calling * program */ @@ -1494,7 +1504,6 @@ mptctl_eventquery (unsigned long arg) MPT_ADAPTER *ioc; int iocnum; - dctlprintk(("mptctl_eventquery called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to read in mpt_ioctl_eventquery struct @ %p\n", @@ -1504,11 +1513,13 @@ mptctl_eventquery (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_eventquery() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n", + ioc->name)); karg.eventEntries = MPTCTL_EVENT_LOG_SIZE; karg.eventTypes = ioc->eventTypes; @@ -1532,7 +1543,6 @@ mptctl_eventenable (unsigned long arg) MPT_ADAPTER *ioc; int iocnum; - dctlprintk(("mptctl_eventenable called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { printk(KERN_ERR "%s@%d::mptctl_eventenable - " "Unable to read in mpt_ioctl_eventenable struct @ %p\n", @@ -1542,11 +1552,13 @@ mptctl_eventenable (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_eventenable() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n", + ioc->name)); if (ioc->events == NULL) { /* Have not yet allocated memory - do so now. */ @@ -1579,7 +1591,6 @@ mptctl_eventreport (unsigned long arg) int iocnum; int numBytes, maxEvents, max; - dctlprintk(("mptctl_eventreport called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to read in mpt_ioctl_eventreport struct @ %p\n", @@ -1589,10 +1600,12 @@ mptctl_eventreport (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_eventreport() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n", + ioc->name)); numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header); maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS); @@ -1632,7 +1645,6 @@ mptctl_replace_fw (unsigned long arg) int iocnum; int newFwSize; - dctlprintk(("mptctl_replace_fw called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", @@ -1642,11 +1654,13 @@ mptctl_replace_fw (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n", + ioc->name)); /* If caching FW, Free the old FW image */ if (ioc->cached_fw == NULL) @@ -1704,7 +1718,6 @@ mptctl_mpt_command (unsigned long arg) int iocnum; int rc; - dctlprintk(("mptctl_command called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { printk(KERN_ERR "%s@%d::mptctl_mpt_command - " @@ -1715,8 +1728,8 @@ mptctl_mpt_command (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1756,13 +1769,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ulong timeout; struct scsi_device *sdev; - dctlprintk(("mptctl_do_mpt_command called.\n")); bufIn.kptr = bufOut.kptr = NULL; if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } if (!ioc->ioctl) { @@ -1816,6 +1828,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) /* Verify that this request is allowed. */ + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n", + ioc->name, hdr->Function, mf)); + switch (hdr->Function) { case MPI_FUNCTION_IOC_FACTS: case MPI_FUNCTION_PORT_FACTS: @@ -1823,6 +1838,18 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) break; case MPI_FUNCTION_CONFIG: + { + Config_t *config_frame; + config_frame = (Config_t *)mf; + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\ttype=0x%02x ext_type=0x%02x " + "number=0x%02x action=0x%02x\n", ioc->name, + config_frame->Header.PageType, + config_frame->ExtPageType, + config_frame->Header.PageNumber, + config_frame->Action)); + break; + } + case MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND: case MPI_FUNCTION_FC_EX_LINK_SRVC_SEND: case MPI_FUNCTION_FW_UPLOAD: @@ -2158,12 +2185,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ioc->ioctl->wait_done = 0; if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { - DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); + DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); if (mpt_send_handshake_request(mptctl_id, ioc, sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" " (ioc %p, mf %p) \n", ioc->name, ioc, mf)); mptctl_free_tm_flags(ioc); @@ -2303,7 +2330,6 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) MPT_FRAME_HDR *mf = NULL; MPIHeader_t *mpi_hdr; - dctlprintk((": mptctl_hp_hostinfo called.\n")); /* Reset long to int. Should affect IA64 and SPARC only */ if (data_size == sizeof(hp_host_info_t)) @@ -2322,10 +2348,12 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n", + ioc->name)); /* Fill in the data and return the structure to the calling * program @@ -2441,7 +2469,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) * Gather ISTWI(Industry Standard Two Wire Interface) Data */ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", ioc->name,__FUNCTION__)); goto out; } @@ -2474,7 +2502,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); if(rc <=0 && (ioc->ioctl->wait_done != 1 )) { - /* + /* * Now we need to reset the board */ mpt_free_msg_frame(ioc, mf); @@ -2482,7 +2510,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) goto out; } - /* + /* *ISTWI Data Definition * pbuf[0] = FW_VERSION = 0x4 * pbuf[1] = Bay Count = 6 or 4 or 2, depending on @@ -2538,7 +2566,6 @@ mptctl_hp_targetinfo(unsigned long arg) ConfigPageHeader_t hdr; int tmp, np, rc = 0; - dctlprintk((": mptctl_hp_targetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " "Unable to read in hp_host_targetinfo struct @ %p\n", @@ -2548,10 +2575,12 @@ mptctl_hp_targetinfo(unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + printk(KERN_DEBUG "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", + __FILE__, __LINE__, iocnum); return -ENODEV; } + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_targetinfo called.\n", + ioc->name)); /* There is nothing to do for FCP parts. */ @@ -2694,7 +2723,6 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, int nonblock = (filp->f_flags & O_NONBLOCK); int ret; - dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n")); if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32))) return -EFAULT; @@ -2703,14 +2731,16 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, iocnumX = kfw32.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dctlprintk((KERN_ERR MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n", - __LINE__, iocnumX)); + printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n", + __LINE__, iocnumX); return -ENODEV; } if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) return ret; + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "compat_mptfwxfer_ioctl() called\n", + iocp->name)); kfw.iocnum = iocnum; kfw.fwlen = kfw32.fwlen; kfw.bufp = compat_ptr(kfw32.bufp); @@ -2734,8 +2764,6 @@ compat_mpt_command(struct file *filp, unsigned int cmd, int nonblock = (filp->f_flags & O_NONBLOCK); int ret; - dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n")); - if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) return -EFAULT; @@ -2743,14 +2771,16 @@ compat_mpt_command(struct file *filp, unsigned int cmd, iocnumX = karg32.hdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dctlprintk((KERN_ERR MYNAM "::compat_mpt_command @%d - ioc%d not found!\n", - __LINE__, iocnumX)); + printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n", + __LINE__, iocnumX); return -ENODEV; } if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) return ret; + dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "compat_mpt_command() called\n", + iocp->name)); /* Copy data to karg */ karg.hdr.iocnum = karg32.hdr.iocnum; karg.hdr.port = karg32.hdr.port; @@ -2878,11 +2908,7 @@ static int __init mptctl_init(void) show_mptmod_ver(my_NAME, my_VERSION); - if(mpt_device_driver_register(&mptctl_driver, - MPTCTL_DRIVER) != 0 ) { - dprintk((KERN_INFO MYNAM - ": failed to register dd callbacks\n")); - } + mpt_device_driver_register(&mptctl_driver, MPTCTL_DRIVER); /* Register this device */ err = misc_register(&mptctl_miscdev); @@ -2905,16 +2931,8 @@ static int __init mptctl_init(void) goto out_fail; } - if (mpt_reset_register(mptctl_id, mptctl_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); - } else { - /* FIXME! */ - } - - if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { - devtverboseprintk((KERN_INFO MYNAM - ": Registered for IOC event notifications\n")); - } + mpt_reset_register(mptctl_id, mptctl_ioc_reset); + mpt_event_register(mptctl_id, mptctl_event_process); return 0; @@ -2934,11 +2952,9 @@ static void mptctl_exit(void) /* De-register reset handler from base module */ mpt_reset_deregister(mptctl_id); - dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); /* De-register callback handler from base module */ mpt_deregister(mptctl_id); - printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n"); mpt_device_driver_deregister(MPTCTL_DRIVER); diff --git a/drivers/message/fusion/mptdebug.h b/drivers/message/fusion/mptdebug.h new file mode 100644 index 0000000..ffdb0a6 --- /dev/null +++ b/drivers/message/fusion/mptdebug.h @@ -0,0 +1,288 @@ +/* + * linux/drivers/message/fusion/mptdebug.h + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2007 LSI Corporation + * (mailto:DL-MPTFusionLinux@lsi.com) + * + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +#ifndef MPTDEBUG_H_INCLUDED +#define MPTDEBUG_H_INCLUDED + +/* + * debug level can be programmed on the fly via SysFS (hex values) + * + * Example: (programming for MPT_DEBUG_EVENTS on host 5) + * + * echo 8 > /sys/class/scsi_host/host5/debug_level + * + * -------------------------------------------------------- + * mpt_debug_level - command line parameter + * this allow enabling debug at driver load time (for all iocs) + * + * Example (programming for MPT_DEBUG_EVENTS) + * + * insmod mptbase.ko mpt_debug_level=8 + * + * -------------------------------------------------------- + * CONFIG_FUSION_LOGGING - enables compiling debug into driver + * this can be enabled in the driver Makefile + * + * + * -------------------------------------------------------- + * Please note most debug prints are set to logging priority = debug + * This is the lowest level, and most verbose. Please refer to manual + * pages for syslogd or syslogd-ng on how to configure this. + */ + +#define MPT_DEBUG 0x00000001 +#define MPT_DEBUG_MSG_FRAME 0x00000002 +#define MPT_DEBUG_SG 0x00000004 +#define MPT_DEBUG_EVENTS 0x00000008 +#define MPT_DEBUG_VERBOSE_EVENTS 0x00000010 +#define MPT_DEBUG_INIT 0x00000020 +#define MPT_DEBUG_EXIT 0x00000040 +#define MPT_DEBUG_FAIL 0x00000080 +#define MPT_DEBUG_TM 0x00000100 +#define MPT_DEBUG_DV 0x00000200 +#define MPT_DEBUG_REPLY 0x00000400 +#define MPT_DEBUG_HANDSHAKE 0x00000800 +#define MPT_DEBUG_CONFIG 0x00001000 +#define MPT_DEBUG_DL 0x00002000 +#define MPT_DEBUG_RESET 0x00008000 +#define MPT_DEBUG_SCSI 0x00010000 +#define MPT_DEBUG_IOCTL 0x00020000 +#define MPT_DEBUG_FC 0x00080000 +#define MPT_DEBUG_SAS 0x00100000 +#define MPT_DEBUG_SAS_WIDE 0x00200000 + +/* + * CONFIG_FUSION_LOGGING - enabled in Kconfig + */ + +#ifdef CONFIG_FUSION_LOGGING +#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ +{ \ + if (IOC->debug_level & BITS) \ + CMD; \ +} +#else +#define MPT_CHECK_LOGGING(IOC, CMD, BITS) +#endif + + +/* + * debug macros + */ + +#define dprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG) + +#define dsgprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG) + +#define devtprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS) + +#define devtverboseprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_VERBOSE_EVENTS) + +#define dinitprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT) + +#define dexitprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT) + +#define dfailprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL) + +#define dtmprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM) + +#define ddvprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DV) + +#define dreplyprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY) + +#define dhsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE) + +#define dcprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG) + +#define ddlprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL) + +#define drsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET) + +#define dsprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI) + +#define dctlprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL) + +#define dfcprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FC) + +#define dsasprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS) + +#define dsaswideprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) + + + +/* + * Verbose logging + */ +#if defined(MPT_DEBUG_VERBOSE) && defined(CONFIG_FUSION_LOGGING) +static inline void +DBG_DUMP_FW_DOWNLOAD(MPT_ADAPTER *ioc, u32 *mfp, int numfrags) +{ + int i; + + if (!(ioc->debug_level & MPT_DEBUG)) + return; + printk(KERN_DEBUG "F/W download request:\n"); + for (i=0; i < 7+numfrags*2; i++) + printk(" %08x", le32_to_cpu(mfp[i])); + printk("\n"); +} + +static inline void +DBG_DUMP_PUT_MSG_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int ii, n; + + if (!(ioc->debug_level & MPT_DEBUG_MSG_FRAME)) + return; + printk(KERN_DEBUG "%s: About to Put msg frame @ %p:\n", + ioc->name, mfp); + n = ioc->req_sz/4 - 1; + while (mfp[n] == 0) + n--; + for (ii=0; ii<=n; ii++) { + if (ii && ((ii%8)==0)) + printk("\n"); + printk(" %08x", le32_to_cpu(mfp[ii])); + } + printk("\n"); +} + +static inline void +DBG_DUMP_FW_REQUEST_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_MSG_FRAME)) + return; + n = 10; + printk(KERN_INFO " "); + for (i = 0; i < n; i++) + printk(" %08x", le32_to_cpu(mfp[i])); + printk("\n"); +} + +static inline void +DBG_DUMP_REQUEST_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_MSG_FRAME)) + return; + n = 24; + for (i=0; i<n; i++) { + if (i && ((i%8)==0)) + printk("\n"); + printk("%08x ", le32_to_cpu(mfp[i])); + } + printk("\n"); +} + +static inline void +DBG_DUMP_REPLY_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_MSG_FRAME)) + return; + n = (le32_to_cpu(mfp[0]) & 0x00FF0000) >> 16; + printk(KERN_INFO " "); + for (i=0; i<n; i++) + printk(" %08x", le32_to_cpu(mfp[i])); + printk("\n"); +} + +static inline void +DBG_DUMP_REQUEST_FRAME_HDR(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_MSG_FRAME)) + return; + n = 3; + printk(KERN_INFO " "); + for (i=0; i<n; i++) + printk(" %08x", le32_to_cpu(mfp[i])); + printk("\n"); +} + +static inline void +DBG_DUMP_TM_REQUEST_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_TM)) + return; + n = 13; + printk(KERN_DEBUG "TM_REQUEST:\n"); + for (i=0; i<n; i++) { + if (i && ((i%8)==0)) + printk("\n"); + printk("%08x ", le32_to_cpu(mfp[i])); + } + printk("\n"); +} + +static inline void +DBG_DUMP_TM_REPLY_FRAME(MPT_ADAPTER *ioc, u32 *mfp) +{ + int i, n; + + if (!(ioc->debug_level & MPT_DEBUG_TM)) + return; + n = (le32_to_cpu(mfp[0]) & 0x00FF0000) >> 16; + printk(KERN_DEBUG "TM_REPLY MessageLength=%d:\n", n); + for (i=0; i<n; i++) { + if (i && ((i%8)==0)) + printk("\n"); + printk(" %08x", le32_to_cpu(mfp[i])); + } + printk("\n"); +} + +#define dmfprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) + +# else /* ifdef MPT_DEBUG_MF */ + +#define DBG_DUMP_FW_DOWNLOAD(IOC, mfp, numfrags) +#define DBG_DUMP_PUT_MSG_FRAME(IOC, mfp) +#define DBG_DUMP_FW_REQUEST_FRAME(IOC, mfp) +#define DBG_DUMP_REQUEST_FRAME(IOC, mfp) +#define DBG_DUMP_REPLY_FRAME(IOC, mfp) +#define DBG_DUMP_REQUEST_FRAME_HDR(IOC, mfp) +#define DBG_DUMP_TM_REQUEST_FRAME(IOC, mfp) +#define DBG_DUMP_TM_REPLY_FRAME(IOC, mfp) + +#define dmfprintk(IOC, CMD) \ + MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) + +#endif /* defined(MPT_DEBUG_VERBOSE) && defined(CONFIG_FUSION_LOGGING) */ + +#endif /* ifndef MPTDEBUG_H_INCLUDED */ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index f2ebaa9..8422c25 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -188,16 +188,18 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, int (*func)(struct scsi_cmnd *SCpnt), const char *caller) { + MPT_SCSI_HOST *hd; struct scsi_device *sdev = SCpnt->device; struct Scsi_Host *shost = sdev->host; struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); unsigned long flags; int ready; + hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; spin_lock_irqsave(shost->host_lock, flags); while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) { spin_unlock_irqrestore(shost->host_lock, flags); - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_block_error_handler.%d: %d:%d, port status is " "DID_IMM_RETRY, deferring %s recovery.\n", ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, @@ -209,7 +211,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, spin_unlock_irqrestore(shost->host_lock, flags); if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) { - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, failing recovery, " "port state %d, vdev %p.\n", caller, ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, @@ -218,7 +220,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, SCpnt->device->hostdata)); return FAILED; } - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, executing recovery.\n", caller, ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, @@ -483,7 +485,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low; - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " "rport tid %d, tmo %d\n", ioc->name, @@ -559,6 +561,35 @@ mptfc_target_alloc(struct scsi_target *starget) return rc; } +/* + * mptfc_dump_lun_info + * @ioc + * @rport + * @sdev + * + */ +static void +mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev, + VirtTarget *vtarget) +{ + u64 nn, pn; + struct mptfc_rport_info *ri; + + ri = *((struct mptfc_rport_info **)rport->dd_data); + pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; + nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low; + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT + "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " + "CurrentTargetID %d, %x %llx %llx\n", + ioc->name, + sdev->host->host_no, + vtarget->num_luns, + sdev->id, ri->pg0.CurrentTargetID, + ri->pg0.PortIdentifier, + (unsigned long long)pn, + (unsigned long long)nn)); +} + /* * OS entry point to allow host driver to alloc memory @@ -606,25 +637,7 @@ mptfc_slave_alloc(struct scsi_device *sdev) vtarget->num_luns++; -#ifdef DMPT_DEBUG_FC - { - u64 nn, pn; - struct mptfc_rport_info *ri; - ri = *((struct mptfc_rport_info **)rport->dd_data); - pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; - nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low; - dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " - "CurrentTargetID %d, %x %llx %llx\n", - hd->ioc->name, - sdev->host->host_no, - vtarget->num_luns, - sdev->id, ri->pg0.CurrentTargetID, - ri->pg0.PortIdentifier, - (unsigned long long)pn, - (unsigned long long)nn)); - } -#endif + mptfc_dump_lun_info(hd->ioc, rport, sdev, vtarget); return 0; } @@ -653,27 +666,12 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* dd_data is null until finished adding target */ ri = *((struct mptfc_rport_info **)rport->dd_data); if (unlikely(!ri)) { - dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_qcmd.%d: %d:%d, dd_data is null.\n", - ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, - ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun)); SCpnt->result = DID_IMM_RETRY << 16; done(SCpnt); return 0; } - err = mptscsih_qcmd(SCpnt,done); -#ifdef DMPT_DEBUG_FC - if (unlikely(err)) { - dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n", - ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, - ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun,err)); - } -#endif - return err; + return mptscsih_qcmd(SCpnt,done); } /* @@ -1041,7 +1039,7 @@ mptfc_setup_reset(struct work_struct *work) pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_setup_reset.%d: %llx deleted\n", ioc->name, ioc->sh->host_no, @@ -1088,7 +1086,7 @@ mptfc_rescan_devices(struct work_struct *work) pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; - dfcprintk ((MYIOC_s_INFO_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_rescan.%d: %llx deleted\n", ioc->name, ioc->sh->host_no, @@ -1212,7 +1210,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (numSGE < sh->sg_tablesize) { /* Reset this value */ - dprintk((MYIOC_s_INFO_FMT + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; @@ -1232,7 +1230,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptfc_probe; } - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); /* Clear the TM flags @@ -1264,7 +1262,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->transportt = mptfc_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { - dprintk((KERN_ERR MYNAM + dprintk(ioc, printk(KERN_ERR MYNAM "scsi_add_host failed\n")); goto out_mptfc_probe; } @@ -1323,7 +1321,7 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) unsigned long flags; int rc=1; - devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); if (ioc->sh == NULL || @@ -1357,8 +1355,8 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) return rc; - dtmprintk((KERN_WARNING MYNAM - ": IOC %s_reset routed to FC host driver!\n", + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + ": IOC %s_reset routed to FC host driver!\n",ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); @@ -1413,15 +1411,8 @@ mptfc_init(void) mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); - if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { - devtverboseprintk((KERN_INFO MYNAM - ": Registered for IOC event notifications\n")); - } - - if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM - ": Registered for IOC reset notifications\n")); - } + mpt_event_register(mptfcDoneCtx, mptfc_event_process); + mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset); error = pci_register_driver(&mptfc_driver); if (error) @@ -1486,12 +1477,7 @@ mptfc_exit(void) fc_release_transport(mptfc_transport_template); mpt_reset_deregister(mptfcDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC reset notifications\n")); - mpt_event_deregister(mptfcDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC event notifications\n")); mpt_deregister(mptfcInternalCtx); mpt_deregister(mptfcTaskCtx); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 7e8a90c..01fc397 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1524,8 +1524,7 @@ static int __init mpt_lan_init (void) dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); - if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER)) - dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n")); + mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER); return 0; } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index d506646..29add83 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -201,103 +201,91 @@ struct mptsas_enclosure { u8 sep_channel; /* SEP channel logical channel id */ }; -#ifdef MPT_DEBUG_SAS -static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) -{ - printk("---- IO UNIT PAGE 0 ------------\n"); - printk("Handle=0x%X\n", - le16_to_cpu(phy_data->AttachedDeviceHandle)); - printk("Controller Handle=0x%X\n", - le16_to_cpu(phy_data->ControllerDevHandle)); - printk("Port=0x%X\n", phy_data->Port); - printk("Port Flags=0x%X\n", phy_data->PortFlags); - printk("PHY Flags=0x%X\n", phy_data->PhyFlags); - printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate); - printk("Controller PHY Device Info=0x%X\n", - le32_to_cpu(phy_data->ControllerPhyDeviceInfo)); - printk("DiscoveryStatus=0x%X\n", - le32_to_cpu(phy_data->DiscoveryStatus)); - printk("\n"); +static void mptsas_print_phy_data(MPT_ADAPTER *ioc, + MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) +{ + dsasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n")); + dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n", + le16_to_cpu(phy_data->AttachedDeviceHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n", + le16_to_cpu(phy_data->ControllerDevHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n", phy_data->Port)); + dsasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n", phy_data->PortFlags)); + dsasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n", phy_data->PhyFlags)); + dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate)); + dsasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n", + le32_to_cpu(phy_data->ControllerPhyDeviceInfo))); + dsasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n\n", + le32_to_cpu(phy_data->DiscoveryStatus))); } -static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0) +static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0) { __le64 sas_address; memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - printk("---- SAS PHY PAGE 0 ------------\n"); - printk("Attached Device Handle=0x%X\n", - le16_to_cpu(pg0->AttachedDevHandle)); - printk("SAS Address=0x%llX\n", - (unsigned long long)le64_to_cpu(sas_address)); - printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier); - printk("Attached Device Info=0x%X\n", - le32_to_cpu(pg0->AttachedDeviceInfo)); - printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate); - printk("Change Count=0x%X\n", pg0->ChangeCount); - printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo)); - printk("\n"); + dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n")); + dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n", + le16_to_cpu(pg0->AttachedDevHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", + (unsigned long long)le64_to_cpu(sas_address))); + dsasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier)); + dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n", + le32_to_cpu(pg0->AttachedDeviceInfo))); + dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate)); + dsasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n", pg0->ChangeCount)); + dsasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n\n", le32_to_cpu(pg0->PhyInfo))); } -static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1) +static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1) { - printk("---- SAS PHY PAGE 1 ------------\n"); - printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount); - printk("Running Disparity Error Count=0x%x\n", - pg1->RunningDisparityErrorCount); - printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount); - printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount); - printk("\n"); + dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n")); + dsasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount)); + dsasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n", + pg1->RunningDisparityErrorCount)); + dsasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount)); + dsasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n\n", pg1->PhyResetProblemCount)); } -static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) +static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0) { __le64 sas_address; memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - printk("---- SAS DEVICE PAGE 0 ---------\n"); - printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); - printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)); - printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); - printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); - printk("SAS Address=0x%llX\n", (unsigned long long) - le64_to_cpu(sas_address)); - printk("Target ID=0x%X\n", pg0->TargetID); - printk("Bus=0x%X\n", pg0->Bus); + dsasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 0 ---------\n")); + dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Slot=0x%X\n", le16_to_cpu(pg0->Slot))); + dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", (unsigned long long) + le64_to_cpu(sas_address))); + dsasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%X\n", pg0->TargetID)); + dsasprintk(ioc, printk(KERN_DEBUG "Bus=0x%X\n", pg0->Bus)); /* The PhyNum field specifies the PHY number of the parent * device this device is linked to */ - printk("Parent Phy Num=0x%X\n", pg0->PhyNum); - printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus)); - printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)); - printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags)); - printk("Physical Port=0x%X\n", pg0->PhysicalPort); - printk("\n"); + dsasprintk(ioc, printk(KERN_DEBUG "Parent Phy Num=0x%X\n", pg0->PhyNum)); + dsasprintk(ioc, printk(KERN_DEBUG "Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus))); + dsasprintk(ioc, printk(KERN_DEBUG "Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo))); + dsasprintk(ioc, printk(KERN_DEBUG "Flags=0x%X\n", le16_to_cpu(pg0->Flags))); + dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n\n", pg0->PhysicalPort)); } -static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) -{ - printk("---- SAS EXPANDER PAGE 1 ------------\n"); - - printk("Physical Port=0x%X\n", pg1->PhysicalPort); - printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier); - printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate); - printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate); - printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate); - printk("Owner Device Handle=0x%X\n", - le16_to_cpu(pg1->OwnerDevHandle)); - printk("Attached Device Handle=0x%X\n", - le16_to_cpu(pg1->AttachedDevHandle)); +static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1) +{ + dsasprintk(ioc, printk(KERN_DEBUG "---- SAS EXPANDER PAGE 1 ------------\n")); + dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n", pg1->PhysicalPort)); + dsasprintk(ioc, printk(KERN_DEBUG "PHY Identifier=0x%X\n", pg1->PhyIdentifier)); + dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate)); + dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate)); + dsasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n", pg1->HwLinkRate)); + dsasprintk(ioc, printk(KERN_DEBUG "Owner Device Handle=0x%X\n", + le16_to_cpu(pg1->OwnerDevHandle))); + dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n\n", + le16_to_cpu(pg1->AttachedDevHandle))); } -#else -#define mptsas_print_phy_data(phy_data) do { } while (0) -#define mptsas_print_phy_pg0(pg0) do { } while (0) -#define mptsas_print_phy_pg1(pg1) do { } while (0) -#define mptsas_print_device_pg0(pg0) do { } while (0) -#define mptsas_print_expander_pg1(pg1) do { } while (0) -#endif static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) { @@ -354,7 +342,7 @@ mptsas_is_end_device(struct mptsas_devinfo * attached) /* no mutex */ static void -mptsas_port_delete(struct mptsas_portinfo_details * port_details) +mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details) { struct mptsas_portinfo *port_info; struct mptsas_phyinfo *phy_info; @@ -366,7 +354,7 @@ mptsas_port_delete(struct mptsas_portinfo_details * port_details) port_info = port_details->port_info; phy_info = port_info->phy_info; - dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d " + dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: num_phys=%02d " "bitmask=0x%016llX\n", __FUNCTION__, port_details, port_details->num_phys, (unsigned long long) port_details->phy_bitmask)); @@ -390,20 +378,19 @@ mptsas_get_rphy(struct mptsas_phyinfo *phy_info) } static inline void -mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy) +mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy) { if (phy_info->port_details) { phy_info->port_details->rphy = rphy; - dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy)); + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy)); } -#ifdef MPT_DEBUG_SAS_WIDE if (rphy) { - dev_printk(KERN_DEBUG, &rphy->dev, "add:"); - printk("rphy=%p release=%p\n", - rphy, rphy->dev.release); + dsaswideprintk(ioc, dev_printk(KERN_DEBUG, + &rphy->dev, "add:")); + dsaswideprintk(ioc, printk(KERN_DEBUG "rphy=%p release=%p\n", + rphy, rphy->dev.release)); } -#endif } static inline struct sas_port * @@ -416,18 +403,17 @@ mptsas_get_port(struct mptsas_phyinfo *phy_info) } static inline void -mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port) +mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port) { if (phy_info->port_details) phy_info->port_details->port = port; -#ifdef MPT_DEBUG_SAS_WIDE if (port) { - dev_printk(KERN_DEBUG, &port->dev, "add: "); - printk("port=%p release=%p\n", - port, port->dev.release); + dsaswideprintk(ioc, dev_printk(KERN_DEBUG, + &port->dev, "add:")); + dsaswideprintk(ioc, printk(KERN_DEBUG "port=%p release=%p\n", + port, port->dev.release)); } -#endif } static inline struct scsi_target * @@ -477,7 +463,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) * Removing a phy from a port, letting the last * phy be removed by firmware events. */ - dsaswideprintk((KERN_DEBUG + dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: deleting phy = %d\n", __FUNCTION__, port_details, i)); port_details->num_phys--; @@ -493,7 +479,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) phy_info = port_info->phy_info; for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) { sas_address = phy_info->attached.sas_address; - dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n", + dsaswideprintk(ioc, printk(KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n", i, (unsigned long long)sas_address)); if (!sas_address) continue; @@ -512,7 +498,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_details->phy_bitmask |= (1 << phy_info->phy_id); phy_info->sas_port_add_phy=1; - dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t" + dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tForming port\n\t\t" "phy_id=%d sas_address=0x%018llX\n", i, (unsigned long long)sas_address)); phy_info->port_details = port_details; @@ -529,7 +515,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) continue; if (phy_info_cmp->port_details == port_details ) continue; - dsaswideprintk((KERN_DEBUG + dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tphy_id=%d sas_address=0x%018llX\n", j, (unsigned long long) phy_info_cmp->attached.sas_address)); @@ -559,21 +545,19 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) out: -#ifdef MPT_DEBUG_SAS_WIDE for (i = 0; i < port_info->num_phys; i++) { port_details = port_info->phy_info[i].port_details; if (!port_details) continue; - dsaswideprintk((KERN_DEBUG + dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: phy_id=%02d num_phys=%02d " "bitmask=0x%016llX\n", __FUNCTION__, port_details, i, port_details->num_phys, (unsigned long long)port_details->phy_bitmask)); - dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n", + dsaswideprintk(ioc, printk(KERN_DEBUG"\t\tport = %p rphy=%p\n", port_details->port, port_details->rphy)); } - dsaswideprintk((KERN_DEBUG"\n")); -#endif + dsaswideprintk(ioc, printk(KERN_DEBUG"\n")); mutex_unlock(&ioc->sas_topology_mutex); } @@ -622,7 +606,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) SCSITaskMgmt_t *pScsiTm; if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", ioc->name,__FUNCTION__, __LINE__)); return 0; } @@ -637,12 +621,12 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; - DBG_DUMP_TM_REQUEST_FRAME(mf); + DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); if (mpt_send_handshake_request(ioc->TaskCtx, ioc, sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) { mpt_free_msg_frame(ioc, mf); - dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", ioc->name,__FUNCTION__, __LINE__)); return 0; } @@ -681,7 +665,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, target_reset_list = kzalloc(sizeof(*target_reset_list), GFP_ATOMIC); if (!target_reset_list) { - dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", ioc->name,__FUNCTION__, __LINE__)); return; } @@ -748,7 +732,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc) ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", ioc->name,__FUNCTION__, __LINE__)); return; } @@ -1168,7 +1152,7 @@ static int mptsas_get_linkerrors(struct sas_phy *phy) if (error) goto out_free_consistent; - mptsas_print_phy_pg1(buffer); + mptsas_print_phy_pg1(ioc, buffer); phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount); phy->running_disparity_error_count = @@ -1397,7 +1381,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) le16_to_cpu(buffer->NvdataVersionDefault); for (i = 0; i < port_info->num_phys; i++) { - mptsas_print_phy_data(&buffer->PhyData[i]); + mptsas_print_phy_data(ioc, &buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; port_info->phy_info[i].port_id = buffer->PhyData[i].Port; @@ -1522,7 +1506,7 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, if (error) goto out_free_consistent; - mptsas_print_phy_pg0(buffer); + mptsas_print_phy_pg0(ioc, buffer); phy_info->hw_link_rate = buffer->HwLinkRate; phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; @@ -1589,7 +1573,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, if (error) goto out_free_consistent; - mptsas_print_device_pg0(buffer); + mptsas_print_device_pg0(ioc, buffer); device_info->handle = le16_to_cpu(buffer->DevHandle); device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); @@ -1737,7 +1721,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, goto out_free_consistent; - mptsas_print_expander_pg1(buffer); + mptsas_print_expander_pg1(ioc, buffer); /* save config data */ phy_info->phy_id = buffer->PhyIdentifier; @@ -1946,17 +1930,17 @@ static int mptsas_probe_one_phy(struct device *dev, } error = sas_port_add(port); if (error) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); goto out; } - mptsas_set_port(phy_info, port); - dsaswideprintk((KERN_DEBUG + mptsas_set_port(ioc, phy_info, port); + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_alloc: port=%p dev=%p port_id=%d\n", port, dev, port->port_identifier)); } - dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n", + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_add_phy: phy_id=%d\n", phy_info->phy_id)); sas_port_add_phy(port, phy_info->phy); phy_info->sas_port_add_phy = 0; @@ -2017,7 +2001,7 @@ static int mptsas_probe_one_phy(struct device *dev, break; } if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); goto out; @@ -2026,13 +2010,13 @@ static int mptsas_probe_one_phy(struct device *dev, rphy->identify = identify; error = sas_rphy_add(rphy); if (error) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); sas_rphy_free(rphy); goto out; } - mptsas_set_rphy(phy_info, rphy); + mptsas_set_rphy(ioc, phy_info, rphy); } out: @@ -2258,18 +2242,17 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) if (phy_info->attached.sas_address != expander_sas_address) continue; -#ifdef MPT_DEBUG_SAS_WIDE - dev_printk(KERN_DEBUG, &port->dev, - "delete port (%d)\n", port->port_identifier); -#endif + dsaswideprintk(ioc, + dev_printk(KERN_DEBUG, &port->dev, + "delete port (%d)\n", port->port_identifier)); sas_port_delete(port); - mptsas_port_delete(phy_info->port_details); + mptsas_port_delete(ioc, phy_info->port_details); } next_port: phy_info = port_info->phy_info; for (i = 0; i < port_info->num_phys; i++, phy_info++) - mptsas_port_delete(phy_info->port_details); + mptsas_port_delete(ioc, phy_info->port_details); list_del(&port_info->list); kfree(port_info->phy_info); @@ -2555,7 +2538,7 @@ mptsas_hotplug_work(struct work_struct *work) (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), (ev->channel << 8) + ev->id)) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2575,20 +2558,20 @@ mptsas_hotplug_work(struct work_struct *work) * Sanity checks, for non-existing phys and remote rphys. */ if (!phy_info){ - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; } if (!phy_info->port_details) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; } rphy = mptsas_get_rphy(phy_info); if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2596,7 +2579,7 @@ mptsas_hotplug_work(struct work_struct *work) port = mptsas_get_port(phy_info); if (!port) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2607,7 +2590,7 @@ mptsas_hotplug_work(struct work_struct *work) vtarget = starget->hostdata; if (!vtarget) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2645,12 +2628,10 @@ mptsas_hotplug_work(struct work_struct *work) printk(MYIOC_s_INFO_FMT "removing %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); -#ifdef MPT_DEBUG_SAS_WIDE dev_printk(KERN_DEBUG, &port->dev, "delete port (%d)\n", port->port_identifier); -#endif sas_port_delete(port); - mptsas_port_delete(phy_info->port_details); + mptsas_port_delete(ioc, phy_info->port_details); break; case MPTSAS_ADD_DEVICE: @@ -2664,7 +2645,7 @@ mptsas_hotplug_work(struct work_struct *work) (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), (ev->channel << 8) + ev->id)) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2676,7 +2657,7 @@ mptsas_hotplug_work(struct work_struct *work) sas_device.sas_address); if (!phy_info || !phy_info->port_details) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2688,7 +2669,7 @@ mptsas_hotplug_work(struct work_struct *work) vtarget = starget->hostdata; if (!vtarget) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2711,7 +2692,7 @@ mptsas_hotplug_work(struct work_struct *work) } if (mptsas_get_rphy(phy_info)) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); if (ev->channel) printk("%d\n", __LINE__); @@ -2720,7 +2701,7 @@ mptsas_hotplug_work(struct work_struct *work) port = mptsas_get_port(phy_info); if (!port) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; @@ -2745,7 +2726,7 @@ mptsas_hotplug_work(struct work_struct *work) mptsas_parse_device_info(&identify, &phy_info->attached); rphy = sas_end_device_alloc(port); if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; /* non-fatal: an rphy can be added later */ @@ -2753,13 +2734,13 @@ mptsas_hotplug_work(struct work_struct *work) rphy->identify = identify; if (sas_rphy_add(rphy)) { - dfailprintk((MYIOC_s_ERR_FMT + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); sas_rphy_free(rphy); break; } - mptsas_set_rphy(phy_info, rphy); + mptsas_set_rphy(ioc, phy_info, rphy); break; case MPTSAS_ADD_RAID: sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, @@ -3175,7 +3156,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (numSGE < sh->sg_tablesize) { /* Reset this value */ - dprintk((MYIOC_s_INFO_FMT + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; @@ -3193,7 +3174,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptsas_probe; } - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); /* Clear the TM flags @@ -3233,7 +3214,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) error = scsi_add_host(sh, &ioc->pcidev->dev); if (error) { - dprintk((KERN_ERR MYNAM + dprintk(ioc, printk(KERN_ERR MYNAM "scsi_add_host failed\n")); goto out_mptsas_probe; } @@ -3261,7 +3242,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { list_del(&p->list); for (i = 0 ; i < p->num_phys ; i++) - mptsas_port_delete(p->phy_info[i].port_details); + mptsas_port_delete(ioc, p->phy_info[i].port_details); kfree(p->phy_info); kfree(p); } @@ -3316,15 +3297,8 @@ mptsas_init(void) mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); - if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { - devtverboseprintk((KERN_INFO MYNAM - ": Registered for IOC event notifications\n")); - } - - if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM - ": Registered for IOC reset notifications\n")); - } + mpt_event_register(mptsasDoneCtx, mptsas_event_process); + mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset); error = pci_register_driver(&mptsas_driver); if (error) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index fd3aa26..5431529 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -191,7 +191,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) int rc; int chain_idx; - dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n", + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n", ioc->name)); spin_lock_irqsave(&ioc->FreeQlock, flags); if (!list_empty(&ioc->FreeChainQ)) { @@ -203,12 +203,12 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; chain_idx = offset / ioc->req_sz; rc = SUCCESS; - dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx)); } else { rc = FAILED; chain_idx = MPT_HOST_NO_CHAIN; - dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n", + dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n", ioc->name)); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -337,7 +337,7 @@ nextSGEset: */ pReq->ChainOffset = 0; RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; - dsgprintk((MYIOC_s_INFO_FMT + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); ioc->RequestNB[req_idx] = RequestNB; } @@ -353,7 +353,7 @@ nextSGEset: * Loop until done. */ - dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n", + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n", ioc->name, sg_done)); /* Set LAST_ELEMENT flag for last non-chain element @@ -386,7 +386,7 @@ nextSGEset: */ pReq->ChainOffset = (u8) (sgeOffset >> 2); RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; - dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); ioc->RequestNB[req_idx] = RequestNB; } @@ -397,7 +397,7 @@ nextSGEset: * in current buffer. Get a chain buffer. */ if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) { - dfailprintk((MYIOC_s_INFO_FMT + dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n", ioc->name, pReq->CDB[0], SCpnt)); return FAILED; @@ -419,7 +419,7 @@ nextSGEset: * out the Address and Flags fields. */ chainSge = (char *) psge; - dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)", + dsgprintk(ioc, printk(KERN_DEBUG " Current buff @ %p (index 0x%x)", psge, req_idx)); /* Start the SGE for the next buffer @@ -428,7 +428,7 @@ nextSGEset: sgeOffset = 0; sg_done = 0; - dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n", + dsgprintk(ioc, printk(KERN_DEBUG " Chain buff @ %p (index 0x%x)\n", psge, chain_idx)); /* Start the SGE for the next buffer @@ -456,7 +456,7 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, return; if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n", + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n", ioc->name,__FUNCTION__)); return; } @@ -467,93 +467,158 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, SEPMsg->TargetID = vtarget->id; SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; SEPMsg->SlotStatus = SlotStatus; - devtverboseprintk((MYIOC_s_WARN_FMT + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending SEP cmd=%x channel=%d id=%d\n", ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } -#ifdef MPT_DEBUG_REPLY +#ifdef CONFIG_FUSION_LOGGING /** - * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO + * mptscsih_info_scsiio - debug print info on reply frame * @ioc: Pointer to MPT_ADAPTER structure - * @ioc_status: U32 IOCStatus word from IOC - * @scsi_status: U8 sam status from target - * @scsi_state: U8 scsi state * @sc: original scsi cmnd pointer - * @mf: Pointer to MPT request frame + * @pScsiReply: Pointer to MPT reply frame + * + * MPT_DEBUG_REPLY needs to be enabled to obtain this info * * Refer to lsi/mpi.h. **/ static void -mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status, - u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc) +mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply) { - char extend_desc[EVENT_DESCR_STR_SZ]; - char *desc = NULL; + char *desc = NULL; + char *desc1 = NULL; + u16 ioc_status; + u8 skey, asc, ascq; + + ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; switch (ioc_status) { - case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ - desc = "SCSI Invalid Bus"; + case MPI_IOCSTATUS_SUCCESS: + desc = "success"; break; - - case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ - desc = "SCSI Invalid TargetID"; + case MPI_IOCSTATUS_SCSI_INVALID_BUS: + desc = "invalid bus"; break; - - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ - /* - * Inquiry is issued for device scanning - */ - if (sc->cmnd[0] != 0x12) - desc = "SCSI Device Not There"; + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: + desc = "invalid target_id"; break; - - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ - desc = "SCSI Data Overrun"; + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: + desc = "device not there"; break; - - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ - desc = "SCSI I/O Data Error"; + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: + desc = "data overrun"; break; - - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - desc = "SCSI Protocol Error"; + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: + desc = "data underrun"; break; - - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ - desc = "SCSI Task Terminated"; + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: + desc = "I/O data error"; break; - - case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - desc = "SCSI Residual Mismatch"; + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: + desc = "protocol error"; break; - - case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ - desc = "SCSI Task Management Failed"; + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: + desc = "task terminated"; break; - - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ - desc = "SCSI IOC Terminated"; + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: + desc = "residual mismatch"; + break; + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: + desc = "task management failed"; + break; + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: + desc = "IOC terminated"; + break; + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: + desc = "ext terminated"; break; + default: + desc = ""; + break; + } + + switch (pScsiReply->SCSIStatus) + { - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ - desc = "SCSI Ext Terminated"; + case MPI_SCSI_STATUS_SUCCESS: + desc1 = "success"; + break; + case MPI_SCSI_STATUS_CHECK_CONDITION: + desc1 = "check condition"; + break; + case MPI_SCSI_STATUS_CONDITION_MET: + desc1 = "condition met"; + break; + case MPI_SCSI_STATUS_BUSY: + desc1 = "busy"; + break; + case MPI_SCSI_STATUS_INTERMEDIATE: + desc1 = "intermediate"; + break; + case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET: + desc1 = "intermediate condmet"; + break; + case MPI_SCSI_STATUS_RESERVATION_CONFLICT: + desc1 = "reservation conflict"; + break; + case MPI_SCSI_STATUS_COMMAND_TERMINATED: + desc1 = "command terminated"; + break; + case MPI_SCSI_STATUS_TASK_SET_FULL: + desc1 = "task set full"; + break; + case MPI_SCSI_STATUS_ACA_ACTIVE: + desc1 = "aca active"; + break; + case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT: + desc1 = "fcpext device logged out"; + break; + case MPI_SCSI_STATUS_FCPEXT_NO_LINK: + desc1 = "fcpext no link"; + break; + case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED: + desc1 = "fcpext unassigned"; + break; + default: + desc1 = ""; break; } - if (!desc) - return; + scsi_print_command(sc); + printk(KERN_DEBUG "\tfw_channel = %d, fw_id = %d\n", + pScsiReply->Bus, pScsiReply->TargetID); + printk(KERN_DEBUG "\trequest_len = %d, underflow = %d, resid = %d\n", + scsi_bufflen(sc), sc->underflow, scsi_get_resid(sc)); + printk(KERN_DEBUG "\ttag = %d, transfer_count = %d, sc->result = %08X\n", + le16_to_cpu(pScsiReply->TaskTag), + le32_to_cpu(pScsiReply->TransferCount), sc->result); - snprintf(extend_desc, EVENT_DESCR_STR_SZ, - "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh", - sc->device->host->host_no, - sc->device->channel, sc->device->id, sc->device->lun, - sc->cmnd[0], scsi_status, scsi_state); + printk(KERN_DEBUG "\tiocstatus = %s (0x%04x), " + "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", + desc, ioc_status, + desc1, pScsiReply->SCSIStatus, + pScsiReply->SCSIState); - printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", - ioc->name, ioc_status, desc, extend_desc); + if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { + skey = sc->sense_buffer[2] & 0x0F; + asc = sc->sense_buffer[12]; + ascq = sc->sense_buffer[13]; + + printk(KERN_DEBUG "\t[sense_key,asc,ascq]: " + "[0x%02x,0x%02x,0x%02x]\n", + skey, asc, ascq); + } + + /* + * Look for + dump FCP ResponseInfo[]! + */ + if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID && + pScsiReply->ResponseInfo) + printk(KERN_DEBUG "response_info = %08xh\n", + le32_to_cpu(pScsiReply->ResponseInfo)); } #endif @@ -627,11 +692,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) pScsiReply = (SCSIIOReply_t *) mr; if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){ - dmfprintk((MYIOC_s_INFO_FMT + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n", ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag)); }else{ - dmfprintk((MYIOC_s_INFO_FMT + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", ioc->name, mf, mr, sc, req_idx)); } @@ -759,7 +824,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->result=DID_SOFT_ERROR << 16; else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; - dreplyprintk((KERN_NOTICE + dreplyprintk(ioc, printk(KERN_DEBUG "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", sc->result, sc->device->channel, sc->device->id)); break; @@ -792,9 +857,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } } - dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", + + dreplyprintk(ioc, printk(KERN_DEBUG " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow)); - dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); + dreplyprintk(ioc, printk(KERN_DEBUG " ActBytesXferd=%02xh\n", xfer_cnt)); + /* Report Queue Full */ if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) @@ -871,27 +938,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ -#ifdef MPT_DEBUG_REPLY - if (sc->result) { - - mptscsih_iocstatus_info_scsiio(ioc, status, - scsi_status, scsi_state, sc); - - dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x " - "result=0x%08x\n\tiocstatus=0x%04X " - "scsi_state=0x%02X scsi_status=0x%02X " - "loginfo=0x%08X\n", __FUNCTION__, - sc->device->host->host_no, sc->device->channel, sc->device->id, - sc->device->lun, sc->cmnd[0], sc->result, status, - scsi_state, scsi_status, log_info)); - - dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d " - "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, - sc->device->host->host_no, - sc->device->channel, sc->device->id, - sc->device->lun, scsi_get_resid(sc), - scsi_bufflen(sc), xfer_cnt)); - } +#ifdef CONFIG_FUSION_LOGGING + if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY)) + mptscsih_info_scsiio(ioc, sc, pScsiReply); #endif } /* end of address reply case */ @@ -925,7 +974,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) int ii; int max = ioc->req_depth; - dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); + dprintk(ioc, printk(KERN_DEBUG MYNAM ": flush_ScsiLookup called\n")); for (ii= 0; ii < max; ii++) { if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { @@ -937,7 +986,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) hd->ScsiLookup[ii] = NULL; mf = MPT_INDEX_2_MFPTR(ioc, ii); - dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", + dmfprintk(ioc, printk(KERN_DEBUG MYNAM ": flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt)); /* Free Chain buffers */ @@ -987,7 +1036,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) struct scsi_cmnd *sc; struct scsi_lun lun; - dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n", + dsprintk(hd->ioc, printk(KERN_DEBUG MYNAM ": search_running channel %d id %d lun %d max %d\n", vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); for (ii=0; ii < max; ii++) { @@ -1020,9 +1069,9 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) scsi_dma_unmap(sc); sc->host_scribble = NULL; sc->result = DID_NO_CONNECT << 16; - dsprintk(( "search_running: found (sc=%p, mf = %p) " - "channel %d id %d, lun %d \n", sc, mf, - vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun)); + sdev_printk(KERN_INFO, sc->device, "completing cmds: fw_channel %d," + "fw_id %d, sc=%p, mf = %p, idx=%x\n", vdevice->vtarget->channel, + vdevice->vtarget->id, sc, mf, ii); sc->scsi_done(sc); } } @@ -1057,7 +1106,7 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI return; if (time - hd->last_queue_full > 10 * HZ) { - dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", + dprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", hd->ioc->name, 0, sc->device->id, sc->device->lun)); hd->last_queue_full = time; } @@ -1098,7 +1147,7 @@ mptscsih_remove(struct pci_dev *pdev) hd->ScsiLookup = NULL; } - dprintk((MYIOC_s_INFO_FMT + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Free'd ScsiLookup (%d) memory\n", hd->ioc->name, sz1)); @@ -1317,17 +1366,19 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) u32 cmd_len; int my_idx; int ii; + MPT_ADAPTER *ioc; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + ioc = hd->ioc; lun = SCpnt->device->lun; SCpnt->scsi_done = done; - dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", + ioc->name, SCpnt, done)); if (hd->resetPending) { - dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); + dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", + ioc->name, SCpnt)); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1335,8 +1386,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) * Put together a MPT SCSI request... */ if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { - dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", - hd->ioc->name)); + dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", + ioc->name)); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1422,9 +1473,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) hd->ScsiLookup[my_idx] = SCpnt; mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); - dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", - hd->ioc->name, SCpnt, mf, my_idx)); - DBG_DUMP_REQUEST_FRAME(mf) + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", + ioc->name, SCpnt, mf, my_idx)); + DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf) return 0; fail: @@ -1475,7 +1526,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); - dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n", + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n", ioc->name, chain_idx)); /* handle next */ @@ -1519,7 +1570,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c unsigned long flags; ioc = hd->ioc; - dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name)); // SJR - CHECKME - Can we avoid this here? // (mpt_HardResetHandler has this check...) @@ -1539,20 +1590,20 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c */ if (mptscsih_tm_pending_wait(hd) == FAILED) { if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler abort: " "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); + ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler target " "reset: Timed out waiting for last TM (%d) " - "to complete! \n", hd->ioc->name, + "to complete! \n", ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); + ioc->name, hd->tmPending)); return FAILED; } } else { @@ -1591,12 +1642,13 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c ctx2abort, timeout); if (rc) printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", - hd->ioc->name); + ioc->name); else - dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", - hd->ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n", + ioc->name)); - dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "TMHandler rc = %d!\n", ioc->name, rc)); return rc; } @@ -1632,11 +1684,11 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i /* Return Fail to calling function if no message frames available. */ if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) { - dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", + dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", hd->ioc->name)); return FAILED; } - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", hd->ioc->name, mf)); /* Format the Request @@ -1660,27 +1712,27 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " "type=%d\n", hd->ioc->name, ctx2abort, type)); - DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); + DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!" + dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, hd->ioc, mf, retval)); goto fail_out; } if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!" + dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", hd->ioc->name)); retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); - dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n", + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", hd->ioc->name, retval)); goto fail_out; } @@ -1748,8 +1800,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: Can't locate " - "host! (sc=%p)\n", SCpnt)); + printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate " + "host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1760,7 +1812,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdevice = SCpnt->device->hostdata; if (!vdevice || !vdevice->vtarget) { - dtmprintk((MYIOC_s_DEBUG_FMT "task abort: device has been " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: device has been " "deleted (sc=%p)\n", ioc->name, SCpnt)); SCpnt->result = DID_NO_CONNECT << 16; SCpnt->scsi_done(SCpnt); @@ -1771,7 +1823,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Task aborts are not supported for hidden raid components. */ if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - dtmprintk((MYIOC_s_DEBUG_FMT "task abort: hidden raid " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid " "component (sc=%p)\n", ioc->name, SCpnt)); SCpnt->result = DID_RESET << 16; retval = FAILED; @@ -1785,7 +1837,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * Do OS callback. */ SCpnt->result = DID_RESET << 16; - dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", ioc->name, SCpnt)); retval = 0; @@ -1850,8 +1902,8 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: Can't " - "locate host! (sc=%p)\n", SCpnt)); + printk(KERN_DEBUG MYNAM ": mptscsih_dev_reset: Can't " + "locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1913,8 +1965,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: Can't " - "locate host! (sc=%p)\n", SCpnt )); + printk(KERN_DEBUG MYNAM ": mptscsih_bus_reset: Can't " + "locate host! (sc=%p)\n", SCpnt ); return FAILED; } @@ -1957,8 +2009,8 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /* If we can't locate the host to reset, then we failed. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: Can't " - "locate host! (sc=%p)\n", SCpnt)); + printk( KERN_DEBUG MYNAM ": mptscsih_host_reset: Can't " + "locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -2106,16 +2158,16 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m u8 tmType; u32 termination_count; - dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", ioc->name, mf, mr)); if (!ioc->sh) { - dtmprintk((MYIOC_s_WARN_FMT + dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); return 1; } if (mr == NULL) { - dtmprintk((MYIOC_s_WARN_FMT + dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); return 1; } @@ -2131,19 +2183,21 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m pScsiTmReply->ResponseCode) mptscsih_taskmgmt_response_code(ioc, pScsiTmReply->ResponseCode); - DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); - -#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM) - printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " - "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " - "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, - pScsiTmReply->TargetID, pScsiTmReq->TaskType, - le16_to_cpu(pScsiTmReply->IOCStatus), - le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, - le32_to_cpu(pScsiTmReply->TerminationCount)); + DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); + +#ifdef CONFIG_FUSION_LOGGING + if ((ioc->debug_level & MPT_DEBUG_REPLY) || + (ioc->debug_level & MPT_DEBUG_TM )) + printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " + "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " + "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, + pScsiTmReply->TargetID, pScsiTmReq->TaskType, + le16_to_cpu(pScsiTmReply->IOCStatus), + le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, + le32_to_cpu(pScsiTmReply->TerminationCount)); #endif if (!iocstatus) { - dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name)); hd->abortSCpnt = NULL; goto out; } @@ -2224,10 +2278,6 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, geom[1] = sectors; geom[2] = cylinders; - dprintk((KERN_NOTICE - ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n", - sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors)); - return 0; } @@ -2393,11 +2443,11 @@ mptscsih_slave_configure(struct scsi_device *sdev) vtarget = starget->hostdata; vdevice = sdev->hostdata; - dsprintk((MYIOC_s_INFO_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "device @ %p, channel=%d, id=%d, lun=%d\n", hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); if (hd->ioc->bus_type == SPI) - dsprintk((MYIOC_s_INFO_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", hd->ioc->name, sdev->sdtr, sdev->wdtr, sdev->ppr, sdev->inquiry_len)); @@ -2411,19 +2461,19 @@ mptscsih_slave_configure(struct scsi_device *sdev) vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); - dsprintk((MYIOC_s_INFO_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Queue depth=%d, tflags=%x\n", hd->ioc->name, sdev->queue_depth, vtarget->tflags)); if (hd->ioc->bus_type == SPI) - dsprintk((MYIOC_s_INFO_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); slave_configure_exit: - dsprintk((MYIOC_s_INFO_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d, ordered %d\n", hd->ioc->name,sdev->tagged_supported, sdev->simple_tags, sdev->ordered_tags)); @@ -2490,7 +2540,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR } } } else { - dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n", + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", hd->ioc->name)); } } @@ -2520,7 +2570,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) unsigned long flags; int ii; - dtmprintk((KERN_WARNING MYNAM + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": IOC %s_reset routed to SCSI host driver!\n", reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); @@ -2535,7 +2585,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; if (reset_phase == MPT_IOC_SETUP_RESET) { - dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); /* Clean Up: * 1. Set Hard Reset Pending Flag @@ -2544,7 +2594,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->resetPending = 1; } else if (reset_phase == MPT_IOC_PRE_RESET) { - dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name)); /* 2. Flush running commands * Clean ScsiLookup (and associated memory) @@ -2564,10 +2614,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) mpt_free_msg_frame(ioc, hd->cmdPtr); } - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name)); } else { - dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name)); /* Once a FW reload begins, all new OS commands are * redirected to the doneQ w/ a reset status. @@ -2607,7 +2657,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name)); } @@ -2621,7 +2671,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); if (ioc->sh == NULL || @@ -2663,7 +2713,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) case MPI_EVENT_STATE_CHANGE: /* 02 */ case MPI_EVENT_EVENT_CHANGE: /* 0A */ default: - dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event)); + dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event)); break; } @@ -2724,7 +2774,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } hd->cmdPtr = NULL; - ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", hd->ioc->name, mf, mr, req_idx)); hd->pLocal = &hd->localReply; @@ -2744,9 +2794,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_status = pReply->SCSIStatus; - ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n", - status, pReply->SCSIState, scsi_status, - le32_to_cpu(pReply->IOCLogInfo))); switch(status) { @@ -2799,7 +2846,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) SCSI_STD_SENSE_BYTES); memcpy(hd->pLocal->sense, sense_data, sz); - ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n", + ddvprintk(ioc, printk(KERN_DEBUG " Check Condition, sense ptr %p\n", sense_data)); } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { if (pReq->CDB[0] == INQUIRY) @@ -2830,8 +2877,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ - ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n", - completionCode)); } /* end of address reply case */ hd->pLocal->completion = completionCode; @@ -2862,7 +2907,7 @@ mptscsih_timer_expired(unsigned long data) { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; - ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); if (hd->cmdPtr) { MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; @@ -2874,7 +2919,6 @@ mptscsih_timer_expired(unsigned long data) * If new eh code, do nothing. Wait for OS cmd timeout * for bus reset. */ - ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name)); } else { /* Perform a FW reload */ if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { @@ -2891,7 +2935,7 @@ mptscsih_timer_expired(unsigned long data) * The FW will reply to all outstanding commands, callback will finish cleanup. * Hard reset clean-up will free all resources. */ - ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name)); return; } @@ -2932,7 +2976,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) in_isr = in_interrupt(); if (in_isr) { - dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n", + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", hd->ioc->name)); return -EPERM; } @@ -3035,7 +3079,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /* Get and Populate a free Frame */ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { - ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n", + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "No msg frames!\n", hd->ioc->name)); return -EBUSY; } @@ -3075,7 +3119,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) if (cmd == REQUEST_SENSE) { pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); - ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", hd->ioc->name, cmd)); } @@ -3086,7 +3130,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); - ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", hd->ioc->name, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) { @@ -3138,7 +3182,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) } else { rc = -EFAULT; /* This should never happen. */ - ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n", + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", hd->ioc->name)); } @@ -3324,6 +3368,35 @@ mptscsih_device_delay_show(struct class_device *cdev, char *buf) static CLASS_DEVICE_ATTR(device_delay, S_IRUGO, mptscsih_device_delay_show, NULL); +static ssize_t +mptscsih_debug_level_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level); +} +static ssize_t +mptscsih_debug_level_store(struct class_device *cdev, const char *buf, + size_t count) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + int val = 0; + + if (sscanf(buf, "%x", &val) != 1) + return -EINVAL; + + ioc->debug_level = val; + printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n", + ioc->name, ioc->debug_level); + return strlen(buf); +} +static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR, + mptscsih_debug_level_show, mptscsih_debug_level_store); + struct class_device_attribute *mptscsih_host_attrs[] = { &class_device_attr_version_fw, &class_device_attr_version_bios, @@ -3336,6 +3409,7 @@ struct class_device_attribute *mptscsih_host_attrs[] = { &class_device_attr_board_tracer, &class_device_attr_io_delay, &class_device_attr_device_delay, + &class_device_attr_debug_level, NULL, }; EXPORT_SYMBOL(mptscsih_host_attrs); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 947fe29..8c98420 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -138,7 +138,9 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, else { factor = MPT_ULTRA320; if (scsi_device_qas(sdev)) { - ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); + ddvprintk(hd->ioc, + printk(KERN_DEBUG "Enabling QAS due to " + "byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); noQas = 0; } if (sdev->type == TYPE_TAPE && @@ -225,7 +227,8 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /* Disable QAS in a mixed configuration case */ - ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + ddvprintk(hd->ioc, printk(KERN_DEBUG + "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); } } @@ -256,8 +259,8 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) /* Get a MF for this command. */ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", - ioc->name)); + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT + "writeIOCPage4 : no msg frames!\n",ioc->name)); return -EAGAIN; } @@ -297,7 +300,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - ddvprintk((MYIOC_s_INFO_FMT + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel)); @@ -422,7 +425,7 @@ static int mptspi_target_alloc(struct scsi_target *starget) if (starget->channel == 0 && mptspi_is_raid(hd, starget->id)) { vtarget->raidVolume = 1; - ddvprintk((KERN_INFO + ddvprintk(hd->ioc, printk(KERN_DEBUG "RAID Volume @ channel=%d id=%d\n", starget->channel, starget->id)); } @@ -462,7 +465,7 @@ mptspi_target_destroy(struct scsi_target *starget) static void mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) { - ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x" + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Requested = 0x%08x" " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", hd->ioc->name, starget->id, ii, ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", @@ -487,7 +490,7 @@ mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, static void mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) { - ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x" + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Read = 0x%08x" " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", hd->ioc->name, starget->id, ii, ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", @@ -613,7 +616,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) /* Get and Populate a free Frame */ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { - ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", + ddvprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", hd->ioc->name)); return -EAGAIN; } @@ -635,7 +638,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) mpt_add_sge((char *)&pReq->ActionDataSGE, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n", + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", hd->ioc->name, pReq->Action, channel, id)); hd->pLocal = NULL; @@ -735,7 +738,7 @@ static int mptspi_slave_configure(struct scsi_device *sdev) if (ret) return ret; - ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x" + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d min_period=0x%02x" " max_offset=0x%02x max_width=%d\n", hd->ioc->name, sdev->id, spi_min_period(scsi_target(sdev)), spi_max_offset(scsi_target(sdev)), @@ -768,10 +771,8 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return 0; } -#ifdef MPT_DEBUG_DV if (spi_dv_pending(scsi_target(SCpnt->device))) - scsi_print_command(SCpnt); -#endif + ddvprintk(hd->ioc, scsi_print_command(SCpnt)); return mptscsih_qcmd(SCpnt,done); } @@ -1415,7 +1416,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (numSGE < sh->sg_tablesize) { /* Reset this value */ - dprintk((MYIOC_s_INFO_FMT + dprintk(ioc, printk(MYIOC_s_INFO_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; @@ -1435,7 +1436,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptspi_probe; } - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); /* Clear the TM flags @@ -1463,7 +1464,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->spi_data.Saf_Te = mpt_saf_te; hd->negoNvram = MPT_SCSICFG_USE_NVRAM; - ddvprintk((MYIOC_s_INFO_FMT + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "saf_te %x\n", ioc->name, mpt_saf_te)); @@ -1481,7 +1482,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { - dprintk((KERN_ERR MYNAM + dprintk(ioc, printk(KERN_ERR MYNAM "scsi_add_host failed\n")); goto out_mptspi_probe; } @@ -1536,15 +1537,8 @@ mptspi_init(void) mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); - if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { - devtverboseprintk((KERN_INFO MYNAM - ": Registered for IOC event notifications\n")); - } - - if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) { - dprintk((KERN_INFO MYNAM - ": Registered for IOC reset notifications\n")); - } + mpt_event_register(mptspiDoneCtx, mptspi_event_process); + mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset); error = pci_register_driver(&mptspi_driver); if (error) @@ -1564,12 +1558,7 @@ mptspi_exit(void) pci_unregister_driver(&mptspi_driver); mpt_reset_deregister(mptspiDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC reset notifications\n")); - mpt_event_deregister(mptspiDoneCtx); - dprintk((KERN_INFO MYNAM - ": Deregistered for IOC event notifications\n")); mpt_deregister(mptspiInternalCtx); mpt_deregister(mptspiTaskCtx); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 988c8ce..50b2c73 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -159,7 +159,7 @@ static int i2o_block_device_flush(struct i2o_device *dev) * Returns 0 on success or negative error code on failure. */ -static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, +static int i2o_block_issue_flush(struct request_queue * queue, struct gendisk *disk, sector_t * error_sector) { struct i2o_block_device *i2o_blk_dev = queue->queuedata; @@ -445,7 +445,7 @@ static void i2o_block_end_request(struct request *req, int uptodate, { struct i2o_block_request *ireq = req->special; struct i2o_block_device *dev = ireq->i2o_blk_dev; - request_queue_t *q = req->q; + struct request_queue *q = req->q; unsigned long flags; if (end_that_request_chunk(req, uptodate, nr_bytes)) { @@ -744,7 +744,7 @@ static int i2o_block_transfer(struct request *req) { struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c; - int tid = dev->i2o_dev->lct_data.tid; + u32 tid = dev->i2o_dev->lct_data.tid; struct i2o_message *msg; u32 *mptr; struct i2o_block_request *ireq = req->special; diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index f753060..d0fc4fd 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -53,7 +53,6 @@ #define ASUS_HOTK_NAME "Asus Laptop Support" #define ASUS_HOTK_CLASS "hotkey" #define ASUS_HOTK_DEVICE_NAME "Hotkey" -#define ASUS_HOTK_HID "ATK0100" #define ASUS_HOTK_FILE "asus-laptop" #define ASUS_HOTK_PREFIX "\\_SB.ATKD." @@ -197,12 +196,18 @@ static struct asus_hotk *hotk; /* * The hotkey driver declaration */ +static const struct acpi_device_id asus_device_ids[] = { + {"ATK0100", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, asus_device_ids); + static int asus_hotk_add(struct acpi_device *device); static int asus_hotk_remove(struct acpi_device *device, int type); static struct acpi_driver asus_hotk_driver = { .name = ASUS_HOTK_NAME, .class = ASUS_HOTK_CLASS, - .ids = ASUS_HOTK_HID, + .ids = asus_device_ids, .ops = { .add = asus_hotk_add, .remove = asus_hotk_remove, @@ -1067,19 +1072,16 @@ static void asus_backlight_exit(void) } #define ASUS_LED_UNREGISTER(object) \ - if(object##_led.class_dev \ - && !IS_ERR(object##_led.class_dev)) \ - led_classdev_unregister(&object##_led) + led_classdev_unregister(&object##_led) static void asus_led_exit(void) { + destroy_workqueue(led_workqueue); ASUS_LED_UNREGISTER(mled); ASUS_LED_UNREGISTER(tled); ASUS_LED_UNREGISTER(pled); ASUS_LED_UNREGISTER(rled); ASUS_LED_UNREGISTER(gled); - - destroy_workqueue(led_workqueue); } static void __exit asus_laptop_exit(void) @@ -1135,29 +1137,42 @@ static int asus_led_init(struct device *dev) rv = ASUS_LED_REGISTER(mled, dev); if (rv) - return rv; + goto out; rv = ASUS_LED_REGISTER(tled, dev); if (rv) - return rv; + goto out1; rv = ASUS_LED_REGISTER(rled, dev); if (rv) - return rv; + goto out2; rv = ASUS_LED_REGISTER(pled, dev); if (rv) - return rv; + goto out3; rv = ASUS_LED_REGISTER(gled, dev); if (rv) - return rv; + goto out4; led_workqueue = create_singlethread_workqueue("led_workqueue"); if (!led_workqueue) - return -ENOMEM; + goto out5; return 0; +out5: + rv = -ENOMEM; + ASUS_LED_UNREGISTER(gled); +out4: + ASUS_LED_UNREGISTER(pled); +out3: + ASUS_LED_UNREGISTER(rled); +out2: + ASUS_LED_UNREGISTER(tled); +out1: + ASUS_LED_UNREGISTER(mled); +out: + return rv; } static int __init asus_laptop_init(void) diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 303e48c..14ee06c 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -1124,10 +1124,22 @@ static int sony_nc_remove(struct acpi_device *device, int type) return 0; } +static const struct acpi_device_id sony_device_ids[] = { + {SONY_NC_HID, 0}, + {SONY_PIC_HID, 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, sony_device_ids); + +static const struct acpi_device_id sony_nc_device_ids[] = { + {SONY_NC_HID, 0}, + {"", 0}, +}; + static struct acpi_driver sony_nc_driver = { .name = SONY_NC_DRIVER_NAME, .class = SONY_NC_CLASS, - .ids = SONY_NC_HID, + .ids = sony_nc_device_ids, .owner = THIS_MODULE, .ops = { .add = sony_nc_add, @@ -2470,10 +2482,15 @@ static int sony_pic_resume(struct acpi_device *device) return 0; } +static const struct acpi_device_id sony_pic_device_ids[] = { + {SONY_PIC_HID, 0}, + {"", 0}, +}; + static struct acpi_driver sony_pic_driver = { .name = SONY_PIC_DRIVER_NAME, .class = SONY_PIC_CLASS, - .ids = SONY_PIC_HID, + .ids = sony_pic_device_ids, .owner = THIS_MODULE, .ops = { .add = sony_pic_add, diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index f15a58f..fa80f35 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -411,12 +411,13 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name); ibm->acpi->driver->ids = ibm->acpi->hid; + ibm->acpi->driver->ops.add = &tpacpi_device_add; rc = acpi_bus_register_driver(ibm->acpi->driver); if (rc < 0) { printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n", - ibm->acpi->hid, rc); + ibm->name, rc); kfree(ibm->acpi->driver); ibm->acpi->driver = NULL; } else if (!rc) @@ -1316,8 +1317,13 @@ errexit: return res; } +static const struct acpi_device_id ibm_htk_device_ids[] = { + {IBM_HKEY_HID, 0}, + {"", 0}, +}; + static struct tp_acpi_drv_struct ibm_hotkey_acpidriver = { - .hid = IBM_HKEY_HID, + .hid = ibm_htk_device_ids, .notify = hotkey_notify, .handle = &hkey_handle, .type = ACPI_DEVICE_NOTIFY, @@ -2080,6 +2086,11 @@ IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ /* don't list other alternatives as we install a notify handler on the 570 */ IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ +static const struct acpi_device_id ibm_pci_device_ids[] = { + {PCI_ROOT_HID_STRING, 0}, + {"", 0}, +}; + static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { { .notify = dock_notify, @@ -2090,7 +2101,7 @@ static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. * We just use it to get notifications of dock hotplug * in very old thinkpads */ - .hid = PCI_ROOT_HID_STRING, + .hid = ibm_pci_device_ids, .notify = dock_notify, .handle = &pci_handle, .type = ACPI_SYSTEM_NOTIFY, @@ -2149,7 +2160,8 @@ static int __init dock_init2(struct ibm_init_struct *iibm) static void dock_notify(struct ibm_struct *ibm, u32 event) { int docked = dock_docked(); - int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, PCI_ROOT_HID_STRING); + int pci = ibm->acpi->hid && ibm->acpi->device && + acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); if (event == 1 && !pci) /* 570 */ acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index b7a4a88..88af089 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h @@ -193,7 +193,7 @@ static void thinkpad_acpi_module_exit(void); struct ibm_struct; struct tp_acpi_drv_struct { - char *hid; + const struct acpi_device_id *hid; struct acpi_driver *driver; void (*notify) (struct ibm_struct *, u32); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index b53dac8..c9a289c 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/queue.c + * linux/drivers/mmc/card/queue.c * * Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright 2006-2007 Pierre Ossman @@ -83,7 +83,7 @@ static int mmc_queue_thread(void *d) * on any queue on this host, and attempt to issue it. This may * not be the queue we were asked to process. */ -static void mmc_request(request_queue_t *q) +static void mmc_request(struct request_queue *q) { struct mmc_queue *mq = q->queuedata; struct request *req; @@ -211,7 +211,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock void mmc_cleanup_queue(struct mmc_queue *mq) { - request_queue_t *q = mq->queue; + struct request_queue *q = mq->queue; unsigned long flags; /* Mark that we should start throwing out stragglers */ @@ -252,7 +252,7 @@ EXPORT_SYMBOL(mmc_cleanup_queue); */ void mmc_queue_suspend(struct mmc_queue *mq) { - request_queue_t *q = mq->queue; + struct request_queue *q = mq->queue; unsigned long flags; if (!(mq->flags & MMC_QUEUE_SUSPENDED)) { @@ -272,7 +272,7 @@ void mmc_queue_suspend(struct mmc_queue *mq) */ void mmc_queue_resume(struct mmc_queue *mq) { - request_queue_t *q = mq->queue; + struct request_queue *q = mq->queue; unsigned long flags; if (mq->flags & MMC_QUEUE_SUSPENDED) { diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 348b566..fe0e785 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -209,10 +209,30 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host) int mmc_add_card(struct mmc_card *card) { int ret; + const char *type; snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), "%s:%04x", mmc_hostname(card->host), card->rca); + switch (card->type) { + case MMC_TYPE_MMC: + type = "MMC"; + break; + case MMC_TYPE_SD: + type = "SD"; + if (mmc_card_blockaddr(card)) + type = "SDHC"; + break; + default: + type = "?"; + break; + } + + printk(KERN_INFO "%s: new %s%s card at address %04x\n", + mmc_hostname(card->host), + mmc_card_highspeed(card) ? "high speed " : "", + type, card->rca); + card->dev.uevent_suppress = 1; ret = device_add(&card->dev); @@ -243,6 +263,9 @@ int mmc_add_card(struct mmc_card *card) void mmc_remove_card(struct mmc_card *card) { if (mmc_card_present(card)) { + printk(KERN_INFO "%s: card %04x removed\n", + mmc_hostname(card->host), card->rca); + if (card->host->bus_ops->sysfs_remove) card->host->bus_ops->sysfs_remove(card->host, card); device_del(&card->dev); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b5d8a6d..bfd2ae5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -68,32 +68,41 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) struct mmc_command *cmd = mrq->cmd; int err = cmd->error; - pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n", - mmc_hostname(host), cmd->opcode, err, - mrq->data ? mrq->data->error : 0, - mrq->stop ? mrq->stop->error : 0, - cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); - if (err && cmd->retries) { + pr_debug("%s: req failed (CMD%u): %d, retrying...\n", + mmc_hostname(host), cmd->opcode, err); + cmd->retries--; cmd->error = 0; host->ops->request(host, mrq); - } else if (mrq->done) { - mrq->done(mrq); + } else { + pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", + mmc_hostname(host), cmd->opcode, err, + cmd->resp[0], cmd->resp[1], + cmd->resp[2], cmd->resp[3]); + + if (mrq->data) { + pr_debug("%s: %d bytes transferred: %d\n", + mmc_hostname(host), + mrq->data->bytes_xfered, mrq->data->error); + } + + if (mrq->stop) { + pr_debug("%s: (CMD%u): %d: %08x %08x %08x %08x\n", + mmc_hostname(host), mrq->stop->opcode, + mrq->stop->error, + mrq->stop->resp[0], mrq->stop->resp[1], + mrq->stop->resp[2], mrq->stop->resp[3]); + } + + if (mrq->done) + mrq->done(mrq); } } EXPORT_SYMBOL(mmc_request_done); -/** - * mmc_start_request - start a command on a host - * @host: MMC host to start command on - * @mrq: MMC request to start - * - * Queue a command on the specified host. We expect the - * caller to be holding the host lock with interrupts disabled. - */ -void +static void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { #ifdef CONFIG_MMC_DEBUG @@ -104,6 +113,21 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mmc_hostname(host), mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); + if (mrq->data) { + pr_debug("%s: blksz %d blocks %d flags %08x " + "tsac %d ms nsac %d\n", + mmc_hostname(host), mrq->data->blksz, + mrq->data->blocks, mrq->data->flags, + mrq->data->timeout_ns / 10000000, + mrq->data->timeout_clks); + } + + if (mrq->stop) { + pr_debug("%s: CMD%u arg %08x flags %08x\n", + mmc_hostname(host), mrq->stop->opcode, + mrq->stop->arg, mrq->stop->flags); + } + WARN_ON(!host->claimed); mrq->cmd->error = 0; @@ -133,14 +157,21 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) host->ops->request(host, mrq); } -EXPORT_SYMBOL(mmc_start_request); - static void mmc_wait_done(struct mmc_request *mrq) { complete(mrq->done_data); } -int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) +/** + * mmc_wait_for_req - start a request and wait for completion + * @host: MMC host to start command + * @mrq: MMC request to start + * + * Start a new MMC custom command request for a host, and wait + * for the command to complete. Does not attempt to parse the + * response. + */ +void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { DECLARE_COMPLETION_ONSTACK(complete); @@ -150,8 +181,6 @@ int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) mmc_start_request(host, mrq); wait_for_completion(&complete); - - return 0; } EXPORT_SYMBOL(mmc_wait_for_req); @@ -192,6 +221,9 @@ EXPORT_SYMBOL(mmc_wait_for_cmd); * @data: data phase for command * @card: the MMC card associated with the data transfer * @write: flag to differentiate reads from writes + * + * Computes the data timeout parameters according to the + * correct algorithm given the card type. */ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, int write) @@ -240,21 +272,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, EXPORT_SYMBOL(mmc_set_data_timeout); /** - * __mmc_claim_host - exclusively claim a host + * mmc_claim_host - exclusively claim a host * @host: mmc host to claim - * @card: mmc card to claim host for - * - * Claim a host for a set of operations. If a valid card - * is passed and this wasn't the last card selected, select - * the card before returning. * - * Note: you should use mmc_card_claim_host or mmc_claim_host. + * Claim a host for a set of operations. */ void mmc_claim_host(struct mmc_host *host) { DECLARE_WAITQUEUE(wait, current); unsigned long flags; + might_sleep(); + add_wait_queue(&host->wq, &wait); spin_lock_irqsave(&host->lock, flags); while (1) { @@ -433,6 +462,45 @@ static void mmc_power_off(struct mmc_host *host) } /* + * Cleanup when the last reference to the bus operator is dropped. + */ +void __mmc_release_bus(struct mmc_host *host) +{ + BUG_ON(!host); + BUG_ON(host->bus_refs); + BUG_ON(!host->bus_dead); + + host->bus_ops = NULL; +} + +/* + * Increase reference count of bus operator + */ +static inline void mmc_bus_get(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs++; + spin_unlock_irqrestore(&host->lock, flags); +} + +/* + * Decrease reference count of bus operator and free it if + * it is the last reference. + */ +static inline void mmc_bus_put(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->bus_refs--; + if ((host->bus_refs == 0) && host->bus_ops) + __mmc_release_bus(host); + spin_unlock_irqrestore(&host->lock, flags); +} + +/* * Assign a mmc bus handler to a host. Only one bus handler may control a * host at any given time. */ @@ -481,25 +549,15 @@ void mmc_detach_bus(struct mmc_host *host) mmc_bus_put(host); } -/* - * Cleanup when the last reference to the bus operator is dropped. - */ -void __mmc_release_bus(struct mmc_host *host) -{ - BUG_ON(!host); - BUG_ON(host->bus_refs); - BUG_ON(!host->bus_dead); - - host->bus_ops = NULL; -} - /** * mmc_detect_change - process change of state on a MMC socket * @host: host which changed state. * @delay: optional delay to wait before detection (jiffies) * - * All we know is that card(s) have been inserted or removed - * from the socket(s). We don't know which socket or cards. + * MMC drivers should call this when they detect a card has been + * inserted or removed. The MMC layer will confirm that any + * present card is still functional, and initialize any newly + * inserted. */ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index ae006b3..bb2774a 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -27,28 +27,6 @@ struct mmc_bus_ops { void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); void mmc_detach_bus(struct mmc_host *host); -void __mmc_release_bus(struct mmc_host *host); - -static inline void mmc_bus_get(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->bus_refs++; - spin_unlock_irqrestore(&host->lock, flags); -} - -static inline void mmc_bus_put(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->bus_refs--; - if ((host->bus_refs == 0) && host->bus_ops) - __mmc_release_bus(host); - spin_unlock_irqrestore(&host->lock, flags); -} - void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 1433d95..6a7e298 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -93,6 +93,10 @@ EXPORT_SYMBOL(mmc_alloc_host); /** * mmc_add_host - initialise host hardware * @host: mmc host + * + * Register the host with the driver model. The host must be + * prepared to start servicing requests before this function + * completes. */ int mmc_add_host(struct mmc_host *host) { @@ -126,7 +130,8 @@ EXPORT_SYMBOL(mmc_add_host); * @host: mmc host * * Unregister and remove all cards associated with this host, - * and power down the MMC bus. + * and power down the MMC bus. No new requests will be issued + * after this function has returned. */ void mmc_remove_host(struct mmc_host *host) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 66f85bf..21d7f48 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/mmc.c + * linux/drivers/mmc/core/mmc.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. @@ -100,7 +100,7 @@ static int mmc_decode_cid(struct mmc_card *card) break; default: - printk("%s: card has unknown MMCA version %d\n", + printk(KERN_ERR "%s: card has unknown MMCA version %d\n", mmc_hostname(card->host), card->csd.mmca_vsn); return -EINVAL; } @@ -123,7 +123,7 @@ static int mmc_decode_csd(struct mmc_card *card) */ csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 1 && csd_struct != 2) { - printk("%s: unrecognised CSD structure version %d\n", + printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); return -EINVAL; } @@ -499,14 +499,17 @@ static void mmc_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); - err = mmc_init_card(host, host->ocr, host->card); + mmc_release_host(host); + if (err != MMC_ERR_NONE) { mmc_remove(host); + + mmc_claim_host(host); mmc_detach_bus(host); + mmc_release_host(host); } - mmc_release_host(host); } #else @@ -553,8 +556,10 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) /* * Can we support the voltage of the card? */ - if (!host->ocr) + if (!host->ocr) { + err = -EINVAL; goto err; + } /* * Detect and init the card. @@ -567,18 +572,21 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) err = mmc_add_card(host->card); if (err) - goto reclaim_host; + goto remove_card; return 0; -reclaim_host: - mmc_claim_host(host); +remove_card: mmc_remove_card(host->card); host->card = NULL; + mmc_claim_host(host); err: mmc_detach_bus(host); mmc_release_host(host); + printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", + mmc_hostname(host), err); + return 0; } diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 7dd720f..913e75f 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/mmc_ops.h + * linux/drivers/mmc/core/mmc_ops.h * * Copyright 2006-2007 Pierre Ossman * diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 7a481e8..76d09a9 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/mmc_ops.h + * linux/drivers/mmc/core/mmc_ops.h * * Copyright 2006-2007 Pierre Ossman * diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 1240684..1edc62b 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/sd.c + * linux/drivers/mmc/core/sd.c * * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. @@ -149,7 +149,7 @@ static int mmc_decode_csd(struct mmc_card *card) csd->write_partial = 0; break; default: - printk("%s: unrecognised CSD structure version %d\n", + printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); return -EINVAL; } @@ -173,7 +173,7 @@ static int mmc_decode_scr(struct mmc_card *card) scr_struct = UNSTUFF_BITS(resp, 60, 4); if (scr_struct != 0) { - printk("%s: unrecognised SCR structure version %d\n", + printk(KERN_ERR "%s: unrecognised SCR structure version %d\n", mmc_hostname(card->host), scr_struct); return -EINVAL; } @@ -206,9 +206,8 @@ static int mmc_read_switch(struct mmc_card *card) status = kmalloc(64, GFP_KERNEL); if (!status) { - printk("%s: could not allocate a buffer for switch " - "capabilities.\n", - mmc_hostname(card->host)); + printk(KERN_ERR "%s: could not allocate a buffer for " + "switch capabilities.\n", mmc_hostname(card->host)); return err; } @@ -254,9 +253,8 @@ static int mmc_switch_hs(struct mmc_card *card) status = kmalloc(64, GFP_KERNEL); if (!status) { - printk("%s: could not allocate a buffer for switch " - "capabilities.\n", - mmc_hostname(card->host)); + printk(KERN_ERR "%s: could not allocate a buffer for " + "switch capabilities.\n", mmc_hostname(card->host)); return err; } @@ -573,14 +571,17 @@ static void mmc_sd_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); - err = mmc_sd_init_card(host, host->ocr, host->card); + mmc_release_host(host); + if (err != MMC_ERR_NONE) { mmc_sd_remove(host); + + mmc_claim_host(host); mmc_detach_bus(host); + mmc_release_host(host); } - mmc_release_host(host); } #else @@ -634,8 +635,10 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) /* * Can we support the voltage(s) of the card(s)? */ - if (!host->ocr) + if (!host->ocr) { + err = -EINVAL; goto err; + } /* * Detect and init the card. @@ -648,18 +651,21 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) err = mmc_add_card(host->card); if (err) - goto reclaim_host; + goto remove_card; return 0; -reclaim_host: - mmc_claim_host(host); +remove_card: mmc_remove_card(host->card); host->card = NULL; + mmc_claim_host(host); err: mmc_detach_bus(host); mmc_release_host(host); + printk(KERN_ERR "%s: error %d whilst initialising SD card\n", + mmc_hostname(host), err); + return 0; } diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 9697ce5..342f340 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/sd_ops.h + * linux/drivers/mmc/core/sd_ops.h * * Copyright 2006-2007 Pierre Ossman * @@ -21,11 +21,40 @@ #include "core.h" #include "sd_ops.h" +static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) +{ + int err; + struct mmc_command cmd; + + BUG_ON(!host); + BUG_ON(card && (card->host != host)); + + cmd.opcode = MMC_APP_CMD; + + if (card) { + cmd.arg = card->rca << 16; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + } else { + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR; + } + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err != MMC_ERR_NONE) + return err; + + /* Check that card supported application commands */ + if (!(cmd.resp[0] & R1_APP_CMD)) + return MMC_ERR_FAILED; + + return MMC_ERR_NONE; +} + /** * mmc_wait_for_app_cmd - start an application command and wait for completion * @host: MMC host to start command - * @rca: RCA to send MMC_APP_CMD to + * @card: Card to send MMC_APP_CMD to * @cmd: MMC command to start * @retries: maximum number of retries * @@ -77,35 +106,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, EXPORT_SYMBOL(mmc_wait_for_app_cmd); -int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) -{ - int err; - struct mmc_command cmd; - - BUG_ON(!host); - BUG_ON(card && (card->host != host)); - - cmd.opcode = MMC_APP_CMD; - - if (card) { - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.arg = 0; - cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR; - } - - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err != MMC_ERR_NONE) - return err; - - /* Check that card supported application commands */ - if (!(cmd.resp[0] & R1_APP_CMD)) - return MMC_ERR_FAILED; - - return MMC_ERR_NONE; -} - int mmc_app_set_bus_width(struct mmc_card *card, int width) { int err; diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 1240fdd..9742d8a 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/sd_ops.h + * linux/drivers/mmc/core/sd_ops.h * * Copyright 2006-2007 Pierre Ossman * @@ -12,7 +12,6 @@ #ifndef _MMC_SD_OPS_H #define _MMC_SD_OPS_H -int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); int mmc_app_set_bus_width(struct mmc_card *card, int width); int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_send_if_cond(struct mmc_host *host, u32 ocr); diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 15aab37..62564cc 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/at91_mci.c - ATMEL AT91 MCI Driver + * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver * * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved * diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 52b63f1..34c99d4 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/au1xmmc.c - AU1XX0 MMC driver + * linux/drivers/mmc/host/au1xmmc.c - AU1XX0 MMC driver * * Copyright (c) 2005, Advanced Micro Devices, Inc. * diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 7ee2045..54bfc9f 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver + * linux/drivers/mmc/host/imxmmc.c - Motorola i.MX MMCI driver * * Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de> * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index d11c2d2..be730c0 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver + * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 6d7eadc..000e6a9 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver + * linux/drivers/mmc/host/mmci.h - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index b0824a3..0cf97ed 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1,5 +1,5 @@ /* - * linux/drivers/media/mmc/omap.c + * linux/drivers/mmc/host/omap.c * * Copyright (C) 2004 Nokia Corporation * Written by Tuukka Tikkanen and Juha Yrjölä<juha.yrjola@nokia.com> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index f8985c5..ff96033 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/pxa.c - PXA MMCI driver + * linux/drivers/mmc/host/pxa.c - PXA MMCI driver * * Copyright (C) 2003 Russell King, All Rights Reserved. * diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 4a24db0..f2bc87a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver + * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver * * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * @@ -34,6 +34,7 @@ static unsigned int debug_quirks = 0; /* Controller doesn't like some resets when there is no card inserted. */ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) +#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -78,6 +79,24 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, }, + { + .vendor = PCI_VENDOR_ID_ENE, + .device = PCI_DEVICE_ID_ENE_CB714_SD, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | + SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, + }, + + { + .vendor = PCI_VENDOR_ID_ENE, + .device = PCI_DEVICE_ID_ENE_CB714_SD_2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | + SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, + }, + { /* Generic SD host controller */ PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) }, @@ -361,11 +380,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) if (data == NULL) return; - DBG("blksz %04x blks %04x flags %08x\n", - data->blksz, data->blocks, data->flags); - DBG("tsac %d ms nsac %d clk\n", - data->timeout_ns / 1000000, data->timeout_clks); - /* Sanity checks */ BUG_ON(data->blksz * data->blocks > 524288); BUG_ON(data->blksz > host->mmc->max_blk_size); @@ -476,8 +490,6 @@ static void sdhci_finish_data(struct sdhci_host *host) data->error = MMC_ERR_FAILED; } - DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered); - if (data->stop) { /* * The controller needs a reset of internal state machines @@ -501,8 +513,6 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) WARN_ON(host->cmd); - DBG("Sending cmd (%x)\n", cmd->opcode); - /* Wait max 10 ms */ timeout = 10; @@ -590,8 +600,6 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd->error = MMC_ERR_NONE; - DBG("Ending cmd (%x)\n", host->cmd->opcode); - if (host->cmd->data) host->data = host->cmd->data; else @@ -759,6 +767,14 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); + /* + * Some (ENE) controllers go apeshit on some ios operation, + * signalling timeout and CRC errors even on CMD0. Resetting + * it on each ios seems to solve the problem. + */ + if(host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + mmiowb(); spin_unlock_irqrestore(&host->lock, flags); } @@ -835,8 +851,6 @@ static void sdhci_tasklet_finish(unsigned long param) mrq = host->mrq; - DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode); - /* * The controller needs a reset of internal state machines * upon error conditions. @@ -922,20 +936,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) return; } - if (intmask & SDHCI_INT_RESPONSE) - sdhci_finish_command(host); - else { - if (intmask & SDHCI_INT_TIMEOUT) - host->cmd->error = MMC_ERR_TIMEOUT; - else if (intmask & SDHCI_INT_CRC) - host->cmd->error = MMC_ERR_BADCRC; - else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) - host->cmd->error = MMC_ERR_FAILED; - else - host->cmd->error = MMC_ERR_INVALID; + if (intmask & SDHCI_INT_TIMEOUT) + host->cmd->error = MMC_ERR_TIMEOUT; + else if (intmask & SDHCI_INT_CRC) + host->cmd->error = MMC_ERR_BADCRC; + else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) + host->cmd->error = MMC_ERR_FAILED; + if (host->cmd->error != MMC_ERR_NONE) tasklet_schedule(&host->finish_tasklet); - } + else if (intmask & SDHCI_INT_RESPONSE) + sdhci_finish_command(host); } static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index a6c8704..d157776 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver + * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver * * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. * diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 867ca6a..e0c9808 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver + * linux/drivers/mmc/host/wbsd.c - Winbond W83L51xD SD/MMC driver * * Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved. * @@ -207,8 +207,6 @@ static void wbsd_request_end(struct wbsd_host *host, struct mmc_request *mrq) { unsigned long dmaflags; - DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode); - if (host->dma >= 0) { /* * Release ISA DMA controller. @@ -360,8 +358,6 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) int i; u8 status, isr; - DBGF("Sending cmd (%x)\n", cmd->opcode); - /* * Clear accumulated ISR. The interrupt routine * will fill this one with events that occur during @@ -411,8 +407,6 @@ static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd) wbsd_get_short_reply(host, cmd); } } - - DBGF("Sent cmd (%x), res %d\n", cmd->opcode, cmd->error); } /* @@ -550,11 +544,6 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data) unsigned long dmaflags; unsigned int size; - DBGF("blksz %04x blks %04x flags %08x\n", - data->blksz, data->blocks, data->flags); - DBGF("tsac %d ms nsac %d clk\n", - data->timeout_ns / 1000000, data->timeout_clks); - /* * Calculate size. */ @@ -752,8 +741,6 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data) } } - DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered); - wbsd_request_end(host, host->mrq); } diff --git a/drivers/mmc/host/wbsd.h b/drivers/mmc/host/wbsd.h index 873bda1..0877866 100644 --- a/drivers/mmc/host/wbsd.h +++ b/drivers/mmc/host/wbsd.h @@ -1,5 +1,5 @@ /* - * linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver + * linux/drivers/mmc/host/wbsd.h - Winbond W83L51xD SD/MMC driver * * Copyright (C) 2004-2007 Pierre Ossman, All Rights Reserved. * diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index d574916..d8cc94e 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -81,10 +81,7 @@ static unsigned long __initdata doc_locations[] = { #endif /* CONFIG_MTD_DOCPROBE_HIGH */ #elif defined(__PPC__) 0xe4000000, -#elif defined(CONFIG_MOMENCO_OCELOT) - 0x2f000000, - 0xff000000, -##else +#else #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif 0xffffffff }; diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index f88ebc5..cc6c734 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -103,7 +103,7 @@ config MTD_PMC_MSP_RAMROOT config MTD_SUN_UFLASH tristate "Sun Microsystems userflash support" - depends on SPARC && MTD_CFI + depends on SPARC && MTD_CFI && PCI help This provides a 'mapping' driver which supports the way in which user-programmable flash chips are connected on various diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 5f3049a..ab9f5c5 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -56,9 +56,6 @@ static unsigned long __initdata doc_locations[] = { #endif /* CONFIG_MTD_DOCPROBE_HIGH */ #elif defined(__PPC__) 0xe4000000, -#elif defined(CONFIG_MOMENCO_OCELOT) - 0x2f000000, - 0xff000000, #else #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 6deb20f..001c66d 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2886,7 +2886,6 @@ static const struct ethtool_ops vortex_ethtool_ops = { .set_settings = vortex_set_settings, .get_link = ethtool_op_get_link, .nway_reset = vortex_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, }; #ifdef CONFIG_PCI diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index e970e64..a79f28c 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -1578,7 +1578,6 @@ static const struct ethtool_ops cp_ethtool_ops = { .set_wol = cp_set_wol, .get_strings = cp_get_strings, .get_ethtool_stats = cp_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, .get_eeprom_len = cp_get_eeprom_len, .get_eeprom = cp_get_eeprom, .set_eeprom = cp_set_eeprom, diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 327eaa7..f4e4298 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -2452,7 +2452,6 @@ static const struct ethtool_ops rtl8139_ethtool_ops = { .get_strings = rtl8139_get_strings, .get_stats_count = rtl8139_get_stats_count, .get_ethtool_stats = rtl8139_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 3ff1155..d915837 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -57,6 +57,7 @@ #include <asm/io.h> #include <asm/dma.h> #include <asm/pgtable.h> +#include <asm/cacheflush.h> static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f8a602c..81ef81c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2851,7 +2851,7 @@ config PPPOATM config PPPOL2TP tristate "PPP over L2TP (EXPERIMENTAL)" - depends on EXPERIMENTAL && PPP + depends on EXPERIMENTAL && PPP && INET help Support for PPP-over-L2TP socket family. L2TP is a protocol used by ISPs and enterprises to tunnel PPP traffic over UDP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 336af06..e684212 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,7 +18,7 @@ gianfar_driver-objs := gianfar.o \ gianfar_sysfs.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o -ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o +ucc_geth_driver-objs := ucc_geth.o ucc_geth_mii.o ucc_geth_ethtool.o # # link order important here @@ -177,7 +177,7 @@ obj-$(CONFIG_ZORRO8390) += zorro8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_EQUALIZER) += eql.o -obj-$(CONFIG_LGUEST_GUEST) += lguest_net.o +obj-$(CONFIG_LGUEST_NET) += lguest_net.o obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index b78a4e5..62e660a 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -3128,12 +3128,6 @@ static int __devinit read_eeprom_byte(struct net_device *dev, int result = 0; short i; - if (!dev) { - printk(KERN_ERR "No device!\n"); - result = -ENODEV; - goto out; - } - /* * Don't take interrupts on this CPU will bit banging * the %#%#@$ I2C device diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h index 100c09c..939aa0f 100644 --- a/drivers/net/atl1/atl1_hw.h +++ b/drivers/net/atl1/atl1_hw.h @@ -680,11 +680,6 @@ void atl1_check_options(struct atl1_adapter *adapter); #define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */ #define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */ -/* The size (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */ -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */ -#define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x2800 #define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ @@ -929,8 +924,8 @@ enum atl1_dma_req_block { atl1_dma_req_128 = 0, atl1_dma_req_256 = 1, atl1_dma_req_512 = 2, - atl1_dam_req_1024 = 3, - atl1_dam_req_2048 = 4, + atl1_dma_req_1024 = 3, + atl1_dma_req_2048 = 4, atl1_dma_req_4096 = 5 }; diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index fd1e156..56f6389 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -59,6 +59,7 @@ #include <linux/skbuff.h> #include <linux/etherdevice.h> #include <linux/if_vlan.h> +#include <linux/if_ether.h> #include <linux/irqreturn.h> #include <linux/workqueue.h> #include <linux/timer.h> @@ -120,8 +121,8 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter) struct atl1_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; adapter->wol = 0; adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7; @@ -314,7 +315,7 @@ err_nomem: return -ENOMEM; } -void atl1_init_ring_ptrs(struct atl1_adapter *adapter) +static void atl1_init_ring_ptrs(struct atl1_adapter *adapter) { struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; @@ -688,9 +689,9 @@ static int atl1_change_mtu(struct net_device *netdev, int new_mtu) { struct atl1_adapter *adapter = netdev_priv(netdev); int old_mtu = netdev->mtu; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || + if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); return -EINVAL; @@ -908,8 +909,8 @@ static u32 atl1_configure(struct atl1_adapter *adapter) /* config DMA Engine */ value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | - ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN | + ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) + << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN; value |= (u32) hw->dma_ord; if (atl1_rcb_128 == hw->rcb_value) @@ -917,7 +918,10 @@ static u32 atl1_configure(struct atl1_adapter *adapter) iowrite32(value, hw->hw_addr + REG_DMA_CTRL); /* config CMB / SMB */ - value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16); + value = (hw->cmb_tpd > adapter->tpd_ring.count) ? + hw->cmb_tpd : adapter->tpd_ring.count; + value <<= 16; + value |= hw->cmb_rrd; iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH); value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16); iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER); @@ -1334,7 +1338,7 @@ rrd_ok: skb = buffer_info->skb; length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); - skb_put(skb, length - ETHERNET_FCS_SIZE); + skb_put(skb, length - ETH_FCS_LEN); /* Receive Checksum Offload */ atl1_rx_checksum(adapter, rrd, skb); @@ -1422,7 +1426,7 @@ static void atl1_intr_tx(struct atl1_adapter *adapter) netif_wake_queue(adapter->netdev); } -static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring) +static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring) { u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); u16 next_to_use = atomic_read(&tpd_ring->next_to_use); @@ -1453,7 +1457,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, 0); ipofst = skb_network_offset(skb); - if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */ + if (ipofst != ETH_HLEN) /* 802.3 frame */ tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT; tso->tsopl |= (iph->ihl & @@ -1708,7 +1712,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_LOCKED; } - if (tpd_avail(&adapter->tpd_ring) < count) { + if (atl1_tpd_avail(&adapter->tpd_ring) < count) { /* not enough descriptors */ netif_stop_queue(netdev); spin_unlock_irqrestore(&adapter->lock, flags); diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 1d88236..83da177 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -580,7 +580,6 @@ static const struct ethtool_ops ax_ethtool_ops = { .set_settings = ax_set_settings, .nway_reset = ax_nway_reset, .get_link = ax_get_link, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* setup code */ @@ -819,7 +818,7 @@ static int ax_probe(struct platform_device *pdev) } ei_status.mem = ioremap(res->start, size); - dev->base_addr = (long)ei_status.mem; + dev->base_addr = (unsigned long)ei_status.mem; if (ei_status.mem == NULL) { dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n", diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 37f1b6f..0795df2 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2033,7 +2033,6 @@ static const struct ethtool_ops b44_ethtool_ops = { .get_strings = b44_get_strings, .get_stats_count = b44_get_stats_count, .get_ethtool_stats = b44_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 9a08d65..2bb97d4 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -798,6 +798,7 @@ static void bf537mac_shutdown(struct net_device *dev) */ static int bf537mac_open(struct net_device *dev) { + int retval; pr_debug("%s: %s\n", dev->name, __FUNCTION__); /* @@ -811,7 +812,10 @@ static int bf537mac_open(struct net_device *dev) } /* initial rx and tx list */ - desc_list_init(); + retval = desc_list_init(); + + if (retval) + return retval; bf537mac_setphy(dev); setup_system_regs(dev); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a729da0..d53dfc5 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6269,7 +6269,6 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .phys_id = bnx2_phys_id, .get_stats_count = bnx2_get_stats_count, .get_ethtool_stats = bnx2_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* Called with rtnl_lock */ diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index cb9cb30..070b78d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -613,38 +613,20 @@ down: static int bond_update_speed_duplex(struct slave *slave) { struct net_device *slave_dev = slave->dev; - static int (* ioctl)(struct net_device *, struct ifreq *, int); - struct ifreq ifr; struct ethtool_cmd etool; + int res; /* Fake speed and duplex */ slave->speed = SPEED_100; slave->duplex = DUPLEX_FULL; - if (slave_dev->ethtool_ops) { - int res; - - if (!slave_dev->ethtool_ops->get_settings) { - return -1; - } - - res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); - if (res < 0) { - return -1; - } - - goto verify; - } + if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings) + return -1; - ioctl = slave_dev->do_ioctl; - strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); - etool.cmd = ETHTOOL_GSET; - ifr.ifr_data = (char*)&etool; - if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) { + res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); + if (res < 0) return -1; - } -verify: switch (etool.speed) { case SPEED_10: case SPEED_100: @@ -690,7 +672,6 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; - struct ethtool_value etool; if (bond->params.use_carrier) { return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; @@ -721,9 +702,10 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de } } - /* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */ - /* for a period of time so we attempt to get link status */ - /* from it last if the above MII ioctls fail... */ + /* + * Some drivers cache ETHTOOL_GLINK for a period of time so we only + * attempt to get link status from it if the above MII ioctls fail. + */ if (slave_dev->ethtool_ops) { if (slave_dev->ethtool_ops->get_link) { u32 link; @@ -734,23 +716,9 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de } } - if (ioctl) { - strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); - etool.cmd = ETHTOOL_GLINK; - ifr.ifr_data = (char*)&etool; - if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) { - if (etool.data == 1) { - return BMSR_LSTATUS; - } else { - dprintk("SIOCETHTOOL shows link down\n"); - return 0; - } - } - } - /* * If reporting, report that either there's no dev->do_ioctl, - * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we + * or both SIOCGMIIREG and get_link failed (meaning that we * cannot report link status). If not reporting, pretend * we're ok. */ diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 6fd1e52..dc5d269 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1583,7 +1583,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_wol = get_wol, .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, - .get_perm_addr = ethtool_op_get_perm_addr }; static int in_range(int val, int lo, int hi) diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index ebcf35e..e620ed4c 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -699,7 +699,7 @@ static int do_cr(struct t3cdev *dev, struct sk_buff *skb) * the buffer. */ static struct sk_buff *cxgb3_get_cpl_reply_skb(struct sk_buff *skb, size_t len, - int gfp) + gfp_t gfp) { if (likely(!skb_cloned(skb))) { BUG_ON(skb->len < len); diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 7df23dc..9c8e3f9 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -200,6 +200,7 @@ /* Include files */ #include <linux/bitops.h> +#include <linux/compiler.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/eisa.h> @@ -240,8 +241,6 @@ static char version[] __devinitdata = */ #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) -#define __unused __attribute__ ((unused)) - #ifdef CONFIG_PCI #define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type) #else @@ -375,7 +374,7 @@ static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data) static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -399,7 +398,7 @@ static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data) static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; @@ -866,7 +865,7 @@ static void __devinit dfx_bus_uninit(struct net_device *dev) static void __devinit dfx_bus_config_check(DFX_board_t *bp) { - struct device __unused *bdev = bp->bus_dev; + struct device __maybe_unused *bdev = bp->bus_dev; int dfx_bus_eisa = DFX_BUS_EISA(bdev); int status; /* return code from adapter port control call */ u32 host_data; /* LW data returned from port control call */ @@ -3624,8 +3623,8 @@ static void __devexit dfx_unregister(struct device *bdev) } -static int __devinit __unused dfx_dev_register(struct device *); -static int __devexit __unused dfx_dev_unregister(struct device *); +static int __devinit __maybe_unused dfx_dev_register(struct device *); +static int __devexit __maybe_unused dfx_dev_unregister(struct device *); #ifdef CONFIG_PCI static int __devinit dfx_pci_register(struct pci_dev *, @@ -3699,7 +3698,7 @@ static struct tc_driver dfx_tc_driver = { }; #endif /* CONFIG_TC */ -static int __devinit __unused dfx_dev_register(struct device *dev) +static int __devinit __maybe_unused dfx_dev_register(struct device *dev) { int status; @@ -3709,7 +3708,7 @@ static int __devinit __unused dfx_dev_register(struct device *dev) return status; } -static int __devexit __unused dfx_dev_unregister(struct device *dev) +static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev) { put_device(dev); dfx_unregister(dev); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 6b6401e..280313b 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2506,7 +2506,6 @@ static const struct ethtool_ops e100_ethtool_ops = { .phys_id = e100_phys_id, .get_stats_count = e100_get_stats_count, .get_ethtool_stats = e100_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index bb08375..c90c92e 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1973,7 +1973,6 @@ static const struct ethtool_ops e1000_ethtool_ops = { .phys_id = e1000_phys_id, .get_stats_count = e1000_get_stats_count, .get_ethtool_stats = e1000_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; void e1000_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 489c8b2..8ee2c2c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -39,7 +39,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0071" +#define DRV_VERSION "EHEA_0072" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 4c70a93..58702f5 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -589,6 +589,23 @@ static int ehea_poll(struct net_device *dev, int *budget) return 1; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ehea_netpoll(struct net_device *dev) +{ + struct ehea_port *port = netdev_priv(dev); + + netif_rx_schedule(port->port_res[0].d_netdev); +} +#endif + +static int ehea_poll_firstqueue(struct net_device *dev, int *budget) +{ + struct ehea_port *port = netdev_priv(dev); + struct net_device *d_dev = port->port_res[0].d_netdev; + + return ehea_poll(d_dev, budget); +} + static irqreturn_t ehea_recv_irq_handler(int irq, void *param) { struct ehea_port_res *pr = param; @@ -2626,7 +2643,10 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN); dev->open = ehea_open; - dev->poll = ehea_poll; + dev->poll = ehea_poll_firstqueue; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = ehea_netpoll; +#endif dev->weight = 64; dev->stop = ehea_stop; dev->hard_start_xmit = ehea_start_xmit; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 03023dd..4e8df91 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -47,6 +47,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/pgtable.h> +#include <asm/cacheflush.h> #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ @@ -98,8 +99,6 @@ static unsigned char fec_mac_default[] = { #define FEC_FLASHMAC 0xf0006006 #elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) #define FEC_FLASHMAC 0xf0006000 -#elif defined (CONFIG_MTD_KeyTechnology) -#define FEC_FLASHMAC 0xffe04000 #elif defined(CONFIG_CANCam) #define FEC_FLASHMAC 0xf0020000 #elif defined (CONFIG_M5272C3) @@ -191,6 +190,8 @@ struct fec_enet_private { /* Hardware registers of the FEC device */ volatile fec_t *hwp; + struct net_device *netdev; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; @@ -1269,7 +1270,7 @@ static void __inline__ fec_request_intrs(struct net_device *dev) icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3); *icrp = 0x00000ddd; icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x70777777) | 0x0d000000; + *icrp = 0x0d000000; } static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) @@ -1331,7 +1332,7 @@ static void __inline__ fec_disable_phy_intr(void) { volatile unsigned long *icrp; icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x70777777) | 0x08000000; + *icrp = 0x08000000; } static void __inline__ fec_phy_ack_intr(void) @@ -1339,7 +1340,7 @@ static void __inline__ fec_phy_ack_intr(void) volatile unsigned long *icrp; /* Acknowledge the interrupt */ icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x77777777) | 0x08000000; + *icrp = 0x0d000000; } static void __inline__ fec_localhw_setup(void) @@ -1426,6 +1427,29 @@ static void __inline__ fec_request_intrs(struct net_device *dev) *gpio_pehlpar = 0xc0; } #endif + +#if defined(CONFIG_M527x) + /* Set up gpio outputs for MII lines */ + { + volatile u8 *gpio_par_fec; + volatile u16 *gpio_par_feci2c; + + gpio_par_feci2c = (volatile u16 *)(MCF_IPSBAR + 0x100082); + /* Set up gpio outputs for FEC0 MII lines */ + gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100078); + + *gpio_par_feci2c |= 0x0f00; + *gpio_par_fec |= 0xc0; + +#if defined(CONFIG_FEC2) + /* Set up gpio outputs for FEC1 MII lines */ + gpio_par_fec = (volatile u8 *)(MCF_IPSBAR + 0x100079); + + *gpio_par_feci2c |= 0x00a0; + *gpio_par_fec |= 0xc0; +#endif /* CONFIG_FEC2 */ + } +#endif /* CONFIG_M527x */ } static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) @@ -1940,9 +1964,10 @@ static void mii_display_status(struct net_device *dev) printk(".\n"); } -static void mii_display_config(struct net_device *dev) +static void mii_display_config(struct work_struct *work) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->netdev; uint status = fep->phy_status; /* @@ -1976,9 +2001,10 @@ static void mii_display_config(struct net_device *dev) fep->sequence_done = 1; } -static void mii_relink(struct net_device *dev) +static void mii_relink(struct work_struct *work) { - struct fec_enet_private *fep = netdev_priv(dev); + struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->netdev; int duplex; /* @@ -2022,7 +2048,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) return; fep->mii_phy_task_queued = 1; - INIT_WORK(&fep->phy_task, (void*)mii_relink, dev); + INIT_WORK(&fep->phy_task, mii_relink); schedule_work(&fep->phy_task); } @@ -2035,7 +2061,7 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev) return; fep->mii_phy_task_queued = 1; - INIT_WORK(&fep->phy_task, (void*)mii_display_config, dev); + INIT_WORK(&fep->phy_task, mii_display_config); schedule_work(&fep->phy_task); } @@ -2330,6 +2356,7 @@ int __init fec_enet_init(struct net_device *dev) fep->index = index; fep->hwp = fecp; + fep->netdev = dev; /* Whack a reset. We should wait for this. */ diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 6d1d50a..69f5f36 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -178,6 +178,7 @@ #define DEV_HAS_STATISTICS_V2 0x0800 /* device supports hw statistics version 2 */ #define DEV_HAS_TEST_EXTENDED 0x1000 /* device supports extended diagnostic test */ #define DEV_HAS_MGMT_UNIT 0x2000 /* device supports management unit */ +#define DEV_HAS_CORRECT_MACADDR 0x4000 /* device supports correct mac address order */ enum { NvRegIrqStatus = 0x000, @@ -4706,7 +4707,6 @@ static const struct ethtool_ops ops = { .get_regs_len = nv_get_regs_len, .get_regs = nv_get_regs, .nway_reset = nv_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, .get_tso = ethtool_op_get_tso, .set_tso = nv_set_tso, .get_ringparam = nv_get_ringparam, @@ -5172,7 +5172,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* check the workaround bit for correct mac address order */ txreg = readl(base + NvRegTransmitPoll); - if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { + if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || + (id->driver_data & DEV_HAS_CORRECT_MACADDR)) { /* mac address is already in correct order */ dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; @@ -5500,51 +5501,67 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + }, + { /* MCP73 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, {0,}, }; diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index ac3596f..100bf41 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -245,7 +245,7 @@ int __init gfar_mdio_init(void) return driver_register(&gianfar_mdio_driver); } -void __exit gfar_mdio_exit(void) +void gfar_mdio_exit(void) { driver_unregister(&gianfar_mdio_driver); } diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 5d34004..b373091 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h @@ -42,5 +42,5 @@ struct gfar_mii { int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum); int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); int __init gfar_mdio_init(void); -void __exit gfar_mdio_exit(void); +void gfar_mdio_exit(void); #endif /* GIANFAR_PHY_H */ diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 656f278..cc0ee93 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -413,12 +413,12 @@ static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos) ++*pos; if (v == SEQ_START_TOKEN) - p = bpq_devices.next; + p = rcu_dereference(bpq_devices.next); else - p = ((struct bpqdev *)v)->bpq_list.next; + p = rcu_dereference(((struct bpqdev *)v)->bpq_list.next); return (p == &bpq_devices) ? NULL - : rcu_dereference(list_entry(p, struct bpqdev, bpq_list)); + : list_entry(p, struct bpqdev, bpq_list); } static void bpq_seq_stop(struct seq_file *seq, void *v) diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index afde848..0413cd9 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -724,7 +724,6 @@ static const struct ethtool_ops ixgb_ethtool_ops = { .phys_id = ixgb_phys_id, .get_stats_count = ixgb_get_stats_count, .get_ethtool_stats = ixgb_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; void ixgb_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/lguest_net.c b/drivers/net/lguest_net.c index 1127786..cab5791 100644 --- a/drivers/net/lguest_net.c +++ b/drivers/net/lguest_net.c @@ -1,6 +1,13 @@ -/* A simple network driver for lguest. +/*D:500 + * The Guest network driver. * - * Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation + * This is very simple a virtual network driver, and our last Guest driver. + * The only trick is that it can talk directly to multiple other recipients + * (ie. other Guests on the same network). It can also be used with only the + * Host on the network. + :*/ + +/* Copyright 2006 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation * * 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 @@ -28,23 +35,47 @@ #define MAX_LANS 4 #define NUM_SKBS 8 +/*M:011 Network code master Jeff Garzik points out numerous shortcomings in + * this driver if it aspires to greatness. + * + * Firstly, it doesn't use "NAPI": the networking's New API, and is poorer for + * it. As he says "NAPI means system-wide load leveling, across multiple + * network interfaces. Lack of NAPI can mean competition at higher loads." + * + * He also points out that we don't implement set_mac_address, so users cannot + * change the devices hardware address. When I asked why one would want to: + * "Bonding, and situations where you /do/ want the MAC address to "leak" out + * of the host onto the wider net." + * + * Finally, he would like module unloading: "It is not unrealistic to think of + * [un|re|]loading the net support module in an lguest guest. And, adding + * module support makes the programmer more responsible, because they now have + * to learn to clean up after themselves. Any driver that cannot clean up + * after itself is an incomplete driver in my book." + :*/ + +/*D:530 The "struct lguestnet_info" contains all the information we need to + * know about the network device. */ struct lguestnet_info { - /* The shared page(s). */ + /* The mapped device page(s) (an array of "struct lguest_net"). */ struct lguest_net *peer; + /* The physical address of the device page(s) */ unsigned long peer_phys; + /* The size of the device page(s). */ unsigned long mapsize; /* The lguest_device I come from */ struct lguest_device *lgdev; - /* My peerid. */ + /* My peerid (ie. my slot in the array). */ unsigned int me; - /* Receive queue. */ + /* Receive queue: the network packets waiting to be filled. */ struct sk_buff *skb[NUM_SKBS]; struct lguest_dma dma[NUM_SKBS]; }; +/*:*/ /* How many bytes left in this page. */ static unsigned int rest_of_page(void *data) @@ -52,39 +83,82 @@ static unsigned int rest_of_page(void *data) return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); } -/* Simple convention: offset 4 * peernum. */ +/*D:570 Each peer (ie. Guest or Host) on the network binds their receive + * buffers to a different key: we simply use the physical address of the + * device's memory page plus the peer number. The Host insists that all keys + * be a multiple of 4, so we multiply the peer number by 4. */ static unsigned long peer_key(struct lguestnet_info *info, unsigned peernum) { return info->peer_phys + 4 * peernum; } +/* This is the routine which sets up a "struct lguest_dma" to point to a + * network packet, similar to req_to_dma() in lguest_blk.c. The structure of a + * "struct sk_buff" has grown complex over the years: it consists of a "head" + * linear section pointed to by "skb->data", and possibly an array of + * "fragments" in the case of a non-linear packet. + * + * Our receive buffers don't use fragments at all but outgoing skbs might, so + * we handle it. */ static void skb_to_dma(const struct sk_buff *skb, unsigned int headlen, struct lguest_dma *dma) { unsigned int i, seg; + /* First, we put the linear region into the "struct lguest_dma". Each + * entry can't go over a page boundary, so even though all our packets + * are 1514 bytes or less, we might need to use two entries here: */ for (i = seg = 0; i < headlen; seg++, i += rest_of_page(skb->data+i)) { dma->addr[seg] = virt_to_phys(skb->data + i); dma->len[seg] = min((unsigned)(headlen - i), rest_of_page(skb->data + i)); } + + /* Now we handle the fragments: at least they're guaranteed not to go + * over a page. skb_shinfo(skb) returns a pointer to the structure + * which tells us about the number of fragments and the fragment + * array. */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, seg++) { const skb_frag_t *f = &skb_shinfo(skb)->frags[i]; /* Should not happen with MTU less than 64k - 2 * PAGE_SIZE. */ if (seg == LGUEST_MAX_DMA_SECTIONS) { + /* We will end up sending a truncated packet should + * this ever happen. Plus, a cool log message! */ printk("Woah dude! Megapacket!\n"); break; } dma->addr[seg] = page_to_phys(f->page) + f->page_offset; dma->len[seg] = f->size; } + + /* If after all that we didn't use the entire "struct lguest_dma" + * array, we terminate it with a 0 length. */ if (seg < LGUEST_MAX_DMA_SECTIONS) dma->len[seg] = 0; } -/* We overload multicast bit to show promiscuous mode. */ +/* + * Packet transmission. + * + * Our packet transmission is a little unusual. A real network card would just + * send out the packet and leave the receivers to decide if they're interested. + * Instead, we look through the network device memory page and see if any of + * the ethernet addresses match the packet destination, and if so we send it to + * that Guest. + * + * This is made a little more complicated in two cases. The first case is + * broadcast packets: for that we send the packet to all Guests on the network, + * one at a time. The second case is "promiscuous" mode, where a Guest wants + * to see all the packets on the network. We need a way for the Guest to tell + * us it wants to see all packets, so it sets the "multicast" bit on its + * published MAC address, which is never valid in a real ethernet address. + */ #define PROMISC_BIT 0x01 +/* This is the callback which is summoned whenever the network device's + * multicast or promiscuous state changes. If the card is in promiscuous mode, + * we advertise that in our ethernet address in the device's memory. We do the + * same if Linux wants any or all multicast traffic. */ static void lguestnet_set_multicast(struct net_device *dev) { struct lguestnet_info *info = netdev_priv(dev); @@ -95,11 +169,14 @@ static void lguestnet_set_multicast(struct net_device *dev) info->peer[info->me].mac[0] &= ~PROMISC_BIT; } +/* A simple test function to see if a peer wants to see all packets.*/ static int promisc(struct lguestnet_info *info, unsigned int peer) { return info->peer[peer].mac[0] & PROMISC_BIT; } +/* Another simple function to see if a peer's advertised ethernet address + * matches a packet's destination ethernet address. */ static int mac_eq(const unsigned char mac[ETH_ALEN], struct lguestnet_info *info, unsigned int peer) { @@ -109,6 +186,8 @@ static int mac_eq(const unsigned char mac[ETH_ALEN], return memcmp(mac+1, info->peer[peer].mac+1, ETH_ALEN-1) == 0; } +/* This is the function which actually sends a packet once we've decided a + * peer wants it: */ static void transfer_packet(struct net_device *dev, struct sk_buff *skb, unsigned int peernum) @@ -116,76 +195,134 @@ static void transfer_packet(struct net_device *dev, struct lguestnet_info *info = netdev_priv(dev); struct lguest_dma dma; + /* We use our handy "struct lguest_dma" packing function to prepare + * the skb for sending. */ skb_to_dma(skb, skb_headlen(skb), &dma); pr_debug("xfer length %04x (%u)\n", htons(skb->len), skb->len); + /* This is the actual send call which copies the packet. */ lguest_send_dma(peer_key(info, peernum), &dma); + + /* Check that the entire packet was transmitted. If not, it could mean + * that the other Guest registered a short receive buffer, but this + * driver should never do that. More likely, the peer is dead. */ if (dma.used_len != skb->len) { dev->stats.tx_carrier_errors++; pr_debug("Bad xfer to peer %i: %i of %i (dma %p/%i)\n", peernum, dma.used_len, skb->len, (void *)dma.addr[0], dma.len[0]); } else { + /* On success we update the stats. */ dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++; } } +/* Another helper function to tell is if a slot in the device memory is unused. + * Since we always set the Local Assignment bit in the ethernet address, the + * first byte can never be 0. */ static int unused_peer(const struct lguest_net peer[], unsigned int num) { return peer[num].mac[0] == 0; } +/* Finally, here is the routine which handles an outgoing packet. It's called + * "start_xmit" for traditional reasons. */ static int lguestnet_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int i; int broadcast; struct lguestnet_info *info = netdev_priv(dev); + /* Extract the destination ethernet address from the packet. */ const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; pr_debug("%s: xmit %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, dest[0],dest[1],dest[2],dest[3],dest[4],dest[5]); + /* If it's a multicast packet, we broadcast to everyone. That's not + * very efficient, but there are very few applications which actually + * use multicast, which is a shame really. + * + * As etherdevice.h points out: "By definition the broadcast address is + * also a multicast address." So we don't have to test for broadcast + * packets separately. */ broadcast = is_multicast_ether_addr(dest); + + /* Look through all the published ethernet addresses to see if we + * should send this packet. */ for (i = 0; i < info->mapsize/sizeof(struct lguest_net); i++) { + /* We don't send to ourselves (we actually can't SEND_DMA to + * ourselves anyway), and don't send to unused slots.*/ if (i == info->me || unused_peer(info->peer, i)) continue; + /* If it's broadcast we send it. If they want every packet we + * send it. If the destination matches their address we send + * it. Otherwise we go to the next peer. */ if (!broadcast && !promisc(info, i) && !mac_eq(dest, info, i)) continue; pr_debug("lguestnet %s: sending from %i to %i\n", dev->name, info->me, i); + /* Our routine which actually does the transfer. */ transfer_packet(dev, skb, i); } + + /* An xmit routine is expected to dispose of the packet, so we do. */ dev_kfree_skb(skb); + + /* As per kernel convention, 0 means success. This is why I love + * networking: even if we never sent to anyone, that's still + * success! */ return 0; } -/* Find a new skb to put in this slot in shared mem. */ +/*D:560 + * Packet receiving. + * + * First, here's a helper routine which fills one of our array of receive + * buffers: */ static int fill_slot(struct net_device *dev, unsigned int slot) { struct lguestnet_info *info = netdev_priv(dev); - /* Try to create and register a new one. */ + + /* We can receive ETH_DATA_LEN (1500) byte packets, plus a standard + * ethernet header of ETH_HLEN (14) bytes. */ info->skb[slot] = netdev_alloc_skb(dev, ETH_HLEN + ETH_DATA_LEN); if (!info->skb[slot]) { printk("%s: could not fill slot %i\n", dev->name, slot); return -ENOMEM; } + /* skb_to_dma() is a helper which sets up the "struct lguest_dma" to + * point to the data in the skb: we also use it for sending out a + * packet. */ skb_to_dma(info->skb[slot], ETH_HLEN + ETH_DATA_LEN, &info->dma[slot]); + + /* This is a Write Memory Barrier: it ensures that the entry in the + * receive buffer array is written *before* we set the "used_len" entry + * to 0. If the Host were looking at the receive buffer array from a + * different CPU, it could potentially see "used_len = 0" and not see + * the updated receive buffer information. This would be a horribly + * nasty bug, so make sure the compiler and CPU know this has to happen + * first. */ wmb(); - /* Now we tell hypervisor it can use the slot. */ + /* Writing 0 to "used_len" tells the Host it can use this receive + * buffer now. */ info->dma[slot].used_len = 0; return 0; } +/* This is the actual receive routine. When we receive an interrupt from the + * Host to tell us a packet has been delivered, we arrive here: */ static irqreturn_t lguestnet_rcv(int irq, void *dev_id) { struct net_device *dev = dev_id; struct lguestnet_info *info = netdev_priv(dev); unsigned int i, done = 0; + /* Look through our entire receive array for an entry which has data + * in it. */ for (i = 0; i < ARRAY_SIZE(info->dma); i++) { unsigned int length; struct sk_buff *skb; @@ -194,10 +331,16 @@ static irqreturn_t lguestnet_rcv(int irq, void *dev_id) if (length == 0) continue; + /* We've found one! Remember the skb (we grabbed the length + * above), and immediately refill the slot we've taken it + * from. */ done++; skb = info->skb[i]; fill_slot(dev, i); + /* This shouldn't happen: micropackets could be sent by a + * badly-behaved Guest on the network, but the Host will never + * stuff more data in the buffer than the buffer length. */ if (length < ETH_HLEN || length > ETH_HLEN + ETH_DATA_LEN) { pr_debug(KERN_WARNING "%s: unbelievable skb len: %i\n", dev->name, length); @@ -205,36 +348,72 @@ static irqreturn_t lguestnet_rcv(int irq, void *dev_id) continue; } + /* skb_put(), what a great function! I've ranted about this + * function before (http://lkml.org/lkml/1999/9/26/24). You + * call it after you've added data to the end of an skb (in + * this case, it was the Host which wrote the data). */ skb_put(skb, length); + + /* The ethernet header contains a protocol field: we use the + * standard helper to extract it, and place the result in + * skb->protocol. The helper also sets up skb->pkt_type and + * eats up the ethernet header from the front of the packet. */ skb->protocol = eth_type_trans(skb, dev); - /* This is a reliable transport. */ + + /* If this device doesn't need checksums for sending, we also + * don't need to check the packets when they come in. */ if (dev->features & NETIF_F_NO_CSUM) skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* As a last resort for debugging the driver or the lguest I/O + * subsystem, you can uncomment the "#define DEBUG" at the top + * of this file, which turns all the pr_debug() into printk() + * and floods the logs. */ pr_debug("Receiving skb proto 0x%04x len %i type %i\n", ntohs(skb->protocol), skb->len, skb->pkt_type); + /* Update the packet and byte counts (visible from ifconfig, + * and good for debugging). */ dev->stats.rx_bytes += skb->len; dev->stats.rx_packets++; + + /* Hand our fresh network packet into the stack's "network + * interface receive" routine. That will free the packet + * itself when it's finished. */ netif_rx(skb); } + + /* If we found any packets, we assume the interrupt was for us. */ return done ? IRQ_HANDLED : IRQ_NONE; } +/*D:550 This is where we start: when the device is brought up by dhcpd or + * ifconfig. At this point we advertise our MAC address to the rest of the + * network, and register receive buffers ready for incoming packets. */ static int lguestnet_open(struct net_device *dev) { int i; struct lguestnet_info *info = netdev_priv(dev); - /* Set up our MAC address */ + /* Copy our MAC address into the device page, so others on the network + * can find us. */ memcpy(info->peer[info->me].mac, dev->dev_addr, ETH_ALEN); - /* Turn on promisc mode if needed */ + /* We might already be in promisc mode (dev->flags & IFF_PROMISC). Our + * set_multicast callback handles this already, so we call it now. */ lguestnet_set_multicast(dev); + /* Allocate packets and put them into our "struct lguest_dma" array. + * If we fail to allocate all the packets we could still limp along, + * but it's a sign of real stress so we should probably give up now. */ for (i = 0; i < ARRAY_SIZE(info->dma); i++) { if (fill_slot(dev, i) != 0) goto cleanup; } + + /* Finally we tell the Host where our array of "struct lguest_dma" + * receive buffers is, binding it to the key corresponding to the + * device's physical memory plus our peerid. */ if (lguest_bind_dma(peer_key(info,info->me), info->dma, NUM_SKBS, lgdev_irq(info->lgdev)) != 0) goto cleanup; @@ -245,22 +424,29 @@ cleanup: dev_kfree_skb(info->skb[i]); return -ENOMEM; } +/*:*/ +/* The close routine is called when the device is no longer in use: we clean up + * elegantly. */ static int lguestnet_close(struct net_device *dev) { unsigned int i; struct lguestnet_info *info = netdev_priv(dev); - /* Clear all trace: others might deliver packets, we'll ignore it. */ + /* Clear all trace of our existence out of the device memory by setting + * the slot which held our MAC address to 0 (unused). */ memset(&info->peer[info->me], 0, sizeof(info->peer[info->me])); - /* Deregister sg lists. */ + /* Unregister our array of receive buffers */ lguest_unbind_dma(peer_key(info, info->me), info->dma); for (i = 0; i < ARRAY_SIZE(info->dma); i++) dev_kfree_skb(info->skb[i]); return 0; } +/*D:510 The network device probe function is basically a standard ethernet + * device setup. It reads the "struct lguest_device_desc" and sets the "struct + * net_device". Oh, the line-by-line excitement! Let's skip over it. :*/ static int lguestnet_probe(struct lguest_device *lgdev) { int err, irqf = IRQF_SHARED; @@ -290,10 +476,16 @@ static int lguestnet_probe(struct lguest_device *lgdev) dev->stop = lguestnet_close; dev->hard_start_xmit = lguestnet_start_xmit; - /* Turning on/off promisc will call dev->set_multicast_list. - * We don't actually support multicast yet */ + /* We don't actually support multicast yet, but turning on/off + * promisc also calls dev->set_multicast_list. */ dev->set_multicast_list = lguestnet_set_multicast; SET_NETDEV_DEV(dev, &lgdev->dev); + + /* The network code complains if you have "scatter-gather" capability + * if you don't also handle checksums (it seem that would be + * "illogical"). So we use a lie of omission and don't tell it that we + * can handle scattered packets unless we also don't want checksums, + * even though to us they're completely independent. */ if (desc->features & LGUEST_NET_F_NOCSUM) dev->features = NETIF_F_SG|NETIF_F_NO_CSUM; @@ -325,6 +517,9 @@ static int lguestnet_probe(struct lguest_device *lgdev) } pr_debug("lguestnet: registered device %s\n", dev->name); + /* Finally, we put the "struct net_device" in the generic "struct + * lguest_device"s private pointer. Again, it's not necessary, but + * makes sure the cool kernel kids don't tease us. */ lgdev->private = dev; return 0; @@ -352,3 +547,11 @@ module_init(lguestnet_init); MODULE_DESCRIPTION("Lguest network driver"); MODULE_LICENSE("GPL"); + +/*D:580 + * This is the last of the Drivers, and with this we have covered the many and + * wonderous and fine (and boring) details of the Guest. + * + * "make Launcher" beckons, where we answer questions like "Where do Guests + * come from?", and "What do you do when someone asks for optimization?" + */ diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 5c86e73..c429a50 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -143,6 +143,52 @@ static void __NS8390_init(struct net_device *dev, int startp); * annoying the transmit function is called bh atomic. That places * restrictions on the user context callers as disable_irq won't save * them. + * + * Additional explanation of problems with locking by Alan Cox: + * + * "The author (me) didn't use spin_lock_irqsave because the slowness of the + * card means that approach caused horrible problems like losing serial data + * at 38400 baud on some chips. Rememeber many 8390 nics on PCI were ISA + * chips with FPGA front ends. + * + * Ok the logic behind the 8390 is very simple: + * + * Things to know + * - IRQ delivery is asynchronous to the PCI bus + * - Blocking the local CPU IRQ via spin locks was too slow + * - The chip has register windows needing locking work + * + * So the path was once (I say once as people appear to have changed it + * in the mean time and it now looks rather bogus if the changes to use + * disable_irq_nosync_irqsave are disabling the local IRQ) + * + * + * Take the page lock + * Mask the IRQ on chip + * Disable the IRQ (but not mask locally- someone seems to have + * broken this with the lock validator stuff) + * [This must be _nosync as the page lock may otherwise + * deadlock us] + * Drop the page lock and turn IRQs back on + * + * At this point an existing IRQ may still be running but we can't + * get a new one + * + * Take the lock (so we know the IRQ has terminated) but don't mask + * the IRQs on the processor + * Set irqlock [for debug] + * + * Transmit (slow as ****) + * + * re-enable the IRQ + * + * + * We have to use disable_irq because otherwise you will get delayed + * interrupts on the APIC bus deadlocking the transmit path. + * + * Quite hairy but the chip simply wasn't designed for SMP and you can't + * even ACK an interrupt without risking corrupting other parallel + * activities on the chip." [lkml, 25 Jul 2007] */ @@ -219,15 +265,6 @@ static void ei_tx_timeout(struct net_device *dev) int txsr, isr, tickssofar = jiffies - dev->trans_start; unsigned long flags; -#if defined(CONFIG_M32R) && defined(CONFIG_SMP) - unsigned long icucr; - - local_irq_save(flags); - icucr = inl(M32R_ICU_CR1_PORTL); - icucr |= M32R_ICUCR_ISMOD11; - outl(icucr, M32R_ICU_CR1_PORTL); - local_irq_restore(flags); -#endif ei_local->stat.tx_errors++; spin_lock_irqsave(&ei_local->page_lock, flags); diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 6ba6ed2..5106c23 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -229,7 +229,12 @@ struct net_device loopback_dev = { /* Setup and register the loopback device. */ static int __init loopback_init(void) { - return register_netdev(&loopback_dev); + int err = register_netdev(&loopback_dev); + + if (err) + panic("loopback: Failed to register netdevice: %d\n", err); + + return err; }; module_init(loopback_init); diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index d0808fa..5b87183 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -255,10 +255,8 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, int err; index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); - if (index == -1) { - err = -ENOMEM; - goto err; - } + if (index == -1) + return -ENOMEM; mr->iova = iova; mr->size = size; @@ -269,15 +267,8 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); if (err) - goto err_index; - - return 0; - -err_index: - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); + mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); -err: - kfree(mr); return err; } EXPORT_SYMBOL_GPL(mlx4_mr_alloc); diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index cfdeaf7..f81d939 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -638,7 +638,6 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = { .get_drvinfo = ne2k_pci_get_drvinfo, .get_tx_csum = ethtool_op_get_tx_csum, .get_sg = ethtool_op_get_sg, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 325269d..d4c92cc 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1179,8 +1179,7 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) printk(KERN_ERR "failed to read dma watchdog status\n"); - return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) && - (netxen_get_dma_watchdog_disabled(ctrl) == 0)); + return (netxen_get_dma_watchdog_enabled(ctrl) == 0); } static inline int diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 0175f6c..a6138b4 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -755,5 +755,4 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .get_strings = netxen_nic_get_strings, .get_stats_count = netxen_nic_get_stats_count, .get_ethtool_stats = netxen_nic_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index b703ccf..08a62ac 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -46,7 +46,7 @@ MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); -char netxen_nic_driver_name[] = "netxen-nic"; +char netxen_nic_driver_name[] = "netxen_nic"; static char netxen_nic_driver_string[] = "NetXen Network Driver version " NETXEN_NIC_LINUX_VERSIONID; @@ -335,7 +335,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ahw.pdev = pdev; adapter->ahw.pci_func = pci_func_id; spin_lock_init(&adapter->tx_lock); - spin_lock_init(&adapter->lock); /* remap phys address */ mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ @@ -640,6 +639,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); /* Handshake with the card before we register the devices. */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + netxen_pinit_from_rom(adapter, 0); + msleep(1); + netxen_load_firmware(adapter); netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); } @@ -782,19 +785,18 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->portnum == 0) { if (init_firmware_done) { - dma_watchdog_shutdown_request(adapter); - msleep(100); i = 100; - while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { - printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + do { + if (dma_watchdog_shutdown_request(adapter) == 1) + break; msleep(100); - i--; - } + if (dma_watchdog_shutdown_poll_result(adapter) == 1) + break; + } while (--i); - if (i == 0) { - printk(KERN_ERR "dma_watchdog_shutdown_request failed\n"); - return; - } + if (i == 0) + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + netdev->name); /* clear the register for future unloads/loads */ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); @@ -803,11 +805,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) /* leave the hw in the same state as reboot */ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - if (netxen_pinit_from_rom(adapter, 0)) - return; + netxen_pinit_from_rom(adapter, 0); msleep(1); - if (netxen_load_firmware(adapter)) - return; + netxen_load_firmware(adapter); netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); } @@ -816,22 +816,21 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) printk(KERN_INFO "State: 0x%0x\n", readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); - dma_watchdog_shutdown_request(adapter); - msleep(100); i = 100; - while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { - printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + do { + if (dma_watchdog_shutdown_request(adapter) == 1) + break; msleep(100); - i--; - } + if (dma_watchdog_shutdown_poll_result(adapter) == 1) + break; + } while (--i); if (i) { netxen_free_adapter_offload(adapter); } else { - printk(KERN_ERR "failed to dma shutdown\n"); - return; + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + netdev->name); } - } iounmap(adapter->ahw.db_base); @@ -895,8 +894,6 @@ static int netxen_nic_open(struct net_device *netdev) /* Done here again so that even if phantom sw overwrote it, * we set it */ - if (adapter->macaddr_set) - adapter->macaddr_set(adapter, netdev->dev_addr); if (adapter->init_port && adapter->init_port(adapter, adapter->portnum) != 0) { del_timer_sync(&adapter->watchdog_timer); @@ -904,6 +901,8 @@ static int netxen_nic_open(struct net_device *netdev) netxen_nic_driver_name, adapter->portnum); return -EIO; } + if (adapter->macaddr_set) + adapter->macaddr_set(adapter, netdev->dev_addr); netxen_nic_set_link_parameters(adapter); @@ -930,6 +929,8 @@ static int netxen_nic_close(struct net_device *netdev) netif_carrier_off(netdev); netif_stop_queue(netdev); + netxen_nic_disable_int(adapter); + cmd_buff = adapter->cmd_buf_arr; for (i = 0; i < adapter->max_tx_desc_count; i++) { buffrag = cmd_buff->frag_array; @@ -1226,15 +1227,12 @@ static void netxen_tx_timeout_task(struct work_struct *work) { struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, tx_timeout_task); - unsigned long flags; printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, adapter->netdev->name); - spin_lock_irqsave(&adapter->lock, flags); netxen_nic_close(adapter->netdev); netxen_nic_open(adapter->netdev); - spin_unlock_irqrestore(&adapter->lock, flags); adapter->netdev->trans_start = jiffies; netif_wake_queue(adapter->netdev); } @@ -1243,28 +1241,12 @@ static int netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) { u32 ret = 0; - u32 our_int = 0; DPRINTK(INFO, "Entered handle ISR\n"); adapter->stats.ints++; - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - /* not our interrupt */ - if ((our_int & (0x80 << adapter->portnum)) == 0) - return ret; - } - netxen_nic_disable_int(adapter); - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { - /* claim interrupt */ - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - writel(our_int & ~((u32)(0x80 << adapter->portnum)), - NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - } - } - if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { if (netif_rx_schedule_prep(netdev)) { /* @@ -1298,6 +1280,7 @@ irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter; struct net_device *netdev; + u32 our_int = 0; if (unlikely(!irq)) { return IRQ_NONE; /* Not our interrupt */ @@ -1305,7 +1288,22 @@ irqreturn_t netxen_intr(int irq, void *data) adapter = (struct netxen_adapter *)data; netdev = adapter->netdev; - /* process our status queue (for all 4 ports) */ + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + /* not our interrupt */ + if ((our_int & (0x80 << adapter->portnum)) == 0) + return IRQ_NONE; + } + + if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { + /* claim interrupt */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + writel(our_int & ~((u32)(0x80 << adapter->portnum)), + NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } + } + if (netif_running(netdev)) netxen_handle_int(adapter, netdev); diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 73da611..997c2d0 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -996,7 +996,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; mace_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; + kio_addr_t ioaddr; int status; int IntrCnt = MACE_MAX_IR_ITERATIONS; @@ -1006,6 +1006,8 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) return IRQ_NONE; } + ioaddr = dev->base_addr; + if (lp->tx_irq_disabled) { printk( (lp->tx_irq_disabled? diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7912dbd..af6728c 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1368,6 +1368,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) kio_addr_t ioaddr = dev->base_addr; u_short num_pages; short time_out, ir; + unsigned long flags; netif_stop_queue(dev); @@ -1395,6 +1396,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* A packet is now waiting. */ smc->packets_waiting++; + spin_lock_irqsave(&smc->lock, flags); SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */ /* need MC_RESET to keep the memory consistent. errata? */ @@ -1411,6 +1413,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Acknowledge the interrupt, send the packet. */ outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT); smc_hardware_send_packet(dev); /* Send the packet now.. */ + spin_unlock_irqrestore(&smc->lock, flags); return 0; } } @@ -1418,6 +1421,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Otherwise defer until the Tx-space-allocated interrupt. */ DEBUG(2, "%s: memory allocation deferred.\n", dev->name); outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT); + spin_unlock_irqrestore(&smc->lock, flags); return 0; } @@ -1523,6 +1527,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, irq, ioaddr); + spin_lock(&smc->lock); smc->watchdog = 0; saved_bank = inw(ioaddr + BANK_SELECT); if ((saved_bank & 0xff00) != 0x3300) { @@ -1620,6 +1625,7 @@ irq_done: readb(smc->base+MEGAHERTZ_ISR); } #endif + spin_unlock(&smc->lock); return IRQ_RETVAL(handled); } @@ -1902,6 +1908,9 @@ static void media_check(u_long arg) kio_addr_t ioaddr = dev->base_addr; u_short i, media, saved_bank; u_short link; + unsigned long flags; + + spin_lock_irqsave(&smc->lock, flags); saved_bank = inw(ioaddr + BANK_SELECT); @@ -1934,6 +1943,7 @@ static void media_check(u_long arg) smc->media.expires = jiffies + HZ/100; add_timer(&smc->media); SMC_SELECT_BANK(saved_bank); + spin_unlock_irqrestore(&smc->lock, flags); return; } @@ -2007,6 +2017,7 @@ reschedule: smc->media.expires = jiffies + HZ; add_timer(&smc->media); SMC_SELECT_BANK(saved_bank); + spin_unlock_irqrestore(&smc->lock, flags); } static int smc_link_ok(struct net_device *dev) @@ -2094,14 +2105,14 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); if (smc->cfg & CFG_MII_SELECT) ret = mii_ethtool_gset(&smc->mii_if, ecmd); else ret = smc_netdev_get_ecmd(dev, ecmd); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } @@ -2112,14 +2123,14 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); if (smc->cfg & CFG_MII_SELECT) ret = mii_ethtool_sset(&smc->mii_if, ecmd); else ret = smc_netdev_set_ecmd(dev, ecmd); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } @@ -2130,11 +2141,11 @@ static u32 smc_get_link(struct net_device *dev) u16 saved_bank = inw(ioaddr + BANK_SELECT); u32 ret; - SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); + SMC_SELECT_BANK(3); ret = smc_link_ok(dev); - spin_unlock_irq(&smc->lock); SMC_SELECT_BANK(saved_bank); + spin_unlock_irq(&smc->lock); return ret; } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 465485a..e6a6753 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1515,7 +1515,6 @@ static const struct ethtool_ops pcnet32_ethtool_ops = { .phys_id = pcnet32_phys_id, .get_regs_len = pcnet32_get_regs_len, .get_regs = pcnet32_get_regs, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* only probes for non-PCI devices, the rest are handled by diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 6a53856..8874497 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -109,7 +109,7 @@ static int vsc824x_config_intr(struct phy_device *phydev) */ err = phy_read(phydev, MII_VSC8244_ISTAT); - if (err) + if (err < 0) return err; err = phy_write(phydev, MII_VSC8244_IMASK, 0); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 6f98834..68631a5 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -108,19 +108,24 @@ static inline int cmp_addr(struct pppoe_addr *a, unsigned long sid, char *addr) (memcmp(a->remote,addr,ETH_ALEN) == 0)); } -static int hash_item(unsigned long sid, unsigned char *addr) +#if 8%PPPOE_HASH_BITS +#error 8 must be a multiple of PPPOE_HASH_BITS +#endif + +static int hash_item(unsigned int sid, unsigned char *addr) { - char hash = 0; - int i, j; + unsigned char hash = 0; + unsigned int i; - for (i = 0; i < ETH_ALEN ; ++i) { - for (j = 0; j < 8/PPPOE_HASH_BITS ; ++j) { - hash ^= addr[i] >> ( j * PPPOE_HASH_BITS ); - } + for (i = 0 ; i < ETH_ALEN ; i++) { + hash ^= addr[i]; + } + for (i = 0 ; i < sizeof(sid_t)*8 ; i += 8 ){ + hash ^= sid>>i; + } + for (i = 8 ; (i>>=1) >= PPPOE_HASH_BITS ; ) { + hash ^= hash>>i; } - - for (i = 0; i < (sizeof(unsigned long)*8) / PPPOE_HASH_BITS ; ++i) - hash ^= sid >> (i*PPPOE_HASH_BITS); return hash & ( PPPOE_HASH_SIZE - 1 ); } @@ -664,8 +669,8 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, { struct sock *sk = sock->sk; struct pppox_sock *po = pppox_sk(sk); - int val = 0; - int err = 0; + int val; + int err; switch (cmd) { case PPPIOCGMRU: @@ -754,8 +759,9 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, err = 0; break; - default:; - }; + default: + err = -ENOTTY; + } return err; } @@ -773,6 +779,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct net_device *dev; char *start; + lock_sock(sk); if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) { error = -ENOTCONN; goto end; @@ -783,8 +790,6 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, hdr.code = 0; hdr.sid = po->num; - lock_sock(sk); - dev = po->pppoe_dev; error = -EMSGSIZE; diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f871760..266e8b3 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -2054,7 +2054,7 @@ end: */ static int pppol2tp_tunnel_getsockopt(struct sock *sk, struct pppol2tp_tunnel *tunnel, - int optname, int __user *val) + int optname, int *val) { int err = 0; @@ -2077,7 +2077,7 @@ static int pppol2tp_tunnel_getsockopt(struct sock *sk, */ static int pppol2tp_session_getsockopt(struct sock *sk, struct pppol2tp_session *session, - int optname, int __user *val) + int optname, int *val) { int err = 0; diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index f3e47d0..25c52b5 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c @@ -73,7 +73,7 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; struct pppox_sock *po = pppox_sk(sk); - int rc = 0; + int rc; lock_sock(sk); @@ -94,12 +94,9 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } default: - if (pppox_protos[sk->sk_protocol]->ioctl) - rc = pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, - arg); - - break; - }; + rc = pppox_protos[sk->sk_protocol]->ioctl ? + pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, arg) : -ENOTTY; + } release_sock(sk); return rc; diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 08d2506..13d1c0a 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -290,7 +290,8 @@ static void gelic_net_release_rx_chain(struct gelic_net_card *card) descr->buf_addr = 0; dev_kfree_skb_any(descr->skb); descr->skb = NULL; - descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE; + gelic_net_set_descr_status(descr, + GELIC_NET_DESCR_NOT_IN_USE); } descr = descr->next; } while (descr != card->rx_chain.head); @@ -374,7 +375,7 @@ static void gelic_net_release_tx_descr(struct gelic_net_card *card, descr->skb = NULL; /* set descr status */ - descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE; + gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); } /** @@ -403,26 +404,29 @@ static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop) "%s: forcing end of tx descriptor " \ "with status %x\n", __func__, status); - card->netdev_stats.tx_dropped++; + card->netdev->stats.tx_dropped++; break; case GELIC_NET_DESCR_COMPLETE: - card->netdev_stats.tx_packets++; - card->netdev_stats.tx_bytes += - tx_chain->tail->skb->len; + if (tx_chain->tail->skb) { + card->netdev->stats.tx_packets++; + card->netdev->stats.tx_bytes += + tx_chain->tail->skb->len; + } break; case GELIC_NET_DESCR_CARDOWNED: /* pending tx request */ default: /* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */ - goto out; + if (!stop) + goto out; } gelic_net_release_tx_descr(card, tx_chain->tail); - release = 1; + release ++; } out: - if (!stop && release) + if (!stop && (2 < release)) netif_wake_queue(card->netdev); } @@ -659,19 +663,21 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, { dma_addr_t buf[2]; unsigned int vlan_len; + struct gelic_net_descr *sec_descr = descr->next; if (skb->len < GELIC_NET_VLAN_POS) return -EINVAL; - memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS); + vlan_len = GELIC_NET_VLAN_POS; + memcpy(&descr->vlan, skb->data, vlan_len); if (card->vlan_index != -1) { + /* internal vlan tag used */ descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/ descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]); - vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */ - } else - vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */ + vlan_len += VLAN_HLEN; /* added for above two lines */ + } - /* first descr */ + /* map data area */ buf[0] = dma_map_single(ctodev(card), &descr->vlan, vlan_len, DMA_TO_DEVICE); @@ -682,20 +688,6 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, return -ENOMEM; } - descr->buf_addr = buf[0]; - descr->buf_size = vlan_len; - descr->skb = skb; /* not used */ - descr->data_status = 0; - gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */ - - /* second descr */ - card->tx_chain.head = card->tx_chain.head->next; - descr->next_descr_addr = descr->next->bus_addr; - descr = descr->next; - if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) - /* XXX will be removed */ - dev_err(ctodev(card), "descr is not free!\n"); - buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS, skb->len - GELIC_NET_VLAN_POS, DMA_TO_DEVICE); @@ -710,13 +702,24 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, return -ENOMEM; } - descr->buf_addr = buf[1]; - descr->buf_size = skb->len - GELIC_NET_VLAN_POS; - descr->skb = skb; + /* first descr */ + descr->buf_addr = buf[0]; + descr->buf_size = vlan_len; + descr->skb = NULL; /* not used */ descr->data_status = 0; - descr->next_descr_addr = 0; /* terminate hw descr */ - gelic_net_set_txdescr_cmdstat(descr, skb, 0); + descr->next_descr_addr = descr->next->bus_addr; + gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */ + /* second descr */ + sec_descr->buf_addr = buf[1]; + sec_descr->buf_size = skb->len - GELIC_NET_VLAN_POS; + sec_descr->skb = skb; + sec_descr->data_status = 0; + sec_descr->next_descr_addr = 0; /* terminate hw descr */ + gelic_net_set_txdescr_cmdstat(sec_descr, skb, 0); + + /* bump free descriptor pointer */ + card->tx_chain.head = sec_descr->next; return 0; } @@ -729,7 +732,7 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, static int gelic_net_kick_txdma(struct gelic_net_card *card, struct gelic_net_descr *descr) { - int status = -ENXIO; + int status = 0; int count = 10; if (card->tx_dma_progress) @@ -763,47 +766,62 @@ static int gelic_net_kick_txdma(struct gelic_net_card *card, static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct gelic_net_card *card = netdev_priv(netdev); - struct gelic_net_descr *descr = NULL; + struct gelic_net_descr *descr; int result; unsigned long flags; spin_lock_irqsave(&card->tx_dma_lock, flags); gelic_net_release_tx_chain(card, 0); - if (!skb) - goto kick; + descr = gelic_net_get_next_tx_descr(card); if (!descr) { + /* + * no more descriptors free + */ netif_stop_queue(netdev); spin_unlock_irqrestore(&card->tx_dma_lock, flags); return NETDEV_TX_BUSY; } - result = gelic_net_prepare_tx_descr_v(card, descr, skb); - - if (result) - goto error; - card->tx_chain.head = card->tx_chain.head->next; - - if (descr->prev) - descr->prev->next_descr_addr = descr->bus_addr; -kick: + result = gelic_net_prepare_tx_descr_v(card, descr, skb); + if (result) { + /* + * DMA map failed. As chanses are that failure + * would continue, just release skb and return + */ + card->netdev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&card->tx_dma_lock, flags); + return NETDEV_TX_OK; + } + /* + * link this prepared descriptor to previous one + * to achieve high performance + */ + descr->prev->next_descr_addr = descr->bus_addr; /* * as hardware descriptor is modified in the above lines, * ensure that the hardware sees it */ wmb(); - if (gelic_net_kick_txdma(card, card->tx_chain.tail)) - goto error; + if (gelic_net_kick_txdma(card, descr)) { + /* + * kick failed. + * release descriptors which were just prepared + */ + card->netdev->stats.tx_dropped++; + gelic_net_release_tx_descr(card, descr); + gelic_net_release_tx_descr(card, descr->next); + card->tx_chain.tail = descr->next->next; + dev_info(ctodev(card), "%s: kick failure\n", __func__); + } else { + /* OK, DMA started/reserved */ + netdev->trans_start = jiffies; + } - netdev->trans_start = jiffies; spin_unlock_irqrestore(&card->tx_dma_lock, flags); return NETDEV_TX_OK; - -error: - card->netdev_stats.tx_dropped++; - spin_unlock_irqrestore(&card->tx_dma_lock, flags); - return NETDEV_TX_LOCKED; } /** @@ -854,8 +872,8 @@ static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, skb->ip_summed = CHECKSUM_NONE; /* update netdevice statistics */ - card->netdev_stats.rx_packets++; - card->netdev_stats.rx_bytes += skb->len; + card->netdev->stats.rx_packets++; + card->netdev->stats.rx_bytes += skb->len; /* pass skb up to stack */ netif_receive_skb(skb); @@ -895,38 +913,67 @@ static int gelic_net_decode_one_descr(struct gelic_net_card *card) (status == GELIC_NET_DESCR_FORCE_END)) { dev_info(ctodev(card), "dropping RX descriptor with state %x\n", status); - card->netdev_stats.rx_dropped++; + card->netdev->stats.rx_dropped++; goto refill; } - if ((status != GELIC_NET_DESCR_COMPLETE) && - (status != GELIC_NET_DESCR_FRAME_END)) { + if (status == GELIC_NET_DESCR_BUFFER_FULL) { + /* + * Buffer full would occur if and only if + * the frame length was longer than the size of this + * descriptor's buffer. If the frame length was equal + * to or shorter than buffer'size, FRAME_END condition + * would occur. + * Anyway this frame was longer than the MTU, + * just drop it. + */ + dev_info(ctodev(card), "overlength frame\n"); + goto refill; + } + /* + * descriptoers any other than FRAME_END here should + * be treated as error. + */ + if (status != GELIC_NET_DESCR_FRAME_END) { dev_dbg(ctodev(card), "RX descriptor with state %x\n", status); goto refill; } /* ok, we've got a packet in descr */ - gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */ - + gelic_net_pass_skb_up(descr, card); refill: - descr->next_descr_addr = 0; /* unlink the descr */ + /* + * So that always DMAC can see the end + * of the descriptor chain to avoid + * from unwanted DMAC overrun. + */ + descr->next_descr_addr = 0; /* change the descriptor state: */ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); - /* refill one desc - * FIXME: this can fail, but for now, just leave this - * descriptor without skb + /* + * this call can fail, but for now, just leave this + * decriptor without skb */ gelic_net_prepare_rx_descr(card, descr); + chain->head = descr; chain->tail = descr->next; + + /* + * Set this descriptor the end of the chain. + */ descr->prev->next_descr_addr = descr->bus_addr; + /* + * If dmac chain was met, DMAC stopped. + * thus re-enable it + */ if (dmac_chain_ended) { - gelic_net_enable_rxdmac(card); - dev_dbg(ctodev(card), "reenable rx dma\n"); + card->rx_dma_restart_required = 1; + dev_dbg(ctodev(card), "reenable rx dma scheduled\n"); } return 1; @@ -968,20 +1015,6 @@ static int gelic_net_poll(struct net_device *netdev, int *budget) } else return 1; } - -/** - * gelic_net_get_stats - get interface statistics - * @netdev: interface device structure - * - * returns the interface statistics residing in the gelic_net_card struct - */ -static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev) -{ - struct gelic_net_card *card = netdev_priv(netdev); - - return &card->netdev_stats; -} - /** * gelic_net_change_mtu - changes the MTU of an interface * @netdev: interface device structure @@ -1016,6 +1049,11 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr) if (!status) return IRQ_NONE; + if (card->rx_dma_restart_required) { + card->rx_dma_restart_required = 0; + gelic_net_enable_rxdmac(card); + } + if (status & GELIC_NET_RXINT) { gelic_net_rx_irq_off(card); netif_rx_schedule(netdev); @@ -1024,9 +1062,10 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr) if (status & GELIC_NET_TXINT) { spin_lock_irqsave(&card->tx_dma_lock, flags); card->tx_dma_progress = 0; + gelic_net_release_tx_chain(card, 0); + /* kick outstanding tx descriptor if any */ + gelic_net_kick_txdma(card, card->tx_chain.tail); spin_unlock_irqrestore(&card->tx_dma_lock, flags); - /* start pending DMA */ - gelic_net_xmit(NULL, netdev); } return IRQ_HANDLED; } @@ -1068,7 +1107,7 @@ static int gelic_net_open_device(struct gelic_net_card *card) } result = request_irq(card->netdev->irq, gelic_net_interrupt, - IRQF_DISABLED, "gelic network", card->netdev); + IRQF_DISABLED, card->netdev->name, card->netdev); if (result) { dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n", @@ -1107,7 +1146,7 @@ static int gelic_net_open(struct net_device *netdev) card->descr, GELIC_NET_TX_DESCRIPTORS)) goto alloc_tx_failed; if (gelic_net_init_chain(card, &card->rx_chain, - card->descr + GELIC_NET_RX_DESCRIPTORS, + card->descr + GELIC_NET_TX_DESCRIPTORS, GELIC_NET_RX_DESCRIPTORS)) goto alloc_rx_failed; @@ -1129,7 +1168,6 @@ static int gelic_net_open(struct net_device *netdev) netif_start_queue(netdev); netif_carrier_on(netdev); - netif_poll_enable(netdev); return 0; @@ -1141,7 +1179,6 @@ alloc_tx_failed: return -ENOMEM; } -#ifdef GELIC_NET_ETHTOOL static void gelic_net_get_drvinfo (struct net_device *netdev, struct ethtool_drvinfo *info) { @@ -1261,7 +1298,6 @@ static struct ethtool_ops gelic_net_ethtool_ops = { .get_rx_csum = gelic_net_get_rx_csum, .set_rx_csum = gelic_net_set_rx_csum, }; -#endif /** * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout @@ -1320,7 +1356,6 @@ static void gelic_net_setup_netdev_ops(struct net_device *netdev) netdev->open = &gelic_net_open; netdev->stop = &gelic_net_stop; netdev->hard_start_xmit = &gelic_net_xmit; - netdev->get_stats = &gelic_net_get_stats; netdev->set_multicast_list = &gelic_net_set_multi; netdev->change_mtu = &gelic_net_change_mtu; /* tx watchdog */ @@ -1329,9 +1364,7 @@ static void gelic_net_setup_netdev_ops(struct net_device *netdev) /* NAPI */ netdev->poll = &gelic_net_poll; netdev->weight = GELIC_NET_NAPI_WEIGHT; -#ifdef GELIC_NET_ETHTOOL netdev->ethtool_ops = &gelic_net_ethtool_ops; -#endif } /** diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index 5e1c286..a9c4c4f 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h @@ -28,21 +28,12 @@ #ifndef _GELIC_NET_H #define _GELIC_NET_H -#define GELIC_NET_DRV_NAME "Gelic Network Driver" -#define GELIC_NET_DRV_VERSION "1.0" - -#define GELIC_NET_ETHTOOL /* use ethtool */ - -/* ioctl */ -#define GELIC_NET_GET_MODE (SIOCDEVPRIVATE + 0) -#define GELIC_NET_SET_MODE (SIOCDEVPRIVATE + 1) - /* descriptors */ #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ -#define GELIC_NET_MAX_MTU 2308 -#define GELIC_NET_MIN_MTU 64 +#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN +#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN #define GELIC_NET_RXBUF_ALIGN 128 #define GELIC_NET_RX_CSUM_DEFAULT 1 /* hw chksum */ #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ @@ -90,7 +81,8 @@ enum gelic_net_int1_status { */ #define GELIC_NET_RXVLNPKT 0x00200000 /* VLAN packet */ /* bit 20..16 reserved */ -#define GELIC_NET_RXRECNUM 0x0000ff00 /* reception receipt number */ +#define GELIC_NET_RXRRECNUM 0x0000ff00 /* reception receipt number */ +#define GELIC_NET_RXRRECNUM_SHIFT 8 /* bit 7..0 reserved */ #define GELIC_NET_TXDESC_TAIL 0 @@ -133,19 +125,19 @@ enum gelic_net_int1_status { * interrupt status */ #define GELIC_NET_DMAC_CMDSTAT_CHAIN_END 0x00000002 /* RXDCEIS:DMA stopped */ -#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000 #define GELIC_NET_DESCR_IND_PROC_SHIFT 28 #define GELIC_NET_DESCR_IND_PROC_MASKO 0x0fffffff enum gelic_net_descr_status { - GELIC_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */ + GELIC_NET_DESCR_COMPLETE = 0x00, /* used in tx */ + GELIC_NET_DESCR_BUFFER_FULL = 0x00, /* used in rx */ GELIC_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */ GELIC_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */ GELIC_NET_DESCR_FRAME_END = 0x04, /* used in rx */ GELIC_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */ GELIC_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */ - GELIC_NET_DESCR_NOT_IN_USE /* any other value */ + GELIC_NET_DESCR_NOT_IN_USE = 0x0b /* any other value */ }; /* for lv1_net_control */ #define GELIC_NET_GET_MAC_ADDRESS 0x0000000000000001 @@ -216,10 +208,10 @@ struct gelic_net_card { struct gelic_net_descr_chain tx_chain; struct gelic_net_descr_chain rx_chain; + int rx_dma_restart_required; /* gurad dmac descriptor chain*/ spinlock_t chain_lock; - struct net_device_stats netdev_stats; int rx_csum; /* guard tx_dma_progress */ spinlock_t tx_dma_lock; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 8be8be4..69da95b 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1904,7 +1904,6 @@ static void ql_get_pauseparam(struct net_device *ndev, static const struct ethtool_ops ql3xxx_ethtool_ops = { .get_settings = ql_get_settings, .get_drvinfo = ql_get_drvinfo, - .get_perm_addr = ethtool_op_get_perm_addr, .get_link = ethtool_op_get_link, .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index bb6896a..c9333b9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1066,7 +1066,6 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .get_strings = rtl8169_get_strings, .get_stats_count = rtl8169_get_stats_count, .get_ethtool_stats = rtl8169_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 4cb710b..cfa2679 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -747,10 +747,9 @@ struct XENA_dev_config { #define MC_ERR_REG_MIRI_CRI_ERR_1 BIT(23) #define MC_ERR_REG_SM_ERR BIT(31) #define MC_ERR_REG_ECC_ALL_SNG (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\ - BIT(6) | BIT(7) | BIT(17) | BIT(19)) + BIT(17) | BIT(19)) #define MC_ERR_REG_ECC_ALL_DBL (BIT(10) | BIT(11) | BIT(12) |\ - BIT(13) | BIT(14) | BIT(15) |\ - BIT(18) | BIT(20)) + BIT(13) | BIT(18) | BIT(20)) u64 mc_err_mask; u64 mc_err_alarm; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index afef6c0..2be0a0f 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -32,12 +32,12 @@ * rx_ring_sz: This defines the number of receive blocks each ring can have. * This is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid - * values are 1, 2 and 3. + * values are 1, 2. * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. * tx_fifo_len: This too is an array of 8. Each element defines the number of * Tx descriptors that can be associated with each corresponding FIFO. * intr_type: This defines the type of interrupt. The values can be 0(INTA), - * 1(MSI), 2(MSI_X). Default value is '0(INTA)' + * 2(MSI_X). Default value is '0(INTA)' * lro: Specifies whether to enable Large Receive Offload (LRO) or not. * Possible values '1' for enable '0' for disable. Default is '0' * lro_max_pkts: This parameter defines maximum number of packets can be @@ -84,14 +84,14 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.23.1" +#define DRV_VERSION "2.0.25.1" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; static char s2io_driver_version[] = DRV_VERSION; -static int rxd_size[4] = {32,48,48,64}; -static int rxd_count[4] = {127,85,85,63}; +static int rxd_size[2] = {32,48}; +static int rxd_count[2] = {127,85}; static inline int RXD_IS_UP2DT(struct RxD_t *rxdp) { @@ -282,6 +282,7 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = { ("lro_flush_due_to_max_pkts"), ("lro_avg_aggr_pkts"), ("mem_alloc_fail_cnt"), + ("pci_map_fail_cnt"), ("watchdog_timer_cnt"), ("mem_allocated"), ("mem_freed"), @@ -426,7 +427,7 @@ S2IO_PARM_INT(bimodal, 0); S2IO_PARM_INT(l3l4hdr_size, 128); /* Frequency of Rx desc syncs expressed as power of 2 */ S2IO_PARM_INT(rxsync_frequency, 3); -/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ +/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */ S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ S2IO_PARM_INT(lro, 0); @@ -701,7 +702,7 @@ static int init_shared_mem(struct s2io_nic *nic) (u64) tmp_p_addr_next; } } - if (nic->rxd_mode >= RXD_MODE_3A) { + if (nic->rxd_mode == RXD_MODE_3B) { /* * Allocation of Storages for buffer addresses in 2BUFF mode * and the buffers as well. @@ -870,7 +871,7 @@ static void free_shared_mem(struct s2io_nic *nic) } } - if (nic->rxd_mode >= RXD_MODE_3A) { + if (nic->rxd_mode == RXD_MODE_3B) { /* Freeing buffer storage addresses in 2BUFF mode. */ for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = config->rx_cfg[i].num_rxd / @@ -2233,44 +2234,6 @@ static void stop_nic(struct s2io_nic *nic) writeq(val64, &bar0->adapter_control); } -static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \ - sk_buff *skb) -{ - struct net_device *dev = nic->dev; - struct sk_buff *frag_list; - void *tmp; - - /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = pci_map_single - (nic->pdev, skb->data, l3l4hdr_size + 4, - PCI_DMA_FROMDEVICE); - - /* skb_shinfo(skb)->frag_list will have L4 data payload */ - skb_shinfo(skb)->frag_list = dev_alloc_skb(dev->mtu + ALIGN_SIZE); - if (skb_shinfo(skb)->frag_list == NULL) { - nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; - DBG_PRINT(INFO_DBG, "%s: dev_alloc_skb failed\n ", dev->name); - return -ENOMEM ; - } - frag_list = skb_shinfo(skb)->frag_list; - skb->truesize += frag_list->truesize; - nic->mac_control.stats_info->sw_stat.mem_allocated - += frag_list->truesize; - frag_list->next = NULL; - tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1); - frag_list->data = tmp; - skb_reset_tail_pointer(frag_list); - - /* Buffer-2 receives L4 data payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev, - frag_list->data, dev->mtu, - PCI_DMA_FROMDEVICE); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); - - return SUCCESS; -} - /** * fill_rx_buffers - Allocates the Rx side skbs * @nic: device private variable @@ -2307,6 +2270,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) unsigned long flags; struct RxD_t *first_rxdp = NULL; u64 Buffer0_ptr = 0, Buffer1_ptr = 0; + struct RxD1 *rxdp1; + struct RxD3 *rxdp3; + struct swStat *stats = &nic->mac_control.stats_info->sw_stat; mac_control = &nic->mac_control; config = &nic->config; @@ -2359,7 +2325,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; } if ((rxdp->Control_1 & RXD_OWN_XENA) && - ((nic->rxd_mode >= RXD_MODE_3A) && + ((nic->rxd_mode == RXD_MODE_3B) && (rxdp->Control_2 & BIT(0)))) { mac_control->rings[ring_no].rx_curr_put_info. offset = off; @@ -2370,10 +2336,8 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) HEADER_802_2_SIZE + HEADER_SNAP_SIZE; if (nic->rxd_mode == RXD_MODE_1) size += NET_IP_ALIGN; - else if (nic->rxd_mode == RXD_MODE_3B) - size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; else - size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; + size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; /* allocate skb */ skb = dev_alloc_skb(size); @@ -2392,33 +2356,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) += skb->truesize; if (nic->rxd_mode == RXD_MODE_1) { /* 1 buffer mode - normal operation mode */ + rxdp1 = (struct RxD1*)rxdp; memset(rxdp, 0, sizeof(struct RxD1)); skb_reserve(skb, NET_IP_ALIGN); - ((struct RxD1*)rxdp)->Buffer0_ptr = pci_map_single + rxdp1->Buffer0_ptr = pci_map_single (nic->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == + DMA_ERROR_CODE)) + goto pci_map_failed; + rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); - } else if (nic->rxd_mode >= RXD_MODE_3A) { + } else if (nic->rxd_mode == RXD_MODE_3B) { /* - * 2 or 3 buffer mode - - * Both 2 buffer mode and 3 buffer mode provides 128 + * 2 buffer mode - + * 2 buffer mode provides 128 * byte aligned receive buffers. - * - * 3 buffer mode provides header separation where in - * skb->data will have L3/L4 headers where as - * skb_shinfo(skb)->frag_list will have the L4 data - * payload */ + rxdp3 = (struct RxD3*)rxdp; /* save buffer pointers to avoid frequent dma mapping */ - Buffer0_ptr = ((struct RxD3*)rxdp)->Buffer0_ptr; - Buffer1_ptr = ((struct RxD3*)rxdp)->Buffer1_ptr; + Buffer0_ptr = rxdp3->Buffer0_ptr; + Buffer1_ptr = rxdp3->Buffer1_ptr; memset(rxdp, 0, sizeof(struct RxD3)); /* restore the buffer pointers for dma sync*/ - ((struct RxD3*)rxdp)->Buffer0_ptr = Buffer0_ptr; - ((struct RxD3*)rxdp)->Buffer1_ptr = Buffer1_ptr; + rxdp3->Buffer0_ptr = Buffer0_ptr; + rxdp3->Buffer1_ptr = Buffer1_ptr; ba = &mac_control->rings[ring_no].ba[block_no][off]; skb_reserve(skb, BUF0_LEN); @@ -2428,14 +2394,18 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb_reset_tail_pointer(skb); - if (!(((struct RxD3*)rxdp)->Buffer0_ptr)) - ((struct RxD3*)rxdp)->Buffer0_ptr = + if (!(rxdp3->Buffer0_ptr)) + rxdp3->Buffer0_ptr = pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); else pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr, + (dma_addr_t) rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) + goto pci_map_failed; + rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2444,33 +2414,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) * Buffer2 will have L3/L4 header plus * L4 payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single + rxdp3->Buffer2_ptr = pci_map_single (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer. Not used */ - if (!(((struct RxD3*)rxdp)->Buffer1_ptr)) { - ((struct RxD3*)rxdp)->Buffer1_ptr = + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) + goto pci_map_failed; + + rxdp3->Buffer1_ptr = pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + pci_unmap_single + (nic->pdev, + (dma_addr_t)skb->data, + dev->mtu + 4, + PCI_DMA_FROMDEVICE); + goto pci_map_failed; } rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); - } else { - /* 3 buffer mode */ - if (fill_rxd_3buf(nic, rxdp, skb) == -ENOMEM) { - nic->mac_control.stats_info->sw_stat.\ - mem_freed += skb->truesize; - dev_kfree_skb_irq(skb); - if (first_rxdp) { - wmb(); - first_rxdp->Control_1 |= - RXD_OWN_XENA; - } - return -ENOMEM ; - } } rxdp->Control_2 |= BIT(0); } @@ -2505,6 +2472,11 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) } return SUCCESS; +pci_map_failed: + stats->pci_map_fail_cnt++; + stats->mem_freed += skb->truesize; + dev_kfree_skb_irq(skb); + return -ENOMEM; } static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) @@ -2515,6 +2487,8 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) struct RxD_t *rxdp; struct mac_info *mac_control; struct buffAdd *ba; + struct RxD1 *rxdp1; + struct RxD3 *rxdp3; mac_control = &sp->mac_control; for (j = 0 ; j < rxd_count[sp->rxd_mode]; j++) { @@ -2526,40 +2500,30 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) continue; } if (sp->rxd_mode == RXD_MODE_1) { + rxdp1 = (struct RxD1*)rxdp; pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, - dev->mtu + - HEADER_ETHERNET_II_802_3_SIZE - + HEADER_802_2_SIZE + - HEADER_SNAP_SIZE, - PCI_DMA_FROMDEVICE); + rxdp1->Buffer0_ptr, + dev->mtu + + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + + HEADER_SNAP_SIZE, + PCI_DMA_FROMDEVICE); memset(rxdp, 0, sizeof(struct RxD1)); } else if(sp->rxd_mode == RXD_MODE_3B) { + rxdp3 = (struct RxD3*)rxdp; ba = &mac_control->rings[ring_no]. ba[blk][j]; pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, - BUF0_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - BUF1_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu + 4, - PCI_DMA_FROMDEVICE); - memset(rxdp, 0, sizeof(struct RxD3)); - } else { - pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, + rxdp3->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - l3l4hdr_size + 4, + rxdp3->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, dev->mtu, + rxdp3->Buffer2_ptr, + dev->mtu + 4, PCI_DMA_FROMDEVICE); memset(rxdp, 0, sizeof(struct RxD3)); } @@ -2756,6 +2720,8 @@ static void rx_intr_handler(struct ring_info *ring_data) struct sk_buff *skb; int pkt_cnt = 0; int i; + struct RxD1* rxdp1; + struct RxD3* rxdp3; spin_lock(&nic->rx_lock); if (atomic_read(&nic->card_state) == CARD_DOWN) { @@ -2796,32 +2762,23 @@ static void rx_intr_handler(struct ring_info *ring_data) return; } if (nic->rxd_mode == RXD_MODE_1) { + rxdp1 = (struct RxD1*)rxdp; pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, - dev->mtu + - HEADER_ETHERNET_II_802_3_SIZE + - HEADER_802_2_SIZE + - HEADER_SNAP_SIZE, - PCI_DMA_FROMDEVICE); + rxdp1->Buffer0_ptr, + dev->mtu + + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + + HEADER_SNAP_SIZE, + PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { + rxdp3 = (struct RxD3*)rxdp; pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, - BUF0_LEN, PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu + 4, - PCI_DMA_FROMDEVICE); - } else { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, - PCI_DMA_FROMDEVICE); - pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, - l3l4hdr_size + 4, - PCI_DMA_FROMDEVICE); + rxdp3->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, - dev->mtu, PCI_DMA_FROMDEVICE); + rxdp3->Buffer2_ptr, + dev->mtu + 4, + PCI_DMA_FROMDEVICE); } prefetch(skb->data); rx_osm_handler(ring_data, rxdp); @@ -3425,23 +3382,8 @@ static void s2io_reset(struct s2io_nic * sp) /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); - if (sp->device_type == XFRAME_II_DEVICE) { - int ret; - ret = pci_set_power_state(sp->pdev, 3); - if (!ret) - ret = pci_set_power_state(sp->pdev, 0); - else { - DBG_PRINT(ERR_DBG,"%s PME based SW_Reset failed!\n", - __FUNCTION__); - goto old_way; - } - msleep(20); - goto new_way; - } -old_way: val64 = SW_RESET_ALL; writeq(val64, &bar0->sw_reset); -new_way: if (strstr(sp->product_name, "CX4")) { msleep(750); } @@ -3731,56 +3673,6 @@ static void store_xmsi_data(struct s2io_nic *nic) } } -int s2io_enable_msi(struct s2io_nic *nic) -{ - struct XENA_dev_config __iomem *bar0 = nic->bar0; - u16 msi_ctrl, msg_val; - struct config_param *config = &nic->config; - struct net_device *dev = nic->dev; - u64 val64, tx_mat, rx_mat; - int i, err; - - val64 = readq(&bar0->pic_control); - val64 &= ~BIT(1); - writeq(val64, &bar0->pic_control); - - err = pci_enable_msi(nic->pdev); - if (err) { - DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n", - nic->dev->name); - return err; - } - - /* - * Enable MSI and use MSI-1 in stead of the standard MSI-0 - * for interrupt handling. - */ - pci_read_config_word(nic->pdev, 0x4c, &msg_val); - msg_val ^= 0x1; - pci_write_config_word(nic->pdev, 0x4c, msg_val); - pci_read_config_word(nic->pdev, 0x4c, &msg_val); - - pci_read_config_word(nic->pdev, 0x42, &msi_ctrl); - msi_ctrl |= 0x10; - pci_write_config_word(nic->pdev, 0x42, msi_ctrl); - - /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */ - tx_mat = readq(&bar0->tx_mat0_n[0]); - for (i=0; i<config->tx_fifo_num; i++) { - tx_mat |= TX_MAT_SET(i, 1); - } - writeq(tx_mat, &bar0->tx_mat0_n[0]); - - rx_mat = readq(&bar0->rx_mat); - for (i=0; i<config->rx_ring_num; i++) { - rx_mat |= RX_MAT_SET(i, 1); - } - writeq(rx_mat, &bar0->rx_mat); - - dev->irq = nic->pdev->irq; - return 0; -} - static int s2io_enable_msi_x(struct s2io_nic *nic) { struct XENA_dev_config __iomem *bar0 = nic->bar0; @@ -4001,6 +3893,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) struct mac_info *mac_control; struct config_param *config; int offload_type; + struct swStat *stats = &sp->mac_control.stats_info->sw_stat; mac_control = &sp->mac_control; config = &sp->config; @@ -4085,11 +3978,18 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Buffer_Pointer = pci_map_single(sp->pdev, sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + goto pci_map_failed; txdp++; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + goto pci_map_failed; + txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); if (offload_type == SKB_GSO_UDP) @@ -4146,6 +4046,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sp->tx_lock, flags); return 0; +pci_map_failed: + stats->pci_map_fail_cnt++; + netif_stop_queue(dev); + stats->mem_freed += skb->truesize; + dev_kfree_skb(skb); + spin_unlock_irqrestore(&sp->tx_lock, flags); + return 0; } static void @@ -4186,39 +4093,6 @@ static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) return 0; } -static irqreturn_t s2io_msi_handle(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct s2io_nic *sp = dev->priv; - int i; - struct mac_info *mac_control; - struct config_param *config; - - atomic_inc(&sp->isr_cnt); - mac_control = &sp->mac_control; - config = &sp->config; - DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__); - - /* If Intr is because of Rx Traffic */ - for (i = 0; i < config->rx_ring_num; i++) - rx_intr_handler(&mac_control->rings[i]); - - /* If Intr is because of Tx Traffic */ - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); - - /* - * If the Rx buffer count is below the panic threshold then - * reallocate the buffers from the interrupt handler itself, - * else schedule a tasklet to reallocate the buffers. - */ - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); - - atomic_dec(&sp->isr_cnt); - return IRQ_HANDLED; -} - static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) { struct ring_info *ring = (struct ring_info *)dev_id; @@ -4927,19 +4801,17 @@ static void s2io_ethtool_gringparam(struct net_device *dev, ering->rx_max_pending = MAX_RX_DESC_1; else if (sp->rxd_mode == RXD_MODE_3B) ering->rx_max_pending = MAX_RX_DESC_2; - else if (sp->rxd_mode == RXD_MODE_3A) - ering->rx_max_pending = MAX_RX_DESC_3; ering->tx_max_pending = MAX_TX_DESC; - for (i = 0 ; i < sp->config.tx_fifo_num ; i++) { + for (i = 0 ; i < sp->config.tx_fifo_num ; i++) tx_desc_count += sp->config.tx_cfg[i].fifo_len; - } + DBG_PRINT(INFO_DBG,"\nmax txds : %d\n",sp->config.max_txds); ering->tx_pending = tx_desc_count; rx_desc_count = 0; - for (i = 0 ; i < sp->config.rx_ring_num ; i++) { + for (i = 0 ; i < sp->config.rx_ring_num ; i++) rx_desc_count += sp->config.rx_cfg[i].num_rxd; - } + ering->rx_pending = rx_desc_count; ering->rx_mini_max_pending = 0; @@ -5923,6 +5795,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev, else tmp_stats[i++] = 0; tmp_stats[i++] = stat_info->sw_stat.mem_alloc_fail_cnt; + tmp_stats[i++] = stat_info->sw_stat.pci_map_fail_cnt; tmp_stats[i++] = stat_info->sw_stat.watchdog_timer_cnt; tmp_stats[i++] = stat_info->sw_stat.mem_allocated; tmp_stats[i++] = stat_info->sw_stat.mem_freed; @@ -6266,9 +6139,10 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, u64 *temp2, int size) { struct net_device *dev = sp->dev; - struct sk_buff *frag_list; + struct swStat *stats = &sp->mac_control.stats_info->sw_stat; if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) { + struct RxD1 *rxdp1 = (struct RxD1 *)rxdp; /* allocate skb */ if (*skb) { DBG_PRINT(INFO_DBG, "SKB is not NULL\n"); @@ -6277,7 +6151,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * using same mapped address for the Rxd * buffer pointer */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0; + rxdp1->Buffer0_ptr = *temp0; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -6294,18 +6168,23 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * such it will be used for next rxd whose * Host Control is NULL */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0 = + rxdp1->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, (*skb)->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) { + goto memalloc_failed; + } rxdp->Host_Control = (unsigned long) (*skb); } } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { + struct RxD3 *rxdp3 = (struct RxD3 *)rxdp; /* Two buffer Mode */ if (*skb) { - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; + rxdp3->Buffer2_ptr = *temp2; + rxdp3->Buffer0_ptr = *temp0; + rxdp3->Buffer1_ptr = *temp1; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -6318,73 +6197,47 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, } sp->mac_control.stats_info->sw_stat.mem_allocated += (*skb)->truesize; - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = + rxdp3->Buffer2_ptr = *temp2 = pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) { + goto memalloc_failed; + } + rxdp3->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) { + pci_unmap_single (sp->pdev, + (dma_addr_t)(*skb)->data, + dev->mtu + 4, PCI_DMA_FROMDEVICE); + goto memalloc_failed; + } rxdp->Host_Control = (unsigned long) (*skb); /* Buffer-1 will be dummy buffer not used */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = + rxdp3->Buffer1_ptr = *temp1 = pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); - } - } else if ((rxdp->Host_Control == 0)) { - /* Three buffer mode */ - if (*skb) { - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; - } else { - *skb = dev_alloc_skb(size); - if (!(*skb)) { - DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name); - DBG_PRINT(INFO_DBG, "memory to allocate "); - DBG_PRINT(INFO_DBG, "3 buf mode SKBs\n"); - sp->mac_control.stats_info->sw_stat. \ - mem_alloc_fail_cnt++; - return -ENOMEM; - } - sp->mac_control.stats_info->sw_stat.mem_allocated - += (*skb)->truesize; - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = - pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, - PCI_DMA_FROMDEVICE); - /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = - pci_map_single( sp->pdev, (*skb)->data, - l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); - /* - * skb_shinfo(skb)->frag_list will have L4 - * data payload - */ - skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu + - ALIGN_SIZE); - if (skb_shinfo(*skb)->frag_list == NULL) { - DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \ - failed\n ", dev->name); - sp->mac_control.stats_info->sw_stat. \ - mem_alloc_fail_cnt++; - return -ENOMEM ; + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + pci_unmap_single (sp->pdev, + (dma_addr_t)(*skb)->data, + dev->mtu + 4, PCI_DMA_FROMDEVICE); + goto memalloc_failed; } - frag_list = skb_shinfo(*skb)->frag_list; - frag_list->next = NULL; - sp->mac_control.stats_info->sw_stat.mem_allocated - += frag_list->truesize; - /* - * Buffer-2 receives L4 data payload - */ - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = - pci_map_single( sp->pdev, frag_list->data, - dev->mtu, PCI_DMA_FROMDEVICE); } } return 0; + memalloc_failed: + stats->pci_map_fail_cnt++; + stats->mem_freed += (*skb)->truesize; + dev_kfree_skb(*skb); + return -ENOMEM; } + static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, int size) { @@ -6395,10 +6248,6 @@ static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4); - } else { - rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); } } @@ -6420,8 +6269,6 @@ static int rxd_owner_bit_reset(struct s2io_nic *sp) size += NET_IP_ALIGN; else if (sp->rxd_mode == RXD_MODE_3B) size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; - else - size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = config->rx_cfg[i].num_rxd / @@ -6431,7 +6278,7 @@ static int rxd_owner_bit_reset(struct s2io_nic *sp) for (k = 0; k < rxd_count[sp->rxd_mode]; k++) { rxdp = mac_control->rings[i]. rx_blocks[j].rxds[k].virt_addr; - if(sp->rxd_mode >= RXD_MODE_3A) + if(sp->rxd_mode == RXD_MODE_3B) ba = &mac_control->rings[i].ba[j][k]; if (set_rxd_buffer_pointer(sp, rxdp, ba, &skb,(u64 *)&temp0_64, @@ -6458,9 +6305,7 @@ static int s2io_add_isr(struct s2io_nic * sp) struct net_device *dev = sp->dev; int err = 0; - if (sp->intr_type == MSI) - ret = s2io_enable_msi(sp); - else if (sp->intr_type == MSI_X) + if (sp->intr_type == MSI_X) ret = s2io_enable_msi_x(sp); if (ret) { DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name); @@ -6471,16 +6316,6 @@ static int s2io_add_isr(struct s2io_nic * sp) store_xmsi_data(sp); /* After proper initialization of H/W, register ISR */ - if (sp->intr_type == MSI) { - err = request_irq((int) sp->pdev->irq, s2io_msi_handle, - IRQF_SHARED, sp->name, dev); - if (err) { - pci_disable_msi(sp->pdev); - DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n", - dev->name); - return -1; - } - } if (sp->intr_type == MSI_X) { int i, msix_tx_cnt=0,msix_rx_cnt=0; @@ -6567,14 +6402,6 @@ static void s2io_rem_isr(struct s2io_nic * sp) pci_disable_msix(sp->pdev); } else { free_irq(sp->pdev->irq, dev); - if (sp->intr_type == MSI) { - u16 val; - - pci_disable_msi(sp->pdev); - pci_read_config_word(sp->pdev, 0x4c, &val); - val ^= 0x1; - pci_write_config_word(sp->pdev, 0x4c, val); - } } /* Waiting till all Interrupt handlers are complete */ cnt = 0; @@ -6907,6 +6734,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) } /* Updating statistics */ + sp->stats.rx_packets++; rxdp->Host_Control = 0; if (sp->rxd_mode == RXD_MODE_1) { int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2); @@ -6914,7 +6742,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) sp->stats.rx_bytes += len; skb_put(skb, len); - } else if (sp->rxd_mode >= RXD_MODE_3A) { + } else if (sp->rxd_mode == RXD_MODE_3B) { int get_block = ring_data->rx_curr_get_info.block_index; int get_off = ring_data->rx_curr_get_info.offset; int buf0_len = RXD_GET_BUFFER0_SIZE_3(rxdp->Control_2); @@ -6924,18 +6752,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) struct buffAdd *ba = &ring_data->ba[get_block][get_off]; sp->stats.rx_bytes += buf0_len + buf2_len; memcpy(buff, ba->ba_0, buf0_len); - - if (sp->rxd_mode == RXD_MODE_3A) { - int buf1_len = RXD_GET_BUFFER1_SIZE_3(rxdp->Control_2); - - skb_put(skb, buf1_len); - skb->len += buf2_len; - skb->data_len += buf2_len; - skb_put(skb_shinfo(skb)->frag_list, buf2_len); - sp->stats.rx_bytes += buf1_len; - - } else - skb_put(skb, buf2_len); + skb_put(skb, buf2_len); } if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) || @@ -7131,7 +6948,7 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) *dev_intr_type = INTA; } #else - if (*dev_intr_type > MSI_X) { + if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " "Defaulting to INTA\n"); *dev_intr_type = INTA; @@ -7145,10 +6962,10 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) *dev_intr_type = INTA; } - if (rx_ring_mode > 3) { + if ((rx_ring_mode != 1) && (rx_ring_mode != 2)) { DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n"); - DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n"); - rx_ring_mode = 3; + DBG_PRINT(ERR_DBG, "s2io: Defaulting to 1-buffer mode\n"); + rx_ring_mode = 1; } return SUCCESS; } @@ -7240,28 +7057,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) pci_disable_device(pdev); return -ENOMEM; } - if (dev_intr_type != MSI_X) { - if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"); - pci_disable_device(pdev); - return -ENODEV; - } - } - else { - if (!(request_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), s2io_driver_name))) { - DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n"); - pci_disable_device(pdev); - return -ENODEV; - } - if (!(request_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2), s2io_driver_name))) { - DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n"); - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - pci_disable_device(pdev); - return -ENODEV; - } + if ((ret = pci_request_regions(pdev, s2io_driver_name))) { + DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __FUNCTION__, ret); + pci_disable_device(pdev); + return -ENODEV; } dev = alloc_etherdev(sizeof(struct s2io_nic)); @@ -7288,8 +7087,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) sp->rxd_mode = RXD_MODE_1; if (rx_ring_mode == 2) sp->rxd_mode = RXD_MODE_3B; - if (rx_ring_mode == 3) - sp->rxd_mode = RXD_MODE_3A; sp->intr_type = dev_intr_type; @@ -7565,10 +7362,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n", dev->name); break; - case RXD_MODE_3A: - DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n", - dev->name); - break; } if (napi) @@ -7577,9 +7370,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) case INTA: DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name); break; - case MSI: - DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name); - break; case MSI_X: DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name); break; @@ -7619,14 +7409,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) mem_alloc_failed: free_shared_mem(sp); pci_disable_device(pdev); - if (dev_intr_type != MSI_X) - pci_release_regions(pdev); - else { - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - } + pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); @@ -7661,14 +7444,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) free_shared_mem(sp); iounmap(sp->bar0); iounmap(sp->bar1); - if (sp->intr_type != MSI_X) - pci_release_regions(pdev); - else { - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - } + pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); pci_disable_device(pdev); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 3887fe6..92983ee 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -74,6 +74,10 @@ static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, args...) if(!(debug_level<dbg_level)) printk(args) +#ifndef DMA_ERROR_CODE +#define DMA_ERROR_CODE (~(dma_addr_t)0x0) +#endif + /* Protocol assist features of the NIC */ #define L3_CKSUM_OK 0xFFFF #define L4_CKSUM_OK 0xFFFF @@ -97,6 +101,7 @@ struct swStat { unsigned long long num_aggregations; /* Other statistics */ unsigned long long mem_alloc_fail_cnt; + unsigned long long pci_map_fail_cnt; unsigned long long watchdog_timer_cnt; unsigned long long mem_allocated; unsigned long long mem_freed; @@ -575,8 +580,7 @@ struct RxD_block { #define SIZE_OF_BLOCK 4096 #define RXD_MODE_1 0 /* One Buffer mode */ -#define RXD_MODE_3A 1 /* Three Buffer mode */ -#define RXD_MODE_3B 2 /* Two Buffer mode */ +#define RXD_MODE_3B 1 /* Two Buffer mode */ /* Structure to hold virtual addresses of Buf0 and Buf1 in * 2buf mode. */ @@ -876,7 +880,6 @@ struct s2io_nic { u16 lro_max_aggr_per_sess; #define INTA 0 -#define MSI 1 #define MSI_X 2 u8 intr_type; @@ -1020,8 +1023,6 @@ static int s2io_poll(struct net_device *dev, int *budget); static void s2io_init_pci(struct s2io_nic * sp); static int s2io_set_mac_addr(struct net_device *dev, u8 * addr); static void s2io_alarm_handle(unsigned long data); -static int s2io_enable_msi(struct s2io_nic *nic); -static irqreturn_t s2io_msi_handle(int irq, void *dev_id); static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id); static irqreturn_t diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 5b7284c..872cb1c 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1402,7 +1402,6 @@ static struct ethtool_ops sc92031_ethtool_ops = { .get_strings = sc92031_ethtool_get_strings, .get_stats_count = sc92031_ethtool_get_stats_count, .get_ethtool_stats = sc92031_ethtool_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, .get_ufo = ethtool_op_get_ufo, }; diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c index efc639c..ea85de9 100644 --- a/drivers/net/skfp/pmf.c +++ b/drivers/net/skfp/pmf.c @@ -575,7 +575,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para, int sp_len ; /* - * skip if errror + * skip if error */ if (pcon->pc_err) return ; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 7766929..e3d8520 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -821,7 +821,6 @@ static const struct ethtool_ops skge_ethtool_ops = { .phys_id = skge_phys_id, .get_stats_count = skge_get_stats_count, .get_ethtool_stats = skge_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; /* diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 13f08a3..e7a2ead 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3548,7 +3548,6 @@ static const struct ethtool_ops sky2_ethtool_ops = { .phys_id = sky2_phys_id, .get_stats_count = sky2_get_stats_count, .get_ethtool_stats = sky2_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; #ifdef CONFIG_SKY2_DEBUG diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index af0c983..a8f2af8 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1586,7 +1586,6 @@ static const struct ethtool_ops ethtool_ops = { .get_link = get_link, .get_msglevel = get_msglevel, .set_msglevel = set_msglevel, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 053b7cb..68e4f66 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -99,8 +99,7 @@ static char lancestr[] = "LANCE"; #include <asm/byteorder.h> /* Used by the checksum routines */ #include <asm/idprom.h> #include <asm/sbus.h> -#include <asm/openprom.h> -#include <asm/oplib.h> +#include <asm/prom.h> #include <asm/auxio.h> /* For tpe-link-test? setting */ #include <asm/irq.h> @@ -1326,6 +1325,7 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, struct sbus_dev *lebuffer) { static unsigned version_printed; + struct device_node *dp = sdev->ofdev.node; struct net_device *dev; struct lance_private *lp; int i; @@ -1389,54 +1389,46 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, lp->rx = lance_rx_dvma; lp->tx = lance_tx_dvma; } - lp->busmaster_regval = prom_getintdefault(sdev->prom_node, - "busmaster-regval", - (LE_C3_BSWP | LE_C3_ACON | - LE_C3_BCON)); + lp->busmaster_regval = of_getintprop_default(dp, "busmaster-regval", + (LE_C3_BSWP | + LE_C3_ACON | + LE_C3_BCON)); lp->name = lancestr; lp->ledma = ledma; lp->burst_sizes = 0; if (lp->ledma) { - char prop[6]; + struct device_node *ledma_dp = ledma->sdev->ofdev.node; + const char *prop; unsigned int sbmask; u32 csr; /* Find burst-size property for ledma */ - lp->burst_sizes = prom_getintdefault(ledma->sdev->prom_node, - "burst-sizes", 0); + lp->burst_sizes = of_getintprop_default(ledma_dp, + "burst-sizes", 0); /* ledma may be capable of fast bursts, but sbus may not. */ - sbmask = prom_getintdefault(ledma->sdev->bus->prom_node, - "burst-sizes", DMA_BURSTBITS); + sbmask = of_getintprop_default(ledma_dp, "burst-sizes", + DMA_BURSTBITS); lp->burst_sizes &= sbmask; /* Get the cable-selection property */ - memset(prop, 0, sizeof(prop)); - prom_getstring(ledma->sdev->prom_node, "cable-selection", - prop, sizeof(prop)); - if (prop[0] == 0) { - int topnd, nd; + prop = of_get_property(ledma_dp, "cable-selection", NULL); + if (!prop || prop[0] == '\0') { + struct device_node *nd; - printk(KERN_INFO "SunLance: using auto-carrier-detection.\n"); + printk(KERN_INFO "SunLance: using " + "auto-carrier-detection.\n"); - /* Is this found at /options .attributes in all - * Prom versions? XXX - */ - topnd = prom_getchild(prom_root_node); - - nd = prom_searchsiblings(topnd, "options"); + nd = of_find_node_by_path("/options"); if (!nd) goto no_link_test; - if (!prom_node_has_property(nd, "tpe-link-test?")) + prop = of_get_property(nd, "tpe-link-test?", NULL); + if (!prop) goto no_link_test; - memset(prop, 0, sizeof(prop)); - prom_getstring(nd, "tpe-link-test?", prop, - sizeof(prop)); - if (strcmp(prop, "true")) { printk(KERN_NOTICE "SunLance: warning: overriding option " "'tpe-link-test?'\n"); diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 61f9825..ff1028a 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -906,7 +906,6 @@ static const struct ethtool_ops vnet_ethtool_ops = { .get_msglevel = vnet_get_msglevel, .set_msglevel = vnet_set_msglevel, .get_link = ethtool_op_get_link, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void vnet_port_free_tx_bufs(struct vnet_port *port) diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 7f94ca9..ec41469 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -2198,7 +2198,6 @@ static const struct ethtool_ops tc35815_ethtool_ops = { .get_strings = tc35815_get_strings, .get_stats_count = tc35815_get_stats_count, .get_ethtool_stats = tc35815_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 887b9a5..dc41c05 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9294,7 +9294,6 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_ethtool_stats = tg3_get_ethtool_stats, .get_coalesce = tg3_get_coalesce, .set_coalesce = tg3_set_coalesce, - .get_perm_addr = ethtool_op_get_perm_addr, }; static void __devinit tg3_get_eeprom_size(struct tg3 *tp) diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index f87d769..eca984f 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1471,14 +1471,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, sa_offset = 2; /* Grrr, damn Matrox boards. */ multiport_cnt = 4; } -#ifdef CONFIG_DDB5477 - if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) { - /* DDB5477 MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif #ifdef CONFIG_MIPS_COBALT if ((pdev->bus->number == 0) && ((PCI_SLOT(pdev->devfn) == 7) || diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e4736a3..12e01b2 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -43,10 +43,6 @@ #undef DEBUG -#define DRV_DESC "QE UCC Gigabit Ethernet Controller" -#define DRV_NAME "ucc_geth" -#define DRV_VERSION "1.1" - #define ugeth_printk(level, format, arg...) \ printk(level format "\n", ## arg) @@ -64,9 +60,19 @@ #else #define ugeth_vdbg(fmt, args...) do { } while (0) #endif /* UGETH_VERBOSE_DEBUG */ +#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 +void uec_set_ethtool_ops(struct net_device *netdev); + static DEFINE_SPINLOCK(ugeth_lock); +static struct { + u32 msg_enable; +} debug = { -1 }; + +module_param_named(debug, debug.msg_enable, int, 0); +MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)"); + static struct ucc_geth_info ugeth_primary_info = { .uf_info = { .bd_mem_part = MEM_PART_SYSTEM, @@ -104,6 +110,7 @@ static struct ucc_geth_info ugeth_primary_info = { .maxRetransmission = 0xf, .collisionWindow = 0x37, .receiveFlowControl = 1, + .transmitFlowControl = 1, .maxGroupAddrInHash = 4, .maxIndAddrInHash = 4, .prel = 7, @@ -139,7 +146,9 @@ static struct ucc_geth_info ugeth_primary_info = { .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, .largestexternallookupkeysize = QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, - .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE, + .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE | + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX | + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX, .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, @@ -281,7 +290,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth, for (i = 0; i < num_entries; i++) { if ((snum = qe_get_snum()) < 0) { - ugeth_err("fill_init_enet_entries: Can not get SNUM."); + if (netif_msg_ifup(ugeth)) + ugeth_err("fill_init_enet_entries: Can not get SNUM."); return snum; } if ((i == 0) && skip_page_for_first_entry) @@ -291,8 +301,8 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth, init_enet_offset = qe_muram_alloc(thread_size, thread_alignment); if (IS_ERR_VALUE(init_enet_offset)) { - ugeth_err - ("fill_init_enet_entries: Can not allocate DPRAM memory."); + if (netif_msg_ifup(ugeth)) + ugeth_err("fill_init_enet_entries: Can not allocate DPRAM memory."); qe_put_snum((u8) snum); return -ENOMEM; } @@ -1200,7 +1210,7 @@ static int init_inter_frame_gap_params(u8 non_btb_cs_ipg, return 0; } -static int init_flow_control_params(u32 automatic_flow_control_mode, +int init_flow_control_params(u32 automatic_flow_control_mode, int rx_flow_control_enable, int tx_flow_control_enable, u16 pause_period, @@ -1486,9 +1496,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); if (ret_val != 0) { - ugeth_err - ("%s: Preamble length must be between 3 and 7 inclusive.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Preamble length must be between 3 and 7 inclusive.", + __FUNCTION__); return ret_val; } @@ -1726,7 +1736,8 @@ static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); return -EINVAL; } @@ -1754,7 +1765,8 @@ static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode) /* check if the UCC number is in range. */ if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); return -EINVAL; } @@ -2306,7 +2318,9 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || (uf_info->bd_mem_part == MEM_PART_MURAM))) { - ugeth_err("%s: Bad memory partition value.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Bad memory partition value.", + __FUNCTION__); return -EINVAL; } @@ -2315,9 +2329,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || (ug_info->bdRingLenRx[i] % UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { - ugeth_err - ("%s: Rx BD ring length must be multiple of 4," - " no smaller than 8.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: Rx BD ring length must be multiple of 4, no smaller than 8.", + __FUNCTION__); return -EINVAL; } } @@ -2325,9 +2340,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* Tx BD lengths */ for (i = 0; i < ug_info->numQueuesTx; i++) { if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { - ugeth_err - ("%s: Tx BD ring length must be no smaller than 2.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: Tx BD ring length must be no smaller than 2.", + __FUNCTION__); return -EINVAL; } } @@ -2335,31 +2351,35 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* mrblr */ if ((uf_info->max_rx_buf_length == 0) || (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { - ugeth_err - ("%s: max_rx_buf_length must be non-zero multiple of 128.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: max_rx_buf_length must be non-zero multiple of 128.", + __FUNCTION__); return -EINVAL; } /* num Tx queues */ if (ug_info->numQueuesTx > NUM_TX_QUEUES) { - ugeth_err("%s: number of tx queues too large.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: number of tx queues too large.", __FUNCTION__); return -EINVAL; } /* num Rx queues */ if (ug_info->numQueuesRx > NUM_RX_QUEUES) { - ugeth_err("%s: number of rx queues too large.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: number of rx queues too large.", __FUNCTION__); return -EINVAL; } /* l2qt */ for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: VLAN priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: VLAN priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); return -EINVAL; } } @@ -2367,26 +2387,29 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) /* l3qt */ for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: IP priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err + ("%s: IP priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); return -EINVAL; } } if (ug_info->cam && !ug_info->ecamptr) { - ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", + __FUNCTION__); return -EINVAL; } if ((ug_info->numStationAddresses != UCC_GETH_NUM_OF_STATION_ADDRESSES_1) && ug_info->rxExtendedFiltering) { - ugeth_err("%s: Number of station addresses greater than 1 " - "not allowed in extended parsing mode.", - __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Number of station addresses greater than 1 " + "not allowed in extended parsing mode.", + __FUNCTION__); return -EINVAL; } @@ -2399,7 +2422,8 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); /* Initialize the general fast UCC block. */ if (ucc_fast_init(uf_info, &ugeth->uccf)) { - ugeth_err("%s: Failed to init uccf.", __FUNCTION__); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Failed to init uccf.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2452,7 +2476,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) numThreadsRxNumerical = 8; break; default: - ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Bad number of Rx threads value.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2475,7 +2501,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) numThreadsTxNumerical = 8; break; default: - ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Bad number of Tx threads value.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; break; @@ -2507,7 +2535,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* For more details see the hardware spec. */ init_flow_control_params(ug_info->aufc, ug_info->receiveFlowControl, - 1, + ug_info->transmitFlowControl, ug_info->pausePeriod, ug_info->extensionField, &uf_regs->upsmr, @@ -2527,8 +2555,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->backToBackInterFrameGap, &ug_regs->ipgifg); if (ret_val != 0) { - ugeth_err("%s: IPGIFG initialization parameter too large.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: IPGIFG initialization parameter too large.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -2544,7 +2573,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) ug_info->collisionWindow, &ug_regs->hafdup); if (ret_val != 0) { - ugeth_err("%s: Half Duplex initialization parameter too large.", + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Half Duplex initialization parameter too large.", __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; @@ -2597,9 +2627,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) tx_bd_ring_offset[j]); } if (!ugeth->p_tx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Tx bd rings.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for Tx bd rings.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2632,9 +2663,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) rx_bd_ring_offset[j]); } if (!ugeth->p_rx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Rx bd rings.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for Rx bd rings.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2648,8 +2680,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) GFP_KERNEL); if (ugeth->tx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate tx_skbuff", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Could not allocate tx_skbuff", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2679,8 +2712,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) GFP_KERNEL); if (ugeth->rx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate rx_skbuff", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Could not allocate rx_skbuff", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2711,9 +2745,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2733,9 +2768,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) 32 * (numThreadsTxNumerical == 1), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2761,9 +2797,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_send_queue_qd), UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2804,9 +2841,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_scheduler), UCC_GETH_SCHEDULER_ALIGNMENT); if (IS_ERR_VALUE(ugeth->scheduler_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_scheduler.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_scheduler.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2852,9 +2890,11 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) (struct ucc_geth_tx_firmware_statistics_pram), UCC_GETH_TX_STATISTICS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_tx_fw_statistics_pram.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_tx_fw_statistics_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2891,9 +2931,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2912,9 +2953,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_thread_data_rx), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2935,9 +2977,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) (struct ucc_geth_rx_firmware_statistics_pram), UCC_GETH_RX_STATISTICS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_fw_statistics_pram.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_fw_statistics_pram.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -2957,9 +3000,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_irq_coalescing_tbl.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_irq_coalescing_tbl.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3025,9 +3069,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_rx_prefetched_bds)), UCC_GETH_RX_BD_QUEUES_ALIGNMENT); if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3102,8 +3147,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* initialize extended filtering */ if (ug_info->rxExtendedFiltering) { if (!ug_info->extendedFilteringChainPointer) { - ugeth_err("%s: Null Extended Filtering Chain Pointer.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Null Extended Filtering Chain Pointer.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3114,9 +3160,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_exf_glbl_param.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_exf_glbl_param.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3161,9 +3208,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) */ if (!(ugeth->p_init_enet_param_shadow = kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { - ugeth_err - ("%s: Can not allocate memory for" - " p_UccInitEnetParamShadows.", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate memory for" + " p_UccInitEnetParamShadows.", __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3196,8 +3244,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) && (ug_info->largestexternallookupkeysize != QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { - ugeth_err("%s: Invalid largest External Lookup Key Size.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Invalid largest External Lookup Key Size.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -EINVAL; } @@ -3222,8 +3271,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Rx needs one extra for terminator */ , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, ug_info->riscRx, 1)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3237,8 +3287,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) sizeof(struct ucc_geth_thread_tx_pram), UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, ug_info->riscTx, 0)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3246,8 +3297,9 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Load Rx bds with buffers */ for (i = 0; i < ug_info->numQueuesRx; i++) { if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { - ugeth_err("%s: Can not fill Rx bds with buffers.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Can not fill Rx bds with buffers.", + __FUNCTION__); ucc_geth_memclean(ugeth); return ret_val; } @@ -3256,9 +3308,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Allocate InitEnet command parameter structure */ init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); if (IS_ERR_VALUE(init_enet_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", - __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err + ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", + __FUNCTION__); ucc_geth_memclean(ugeth); return -ENOMEM; } @@ -3428,8 +3481,9 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit if (!skb || (!(bd_status & (R_F | R_L))) || (bd_status & R_ERRORS_FATAL)) { - ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x", - __FUNCTION__, __LINE__, (u32) skb); + if (netif_msg_rx_err(ugeth)) + ugeth_err("%s, %d: ERROR!!! skb - 0x%08x", + __FUNCTION__, __LINE__, (u32) skb); if (skb) dev_kfree_skb_any(skb); @@ -3458,7 +3512,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit skb = get_new_skb(ugeth, bd); if (!skb) { - ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); + if (netif_msg_rx_err(ugeth)) + ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); ugeth->stats.rx_dropped++; break; } @@ -3649,28 +3704,32 @@ static int ucc_geth_open(struct net_device *dev) /* Test station address */ if (dev->dev_addr[0] & ENET_GROUP_ADDR) { - ugeth_err("%s: Multicast address used for station address" - " - is this what you wanted?", __FUNCTION__); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Multicast address used for station address" + " - is this what you wanted?", __FUNCTION__); return -EINVAL; } err = ucc_struct_init(ugeth); if (err) { - ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name); return err; } err = ucc_geth_startup(ugeth); if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); return err; } err = adjust_enet_interface(ugeth); if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); return err; } @@ -3687,7 +3746,8 @@ static int ucc_geth_open(struct net_device *dev) err = init_phy(dev); if (err) { - ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot initialize PHY, aborting.", dev->name); return err; } @@ -3697,15 +3757,17 @@ static int ucc_geth_open(struct net_device *dev) request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, "UCC Geth", dev); if (err) { - ugeth_err("%s: Cannot get IRQ for net device, aborting.", - dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot get IRQ for net device, aborting.", + dev->name); ucc_geth_stop(ugeth); return err; } err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); if (err) { - ugeth_err("%s: Cannot enable net device, aborting.", dev->name); + if (netif_msg_ifup(ugeth)) + ugeth_err("%s: Cannot enable net device, aborting.", dev->name); ucc_geth_stop(ugeth); return err; } @@ -3732,8 +3794,6 @@ static int ucc_geth_close(struct net_device *dev) return 0; } -const struct ethtool_ops ucc_geth_ethtool_ops = { }; - static phy_interface_t to_phy_interface(const char *phy_connection_type) { if (strcasecmp(phy_connection_type, "mii") == 0) @@ -3790,6 +3850,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma return -ENODEV; ug_info = &ugeth_info[ucc_num]; + if (ug_info == NULL) { + if (netif_msg_probe(&debug)) + ugeth_err("%s: [%d] Missing additional data!", + __FUNCTION__, ucc_num); + return -ENODEV; + } + ug_info->uf_info.ucc_num = ucc_num; prop = of_get_property(np, "rx-clock", NULL); @@ -3868,15 +3935,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->mdio_bus = res.start; - printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", - ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, - ug_info->uf_info.irq); - - if (ug_info == NULL) { - ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__, - ucc_num); - return -ENODEV; - } + if (netif_msg_probe(&debug)) + printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", + ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, + ug_info->uf_info.irq); /* Create an ethernet device instance */ dev = alloc_etherdev(sizeof(*ugeth)); @@ -3896,6 +3958,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma SET_NETDEV_DEV(dev, device); /* Fill in the dev structure */ + uec_set_ethtool_ops(dev); dev->open = ucc_geth_open; dev->hard_start_xmit = ucc_geth_start_xmit; dev->tx_timeout = ucc_geth_timeout; @@ -3909,16 +3972,16 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma // dev->change_mtu = ucc_geth_change_mtu; dev->mtu = 1500; dev->set_multicast_list = ucc_geth_set_multi; - dev->ethtool_ops = &ucc_geth_ethtool_ops; - ugeth->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; + ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); ugeth->phy_interface = phy_interface; ugeth->max_speed = max_speed; err = register_netdev(dev); if (err) { - ugeth_err("%s: Cannot register net device, aborting.", - dev->name); + if (netif_msg_probe(ugeth)) + ugeth_err("%s: Cannot register net device, aborting.", + dev->name); free_netdev(dev); return err; } @@ -3972,7 +4035,8 @@ static int __init ucc_geth_init(void) if (ret) return ret; - printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); + if (netif_msg_drv(&debug)) + printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); for (i = 0; i < 8; i++) memcpy(&(ugeth_info[i]), &ugeth_primary_info, sizeof(ugeth_primary_info)); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index a29e1c3..bb4dac8 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -30,6 +30,10 @@ #include "ucc_geth_mii.h" +#define DRV_DESC "QE UCC Gigabit Ethernet Controller" +#define DRV_NAME "ucc_geth" +#define DRV_VERSION "1.1" + #define NUM_TX_QUEUES 8 #define NUM_RX_QUEUES 8 #define NUM_BDS_IN_PREFETCHED_BDS 4 @@ -896,6 +900,7 @@ struct ucc_geth_hardware_statistics { #define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX 8 #define UCC_GETH_RX_BD_RING_SIZE_MIN 8 #define UCC_GETH_TX_BD_RING_SIZE_MIN 2 +#define UCC_GETH_BD_RING_SIZE_MAX 0xffff #define UCC_GETH_SIZE_OF_BD QE_SIZEOF_BD @@ -1135,6 +1140,7 @@ struct ucc_geth_info { int bro; int ecm; int receiveFlowControl; + int transmitFlowControl; u8 maxGroupAddrInHash; u8 maxIndAddrInHash; u8 prel; diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c new file mode 100644 index 0000000..a8994c7 --- /dev/null +++ b/drivers/net/ucc_geth_ethtool.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2007 Freescale Semiconductor, Inc. All rights reserved. + * + * Description: QE UCC Gigabit Ethernet Ethtool API Set + * + * Author: Li Yang <leoli@freescale.com> + * + * Limitation: + * Can only get/set setttings of the first queue. + * Need to re-open the interface manually after changing some paramters. + * + * 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 the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/stddef.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/fsl_devices.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/phy.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> +#include <asm/types.h> +#include <asm/uaccess.h> + +#include "ucc_geth.h" +#include "ucc_geth_mii.h" + +static char hw_stat_gstrings[][ETH_GSTRING_LEN] = { + "tx-64-frames", + "tx-65-127-frames", + "tx-128-255-frames", + "rx-64-frames", + "rx-65-127-frames", + "rx-128-255-frames", + "tx-bytes-ok", + "tx-pause-frames", + "tx-multicast-frames", + "tx-broadcast-frames", + "rx-frames", + "rx-bytes-ok", + "rx-bytes-all", + "rx-multicast-frames", + "rx-broadcast-frames", + "stats-counter-carry", + "stats-counter-mask", + "rx-dropped-frames", +}; + +static char tx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { + "tx-single-collision", + "tx-multiple-collision", + "tx-late-collsion", + "tx-aborted-frames", + "tx-lost-frames", + "tx-carrier-sense-errors", + "tx-frames-ok", + "tx-excessive-differ-frames", + "tx-256-511-frames", + "tx-1024-1518-frames", + "tx-jumbo-frames", +}; + +static char rx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { + "rx-crc-errors", + "rx-alignment-errors", + "rx-in-range-length-errors", + "rx-out-of-range-length-errors", + "rx-too-long-frames", + "rx-runt", + "rx-very-long-event", + "rx-symbol-errors", + "rx-busy-drop-frames", + "reserved", + "reserved", + "rx-mismatch-drop-frames", + "rx-small-than-64", + "rx-256-511-frames", + "rx-512-1023-frames", + "rx-1024-1518-frames", + "rx-jumbo-frames", + "rx-mac-error-loss", + "rx-pause-frames", + "reserved", + "rx-vlan-removed", + "rx-vlan-replaced", + "rx-vlan-inserted", + "rx-ip-checksum-errors", +}; + +#define UEC_HW_STATS_LEN ARRAY_SIZE(hw_stat_gstrings) +#define UEC_TX_FW_STATS_LEN ARRAY_SIZE(tx_fw_stat_gstrings) +#define UEC_RX_FW_STATS_LEN ARRAY_SIZE(rx_fw_stat_gstrings) + +extern int init_flow_control_params(u32 automatic_flow_control_mode, + int rx_flow_control_enable, + int tx_flow_control_enable, u16 pause_period, + u16 extension_field, volatile u32 *upsmr_register, + volatile u32 *uempr_register, volatile u32 *maccfg1_register); + +static int +uec_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct phy_device *phydev = ugeth->phydev; + struct ucc_geth_info *ug_info = ugeth->ug_info; + + if (!phydev) + return -ENODEV; + + ecmd->maxtxpkt = 1; + ecmd->maxrxpkt = ug_info->interruptcoalescingmaxvalue[0]; + + return phy_ethtool_gset(phydev, ecmd); +} + +static int +uec_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct phy_device *phydev = ugeth->phydev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_sset(phydev, ecmd); +} + +static void +uec_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + + pause->autoneg = ugeth->phydev->autoneg; + + if (ugeth->ug_info->receiveFlowControl) + pause->rx_pause = 1; + if (ugeth->ug_info->transmitFlowControl) + pause->tx_pause = 1; +} + +static int +uec_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + int ret = 0; + + ugeth->ug_info->receiveFlowControl = pause->rx_pause; + ugeth->ug_info->transmitFlowControl = pause->tx_pause; + + if (ugeth->phydev->autoneg) { + if (netif_running(netdev)) { + /* FIXME: automatically restart */ + printk(KERN_INFO + "Please re-open the interface.\n"); + } + } else { + struct ucc_geth_info *ug_info = ugeth->ug_info; + + ret = init_flow_control_params(ug_info->aufc, + ug_info->receiveFlowControl, + ug_info->transmitFlowControl, + ug_info->pausePeriod, + ug_info->extensionField, + &ugeth->uccf->uf_regs->upsmr, + &ugeth->ug_regs->uempr, + &ugeth->ug_regs->maccfg1); + } + + return ret; +} + +static uint32_t +uec_get_msglevel(struct net_device *netdev) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + return ugeth->msg_enable; +} + +static void +uec_set_msglevel(struct net_device *netdev, uint32_t data) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + ugeth->msg_enable = data; +} + +static int +uec_get_regs_len(struct net_device *netdev) +{ + return sizeof(struct ucc_geth); +} + +static void +uec_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + int i; + struct ucc_geth_private *ugeth = netdev_priv(netdev); + u32 __iomem *ug_regs = (u32 __iomem *)ugeth->ug_regs; + u32 *buff = p; + + for (i = 0; i < sizeof(struct ucc_geth) / sizeof(u32); i++) + buff[i] = in_be32(&ug_regs[i]); +} + +static void +uec_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct ucc_geth_info *ug_info = ugeth->ug_info; + int queue = 0; + + ring->rx_max_pending = UCC_GETH_BD_RING_SIZE_MAX; + ring->rx_mini_max_pending = UCC_GETH_BD_RING_SIZE_MAX; + ring->rx_jumbo_max_pending = UCC_GETH_BD_RING_SIZE_MAX; + ring->tx_max_pending = UCC_GETH_BD_RING_SIZE_MAX; + + ring->rx_pending = ug_info->bdRingLenRx[queue]; + ring->rx_mini_pending = ug_info->bdRingLenRx[queue]; + ring->rx_jumbo_pending = ug_info->bdRingLenRx[queue]; + ring->tx_pending = ug_info->bdRingLenTx[queue]; +} + +static int +uec_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct ucc_geth_info *ug_info = ugeth->ug_info; + int queue = 0, ret = 0; + + if (ring->rx_pending < UCC_GETH_RX_BD_RING_SIZE_MIN) { + printk("%s: RxBD ring size must be no smaller than %d.\n", + netdev->name, UCC_GETH_RX_BD_RING_SIZE_MIN); + return -EINVAL; + } + if (ring->rx_pending % UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT) { + printk("%s: RxBD ring size must be multiple of %d.\n", + netdev->name, UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT); + return -EINVAL; + } + if (ring->tx_pending < UCC_GETH_TX_BD_RING_SIZE_MIN) { + printk("%s: TxBD ring size must be no smaller than %d.\n", + netdev->name, UCC_GETH_TX_BD_RING_SIZE_MIN); + return -EINVAL; + } + + ug_info->bdRingLenRx[queue] = ring->rx_pending; + ug_info->bdRingLenTx[queue] = ring->tx_pending; + + if (netif_running(netdev)) { + /* FIXME: restart automatically */ + printk(KERN_INFO + "Please re-open the interface.\n"); + } + + return ret; +} + +static int uec_get_stats_count(struct net_device *netdev) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + u32 stats_mode = ugeth->ug_info->statisticsMode; + int len = 0; + + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) + len += UEC_HW_STATS_LEN; + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) + len += UEC_TX_FW_STATS_LEN; + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) + len += UEC_RX_FW_STATS_LEN; + + return len; +} + +static void uec_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + u32 stats_mode = ugeth->ug_info->statisticsMode; + + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { + memcpy(buf, hw_stat_gstrings, UEC_HW_STATS_LEN * + ETH_GSTRING_LEN); + buf += UEC_HW_STATS_LEN * ETH_GSTRING_LEN; + } + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { + memcpy(buf, tx_fw_stat_gstrings, UEC_TX_FW_STATS_LEN * + ETH_GSTRING_LEN); + buf += UEC_TX_FW_STATS_LEN * ETH_GSTRING_LEN; + } + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) + memcpy(buf, tx_fw_stat_gstrings, UEC_RX_FW_STATS_LEN * + ETH_GSTRING_LEN); +} + +static void uec_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + u32 stats_mode = ugeth->ug_info->statisticsMode; + u32 __iomem *base; + int i, j = 0; + + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { + base = (u32 __iomem *)&ugeth->ug_regs->tx64; + for (i = 0; i < UEC_HW_STATS_LEN; i++) + data[j++] = (u64)in_be32(&base[i]); + } + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { + base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; + for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) + data[j++] = (u64)in_be32(&base[i]); + } + if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { + base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; + for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) + data[j++] = (u64)in_be32(&base[i]); + } +} + +static int uec_nway_reset(struct net_device *netdev) +{ + struct ucc_geth_private *ugeth = netdev_priv(netdev); + + return phy_start_aneg(ugeth->phydev); +} + +/* Report driver information */ +static void +uec_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + strncpy(drvinfo->driver, DRV_NAME, 32); + strncpy(drvinfo->version, DRV_VERSION, 32); + strncpy(drvinfo->fw_version, "N/A", 32); + strncpy(drvinfo->bus_info, "QUICC ENGINE", 32); + drvinfo->n_stats = uec_get_stats_count(netdev); + drvinfo->testinfo_len = 0; + drvinfo->eedump_len = 0; + drvinfo->regdump_len = uec_get_regs_len(netdev); +} + +static const struct ethtool_ops uec_ethtool_ops = { + .get_settings = uec_get_settings, + .set_settings = uec_set_settings, + .get_drvinfo = uec_get_drvinfo, + .get_regs_len = uec_get_regs_len, + .get_regs = uec_get_regs, + .get_msglevel = uec_get_msglevel, + .set_msglevel = uec_set_msglevel, + .nway_reset = uec_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = uec_get_ringparam, + .set_ringparam = uec_set_ringparam, + .get_pauseparam = uec_get_pauseparam, + .set_pauseparam = uec_set_pauseparam, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .get_stats_count = uec_get_stats_count, + .get_strings = uec_get_strings, + .get_ethtool_stats = uec_get_ethtool_stats, + .get_perm_addr = ethtool_op_get_perm_addr, +}; + +void uec_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &uec_ethtool_ops); +} diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index 7bcb82f..5f8c2d3 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c @@ -54,8 +54,8 @@ #define vdbg(format, arg...) do {} while(0) #endif -#define DRV_DESC "QE UCC Ethernet Controller MII Bus" -#define DRV_NAME "fsl-uec_mdio" +#define MII_DRV_DESC "QE UCC Ethernet Controller MII Bus" +#define MII_DRV_NAME "fsl-uec_mdio" /* Write value to the PHY for this device to the register at regnum, */ /* waiting until the write is done before it returns. All PHY */ @@ -261,7 +261,7 @@ static struct of_device_id uec_mdio_match[] = { }; static struct of_platform_driver uec_mdio_driver = { - .name = DRV_NAME, + .name = MII_DRV_NAME, .probe = uec_mdio_probe, .remove = uec_mdio_remove, .match_table = uec_mdio_match, diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index a05fd97..04cba6b 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -768,11 +768,13 @@ done: static void write_bulk_callback(struct urb *urb) { pegasus_t *pegasus = urb->context; - struct net_device *net = pegasus->net; + struct net_device *net; if (!pegasus) return; + net = pegasus->net; + if (!netif_device_present(net) || !netif_running(net)) return; diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index f51c2c1..c3fe230 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1805,7 +1805,6 @@ static const struct ethtool_ops netdev_ethtool_ops = { .set_wol = rhine_set_wol, .get_sg = ethtool_op_get_sg, .get_tx_csum = ethtool_op_get_tx_csum, - .get_perm_addr = ethtool_op_get_perm_addr, }; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index f331843..93574ad 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1613,7 +1613,7 @@ static void velocity_error(struct velocity_info *vptr, int status) if (status & ISR_TXSTLI) { struct mac_regs __iomem * regs = vptr->mac_regs; - printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(®s->TDIdx[0])); + printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(®s->TDIdx[0])); BYTE_REG_BITS_ON(TXESR_TDSTR, ®s->TXESR); writew(TRDCSR_RUN, ®s->TDCSRClr); netif_stop_queue(vptr->dev); diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 5d58ad5..e2be840 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -3445,7 +3445,6 @@ static void __exit parport_pc_exit(void) pnp_unregister_driver (&parport_pc_pnp_driver); platform_driver_unregister(&parport_pc_platform_driver); - spin_lock(&ports_lock); while (!list_empty(&ports_list)) { struct parport_pc_private *priv; struct parport *port; @@ -3455,11 +3454,8 @@ static void __exit parport_pc_exit(void) if (port->dev && port->dev->bus == &platform_bus_type) platform_device_unregister( to_platform_device(port->dev)); - spin_unlock(&ports_lock); parport_pc_unregister_port(port); - spin_lock(&ports_lock); } - spin_unlock(&ports_lock); } MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c806249..5c6a5d0 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -220,6 +220,7 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) } EXPORT_SYMBOL(pci_osc_control_set); +#ifdef CONFIG_ACPI_SLEEP /* * _SxD returns the D-state with the highest power * (lowest D-state number) supported in the S-state "x". @@ -245,16 +246,34 @@ EXPORT_SYMBOL(pci_osc_control_set); * currently we simply return _SxD, if present. */ -static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state) +static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev, + pm_message_t state) { - /* TBD */ - - return -ENODEV; + int acpi_state; + + acpi_state = acpi_pm_device_sleep_state(&pdev->dev, + device_may_wakeup(&pdev->dev), NULL); + if (acpi_state < 0) + return PCI_POWER_ERROR; + + switch (acpi_state) { + case ACPI_STATE_D0: + return PCI_D0; + case ACPI_STATE_D1: + return PCI_D1; + case ACPI_STATE_D2: + return PCI_D2; + case ACPI_STATE_D3: + return PCI_D3hot; + } + return PCI_POWER_ERROR; } +#endif static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); + acpi_handle tmp; static int state_conv[] = { [0] = 0, [1] = 1, @@ -266,6 +285,9 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) if (!handle) return -ENODEV; + /* If the ACPI device has _EJ0, ignore the device */ + if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) + return 0; return acpi_bus_set_power(handle, acpi_state); } @@ -320,7 +342,9 @@ static int __init acpi_pci_init(void) ret = register_acpi_bus_type(&acpi_pci_bus); if (ret) return 0; +#ifdef CONFIG_ACPI_SLEEP platform_pci_choose_state = acpi_pci_choose_state; +#endif platform_pci_set_power_state = acpi_pci_set_power_state; return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 03fd59e..1ee9cd9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -499,7 +499,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) return 0; } -int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); +pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); /** * pci_choose_state - Choose the power state of a PCI device @@ -513,15 +513,15 @@ int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { - int ret; + pci_power_t ret; if (!pci_find_capability(dev, PCI_CAP_ID_PM)) return PCI_D0; if (platform_pci_choose_state) { ret = platform_pci_choose_state(dev, state); - if (ret >= 0) - state.event = ret; + if (ret != PCI_POWER_ERROR) + return ret; } switch (state.event) { @@ -1517,7 +1517,7 @@ EXPORT_SYMBOL(pcie_get_readrq); /** * pcie_set_readrq - set PCI Express maximum memory read request * @dev: PCI device to query - * @count: maximum memory read count in bytes + * @rq: maximum memory read count in bytes * valid values are 128, 256, 512, 1024, 2048, 4096 * * If possible sets maximum read byte count @@ -1604,6 +1604,7 @@ early_param("pci", pci_setup); device_initcall(pci_init); EXPORT_SYMBOL_GPL(pci_restore_bars); +EXPORT_SYMBOL(__pci_reenable_device); EXPORT_SYMBOL(pci_enable_device_bars); EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pcim_enable_device); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 3fec13d..c6e132d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,6 +1,5 @@ /* Functions internal to the PCI core code */ -extern int __must_check __pci_reenable_device(struct pci_dev *); extern int pci_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); @@ -13,7 +12,7 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, resource_size_t, resource_size_t), void *alignf_data); /* Firmware callbacks */ -extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); +extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state); extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state); extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 7c93a10..f8b13f0 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -409,6 +409,9 @@ static void socket_shutdown(struct pcmcia_socket *s) #endif s->functions = 0; + /* give socket some time to power down */ + msleep(100); + s->ops->get_status(s, &status); if (status & SS_POWERON) { printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index dd6384b..b6a4f02 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -2,7 +2,6 @@ * card.c - contains functions for managing groups of PnP devices * * Copyright 2002 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/module.h> @@ -13,26 +12,31 @@ LIST_HEAD(pnp_cards); static LIST_HEAD(pnp_card_drivers); - -static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) +static const struct pnp_card_device_id *match_card(struct pnp_card_driver *drv, + struct pnp_card *card) { - const struct pnp_card_device_id * drv_id = drv->id_table; - while (*drv_id->id){ - if (compare_pnp_id(card->id,drv_id->id)) { + const struct pnp_card_device_id *drv_id = drv->id_table; + + while (*drv_id->id) { + if (compare_pnp_id(card->id, drv_id->id)) { int i = 0; + for (;;) { int found; struct pnp_dev *dev; - if (i == PNP_MAX_DEVICES || ! *drv_id->devs[i].id) + + if (i == PNP_MAX_DEVICES + || !*drv_id->devs[i].id) return drv_id; found = 0; card_for_each_dev(card, dev) { - if (compare_pnp_id(dev->id, drv_id->devs[i].id)) { + if (compare_pnp_id + (dev->id, drv_id->devs[i].id)) { found = 1; break; } } - if (! found) + if (!found) break; i++; } @@ -42,14 +46,15 @@ static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv return NULL; } -static void card_remove(struct pnp_dev * dev) +static void card_remove(struct pnp_dev *dev) { dev->card_link = NULL; } -static void card_remove_first(struct pnp_dev * dev) +static void card_remove_first(struct pnp_dev *dev) { - struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); + struct pnp_card_driver *drv = to_pnp_card_driver(dev->driver); + if (!dev->card || !drv) return; if (drv->remove) @@ -67,7 +72,7 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) if (!drv->probe) return 0; - id = match_card(drv,card); + id = match_card(drv, card); if (!id) return 0; @@ -94,12 +99,11 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) * pnp_add_card_id - adds an EISA id to the specified card * @id: pointer to a pnp_id structure * @card: pointer to the desired card - * */ - -int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card) +int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { - struct pnp_id * ptr; + struct pnp_id *ptr; + if (!id) return -EINVAL; if (!card) @@ -115,10 +119,11 @@ int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card) return 0; } -static void pnp_free_card_ids(struct pnp_card * card) +static void pnp_free_card_ids(struct pnp_card *card) { - struct pnp_id * id; + struct pnp_id *id; struct pnp_id *next; + if (!card) return; id = card->id; @@ -131,49 +136,55 @@ static void pnp_free_card_ids(struct pnp_card * card) static void pnp_release_card(struct device *dmdev) { - struct pnp_card * card = to_pnp_card(dmdev); + struct pnp_card *card = to_pnp_card(dmdev); + pnp_free_card_ids(card); kfree(card); } - -static ssize_t pnp_show_card_name(struct device *dmdev, struct device_attribute *attr, char *buf) +static ssize_t pnp_show_card_name(struct device *dmdev, + struct device_attribute *attr, char *buf) { char *str = buf; struct pnp_card *card = to_pnp_card(dmdev); - str += sprintf(str,"%s\n", card->name); + + str += sprintf(str, "%s\n", card->name); return (str - buf); } -static DEVICE_ATTR(name,S_IRUGO,pnp_show_card_name,NULL); +static DEVICE_ATTR(name, S_IRUGO, pnp_show_card_name, NULL); -static ssize_t pnp_show_card_ids(struct device *dmdev, struct device_attribute *attr, char *buf) +static ssize_t pnp_show_card_ids(struct device *dmdev, + struct device_attribute *attr, char *buf) { char *str = buf; struct pnp_card *card = to_pnp_card(dmdev); - struct pnp_id * pos = card->id; + struct pnp_id *pos = card->id; while (pos) { - str += sprintf(str,"%s\n", pos->id); + str += sprintf(str, "%s\n", pos->id); pos = pos->next; } return (str - buf); } -static DEVICE_ATTR(card_id,S_IRUGO,pnp_show_card_ids,NULL); +static DEVICE_ATTR(card_id, S_IRUGO, pnp_show_card_ids, NULL); static int pnp_interface_attach_card(struct pnp_card *card) { - int rc = device_create_file(&card->dev,&dev_attr_name); - if (rc) return rc; + int rc = device_create_file(&card->dev, &dev_attr_name); - rc = device_create_file(&card->dev,&dev_attr_card_id); - if (rc) goto err_name; + if (rc) + return rc; + + rc = device_create_file(&card->dev, &dev_attr_card_id); + if (rc) + goto err_name; return 0; -err_name: - device_remove_file(&card->dev,&dev_attr_name); + err_name: + device_remove_file(&card->dev, &dev_attr_name); return rc; } @@ -181,15 +192,16 @@ err_name: * pnp_add_card - adds a PnP card to the PnP Layer * @card: pointer to the card to add */ - -int pnp_add_card(struct pnp_card * card) +int pnp_add_card(struct pnp_card *card) { int error; - struct list_head * pos, * temp; + struct list_head *pos, *temp; + if (!card || !card->protocol) return -EINVAL; - sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number); + sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, + card->number); card->dev.parent = &card->protocol->dev; card->dev.bus = NULL; card->dev.release = &pnp_release_card; @@ -205,18 +217,21 @@ int pnp_add_card(struct pnp_card * card) /* we wait until now to add devices in order to ensure the drivers * will be able to use all of the related devices on the card * without waiting any unresonable length of time */ - list_for_each(pos,&card->devices){ + list_for_each(pos, &card->devices) { struct pnp_dev *dev = card_to_pnp_dev(pos); __pnp_add_device(dev); } /* match with card drivers */ - list_for_each_safe(pos,temp,&pnp_card_drivers){ - struct pnp_card_driver * drv = list_entry(pos, struct pnp_card_driver, global_list); - card_probe(card,drv); + list_for_each_safe(pos, temp, &pnp_card_drivers) { + struct pnp_card_driver *drv = + list_entry(pos, struct pnp_card_driver, + global_list); + card_probe(card, drv); } } else - pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id); + pnp_err("sysfs failure, card '%s' will be unavailable", + card->dev.bus_id); return error; } @@ -224,10 +239,10 @@ int pnp_add_card(struct pnp_card * card) * pnp_remove_card - removes a PnP card from the PnP Layer * @card: pointer to the card to remove */ - -void pnp_remove_card(struct pnp_card * card) +void pnp_remove_card(struct pnp_card *card) { struct list_head *pos, *temp; + if (!card) return; device_unregister(&card->dev); @@ -235,7 +250,7 @@ void pnp_remove_card(struct pnp_card * card) list_del(&card->global_list); list_del(&card->protocol_list); spin_unlock(&pnp_lock); - list_for_each_safe(pos,temp,&card->devices){ + list_for_each_safe(pos, temp, &card->devices) { struct pnp_dev *dev = card_to_pnp_dev(pos); pnp_remove_card_device(dev); } @@ -246,15 +261,14 @@ void pnp_remove_card(struct pnp_card * card) * @card: pointer to the card to add to * @dev: pointer to the device to add */ - -int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) +int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { if (!card || !dev || !dev->protocol) return -EINVAL; dev->dev.parent = &card->dev; dev->card_link = NULL; - snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number, - card->number,dev->number); + snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", + dev->protocol->number, card->number, dev->number); spin_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); @@ -266,8 +280,7 @@ int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) * pnp_remove_card_device- removes a device from the specified card * @dev: pointer to the device to remove */ - -void pnp_remove_card_device(struct pnp_dev * dev) +void pnp_remove_card_device(struct pnp_dev *dev) { spin_lock(&pnp_lock); dev->card = NULL; @@ -282,13 +295,14 @@ void pnp_remove_card_device(struct pnp_dev * dev) * @id: pointer to a PnP ID structure that explains the rules for finding the device * @from: Starting place to search from. If NULL it will start from the begining. */ - -struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) +struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, + const char *id, struct pnp_dev *from) { - struct list_head * pos; - struct pnp_dev * dev; - struct pnp_card_driver * drv; - struct pnp_card * card; + struct list_head *pos; + struct pnp_dev *dev; + struct pnp_card_driver *drv; + struct pnp_card *card; + if (!clink || !id) goto done; card = clink->card; @@ -302,15 +316,15 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char } while (pos != &card->devices) { dev = card_to_pnp_dev(pos); - if ((!dev->card_link) && compare_pnp_id(dev->id,id)) + if ((!dev->card_link) && compare_pnp_id(dev->id, id)) goto found; pos = pos->next; } -done: + done: return NULL; -found: + found: dev->card_link = clink; dev->dev.driver = &drv->link.driver; if (pnp_bus_type.probe(&dev->dev)) @@ -320,7 +334,7 @@ found: return dev; -err_out: + err_out: dev->dev.driver = NULL; dev->card_link = NULL; return NULL; @@ -330,10 +344,10 @@ err_out: * pnp_release_card_device - call this when the driver no longer needs the device * @dev: pointer to the PnP device stucture */ - -void pnp_release_card_device(struct pnp_dev * dev) +void pnp_release_card_device(struct pnp_dev *dev) { - struct pnp_card_driver * drv = dev->card_link->driver; + struct pnp_card_driver *drv = dev->card_link->driver; + if (!drv) return; drv->link.remove = &card_remove; @@ -347,6 +361,7 @@ void pnp_release_card_device(struct pnp_dev * dev) static int card_suspend(struct pnp_dev *dev, pm_message_t state) { struct pnp_card_link *link = dev->card_link; + if (link->pm_state.event == state.event) return 0; link->pm_state = state; @@ -356,6 +371,7 @@ static int card_suspend(struct pnp_dev *dev, pm_message_t state) static int card_resume(struct pnp_dev *dev) { struct pnp_card_link *link = dev->card_link; + if (link->pm_state.event == PM_EVENT_ON) return 0; link->pm_state = PMSG_ON; @@ -367,8 +383,7 @@ static int card_resume(struct pnp_dev *dev) * pnp_register_card_driver - registers a PnP card driver with the PnP Layer * @drv: pointer to the driver to register */ - -int pnp_register_card_driver(struct pnp_card_driver * drv) +int pnp_register_card_driver(struct pnp_card_driver *drv) { int error; struct list_head *pos, *temp; @@ -389,9 +404,10 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) list_add_tail(&drv->global_list, &pnp_card_drivers); spin_unlock(&pnp_lock); - list_for_each_safe(pos,temp,&pnp_cards){ - struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); - card_probe(card,drv); + list_for_each_safe(pos, temp, &pnp_cards) { + struct pnp_card *card = + list_entry(pos, struct pnp_card, global_list); + card_probe(card, drv); } return 0; } @@ -400,8 +416,7 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer * @drv: pointer to the driver to unregister */ - -void pnp_unregister_card_driver(struct pnp_card_driver * drv) +void pnp_unregister_card_driver(struct pnp_card_driver *drv) { spin_lock(&pnp_lock); list_del(&drv->global_list); @@ -409,13 +424,6 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv) pnp_unregister_driver(&drv->link); } -#if 0 -EXPORT_SYMBOL(pnp_add_card); -EXPORT_SYMBOL(pnp_remove_card); -EXPORT_SYMBOL(pnp_add_card_device); -EXPORT_SYMBOL(pnp_remove_card_device); -EXPORT_SYMBOL(pnp_add_card_id); -#endif /* 0 */ EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_register_card_driver); diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 8e7b2dd..61066fd 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -2,7 +2,6 @@ * core.c - contains all core device and protocol registration functions * * Copyright 2002 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/pnp.h> @@ -18,7 +17,6 @@ #include "base.h" - static LIST_HEAD(pnp_protocols); LIST_HEAD(pnp_global); DEFINE_SPINLOCK(pnp_lock); @@ -36,7 +34,7 @@ void *pnp_alloc(long size) void *result; result = kzalloc(size, GFP_KERNEL); - if (!result){ + if (!result) { printk(KERN_ERR "pnp: Out of Memory\n"); return NULL; } @@ -49,11 +47,10 @@ void *pnp_alloc(long size) * * Ex protocols: ISAPNP, PNPBIOS, etc */ - int pnp_register_protocol(struct pnp_protocol *protocol) { int nodenum; - struct list_head * pos; + struct list_head *pos; if (!protocol) return -EINVAL; @@ -64,9 +61,9 @@ int pnp_register_protocol(struct pnp_protocol *protocol) spin_lock(&pnp_lock); /* assign the lowest unused number */ - list_for_each(pos,&pnp_protocols) { - struct pnp_protocol * cur = to_pnp_protocol(pos); - if (cur->number == nodenum){ + list_for_each(pos, &pnp_protocols) { + struct pnp_protocol *cur = to_pnp_protocol(pos); + if (cur->number == nodenum) { pos = &pnp_protocols; nodenum++; } @@ -83,7 +80,6 @@ int pnp_register_protocol(struct pnp_protocol *protocol) /** * pnp_protocol_unregister - removes a pnp protocol from the pnp layer * @protocol: pointer to the corresponding pnp_protocol structure - * */ void pnp_unregister_protocol(struct pnp_protocol *protocol) { @@ -93,11 +89,11 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol) device_unregister(&protocol->dev); } - static void pnp_free_ids(struct pnp_dev *dev) { - struct pnp_id * id; - struct pnp_id * next; + struct pnp_id *id; + struct pnp_id *next; + if (!dev) return; id = dev->id; @@ -110,7 +106,8 @@ static void pnp_free_ids(struct pnp_dev *dev) static void pnp_release_device(struct device *dmdev) { - struct pnp_dev * dev = to_pnp_dev(dmdev); + struct pnp_dev *dev = to_pnp_dev(dmdev); + pnp_free_option(dev->independent); pnp_free_option(dev->dependent); pnp_free_ids(dev); @@ -120,6 +117,7 @@ static void pnp_release_device(struct device *dmdev) int __pnp_add_device(struct pnp_dev *dev) { int ret; + pnp_fixup_device(dev); dev->dev.bus = &pnp_bus_type; dev->dev.dma_mask = &dev->dma_mask; @@ -143,13 +141,13 @@ int __pnp_add_device(struct pnp_dev *dev) * * adds to driver model, name database, fixups, interface, etc. */ - int pnp_add_device(struct pnp_dev *dev) { if (!dev || !dev->protocol || dev->card) return -EINVAL; dev->dev.parent = &dev->protocol->dev; - sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, dev->number); + sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, + dev->number); return __pnp_add_device(dev); } @@ -162,21 +160,6 @@ void __pnp_remove_device(struct pnp_dev *dev) device_unregister(&dev->dev); } -/** - * pnp_remove_device - removes a pnp device from the pnp layer - * @dev: pointer to dev to add - * - * this function will free all mem used by dev - */ -#if 0 -void pnp_remove_device(struct pnp_dev *dev) -{ - if (!dev || dev->card) - return; - __pnp_remove_device(dev); -} -#endif /* 0 */ - static int __init pnp_init(void) { printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n"); @@ -184,10 +167,3 @@ static int __init pnp_init(void) } subsys_initcall(pnp_init); - -#if 0 -EXPORT_SYMBOL(pnp_register_protocol); -EXPORT_SYMBOL(pnp_unregister_protocol); -EXPORT_SYMBOL(pnp_add_device); -EXPORT_SYMBOL(pnp_remove_device); -#endif /* 0 */ diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index e161423..30b8f6f 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -2,7 +2,6 @@ * driver.c - device id matching, driver model, etc. * * Copyright 2002 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/string.h> @@ -16,12 +15,11 @@ static int compare_func(const char *ida, const char *idb) { int i; + /* we only need to compare the last 4 chars */ - for (i=3; i<7; i++) - { + for (i = 3; i < 7; i++) { if (ida[i] != 'X' && - idb[i] != 'X' && - toupper(ida[i]) != toupper(idb[i])) + idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i])) return 0; } return 1; @@ -31,20 +29,22 @@ int compare_pnp_id(struct pnp_id *pos, const char *id) { if (!pos || !id || (strlen(id) != 7)) return 0; - if (memcmp(id,"ANYDEVS",7)==0) + if (memcmp(id, "ANYDEVS", 7) == 0) return 1; - while (pos){ - if (memcmp(pos->id,id,3)==0) - if (compare_func(pos->id,id)==1) + while (pos) { + if (memcmp(pos->id, id, 3) == 0) + if (compare_func(pos->id, id) == 1) return 1; pos = pos->next; } return 0; } -static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev) +static const struct pnp_device_id *match_device(struct pnp_driver *drv, + struct pnp_dev *dev) { const struct pnp_device_id *drv_id = drv->id_table; + if (!drv_id) return NULL; @@ -59,7 +59,7 @@ static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct int pnp_device_attach(struct pnp_dev *pnp_dev) { spin_lock(&pnp_lock); - if(pnp_dev->status != PNP_READY){ + if (pnp_dev->status != PNP_READY) { spin_unlock(&pnp_lock); return -EBUSY; } @@ -86,7 +86,8 @@ static int pnp_device_probe(struct device *dev) pnp_dev = to_pnp_dev(dev); pnp_drv = to_pnp_driver(dev->driver); - pnp_dbg("match found with the PnP device '%s' and the driver '%s'", dev->bus_id,pnp_drv->name); + pnp_dbg("match found with the PnP device '%s' and the driver '%s'", + dev->bus_id, pnp_drv->name); error = pnp_device_attach(pnp_dev); if (error < 0) @@ -99,7 +100,7 @@ static int pnp_device_probe(struct device *dev) return error; } } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) - == PNP_DRIVER_RES_DISABLE) { + == PNP_DRIVER_RES_DISABLE) { error = pnp_disable_dev(pnp_dev); if (error < 0) return error; @@ -110,22 +111,22 @@ static int pnp_device_probe(struct device *dev) if (dev_id != NULL) error = pnp_drv->probe(pnp_dev, dev_id); } - if (error >= 0){ + if (error >= 0) { pnp_dev->driver = pnp_drv; error = 0; } else goto fail; return error; -fail: + fail: pnp_device_detach(pnp_dev); return error; } static int pnp_device_remove(struct device *dev) { - struct pnp_dev * pnp_dev = to_pnp_dev(dev); - struct pnp_driver * drv = pnp_dev->driver; + struct pnp_dev *pnp_dev = to_pnp_dev(dev); + struct pnp_driver *drv = pnp_dev->driver; if (drv) { if (drv->remove) @@ -138,8 +139,9 @@ static int pnp_device_remove(struct device *dev) static int pnp_bus_match(struct device *dev, struct device_driver *drv) { - struct pnp_dev * pnp_dev = to_pnp_dev(dev); - struct pnp_driver * pnp_drv = to_pnp_driver(drv); + struct pnp_dev *pnp_dev = to_pnp_dev(dev); + struct pnp_driver *pnp_drv = to_pnp_driver(drv); + if (match_device(pnp_drv, pnp_dev) == NULL) return 0; return 1; @@ -147,8 +149,8 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv) static int pnp_bus_suspend(struct device *dev, pm_message_t state) { - struct pnp_dev * pnp_dev = to_pnp_dev(dev); - struct pnp_driver * pnp_drv = pnp_dev->driver; + struct pnp_dev *pnp_dev = to_pnp_dev(dev); + struct pnp_driver *pnp_drv = pnp_dev->driver; int error; if (!pnp_drv) @@ -162,23 +164,28 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && pnp_can_disable(pnp_dev)) { - error = pnp_stop_dev(pnp_dev); - if (error) - return error; + error = pnp_stop_dev(pnp_dev); + if (error) + return error; } + if (pnp_dev->protocol && pnp_dev->protocol->suspend) + pnp_dev->protocol->suspend(pnp_dev, state); return 0; } static int pnp_bus_resume(struct device *dev) { - struct pnp_dev * pnp_dev = to_pnp_dev(dev); - struct pnp_driver * pnp_drv = pnp_dev->driver; + struct pnp_dev *pnp_dev = to_pnp_dev(dev); + struct pnp_driver *pnp_drv = pnp_dev->driver; int error; if (!pnp_drv) return 0; + if (pnp_dev->protocol && pnp_dev->protocol->resume) + pnp_dev->protocol->resume(pnp_dev); + if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { error = pnp_start_dev(pnp_dev); if (error) @@ -192,12 +199,12 @@ static int pnp_bus_resume(struct device *dev) } struct bus_type pnp_bus_type = { - .name = "pnp", - .match = pnp_bus_match, - .probe = pnp_device_probe, - .remove = pnp_device_remove, + .name = "pnp", + .match = pnp_bus_match, + .probe = pnp_device_probe, + .remove = pnp_device_remove, .suspend = pnp_bus_suspend, - .resume = pnp_bus_resume, + .resume = pnp_bus_resume, }; int pnp_register_driver(struct pnp_driver *drv) @@ -220,12 +227,11 @@ void pnp_unregister_driver(struct pnp_driver *drv) * pnp_add_id - adds an EISA id to the specified device * @id: pointer to a pnp_id structure * @dev: pointer to the desired device - * */ - int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) { struct pnp_id *ptr; + if (!id) return -EINVAL; if (!dev) @@ -243,8 +249,5 @@ int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_unregister_driver); -#if 0 -EXPORT_SYMBOL(pnp_add_id); -#endif EXPORT_SYMBOL(pnp_device_attach); EXPORT_SYMBOL(pnp_device_detach); diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index ac9fcd4..fe6684e 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -3,7 +3,6 @@ * * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@suse.cz> * Copyright 2002 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/pnp.h> @@ -29,7 +28,7 @@ struct pnp_info_buffer { typedef struct pnp_info_buffer pnp_info_buffer_t; -static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...) +static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...) { va_list args; int res; @@ -48,14 +47,18 @@ static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...) return res; } -static void pnp_print_port(pnp_info_buffer_t *buffer, char *space, struct pnp_port *port) +static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, + struct pnp_port *port) { - pnp_printf(buffer, "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n", - space, port->min, port->max, port->align ? (port->align-1) : 0, port->size, - port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10); + pnp_printf(buffer, + "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n", + space, port->min, port->max, + port->align ? (port->align - 1) : 0, port->size, + port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10); } -static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq *irq) +static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, + struct pnp_irq *irq) { int first = 1, i; @@ -85,14 +88,15 @@ static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq pnp_printf(buffer, "\n"); } -static void pnp_print_dma(pnp_info_buffer_t *buffer, char *space, struct pnp_dma *dma) +static void pnp_print_dma(pnp_info_buffer_t * buffer, char *space, + struct pnp_dma *dma) { int first = 1, i; char *s; pnp_printf(buffer, "%sdma ", space); for (i = 0; i < 8; i++) - if (dma->map & (1<<i)) { + if (dma->map & (1 << i)) { if (!first) { pnp_printf(buffer, ","); } else { @@ -136,12 +140,13 @@ static void pnp_print_dma(pnp_info_buffer_t *buffer, char *space, struct pnp_dma pnp_printf(buffer, " %s\n", s); } -static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem *mem) +static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, + struct pnp_mem *mem) { char *s; pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x", - space, mem->min, mem->max, mem->align, mem->size); + space, mem->min, mem->max, mem->align, mem->size); if (mem->flags & IORESOURCE_MEM_WRITEABLE) pnp_printf(buffer, ", writeable"); if (mem->flags & IORESOURCE_MEM_CACHEABLE) @@ -168,7 +173,7 @@ static void pnp_print_mem(pnp_info_buffer_t *buffer, char *space, struct pnp_mem pnp_printf(buffer, ", %s\n", s); } -static void pnp_print_option(pnp_info_buffer_t *buffer, char *space, +static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, struct pnp_option *option, int dep) { char *s; @@ -179,19 +184,19 @@ static void pnp_print_option(pnp_info_buffer_t *buffer, char *space, if (dep) { switch (option->priority) { - case PNP_RES_PRIORITY_PREFERRED: + case PNP_RES_PRIORITY_PREFERRED: s = "preferred"; break; - case PNP_RES_PRIORITY_ACCEPTABLE: + case PNP_RES_PRIORITY_ACCEPTABLE: s = "acceptable"; break; - case PNP_RES_PRIORITY_FUNCTIONAL: + case PNP_RES_PRIORITY_FUNCTIONAL: s = "functional"; break; - default: + default: s = "invalid"; } - pnp_printf(buffer, "Dependent: %02i - Priority %s\n",dep, s); + pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s); } for (port = option->port; port; port = port->next) @@ -204,16 +209,16 @@ static void pnp_print_option(pnp_info_buffer_t *buffer, char *space, pnp_print_mem(buffer, space, mem); } - -static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *attr, char *buf) +static ssize_t pnp_show_options(struct device *dmdev, + struct device_attribute *attr, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); - struct pnp_option * independent = dev->independent; - struct pnp_option * dependent = dev->dependent; + struct pnp_option *independent = dev->independent; + struct pnp_option *dependent = dev->dependent; int ret, dep = 1; pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) - pnp_alloc(sizeof(pnp_info_buffer_t)); + pnp_alloc(sizeof(pnp_info_buffer_t)); if (!buffer) return -ENOMEM; @@ -223,7 +228,7 @@ static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *a if (independent) pnp_print_option(buffer, "", independent, 0); - while (dependent){ + while (dependent) { pnp_print_option(buffer, " ", dependent, dep); dependent = dependent->next; dep++; @@ -233,10 +238,11 @@ static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *a return ret; } -static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL); +static DEVICE_ATTR(options, S_IRUGO, pnp_show_options, NULL); - -static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_attribute *attr, char *buf) +static ssize_t pnp_show_current_resources(struct device *dmdev, + struct device_attribute *attr, + char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); int i, ret; @@ -252,52 +258,56 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at buffer->buffer = buf; buffer->curr = buffer->buffer; - pnp_printf(buffer,"state = "); + pnp_printf(buffer, "state = "); if (dev->active) - pnp_printf(buffer,"active\n"); + pnp_printf(buffer, "active\n"); else - pnp_printf(buffer,"disabled\n"); + pnp_printf(buffer, "disabled\n"); for (i = 0; i < PNP_MAX_PORT; i++) { if (pnp_port_valid(dev, i)) { - pnp_printf(buffer,"io"); + pnp_printf(buffer, "io"); if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED) - pnp_printf(buffer," disabled\n"); + pnp_printf(buffer, " disabled\n"); else - pnp_printf(buffer," 0x%llx-0x%llx\n", - (unsigned long long)pnp_port_start(dev, i), - (unsigned long long)pnp_port_end(dev, i)); + pnp_printf(buffer, " 0x%llx-0x%llx\n", + (unsigned long long) + pnp_port_start(dev, i), + (unsigned long long)pnp_port_end(dev, + i)); } } for (i = 0; i < PNP_MAX_MEM; i++) { if (pnp_mem_valid(dev, i)) { - pnp_printf(buffer,"mem"); + pnp_printf(buffer, "mem"); if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED) - pnp_printf(buffer," disabled\n"); + pnp_printf(buffer, " disabled\n"); else - pnp_printf(buffer," 0x%llx-0x%llx\n", - (unsigned long long)pnp_mem_start(dev, i), - (unsigned long long)pnp_mem_end(dev, i)); + pnp_printf(buffer, " 0x%llx-0x%llx\n", + (unsigned long long) + pnp_mem_start(dev, i), + (unsigned long long)pnp_mem_end(dev, + i)); } } for (i = 0; i < PNP_MAX_IRQ; i++) { if (pnp_irq_valid(dev, i)) { - pnp_printf(buffer,"irq"); + pnp_printf(buffer, "irq"); if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED) - pnp_printf(buffer," disabled\n"); + pnp_printf(buffer, " disabled\n"); else - pnp_printf(buffer," %lld\n", - (unsigned long long)pnp_irq(dev, i)); + pnp_printf(buffer, " %lld\n", + (unsigned long long)pnp_irq(dev, i)); } } for (i = 0; i < PNP_MAX_DMA; i++) { if (pnp_dma_valid(dev, i)) { - pnp_printf(buffer,"dma"); + pnp_printf(buffer, "dma"); if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED) - pnp_printf(buffer," disabled\n"); + pnp_printf(buffer, " disabled\n"); else - pnp_printf(buffer," %lld\n", - (unsigned long long)pnp_dma(dev, i)); + pnp_printf(buffer, " %lld\n", + (unsigned long long)pnp_dma(dev, i)); } } ret = (buffer->curr - buf); @@ -308,55 +318,57 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at extern struct semaphore pnp_res_mutex; static ssize_t -pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, const char * ubuf, size_t count) +pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, + const char *ubuf, size_t count) { struct pnp_dev *dev = to_pnp_dev(dmdev); - char *buf = (void *)ubuf; - int retval = 0; + char *buf = (void *)ubuf; + int retval = 0; if (dev->status & PNP_ATTACHED) { retval = -EBUSY; - pnp_info("Device %s cannot be configured because it is in use.", dev->dev.bus_id); + pnp_info("Device %s cannot be configured because it is in use.", + dev->dev.bus_id); goto done; } while (isspace(*buf)) ++buf; - if (!strnicmp(buf,"disable",7)) { + if (!strnicmp(buf, "disable", 7)) { retval = pnp_disable_dev(dev); goto done; } - if (!strnicmp(buf,"activate",8)) { + if (!strnicmp(buf, "activate", 8)) { retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf,"fill",4)) { + if (!strnicmp(buf, "fill", 4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf,"auto",4)) { + if (!strnicmp(buf, "auto", 4)) { if (dev->active) goto done; pnp_init_resource_table(&dev->res); retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf,"clear",5)) { + if (!strnicmp(buf, "clear", 5)) { if (dev->active) goto done; pnp_init_resource_table(&dev->res); goto done; } - if (!strnicmp(buf,"get",3)) { + if (!strnicmp(buf, "get", 3)) { down(&pnp_res_mutex); if (pnp_can_read(dev)) dev->protocol->get(dev, &dev->res); up(&pnp_res_mutex); goto done; } - if (!strnicmp(buf,"set",3)) { + if (!strnicmp(buf, "set", 3)) { int nport = 0, nmem = 0, nirq = 0, ndma = 0; if (dev->active) goto done; @@ -366,65 +378,77 @@ pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, while (1) { while (isspace(*buf)) ++buf; - if (!strnicmp(buf,"io",2)) { + if (!strnicmp(buf, "io", 2)) { buf += 2; while (isspace(*buf)) ++buf; - dev->res.port_resource[nport].start = simple_strtoul(buf,&buf,0); + dev->res.port_resource[nport].start = + simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; - if(*buf == '-') { + if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - dev->res.port_resource[nport].end = simple_strtoul(buf,&buf,0); + dev->res.port_resource[nport].end = + simple_strtoul(buf, &buf, 0); } else - dev->res.port_resource[nport].end = dev->res.port_resource[nport].start; - dev->res.port_resource[nport].flags = IORESOURCE_IO; + dev->res.port_resource[nport].end = + dev->res.port_resource[nport].start; + dev->res.port_resource[nport].flags = + IORESOURCE_IO; nport++; if (nport >= PNP_MAX_PORT) break; continue; } - if (!strnicmp(buf,"mem",3)) { + if (!strnicmp(buf, "mem", 3)) { buf += 3; while (isspace(*buf)) ++buf; - dev->res.mem_resource[nmem].start = simple_strtoul(buf,&buf,0); + dev->res.mem_resource[nmem].start = + simple_strtoul(buf, &buf, 0); while (isspace(*buf)) ++buf; - if(*buf == '-') { + if (*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; - dev->res.mem_resource[nmem].end = simple_strtoul(buf,&buf,0); + dev->res.mem_resource[nmem].end = + simple_strtoul(buf, &buf, 0); } else - dev->res.mem_resource[nmem].end = dev->res.mem_resource[nmem].start; - dev->res.mem_resource[nmem].flags = IORESOURCE_MEM; + dev->res.mem_resource[nmem].end = + dev->res.mem_resource[nmem].start; + dev->res.mem_resource[nmem].flags = + IORESOURCE_MEM; nmem++; if (nmem >= PNP_MAX_MEM) break; continue; } - if (!strnicmp(buf,"irq",3)) { + if (!strnicmp(buf, "irq", 3)) { buf += 3; while (isspace(*buf)) ++buf; dev->res.irq_resource[nirq].start = - dev->res.irq_resource[nirq].end = simple_strtoul(buf,&buf,0); - dev->res.irq_resource[nirq].flags = IORESOURCE_IRQ; + dev->res.irq_resource[nirq].end = + simple_strtoul(buf, &buf, 0); + dev->res.irq_resource[nirq].flags = + IORESOURCE_IRQ; nirq++; if (nirq >= PNP_MAX_IRQ) break; continue; } - if (!strnicmp(buf,"dma",3)) { + if (!strnicmp(buf, "dma", 3)) { buf += 3; while (isspace(*buf)) ++buf; dev->res.dma_resource[ndma].start = - dev->res.dma_resource[ndma].end = simple_strtoul(buf,&buf,0); - dev->res.dma_resource[ndma].flags = IORESOURCE_DMA; + dev->res.dma_resource[ndma].end = + simple_strtoul(buf, &buf, 0); + dev->res.dma_resource[ndma].flags = + IORESOURCE_DMA; ndma++; if (ndma >= PNP_MAX_DMA) break; @@ -435,45 +459,50 @@ pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, up(&pnp_res_mutex); goto done; } - done: + done: if (retval < 0) return retval; return count; } -static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR, - pnp_show_current_resources,pnp_set_current_resources); +static DEVICE_ATTR(resources, S_IRUGO | S_IWUSR, + pnp_show_current_resources, pnp_set_current_resources); -static ssize_t pnp_show_current_ids(struct device *dmdev, struct device_attribute *attr, char *buf) +static ssize_t pnp_show_current_ids(struct device *dmdev, + struct device_attribute *attr, char *buf) { char *str = buf; struct pnp_dev *dev = to_pnp_dev(dmdev); - struct pnp_id * pos = dev->id; + struct pnp_id *pos = dev->id; while (pos) { - str += sprintf(str,"%s\n", pos->id); + str += sprintf(str, "%s\n", pos->id); pos = pos->next; } return (str - buf); } -static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL); +static DEVICE_ATTR(id, S_IRUGO, pnp_show_current_ids, NULL); int pnp_interface_attach_device(struct pnp_dev *dev) { - int rc = device_create_file(&dev->dev,&dev_attr_options); - if (rc) goto err; - rc = device_create_file(&dev->dev,&dev_attr_resources); - if (rc) goto err_opt; - rc = device_create_file(&dev->dev,&dev_attr_id); - if (rc) goto err_res; + int rc = device_create_file(&dev->dev, &dev_attr_options); + + if (rc) + goto err; + rc = device_create_file(&dev->dev, &dev_attr_resources); + if (rc) + goto err_opt; + rc = device_create_file(&dev->dev, &dev_attr_id); + if (rc) + goto err_res; return 0; -err_res: - device_remove_file(&dev->dev,&dev_attr_resources); -err_opt: - device_remove_file(&dev->dev,&dev_attr_options); -err: + err_res: + device_remove_file(&dev->dev, &dev_attr_resources); + err_opt: + device_remove_file(&dev->dev, &dev_attr_options); + err: return rc; } diff --git a/drivers/pnp/isapnp/compat.c b/drivers/pnp/isapnp/compat.c index 0697ab8..10bdcc4 100644 --- a/drivers/pnp/isapnp/compat.c +++ b/drivers/pnp/isapnp/compat.c @@ -3,34 +3,30 @@ * the old isapnp APIs. If possible use the new APIs instead. * * Copyright 2002 Adam Belay <ambx1@neo.rr.com> - * */ - -/* TODO: see if more isapnp functions are needed here */ #include <linux/module.h> #include <linux/isapnp.h> #include <linux/string.h> -static void pnp_convert_id(char *buf, unsigned short vendor, unsigned short device) +static void pnp_convert_id(char *buf, unsigned short vendor, + unsigned short device) { sprintf(buf, "%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, - (device >> 12) & 0x0f, - (device >> 8) & 0x0f); + 'A' + ((vendor >> 2) & 0x3f) - 1, + 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, + 'A' + ((vendor >> 8) & 0x1f) - 1, + (device >> 4) & 0x0f, device & 0x0f, + (device >> 12) & 0x0f, (device >> 8) & 0x0f); } -struct pnp_card *pnp_find_card(unsigned short vendor, - unsigned short device, +struct pnp_card *pnp_find_card(unsigned short vendor, unsigned short device, struct pnp_card *from) { char id[8]; char any[8]; struct list_head *list; + pnp_convert_id(id, vendor, device); pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID); @@ -38,20 +34,20 @@ struct pnp_card *pnp_find_card(unsigned short vendor, while (list != &pnp_cards) { struct pnp_card *card = global_to_pnp_card(list); - if (compare_pnp_id(card->id,id) || (memcmp(id,any,7)==0)) + + if (compare_pnp_id(card->id, id) || (memcmp(id, any, 7) == 0)) return card; list = list->next; } return NULL; } -struct pnp_dev *pnp_find_dev(struct pnp_card *card, - unsigned short vendor, - unsigned short function, - struct pnp_dev *from) +struct pnp_dev *pnp_find_dev(struct pnp_card *card, unsigned short vendor, + unsigned short function, struct pnp_dev *from) { char id[8]; char any[8]; + pnp_convert_id(id, vendor, function); pnp_convert_id(any, ISAPNP_ANY_ID, ISAPNP_ANY_ID); if (card == NULL) { /* look for a logical device from all cards */ @@ -63,7 +59,9 @@ struct pnp_dev *pnp_find_dev(struct pnp_card *card, while (list != &pnp_global) { struct pnp_dev *dev = global_to_pnp_dev(list); - if (compare_pnp_id(dev->id,id) || (memcmp(id,any,7)==0)) + + if (compare_pnp_id(dev->id, id) || + (memcmp(id, any, 7) == 0)) return dev; list = list->next; } @@ -78,7 +76,8 @@ struct pnp_dev *pnp_find_dev(struct pnp_card *card, } while (list != &card->devices) { struct pnp_dev *dev = card_to_pnp_dev(list); - if (compare_pnp_id(dev->id,id)) + + if (compare_pnp_id(dev->id, id)) return dev; list = list->next; } diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 914d00c..b4e2aa9 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -51,10 +51,10 @@ #define ISAPNP_DEBUG #endif -int isapnp_disable; /* Disable ISA PnP */ -static int isapnp_rdp; /* Read Data Port */ -static int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ -static int isapnp_verbose = 1; /* verbose mode */ +int isapnp_disable; /* Disable ISA PnP */ +static int isapnp_rdp; /* Read Data Port */ +static int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ +static int isapnp_verbose = 1; /* verbose mode */ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_DESCRIPTION("Generic ISA Plug & Play support"); @@ -126,7 +126,7 @@ static unsigned short isapnp_read_word(unsigned char idx) unsigned short val; val = isapnp_read_byte(idx); - val = (val << 8) + isapnp_read_byte(idx+1); + val = (val << 8) + isapnp_read_byte(idx + 1); return val; } @@ -139,7 +139,7 @@ void isapnp_write_byte(unsigned char idx, unsigned char val) static void isapnp_write_word(unsigned char idx, unsigned short val) { isapnp_write_byte(idx, val >> 8); - isapnp_write_byte(idx+1, val); + isapnp_write_byte(idx + 1, val); } static void isapnp_key(void) @@ -193,7 +193,7 @@ static void isapnp_deactivate(unsigned char logdev) static void __init isapnp_peek(unsigned char *data, int bytes) { int i, j; - unsigned char d=0; + unsigned char d = 0; for (i = 1; i <= bytes; i++) { for (j = 0; j < 20; j++) { @@ -220,19 +220,18 @@ static int isapnp_next_rdp(void) { int rdp = isapnp_rdp; static int old_rdp = 0; - - if(old_rdp) - { + + if (old_rdp) { release_region(old_rdp, 1); old_rdp = 0; } while (rdp <= 0x3ff) { /* - * We cannot use NE2000 probe spaces for ISAPnP or we - * will lock up machines. + * We cannot use NE2000 probe spaces for ISAPnP or we + * will lock up machines. */ - if ((rdp < 0x280 || rdp > 0x380) && request_region(rdp, 1, "ISAPnP")) - { + if ((rdp < 0x280 || rdp > 0x380) + && request_region(rdp, 1, "ISAPnP")) { isapnp_rdp = rdp; old_rdp = rdp; return 0; @@ -253,7 +252,6 @@ static inline void isapnp_set_rdp(void) * Perform an isolation. The port selection code now tries to avoid * "dangerous to read" ports. */ - static int __init isapnp_isolate_rdp_select(void) { isapnp_wait(); @@ -282,7 +280,6 @@ static int __init isapnp_isolate_rdp_select(void) /* * Isolate (assign uniqued CSN) to all ISA PnP devices. */ - static int __init isapnp_isolate(void) { unsigned char checksum = 0x6a; @@ -305,7 +302,9 @@ static int __init isapnp_isolate(void) udelay(250); if (data == 0x55aa) bit = 0x01; - checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1); + checksum = + ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) + | (checksum >> 1); bit = 0x00; } for (i = 65; i <= 72; i++) { @@ -351,13 +350,12 @@ static int __init isapnp_isolate(void) /* * Read one tag from stream. */ - static int __init isapnp_read_tag(unsigned char *type, unsigned short *size) { unsigned char tag, tmp[2]; isapnp_peek(&tag, 1); - if (tag == 0) /* invalid tag */ + if (tag == 0) /* invalid tag */ return -1; if (tag & 0x80) { /* large item */ *type = tag; @@ -368,7 +366,8 @@ static int __init isapnp_read_tag(unsigned char *type, unsigned short *size) *size = tag & 0x07; } #if 0 - printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size); + printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, + *size); #endif if (*type == 0xff && *size == 0xffff) /* probably invalid data */ return -1; @@ -378,7 +377,6 @@ static int __init isapnp_read_tag(unsigned char *type, unsigned short *size) /* * Skip specified number of bytes from stream. */ - static void __init isapnp_skip_bytes(int count) { isapnp_peek(NULL, count); @@ -387,31 +385,30 @@ static void __init isapnp_skip_bytes(int count) /* * Parse EISA id. */ - -static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigned short device) +static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor, + unsigned short device) { - struct pnp_id * id; + struct pnp_id *id; + if (!dev) return; id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); if (!id) return; sprintf(id->id, "%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, - (device >> 12) & 0x0f, - (device >> 8) & 0x0f); + 'A' + ((vendor >> 2) & 0x3f) - 1, + 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, + 'A' + ((vendor >> 8) & 0x1f) - 1, + (device >> 4) & 0x0f, + device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); pnp_add_id(id, dev); } /* * Parse logical device tag. */ - -static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int size, int number) +static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, + int size, int number) { unsigned char tmp[6]; struct pnp_dev *dev; @@ -435,13 +432,11 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si return dev; } - /* * Add IRQ resource to resources list. */ - static void __init isapnp_parse_irq_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[3]; struct pnp_irq *irq; @@ -458,15 +453,13 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, else irq->flags = IORESOURCE_IRQ_HIGHEDGE; pnp_register_irq_resource(option, irq); - return; } /* * Add DMA resource to resources list. */ - static void __init isapnp_parse_dma_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[2]; struct pnp_dma *dma; @@ -478,15 +471,13 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, dma->map = tmp[0]; dma->flags = tmp[1]; pnp_register_dma_resource(option, dma); - return; } /* * Add port resource to resources list. */ - static void __init isapnp_parse_port_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[7]; struct pnp_port *port; @@ -500,16 +491,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, port->align = tmp[5]; port->size = tmp[6]; port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option,port); - return; + pnp_register_port_resource(option, port); } /* * Add fixed port resource to resources list. */ - static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[3]; struct pnp_port *port; @@ -522,16 +511,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, port->size = tmp[2]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); - return; + pnp_register_port_resource(option, port); } /* * Add memory resource to resources list. */ - static void __init isapnp_parse_mem_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[9]; struct pnp_mem *mem; @@ -545,16 +532,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, mem->align = (tmp[6] << 8) | tmp[5]; mem->size = ((tmp[8] << 8) | tmp[7]) << 8; mem->flags = tmp[0]; - pnp_register_mem_resource(option,mem); - return; + pnp_register_mem_resource(option, mem); } /* * Add 32-bit memory resource to resources list. */ - static void __init isapnp_parse_mem32_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[17]; struct pnp_mem *mem; @@ -565,18 +550,19 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, return; mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; mem->max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; - mem->align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; - mem->size = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; + mem->align = + (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; + mem->size = + (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; mem->flags = tmp[0]; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); } /* * Add 32-bit fixed memory resource to resources list. */ - static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, - int size) + int size) { unsigned char tmp[9]; struct pnp_mem *mem; @@ -585,28 +571,29 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; - mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; + mem->min = mem->max = + (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; mem->align = 0; mem->flags = tmp[0]; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); } /* * Parse card name for ISA PnP device. - */ - + */ static void __init isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) { if (name[0] == '\0') { - unsigned short size1 = *size >= name_max ? (name_max - 1) : *size; + unsigned short size1 = + *size >= name_max ? (name_max - 1) : *size; isapnp_peek(name, size1); name[size1] = '\0'; *size -= size1; /* clean whitespace from end of string */ - while (size1 > 0 && name[--size1] == ' ') + while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; } } @@ -614,7 +601,6 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) /* * Parse resource map for logical device. */ - static int __init isapnp_create_device(struct pnp_card *card, unsigned short size) { @@ -622,6 +608,7 @@ static int __init isapnp_create_device(struct pnp_card *card, unsigned char type, tmp[17]; struct pnp_option *option; struct pnp_dev *dev; + if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; option = pnp_register_independent_option(dev); @@ -629,17 +616,19 @@ static int __init isapnp_create_device(struct pnp_card *card, kfree(dev); return 1; } - pnp_add_card_device(card,dev); + pnp_add_card_device(card, dev); while (1) { - if (isapnp_read_tag(&type, &size)<0) + if (isapnp_read_tag(&type, &size) < 0) return 1; if (skip && type != _STAG_LOGDEVID && type != _STAG_END) goto __skip; switch (type) { case _STAG_LOGDEVID: if (size >= 5 && size <= 6) { - if ((dev = isapnp_parse_device(card, size, number++)) == NULL) + if ((dev = + isapnp_parse_device(card, size, + number++)) == NULL) return 1; size = 0; skip = 0; @@ -648,7 +637,7 @@ static int __init isapnp_create_device(struct pnp_card *card, kfree(dev); return 1; } - pnp_add_card_device(card,dev); + pnp_add_card_device(card, dev); } else { skip = 1; } @@ -658,7 +647,8 @@ static int __init isapnp_create_device(struct pnp_card *card, case _STAG_COMPATDEVID: if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { isapnp_peek(tmp, 4); - isapnp_parse_id(dev,(tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]); + isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], + (tmp[3] << 8) | tmp[2]); compat++; size = 0; } @@ -684,7 +674,7 @@ static int __init isapnp_create_device(struct pnp_card *card, priority = 0x100 | tmp[0]; size = 0; } - option = pnp_register_dependent_option(dev,priority); + option = pnp_register_dependent_option(dev, priority); if (!option) return 1; break; @@ -739,11 +729,13 @@ static int __init isapnp_create_device(struct pnp_card *card, isapnp_skip_bytes(size); return 1; default: - printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->number, card->number); + printk(KERN_ERR + "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", + type, dev->number, card->number); } __skip: - if (size > 0) - isapnp_skip_bytes(size); + if (size > 0) + isapnp_skip_bytes(size); } return 0; } @@ -751,14 +743,13 @@ static int __init isapnp_create_device(struct pnp_card *card, /* * Parse resource map for ISA PnP card. */ - static void __init isapnp_parse_resource_map(struct pnp_card *card) { unsigned char type, tmp[17]; unsigned short size; while (1) { - if (isapnp_read_tag(&type, &size)<0) + if (isapnp_read_tag(&type, &size) < 0) return; switch (type) { case _STAG_PNPVERNO: @@ -771,7 +762,7 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) break; case _STAG_LOGDEVID: if (size >= 5 && size <= 6) { - if (isapnp_create_device(card, size)==1) + if (isapnp_create_device(card, size) == 1) return; size = 0; } @@ -779,7 +770,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) case _STAG_VENDOR: break; case _LTAG_ANSISTR: - isapnp_parse_name(card->name, sizeof(card->name), &size); + isapnp_parse_name(card->name, sizeof(card->name), + &size); break; case _LTAG_UNICODESTR: /* silently ignore */ @@ -792,18 +784,19 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) isapnp_skip_bytes(size); return; default: - printk(KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number); + printk(KERN_ERR + "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", + type, card->number); } __skip: - if (size > 0) - isapnp_skip_bytes(size); + if (size > 0) + isapnp_skip_bytes(size); } } /* * Compute ISA PnP checksum for first eight bytes. */ - static unsigned char __init isapnp_checksum(unsigned char *data) { int i, j; @@ -815,7 +808,9 @@ static unsigned char __init isapnp_checksum(unsigned char *data) bit = 0; if (b & (1 << j)) bit = 1; - checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1); + checksum = + ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) + | (checksum >> 1); } } return checksum; @@ -824,27 +819,25 @@ static unsigned char __init isapnp_checksum(unsigned char *data) /* * Parse EISA id for ISA PnP card. */ - -static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device) +static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor, + unsigned short device) { - struct pnp_id * id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); + if (!id) return; sprintf(id->id, "%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, - (device >> 12) & 0x0f, - (device >> 8) & 0x0f); - pnp_add_card_id(id,card); + 'A' + ((vendor >> 2) & 0x3f) - 1, + 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, + 'A' + ((vendor >> 8) & 0x1f) - 1, + (device >> 4) & 0x0f, + device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); + pnp_add_card_id(id, card); } /* * Build device list for all present ISA PnP devices. */ - static int __init isapnp_build_device_list(void) { int csn; @@ -858,22 +851,29 @@ static int __init isapnp_build_device_list(void) isapnp_peek(header, 9); checksum = isapnp_checksum(header); #if 0 - printk(KERN_DEBUG "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - header[0], header[1], header[2], header[3], - header[4], header[5], header[6], header[7], header[8]); + printk(KERN_DEBUG + "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + header[0], header[1], header[2], header[3], header[4], + header[5], header[6], header[7], header[8]); printk(KERN_DEBUG "checksum = 0x%x\n", checksum); #endif - if ((card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL) + if ((card = + kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL) continue; card->number = csn; INIT_LIST_HEAD(&card->devices); - isapnp_parse_card_id(card, (header[1] << 8) | header[0], (header[3] << 8) | header[2]); - card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4]; + isapnp_parse_card_id(card, (header[1] << 8) | header[0], + (header[3] << 8) | header[2]); + card->serial = + (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | + header[4]; isapnp_checksum_value = 0x00; isapnp_parse_resource_map(card); if (isapnp_checksum_value != 0x00) - printk(KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value); + printk(KERN_ERR + "isapnp: checksum for device %i is not valid (0x%x)\n", + csn, isapnp_checksum_value); card->checksum = isapnp_checksum_value; card->protocol = &isapnp_protocol; @@ -890,6 +890,7 @@ static int __init isapnp_build_device_list(void) int isapnp_present(void) { struct pnp_card *card; + pnp_for_each_card(card) { if (card->protocol == &isapnp_protocol) return 1; @@ -911,13 +912,13 @@ int isapnp_cfg_begin(int csn, int logdev) /* it is possible to set RDP only in the isolation phase */ /* Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> */ isapnp_write_byte(0x02, 0x04); /* clear CSN of card */ - mdelay(2); /* is this necessary? */ - isapnp_wake(csn); /* bring card into sleep state */ - isapnp_wake(0); /* bring card into isolation state */ - isapnp_set_rdp(); /* reset the RDP port */ - udelay(1000); /* delay 1000us */ + mdelay(2); /* is this necessary? */ + isapnp_wake(csn); /* bring card into sleep state */ + isapnp_wake(0); /* bring card into isolation state */ + isapnp_set_rdp(); /* reset the RDP port */ + udelay(1000); /* delay 1000us */ isapnp_write_byte(0x06, csn); /* reset CSN to previous value */ - udelay(250); /* is this necessary? */ + udelay(250); /* is this necessary? */ #endif if (logdev >= 0) isapnp_device(logdev); @@ -931,12 +932,10 @@ int isapnp_cfg_end(void) return 0; } - /* - * Inititialization. + * Initialization. */ - EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); @@ -946,7 +945,8 @@ EXPORT_SYMBOL(isapnp_read_byte); #endif EXPORT_SYMBOL(isapnp_write_byte); -static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res) +static int isapnp_read_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { int tmp, ret; @@ -960,31 +960,37 @@ static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table res->port_resource[tmp].flags = IORESOURCE_IO; } for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { - ret = isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; + ret = + isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; if (!ret) continue; res->mem_resource[tmp].start = ret; res->mem_resource[tmp].flags = IORESOURCE_MEM; } for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { - ret = (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 8); + ret = + (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> + 8); if (!ret) continue; - res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret; + res->irq_resource[tmp].start = + res->irq_resource[tmp].end = ret; res->irq_resource[tmp].flags = IORESOURCE_IRQ; } for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); if (ret == 4) continue; - res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret; + res->dma_resource[tmp].start = + res->dma_resource[tmp].end = ret; res->dma_resource[tmp].flags = IORESOURCE_DMA; } } return 0; } -static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res) +static int isapnp_get_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { int ret; pnp_init_resource_table(res); @@ -994,24 +1000,44 @@ static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * return ret; } -static int isapnp_set_resources(struct pnp_dev *dev, struct pnp_resource_table * res) +static int isapnp_set_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { int tmp; isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; - for (tmp = 0; tmp < PNP_MAX_PORT && (res->port_resource[tmp].flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; tmp++) - isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), res->port_resource[tmp].start); - for (tmp = 0; tmp < PNP_MAX_IRQ && (res->irq_resource[tmp].flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; tmp++) { + for (tmp = 0; + tmp < PNP_MAX_PORT + && (res->port_resource[tmp]. + flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; + tmp++) + isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), + res->port_resource[tmp].start); + for (tmp = 0; + tmp < PNP_MAX_IRQ + && (res->irq_resource[tmp]. + flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; + tmp++) { int irq = res->irq_resource[tmp].start; if (irq == 2) irq = 9; - isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq); + isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); } - for (tmp = 0; tmp < PNP_MAX_DMA && (res->dma_resource[tmp].flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; tmp++) - isapnp_write_byte(ISAPNP_CFG_DMA+tmp, res->dma_resource[tmp].start); - for (tmp = 0; tmp < PNP_MAX_MEM && (res->mem_resource[tmp].flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; tmp++) - isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<3), (res->mem_resource[tmp].start >> 8) & 0xffff); + for (tmp = 0; + tmp < PNP_MAX_DMA + && (res->dma_resource[tmp]. + flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; + tmp++) + isapnp_write_byte(ISAPNP_CFG_DMA + tmp, + res->dma_resource[tmp].start); + for (tmp = 0; + tmp < PNP_MAX_MEM + && (res->mem_resource[tmp]. + flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; + tmp++) + isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), + (res->mem_resource[tmp].start >> 8) & 0xffff); /* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate(dev->number); isapnp_cfg_end(); @@ -1030,9 +1056,9 @@ static int isapnp_disable_resources(struct pnp_dev *dev) } struct pnp_protocol isapnp_protocol = { - .name = "ISA Plug and Play", - .get = isapnp_get_resources, - .set = isapnp_set_resources, + .name = "ISA Plug and Play", + .get = isapnp_get_resources, + .set = isapnp_set_resources, .disable = isapnp_disable_resources, }; @@ -1053,31 +1079,36 @@ static int __init isapnp_init(void) #endif #ifdef ISAPNP_REGION_OK if (!request_region(_PIDXR, 1, "isapnp index")) { - printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR); + printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", + _PIDXR); return -EBUSY; } #endif if (!request_region(_PNPWRP, 1, "isapnp write")) { - printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP); + printk(KERN_ERR + "isapnp: Write Data Register 0x%x already used\n", + _PNPWRP); #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif return -EBUSY; } - if(pnp_register_protocol(&isapnp_protocol)<0) + if (pnp_register_protocol(&isapnp_protocol) < 0) return -EBUSY; /* - * Print a message. The existing ISAPnP code is hanging machines - * so let the user know where. + * Print a message. The existing ISAPnP code is hanging machines + * so let the user know where. */ - + printk(KERN_INFO "isapnp: Scanning for PnP cards...\n"); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) { isapnp_rdp |= 3; if (!request_region(isapnp_rdp, 1, "isapnp read")) { - printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp); + printk(KERN_ERR + "isapnp: Read Data Register 0x%x already used\n", + isapnp_rdp); #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif @@ -1089,14 +1120,14 @@ static int __init isapnp_init(void) isapnp_detected = 1; if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) { cards = isapnp_isolate(); - if (cards < 0 || - (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) { + if (cards < 0 || (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) { #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif release_region(_PNPWRP, 1); isapnp_detected = 0; - printk(KERN_INFO "isapnp: No Plug & Play device found\n"); + printk(KERN_INFO + "isapnp: No Plug & Play device found\n"); return 0; } request_region(isapnp_rdp, 1, "isapnp read"); @@ -1104,19 +1135,23 @@ static int __init isapnp_init(void) isapnp_build_device_list(); cards = 0; - protocol_for_each_card(&isapnp_protocol,card) { + protocol_for_each_card(&isapnp_protocol, card) { cards++; if (isapnp_verbose) { - printk(KERN_INFO "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown"); + printk(KERN_INFO "isapnp: Card '%s'\n", + card->name[0] ? card->name : "Unknown"); if (isapnp_verbose < 2) continue; - card_for_each_dev(card,dev) { - printk(KERN_INFO "isapnp: Device '%s'\n", dev->name[0]?dev->name:"Unknown"); + card_for_each_dev(card, dev) { + printk(KERN_INFO "isapnp: Device '%s'\n", + dev->name[0] ? dev->name : "Unknown"); } } } if (cards) { - printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":""); + printk(KERN_INFO + "isapnp: %i Plug & Play card%s detected total\n", cards, + cards > 1 ? "s" : ""); } else { printk(KERN_INFO "isapnp: No Plug & Play card found\n"); } @@ -1141,11 +1176,10 @@ __setup("noisapnp", isapnp_setup_disable); static int __init isapnp_setup_isapnp(char *str) { - (void)((get_option(&str,&isapnp_rdp) == 2) && - (get_option(&str,&isapnp_reset) == 2) && - (get_option(&str,&isapnp_verbose) == 2)); + (void)((get_option(&str, &isapnp_rdp) == 2) && + (get_option(&str, &isapnp_reset) == 2) && + (get_option(&str, &isapnp_verbose) == 2)); return 1; } __setup("isapnp=", isapnp_setup_isapnp); - diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c index 40b724e..3fbc0f9 100644 --- a/drivers/pnp/isapnp/proc.c +++ b/drivers/pnp/isapnp/proc.c @@ -2,7 +2,6 @@ * ISA Plug & Play support * Copyright (c) by Jaroslav Kysela <perex@suse.cz> * - * * 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 * the Free Software Foundation; either version 2 of the License, or @@ -16,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ #include <linux/module.h> @@ -54,7 +52,8 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) return (file->f_pos = new); } -static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) +static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf, + size_t nbytes, loff_t * ppos) { struct inode *ino = file->f_path.dentry->d_inode; struct proc_dir_entry *dp = PDE(ino); @@ -74,7 +73,7 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t return -EINVAL; isapnp_cfg_begin(dev->card->number, dev->number); - for ( ; pos < 256 && cnt > 0; pos++, buf++, cnt--) { + for (; pos < 256 && cnt > 0; pos++, buf++, cnt--) { unsigned char val; val = isapnp_read_byte(pos); __put_user(val, buf); @@ -85,10 +84,9 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t return nbytes; } -static const struct file_operations isapnp_proc_bus_file_operations = -{ - .llseek = isapnp_proc_bus_lseek, - .read = isapnp_proc_bus_read, +static const struct file_operations isapnp_proc_bus_file_operations = { + .llseek = isapnp_proc_bus_lseek, + .read = isapnp_proc_bus_read, }; static int isapnp_proc_attach_device(struct pnp_dev *dev) @@ -139,13 +137,14 @@ static int __exit isapnp_proc_detach_bus(struct pnp_card *bus) remove_proc_entry(name, isapnp_proc_bus_dir); return 0; } -#endif /* MODULE */ +#endif /* MODULE */ int __init isapnp_proc_init(void) { struct pnp_dev *dev; + isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus); - protocol_for_each_dev(&isapnp_protocol,dev) { + protocol_for_each_dev(&isapnp_protocol, dev) { isapnp_proc_attach_device(dev); } return 0; @@ -167,4 +166,4 @@ int __exit isapnp_proc_done(void) remove_proc_entry("isapnp", proc_bus); return 0; } -#endif /* MODULE */ +#endif /* MODULE */ diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 57e6ab1..3bda513 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -3,7 +3,6 @@ * * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz> * Copyright 2003 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/errno.h> @@ -26,7 +25,8 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) return -EINVAL; if (idx >= PNP_MAX_PORT) { - pnp_err("More than 4 ports is incompatible with pnp specifications."); + pnp_err + ("More than 4 ports is incompatible with pnp specifications."); /* pretend we were successful so at least the manager won't try again */ return 1; } @@ -41,11 +41,11 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) /* set the initial values */ *flags |= rule->flags | IORESOURCE_IO; - *flags &= ~IORESOURCE_UNSET; + *flags &= ~IORESOURCE_UNSET; if (!rule->size) { *flags |= IORESOURCE_DISABLED; - return 1; /* skip disabled resource requests */ + return 1; /* skip disabled resource requests */ } *start = rule->min; @@ -70,7 +70,8 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) return -EINVAL; if (idx >= PNP_MAX_MEM) { - pnp_err("More than 8 mems is incompatible with pnp specifications."); + pnp_err + ("More than 8 mems is incompatible with pnp specifications."); /* pretend we were successful so at least the manager won't try again */ return 1; } @@ -85,7 +86,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) /* set the initial values */ *flags |= rule->flags | IORESOURCE_MEM; - *flags &= ~IORESOURCE_UNSET; + *flags &= ~IORESOURCE_UNSET; /* convert pnp flags to standard Linux flags */ if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) @@ -99,11 +100,11 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) if (!rule->size) { *flags |= IORESOURCE_DISABLED; - return 1; /* skip disabled resource requests */ + return 1; /* skip disabled resource requests */ } *start = rule->min; - *end = *start + rule->size -1; + *end = *start + rule->size - 1; /* run through until pnp_check_mem is happy */ while (!pnp_check_mem(dev, idx)) { @@ -115,7 +116,7 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) return 1; } -static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) +static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) { resource_size_t *start, *end; unsigned long *flags; @@ -130,7 +131,8 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) return -EINVAL; if (idx >= PNP_MAX_IRQ) { - pnp_err("More than 2 irqs is incompatible with pnp specifications."); + pnp_err + ("More than 2 irqs is incompatible with pnp specifications."); /* pretend we were successful so at least the manager won't try again */ return 1; } @@ -145,11 +147,11 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) /* set the initial values */ *flags |= rule->flags | IORESOURCE_IRQ; - *flags &= ~IORESOURCE_UNSET; + *flags &= ~IORESOURCE_UNSET; if (bitmap_empty(rule->map, PNP_IRQ_NR)) { *flags |= IORESOURCE_DISABLED; - return 1; /* skip disabled resource requests */ + return 1; /* skip disabled resource requests */ } /* TBD: need check for >16 IRQ */ @@ -159,9 +161,9 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) return 1; } for (i = 0; i < 16; i++) { - if(test_bit(xtab[i], rule->map)) { + if (test_bit(xtab[i], rule->map)) { *start = *end = xtab[i]; - if(pnp_check_irq(dev, idx)) + if (pnp_check_irq(dev, idx)) return 1; } } @@ -183,7 +185,8 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) return -EINVAL; if (idx >= PNP_MAX_DMA) { - pnp_err("More than 2 dmas is incompatible with pnp specifications."); + pnp_err + ("More than 2 dmas is incompatible with pnp specifications."); /* pretend we were successful so at least the manager won't try again */ return 1; } @@ -198,17 +201,17 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) /* set the initial values */ *flags |= rule->flags | IORESOURCE_DMA; - *flags &= ~IORESOURCE_UNSET; + *flags &= ~IORESOURCE_UNSET; if (!rule->map) { *flags |= IORESOURCE_DISABLED; - return 1; /* skip disabled resource requests */ + return 1; /* skip disabled resource requests */ } for (i = 0; i < 8; i++) { - if(rule->map & (1<<xtab[i])) { + if (rule->map & (1 << xtab[i])) { *start = *end = xtab[i]; - if(pnp_check_dma(dev, idx)) + if (pnp_check_dma(dev, idx)) return 1; } } @@ -218,72 +221,80 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) /** * pnp_init_resources - Resets a resource table to default values. * @table: pointer to the desired resource table - * */ void pnp_init_resource_table(struct pnp_resource_table *table) { int idx; + for (idx = 0; idx < PNP_MAX_IRQ; idx++) { table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; + table->irq_resource[idx].flags = + IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { table->dma_resource[idx].name = NULL; table->dma_resource[idx].start = -1; table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; + table->dma_resource[idx].flags = + IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { table->port_resource[idx].name = NULL; table->port_resource[idx].start = 0; table->port_resource[idx].end = 0; - table->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; + table->port_resource[idx].flags = + IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { table->mem_resource[idx].name = NULL; table->mem_resource[idx].start = 0; table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; + table->mem_resource[idx].flags = + IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; } } /** * pnp_clean_resources - clears resources that were not manually set * @res: the resources to clean - * */ -static void pnp_clean_resource_table(struct pnp_resource_table * res) +static void pnp_clean_resource_table(struct pnp_resource_table *res) { int idx; + for (idx = 0; idx < PNP_MAX_IRQ; idx++) { if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) continue; res->irq_resource[idx].start = -1; res->irq_resource[idx].end = -1; - res->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; + res->irq_resource[idx].flags = + IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) continue; res->dma_resource[idx].start = -1; res->dma_resource[idx].end = -1; - res->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; + res->dma_resource[idx].flags = + IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) continue; res->port_resource[idx].start = 0; res->port_resource[idx].end = 0; - res->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; + res->port_resource[idx].flags = + IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) continue; res->mem_resource[idx].start = 0; res->mem_resource[idx].end = 0; - res->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; + res->mem_resource[idx].flags = + IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; } } @@ -306,7 +317,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) return -ENODEV; down(&pnp_res_mutex); - pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ + pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ if (dev->independent) { port = dev->independent->port; mem = dev->independent->mem; @@ -341,10 +352,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) if (depnum) { struct pnp_option *dep; int i; - for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next) - if(!dep) + for (i = 1, dep = dev->dependent; i < depnum; + i++, dep = dep->next) + if (!dep) goto fail; - port =dep->port; + port = dep->port; mem = dep->mem; irq = dep->irq; dma = dep->dma; @@ -378,7 +390,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) up(&pnp_res_mutex); return 1; -fail: + fail: pnp_clean_resource_table(&dev->res); up(&pnp_res_mutex); return 0; @@ -392,10 +404,12 @@ fail: * * This function can be used by drivers that want to manually set thier resources. */ -int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode) +int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, + int mode) { int i; - struct pnp_resource_table * bak; + struct pnp_resource_table *bak; + if (!dev || !res) return -EINVAL; if (!pnp_can_configure(dev)) @@ -409,19 +423,19 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, dev->res = *res; if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { - if(!pnp_check_port(dev,i)) + if (!pnp_check_port(dev, i)) goto fail; } for (i = 0; i < PNP_MAX_MEM; i++) { - if(!pnp_check_mem(dev,i)) + if (!pnp_check_mem(dev, i)) goto fail; } for (i = 0; i < PNP_MAX_IRQ; i++) { - if(!pnp_check_irq(dev,i)) + if (!pnp_check_irq(dev, i)) goto fail; } for (i = 0; i < PNP_MAX_DMA; i++) { - if(!pnp_check_dma(dev,i)) + if (!pnp_check_dma(dev, i)) goto fail; } } @@ -430,7 +444,7 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, kfree(bak); return 0; -fail: + fail: dev->res = *bak; up(&pnp_res_mutex); kfree(bak); @@ -440,18 +454,18 @@ fail: /** * pnp_auto_config_dev - automatically assigns resources to a device * @dev: pointer to the desired device - * */ int pnp_auto_config_dev(struct pnp_dev *dev) { struct pnp_option *dep; int i = 1; - if(!dev) + if (!dev) return -EINVAL; - if(!pnp_can_configure(dev)) { - pnp_dbg("Device %s does not support resource configuration.", dev->dev.bus_id); + if (!pnp_can_configure(dev)) { + pnp_dbg("Device %s does not support resource configuration.", + dev->dev.bus_id); return -ENODEV; } @@ -476,23 +490,22 @@ int pnp_auto_config_dev(struct pnp_dev *dev) * pnp_start_dev - low-level start of the PnP device * @dev: pointer to the desired device * - * assumes that resources have alread been allocated + * assumes that resources have already been allocated */ - int pnp_start_dev(struct pnp_dev *dev) { if (!pnp_can_write(dev)) { - pnp_dbg("Device %s does not support activation.", dev->dev.bus_id); + pnp_dbg("Device %s does not support activation.", + dev->dev.bus_id); return -EINVAL; } - if (dev->protocol->set(dev, &dev->res)<0) { + if (dev->protocol->set(dev, &dev->res) < 0) { pnp_err("Failed to activate device %s.", dev->dev.bus_id); return -EIO; } pnp_info("Device %s activated.", dev->dev.bus_id); - return 0; } @@ -502,20 +515,19 @@ int pnp_start_dev(struct pnp_dev *dev) * * does not free resources */ - int pnp_stop_dev(struct pnp_dev *dev) { if (!pnp_can_disable(dev)) { - pnp_dbg("Device %s does not support disabling.", dev->dev.bus_id); + pnp_dbg("Device %s does not support disabling.", + dev->dev.bus_id); return -EINVAL; } - if (dev->protocol->disable(dev)<0) { + if (dev->protocol->disable(dev) < 0) { pnp_err("Failed to disable device %s.", dev->dev.bus_id); return -EIO; } pnp_info("Device %s disabled.", dev->dev.bus_id); - return 0; } @@ -531,9 +543,8 @@ int pnp_activate_dev(struct pnp_dev *dev) if (!dev) return -EINVAL; - if (dev->active) { - return 0; /* the device is already active */ - } + if (dev->active) + return 0; /* the device is already active */ /* ensure resources are allocated */ if (pnp_auto_config_dev(dev)) @@ -544,7 +555,6 @@ int pnp_activate_dev(struct pnp_dev *dev) return error; dev->active = 1; - return 1; } @@ -558,11 +568,10 @@ int pnp_disable_dev(struct pnp_dev *dev) { int error; - if (!dev) - return -EINVAL; - if (!dev->active) { - return 0; /* the device is already disabled */ - } + if (!dev) + return -EINVAL; + if (!dev->active) + return 0; /* the device is already disabled */ error = pnp_stop_dev(dev); if (error) @@ -583,10 +592,9 @@ int pnp_disable_dev(struct pnp_dev *dev) * @resource: pointer to resource to be changed * @start: start of region * @size: size of region - * */ void pnp_resource_change(struct resource *resource, resource_size_t start, - resource_size_t size) + resource_size_t size) { if (resource == NULL) return; @@ -595,11 +603,7 @@ void pnp_resource_change(struct resource *resource, resource_size_t start, resource->end = start + size - 1; } - EXPORT_SYMBOL(pnp_manual_config_dev); -#if 0 -EXPORT_SYMBOL(pnp_auto_config_dev); -#endif EXPORT_SYMBOL(pnp_start_dev); EXPORT_SYMBOL(pnp_stop_dev); EXPORT_SYMBOL(pnp_activate_dev); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index a005487..616fc72 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -21,7 +21,10 @@ #include <linux/acpi.h> #include <linux/pnp.h> +#include <linux/mod_devicetable.h> #include <acpi/acpi_bus.h> +#include <acpi/actypes.h> + #include "pnpacpi.h" static int num = 0; @@ -31,17 +34,19 @@ static int num = 0; * used by the kernel (PCI root, ...), as it is harmless and there were * already present in pnpbios. But there is an exception for devices that * have irqs (PIC, Timer) because we call acpi_register_gsi. - * Finaly only devices that have a CRS method need to be in this list. + * Finally, only devices that have a CRS method need to be in this list. */ -static char __initdata excluded_id_list[] = - "PNP0C09," /* EC */ - "PNP0C0F," /* Link device */ - "PNP0000," /* PIC */ - "PNP0100," /* Timer */ - ; +static struct __initdata acpi_device_id excluded_id_list[] = { + {"PNP0C09", 0}, /* EC */ + {"PNP0C0F", 0}, /* Link device */ + {"PNP0000", 0}, /* PIC */ + {"PNP0100", 0}, /* Timer */ + {"", 0}, +}; + static inline int is_exclusive_device(struct acpi_device *dev) { - return (!acpi_match_ids(dev, excluded_id_list)); + return (!acpi_match_device_ids(dev, excluded_id_list)); } /* @@ -79,15 +84,18 @@ static void __init pnpidacpi_to_pnpid(char *id, char *str) str[7] = '\0'; } -static int pnpacpi_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res) +static int pnpacpi_get_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { acpi_status status; - status = pnpacpi_parse_allocated_resource((acpi_handle)dev->data, - &dev->res); + + status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data, + &dev->res); return ACPI_FAILURE(status) ? -ENODEV : 0; } -static int pnpacpi_set_resources(struct pnp_dev * dev, struct pnp_resource_table * res) +static int pnpacpi_set_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { acpi_handle handle = dev->data; struct acpi_buffer buffer; @@ -114,16 +122,36 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) acpi_status status; /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ - status = acpi_evaluate_object((acpi_handle)dev->data, - "_DIS", NULL, NULL); + status = acpi_evaluate_object((acpi_handle) dev->data, + "_DIS", NULL, NULL); return ACPI_FAILURE(status) ? -ENODEV : 0; } +#ifdef CONFIG_ACPI_SLEEP +static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) +{ + return acpi_bus_set_power((acpi_handle) dev->data, + acpi_pm_device_sleep_state(&dev->dev, + device_may_wakeup + (&dev->dev), + NULL)); +} + +static int pnpacpi_resume(struct pnp_dev *dev) +{ + return acpi_bus_set_power((acpi_handle) dev->data, ACPI_STATE_D0); +} +#endif + static struct pnp_protocol pnpacpi_protocol = { - .name = "Plug and Play ACPI", - .get = pnpacpi_get_resources, - .set = pnpacpi_set_resources, + .name = "Plug and Play ACPI", + .get = pnpacpi_get_resources, + .set = pnpacpi_set_resources, .disable = pnpacpi_disable_resources, +#ifdef CONFIG_ACPI_SLEEP + .suspend = pnpacpi_suspend, + .resume = pnpacpi_resume, +#endif }; static int __init pnpacpi_add_device(struct acpi_device *device) @@ -135,17 +163,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) status = acpi_get_handle(device->handle, "_CRS", &temp); if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || - is_exclusive_device(device)) + is_exclusive_device(device)) return 0; pnp_dbg("ACPI device : hid %s", acpi_device_hid(device)); - dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) { pnp_err("Out of memory"); return -ENOMEM; } dev->data = device->handle; - /* .enabled means if the device can decode the resources */ + /* .enabled means the device can decode the resources */ dev->active = device->status.enabled; status = acpi_get_handle(device->handle, "_SRS", &temp); if (ACPI_SUCCESS(status)) @@ -175,20 +203,23 @@ static int __init pnpacpi_add_device(struct acpi_device *device) pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); pnp_add_id(dev_id, dev); - if(dev->active) { + if (dev->active) { /* parse allocated resource */ - status = pnpacpi_parse_allocated_resource(device->handle, &dev->res); + status = pnpacpi_parse_allocated_resource(device->handle, + &dev->res); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", dev_id->id); + pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", + dev_id->id); goto err1; } } - if(dev->capabilities & PNP_CONFIGURABLE) { + if (dev->capabilities & PNP_CONFIGURABLE) { status = pnpacpi_parse_resource_option_data(device->handle, - dev); + dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", dev_id->id); + pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", + dev_id->id); goto err1; } } @@ -214,18 +245,19 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (!dev->active) pnp_init_resource_table(&dev->res); pnp_add_device(dev); - num ++; + num++; return AE_OK; -err1: + err1: kfree(dev_id); -err: + err: kfree(dev); return -EINVAL; } static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, - u32 lvl, void *context, void **rv) + u32 lvl, void *context, + void **rv) { struct acpi_device *device; @@ -238,23 +270,22 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, static int __init acpi_pnp_match(struct device *dev, void *_pnp) { - struct acpi_device *acpi = to_acpi_device(dev); - struct pnp_dev *pnp = _pnp; + struct acpi_device *acpi = to_acpi_device(dev); + struct pnp_dev *pnp = _pnp; /* true means it matched */ return acpi->flags.hardware_id - && !acpi_get_physical_device(acpi->handle) - && compare_pnp_id(pnp->id, acpi->pnp.hardware_id); + && !acpi_get_physical_device(acpi->handle) + && compare_pnp_id(pnp->id, acpi->pnp.hardware_id); } -static int __init acpi_pnp_find_device(struct device *dev, acpi_handle *handle) +static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) { - struct device *adev; - struct acpi_device *acpi; + struct device *adev; + struct acpi_device *acpi; adev = bus_find_device(&acpi_bus_type, NULL, - to_pnp_dev(dev), - acpi_pnp_match); + to_pnp_dev(dev), acpi_pnp_match); if (!adev) return -ENODEV; @@ -268,7 +299,7 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle *handle) * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. */ static struct acpi_bus_type __initdata acpi_pnp_bus = { - .bus = &pnp_bus_type, + .bus = &pnp_bus_type, .find_device = acpi_pnp_find_device, }; @@ -288,6 +319,7 @@ static int __init pnpacpi_init(void) pnp_platform_devices = 1; return 0; } + subsys_initcall(pnpacpi_init); static int __init pnpacpi_setup(char *str) @@ -298,8 +330,5 @@ static int __init pnpacpi_setup(char *str) pnpacpi_disabled = 1; return 1; } -__setup("pnpacpi=", pnpacpi_setup); -#if 0 -EXPORT_SYMBOL(pnpacpi_protocol); -#endif +__setup("pnpacpi=", pnpacpi_setup); diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 118ac97..ce5027f 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -40,8 +40,7 @@ static int irq_flags(int triggering, int polarity) flag = IORESOURCE_IRQ_LOWLEVEL; else flag = IORESOURCE_IRQ_HIGHLEVEL; - } - else { + } else { if (polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWEDGE; else @@ -72,9 +71,9 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) } } -static void -pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, - int triggering, int polarity, int shareable) +static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, + u32 gsi, int triggering, + int polarity, int shareable) { int i = 0; int irq; @@ -83,12 +82,12 @@ pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, return; while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && - i < PNP_MAX_IRQ) + i < PNP_MAX_IRQ) i++; if (i >= PNP_MAX_IRQ) return; - res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag + res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag res->irq_resource[i].flags |= irq_flags(triggering, polarity); irq = acpi_register_gsi(gsi, triggering, polarity); if (irq < 0) { @@ -147,17 +146,19 @@ static int dma_flags(int type, int bus_master, int transfer) return flags; } -static void -pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma, - int type, int bus_master, int transfer) +static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, + u32 dma, int type, + int bus_master, int transfer) { int i = 0; + while (i < PNP_MAX_DMA && - !(res->dma_resource[i].flags & IORESOURCE_UNSET)) + !(res->dma_resource[i].flags & IORESOURCE_UNSET)) i++; if (i < PNP_MAX_DMA) { - res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag - res->dma_resource[i].flags |= dma_flags(type, bus_master, transfer); + res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag + res->dma_resource[i].flags |= + dma_flags(type, bus_master, transfer); if (dma == -1) { res->dma_resource[i].flags |= IORESOURCE_DISABLED; return; @@ -167,19 +168,19 @@ pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma, } } -static void -pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, - u64 io, u64 len, int io_decode) +static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, + u64 io, u64 len, int io_decode) { int i = 0; + while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && - i < PNP_MAX_PORT) + i < PNP_MAX_PORT) i++; if (i < PNP_MAX_PORT) { - res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag if (io_decode == ACPI_DECODE_16) res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR; - if (len <= 0 || (io + len -1) >= 0x10003) { + if (len <= 0 || (io + len - 1) >= 0x10003) { res->port_resource[i].flags |= IORESOURCE_DISABLED; return; } @@ -188,21 +189,22 @@ pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, } } -static void -pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, - u64 mem, u64 len, int write_protect) +static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, + u64 mem, u64 len, + int write_protect) { int i = 0; + while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && - (i < PNP_MAX_MEM)) + (i < PNP_MAX_MEM)) i++; if (i < PNP_MAX_MEM) { - res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag if (len <= 0) { res->mem_resource[i].flags |= IORESOURCE_DISABLED; return; } - if(write_protect == ACPI_READ_WRITE_MEMORY) + if (write_protect == ACPI_READ_WRITE_MEMORY) res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE; res->mem_resource[i].start = mem; @@ -210,9 +212,8 @@ pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, } } -static void -pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, - struct acpi_resource *res) +static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, + struct acpi_resource *res) { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; @@ -220,7 +221,7 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, status = acpi_resource_to_address64(res, p); if (!ACPI_SUCCESS(status)) { pnp_warn("PnPACPI: failed to convert resource type %d", - res->type); + res->type); return; } @@ -229,17 +230,20 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(res_table, - p->minimum, p->address_length, p->info.mem.write_protect); + p->minimum, p->address_length, + p->info.mem.write_protect); else if (p->resource_type == ACPI_IO_RANGE) pnpacpi_parse_allocated_ioresource(res_table, - p->minimum, p->address_length, - p->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16); + p->minimum, p->address_length, + p->granularity == 0xfff ? ACPI_DECODE_10 : + ACPI_DECODE_16); } static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, - void *data) + void *data) { - struct pnp_resource_table *res_table = (struct pnp_resource_table *)data; + struct pnp_resource_table *res_table = + (struct pnp_resource_table *)data; int i; switch (res->type) { @@ -260,17 +264,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_DMA: if (res->data.dma.channel_count > 0) pnpacpi_parse_allocated_dmaresource(res_table, - res->data.dma.channels[0], - res->data.dma.type, - res->data.dma.bus_master, - res->data.dma.transfer); + res->data.dma.channels[0], + res->data.dma.type, + res->data.dma.bus_master, + res->data.dma.transfer); break; case ACPI_RESOURCE_TYPE_IO: pnpacpi_parse_allocated_ioresource(res_table, - res->data.io.minimum, - res->data.io.address_length, - res->data.io.io_decode); + res->data.io.minimum, + res->data.io.address_length, + res->data.io.io_decode); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -279,9 +283,9 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_FIXED_IO: pnpacpi_parse_allocated_ioresource(res_table, - res->data.fixed_io.address, - res->data.fixed_io.address_length, - ACPI_DECODE_10); + res->data.fixed_io.address, + res->data.fixed_io.address_length, + ACPI_DECODE_10); break; case ACPI_RESOURCE_TYPE_VENDOR: @@ -292,21 +296,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_MEMORY24: pnpacpi_parse_allocated_memresource(res_table, - res->data.memory24.minimum, - res->data.memory24.address_length, - res->data.memory24.write_protect); + res->data.memory24.minimum, + res->data.memory24.address_length, + res->data.memory24.write_protect); break; case ACPI_RESOURCE_TYPE_MEMORY32: pnpacpi_parse_allocated_memresource(res_table, - res->data.memory32.minimum, - res->data.memory32.address_length, - res->data.memory32.write_protect); + res->data.memory32.minimum, + res->data.memory32.address_length, + res->data.memory32.write_protect); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnpacpi_parse_allocated_memresource(res_table, - res->data.fixed_memory32.address, - res->data.fixed_memory32.address_length, - res->data.fixed_memory32.write_protect); + res->data.fixed_memory32.address, + res->data.fixed_memory32.address_length, + res->data.fixed_memory32.write_protect); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: @@ -343,18 +347,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, return AE_OK; } -acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table *res) +acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, + struct pnp_resource_table * res) { /* Blank the resource table values */ pnp_init_resource_table(res); - return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, res); + return acpi_walk_resources(handle, METHOD_NAME__CRS, + pnpacpi_allocated_resource, res); } -static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_resource_dma *p) +static void pnpacpi_parse_dma_option(struct pnp_option *option, + struct acpi_resource_dma *p) { int i; - struct pnp_dma * dma; + struct pnp_dma *dma; if (p->channel_count == 0) return; @@ -362,18 +369,16 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso if (!dma) return; - for(i = 0; i < p->channel_count; i++) + for (i = 0; i < p->channel_count; i++) dma->map |= 1 << p->channels[i]; dma->flags = dma_flags(p->type, p->bus_master, p->transfer); pnp_register_dma_resource(option, dma); - return; } - static void pnpacpi_parse_irq_option(struct pnp_option *option, - struct acpi_resource_irq *p) + struct acpi_resource_irq *p) { int i; struct pnp_irq *irq; @@ -384,17 +389,16 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, if (!irq) return; - for(i = 0; i < p->interrupt_count; i++) + for (i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); irq->flags = irq_flags(p->triggering, p->polarity); pnp_register_irq_resource(option, irq); - return; } static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, - struct acpi_resource_extended_irq *p) + struct acpi_resource_extended_irq *p) { int i; struct pnp_irq *irq; @@ -405,18 +409,16 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, if (!irq) return; - for(i = 0; i < p->interrupt_count; i++) + for (i = 0; i < p->interrupt_count; i++) if (p->interrupts[i]) __set_bit(p->interrupts[i], irq->map); irq->flags = irq_flags(p->triggering, p->polarity); pnp_register_irq_resource(option, irq); - return; } -static void -pnpacpi_parse_port_option(struct pnp_option *option, - struct acpi_resource_io *io) +static void pnpacpi_parse_port_option(struct pnp_option *option, + struct acpi_resource_io *io) { struct pnp_port *port; @@ -430,14 +432,12 @@ pnpacpi_parse_port_option(struct pnp_option *option, port->align = io->alignment; port->size = io->address_length; port->flags = ACPI_DECODE_16 == io->io_decode ? - PNP_PORT_FLAG_16BITADDR : 0; + PNP_PORT_FLAG_16BITADDR : 0; pnp_register_port_resource(option, port); - return; } -static void -pnpacpi_parse_fixed_port_option(struct pnp_option *option, - struct acpi_resource_fixed_io *io) +static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, + struct acpi_resource_fixed_io *io) { struct pnp_port *port; @@ -451,12 +451,10 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; pnp_register_port_resource(option, port); - return; } -static void -pnpacpi_parse_mem24_option(struct pnp_option *option, - struct acpi_resource_memory24 *p) +static void pnpacpi_parse_mem24_option(struct pnp_option *option, + struct acpi_resource_memory24 *p) { struct pnp_mem *mem; @@ -471,15 +469,13 @@ pnpacpi_parse_mem24_option(struct pnp_option *option, mem->size = p->address_length; mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? - IORESOURCE_MEM_WRITEABLE : 0; + IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option, mem); - return; } -static void -pnpacpi_parse_mem32_option(struct pnp_option *option, - struct acpi_resource_memory32 *p) +static void pnpacpi_parse_mem32_option(struct pnp_option *option, + struct acpi_resource_memory32 *p) { struct pnp_mem *mem; @@ -494,15 +490,13 @@ pnpacpi_parse_mem32_option(struct pnp_option *option, mem->size = p->address_length; mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? - IORESOURCE_MEM_WRITEABLE : 0; + IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option, mem); - return; } -static void -pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, - struct acpi_resource_fixed_memory32 *p) +static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, + struct acpi_resource_fixed_memory32 *p) { struct pnp_mem *mem; @@ -516,14 +510,13 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, mem->align = 0; mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? - IORESOURCE_MEM_WRITEABLE : 0; + IORESOURCE_MEM_WRITEABLE : 0; pnp_register_mem_resource(option, mem); - return; } -static void -pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) +static void pnpacpi_parse_address_option(struct pnp_option *option, + struct acpi_resource *r) { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; @@ -532,7 +525,8 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) status = acpi_resource_to_address64(r, p); if (!ACPI_SUCCESS(status)) { - pnp_warn("PnPACPI: failed to convert resource type %d", r->type); + pnp_warn("PnPACPI: failed to convert resource type %d", + r->type); return; } @@ -547,7 +541,8 @@ pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r) mem->size = p->address_length; mem->align = 0; mem->flags = (p->info.mem.write_protect == - ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; + ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE + : 0; pnp_register_mem_resource(option, mem); } else if (p->resource_type == ACPI_IO_RANGE) { port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); @@ -568,109 +563,108 @@ struct acpipnp_parse_option_s { }; static acpi_status pnpacpi_option_resource(struct acpi_resource *res, - void *data) + void *data) { int priority = 0; - struct acpipnp_parse_option_s *parse_data = (struct acpipnp_parse_option_s *)data; + struct acpipnp_parse_option_s *parse_data = + (struct acpipnp_parse_option_s *)data; struct pnp_dev *dev = parse_data->dev; struct pnp_option *option = parse_data->option; switch (res->type) { - case ACPI_RESOURCE_TYPE_IRQ: - pnpacpi_parse_irq_option(option, &res->data.irq); - break; + case ACPI_RESOURCE_TYPE_IRQ: + pnpacpi_parse_irq_option(option, &res->data.irq); + break; - case ACPI_RESOURCE_TYPE_DMA: - pnpacpi_parse_dma_option(option, &res->data.dma); - break; + case ACPI_RESOURCE_TYPE_DMA: + pnpacpi_parse_dma_option(option, &res->data.dma); + break; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - switch (res->data.start_dpf.compatibility_priority) { - case ACPI_GOOD_CONFIGURATION: - priority = PNP_RES_PRIORITY_PREFERRED; - break; - - case ACPI_ACCEPTABLE_CONFIGURATION: - priority = PNP_RES_PRIORITY_ACCEPTABLE; - break; - - case ACPI_SUB_OPTIMAL_CONFIGURATION: - priority = PNP_RES_PRIORITY_FUNCTIONAL; - break; - default: - priority = PNP_RES_PRIORITY_INVALID; - break; - } - /* TBD: Considering performace/robustness bits */ - option = pnp_register_dependent_option(dev, priority); - if (!option) - return AE_ERROR; - parse_data->option = option; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + switch (res->data.start_dpf.compatibility_priority) { + case ACPI_GOOD_CONFIGURATION: + priority = PNP_RES_PRIORITY_PREFERRED; break; - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - /*only one EndDependentFn is allowed*/ - if (!parse_data->option_independent) { - pnp_warn("PnPACPI: more than one EndDependentFn"); - return AE_ERROR; - } - parse_data->option = parse_data->option_independent; - parse_data->option_independent = NULL; + case ACPI_ACCEPTABLE_CONFIGURATION: + priority = PNP_RES_PRIORITY_ACCEPTABLE; break; - case ACPI_RESOURCE_TYPE_IO: - pnpacpi_parse_port_option(option, &res->data.io); + case ACPI_SUB_OPTIMAL_CONFIGURATION: + priority = PNP_RES_PRIORITY_FUNCTIONAL; break; - - case ACPI_RESOURCE_TYPE_FIXED_IO: - pnpacpi_parse_fixed_port_option(option, - &res->data.fixed_io); + default: + priority = PNP_RES_PRIORITY_INVALID; break; + } + /* TBD: Consider performance/robustness bits */ + option = pnp_register_dependent_option(dev, priority); + if (!option) + return AE_ERROR; + parse_data->option = option; + break; - case ACPI_RESOURCE_TYPE_VENDOR: - case ACPI_RESOURCE_TYPE_END_TAG: - break; + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + /*only one EndDependentFn is allowed */ + if (!parse_data->option_independent) { + pnp_warn("PnPACPI: more than one EndDependentFn"); + return AE_ERROR; + } + parse_data->option = parse_data->option_independent; + parse_data->option_independent = NULL; + break; - case ACPI_RESOURCE_TYPE_MEMORY24: - pnpacpi_parse_mem24_option(option, &res->data.memory24); - break; + case ACPI_RESOURCE_TYPE_IO: + pnpacpi_parse_port_option(option, &res->data.io); + break; - case ACPI_RESOURCE_TYPE_MEMORY32: - pnpacpi_parse_mem32_option(option, &res->data.memory32); - break; + case ACPI_RESOURCE_TYPE_FIXED_IO: + pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io); + break; - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - pnpacpi_parse_fixed_mem32_option(option, - &res->data.fixed_memory32); - break; + case ACPI_RESOURCE_TYPE_VENDOR: + case ACPI_RESOURCE_TYPE_END_TAG: + break; - case ACPI_RESOURCE_TYPE_ADDRESS16: - case ACPI_RESOURCE_TYPE_ADDRESS32: - case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_address_option(option, res); - break; + case ACPI_RESOURCE_TYPE_MEMORY24: + pnpacpi_parse_mem24_option(option, &res->data.memory24); + break; - case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: - break; + case ACPI_RESOURCE_TYPE_MEMORY32: + pnpacpi_parse_mem32_option(option, &res->data.memory32); + break; - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - pnpacpi_parse_ext_irq_option(option, - &res->data.extended_irq); - break; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + pnpacpi_parse_fixed_mem32_option(option, + &res->data.fixed_memory32); + break; - case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + pnpacpi_parse_address_option(option, res); + break; - default: - pnp_warn("PnPACPI: unknown resource type %d", res->type); - return AE_ERROR; + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + break; + + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq); + break; + + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: + break; + + default: + pnp_warn("PnPACPI: unknown resource type %d", res->type); + return AE_ERROR; } return AE_OK; } acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, - struct pnp_dev *dev) + struct pnp_dev * dev) { acpi_status status; struct acpipnp_parse_option_s parse_data; @@ -681,7 +675,7 @@ acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, parse_data.option_independent = parse_data.option; parse_data.dev = dev; status = acpi_walk_resources(handle, METHOD_NAME__PRS, - pnpacpi_option_resource, &parse_data); + pnpacpi_option_resource, &parse_data); return status; } @@ -709,7 +703,7 @@ static int pnpacpi_supported_resource(struct acpi_resource *res) * Set resource */ static acpi_status pnpacpi_count_resources(struct acpi_resource *res, - void *data) + void *data) { int *res_cnt = (int *)data; @@ -732,14 +726,14 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) } int pnpacpi_build_resource_template(acpi_handle handle, - struct acpi_buffer *buffer) + struct acpi_buffer *buffer) { struct acpi_resource *resource; int res_cnt = 0; acpi_status status; status = acpi_walk_resources(handle, METHOD_NAME__CRS, - pnpacpi_count_resources, &res_cnt); + pnpacpi_count_resources, &res_cnt); if (ACPI_FAILURE(status)) { pnp_err("Evaluate _CRS failed"); return -EINVAL; @@ -753,7 +747,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, pnp_dbg("Res cnt %d", res_cnt); resource = (struct acpi_resource *)buffer->pointer; status = acpi_walk_resources(handle, METHOD_NAME__CRS, - pnpacpi_type_resources, &resource); + pnpacpi_type_resources, &resource); if (ACPI_FAILURE(status)) { kfree(buffer->pointer); pnp_err("Evaluate _CRS failed"); @@ -766,7 +760,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, } static void pnpacpi_encode_irq(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { int triggering, polarity; @@ -782,7 +776,7 @@ static void pnpacpi_encode_irq(struct acpi_resource *resource, } static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { int triggering, polarity; @@ -799,32 +793,32 @@ static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, } static void pnpacpi_encode_dma(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { - case IORESOURCE_DMA_TYPEA: - resource->data.dma.type = ACPI_TYPE_A; - break; - case IORESOURCE_DMA_TYPEB: - resource->data.dma.type = ACPI_TYPE_B; - break; - case IORESOURCE_DMA_TYPEF: - resource->data.dma.type = ACPI_TYPE_F; - break; - default: - resource->data.dma.type = ACPI_COMPATIBILITY; + case IORESOURCE_DMA_TYPEA: + resource->data.dma.type = ACPI_TYPE_A; + break; + case IORESOURCE_DMA_TYPEB: + resource->data.dma.type = ACPI_TYPE_B; + break; + case IORESOURCE_DMA_TYPEF: + resource->data.dma.type = ACPI_TYPE_F; + break; + default: + resource->data.dma.type = ACPI_COMPATIBILITY; } switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { - case IORESOURCE_DMA_8BIT: - resource->data.dma.transfer = ACPI_TRANSFER_8; - break; - case IORESOURCE_DMA_8AND16BIT: - resource->data.dma.transfer = ACPI_TRANSFER_8_16; - break; - default: - resource->data.dma.transfer = ACPI_TRANSFER_16; + case IORESOURCE_DMA_8BIT: + resource->data.dma.transfer = ACPI_TRANSFER_8; + break; + case IORESOURCE_DMA_8AND16BIT: + resource->data.dma.transfer = ACPI_TRANSFER_8_16; + break; + default: + resource->data.dma.transfer = ACPI_TRANSFER_16; } resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); @@ -833,31 +827,31 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, } static void pnpacpi_encode_io(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ - resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? - ACPI_DECODE_16 : ACPI_DECODE_10; + resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? + ACPI_DECODE_16 : ACPI_DECODE_10; resource->data.io.minimum = p->start; resource->data.io.maximum = p->end; - resource->data.io.alignment = 0; /* Correct? */ + resource->data.io.alignment = 0; /* Correct? */ resource->data.io.address_length = p->end - p->start + 1; } static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { resource->data.fixed_io.address = p->start; resource->data.fixed_io.address_length = p->end - p->start + 1; } static void pnpacpi_encode_mem24(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ resource->data.memory24.write_protect = - (p->flags & IORESOURCE_MEM_WRITEABLE) ? - ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; + (p->flags & IORESOURCE_MEM_WRITEABLE) ? + ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; resource->data.memory24.minimum = p->start; resource->data.memory24.maximum = p->end; resource->data.memory24.alignment = 0; @@ -865,11 +859,11 @@ static void pnpacpi_encode_mem24(struct acpi_resource *resource, } static void pnpacpi_encode_mem32(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { resource->data.memory32.write_protect = - (p->flags & IORESOURCE_MEM_WRITEABLE) ? - ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; + (p->flags & IORESOURCE_MEM_WRITEABLE) ? + ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; resource->data.memory32.minimum = p->start; resource->data.memory32.maximum = p->end; resource->data.memory32.alignment = 0; @@ -877,74 +871,77 @@ static void pnpacpi_encode_mem32(struct acpi_resource *resource, } static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, - struct resource *p) + struct resource *p) { resource->data.fixed_memory32.write_protect = - (p->flags & IORESOURCE_MEM_WRITEABLE) ? - ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; + (p->flags & IORESOURCE_MEM_WRITEABLE) ? + ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; resource->data.fixed_memory32.address = p->start; resource->data.fixed_memory32.address_length = p->end - p->start + 1; } int pnpacpi_encode_resources(struct pnp_resource_table *res_table, - struct acpi_buffer *buffer) + struct acpi_buffer *buffer) { int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ - int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1; - struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer; + int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1; + struct acpi_resource *resource = + (struct acpi_resource *)buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; pnp_dbg("res cnt %d", res_cnt); while (i < res_cnt) { - switch(resource->type) { + switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: pnp_dbg("Encode irq"); pnpacpi_encode_irq(resource, - &res_table->irq_resource[irq]); + &res_table->irq_resource[irq]); irq++; break; case ACPI_RESOURCE_TYPE_DMA: pnp_dbg("Encode dma"); pnpacpi_encode_dma(resource, - &res_table->dma_resource[dma]); + &res_table->dma_resource[dma]); dma++; break; case ACPI_RESOURCE_TYPE_IO: pnp_dbg("Encode io"); pnpacpi_encode_io(resource, - &res_table->port_resource[port]); + &res_table->port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, - &res_table->port_resource[port]); + &res_table-> + port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, - &res_table->mem_resource[mem]); + &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, - &res_table->mem_resource[mem]); + &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, - &res_table->mem_resource[mem]); + &res_table-> + mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnp_dbg("Encode ext irq"); pnpacpi_encode_ext_irq(resource, - &res_table->irq_resource[irq]); + &res_table->irq_resource[irq]); irq++; break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -956,7 +953,7 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - default: /* other type */ + default: /* other type */ pnp_warn("unknown resource type %d", resource->type); return -EINVAL; } diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index a1f0b0b..5dba68f 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -1,6 +1,5 @@ /* * bioscalls.c - the lowlevel layer of the PnPBIOS driver - * */ #include <linux/types.h> @@ -26,11 +25,10 @@ #include "pnpbios.h" static struct { - u16 offset; - u16 segment; + u16 offset; + u16 segment; } pnp_bios_callpoint; - /* * These are some opcodes for a "static asmlinkage" * As this code is *not* executed inside the linux kernel segment, but in a @@ -44,8 +42,7 @@ static struct { asmlinkage void pnp_bios_callfunc(void); -__asm__( - ".text \n" +__asm__(".text \n" __ALIGN_STR "\n" "pnp_bios_callfunc:\n" " pushl %edx \n" @@ -55,8 +52,7 @@ __asm__( " lcallw *pnp_bios_callpoint\n" " addl $16, %esp \n" " lret \n" - ".previous \n" -); + ".previous \n"); #define Q2_SET_SEL(cpu, selname, address, size) \ do { \ @@ -78,7 +74,6 @@ u32 pnp_bios_is_utter_crap = 0; static spinlock_t pnp_bios_lock; - /* * Support Functions */ @@ -97,7 +92,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, * PnP BIOSes are generally not terribly re-entrant. * Also, don't rely on them to save everything correctly. */ - if(pnp_bios_is_utter_crap) + if (pnp_bios_is_utter_crap) return PNP_FUNCTION_NOT_SUPPORTED; cpu = get_cpu(); @@ -113,112 +108,128 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, if (ts2_size) Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size); - __asm__ __volatile__( - "pushl %%ebp\n\t" - "pushl %%edi\n\t" - "pushl %%esi\n\t" - "pushl %%ds\n\t" - "pushl %%es\n\t" - "pushl %%fs\n\t" - "pushl %%gs\n\t" - "pushfl\n\t" - "movl %%esp, pnp_bios_fault_esp\n\t" - "movl $1f, pnp_bios_fault_eip\n\t" - "lcall %5,%6\n\t" - "1:popfl\n\t" - "popl %%gs\n\t" - "popl %%fs\n\t" - "popl %%es\n\t" - "popl %%ds\n\t" - "popl %%esi\n\t" - "popl %%edi\n\t" - "popl %%ebp\n\t" - : "=a" (status) - : "0" ((func) | (((u32)arg1) << 16)), - "b" ((arg2) | (((u32)arg3) << 16)), - "c" ((arg4) | (((u32)arg5) << 16)), - "d" ((arg6) | (((u32)arg7) << 16)), - "i" (PNP_CS32), - "i" (0) - : "memory" - ); + __asm__ __volatile__("pushl %%ebp\n\t" + "pushl %%edi\n\t" + "pushl %%esi\n\t" + "pushl %%ds\n\t" + "pushl %%es\n\t" + "pushl %%fs\n\t" + "pushl %%gs\n\t" + "pushfl\n\t" + "movl %%esp, pnp_bios_fault_esp\n\t" + "movl $1f, pnp_bios_fault_eip\n\t" + "lcall %5,%6\n\t" + "1:popfl\n\t" + "popl %%gs\n\t" + "popl %%fs\n\t" + "popl %%es\n\t" + "popl %%ds\n\t" + "popl %%esi\n\t" + "popl %%edi\n\t" + "popl %%ebp\n\t":"=a"(status) + :"0"((func) | (((u32) arg1) << 16)), + "b"((arg2) | (((u32) arg3) << 16)), + "c"((arg4) | (((u32) arg5) << 16)), + "d"((arg6) | (((u32) arg7) << 16)), + "i"(PNP_CS32), "i"(0) + :"memory"); spin_unlock_irqrestore(&pnp_bios_lock, flags); get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; put_cpu(); /* If we get here and this is set then the PnP BIOS faulted on us. */ - if(pnp_bios_is_utter_crap) - { - printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n"); - printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n"); - printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n"); + if (pnp_bios_is_utter_crap) { + printk(KERN_ERR + "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n"); + printk(KERN_ERR + "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n"); + printk(KERN_ERR + "PnPBIOS: Check with your vendor for an updated BIOS\n"); } return status; } -void pnpbios_print_status(const char * module, u16 status) +void pnpbios_print_status(const char *module, u16 status) { - switch(status) { + switch (status) { case PNP_SUCCESS: printk(KERN_ERR "PnPBIOS: %s: function successful\n", module); break; case PNP_NOT_SET_STATICALLY: - printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module); + printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", + module); break; case PNP_UNKNOWN_FUNCTION: - printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module); + printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", + module); break; case PNP_FUNCTION_NOT_SUPPORTED: - printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module); + printk(KERN_ERR + "PnPBIOS: %s: function not supported on this system\n", + module); break; case PNP_INVALID_HANDLE: printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module); break; case PNP_BAD_PARAMETER: - printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module); + printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", + module); break; case PNP_SET_FAILED: - printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module); + printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", + module); break; case PNP_EVENTS_NOT_PENDING: printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module); break; case PNP_SYSTEM_NOT_DOCKED: - printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module); + printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", + module); break; case PNP_NO_ISA_PNP_CARDS: - printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module); + printk(KERN_ERR + "PnPBIOS: %s: no isapnp cards are installed on this system\n", + module); break; case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES: - printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module); + printk(KERN_ERR + "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", + module); break; case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY: - printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module); + printk(KERN_ERR + "PnPBIOS: %s: unable to undock, the system does not have a battery\n", + module); break; case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT: - printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module); + printk(KERN_ERR + "PnPBIOS: %s: could not dock due to resource conflicts\n", + module); break; case PNP_BUFFER_TOO_SMALL: - printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module); + printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", + module); break; case PNP_USE_ESCD_SUPPORT: printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module); break; case PNP_MESSAGE_NOT_SUPPORTED: - printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module); + printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", + module); break; case PNP_HARDWARE_ERROR: - printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module); + printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", + module); break; default: - printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status); + printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, + status); break; } } - /* * PnP BIOS Low Level Calls */ @@ -243,19 +254,22 @@ void pnpbios_print_status(const char * module, u16 status) static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data) { u16 status; + if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0, - data, sizeof(struct pnp_dev_node_info), NULL, 0); + status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, + PNP_TS1, PNP_DS, 0, 0, data, + sizeof(struct pnp_dev_node_info), NULL, 0); data->no_nodes &= 0xff; return status; } int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) { - int status = __pnp_bios_dev_node_info( data ); - if ( status ) - pnpbios_print_status( "dev_node_info", status ); + int status = __pnp_bios_dev_node_info(data); + + if (status) + pnpbios_print_status("dev_node_info", status); return status; } @@ -273,17 +287,20 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) * or volatile current (0) config * Output: *nodenum=next node or 0xff if no more nodes */ -static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) +static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, + struct pnp_bios_node *data) { u16 status; u16 tmp_nodenum; + if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - if ( !boot && pnpbios_dont_use_current_config ) + if (!boot && pnpbios_dont_use_current_config) return PNP_FUNCTION_NOT_SUPPORTED; tmp_nodenum = *nodenum; - status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, - &tmp_nodenum, sizeof(tmp_nodenum), data, 65536); + status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, + boot ? 2 : 1, PNP_DS, 0, &tmp_nodenum, + sizeof(tmp_nodenum), data, 65536); *nodenum = tmp_nodenum; return status; } @@ -291,104 +308,66 @@ static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) { int status; - status = __pnp_bios_get_dev_node( nodenum, boot, data ); - if ( status ) - pnpbios_print_status( "get_dev_node", status ); + + status = __pnp_bios_get_dev_node(nodenum, boot, data); + if (status) + pnpbios_print_status("get_dev_node", status); return status; } - /* * Call PnP BIOS with function 0x02, "set system device node" * Input: *nodenum = desired node, * boot = whether to set nonvolatile boot (!=0) * or volatile current (0) config */ -static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) +static int __pnp_bios_set_dev_node(u8 nodenum, char boot, + struct pnp_bios_node *data) { u16 status; + if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - if ( !boot && pnpbios_dont_use_current_config ) + if (!boot && pnpbios_dont_use_current_config) return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0, - data, 65536, NULL, 0); + status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, + boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, NULL, + 0); return status; } int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) { int status; - status = __pnp_bios_set_dev_node( nodenum, boot, data ); - if ( status ) { - pnpbios_print_status( "set_dev_node", status ); + + status = __pnp_bios_set_dev_node(nodenum, boot, data); + if (status) { + pnpbios_print_status("set_dev_node", status); return status; } - if ( !boot ) { /* Update devlist */ - status = pnp_bios_get_dev_node( &nodenum, boot, data ); - if ( status ) + if (!boot) { /* Update devlist */ + status = pnp_bios_get_dev_node(&nodenum, boot, data); + if (status) return status; } return status; } -#if needed -/* - * Call PnP BIOS with function 0x03, "get event" - */ -static int pnp_bios_get_event(u16 *event) -{ - u16 status; - if (!pnp_bios_present()) - return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0, - event, sizeof(u16), NULL, 0); - return status; -} -#endif - -#if needed -/* - * Call PnP BIOS with function 0x04, "send message" - */ -static int pnp_bios_send_message(u16 message) -{ - u16 status; - if (!pnp_bios_present()) - return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0); - return status; -} -#endif - /* * Call PnP BIOS with function 0x05, "get docking station information" */ int pnp_bios_dock_station_info(struct pnp_docking_station_info *data) { u16 status; - if (!pnp_bios_present()) - return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, - data, sizeof(struct pnp_docking_station_info), NULL, 0); - return status; -} -#if needed -/* - * Call PnP BIOS with function 0x09, "set statically allocated resource - * information" - */ -static int pnp_bios_set_stat_res(char *info) -{ - u16 status; if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, - info, *((u16 *) info), 0, 0); + status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, + PNP_DS, 0, 0, 0, 0, data, + sizeof(struct pnp_docking_station_info), NULL, + 0); return status; } -#endif /* * Call PnP BIOS with function 0x0a, "get statically allocated resource @@ -397,36 +376,23 @@ static int pnp_bios_set_stat_res(char *info) static int __pnp_bios_get_stat_res(char *info) { u16 status; + if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, - info, 65536, NULL, 0); + status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, + PNP_DS, 0, 0, 0, 0, info, 65536, NULL, 0); return status; } int pnp_bios_get_stat_res(char *info) { int status; - status = __pnp_bios_get_stat_res( info ); - if ( status ) - pnpbios_print_status( "get_stat_res", status ); - return status; -} -#if needed -/* - * Call PnP BIOS with function 0x0b, "get APM id table" - */ -static int pnp_bios_apm_id_table(char *table, u16 *size) -{ - u16 status; - if (!pnp_bios_present()) - return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0, - table, *size, size, sizeof(u16)); + status = __pnp_bios_get_stat_res(info); + if (status) + pnpbios_print_status("get_stat_res", status); return status; } -#endif /* * Call PnP BIOS with function 0x40, "get isa pnp configuration structure" @@ -434,19 +400,22 @@ static int pnp_bios_apm_id_table(char *table, u16 *size) static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) { u16 status; + if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0, - data, sizeof(struct pnp_isa_config_struc), NULL, 0); + status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, + 0, 0, 0, 0, data, + sizeof(struct pnp_isa_config_struc), NULL, 0); return status; } int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) { int status; - status = __pnp_bios_isapnp_config( data ); - if ( status ) - pnpbios_print_status( "isapnp_config", status ); + + status = __pnp_bios_isapnp_config(data); + if (status) + pnpbios_print_status("isapnp_config", status); return status; } @@ -456,19 +425,22 @@ int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) static int __pnp_bios_escd_info(struct escd_info_struc *data) { u16 status; + if (!pnp_bios_present()) return ESCD_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS, - data, sizeof(struct escd_info_struc), NULL, 0); + status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, + PNP_TS1, PNP_DS, data, + sizeof(struct escd_info_struc), NULL, 0); return status; } int pnp_bios_escd_info(struct escd_info_struc *data) { int status; - status = __pnp_bios_escd_info( data ); - if ( status ) - pnpbios_print_status( "escd_info", status ); + + status = __pnp_bios_escd_info(data); + if (status) + pnpbios_print_status("escd_info", status); return status; } @@ -479,57 +451,42 @@ int pnp_bios_escd_info(struct escd_info_struc *data) static int __pnp_bios_read_escd(char *data, u32 nvram_base) { u16 status; + if (!pnp_bios_present()) return ESCD_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0, - data, 65536, __va(nvram_base), 65536); + status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, + 0, data, 65536, __va(nvram_base), 65536); return status; } int pnp_bios_read_escd(char *data, u32 nvram_base) { int status; - status = __pnp_bios_read_escd( data, nvram_base ); - if ( status ) - pnpbios_print_status( "read_escd", status ); - return status; -} -#if needed -/* - * Call PnP BIOS function 0x43, "write ESCD" - */ -static int pnp_bios_write_escd(char *data, u32 nvram_base) -{ - u16 status; - if (!pnp_bios_present()) - return ESCD_FUNCTION_NOT_SUPPORTED; - status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0, - data, 65536, __va(nvram_base), 65536); + status = __pnp_bios_read_escd(data, nvram_base); + if (status) + pnpbios_print_status("read_escd", status); return status; } -#endif - - -/* - * Initialization - */ void pnpbios_calls_init(union pnp_bios_install_struct *header) { int i; + spin_lock_init(&pnp_bios_lock); pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment = PNP_CS16; set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); - for (i = 0; i < NR_CPUS; i++) { - struct desc_struct *gdt = get_cpu_gdt_table(i); - if (!gdt) - continue; - set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc); - set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg)); - set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg)); - } + for (i = 0; i < NR_CPUS; i++) { + struct desc_struct *gdt = get_cpu_gdt_table(i); + if (!gdt) + continue; + set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc); + set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], + __va(header->fields.pm16cseg)); + set_base(gdt[GDT_ENTRY_PNPBIOS_DS], + __va(header->fields.pm16dseg)); + } } diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index ed112ee..3692a09 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -32,7 +32,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - + /* Change Log * * Adam Belay - <ambx1@neo.rr.com> - March 16, 2003 @@ -71,14 +71,13 @@ #include "pnpbios.h" - /* * * PnP BIOS INTERFACE * */ -static union pnp_bios_install_struct * pnp_bios_install = NULL; +static union pnp_bios_install_struct *pnp_bios_install = NULL; int pnp_bios_present(void) { @@ -101,36 +100,35 @@ static struct completion unload_sem; /* * (Much of this belongs in a shared routine somewhere) */ - static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) { - char *argv [3], **envp, *buf, *scratch; + char *argv[3], **envp, *buf, *scratch; int i = 0, value; - if (!current->fs->root) { + if (!current->fs->root) return -EAGAIN; - } - if (!(envp = kcalloc(20, sizeof (char *), GFP_KERNEL))) { + if (!(envp = kcalloc(20, sizeof(char *), GFP_KERNEL))) return -ENOMEM; - } if (!(buf = kzalloc(256, GFP_KERNEL))) { - kfree (envp); + kfree(envp); return -ENOMEM; } - /* FIXME: if there are actual users of this, it should be integrated into - * the driver core and use the usual infrastructure like sysfs and uevents */ - argv [0] = "/sbin/pnpbios"; - argv [1] = "dock"; - argv [2] = NULL; + /* FIXME: if there are actual users of this, it should be + * integrated into the driver core and use the usual infrastructure + * like sysfs and uevents + */ + argv[0] = "/sbin/pnpbios"; + argv[1] = "dock"; + argv[2] = NULL; /* minimal command environment */ - envp [i++] = "HOME=/"; - envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + envp[i++] = "HOME=/"; + envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; #ifdef DEBUG /* hint that policy agent should enter no-stdout debug mode */ - envp [i++] = "DEBUG=kernel"; + envp[i++] = "DEBUG=kernel"; #endif /* extensible set of named bus-specific parameters, * supporting multiple driver selection algorithms. @@ -138,33 +136,33 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) scratch = buf; /* action: add, remove */ - envp [i++] = scratch; - scratch += sprintf (scratch, "ACTION=%s", dock?"add":"remove") + 1; + envp[i++] = scratch; + scratch += sprintf(scratch, "ACTION=%s", dock ? "add" : "remove") + 1; /* Report the ident for the dock */ - envp [i++] = scratch; - scratch += sprintf (scratch, "DOCK=%x/%x/%x", - info->location_id, info->serial, info->capabilities); + envp[i++] = scratch; + scratch += sprintf(scratch, "DOCK=%x/%x/%x", + info->location_id, info->serial, info->capabilities); envp[i] = NULL; - - value = call_usermodehelper (argv [0], argv, envp, UMH_WAIT_EXEC); - kfree (buf); - kfree (envp); + + value = call_usermodehelper(argv [0], argv, envp, UMH_WAIT_EXEC); + kfree(buf); + kfree(envp); return 0; } /* * Poll the PnP docking at regular intervals */ -static int pnp_dock_thread(void * unused) +static int pnp_dock_thread(void *unused) { static struct pnp_docking_station_info now; int docked = -1, d = 0; + set_freezable(); - while (!unloading) - { + while (!unloading) { int status; - + /* * Poll every 2 seconds */ @@ -175,30 +173,29 @@ static int pnp_dock_thread(void * unused) status = pnp_bios_dock_station_info(&now); - switch(status) - { + switch (status) { /* * No dock to manage */ - case PNP_FUNCTION_NOT_SUPPORTED: - complete_and_exit(&unload_sem, 0); - case PNP_SYSTEM_NOT_DOCKED: - d = 0; - break; - case PNP_SUCCESS: - d = 1; - break; - default: - pnpbios_print_status( "pnp_dock_thread", status ); - continue; + case PNP_FUNCTION_NOT_SUPPORTED: + complete_and_exit(&unload_sem, 0); + case PNP_SYSTEM_NOT_DOCKED: + d = 0; + break; + case PNP_SUCCESS: + d = 1; + break; + default: + pnpbios_print_status("pnp_dock_thread", status); + continue; } - if(d != docked) - { - if(pnp_dock_event(d, &now)==0) - { + if (d != docked) { + if (pnp_dock_event(d, &now) == 0) { docked = d; #if 0 - printk(KERN_INFO "PnPBIOS: Docking station %stached\n", docked?"at":"de"); + printk(KERN_INFO + "PnPBIOS: Docking station %stached\n", + docked ? "at" : "de"); #endif } } @@ -206,21 +203,21 @@ static int pnp_dock_thread(void * unused) complete_and_exit(&unload_sem, 0); } -#endif /* CONFIG_HOTPLUG */ +#endif /* CONFIG_HOTPLUG */ -static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res) +static int pnpbios_get_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { u8 nodenum = dev->number; - struct pnp_bios_node * node; + struct pnp_bios_node *node; - /* just in case */ - if(!pnpbios_is_dynamic(dev)) + if (!pnpbios_is_dynamic(dev)) return -EPERM; node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { + if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) { kfree(node); return -ENODEV; } @@ -230,24 +227,24 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table return 0; } -static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table * res) +static int pnpbios_set_resources(struct pnp_dev *dev, + struct pnp_resource_table *res) { u8 nodenum = dev->number; - struct pnp_bios_node * node; + struct pnp_bios_node *node; int ret; - /* just in case */ if (!pnpbios_is_dynamic(dev)) return -EPERM; node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { + if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) { kfree(node); return -ENODEV; } - if(pnpbios_write_resources_to_node(res, node)<0) { + if (pnpbios_write_resources_to_node(res, node) < 0) { kfree(node); return -1; } @@ -258,18 +255,19 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table return ret; } -static void pnpbios_zero_data_stream(struct pnp_bios_node * node) +static void pnpbios_zero_data_stream(struct pnp_bios_node *node) { - unsigned char * p = (char *)node->data; - unsigned char * end = (char *)(node->data + node->size); + unsigned char *p = (char *)node->data; + unsigned char *end = (char *)(node->data + node->size); unsigned int len; int i; + while ((char *)p < (char *)end) { - if(p[0] & 0x80) { /* large tag */ + if (p[0] & 0x80) { /* large tag */ len = (p[2] << 8) | p[1]; p += 3; } else { - if (((p[0]>>3) & 0x0f) == 0x0f) + if (((p[0] >> 3) & 0x0f) == 0x0f) return; len = p[0] & 0x07; p += 1; @@ -278,24 +276,24 @@ static void pnpbios_zero_data_stream(struct pnp_bios_node * node) p[i] = 0; p += len; } - printk(KERN_ERR "PnPBIOS: Resource structure did not contain an end tag.\n"); + printk(KERN_ERR + "PnPBIOS: Resource structure did not contain an end tag.\n"); } static int pnpbios_disable_resources(struct pnp_dev *dev) { - struct pnp_bios_node * node; + struct pnp_bios_node *node; u8 nodenum = dev->number; int ret; - /* just in case */ - if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) + if (dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) return -EPERM; node = kzalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { + if (pnp_bios_get_dev_node(&nodenum, (char)PNPMODE_DYNAMIC, node)) { kfree(node); return -ENODEV; } @@ -311,22 +309,22 @@ static int pnpbios_disable_resources(struct pnp_dev *dev) /* PnP Layer support */ struct pnp_protocol pnpbios_protocol = { - .name = "Plug and Play BIOS", - .get = pnpbios_get_resources, - .set = pnpbios_set_resources, + .name = "Plug and Play BIOS", + .get = pnpbios_get_resources, + .set = pnpbios_set_resources, .disable = pnpbios_disable_resources, }; -static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) +static int insert_device(struct pnp_dev *dev, struct pnp_bios_node *node) { - struct list_head * pos; - struct pnp_dev * pnp_dev; + struct list_head *pos; + struct pnp_dev *pnp_dev; struct pnp_id *dev_id; char id[8]; /* check if the device is already added */ dev->number = node->handle; - list_for_each (pos, &pnpbios_protocol.devices){ + list_for_each(pos, &pnpbios_protocol.devices) { pnp_dev = list_entry(pos, struct pnp_dev, protocol_list); if (dev->number == pnp_dev->number) return -1; @@ -336,8 +334,8 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) return -1; - pnpid32_to_pnpid(node->eisa_id,id); - memcpy(dev_id->id,id,7); + pnpid32_to_pnpid(node->eisa_id, id); + memcpy(dev_id->id, id, 7); pnp_add_id(dev_id, dev); pnpbios_parse_data_stream(dev, node); dev->active = pnp_is_active(dev); @@ -375,35 +373,41 @@ static void __init build_devlist(void) if (!node) return; - for(nodenum=0; nodenum<0xff; ) { + for (nodenum = 0; nodenum < 0xff;) { u8 thisnodenum = nodenum; /* eventually we will want to use PNPMODE_STATIC here but for now * dynamic will help us catch buggy bioses to add to the blacklist. */ if (!pnpbios_dont_use_current_config) { - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) + if (pnp_bios_get_dev_node + (&nodenum, (char)PNPMODE_DYNAMIC, node)) break; } else { - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_STATIC, node)) + if (pnp_bios_get_dev_node + (&nodenum, (char)PNPMODE_STATIC, node)) break; } nodes_got++; - dev = kzalloc(sizeof (struct pnp_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) break; - if(insert_device(dev,node)<0) + if (insert_device(dev, node) < 0) kfree(dev); else devs++; if (nodenum <= thisnodenum) { - printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum); + printk(KERN_ERR + "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", + (unsigned int)nodenum, + (unsigned int)thisnodenum); break; } } kfree(node); - printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n", - nodes_got, nodes_got != 1 ? "s" : "", devs); + printk(KERN_INFO + "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n", + nodes_got, nodes_got != 1 ? "s" : "", devs); } /* @@ -412,8 +416,8 @@ static void __init build_devlist(void) * */ -static int pnpbios_disabled; /* = 0 */ -int pnpbios_dont_use_current_config; /* = 0 */ +static int pnpbios_disabled; +int pnpbios_dont_use_current_config; #ifndef MODULE static int __init pnpbios_setup(char *str) @@ -422,9 +426,9 @@ static int __init pnpbios_setup(char *str) while ((str != NULL) && (*str != '\0')) { if (strncmp(str, "off", 3) == 0) - pnpbios_disabled=1; + pnpbios_disabled = 1; if (strncmp(str, "on", 2) == 0) - pnpbios_disabled=0; + pnpbios_disabled = 0; invert = (strncmp(str, "no-", 3) == 0); if (invert) str += 3; @@ -453,35 +457,41 @@ static int __init pnpbios_probe_system(void) printk(KERN_INFO "PnPBIOS: Scanning system for PnP BIOS support...\n"); /* - * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS + * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS * structure and, if one is found, sets up the selectors and * entry points */ - for (check = (union pnp_bios_install_struct *) __va(0xf0000); - check < (union pnp_bios_install_struct *) __va(0xffff0); + for (check = (union pnp_bios_install_struct *)__va(0xf0000); + check < (union pnp_bios_install_struct *)__va(0xffff0); check = (void *)check + 16) { if (check->fields.signature != PNP_SIGNATURE) continue; - printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check); + printk(KERN_INFO + "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", + check); length = check->fields.length; if (!length) { - printk(KERN_ERR "PnPBIOS: installation structure is invalid, skipping\n"); + printk(KERN_ERR + "PnPBIOS: installation structure is invalid, skipping\n"); continue; } for (sum = 0, i = 0; i < length; i++) sum += check->chars[i]; if (sum) { - printk(KERN_ERR "PnPBIOS: installation structure is corrupted, skipping\n"); + printk(KERN_ERR + "PnPBIOS: installation structure is corrupted, skipping\n"); continue; } if (check->fields.version < 0x10) { - printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n", + printk(KERN_WARNING + "PnPBIOS: PnP BIOS version %d.%d is not supported\n", check->fields.version >> 4, check->fields.version & 15); continue; } - printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n", - check->fields.version >> 4, check->fields.version & 15, + printk(KERN_INFO + "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n", + check->fields.version >> 4, check->fields.version & 15, check->fields.pm16cseg, check->fields.pm16offset, check->fields.pm16dseg); pnp_bios_install = check; @@ -499,25 +509,25 @@ static int __init exploding_pnp_bios(struct dmi_system_id *d) } static struct dmi_system_id pnpbios_dmi_table[] __initdata = { - { /* PnPBIOS GPF on boot */ - .callback = exploding_pnp_bios, - .ident = "Higraded P14H", - .matches = { - DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), - DMI_MATCH(DMI_BIOS_VERSION, "07.00T"), - DMI_MATCH(DMI_SYS_VENDOR, "Higraded"), - DMI_MATCH(DMI_PRODUCT_NAME, "P14H"), - }, - }, - { /* PnPBIOS GPF on boot */ - .callback = exploding_pnp_bios, - .ident = "ASUS P4P800", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_BOARD_NAME, "P4P800"), - }, - }, - { } + { /* PnPBIOS GPF on boot */ + .callback = exploding_pnp_bios, + .ident = "Higraded P14H", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + DMI_MATCH(DMI_BIOS_VERSION, "07.00T"), + DMI_MATCH(DMI_SYS_VENDOR, "Higraded"), + DMI_MATCH(DMI_PRODUCT_NAME, "P14H"), + }, + }, + { /* PnPBIOS GPF on boot */ + .callback = exploding_pnp_bios, + .ident = "ASUS P4P800", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_BOARD_NAME, "P4P800"), + }, + }, + {} }; static int __init pnpbios_init(void) @@ -533,14 +543,13 @@ static int __init pnpbios_init(void) printk(KERN_INFO "PnPBIOS: Disabled\n"); return -ENODEV; } - #ifdef CONFIG_PNPACPI if (!acpi_disabled && !pnpacpi_disabled) { pnpbios_disabled = 1; printk(KERN_INFO "PnPBIOS: Disabled by ACPI PNP\n"); return -ENODEV; } -#endif /* CONFIG_ACPI */ +#endif /* CONFIG_ACPI */ /* scan the system for pnpbios support */ if (!pnpbios_probe_system()) @@ -552,14 +561,16 @@ static int __init pnpbios_init(void) /* read the node info */ ret = pnp_bios_dev_node_info(&node_info); if (ret) { - printk(KERN_ERR "PnPBIOS: Unable to get node info. Aborting.\n"); + printk(KERN_ERR + "PnPBIOS: Unable to get node info. Aborting.\n"); return ret; } /* register with the pnp layer */ ret = pnp_register_protocol(&pnpbios_protocol); if (ret) { - printk(KERN_ERR "PnPBIOS: Unable to register driver. Aborting.\n"); + printk(KERN_ERR + "PnPBIOS: Unable to register driver. Aborting.\n"); return ret; } diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index 8027073..9c8c077 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c @@ -18,9 +18,6 @@ * The other files are human-readable. */ -//#include <pcmcia/config.h> -//#include <pcmcia/k_compat.h> - #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -37,42 +34,37 @@ static struct proc_dir_entry *proc_pnp = NULL; static struct proc_dir_entry *proc_pnp_boot = NULL; static int proc_read_pnpconfig(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { struct pnp_isa_config_struc pnps; if (pnp_bios_isapnp_config(&pnps)) return -EIO; return snprintf(buf, count, - "structure_revision %d\n" - "number_of_CSNs %d\n" - "ISA_read_data_port 0x%x\n", - pnps.revision, - pnps.no_csns, - pnps.isa_rd_data_port - ); + "structure_revision %d\n" + "number_of_CSNs %d\n" + "ISA_read_data_port 0x%x\n", + pnps.revision, pnps.no_csns, pnps.isa_rd_data_port); } static int proc_read_escdinfo(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { struct escd_info_struc escd; if (pnp_bios_escd_info(&escd)) return -EIO; return snprintf(buf, count, - "min_ESCD_write_size %d\n" - "ESCD_size %d\n" - "NVRAM_base 0x%x\n", - escd.min_escd_write_size, - escd.escd_size, - escd.nv_storage_base - ); + "min_ESCD_write_size %d\n" + "ESCD_size %d\n" + "NVRAM_base 0x%x\n", + escd.min_escd_write_size, + escd.escd_size, escd.nv_storage_base); } #define MAX_SANE_ESCD_SIZE (32*1024) static int proc_read_escd(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { struct escd_info_struc escd; char *tmpbuf; @@ -83,30 +75,36 @@ static int proc_read_escd(char *buf, char **start, off_t pos, /* sanity check */ if (escd.escd_size > MAX_SANE_ESCD_SIZE) { - printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n"); + printk(KERN_ERR + "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n"); return -EFBIG; } tmpbuf = kzalloc(escd.escd_size, GFP_KERNEL); - if (!tmpbuf) return -ENOMEM; + if (!tmpbuf) + return -ENOMEM; if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) { kfree(tmpbuf); return -EIO; } - escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256; + escd_size = + (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1]) * 256; /* sanity check */ if (escd_size > MAX_SANE_ESCD_SIZE) { - printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by BIOS read_escd call is too great\n"); + printk(KERN_ERR + "PnPBIOS: proc_read_escd: ESCD size reported by BIOS read_escd call is too great\n"); return -EFBIG; } escd_left_to_read = escd_size - pos; - if (escd_left_to_read < 0) escd_left_to_read = 0; - if (escd_left_to_read == 0) *eof = 1; - n = min(count,escd_left_to_read); + if (escd_left_to_read < 0) + escd_left_to_read = 0; + if (escd_left_to_read == 0) + *eof = 1; + n = min(count, escd_left_to_read); memcpy(buf, tmpbuf + pos, n); kfree(tmpbuf); *start = buf; @@ -114,17 +112,17 @@ static int proc_read_escd(char *buf, char **start, off_t pos, } static int proc_read_legacyres(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { /* Assume that the following won't overflow the buffer */ - if (pnp_bios_get_stat_res(buf)) + if (pnp_bios_get_stat_res(buf)) return -EIO; - return count; // FIXME: Return actual length + return count; // FIXME: Return actual length } static int proc_read_devices(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { struct pnp_bios_node *node; u8 nodenum; @@ -134,9 +132,10 @@ static int proc_read_devices(char *buf, char **start, off_t pos, return 0; node = kzalloc(node_info.max_node_size, GFP_KERNEL); - if (!node) return -ENOMEM; + if (!node) + return -ENOMEM; - for (nodenum=pos; nodenum<0xff; ) { + for (nodenum = pos; nodenum < 0xff;) { u8 thisnodenum = nodenum; /* 26 = the number of characters per line sprintf'ed */ if ((p - buf + 26) > count) @@ -148,7 +147,11 @@ static int proc_read_devices(char *buf, char **start, off_t pos, node->type_code[0], node->type_code[1], node->type_code[2], node->flags); if (nodenum <= thisnodenum) { - printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum); + printk(KERN_ERR + "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", + "PnPBIOS: proc_read_devices:", + (unsigned int)nodenum, + (unsigned int)thisnodenum); *eof = 1; break; } @@ -156,12 +159,12 @@ static int proc_read_devices(char *buf, char **start, off_t pos, kfree(node); if (nodenum == 0xff) *eof = 1; - *start = (char *)((off_t)nodenum - pos); + *start = (char *)((off_t) nodenum - pos); return p - buf; } static int proc_read_node(char *buf, char **start, off_t pos, - int count, int *eof, void *data) + int count, int *eof, void *data) { struct pnp_bios_node *node; int boot = (long)data >> 8; @@ -169,7 +172,8 @@ static int proc_read_node(char *buf, char **start, off_t pos, int len; node = kzalloc(node_info.max_node_size, GFP_KERNEL); - if (!node) return -ENOMEM; + if (!node) + return -ENOMEM; if (pnp_bios_get_dev_node(&nodenum, boot, node)) { kfree(node); return -EIO; @@ -180,8 +184,8 @@ static int proc_read_node(char *buf, char **start, off_t pos, return len; } -static int proc_write_node(struct file *file, const char __user *buf, - unsigned long count, void *data) +static int proc_write_node(struct file *file, const char __user * buf, + unsigned long count, void *data) { struct pnp_bios_node *node; int boot = (long)data >> 8; @@ -208,12 +212,12 @@ static int proc_write_node(struct file *file, const char __user *buf, goto out; } ret = count; -out: + out: kfree(node); return ret; } -int pnpbios_interface_attach_device(struct pnp_bios_node * node) +int pnpbios_interface_attach_device(struct pnp_bios_node *node) { char name[3]; struct proc_dir_entry *ent; @@ -222,7 +226,7 @@ int pnpbios_interface_attach_device(struct pnp_bios_node * node) if (!proc_pnp) return -EIO; - if ( !pnpbios_dont_use_current_config ) { + if (!pnpbios_dont_use_current_config) { ent = create_proc_entry(name, 0, proc_pnp); if (ent) { ent->read_proc = proc_read_node; @@ -237,7 +241,7 @@ int pnpbios_interface_attach_device(struct pnp_bios_node * node) if (ent) { ent->read_proc = proc_read_node; ent->write_proc = proc_write_node; - ent->data = (void *)(long)(node->handle+0x100); + ent->data = (void *)(long)(node->handle + 0x100); return 0; } @@ -249,7 +253,7 @@ int pnpbios_interface_attach_device(struct pnp_bios_node * node) * work and the pnpbios_dont_use_current_config flag * should already have been set to the appropriate value */ -int __init pnpbios_proc_init( void ) +int __init pnpbios_proc_init(void) { proc_pnp = proc_mkdir("pnp", proc_bus); if (!proc_pnp) @@ -258,10 +262,13 @@ int __init pnpbios_proc_init( void ) if (!proc_pnp_boot) return -EIO; create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL); - create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL); - create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL); + create_proc_read_entry("configuration_info", 0, proc_pnp, + proc_read_pnpconfig, NULL); + create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, + NULL); create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL); - create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL); + create_proc_read_entry("legacy_device_resources", 0, proc_pnp, + proc_read_legacyres, NULL); return 0; } @@ -274,9 +281,9 @@ void __exit pnpbios_proc_exit(void) if (!proc_pnp) return; - for (i=0; i<0xff; i++) { + for (i = 0; i < 0xff; i++) { sprintf(name, "%02x", i); - if ( !pnpbios_dont_use_current_config ) + if (!pnpbios_dont_use_current_config) remove_proc_entry(name, proc_pnp); remove_proc_entry(name, proc_pnp_boot); } @@ -287,6 +294,4 @@ void __exit pnpbios_proc_exit(void) remove_proc_entry("devices", proc_pnp); remove_proc_entry("boot", proc_pnp); remove_proc_entry("pnp", proc_bus); - - return; } diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 3c2ab839..04ecd7b 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -1,6 +1,5 @@ /* * rsparser.c - parses and encodes pnpbios resource data streams - * */ #include <linux/ctype.h> @@ -12,8 +11,10 @@ #ifdef CONFIG_PCI #include <linux/pci.h> #else -inline void pcibios_penalize_isa_irq(int irq, int active) {} -#endif /* CONFIG_PCI */ +inline void pcibios_penalize_isa_irq(int irq, int active) +{ +} +#endif /* CONFIG_PCI */ #include "pnpbios.h" @@ -52,75 +53,88 @@ inline void pcibios_penalize_isa_irq(int irq, int active) {} * Allocated Resources */ -static void -pnpbios_parse_allocated_irqresource(struct pnp_resource_table * res, int irq) +static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res, + int irq) { int i = 0; - while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_IRQ) i++; + + while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) + && i < PNP_MAX_IRQ) + i++; if (i < PNP_MAX_IRQ) { - res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag + res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag if (irq == -1) { res->irq_resource[i].flags |= IORESOURCE_DISABLED; return; } res->irq_resource[i].start = - res->irq_resource[i].end = (unsigned long) irq; + res->irq_resource[i].end = (unsigned long)irq; pcibios_penalize_isa_irq(irq, 1); } } -static void -pnpbios_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma) +static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res, + int dma) { int i = 0; + while (i < PNP_MAX_DMA && - !(res->dma_resource[i].flags & IORESOURCE_UNSET)) + !(res->dma_resource[i].flags & IORESOURCE_UNSET)) i++; if (i < PNP_MAX_DMA) { - res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag + res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag if (dma == -1) { res->dma_resource[i].flags |= IORESOURCE_DISABLED; return; } res->dma_resource[i].start = - res->dma_resource[i].end = (unsigned long) dma; + res->dma_resource[i].end = (unsigned long)dma; } } -static void -pnpbios_parse_allocated_ioresource(struct pnp_resource_table * res, int io, int len) +static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res, + int io, int len) { int i = 0; - while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_PORT) i++; + + while (!(res->port_resource[i].flags & IORESOURCE_UNSET) + && i < PNP_MAX_PORT) + i++; if (i < PNP_MAX_PORT) { - res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag - if (len <= 0 || (io + len -1) >= 0x10003) { + res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag + if (len <= 0 || (io + len - 1) >= 0x10003) { res->port_resource[i].flags |= IORESOURCE_DISABLED; return; } - res->port_resource[i].start = (unsigned long) io; + res->port_resource[i].start = (unsigned long)io; res->port_resource[i].end = (unsigned long)(io + len - 1); } } -static void -pnpbios_parse_allocated_memresource(struct pnp_resource_table * res, int mem, int len) +static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res, + int mem, int len) { int i = 0; - while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_MEM) i++; + + while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) + && i < PNP_MAX_MEM) + i++; if (i < PNP_MAX_MEM) { - res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag + res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag if (len <= 0) { res->mem_resource[i].flags |= IORESOURCE_DISABLED; return; } - res->mem_resource[i].start = (unsigned long) mem; + res->mem_resource[i].start = (unsigned long)mem; res->mem_resource[i].end = (unsigned long)(mem + len - 1); } } -static unsigned char * -pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) +static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, + unsigned char *end, + struct + pnp_resource_table + *res) { unsigned int len, tag; int io, size, mask, i; @@ -134,12 +148,12 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st while ((char *)p < (char *)end) { /* determine the type of tag */ - if (p[0] & LARGE_TAG) { /* large tag */ + if (p[0] & LARGE_TAG) { /* large tag */ len = (p[2] << 8) | p[1]; tag = p[0]; - } else { /* small tag */ + } else { /* small tag */ len = p[0] & 0x07; - tag = ((p[0]>>3) & 0x0f); + tag = ((p[0] >> 3) & 0x0f); } switch (tag) { @@ -147,8 +161,8 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st case LARGE_TAG_MEM: if (len != 9) goto len_err; - io = *(short *) &p[4]; - size = *(short *) &p[10]; + io = *(short *)&p[4]; + size = *(short *)&p[10]; pnpbios_parse_allocated_memresource(res, io, size); break; @@ -163,16 +177,16 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st case LARGE_TAG_MEM32: if (len != 17) goto len_err; - io = *(int *) &p[4]; - size = *(int *) &p[16]; + io = *(int *)&p[4]; + size = *(int *)&p[16]; pnpbios_parse_allocated_memresource(res, io, size); break; case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err; - io = *(int *) &p[4]; - size = *(int *) &p[8]; + io = *(int *)&p[4]; + size = *(int *)&p[8]; pnpbios_parse_allocated_memresource(res, io, size); break; @@ -180,9 +194,10 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st if (len < 2 || len > 3) goto len_err; io = -1; - mask= p[1] + p[2]*256; - for (i=0;i<16;i++, mask=mask>>1) - if(mask & 0x01) io=i; + mask = p[1] + p[2] * 256; + for (i = 0; i < 16; i++, mask = mask >> 1) + if (mask & 0x01) + io = i; pnpbios_parse_allocated_irqresource(res, io); break; @@ -191,15 +206,16 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st goto len_err; io = -1; mask = p[1]; - for (i=0;i<8;i++, mask = mask>>1) - if(mask & 0x01) io=i; + for (i = 0; i < 8; i++, mask = mask >> 1) + if (mask & 0x01) + io = i; pnpbios_parse_allocated_dmaresource(res, io); break; case SMALL_TAG_PORT: if (len != 7) goto len_err; - io = p[2] + p[3] *256; + io = p[2] + p[3] * 256; size = p[7]; pnpbios_parse_allocated_ioresource(res, io, size); break; @@ -218,12 +234,14 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st case SMALL_TAG_END: p = p + 2; - return (unsigned char *)p; + return (unsigned char *)p; break; - default: /* an unkown tag */ - len_err: - printk(KERN_ERR "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len); + default: /* an unkown tag */ + len_err: + printk(KERN_ERR + "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", + tag, len); break; } @@ -234,20 +252,21 @@ pnpbios_parse_allocated_resource_data(unsigned char * p, unsigned char * end, st p += len + 1; } - printk(KERN_ERR "PnPBIOS: Resource structure does not contain an end tag.\n"); + printk(KERN_ERR + "PnPBIOS: Resource structure does not contain an end tag.\n"); return NULL; } - /* * Resource Configuration Options */ -static void -pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_mem_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_mem * mem; + struct pnp_mem *mem; + mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; @@ -256,14 +275,14 @@ pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option) mem->align = (p[9] << 8) | p[8]; mem->size = ((p[11] << 8) | p[10]) << 8; mem->flags = p[3]; - pnp_register_mem_resource(option,mem); - return; + pnp_register_mem_resource(option, mem); } -static void -pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_mem32_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_mem * mem; + struct pnp_mem *mem; + mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; @@ -272,14 +291,13 @@ pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; mem->flags = p[3]; - pnp_register_mem_resource(option,mem); - return; + pnp_register_mem_resource(option, mem); } -static void -pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_mem * mem; + struct pnp_mem *mem; mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL); if (!mem) return; @@ -287,14 +305,13 @@ pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option * mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; mem->align = 0; mem->flags = p[3]; - pnp_register_mem_resource(option,mem); - return; + pnp_register_mem_resource(option, mem); } -static void -pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_irq_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_irq * irq; + struct pnp_irq *irq; unsigned long bits; irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL); @@ -306,27 +323,27 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option) irq->flags = p[3]; else irq->flags = IORESOURCE_IRQ_HIGHEDGE; - pnp_register_irq_resource(option,irq); - return; + pnp_register_irq_resource(option, irq); } -static void -pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_dma_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_dma * dma; + struct pnp_dma *dma; + dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL); if (!dma) return; dma->map = p[1]; dma->flags = p[2]; - pnp_register_dma_resource(option,dma); - return; + pnp_register_dma_resource(option, dma); } -static void -pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_port_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_port * port; + struct pnp_port *port; + port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; @@ -335,14 +352,14 @@ pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option) port->align = p[6]; port->size = p[7]; port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option,port); - return; + pnp_register_port_resource(option, port); } -static void -pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option) +static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, + struct pnp_option *option) { - struct pnp_port * port; + struct pnp_port *port; + port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); if (!port) return; @@ -350,12 +367,12 @@ pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *o port->size = p[3]; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); - return; + pnp_register_port_resource(option, port); } -static unsigned char * -pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struct pnp_dev *dev) +static unsigned char *pnpbios_parse_resource_option_data(unsigned char *p, + unsigned char *end, + struct pnp_dev *dev) { unsigned int len, tag; int priority = 0; @@ -371,12 +388,12 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc while ((char *)p < (char *)end) { /* determine the type of tag */ - if (p[0] & LARGE_TAG) { /* large tag */ + if (p[0] & LARGE_TAG) { /* large tag */ len = (p[2] << 8) | p[1]; tag = p[0]; - } else { /* small tag */ + } else { /* small tag */ len = p[0] & 0x07; - tag = ((p[0]>>3) & 0x0f); + tag = ((p[0] >> 3) & 0x0f); } switch (tag) { @@ -442,16 +459,19 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc if (len != 0) goto len_err; if (option_independent == option) - printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); + printk(KERN_WARNING + "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); option = option_independent; break; case SMALL_TAG_END: - return p + 2; + return p + 2; - default: /* an unkown tag */ - len_err: - printk(KERN_ERR "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len); + default: /* an unkown tag */ + len_err: + printk(KERN_ERR + "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", + tag, len); break; } @@ -462,19 +482,18 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc p += len + 1; } - printk(KERN_ERR "PnPBIOS: Resource structure does not contain an end tag.\n"); + printk(KERN_ERR + "PnPBIOS: Resource structure does not contain an end tag.\n"); return NULL; } - /* * Compatible Device IDs */ #define HEX(id,a) hex[((id)>>a) & 15] #define CHAR(id,a) (0x40 + (((id)>>a) & 31)) -// void pnpid32_to_pnpid(u32 id, char *str) { @@ -483,21 +502,20 @@ void pnpid32_to_pnpid(u32 id, char *str) id = be32_to_cpu(id); str[0] = CHAR(id, 26); str[1] = CHAR(id, 21); - str[2] = CHAR(id,16); + str[2] = CHAR(id, 16); str[3] = HEX(id, 12); str[4] = HEX(id, 8); str[5] = HEX(id, 4); str[6] = HEX(id, 0); str[7] = '\0'; - - return; } -// + #undef CHAR #undef HEX -static unsigned char * -pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_dev *dev) +static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, + unsigned char *end, + struct pnp_dev *dev) { int len, tag; char id[8]; @@ -509,40 +527,45 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de while ((char *)p < (char *)end) { /* determine the type of tag */ - if (p[0] & LARGE_TAG) { /* large tag */ + if (p[0] & LARGE_TAG) { /* large tag */ len = (p[2] << 8) | p[1]; tag = p[0]; - } else { /* small tag */ + } else { /* small tag */ len = p[0] & 0x07; - tag = ((p[0]>>3) & 0x0f); + tag = ((p[0] >> 3) & 0x0f); } switch (tag) { case LARGE_TAG_ANSISTR: - strncpy(dev->name, p + 3, len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len); - dev->name[len >= PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0'; + strncpy(dev->name, p + 3, + len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len); + dev->name[len >= + PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0'; break; - case SMALL_TAG_COMPATDEVID: /* compatible ID */ + case SMALL_TAG_COMPATDEVID: /* compatible ID */ if (len != 4) goto len_err; - dev_id = kzalloc(sizeof (struct pnp_id), GFP_KERNEL); + dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) return NULL; - pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24,id); + pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << + 24, id); memcpy(&dev_id->id, id, 7); pnp_add_id(dev_id, dev); break; case SMALL_TAG_END: p = p + 2; - return (unsigned char *)p; + return (unsigned char *)p; break; - default: /* an unkown tag */ - len_err: - printk(KERN_ERR "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len); + default: /* an unkown tag */ + len_err: + printk(KERN_ERR + "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", + tag, len); break; } @@ -553,33 +576,34 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de p += len + 1; } - printk(KERN_ERR "PnPBIOS: Resource structure does not contain an end tag.\n"); + printk(KERN_ERR + "PnPBIOS: Resource structure does not contain an end tag.\n"); return NULL; } - /* * Allocated Resource Encoding */ -static void pnpbios_encode_mem(unsigned char *p, struct resource * res) +static void pnpbios_encode_mem(unsigned char *p, struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; + p[4] = (base >> 8) & 0xff; p[5] = ((base >> 8) >> 8) & 0xff; p[6] = (base >> 8) & 0xff; p[7] = ((base >> 8) >> 8) & 0xff; p[10] = (len >> 8) & 0xff; p[11] = ((len >> 8) >> 8) & 0xff; - return; } -static void pnpbios_encode_mem32(unsigned char *p, struct resource * res) +static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; + p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; p[6] = (base >> 16) & 0xff; @@ -592,12 +616,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource * res) p[17] = (len >> 8) & 0xff; p[18] = (len >> 16) & 0xff; p[19] = (len >> 24) & 0xff; - return; } -static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource * res) -{ unsigned long base = res->start; +static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) +{ + unsigned long base = res->start; unsigned long len = res->end - res->start + 1; + p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; p[6] = (base >> 16) & 0xff; @@ -606,50 +631,52 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource * res) p[9] = (len >> 8) & 0xff; p[10] = (len >> 16) & 0xff; p[11] = (len >> 24) & 0xff; - return; } -static void pnpbios_encode_irq(unsigned char *p, struct resource * res) +static void pnpbios_encode_irq(unsigned char *p, struct resource *res) { unsigned long map = 0; + map = 1 << res->start; p[1] = map & 0xff; p[2] = (map >> 8) & 0xff; - return; } -static void pnpbios_encode_dma(unsigned char *p, struct resource * res) +static void pnpbios_encode_dma(unsigned char *p, struct resource *res) { unsigned long map = 0; + map = 1 << res->start; p[1] = map & 0xff; - return; } -static void pnpbios_encode_port(unsigned char *p, struct resource * res) +static void pnpbios_encode_port(unsigned char *p, struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; + p[2] = base & 0xff; p[3] = (base >> 8) & 0xff; p[4] = base & 0xff; p[5] = (base >> 8) & 0xff; p[7] = len & 0xff; - return; } -static void pnpbios_encode_fixed_port(unsigned char *p, struct resource * res) +static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) { unsigned long base = res->start; unsigned long len = res->end - res->start + 1; + p[1] = base & 0xff; p[2] = (base >> 8) & 0xff; p[3] = len & 0xff; - return; } -static unsigned char * -pnpbios_encode_allocated_resource_data(unsigned char * p, unsigned char * end, struct pnp_resource_table * res) +static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, + unsigned char *end, + struct + pnp_resource_table + *res) { unsigned int len, tag; int port = 0, irq = 0, dma = 0, mem = 0; @@ -660,12 +687,12 @@ pnpbios_encode_allocated_resource_data(unsigned char * p, unsigned char * end, s while ((char *)p < (char *)end) { /* determine the type of tag */ - if (p[0] & LARGE_TAG) { /* large tag */ + if (p[0] & LARGE_TAG) { /* large tag */ len = (p[2] << 8) | p[1]; tag = p[0]; - } else { /* small tag */ + } else { /* small tag */ len = p[0] & 0x07; - tag = ((p[0]>>3) & 0x0f); + tag = ((p[0] >> 3) & 0x0f); } switch (tag) { @@ -725,12 +752,14 @@ pnpbios_encode_allocated_resource_data(unsigned char * p, unsigned char * end, s case SMALL_TAG_END: p = p + 2; - return (unsigned char *)p; + return (unsigned char *)p; break; - default: /* an unkown tag */ - len_err: - printk(KERN_ERR "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", tag, len); + default: /* an unkown tag */ + len_err: + printk(KERN_ERR + "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", + tag, len); break; } @@ -741,52 +770,52 @@ pnpbios_encode_allocated_resource_data(unsigned char * p, unsigned char * end, s p += len + 1; } - printk(KERN_ERR "PnPBIOS: Resource structure does not contain an end tag.\n"); + printk(KERN_ERR + "PnPBIOS: Resource structure does not contain an end tag.\n"); return NULL; } - /* * Core Parsing Functions */ -int -pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node) +int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node *node) { - unsigned char * p = (char *)node->data; - unsigned char * end = (char *)(node->data + node->size); - p = pnpbios_parse_allocated_resource_data(p,end,&dev->res); + unsigned char *p = (char *)node->data; + unsigned char *end = (char *)(node->data + node->size); + + p = pnpbios_parse_allocated_resource_data(p, end, &dev->res); if (!p) return -EIO; - p = pnpbios_parse_resource_option_data(p,end,dev); + p = pnpbios_parse_resource_option_data(p, end, dev); if (!p) return -EIO; - p = pnpbios_parse_compatible_ids(p,end,dev); + p = pnpbios_parse_compatible_ids(p, end, dev); if (!p) return -EIO; return 0; } -int -pnpbios_read_resources_from_node(struct pnp_resource_table *res, - struct pnp_bios_node * node) +int pnpbios_read_resources_from_node(struct pnp_resource_table *res, + struct pnp_bios_node *node) { - unsigned char * p = (char *)node->data; - unsigned char * end = (char *)(node->data + node->size); - p = pnpbios_parse_allocated_resource_data(p,end,res); + unsigned char *p = (char *)node->data; + unsigned char *end = (char *)(node->data + node->size); + + p = pnpbios_parse_allocated_resource_data(p, end, res); if (!p) return -EIO; return 0; } -int -pnpbios_write_resources_to_node(struct pnp_resource_table *res, - struct pnp_bios_node * node) +int pnpbios_write_resources_to_node(struct pnp_resource_table *res, + struct pnp_bios_node *node) { - unsigned char * p = (char *)node->data; - unsigned char * end = (char *)(node->data + node->size); - p = pnpbios_encode_allocated_resource_data(p,end,res); + unsigned char *p = (char *)node->data; + unsigned char *end = (char *)(node->data + node->size); + + p = pnpbios_encode_allocated_resource_data(p, end, res); if (!p) return -EIO; return 0; diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 7c32366..90755d4 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -19,7 +19,6 @@ #include <linux/io.h> #include "base.h" - static void quirk_awe32_resources(struct pnp_dev *dev) { struct pnp_port *port, *port2, *port3; @@ -31,7 +30,7 @@ static void quirk_awe32_resources(struct pnp_dev *dev) * two extra ports (at offset 0x400 and 0x800 from the one given) by * hand. */ - for ( ; res ; res = res->next ) { + for (; res; res = res->next) { port2 = pnp_alloc(sizeof(struct pnp_port)); if (!port2) return; @@ -58,18 +57,19 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev) struct pnp_option *res = dev->dependent; unsigned long tmp; - for ( ; res ; res = res->next ) { + for (; res; res = res->next) { struct pnp_irq *irq; struct pnp_dma *dma; - for( irq = res->irq; irq; irq = irq->next ) { // Valid irqs are 5, 7, 10 + for (irq = res->irq; irq; irq = irq->next) { // Valid irqs are 5, 7, 10 tmp = 0x04A0; bitmap_copy(irq->map, &tmp, 16); // 0000 0100 1010 0000 } - for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3 - if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT ) + for (dma = res->dma; dma; dma = dma->next) // Valid 8bit dma channels are 1,3 + if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) == + IORESOURCE_DMA_8BIT) dma->map = 0x000A; } printk(KERN_INFO "pnp: CMI8330 quirk - fixing interrupts and dma\n"); @@ -79,7 +79,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) { struct pnp_port *port; struct pnp_option *res = dev->dependent; - int changed = 0; + int changed = 0; /* * The default range on the mpu port for these devices is 0x388-0x388. @@ -87,24 +87,24 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) * auto-configured. */ - for( ; res ; res = res->next ) { + for (; res; res = res->next) { port = res->port; - if(!port) + if (!port) continue; port = port->next; - if(!port) + if (!port) continue; port = port->next; - if(!port) + if (!port) continue; - if(port->min != port->max) + if (port->min != port->max) continue; port->max += 0x70; changed = 1; } - if(changed) - printk(KERN_INFO "pnp: SB audio device quirk - increasing port range\n"); - return; + if (changed) + printk(KERN_INFO + "pnp: SB audio device quirk - increasing port range\n"); } static int quirk_smc_fir_enabled(struct pnp_dev *dev) @@ -124,7 +124,7 @@ static int quirk_smc_fir_enabled(struct pnp_dev *dev) outb(bank, firbase + 7); high = inb(firbase + 0); - low = inb(firbase + 1); + low = inb(firbase + 1); chip = inb(firbase + 2); /* This corresponds to the check in smsc_ircc_present() */ @@ -153,8 +153,8 @@ static void quirk_smc_enable(struct pnp_dev *dev) */ dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; " "auto-configuring\n", dev->id->id, - (unsigned long) pnp_port_start(dev, 0), - (unsigned long) pnp_port_start(dev, 1)); + (unsigned long)pnp_port_start(dev, 0), + (unsigned long)pnp_port_start(dev, 1)); pnp_disable_dev(dev); pnp_init_resource_table(&dev->res); @@ -162,8 +162,8 @@ static void quirk_smc_enable(struct pnp_dev *dev) pnp_activate_dev(dev); if (quirk_smc_fir_enabled(dev)) { dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n", - (unsigned long) pnp_port_start(dev, 0), - (unsigned long) pnp_port_start(dev, 1)); + (unsigned long)pnp_port_start(dev, 0), + (unsigned long)pnp_port_start(dev, 1)); return; } @@ -175,8 +175,8 @@ static void quirk_smc_enable(struct pnp_dev *dev) */ dev_err(&dev->dev, "not responding at SIR 0x%lx, FIR 0x%lx; " "swapping SIR/FIR and reconfiguring\n", - (unsigned long) pnp_port_start(dev, 0), - (unsigned long) pnp_port_start(dev, 1)); + (unsigned long)pnp_port_start(dev, 0), + (unsigned long)pnp_port_start(dev, 1)); /* * Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign @@ -200,8 +200,8 @@ static void quirk_smc_enable(struct pnp_dev *dev) if (quirk_smc_fir_enabled(dev)) { dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n", - (unsigned long) pnp_port_start(dev, 0), - (unsigned long) pnp_port_start(dev, 1)); + (unsigned long)pnp_port_start(dev, 0), + (unsigned long)pnp_port_start(dev, 1)); return; } @@ -209,7 +209,6 @@ static void quirk_smc_enable(struct pnp_dev *dev) "email bjorn.helgaas@hp.com\n"); } - /* * PnP Quirks * Cards or devices that need some tweaking due to incomplete resource info @@ -217,21 +216,21 @@ static void quirk_smc_enable(struct pnp_dev *dev) static struct pnp_fixup pnp_fixups[] = { /* Soundblaster awe io port quirk */ - { "CTL0021", quirk_awe32_resources }, - { "CTL0022", quirk_awe32_resources }, - { "CTL0023", quirk_awe32_resources }, + {"CTL0021", quirk_awe32_resources}, + {"CTL0022", quirk_awe32_resources}, + {"CTL0023", quirk_awe32_resources}, /* CMI 8330 interrupt and dma fix */ - { "@X@0001", quirk_cmi8330_resources }, + {"@X@0001", quirk_cmi8330_resources}, /* Soundblaster audio device io port range quirk */ - { "CTL0001", quirk_sb16audio_resources }, - { "CTL0031", quirk_sb16audio_resources }, - { "CTL0041", quirk_sb16audio_resources }, - { "CTL0042", quirk_sb16audio_resources }, - { "CTL0043", quirk_sb16audio_resources }, - { "CTL0044", quirk_sb16audio_resources }, - { "CTL0045", quirk_sb16audio_resources }, - { "SMCf010", quirk_smc_enable }, - { "" } + {"CTL0001", quirk_sb16audio_resources}, + {"CTL0031", quirk_sb16audio_resources}, + {"CTL0041", quirk_sb16audio_resources}, + {"CTL0042", quirk_sb16audio_resources}, + {"CTL0043", quirk_sb16audio_resources}, + {"CTL0044", quirk_sb16audio_resources}, + {"CTL0045", quirk_sb16audio_resources}, + {"SMCf010", quirk_smc_enable}, + {""} }; void pnp_fixup_device(struct pnp_dev *dev) @@ -239,9 +238,8 @@ void pnp_fixup_device(struct pnp_dev *dev) int i = 0; while (*pnp_fixups[i].id) { - if (compare_pnp_id(dev->id,pnp_fixups[i].id)) { - pnp_dbg("Calling quirk for %s", - dev->dev.bus_id); + if (compare_pnp_id(dev->id, pnp_fixups[i].id)) { + pnp_dbg("Calling quirk for %s", dev->dev.bus_id); pnp_fixups[i].quirk_function(dev); } i++; diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index a685fbe..ea6ec14 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -3,7 +3,6 @@ * * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz> * Copyright 2003 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/module.h> @@ -20,21 +19,19 @@ #include <linux/pnp.h> #include "base.h" -static int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ -static int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */ -static int pnp_reserve_io[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some I/O region */ -static int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memory region */ - +static int pnp_reserve_irq[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ +static int pnp_reserve_dma[8] = {[0 ... 7] = -1 }; /* reserve (don't use) some DMA */ +static int pnp_reserve_io[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */ +static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some memory region */ /* * option registration */ -static struct pnp_option * pnp_build_option(int priority) +static struct pnp_option *pnp_build_option(int priority) { struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); - /* check if pnp_alloc ran out of memory */ if (!option) return NULL; @@ -46,9 +43,10 @@ static struct pnp_option * pnp_build_option(int priority) return option; } -struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) +struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) { struct pnp_option *option; + if (!dev) return NULL; @@ -61,9 +59,11 @@ struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) return option; } -struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority) +struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, + int priority) { struct pnp_option *option; + if (!dev) return NULL; @@ -82,6 +82,7 @@ struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int prior int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { struct pnp_irq *ptr; + if (!option) return -EINVAL; if (!data) @@ -110,6 +111,7 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) { struct pnp_dma *ptr; + if (!option) return -EINVAL; if (!data) @@ -129,6 +131,7 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { struct pnp_port *ptr; + if (!option) return -EINVAL; if (!data) @@ -148,6 +151,7 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { struct pnp_mem *ptr; + if (!option) return -EINVAL; if (!data) @@ -222,7 +226,6 @@ void pnp_free_option(struct pnp_option *option) } } - /* * resource validity checking */ @@ -236,11 +239,12 @@ void pnp_free_option(struct pnp_option *option) #define cannot_compare(flags) \ ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) -int pnp_check_port(struct pnp_dev * dev, int idx) +int pnp_check_port(struct pnp_dev *dev, int idx) { int tmp; struct pnp_dev *tdev; resource_size_t *port, *end, *tport, *tend; + port = &dev->res.port_resource[idx].start; end = &dev->res.port_resource[idx].end; @@ -250,8 +254,8 @@ int pnp_check_port(struct pnp_dev * dev, int idx) /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ - if(!dev->active) { - if (__check_region(&ioport_resource, *port, length(port,end))) + if (!dev->active) { + if (__check_region(&ioport_resource, *port, length(port, end))) return 0; } @@ -259,7 +263,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx) for (tmp = 0; tmp < 8; tmp++) { int rport = pnp_reserve_io[tmp << 1]; int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; - if (ranged_conflict(port,end,&rport,&rend)) + if (ranged_conflict(port, end, &rport, &rend)) return 0; } @@ -268,7 +272,7 @@ int pnp_check_port(struct pnp_dev * dev, int idx) if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) { tport = &dev->res.port_resource[tmp].start; tend = &dev->res.port_resource[tmp].end; - if (ranged_conflict(port,end,tport,tend)) + if (ranged_conflict(port, end, tport, tend)) return 0; } } @@ -279,11 +283,12 @@ int pnp_check_port(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { - if (cannot_compare(tdev->res.port_resource[tmp].flags)) + if (cannot_compare + (tdev->res.port_resource[tmp].flags)) continue; tport = &tdev->res.port_resource[tmp].start; tend = &tdev->res.port_resource[tmp].end; - if (ranged_conflict(port,end,tport,tend)) + if (ranged_conflict(port, end, tport, tend)) return 0; } } @@ -292,11 +297,12 @@ int pnp_check_port(struct pnp_dev * dev, int idx) return 1; } -int pnp_check_mem(struct pnp_dev * dev, int idx) +int pnp_check_mem(struct pnp_dev *dev, int idx) { int tmp; struct pnp_dev *tdev; resource_size_t *addr, *end, *taddr, *tend; + addr = &dev->res.mem_resource[idx].start; end = &dev->res.mem_resource[idx].end; @@ -306,8 +312,8 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ - if(!dev->active) { - if (check_mem_region(*addr, length(addr,end))) + if (!dev->active) { + if (check_mem_region(*addr, length(addr, end))) return 0; } @@ -315,7 +321,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) for (tmp = 0; tmp < 8; tmp++) { int raddr = pnp_reserve_mem[tmp << 1]; int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; - if (ranged_conflict(addr,end,&raddr,&rend)) + if (ranged_conflict(addr, end, &raddr, &rend)) return 0; } @@ -324,7 +330,7 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { taddr = &dev->res.mem_resource[tmp].start; tend = &dev->res.mem_resource[tmp].end; - if (ranged_conflict(addr,end,taddr,tend)) + if (ranged_conflict(addr, end, taddr, tend)) return 0; } } @@ -335,11 +341,12 @@ int pnp_check_mem(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { - if (cannot_compare(tdev->res.mem_resource[tmp].flags)) + if (cannot_compare + (tdev->res.mem_resource[tmp].flags)) continue; taddr = &tdev->res.mem_resource[tmp].start; tend = &tdev->res.mem_resource[tmp].end; - if (ranged_conflict(addr,end,taddr,tend)) + if (ranged_conflict(addr, end, taddr, tend)) return 0; } } @@ -353,11 +360,11 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) return IRQ_HANDLED; } -int pnp_check_irq(struct pnp_dev * dev, int idx) +int pnp_check_irq(struct pnp_dev *dev, int idx) { int tmp; struct pnp_dev *tdev; - resource_size_t * irq = &dev->res.irq_resource[idx].start; + resource_size_t *irq = &dev->res.irq_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ if (cannot_compare(dev->res.irq_resource[idx].flags)) @@ -394,9 +401,9 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ - if(!dev->active) { + if (!dev->active) { if (request_irq(*irq, pnp_test_handler, - IRQF_DISABLED|IRQF_PROBE_SHARED, "pnp", NULL)) + IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL)) return 0; free_irq(*irq, NULL); } @@ -407,7 +414,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { - if (cannot_compare(tdev->res.irq_resource[tmp].flags)) + if (cannot_compare + (tdev->res.irq_resource[tmp].flags)) continue; if ((tdev->res.irq_resource[tmp].start == *irq)) return 0; @@ -418,12 +426,12 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) return 1; } -int pnp_check_dma(struct pnp_dev * dev, int idx) +int pnp_check_dma(struct pnp_dev *dev, int idx) { #ifndef CONFIG_IA64 int tmp; struct pnp_dev *tdev; - resource_size_t * dma = &dev->res.dma_resource[idx].start; + resource_size_t *dma = &dev->res.dma_resource[idx].start; /* if the resource doesn't exist, don't complain about it */ if (cannot_compare(dev->res.dma_resource[idx].flags)) @@ -449,7 +457,7 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) /* check if the resource is already in use, skip if the * device is active because it itself may be in use */ - if(!dev->active) { + if (!dev->active) { if (request_dma(*dma, "pnp")) return 0; free_dma(*dma); @@ -461,7 +469,8 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) continue; for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { - if (cannot_compare(tdev->res.dma_resource[tmp].flags)) + if (cannot_compare + (tdev->res.dma_resource[tmp].flags)) continue; if ((tdev->res.dma_resource[tmp].start == *dma)) return 0; @@ -471,30 +480,18 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) return 1; #else - /* IA64 hasn't legacy DMA */ + /* IA64 does not have legacy DMA */ return 0; #endif } - -#if 0 -EXPORT_SYMBOL(pnp_register_dependent_option); -EXPORT_SYMBOL(pnp_register_independent_option); -EXPORT_SYMBOL(pnp_register_irq_resource); -EXPORT_SYMBOL(pnp_register_dma_resource); -EXPORT_SYMBOL(pnp_register_port_resource); -EXPORT_SYMBOL(pnp_register_mem_resource); -#endif /* 0 */ - - /* format is: pnp_reserve_irq=irq1[,irq2] .... */ - static int __init pnp_setup_reserve_irq(char *str) { int i; for (i = 0; i < 16; i++) - if (get_option(&str,&pnp_reserve_irq[i]) != 2) + if (get_option(&str, &pnp_reserve_irq[i]) != 2) break; return 1; } @@ -502,13 +499,12 @@ static int __init pnp_setup_reserve_irq(char *str) __setup("pnp_reserve_irq=", pnp_setup_reserve_irq); /* format is: pnp_reserve_dma=dma1[,dma2] .... */ - static int __init pnp_setup_reserve_dma(char *str) { int i; for (i = 0; i < 8; i++) - if (get_option(&str,&pnp_reserve_dma[i]) != 2) + if (get_option(&str, &pnp_reserve_dma[i]) != 2) break; return 1; } @@ -516,13 +512,12 @@ static int __init pnp_setup_reserve_dma(char *str) __setup("pnp_reserve_dma=", pnp_setup_reserve_dma); /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */ - static int __init pnp_setup_reserve_io(char *str) { int i; for (i = 0; i < 16; i++) - if (get_option(&str,&pnp_reserve_io[i]) != 2) + if (get_option(&str, &pnp_reserve_io[i]) != 2) break; return 1; } @@ -530,13 +525,12 @@ static int __init pnp_setup_reserve_io(char *str) __setup("pnp_reserve_io=", pnp_setup_reserve_io); /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */ - static int __init pnp_setup_reserve_mem(char *str) { int i; for (i = 0; i < 16; i++) - if (get_option(&str,&pnp_reserve_mem[i]) != 2) + if (get_option(&str, &pnp_reserve_mem[i]) != 2) break; return 1; } diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 946a0dc..13c608f 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -1,8 +1,7 @@ /* - * support.c - provides standard pnp functions for the use of pnp protocol drivers, + * support.c - standard functions for the use of pnp protocol drivers * * Copyright 2003 Adam Belay <ambx1@neo.rr.com> - * */ #include <linux/module.h> @@ -11,22 +10,18 @@ #include "base.h" /** - * pnp_is_active - Determines if a device is active based on its current resources + * pnp_is_active - Determines if a device is active based on its current + * resources * @dev: pointer to the desired PnP device - * */ - -int pnp_is_active(struct pnp_dev * dev) +int pnp_is_active(struct pnp_dev *dev) { if (!pnp_port_start(dev, 0) && pnp_port_len(dev, 0) <= 1 && !pnp_mem_start(dev, 0) && pnp_mem_len(dev, 0) <= 1 && - pnp_irq(dev, 0) == -1 && - pnp_dma(dev, 0) == -1) - return 0; + pnp_irq(dev, 0) == -1 && pnp_dma(dev, 0) == -1) + return 0; else return 1; } - - EXPORT_SYMBOL(pnp_is_active); diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index a8a9554..a06f980 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -16,13 +16,14 @@ static const struct pnp_device_id pnp_dev_table[] = { /* General ID for reserving resources */ - { "PNP0c02", 0 }, + {"PNP0c02", 0}, /* memory controller */ - { "PNP0c01", 0 }, - { "", 0 } + {"PNP0c01", 0}, + {"", 0} }; -static void reserve_range(const char *pnpid, resource_size_t start, resource_size_t end, int port) +static void reserve_range(const char *pnpid, resource_size_t start, + resource_size_t end, int port) { struct resource *res; char *regionid; @@ -32,9 +33,9 @@ static void reserve_range(const char *pnpid, resource_size_t start, resource_siz return; snprintf(regionid, 16, "pnp %s", pnpid); if (port) - res = request_region(start, end-start+1, regionid); + res = request_region(start, end - start + 1, regionid); else - res = request_mem_region(start, end-start+1, regionid); + res = request_mem_region(start, end - start + 1, regionid); if (res == NULL) kfree(regionid); else @@ -44,11 +45,10 @@ static void reserve_range(const char *pnpid, resource_size_t start, resource_siz * example do reserve stuff they know about too, so we may well * have double reservations. */ - printk(KERN_INFO - "pnp: %s: %s range 0x%llx-0x%llx %s reserved\n", - pnpid, port ? "ioport" : "iomem", - (unsigned long long)start, (unsigned long long)end, - NULL != res ? "has been" : "could not be"); + printk(KERN_INFO "pnp: %s: %s range 0x%llx-0x%llx %s reserved\n", + pnpid, port ? "ioport" : "iomem", + (unsigned long long)start, (unsigned long long)end, + NULL != res ? "has been" : "could not be"); } static void reserve_resources_of_dev(const struct pnp_dev *dev) @@ -74,7 +74,7 @@ static void reserve_resources_of_dev(const struct pnp_dev *dev) continue; /* invalid */ reserve_range(dev->dev.bus_id, pnp_port_start(dev, i), - pnp_port_end(dev, i), 1); + pnp_port_end(dev, i), 1); } for (i = 0; i < PNP_MAX_MEM; i++) { @@ -82,24 +82,22 @@ static void reserve_resources_of_dev(const struct pnp_dev *dev) continue; reserve_range(dev->dev.bus_id, pnp_mem_start(dev, i), - pnp_mem_end(dev, i), 0); + pnp_mem_end(dev, i), 0); } - - return; } -static int system_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +static int system_pnp_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id) { reserve_resources_of_dev(dev); return 0; } static struct pnp_driver system_pnp_driver = { - .name = "system", - .id_table = pnp_dev_table, - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .probe = system_pnp_probe, - .remove = NULL, + .name = "system", + .id_table = pnp_dev_table, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + .probe = system_pnp_probe, }; static int __init pnp_system_init(void) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9d8d40d..ff9e35c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -2,15 +2,13 @@ # RTC class/drivers configuration # -menu "Real Time Clock" - depends on !S390 - config RTC_LIB tristate -config RTC_CLASS - tristate "RTC class" +menuconfig RTC_CLASS + tristate "Real Time Clock" default n + depends on !S390 select RTC_LIB help Generic RTC class support. If you say yes here, you will @@ -20,6 +18,8 @@ config RTC_CLASS This driver can also be built as a module. If so, the module will be called rtc-class. +if RTC_CLASS + config RTC_HCTOSYS bool "Set system time from RTC on startup and resume" depends on RTC_CLASS = y @@ -58,11 +58,10 @@ config RTC_DEBUG and individual RTC drivers. comment "RTC interfaces" - depends on RTC_CLASS config RTC_INTF_SYSFS boolean "/sys/class/rtc/rtcN (sysfs)" - depends on RTC_CLASS && SYSFS + depends on SYSFS default RTC_CLASS help Say yes here if you want to use your RTCs using sysfs interfaces, @@ -73,7 +72,7 @@ config RTC_INTF_SYSFS config RTC_INTF_PROC boolean "/proc/driver/rtc (procfs for rtc0)" - depends on RTC_CLASS && PROC_FS + depends on PROC_FS default RTC_CLASS help Say yes here if you want to use your first RTC through the proc @@ -85,7 +84,6 @@ config RTC_INTF_PROC config RTC_INTF_DEV boolean "/dev/rtcN (character devices)" - depends on RTC_CLASS default RTC_CLASS help Say yes here if you want to use your RTCs using the /dev @@ -107,7 +105,6 @@ config RTC_INTF_DEV_UIE_EMUL config RTC_DRV_TEST tristate "Test driver/device" - depends on RTC_CLASS help If you say yes here you get support for the RTC test driver. It's a software RTC which can be @@ -121,11 +118,12 @@ config RTC_DRV_TEST will be called rtc-test. comment "I2C RTC drivers" - depends on RTC_CLASS && I2C + depends on I2C + +if I2C config RTC_DRV_DS1307 tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" - depends on RTC_CLASS && I2C help If you say yes here you get support for various compatible RTC chips (often with battery backup) connected with I2C. This driver @@ -143,7 +141,6 @@ config RTC_DRV_DS1307 config RTC_DRV_DS1672 tristate "Dallas/Maxim DS1672" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Dallas/Maxim DS1672 timekeeping chip. @@ -153,7 +150,6 @@ config RTC_DRV_DS1672 config RTC_DRV_MAX6900 tristate "Maxim 6900" - depends on RTC_CLASS && I2C help If you say yes here you will get support for the Maxim MAX6900 I2C RTC chip. @@ -163,7 +159,6 @@ config RTC_DRV_MAX6900 config RTC_DRV_RS5C372 tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips. @@ -173,7 +168,6 @@ config RTC_DRV_RS5C372 config RTC_DRV_ISL1208 tristate "Intersil 1208" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Intersil 1208 RTC chip. @@ -183,7 +177,6 @@ config RTC_DRV_ISL1208 config RTC_DRV_X1205 tristate "Xicor/Intersil X1205" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Xicor/Intersil X1205 RTC chip. @@ -193,7 +186,6 @@ config RTC_DRV_X1205 config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Philips PCF8563 RTC chip. The Epson RTC8564 @@ -204,7 +196,6 @@ config RTC_DRV_PCF8563 config RTC_DRV_PCF8583 tristate "Philips PCF8583" - depends on RTC_CLASS && I2C help If you say yes here you get support for the Philips PCF8583 RTC chip found on Acorn RiscPCs. This driver supports the @@ -217,7 +208,6 @@ config RTC_DRV_PCF8583 config RTC_DRV_M41T80 tristate "ST M41T80 series RTC" - depends on RTC_CLASS && I2C help If you say Y here you will get support for the ST M41T80 RTC chips series. Currently following chips are @@ -236,19 +226,21 @@ config RTC_DRV_M41T80_WDT config RTC_DRV_TWL92330 boolean "TI TWL92330/Menelaus" - depends on RTC_CLASS && I2C && MENELAUS + depends on MENELAUS help If you say yes here you get support for the RTC on the TWL92330 "Menelaus" power mangement chip, used with OMAP2 platforms. The support is integrated with the rest of the Menelaus driver; it's not separate module. +endif # I2C + comment "SPI RTC drivers" - depends on RTC_CLASS && SPI_MASTER + +if SPI_MASTER config RTC_DRV_RS5C348 tristate "Ricoh RS5C348A/B" - depends on RTC_CLASS && SPI_MASTER help If you say yes here you get support for the Ricoh RS5C348A and RS5C348B RTC chips. @@ -258,7 +250,6 @@ config RTC_DRV_RS5C348 config RTC_DRV_MAX6902 tristate "Maxim 6902" - depends on RTC_CLASS && SPI_MASTER help If you say yes here you will get support for the Maxim MAX6902 SPI RTC chip. @@ -266,8 +257,9 @@ config RTC_DRV_MAX6902 This driver can also be built as a module. If so, the module will be called rtc-max6902. +endif # SPI_MASTER + comment "Platform RTC drivers" - depends on RTC_CLASS # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> # requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a @@ -275,8 +267,7 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" - depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ - || M32R || ATARI || PPC || MIPS) + depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS help Say "yes" here to get direct support for the real time clock found in every PC or ACPI-based system, and some other boards. @@ -294,13 +285,12 @@ config RTC_DRV_CMOS config RTC_DRV_DS1216 tristate "Dallas DS1216" - depends on RTC_CLASS && SNI_RM + depends on SNI_RM help If you say yes here you get support for the Dallas DS1216 RTC chips. config RTC_DRV_DS1553 tristate "Dallas DS1553" - depends on RTC_CLASS help If you say yes here you get support for the Dallas DS1553 timekeeping chip. @@ -320,7 +310,6 @@ config RTC_DRV_STK17TA8 config RTC_DRV_DS1742 tristate "Dallas DS1742/1743" - depends on RTC_CLASS help If you say yes here you get support for the Dallas DS1742/1743 timekeeping chip. @@ -330,7 +319,6 @@ config RTC_DRV_DS1742 config RTC_DRV_M48T86 tristate "ST M48T86/Dallas DS12887" - depends on RTC_CLASS help If you say Y here you will get support for the ST M48T86 and Dallas DS12887 RTC chips. @@ -340,7 +328,6 @@ config RTC_DRV_M48T86 config RTC_DRV_M48T59 tristate "ST M48T59" - depends on RTC_CLASS help If you say Y here you will get support for the ST M48T59 RTC chip. @@ -350,7 +337,6 @@ config RTC_DRV_M48T59 config RTC_DRV_V3020 tristate "EM Microelectronic V3020" - depends on RTC_CLASS help If you say yes here you will get support for the EM Microelectronic v3020 RTC chip. @@ -359,19 +345,17 @@ config RTC_DRV_V3020 will be called rtc-v3020. comment "on-CPU RTC drivers" - depends on RTC_CLASS config RTC_DRV_OMAP tristate "TI OMAP1" - depends on RTC_CLASS && ( \ - ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 ) + depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 help Say "yes" here to support the real time clock on TI OMAP1 chips. This driver can also be built as a module called rtc-omap. config RTC_DRV_S3C tristate "Samsung S3C series SoC RTC" - depends on RTC_CLASS && ARCH_S3C2410 + depends on ARCH_S3C2410 help RTC (Realtime Clock) driver for the clock inbuilt into the Samsung S3C24XX series of SoCs. This can provide periodic @@ -387,7 +371,7 @@ config RTC_DRV_S3C config RTC_DRV_EP93XX tristate "Cirrus Logic EP93XX" - depends on RTC_CLASS && ARCH_EP93XX + depends on ARCH_EP93XX help If you say yes here you get support for the RTC embedded in the Cirrus Logic EP93XX processors. @@ -397,7 +381,7 @@ config RTC_DRV_EP93XX config RTC_DRV_SA1100 tristate "SA11x0/PXA2xx" - depends on RTC_CLASS && (ARCH_SA1100 || ARCH_PXA) + depends on ARCH_SA1100 || ARCH_PXA help If you say Y here you will get access to the real time clock built into your SA11x0 or PXA2xx CPU. @@ -407,7 +391,7 @@ config RTC_DRV_SA1100 config RTC_DRV_SH tristate "SuperH On-Chip RTC" - depends on RTC_CLASS && SUPERH && (CPU_SH3 || CPU_SH4) + depends on RTC_CLASS && (CPU_SH3 || CPU_SH4) help Say Y here to enable support for the on-chip RTC found in most SuperH processors. @@ -417,7 +401,7 @@ config RTC_DRV_SH config RTC_DRV_VR41XX tristate "NEC VR41XX" - depends on RTC_CLASS && CPU_VR41XX + depends on CPU_VR41XX help If you say Y here you will get access to the real time clock built into your NEC VR41XX CPU. @@ -427,7 +411,7 @@ config RTC_DRV_VR41XX config RTC_DRV_PL031 tristate "ARM AMBA PL031 RTC" - depends on RTC_CLASS && ARM_AMBA + depends on ARM_AMBA help If you say Y here you will get access to ARM AMBA PrimeCell PL031 RTC found on certain ARM SOCs. @@ -437,20 +421,20 @@ config RTC_DRV_PL031 config RTC_DRV_AT32AP700X tristate "AT32AP700X series RTC" - depends on RTC_CLASS && PLATFORM_AT32AP + depends on PLATFORM_AT32AP help Driver for the internal RTC (Realtime Clock) on Atmel AVR32 AT32AP700x family processors. config RTC_DRV_AT91RM9200 tristate "AT91RM9200" - depends on RTC_CLASS && ARCH_AT91RM9200 + depends on ARCH_AT91RM9200 help Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). config RTC_DRV_BFIN tristate "Blackfin On-Chip RTC" - depends on RTC_CLASS && BFIN + depends on BFIN help If you say yes here you will get support for the Blackfin On-Chip Real Time Clock. @@ -460,8 +444,8 @@ config RTC_DRV_BFIN config RTC_DRV_RS5C313 tristate "Ricoh RS5C313" - depends on RTC_CLASS && SH_LANDISK + depends on SH_LANDISK help If you say yes here you get support for the Ricoh RS5C313 RTC chips. -endmenu +endif # RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7ede9e7..d3a33aa 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -15,34 +15,36 @@ rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o +# Keep the list ordered. + +obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o +obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o +obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o -obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o -obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o -obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_AT32AP700X) += rtc-at32ap700x.o +obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o +obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o +obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o +obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o +obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o +obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o +obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o +obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o +obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o +obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o +obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o +obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o -obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o -obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o -obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o -obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o -obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o -obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o -obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o -obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o -obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o -obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o -obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o -obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o -obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o -obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o -obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o -obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o +obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o +obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o +obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o +obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o +obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 8b3cd31..10ab3b7 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -46,6 +46,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; + struct timespec ts = current_kernel_time(); if (strncmp(rtc->dev.bus_id, CONFIG_RTC_HCTOSYS_DEVICE, @@ -57,8 +58,8 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */ set_normalized_timespec(&delta, - xtime.tv_sec - oldtime, - xtime.tv_nsec - (NSEC_PER_SEC >> 1)); + ts.tv_sec - oldtime, + ts.tv_nsec - (NSEC_PER_SEC >> 1)); return 0; } diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 260ead9..1aa709d 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -1,6 +1,6 @@ /* * Blackfin On-Chip Real Time Clock Driver - * Supports BF531/BF532/BF533/BF534/BF536/BF537 + * Supports BF53[123]/BF53[467]/BF54[2489] * * Copyright 2004-2007 Analog Devices Inc. * diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 3045359..005fff3 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -348,6 +348,8 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, case RTC_IRQP_SET: if (ops->irq_set_freq) err = rtc_irq_set_freq(rtc, rtc->irq_task, arg); + else + err = -ENOTTY; break; #if 0 diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 5158a62..db6f3f0 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -352,7 +352,7 @@ read_rtc: /* oscillator fault? clear flag, and warn */ if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL, - ds1307->regs[DS1337_REG_CONTROL] + ds1307->regs[DS1307_REG_CONTROL] & ~DS1338_BIT_OSF); dev_warn(&client->dev, "SET TIME!\n"); goto read_rtc; diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 33b7523..bf60d35 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -35,7 +35,7 @@ struct m48t59_private { void __iomem *ioaddr; unsigned int size; /* iomem size */ - unsigned int irq; + int irq; struct rtc_device *rtc; spinlock_t lock; /* serialize the NVRAM and RTC access */ }; diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 54b6130..8c1012b 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -29,7 +29,7 @@ #include <asm/mach/time.h> -#include <asm/arch/regs-rtc.h> +#include <asm/plat-s3c/regs-rtc.h> /* I have yet to find an S3C implementation with more than one * of these rtc blocks in */ diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e0f91df..93ee05e 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -365,6 +365,7 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) /* Reset pre-scaler & stop RTC */ tmp = readb(rtc->regbase + RCR2); tmp |= RCR2_RESET; + tmp &= ~RCR2_START; writeb(tmp, rtc->regbase + RCR2); writeb(BIN2BCD(tm->tm_sec), rtc->regbase + RSECCNT); diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index f10d3fa..8288b6b 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -258,7 +258,8 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { .ioctl = stk17ta8_rtc_ioctl, }; -static ssize_t stk17ta8_nvram_read(struct kobject *kobj, char *buf, +static ssize_t stk17ta8_nvram_read(struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t pos, size_t size) { struct platform_device *pdev = @@ -272,7 +273,8 @@ static ssize_t stk17ta8_nvram_read(struct kobject *kobj, char *buf, return count; } -static ssize_t stk17ta8_nvram_write(struct kobject *kobj, char *buf, +static ssize_t stk17ta8_nvram_write(struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t pos, size_t size) { struct platform_device *pdev = diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index bfeca57..e6bfce6 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1187,7 +1187,7 @@ dasd_end_request_cb(struct dasd_ccw_req * cqr, void *data) static void __dasd_process_blk_queue(struct dasd_device * device) { - request_queue_t *queue; + struct request_queue *queue; struct request *req; struct dasd_ccw_req *cqr; int nr_queued; @@ -1740,7 +1740,7 @@ dasd_cancel_req(struct dasd_ccw_req *cqr) * Dasd request queue function. Called from ll_rw_blk.c */ static void -do_dasd_request(request_queue_t * queue) +do_dasd_request(struct request_queue * queue) { struct dasd_device *device; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 418b4e6..ea63ba7 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -555,7 +555,7 @@ dasd_eckd_read_conf(struct dasd_device *device) if (conf_data == NULL) { MESSAGE(KERN_WARNING, "%s", "No configuration " "data retrieved"); - continue; /* no errror */ + continue; /* no error */ } if (conf_len != sizeof (struct dasd_eckd_confdata)) { MESSAGE(KERN_WARNING, @@ -564,7 +564,7 @@ dasd_eckd_read_conf(struct dasd_device *device) conf_len, sizeof (struct dasd_eckd_confdata)); kfree(conf_data); - continue; /* no errror */ + continue; /* no error */ } /* save first valid configuration data */ if (!conf_data_saved){ diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 241294c..aeda526 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -293,7 +293,7 @@ struct dasd_uid { struct dasd_device { /* Block device stuff. */ struct gendisk *gdp; - request_queue_t *request_queue; + struct request_queue *request_queue; spinlock_t request_queue_lock; struct block_device *bdev; unsigned int devindex; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 35765f6..4d8798b 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -621,7 +621,7 @@ out: } static int -dcssblk_make_request(request_queue_t *q, struct bio *bio) +dcssblk_make_request(struct request_queue *q, struct bio *bio) { struct dcssblk_dev_info *dev_info; struct bio_vec *bvec; diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index a04d912..354a060 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -191,7 +191,7 @@ static unsigned long __init xpram_highest_page_index(void) /* * Block device make request function. */ -static int xpram_make_request(request_queue_t *q, struct bio *bio) +static int xpram_make_request(struct request_queue *q, struct bio *bio) { xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data; struct bio_vec *bvec; diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 3f36cb3..6430338 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -44,15 +44,9 @@ config CCW_CONSOLE depends on TN3215_CONSOLE || TN3270_CONSOLE default y -config SCLP - bool "Support for SCLP" - depends on S390 - help - Include support for the SCLP interface to the service element. - config SCLP_TTY bool "Support for SCLP line mode terminal" - depends on SCLP + depends on S390 help Include support for IBM SCLP line-mode terminals. @@ -65,7 +59,7 @@ config SCLP_CONSOLE config SCLP_VT220_TTY bool "Support for SCLP VT220-compatible terminal" - depends on SCLP + depends on S390 help Include support for an IBM SCLP VT220-compatible terminal. @@ -78,7 +72,7 @@ config SCLP_VT220_CONSOLE config SCLP_CPI tristate "Control-Program Identification" - depends on SCLP + depends on S390 help This option enables the hardware console interface for system identification. This is commonly used for workload management and diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 743944a..4f2f81b 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -147,8 +147,7 @@ raw3270_request_alloc(size_t size) * Allocate a new 3270 ccw request from bootmem. Only works very * early in the boot process. Only con3270.c should be using this. */ -struct raw3270_request * -raw3270_request_alloc_bootmem(size_t size) +struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size) { struct raw3270_request *rq; @@ -848,8 +847,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) /* * Setup 3270 device configured as console. */ -struct raw3270 * -raw3270_setup_console(struct ccw_device *cdev) +struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev) { struct raw3270 *rp; char *ascebc; diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 7263347..40cd21b 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -621,11 +621,24 @@ sclp_vt220_flush_buffer(struct tty_struct *tty) /* * Initialize all relevant components and register driver with system. */ -static int -__sclp_vt220_init(int early) +static void __init __sclp_vt220_cleanup(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_vt220_empty) { + list_del(page); + if (slab_is_available()) + free_page((unsigned long) page); + else + free_bootmem((unsigned long) page, PAGE_SIZE); + } +} + +static int __init __sclp_vt220_init(void) { void *page; int i; + int num_pages; if (sclp_vt220_initialized) return 0; @@ -642,13 +655,16 @@ __sclp_vt220_init(int early) sclp_vt220_flush_later = 0; /* Allocate pages for output buffering */ - for (i = 0; i < (early ? MAX_CONSOLE_PAGES : MAX_KMEM_PAGES); i++) { - if (early) - page = alloc_bootmem_low_pages(PAGE_SIZE); - else + num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES; + for (i = 0; i < num_pages; i++) { + if (slab_is_available()) page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!page) + else + page = alloc_bootmem_low_pages(PAGE_SIZE); + if (!page) { + __sclp_vt220_cleanup(); return -ENOMEM; + } list_add_tail((struct list_head *) page, &sclp_vt220_empty); } return 0; @@ -662,14 +678,13 @@ static const struct tty_operations sclp_vt220_ops = { .flush_chars = sclp_vt220_flush_chars, .write_room = sclp_vt220_write_room, .chars_in_buffer = sclp_vt220_chars_in_buffer, - .flush_buffer = sclp_vt220_flush_buffer + .flush_buffer = sclp_vt220_flush_buffer, }; /* * Register driver with SCLP and Linux and initialize internal tty structures. */ -static int __init -sclp_vt220_tty_init(void) +static int __init sclp_vt220_tty_init(void) { struct tty_driver *driver; int rc; @@ -679,18 +694,15 @@ sclp_vt220_tty_init(void) driver = alloc_tty_driver(1); if (!driver) return -ENOMEM; - rc = __sclp_vt220_init(0); - if (rc) { - put_tty_driver(driver); - return rc; - } + rc = __sclp_vt220_init(); + if (rc) + goto out_driver; rc = sclp_register(&sclp_vt220_register); if (rc) { printk(KERN_ERR SCLP_VT220_PRINT_HEADER "could not register tty - " "sclp_register returned %d\n", rc); - put_tty_driver(driver); - return rc; + goto out_init; } driver->owner = THIS_MODULE; @@ -709,14 +721,20 @@ sclp_vt220_tty_init(void) printk(KERN_ERR SCLP_VT220_PRINT_HEADER "could not register tty - " "tty_register_driver returned %d\n", rc); - put_tty_driver(driver); - return rc; + goto out_sclp; } sclp_vt220_driver = driver; return 0; -} -module_init(sclp_vt220_tty_init); +out_sclp: + sclp_unregister(&sclp_vt220_register); +out_init: + __sclp_vt220_cleanup(); +out_driver: + put_tty_driver(driver); + return rc; +} +__initcall(sclp_vt220_tty_init); #ifdef CONFIG_SCLP_VT220_CONSOLE @@ -762,7 +780,7 @@ sclp_vt220_con_init(void) if (!CONSOLE_IS_SCLP) return 0; - rc = __sclp_vt220_init(1); + rc = __sclp_vt220_init(); if (rc) return rc; /* Attach linux console */ diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index 3b52f5c..dddf8d6 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h @@ -188,7 +188,7 @@ struct tape_blk_data { struct tape_device * device; /* Block device request queue. */ - request_queue_t * request_queue; + struct request_queue * request_queue; spinlock_t request_queue_lock; /* Task to move entries from block request to CCS request queue. */ diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index dd0ecae..eeb92e2 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -147,7 +147,7 @@ static void tapeblock_requeue(struct work_struct *work) { struct tape_blk_data * blkdat; struct tape_device * device; - request_queue_t * queue; + struct request_queue * queue; int nr_queued; struct request * req; struct list_head * l; @@ -194,7 +194,7 @@ tapeblock_requeue(struct work_struct *work) { * Tape request queue function. Called from ll_rw_blk.c */ static void -tapeblock_request_fn(request_queue_t *queue) +tapeblock_request_fn(struct request_queue *queue) { struct tape_device *device; diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index e90b0f8..161867c 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -486,7 +486,7 @@ static ssize_t diag14_read(struct file *file, char __user *ubuf, size_t count, } if (rc) goto fail; - if (reclen) + if (reclen && (copied == 0) && (*offs < PAGE_SIZE)) *((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen; len = min(count - copied, PAGE_SIZE - res); if (copy_to_user(ubuf + copied, buf + res, len)) { diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index ec04048..bd5f16f 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -51,7 +51,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to, to = from; if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) { - printk (KERN_WARNING "Invalid blacklist range " + printk (KERN_WARNING "cio: Invalid blacklist range " "0.%x.%04x to 0.%x.%04x, skipping\n", ssid, from, ssid, to); return; @@ -119,7 +119,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno) return 0; confused: strsep(str, ",\n"); - printk(KERN_WARNING "Invalid cio_ignore parameter '%s'\n", sav); + printk(KERN_WARNING "cio: Invalid cio_ignore parameter '%s'\n", sav); return 1; } @@ -166,22 +166,19 @@ blacklist_parse_parameters (char *str, range_action action) continue; } if (*str == '-') { - printk(KERN_WARNING "invalid cio_ignore " + printk(KERN_WARNING "cio: invalid cio_ignore " "parameter '%s'\n", strsep(&str, ",\n")); continue; } if ((from_id0 != to_id0) || (from_ssid != to_ssid)) { - printk(KERN_WARNING "invalid cio_ignore range " - "%x.%x.%04x-%x.%x.%04x\n", - from_id0, from_ssid, from, - to_id0, to_ssid, to); + printk(KERN_WARNING "cio: invalid cio_ignore " + "range %x.%x.%04x-%x.%x.%04x\n", + from_id0, from_ssid, from, + to_id0, to_ssid, to); continue; } - pr_debug("blacklist_setup: adding range " - "from %x.%x.%04x to %x.%x.%04x\n", - from_id0, from_ssid, from, to_id0, to_ssid, to); blacklist_range (ra, from, to, to_ssid); } } @@ -239,7 +236,7 @@ blacklist_parse_proc_parameters (char *buf) */ blacklist_parse_parameters (buf + 4, add); } else { - printk (KERN_WARNING "cio_ignore: Parse error; \n" + printk (KERN_WARNING "cio: cio_ignore: Parse error; \n" KERN_WARNING "try using 'free all|<devno-range>," "<devno-range>,...'\n" KERN_WARNING "or 'add <devno-range>," diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e5ccda6..b0a18f5 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -359,7 +359,6 @@ ccwgroup_probe (struct device *dev) if ((ret = device_create_file(dev, &dev_attr_online))) return ret; - pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id); ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV; if (ret) device_remove_file(dev, &dev_attr_online); @@ -376,8 +375,6 @@ ccwgroup_remove (struct device *dev) gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id); - device_remove_file(dev, &dev_attr_online); if (gdrv && gdrv->remove) diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index b57d93d..920dd71 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -121,14 +121,8 @@ static int s390_vary_chpid(struct chp_id chpid, int on) CIO_TRACE_EVENT( 2, dbf_text); status = chp_get_status(chpid); - if (status < 0) { - printk(KERN_ERR "Can't vary unknown chpid %x.%02x\n", - chpid.cssid, chpid.id); - return -EINVAL; - } - if (!on && !status) { - printk(KERN_ERR "chpid %x.%02x is already offline\n", + printk(KERN_ERR "cio: chpid %x.%02x is already offline\n", chpid.cssid, chpid.id); return -EINVAL; } @@ -421,21 +415,14 @@ int chp_new(struct chp_id chpid) if (ret) goto out_free; } else { - static int msg_done; - - if (!msg_done) { - printk(KERN_WARNING "cio: Channel measurements not " - "available, continuing.\n"); - msg_done = 1; - } chp->cmg = -1; } /* make it known to the system */ ret = device_register(&chp->dev); if (ret) { - printk(KERN_WARNING "%s: could not register %x.%02x\n", - __func__, chpid.cssid, chpid.id); + CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n", + chpid.cssid, chpid.id, ret); goto out_free; } ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index ea92ac4..597c0c7 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -990,16 +990,20 @@ out: return ret; } -static int __init -chsc_alloc_sei_area(void) +int __init chsc_alloc_sei_area(void) { sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!sei_page) - printk(KERN_WARNING"Can't allocate page for processing of " \ - "chsc machine checks!\n"); + CIO_MSG_EVENT(0, "Can't allocate page for processing of " + "chsc machine checks!\n"); return (sei_page ? 0 : -ENOMEM); } +void __init chsc_free_sei_area(void) +{ + kfree(sei_page); +} + int __init chsc_enable_facility(int operation_code) { @@ -1051,8 +1055,6 @@ chsc_enable_facility(int operation_code) return ret; } -subsys_initcall(chsc_alloc_sei_area); - struct css_general_char css_general_characteristics; struct css_chsc_char css_chsc_characteristics; @@ -1073,8 +1075,8 @@ chsc_determine_css_characteristics(void) scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scsc_area) { - printk(KERN_WARNING"cio: Was not able to determine available" \ - "CHSCs due to no memory.\n"); + CIO_MSG_EVENT(0, "Was not able to determine available" + "CHSCs due to no memory.\n"); return -ENOMEM; } @@ -1083,15 +1085,15 @@ chsc_determine_css_characteristics(void) result = chsc(scsc_area); if (result) { - printk(KERN_WARNING"cio: Was not able to determine " \ - "available CHSCs, cc=%i.\n", result); + CIO_MSG_EVENT(0, "Was not able to determine available CHSCs, " + "cc=%i.\n", result); result = -EIO; goto exit; } if (scsc_area->response.code != 1) { - printk(KERN_WARNING"cio: Was not able to determine " \ - "available CHSCs.\n"); + CIO_MSG_EVENT(0, "Was not able to determine " + "available CHSCs.\n"); result = -EIO; goto exit; } diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 2ad81d1..d1f5db1 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -79,6 +79,8 @@ extern int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd); extern int chsc_determine_css_characteristics(void); extern int css_characteristics_avail; +extern int chsc_alloc_sei_area(void); +extern void chsc_free_sei_area(void); extern int chsc_enable_facility(int); struct channel_subsystem; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index ea1defb..f2708d6 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -47,8 +47,8 @@ cio_setup (char *parm) else if (!strcmp (parm, "no")) cio_show_msg = 0; else - printk (KERN_ERR "cio_setup : invalid cio_msg parameter '%s'", - parm); + printk(KERN_ERR "cio: cio_setup: " + "invalid cio_msg parameter '%s'", parm); return 1; } @@ -80,7 +80,6 @@ cio_debug_init (void) goto out_unregister; debug_register_view (cio_debug_crw_id, &debug_sprintf_view); debug_set_level (cio_debug_crw_id, 2); - pr_debug("debugging initialized\n"); return 0; out_unregister: @@ -90,7 +89,7 @@ out_unregister: debug_unregister (cio_debug_trace_id); if (cio_debug_crw_id) debug_unregister (cio_debug_crw_id); - pr_debug("could not initialize debugging\n"); + printk(KERN_WARNING"cio: could not initialize debugging\n"); return -1; } @@ -568,7 +567,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) */ if (sch->st != 0) { CIO_DEBUG(KERN_INFO, 0, - "Subchannel 0.%x.%04x reports " + "cio: Subchannel 0.%x.%04x reports " "non-I/O subchannel type %04X\n", sch->schid.ssid, sch->schid.sch_no, sch->st); /* We stop here for non-io subchannels. */ @@ -601,7 +600,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) sch->lpm = sch->schib.pmcw.pam & sch->opm; CIO_DEBUG(KERN_INFO, 0, - "Detected device %04x on subchannel 0.%x.%04X" + "cio: Detected device %04x on subchannel 0.%x.%04X" " - PIM = %02X, PAM = %02X, POM = %02X\n", sch->schib.pmcw.dev, sch->schid.ssid, sch->schid.sch_no, sch->schib.pmcw.pim, @@ -766,7 +765,7 @@ cio_get_console_sch_no(void) /* unlike in 2.4, we cannot autoprobe here, since * the channel subsystem is not fully initialized. * With some luck, the HWC console can take over */ - printk(KERN_WARNING "No ccw console found!\n"); + printk(KERN_WARNING "cio: No ccw console found!\n"); return -1; } return console_irq; diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h index f88844a..c9bf898 100644 --- a/drivers/s390/cio/cio_debug.h +++ b/drivers/s390/cio/cio_debug.h @@ -23,6 +23,8 @@ extern debug_info_t *cio_debug_crw_id; static inline void CIO_HEX_EVENT(int level, void *data, int length) { + if (unlikely(!cio_debug_trace_id)) + return; while (length > 0) { debug_event(cio_debug_trace_id, level, data, length); length -= cio_debug_trace_id->buf_size; diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 28abd69..02fd00b 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1185,12 +1185,12 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att case '0': ret = disable_cmf(cdev); if (ret) - printk(KERN_INFO "disable_cmf failed (%d)\n", ret); + dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret); break; case '1': ret = enable_cmf(cdev); if (ret && ret != -EBUSY) - printk(KERN_INFO "enable_cmf failed (%d)\n", ret); + dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret); break; } @@ -1280,10 +1280,10 @@ init_cmf(void) format_string = "basic"; cmbops = &cmbops_basic; if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) { - printk(KERN_ERR "Basic channel measurement facility" - " can only use 1 to 4096 devices\n" + printk(KERN_ERR "cio: Basic channel measurement " + "facility can only use 1 to 4096 devices\n" KERN_ERR "when the cmf driver is built" - " as a loadable module\n"); + " as a loadable module\n"); return 1; } break; @@ -1292,13 +1292,13 @@ init_cmf(void) cmbops = &cmbops_extended; break; default: - printk(KERN_ERR "Invalid format %d for channel " + printk(KERN_ERR "cio: Invalid format %d for channel " "measurement facility\n", format); return 1; } - printk(KERN_INFO "Channel measurement facility using %s format (%s)\n", - format_string, detect_string); + printk(KERN_INFO "cio: Channel measurement facility using %s " + "format (%s)\n", format_string, detect_string); return 0; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index dfca0ef..1c27a5a 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -109,7 +109,7 @@ css_subchannel_release(struct device *dev) } } -int css_sch_device_register(struct subchannel *sch) +static int css_sch_device_register(struct subchannel *sch) { int ret; @@ -184,8 +184,8 @@ static int css_register_subchannel(struct subchannel *sch) /* make it known to the system */ ret = css_sch_device_register(sch); if (ret) { - printk (KERN_WARNING "%s: could not register %s\n", - __func__, sch->dev.bus_id); + CIO_MSG_EVENT(0, "Could not register sch 0.%x.%04x: %d\n", + sch->schid.ssid, sch->schid.sch_no, ret); return ret; } return ret; @@ -371,15 +371,12 @@ static int __init slow_subchannel_init(void) spin_lock_init(&slow_subchannel_lock); slow_subchannel_set = idset_sch_new(); if (!slow_subchannel_set) { - printk(KERN_WARNING "cio: could not allocate slow subchannel " - "set\n"); + CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); return -ENOMEM; } return 0; } -subsys_initcall(slow_subchannel_init); - static void css_slow_path_func(struct work_struct *unused) { struct subchannel_id schid; @@ -425,8 +422,8 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) struct subchannel *sch; int ret; - CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n", - schid.ssid, schid.sch_no); + CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n", + schid.ssid, schid.sch_no); if (need_reprobe) return -EAGAIN; @@ -642,9 +639,20 @@ init_channel_subsystem (void) { int ret, i; - if (chsc_determine_css_characteristics() == 0) + ret = chsc_determine_css_characteristics(); + if (ret == -ENOMEM) + goto out; /* No need to continue. */ + if (ret == 0) css_characteristics_avail = 1; + ret = chsc_alloc_sei_area(); + if (ret) + goto out; + + ret = slow_subchannel_init(); + if (ret) + goto out; + if ((ret = bus_register(&css_bus_type))) goto out; @@ -710,6 +718,10 @@ out_unregister: out_bus: bus_unregister(&css_bus_type); out: + chsc_free_sei_area(); + kfree(slow_subchannel_set); + printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n", + ret); return ret; } diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index ed79775..5d65e83 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -139,7 +139,6 @@ struct css_driver { */ extern struct bus_type css_bus_type; -extern int css_sch_device_register(struct subchannel *); extern void css_sch_device_unregister(struct subchannel *); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); extern int css_init_done; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 001682e..297659f 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -338,15 +338,20 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) rc = device_schedule_callback(&cdev->dev, ccw_device_remove_orphan_cb); if (rc) - dev_info(&cdev->dev, "Couldn't unregister orphan\n"); + CIO_MSG_EVENT(2, "Couldn't unregister orphan " + "0.%x.%04x\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); return; } /* Deregister subchannel, which will kill the ccw device. */ rc = device_schedule_callback(cdev->dev.parent, ccw_device_remove_sch_cb); if (rc) - dev_info(&cdev->dev, - "Couldn't unregister disconnected device\n"); + CIO_MSG_EVENT(2, "Couldn't unregister disconnected device " + "0.%x.%04x\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); } int @@ -379,8 +384,10 @@ ccw_device_set_offline(struct ccw_device *cdev) if (ret == 0) wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); else { - pr_debug("ccw_device_offline returned %d, device %s\n", - ret, cdev->dev.bus_id); + CIO_MSG_EVENT(2, "ccw_device_offline returned %d, " + "device 0.%x.%04x\n", + ret, cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); cdev->online = 1; } return ret; @@ -402,8 +409,10 @@ ccw_device_set_online(struct ccw_device *cdev) if (ret == 0) wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); else { - pr_debug("ccw_device_online returned %d, device %s\n", - ret, cdev->dev.bus_id); + CIO_MSG_EVENT(2, "ccw_device_online returned %d, " + "device 0.%x.%04x\n", + ret, cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); return ret; } if (cdev->private->state != DEV_STATE_ONLINE) @@ -417,9 +426,11 @@ ccw_device_set_online(struct ccw_device *cdev) spin_unlock_irq(cdev->ccwlock); if (ret == 0) wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); - else - pr_debug("ccw_device_offline returned %d, device %s\n", - ret, cdev->dev.bus_id); + else + CIO_MSG_EVENT(2, "ccw_device_offline returned %d, " + "device 0.%x.%04x\n", + ret, cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); return (ret == 0) ? -ENODEV : ret; } @@ -439,9 +450,10 @@ static int online_store_recog_and_online(struct ccw_device *cdev) if (cdev->id.cu_type == 0) { ret = ccw_device_recognition(cdev); if (ret) { - printk(KERN_WARNING"Couldn't start recognition " - "for device %s (ret=%d)\n", - cdev->dev.bus_id, ret); + CIO_MSG_EVENT(0, "Couldn't start recognition " + "for device 0.%x.%04x (ret=%d)\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno, ret); return ret; } wait_event(cdev->private->wait_q, @@ -461,8 +473,8 @@ static void online_store_handle_online(struct ccw_device *cdev, int force) if (force && cdev->private->state == DEV_STATE_BOXED) { ret = ccw_device_stlck(cdev); if (ret) { - printk(KERN_WARNING"ccw_device_stlck for device %s " - "returned %d!\n", cdev->dev.bus_id, ret); + dev_warn(&cdev->dev, + "ccw_device_stlck returned %d!\n", ret); return; } if (cdev->id.cu_type == 0) @@ -893,8 +905,10 @@ io_subchannel_register(struct work_struct *work) ret = device_reprobe(&cdev->dev); if (ret) /* We can't do much here. */ - dev_info(&cdev->dev, "device_reprobe() returned" - " %d\n", ret); + CIO_MSG_EVENT(2, "device_reprobe() returned" + " %d for 0.%x.%04x\n", ret, + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); } goto out; } @@ -907,8 +921,9 @@ io_subchannel_register(struct work_struct *work) /* make it known to the system */ ret = ccw_device_register(cdev); if (ret) { - printk (KERN_WARNING "%s: could not register %s\n", - __func__, cdev->dev.bus_id); + CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno, ret); put_device(&cdev->dev); spin_lock_irqsave(sch->lock, flags); sch->dev.driver_data = NULL; @@ -1361,7 +1376,6 @@ ccw_device_remove (struct device *dev) struct ccw_driver *cdrv = cdev->drv; int ret; - pr_debug("removing device %s\n", cdev->dev.bus_id); if (cdrv->remove) cdrv->remove(cdev); if (cdev->online) { @@ -1374,8 +1388,10 @@ ccw_device_remove (struct device *dev) dev_fsm_final_state(cdev)); else //FIXME: we can't fail! - pr_debug("ccw_device_offline returned %d, device %s\n", - ret, cdev->dev.bus_id); + CIO_MSG_EVENT(2, "ccw_device_offline returned %d, " + "device 0.%x.%04x\n", + ret, cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); } ccw_device_set_timeout(cdev, 0); cdev->drv = NULL; diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 6bba809..8633dc5 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -268,7 +268,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) switch (state) { case DEV_STATE_NOT_OPER: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : unknown device %04x on subchannel " + "cio: SenseID : unknown device %04x on subchannel " "0.%x.%04x\n", cdev->private->dev_id.devno, sch->schid.ssid, sch->schid.sch_no); break; @@ -293,7 +293,8 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) return; } /* Issue device info message. */ - CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: " + CIO_DEBUG(KERN_INFO, 2, + "cio: SenseID : device 0.%x.%04x reports: " "CU Type/Mod = %04X/%02X, Dev Type/Mod = " "%04X/%02X\n", cdev->private->dev_id.ssid, @@ -303,7 +304,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) break; case DEV_STATE_BOXED: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : boxed device %04x on subchannel " + "cio: SenseID : boxed device %04x on subchannel " "0.%x.%04x\n", cdev->private->dev_id.devno, sch->schid.ssid, sch->schid.sch_no); break; @@ -388,7 +389,7 @@ ccw_device_done(struct ccw_device *cdev, int state) if (state == DEV_STATE_BOXED) CIO_DEBUG(KERN_WARNING, 2, - "Boxed device %04x on subchannel %04x\n", + "cio: Boxed device %04x on subchannel %04x\n", cdev->private->dev_id.devno, sch->schid.sch_no); if (cdev->private->flags.donotify) { @@ -946,9 +947,10 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) /* Basic sense hasn't started. Try again. */ ccw_device_do_sense(cdev, irb); else { - printk(KERN_INFO "Huh? %s(%s): unsolicited " - "interrupt...\n", - __FUNCTION__, cdev->dev.bus_id); + CIO_MSG_EVENT(2, "Huh? 0.%x.%04x: unsolicited " + "interrupt during w4sense...\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno); if (cdev->handler) cdev->handler (cdev, 0, irb); } @@ -1215,8 +1217,8 @@ ccw_device_nop(struct ccw_device *cdev, enum dev_event dev_event) static void ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event) { - printk(KERN_EMERG "dev_jumptable[%i][%i] == NULL\n", - cdev->private->state, dev_event); + CIO_MSG_EVENT(0, "dev_jumptable[%i][%i] == NULL\n", + cdev->private->state, dev_event); BUG(); } diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index a5d263f..14eba85 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -288,253 +288,6 @@ ccw_device_get_path_mask(struct ccw_device *cdev) return sch->lpm; } -static void -ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) -{ - if (!ip) - /* unsolicited interrupt */ - return; - - /* Abuse intparm for error reporting. */ - if (IS_ERR(irb)) - cdev->private->intparm = -EIO; - else if (irb->scsw.cc == 1) - /* Retry for deferred condition code. */ - cdev->private->intparm = -EAGAIN; - else if ((irb->scsw.dstat != - (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) || - (irb->scsw.cstat != 0)) { - /* - * We didn't get channel end / device end. Check if path - * verification has been started; we can retry after it has - * finished. We also retry unit checks except for command reject - * or intervention required. Also check for long busy - * conditions. - */ - if (cdev->private->flags.doverify || - cdev->private->state == DEV_STATE_VERIFY) - cdev->private->intparm = -EAGAIN; - else if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) && - !(irb->ecw[0] & - (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) - cdev->private->intparm = -EAGAIN; - else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) && - (irb->scsw.dstat & DEV_STAT_DEV_END) && - (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP)) - cdev->private->intparm = -EAGAIN; - else - cdev->private->intparm = -EIO; - - } else - cdev->private->intparm = 0; - wake_up(&cdev->private->wait_q); -} - -static int -__ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm) -{ - int ret; - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - do { - ccw_device_set_timeout(cdev, 60 * HZ); - ret = cio_start (sch, ccw, lpm); - if (ret != 0) - ccw_device_set_timeout(cdev, 0); - if (ret == -EBUSY) { - /* Try again later. */ - spin_unlock_irq(sch->lock); - msleep(10); - spin_lock_irq(sch->lock); - continue; - } - if (ret != 0) - /* Non-retryable error. */ - break; - /* Wait for end of request. */ - cdev->private->intparm = magic; - spin_unlock_irq(sch->lock); - wait_event(cdev->private->wait_q, - (cdev->private->intparm == -EIO) || - (cdev->private->intparm == -EAGAIN) || - (cdev->private->intparm == 0)); - spin_lock_irq(sch->lock); - /* Check at least for channel end / device end */ - if (cdev->private->intparm == -EIO) { - /* Non-retryable error. */ - ret = -EIO; - break; - } - if (cdev->private->intparm == 0) - /* Success. */ - break; - /* Try again later. */ - spin_unlock_irq(sch->lock); - msleep(10); - spin_lock_irq(sch->lock); - } while (1); - - return ret; -} - -/** - * read_dev_chars() - read device characteristics - * @param cdev target ccw device - * @param buffer pointer to buffer for rdc data - * @param length size of rdc data - * @returns 0 for success, negative error value on failure - * - * Context: - * called for online device, lock not held - **/ -int -read_dev_chars (struct ccw_device *cdev, void **buffer, int length) -{ - void (*handler)(struct ccw_device *, unsigned long, struct irb *); - struct subchannel *sch; - int ret; - struct ccw1 *rdc_ccw; - - if (!cdev) - return -ENODEV; - if (!buffer || !length) - return -EINVAL; - sch = to_subchannel(cdev->dev.parent); - - CIO_TRACE_EVENT (4, "rddevch"); - CIO_TRACE_EVENT (4, sch->dev.bus_id); - - rdc_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); - if (!rdc_ccw) - return -ENOMEM; - rdc_ccw->cmd_code = CCW_CMD_RDC; - rdc_ccw->count = length; - rdc_ccw->flags = CCW_FLAG_SLI; - ret = set_normalized_cda (rdc_ccw, (*buffer)); - if (ret != 0) { - kfree(rdc_ccw); - return ret; - } - - spin_lock_irq(sch->lock); - /* Save interrupt handler. */ - handler = cdev->handler; - /* Temporarily install own handler. */ - cdev->handler = ccw_device_wake_up; - if (cdev->private->state != DEV_STATE_ONLINE) - ret = -ENODEV; - else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) && - !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) || - cdev->private->flags.doverify) - ret = -EBUSY; - else - /* 0x00D9C4C3 == ebcdic "RDC" */ - ret = __ccw_device_retry_loop(cdev, rdc_ccw, 0x00D9C4C3, 0); - - /* Restore interrupt handler. */ - cdev->handler = handler; - spin_unlock_irq(sch->lock); - - clear_normalized_cda (rdc_ccw); - kfree(rdc_ccw); - - return ret; -} - -/* - * Read Configuration data using path mask - */ -int -read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lpm) -{ - void (*handler)(struct ccw_device *, unsigned long, struct irb *); - struct subchannel *sch; - struct ciw *ciw; - char *rcd_buf; - int ret; - struct ccw1 *rcd_ccw; - - if (!cdev) - return -ENODEV; - if (!buffer || !length) - return -EINVAL; - sch = to_subchannel(cdev->dev.parent); - - CIO_TRACE_EVENT (4, "rdconf"); - CIO_TRACE_EVENT (4, sch->dev.bus_id); - - /* - * scan for RCD command in extended SenseID data - */ - ciw = ccw_device_get_ciw(cdev, CIW_TYPE_RCD); - if (!ciw || ciw->cmd == 0) - return -EOPNOTSUPP; - - /* Adjust requested path mask to excluded varied off paths. */ - if (lpm) { - lpm &= sch->opm; - if (lpm == 0) - return -EACCES; - } - - rcd_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); - if (!rcd_ccw) - return -ENOMEM; - rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA); - if (!rcd_buf) { - kfree(rcd_ccw); - return -ENOMEM; - } - rcd_ccw->cmd_code = ciw->cmd; - rcd_ccw->cda = (__u32) __pa (rcd_buf); - rcd_ccw->count = ciw->count; - rcd_ccw->flags = CCW_FLAG_SLI; - - spin_lock_irq(sch->lock); - /* Save interrupt handler. */ - handler = cdev->handler; - /* Temporarily install own handler. */ - cdev->handler = ccw_device_wake_up; - if (cdev->private->state != DEV_STATE_ONLINE) - ret = -ENODEV; - else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) && - !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) || - cdev->private->flags.doverify) - ret = -EBUSY; - else - /* 0x00D9C3C4 == ebcdic "RCD" */ - ret = __ccw_device_retry_loop(cdev, rcd_ccw, 0x00D9C3C4, lpm); - - /* Restore interrupt handler. */ - cdev->handler = handler; - spin_unlock_irq(sch->lock); - - /* - * on success we update the user input parms - */ - if (ret) { - kfree (rcd_buf); - *buffer = NULL; - *length = 0; - } else { - *length = ciw->count; - *buffer = rcd_buf; - } - kfree(rcd_ccw); - - return ret; -} - -/* - * Read Configuration data - */ -int -read_conf_data (struct ccw_device *cdev, void **buffer, int *length) -{ - return read_conf_data_lpm (cdev, buffer, length, 0); -} - /* * Try to break the lock on a boxed device. */ @@ -635,12 +388,6 @@ _ccw_device_get_subchannel_number(struct ccw_device *cdev) return cdev->private->schid.sch_no; } -int -_ccw_device_get_device_number(struct ccw_device *cdev) -{ - return cdev->private->dev_id.devno; -} - MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ccw_device_set_options_mask); @@ -655,9 +402,5 @@ EXPORT_SYMBOL(ccw_device_start_timeout_key); EXPORT_SYMBOL(ccw_device_start_key); EXPORT_SYMBOL(ccw_device_get_ciw); EXPORT_SYMBOL(ccw_device_get_path_mask); -EXPORT_SYMBOL(read_conf_data); -EXPORT_SYMBOL(read_dev_chars); EXPORT_SYMBOL(_ccw_device_get_subchannel_number); -EXPORT_SYMBOL(_ccw_device_get_device_number); EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc); -EXPORT_SYMBOL_GPL(read_conf_data_lpm); diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index b20fd06..92e8a37 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -674,7 +674,7 @@ ch_action_txdone(fsm_instance * fi, int event, void *arg) int first = 1; int i; unsigned long duration; - struct timespec done_stamp = xtime; + struct timespec done_stamp = current_kernel_time(); DBF_TEXT(trace, 4, __FUNCTION__); @@ -730,7 +730,7 @@ ch_action_txdone(fsm_instance * fi, int event, void *arg) spin_unlock(&ch->collect_lock); ch->ccw[1].count = ch->trans_skb->len; fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); - ch->prof.send_stamp = xtime; + ch->prof.send_stamp = current_kernel_time(); rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0); ch->prof.doios_multi++; @@ -2281,7 +2281,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) fsm_newstate(ch->fsm, CH_STATE_TX); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); - ch->prof.send_stamp = xtime; + ch->prof.send_stamp = current_kernel_time(); rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx], (unsigned long) ch, 0xff, 0); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 3d28e1a..2688894 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -753,7 +753,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg) header.next = 0; memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN); - conn->prof.send_stamp = xtime; + conn->prof.send_stamp = current_kernel_time(); txmsg.class = 0; txmsg.tag = 0; rc = iucv_message_send(conn->path, &txmsg, 0, 0, @@ -1185,7 +1185,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn, memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN); fsm_newstate(conn->fsm, CONN_STATE_TX); - conn->prof.send_stamp = xtime; + conn->prof.send_stamp = current_kernel_time(); msg.tag = 1; msg.class = 0; diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 35a7316..400c65b 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig @@ -15,6 +15,7 @@ config SUN_OPENPROMIO config SUN_MOSTEK_RTC tristate "Mostek real time clock support" + depends on SPARC32 help The Mostek RTC chip is used on all known Sun computers except some JavaStations. For a JavaStation you need to say Y both here diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index e821a15..0bde269 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -479,11 +479,12 @@ static int kenvctrld(void *__unused) static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) { - struct bbc_cpu_temperature *tp = kmalloc(sizeof(*tp), GFP_KERNEL); + struct bbc_cpu_temperature *tp; + tp = kzalloc(sizeof(*tp), GFP_KERNEL); if (!tp) return; - memset(tp, 0, sizeof(*tp)); + tp->client = bbc_i2c_attach(echild); if (!tp->client) { kfree(tp); @@ -525,11 +526,12 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) { - struct bbc_fan_control *fp = kmalloc(sizeof(*fp), GFP_KERNEL); + struct bbc_fan_control *fp; + fp = kzalloc(sizeof(*fp), GFP_KERNEL); if (!fp) return; - memset(fp, 0, sizeof(*fp)); + fp->client = bbc_i2c_attach(echild); if (!fp->client) { kfree(fp); diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index fbadd4d..ac8ef2c 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -357,13 +357,13 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) { - struct bbc_i2c_bus *bp = kmalloc(sizeof(*bp), GFP_KERNEL); + struct bbc_i2c_bus *bp; struct linux_ebus_child *echild; int entry; + bp = kzalloc(sizeof(*bp), GFP_KERNEL); if (!bp) return -ENOMEM; - memset(bp, 0, sizeof(*bp)); bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2); if (!bp->i2c_control_regs) diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 5157a2a..4b7079f 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -185,7 +185,7 @@ static void jsfd_read(char *buf, unsigned long p, size_t togo) { } } -static void jsfd_do_request(request_queue_t *q) +static void jsfd_do_request(struct request_queue *q) { struct request *req; diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 26b1d2a..9269f7f 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -248,6 +248,7 @@ static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp) buffer,inout.len); if (copy_to_user(argp,&inout,sizeof(inout))) { + vfc_unlock_device(dev); kfree(buffer); return -EFAULT; } diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 2553629..c37d7c2 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -210,6 +210,10 @@ static void __init walk_children(struct device_node *dp, struct sbus_dev *parent sdev->bus = sbus; sdev->parent = parent; + sdev->ofdev.dev.archdata.iommu = + sbus->ofdev.dev.archdata.iommu; + sdev->ofdev.dev.archdata.stc = + sbus->ofdev.dev.archdata.stc; fill_sbus_device(dp, sdev); @@ -269,6 +273,11 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus) sdev->bus = sbus; sdev->parent = NULL; + sdev->ofdev.dev.archdata.iommu = + sbus->ofdev.dev.archdata.iommu; + sdev->ofdev.dev.archdata.stc = + sbus->ofdev.dev.archdata.stc; + fill_sbus_device(dev_dp, sdev); walk_children(dev_dp, sdev, sbus); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index a26baab..6800e57 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -194,8 +194,7 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd, struct scsi_device *device; if (unlikely(!scsicmd || !scsicmd->scsi_done )) { - dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")) -; + dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")); aac_fib_complete(fibptr); aac_fib_free(fibptr); return 0; @@ -1689,23 +1688,23 @@ static void synchronize_callback(void *context, struct fib *fibptr) if (!aac_valid_context(cmd, fibptr)) return; - dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", + dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); synchronizereply = fib_data(fibptr); if (le32_to_cpu(synchronizereply->status) == CT_OK) - cmd->result = DID_OK << 16 | + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; else { struct scsi_device *sdev = cmd->device; struct aac_dev *dev = fibptr->dev; u32 cid = sdev_id(sdev); - printk(KERN_WARNING + printk(KERN_WARNING "synchronize_callback: synchronize failed, status = %d\n", le32_to_cpu(synchronizereply->status)); - cmd->result = DID_OK << 16 | + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *)&dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, @@ -1713,7 +1712,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - min(sizeof(dev->fsa_dev[cid].sense_data), + min(sizeof(dev->fsa_dev[cid].sense_data), sizeof(cmd->sense_buffer))); } @@ -1731,6 +1730,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) struct scsi_device *sdev = scsicmd->device; int active = 0; struct aac_dev *aac; + u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; unsigned long flags; /* @@ -1739,7 +1741,51 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) */ spin_lock_irqsave(&sdev->list_lock, flags); list_for_each_entry(cmd, &sdev->cmd_list, list) - if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) { + if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) { + u64 cmnd_lba; + u32 cmnd_count; + + if (cmd->cmnd[0] == WRITE_6) { + cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) | + (cmd->cmnd[2] << 8) | + cmd->cmnd[3]; + cmnd_count = cmd->cmnd[4]; + if (cmnd_count == 0) + cmnd_count = 256; + } else if (cmd->cmnd[0] == WRITE_16) { + cmnd_lba = ((u64)cmd->cmnd[2] << 56) | + ((u64)cmd->cmnd[3] << 48) | + ((u64)cmd->cmnd[4] << 40) | + ((u64)cmd->cmnd[5] << 32) | + ((u64)cmd->cmnd[6] << 24) | + (cmd->cmnd[7] << 16) | + (cmd->cmnd[8] << 8) | + cmd->cmnd[9]; + cmnd_count = (cmd->cmnd[10] << 24) | + (cmd->cmnd[11] << 16) | + (cmd->cmnd[12] << 8) | + cmd->cmnd[13]; + } else if (cmd->cmnd[0] == WRITE_12) { + cmnd_lba = ((u64)cmd->cmnd[2] << 24) | + (cmd->cmnd[3] << 16) | + (cmd->cmnd[4] << 8) | + cmd->cmnd[5]; + cmnd_count = (cmd->cmnd[6] << 24) | + (cmd->cmnd[7] << 16) | + (cmd->cmnd[8] << 8) | + cmd->cmnd[9]; + } else if (cmd->cmnd[0] == WRITE_10) { + cmnd_lba = ((u64)cmd->cmnd[2] << 24) | + (cmd->cmnd[3] << 16) | + (cmd->cmnd[4] << 8) | + cmd->cmnd[5]; + cmnd_count = (cmd->cmnd[7] << 8) | + cmd->cmnd[8]; + } else + continue; + if (((cmnd_lba + cmnd_count) < lba) || + (count && ((lba + count) < cmnd_lba))) + continue; ++active; break; } @@ -1768,7 +1814,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); - synchronizecmd->count = + synchronizecmd->count = cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); /* @@ -1790,7 +1836,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) return 0; } - printk(KERN_WARNING + printk(KERN_WARNING "aac_synchronize: aac_fib_send failed with status: %d.\n", status); aac_fib_complete(cmd_fibcontext); aac_fib_free(cmd_fibcontext); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 400d034..94727b9 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2447 +# define AAC_DRIVER_BUILD 2449 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -1807,10 +1807,10 @@ struct aac_aifcmd { * accounting for the fact capacity could be a 64 bit value * */ -static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) +static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) { sector_div(capacity, divisor); - return (u32)capacity; + return capacity; } /* SCp.phase values */ diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index d76e1a8..813556c 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -636,6 +636,8 @@ static int aac_cfg_open(struct inode *inode, struct file *file) static int aac_cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } @@ -689,6 +691,8 @@ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); } #endif @@ -822,7 +826,7 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev, tmp = aac_adapter_check_health(dev); if ((tmp == 0) && dev->in_reset) tmp = -EBUSY; - len = snprintf(buf, PAGE_SIZE, "0x%x", tmp); + len = snprintf(buf, PAGE_SIZE, "0x%x\n", tmp); return len; } @@ -1122,9 +1126,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, static void aac_shutdown(struct pci_dev *dev) { struct Scsi_Host *shost = pci_get_drvdata(dev); - struct aac_dev *aac = (struct aac_dev *)shost->hostdata; scsi_block_requests(shost); - __aac_shutdown(aac); + __aac_shutdown((struct aac_dev *)shost->hostdata); } static void __devexit aac_remove_one(struct pci_dev *pdev) diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index a8ace56..c55f7c8 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c @@ -1,11 +1,10 @@ /* * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com> * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2006-2007 Adaptec, Inc. (aacraid@adaptec.com) * * 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 diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 9c5fcfb..8cd6588 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * 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 diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index ebc65b9..73eef3d 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -472,7 +472,7 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) else { bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (!bled && (var != 0x00000001)) + if (!bled && (var != 0x00000001) && (var != 0x3803000F)) bled = -EINVAL; } if (bled && (bled != -ETIMEDOUT)) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 2b66897..79c0b6e 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -1,4 +1,4 @@ -#define ASC_VERSION "3.3K" /* AdvanSys Driver Version */ +#define ASC_VERSION "3.3K" /* AdvanSys Driver Version */ /* * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters @@ -802,7 +802,6 @@ #include <linux/pci.h> #endif /* CONFIG_PCI */ - /* * --- Driver Options */ @@ -816,18 +815,6 @@ /* Enable driver tracing. */ /* #define ADVANSYS_DEBUG */ - -/* - * --- Debugging Header - */ - -#ifdef ADVANSYS_DEBUG -#define STATIC -#else /* ADVANSYS_DEBUG */ -#define STATIC static -#endif /* ADVANSYS_DEBUG */ - - /* * --- Asc Library Constants and Macros */ @@ -845,10 +832,10 @@ * are all consistent at 8, 16, and 32 bits respectively. Pointers * and long types are 64 bits on Alpha and UltraSPARC. */ -#define ASC_PADDR __u32 /* Physical/Bus address data type. */ -#define ASC_VADDR __u32 /* Virtual address data type. */ -#define ASC_DCNT __u32 /* Unsigned Data count type. */ -#define ASC_SDCNT __s32 /* Signed Data count type. */ +#define ASC_PADDR __u32 /* Physical/Bus address data type. */ +#define ASC_VADDR __u32 /* Virtual address data type. */ +#define ASC_DCNT __u32 /* Unsigned Data count type. */ +#define ASC_SDCNT __s32 /* Signed Data count type. */ /* * These macros are used to convert a virtual address to a @@ -911,7 +898,7 @@ typedef unsigned char uchar; #define CC_VERY_LONG_SG_LIST 0 #define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr) -#define PortAddr unsigned short /* port address size */ +#define PortAddr unsigned short /* port address size */ #define inp(port) inb(port) #define outp(port, byte) outb((byte), (port)) @@ -1038,17 +1025,17 @@ typedef unsigned char uchar; #define ASC_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) typedef struct { - uchar periph; - uchar devtype; - uchar ver; - uchar byte3; - uchar add_len; - uchar res1; - uchar res2; - uchar flags; - uchar vendor_id[8]; - uchar product_id[16]; - uchar product_rev_level[4]; + uchar periph; + uchar devtype; + uchar ver; + uchar byte3; + uchar add_len; + uchar res1; + uchar res2; + uchar flags; + uchar vendor_id[8]; + uchar product_id[16]; + uchar product_rev_level[4]; } ASC_SCSI_INQUIRY; #define ASC_SG_LIST_PER_Q 7 @@ -1165,139 +1152,139 @@ typedef struct { #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6)) typedef struct asc_scsiq_1 { - uchar status; - uchar q_no; - uchar cntl; - uchar sg_queue_cnt; - uchar target_id; - uchar target_lun; - ASC_PADDR data_addr; - ASC_DCNT data_cnt; - ASC_PADDR sense_addr; - uchar sense_len; - uchar extra_bytes; + uchar status; + uchar q_no; + uchar cntl; + uchar sg_queue_cnt; + uchar target_id; + uchar target_lun; + ASC_PADDR data_addr; + ASC_DCNT data_cnt; + ASC_PADDR sense_addr; + uchar sense_len; + uchar extra_bytes; } ASC_SCSIQ_1; typedef struct asc_scsiq_2 { - ASC_VADDR srb_ptr; - uchar target_ix; - uchar flag; - uchar cdb_len; - uchar tag_code; - ushort vm_id; + ASC_VADDR srb_ptr; + uchar target_ix; + uchar flag; + uchar cdb_len; + uchar tag_code; + ushort vm_id; } ASC_SCSIQ_2; typedef struct asc_scsiq_3 { - uchar done_stat; - uchar host_stat; - uchar scsi_stat; - uchar scsi_msg; + uchar done_stat; + uchar host_stat; + uchar scsi_stat; + uchar scsi_msg; } ASC_SCSIQ_3; typedef struct asc_scsiq_4 { - uchar cdb[ASC_MAX_CDB_LEN]; - uchar y_first_sg_list_qp; - uchar y_working_sg_qp; - uchar y_working_sg_ix; - uchar y_res; - ushort x_req_count; - ushort x_reconnect_rtn; - ASC_PADDR x_saved_data_addr; - ASC_DCNT x_saved_data_cnt; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar y_first_sg_list_qp; + uchar y_working_sg_qp; + uchar y_working_sg_ix; + uchar y_res; + ushort x_req_count; + ushort x_reconnect_rtn; + ASC_PADDR x_saved_data_addr; + ASC_DCNT x_saved_data_cnt; } ASC_SCSIQ_4; typedef struct asc_q_done_info { - ASC_SCSIQ_2 d2; - ASC_SCSIQ_3 d3; - uchar q_status; - uchar q_no; - uchar cntl; - uchar sense_len; - uchar extra_bytes; - uchar res; - ASC_DCNT remain_bytes; + ASC_SCSIQ_2 d2; + ASC_SCSIQ_3 d3; + uchar q_status; + uchar q_no; + uchar cntl; + uchar sense_len; + uchar extra_bytes; + uchar res; + ASC_DCNT remain_bytes; } ASC_QDONE_INFO; typedef struct asc_sg_list { - ASC_PADDR addr; - ASC_DCNT bytes; + ASC_PADDR addr; + ASC_DCNT bytes; } ASC_SG_LIST; typedef struct asc_sg_head { - ushort entry_cnt; - ushort queue_cnt; - ushort entry_to_copy; - ushort res; - ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; + ushort entry_cnt; + ushort queue_cnt; + ushort entry_to_copy; + ushort res; + ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; } ASC_SG_HEAD; #define ASC_MIN_SG_LIST 2 typedef struct asc_min_sg_head { - ushort entry_cnt; - ushort queue_cnt; - ushort entry_to_copy; - ushort res; - ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; + ushort entry_cnt; + ushort queue_cnt; + ushort entry_to_copy; + ushort res; + ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; } ASC_MIN_SG_HEAD; #define QCX_SORT (0x0001) #define QCX_COALEASE (0x0002) typedef struct asc_scsi_q { - ASC_SCSIQ_1 q1; - ASC_SCSIQ_2 q2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - ushort remain_sg_entry_cnt; - ushort next_sg_index; + ASC_SCSIQ_1 q1; + ASC_SCSIQ_2 q2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + ushort remain_sg_entry_cnt; + ushort next_sg_index; } ASC_SCSI_Q; typedef struct asc_scsi_req_q { - ASC_SCSIQ_1 r1; - ASC_SCSIQ_2 r2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - uchar *sense_ptr; - ASC_SCSIQ_3 r3; - uchar cdb[ASC_MAX_CDB_LEN]; - uchar sense[ASC_MIN_SENSE_LEN]; + ASC_SCSIQ_1 r1; + ASC_SCSIQ_2 r2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + uchar *sense_ptr; + ASC_SCSIQ_3 r3; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar sense[ASC_MIN_SENSE_LEN]; } ASC_SCSI_REQ_Q; typedef struct asc_scsi_bios_req_q { - ASC_SCSIQ_1 r1; - ASC_SCSIQ_2 r2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - uchar *sense_ptr; - ASC_SCSIQ_3 r3; - uchar cdb[ASC_MAX_CDB_LEN]; - uchar sense[ASC_MIN_SENSE_LEN]; + ASC_SCSIQ_1 r1; + ASC_SCSIQ_2 r2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + uchar *sense_ptr; + ASC_SCSIQ_3 r3; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar sense[ASC_MIN_SENSE_LEN]; } ASC_SCSI_BIOS_REQ_Q; typedef struct asc_risc_q { - uchar fwd; - uchar bwd; - ASC_SCSIQ_1 i1; - ASC_SCSIQ_2 i2; - ASC_SCSIQ_3 i3; - ASC_SCSIQ_4 i4; + uchar fwd; + uchar bwd; + ASC_SCSIQ_1 i1; + ASC_SCSIQ_2 i2; + ASC_SCSIQ_3 i3; + ASC_SCSIQ_4 i4; } ASC_RISC_Q; typedef struct asc_sg_list_q { - uchar seq_no; - uchar q_no; - uchar cntl; - uchar sg_head_qp; - uchar sg_list_cnt; - uchar sg_cur_list_cnt; + uchar seq_no; + uchar q_no; + uchar cntl; + uchar sg_head_qp; + uchar sg_list_cnt; + uchar sg_cur_list_cnt; } ASC_SG_LIST_Q; typedef struct asc_risc_sg_list_q { - uchar fwd; - uchar bwd; - ASC_SG_LIST_Q sg; - ASC_SG_LIST sg_list[7]; + uchar fwd; + uchar bwd; + ASC_SG_LIST_Q sg; + ASC_SG_LIST sg_list[7]; } ASC_RISC_SG_LIST_Q; #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL @@ -1431,25 +1418,25 @@ typedef struct asc_risc_sg_list_q { #define SYN_ULTRA_XFER_NS_15 107 typedef struct ext_msg { - uchar msg_type; - uchar msg_len; - uchar msg_req; - union { - struct { - uchar sdtr_xfer_period; - uchar sdtr_req_ack_offset; - } sdtr; - struct { - uchar wdtr_width; - } wdtr; - struct { - uchar mdp_b3; - uchar mdp_b2; - uchar mdp_b1; - uchar mdp_b0; - } mdp; - } u_ext_msg; - uchar res; + uchar msg_type; + uchar msg_len; + uchar msg_req; + union { + struct { + uchar sdtr_xfer_period; + uchar sdtr_req_ack_offset; + } sdtr; + struct { + uchar wdtr_width; + } wdtr; + struct { + uchar mdp_b3; + uchar mdp_b2; + uchar mdp_b1; + uchar mdp_b0; + } mdp; + } u_ext_msg; + uchar res; } EXT_MSG; #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period @@ -1461,24 +1448,24 @@ typedef struct ext_msg { #define mdp_b0 u_ext_msg.mdp_b0 typedef struct asc_dvc_cfg { - ASC_SCSI_BIT_ID_TYPE can_tagged_qng; - ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; - ASC_SCSI_BIT_ID_TYPE disc_enable; - ASC_SCSI_BIT_ID_TYPE sdtr_enable; - uchar chip_scsi_id; - uchar isa_dma_speed; - uchar isa_dma_channel; - uchar chip_version; - ushort lib_serial_no; - ushort lib_version; - ushort mcode_date; - ushort mcode_version; - uchar max_tag_qng[ASC_MAX_TID + 1]; - uchar *overrun_buf; - uchar sdtr_period_offset[ASC_MAX_TID + 1]; - ushort pci_slot_info; - uchar adapter_info[6]; - struct device *dev; + ASC_SCSI_BIT_ID_TYPE can_tagged_qng; + ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; + ASC_SCSI_BIT_ID_TYPE disc_enable; + ASC_SCSI_BIT_ID_TYPE sdtr_enable; + uchar chip_scsi_id; + uchar isa_dma_speed; + uchar isa_dma_channel; + uchar chip_version; + ushort lib_serial_no; + ushort lib_version; + ushort mcode_date; + ushort mcode_version; + uchar max_tag_qng[ASC_MAX_TID + 1]; + uchar *overrun_buf; + uchar sdtr_period_offset[ASC_MAX_TID + 1]; + ushort pci_slot_info; + uchar adapter_info[6]; + struct device *dev; } ASC_DVC_CFG; #define ASC_DEF_DVC_CNTL 0xFFFF @@ -1501,64 +1488,64 @@ typedef struct asc_dvc_cfg { #define ASC_MIN_TAGGED_CMD 7 #define ASC_MAX_SCSI_RESET_WAIT 30 -struct asc_dvc_var; /* Forward Declaration. */ +struct asc_dvc_var; /* Forward Declaration. */ -typedef void (* ASC_ISR_CALLBACK)(struct asc_dvc_var *, ASC_QDONE_INFO *); -typedef int (* ASC_EXE_CALLBACK)(struct asc_dvc_var *, ASC_SCSI_Q *); +typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *); +typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *); typedef struct asc_dvc_var { - PortAddr iop_base; - ushort err_code; - ushort dvc_cntl; - ushort bug_fix_cntl; - ushort bus_type; - ASC_ISR_CALLBACK isr_callback; - ASC_EXE_CALLBACK exe_callback; - ASC_SCSI_BIT_ID_TYPE init_sdtr; - ASC_SCSI_BIT_ID_TYPE sdtr_done; - ASC_SCSI_BIT_ID_TYPE use_tagged_qng; - ASC_SCSI_BIT_ID_TYPE unit_not_ready; - ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; - ASC_SCSI_BIT_ID_TYPE start_motor; - uchar scsi_reset_wait; - uchar chip_no; - char is_in_int; - uchar max_total_qng; - uchar cur_total_qng; - uchar in_critical_cnt; - uchar irq_no; - uchar last_q_shortage; - ushort init_state; - uchar cur_dvc_qng[ASC_MAX_TID + 1]; - uchar max_dvc_qng[ASC_MAX_TID + 1]; - ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; - ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; - uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; - ASC_DVC_CFG *cfg; - ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; - char redo_scam; - ushort res2; - uchar dos_int13_table[ASC_MAX_TID + 1]; - ASC_DCNT max_dma_count; - ASC_SCSI_BIT_ID_TYPE no_scam; - ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; - uchar max_sdtr_index; - uchar host_init_sdtr_index; - struct asc_board *drv_ptr; - ASC_DCNT uc_break; + PortAddr iop_base; + ushort err_code; + ushort dvc_cntl; + ushort bug_fix_cntl; + ushort bus_type; + ASC_ISR_CALLBACK isr_callback; + ASC_EXE_CALLBACK exe_callback; + ASC_SCSI_BIT_ID_TYPE init_sdtr; + ASC_SCSI_BIT_ID_TYPE sdtr_done; + ASC_SCSI_BIT_ID_TYPE use_tagged_qng; + ASC_SCSI_BIT_ID_TYPE unit_not_ready; + ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; + ASC_SCSI_BIT_ID_TYPE start_motor; + uchar scsi_reset_wait; + uchar chip_no; + char is_in_int; + uchar max_total_qng; + uchar cur_total_qng; + uchar in_critical_cnt; + uchar irq_no; + uchar last_q_shortage; + ushort init_state; + uchar cur_dvc_qng[ASC_MAX_TID + 1]; + uchar max_dvc_qng[ASC_MAX_TID + 1]; + ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; + ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; + uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; + ASC_DVC_CFG *cfg; + ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; + char redo_scam; + ushort res2; + uchar dos_int13_table[ASC_MAX_TID + 1]; + ASC_DCNT max_dma_count; + ASC_SCSI_BIT_ID_TYPE no_scam; + ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; + uchar max_sdtr_index; + uchar host_init_sdtr_index; + struct asc_board *drv_ptr; + ASC_DCNT uc_break; } ASC_DVC_VAR; typedef struct asc_dvc_inq_info { - uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; + uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; } ASC_DVC_INQ_INFO; typedef struct asc_cap_info { - ASC_DCNT lba; - ASC_DCNT blk_size; + ASC_DCNT lba; + ASC_DCNT blk_size; } ASC_CAP_INFO; typedef struct asc_cap_info_array { - ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; + ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; } ASC_CAP_INFO_ARRAY; #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001 @@ -1603,23 +1590,23 @@ typedef struct asc_cap_info_array { ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4) typedef struct asceep_config { - ushort cfg_lsw; - ushort cfg_msw; - uchar init_sdtr; - uchar disc_enable; - uchar use_cmd_qng; - uchar start_motor; - uchar max_total_qng; - uchar max_tag_qng; - uchar bios_scan; - uchar power_up_wait; - uchar no_scam; - uchar id_speed; /* low order 4 bits is chip scsi id */ - /* high order 4 bits is isa dma speed */ - uchar dos_int13_table[ASC_MAX_TID + 1]; - uchar adapter_info[6]; - ushort cntl; - ushort chksum; + ushort cfg_lsw; + ushort cfg_msw; + uchar init_sdtr; + uchar disc_enable; + uchar use_cmd_qng; + uchar start_motor; + uchar max_total_qng; + uchar max_tag_qng; + uchar bios_scan; + uchar power_up_wait; + uchar no_scam; + uchar id_speed; /* low order 4 bits is chip scsi id */ + /* high order 4 bits is isa dma speed */ + uchar dos_int13_table[ASC_MAX_TID + 1]; + uchar adapter_info[6]; + ushort cntl; + ushort chksum; } ASCEEP_CONFIG; #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800 @@ -1827,8 +1814,8 @@ typedef struct asceep_config { #define ASC_MC_SAVE_DATA_WSIZE 0x40 typedef struct asc_mc_saved { - ushort data[ASC_MC_SAVE_DATA_WSIZE]; - ushort code[ASC_MC_SAVE_CODE_WSIZE]; + ushort data[ASC_MC_SAVE_DATA_WSIZE]; + ushort code[ASC_MC_SAVE_CODE_WSIZE]; } ASC_MC_SAVED; #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B) @@ -1900,120 +1887,113 @@ typedef struct asc_mc_saved { #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) -STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); -STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); -STATIC void AscWaitEEPRead(void); -STATIC void AscWaitEEPWrite(void); -STATIC ushort AscReadEEPWord(PortAddr, uchar); -STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort); -STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscStartChip(PortAddr); -STATIC int AscStopChip(PortAddr); -STATIC void AscSetChipIH(PortAddr, ushort); -STATIC int AscIsChipHalted(PortAddr); -STATIC void AscAckInterrupt(PortAddr); -STATIC void AscDisableInterrupt(PortAddr); -STATIC void AscEnableInterrupt(PortAddr); -STATIC void AscSetBank(PortAddr, uchar); -STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *); +static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); +static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); +static void AscWaitEEPRead(void); +static void AscWaitEEPWrite(void); +static ushort AscReadEEPWord(PortAddr, uchar); +static ushort AscWriteEEPWord(PortAddr, uchar, ushort); +static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscStartChip(PortAddr); +static int AscStopChip(PortAddr); +static void AscSetChipIH(PortAddr, ushort); +static int AscIsChipHalted(PortAddr); +static void AscAckInterrupt(PortAddr); +static void AscDisableInterrupt(PortAddr); +static void AscEnableInterrupt(PortAddr); +static void AscSetBank(PortAddr, uchar); +static int AscResetChipAndScsiBus(ASC_DVC_VAR *); #ifdef CONFIG_ISA -STATIC ushort AscGetIsaDmaChannel(PortAddr); -STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort); -STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar); -STATIC uchar AscGetIsaDmaSpeed(PortAddr); +static ushort AscGetIsaDmaChannel(PortAddr); +static ushort AscSetIsaDmaChannel(PortAddr, ushort); +static uchar AscSetIsaDmaSpeed(PortAddr, uchar); +static uchar AscGetIsaDmaSpeed(PortAddr); #endif /* CONFIG_ISA */ -STATIC uchar AscReadLramByte(PortAddr, ushort); -STATIC ushort AscReadLramWord(PortAddr, ushort); +static uchar AscReadLramByte(PortAddr, ushort); +static ushort AscReadLramWord(PortAddr, ushort); #if CC_VERY_LONG_SG_LIST -STATIC ASC_DCNT AscReadLramDWord(PortAddr, ushort); +static ASC_DCNT AscReadLramDWord(PortAddr, ushort); #endif /* CC_VERY_LONG_SG_LIST */ -STATIC void AscWriteLramWord(PortAddr, ushort, ushort); -STATIC void AscWriteLramByte(PortAddr, ushort, uchar); -STATIC ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); -STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, int); -STATIC void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -STATIC void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -STATIC void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); -STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR *); -STATIC ushort AscInitFromEEP(ASC_DVC_VAR *); -STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR *); -STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR *); -STATIC int AscTestExternalLram(ASC_DVC_VAR *); -STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); -STATIC uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); -STATIC void AscSetChipSDTR(PortAddr, uchar, uchar); -STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); -STATIC uchar AscAllocFreeQueue(PortAddr, uchar); -STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); -STATIC int AscHostReqRiscHalt(PortAddr); -STATIC int AscStopQueueExe(PortAddr); -STATIC int AscSendScsiQueue(ASC_DVC_VAR *, - ASC_SCSI_Q * scsiq, - uchar n_q_required); -STATIC int AscPutReadyQueue(ASC_DVC_VAR *, - ASC_SCSI_Q *, uchar); -STATIC int AscPutReadySgListQueue(ASC_DVC_VAR *, - ASC_SCSI_Q *, uchar); -STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar); -STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); -STATIC ushort AscInitLram(ASC_DVC_VAR *); -STATIC ushort AscInitQLinkVar(ASC_DVC_VAR *); -STATIC int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); -STATIC int AscIsrChipHalted(ASC_DVC_VAR *); -STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, - ASC_QDONE_INFO *, ASC_DCNT); -STATIC int AscIsrQDone(ASC_DVC_VAR *); -STATIC int AscCompareString(uchar *, uchar *, int); +static void AscWriteLramWord(PortAddr, ushort, ushort); +static void AscWriteLramByte(PortAddr, ushort, uchar); +static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); +static void AscMemWordSetLram(PortAddr, ushort, ushort, int); +static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); +static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); +static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); +static ushort AscInitAscDvcVar(ASC_DVC_VAR *); +static ushort AscInitFromEEP(ASC_DVC_VAR *); +static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *); +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *); +static int AscTestExternalLram(ASC_DVC_VAR *); +static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); +static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); +static void AscSetChipSDTR(PortAddr, uchar, uchar); +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); +static uchar AscAllocFreeQueue(PortAddr, uchar); +static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); +static int AscHostReqRiscHalt(PortAddr); +static int AscStopQueueExe(PortAddr); +static int AscSendScsiQueue(ASC_DVC_VAR *, + ASC_SCSI_Q *scsiq, uchar n_q_required); +static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); +static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); +static int AscSetChipSynRegAtID(PortAddr, uchar, uchar); +static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); +static ushort AscInitLram(ASC_DVC_VAR *); +static ushort AscInitQLinkVar(ASC_DVC_VAR *); +static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); +static int AscIsrChipHalted(ASC_DVC_VAR *); +static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, + ASC_QDONE_INFO *, ASC_DCNT); +static int AscIsrQDone(ASC_DVC_VAR *); +static int AscCompareString(uchar *, uchar *, int); #ifdef CONFIG_ISA -STATIC ushort AscGetEisaChipCfg(PortAddr); -STATIC ASC_DCNT AscGetEisaProductID(PortAddr); -STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr); -STATIC PortAddr AscSearchIOPortAddr11(PortAddr); -STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort); -STATIC void AscSetISAPNPWaitForKey(void); +static ushort AscGetEisaChipCfg(PortAddr); +static ASC_DCNT AscGetEisaProductID(PortAddr); +static PortAddr AscSearchIOPortAddrEISA(PortAddr); +static PortAddr AscSearchIOPortAddr11(PortAddr); +static PortAddr AscSearchIOPortAddr(PortAddr, ushort); +static void AscSetISAPNPWaitForKey(void); #endif /* CONFIG_ISA */ -STATIC uchar AscGetChipScsiCtrl(PortAddr); -STATIC uchar AscSetChipScsiID(PortAddr, uchar); -STATIC uchar AscGetChipVersion(PortAddr, ushort); -STATIC ushort AscGetChipBusType(PortAddr); -STATIC ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); -STATIC int AscFindSignature(PortAddr); -STATIC void AscToggleIRQAct(PortAddr); -STATIC uchar AscGetChipIRQ(PortAddr, ushort); -STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort); -STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); -STATIC inline ulong DvcEnterCritical(void); -STATIC inline void DvcLeaveCritical(ulong); +static uchar AscGetChipScsiCtrl(PortAddr); +static uchar AscSetChipScsiID(PortAddr, uchar); +static uchar AscGetChipVersion(PortAddr, ushort); +static ushort AscGetChipBusType(PortAddr); +static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); +static int AscFindSignature(PortAddr); +static void AscToggleIRQAct(PortAddr); +static uchar AscGetChipIRQ(PortAddr, ushort); +static uchar AscSetChipIRQ(PortAddr, uchar, ushort); +static ushort AscGetChipBiosAddress(PortAddr, ushort); +static inline ulong DvcEnterCritical(void); +static inline void DvcLeaveCritical(ulong); #ifdef CONFIG_PCI -STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort); -STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR *, - ushort, uchar); +static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort); +static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar); #endif /* CONFIG_PCI */ -STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); -STATIC void DvcSleepMilliSecond(ASC_DCNT); -STATIC void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT); -STATIC void DvcPutScsiQ(PortAddr, ushort, uchar *, int); -STATIC void DvcGetQinfo(PortAddr, ushort, uchar *, int); -STATIC ushort AscInitGetConfig(ASC_DVC_VAR *); -STATIC ushort AscInitSetConfig(ASC_DVC_VAR *); -STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR *); -STATIC void AscAsyncFix(ASC_DVC_VAR *, uchar, - ASC_SCSI_INQUIRY *); -STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); -STATIC void AscInquiryHandling(ASC_DVC_VAR *, - uchar, ASC_SCSI_INQUIRY *); -STATIC int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); -STATIC int AscISR(ASC_DVC_VAR *); -STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, - uchar); -STATIC int AscSgListToQueue(int); +static ushort AscGetChipBiosAddress(PortAddr, ushort); +static void DvcSleepMilliSecond(ASC_DCNT); +static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT); +static void DvcPutScsiQ(PortAddr, ushort, uchar *, int); +static void DvcGetQinfo(PortAddr, ushort, uchar *, int); +static ushort AscInitGetConfig(ASC_DVC_VAR *); +static ushort AscInitSetConfig(ASC_DVC_VAR *); +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *); +static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); +static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); +static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); +static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); +static int AscISR(ASC_DVC_VAR *); +static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar); +static int AscSgListToQueue(int); #ifdef CONFIG_ISA -STATIC void AscEnableIsaDma(uchar); +static void AscEnableIsaDma(uchar); #endif /* CONFIG_ISA */ -STATIC ASC_DCNT AscGetMaxDmaCount(ushort); -static const char *advansys_info(struct Scsi_Host *shp); +static ASC_DCNT AscGetMaxDmaCount(ushort); +static const char *advansys_info(struct Scsi_Host *shost); /* * --- Adv Library Constants and Macros @@ -2035,10 +2015,10 @@ static const char *advansys_info(struct Scsi_Host *shp); * are all consistent at 8, 16, and 32 bits respectively. Pointers * and long types are 64 bits on Alpha and UltraSPARC. */ -#define ADV_PADDR __u32 /* Physical address data type. */ -#define ADV_VADDR __u32 /* Virtual address data type. */ -#define ADV_DCNT __u32 /* Unsigned Data count type. */ -#define ADV_SDCNT __s32 /* Signed Data count type. */ +#define ADV_PADDR __u32 /* Physical address data type. */ +#define ADV_VADDR __u32 /* Virtual address data type. */ +#define ADV_DCNT __u32 /* Unsigned Data count type. */ +#define ADV_SDCNT __s32 /* Signed Data count type. */ /* * These macros are used to convert a virtual address to a @@ -2051,7 +2031,7 @@ static const char *advansys_info(struct Scsi_Host *shp); #define ADV_VADDR_TO_U32 virt_to_bus #define ADV_U32_TO_VADDR bus_to_virt -#define AdvPortAddr void __iomem * /* Virtual memory address size */ +#define AdvPortAddr void __iomem * /* Virtual memory address size */ /* * Define Adv Library required memory access macros. @@ -2103,20 +2083,20 @@ static const char *advansys_info(struct Scsi_Host *shp); #define ADV_EEP_DVC_CFG_BEGIN (0x00) #define ADV_EEP_DVC_CFG_END (0x15) -#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ +#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ #define ADV_EEP_MAX_WORD_ADDR (0x1E) #define ADV_EEP_DELAY_MS 100 -#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */ -#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */ +#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */ +#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */ /* * For the ASC3550 Bit 13 is Termination Polarity control bit. * For later ICs Bit 13 controls whether the CIS (Card Information * Service Section) is loaded from EEPROM. */ -#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */ -#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */ +#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */ +#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */ /* * ASC38C1600 Bit 11 * @@ -2128,280 +2108,277 @@ static const char *advansys_info(struct Scsi_Host *shp); * INT B in the PCI Configuration Space Int Pin field. If it is 1, then * Function 1 will specify INT A. */ -#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */ - -typedef struct adveep_3550_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 13 set - Term Polarity Control */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_able; /* 04 Synchronous DTR able */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar reserved1; /* reserved byte (not used) */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 */ - /* bit 14 */ - /* bit 15 */ - ushort ultra_able; /* 13 ULTRA speed able */ - ushort reserved2; /* 14 reserved */ - uchar max_host_qng; /* 15 maximum host queuing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort bug_fix; /* 17 control bit for bug fix */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort num_of_err; /* 36 number of error */ +#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */ + +typedef struct adveep_3550_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 13 set - Term Polarity Control */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_able; /* 04 Synchronous DTR able */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar reserved1; /* reserved byte (not used) */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 */ + /* bit 14 */ + /* bit 15 */ + ushort ultra_able; /* 13 ULTRA speed able */ + ushort reserved2; /* 14 reserved */ + uchar max_host_qng; /* 15 maximum host queuing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort bug_fix; /* 17 control bit for bug fix */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort num_of_err; /* 36 number of error */ } ADVEEP_3550_CONFIG; -typedef struct adveep_38C0800_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 13 set - Load CIS */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination_se; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar termination_lvd; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 */ - /* bit 14 */ - /* bit 15 */ - ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ - ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ - uchar max_host_qng; /* 15 maximum host queueing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort reserved36; /* 36 reserved */ - ushort reserved37; /* 37 reserved */ - ushort reserved38; /* 38 reserved */ - ushort reserved39; /* 39 reserved */ - ushort reserved40; /* 40 reserved */ - ushort reserved41; /* 41 reserved */ - ushort reserved42; /* 42 reserved */ - ushort reserved43; /* 43 reserved */ - ushort reserved44; /* 44 reserved */ - ushort reserved45; /* 45 reserved */ - ushort reserved46; /* 46 reserved */ - ushort reserved47; /* 47 reserved */ - ushort reserved48; /* 48 reserved */ - ushort reserved49; /* 49 reserved */ - ushort reserved50; /* 50 reserved */ - ushort reserved51; /* 51 reserved */ - ushort reserved52; /* 52 reserved */ - ushort reserved53; /* 53 reserved */ - ushort reserved54; /* 54 reserved */ - ushort reserved55; /* 55 reserved */ - ushort cisptr_lsw; /* 56 CIS PTR LSW */ - ushort cisprt_msw; /* 57 CIS PTR MSW */ - ushort subsysvid; /* 58 SubSystem Vendor ID */ - ushort subsysid; /* 59 SubSystem ID */ - ushort reserved60; /* 60 reserved */ - ushort reserved61; /* 61 reserved */ - ushort reserved62; /* 62 reserved */ - ushort reserved63; /* 63 reserved */ +typedef struct adveep_38C0800_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 13 set - Load CIS */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination_se; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar termination_lvd; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 */ + /* bit 14 */ + /* bit 15 */ + ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ + ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ + uchar max_host_qng; /* 15 maximum host queueing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort reserved36; /* 36 reserved */ + ushort reserved37; /* 37 reserved */ + ushort reserved38; /* 38 reserved */ + ushort reserved39; /* 39 reserved */ + ushort reserved40; /* 40 reserved */ + ushort reserved41; /* 41 reserved */ + ushort reserved42; /* 42 reserved */ + ushort reserved43; /* 43 reserved */ + ushort reserved44; /* 44 reserved */ + ushort reserved45; /* 45 reserved */ + ushort reserved46; /* 46 reserved */ + ushort reserved47; /* 47 reserved */ + ushort reserved48; /* 48 reserved */ + ushort reserved49; /* 49 reserved */ + ushort reserved50; /* 50 reserved */ + ushort reserved51; /* 51 reserved */ + ushort reserved52; /* 52 reserved */ + ushort reserved53; /* 53 reserved */ + ushort reserved54; /* 54 reserved */ + ushort reserved55; /* 55 reserved */ + ushort cisptr_lsw; /* 56 CIS PTR LSW */ + ushort cisprt_msw; /* 57 CIS PTR MSW */ + ushort subsysvid; /* 58 SubSystem Vendor ID */ + ushort subsysid; /* 59 SubSystem ID */ + ushort reserved60; /* 60 reserved */ + ushort reserved61; /* 61 reserved */ + ushort reserved62; /* 62 reserved */ + ushort reserved63; /* 63 reserved */ } ADVEEP_38C0800_CONFIG; -typedef struct adveep_38C1600_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 11 set - Func. 0 INTB, Func. 1 INTA */ - /* clear - Func. 0 INTA, Func. 1 INTB */ - /* bit 13 set - Load CIS */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination_se; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar termination_lvd; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 Basic Integrity Checking disabled */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */ - /* bit 14 */ - /* bit 15 */ - ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ - ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ - uchar max_host_qng; /* 15 maximum host queueing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort reserved36; /* 36 reserved */ - ushort reserved37; /* 37 reserved */ - ushort reserved38; /* 38 reserved */ - ushort reserved39; /* 39 reserved */ - ushort reserved40; /* 40 reserved */ - ushort reserved41; /* 41 reserved */ - ushort reserved42; /* 42 reserved */ - ushort reserved43; /* 43 reserved */ - ushort reserved44; /* 44 reserved */ - ushort reserved45; /* 45 reserved */ - ushort reserved46; /* 46 reserved */ - ushort reserved47; /* 47 reserved */ - ushort reserved48; /* 48 reserved */ - ushort reserved49; /* 49 reserved */ - ushort reserved50; /* 50 reserved */ - ushort reserved51; /* 51 reserved */ - ushort reserved52; /* 52 reserved */ - ushort reserved53; /* 53 reserved */ - ushort reserved54; /* 54 reserved */ - ushort reserved55; /* 55 reserved */ - ushort cisptr_lsw; /* 56 CIS PTR LSW */ - ushort cisprt_msw; /* 57 CIS PTR MSW */ - ushort subsysvid; /* 58 SubSystem Vendor ID */ - ushort subsysid; /* 59 SubSystem ID */ - ushort reserved60; /* 60 reserved */ - ushort reserved61; /* 61 reserved */ - ushort reserved62; /* 62 reserved */ - ushort reserved63; /* 63 reserved */ +typedef struct adveep_38C1600_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 11 set - Func. 0 INTB, Func. 1 INTA */ + /* clear - Func. 0 INTA, Func. 1 INTB */ + /* bit 13 set - Load CIS */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination_se; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar termination_lvd; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 Basic Integrity Checking disabled */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */ + /* bit 14 */ + /* bit 15 */ + ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ + ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ + uchar max_host_qng; /* 15 maximum host queueing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort reserved36; /* 36 reserved */ + ushort reserved37; /* 37 reserved */ + ushort reserved38; /* 38 reserved */ + ushort reserved39; /* 39 reserved */ + ushort reserved40; /* 40 reserved */ + ushort reserved41; /* 41 reserved */ + ushort reserved42; /* 42 reserved */ + ushort reserved43; /* 43 reserved */ + ushort reserved44; /* 44 reserved */ + ushort reserved45; /* 45 reserved */ + ushort reserved46; /* 46 reserved */ + ushort reserved47; /* 47 reserved */ + ushort reserved48; /* 48 reserved */ + ushort reserved49; /* 49 reserved */ + ushort reserved50; /* 50 reserved */ + ushort reserved51; /* 51 reserved */ + ushort reserved52; /* 52 reserved */ + ushort reserved53; /* 53 reserved */ + ushort reserved54; /* 54 reserved */ + ushort reserved55; /* 55 reserved */ + ushort cisptr_lsw; /* 56 CIS PTR LSW */ + ushort cisprt_msw; /* 57 CIS PTR MSW */ + ushort subsysvid; /* 58 SubSystem Vendor ID */ + ushort subsysid; /* 59 SubSystem ID */ + ushort reserved60; /* 60 reserved */ + ushort reserved61; /* 61 reserved */ + ushort reserved62; /* 62 reserved */ + ushort reserved63; /* 63 reserved */ } ADVEEP_38C1600_CONFIG; /* @@ -2427,11 +2404,11 @@ typedef struct adveep_38C1600_config #define BIOS_CTRL_SCSI_PARITY 0x1000 #define BIOS_CTRL_AIPP_DIS 0x2000 -#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */ -#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */ +#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */ +#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */ -#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */ +#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */ +#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */ /* * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is @@ -2440,9 +2417,9 @@ typedef struct adveep_38C1600_config * * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory * */ -#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */ -#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */ +#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */ +#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */ +#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */ /* * Byte I/O register address from base of 'iop_base'. @@ -2515,39 +2492,39 @@ typedef struct adveep_38C1600_config /* * Word I/O register address from base of 'iop_base'. */ -#define IOPW_CHIP_ID_0 0x00 /* CID0 */ -#define IOPW_CTRL_REG 0x02 /* CC */ -#define IOPW_RAM_ADDR 0x04 /* LA */ -#define IOPW_RAM_DATA 0x06 /* LD */ +#define IOPW_CHIP_ID_0 0x00 /* CID0 */ +#define IOPW_CTRL_REG 0x02 /* CC */ +#define IOPW_RAM_ADDR 0x04 /* LA */ +#define IOPW_RAM_DATA 0x06 /* LD */ #define IOPW_RES_ADDR_08 0x08 -#define IOPW_RISC_CSR 0x0A /* CSR */ -#define IOPW_SCSI_CFG0 0x0C /* CFG0 */ -#define IOPW_SCSI_CFG1 0x0E /* CFG1 */ +#define IOPW_RISC_CSR 0x0A /* CSR */ +#define IOPW_SCSI_CFG0 0x0C /* CFG0 */ +#define IOPW_SCSI_CFG1 0x0E /* CFG1 */ #define IOPW_RES_ADDR_10 0x10 -#define IOPW_SEL_MASK 0x12 /* SM */ +#define IOPW_SEL_MASK 0x12 /* SM */ #define IOPW_RES_ADDR_14 0x14 -#define IOPW_FLASH_ADDR 0x16 /* FA */ +#define IOPW_FLASH_ADDR 0x16 /* FA */ #define IOPW_RES_ADDR_18 0x18 -#define IOPW_EE_CMD 0x1A /* EC */ -#define IOPW_EE_DATA 0x1C /* ED */ -#define IOPW_SFIFO_CNT 0x1E /* SFC */ +#define IOPW_EE_CMD 0x1A /* EC */ +#define IOPW_EE_DATA 0x1C /* ED */ +#define IOPW_SFIFO_CNT 0x1E /* SFC */ #define IOPW_RES_ADDR_20 0x20 -#define IOPW_Q_BASE 0x22 /* QB */ -#define IOPW_QP 0x24 /* QP */ -#define IOPW_IX 0x26 /* IX */ -#define IOPW_SP 0x28 /* SP */ -#define IOPW_PC 0x2A /* PC */ +#define IOPW_Q_BASE 0x22 /* QB */ +#define IOPW_QP 0x24 /* QP */ +#define IOPW_IX 0x26 /* IX */ +#define IOPW_SP 0x28 /* SP */ +#define IOPW_PC 0x2A /* PC */ #define IOPW_RES_ADDR_2C 0x2C #define IOPW_RES_ADDR_2E 0x2E -#define IOPW_SCSI_DATA 0x30 /* SD */ -#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */ -#define IOPW_SCSI_CTRL 0x34 /* SC */ -#define IOPW_HSHK_CFG 0x36 /* HCFG */ -#define IOPW_SXFR_STATUS 0x36 /* SXS */ -#define IOPW_SXFR_CNTL 0x38 /* SXL */ -#define IOPW_SXFR_CNTH 0x3A /* SXH */ +#define IOPW_SCSI_DATA 0x30 /* SD */ +#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */ +#define IOPW_SCSI_CTRL 0x34 /* SC */ +#define IOPW_HSHK_CFG 0x36 /* HCFG */ +#define IOPW_SXFR_STATUS 0x36 /* SXS */ +#define IOPW_SXFR_CNTL 0x38 /* SXL */ +#define IOPW_SXFR_CNTH 0x3A /* SXH */ #define IOPW_RES_ADDR_3C 0x3C -#define IOPW_RFIFO_DATA 0x3E /* RFD */ +#define IOPW_RFIFO_DATA 0x3E /* RFD */ /* * Doubleword I/O register address from base of 'iop_base'. @@ -2621,36 +2598,36 @@ typedef struct adveep_38C1600_config /* * SCSI_CFG0 Register bit definitions */ -#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */ -#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */ -#define EVEN_PARITY 0x1000 /* Select Even Parity */ -#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */ -#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */ -#define PRIM_MODE 0x0100 /* Primitive SCSI mode */ -#define SCAM_EN 0x0080 /* Enable SCAM selection */ -#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */ -#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */ -#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */ -#define OUR_ID 0x000F /* SCSI ID */ +#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */ +#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */ +#define EVEN_PARITY 0x1000 /* Select Even Parity */ +#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */ +#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */ +#define PRIM_MODE 0x0100 /* Primitive SCSI mode */ +#define SCAM_EN 0x0080 /* Enable SCAM selection */ +#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */ +#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */ +#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */ +#define OUR_ID 0x000F /* SCSI ID */ /* * SCSI_CFG1 Register bit definitions */ -#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */ -#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */ -#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */ -#define FILTER_SEL 0x0C00 /* Filter Period Selection */ -#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */ -#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */ -#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */ -#define ACTIVE_DBL 0x0200 /* Disable Active Negation */ -#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */ -#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */ -#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */ -#define TERM_CTL 0x0030 /* External SCSI Termination Bits */ -#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */ -#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */ -#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */ +#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */ +#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */ +#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */ +#define FILTER_SEL 0x0C00 /* Filter Period Selection */ +#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */ +#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */ +#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */ +#define ACTIVE_DBL 0x0200 /* Disable Active Negation */ +#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */ +#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */ +#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */ +#define TERM_CTL 0x0030 /* External SCSI Termination Bits */ +#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */ +#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */ +#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */ /* * Addendum for ASC-38C0800 Chip @@ -2663,24 +2640,23 @@ typedef struct adveep_38C1600_config * Also each ASC-38C1600 function or channel uses only cable bits [5:4] * and [1:0]. Bits [14], [7:6], [3:2] are unused. */ -#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */ -#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */ -#define HVD 0x1000 /* HVD Device Detect */ -#define LVD 0x0800 /* LVD Device Detect */ -#define SE 0x0400 /* SE Device Detect */ -#define TERM_LVD 0x00C0 /* LVD Termination Bits */ -#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */ -#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */ -#define TERM_SE 0x0030 /* SE Termination Bits */ -#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */ -#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */ -#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */ -#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */ -#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */ -#define C_DET_SE 0x0003 /* SE Cable Detect Bits */ -#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */ -#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */ - +#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */ +#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */ +#define HVD 0x1000 /* HVD Device Detect */ +#define LVD 0x0800 /* LVD Device Detect */ +#define SE 0x0400 /* SE Device Detect */ +#define TERM_LVD 0x00C0 /* LVD Termination Bits */ +#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */ +#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */ +#define TERM_SE 0x0030 /* SE Termination Bits */ +#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */ +#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */ +#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */ +#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */ +#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */ +#define C_DET_SE 0x0003 /* SE Cable Detect Bits */ +#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */ +#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */ #define CABLE_ILLEGAL_A 0x7 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */ @@ -2691,39 +2667,39 @@ typedef struct adveep_38C1600_config /* * MEM_CFG Register bit definitions */ -#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */ -#define FAST_EE_CLK 0x20 /* Diagnostic Bit */ -#define RAM_SZ 0x1C /* Specify size of RAM to RISC */ -#define RAM_SZ_2KB 0x00 /* 2 KB */ -#define RAM_SZ_4KB 0x04 /* 4 KB */ -#define RAM_SZ_8KB 0x08 /* 8 KB */ -#define RAM_SZ_16KB 0x0C /* 16 KB */ -#define RAM_SZ_32KB 0x10 /* 32 KB */ -#define RAM_SZ_64KB 0x14 /* 64 KB */ +#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */ +#define FAST_EE_CLK 0x20 /* Diagnostic Bit */ +#define RAM_SZ 0x1C /* Specify size of RAM to RISC */ +#define RAM_SZ_2KB 0x00 /* 2 KB */ +#define RAM_SZ_4KB 0x04 /* 4 KB */ +#define RAM_SZ_8KB 0x08 /* 8 KB */ +#define RAM_SZ_16KB 0x0C /* 16 KB */ +#define RAM_SZ_32KB 0x10 /* 32 KB */ +#define RAM_SZ_64KB 0x14 /* 64 KB */ /* * DMA_CFG0 Register bit definitions * * This register is only accessible to the host. */ -#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */ -#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */ -#define FIFO_THRESH_16B 0x00 /* 16 bytes */ -#define FIFO_THRESH_32B 0x20 /* 32 bytes */ -#define FIFO_THRESH_48B 0x30 /* 48 bytes */ -#define FIFO_THRESH_64B 0x40 /* 64 bytes */ -#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */ -#define FIFO_THRESH_96B 0x60 /* 96 bytes */ -#define FIFO_THRESH_112B 0x70 /* 112 bytes */ -#define START_CTL 0x0C /* DMA start conditions */ -#define START_CTL_TH 0x00 /* Wait threshold level (default) */ -#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */ -#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */ -#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */ -#define READ_CMD 0x03 /* Memory Read Method */ -#define READ_CMD_MR 0x00 /* Memory Read */ -#define READ_CMD_MRL 0x02 /* Memory Read Long */ -#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */ +#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */ +#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */ +#define FIFO_THRESH_16B 0x00 /* 16 bytes */ +#define FIFO_THRESH_32B 0x20 /* 32 bytes */ +#define FIFO_THRESH_48B 0x30 /* 48 bytes */ +#define FIFO_THRESH_64B 0x40 /* 64 bytes */ +#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */ +#define FIFO_THRESH_96B 0x60 /* 96 bytes */ +#define FIFO_THRESH_112B 0x70 /* 112 bytes */ +#define START_CTL 0x0C /* DMA start conditions */ +#define START_CTL_TH 0x00 /* Wait threshold level (default) */ +#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */ +#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */ +#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */ +#define READ_CMD 0x03 /* Memory Read Method */ +#define READ_CMD_MR 0x00 /* Memory Read */ +#define READ_CMD_MRL 0x02 /* Memory Read Long */ +#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */ /* * ASC-38C0800 RAM BIST Register bit definitions @@ -2747,7 +2723,7 @@ typedef struct adveep_38C1600_config * IOPB_PCI_INT_CFG Bit Field Definitions */ -#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */ +#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */ /* * Bit 1 can be set to change the interrupt for the Function to operate in @@ -2780,53 +2756,52 @@ typedef struct adveep_38C1600_config #define ADV_BUSY 0 #define ADV_ERROR (-1) - /* * ADV_DVC_VAR 'warn_code' values */ -#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */ -#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ -#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ -#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ -#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ +#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */ +#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ +#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ +#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ +#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ -#define ADV_MAX_TID 15 /* max. target identifier */ -#define ADV_MAX_LUN 7 /* max. logical unit number */ +#define ADV_MAX_TID 15 /* max. target identifier */ +#define ADV_MAX_LUN 7 /* max. logical unit number */ /* * Error code values are set in ADV_DVC_VAR 'err_code'. */ -#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ -#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ -#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */ -#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ -#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ -#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ -#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */ -#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ -#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ -#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ -#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ -#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */ -#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */ -#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */ +#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ +#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ +#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */ +#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ +#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ +#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ +#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */ +#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ +#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ +#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ +#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ +#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */ +#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */ +#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */ /* * Fixed locations of microcode operating variables. */ -#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ -#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */ -#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */ -#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */ -#define ASC_MC_VERSION_NUM 0x003A /* microcode number */ -#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */ -#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */ -#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */ -#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */ -#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */ -#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */ -#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */ -#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */ +#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ +#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */ +#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */ +#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */ +#define ASC_MC_VERSION_NUM 0x003A /* microcode number */ +#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */ +#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */ +#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */ +#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */ +#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */ +#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */ +#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */ +#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */ #define ASC_MC_CHIP_TYPE 0x009A #define ASC_MC_INTRB_CODE 0x009B #define ASC_MC_WDTR_ABLE 0x009C @@ -2844,9 +2819,9 @@ typedef struct adveep_38C1600_config #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0 #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0 #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100 -#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */ +#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */ #define ASC_MC_WDTR_DONE 0x0124 -#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */ +#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */ #define ASC_MC_ICQ 0x0160 #define ASC_MC_IRQ 0x0164 #define ASC_MC_PPR_ABLE 0x017A @@ -2865,8 +2840,8 @@ typedef struct adveep_38C1600_config * Flags set by the Adv Library in RISC variable 'control_flag' (0x122) * and handled by the microcode. */ -#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */ -#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */ +#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */ +#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */ /* * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format @@ -2875,45 +2850,44 @@ typedef struct adveep_38C1600_config #define HSHK_CFG_RATE 0x0F00 #define HSHK_CFG_OFFSET 0x001F -#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */ -#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */ -#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */ -#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */ - -#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */ -#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */ -#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */ -#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */ -#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */ - -#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */ -#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */ -#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */ -#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */ -#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */ +#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */ +#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */ +#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */ +#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */ + +#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */ +#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */ +#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */ +#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */ +#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */ + +#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */ +#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */ +#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */ +#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */ +#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */ /* * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used. */ -#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */ -#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */ +#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */ +#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */ /* * All fields here are accessed by the board microcode and need to be * little-endian. */ -typedef struct adv_carr_t -{ - ADV_VADDR carr_va; /* Carrier Virtual Address */ - ADV_PADDR carr_pa; /* Carrier Physical Address */ - ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */ - /* - * next_vpa [31:4] Carrier Virtual or Physical Next Pointer - * - * next_vpa [3:1] Reserved Bits - * next_vpa [0] Done Flag set in Response Queue. - */ - ADV_VADDR next_vpa; +typedef struct adv_carr_t { + ADV_VADDR carr_va; /* Carrier Virtual Address */ + ADV_PADDR carr_pa; /* Carrier Physical Address */ + ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */ + /* + * next_vpa [31:4] Carrier Virtual or Physical Next Pointer + * + * next_vpa [3:1] Reserved Bits + * next_vpa [0] Done Flag set in Response Queue. + */ + ADV_VADDR next_vpa; } ADV_CARR_T; /* @@ -2940,13 +2914,13 @@ typedef struct adv_carr_t * The Adv Library should limit use to the lower nibble (4 bits) of * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag. */ -#define ADV_POLL_REQUEST 0x01 /* poll for request completion */ -#define ADV_SCSIQ_DONE 0x02 /* request done */ -#define ADV_DONT_RETRY 0x08 /* don't do retry */ +#define ADV_POLL_REQUEST 0x01 /* poll for request completion */ +#define ADV_SCSIQ_DONE 0x02 /* request done */ +#define ADV_DONT_RETRY 0x08 /* don't do retry */ -#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */ -#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */ -#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */ +#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */ +#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */ +#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */ /* * Adapter temporary configuration structure @@ -2960,30 +2934,30 @@ typedef struct adv_carr_t * value of the field is never reset. */ typedef struct adv_dvc_cfg { - ushort disc_enable; /* enable disconnection */ - uchar chip_version; /* chip version */ - uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ - ushort lib_version; /* Adv Library version number */ - ushort control_flag; /* Microcode Control Flag */ - ushort mcode_date; /* Microcode date */ - ushort mcode_version; /* Microcode version */ - ushort pci_slot_info; /* high byte device/function number */ - /* bits 7-3 device num., bits 2-0 function num. */ - /* low byte bus num. */ - ushort serial1; /* EEPROM serial number word 1 */ - ushort serial2; /* EEPROM serial number word 2 */ - ushort serial3; /* EEPROM serial number word 3 */ - struct device *dev; /* pointer to the pci dev structure for this board */ + ushort disc_enable; /* enable disconnection */ + uchar chip_version; /* chip version */ + uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ + ushort lib_version; /* Adv Library version number */ + ushort control_flag; /* Microcode Control Flag */ + ushort mcode_date; /* Microcode date */ + ushort mcode_version; /* Microcode version */ + ushort pci_slot_info; /* high byte device/function number */ + /* bits 7-3 device num., bits 2-0 function num. */ + /* low byte bus num. */ + ushort serial1; /* EEPROM serial number word 1 */ + ushort serial2; /* EEPROM serial number word 2 */ + ushort serial3; /* EEPROM serial number word 3 */ + struct device *dev; /* pointer to the pci dev structure for this board */ } ADV_DVC_CFG; struct adv_dvc_var; struct adv_scsi_req_q; -typedef void (* ADV_ISR_CALLBACK) - (struct adv_dvc_var *, struct adv_scsi_req_q *); +typedef void (*ADV_ISR_CALLBACK) + (struct adv_dvc_var *, struct adv_scsi_req_q *); -typedef void (* ADV_ASYNC_CALLBACK) - (struct adv_dvc_var *, uchar); +typedef void (*ADV_ASYNC_CALLBACK) + (struct adv_dvc_var *, uchar); /* * Adapter operation variable structure. @@ -2998,55 +2972,55 @@ typedef void (* ADV_ASYNC_CALLBACK) * of the feature, the field is cleared. */ typedef struct adv_dvc_var { - AdvPortAddr iop_base; /* I/O port address */ - ushort err_code; /* fatal error code */ - ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ - ADV_ISR_CALLBACK isr_callback; - ADV_ASYNC_CALLBACK async_callback; - ushort wdtr_able; /* try WDTR for a device */ - ushort sdtr_able; /* try SDTR for a device */ - ushort ultra_able; /* try SDTR Ultra speed for a device */ - ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ - ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ - ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ - ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ - ushort tagqng_able; /* try tagged queuing with a device */ - ushort ppr_able; /* PPR message capable per TID bitmask. */ - uchar max_dvc_qng; /* maximum number of tagged commands per device */ - ushort start_motor; /* start motor command allowed */ - uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ - uchar chip_no; /* should be assigned by caller */ - uchar max_host_qng; /* maximum number of Q'ed command allowed */ - uchar irq_no; /* IRQ number */ - ushort no_scam; /* scam_tolerant of EEPROM */ - struct asc_board *drv_ptr; /* driver pointer to private structure */ - uchar chip_scsi_id; /* chip SCSI target ID */ - uchar chip_type; - uchar bist_err_code; - ADV_CARR_T *carrier_buf; - ADV_CARR_T *carr_freelist; /* Carrier free list. */ - ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ - ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ - ushort carr_pending_cnt; /* Count of pending carriers. */ - /* - * Note: The following fields will not be used after initialization. The - * driver may discard the buffer after initialization is done. - */ - ADV_DVC_CFG *cfg; /* temporary configuration structure */ + AdvPortAddr iop_base; /* I/O port address */ + ushort err_code; /* fatal error code */ + ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ + ADV_ISR_CALLBACK isr_callback; + ADV_ASYNC_CALLBACK async_callback; + ushort wdtr_able; /* try WDTR for a device */ + ushort sdtr_able; /* try SDTR for a device */ + ushort ultra_able; /* try SDTR Ultra speed for a device */ + ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ + ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ + ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ + ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ + ushort tagqng_able; /* try tagged queuing with a device */ + ushort ppr_able; /* PPR message capable per TID bitmask. */ + uchar max_dvc_qng; /* maximum number of tagged commands per device */ + ushort start_motor; /* start motor command allowed */ + uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ + uchar chip_no; /* should be assigned by caller */ + uchar max_host_qng; /* maximum number of Q'ed command allowed */ + uchar irq_no; /* IRQ number */ + ushort no_scam; /* scam_tolerant of EEPROM */ + struct asc_board *drv_ptr; /* driver pointer to private structure */ + uchar chip_scsi_id; /* chip SCSI target ID */ + uchar chip_type; + uchar bist_err_code; + ADV_CARR_T *carrier_buf; + ADV_CARR_T *carr_freelist; /* Carrier free list. */ + ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ + ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ + ushort carr_pending_cnt; /* Count of pending carriers. */ + /* + * Note: The following fields will not be used after initialization. The + * driver may discard the buffer after initialization is done. + */ + ADV_DVC_CFG *cfg; /* temporary configuration structure */ } ADV_DVC_VAR; #define NO_OF_SG_PER_BLOCK 15 typedef struct asc_sg_block { - uchar reserved1; - uchar reserved2; - uchar reserved3; - uchar sg_cnt; /* Valid entries in block. */ - ADV_PADDR sg_ptr; /* Pointer to next sg block. */ - struct { - ADV_PADDR sg_addr; /* SG element address. */ - ADV_DCNT sg_count; /* SG element count. */ - } sg_list[NO_OF_SG_PER_BLOCK]; + uchar reserved1; + uchar reserved2; + uchar reserved3; + uchar sg_cnt; /* Valid entries in block. */ + ADV_PADDR sg_ptr; /* Pointer to next sg block. */ + struct { + ADV_PADDR sg_addr; /* SG element address. */ + ADV_DCNT sg_count; /* SG element count. */ + } sg_list[NO_OF_SG_PER_BLOCK]; } ADV_SG_BLOCK; /* @@ -3061,37 +3035,37 @@ typedef struct asc_sg_block { * order. */ typedef struct adv_scsi_req_q { - uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */ - uchar target_cmd; - uchar target_id; /* Device target identifier. */ - uchar target_lun; /* Device target logical unit number. */ - ADV_PADDR data_addr; /* Data buffer physical address. */ - ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */ - ADV_PADDR sense_addr; - ADV_PADDR carr_pa; - uchar mflag; - uchar sense_len; - uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */ - uchar scsi_cntl; - uchar done_status; /* Completion status. */ - uchar scsi_status; /* SCSI status byte. */ - uchar host_status; /* Ucode host status. */ - uchar sg_working_ix; - uchar cdb[12]; /* SCSI CDB bytes 0-11. */ - ADV_PADDR sg_real_addr; /* SG list physical address. */ - ADV_PADDR scsiq_rptr; - uchar cdb16[4]; /* SCSI CDB bytes 12-15. */ - ADV_VADDR scsiq_ptr; - ADV_VADDR carr_va; - /* - * End of microcode structure - 60 bytes. The rest of the structure - * is used by the Adv Library and ignored by the microcode. - */ - ADV_VADDR srb_ptr; - ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */ - char *vdata_addr; /* Data buffer virtual address. */ - uchar a_flag; - uchar pad[2]; /* Pad out to a word boundary. */ + uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */ + uchar target_cmd; + uchar target_id; /* Device target identifier. */ + uchar target_lun; /* Device target logical unit number. */ + ADV_PADDR data_addr; /* Data buffer physical address. */ + ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */ + ADV_PADDR sense_addr; + ADV_PADDR carr_pa; + uchar mflag; + uchar sense_len; + uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */ + uchar scsi_cntl; + uchar done_status; /* Completion status. */ + uchar scsi_status; /* SCSI status byte. */ + uchar host_status; /* Ucode host status. */ + uchar sg_working_ix; + uchar cdb[12]; /* SCSI CDB bytes 0-11. */ + ADV_PADDR sg_real_addr; /* SG list physical address. */ + ADV_PADDR scsiq_rptr; + uchar cdb16[4]; /* SCSI CDB bytes 12-15. */ + ADV_VADDR scsiq_ptr; + ADV_VADDR carr_va; + /* + * End of microcode structure - 60 bytes. The rest of the structure + * is used by the Adv Library and ignored by the microcode. + */ + ADV_VADDR srb_ptr; + ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */ + char *vdata_addr; /* Data buffer virtual address. */ + uchar a_flag; + uchar pad[2]; /* Pad out to a word boundary. */ } ADV_SCSI_REQ_Q; /* @@ -3103,8 +3077,8 @@ typedef struct adv_scsi_req_q { #define IDLE_CMD_SEND_INT 0x0004 #define IDLE_CMD_ABORT 0x0008 #define IDLE_CMD_DEVICE_RESET 0x0010 -#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */ -#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */ +#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */ +#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */ #define IDLE_CMD_SCSIREQ 0x0080 #define IDLE_CMD_STATUS_SUCCESS 0x0001 @@ -3118,60 +3092,59 @@ typedef struct adv_scsi_req_q { /* * Wait loop time out values. */ -#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */ -#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */ -#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */ -#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */ -#define SCSI_MAX_RETRY 10 /* retry count */ - -#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */ -#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */ -#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */ -#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */ +#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */ +#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */ +#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */ +#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */ +#define SCSI_MAX_RETRY 10 /* retry count */ +#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */ +#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */ +#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */ +#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */ -#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ +#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ /* * Device drivers must define the following functions. */ -STATIC inline ulong DvcEnterCritical(void); -STATIC inline void DvcLeaveCritical(ulong); -STATIC void DvcSleepMilliSecond(ADV_DCNT); -STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); -STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); -STATIC ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, - uchar *, ASC_SDCNT *, int); -STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); +static inline ulong DvcEnterCritical(void); +static inline void DvcLeaveCritical(ulong); +static void DvcSleepMilliSecond(ADV_DCNT); +static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); +static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); +static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, + uchar *, ASC_SDCNT *, int); +static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); /* * Adv Library functions available to drivers. */ -STATIC int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC int AdvISR(ADV_DVC_VAR *); -STATIC int AdvInitGetConfig(ADV_DVC_VAR *); -STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *); -STATIC int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); -STATIC int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); -STATIC int AdvResetChipAndSB(ADV_DVC_VAR *); -STATIC int AdvResetSB(ADV_DVC_VAR *asc_dvc); +static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static int AdvISR(ADV_DVC_VAR *); +static int AdvInitGetConfig(ADV_DVC_VAR *); +static int AdvInitAsc3550Driver(ADV_DVC_VAR *); +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); +static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); +static int AdvResetChipAndSB(ADV_DVC_VAR *); +static int AdvResetSB(ADV_DVC_VAR *asc_dvc); /* * Internal Adv Library functions. */ -STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); -STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC int AdvInitFrom3550EEP(ADV_DVC_VAR *); -STATIC int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); -STATIC int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); -STATIC ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -STATIC void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -STATIC ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -STATIC void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -STATIC ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -STATIC void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -STATIC void AdvWaitEEPCmd(AdvPortAddr); -STATIC ushort AdvReadEEPWord(AdvPortAddr, int); +static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); +static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static int AdvInitFrom3550EEP(ADV_DVC_VAR *); +static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); +static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); +static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); +static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); +static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); +static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); +static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); +static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); +static void AdvWaitEEPCmd(AdvPortAddr); +static ushort AdvReadEEPWord(AdvPortAddr, int); /* * PCI Bus Definitions @@ -3241,7 +3214,6 @@ do { \ #define AdvWriteWordAutoIncLram(iop_base, word) \ (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word))) - /* * Define macro to check for Condor signature. * @@ -3313,7 +3285,7 @@ do { \ * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values. */ -#define QD_NO_STATUS 0x00 /* Request not completed yet. */ +#define QD_NO_STATUS 0x00 /* Request not completed yet. */ #define QD_NO_ERROR 0x01 #define QD_ABORTED_BY_HOST 0x02 #define QD_WITH_ERROR 0x04 @@ -3323,30 +3295,29 @@ do { \ #define QHSTA_M_DATA_OVER_RUN 0x12 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 #define QHSTA_M_QUEUE_ABORTED 0x15 -#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */ -#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */ -#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */ -#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */ -#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */ -#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */ -#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */ +#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */ +#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */ +#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */ +#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */ +#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */ +#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */ +#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */ /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */ -#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */ -#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */ -#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */ -#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */ -#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */ -#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */ -#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */ -#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */ +#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */ +#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */ +#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */ +#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */ +#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */ +#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */ +#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */ +#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */ #define QHSTA_M_WTM_TIMEOUT 0x41 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 -#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */ -#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */ -#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */ - +#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */ +#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */ +#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */ /* * Default EEPROM Configuration structure defined in a_init.c. @@ -3358,12 +3329,12 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; /* * DvcGetPhyAddr() flag arguments */ -#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ -#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ -#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ -#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ -#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ -#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */ +#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ +#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ +#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ +#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ +#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ +#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */ /* Return the address that is aligned at the next doubleword >= to 'addr'. */ #define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7) @@ -3413,43 +3384,42 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; #define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) typedef struct { - uchar periph; /* peripheral device type [0:4] */ - /* peripheral qualifier [5:7] */ - uchar devtype; /* device type modifier (for SCSI I) [0:6] */ - /* RMB - removable medium bit [7] */ - uchar ver; /* ANSI approved version [0:2] */ - /* ECMA version [3:5] */ - /* ISO version [6:7] */ - uchar byte3; /* response data format [0:3] */ - /* 0 SCSI 1 */ - /* 1 CCS */ - /* 2 SCSI-2 */ - /* 3-F reserved */ - /* reserved [4:5] */ - /* terminate I/O process bit (see 5.6.22) [6] */ - /* asynch. event notification (processor) [7] */ - uchar add_len; /* additional length */ - uchar res1; /* reserved */ - uchar res2; /* reserved */ - uchar flags; /* soft reset implemented [0] */ - /* command queuing [1] */ - /* reserved [2] */ - /* linked command for this logical unit [3] */ - /* synchronous data transfer [4] */ - /* wide bus 16 bit data transfer [5] */ - /* wide bus 32 bit data transfer [6] */ - /* relative addressing mode [7] */ - uchar vendor_id[8]; /* vendor identification */ - uchar product_id[16]; /* product identification */ - uchar product_rev_level[4]; /* product revision level */ - uchar vendor_specific[20]; /* vendor specific */ - uchar info; /* information unit supported [0] */ - /* quick arbitrate supported [1] */ - /* clocking field [2:3] */ - /* reserved [4:7] */ - uchar res3; /* reserved */ -} ADV_SCSI_INQUIRY; /* 58 bytes */ - + uchar periph; /* peripheral device type [0:4] */ + /* peripheral qualifier [5:7] */ + uchar devtype; /* device type modifier (for SCSI I) [0:6] */ + /* RMB - removable medium bit [7] */ + uchar ver; /* ANSI approved version [0:2] */ + /* ECMA version [3:5] */ + /* ISO version [6:7] */ + uchar byte3; /* response data format [0:3] */ + /* 0 SCSI 1 */ + /* 1 CCS */ + /* 2 SCSI-2 */ + /* 3-F reserved */ + /* reserved [4:5] */ + /* terminate I/O process bit (see 5.6.22) [6] */ + /* asynch. event notification (processor) [7] */ + uchar add_len; /* additional length */ + uchar res1; /* reserved */ + uchar res2; /* reserved */ + uchar flags; /* soft reset implemented [0] */ + /* command queuing [1] */ + /* reserved [2] */ + /* linked command for this logical unit [3] */ + /* synchronous data transfer [4] */ + /* wide bus 16 bit data transfer [5] */ + /* wide bus 32 bit data transfer [6] */ + /* relative addressing mode [7] */ + uchar vendor_id[8]; /* vendor identification */ + uchar product_id[16]; /* product identification */ + uchar product_rev_level[4]; /* product revision level */ + uchar vendor_specific[20]; /* vendor specific */ + uchar info; /* information unit supported [0] */ + /* quick arbitrate supported [1] */ + /* clocking field [2:3] */ + /* reserved [4:7] */ + uchar res3; /* reserved */ +} ADV_SCSI_INQUIRY; /* 58 bytes */ /* * --- Driver Constants and Macros @@ -3464,15 +3434,15 @@ typedef struct { /* asc_board_t flags */ #define ASC_HOST_IN_RESET 0x01 -#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ +#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ #define ASC_SELECT_QUEUE_DEPTHS 0x08 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0) #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD) -#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ +#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ -#define ASC_INFO_SIZE 128 /* advansys_info() line size */ +#define ASC_INFO_SIZE 128 /* advansys_info() line size */ #ifdef CONFIG_PROC_FS /* /proc/scsi/advansys/[0...] related definitions */ @@ -3514,7 +3484,7 @@ typedef struct { * REQPTIME(reqp) - reqp's time stamp value * REQTIMESTAMP() - system time stamp value */ -typedef struct scsi_cmnd REQ, *REQP; +typedef struct scsi_cmnd REQ, *REQP; #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble)) #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble)) #define REQPTID(reqp) ((reqp)->device->id) @@ -3564,17 +3534,17 @@ typedef struct scsi_cmnd REQ, *REQP; #define PCI_MAX_SLOT 0x1F #define PCI_MAX_BUS 0xFF #define PCI_IOADDRESS_MASK 0xFFFE -#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ +#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ #ifndef ADVANSYS_STATS -#define ASC_STATS(shp, counter) -#define ASC_STATS_ADD(shp, counter, count) +#define ASC_STATS(shost, counter) +#define ASC_STATS_ADD(shost, counter, count) #else /* ADVANSYS_STATS */ -#define ASC_STATS(shp, counter) \ - (ASC_BOARDP(shp)->asc_stats.counter++) +#define ASC_STATS(shost, counter) \ + (ASC_BOARDP(shost)->asc_stats.counter++) -#define ASC_STATS_ADD(shp, counter, count) \ - (ASC_BOARDP(shp)->asc_stats.counter += (count)) +#define ASC_STATS_ADD(shost, counter, count) \ + (ASC_BOARDP(shost)->asc_stats.counter += (count)) #endif /* ADVANSYS_STATS */ #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit)) @@ -3617,7 +3587,6 @@ typedef struct scsi_cmnd REQ, *REQP; printk((s), (a1), (a2), (a3), (a4)); \ } - #ifndef ADVANSYS_DEBUG #define ASC_DBG(lvl, s) @@ -3746,7 +3715,6 @@ typedef struct scsi_cmnd REQ, *REQP; #endif /* ADVANSYS_ASSERT */ - /* * --- Driver Structures */ @@ -3755,27 +3723,27 @@ typedef struct scsi_cmnd REQ, *REQP; /* Per board statistics structure */ struct asc_stats { - /* Driver Entrypoint Statistics */ - ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */ - ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */ - ADV_DCNT biosparam; /* # calls to advansys_biosparam() */ - ADV_DCNT interrupt; /* # advansys_interrupt() calls */ - ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */ - ADV_DCNT done; /* # calls to request's scsi_done function */ - ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */ - ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */ - ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */ - /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */ - ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */ - ADV_DCNT exe_busy; /* # ASC_BUSY returns. */ - ADV_DCNT exe_error; /* # ASC_ERROR returns. */ - ADV_DCNT exe_unknown; /* # unknown returns. */ - /* Data Transfer Statistics */ - ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */ - ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */ - ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */ - ADV_DCNT sg_elem; /* # scatter-gather elements */ - ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */ + /* Driver Entrypoint Statistics */ + ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */ + ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */ + ADV_DCNT biosparam; /* # calls to advansys_biosparam() */ + ADV_DCNT interrupt; /* # advansys_interrupt() calls */ + ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */ + ADV_DCNT done; /* # calls to request's scsi_done function */ + ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */ + ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */ + ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */ + /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */ + ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */ + ADV_DCNT exe_busy; /* # ASC_BUSY returns. */ + ADV_DCNT exe_error; /* # ASC_ERROR returns. */ + ADV_DCNT exe_unknown; /* # unknown returns. */ + /* Data Transfer Statistics */ + ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */ + ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */ + ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */ + ADV_DCNT sg_elem; /* # scatter-gather elements */ + ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */ }; #endif /* ADVANSYS_STATS */ @@ -3783,17 +3751,17 @@ struct asc_stats { * Request queuing structure */ typedef struct asc_queue { - ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ - REQP q_first[ADV_MAX_TID+1]; /* first queued request */ - REQP q_last[ADV_MAX_TID+1]; /* last queued request */ + ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ + REQP q_first[ADV_MAX_TID + 1]; /* first queued request */ + REQP q_last[ADV_MAX_TID + 1]; /* last queued request */ #ifdef ADVANSYS_STATS - short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */ - short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */ - ADV_DCNT q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */ - ADV_DCNT q_tot_tim[ADV_MAX_TID+1]; /* total time queued */ - ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */ - ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */ -#endif /* ADVANSYS_STATS */ + short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */ + short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */ + ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */ + ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */ + ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */ + ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */ +#endif /* ADVANSYS_STATS */ } asc_queue_t; /* @@ -3814,17 +3782,17 @@ typedef struct asc_queue { * Both structures must be 32 byte aligned. */ typedef struct adv_sgblk { - ADV_SG_BLOCK sg_block; /* Sgblock structure. */ - uchar align[32]; /* Sgblock structure padding. */ - struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ + ADV_SG_BLOCK sg_block; /* Sgblock structure. */ + uchar align[32]; /* Sgblock structure padding. */ + struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ } adv_sgblk_t; typedef struct adv_req { - ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ - uchar align[32]; /* Request structure padding. */ - struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ - adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ - struct adv_req *next_reqp; /* Next Request Structure. */ + ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ + uchar align[32]; /* Request structure padding. */ + struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ + adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ + struct adv_req *next_reqp; /* Next Request Structure. */ } adv_req_t; /* @@ -3835,113 +3803,109 @@ typedef struct adv_req { * field. It is guaranteed to be allocated from DMA-able memory. */ typedef struct asc_board { - int id; /* Board Id */ - uint flags; /* Board flags */ - union { - ASC_DVC_VAR asc_dvc_var; /* Narrow board */ - ADV_DVC_VAR adv_dvc_var; /* Wide board */ - } dvc_var; - union { - ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */ - ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ - } dvc_cfg; - ushort asc_n_io_port; /* Number I/O ports. */ - asc_queue_t active; /* Active command queue */ - asc_queue_t waiting; /* Waiting command queue */ - asc_queue_t done; /* Done command queue */ - ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ - struct scsi_device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */ - ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */ - ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ - ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */ - union { - ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */ - ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */ - ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */ - ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */ - } eep_config; - ulong last_reset; /* Saved last reset time */ - spinlock_t lock; /* Board spinlock */ + int id; /* Board Id */ + uint flags; /* Board flags */ + union { + ASC_DVC_VAR asc_dvc_var; /* Narrow board */ + ADV_DVC_VAR adv_dvc_var; /* Wide board */ + } dvc_var; + union { + ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */ + ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ + } dvc_cfg; + ushort asc_n_io_port; /* Number I/O ports. */ + asc_queue_t active; /* Active command queue */ + asc_queue_t waiting; /* Waiting command queue */ + asc_queue_t done; /* Done command queue */ + ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ + struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ + ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ + ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ + ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */ + union { + ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */ + ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */ + ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */ + ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */ + } eep_config; + ulong last_reset; /* Saved last reset time */ + spinlock_t lock; /* Board spinlock */ #ifdef CONFIG_PROC_FS - /* /proc/scsi/advansys/[0...] */ - char *prtbuf; /* /proc print buffer */ -#endif /* CONFIG_PROC_FS */ + /* /proc/scsi/advansys/[0...] */ + char *prtbuf; /* /proc print buffer */ +#endif /* CONFIG_PROC_FS */ #ifdef ADVANSYS_STATS - struct asc_stats asc_stats; /* Board statistics */ -#endif /* ADVANSYS_STATS */ - /* - * The following fields are used only for Narrow Boards. - */ - /* The following three structures must be in DMA-able memory. */ - ASC_SCSI_REQ_Q scsireqq; - ASC_CAP_INFO cap_info; - ASC_SCSI_INQUIRY inquiry; - uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */ - /* - * The following fields are used only for Wide Boards. - */ - void __iomem *ioremap_addr; /* I/O Memory remap address. */ - ushort ioport; /* I/O Port address. */ - ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */ - adv_req_t *orig_reqp; /* adv_req_t memory block. */ - adv_req_t *adv_reqp; /* Request structures. */ - adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ - ushort bios_signature; /* BIOS Signature. */ - ushort bios_version; /* BIOS Version. */ - ushort bios_codeseg; /* BIOS Code Segment. */ - ushort bios_codelen; /* BIOS Code Segment Length. */ + struct asc_stats asc_stats; /* Board statistics */ +#endif /* ADVANSYS_STATS */ + /* + * The following fields are used only for Narrow Boards. + */ + /* The following three structures must be in DMA-able memory. */ + ASC_SCSI_REQ_Q scsireqq; + ASC_CAP_INFO cap_info; + ASC_SCSI_INQUIRY inquiry; + uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */ + /* + * The following fields are used only for Wide Boards. + */ + void __iomem *ioremap_addr; /* I/O Memory remap address. */ + ushort ioport; /* I/O Port address. */ + ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */ + adv_req_t *orig_reqp; /* adv_req_t memory block. */ + adv_req_t *adv_reqp; /* Request structures. */ + adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ + ushort bios_signature; /* BIOS Signature. */ + ushort bios_version; /* BIOS Version. */ + ushort bios_codeseg; /* BIOS Code Segment. */ + ushort bios_codelen; /* BIOS Code Segment Length. */ } asc_board_t; /* * PCI configuration structures */ -typedef struct _PCI_DATA_ -{ - uchar type; - uchar bus; - uchar slot; - uchar func; - uchar offset; +typedef struct _PCI_DATA_ { + uchar type; + uchar bus; + uchar slot; + uchar func; + uchar offset; } PCI_DATA; -typedef struct _PCI_DEVICE_ -{ - ushort vendorID; - ushort deviceID; - ushort slotNumber; - ushort slotFound; - uchar busNumber; - uchar maxBusNumber; - uchar devFunc; - ushort startSlot; - ushort endSlot; - uchar bridge; - uchar type; +typedef struct _PCI_DEVICE_ { + ushort vendorID; + ushort deviceID; + ushort slotNumber; + ushort slotFound; + uchar busNumber; + uchar maxBusNumber; + uchar devFunc; + ushort startSlot; + ushort endSlot; + uchar bridge; + uchar type; } PCI_DEVICE; -typedef struct _PCI_CONFIG_SPACE_ -{ - ushort vendorID; - ushort deviceID; - ushort command; - ushort status; - uchar revision; - uchar classCode[3]; - uchar cacheSize; - uchar latencyTimer; - uchar headerType; - uchar bist; - ADV_PADDR baseAddress[6]; - ushort reserved[4]; - ADV_PADDR optionRomAddr; - ushort reserved2[4]; - uchar irqLine; - uchar irqPin; - uchar minGnt; - uchar maxLatency; +typedef struct _PCI_CONFIG_SPACE_ { + ushort vendorID; + ushort deviceID; + ushort command; + ushort status; + uchar revision; + uchar classCode[3]; + uchar cacheSize; + uchar latencyTimer; + uchar headerType; + uchar bist; + ADV_PADDR baseAddress[6]; + ushort reserved[4]; + ADV_PADDR optionRomAddr; + ushort reserved2[4]; + uchar irqLine; + uchar irqPin; + uchar minGnt; + uchar maxLatency; } PCI_CONFIG_SPACE; - /* * --- Driver Data */ @@ -3949,44 +3913,42 @@ typedef struct _PCI_CONFIG_SPACE_ /* Note: All driver global data should be initialized. */ /* Number of boards detected in system. */ -STATIC int asc_board_count = 0; -STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; +static int asc_board_count = 0; +static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; /* Overrun buffer used by all narrow boards. */ -STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; +static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; /* * Global structures required to issue a command. */ -STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } }; -STATIC ASC_SG_HEAD asc_sg_head = { 0 }; +static ASC_SCSI_Q asc_scsi_q = { {0} }; +static ASC_SG_HEAD asc_sg_head = { 0 }; /* List of supported bus types. */ -STATIC ushort asc_bus[ASC_NUM_BUS] __initdata = { - ASC_IS_ISA, - ASC_IS_VL, - ASC_IS_EISA, - ASC_IS_PCI, +static ushort asc_bus[ASC_NUM_BUS] __initdata = { + ASC_IS_ISA, + ASC_IS_VL, + ASC_IS_EISA, + ASC_IS_PCI, }; -STATIC int asc_iopflag = ASC_FALSE; -STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; +static int asc_iopflag = ASC_FALSE; +static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; #ifdef ADVANSYS_DEBUG -STATIC char * -asc_bus_name[ASC_NUM_BUS] = { - "ASC_IS_ISA", - "ASC_IS_VL", - "ASC_IS_EISA", - "ASC_IS_PCI", +static char *asc_bus_name[ASC_NUM_BUS] = { + "ASC_IS_ISA", + "ASC_IS_VL", + "ASC_IS_EISA", + "ASC_IS_PCI", }; -STATIC int asc_dbglvl = 3; +static int asc_dbglvl = 3; #endif /* ADVANSYS_DEBUG */ /* Declaration for Asc Library internal data referenced by driver. */ -STATIC PortAddr _asc_def_iop_base[]; - +static PortAddr _asc_def_iop_base[]; /* * --- Driver Function Prototypes @@ -3994,62 +3956,61 @@ STATIC PortAddr _asc_def_iop_base[]; * advansys.h contains function prototypes for functions global to Linux. */ -STATIC irqreturn_t advansys_interrupt(int, void *); -STATIC int advansys_slave_configure(struct scsi_device *); -STATIC void asc_scsi_done_list(struct scsi_cmnd *); -STATIC int asc_execute_scsi_cmnd(struct scsi_cmnd *); -STATIC int asc_build_req(asc_board_t *, struct scsi_cmnd *); -STATIC int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); -STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); -STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); -STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC void adv_async_callback(ADV_DVC_VAR *, uchar); -STATIC void asc_enqueue(asc_queue_t *, REQP, int); -STATIC REQP asc_dequeue(asc_queue_t *, int); -STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int); -STATIC int asc_rmqueue(asc_queue_t *, REQP); -STATIC void asc_execute_queue(asc_queue_t *); +static irqreturn_t advansys_interrupt(int, void *); +static int advansys_slave_configure(struct scsi_device *); +static void asc_scsi_done_list(struct scsi_cmnd *); +static int asc_execute_scsi_cmnd(struct scsi_cmnd *); +static int asc_build_req(asc_board_t *, struct scsi_cmnd *); +static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); +static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); +static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); +static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static void adv_async_callback(ADV_DVC_VAR *, uchar); +static void asc_enqueue(asc_queue_t *, REQP, int); +static REQP asc_dequeue(asc_queue_t *, int); +static REQP asc_dequeue_list(asc_queue_t *, REQP *, int); +static int asc_rmqueue(asc_queue_t *, REQP); +static void asc_execute_queue(asc_queue_t *); #ifdef CONFIG_PROC_FS -STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int); -STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int); -STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp); -STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); -STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int); -STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); -STATIC int asc_prt_line(char *, int, char *fmt, ...); +static int asc_proc_copy(off_t, off_t, char *, int, char *, int); +static int asc_prt_board_devices(struct Scsi_Host *, char *, int); +static int asc_prt_adv_bios(struct Scsi_Host *, char *, int); +static int asc_get_eeprom_string(ushort *serialnum, uchar *cp); +static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); +static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); +static int asc_prt_driver_conf(struct Scsi_Host *, char *, int); +static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); +static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); +static int asc_prt_line(char *, int, char *fmt, ...); #endif /* CONFIG_PROC_FS */ /* Declaration for Asc Library internal functions referenced by driver. */ -STATIC int AscFindSignature(PortAddr); -STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscFindSignature(PortAddr); +static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); /* Statistics function prototypes. */ #ifdef ADVANSYS_STATS #ifdef CONFIG_PROC_FS -STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int); -STATIC int asc_prt_target_stats(struct Scsi_Host *, int, char *, int); +static int asc_prt_board_stats(struct Scsi_Host *, char *, int); +static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int); #endif /* CONFIG_PROC_FS */ #endif /* ADVANSYS_STATS */ /* Debug function prototypes. */ #ifdef ADVANSYS_DEBUG -STATIC void asc_prt_scsi_host(struct Scsi_Host *); -STATIC void asc_prt_scsi_cmnd(struct scsi_cmnd *); -STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); -STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *); -STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *); -STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); -STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); -STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *); -STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); -STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); -STATIC void asc_prt_hex(char *f, uchar *, int); +static void asc_prt_scsi_host(struct Scsi_Host *); +static void asc_prt_scsi_cmnd(struct scsi_cmnd *); +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *); +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *); +static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); +static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); +static void asc_prt_adv_dvc_var(ADV_DVC_VAR *); +static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); +static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); +static void asc_prt_hex(char *f, uchar *, int); #endif /* ADVANSYS_DEBUG */ - #ifdef CONFIG_PROC_FS /* * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] @@ -4073,1389 +4034,210 @@ STATIC void asc_prt_hex(char *f, uchar *, int); */ static int advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, - off_t offset, int length, int inout) + off_t offset, int length, int inout) { - struct Scsi_Host *shp; - asc_board_t *boardp; - int i; - char *cp; - int cplen; - int cnt; - int totcnt; - int leftlen; - char *curbuf; - off_t advoffset; + struct Scsi_Host *shp; + asc_board_t *boardp; + int i; + char *cp; + int cplen; + int cnt; + int totcnt; + int leftlen; + char *curbuf; + off_t advoffset; #ifdef ADVANSYS_STATS - int tgt_id; + int tgt_id; #endif /* ADVANSYS_STATS */ - ASC_DBG(1, "advansys_proc_info: begin\n"); - - /* - * User write not supported. - */ - if (inout == TRUE) { - return(-ENOSYS); - } + ASC_DBG(1, "advansys_proc_info: begin\n"); - /* - * User read of /proc/scsi/advansys/[0...] file. - */ - - /* Find the specified board. */ - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i]->host_no == shost->host_no) { - break; - } - } - if (i == asc_board_count) { - return(-ENOENT); - } - - shp = asc_host[i]; - boardp = ASC_BOARDP(shp); - - /* Copy read data starting at the beginning of the buffer. */ - *start = buffer; - curbuf = buffer; - advoffset = 0; - totcnt = 0; - leftlen = length; - - /* - * Get board configuration information. - * - * advansys_info() returns the board string from its own static buffer. - */ - cp = (char *) advansys_info(shp); - strcat(cp, "\n"); - cplen = strlen(cp); - /* Copy board information. */ - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* + * User write not supported. + */ + if (inout == TRUE) { + return (-ENOSYS); + } - /* - * Display Wide Board BIOS Information. - */ - if (ASC_WIDE_BOARD(boardp)) { - cp = boardp->prtbuf; - cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } + /* + * User read of /proc/scsi/advansys/[0...] file. + */ - /* - * Display driver information for each device attached to the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* Find the specified board. */ + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i]->host_no == shost->host_no) { + break; + } + } + if (i == asc_board_count) { + return (-ENOENT); + } - /* - * Display EEPROM configuration for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + shp = asc_host[i]; + boardp = ASC_BOARDP(shp); + + /* Copy read data starting at the beginning of the buffer. */ + *start = buffer; + curbuf = buffer; + advoffset = 0; + totcnt = 0; + leftlen = length; + + /* + * Get board configuration information. + * + * advansys_info() returns the board string from its own static buffer. + */ + cp = (char *)advansys_info(shp); + strcat(cp, "\n"); + cplen = strlen(cp); + /* Copy board information. */ + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display Wide Board BIOS Information. + */ + if (ASC_WIDE_BOARD(boardp)) { + cp = boardp->prtbuf; + cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = + asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, + cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } - /* - * Display driver configuration and information for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* + * Display driver information for each device attached to the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display EEPROM configuration for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); + } else { + cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); + } + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display driver configuration and information for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; #ifdef ADVANSYS_STATS - /* - * Display driver statistics for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Display driver statistics for each target. - */ - for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) { - cp = boardp->prtbuf; - cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } + /* + * Display driver statistics for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display driver statistics for each target. + */ + for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) { + cp = boardp->prtbuf; + cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); + cnt = + asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, + cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } #endif /* ADVANSYS_STATS */ - /* - * Display Asc Library dynamic configuration information - * for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - - return totcnt; -} -#endif /* CONFIG_PROC_FS */ - -/* - * advansys_detect() - * - * Detect function for AdvanSys adapters. - * - * Argument is a pointer to the host driver's scsi_hosts entry. - * - * Return number of adapters found. - * - * Note: Because this function is called during system initialization - * it must not call SCSI mid-level functions including scsi_malloc() - * and scsi_free(). - */ -static int __init -advansys_detect(struct scsi_host_template *tpnt) -{ - static int detect_called = ASC_FALSE; - int iop; - int bus; - struct Scsi_Host *shp = NULL; - asc_board_t *boardp = NULL; - ASC_DVC_VAR *asc_dvc_varp = NULL; - ADV_DVC_VAR *adv_dvc_varp = NULL; - adv_sgblk_t *sgp = NULL; - int ioport = 0; - int share_irq = FALSE; - int iolen = 0; - struct device *dev = NULL; -#ifdef CONFIG_PCI - int pci_init_search = 0; - struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; - int pci_card_cnt_max = 0; - int pci_card_cnt = 0; - struct pci_dev *pci_devp = NULL; - int pci_device_id_cnt = 0; - unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { - PCI_DEVICE_ID_ASP_1200A, - PCI_DEVICE_ID_ASP_ABP940, - PCI_DEVICE_ID_ASP_ABP940U, - PCI_DEVICE_ID_ASP_ABP940UW, - PCI_DEVICE_ID_38C0800_REV1, - PCI_DEVICE_ID_38C1600_REV1 - }; - ADV_PADDR pci_memory_address; -#endif /* CONFIG_PCI */ - int warn_code, err_code; - int ret; - - if (detect_called == ASC_FALSE) { - detect_called = ASC_TRUE; - } else { - printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); - return 0; - } - - ASC_DBG(1, "advansys_detect: begin\n"); - - asc_board_count = 0; - - /* - * If I/O port probing has been modified, then verify and - * clean-up the 'asc_ioport' list. - */ - if (asc_iopflag == ASC_TRUE) { - for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { - ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n", - ioport, asc_ioport[ioport]); - if (asc_ioport[ioport] != 0) { - for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) { - if (_asc_def_iop_base[iop] == asc_ioport[ioport]) { - break; - } - } - if (iop == ASC_IOADR_TABLE_MAX_IX) { - printk( -"AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", - asc_ioport[ioport]); - asc_ioport[ioport] = 0; - } - } - } - ioport = 0; - } - - for (bus = 0; bus < ASC_NUM_BUS; bus++) { - - ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", - bus, asc_bus_name[bus]); - iop = 0; - - while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { - - ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", - asc_board_count); - - switch (asc_bus[bus]) { - case ASC_IS_ISA: - case ASC_IS_VL: -#ifdef CONFIG_ISA - if (asc_iopflag == ASC_FALSE) { - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); - } else { - /* - * ISA and VL I/O port scanning has either been - * eliminated or limited to selected ports on - * the LILO command line, /etc/lilo.conf, or - * by setting variables when the module was loaded. - */ - ASC_DBG(1, "advansys_detect: I/O port scanning modified\n"); - ioport_try_again: - iop = 0; - for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { - if ((iop = asc_ioport[ioport]) != 0) { - break; - } - } - if (iop) { - ASC_DBG1(1, - "advansys_detect: probing I/O port 0x%x...\n", - iop); - if (!request_region(iop, ASC_IOADR_GAP, "advansys")){ - printk( -"AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); - /* Don't try this I/O port twice. */ - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else if (AscFindSignature(iop) == ASC_FALSE) { - printk( -"AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); - /* Don't try this I/O port twice. */ - release_region(iop, ASC_IOADR_GAP); - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else { - /* - * If this isn't an ISA board, then it must be - * a VL board. If currently looking an ISA - * board is being looked for then try for - * another ISA board in 'asc_ioport'. - */ - if (asc_bus[bus] == ASC_IS_ISA && - (AscGetChipVersion(iop, ASC_IS_ISA) & - ASC_CHIP_VER_ISA_BIT) == 0) { - /* - * Don't clear 'asc_ioport[ioport]'. Try - * this board again for VL. Increment - * 'ioport' past this board. - */ - ioport++; - release_region(iop, ASC_IOADR_GAP); - goto ioport_try_again; - } - } - /* - * This board appears good, don't try the I/O port - * again by clearing its value. Increment 'ioport' - * for the next iteration. - */ - asc_ioport[ioport++] = 0; - } - } -#endif /* CONFIG_ISA */ - break; - - case ASC_IS_EISA: -#ifdef CONFIG_ISA - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); -#endif /* CONFIG_ISA */ - break; - - case ASC_IS_PCI: -#ifdef CONFIG_PCI - if (pci_init_search == 0) { - int i, j; - - pci_init_search = 1; - - /* Find all PCI cards. */ - while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { - if ((pci_devp = pci_find_device(PCI_VENDOR_ID_ASP, - pci_device_id[pci_device_id_cnt], pci_devp)) == - NULL) { - pci_device_id_cnt++; - } else { - if (pci_enable_device(pci_devp) == 0) { - pci_devicep[pci_card_cnt_max++] = pci_devp; - } - } - } - - /* - * Sort PCI cards in ascending order by PCI Bus, Slot, - * and Device Number. - */ - for (i = 0; i < pci_card_cnt_max - 1; i++) - { - for (j = i + 1; j < pci_card_cnt_max; j++) { - if ((pci_devicep[j]->bus->number < - pci_devicep[i]->bus->number) || - ((pci_devicep[j]->bus->number == - pci_devicep[i]->bus->number) && - (pci_devicep[j]->devfn < - pci_devicep[i]->devfn))) { - pci_devp = pci_devicep[i]; - pci_devicep[i] = pci_devicep[j]; - pci_devicep[j] = pci_devp; - } - } - } - - pci_card_cnt = 0; - } else { - pci_card_cnt++; - } - - if (pci_card_cnt == pci_card_cnt_max) { - iop = 0; - } else { - pci_devp = pci_devicep[pci_card_cnt]; - - ASC_DBG2(2, - "advansys_detect: devfn %d, bus number %d\n", - pci_devp->devfn, pci_devp->bus->number); - iop = pci_resource_start(pci_devp, 0); - ASC_DBG2(1, - "advansys_detect: vendorID %X, deviceID %X\n", - pci_devp->vendor, pci_devp->device); - ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", - iop, pci_devp->irq); - } - if(pci_devp) - dev = &pci_devp->dev; - -#endif /* CONFIG_PCI */ - break; - - default: - ASC_PRINT1("advansys_detect: unknown bus type: %d\n", - asc_bus[bus]); - break; - } - ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); - - /* - * Adapter not found, try next bus type. - */ - if (iop == 0) { - break; - } - - /* - * Adapter found. - * - * Register the adapter, get its configuration, and - * initialize it. - */ - ASC_DBG(2, "advansys_detect: scsi_register()\n"); - shp = scsi_register(tpnt, sizeof(asc_board_t)); - - if (shp == NULL) { - continue; - } - - /* Save a pointer to the Scsi_Host of each board found. */ - asc_host[asc_board_count++] = shp; - - /* Initialize private per board data */ - boardp = ASC_BOARDP(shp); - memset(boardp, 0, sizeof(asc_board_t)); - boardp->id = asc_board_count - 1; - - /* Initialize spinlock. */ - spin_lock_init(&boardp->lock); - - /* - * Handle both narrow and wide boards. - * - * If a Wide board was detected, set the board structure - * wide board flag. Set-up the board structure based on - * the board type. - */ -#ifdef CONFIG_PCI - if (asc_bus[bus] == ASC_IS_PCI && - (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW || - pci_devp->device == PCI_DEVICE_ID_38C0800_REV1 || - pci_devp->device == PCI_DEVICE_ID_38C1600_REV1)) - { - boardp->flags |= ASC_IS_WIDE_BOARD; - } -#endif /* CONFIG_PCI */ - - if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(1, "advansys_detect: narrow board\n"); - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - asc_dvc_varp->bus_type = asc_bus[bus]; - asc_dvc_varp->drv_ptr = boardp; - asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; - asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; - asc_dvc_varp->iop_base = iop; - asc_dvc_varp->isr_callback = asc_isr_callback; - } else { - ASC_DBG(1, "advansys_detect: wide board\n"); - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - adv_dvc_varp->drv_ptr = boardp; - adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; - adv_dvc_varp->isr_callback = adv_isr_callback; - adv_dvc_varp->async_callback = adv_async_callback; -#ifdef CONFIG_PCI - if (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW) - { - ASC_DBG(1, "advansys_detect: ASC-3550\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; - } else if (pci_devp->device == PCI_DEVICE_ID_38C0800_REV1) - { - ASC_DBG(1, "advansys_detect: ASC-38C0800\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; - } else - { - ASC_DBG(1, "advansys_detect: ASC-38C1600\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; - } -#endif /* CONFIG_PCI */ - - /* - * Map the board's registers into virtual memory for - * PCI slave access. Only memory accesses are used to - * access the board's registers. - * - * Note: The PCI register base address is not always - * page aligned, but the address passed to ioremap() - * must be page aligned. It is guaranteed that the - * PCI register base address will not cross a page - * boundary. - */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - iolen = ADV_3550_IOLEN; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - iolen = ADV_38C0800_IOLEN; - } else - { - iolen = ADV_38C1600_IOLEN; - } -#ifdef CONFIG_PCI - pci_memory_address = pci_resource_start(pci_devp, 1); - ASC_DBG1(1, "advansys_detect: pci_memory_address: 0x%lx\n", - (ulong) pci_memory_address); - if ((boardp->ioremap_addr = - ioremap(pci_memory_address & PAGE_MASK, - PAGE_SIZE)) == 0) { - ASC_PRINT3( -"advansys_detect: board %d: ioremap(%x, %d) returned NULL\n", - boardp->id, pci_memory_address, iolen); - scsi_unregister(shp); - asc_board_count--; - continue; - } - ASC_DBG1(1, "advansys_detect: ioremap_addr: 0x%lx\n", - (ulong) boardp->ioremap_addr); - adv_dvc_varp->iop_base = (AdvPortAddr) - (boardp->ioremap_addr + - (pci_memory_address - (pci_memory_address & PAGE_MASK))); - ASC_DBG1(1, "advansys_detect: iop_base: 0x%lx\n", - adv_dvc_varp->iop_base); -#endif /* CONFIG_PCI */ - - /* - * Even though it isn't used to access wide boards, other - * than for the debug line below, save I/O Port address so - * that it can be reported. - */ - boardp->ioport = iop; - - ASC_DBG2(1, -"advansys_detect: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", - (ushort) inp(iop + 1), (ushort) inpw(iop)); - } - -#ifdef CONFIG_PROC_FS - /* - * Allocate buffer for printing information from - * /proc/scsi/advansys/[0...]. - */ - if ((boardp->prtbuf = - kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { - ASC_PRINT3( -"advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n", - boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); - scsi_unregister(shp); - asc_board_count--; - continue; - } -#endif /* CONFIG_PROC_FS */ - - if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp->cfg->dev = dev; - /* - * Set the board bus type and PCI IRQ before - * calling AscInitGetConfig(). - */ - switch (asc_dvc_varp->bus_type) { -#ifdef CONFIG_ISA - case ASC_IS_ISA: - shp->unchecked_isa_dma = TRUE; - share_irq = FALSE; - break; - case ASC_IS_VL: - shp->unchecked_isa_dma = FALSE; - share_irq = FALSE; - break; - case ASC_IS_EISA: - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; - break; -#endif /* CONFIG_ISA */ -#ifdef CONFIG_PCI - case ASC_IS_PCI: - shp->irq = asc_dvc_varp->irq_no = pci_devp->irq; - asc_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pci_devp->bus->number, - PCI_SLOT(pci_devp->devfn), - PCI_FUNC(pci_devp->devfn)); - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; - break; -#endif /* CONFIG_PCI */ - default: - ASC_PRINT2( -"advansys_detect: board %d: unknown adapter type: %d\n", - boardp->id, asc_dvc_varp->bus_type); - shp->unchecked_isa_dma = TRUE; - share_irq = FALSE; - break; - } - } else { - adv_dvc_varp->cfg->dev = dev; - /* - * For Wide boards set PCI information before calling - * AdvInitGetConfig(). - */ -#ifdef CONFIG_PCI - shp->irq = adv_dvc_varp->irq_no = pci_devp->irq; - adv_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pci_devp->bus->number, - PCI_SLOT(pci_devp->devfn), - PCI_FUNC(pci_devp->devfn)); - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; -#endif /* CONFIG_PCI */ - } - - /* - * Read the board configuration. - */ - if (ASC_NARROW_BOARD(boardp)) { - /* - * NOTE: AscInitGetConfig() may change the board's - * bus_type value. The asc_bus[bus] value should no - * longer be used. If the bus_type field must be - * referenced only use the bit-wise AND operator "&". - */ - ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); - switch(ret = AscInitGetConfig(asc_dvc_varp)) { - case 0: /* No error */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1( -"AscInitGetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1( -"AscInitGetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1( -"AscInitGetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1( -"AscInitGetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1( -"AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2( -"AscInitGetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if ((err_code = asc_dvc_varp->err_code) != 0) { - ASC_PRINT3( -"AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - asc_dvc_varp->err_code); - } - } else { - ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n"); - if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { - ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n", - boardp->id, ret); - } - if ((err_code = adv_dvc_varp->err_code) != 0) { - ASC_PRINT2( -"AdvInitGetConfig: board %d error: err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - } - } - - if (err_code != 0) { -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Save the EEPROM configuration so that it can be displayed - * from /proc/scsi/advansys/[0...]. - */ - if (ASC_NARROW_BOARD(boardp)) { - - ASCEEP_CONFIG *ep; - - /* - * Set the adapter's target id bit in the 'init_tidmask' field. - */ - boardp->init_tidmask |= - ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id); - - /* - * Save EEPROM settings for the board. - */ - ep = &boardp->eep_config.asc_eep; - - ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; - ep->disc_enable = asc_dvc_varp->cfg->disc_enable; - ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; - ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed); - ep->start_motor = asc_dvc_varp->start_motor; - ep->cntl = asc_dvc_varp->dvc_cntl; - ep->no_scam = asc_dvc_varp->no_scam; - ep->max_total_qng = asc_dvc_varp->max_total_qng; - ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id); - /* 'max_tag_qng' is set to the same value for every device. */ - ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0]; - ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0]; - ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1]; - ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2]; - ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; - ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; - ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; - - /* - * Modify board configuration. - */ - ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n"); - switch (ret = AscInitSetConfig(asc_dvc_varp)) { - case 0: /* No error. */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1( -"AscInitSetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1( -"AscInitSetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1( -"AscInitSetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1( -"AscInitSetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1( -"AscInitSetConfig: board %d: tag queuing w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2( -"AscInitSetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if (asc_dvc_varp->err_code != 0) { - ASC_PRINT3( -"AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - asc_dvc_varp->err_code); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ - if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { - shp->irq = asc_dvc_varp->irq_no; - } - } else { - ADVEEP_3550_CONFIG *ep_3550; - ADVEEP_38C0800_CONFIG *ep_38C0800; - ADVEEP_38C1600_CONFIG *ep_38C1600; - - /* - * Save Wide EEP Configuration Information. - */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ep_3550 = &boardp->eep_config.adv_3550_eep; - - ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_3550->max_host_qng = adv_dvc_varp->max_host_qng; - ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_3550->termination = adv_dvc_varp->cfg->termination; - ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_3550->wdtr_able = adv_dvc_varp->wdtr_able; - ep_3550->sdtr_able = adv_dvc_varp->sdtr_able; - ep_3550->ultra_able = adv_dvc_varp->ultra_able; - ep_3550->tagqng_able = adv_dvc_varp->tagqng_able; - ep_3550->start_motor = adv_dvc_varp->start_motor; - ep_3550->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait; - ep_3550->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_3550->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_3550->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; - - ep_38C0800->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng; - ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_38C0800->termination_lvd = - adv_dvc_varp->cfg->termination; - ep_38C0800->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able; - ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; - ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; - ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; - ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; - ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C0800->start_motor = adv_dvc_varp->start_motor; - ep_38C0800->scsi_reset_delay = - adv_dvc_varp->scsi_reset_wait; - ep_38C0800->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_38C0800->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_38C0800->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } else - { - ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; - - ep_38C1600->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng; - ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_38C1600->termination_lvd = - adv_dvc_varp->cfg->termination; - ep_38C1600->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able; - ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; - ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; - ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; - ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; - ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C1600->start_motor = adv_dvc_varp->start_motor; - ep_38C1600->scsi_reset_delay = - adv_dvc_varp->scsi_reset_wait; - ep_38C1600->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_38C1600->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_38C1600->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } - - /* - * Set the adapter's target id bit in the 'init_tidmask' field. - */ - boardp->init_tidmask |= - ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - shp->irq = adv_dvc_varp->irq_no; - } - - /* - * Channels are numbered beginning with 0. For AdvanSys one host - * structure supports one channel. Multi-channel boards have a - * separate host structure for each channel. - */ - shp->max_channel = 0; - if (ASC_NARROW_BOARD(boardp)) { - shp->max_id = ASC_MAX_TID + 1; - shp->max_lun = ASC_MAX_LUN + 1; - - shp->io_port = asc_dvc_varp->iop_base; - boardp->asc_n_io_port = ASC_IOADR_GAP; - shp->this_id = asc_dvc_varp->cfg->chip_scsi_id; - - /* Set maximum number of queues the adapter can handle. */ - shp->can_queue = asc_dvc_varp->max_total_qng; - } else { - shp->max_id = ADV_MAX_TID + 1; - shp->max_lun = ADV_MAX_LUN + 1; - - /* - * Save the I/O Port address and length even though - * I/O ports are not used to access Wide boards. - * Instead the Wide boards are accessed with - * PCI Memory Mapped I/O. - */ - shp->io_port = iop; - boardp->asc_n_io_port = iolen; - - shp->this_id = adv_dvc_varp->chip_scsi_id; - - /* Set maximum number of queues the adapter can handle. */ - shp->can_queue = adv_dvc_varp->max_host_qng; - } - - /* - * 'n_io_port' currently is one byte. - * - * Set a value to 'n_io_port', but never referenced it because - * it may be truncated. - */ - shp->n_io_port = boardp->asc_n_io_port <= 255 ? - boardp->asc_n_io_port : 255; - - /* - * Following v1.3.89, 'cmd_per_lun' is no longer needed - * and should be set to zero. - * - * But because of a bug introduced in v1.3.89 if the driver is - * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level - * SCSI function 'allocate_device' will panic. To allow the driver - * to work as a module in these kernels set 'cmd_per_lun' to 1. - * - * Note: This is wrong. cmd_per_lun should be set to the depth - * you want on untagged devices always. -#ifdef MODULE - */ - shp->cmd_per_lun = 1; -/* #else - shp->cmd_per_lun = 0; -#endif */ - - /* - * Set the maximum number of scatter-gather elements the - * adapter can handle. - */ - if (ASC_NARROW_BOARD(boardp)) { - /* - * Allow two commands with 'sg_tablesize' scatter-gather - * elements to be executed simultaneously. This value is - * the theoretical hardware limit. It may be decreased - * below. - */ - shp->sg_tablesize = - (((asc_dvc_varp->max_total_qng - 2) / 2) * - ASC_SG_LIST_PER_Q) + 1; - } else { - shp->sg_tablesize = ADV_MAX_SG_LIST; - } - - /* - * The value of 'sg_tablesize' can not exceed the SCSI - * mid-level driver definition of SG_ALL. SG_ALL also - * must not be exceeded, because it is used to define the - * size of the scatter-gather table in 'struct asc_sg_head'. - */ - if (shp->sg_tablesize > SG_ALL) { - shp->sg_tablesize = SG_ALL; - } - - ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n", - shp->sg_tablesize); - - /* BIOS start address. */ - if (ASC_NARROW_BOARD(boardp)) { - shp->base = - ((ulong) AscGetChipBiosAddress( - asc_dvc_varp->iop_base, - asc_dvc_varp->bus_type)); - } else { - /* - * Fill-in BIOS board variables. The Wide BIOS saves - * information in LRAM that is used by the driver. - */ - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE, - boardp->bios_signature); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION, - boardp->bios_version); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG, - boardp->bios_codeseg); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN, - boardp->bios_codelen); - - ASC_DBG2(1, - "advansys_detect: bios_signature 0x%x, bios_version 0x%x\n", - boardp->bios_signature, boardp->bios_version); - - ASC_DBG2(1, - "advansys_detect: bios_codeseg 0x%x, bios_codelen 0x%x\n", - boardp->bios_codeseg, boardp->bios_codelen); - - /* - * If the BIOS saved a valid signature, then fill in - * the BIOS code segment base address. - */ - if (boardp->bios_signature == 0x55AA) { - /* - * Convert x86 realmode code segment to a linear - * address by shifting left 4. - */ - shp->base = ((ulong) boardp->bios_codeseg << 4); - } else { - shp->base = 0; - } - } - - /* - * Register Board Resources - I/O Port, DMA, IRQ - */ - - /* - * Register I/O port range. - * - * For Wide boards the I/O ports are not used to access - * the board, but request the region anyway. - * - * 'shp->n_io_port' is not referenced, because it may be truncated. - */ - ASC_DBG2(2, - "advansys_detect: request_region port 0x%lx, len 0x%x\n", - (ulong) shp->io_port, boardp->asc_n_io_port); - if (request_region(shp->io_port, boardp->asc_n_io_port, - "advansys") == NULL) { - ASC_PRINT3( -"advansys_detect: board %d: request_region() failed, port 0x%lx, len 0x%x\n", - boardp->id, (ulong) shp->io_port, boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* Register DMA Channel for Narrow boards. */ - shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ -#ifdef CONFIG_ISA - if (ASC_NARROW_BOARD(boardp)) { - /* Register DMA channel for ISA bus. */ - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; - if ((ret = - request_dma(shp->dma_channel, "advansys")) != 0) { - ASC_PRINT3( -"advansys_detect: board %d: request_dma() %d failed %d\n", - boardp->id, shp->dma_channel, ret); - release_region(shp->io_port, boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - AscEnableIsaDma(shp->dma_channel); - } - } -#endif /* CONFIG_ISA */ + /* + * Display Asc Library dynamic configuration information + * for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); + } else { + cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); + } + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; - /* Register IRQ Number. */ - ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq); - /* - * If request_irq() fails with the IRQF_DISABLED flag set, - * then try again without the IRQF_DISABLED flag set. This - * allows IRQ sharing to work even with other drivers that - * do not set the IRQF_DISABLED flag. - * - * If IRQF_DISABLED is not set, then interrupts are enabled - * before the driver interrupt function is called. - */ - if (((ret = request_irq(shp->irq, advansys_interrupt, - IRQF_DISABLED | (share_irq == TRUE ? IRQF_SHARED : 0), - "advansys", boardp)) != 0) && - ((ret = request_irq(shp->irq, advansys_interrupt, - (share_irq == TRUE ? IRQF_SHARED : 0), - "advansys", boardp)) != 0)) - { - if (ret == -EBUSY) { - ASC_PRINT2( -"advansys_detect: board %d: request_irq(): IRQ 0x%x already in use.\n", - boardp->id, shp->irq); - } else if (ret == -EINVAL) { - ASC_PRINT2( -"advansys_detect: board %d: request_irq(): IRQ 0x%x not valid.\n", - boardp->id, shp->irq); - } else { - ASC_PRINT3( -"advansys_detect: board %d: request_irq(): IRQ 0x%x failed with %d\n", - boardp->id, shp->irq, ret); - } - release_region(shp->io_port, boardp->asc_n_io_port); - iounmap(boardp->ioremap_addr); - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Initialize board RISC chip and enable interrupts. - */ - if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n"); - warn_code = AscInitAsc1000Driver(asc_dvc_varp); - err_code = asc_dvc_varp->err_code; - - if (warn_code || err_code) { - ASC_PRINT4( -"advansys_detect: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - warn_code, err_code); - } - } else { - ADV_CARR_T *carrp; - int req_cnt = 0; - adv_req_t *reqp = NULL; - int sg_cnt = 0; - - /* - * Allocate buffer carrier structures. The total size - * is about 4 KB, so allocate all at once. - */ - carrp = - (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC); - ASC_DBG1(1, "advansys_detect: carrp 0x%lx\n", (ulong) carrp); - - if (carrp == NULL) { - goto kmalloc_error; - } - - /* - * Allocate up to 'max_host_qng' request structures for - * the Wide board. The total size is about 16 KB, so - * allocate all at once. If the allocation fails decrement - * and try again. - */ - for (req_cnt = adv_dvc_varp->max_host_qng; - req_cnt > 0; req_cnt--) { - - reqp = (adv_req_t *) - kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); - - ASC_DBG3(1, - "advansys_detect: reqp 0x%lx, req_cnt %d, bytes %lu\n", - (ulong) reqp, req_cnt, - (ulong) sizeof(adv_req_t) * req_cnt); - - if (reqp != NULL) { - break; - } - } - if (reqp == NULL) - { - goto kmalloc_error; - } - - /* - * Allocate up to ADV_TOT_SG_BLOCK request structures for - * the Wide board. Each structure is about 136 bytes. - */ - boardp->adv_sgblkp = NULL; - for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { - - sgp = (adv_sgblk_t *) - kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); - - if (sgp == NULL) { - break; - } - - sgp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgp; - - } - ASC_DBG3(1, - "advansys_detect: sg_cnt %d * %u = %u bytes\n", - sg_cnt, sizeof(adv_sgblk_t), - (unsigned) (sizeof(adv_sgblk_t) * sg_cnt)); - - /* - * If no request structures or scatter-gather structures could - * be allocated, then return an error. Otherwise continue with - * initialization. - */ - kmalloc_error: - if (carrp == NULL) - { - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() carrier buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (reqp == NULL) { - kfree(carrp); - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() adv_req_t buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (boardp->adv_sgblkp == NULL) { - kfree(carrp); - kfree(reqp); - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n", - boardp->id); - err_code = ADV_ERROR; - } else { - - /* Save carrier buffer pointer. */ - boardp->orig_carrp = carrp; - - /* - * Save original pointer for kfree() in case the - * driver is built as a module and can be unloaded. - */ - boardp->orig_reqp = reqp; - - adv_dvc_varp->carrier_buf = carrp; - - /* - * Point 'adv_reqp' to the request structures and - * link them together. - */ - req_cnt--; - reqp[req_cnt].next_reqp = NULL; - for (; req_cnt > 0; req_cnt--) { - reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; - } - boardp->adv_reqp = &reqp[0]; - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ASC_DBG(2, - "advansys_detect: AdvInitAsc3550Driver()\n"); - warn_code = AdvInitAsc3550Driver(adv_dvc_varp); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - ASC_DBG(2, - "advansys_detect: AdvInitAsc38C0800Driver()\n"); - warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp); - } else { - ASC_DBG(2, - "advansys_detect: AdvInitAsc38C1600Driver()\n"); - warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp); - } - err_code = adv_dvc_varp->err_code; - - if (warn_code || err_code) { - ASC_PRINT3( -"advansys_detect: board %d error: warn 0x%x, error 0x%x\n", - boardp->id, warn_code, err_code); - } - } - } - - if (err_code != 0) { - release_region(shp->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) - { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - free_irq(shp->irq, boardp); - scsi_unregister(shp); - asc_board_count--; - continue; - } - ASC_DBG_PRT_SCSI_HOST(2, shp); - } - } + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count); - return asc_board_count; + return totcnt; } - -/* - * advansys_release() - * - * Release resources allocated for a single AdvanSys adapter. - */ -static int -advansys_release(struct Scsi_Host *shp) -{ - asc_board_t *boardp; - - ASC_DBG(1, "advansys_release: begin\n"); - boardp = ASC_BOARDP(shp); - free_irq(shp->irq, boardp); - if (shp->dma_channel != NO_ISA_DMA) { - ASC_DBG(1, "advansys_release: free_dma()\n"); - free_dma(shp->dma_channel); - } - release_region(shp->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - adv_sgblk_t *sgp = NULL; - - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) - { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } -#ifdef CONFIG_PROC_FS - ASC_ASSERT(boardp->prtbuf != NULL); - kfree(boardp->prtbuf); #endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - ASC_DBG(1, "advansys_release: end\n"); - return 0; -} /* * advansys_info() @@ -5466,91 +4248,87 @@ advansys_release(struct Scsi_Host *shp) * Note: The information line should not exceed ASC_INFO_SIZE bytes, * otherwise the static 'info' array will be overrun. */ -static const char * -advansys_info(struct Scsi_Host *shp) +static const char *advansys_info(struct Scsi_Host *shost) { - static char info[ASC_INFO_SIZE]; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - char *busname; - int iolen; - char *widename = NULL; - - boardp = ASC_BOARDP(shp); - if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ASC_DBG(1, "advansys_info: begin\n"); - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) { - busname = "ISA PnP"; - } else { - busname = "ISA"; - } - /* Don't reference 'shp->n_io_port'; It may be truncated. */ - sprintf(info, -"AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", - ASC_VERSION, busname, - (ulong) shp->io_port, - (ulong) shp->io_port + boardp->asc_n_io_port - 1, - shp->irq, shp->dma_channel); - } else { - if (asc_dvc_varp->bus_type & ASC_IS_VL) { - busname = "VL"; - } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { - busname = "EISA"; - } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { - if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) - == ASC_IS_PCI_ULTRA) { - busname = "PCI Ultra"; - } else { - busname = "PCI"; - } - } else { - busname = "?"; - ASC_PRINT2( "advansys_info: board %d: unknown bus type %d\n", - boardp->id, asc_dvc_varp->bus_type); - } - /* Don't reference 'shp->n_io_port'; It may be truncated. */ - sprintf(info, - "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, busname, - (ulong) shp->io_port, - (ulong) shp->io_port + boardp->asc_n_io_port - 1, - shp->irq); - } - } else { - /* - * Wide Adapter Information - * - * Memory-mapped I/O is used instead of I/O space to access - * the adapter, but display the I/O Port range. The Memory - * I/O address is displayed through the driver /proc file. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - iolen = ADV_3550_IOLEN; - widename = "Ultra-Wide"; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - iolen = ADV_38C0800_IOLEN; - widename = "Ultra2-Wide"; - } else - { - iolen = ADV_38C1600_IOLEN; - widename = "Ultra3-Wide"; - } - sprintf(info, "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, - widename, - (ulong) adv_dvc_varp->iop_base, - (ulong) adv_dvc_varp->iop_base + iolen - 1, - shp->irq); - } - ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); - ASC_DBG(1, "advansys_info: end\n"); - return info; + static char info[ASC_INFO_SIZE]; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + char *busname; + int iolen; + char *widename = NULL; + + boardp = ASC_BOARDP(shost); + if (ASC_NARROW_BOARD(boardp)) { + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + ASC_DBG(1, "advansys_info: begin\n"); + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == + ASC_IS_ISAPNP) { + busname = "ISA PnP"; + } else { + busname = "ISA"; + } + /* Don't reference 'shost->n_io_port'; It may be truncated. */ + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + boardp->asc_n_io_port - + 1, shost->irq, shost->dma_channel); + } else { + if (asc_dvc_varp->bus_type & ASC_IS_VL) { + busname = "VL"; + } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { + busname = "EISA"; + } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { + if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) + == ASC_IS_PCI_ULTRA) { + busname = "PCI Ultra"; + } else { + busname = "PCI"; + } + } else { + busname = "?"; + ASC_PRINT2 + ("advansys_info: board %d: unknown bus type %d\n", + boardp->id, asc_dvc_varp->bus_type); + } + /* Don't reference 'shost->n_io_port'; It may be truncated. */ + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + boardp->asc_n_io_port - + 1, shost->irq); + } + } else { + /* + * Wide Adapter Information + * + * Memory-mapped I/O is used instead of I/O space to access + * the adapter, but display the I/O Port range. The Memory + * I/O address is displayed through the driver /proc file. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + iolen = ADV_3550_IOLEN; + widename = "Ultra-Wide"; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + iolen = ADV_38C0800_IOLEN; + widename = "Ultra2-Wide"; + } else { + iolen = ADV_38C1600_IOLEN; + widename = "Ultra3-Wide"; + } + sprintf(info, + "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, + (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq); + } + ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); + ASC_DBG(1, "advansys_info: end\n"); + return info; } /* @@ -5560,82 +4338,82 @@ advansys_info(struct Scsi_Host *shp) * in the 'scp' result field. */ static int -advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) +advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) { - struct Scsi_Host *shp; - asc_board_t *boardp; - ulong flags; - struct scsi_cmnd *done_scp; + struct Scsi_Host *shost; + asc_board_t *boardp; + ulong flags; + struct scsi_cmnd *done_scp; - shp = scp->device->host; - boardp = ASC_BOARDP(shp); - ASC_STATS(shp, queuecommand); + shost = scp->device->host; + boardp = ASC_BOARDP(shost); + ASC_STATS(shost, queuecommand); - /* host_lock taken by mid-level prior to call but need to protect */ - /* against own ISR */ - spin_lock_irqsave(&boardp->lock, flags); + /* host_lock taken by mid-level prior to call but need to protect */ + /* against own ISR */ + spin_lock_irqsave(&boardp->lock, flags); - /* - * Block new commands while handling a reset or abort request. - */ - if (boardp->flags & ASC_HOST_IN_RESET) { - ASC_DBG1(1, - "advansys_queuecommand: scp 0x%lx blocked for reset request\n", - (ulong) scp); - scp->result = HOST_BYTE(DID_RESET); - - /* - * Add blocked requests to the board's 'done' queue. The queued - * requests will be completed at the end of the abort or reset - * handling. - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - spin_unlock_irqrestore(&boardp->lock, flags); - return 0; - } + /* + * Block new commands while handling a reset or abort request. + */ + if (boardp->flags & ASC_HOST_IN_RESET) { + ASC_DBG1(1, + "advansys_queuecommand: scp 0x%lx blocked for reset request\n", + (ulong)scp); + scp->result = HOST_BYTE(DID_RESET); - /* - * Attempt to execute any waiting commands for the board. - */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, - "advansys_queuecommand: before asc_execute_queue() waiting\n"); - asc_execute_queue(&boardp->waiting); - } + /* + * Add blocked requests to the board's 'done' queue. The queued + * requests will be completed at the end of the abort or reset + * handling. + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); + spin_unlock_irqrestore(&boardp->lock, flags); + return 0; + } - /* - * Save the function pointer to Linux mid-level 'done' function - * and attempt to execute the command. - * - * If ASC_NOERROR is returned the request has been added to the - * board's 'active' queue and will be completed by the interrupt - * handler. - * - * If ASC_BUSY is returned add the request to the board's per - * target waiting list. This is the first time the request has - * been tried. Add it to the back of the waiting list. It will be - * retried later. - * - * If an error occurred, the request will have been placed on the - * board's 'done' queue and must be completed before returning. - */ - scp->scsi_done = done; - switch (asc_execute_scsi_cmnd(scp)) { - case ASC_NOERROR: - break; - case ASC_BUSY: - asc_enqueue(&boardp->waiting, scp, ASC_BACK); - break; - case ASC_ERROR: - default: - done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); - /* Interrupts could be enabled here. */ - asc_scsi_done_list(done_scp); - break; - } - spin_unlock_irqrestore(&boardp->lock, flags); + /* + * Attempt to execute any waiting commands for the board. + */ + if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { + ASC_DBG(1, + "advansys_queuecommand: before asc_execute_queue() waiting\n"); + asc_execute_queue(&boardp->waiting); + } + + /* + * Save the function pointer to Linux mid-level 'done' function + * and attempt to execute the command. + * + * If ASC_NOERROR is returned the request has been added to the + * board's 'active' queue and will be completed by the interrupt + * handler. + * + * If ASC_BUSY is returned add the request to the board's per + * target waiting list. This is the first time the request has + * been tried. Add it to the back of the waiting list. It will be + * retried later. + * + * If an error occurred, the request will have been placed on the + * board's 'done' queue and must be completed before returning. + */ + scp->scsi_done = done; + switch (asc_execute_scsi_cmnd(scp)) { + case ASC_NOERROR: + break; + case ASC_BUSY: + asc_enqueue(&boardp->waiting, scp, ASC_BACK); + break; + case ASC_ERROR: + default: + done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); + /* Interrupts could be enabled here. */ + asc_scsi_done_list(done_scp); + break; + } + spin_unlock_irqrestore(&boardp->lock, flags); - return 0; + return 0; } /* @@ -5647,178 +4425,187 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) * sleeping is allowed and no locking other than for host structures is * required. Returns SUCCESS or FAILED. */ -static int -advansys_reset(struct scsi_cmnd *scp) +static int advansys_reset(struct scsi_cmnd *scp) { - struct Scsi_Host *shp; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ulong flags; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *tscp, *new_last_scp; - int status; - int ret = SUCCESS; - - ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong) scp); + struct Scsi_Host *shost; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + ulong flags; + struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; + struct scsi_cmnd *tscp, *new_last_scp; + int status; + int ret = SUCCESS; + + ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); #ifdef ADVANSYS_STATS - if (scp->device->host != NULL) { - ASC_STATS(scp->device->host, reset); - } + if (scp->device->host != NULL) { + ASC_STATS(scp->device->host, reset); + } #endif /* ADVANSYS_STATS */ - if ((shp = scp->device->host) == NULL) { - scp->result = HOST_BYTE(DID_ERROR); - return FAILED; - } + if ((shost = scp->device->host) == NULL) { + scp->result = HOST_BYTE(DID_ERROR); + return FAILED; + } - boardp = ASC_BOARDP(shp); + boardp = ASC_BOARDP(shost); - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", - boardp->id); - /* - * Check for re-entrancy. - */ - spin_lock_irqsave(&boardp->lock, flags); - if (boardp->flags & ASC_HOST_IN_RESET) { - spin_unlock_irqrestore(&boardp->lock, flags); - return FAILED; - } - boardp->flags |= ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); - - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - - /* - * Reset the chip and SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); - status = AscInitAsc1000Driver(asc_dvc_varp); - - /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ - if (asc_dvc_varp->err_code) { - ASC_PRINT2( - "advansys_reset: board %d: SCSI bus reset error: 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ret = FAILED; - } else if (status) { - ASC_PRINT2( - "advansys_reset: board %d: SCSI bus reset warning: 0x%x\n", - boardp->id, status); - } else { - ASC_PRINT1( - "advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - } - - ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); + ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", + boardp->id); + /* + * Check for re-entrancy. + */ spin_lock_irqsave(&boardp->lock, flags); + if (boardp->flags & ASC_HOST_IN_RESET) { + spin_unlock_irqrestore(&boardp->lock, flags); + return FAILED; + } + boardp->flags |= ASC_HOST_IN_RESET; + spin_unlock_irqrestore(&boardp->lock, flags); - } else { - /* - * Wide Board - * - * If the suggest reset bus flags are set, then reset the bus. - * Otherwise only reset the device. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - - /* - * Reset the target's SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); - switch (AdvResetChipAndSB(adv_dvc_varp)) { - case ASC_TRUE: - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - break; - case ASC_FALSE: - default: - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset error.\n", - boardp->id); - ret = FAILED; - break; - } - spin_lock_irqsave(&boardp->lock, flags); - (void) AdvISR(adv_dvc_varp); - } - /* Board lock is held. */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * Narrow Board + */ + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - /* - * Dequeue all board 'done' requests. A pointer to the last request - * is returned in 'last_scp'. - */ - done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); + /* + * Reset the chip and SCSI bus. + */ + ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); + status = AscInitAsc1000Driver(asc_dvc_varp); + + /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ + if (asc_dvc_varp->err_code) { + ASC_PRINT2 + ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ret = FAILED; + } else if (status) { + ASC_PRINT2 + ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n", + boardp->id, status); + } else { + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset successful.\n", + boardp->id); + } + + ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); + spin_lock_irqsave(&boardp->lock, flags); - /* - * Dequeue all board 'active' requests for all devices and set - * the request status to DID_RESET. A pointer to the last request - * is returned in 'last_scp'. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->active, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } + } else { + /* + * Wide Board + * + * If the suggest reset bus flags are set, then reset the bus. + * Otherwise only reset the device. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - /* - * Dequeue all 'waiting' requests and set the request status - * to DID_RESET. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->waiting, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } + /* + * Reset the target's SCSI bus. + */ + ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); + switch (AdvResetChipAndSB(adv_dvc_varp)) { + case ASC_TRUE: + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset successful.\n", + boardp->id); + break; + case ASC_FALSE: + default: + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset error.\n", + boardp->id); + ret = FAILED; + break; + } + spin_lock_irqsave(&boardp->lock, flags); + (void)AdvISR(adv_dvc_varp); + } + /* Board lock is held. */ + + /* + * Dequeue all board 'done' requests. A pointer to the last request + * is returned in 'last_scp'. + */ + done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); + + /* + * Dequeue all board 'active' requests for all devices and set + * the request status to DID_RESET. A pointer to the last request + * is returned in 'last_scp'. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL); + for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + } else { + /* Append to 'done_scp' at the end with 'last_scp'. */ + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp->active, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + for (tscp = REQPNEXT(last_scp); tscp; + tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + last_scp = new_last_scp; + } + } - /* Save the time of the most recently completed reset. */ - boardp->last_reset = jiffies; + /* + * Dequeue all 'waiting' requests and set the request status + * to DID_RESET. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL); + for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + } else { + /* Append to 'done_scp' at the end with 'last_scp'. */ + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp->waiting, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + for (tscp = REQPNEXT(last_scp); tscp; + tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + last_scp = new_last_scp; + } + } - /* Clear reset flag. */ - boardp->flags &= ~ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); + /* Save the time of the most recently completed reset. */ + boardp->last_reset = jiffies; - /* - * Complete all the 'done_scp' requests. - */ - if (done_scp != NULL) { - asc_scsi_done_list(done_scp); - } + /* Clear reset flag. */ + boardp->flags &= ~ASC_HOST_IN_RESET; + spin_unlock_irqrestore(&boardp->lock, flags); - ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + /* + * Complete all the 'done_scp' requests. + */ + if (done_scp != NULL) { + asc_scsi_done_list(done_scp); + } - return ret; + ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + + return ret; } /* @@ -5834,71 +4621,70 @@ advansys_reset(struct scsi_cmnd *scp) */ static int advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int ip[]) + sector_t capacity, int ip[]) { - asc_board_t *boardp; - - ASC_DBG(1, "advansys_biosparam: begin\n"); - ASC_STATS(sdev->host, biosparam); - boardp = ASC_BOARDP(sdev->host); - if (ASC_NARROW_BOARD(boardp)) { - if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & - ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } else { - if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & - BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } - ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); - ASC_DBG(1, "advansys_biosparam: end\n"); - return 0; + asc_board_t *boardp; + + ASC_DBG(1, "advansys_biosparam: begin\n"); + ASC_STATS(sdev->host, biosparam); + boardp = ASC_BOARDP(sdev->host); + if (ASC_NARROW_BOARD(boardp)) { + if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & + ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } + } else { + if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & + BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } + } + ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); + ASC_DBG(1, "advansys_biosparam: end\n"); + return 0; } -/* - * --- Loadable Driver Support - */ +static int __init advansys_detect(struct scsi_host_template *tpnt); +static int advansys_release(struct Scsi_Host *shp); static struct scsi_host_template driver_template = { - .proc_name = "advansys", + .proc_name = "advansys", #ifdef CONFIG_PROC_FS - .proc_info = advansys_proc_info, + .proc_info = advansys_proc_info, #endif - .name = "advansys", - .detect = advansys_detect, - .release = advansys_release, - .info = advansys_info, - .queuecommand = advansys_queuecommand, - .eh_bus_reset_handler = advansys_reset, - .bios_param = advansys_biosparam, - .slave_configure = advansys_slave_configure, - /* - * Because the driver may control an ISA adapter 'unchecked_isa_dma' - * must be set. The flag will be cleared in advansys_detect for non-ISA - * adapters. Refer to the comment in scsi_module.c for more information. - */ - .unchecked_isa_dma = 1, - /* - * All adapters controlled by this driver are capable of large - * scatter-gather lists. According to the mid-level SCSI documentation - * this obviates any performance gain provided by setting - * 'use_clustering'. But empirically while CPU utilization is increased - * by enabling clustering, I/O throughput increases as well. - */ - .use_clustering = ENABLE_CLUSTERING, + .name = "advansys", + .detect = advansys_detect, + .release = advansys_release, + .info = advansys_info, + .queuecommand = advansys_queuecommand, + .eh_bus_reset_handler = advansys_reset, + .bios_param = advansys_biosparam, + .slave_configure = advansys_slave_configure, + /* + * Because the driver may control an ISA adapter 'unchecked_isa_dma' + * must be set. The flag will be cleared in advansys_detect for non-ISA + * adapters. Refer to the comment in scsi_module.c for more information. + */ + .unchecked_isa_dma = 1, + /* + * All adapters controlled by this driver are capable of large + * scatter-gather lists. According to the mid-level SCSI documentation + * this obviates any performance gain provided by setting + * 'use_clustering'. But empirically while CPU utilization is increased + * by enabling clustering, I/O throughput increases as well. + */ + .use_clustering = ENABLE_CLUSTERING, }; -#include "scsi_module.c" +#include "scsi_module.c" /* * --- Miscellaneous Driver Functions @@ -5913,130 +4699,138 @@ static struct scsi_host_template driver_template = { * to the AdvanSys driver which is for a device sharing an interrupt with * an AdvanSys adapter. */ -STATIC irqreturn_t -advansys_interrupt(int irq, void *dev_id) +static irqreturn_t advansys_interrupt(int irq, void *dev_id) { - ulong flags; - int i; - asc_board_t *boardp; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *new_last_scp; - struct Scsi_Host *shp; - - ASC_DBG(1, "advansys_interrupt: begin\n"); + ulong flags; + int i; + asc_board_t *boardp; + struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; + struct scsi_cmnd *new_last_scp; + struct Scsi_Host *shost; + + ASC_DBG(1, "advansys_interrupt: begin\n"); + + /* + * Check for interrupts on all boards. + * AscISR() will call asc_isr_callback(). + */ + for (i = 0; i < asc_board_count; i++) { + shost = asc_host[i]; + boardp = ASC_BOARDP(shost); + ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", + i, (ulong)boardp); + spin_lock_irqsave(&boardp->lock, flags); + if (ASC_NARROW_BOARD(boardp)) { + /* + * Narrow Board + */ + if (AscIsIntPending(shost->io_port)) { + ASC_STATS(shost, interrupt); + ASC_DBG(1, + "advansys_interrupt: before AscISR()\n"); + AscISR(&boardp->dvc_var.asc_dvc_var); + } + } else { + /* + * Wide Board + */ + ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); + if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { + ASC_STATS(shost, interrupt); + } + } - /* - * Check for interrupts on all boards. - * AscISR() will call asc_isr_callback(). - */ - for (i = 0; i < asc_board_count; i++) { - shp = asc_host[i]; - boardp = ASC_BOARDP(shp); - ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", - i, (ulong) boardp); - spin_lock_irqsave(&boardp->lock, flags); - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - if (AscIsIntPending(shp->io_port)) { - ASC_STATS(shp, interrupt); - ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); - AscISR(&boardp->dvc_var.asc_dvc_var); - } - } else { - /* - * Wide Board - */ - ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); - if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { - ASC_STATS(shp, interrupt); - } - } - - /* - * Start waiting requests and create a list of completed requests. - * - * If a reset request is being performed for the board, the reset - * handler will complete pending requests after it has completed. - */ - if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { - ASC_DBG2(1, "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", - (ulong) done_scp, (ulong) last_scp); - - /* Start any waiting commands for the board. */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); - asc_execute_queue(&boardp->waiting); - } - - /* - * Add to the list of requests that must be completed. - * - * 'done_scp' will always be NULL on the first iteration - * of this loop. 'last_scp' is set at the same time as - * 'done_scp'. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->done, &last_scp, - ASC_TID_ALL); - } else { - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->done, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - last_scp = new_last_scp; - } - } - } - spin_unlock_irqrestore(&boardp->lock, flags); - } + /* + * Start waiting requests and create a list of completed requests. + * + * If a reset request is being performed for the board, the reset + * handler will complete pending requests after it has completed. + */ + if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { + ASC_DBG2(1, + "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", + (ulong)done_scp, (ulong)last_scp); + + /* Start any waiting commands for the board. */ + if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { + ASC_DBG(1, + "advansys_interrupt: before asc_execute_queue()\n"); + asc_execute_queue(&boardp->waiting); + } + + /* + * Add to the list of requests that must be completed. + * + * 'done_scp' will always be NULL on the first iteration + * of this loop. 'last_scp' is set at the same time as + * 'done_scp'. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->done, &last_scp, + ASC_TID_ALL); + } else { + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp-> + done, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + last_scp = new_last_scp; + } + } + } + spin_unlock_irqrestore(&boardp->lock, flags); + } - /* - * If interrupts were enabled on entry, then they - * are now enabled here. - * - * Complete all requests on the done list. - */ + /* + * If interrupts were enabled on entry, then they + * are now enabled here. + * + * Complete all requests on the done list. + */ - asc_scsi_done_list(done_scp); + asc_scsi_done_list(done_scp); - ASC_DBG(1, "advansys_interrupt: end\n"); - return IRQ_HANDLED; + ASC_DBG(1, "advansys_interrupt: end\n"); + return IRQ_HANDLED; } /* * Set the number of commands to queue per device for the * specified host adapter. */ -STATIC int -advansys_slave_configure(struct scsi_device *device) +static int advansys_slave_configure(struct scsi_device *device) { - asc_board_t *boardp; + asc_board_t *boardp; - boardp = ASC_BOARDP(device->host); - boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; - /* - * Save a pointer to the device and set its initial/maximum - * queue depth. Only save the pointer for a lun0 dev though. - */ - if(device->lun == 0) - boardp->device[device->id] = device; - if(device->tagged_supported) { - if (ASC_NARROW_BOARD(boardp)) { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id]); - } else { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.adv_dvc_var.max_dvc_qng); - } - } else { - scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); - } - ASC_DBG4(1, "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", - (ulong) device, (ulong) boardp, device->id, device->queue_depth); - return 0; + boardp = ASC_BOARDP(device->host); + boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; + /* + * Save a pointer to the device and set its initial/maximum + * queue depth. Only save the pointer for a lun0 dev though. + */ + if (device->lun == 0) + boardp->device[device->id] = device; + if (device->tagged_supported) { + if (ASC_NARROW_BOARD(boardp)) { + scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, + boardp->dvc_var.asc_dvc_var. + max_dvc_qng[device->id]); + } else { + scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, + boardp->dvc_var.adv_dvc_var. + max_dvc_qng); + } + } else { + scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); + } + ASC_DBG4(1, + "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", + (ulong)device, (ulong)boardp, device->id, device->queue_depth); + return 0; } /* @@ -6045,43 +4839,44 @@ advansys_slave_configure(struct scsi_device *device) * * Interrupts can be enabled on entry. */ -STATIC void -asc_scsi_done_list(struct scsi_cmnd *scp) +static void asc_scsi_done_list(struct scsi_cmnd *scp) { - struct scsi_cmnd *tscp; + struct scsi_cmnd *tscp; - ASC_DBG(2, "asc_scsi_done_list: begin\n"); - while (scp != NULL) { - asc_board_t *boardp; - struct device *dev; + ASC_DBG(2, "asc_scsi_done_list: begin\n"); + while (scp != NULL) { + asc_board_t *boardp; + struct device *dev; - ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp); - tscp = REQPNEXT(scp); - scp->host_scribble = NULL; + ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); + tscp = REQPNEXT(scp); + scp->host_scribble = NULL; - boardp = ASC_BOARDP(scp->device->host); + boardp = ASC_BOARDP(scp->device->host); - if (ASC_NARROW_BOARD(boardp)) - dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - else - dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + if (ASC_NARROW_BOARD(boardp)) + dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + else + dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - if (scp->use_sg) - dma_unmap_sg(dev, (struct scatterlist *)scp->request_buffer, - scp->use_sg, scp->sc_data_direction); - else if (scp->request_bufflen) - dma_unmap_single(dev, scp->SCp.dma_handle, - scp->request_bufflen, scp->sc_data_direction); + if (scp->use_sg) + dma_unmap_sg(dev, + (struct scatterlist *)scp->request_buffer, + scp->use_sg, scp->sc_data_direction); + else if (scp->request_bufflen) + dma_unmap_single(dev, scp->SCp.dma_handle, + scp->request_bufflen, + scp->sc_data_direction); - ASC_STATS(scp->device->host, done); - ASC_ASSERT(scp->scsi_done != NULL); + ASC_STATS(scp->device->host, done); + ASC_ASSERT(scp->scsi_done != NULL); - scp->scsi_done(scp); + scp->scsi_done(scp); - scp = tscp; - } - ASC_DBG(2, "asc_scsi_done_list: done\n"); - return; + scp = tscp; + } + ASC_DBG(2, "asc_scsi_done_list: done\n"); + return; } /* @@ -6130,168 +4925,170 @@ asc_scsi_done_list(struct scsi_cmnd *scp) * If ASC_BUSY is returned the request will be enqueued by the * caller on the target's waiting queue and re-tried later. */ -STATIC int -asc_execute_scsi_cmnd(struct scsi_cmnd *scp) +static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) { - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ADV_SCSI_REQ_Q *adv_scsiqp; - struct scsi_device *device; - int ret; - - ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", - (ulong) scp, (ulong) scp->scsi_done); - - boardp = ASC_BOARDP(scp->device->host); - device = boardp->device[scp->device->id]; - - if (ASC_NARROW_BOARD(boardp)) { - /* - * Build and execute Narrow Board request. - */ - - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - - /* - * Build Asc Library request structure using the - * global structures 'asc_scsi_req' and 'asc_sg_head'. - * - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - * - * asc_build_req() can not return ASC_BUSY. - */ - if (asc_build_req(boardp, scp) == ASC_ERROR) { - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; - } - - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); - break; - case ASC_ERROR: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - default: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - } - } else { - /* - * Build and execute Wide Board request. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - - /* - * Build and get a pointer to an Adv Library request structure. - * - * If the request is successfully built then send it below, - * otherwise return with an error. - */ - switch (adv_build_req(boardp, scp, &adv_scsiqp)) { - case ASC_NOERROR: - ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); - break; - case ASC_BUSY: - ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); - /* - * If busy is returned the request has not been enqueued. - * It will be enqueued by the caller on the target's waiting - * queue and retried later. - * - * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg' - * count wide board busy conditions. They are updated in - * adv_build_req and adv_get_sglist, respectively. - */ - return ASC_BUSY; - case ASC_ERROR: - /* - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - */ - default: - ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; - } - - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); - break; - case ASC_ERROR: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - default: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - } - } + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + ADV_SCSI_REQ_Q *adv_scsiqp; + struct scsi_device *device; + int ret; + + ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", + (ulong)scp, (ulong)scp->scsi_done); + + boardp = ASC_BOARDP(scp->device->host); + device = boardp->device[scp->device->id]; + + if (ASC_NARROW_BOARD(boardp)) { + /* + * Build and execute Narrow Board request. + */ + + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + + /* + * Build Asc Library request structure using the + * global structures 'asc_scsi_req' and 'asc_sg_head'. + * + * If an error is returned, then the request has been + * queued on the board done queue. It will be completed + * by the caller. + * + * asc_build_req() can not return ASC_BUSY. + */ + if (asc_build_req(boardp, scp) == ASC_ERROR) { + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; + } - ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); - return ret; + /* + * Execute the command. If there is no error, add the command + * to the active queue. + */ + switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { + case ASC_NOERROR: + ASC_STATS(scp->device->host, exe_noerror); + /* + * Increment monotonically increasing per device successful + * request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->device->id]++; + asc_enqueue(&boardp->active, scp, ASC_BACK); + ASC_DBG(1, + "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); + break; + case ASC_BUSY: + /* + * Caller will enqueue request on the target's waiting queue + * and retry later. + */ + ASC_STATS(scp->device->host, exe_busy); + break; + case ASC_ERROR: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_error); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + default: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_unknown); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + } + } else { + /* + * Build and execute Wide Board request. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + + /* + * Build and get a pointer to an Adv Library request structure. + * + * If the request is successfully built then send it below, + * otherwise return with an error. + */ + switch (adv_build_req(boardp, scp, &adv_scsiqp)) { + case ASC_NOERROR: + ASC_DBG(3, + "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); + break; + case ASC_BUSY: + ASC_DBG(1, + "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); + /* + * If busy is returned the request has not been enqueued. + * It will be enqueued by the caller on the target's waiting + * queue and retried later. + * + * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg' + * count wide board busy conditions. They are updated in + * adv_build_req and adv_get_sglist, respectively. + */ + return ASC_BUSY; + case ASC_ERROR: + /* + * If an error is returned, then the request has been + * queued on the board done queue. It will be completed + * by the caller. + */ + default: + ASC_DBG(1, + "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; + } + + /* + * Execute the command. If there is no error, add the command + * to the active queue. + */ + switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { + case ASC_NOERROR: + ASC_STATS(scp->device->host, exe_noerror); + /* + * Increment monotonically increasing per device successful + * request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->device->id]++; + asc_enqueue(&boardp->active, scp, ASC_BACK); + ASC_DBG(1, + "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); + break; + case ASC_BUSY: + /* + * Caller will enqueue request on the target's waiting queue + * and retry later. + */ + ASC_STATS(scp->device->host, exe_busy); + break; + case ASC_ERROR: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_error); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + default: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_unknown); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + } + } + + ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); + return ret; } /* @@ -6303,131 +5100,140 @@ asc_execute_scsi_cmnd(struct scsi_cmnd *scp) * If an error occurs, then queue the request on the board done * queue and return ASC_ERROR. */ -STATIC int -asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) +static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) { - struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - - /* - * Mutually exclusive access is required to 'asc_scsi_q' and - * 'asc_sg_head' until after the request is started. - */ - memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); - - /* - * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. - */ - asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); - - /* - * Build the ASC_SCSI_Q request. - * - * For narrow boards a CDB length maximum of 12 bytes - * is supported. - */ - if (scp->cmd_len > ASC_MAX_CDB_LEN) { - ASC_PRINT3( -"asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - asc_scsi_q.cdbptr = &scp->cmnd[0]; - asc_scsi_q.q2.cdb_len = scp->cmd_len; - asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); - asc_scsi_q.q1.target_lun = scp->device->lun; - asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); - asc_scsi_q.q1.sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); + struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + + /* + * Mutually exclusive access is required to 'asc_scsi_q' and + * 'asc_sg_head' until after the request is started. + */ + memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); + + /* + * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. + */ + asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); + + /* + * Build the ASC_SCSI_Q request. + * + * For narrow boards a CDB length maximum of 12 bytes + * is supported. + */ + if (scp->cmd_len > ASC_MAX_CDB_LEN) { + ASC_PRINT3 + ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n", + boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + asc_scsi_q.cdbptr = &scp->cmnd[0]; + asc_scsi_q.q2.cdb_len = scp->cmd_len; + asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); + asc_scsi_q.q1.target_lun = scp->device->lun; + asc_scsi_q.q2.target_ix = + ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); + asc_scsi_q.q1.sense_addr = + cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); + + /* + * If there are any outstanding requests for the current target, + * then every 255th request send an ORDERED request. This heuristic + * tries to retain the benefit of request sorting while preventing + * request starvation. 255 is the max number of tags or pending commands + * a device may have outstanding. + * + * The request count is incremented below for every successfully + * started request. + * + */ + if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && + (boardp->reqcnt[scp->device->id] % 255) == 0) { + asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; + } else { + asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; + } - /* - * If there are any outstanding requests for the current target, - * then every 255th request send an ORDERED request. This heuristic - * tries to retain the benefit of request sorting while preventing - * request starvation. 255 is the max number of tags or pending commands - * a device may have outstanding. - * - * The request count is incremented below for every successfully - * started request. - * - */ - if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && - (boardp->reqcnt[scp->device->id] % 255) == 0) { - asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; - } else { - asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; - } + /* + * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ + if (scp->use_sg == 0) { + /* + * CDB request of single contiguous buffer. + */ + ASC_STATS(scp->device->host, cont_cnt); + scp->SCp.dma_handle = scp->request_bufflen ? + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction) : 0; + asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); + asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); + ASC_STATS_ADD(scp->device->host, cont_xfer, + ASC_CEILING(scp->request_bufflen, 512)); + asc_scsi_q.q1.sg_queue_cnt = 0; + asc_scsi_q.sg_head = NULL; + } else { + /* + * CDB scatter-gather request list. + */ + int sgcnt; + int use_sg; + struct scatterlist *slp; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > scp->device->host->sg_tablesize) { + ASC_PRINT3 + ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", + boardp->id, use_sg, + scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, + scp->sc_data_direction); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + + ASC_STATS(scp->device->host, sg_cnt); - /* - * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - ASC_STATS(scp->device->host, cont_cnt); - scp->SCp.dma_handle = scp->request_bufflen ? - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, scp->sc_data_direction) : 0; - asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); - asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - asc_scsi_q.q1.sg_queue_cnt = 0; - asc_scsi_q.sg_head = NULL; - } else { - /* - * CDB scatter-gather request list. - */ - int sgcnt; - int use_sg; - struct scatterlist *slp; + /* + * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q + * structure to point to it. + */ + memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); + + asc_scsi_q.q1.cntl |= QC_SG_HEAD; + asc_scsi_q.sg_head = &asc_sg_head; + asc_scsi_q.q1.data_cnt = 0; + asc_scsi_q.q1.data_addr = 0; + /* This is a byte value, otherwise it would need to be swapped. */ + asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; + ASC_STATS_ADD(scp->device->host, sg_elem, + asc_sg_head.entry_cnt); - slp = (struct scatterlist *)scp->request_buffer; - use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > scp->device->host->sg_tablesize) { - ASC_PRINT3( -"asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", - boardp->id, use_sg, scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - - ASC_STATS(scp->device->host, sg_cnt); - - /* - * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q - * structure to point to it. - */ - memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); - - asc_scsi_q.q1.cntl |= QC_SG_HEAD; - asc_scsi_q.sg_head = &asc_sg_head; - asc_scsi_q.q1.data_cnt = 0; - asc_scsi_q.q1.data_addr = 0; - /* This is a byte value, otherwise it would need to be swapped. */ - asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; - ASC_STATS_ADD(scp->device->host, sg_elem, asc_sg_head.entry_cnt); - - /* - * Convert scatter-gather list into ASC_SG_HEAD list. - */ - for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { - asc_sg_head.sg_list[sgcnt].addr = cpu_to_le32(sg_dma_address(slp)); - asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); - } - } + /* + * Convert scatter-gather list into ASC_SG_HEAD list. + */ + for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { + asc_sg_head.sg_list[sgcnt].addr = + cpu_to_le32(sg_dma_address(slp)); + asc_sg_head.sg_list[sgcnt].bytes = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, + ASC_CEILING(sg_dma_len(slp), 512)); + } + } - ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - return ASC_NOERROR; + return ASC_NOERROR; } /* @@ -6440,162 +5246,168 @@ asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) * microcode for DMA addresses or math operations are byte swapped * to little-endian order. */ -STATIC int +static int adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, - ADV_SCSI_REQ_Q **adv_scsiqpp) + ADV_SCSI_REQ_Q **adv_scsiqpp) { - adv_req_t *reqp; - ADV_SCSI_REQ_Q *scsiqp; - int i; - int ret; - struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - - /* - * Allocate an adv_req_t structure from the board to execute - * the command. - */ - if (boardp->adv_reqp == NULL) { - ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); - ASC_STATS(scp->device->host, adv_build_noreq); - return ASC_BUSY; - } else { - reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp->next_reqp; - reqp->next_reqp = NULL; - } - - /* - * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. - */ - scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); - - /* - * Initialize the structure. - */ - scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; - - /* - * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. - */ - scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); - - /* - * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. - */ - reqp->cmndp = scp; + adv_req_t *reqp; + ADV_SCSI_REQ_Q *scsiqp; + int i; + int ret; + struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + + /* + * Allocate an adv_req_t structure from the board to execute + * the command. + */ + if (boardp->adv_reqp == NULL) { + ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); + ASC_STATS(scp->device->host, adv_build_noreq); + return ASC_BUSY; + } else { + reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp->next_reqp; + reqp->next_reqp = NULL; + } - /* - * Build the ADV_SCSI_REQ_Q request. - */ + /* + * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. + */ + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + + /* + * Initialize the structure. + */ + scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; + + /* + * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. + */ + scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); + + /* + * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. + */ + reqp->cmndp = scp; + + /* + * Build the ADV_SCSI_REQ_Q request. + */ + + /* + * Set CDB length and copy it to the request structure. + * For wide boards a CDB length maximum of 16 bytes + * is supported. + */ + if (scp->cmd_len > ADV_MAX_CDB_LEN) { + ASC_PRINT3 + ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", + boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + scsiqp->cdb_len = scp->cmd_len; + /* Copy first 12 CDB bytes to cdb[]. */ + for (i = 0; i < scp->cmd_len && i < 12; i++) { + scsiqp->cdb[i] = scp->cmnd[i]; + } + /* Copy last 4 CDB bytes, if present, to cdb16[]. */ + for (; i < scp->cmd_len; i++) { + scsiqp->cdb16[i - 12] = scp->cmnd[i]; + } - /* - * Set CDB length and copy it to the request structure. - * For wide boards a CDB length maximum of 16 bytes - * is supported. - */ - if (scp->cmd_len > ADV_MAX_CDB_LEN) { - ASC_PRINT3( -"adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - scsiqp->cdb_len = scp->cmd_len; - /* Copy first 12 CDB bytes to cdb[]. */ - for (i = 0; i < scp->cmd_len && i < 12; i++) { - scsiqp->cdb[i] = scp->cmnd[i]; - } - /* Copy last 4 CDB bytes, if present, to cdb16[]. */ - for (; i < scp->cmd_len; i++) { - scsiqp->cdb16[i - 12] = scp->cmnd[i]; - } + scsiqp->target_id = scp->device->id; + scsiqp->target_lun = scp->device->lun; - scsiqp->target_id = scp->device->id; - scsiqp->target_lun = scp->device->lun; + scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + scsiqp->sense_len = sizeof(scp->sense_buffer); - scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - scsiqp->sense_len = sizeof(scp->sense_buffer); + /* + * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ - /* - * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - scsiqp->vdata_addr = scp->request_buffer; - scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); - - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - reqp->sgblkp = NULL; scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - if (scp->request_bufflen) { - scsiqp->vdata_addr = scp->request_buffer; - scp->SCp.dma_handle = - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, scp->sc_data_direction); - } else { - scsiqp->vdata_addr = NULL; - scp->SCp.dma_handle = 0; - } - scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); - scsiqp->sg_list_ptr = NULL; - scsiqp->sg_real_addr = 0; - ASC_STATS(scp->device->host, cont_cnt); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - } else { - /* - * CDB scatter-gather request list. - */ - struct scatterlist *slp; - int use_sg; + scsiqp->vdata_addr = scp->request_buffer; + scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); - slp = (struct scatterlist *)scp->request_buffer; - use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > ADV_MAX_SG_LIST) { - ASC_PRINT3( -"adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", - boardp->id, use_sg, scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - - /* - * Free the 'adv_req_t' structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; - - return ASC_ERROR; - } - - if ((ret = adv_get_sglist(boardp, reqp, scp, use_sg)) != ADV_SUCCESS) { - /* - * Free the adv_req_t structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; - - return ret; - } - - ASC_STATS(scp->device->host, sg_cnt); - ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); - } + if (scp->use_sg == 0) { + /* + * CDB request of single contiguous buffer. + */ + reqp->sgblkp = NULL; + scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); + if (scp->request_bufflen) { + scsiqp->vdata_addr = scp->request_buffer; + scp->SCp.dma_handle = + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction); + } else { + scsiqp->vdata_addr = NULL; + scp->SCp.dma_handle = 0; + } + scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); + scsiqp->sg_list_ptr = NULL; + scsiqp->sg_real_addr = 0; + ASC_STATS(scp->device->host, cont_cnt); + ASC_STATS_ADD(scp->device->host, cont_xfer, + ASC_CEILING(scp->request_bufflen, 512)); + } else { + /* + * CDB scatter-gather request list. + */ + struct scatterlist *slp; + int use_sg; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > ADV_MAX_SG_LIST) { + ASC_PRINT3 + ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", + boardp->id, use_sg, + scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, + scp->sc_data_direction); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + + /* + * Free the 'adv_req_t' structure by adding it back to the + * board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ASC_ERROR; + } + + if ((ret = + adv_get_sglist(boardp, reqp, scp, + use_sg)) != ADV_SUCCESS) { + /* + * Free the adv_req_t structure by adding it back to the + * board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ret; + } + + ASC_STATS(scp->device->host, sg_cnt); + ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); + } - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - *adv_scsiqpp = scsiqp; + *adv_scsiqpp = scsiqp; - return ASC_NOERROR; + return ASC_NOERROR; } /* @@ -6610,108 +5422,109 @@ adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, * ADV_SUCCESS(1) - SG List successfully created * ADV_ERROR(-1) - SG List creation failed */ -STATIC int -adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, int use_sg) +static int +adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, + int use_sg) { - adv_sgblk_t *sgblkp; - ADV_SCSI_REQ_Q *scsiqp; - struct scatterlist *slp; - int sg_elem_cnt; - ADV_SG_BLOCK *sg_block, *prev_sg_block; - ADV_PADDR sg_block_paddr; - int i; - - scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); - slp = (struct scatterlist *) scp->request_buffer; - sg_elem_cnt = use_sg; - prev_sg_block = NULL; - reqp->sgblkp = NULL; - - do - { - /* - * Allocate a 'adv_sgblk_t' structure from the board free - * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK - * (15) scatter-gather elements. - */ - if ((sgblkp = boardp->adv_sgblkp) == NULL) { - ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); - ASC_STATS(scp->device->host, adv_build_nosg); - - /* - * Allocation failed. Free 'adv_sgblk_t' structures already - * allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) - { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; - } - return ASC_BUSY; - } else { - /* Complete 'adv_sgblk_t' board allocation. */ - boardp->adv_sgblkp = sgblkp->next_sgblkp; - sgblkp->next_sgblkp = NULL; - - /* - * Get 8 byte aligned virtual and physical addresses for - * the allocated ADV_SG_BLOCK structure. - */ - sg_block = (ADV_SG_BLOCK *) ADV_8BALIGN(&sgblkp->sg_block); - sg_block_paddr = virt_to_bus(sg_block); - - /* - * Check if this is the first 'adv_sgblk_t' for the request. - */ - if (reqp->sgblkp == NULL) - { - /* Request's first scatter-gather block. */ - reqp->sgblkp = sgblkp; - - /* - * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical - * address pointers. - */ - scsiqp->sg_list_ptr = sg_block; - scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr); - } else - { - /* Request's second or later scatter-gather block. */ - sgblkp->next_sgblkp = reqp->sgblkp; - reqp->sgblkp = sgblkp; - - /* - * Point the previous ADV_SG_BLOCK structure to - * the newly allocated ADV_SG_BLOCK structure. - */ - ASC_ASSERT(prev_sg_block != NULL); - prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr); - } - } - - for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) - { - sg_block->sg_list[i].sg_addr = cpu_to_le32(sg_dma_address(slp)); - sg_block->sg_list[i].sg_count = cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); - - if (--sg_elem_cnt == 0) - { /* Last ADV_SG_BLOCK and scatter-gather entry. */ - sg_block->sg_cnt = i + 1; - sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ - return ADV_SUCCESS; - } - slp++; - } - sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; - prev_sg_block = sg_block; - } - while (1); - /* NOTREACHED */ + adv_sgblk_t *sgblkp; + ADV_SCSI_REQ_Q *scsiqp; + struct scatterlist *slp; + int sg_elem_cnt; + ADV_SG_BLOCK *sg_block, *prev_sg_block; + ADV_PADDR sg_block_paddr; + int i; + + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + slp = (struct scatterlist *)scp->request_buffer; + sg_elem_cnt = use_sg; + prev_sg_block = NULL; + reqp->sgblkp = NULL; + + do { + /* + * Allocate a 'adv_sgblk_t' structure from the board free + * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK + * (15) scatter-gather elements. + */ + if ((sgblkp = boardp->adv_sgblkp) == NULL) { + ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); + ASC_STATS(scp->device->host, adv_build_nosg); + + /* + * Allocation failed. Free 'adv_sgblk_t' structures already + * allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; + } + return ASC_BUSY; + } else { + /* Complete 'adv_sgblk_t' board allocation. */ + boardp->adv_sgblkp = sgblkp->next_sgblkp; + sgblkp->next_sgblkp = NULL; + + /* + * Get 8 byte aligned virtual and physical addresses for + * the allocated ADV_SG_BLOCK structure. + */ + sg_block = + (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); + sg_block_paddr = virt_to_bus(sg_block); + + /* + * Check if this is the first 'adv_sgblk_t' for the request. + */ + if (reqp->sgblkp == NULL) { + /* Request's first scatter-gather block. */ + reqp->sgblkp = sgblkp; + + /* + * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical + * address pointers. + */ + scsiqp->sg_list_ptr = sg_block; + scsiqp->sg_real_addr = + cpu_to_le32(sg_block_paddr); + } else { + /* Request's second or later scatter-gather block. */ + sgblkp->next_sgblkp = reqp->sgblkp; + reqp->sgblkp = sgblkp; + + /* + * Point the previous ADV_SG_BLOCK structure to + * the newly allocated ADV_SG_BLOCK structure. + */ + ASC_ASSERT(prev_sg_block != NULL); + prev_sg_block->sg_ptr = + cpu_to_le32(sg_block_paddr); + } + } + + for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { + sg_block->sg_list[i].sg_addr = + cpu_to_le32(sg_dma_address(slp)); + sg_block->sg_list[i].sg_count = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, + ASC_CEILING(sg_dma_len(slp), 512)); + + if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ + sg_block->sg_cnt = i + 1; + sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ + return ADV_SUCCESS; + } + slp++; + } + sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; + prev_sg_block = sg_block; + } + while (1); + /* NOTREACHED */ } /* @@ -6719,165 +5532,171 @@ adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, int * * Interrupt callback function for the Narrow SCSI Asc Library. */ -STATIC void -asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) +static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) { - asc_board_t *boardp; - struct scsi_cmnd *scp; - struct Scsi_Host *shp; - int i; - - ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", - (ulong) asc_dvc_varp, (ulong) qdonep); - ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); + asc_board_t *boardp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + int i; + + ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", + (ulong)asc_dvc_varp, (ulong)qdonep); + ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); + + /* + * Get the struct scsi_cmnd structure and Scsi_Host structure for the + * command that has been completed. + */ + scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); + ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp); + + if (scp == NULL) { + ASC_PRINT("asc_isr_callback: scp is NULL\n"); + return; + } + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + /* + * If the request's host pointer is not valid, display a + * message and return. + */ + shost = scp->device->host; + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i] == shost) { + break; + } + } + if (i == asc_board_count) { + ASC_PRINT2 + ("asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", + (ulong)scp, (ulong)shost); + return; + } - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - */ - scp = (struct scsi_cmnd *) ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); - ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong) scp); - - if (scp == NULL) { - ASC_PRINT("asc_isr_callback: scp is NULL\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + ASC_STATS(shost, callback); + ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); + + /* + * If the request isn't found on the active queue, it may + * have been removed to handle a reset request. + * Display a message and return. + */ + boardp = ASC_BOARDP(shost); + ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); + if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { + ASC_PRINT2 + ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n", + boardp->id, (ulong)scp); + return; + } - /* - * If the request's host pointer is not valid, display a - * message and return. - */ - shp = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shp) { - break; - } - } - if (i == asc_board_count) { - ASC_PRINT2( - "asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong) scp, (ulong) shp); - return; - } + /* + * 'qdonep' contains the command's ending status. + */ + switch (qdonep->d3.done_stat) { + case QD_NO_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); + scp->result = 0; - ASC_STATS(shp, callback); - ASC_DBG1(1, "asc_isr_callback: shp 0x%lx\n", (ulong) shp); + /* + * If an INQUIRY command completed successfully, then call + * the AscInquiryHandling() function to set-up the device. + */ + if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && + (scp->request_bufflen - qdonep->remain_bytes) >= 8) { + AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, + (ASC_SCSI_INQUIRY *)scp-> + request_buffer); + } - /* - * If the request isn't found on the active queue, it may - * have been removed to handle a reset request. - * Display a message and return. - */ - boardp = ASC_BOARDP(shp); - ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2( - "asc_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong) scp); - return; - } + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * then return the number of underrun bytes. + */ + if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && + qdonep->remain_bytes <= scp->request_bufflen) { + ASC_DBG1(1, + "asc_isr_callback: underrun condition %u bytes\n", + (unsigned)qdonep->remain_bytes); + scp->resid = qdonep->remain_bytes; + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); + switch (qdonep->d3.host_stat) { + case QHSTA_NO_ERROR: + if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, + "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by target drivers + * defined in scsi.h shifts the status byte returned by + * host drivers right by 1 bit. This is why target drivers + * also use right shifted status byte definitions. For + * instance target drivers use CHECK_CONDITION, defined to + * 0x1, instead of the SCSI defined check condition value + * of 0x2. Host drivers are supposed to return the status + * byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(qdonep->d3.scsi_stat); + } else { + scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); + } + break; + + default: + /* QHSTA error occurred */ + ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", + qdonep->d3.host_stat); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + + default: + ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", + qdonep->d3.done_stat); + scp->result = + HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + } - /* - * 'qdonep' contains the command's ending status. - */ - switch (qdonep->d3.done_stat) { - case QD_NO_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; - - /* - * If an INQUIRY command completed successfully, then call - * the AscInquiryHandling() function to set-up the device. - */ - if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && - (scp->request_bufflen - qdonep->remain_bytes) >= 8) - { - AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, - (ASC_SCSI_INQUIRY *) scp->request_buffer); - } - - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && - qdonep->remain_bytes <= scp->request_bufflen) { - ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n", - (unsigned) qdonep->remain_bytes); - scp->resid = qdonep->remain_bytes; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(qdonep->d3.scsi_stat); - } else { - scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); - } - break; - - default: - /* QHSTA error occurred */ - ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", - qdonep->d3.host_stat); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - - default: - ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", qdonep->d3.done_stat); - scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - } + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + qdonep->d3.done_stat == QD_NO_ERROR && + qdonep->d3.host_stat == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - qdonep->d3.done_stat == QD_NO_ERROR && - qdonep->d3.host_stat == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); - } + /* + * Because interrupts may be enabled by the 'struct scsi_cmnd' done + * function, add the command to the end of the board's done queue. + * The done function for the command will be called from + * advansys_interrupt(). + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - - return; + return; } /* @@ -6885,238 +5704,240 @@ asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) * * Callback function for the Wide SCSI Adv Library. */ -STATIC void -adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) +static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) { - asc_board_t *boardp; - adv_req_t *reqp; - adv_sgblk_t *sgblkp; - struct scsi_cmnd *scp; - struct Scsi_Host *shp; - int i; - ADV_DCNT resid_cnt; - - - ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", - (ulong) adv_dvc_varp, (ulong) scsiqp); - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); - - /* - * Get the adv_req_t structure for the command that has been - * completed. The adv_req_t structure actually contains the - * completed ADV_SCSI_REQ_Q structure. - */ - reqp = (adv_req_t *) ADV_U32_TO_VADDR(scsiqp->srb_ptr); - ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong) reqp); - if (reqp == NULL) { - ASC_PRINT("adv_isr_callback: reqp is NULL\n"); - return; - } - - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - * - * Note: The adv_req_t request structure and adv_sgblk_t structure, - * if any, are dropped, because a board structure pointer can not be - * determined. - */ - scp = reqp->cmndp; - ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong) scp); - if (scp == NULL) { - ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); - - /* - * If the request's host pointer is not valid, display a message - * and return. - */ - shp = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shp) { - break; - } - } - /* - * Note: If the host structure is not found, the adv_req_t request - * structure and adv_sgblk_t structure, if any, is dropped. - */ - if (i == asc_board_count) { - ASC_PRINT2( - "adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong) scp, (ulong) shp); - return; - } + asc_board_t *boardp; + adv_req_t *reqp; + adv_sgblk_t *sgblkp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + int i; + ADV_DCNT resid_cnt; + + ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", + (ulong)adv_dvc_varp, (ulong)scsiqp); + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + + /* + * Get the adv_req_t structure for the command that has been + * completed. The adv_req_t structure actually contains the + * completed ADV_SCSI_REQ_Q structure. + */ + reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); + ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp); + if (reqp == NULL) { + ASC_PRINT("adv_isr_callback: reqp is NULL\n"); + return; + } - ASC_STATS(shp, callback); - ASC_DBG1(1, "adv_isr_callback: shp 0x%lx\n", (ulong) shp); + /* + * Get the struct scsi_cmnd structure and Scsi_Host structure for the + * command that has been completed. + * + * Note: The adv_req_t request structure and adv_sgblk_t structure, + * if any, are dropped, because a board structure pointer can not be + * determined. + */ + scp = reqp->cmndp; + ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp); + if (scp == NULL) { + ASC_PRINT + ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); + return; + } + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + /* + * If the request's host pointer is not valid, display a message + * and return. + */ + shost = scp->device->host; + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i] == shost) { + break; + } + } + /* + * Note: If the host structure is not found, the adv_req_t request + * structure and adv_sgblk_t structure, if any, is dropped. + */ + if (i == asc_board_count) { + ASC_PRINT2 + ("adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", + (ulong)scp, (ulong)shost); + return; + } - /* - * If the request isn't found on the active queue, it may have been - * removed to handle a reset request. Display a message and return. - * - * Note: Because the structure may still be in use don't attempt - * to free the adv_req_t and adv_sgblk_t, if any, structures. - */ - boardp = ASC_BOARDP(shp); - ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2( - "adv_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong) scp); - return; - } + ASC_STATS(shost, callback); + ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); + + /* + * If the request isn't found on the active queue, it may have been + * removed to handle a reset request. Display a message and return. + * + * Note: Because the structure may still be in use don't attempt + * to free the adv_req_t and adv_sgblk_t, if any, structures. + */ + boardp = ASC_BOARDP(shost); + ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); + if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { + ASC_PRINT2 + ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n", + boardp->id, (ulong)scp); + return; + } - /* - * 'done_status' contains the command's ending status. - */ - switch (scsiqp->done_status) { - case QD_NO_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; - - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - resid_cnt = le32_to_cpu(scsiqp->data_cnt); - if (scp->request_bufflen != 0 && resid_cnt != 0 && - resid_cnt <= scp->request_bufflen) { - ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n", - (ulong) resid_cnt); - scp->resid = resid_cnt; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); - switch (scsiqp->host_status) { - case QHSTA_NO_ERROR: - if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(scsiqp->scsi_status); - } else { - scp->result = STATUS_BYTE(scsiqp->scsi_status); - } - break; - - default: - /* Some other QHSTA error occurred. */ - ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", - scsiqp->host_status); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); - break; - - default: - ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", scsiqp->done_status); - scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); - break; - } + /* + * 'done_status' contains the command's ending status. + */ + switch (scsiqp->done_status) { + case QD_NO_ERROR: + ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); + scp->result = 0; - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - scsiqp->done_status == QD_NO_ERROR && - scsiqp->host_status == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); - } + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * then return the number of underrun bytes. + */ + resid_cnt = le32_to_cpu(scsiqp->data_cnt); + if (scp->request_bufflen != 0 && resid_cnt != 0 && + resid_cnt <= scp->request_bufflen) { + ASC_DBG1(1, + "adv_isr_callback: underrun condition %lu bytes\n", + (ulong)resid_cnt); + scp->resid = resid_cnt; + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); + switch (scsiqp->host_status) { + case QHSTA_NO_ERROR: + if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, + "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by target drivers + * defined in scsi.h shifts the status byte returned by + * host drivers right by 1 bit. This is why target drivers + * also use right shifted status byte definitions. For + * instance target drivers use CHECK_CONDITION, defined to + * 0x1, instead of the SCSI defined check condition value + * of 0x2. Host drivers are supposed to return the status + * byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(scsiqp->scsi_status); + } else { + scp->result = STATUS_BYTE(scsiqp->scsi_status); + } + break; + + default: + /* Some other QHSTA error occurred. */ + ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", + scsiqp->host_status); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); + break; + + default: + ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", + scsiqp->done_status); + scp->result = + HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); + break; + } - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + scsiqp->done_status == QD_NO_ERROR && + scsiqp->host_status == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } - /* - * Free all 'adv_sgblk_t' structures allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) - { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; - } + /* + * Because interrupts may be enabled by the 'struct scsi_cmnd' done + * function, add the command to the end of the board's done queue. + * The done function for the command will be called from + * advansys_interrupt(). + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); + + /* + * Free all 'adv_sgblk_t' structures allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; + } - /* - * Free the adv_req_t structure used with the command by adding - * it back to the board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; + /* + * Free the adv_req_t structure used with the command by adding + * it back to the board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; - ASC_DBG(1, "adv_isr_callback: done\n"); + ASC_DBG(1, "adv_isr_callback: done\n"); - return; + return; } /* * adv_async_callback() - Adv Library asynchronous event callback function. */ -STATIC void -adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) +static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) { - switch (code) - { - case ADV_ASYNC_SCSI_BUS_RESET_DET: - /* - * The firmware detected a SCSI Bus reset. - */ - ASC_DBG(0, "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); - break; - - case ADV_ASYNC_RDMA_FAILURE: - /* - * Handle RDMA failure by resetting the SCSI Bus and - * possibly the chip if it is unresponsive. Log the error - * with a unique code. - */ - ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); - AdvResetChipAndSB(adv_dvc_varp); - break; - - case ADV_HOST_SCSI_BUS_RESET: - /* - * Host generated SCSI bus reset occurred. - */ - ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); - break; - - default: - ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); - break; - } + switch (code) { + case ADV_ASYNC_SCSI_BUS_RESET_DET: + /* + * The firmware detected a SCSI Bus reset. + */ + ASC_DBG(0, + "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); + break; + + case ADV_ASYNC_RDMA_FAILURE: + /* + * Handle RDMA failure by resetting the SCSI Bus and + * possibly the chip if it is unresponsive. Log the error + * with a unique code. + */ + ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); + AdvResetChipAndSB(adv_dvc_varp); + break; + + case ADV_HOST_SCSI_BUS_RESET: + /* + * Host generated SCSI bus reset occurred. + */ + ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); + break; + + default: + ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); + break; + } } /* @@ -7127,50 +5948,50 @@ adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) * * 'REQPNEXT(reqp)' returns reqp's next pointer. */ -STATIC void -asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) +static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) { - int tid; - - ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n", - (ulong) ascq, (ulong) reqp, flag); - ASC_ASSERT(reqp != NULL); - ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if (flag == ASC_FRONT) { - reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; - ascq->q_first[tid] = reqp; - /* If the queue was empty, set the last pointer. */ - if (ascq->q_last[tid] == NULL) { - ascq->q_last[tid] = reqp; - } - } else { /* ASC_BACK */ - if (ascq->q_last[tid] != NULL) { - ascq->q_last[tid]->host_scribble = (unsigned char *)reqp; - } - ascq->q_last[tid] = reqp; - reqp->host_scribble = NULL; - /* If the queue was empty, set the first pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_first[tid] = reqp; - } - } - /* The queue has at least one entry, set its bit. */ - ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); + int tid; + + ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n", + (ulong)ascq, (ulong)reqp, flag); + ASC_ASSERT(reqp != NULL); + ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); + tid = REQPTID(reqp); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + if (flag == ASC_FRONT) { + reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; + ascq->q_first[tid] = reqp; + /* If the queue was empty, set the last pointer. */ + if (ascq->q_last[tid] == NULL) { + ascq->q_last[tid] = reqp; + } + } else { /* ASC_BACK */ + if (ascq->q_last[tid] != NULL) { + ascq->q_last[tid]->host_scribble = + (unsigned char *)reqp; + } + ascq->q_last[tid] = reqp; + reqp->host_scribble = NULL; + /* If the queue was empty, set the first pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_first[tid] = reqp; + } + } + /* The queue has at least one entry, set its bit. */ + ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_tot_cnt[tid]++; - ascq->q_cur_cnt[tid]++; - if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { - ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; - ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", - tid, ascq->q_max_cnt[tid]); - } - REQPTIME(reqp) = REQTIMESTAMP(); + /* Maintain request queue statistics. */ + ascq->q_tot_cnt[tid]++; + ascq->q_cur_cnt[tid]++; + if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { + ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; + ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", + tid, ascq->q_max_cnt[tid]); + } + REQPTIME(reqp) = REQTIMESTAMP(); #endif /* ADVANSYS_STATS */ - ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong) reqp); - return; + ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp); + return; } /* @@ -7180,31 +6001,30 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) * * 'REQPNEXT(reqp)' returns reqp's next pointer. */ -STATIC REQP -asc_dequeue(asc_queue_t *ascq, int tid) +static REQP asc_dequeue(asc_queue_t *ascq, int tid) { - REQP reqp; - - ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong) ascq, tid); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if ((reqp = ascq->q_first[tid]) != NULL) { - ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } + REQP reqp; + + ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + if ((reqp = ascq->q_first[tid]) != NULL) { + ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); + ascq->q_first[tid] = REQPNEXT(reqp); + /* If the queue is empty, clear its bit and the last pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + ASC_ASSERT(ascq->q_last[tid] == reqp); + ascq->q_last[tid] = NULL; + } #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_cur_cnt[tid]--; - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); - REQTIMESTAT("asc_dequeue", ascq, reqp, tid); + /* Maintain request queue statistics. */ + ascq->q_cur_cnt[tid]--; + ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); + REQTIMESTAT("asc_dequeue", ascq, reqp, tid); #endif /* ADVANSYS_STATS */ - } - ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong) reqp); - return reqp; + } + ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp); + return reqp; } /* @@ -7227,74 +6047,76 @@ asc_dequeue(asc_queue_t *ascq, int tid) * Unfortunately collecting queuing time statistics adds overhead to * the function that isn't inherent to the function's algorithm. */ -STATIC REQP -asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) +static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) { - REQP firstp, lastp; - int i; - - ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong) ascq, tid); - ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); - - /* - * If 'tid' is not ASC_TID_ALL, return requests only for - * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all - * requests for all tids. - */ - if (tid != ASC_TID_ALL) { - /* Return all requests for the specified 'tid'. */ - if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { - /* List is empty; Set first and last return pointers to NULL. */ - firstp = lastp = NULL; - } else { - firstp = ascq->q_first[tid]; - lastp = ascq->q_last[tid]; - ascq->q_first[tid] = ascq->q_last[tid] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + REQP firstp, lastp; + int i; + + ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); + ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); + + /* + * If 'tid' is not ASC_TID_ALL, return requests only for + * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all + * requests for all tids. + */ + if (tid != ASC_TID_ALL) { + /* Return all requests for the specified 'tid'. */ + if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { + /* List is empty; Set first and last return pointers to NULL. */ + firstp = lastp = NULL; + } else { + firstp = ascq->q_first[tid]; + lastp = ascq->q_last[tid]; + ascq->q_first[tid] = ascq->q_last[tid] = NULL; + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); #ifdef ADVANSYS_STATS - { - REQP reqp; - ascq->q_cur_cnt[tid] = 0; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid); - } - } + { + REQP reqp; + ascq->q_cur_cnt[tid] = 0; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, + reqp, tid); + } + } #endif /* ADVANSYS_STATS */ - } - } else { - /* Return all requests for all tids. */ - firstp = lastp = NULL; - for (i = 0; i <= ADV_MAX_TID; i++) { - if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { - if (firstp == NULL) { - firstp = ascq->q_first[i]; - lastp = ascq->q_last[i]; - } else { - ASC_ASSERT(lastp != NULL); - lastp->host_scribble = (unsigned char *)ascq->q_first[i]; - lastp = ascq->q_last[i]; - } - ascq->q_first[i] = ascq->q_last[i] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); + } + } else { + /* Return all requests for all tids. */ + firstp = lastp = NULL; + for (i = 0; i <= ADV_MAX_TID; i++) { + if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { + if (firstp == NULL) { + firstp = ascq->q_first[i]; + lastp = ascq->q_last[i]; + } else { + ASC_ASSERT(lastp != NULL); + lastp->host_scribble = + (unsigned char *)ascq->q_first[i]; + lastp = ascq->q_last[i]; + } + ascq->q_first[i] = ascq->q_last[i] = NULL; + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); #ifdef ADVANSYS_STATS - ascq->q_cur_cnt[i] = 0; + ascq->q_cur_cnt[i] = 0; #endif /* ADVANSYS_STATS */ - } - } + } + } #ifdef ADVANSYS_STATS - { - REQP reqp; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->device->id); - } - } + { + REQP reqp; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, reqp, + reqp->device->id); + } + } #endif /* ADVANSYS_STATS */ - } - if (lastpp) { - *lastpp = lastp; - } - ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong) firstp); - return firstp; + } + if (lastpp) { + *lastpp = lastp; + } + ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp); + return firstp; } /* @@ -7307,67 +6129,67 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) * Return ASC_TRUE if the command was found and removed, * otherwise return ASC_FALSE. */ -STATIC int -asc_rmqueue(asc_queue_t *ascq, REQP reqp) +static int asc_rmqueue(asc_queue_t *ascq, REQP reqp) { - REQP currp, prevp; - int tid; - int ret = ASC_FALSE; - - ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", - (ulong) ascq, (ulong) reqp); - ASC_ASSERT(reqp != NULL); - - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - - /* - * Handle the common case of 'reqp' being the first - * entry on the queue. - */ - if (reqp == ascq->q_first[tid]) { - ret = ASC_TRUE; - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is now empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } - } else if (ascq->q_first[tid] != NULL) { - ASC_ASSERT(ascq->q_last[tid] != NULL); - /* - * Because the case of 'reqp' being the first entry has been - * handled above and it is known the queue is not empty, if - * 'reqp' is found on the queue it is guaranteed the queue will - * not become empty and that 'q_first[tid]' will not be changed. - * - * Set 'prevp' to the first entry, 'currp' to the second entry, - * and search for 'reqp'. - */ - for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); - currp; prevp = currp, currp = REQPNEXT(currp)) { - if (currp == reqp) { - ret = ASC_TRUE; - prevp->host_scribble = (unsigned char *)REQPNEXT(currp); - reqp->host_scribble = NULL; - if (ascq->q_last[tid] == reqp) { - ascq->q_last[tid] = prevp; - } - break; - } - } - } + REQP currp, prevp; + int tid; + int ret = ASC_FALSE; + + ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", + (ulong)ascq, (ulong)reqp); + ASC_ASSERT(reqp != NULL); + + tid = REQPTID(reqp); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + + /* + * Handle the common case of 'reqp' being the first + * entry on the queue. + */ + if (reqp == ascq->q_first[tid]) { + ret = ASC_TRUE; + ascq->q_first[tid] = REQPNEXT(reqp); + /* If the queue is now empty, clear its bit and the last pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + ASC_ASSERT(ascq->q_last[tid] == reqp); + ascq->q_last[tid] = NULL; + } + } else if (ascq->q_first[tid] != NULL) { + ASC_ASSERT(ascq->q_last[tid] != NULL); + /* + * Because the case of 'reqp' being the first entry has been + * handled above and it is known the queue is not empty, if + * 'reqp' is found on the queue it is guaranteed the queue will + * not become empty and that 'q_first[tid]' will not be changed. + * + * Set 'prevp' to the first entry, 'currp' to the second entry, + * and search for 'reqp'. + */ + for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); + currp; prevp = currp, currp = REQPNEXT(currp)) { + if (currp == reqp) { + ret = ASC_TRUE; + prevp->host_scribble = + (unsigned char *)REQPNEXT(currp); + reqp->host_scribble = NULL; + if (ascq->q_last[tid] == reqp) { + ascq->q_last[tid] = prevp; + } + break; + } + } + } #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - if (ret == ASC_TRUE) { - ascq->q_cur_cnt[tid]--; - REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); - } - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); + /* Maintain request queue statistics. */ + if (ret == ASC_TRUE) { + ascq->q_cur_cnt[tid]--; + REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); + } + ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); #endif /* ADVANSYS_STATS */ - ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong) reqp, ret); - return ret; + ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret); + return ret; } /* @@ -7375,37 +6197,38 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp) * * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd. */ -STATIC void -asc_execute_queue(asc_queue_t *ascq) +static void asc_execute_queue(asc_queue_t *ascq) { - ADV_SCSI_BIT_ID_TYPE scan_tidmask; - REQP reqp; - int i; - - ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong) ascq); - /* - * Execute queued commands for devices attached to - * the current board in round-robin fashion. - */ - scan_tidmask = ascq->q_tidmask; - do { - for (i = 0; i <= ADV_MAX_TID; i++) { - if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { - if ((reqp = asc_dequeue(ascq, i)) == NULL) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - } else if (asc_execute_scsi_cmnd((struct scsi_cmnd *) reqp) - == ASC_BUSY) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - /* - * The request returned ASC_BUSY. Enqueue at the front of - * target's waiting list to maintain correct ordering. - */ - asc_enqueue(ascq, reqp, ASC_FRONT); - } - } - } - } while (scan_tidmask); - return; + ADV_SCSI_BIT_ID_TYPE scan_tidmask; + REQP reqp; + int i; + + ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq); + /* + * Execute queued commands for devices attached to + * the current board in round-robin fashion. + */ + scan_tidmask = ascq->q_tidmask; + do { + for (i = 0; i <= ADV_MAX_TID; i++) { + if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { + if ((reqp = asc_dequeue(ascq, i)) == NULL) { + scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); + } else + if (asc_execute_scsi_cmnd + ((struct scsi_cmnd *)reqp) + == ASC_BUSY) { + scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); + /* + * The request returned ASC_BUSY. Enqueue at the front of + * target's waiting list to maintain correct ordering. + */ + asc_enqueue(ascq, reqp, ASC_FRONT); + } + } + } + } while (scan_tidmask); + return; } #ifdef CONFIG_PROC_FS @@ -7420,102 +6243,102 @@ asc_execute_queue(asc_queue_t *ascq) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int chip_scsi_id; - int i; - - boardp = ASC_BOARDP(shp); - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; + int i; + + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nDevice Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } - len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X,", i); - ASC_PRT_NEXT(); - } - } - len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X,", i); + ASC_PRT_NEXT(); + } + } + len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); + ASC_PRT_NEXT(); - return totlen; + return totlen; } /* * Display Wide Board BIOS Information. */ -STATIC int -asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - ushort major, minor, letter; - - boardp = ASC_BOARDP(shp); - leftlen = cplen; - totlen = len = 0; + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + ushort major, minor, letter; + + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); + ASC_PRT_NEXT(); + + /* + * If the BIOS saved a valid signature, then fill in + * the BIOS code segment base address. + */ + if (boardp->bios_signature != 0x55AA) { + len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } else { + major = (boardp->bios_version >> 12) & 0xF; + minor = (boardp->bios_version >> 8) & 0xF; + letter = (boardp->bios_version & 0xFF); - len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "%d.%d%c\n", + major, minor, + letter >= 26 ? '?' : letter + 'A'); + ASC_PRT_NEXT(); - /* - * If the BIOS saved a valid signature, then fill in - * the BIOS code segment base address. - */ - if (boardp->bios_signature != 0x55AA) { - len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } else { - major = (boardp->bios_version >> 12) & 0xF; - minor = (boardp->bios_version >> 8) & 0xF; - letter = (boardp->bios_version & 0xFF); - - len = asc_prt_line(cp, leftlen, "%d.%d%c\n", - major, minor, letter >= 26 ? '?' : letter + 'A'); - ASC_PRT_NEXT(); - - /* - * Current available ROM BIOS release is 3.1I for UW - * and 3.2I for U2W. This code doesn't differentiate - * UW and U2W boards. - */ - if (major < 3 || (major <= 3 && minor < 1) || - (major <= 3 && minor <= 1 && letter < ('I'- 'A'))) { - len = asc_prt_line(cp, leftlen, -"Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } - } + /* + * Current available ROM BIOS release is 3.1I for UW + * and 3.2I for U2W. This code doesn't differentiate + * UW and U2W boards. + */ + if (major < 3 || (major <= 3 && minor < 1) || + (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) { + len = asc_prt_line(cp, leftlen, + "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } + } - return totlen; + return totlen; } /* @@ -7541,80 +6364,79 @@ asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen) * * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE. */ -STATIC int -asc_get_eeprom_string(ushort *serialnum, uchar *cp) +static int asc_get_eeprom_string(ushort *serialnum, uchar *cp) { - ushort w, num; - - if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) { - return ASC_FALSE; - } else { - /* - * First word - 6 digits. - */ - w = serialnum[0]; - - /* Product type - 1st digit. */ - if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { - /* Product type is P=Prototype */ - *cp += 0x8; - } - cp++; - - /* Manufacturing location - 2nd digit. */ - *cp++ = 'A' + ((w & 0x1C00) >> 10); - - /* Product ID - 3rd, 4th digits. */ - num = w & 0x3FF; - *cp++ = '0' + (num / 100); - num %= 100; - *cp++ = '0' + (num / 10); - - /* Product revision - 5th digit. */ - *cp++ = 'A' + (num % 10); - - /* - * Second word - */ - w = serialnum[1]; - - /* - * Year - 6th digit. - * - * If bit 15 of third word is set, then the - * last digit of the year is greater than 7. - */ - if (serialnum[2] & 0x8000) { - *cp++ = '8' + ((w & 0x1C0) >> 6); - } else { - *cp++ = '0' + ((w & 0x1C0) >> 6); - } - - /* Week of year - 7th, 8th digits. */ - num = w & 0x003F; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; - - /* - * Third word - */ - w = serialnum[2] & 0x7FFF; - - /* Serial number - 9th digit. */ - *cp++ = 'A' + (w / 1000); - - /* 10th, 11th, 12th digits. */ - num = w % 1000; - *cp++ = '0' + num / 100; - num %= 100; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; - - *cp = '\0'; /* Null Terminate the string. */ - return ASC_TRUE; - } + ushort w, num; + + if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) { + return ASC_FALSE; + } else { + /* + * First word - 6 digits. + */ + w = serialnum[0]; + + /* Product type - 1st digit. */ + if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { + /* Product type is P=Prototype */ + *cp += 0x8; + } + cp++; + + /* Manufacturing location - 2nd digit. */ + *cp++ = 'A' + ((w & 0x1C00) >> 10); + + /* Product ID - 3rd, 4th digits. */ + num = w & 0x3FF; + *cp++ = '0' + (num / 100); + num %= 100; + *cp++ = '0' + (num / 10); + + /* Product revision - 5th digit. */ + *cp++ = 'A' + (num % 10); + + /* + * Second word + */ + w = serialnum[1]; + + /* + * Year - 6th digit. + * + * If bit 15 of third word is set, then the + * last digit of the year is greater than 7. + */ + if (serialnum[2] & 0x8000) { + *cp++ = '8' + ((w & 0x1C0) >> 6); + } else { + *cp++ = '0' + ((w & 0x1C0) >> 6); + } + + /* Week of year - 7th, 8th digits. */ + num = w & 0x003F; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + /* + * Third word + */ + w = serialnum[2] & 0x7FFF; + + /* Serial number - 9th digit. */ + *cp++ = 'A' + (w / 1000); + + /* 10th, 11th, 12th digits. */ + num = w % 1000; + *cp++ = '0' + num / 100; + num %= 100; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + *cp = '\0'; /* Null Terminate the string. */ + return ASC_TRUE; + } } /* @@ -7628,122 +6450,127 @@ asc_get_eeprom_string(ushort *serialnum, uchar *cp) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - int leftlen; - int totlen; - int len; - ASCEEP_CONFIG *ep; - int i; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + int leftlen; + int totlen; + int len; + ASCEEP_CONFIG *ep; + int i; #ifdef CONFIG_ISA - int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; + int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; #endif /* CONFIG_ISA */ - uchar serialstr[13]; - - boardp = ASC_BOARDP(shp); - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ep = &boardp->eep_config.asc_eep; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) == - ASC_TRUE) { - len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); - ASC_PRT_NEXT(); - } else { - if (ep->adapter_info[5] == 0xBB) { - len = asc_prt_line(cp, leftlen, - " Default Settings Used for EEPROM-less Adapter.\n"); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); - } - } + uchar serialstr[13]; + + boardp = ASC_BOARDP(shost); + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + ep = &boardp->eep_config.asc_eep; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr) + == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + if (ep->adapter_info[5] == 0xBB) { + len = asc_prt_line(cp, leftlen, + " Default Settings Used for EEPROM-less Adapter.\n"); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } + } - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, ep->max_tag_qng); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" cntl 0x%x, no_scam 0x%x\n", - ep->cntl, ep->no_scam); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %d", i); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, + ep->max_tag_qng); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %d", i); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); #ifdef CONFIG_ISA - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - len = asc_prt_line(cp, leftlen, -" Host ISA DMA speed: %d MB/S\n", - isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); - ASC_PRT_NEXT(); - } + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + len = asc_prt_line(cp, leftlen, + " Host ISA DMA speed: %d MB/S\n", + isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); + ASC_PRT_NEXT(); + } #endif /* CONFIG_ISA */ - return totlen; + return totlen; } /* @@ -7757,300 +6584,282 @@ asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - ADV_DVC_VAR *adv_dvc_varp; - int leftlen; - int totlen; - int len; - int i; - char *termstr; - uchar serialstr[13]; - ADVEEP_3550_CONFIG *ep_3550 = NULL; - ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; - ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; - ushort word; - ushort *wordp; - ushort sdtr_speed = 0; - - boardp = ASC_BOARDP(shp); - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ep_3550 = &boardp->eep_config.adv_3550_eep; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; - } else - { - ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; - } + asc_board_t *boardp; + ADV_DVC_VAR *adv_dvc_varp; + int leftlen; + int totlen; + int len; + int i; + char *termstr; + uchar serialstr[13]; + ADVEEP_3550_CONFIG *ep_3550 = NULL; + ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; + ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; + ushort word; + ushort *wordp; + ushort sdtr_speed = 0; + + boardp = ASC_BOARDP(shost); + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ep_3550 = &boardp->eep_config.adv_3550_eep; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; + } else { + ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; + } - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - wordp = &ep_3550->serial_number_word1; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - wordp = &ep_38C0800->serial_number_word1; - } else - { - wordp = &ep_38C1600->serial_number_word1; - } + leftlen = cplen; + totlen = len = 0; - if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { - len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_3550->adapter_scsi_id, ep_3550->max_host_qng, - ep_3550->max_dvc_qng); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C0800->adapter_scsi_id, ep_38C0800->max_host_qng, - ep_38C0800->max_dvc_qng); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C1600->adapter_scsi_id, ep_38C1600->max_host_qng, - ep_38C1600->max_dvc_qng); - ASC_PRT_NEXT(); - } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->termination; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->termination_lvd; - } else - { - word = ep_38C1600->termination_lvd; - } - switch (word) { - case 1: - termstr = "Low Off/High Off"; - break; - case 2: - termstr = "Low Off/High On"; - break; - case 3: - termstr = "Low On/High On"; - break; - default: - case 0: - termstr = "Automatic"; - break; - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + wordp = &ep_3550->serial_number_word1; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + wordp = &ep_38C0800->serial_number_word1; + } else { + wordp = &ep_38C1600->serial_number_word1; + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_3550->termination, termstr, ep_3550->bios_ctrl); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C0800->termination_lvd, termstr, ep_38C0800->bios_ctrl); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C1600->termination_lvd, termstr, ep_38C1600->bios_ctrl); - ASC_PRT_NEXT(); - } + if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } - len = asc_prt_line(cp, leftlen, -" Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %X", i); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->disc_enable; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->disc_enable; - } else - { - word = ep_38C1600->disc_enable; - } - len = asc_prt_line(cp, leftlen, -" Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->tagqng_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->tagqng_able; - } else - { - word = ep_38C1600->tagqng_able; - } - len = asc_prt_line(cp, leftlen, -" Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->start_motor; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->start_motor; - } else - { - word = ep_38C1600->start_motor; - } - len = asc_prt_line(cp, leftlen, -" Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_3550->adapter_scsi_id, + ep_3550->max_host_qng, ep_3550->max_dvc_qng); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C0800->adapter_scsi_id, + ep_38C0800->max_host_qng, + ep_38C0800->max_dvc_qng); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C1600->adapter_scsi_id, + ep_38C1600->max_host_qng, + ep_38C1600->max_dvc_qng); + ASC_PRT_NEXT(); + } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->termination; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->termination_lvd; + } else { + word = ep_38C1600->termination_lvd; + } + switch (word) { + case 1: + termstr = "Low Off/High Off"; + break; + case 2: + termstr = "Low Off/High On"; + break; + case 3: + termstr = "Low On/High On"; + break; + default: + case 0: + termstr = "Automatic"; + break; + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Ultra Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_3550->termination, termstr, + ep_3550->bios_ctrl); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C0800->termination_lvd, termstr, + ep_38C0800->bios_ctrl); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C1600->termination_lvd, termstr, + ep_38C1600->bios_ctrl); + ASC_PRT_NEXT(); + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->wdtr_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->wdtr_able; - } else - { - word = ep_38C1600->wdtr_able; - } - len = asc_prt_line(cp, leftlen, -" Wide Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || - adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) - { - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer Speed (Mhz):\n "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - char *speed_str; - - if (i == 0) - { - sdtr_speed = adv_dvc_varp->sdtr_speed1; - } else if (i == 4) - { - sdtr_speed = adv_dvc_varp->sdtr_speed2; - } else if (i == 8) - { - sdtr_speed = adv_dvc_varp->sdtr_speed3; - } else if (i == 12) - { - sdtr_speed = adv_dvc_varp->sdtr_speed4; - } - switch (sdtr_speed & ADV_MAX_TID) - { - case 0: speed_str = "Off"; break; - case 1: speed_str = " 5"; break; - case 2: speed_str = " 10"; break; - case 3: speed_str = " 20"; break; - case 4: speed_str = " 40"; break; - case 5: speed_str = " 80"; break; - default: speed_str = "Unk"; break; - } - len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); - ASC_PRT_NEXT(); - if (i == 7) - { - len = asc_prt_line(cp, leftlen, "\n "); - ASC_PRT_NEXT(); - } - sdtr_speed >>= 4; - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %X", i); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->disc_enable; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->disc_enable; + } else { + word = ep_38C1600->disc_enable; + } + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->tagqng_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->tagqng_able; + } else { + word = ep_38C1600->tagqng_able; + } + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->start_motor; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->start_motor; + } else { + word = ep_38C1600->start_motor; + } + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + sdtr_able & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Ultra Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + ultra_able & ADV_TID_TO_TIDMASK(i)) + ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->wdtr_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->wdtr_able; + } else { + word = ep_38C1600->wdtr_able; + } + len = asc_prt_line(cp, leftlen, " Wide Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || + adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) { + len = asc_prt_line(cp, leftlen, + " Synchronous Transfer Speed (Mhz):\n "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + char *speed_str; + + if (i == 0) { + sdtr_speed = adv_dvc_varp->sdtr_speed1; + } else if (i == 4) { + sdtr_speed = adv_dvc_varp->sdtr_speed2; + } else if (i == 8) { + sdtr_speed = adv_dvc_varp->sdtr_speed3; + } else if (i == 12) { + sdtr_speed = adv_dvc_varp->sdtr_speed4; + } + switch (sdtr_speed & ADV_MAX_TID) { + case 0: + speed_str = "Off"; + break; + case 1: + speed_str = " 5"; + break; + case 2: + speed_str = " 10"; + break; + case 3: + speed_str = " 20"; + break; + case 4: + speed_str = " 40"; + break; + case 5: + speed_str = " 80"; + break; + default: + speed_str = "Unk"; + break; + } + len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); + ASC_PRT_NEXT(); + if (i == 7) { + len = asc_prt_line(cp, leftlen, "\n "); + ASC_PRT_NEXT(); + } + sdtr_speed >>= 4; + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8062,60 +6871,60 @@ asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int chip_scsi_id; - - boardp = ASC_BOARDP(shp); - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", - shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun, - shp->max_channel); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", - shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize, - shp->cmd_per_lun); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" unchecked_isa_dma %d, use_clustering %d\n", - shp->unchecked_isa_dma, shp->use_clustering); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", - boardp->flags, boardp->last_reset, jiffies, boardp->asc_n_io_port); - ASC_PRT_NEXT(); - - /* 'shp->n_io_port' may be truncated because it is only one byte. */ - len = asc_prt_line(cp, leftlen, -" io_port 0x%x, n_io_port 0x%x\n", - shp->io_port, shp->n_io_port); - ASC_PRT_NEXT(); - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; + + boardp = ASC_BOARDP(shost); + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", + shost->host_busy, shost->last_reset, shost->max_id, + shost->max_lun, shost->max_channel); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", + shost->unique_id, shost->can_queue, shost->this_id, + shost->sg_tablesize, shost->cmd_per_lun); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " unchecked_isa_dma %d, use_clustering %d\n", + shost->unchecked_isa_dma, shost->use_clustering); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", + boardp->flags, boardp->last_reset, jiffies, + boardp->asc_n_io_port); + ASC_PRT_NEXT(); + + /* 'shost->n_io_port' may be truncated because it is only one byte. */ + len = asc_prt_line(cp, leftlen, + " io_port 0x%x, n_io_port 0x%x\n", + shost->io_port, shost->n_io_port); + ASC_PRT_NEXT(); + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } - return totlen; + return totlen; } /* @@ -8129,178 +6938,181 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int chip_scsi_id; - int leftlen; - int totlen; - int len; - ASC_DVC_VAR *v; - ASC_DVC_CFG *c; - int i; - int renegotiate = 0; - - boardp = ASC_BOARDP(shp); - v = &boardp->dvc_var.asc_dvc_var; - c = &boardp->dvc_cfg.asc_dvc_cfg; - chip_scsi_id = c->chip_scsi_id; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n", - c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" mcode_version 0x%x, err_code %u\n", - c->mcode_version, v->err_code); - ASC_PRT_NEXT(); - - /* Current number of commands waiting for the host. */ - len = asc_prt_line(cp, leftlen, -" Total Command Pending: %d\n", v->cur_total_qng); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Queuing:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Current number of commands waiting for a device. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Current limit on number of commands that can be sent to a device. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Indicate whether the device has returned queue full status. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Full:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X:Y-%d", - i, boardp->queue_full_cnt[i]); - } else { - len = asc_prt_line(cp, leftlen, " %X:N", i); - } - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - for (i = 0; i <= ASC_MAX_TID; i++) { - uchar syn_period_ix; - - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); - - if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) - { - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else - { - syn_period_ix = - (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1); - - len = asc_prt_line(cp, leftlen, - " Transfer Period Factor: %d (%d.%d Mhz),", - v->sdtr_period_tbl[syn_period_ix], - 250 / v->sdtr_period_tbl[syn_period_ix], - ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix])); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET); - ASC_PRT_NEXT(); - } - - if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else - { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); - } + asc_board_t *boardp; + int chip_scsi_id; + int leftlen; + int totlen; + int len; + ASC_DVC_VAR *v; + ASC_DVC_CFG *c; + int i; + int renegotiate = 0; + + boardp = ASC_BOARDP(shost); + v = &boardp->dvc_var.asc_dvc_var; + c = &boardp->dvc_cfg.asc_dvc_cfg; + chip_scsi_id = c->chip_scsi_id; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n", + c->chip_version, c->lib_version, c->lib_serial_no, + c->mcode_date); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " mcode_version 0x%x, err_code %u\n", + c->mcode_version, v->err_code); + ASC_PRT_NEXT(); + + /* Current number of commands waiting for the host. */ + len = asc_prt_line(cp, leftlen, + " Total Command Pending: %d\n", v->cur_total_qng); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Queuing:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Current number of commands waiting for a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Current limit on number of commands that can be sent to a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Indicate whether the device has returned queue full status. */ + len = asc_prt_line(cp, leftlen, " Command Queue Full:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X:Y-%d", + i, boardp->queue_full_cnt[i]); + } else { + len = asc_prt_line(cp, leftlen, " %X:N", i); + } + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + for (i = 0; i <= ASC_MAX_TID; i++) { + uchar syn_period_ix; + + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); + + if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) { + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + syn_period_ix = + (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - + 1); + + len = asc_prt_line(cp, leftlen, + " Transfer Period Factor: %d (%d.%d Mhz),", + v->sdtr_period_tbl[syn_period_ix], + 250 / + v->sdtr_period_tbl[syn_period_ix], + ASC_TENTHS(250, + v-> + sdtr_period_tbl + [syn_period_ix])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + boardp-> + sdtr_data[i] & ASC_SYN_MAX_OFFSET); + ASC_PRT_NEXT(); + } + + if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); + } - if (renegotiate) - { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); - } + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8314,237 +7126,242 @@ asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int i; - ADV_DVC_VAR *v; - ADV_DVC_CFG *c; - AdvPortAddr iop_base; - ushort chip_scsi_id; - ushort lramword; - uchar lrambyte; - ushort tagqng_able; - ushort sdtr_able, wdtr_able; - ushort wdtr_done, sdtr_done; - ushort period = 0; - int renegotiate = 0; - - boardp = ASC_BOARDP(shp); - v = &boardp->dvc_var.adv_dvc_var; - c = &boardp->dvc_cfg.adv_dvc_cfg; - iop_base = v->iop_base; - chip_scsi_id = v->chip_scsi_id; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" iop_base 0x%lx, cable_detect: %X, err_code %u\n", - v->iop_base, - AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT, - v->err_code); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n", - c->chip_version, c->lib_version, c->mcode_date, c->mcode_version); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - len = asc_prt_line(cp, leftlen, -" Queuing Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - len = asc_prt_line(cp, leftlen, -" Wide Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); - len = asc_prt_line(cp, leftlen, -" Transfer Bit Width:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); - - len = asc_prt_line(cp, leftlen, " %X:%d", - i, (lramword & 0x8000) ? 16 : 8); - ASC_PRT_NEXT(); - - if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && - (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*"); - ASC_PRT_NEXT(); - renegotiate = 1; - } - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - len = asc_prt_line(cp, leftlen, -" Synchronous Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); - for (i = 0; i <= ADV_MAX_TID; i++) { - - AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); - lramword &= ~0x8000; - - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F) == 0) /* Check for REQ/ACK Offset 0. */ - { - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, " Transfer Period Factor: "); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F00) == 0x1100) /* 80 Mhz */ - { - len = asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); - ASC_PRT_NEXT(); - } else if ((lramword & 0x1F00) == 0x1000) /* 40 Mhz */ - { - len = asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); - ASC_PRT_NEXT(); - } else /* 20 Mhz or below. */ - { - period = (((lramword >> 8) * 25) + 50)/4; - - if (period == 0) /* Should never happen. */ - { - len = asc_prt_line(cp, leftlen, "%d (? Mhz), "); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, - "%d (%d.%d Mhz),", - period, 250/period, ASC_TENTHS(250, period)); - ASC_PRT_NEXT(); - } - } - - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - lramword & 0x1F); - ASC_PRT_NEXT(); - } - - if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else - { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int i; + ADV_DVC_VAR *v; + ADV_DVC_CFG *c; + AdvPortAddr iop_base; + ushort chip_scsi_id; + ushort lramword; + uchar lrambyte; + ushort tagqng_able; + ushort sdtr_able, wdtr_able; + ushort wdtr_done, sdtr_done; + ushort period = 0; + int renegotiate = 0; + + boardp = ASC_BOARDP(shost); + v = &boardp->dvc_var.adv_dvc_var; + c = &boardp->dvc_cfg.adv_dvc_cfg; + iop_base = v->iop_base; + chip_scsi_id = v->chip_scsi_id; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " iop_base 0x%lx, cable_detect: %X, err_code %u\n", + v->iop_base, + AdvReadWordRegister(iop_base, + IOPW_SCSI_CFG1) & CABLE_DETECT, + v->err_code); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n", + c->chip_version, c->lib_version, c->mcode_date, + c->mcode_version); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + len = asc_prt_line(cp, leftlen, " Queuing Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, + lrambyte); + + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, + lrambyte); + + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + len = asc_prt_line(cp, leftlen, " Wide Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); + len = asc_prt_line(cp, leftlen, " Transfer Bit Width:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); + + len = asc_prt_line(cp, leftlen, " %X:%d", + i, (lramword & 0x8000) ? 16 : 8); + ASC_PRT_NEXT(); + + if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && + (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*"); + ASC_PRT_NEXT(); + renegotiate = 1; + } + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + len = asc_prt_line(cp, leftlen, " Synchronous Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); + for (i = 0; i <= ADV_MAX_TID; i++) { + + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); + lramword &= ~0x8000; + + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); + + if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */ + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + len = + asc_prt_line(cp, leftlen, + " Transfer Period Factor: "); + ASC_PRT_NEXT(); + + if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */ + len = + asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); + ASC_PRT_NEXT(); + } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */ + len = + asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); + ASC_PRT_NEXT(); + } else { /* 20 Mhz or below. */ + + period = (((lramword >> 8) * 25) + 50) / 4; + + if (period == 0) { /* Should never happen. */ + len = + asc_prt_line(cp, leftlen, + "%d (? Mhz), "); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + "%d (%d.%d Mhz),", + period, 250 / period, + ASC_TENTHS(250, + period)); + ASC_PRT_NEXT(); + } + } + + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + lramword & 0x1F); + ASC_PRT_NEXT(); + } + + if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); + } - if (renegotiate) - { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); - } + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8553,30 +7370,30 @@ asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen) * Copy proc information to a read buffer taking into account the current * read offset in the file and the remaining space in the read buffer. */ -STATIC int +static int asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, - char *cp, int cplen) + char *cp, int cplen) { - int cnt = 0; - - ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", - (unsigned) offset, (unsigned) advoffset, cplen); - if (offset <= advoffset) { - /* Read offset below current offset, copy everything. */ - cnt = min(cplen, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", - (ulong) curbuf, (ulong) cp, cnt); - memcpy(curbuf, cp, cnt); - } else if (offset < advoffset + cplen) { - /* Read offset within current range, partial copy. */ - cnt = (advoffset + cplen) - offset; - cp = (cp + cplen) - cnt; - cnt = min(cnt, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", - (ulong) curbuf, (ulong) cp, cnt); - memcpy(curbuf, cp, cnt); - } - return cnt; + int cnt = 0; + + ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", + (unsigned)offset, (unsigned)advoffset, cplen); + if (offset <= advoffset) { + /* Read offset below current offset, copy everything. */ + cnt = min(cplen, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } else if (offset < advoffset + cplen) { + /* Read offset within current range, partial copy. */ + cnt = (advoffset + cplen) - offset; + cp = (cp + cplen) - cnt; + cnt = min(cnt, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } + return cnt; } /* @@ -8590,29 +7407,27 @@ asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. */ -STATIC int -asc_prt_line(char *buf, int buflen, char *fmt, ...) +static int asc_prt_line(char *buf, int buflen, char *fmt, ...) { - va_list args; - int ret; - char s[ASC_PRTLINE_SIZE]; - - va_start(args, fmt); - ret = vsprintf(s, fmt, args); - ASC_ASSERT(ret < ASC_PRTLINE_SIZE); - if (buf == NULL) { - (void) printk(s); - ret = 0; - } else { - ret = min(buflen, ret); - memcpy(buf, s, ret); - } - va_end(args); - return ret; + va_list args; + int ret; + char s[ASC_PRTLINE_SIZE]; + + va_start(args, fmt); + ret = vsprintf(s, fmt, args); + ASC_ASSERT(ret < ASC_PRTLINE_SIZE); + if (buf == NULL) { + (void)printk(s); + ret = 0; + } else { + ret = min(buflen, ret); + memcpy(buf, s, ret); + } + va_end(args); + return ret; } #endif /* CONFIG_PROC_FS */ - /* * --- Functions Required by the Asc Library */ @@ -8623,31 +7438,28 @@ asc_prt_line(char *buf, int buflen, char *fmt, ...) * from a timer interrupt, because this function may be * called when interrupts are disabled. */ -STATIC void -DvcSleepMilliSecond(ADV_DCNT n) +static void DvcSleepMilliSecond(ADV_DCNT n) { - ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong) n); - mdelay(n); + ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n); + mdelay(n); } /* * Currently and inline noop but leave as a placeholder. * Leave DvcEnterCritical() as a noop placeholder. */ -STATIC inline ulong -DvcEnterCritical(void) +static inline ulong DvcEnterCritical(void) { - return 0; + return 0; } /* * Critical sections are all protected by the board spinlock. * Leave DvcLeaveCritical() as a noop placeholder. */ -STATIC inline void -DvcLeaveCritical(ulong flags) +static inline void DvcLeaveCritical(ulong flags) { - return; + return; } /* @@ -8660,20 +7472,20 @@ DvcLeaveCritical(ulong flags) * Description: * Output an ASC_SCSI_Q structure to the chip */ -STATIC void +static void DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) { - int i; - - ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - if (i == 4 || i == 20) { - continue; - } - outpw(iop_base + IOP_RAM_DATA, - ((ushort) outbuf[i + 1] << 8) | outbuf[i]); - } + int i; + + ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 4 || i == 20) { + continue; + } + outpw(iop_base + IOP_RAM_DATA, + ((ushort)outbuf[i + 1] << 8) | outbuf[i]); + } } /* @@ -8686,52 +7498,46 @@ DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) * Description: * Input an ASC_QDONE_INFO structure from the chip */ -STATIC void +static void DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) { - int i; - ushort word; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - if (i == 10) { - continue; - } - word = inpw(iop_base + IOP_RAM_DATA); - inbuf[i] = word & 0xff; - inbuf[i + 1] = (word >> 8) & 0xff; - } - ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); + int i; + ushort word; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 10) { + continue; + } + word = inpw(iop_base + IOP_RAM_DATA); + inbuf[i] = word & 0xff; + inbuf[i + 1] = (word >> 8) & 0xff; + } + ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); } /* * Read a PCI configuration byte. */ -STATIC uchar __init -DvcReadPCIConfigByte( - ASC_DVC_VAR *asc_dvc, - ushort offset) +static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset) { #ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; + uchar byte_data; + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); + return byte_data; #else /* !defined(CONFIG_PCI) */ - return 0; + return 0; #endif /* !defined(CONFIG_PCI) */ } /* * Write a PCI configuration byte. */ -STATIC void __init -DvcWritePCIConfigByte( - ASC_DVC_VAR *asc_dvc, - ushort offset, - uchar byte_data) +static void __init +DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) { #ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #endif /* CONFIG_PCI */ } @@ -8739,51 +7545,43 @@ DvcWritePCIConfigByte( * Return the BIOS address of the adapter at the specified * I/O port and with the specified bus type. */ -STATIC ushort __init -AscGetChipBiosAddress( - PortAddr iop_base, - ushort bus_type) +static ushort __init AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type) { - ushort cfg_lsw; - ushort bios_addr; - - /* - * The PCI BIOS is re-located by the motherboard BIOS. Because - * of this the driver can not determine where a PCI BIOS is - * loaded and executes. - */ - if (bus_type & ASC_IS_PCI) - { - return(0); - } - + ushort cfg_lsw; + ushort bios_addr; + + /* + * The PCI BIOS is re-located by the motherboard BIOS. Because + * of this the driver can not determine where a PCI BIOS is + * loaded and executes. + */ + if (bus_type & ASC_IS_PCI) { + return (0); + } #ifdef CONFIG_ISA - if((bus_type & ASC_IS_EISA) != 0) - { - cfg_lsw = AscGetEisaChipCfg(iop_base); - cfg_lsw &= 0x000F; - bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + - (cfg_lsw * ASC_BIOS_BANK_SIZE)); - return(bios_addr); - }/* if */ + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + cfg_lsw &= 0x000F; + bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + + (cfg_lsw * ASC_BIOS_BANK_SIZE)); + return (bios_addr); + } /* if */ #endif /* CONFIG_ISA */ - cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); - /* - * ISA PnP uses the top bit as the 32K BIOS flag - */ - if (bus_type == ASC_IS_ISAPNP) - { - cfg_lsw &= 0x7FFF; - }/* if */ - - bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + - ASC_BIOS_MIN_ADDR); - return(bios_addr); + /* + * ISA PnP uses the top bit as the 32K BIOS flag + */ + if (bus_type == ASC_IS_ISAPNP) { + cfg_lsw &= 0x7FFF; + } + /* if */ + bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + + ASC_BIOS_MIN_ADDR); + return (bios_addr); } - /* * --- Functions Required by the Adv Library */ @@ -8801,49 +7599,44 @@ AscGetChipBiosAddress( */ ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, - uchar *vaddr, ADV_SDCNT *lenp, int flag) + uchar *vaddr, ADV_SDCNT *lenp, int flag) { - ADV_PADDR paddr; + ADV_PADDR paddr; - paddr = virt_to_bus(vaddr); + paddr = virt_to_bus(vaddr); - ASC_DBG4(4, - "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", - (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), (ulong) paddr); + ASC_DBG4(4, + "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", + (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp), + (ulong)paddr); - return paddr; + return paddr; } /* * Read a PCI configuration byte. */ -STATIC uchar __init -DvcAdvReadPCIConfigByte( - ADV_DVC_VAR *asc_dvc, - ushort offset) +static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset) { #ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; + uchar byte_data; + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); + return byte_data; #else /* CONFIG_PCI */ - return 0; + return 0; #endif /* CONFIG_PCI */ } /* * Write a PCI configuration byte. */ -STATIC void __init -DvcAdvWritePCIConfigByte( - ADV_DVC_VAR *asc_dvc, - ushort offset, - uchar byte_data) +static void __init +DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) { #ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #else /* CONFIG_PCI */ - return; + return; #endif /* CONFIG_PCI */ } @@ -8862,97 +7655,98 @@ DvcAdvWritePCIConfigByte( * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - asc_board_t *boardp; - - leftlen = cplen; - totlen = len = 0; - - boardp = ASC_BOARDP(shp); - s = &boardp->asc_stats; - - len = asc_prt_line(cp, leftlen, -"\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", - s->queuecommand, s->reset, s->biosparam, s->interrupt); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", - s->callback, s->done, s->build_error, s->adv_build_noreq, - s->adv_build_nosg); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", - s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown); - ASC_PRT_NEXT(); - - /* - * Display data transfer statistics. - */ - if (s->cont_cnt > 0) { - len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", - s->cont_xfer/2, - ASC_TENTHS(s->cont_xfer, 2)); - ASC_PRT_NEXT(); - - /* Contiguous transfer average size */ - len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", - (s->cont_xfer/2)/s->cont_cnt, - ASC_TENTHS((s->cont_xfer/2), s->cont_cnt)); - ASC_PRT_NEXT(); - } + int leftlen; + int totlen; + int len; + struct asc_stats *s; + asc_board_t *boardp; - if (s->sg_cnt > 0) { + leftlen = cplen; + totlen = len = 0; + + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; + + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", + s->queuecommand, s->reset, s->biosparam, + s->interrupt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", + s->callback, s->done, s->build_error, + s->adv_build_noreq, s->adv_build_nosg); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", + s->exe_noerror, s->exe_busy, s->exe_error, + s->exe_unknown); + ASC_PRT_NEXT(); + + /* + * Display data transfer statistics. + */ + if (s->cont_cnt > 0) { + len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", + s->cont_xfer / 2, + ASC_TENTHS(s->cont_xfer, 2)); + ASC_PRT_NEXT(); + + /* Contiguous transfer average size */ + len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", + (s->cont_xfer / 2) / s->cont_cnt, + ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt)); + ASC_PRT_NEXT(); + } - len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", - s->sg_cnt, s->sg_elem); - ASC_PRT_NEXT(); + if (s->sg_cnt > 0) { - len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", - s->sg_xfer/2, - ASC_TENTHS(s->sg_xfer, 2)); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", + s->sg_cnt, s->sg_elem); + ASC_PRT_NEXT(); - /* Scatter gather transfer statistics */ - len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", - s->sg_elem/s->sg_cnt, - ASC_TENTHS(s->sg_elem, s->sg_cnt)); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", + s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2)); + ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", - (s->sg_xfer/2)/s->sg_elem, - ASC_TENTHS((s->sg_xfer/2), s->sg_elem)); - ASC_PRT_NEXT(); + /* Scatter gather transfer statistics */ + len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", + s->sg_elem / s->sg_cnt, + ASC_TENTHS(s->sg_elem, s->sg_cnt)); + ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", - (s->sg_xfer/2)/s->sg_cnt, - ASC_TENTHS((s->sg_xfer/2), s->sg_cnt)); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", + (s->sg_xfer / 2) / s->sg_elem, + ASC_TENTHS((s->sg_xfer / 2), s->sg_elem)); + ASC_PRT_NEXT(); - /* - * Display request queuing statistics. - */ - len = asc_prt_line(cp, leftlen, -" Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", + (s->sg_xfer / 2) / s->sg_cnt, + ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt)); + ASC_PRT_NEXT(); + } + /* + * Display request queuing statistics. + */ + len = asc_prt_line(cp, leftlen, + " Active and Waiting Request Queues (Time Unit: %d HZ):\n", + HZ); + ASC_PRT_NEXT(); - return totlen; + return totlen; } /* @@ -8967,70 +7761,89 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_target_stats(struct Scsi_Host *shp, int tgt_id, char *cp, int cplen) +static int +asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - ushort chip_scsi_id; - asc_board_t *boardp; - asc_queue_t *active; - asc_queue_t *waiting; - - leftlen = cplen; - totlen = len = 0; - - boardp = ASC_BOARDP(shp); - s = &boardp->asc_stats; - - active = &ASC_BOARDP(shp)->active; - waiting = &ASC_BOARDP(shp)->waiting; - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + int leftlen; + int totlen; + int len; + struct asc_stats *s; + ushort chip_scsi_id; + asc_board_t *boardp; + asc_queue_t *active; + asc_queue_t *waiting; - if ((chip_scsi_id == tgt_id) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { - return 0; - } + leftlen = cplen; + totlen = len = 0; + + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; + + active = &ASC_BOARDP(shost)->active; + waiting = &ASC_BOARDP(shost)->waiting; + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } + + if ((chip_scsi_id == tgt_id) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { + return 0; + } - do { - if (active->q_tot_cnt[tgt_id] > 0 || waiting->q_tot_cnt[tgt_id] > 0) { - len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", - active->q_cur_cnt[tgt_id], active->q_max_cnt[tgt_id], - active->q_tot_cnt[tgt_id], - active->q_min_tim[tgt_id], active->q_max_tim[tgt_id], - (active->q_tot_cnt[tgt_id] == 0) ? 0 : - (active->q_tot_tim[tgt_id]/active->q_tot_cnt[tgt_id]), - (active->q_tot_cnt[tgt_id] == 0) ? 0 : - ASC_TENTHS(active->q_tot_tim[tgt_id], - active->q_tot_cnt[tgt_id])); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", - waiting->q_cur_cnt[tgt_id], waiting->q_max_cnt[tgt_id], - waiting->q_tot_cnt[tgt_id], - waiting->q_min_tim[tgt_id], waiting->q_max_tim[tgt_id], - (waiting->q_tot_cnt[tgt_id] == 0) ? 0 : - (waiting->q_tot_tim[tgt_id]/waiting->q_tot_cnt[tgt_id]), - (waiting->q_tot_cnt[tgt_id] == 0) ? 0 : - ASC_TENTHS(waiting->q_tot_tim[tgt_id], - waiting->q_tot_cnt[tgt_id])); - ASC_PRT_NEXT(); - } - } while (0); - - return totlen; + do { + if (active->q_tot_cnt[tgt_id] > 0 + || waiting->q_tot_cnt[tgt_id] > 0) { + len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", + active->q_cur_cnt[tgt_id], + active->q_max_cnt[tgt_id], + active->q_tot_cnt[tgt_id], + active->q_min_tim[tgt_id], + active->q_max_tim[tgt_id], + (active->q_tot_cnt[tgt_id] == + 0) ? 0 : (active-> + q_tot_tim[tgt_id] / + active-> + q_tot_cnt[tgt_id]), + (active->q_tot_cnt[tgt_id] == + 0) ? 0 : ASC_TENTHS(active-> + q_tot_tim + [tgt_id], + active-> + q_tot_cnt + [tgt_id])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", + waiting->q_cur_cnt[tgt_id], + waiting->q_max_cnt[tgt_id], + waiting->q_tot_cnt[tgt_id], + waiting->q_min_tim[tgt_id], + waiting->q_max_tim[tgt_id], + (waiting->q_tot_cnt[tgt_id] == + 0) ? 0 : (waiting-> + q_tot_tim[tgt_id] / + waiting-> + q_tot_cnt[tgt_id]), + (waiting->q_tot_cnt[tgt_id] == + 0) ? 0 : ASC_TENTHS(waiting-> + q_tot_tim + [tgt_id], + waiting-> + q_tot_cnt + [tgt_id])); + ASC_PRT_NEXT(); + } + } while (0); + + return totlen; } #endif /* CONFIG_PROC_FS */ #endif /* ADVANSYS_STATS */ @@ -9039,207 +7852,181 @@ asc_prt_target_stats(struct Scsi_Host *shp, int tgt_id, char *cp, int cplen) /* * asc_prt_scsi_host() */ -STATIC void -asc_prt_scsi_host(struct Scsi_Host *s) +static void asc_prt_scsi_host(struct Scsi_Host *s) { - asc_board_t *boardp; - - boardp = ASC_BOARDP(s); - - printk("Scsi_Host at addr 0x%lx\n", (ulong) s); - printk( -" host_busy %u, host_no %d, last_reset %d,\n", - s->host_busy, s->host_no, - (unsigned) s->last_reset); - - printk( -" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", - (ulong) s->base, (ulong) s->io_port, s->n_io_port, s->irq); - - printk( -" dma_channel %d, this_id %d, can_queue %d,\n", - s->dma_channel, s->this_id, s->can_queue); - - printk( -" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); - - if (ASC_NARROW_BOARD(boardp)) { - asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); - asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); - } else { - asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); - asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); - } + asc_board_t *boardp; + + boardp = ASC_BOARDP(s); + + printk("Scsi_Host at addr 0x%lx\n", (ulong)s); + printk(" host_busy %u, host_no %d, last_reset %d,\n", + s->host_busy, s->host_no, (unsigned)s->last_reset); + + printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", + (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq); + + printk(" dma_channel %d, this_id %d, can_queue %d,\n", + s->dma_channel, s->this_id, s->can_queue); + + printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); + + if (ASC_NARROW_BOARD(boardp)) { + asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); + asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); + } else { + asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); + asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); + } } /* * asc_prt_scsi_cmnd() */ -STATIC void -asc_prt_scsi_cmnd(struct scsi_cmnd *s) +static void asc_prt_scsi_cmnd(struct scsi_cmnd *s) { - printk("struct scsi_cmnd at addr 0x%lx\n", (ulong) s); + printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s); - printk( -" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", - (ulong) s->device->host, (ulong) s->device, s->device->id, s->device->lun, - s->device->channel); + printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", + (ulong)s->device->host, (ulong)s->device, s->device->id, + s->device->lun, s->device->channel); - asc_prt_hex(" CDB", s->cmnd, s->cmd_len); + asc_prt_hex(" CDB", s->cmnd, s->cmd_len); - printk ( -"sc_data_direction %u, resid %d\n", - s->sc_data_direction, s->resid); + printk("sc_data_direction %u, resid %d\n", + s->sc_data_direction, s->resid); - printk( -" use_sg %u, sglist_len %u\n", - s->use_sg, s->sglist_len); + printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); - printk( -" serial_number 0x%x, retries %d, allowed %d\n", - (unsigned) s->serial_number, s->retries, s->allowed); + printk(" serial_number 0x%x, retries %d, allowed %d\n", + (unsigned)s->serial_number, s->retries, s->allowed); - printk( -" timeout_per_command %d\n", - s->timeout_per_command); + printk(" timeout_per_command %d\n", s->timeout_per_command); - printk( -" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", - (ulong) s->scsi_done, (ulong) s->done, - (ulong) s->host_scribble, s->result); + printk + (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", + (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble, + s->result); - printk( -" tag %u, pid %u\n", - (unsigned) s->tag, (unsigned) s->pid); + printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); } /* * asc_prt_asc_dvc_var() */ -STATIC void -asc_prt_asc_dvc_var(ASC_DVC_VAR *h) +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) { - printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong) h); - - printk( -" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n", - h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); - - printk( -" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n", - h->bus_type, (ulong) h->isr_callback, (ulong) h->exe_callback, - (unsigned) h->init_sdtr); - - printk( -" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n", - (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng, - (unsigned) h->unit_not_ready, (unsigned) h->chip_no); - - printk( -" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n", - (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor, - (unsigned) h->scsi_reset_wait); - - printk( -" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n", - (unsigned) h->is_in_int, (unsigned) h->max_total_qng, - (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt); - - printk( -" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n", - (unsigned) h->last_q_shortage, (unsigned) h->init_state, - (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer); - - printk( -" cfg 0x%lx, irq_no 0x%x\n", - (ulong) h->cfg, (unsigned) h->irq_no); + printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); + + printk + (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n", + h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); + + printk + (" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n", + h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback, + (unsigned)h->init_sdtr); + + printk + (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n", + (unsigned)h->sdtr_done, (unsigned)h->use_tagged_qng, + (unsigned)h->unit_not_ready, (unsigned)h->chip_no); + + printk + (" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n", + (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor, + (unsigned)h->scsi_reset_wait); + + printk + (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n", + (unsigned)h->is_in_int, (unsigned)h->max_total_qng, + (unsigned)h->cur_total_qng, (unsigned)h->in_critical_cnt); + + printk + (" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n", + (unsigned)h->last_q_shortage, (unsigned)h->init_state, + (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer); + + printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); } /* * asc_prt_asc_dvc_cfg() */ -STATIC void -asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) { - printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong) h); - - printk( -" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", - h->can_tagged_qng, h->cmd_qng_enabled); - printk( -" disc_enable 0x%x, sdtr_enable 0x%x,\n", - h->disc_enable, h->sdtr_enable); - - printk( -" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", - h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, - h->chip_version); - - printk( -" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", - to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, - h->mcode_date); - - printk( -" mcode_version %d, overrun_buf 0x%lx\n", - h->mcode_version, (ulong) h->overrun_buf); + printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); + + printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", + h->can_tagged_qng, h->cmd_qng_enabled); + printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", + h->disc_enable, h->sdtr_enable); + + printk + (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", + h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, + h->chip_version); + + printk + (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", + to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, + h->mcode_date); + + printk(" mcode_version %d, overrun_buf 0x%lx\n", + h->mcode_version, (ulong)h->overrun_buf); } /* * asc_prt_asc_scsi_q() */ -STATIC void -asc_prt_asc_scsi_q(ASC_SCSI_Q *q) +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) { - ASC_SG_HEAD *sgp; - int i; - - printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong) q); - - printk( -" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", - q->q2.target_ix, q->q1.target_lun, - (ulong) q->q2.srb_ptr, q->q2.tag_code); - - printk( -" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong) le32_to_cpu(q->q1.data_addr), - (ulong) le32_to_cpu(q->q1.data_cnt), - (ulong) le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); - - printk( -" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", - (ulong) q->cdbptr, q->q2.cdb_len, - (ulong) q->sg_head, q->q1.sg_queue_cnt); - - if (q->sg_head) { - sgp = q->sg_head; - printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong) sgp); - printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt); - for (i = 0; i < sgp->entry_cnt; i++) { - printk(" [%u]: addr 0x%lx, bytes %lu\n", - i, (ulong) le32_to_cpu(sgp->sg_list[i].addr), - (ulong) le32_to_cpu(sgp->sg_list[i].bytes)); - } + ASC_SG_HEAD *sgp; + int i; + + printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); + + printk + (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", + q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, + q->q2.tag_code); + + printk + (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->q1.data_addr), + (ulong)le32_to_cpu(q->q1.data_cnt), + (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); + + printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", + (ulong)q->cdbptr, q->q2.cdb_len, + (ulong)q->sg_head, q->q1.sg_queue_cnt); + + if (q->sg_head) { + sgp = q->sg_head; + printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); + printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, + sgp->queue_cnt); + for (i = 0; i < sgp->entry_cnt; i++) { + printk(" [%u]: addr 0x%lx, bytes %lu\n", + i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), + (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); + } - } + } } /* * asc_prt_asc_qdone_info() */ -STATIC void -asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) +static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) { - printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong) q); - printk( -" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", - (ulong) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, - q->d2.tag_code); - printk( -" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", - q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); + printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); + printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", + (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, + q->d2.tag_code); + printk + (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", + q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); } /* @@ -9247,41 +8034,33 @@ asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) * * Display an ADV_DVC_VAR structure. */ -STATIC void -asc_prt_adv_dvc_var(ADV_DVC_VAR *h) +static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) { - printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h); - - printk( -" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", - (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able); - - printk( -" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", - (ulong) h->isr_callback, (unsigned) h->sdtr_able, - (unsigned) h->wdtr_able); - - printk( -" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", - (unsigned) h->start_motor, - (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); - - printk( -" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", - (unsigned) h->max_host_qng, (unsigned) h->max_dvc_qng, - (ulong) h->carr_freelist); - - printk( -" icq_sp 0x%lx, irq_sp 0x%lx\n", - (ulong) h->icq_sp, (ulong) h->irq_sp); - - printk( -" no_scam 0x%x, tagqng_able 0x%x\n", - (unsigned) h->no_scam, (unsigned) h->tagqng_able); - - printk( -" chip_scsi_id 0x%x, cfg 0x%lx\n", - (unsigned) h->chip_scsi_id, (ulong) h->cfg); + printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); + + printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", + (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); + + printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", + (ulong)h->isr_callback, (unsigned)h->sdtr_able, + (unsigned)h->wdtr_able); + + printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", + (unsigned)h->start_motor, + (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no); + + printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", + (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, + (ulong)h->carr_freelist); + + printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", + (ulong)h->icq_sp, (ulong)h->irq_sp); + + printk(" no_scam 0x%x, tagqng_able 0x%x\n", + (unsigned)h->no_scam, (unsigned)h->tagqng_able); + + printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", + (unsigned)h->chip_scsi_id, (ulong)h->cfg); } /* @@ -9289,26 +8068,21 @@ asc_prt_adv_dvc_var(ADV_DVC_VAR *h) * * Display an ADV_DVC_CFG structure. */ -STATIC void -asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) +static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) { - printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h); + printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); - printk( -" disc_enable 0x%x, termination 0x%x\n", - h->disc_enable, h->termination); + printk(" disc_enable 0x%x, termination 0x%x\n", + h->disc_enable, h->termination); - printk( -" chip_version 0x%x, mcode_date 0x%x\n", - h->chip_version, h->mcode_date); + printk(" chip_version 0x%x, mcode_date 0x%x\n", + h->chip_version, h->mcode_date); - printk( -" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", - h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); + printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", + h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); - printk( -" control_flag 0x%x, pci_slot_info 0x%x\n", - h->control_flag, h->pci_slot_info); + printk(" control_flag 0x%x, pci_slot_info 0x%x\n", + h->control_flag, h->pci_slot_info); } /* @@ -9316,60 +8090,54 @@ asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) * * Display an ADV_SCSI_REQ_Q structure. */ -STATIC void -asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) +static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) { - int sg_blk_cnt; - struct asc_sg_block *sg_ptr; - - printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong) q); - - printk( -" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", - q->target_id, q->target_lun, (ulong) q->srb_ptr, q->a_flag); - - printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", - q->cntl, (ulong) le32_to_cpu(q->data_addr), (ulong) q->vdata_addr); - - printk( -" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong) le32_to_cpu(q->data_cnt), - (ulong) le32_to_cpu(q->sense_addr), q->sense_len); - - printk( -" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", - q->cdb_len, q->done_status, q->host_status, q->scsi_status); - - printk( -" sg_working_ix 0x%x, target_cmd %u\n", - q->sg_working_ix, q->target_cmd); - - printk( -" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", - (ulong) le32_to_cpu(q->scsiq_rptr), - (ulong) le32_to_cpu(q->sg_real_addr), (ulong) q->sg_list_ptr); - - /* Display the request's ADV_SG_BLOCK structures. */ - if (q->sg_list_ptr != NULL) - { - sg_blk_cnt = 0; - while (1) { - /* - * 'sg_ptr' is a physical address. Convert it to a virtual - * address by indexing 'sg_blk_cnt' into the virtual address - * array 'sg_list_ptr'. - * - * XXX - Assumes all SG physical blocks are virtually contiguous. - */ - sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[sg_blk_cnt]); - asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); - if (sg_ptr->sg_ptr == 0) - { - break; - } - sg_blk_cnt++; - } - } + int sg_blk_cnt; + struct asc_sg_block *sg_ptr; + + printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); + + printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", + q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); + + printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", + q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); + + printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->data_cnt), + (ulong)le32_to_cpu(q->sense_addr), q->sense_len); + + printk + (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", + q->cdb_len, q->done_status, q->host_status, q->scsi_status); + + printk(" sg_working_ix 0x%x, target_cmd %u\n", + q->sg_working_ix, q->target_cmd); + + printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", + (ulong)le32_to_cpu(q->scsiq_rptr), + (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); + + /* Display the request's ADV_SG_BLOCK structures. */ + if (q->sg_list_ptr != NULL) { + sg_blk_cnt = 0; + while (1) { + /* + * 'sg_ptr' is a physical address. Convert it to a virtual + * address by indexing 'sg_blk_cnt' into the virtual address + * array 'sg_list_ptr'. + * + * XXX - Assumes all SG physical blocks are virtually contiguous. + */ + sg_ptr = + &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); + asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); + if (sg_ptr->sg_ptr == 0) { + break; + } + sg_blk_cnt++; + } + } } /* @@ -9377,24 +8145,23 @@ asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) * * Display an ADV_SG_BLOCK structure. */ -STATIC void -asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) +static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) { - int i; - - printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", - (ulong) b, sgblockno); - printk(" sg_cnt %u, sg_ptr 0x%lx\n", - b->sg_cnt, (ulong) le32_to_cpu(b->sg_ptr)); - ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK); - if (b->sg_ptr != 0) - { - ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK); - } - for (i = 0; i < b->sg_cnt; i++) { - printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", - i, (ulong) b->sg_list[i].sg_addr, (ulong) b->sg_list[i].sg_count); - } + int i; + + printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", + (ulong)b, sgblockno); + printk(" sg_cnt %u, sg_ptr 0x%lx\n", + b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); + ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK); + if (b->sg_ptr != 0) { + ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK); + } + for (i = 0; i < b->sg_cnt; i++) { + printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", + i, (ulong)b->sg_list[i].sg_addr, + (ulong)b->sg_list[i].sg_count); + } } /* @@ -9403,55 +8170,55 @@ asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) * Print hexadecimal output in 4 byte groupings 32 bytes * or 8 double-words per line. */ -STATIC void -asc_prt_hex(char *f, uchar *s, int l) +static void asc_prt_hex(char *f, uchar *s, int l) { - int i; - int j; - int k; - int m; - - printk("%s: (%d bytes)\n", f, l); - - for (i = 0; i < l; i += 32) { - - /* Display a maximum of 8 double-words per line. */ - if ((k = (l - i) / 4) >= 8) { - k = 8; - m = 0; - } else { - m = (l - i) % 4; - } - - for (j = 0; j < k; j++) { - printk(" %2.2X%2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1], - (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]); - } - - switch (m) { - case 0: - default: - break; - case 1: - printk(" %2.2X", - (unsigned) s[i+(j*4)]); - break; - case 2: - printk(" %2.2X%2.2X", - (unsigned) s[i+(j*4)], - (unsigned) s[i+(j*4)+1]); - break; - case 3: - printk(" %2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)+1], - (unsigned) s[i+(j*4)+2], - (unsigned) s[i+(j*4)+3]); - break; - } - - printk("\n"); - } + int i; + int j; + int k; + int m; + + printk("%s: (%d bytes)\n", f, l); + + for (i = 0; i < l; i += 32) { + + /* Display a maximum of 8 double-words per line. */ + if ((k = (l - i) / 4) >= 8) { + k = 8; + m = 0; + } else { + m = (l - i) % 4; + } + + for (j = 0; j < k; j++) { + printk(" %2.2X%2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); + } + + switch (m) { + case 0: + default: + break; + case 1: + printk(" %2.2X", (unsigned)s[i + (j * 4)]); + break; + case 2: + printk(" %2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1]); + break; + case 3: + printk(" %2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); + break; + } + + printk("\n"); + } } #endif /* ADVANSYS_DEBUG */ @@ -9459,3380 +8226,3400 @@ asc_prt_hex(char *f, uchar *s, int l) * --- Asc Library Functions */ -STATIC ushort __init -AscGetEisaChipCfg( - PortAddr iop_base) +static ushort __init AscGetEisaChipCfg(PortAddr iop_base) { - PortAddr eisa_cfg_iop; + PortAddr eisa_cfg_iop; - eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) (ASC_EISA_CFG_IOP_MASK); - return (inpw(eisa_cfg_iop)); + eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) (ASC_EISA_CFG_IOP_MASK); + return (inpw(eisa_cfg_iop)); } -STATIC uchar __init -AscSetChipScsiID( - PortAddr iop_base, - uchar new_host_id -) +static uchar __init AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) { - ushort cfg_lsw; + ushort cfg_lsw; - if (AscGetChipScsiID(iop_base) == new_host_id) { - return (new_host_id); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - cfg_lsw &= 0xF8FF; - cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipScsiID(iop_base)); + if (AscGetChipScsiID(iop_base) == new_host_id) { + return (new_host_id); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw &= 0xF8FF; + cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipScsiID(iop_base)); } -STATIC uchar __init -AscGetChipScsiCtrl( - PortAddr iop_base) +static uchar __init AscGetChipScsiCtrl(PortAddr iop_base) { - uchar sc; + uchar sc; - AscSetBank(iop_base, 1); - sc = inp(iop_base + IOP_REG_SC); - AscSetBank(iop_base, 0); - return (sc); + AscSetBank(iop_base, 1); + sc = inp(iop_base + IOP_REG_SC); + AscSetBank(iop_base, 0); + return (sc); } -STATIC uchar __init -AscGetChipVersion( - PortAddr iop_base, - ushort bus_type -) +static uchar __init AscGetChipVersion(PortAddr iop_base, ushort bus_type) { - if ((bus_type & ASC_IS_EISA) != 0) { - PortAddr eisa_iop; - uchar revision; - eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) ASC_EISA_REV_IOP_MASK; - revision = inp(eisa_iop); - return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision)); - } - return (AscGetChipVerNo(iop_base)); + if ((bus_type & ASC_IS_EISA) != 0) { + PortAddr eisa_iop; + uchar revision; + eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) ASC_EISA_REV_IOP_MASK; + revision = inp(eisa_iop); + return ((uchar)((ASC_CHIP_MIN_VER_EISA - 1) + revision)); + } + return (AscGetChipVerNo(iop_base)); } -STATIC ushort __init -AscGetChipBusType( - PortAddr iop_base) +static ushort __init AscGetChipBusType(PortAddr iop_base) { - ushort chip_ver; - - chip_ver = AscGetChipVerNo(iop_base); - if ( - (chip_ver >= ASC_CHIP_MIN_VER_VL) - && (chip_ver <= ASC_CHIP_MAX_VER_VL) -) { - if ( - ((iop_base & 0x0C30) == 0x0C30) - || ((iop_base & 0x0C50) == 0x0C50) -) { - return (ASC_IS_EISA); - } - return (ASC_IS_VL); - } - if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && - (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { - if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { - return (ASC_IS_ISAPNP); - } - return (ASC_IS_ISA); - } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && - (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { - return (ASC_IS_PCI); - } - return (0); + ushort chip_ver; + + chip_ver = AscGetChipVerNo(iop_base); + if ((chip_ver >= ASC_CHIP_MIN_VER_VL) + && (chip_ver <= ASC_CHIP_MAX_VER_VL) + ) { + if (((iop_base & 0x0C30) == 0x0C30) + || ((iop_base & 0x0C50) == 0x0C50) + ) { + return (ASC_IS_EISA); + } + return (ASC_IS_VL); + } + if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && + (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { + if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { + return (ASC_IS_ISAPNP); + } + return (ASC_IS_ISA); + } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && + (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { + return (ASC_IS_PCI); + } + return (0); } -STATIC ASC_DCNT -AscLoadMicroCode( - PortAddr iop_base, - ushort s_addr, - uchar *mcode_buf, - ushort mcode_size -) +static ASC_DCNT +AscLoadMicroCode(PortAddr iop_base, + ushort s_addr, uchar *mcode_buf, ushort mcode_size) { - ASC_DCNT chksum; - ushort mcode_word_size; - ushort mcode_chksum; - - /* Write the microcode buffer starting at LRAM address 0. */ - mcode_word_size = (ushort) (mcode_size >> 1); - AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); - AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); - - chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); - ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong) chksum); - mcode_chksum = (ushort) AscMemSumLramWord(iop_base, - (ushort) ASC_CODE_SEC_BEG, - (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2)); - ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n", - (ulong) mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); - return (chksum); + ASC_DCNT chksum; + ushort mcode_word_size; + ushort mcode_chksum; + + /* Write the microcode buffer starting at LRAM address 0. */ + mcode_word_size = (ushort)(mcode_size >> 1); + AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); + AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); + + chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); + ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum); + mcode_chksum = (ushort)AscMemSumLramWord(iop_base, + (ushort)ASC_CODE_SEC_BEG, + (ushort)((mcode_size - + s_addr - (ushort) + ASC_CODE_SEC_BEG) / + 2)); + ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n", + (ulong)mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); + return (chksum); } -STATIC int -AscFindSignature( - PortAddr iop_base -) +static int AscFindSignature(PortAddr iop_base) { - ushort sig_word; - - ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureByte(iop_base)); - if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) { - ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureWord(iop_base)); - sig_word = AscGetChipSignatureWord(iop_base); - if ((sig_word == (ushort) ASC_1000_ID0W) || - (sig_word == (ushort) ASC_1000_ID0W_FIX)) { - return (1); - } - } - return (0); + ushort sig_word; + + ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureByte(iop_base)); + if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { + ASC_DBG2(1, + "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureWord(iop_base)); + sig_word = AscGetChipSignatureWord(iop_base); + if ((sig_word == (ushort)ASC_1000_ID0W) || + (sig_word == (ushort)ASC_1000_ID0W_FIX)) { + return (1); + } + } + return (0); } -STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = -{ - 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, - ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 +static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = { + 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, + ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 }; #ifdef CONFIG_ISA -STATIC uchar _isa_pnp_inited __initdata = 0; +static uchar _isa_pnp_inited __initdata = 0; -STATIC PortAddr __init -AscSearchIOPortAddr( - PortAddr iop_beg, - ushort bus_type) +static PortAddr __init AscSearchIOPortAddr(PortAddr iop_beg, ushort bus_type) { - if (bus_type & ASC_IS_VL) { - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_ISA) { - if (_isa_pnp_inited == 0) { - AscSetISAPNPWaitForKey(); - _isa_pnp_inited++; - } - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_EISA) { - if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { - return (iop_beg); - } - return (0); - } - return (0); + if (bus_type & ASC_IS_VL) { + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if (AscGetChipVersion(iop_beg, bus_type) <= + ASC_CHIP_MAX_VER_VL) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_ISA) { + if (_isa_pnp_inited == 0) { + AscSetISAPNPWaitForKey(); + _isa_pnp_inited++; + } + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if ((AscGetChipVersion(iop_beg, bus_type) & + ASC_CHIP_VER_ISA_BIT) != 0) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_EISA) { + if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { + return (iop_beg); + } + return (0); + } + return (0); } -STATIC PortAddr __init -AscSearchIOPortAddr11( - PortAddr s_addr -) +static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr) { - int i; - PortAddr iop_base; + int i; + PortAddr iop_base; - for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { - if (_asc_def_iop_base[i] > s_addr) { - break; - } - } - for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { - iop_base = _asc_def_iop_base[i]; - if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){ - ASC_DBG1(1, - "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", - iop_base); - continue; - } - ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base); - release_region(iop_base, ASC_IOADR_GAP); - if (AscFindSignature(iop_base)) { - return (iop_base); - } - } - return (0); + for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { + if (_asc_def_iop_base[i] > s_addr) { + break; + } + } + for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { + iop_base = _asc_def_iop_base[i]; + if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { + ASC_DBG1(1, + "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", + iop_base); + continue; + } + ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", + iop_base); + release_region(iop_base, ASC_IOADR_GAP); + if (AscFindSignature(iop_base)) { + return (iop_base); + } + } + return (0); } -STATIC void __init -AscSetISAPNPWaitForKey(void) +static void __init AscSetISAPNPWaitForKey(void) { - outp(ASC_ISA_PNP_PORT_ADDR, 0x02); - outp(ASC_ISA_PNP_PORT_WRITE, 0x02); - return; + outp(ASC_ISA_PNP_PORT_ADDR, 0x02); + outp(ASC_ISA_PNP_PORT_WRITE, 0x02); + return; } #endif /* CONFIG_ISA */ -STATIC void __init -AscToggleIRQAct( - PortAddr iop_base -) +static void __init AscToggleIRQAct(PortAddr iop_base) { - AscSetChipStatus(iop_base, CIW_IRQ_ACT); - AscSetChipStatus(iop_base, 0); - return; + AscSetChipStatus(iop_base, CIW_IRQ_ACT); + AscSetChipStatus(iop_base, 0); + return; } -STATIC uchar __init -AscGetChipIRQ( - PortAddr iop_base, - ushort bus_type) +static uchar __init AscGetChipIRQ(PortAddr iop_base, ushort bus_type) { - ushort cfg_lsw; - uchar chip_irq; - - if ((bus_type & ASC_IS_EISA) != 0) { - cfg_lsw = AscGetEisaChipCfg(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10); - if ((chip_irq == 13) || (chip_irq > 15)) { - return (0); - } - return (chip_irq); - } - if ((bus_type & ASC_IS_VL) != 0) { - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07)); - if ((chip_irq == 0) || - (chip_irq == 4) || - (chip_irq == 7)) { - return (0); - } - return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1))); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03)); - if (chip_irq == 3) - chip_irq += (uchar) 2; - return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); + ushort cfg_lsw; + uchar chip_irq; + + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10); + if ((chip_irq == 13) || (chip_irq > 15)) { + return (0); + } + return (chip_irq); + } + if ((bus_type & ASC_IS_VL) != 0) { + cfg_lsw = AscGetChipCfgLsw(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07)); + if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) { + return (0); + } + return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1))); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03)); + if (chip_irq == 3) + chip_irq += (uchar)2; + return ((uchar)(chip_irq + ASC_MIN_IRQ_NO)); } -STATIC uchar __init -AscSetChipIRQ( - PortAddr iop_base, - uchar irq_no, - ushort bus_type) +static uchar __init +AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) { - ushort cfg_lsw; - - if ((bus_type & ASC_IS_VL) != 0) { - if (irq_no != 0) { - if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) { - irq_no = 0; - } else { - irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1)); - } - } - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3); - cfg_lsw |= (ushort) 0x0010; - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0); - cfg_lsw |= (ushort) ((irq_no & 0x07) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - return (AscGetChipIRQ(iop_base, bus_type)); - } - if ((bus_type & (ASC_IS_ISA)) != 0) { - if (irq_no == 15) - irq_no -= (uchar) 2; - irq_no -= (uchar) ASC_MIN_IRQ_NO; - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3); - cfg_lsw |= (ushort) ((irq_no & 0x03) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipIRQ(iop_base, bus_type)); - } - return (0); + ushort cfg_lsw; + + if ((bus_type & ASC_IS_VL) != 0) { + if (irq_no != 0) { + if ((irq_no < ASC_MIN_IRQ_NO) + || (irq_no > ASC_MAX_IRQ_NO)) { + irq_no = 0; + } else { + irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1)); + } + } + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3); + cfg_lsw |= (ushort)0x0010; + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0); + cfg_lsw |= (ushort)((irq_no & 0x07) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + return (AscGetChipIRQ(iop_base, bus_type)); + } + if ((bus_type & (ASC_IS_ISA)) != 0) { + if (irq_no == 15) + irq_no -= (uchar)2; + irq_no -= (uchar)ASC_MIN_IRQ_NO; + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3); + cfg_lsw |= (ushort)((irq_no & 0x03) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipIRQ(iop_base, bus_type)); + } + return (0); } #ifdef CONFIG_ISA -STATIC void __init -AscEnableIsaDma( - uchar dma_channel) +static void __init AscEnableIsaDma(uchar dma_channel) { - if (dma_channel < 4) { - outp(0x000B, (ushort) (0xC0 | dma_channel)); - outp(0x000A, dma_channel); - } else if (dma_channel < 8) { - outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4))); - outp(0x00D4, (ushort) (dma_channel - 4)); - } - return; + if (dma_channel < 4) { + outp(0x000B, (ushort)(0xC0 | dma_channel)); + outp(0x000A, dma_channel); + } else if (dma_channel < 8) { + outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); + outp(0x00D4, (ushort)(dma_channel - 4)); + } + return; } #endif /* CONFIG_ISA */ -STATIC int -AscIsrChipHalted( - ASC_DVC_VAR *asc_dvc -) +static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) { - EXT_MSG ext_msg; - EXT_MSG out_msg; - ushort halt_q_addr; - int sdtr_accept; - ushort int_halt_code; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - uchar tag_code; - uchar q_status; - uchar halt_qp; - uchar sdtr_data; - uchar target_ix; - uchar q_cntl, tid_no; - uchar cur_dvc_qng; - uchar asyn_sdtr; - uchar scsi_status; - asc_board_t *boardp; - - ASC_ASSERT(asc_dvc->drv_ptr != NULL); - boardp = asc_dvc->drv_ptr; - - iop_base = asc_dvc->iop_base; - int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); - - halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); - halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); - target_ix = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX)); - q_cntl = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - tid_no = ASC_TIX_TO_TID(target_ix); - target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no); - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; - } else { - asyn_sdtr = 0; - } - if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - AscSetChipSDTR(iop_base, 0, tid_no); - boardp->sdtr_data[tid_no] = 0; - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { - - AscMemWordCopyPtrFromLram(iop_base, - ASCV_MSGIN_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - - if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_SDTR_CODE && - ext_msg.msg_len == MS_SDTR_LEN) { - sdtr_accept = TRUE; - if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { - - sdtr_accept = FALSE; - ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; - } - if ((ext_msg.xfer_period < - asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) || - (ext_msg.xfer_period > - asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) { - sdtr_accept = FALSE; - ext_msg.xfer_period = - asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]; - } - if (sdtr_accept) { - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - if ((sdtr_data == 0xFF)) { - - q_cntl |= QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - } - if (ext_msg.req_ack_offset == 0) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - } else { - if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - boardp->sdtr_data[tid_no] = sdtr_data; - } else { - - q_cntl |= QC_MSG_OUT; - AscMsgOutSDTR(asc_dvc, - ext_msg.xfer_period, - ext_msg.req_ack_offset); - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - boardp->sdtr_data[tid_no] = sdtr_data; - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - } - } - - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_WDTR_CODE && - ext_msg.msg_len == MS_WDTR_LEN) { - - ext_msg.wdtr_width = 0; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - q_cntl |= QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else { - - ext_msg.msg_type = MESSAGE_REJECT; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - q_cntl |= QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } - } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { - - q_cntl |= QC_REQ_SENSE; - - if ((asc_dvc->init_sdtr & target_id) != 0) { - - asc_dvc->sdtr_done &= ~target_id; - - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - q_cntl |= QC_MSG_OUT; - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & - (uchar) (asc_dvc->max_sdtr_index - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - } - - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - - tag_code = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); - tag_code &= 0xDC; - if ( - (asc_dvc->pci_fix_asyn_xfer & target_id) - && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) -) { - - tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT - | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); - - } - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE), - tag_code); - - q_status = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - q_status |= (QS_READY | QS_BUSY); - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - q_status); - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy); - - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { - - AscMemWordCopyPtrFromLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &out_msg, - sizeof(EXT_MSG) >> 1); - - if ((out_msg.msg_type == MS_EXTEND) && - (out_msg.msg_len == MS_SDTR_LEN) && - (out_msg.msg_req == MS_SDTR_CODE)) { - - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - q_cntl &= ~QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { - - scsi_status = AscReadLramByte(iop_base, - (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS)); - cur_dvc_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix)); - if ((cur_dvc_qng > 0) && - (asc_dvc->cur_dvc_qng[tid_no] > 0)) { - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy |= target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy |= target_id; - - if (scsi_status == SAM_STAT_TASK_SET_FULL) { - if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { - cur_dvc_qng -= 1; - asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; - - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + - (ushort) tid_no), - cur_dvc_qng); - - /* - * Set the device queue depth to the number of - * active requests when the QUEUE FULL condition - * was encountered. - */ - boardp->queue_full |= target_id; - boardp->queue_full_cnt[tid_no] = cur_dvc_qng; - } - } - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } + EXT_MSG ext_msg; + EXT_MSG out_msg; + ushort halt_q_addr; + int sdtr_accept; + ushort int_halt_code; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + uchar tag_code; + uchar q_status; + uchar halt_qp; + uchar sdtr_data; + uchar target_ix; + uchar q_cntl, tid_no; + uchar cur_dvc_qng; + uchar asyn_sdtr; + uchar scsi_status; + asc_board_t *boardp; + + ASC_ASSERT(asc_dvc->drv_ptr != NULL); + boardp = asc_dvc->drv_ptr; + + iop_base = asc_dvc->iop_base; + int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); + + halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); + halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); + target_ix = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_TARGET_IX)); + q_cntl = + AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL)); + tid_no = ASC_TIX_TO_TID(target_ix); + target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no); + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; + } else { + asyn_sdtr = 0; + } + if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + AscSetChipSDTR(iop_base, 0, tid_no); + boardp->sdtr_data[tid_no] = 0; + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { + + AscMemWordCopyPtrFromLram(iop_base, + ASCV_MSGIN_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + + if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_SDTR_CODE && + ext_msg.msg_len == MS_SDTR_LEN) { + sdtr_accept = TRUE; + if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { + + sdtr_accept = FALSE; + ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; + } + if ((ext_msg.xfer_period < + asc_dvc->sdtr_period_tbl[asc_dvc-> + host_init_sdtr_index]) + || (ext_msg.xfer_period > + asc_dvc->sdtr_period_tbl[asc_dvc-> + max_sdtr_index])) { + sdtr_accept = FALSE; + ext_msg.xfer_period = + asc_dvc->sdtr_period_tbl[asc_dvc-> + host_init_sdtr_index]; + } + if (sdtr_accept) { + sdtr_data = + AscCalSDTRData(asc_dvc, ext_msg.xfer_period, + ext_msg.req_ack_offset); + if ((sdtr_data == 0xFF)) { + + q_cntl |= QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, + tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + } + if (ext_msg.req_ack_offset == 0) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + } else { + if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + asc_dvc->pci_fix_asyn_xfer &= + ~target_id; + sdtr_data = + AscCalSDTRData(asc_dvc, + ext_msg.xfer_period, + ext_msg. + req_ack_offset); + AscSetChipSDTR(iop_base, sdtr_data, + tid_no); + boardp->sdtr_data[tid_no] = sdtr_data; + } else { + + q_cntl |= QC_MSG_OUT; + AscMsgOutSDTR(asc_dvc, + ext_msg.xfer_period, + ext_msg.req_ack_offset); + asc_dvc->pci_fix_asyn_xfer &= + ~target_id; + sdtr_data = + AscCalSDTRData(asc_dvc, + ext_msg.xfer_period, + ext_msg. + req_ack_offset); + AscSetChipSDTR(iop_base, sdtr_data, + tid_no); + boardp->sdtr_data[tid_no] = sdtr_data; + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + } + } + + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_WDTR_CODE && + ext_msg.msg_len == MS_WDTR_LEN) { + + ext_msg.wdtr_width = 0; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + q_cntl |= QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else { + + ext_msg.msg_type = MESSAGE_REJECT; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + q_cntl |= QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } + } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { + + q_cntl |= QC_REQ_SENSE; + + if ((asc_dvc->init_sdtr & target_id) != 0) { + + asc_dvc->sdtr_done &= ~target_id; + + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + q_cntl |= QC_MSG_OUT; + AscMsgOutSDTR(asc_dvc, + asc_dvc-> + sdtr_period_tbl[(sdtr_data >> 4) & + (uchar)(asc_dvc-> + max_sdtr_index - + 1)], + (uchar)(sdtr_data & (uchar) + ASC_SYN_MAX_OFFSET)); + } + + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), q_cntl); + + tag_code = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort) + ASC_SCSIQ_B_TAG_CODE)); + tag_code &= 0xDC; + if ((asc_dvc->pci_fix_asyn_xfer & target_id) + && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) + ) { + + tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT + | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); + + } + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_TAG_CODE), + tag_code); + + q_status = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort) + ASC_SCSIQ_B_STATUS)); + q_status |= (QS_READY | QS_BUSY); + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_STATUS), + q_status); + + scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy); + + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { + + AscMemWordCopyPtrFromLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&out_msg, + sizeof(EXT_MSG) >> 1); + + if ((out_msg.msg_type == MS_EXTEND) && + (out_msg.msg_len == MS_SDTR_LEN) && + (out_msg.msg_req == MS_SDTR_CODE)) { + + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + q_cntl &= ~QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { + + scsi_status = AscReadLramByte(iop_base, + (ushort)((ushort)halt_q_addr + + (ushort) + ASC_SCSIQ_SCSI_STATUS)); + cur_dvc_qng = + AscReadLramByte(iop_base, + (ushort)((ushort)ASC_QADR_BEG + + (ushort)target_ix)); + if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) { + + scsi_busy = AscReadLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B); + scsi_busy |= target_id; + AscWriteLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B, scsi_busy); + asc_dvc->queue_full_or_busy |= target_id; + + if (scsi_status == SAM_STAT_TASK_SET_FULL) { + if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { + cur_dvc_qng -= 1; + asc_dvc->max_dvc_qng[tid_no] = + cur_dvc_qng; + + AscWriteLramByte(iop_base, + (ushort)((ushort) + ASCV_MAX_DVC_QNG_BEG + + (ushort) + tid_no), + cur_dvc_qng); + + /* + * Set the device queue depth to the number of + * active requests when the QUEUE FULL condition + * was encountered. + */ + boardp->queue_full |= target_id; + boardp->queue_full_cnt[tid_no] = + cur_dvc_qng; + } + } + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } #if CC_VERY_LONG_SG_LIST - else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) - { - uchar q_no; - ushort q_addr; - uchar sg_wk_q_no; - uchar first_sg_wk_q_no; - ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ - ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ - ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ - ushort sg_list_dwords; - ushort sg_entry_cnt; - uchar next_qp; - int i; - - q_no = AscReadLramByte(iop_base, (ushort) ASCV_REQ_SG_LIST_QP); - if (q_no == ASC_QLINK_END) - { - return(0); - } - - q_addr = ASC_QNO_TO_QADDR(q_no); - - /* - * Convert the request's SRB pointer to a host ASC_SCSI_REQ - * structure pointer using a macro provided by the driver. - * The ASC_SCSI_REQ pointer provides a pointer to the - * host ASC_SG_HEAD structure. - */ - /* Read request's SRB pointer. */ - scsiq = (ASC_SCSI_Q *) - ASC_SRB2SCSIQ( - ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, - (ushort) (q_addr + ASC_SCSIQ_D_SRBPTR)))); - - /* - * Get request's first and working SG queue. - */ - sg_wk_q_no = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_SG_WK_QP)); - - first_sg_wk_q_no = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FIRST_SG_WK_QP)); - - /* - * Reset request's working SG queue back to the - * first SG queue. - */ - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SG_WK_QP), - first_sg_wk_q_no); - - sg_head = scsiq->sg_head; - - /* - * Set sg_entry_cnt to the number of SG elements - * that will be completed on this interrupt. - * - * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 - * SG elements. The data_cnt and data_addr fields which - * add 1 to the SG element capacity are not used when - * restarting SG handling after a halt. - */ - if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) - { - sg_entry_cnt = ASC_MAX_SG_LIST - 1; - - /* - * Keep track of remaining number of SG elements that will - * need to be handled on the next interrupt. - */ - scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); - } else - { - sg_entry_cnt = scsiq->remain_sg_entry_cnt; - scsiq->remain_sg_entry_cnt = 0; - } - - /* - * Copy SG elements into the list of allocated SG queues. - * - * Last index completed is saved in scsiq->next_sg_index. - */ - next_qp = first_sg_wk_q_no; - q_addr = ASC_QNO_TO_QADDR(next_qp); - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for( i = 0; i < sg_head->queue_cnt; i++) - { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) - { - sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - /* - * After very first SG queue RISC FW uses next - * SG queue first element then checks sg_list_cnt - * against zero and then decrements, so set - * sg_list_cnt 1 less than number of SG elements - * in each SG queue. - */ - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; - } else { - /* - * This is the last SG queue in the list of - * allocated SG queues. If there are more - * SG elements than will fit in the allocated - * queues, then set the QCSG_SG_XFER_MORE flag. - */ - if (scsiq->remain_sg_entry_cnt != 0) - { - scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; - } else - { - scsi_sg_q.cntl |= QCSG_SG_XFER_END; - } - /* equals sg_entry_cnt * 2 */ - sg_list_dwords = sg_entry_cnt << 1; - scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; - sg_entry_cnt = 0; - } - - scsi_sg_q.q_no = next_qp; - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_SGHD_CPY_BEG, - (uchar *) &scsi_sg_q, - sizeof(ASC_SG_LIST_Q) >> 1); - - AscMemDWordCopyPtrToLram(iop_base, - q_addr + ASC_SGQ_LIST_BEG, - (uchar *) &sg_head->sg_list[scsiq->next_sg_index], - sg_list_dwords); - - scsiq->next_sg_index += ASC_SG_LIST_PER_Q; - - /* - * If the just completed SG queue contained the - * last SG element, then no more SG queues need - * to be written. - */ - if (scsi_sg_q.cntl & QCSG_SG_XFER_END) - { - break; - } - - next_qp = AscReadLramByte( iop_base, - ( ushort )( q_addr+ASC_SCSIQ_B_FWD ) ); - q_addr = ASC_QNO_TO_QADDR( next_qp ); - } - - /* - * Clear the halt condition so the RISC will be restarted - * after the return. - */ - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return(0); - } + else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) { + uchar q_no; + ushort q_addr; + uchar sg_wk_q_no; + uchar first_sg_wk_q_no; + ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ + ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ + ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ + ushort sg_list_dwords; + ushort sg_entry_cnt; + uchar next_qp; + int i; + + q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP); + if (q_no == ASC_QLINK_END) { + return (0); + } + + q_addr = ASC_QNO_TO_QADDR(q_no); + + /* + * Convert the request's SRB pointer to a host ASC_SCSI_REQ + * structure pointer using a macro provided by the driver. + * The ASC_SCSI_REQ pointer provides a pointer to the + * host ASC_SG_HEAD structure. + */ + /* Read request's SRB pointer. */ + scsiq = (ASC_SCSI_Q *) + ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, + (ushort) + (q_addr + + ASC_SCSIQ_D_SRBPTR)))); + + /* + * Get request's first and working SG queue. + */ + sg_wk_q_no = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_SG_WK_QP)); + + first_sg_wk_q_no = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FIRST_SG_WK_QP)); + + /* + * Reset request's working SG queue back to the + * first SG queue. + */ + AscWriteLramByte(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_SG_WK_QP), + first_sg_wk_q_no); + + sg_head = scsiq->sg_head; + + /* + * Set sg_entry_cnt to the number of SG elements + * that will be completed on this interrupt. + * + * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 + * SG elements. The data_cnt and data_addr fields which + * add 1 to the SG element capacity are not used when + * restarting SG handling after a halt. + */ + if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) { + sg_entry_cnt = ASC_MAX_SG_LIST - 1; + + /* + * Keep track of remaining number of SG elements that will + * need to be handled on the next interrupt. + */ + scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); + } else { + sg_entry_cnt = scsiq->remain_sg_entry_cnt; + scsiq->remain_sg_entry_cnt = 0; + } + + /* + * Copy SG elements into the list of allocated SG queues. + * + * Last index completed is saved in scsiq->next_sg_index. + */ + next_qp = first_sg_wk_q_no; + q_addr = ASC_QNO_TO_QADDR(next_qp); + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + /* + * After very first SG queue RISC FW uses next + * SG queue first element then checks sg_list_cnt + * against zero and then decrements, so set + * sg_list_cnt 1 less than number of SG elements + * in each SG queue. + */ + scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q - 1; + } else { + /* + * This is the last SG queue in the list of + * allocated SG queues. If there are more + * SG elements than will fit in the allocated + * queues, then set the QCSG_SG_XFER_MORE flag. + */ + if (scsiq->remain_sg_entry_cnt != 0) { + scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; + } else { + scsi_sg_q.cntl |= QCSG_SG_XFER_END; + } + /* equals sg_entry_cnt * 2 */ + sg_list_dwords = sg_entry_cnt << 1; + scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; + sg_entry_cnt = 0; + } + + scsi_sg_q.q_no = next_qp; + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_SGHD_CPY_BEG, + (uchar *)&scsi_sg_q, + sizeof(ASC_SG_LIST_Q) >> 1); + + AscMemDWordCopyPtrToLram(iop_base, + q_addr + ASC_SGQ_LIST_BEG, + (uchar *)&sg_head-> + sg_list[scsiq->next_sg_index], + sg_list_dwords); + + scsiq->next_sg_index += ASC_SG_LIST_PER_Q; + + /* + * If the just completed SG queue contained the + * last SG element, then no more SG queues need + * to be written. + */ + if (scsi_sg_q.cntl & QCSG_SG_XFER_END) { + break; + } + + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FWD)); + q_addr = ASC_QNO_TO_QADDR(next_qp); + } + + /* + * Clear the halt condition so the RISC will be restarted + * after the return. + */ + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } #endif /* CC_VERY_LONG_SG_LIST */ - return (0); + return (0); } -STATIC uchar -_AscCopyLramScsiDoneQ( - PortAddr iop_base, - ushort q_addr, - ASC_QDONE_INFO * scsiq, - ASC_DCNT max_dma_count -) +static uchar +_AscCopyLramScsiDoneQ(PortAddr iop_base, + ushort q_addr, + ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count) { - ushort _val; - uchar sg_queue_cnt; - - DvcGetQinfo(iop_base, - q_addr + ASC_SCSIQ_DONE_INFO_BEG, - (uchar *) scsiq, - (sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2); - - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - scsiq->q_status = (uchar) _val; - scsiq->q_no = (uchar) (_val >> 8); - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - scsiq->cntl = (uchar) _val; - sg_queue_cnt = (uchar) (_val >> 8); - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN)); - scsiq->sense_len = (uchar) _val; - scsiq->extra_bytes = (uchar) (_val >> 8); - - /* - * Read high word of remain bytes from alternate location. - */ - scsiq->remain_bytes = (((ADV_DCNT) AscReadLramWord( iop_base, - (ushort) (q_addr+ (ushort) ASC_SCSIQ_W_ALT_DC1))) << 16); - /* - * Read low word of remain bytes from original location. - */ - scsiq->remain_bytes += AscReadLramWord(iop_base, - (ushort) (q_addr+ (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT)); - - scsiq->remain_bytes &= max_dma_count; - return (sg_queue_cnt); + ushort _val; + uchar sg_queue_cnt; + + DvcGetQinfo(iop_base, + q_addr + ASC_SCSIQ_DONE_INFO_BEG, + (uchar *)scsiq, + (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2); + + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS)); + scsiq->q_status = (uchar)_val; + scsiq->q_no = (uchar)(_val >> 8); + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL)); + scsiq->cntl = (uchar)_val; + sg_queue_cnt = (uchar)(_val >> 8); + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_SENSE_LEN)); + scsiq->sense_len = (uchar)_val; + scsiq->extra_bytes = (uchar)(_val >> 8); + + /* + * Read high word of remain bytes from alternate location. + */ + scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base, + (ushort)(q_addr + + (ushort) + ASC_SCSIQ_W_ALT_DC1))) + << 16); + /* + * Read low word of remain bytes from original location. + */ + scsiq->remain_bytes += AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort) + ASC_SCSIQ_DW_REMAIN_XFER_CNT)); + + scsiq->remain_bytes &= max_dma_count; + return (sg_queue_cnt); } -STATIC int -AscIsrQDone( - ASC_DVC_VAR *asc_dvc -) +static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) { - uchar next_qp; - uchar n_q_used; - uchar sg_list_qp; - uchar sg_queue_cnt; - uchar q_cnt; - uchar done_q_tail; - uchar tid_no; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - ushort q_addr; - ushort sg_q_addr; - uchar cur_target_qng; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO *scsiq; - int false_overrun; - ASC_ISR_CALLBACK asc_isr_callback; - - iop_base = asc_dvc->iop_base; - asc_isr_callback = asc_dvc->isr_callback; - n_q_used = 1; - scsiq = (ASC_QDONE_INFO *) & scsiq_buf; - done_q_tail = (uchar) AscGetVarDoneQTail(iop_base); - q_addr = ASC_QNO_TO_QADDR(done_q_tail); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD)); - if (next_qp != ASC_QLINK_END) { - AscPutVarDoneQTail(iop_base, next_qp); - q_addr = ASC_QNO_TO_QADDR(next_qp); - sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, - asc_dvc->max_dma_count); - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED))); - tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); - target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); - if ((scsiq->cntl & QC_SG_HEAD) != 0) { - sg_q_addr = q_addr; - sg_list_qp = next_qp; - for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { - sg_list_qp = AscReadLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD)); - sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); - if (sg_list_qp == ASC_QLINK_END) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS); - scsiq->d3.done_stat = QD_WITH_ERROR; - scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED; - goto FATAL_ERR_QDONE; - } - AscWriteLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - QS_FREE); - } - n_q_used = sg_queue_cnt + 1; - AscPutVarDoneQTail(iop_base, sg_list_qp); - } - if (asc_dvc->queue_full_or_busy & target_id) { - cur_target_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix)); - if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy &= ~target_id; - } - } - if (asc_dvc->cur_total_qng >= n_q_used) { - asc_dvc->cur_total_qng -= n_q_used; - if (asc_dvc->cur_dvc_qng[tid_no] != 0) { - asc_dvc->cur_dvc_qng[tid_no]--; - } - } else { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); - scsiq->d3.done_stat = QD_WITH_ERROR; - goto FATAL_ERR_QDONE; - } - if ((scsiq->d2.srb_ptr == 0UL) || - ((scsiq->q_status & QS_ABORTED) != 0)) { - return (0x11); - } else if (scsiq->q_status == QS_DONE) { - false_overrun = FALSE; - if (scsiq->extra_bytes != 0) { - scsiq->remain_bytes += (ADV_DCNT) scsiq->extra_bytes; - } - if (scsiq->d3.done_stat == QD_WITH_ERROR) { - if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) { - if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } else if (false_overrun) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } - } else if (scsiq->d3.host_stat == - QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { - AscStopChip(iop_base); - AscSetChipControl(iop_base, - (uchar) (CC_SCSI_RESET | CC_HALT)); - DvcDelayNanoSecond(asc_dvc, 60000); - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - AscSetChipControl(iop_base, 0); - } - } - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } else { - if ((AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == - START_STOP)) { - asc_dvc->unit_not_ready &= ~target_id; - if (scsiq->d3.done_stat != QD_NO_ERROR) { - asc_dvc->start_motor &= ~target_id; - } - } - } - return (1); - } else { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); - FATAL_ERR_QDONE: - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } - return (0x80); - } - } - return (0); + uchar next_qp; + uchar n_q_used; + uchar sg_list_qp; + uchar sg_queue_cnt; + uchar q_cnt; + uchar done_q_tail; + uchar tid_no; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + ushort q_addr; + ushort sg_q_addr; + uchar cur_target_qng; + ASC_QDONE_INFO scsiq_buf; + ASC_QDONE_INFO *scsiq; + int false_overrun; + ASC_ISR_CALLBACK asc_isr_callback; + + iop_base = asc_dvc->iop_base; + asc_isr_callback = asc_dvc->isr_callback; + n_q_used = 1; + scsiq = (ASC_QDONE_INFO *)&scsiq_buf; + done_q_tail = (uchar)AscGetVarDoneQTail(iop_base); + q_addr = ASC_QNO_TO_QADDR(done_q_tail); + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD)); + if (next_qp != ASC_QLINK_END) { + AscPutVarDoneQTail(iop_base, next_qp); + q_addr = ASC_QNO_TO_QADDR(next_qp); + sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, + asc_dvc->max_dma_count); + AscWriteLramByte(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_STATUS), + (uchar)(scsiq-> + q_status & (uchar)~(QS_READY | + QS_ABORTED))); + tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); + target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); + if ((scsiq->cntl & QC_SG_HEAD) != 0) { + sg_q_addr = q_addr; + sg_list_qp = next_qp; + for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { + sg_list_qp = AscReadLramByte(iop_base, + (ushort)(sg_q_addr + + (ushort) + ASC_SCSIQ_B_FWD)); + sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); + if (sg_list_qp == ASC_QLINK_END) { + AscSetLibErrorCode(asc_dvc, + ASCQ_ERR_SG_Q_LINKS); + scsiq->d3.done_stat = QD_WITH_ERROR; + scsiq->d3.host_stat = + QHSTA_D_QDONE_SG_LIST_CORRUPTED; + goto FATAL_ERR_QDONE; + } + AscWriteLramByte(iop_base, + (ushort)(sg_q_addr + (ushort) + ASC_SCSIQ_B_STATUS), + QS_FREE); + } + n_q_used = sg_queue_cnt + 1; + AscPutVarDoneQTail(iop_base, sg_list_qp); + } + if (asc_dvc->queue_full_or_busy & target_id) { + cur_target_qng = AscReadLramByte(iop_base, + (ushort)((ushort) + ASC_QADR_BEG + + (ushort) + scsiq->d2. + target_ix)); + if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { + scsi_busy = AscReadLramByte(iop_base, (ushort) + ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B, + scsi_busy); + asc_dvc->queue_full_or_busy &= ~target_id; + } + } + if (asc_dvc->cur_total_qng >= n_q_used) { + asc_dvc->cur_total_qng -= n_q_used; + if (asc_dvc->cur_dvc_qng[tid_no] != 0) { + asc_dvc->cur_dvc_qng[tid_no]--; + } + } else { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); + scsiq->d3.done_stat = QD_WITH_ERROR; + goto FATAL_ERR_QDONE; + } + if ((scsiq->d2.srb_ptr == 0UL) || + ((scsiq->q_status & QS_ABORTED) != 0)) { + return (0x11); + } else if (scsiq->q_status == QS_DONE) { + false_overrun = FALSE; + if (scsiq->extra_bytes != 0) { + scsiq->remain_bytes += + (ADV_DCNT)scsiq->extra_bytes; + } + if (scsiq->d3.done_stat == QD_WITH_ERROR) { + if (scsiq->d3.host_stat == + QHSTA_M_DATA_OVER_RUN) { + if ((scsiq-> + cntl & (QC_DATA_IN | QC_DATA_OUT)) + == 0) { + scsiq->d3.done_stat = + QD_NO_ERROR; + scsiq->d3.host_stat = + QHSTA_NO_ERROR; + } else if (false_overrun) { + scsiq->d3.done_stat = + QD_NO_ERROR; + scsiq->d3.host_stat = + QHSTA_NO_ERROR; + } + } else if (scsiq->d3.host_stat == + QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { + AscStopChip(iop_base); + AscSetChipControl(iop_base, + (uchar)(CC_SCSI_RESET + | CC_HALT)); + DvcDelayNanoSecond(asc_dvc, 60000); + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, + CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + AscSetChipControl(iop_base, 0); + } + } + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } else { + if ((AscReadLramByte(iop_base, + (ushort)(q_addr + (ushort) + ASC_SCSIQ_CDB_BEG)) + == START_STOP)) { + asc_dvc->unit_not_ready &= ~target_id; + if (scsiq->d3.done_stat != QD_NO_ERROR) { + asc_dvc->start_motor &= + ~target_id; + } + } + } + return (1); + } else { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); + FATAL_ERR_QDONE: + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } + return (0x80); + } + } + return (0); } -STATIC int -AscISR( - ASC_DVC_VAR *asc_dvc -) +static int AscISR(ASC_DVC_VAR *asc_dvc) { - ASC_CS_TYPE chipstat; - PortAddr iop_base; - ushort saved_ram_addr; - uchar ctrl_reg; - uchar saved_ctrl_reg; - int int_pending; - int status; - uchar host_flag; - - iop_base = asc_dvc->iop_base; - int_pending = FALSE; - - if (AscIsIntPending(iop_base) == 0) - { - return int_pending; - } + ASC_CS_TYPE chipstat; + PortAddr iop_base; + ushort saved_ram_addr; + uchar ctrl_reg; + uchar saved_ctrl_reg; + int int_pending; + int status; + uchar host_flag; + + iop_base = asc_dvc->iop_base; + int_pending = FALSE; + + if (AscIsIntPending(iop_base) == 0) { + return int_pending; + } - if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) - || (asc_dvc->isr_callback == 0) -) { - return (ERR); - } - if (asc_dvc->in_critical_cnt != 0) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); - return (ERR); - } - if (asc_dvc->is_in_int) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); - return (ERR); - } - asc_dvc->is_in_int = TRUE; - ctrl_reg = AscGetChipControl(iop_base); - saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | - CC_SINGLE_STEP | CC_DIAG | CC_TEST)); - chipstat = AscGetChipStatus(iop_base); - if (chipstat & CSW_SCSI_RESET_LATCH) { - if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { - int i = 10; - int_pending = TRUE; - asc_dvc->sdtr_done = 0; - saved_ctrl_reg &= (uchar) (~CC_HALT); - while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && - (i-- > 0)) - { - DvcSleepMilliSecond(100); - } - AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - chipstat = AscGetChipStatus(iop_base); - } - } - saved_ram_addr = AscGetChipLramAddr(iop_base); - host_flag = AscReadLramByte(iop_base, - ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR)); - if ((chipstat & CSW_INT_PENDING) - || (int_pending) -) { - AscAckInterrupt(iop_base); - int_pending = TRUE; - if ((chipstat & CSW_HALTED) && - (ctrl_reg & CC_SINGLE_STEP)) { - if (AscIsrChipHalted(asc_dvc) == ERR) { - goto ISR_REPORT_QDONE_FATAL_ERROR; - } else { - saved_ctrl_reg &= (uchar) (~CC_HALT); - } - } else { - ISR_REPORT_QDONE_FATAL_ERROR: - if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { - while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) { - } - } else { - do { - if ((status = AscIsrQDone(asc_dvc)) == 1) { - break; - } - } while (status == 0x11); - } - if ((status & 0x80) != 0) - int_pending = ERR; - } - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - AscSetChipLramAddr(iop_base, saved_ram_addr); - AscSetChipControl(iop_base, saved_ctrl_reg); - asc_dvc->is_in_int = FALSE; - return (int_pending); + if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) + || (asc_dvc->isr_callback == 0) + ) { + return (ERR); + } + if (asc_dvc->in_critical_cnt != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); + return (ERR); + } + if (asc_dvc->is_in_int) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); + return (ERR); + } + asc_dvc->is_in_int = TRUE; + ctrl_reg = AscGetChipControl(iop_base); + saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | + CC_SINGLE_STEP | CC_DIAG | CC_TEST)); + chipstat = AscGetChipStatus(iop_base); + if (chipstat & CSW_SCSI_RESET_LATCH) { + if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { + int i = 10; + int_pending = TRUE; + asc_dvc->sdtr_done = 0; + saved_ctrl_reg &= (uchar)(~CC_HALT); + while ((AscGetChipStatus(iop_base) & + CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) { + DvcSleepMilliSecond(100); + } + AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + chipstat = AscGetChipStatus(iop_base); + } + } + saved_ram_addr = AscGetChipLramAddr(iop_base); + host_flag = AscReadLramByte(iop_base, + ASCV_HOST_FLAG_B) & + (uchar)(~ASC_HOST_FLAG_IN_ISR); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR)); + if ((chipstat & CSW_INT_PENDING) + || (int_pending) + ) { + AscAckInterrupt(iop_base); + int_pending = TRUE; + if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) { + if (AscIsrChipHalted(asc_dvc) == ERR) { + goto ISR_REPORT_QDONE_FATAL_ERROR; + } else { + saved_ctrl_reg &= (uchar)(~CC_HALT); + } + } else { + ISR_REPORT_QDONE_FATAL_ERROR: + if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { + while (((status = + AscIsrQDone(asc_dvc)) & 0x01) != 0) { + } + } else { + do { + if ((status = + AscIsrQDone(asc_dvc)) == 1) { + break; + } + } while (status == 0x11); + } + if ((status & 0x80) != 0) + int_pending = ERR; + } + } + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + AscSetChipLramAddr(iop_base, saved_ram_addr); + AscSetChipControl(iop_base, saved_ctrl_reg); + asc_dvc->is_in_int = FALSE; + return (int_pending); } /* Microcode buffer is kept after initialization for error recovery. */ -STATIC uchar _asc_mcode_buf[] = -{ - 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, - 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80, - 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, - 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62, - 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, - 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, - 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88, - 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00, 0x84, 0x97, 0x07, 0xA6, - 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, - 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6, - 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x34, 0x01, 0x00, 0x33, - 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, - 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23, - 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01, 0x00, 0x33, 0x0A, 0x00, - 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, - 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01, - 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x3C, 0x01, 0x00, 0x05, - 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, - 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, - 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0xC2, 0x88, 0x06, 0x23, - 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, - 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, - 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, - 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, - 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88, 0x04, 0x98, 0xF0, 0x80, - 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, - 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95, - 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02, 0x07, 0xA6, 0x5A, 0x02, - 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, - 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, - 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, - 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, - 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02, - 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, - 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, - 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82, - 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8, 0x00, 0x33, 0x1F, 0x00, - 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, - 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6, - 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xEE, 0x82, - 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, - 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, - 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, - 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, - 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33, - 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05, 0xFF, 0xA2, 0x7A, 0x03, - 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, - 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03, - 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, 0xA4, 0x03, 0x00, 0xA6, - 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, - 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42, - 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95, 0xC0, 0x83, 0x00, 0x33, - 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, - 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, - 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04, 0x06, 0xA6, 0x0A, 0x04, - 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, - 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, - 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33, - 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, - 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63, - 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, - 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, - 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, - 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3, - 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, - 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98, - 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xE8, 0x81, - 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, - 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23, - 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33, - 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, - 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05, - 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04, - 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, - 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6, - 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, - 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, - 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, - 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05, - 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, - 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05, - 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85, - 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, - 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0, - 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63, - 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, - 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, - 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, - 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05, - 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, - 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, - 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6, - 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, - 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06, - 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, - 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, - 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E, - 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06, - 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, - 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E, - 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, - 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, - 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, - 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88, 0x00, 0x00, 0x80, 0x67, - 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, - 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00, - 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05, - 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, - 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01, - 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00, - 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, - 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01, - 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33, - 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, - 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07, - 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63, - 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, - 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0, - 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04, - 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, - 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98, - 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01, - 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, - 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08, - 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B, - 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, - 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36, - 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, - 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, - 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, - 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, - 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, - 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, +static uchar _asc_mcode_buf[] = { + 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88, + 0x00, 0x00, 0x00, 0x00, + 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, + 0x03, 0x23, 0x36, 0x40, + 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, + 0xC2, 0x00, 0x92, 0x80, + 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, + 0xB6, 0x00, 0x92, 0x80, + 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, + 0x92, 0x80, 0x80, 0x62, + 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, + 0xCD, 0x04, 0x4D, 0x00, + 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, + 0xE6, 0x84, 0xD2, 0xC1, + 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, + 0xC6, 0x81, 0xC2, 0x88, + 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00, + 0x84, 0x97, 0x07, 0xA6, + 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE, + 0xC2, 0x88, 0xCE, 0x00, + 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, + 0x80, 0x63, 0x07, 0xA6, + 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, + 0x34, 0x01, 0x00, 0x33, + 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, + 0x68, 0x98, 0x4D, 0x04, + 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, + 0xF8, 0x88, 0xFB, 0x23, + 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01, + 0x00, 0x33, 0x0A, 0x00, + 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00, + 0xC2, 0x88, 0xCD, 0x04, + 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, + 0x06, 0xAB, 0x82, 0x01, + 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3, + 0x3C, 0x01, 0x00, 0x05, + 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, + 0x15, 0x23, 0xA1, 0x01, + 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, + 0x06, 0x61, 0x00, 0xA0, + 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, + 0xC2, 0x88, 0x06, 0x23, + 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01, + 0x57, 0x60, 0x00, 0xA0, + 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, + 0x4B, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC, + 0x4F, 0x00, 0x84, 0x97, + 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97, + 0x48, 0x04, 0x84, 0x80, + 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, + 0x81, 0x73, 0x06, 0x29, + 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88, + 0x04, 0x98, 0xF0, 0x80, + 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6, + 0x34, 0x02, 0x03, 0xA6, + 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, + 0x46, 0x82, 0xFE, 0x95, + 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02, + 0x07, 0xA6, 0x5A, 0x02, + 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95, + 0x48, 0x82, 0x60, 0x96, + 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, + 0x04, 0x01, 0x0C, 0xDC, + 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, + 0x6F, 0x00, 0xA5, 0x01, + 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, + 0x02, 0xA6, 0xAA, 0x02, + 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, + 0x01, 0xA6, 0xB4, 0x02, + 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E, + 0x80, 0x63, 0x00, 0x43, + 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, + 0x04, 0x61, 0x84, 0x01, + 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, + 0x00, 0x00, 0xEA, 0x82, + 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8, + 0x00, 0x33, 0x1F, 0x00, + 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, + 0xB6, 0x2D, 0x01, 0xA6, + 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, + 0x10, 0x03, 0x03, 0xA6, + 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88, + 0x7C, 0x95, 0xEE, 0x82, + 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4, + 0x04, 0x01, 0x2D, 0xC8, + 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, + 0x05, 0x05, 0x86, 0x98, + 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6, + 0x3C, 0x04, 0x06, 0xA6, + 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88, + 0x7C, 0x95, 0x32, 0x83, + 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, + 0xEB, 0x04, 0x00, 0x33, + 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05, + 0xFF, 0xA2, 0x7A, 0x03, + 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01, + 0x00, 0xA2, 0x9A, 0x03, + 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, + 0x01, 0xA6, 0x96, 0x03, + 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, + 0xA4, 0x03, 0x00, 0xA6, + 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03, + 0x07, 0xA6, 0xB2, 0x03, + 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, + 0xA8, 0x98, 0x80, 0x42, + 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95, + 0xC0, 0x83, 0x00, 0x33, + 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, + 0xA0, 0x01, 0x12, 0x23, + 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, + 0x80, 0x67, 0x05, 0x23, + 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04, + 0x06, 0xA6, 0x0A, 0x04, + 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96, + 0xF4, 0x83, 0x20, 0x84, + 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, + 0x83, 0x03, 0x80, 0x63, + 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, + 0x38, 0x04, 0x00, 0x33, + 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, + 0x1D, 0x01, 0x06, 0xCC, + 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, + 0xA2, 0x0D, 0x80, 0x63, + 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03, + 0x80, 0x63, 0xA3, 0x01, + 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, + 0x76, 0x04, 0xE0, 0x00, + 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, + 0x00, 0x33, 0x1E, 0x00, + 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, + 0x08, 0x23, 0x22, 0xA3, + 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, + 0xC4, 0x04, 0x42, 0x23, + 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, + 0xF8, 0x88, 0x04, 0x98, + 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, + 0x81, 0x62, 0xE8, 0x81, + 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98, + 0x00, 0x33, 0x00, 0x81, + 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, + 0xF8, 0x88, 0x04, 0x23, + 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, + 0xF4, 0x04, 0x00, 0x33, + 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, + 0x04, 0x23, 0xA0, 0x01, + 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, + 0x00, 0xA3, 0x22, 0x05, + 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, + 0x46, 0x97, 0xCD, 0x04, + 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, + 0x82, 0x01, 0x34, 0x85, + 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, + 0x1D, 0x01, 0x04, 0xD6, + 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, + 0x49, 0x00, 0x81, 0x01, + 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, + 0x49, 0x04, 0x80, 0x01, + 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, + 0x01, 0x23, 0xEA, 0x00, + 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, + 0x07, 0xA4, 0xF8, 0x05, + 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, + 0xC2, 0x88, 0x04, 0xA0, + 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0xA4, 0x05, + 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, + 0x62, 0x97, 0x04, 0x85, + 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, + 0xF4, 0x85, 0x03, 0xA0, + 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, + 0xCC, 0x86, 0x07, 0xA0, + 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, + 0x80, 0x67, 0x80, 0x63, + 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, + 0xF8, 0x88, 0x07, 0x23, + 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, + 0x00, 0x63, 0x4A, 0x00, + 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, + 0x07, 0x41, 0x83, 0x03, + 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88, + 0x1D, 0x01, 0x01, 0xD6, + 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, + 0x07, 0xA6, 0x7C, 0x05, + 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, + 0x52, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, + 0x00, 0x63, 0x1D, 0x01, + 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, + 0x07, 0x41, 0x00, 0x63, + 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, + 0xDF, 0x00, 0x06, 0xA6, + 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, + 0x00, 0x40, 0xC0, 0x20, + 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, + 0x06, 0xA6, 0x94, 0x06, + 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, + 0x40, 0x0E, 0x80, 0x63, + 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, + 0x80, 0x63, 0x00, 0x43, + 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, + 0x80, 0x67, 0x40, 0x0E, + 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, + 0x07, 0xA6, 0xD6, 0x06, + 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, + 0x0A, 0x2B, 0x07, 0xA6, + 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, + 0xF4, 0x06, 0xC0, 0x0E, + 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, + 0x81, 0x62, 0x04, 0x01, + 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, + 0x8C, 0x06, 0x00, 0x33, + 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, + 0x80, 0x63, 0x06, 0xA6, + 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88, + 0x00, 0x00, 0x80, 0x67, + 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, + 0xBF, 0x23, 0x04, 0x61, + 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, + 0x00, 0x01, 0xF2, 0x00, + 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, + 0x80, 0x05, 0x81, 0x05, + 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, + 0x70, 0x00, 0x81, 0x01, + 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, + 0x70, 0x00, 0x80, 0x01, + 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, + 0xF1, 0x00, 0x70, 0x00, + 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, + 0x71, 0x04, 0x70, 0x00, + 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, + 0xA3, 0x01, 0xA2, 0x01, + 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, + 0xC4, 0x07, 0x00, 0x33, + 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, + 0x48, 0x00, 0xB0, 0x01, + 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, + 0x00, 0xA2, 0xE4, 0x07, + 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, + 0x05, 0x05, 0x00, 0x63, + 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, + 0x76, 0x08, 0x80, 0x02, + 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, + 0x00, 0x02, 0x00, 0xA0, + 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, + 0x00, 0x63, 0xF3, 0x04, + 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, + 0x00, 0xA2, 0x44, 0x08, + 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, + 0x24, 0x08, 0x04, 0x98, + 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, + 0x5A, 0x88, 0x02, 0x01, + 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, + 0x00, 0xA3, 0x64, 0x08, + 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, + 0x06, 0xA6, 0x76, 0x08, + 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, + 0x00, 0x63, 0x38, 0x2B, + 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, + 0x05, 0x05, 0xB2, 0x09, + 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, + 0x80, 0x32, 0x80, 0x36, + 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, + 0x40, 0x36, 0x40, 0x3A, + 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08, + 0x5D, 0x00, 0xFE, 0xC3, + 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, + 0xFF, 0xFD, 0x80, 0x73, + 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, + 0xA1, 0x23, 0xA1, 0x01, + 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, + 0x80, 0x00, 0x03, 0xC2, + 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, + 0xA0, 0x01, 0xE6, 0x84, }; -STATIC ushort _asc_mcode_size = sizeof(_asc_mcode_buf); -STATIC ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; +static ushort _asc_mcode_size = sizeof(_asc_mcode_buf); +static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 -STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = -{ - INQUIRY, - REQUEST_SENSE, - READ_CAPACITY, - READ_TOC, - MODE_SELECT, - MODE_SENSE, - MODE_SELECT_10, - MODE_SENSE_10, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF +static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { + INQUIRY, + REQUEST_SENSE, + READ_CAPACITY, + READ_TOC, + MODE_SELECT, + MODE_SENSE, + MODE_SELECT_10, + MODE_SENSE_10, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF }; -STATIC int -AscExeScsiQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq -) +static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) { - PortAddr iop_base; - ulong last_int_level; - int sta; - int n_q_required; - int disable_syn_offset_one_fix; - int i; - ASC_PADDR addr; - ASC_EXE_CALLBACK asc_exe_callback; - ushort sg_entry_cnt = 0; - ushort sg_entry_cnt_minus_one = 0; - uchar target_ix; - uchar tid_no; - uchar sdtr_data; - uchar extra_bytes; - uchar scsi_cmd; - uchar disable_cmd; - ASC_SG_HEAD *sg_head; - ASC_DCNT data_cnt; - - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - asc_exe_callback = asc_dvc->exe_callback; - if (asc_dvc->err_code != 0) - return (ERR); - if (scsiq == (ASC_SCSI_Q *) 0L) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); - return (ERR); - } - scsiq->q1.q_no = 0; - if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { - scsiq->q1.extra_bytes = 0; - } - sta = 0; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - n_q_required = 1; - if (scsiq->cdbptr[0] == REQUEST_SENSE) { - if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { - asc_dvc->sdtr_done &= ~scsiq->q1.target_id; - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & - (uchar) (asc_dvc->max_sdtr_index - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); - } - } - last_int_level = DvcEnterCritical(); - if (asc_dvc->in_critical_cnt != 0) { - DvcLeaveCritical(last_int_level); - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); - return (ERR); - } - asc_dvc->in_critical_cnt++; - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (ERR); - } + PortAddr iop_base; + ulong last_int_level; + int sta; + int n_q_required; + int disable_syn_offset_one_fix; + int i; + ASC_PADDR addr; + ASC_EXE_CALLBACK asc_exe_callback; + ushort sg_entry_cnt = 0; + ushort sg_entry_cnt_minus_one = 0; + uchar target_ix; + uchar tid_no; + uchar sdtr_data; + uchar extra_bytes; + uchar scsi_cmd; + uchar disable_cmd; + ASC_SG_HEAD *sg_head; + ASC_DCNT data_cnt; + + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + asc_exe_callback = asc_dvc->exe_callback; + if (asc_dvc->err_code != 0) + return (ERR); + if (scsiq == (ASC_SCSI_Q *)0L) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); + return (ERR); + } + scsiq->q1.q_no = 0; + if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { + scsiq->q1.extra_bytes = 0; + } + sta = 0; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + n_q_required = 1; + if (scsiq->cdbptr[0] == REQUEST_SENSE) { + if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { + asc_dvc->sdtr_done &= ~scsiq->q1.target_id; + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + AscMsgOutSDTR(asc_dvc, + asc_dvc-> + sdtr_period_tbl[(sdtr_data >> 4) & + (uchar)(asc_dvc-> + max_sdtr_index - + 1)], + (uchar)(sdtr_data & (uchar) + ASC_SYN_MAX_OFFSET)); + scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); + } + } + last_int_level = DvcEnterCritical(); + if (asc_dvc->in_critical_cnt != 0) { + DvcLeaveCritical(last_int_level); + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); + return (ERR); + } + asc_dvc->in_critical_cnt++; + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (ERR); + } #if !CC_VERY_LONG_SG_LIST - if (sg_entry_cnt > ASC_MAX_SG_LIST) - { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return(ERR); - } + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (ERR); + } #endif /* !CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt == 1) { - scsiq->q1.data_addr = (ADV_PADDR) sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = (ADV_DCNT) sg_head->sg_list[0].bytes; - scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); - } - sg_entry_cnt_minus_one = sg_entry_cnt - 1; - } - scsi_cmd = scsiq->cdbptr[0]; - disable_syn_offset_one_fix = FALSE; - if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && - !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { - if (scsiq->q1.cntl & QC_SG_HEAD) { - data_cnt = 0; - for (i = 0; i < sg_entry_cnt; i++) { - data_cnt += (ADV_DCNT) le32_to_cpu(sg_head->sg_list[i].bytes); - } - } else { - data_cnt = le32_to_cpu(scsiq->q1.data_cnt); - } - if (data_cnt != 0UL) { - if (data_cnt < 512UL) { - disable_syn_offset_one_fix = TRUE; - } else { - for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) { - disable_cmd = _syn_offset_one_disable_cmd[i]; - if (disable_cmd == 0xFF) { - break; - } - if (scsi_cmd == disable_cmd) { - disable_syn_offset_one_fix = TRUE; - break; - } - } - } - } - } - if (disable_syn_offset_one_fix) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; - scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | - ASC_TAG_FLAG_DISABLE_DISCONNECT); - } else { - scsiq->q2.tag_code &= 0x27; - } - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = - (ADV_PADDR) le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].addr) + - (ADV_DCNT) le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].bytes); - extra_bytes = (uchar) ((ushort) addr & 0x0003); - if ((extra_bytes != 0) && - ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; - scsiq->q1.extra_bytes = extra_bytes; - data_cnt = le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].bytes); - data_cnt -= (ASC_DCNT) extra_bytes; - sg_head->sg_list[sg_entry_cnt_minus_one].bytes = - cpu_to_le32(data_cnt); - } - } - } - } - sg_head->entry_to_copy = sg_head->entry_cnt; + if (sg_entry_cnt == 1) { + scsiq->q1.data_addr = + (ADV_PADDR)sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = + (ADV_DCNT)sg_head->sg_list[0].bytes; + scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); + } + sg_entry_cnt_minus_one = sg_entry_cnt - 1; + } + scsi_cmd = scsiq->cdbptr[0]; + disable_syn_offset_one_fix = FALSE; + if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && + !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { + if (scsiq->q1.cntl & QC_SG_HEAD) { + data_cnt = 0; + for (i = 0; i < sg_entry_cnt; i++) { + data_cnt += + (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. + bytes); + } + } else { + data_cnt = le32_to_cpu(scsiq->q1.data_cnt); + } + if (data_cnt != 0UL) { + if (data_cnt < 512UL) { + disable_syn_offset_one_fix = TRUE; + } else { + for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; + i++) { + disable_cmd = + _syn_offset_one_disable_cmd[i]; + if (disable_cmd == 0xFF) { + break; + } + if (scsi_cmd == disable_cmd) { + disable_syn_offset_one_fix = + TRUE; + break; + } + } + } + } + } + if (disable_syn_offset_one_fix) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | + ASC_TAG_FLAG_DISABLE_DISCONNECT); + } else { + scsiq->q2.tag_code &= 0x27; + } + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + (ADV_PADDR)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + addr) + + (ADV_DCNT)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + scsiq->q1.extra_bytes = + extra_bytes; + data_cnt = + le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + data_cnt -= + (ASC_DCNT) extra_bytes; + sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes = + cpu_to_le32(data_cnt); + } + } + } + } + sg_head->entry_to_copy = sg_head->entry_cnt; #if CC_VERY_LONG_SG_LIST - /* - * Set the sg_entry_cnt to the maximum possible. The rest of - * the SG elements will be copied when the RISC completes the - * SG elements that fit and halts. - */ - if (sg_entry_cnt > ASC_MAX_SG_LIST) - { - sg_entry_cnt = ASC_MAX_SG_LIST; - } + /* + * Set the sg_entry_cnt to the maximum possible. The rest of + * the SG elements will be copied when the RISC completes the + * SG elements that fit and halts. + */ + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + sg_entry_cnt = ASC_MAX_SG_LIST; + } #endif /* CC_VERY_LONG_SG_LIST */ - n_q_required = AscSgListToQueue(sg_entry_cnt); - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= - (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } else { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = le32_to_cpu(scsiq->q1.data_addr) + - le32_to_cpu(scsiq->q1.data_cnt); - extra_bytes = (uchar) ((ushort) addr & 0x0003); - if ((extra_bytes != 0) && - ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - data_cnt = le32_to_cpu(scsiq->q1.data_cnt); - if (((ushort) data_cnt & 0x01FF) == 0) { - scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; - data_cnt -= (ASC_DCNT) extra_bytes; - scsiq->q1.data_cnt = cpu_to_le32(data_cnt); - scsiq->q1.extra_bytes = extra_bytes; - } - } - } - } - } - n_q_required = 1; - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || - ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (sta); + n_q_required = AscSgListToQueue(sg_entry_cnt); + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= + (uint) n_q_required) + || ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = + AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } else { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + le32_to_cpu(scsiq->q1.data_addr) + + le32_to_cpu(scsiq->q1.data_cnt); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + data_cnt = + le32_to_cpu(scsiq->q1. + data_cnt); + if (((ushort)data_cnt & 0x01FF) + == 0) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + data_cnt -= (ASC_DCNT) + extra_bytes; + scsiq->q1.data_cnt = + cpu_to_le32 + (data_cnt); + scsiq->q1.extra_bytes = + extra_bytes; + } + } + } + } + } + n_q_required = 1; + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || + ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (sta); } -STATIC int -AscSendScsiQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar n_q_required -) +static int +AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) { - PortAddr iop_base; - uchar free_q_head; - uchar next_qp; - uchar tid_no; - uchar target_ix; - int sta; - - iop_base = asc_dvc->iop_base; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - sta = 0; - free_q_head = (uchar) AscGetVarFreeQHead(iop_base); - if (n_q_required > 1) { - if ((next_qp = AscAllocMultipleFreeQueue(iop_base, - free_q_head, (uchar) (n_q_required))) - != (uchar) ASC_QLINK_END) { - asc_dvc->last_q_shortage = 0; - scsiq->sg_head->queue_cnt = n_q_required - 1; - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng += (uchar) (n_q_required); - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } else if (n_q_required == 1) { - if ((next_qp = AscAllocFreeQueue(iop_base, - free_q_head)) != ASC_QLINK_END) { - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadyQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng++; - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } - return (sta); + PortAddr iop_base; + uchar free_q_head; + uchar next_qp; + uchar tid_no; + uchar target_ix; + int sta; + + iop_base = asc_dvc->iop_base; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + sta = 0; + free_q_head = (uchar)AscGetVarFreeQHead(iop_base); + if (n_q_required > 1) { + if ((next_qp = AscAllocMultipleFreeQueue(iop_base, + free_q_head, (uchar) + (n_q_required))) + != (uchar)ASC_QLINK_END) { + asc_dvc->last_q_shortage = 0; + scsiq->sg_head->queue_cnt = n_q_required - 1; + scsiq->q1.q_no = free_q_head; + if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng += (uchar)(n_q_required); + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } else if (n_q_required == 1) { + if ((next_qp = AscAllocFreeQueue(iop_base, + free_q_head)) != + ASC_QLINK_END) { + scsiq->q1.q_no = free_q_head; + if ((sta = AscPutReadyQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng++; + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } + return (sta); } -STATIC int -AscSgListToQueue( - int sg_list -) +static int AscSgListToQueue(int sg_list) { - int n_sg_list_qs; + int n_sg_list_qs; - n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); - if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) - n_sg_list_qs++; - return (n_sg_list_qs + 1); + n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); + if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) + n_sg_list_qs++; + return (n_sg_list_qs + 1); } - -STATIC uint -AscGetNumOfFreeQueue( - ASC_DVC_VAR *asc_dvc, - uchar target_ix, - uchar n_qs -) +static uint +AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) { - uint cur_used_qs; - uint cur_free_qs; - ASC_SCSI_BIT_ID_TYPE target_id; - uchar tid_no; - - target_id = ASC_TIX_TO_TARGET_ID(target_ix); - tid_no = ASC_TIX_TO_TID(target_ix); - if ((asc_dvc->unit_not_ready & target_id) || - (asc_dvc->queue_full_or_busy & target_id)) { - return (0); - } - if (n_qs == 1) { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) asc_dvc->last_q_shortage + - (uint) ASC_MIN_FREE_Q; - } else { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) ASC_MIN_FREE_Q; - } - if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { - cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; - if (asc_dvc->cur_dvc_qng[tid_no] >= - asc_dvc->max_dvc_qng[tid_no]) { - return (0); - } - return (cur_free_qs); - } - if (n_qs > 1) { - if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { - asc_dvc->last_q_shortage = n_qs; - } - } - return (0); + uint cur_used_qs; + uint cur_free_qs; + ASC_SCSI_BIT_ID_TYPE target_id; + uchar tid_no; + + target_id = ASC_TIX_TO_TARGET_ID(target_ix); + tid_no = ASC_TIX_TO_TID(target_ix); + if ((asc_dvc->unit_not_ready & target_id) || + (asc_dvc->queue_full_or_busy & target_id)) { + return (0); + } + if (n_qs == 1) { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; + } else { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) ASC_MIN_FREE_Q; + } + if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { + cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; + if (asc_dvc->cur_dvc_qng[tid_no] >= + asc_dvc->max_dvc_qng[tid_no]) { + return (0); + } + return (cur_free_qs); + } + if (n_qs > 1) { + if ((n_qs > asc_dvc->last_q_shortage) + && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { + asc_dvc->last_q_shortage = n_qs; + } + } + return (0); } -STATIC int -AscPutReadyQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar q_no -) +static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - ushort q_addr; - uchar tid_no; - uchar sdtr_data; - uchar syn_period_ix; - uchar syn_offset; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && - ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { - tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); - syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[syn_period_ix], - syn_offset); - scsiq->q1.cntl |= QC_MSG_OUT; - } - q_addr = ASC_QNO_TO_QADDR(q_no); - if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG ; - } - scsiq->q1.status = QS_FREE; - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_CDB_BEG, - (uchar *) scsiq->cdbptr, - scsiq->q2.cdb_len >> 1); - - DvcPutScsiQ(iop_base, - q_addr + ASC_SCSIQ_CPY_BEG, - (uchar *) &scsiq->q1.cntl, - ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); - AscWriteLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY)); - return (1); + ushort q_addr; + uchar tid_no; + uchar sdtr_data; + uchar syn_period_ix; + uchar syn_offset; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && + ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { + tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + syn_period_ix = + (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); + syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; + AscMsgOutSDTR(asc_dvc, + asc_dvc->sdtr_period_tbl[syn_period_ix], + syn_offset); + scsiq->q1.cntl |= QC_MSG_OUT; + } + q_addr = ASC_QNO_TO_QADDR(q_no); + if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + } + scsiq->q1.status = QS_FREE; + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_CDB_BEG, + (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); + + DvcPutScsiQ(iop_base, + q_addr + ASC_SCSIQ_CPY_BEG, + (uchar *)&scsiq->q1.cntl, + ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); + AscWriteLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), + (ushort)(((ushort)scsiq->q1. + q_no << 8) | (ushort)QS_READY)); + return (1); } -STATIC int -AscPutReadySgListQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar q_no -) +static int +AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - int sta; - int i; - ASC_SG_HEAD *sg_head; - ASC_SG_LIST_Q scsi_sg_q; - ASC_DCNT saved_data_addr; - ASC_DCNT saved_data_cnt; - PortAddr iop_base; - ushort sg_list_dwords; - ushort sg_index; - ushort sg_entry_cnt; - ushort q_addr; - uchar next_qp; - - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - saved_data_addr = scsiq->q1.data_addr; - saved_data_cnt = scsiq->q1.data_cnt; - scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; + int sta; + int i; + ASC_SG_HEAD *sg_head; + ASC_SG_LIST_Q scsi_sg_q; + ASC_DCNT saved_data_addr; + ASC_DCNT saved_data_cnt; + PortAddr iop_base; + ushort sg_list_dwords; + ushort sg_index; + ushort sg_entry_cnt; + ushort q_addr; + uchar next_qp; + + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + saved_data_addr = scsiq->q1.data_addr; + saved_data_cnt = scsiq->q1.data_cnt; + scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; #if CC_VERY_LONG_SG_LIST - /* - * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST - * then not all SG elements will fit in the allocated queues. - * The rest of the SG elements will be copied when the RISC - * completes the SG elements that fit and halts. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) - { - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. ASC_MAX_SG_LIST is - * already inflated by 1 to account for this. For example it - * may be 50 which is 1 + 7 queues * 7 SG elements. - */ - sg_entry_cnt = ASC_MAX_SG_LIST - 1; - - /* - * Keep track of remaining number of SG elements that will - * need to be handled from a_isr.c. - */ - scsiq->remain_sg_entry_cnt = sg_head->entry_cnt - ASC_MAX_SG_LIST; - } else - { + /* + * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST + * then not all SG elements will fit in the allocated queues. + * The rest of the SG elements will be copied when the RISC + * completes the SG elements that fit and halts. + */ + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { + /* + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. ASC_MAX_SG_LIST is + * already inflated by 1 to account for this. For example it + * may be 50 which is 1 + 7 queues * 7 SG elements. + */ + sg_entry_cnt = ASC_MAX_SG_LIST - 1; + + /* + * Keep track of remaining number of SG elements that will + * need to be handled from a_isr.c. + */ + scsiq->remain_sg_entry_cnt = + sg_head->entry_cnt - ASC_MAX_SG_LIST; + } else { #endif /* CC_VERY_LONG_SG_LIST */ - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. - */ - sg_entry_cnt = sg_head->entry_cnt - 1; + /* + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. + */ + sg_entry_cnt = sg_head->entry_cnt - 1; #if CC_VERY_LONG_SG_LIST - } + } #endif /* CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt != 0) { - scsiq->q1.cntl |= QC_SG_HEAD; - q_addr = ASC_QNO_TO_QADDR(q_no); - sg_index = 1; - scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for (i = 0; i < sg_head->queue_cnt; i++) { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { - sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - if (i == 0) { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q; - } else { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; - } - } else { + if (sg_entry_cnt != 0) { + scsiq->q1.cntl |= QC_SG_HEAD; + q_addr = ASC_QNO_TO_QADDR(q_no); + sg_index = 1; + scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + if (i == 0) { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q; + } else { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q - 1; + } + } else { #if CC_VERY_LONG_SG_LIST - /* - * This is the last SG queue in the list of - * allocated SG queues. If there are more - * SG elements than will fit in the allocated - * queues, then set the QCSG_SG_XFER_MORE flag. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) - { - scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; - } else - { + /* + * This is the last SG queue in the list of + * allocated SG queues. If there are more + * SG elements than will fit in the allocated + * queues, then set the QCSG_SG_XFER_MORE flag. + */ + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { + scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; + } else { #endif /* CC_VERY_LONG_SG_LIST */ - scsi_sg_q.cntl |= QCSG_SG_XFER_END; + scsi_sg_q.cntl |= QCSG_SG_XFER_END; #if CC_VERY_LONG_SG_LIST - } + } #endif /* CC_VERY_LONG_SG_LIST */ - sg_list_dwords = sg_entry_cnt << 1; - if (i == 0) { - scsi_sg_q.sg_list_cnt = sg_entry_cnt; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt; - } else { - scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; - } - sg_entry_cnt = 0; - } - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - scsi_sg_q.q_no = next_qp; - q_addr = ASC_QNO_TO_QADDR(next_qp); - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_SGHD_CPY_BEG, - (uchar *) &scsi_sg_q, - sizeof(ASC_SG_LIST_Q) >> 1); - AscMemDWordCopyPtrToLram(iop_base, - q_addr + ASC_SGQ_LIST_BEG, - (uchar *) &sg_head->sg_list[sg_index], - sg_list_dwords); - sg_index += ASC_SG_LIST_PER_Q; - scsiq->next_sg_index = sg_index; - } - } else { - scsiq->q1.cntl &= ~QC_SG_HEAD; - } - sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); - scsiq->q1.data_addr = saved_data_addr; - scsiq->q1.data_cnt = saved_data_cnt; - return (sta); + sg_list_dwords = sg_entry_cnt << 1; + if (i == 0) { + scsi_sg_q.sg_list_cnt = sg_entry_cnt; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt; + } else { + scsi_sg_q.sg_list_cnt = + sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt - 1; + } + sg_entry_cnt = 0; + } + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FWD)); + scsi_sg_q.q_no = next_qp; + q_addr = ASC_QNO_TO_QADDR(next_qp); + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_SGHD_CPY_BEG, + (uchar *)&scsi_sg_q, + sizeof(ASC_SG_LIST_Q) >> 1); + AscMemDWordCopyPtrToLram(iop_base, + q_addr + ASC_SGQ_LIST_BEG, + (uchar *)&sg_head-> + sg_list[sg_index], + sg_list_dwords); + sg_index += ASC_SG_LIST_PER_Q; + scsiq->next_sg_index = sg_index; + } + } else { + scsiq->q1.cntl &= ~QC_SG_HEAD; + } + sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); + scsiq->q1.data_addr = saved_data_addr; + scsiq->q1.data_cnt = saved_data_cnt; + return (sta); } -STATIC int -AscSetRunChipSynRegAtID( - PortAddr iop_base, - uchar tid_no, - uchar sdtr_data -) +static int +AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) { - int sta = FALSE; + int sta = FALSE; - if (AscHostReqRiscHalt(iop_base)) { - sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscStartChip(iop_base); - return (sta); - } - return (sta); + if (AscHostReqRiscHalt(iop_base)) { + sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscStartChip(iop_base); + return (sta); + } + return (sta); } -STATIC int -AscSetChipSynRegAtID( - PortAddr iop_base, - uchar id, - uchar sdtr_data -) +static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) { - ASC_SCSI_BIT_ID_TYPE org_id; - int i; - int sta = TRUE; - - AscSetBank(iop_base, 1); - org_id = AscReadChipDvcID(iop_base); - for (i = 0; i <= ASC_MAX_TID; i++) { - if (org_id == (0x01 << i)) - break; - } - org_id = (ASC_SCSI_BIT_ID_TYPE) i; - AscWriteChipDvcID(iop_base, id); - if (AscReadChipDvcID(iop_base) == (0x01 << id)) { - AscSetBank(iop_base, 0); - AscSetChipSyn(iop_base, sdtr_data); - if (AscGetChipSyn(iop_base) != sdtr_data) { - sta = FALSE; - } - } else { - sta = FALSE; - } - AscSetBank(iop_base, 1); - AscWriteChipDvcID(iop_base, org_id); - AscSetBank(iop_base, 0); - return (sta); + ASC_SCSI_BIT_ID_TYPE org_id; + int i; + int sta = TRUE; + + AscSetBank(iop_base, 1); + org_id = AscReadChipDvcID(iop_base); + for (i = 0; i <= ASC_MAX_TID; i++) { + if (org_id == (0x01 << i)) + break; + } + org_id = (ASC_SCSI_BIT_ID_TYPE) i; + AscWriteChipDvcID(iop_base, id); + if (AscReadChipDvcID(iop_base) == (0x01 << id)) { + AscSetBank(iop_base, 0); + AscSetChipSyn(iop_base, sdtr_data); + if (AscGetChipSyn(iop_base) != sdtr_data) { + sta = FALSE; + } + } else { + sta = FALSE; + } + AscSetBank(iop_base, 1); + AscWriteChipDvcID(iop_base, org_id); + AscSetBank(iop_base, 0); + return (sta); } -STATIC ushort -AscInitLram( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) { - uchar i; - ushort s_addr; - PortAddr iop_base; - ushort warn_code; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, - (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1) -); - i = ASC_MIN_ACTIVE_QNO; - s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (i - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - } - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) ASC_QLINK_END); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) asc_dvc->max_total_qng); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i <= (uchar) (asc_dvc->max_total_qng + 3); - i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i); - } - return (warn_code); + uchar i; + ushort s_addr; + PortAddr iop_base; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, + (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * + 64) >> 1) + ); + i = ASC_MIN_ACTIVE_QNO; + s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(i - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + } + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)ASC_QLINK_END); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)asc_dvc->max_total_qng); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i <= (uchar)(asc_dvc->max_total_qng + 3); + i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); + } + return (warn_code); } -STATIC ushort -AscInitQLinkVar( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - int i; - ushort lram_addr; - - iop_base = asc_dvc->iop_base; - AscPutRiscVarFreeQHead(iop_base, 1); - AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscPutVarFreeQHead(iop_base, 1); - AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 1)); - AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 2)); - AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B, - asc_dvc->max_total_qng); - AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); - AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); - AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); - AscPutQDoneInProgress(iop_base, 0); - lram_addr = ASC_QADR_BEG; - for (i = 0; i < 32; i++, lram_addr += 2) { - AscWriteLramWord(iop_base, lram_addr, 0); - } - return (0); + PortAddr iop_base; + int i; + ushort lram_addr; + + iop_base = asc_dvc->iop_base; + AscPutRiscVarFreeQHead(iop_base, 1); + AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscPutVarFreeQHead(iop_base, 1); + AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 1)); + AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 2)); + AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, + asc_dvc->max_total_qng); + AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); + AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); + AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); + AscPutQDoneInProgress(iop_base, 0); + lram_addr = ASC_QADR_BEG; + for (i = 0; i < 32; i++, lram_addr += 2) { + AscWriteLramWord(iop_base, lram_addr, 0); + } + return (0); } -STATIC int -AscSetLibErrorCode( - ASC_DVC_VAR *asc_dvc, - ushort err_code -) +static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) { - if (asc_dvc->err_code == 0) { - asc_dvc->err_code = err_code; - AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, - err_code); - } - return (err_code); + if (asc_dvc->err_code == 0) { + asc_dvc->err_code = err_code; + AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, + err_code); + } + return (err_code); } - -STATIC uchar -AscMsgOutSDTR( - ASC_DVC_VAR *asc_dvc, - uchar sdtr_period, - uchar sdtr_offset -) +static uchar +AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) { - EXT_MSG sdtr_buf; - uchar sdtr_period_index; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - sdtr_buf.msg_type = MS_EXTEND; - sdtr_buf.msg_len = MS_SDTR_LEN; - sdtr_buf.msg_req = MS_SDTR_CODE; - sdtr_buf.xfer_period = sdtr_period; - sdtr_offset &= ASC_SYN_MAX_OFFSET; - sdtr_buf.req_ack_offset = sdtr_offset; - if ((sdtr_period_index = - AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= - asc_dvc->max_sdtr_index) { - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &sdtr_buf, - sizeof (EXT_MSG) >> 1); - return ((sdtr_period_index << 4) | sdtr_offset); - } else { - - sdtr_buf.req_ack_offset = 0; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &sdtr_buf, - sizeof (EXT_MSG) >> 1); - return (0); - } + EXT_MSG sdtr_buf; + uchar sdtr_period_index; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + sdtr_buf.msg_type = MS_EXTEND; + sdtr_buf.msg_len = MS_SDTR_LEN; + sdtr_buf.msg_req = MS_SDTR_CODE; + sdtr_buf.xfer_period = sdtr_period; + sdtr_offset &= ASC_SYN_MAX_OFFSET; + sdtr_buf.req_ack_offset = sdtr_offset; + if ((sdtr_period_index = + AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= + asc_dvc->max_sdtr_index) { + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return ((sdtr_period_index << 4) | sdtr_offset); + } else { + + sdtr_buf.req_ack_offset = 0; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return (0); + } } -STATIC uchar -AscCalSDTRData( - ASC_DVC_VAR *asc_dvc, - uchar sdtr_period, - uchar syn_offset -) +static uchar +AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) { - uchar byte; - uchar sdtr_period_ix; - - sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); - if ( - (sdtr_period_ix > asc_dvc->max_sdtr_index) -) { - return (0xFF); - } - byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); - return (byte); + uchar byte; + uchar sdtr_period_ix; + + sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + if ((sdtr_period_ix > asc_dvc->max_sdtr_index) + ) { + return (0xFF); + } + byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); + return (byte); } -STATIC void -AscSetChipSDTR( - PortAddr iop_base, - uchar sdtr_data, - uchar tid_no -) +static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) { - AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); - return; + AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); + return; } -STATIC uchar -AscGetSynPeriodIndex( - ASC_DVC_VAR *asc_dvc, - uchar syn_time -) +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) { - uchar *period_table; - int max_index; - int min_index; - int i; - - period_table = asc_dvc->sdtr_period_tbl; - max_index = (int) asc_dvc->max_sdtr_index; - min_index = (int)asc_dvc->host_init_sdtr_index; - if ((syn_time <= period_table[max_index])) { - for (i = min_index; i < (max_index - 1); i++) { - if (syn_time <= period_table[i]) { - return ((uchar) i); - } - } - return ((uchar) max_index); - } else { - return ((uchar) (max_index + 1)); - } + uchar *period_table; + int max_index; + int min_index; + int i; + + period_table = asc_dvc->sdtr_period_tbl; + max_index = (int)asc_dvc->max_sdtr_index; + min_index = (int)asc_dvc->host_init_sdtr_index; + if ((syn_time <= period_table[max_index])) { + for (i = min_index; i < (max_index - 1); i++) { + if (syn_time <= period_table[i]) { + return ((uchar)i); + } + } + return ((uchar)max_index); + } else { + return ((uchar)(max_index + 1)); + } } -STATIC uchar -AscAllocFreeQueue( - PortAddr iop_base, - uchar free_q_head -) +static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) { - ushort q_addr; - uchar next_qp; - uchar q_status; - - q_addr = ASC_QNO_TO_QADDR(free_q_head); - q_status = (uchar) AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_STATUS)); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { - return (next_qp); - } - return (ASC_QLINK_END); + ushort q_addr; + uchar next_qp; + uchar q_status; + + q_addr = ASC_QNO_TO_QADDR(free_q_head); + q_status = (uchar)AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_STATUS)); + next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); + if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { + return (next_qp); + } + return (ASC_QLINK_END); } -STATIC uchar -AscAllocMultipleFreeQueue( - PortAddr iop_base, - uchar free_q_head, - uchar n_free_q -) +static uchar +AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) { - uchar i; + uchar i; - for (i = 0; i < n_free_q; i++) { - if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) - == ASC_QLINK_END) { - return (ASC_QLINK_END); - } - } - return (free_q_head); + for (i = 0; i < n_free_q; i++) { + if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) + == ASC_QLINK_END) { + return (ASC_QLINK_END); + } + } + return (free_q_head); } -STATIC int -AscHostReqRiscHalt( - PortAddr iop_base -) +static int AscHostReqRiscHalt(PortAddr iop_base) { - int count = 0; - int sta = 0; - uchar saved_stop_code; - - if (AscIsChipHalted(iop_base)) - return (1); - saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP -); - do { - if (AscIsChipHalted(iop_base)) { - sta = 1; - break; - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); - return (sta); + int count = 0; + int sta = 0; + uchar saved_stop_code; + + if (AscIsChipHalted(iop_base)) + return (1); + saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); + do { + if (AscIsChipHalted(iop_base)) { + sta = 1; + break; + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + return (sta); } -STATIC int -AscStopQueueExe( - PortAddr iop_base -) +static int AscStopQueueExe(PortAddr iop_base) { - int count = 0; - - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_REQ_RISC_STOP); - do { - if ( - AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & - ASC_STOP_ACK_RISC_STOP) { - return (1); - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - } - return (0); + int count = 0; + + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_REQ_RISC_STOP); + do { + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & + ASC_STOP_ACK_RISC_STOP) { + return (1); + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + } + return (0); } -STATIC void -DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) +static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) { - udelay(micro_sec); + udelay(micro_sec); } -STATIC void -DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) +static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) { - udelay((nano_sec + 999)/1000); + udelay((nano_sec + 999) / 1000); } #ifdef CONFIG_ISA -STATIC ASC_DCNT __init -AscGetEisaProductID( - PortAddr iop_base) +static ASC_DCNT __init AscGetEisaProductID(PortAddr iop_base) { - PortAddr eisa_iop; - ushort product_id_high, product_id_low; - ASC_DCNT product_id; - - eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; - product_id_low = inpw(eisa_iop); - product_id_high = inpw(eisa_iop + 2); - product_id = ((ASC_DCNT) product_id_high << 16) | - (ASC_DCNT) product_id_low; - return (product_id); + PortAddr eisa_iop; + ushort product_id_high, product_id_low; + ASC_DCNT product_id; + + eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; + product_id_low = inpw(eisa_iop); + product_id_high = inpw(eisa_iop + 2); + product_id = ((ASC_DCNT) product_id_high << 16) | + (ASC_DCNT) product_id_low; + return (product_id); } -STATIC PortAddr __init -AscSearchIOPortAddrEISA( - PortAddr iop_base) +static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base) { - ASC_DCNT eisa_product_id; - - if (iop_base == 0) { - iop_base = ASC_EISA_MIN_IOP_ADDR; - } else { - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { - eisa_product_id = AscGetEisaProductID(iop_base); - if ((eisa_product_id == ASC_EISA_ID_740) || - (eisa_product_id == ASC_EISA_ID_750)) { - if (AscFindSignature(iop_base)) { - inpw(iop_base + 4); - return (iop_base); - } - } - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - return (0); + ASC_DCNT eisa_product_id; + + if (iop_base == 0) { + iop_base = ASC_EISA_MIN_IOP_ADDR; + } else { + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { + eisa_product_id = AscGetEisaProductID(iop_base); + if ((eisa_product_id == ASC_EISA_ID_740) || + (eisa_product_id == ASC_EISA_ID_750)) { + if (AscFindSignature(iop_base)) { + inpw(iop_base + 4); + return (iop_base); + } + } + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + return (0); } #endif /* CONFIG_ISA */ -STATIC int -AscStartChip( - PortAddr iop_base -) +static int AscStartChip(PortAddr iop_base) { - AscSetChipControl(iop_base, 0); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - return (0); - } - return (1); + AscSetChipControl(iop_base, 0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + return (0); + } + return (1); } -STATIC int -AscStopChip( - PortAddr iop_base -) +static int AscStopChip(PortAddr iop_base) { - uchar cc_val; - - cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); - AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT)); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { - return (0); - } - return (1); + uchar cc_val; + + cc_val = + AscGetChipControl(iop_base) & + (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); + AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { + return (0); + } + return (1); } -STATIC int -AscIsChipHalted( - PortAddr iop_base -) +static int AscIsChipHalted(PortAddr iop_base) { - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { - return (1); - } - } - return (0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { + return (1); + } + } + return (0); } -STATIC void -AscSetChipIH( - PortAddr iop_base, - ushort ins_code -) +static void AscSetChipIH(PortAddr iop_base, ushort ins_code) { - AscSetBank(iop_base, 1); - AscWriteChipIH(iop_base, ins_code); - AscSetBank(iop_base, 0); - return; + AscSetBank(iop_base, 1); + AscWriteChipIH(iop_base, ins_code); + AscSetBank(iop_base, 0); + return; } -STATIC void -AscAckInterrupt( - PortAddr iop_base -) +static void AscAckInterrupt(PortAddr iop_base) { - uchar host_flag; - uchar risc_flag; - ushort loop; - - loop = 0; - do { - risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); - if (loop++ > 0x7FFF) { - break; - } - } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); - host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT)); - AscSetChipStatus(iop_base, CIW_INT_ACK); - loop = 0; - while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { - AscSetChipStatus(iop_base, CIW_INT_ACK); - if (loop++ > 3) { - break; - } - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - return; + uchar host_flag; + uchar risc_flag; + ushort loop; + + loop = 0; + do { + risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); + if (loop++ > 0x7FFF) { + break; + } + } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); + host_flag = + AscReadLramByte(iop_base, + ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); + AscSetChipStatus(iop_base, CIW_INT_ACK); + loop = 0; + while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { + AscSetChipStatus(iop_base, CIW_INT_ACK); + if (loop++ > 3) { + break; + } + } + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + return; } -STATIC void -AscDisableInterrupt( - PortAddr iop_base -) +static void AscDisableInterrupt(PortAddr iop_base) { - ushort cfg; + ushort cfg; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); - return; + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); + return; } -STATIC void -AscEnableInterrupt( - PortAddr iop_base -) +static void AscEnableInterrupt(PortAddr iop_base) { - ushort cfg; + ushort cfg; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); - return; + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); + return; } - - -STATIC void -AscSetBank( - PortAddr iop_base, - uchar bank -) +static void AscSetBank(PortAddr iop_base, uchar bank) { - uchar val; - - val = AscGetChipControl(iop_base) & - (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET)); - if (bank == 1) { - val |= CC_BANK_ONE; - } else if (bank == 2) { - val |= CC_DIAG | CC_BANK_ONE; - } else { - val &= ~CC_BANK_ONE; - } - AscSetChipControl(iop_base, val); - return; + uchar val; + + val = AscGetChipControl(iop_base) & + (~ + (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | + CC_CHIP_RESET)); + if (bank == 1) { + val |= CC_BANK_ONE; + } else if (bank == 2) { + val |= CC_DIAG | CC_BANK_ONE; + } else { + val &= ~CC_BANK_ONE; + } + AscSetChipControl(iop_base, val); + return; } -STATIC int -AscResetChipAndScsiBus( - ASC_DVC_VAR *asc_dvc -) +static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - int i = 10; + PortAddr iop_base; + int i = 10; - iop_base = asc_dvc->iop_base; - while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) - { - DvcSleepMilliSecond(100); - } - AscStopChip(iop_base); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); - DvcDelayNanoSecond(asc_dvc, 60000); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); - AscSetChipControl(iop_base, CC_HALT); - DvcSleepMilliSecond(200); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - return (AscIsChipHalted(iop_base)); + iop_base = asc_dvc->iop_base; + while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) + && (i-- > 0)) { + DvcSleepMilliSecond(100); + } + AscStopChip(iop_base); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); + DvcDelayNanoSecond(asc_dvc, 60000); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); + AscSetChipControl(iop_base, CC_HALT); + DvcSleepMilliSecond(200); + AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + return (AscIsChipHalted(iop_base)); } -STATIC ASC_DCNT __init -AscGetMaxDmaCount( - ushort bus_type) +static ASC_DCNT __init AscGetMaxDmaCount(ushort bus_type) { - if (bus_type & ASC_IS_ISA) - return (ASC_MAX_ISA_DMA_COUNT); - else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) - return (ASC_MAX_VL_DMA_COUNT); - return (ASC_MAX_PCI_DMA_COUNT); + if (bus_type & ASC_IS_ISA) + return (ASC_MAX_ISA_DMA_COUNT); + else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) + return (ASC_MAX_VL_DMA_COUNT); + return (ASC_MAX_PCI_DMA_COUNT); } #ifdef CONFIG_ISA -STATIC ushort __init -AscGetIsaDmaChannel( - PortAddr iop_base) +static ushort __init AscGetIsaDmaChannel(PortAddr iop_base) { - ushort channel; - - channel = AscGetChipCfgLsw(iop_base) & 0x0003; - if (channel == 0x03) - return (0); - else if (channel == 0x00) - return (7); - return (channel + 4); + ushort channel; + + channel = AscGetChipCfgLsw(iop_base) & 0x0003; + if (channel == 0x03) + return (0); + else if (channel == 0x00) + return (7); + return (channel + 4); } -STATIC ushort __init -AscSetIsaDmaChannel( - PortAddr iop_base, - ushort dma_channel) +static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) { - ushort cfg_lsw; - uchar value; - - if ((dma_channel >= 5) && (dma_channel <= 7)) { - if (dma_channel == 7) - value = 0x00; - else - value = dma_channel - 4; - cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; - cfg_lsw |= value; - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetIsaDmaChannel(iop_base)); - } - return (0); + ushort cfg_lsw; + uchar value; + + if ((dma_channel >= 5) && (dma_channel <= 7)) { + if (dma_channel == 7) + value = 0x00; + else + value = dma_channel - 4; + cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; + cfg_lsw |= value; + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetIsaDmaChannel(iop_base)); + } + return (0); } -STATIC uchar __init -AscSetIsaDmaSpeed( - PortAddr iop_base, - uchar speed_value) +static uchar __init AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) { - speed_value &= 0x07; - AscSetBank(iop_base, 1); - AscWriteChipDmaSpeed(iop_base, speed_value); - AscSetBank(iop_base, 0); - return (AscGetIsaDmaSpeed(iop_base)); + speed_value &= 0x07; + AscSetBank(iop_base, 1); + AscWriteChipDmaSpeed(iop_base, speed_value); + AscSetBank(iop_base, 0); + return (AscGetIsaDmaSpeed(iop_base)); } -STATIC uchar __init -AscGetIsaDmaSpeed( - PortAddr iop_base -) +static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base) { - uchar speed_value; + uchar speed_value; - AscSetBank(iop_base, 1); - speed_value = AscReadChipDmaSpeed(iop_base); - speed_value &= 0x07; - AscSetBank(iop_base, 0); - return (speed_value); + AscSetBank(iop_base, 1); + speed_value = AscReadChipDmaSpeed(iop_base); + speed_value &= 0x07; + AscSetBank(iop_base, 0); + return (speed_value); } #endif /* CONFIG_ISA */ -STATIC ushort __init -AscReadPCIConfigWord( - ASC_DVC_VAR *asc_dvc, - ushort pci_config_offset) +static ushort __init +AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset) { - uchar lsb, msb; + uchar lsb, msb; - lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); - msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); - return ((ushort) ((msb << 8) | lsb)); + lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); + msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); + return ((ushort)((msb << 8) | lsb)); } -STATIC ushort __init -AscInitGetConfig( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitGetConfig(ASC_DVC_VAR *asc_dvc) { - ushort warn_code; - PortAddr iop_base; - ushort PCIDeviceID; - ushort PCIVendorID; - uchar PCIRevisionID; - uchar prevCmdRegBits; - - warn_code = 0; - iop_base = asc_dvc->iop_base; - asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; - if (asc_dvc->err_code != 0) { - return (UW_ERR); - } - if (asc_dvc->bus_type == ASC_IS_PCI) { - PCIVendorID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigVendorIDRegister); - - PCIDeviceID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigDeviceIDRegister); - - PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigRevisionIDRegister); - - if (PCIVendorID != PCI_VENDOR_ID_ASP) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister); - - if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != - AscPCICmdRegBits_IOMemBusMaster) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, - (prevCmdRegBits | - AscPCICmdRegBits_IOMemBusMaster)); - - if ((DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister) - & AscPCICmdRegBits_IOMemBusMaster) - != AscPCICmdRegBits_IOMemBusMaster) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || - (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, 0x00); - if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) - != 0x00) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) < 0x20) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, 0x20); - - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) < 0x20) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - } - } + ushort warn_code; + PortAddr iop_base; + ushort PCIDeviceID; + ushort PCIVendorID; + uchar PCIRevisionID; + uchar prevCmdRegBits; + + warn_code = 0; + iop_base = asc_dvc->iop_base; + asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; + if (asc_dvc->err_code != 0) { + return (UW_ERR); + } + if (asc_dvc->bus_type == ASC_IS_PCI) { + PCIVendorID = AscReadPCIConfigWord(asc_dvc, + AscPCIConfigVendorIDRegister); + + PCIDeviceID = AscReadPCIConfigWord(asc_dvc, + AscPCIConfigDeviceIDRegister); + + PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigRevisionIDRegister); + + if (PCIVendorID != PCI_VENDOR_ID_ASP) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister); + + if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != + AscPCICmdRegBits_IOMemBusMaster) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister, + (prevCmdRegBits | + AscPCICmdRegBits_IOMemBusMaster)); + + if ((DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister) + & AscPCICmdRegBits_IOMemBusMaster) + != AscPCICmdRegBits_IOMemBusMaster) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } + if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || + (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer, 0x00); + if (DvcReadPCIConfigByte + (asc_dvc, AscPCIConfigLatencyTimer) + != 0x00) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { + if (DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer) < + 0x20) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer, + 0x20); + + if (DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer) + < 0x20) { + warn_code |= + ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } + } + } - if (AscFindSignature(iop_base)) { - warn_code |= AscInitAscDvcVar(asc_dvc); - warn_code |= AscInitFromEEP(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; - if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { - asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; - } - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return(warn_code); + if (AscFindSignature(iop_base)) { + warn_code |= AscInitAscDvcVar(asc_dvc); + warn_code |= AscInitFromEEP(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; + if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { + asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; + } + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); } -STATIC ushort __init -AscInitSetConfig( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitSetConfig(ASC_DVC_VAR *asc_dvc) { - ushort warn_code = 0; - - asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (AscFindSignature(asc_dvc->iop_base)) { - warn_code |= AscInitFromAscDvcVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); + ushort warn_code = 0; + + asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (AscFindSignature(asc_dvc->iop_base)) { + warn_code |= AscInitFromAscDvcVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); } -STATIC ushort __init -AscInitFromAscDvcVar( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - ushort cfg_msw; - ushort warn_code; - ushort pci_device_id = 0; + PortAddr iop_base; + ushort cfg_msw; + ushort warn_code; + ushort pci_device_id = 0; - iop_base = asc_dvc->iop_base; + iop_base = asc_dvc->iop_base; #ifdef CONFIG_PCI - if (asc_dvc->cfg->dev) - pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; + if (asc_dvc->cfg->dev) + pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; #endif - warn_code = 0; - cfg_msw = AscGetChipCfgMsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != - asc_dvc->cfg->cmd_qng_enabled) { - asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - } - if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { - if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) - != asc_dvc->irq_no) { - asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; - } - } - if (asc_dvc->bus_type & ASC_IS_PCI) { - cfg_msw &= 0xFFC0; - AscSetChipCfgMsw(iop_base, cfg_msw); - if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { - } else { - if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || - (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; - } - } - } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) - == ASC_CHIP_VER_ASYN_BUG) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; - } - } - if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != - asc_dvc->cfg->chip_scsi_id) { - asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; - } + warn_code = 0; + cfg_msw = AscGetChipCfgMsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != + asc_dvc->cfg->cmd_qng_enabled) { + asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + } + if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { + if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) + != asc_dvc->irq_no) { + asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; + } + } + if (asc_dvc->bus_type & ASC_IS_PCI) { + cfg_msw &= 0xFFC0; + AscSetChipCfgMsw(iop_base, cfg_msw); + if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { + } else { + if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || + (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; + asc_dvc->bug_fix_cntl |= + ASC_BUG_FIX_ASYN_USE_SYN; + } + } + } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) + == ASC_CHIP_VER_ASYN_BUG) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; + } + } + if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != + asc_dvc->cfg->chip_scsi_id) { + asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; + } #ifdef CONFIG_ISA - if (asc_dvc->bus_type & ASC_IS_ISA) { - AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); - AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); - } + if (asc_dvc->bus_type & ASC_IS_ISA) { + AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); + AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); + } #endif /* CONFIG_ISA */ - return (warn_code); + return (warn_code); } -STATIC ushort -AscInitAsc1000Driver( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) { - ushort warn_code; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && - !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (!AscFindSignature(asc_dvc->iop_base)) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return (warn_code); - } - AscDisableInterrupt(iop_base); - warn_code |= AscInitLram(asc_dvc); - if (asc_dvc->err_code != 0) - return (UW_ERR); - ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", - (ulong) _asc_mcode_chksum); - if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, - _asc_mcode_size) != _asc_mcode_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return (warn_code); - } - warn_code |= AscInitMicroCodeVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; - AscEnableInterrupt(iop_base); - return (warn_code); + ushort warn_code; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && + !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { + AscResetChipAndScsiBus(asc_dvc); + DvcSleepMilliSecond((ASC_DCNT) + ((ushort)asc_dvc->scsi_reset_wait * 1000)); + } + asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (!AscFindSignature(asc_dvc->iop_base)) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return (warn_code); + } + AscDisableInterrupt(iop_base); + warn_code |= AscInitLram(asc_dvc); + if (asc_dvc->err_code != 0) + return (UW_ERR); + ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", + (ulong)_asc_mcode_chksum); + if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, + _asc_mcode_size) != _asc_mcode_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return (warn_code); + } + warn_code |= AscInitMicroCodeVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; + AscEnableInterrupt(iop_base); + return (warn_code); } -STATIC ushort __init -AscInitAscDvcVar( - ASC_DVC_VAR *asc_dvc) +static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) { - int i; - PortAddr iop_base; - ushort warn_code; - uchar chip_version; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - asc_dvc->err_code = 0; - if ((asc_dvc->bus_type & - (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { - asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; - } - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, 0); - asc_dvc->bug_fix_cntl = 0; - asc_dvc->pci_fix_asyn_xfer = 0; - asc_dvc->pci_fix_asyn_xfer_always = 0; - /* asc_dvc->init_state initalized in AscInitGetConfig(). */ - asc_dvc->sdtr_done = 0; - asc_dvc->cur_total_qng = 0; - asc_dvc->is_in_int = 0; - asc_dvc->in_critical_cnt = 0; - asc_dvc->last_q_shortage = 0; - asc_dvc->use_tagged_qng = 0; - asc_dvc->no_scam = 0; - asc_dvc->unit_not_ready = 0; - asc_dvc->queue_full_or_busy = 0; - asc_dvc->redo_scam = 0; - asc_dvc->res2 = 0; - asc_dvc->host_init_sdtr_index = 0; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->cfg->cmd_qng_enabled = 0; - asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; - asc_dvc->init_sdtr = 0; - asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; - asc_dvc->scsi_reset_wait = 3; - asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); - asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; - asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; - asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | - ASC_LIB_VERSION_MINOR; - chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); - asc_dvc->cfg->chip_version = chip_version; - asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; - asc_dvc->max_sdtr_index = 7; - if ((asc_dvc->bus_type & ASC_IS_PCI) && - (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { - asc_dvc->bus_type = ASC_IS_PCI_ULTRA; - asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; - asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; - asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; - asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; - asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; - asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; - asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; - asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; - asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; - asc_dvc->max_sdtr_index = 15; - if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) - { - AscSetExtraControl(iop_base, - (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); - } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { - AscSetExtraControl(iop_base, - (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER)); - } - } - if (asc_dvc->bus_type == ASC_IS_PCI) { - AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); - } + int i; + PortAddr iop_base; + ushort warn_code; + uchar chip_version; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + asc_dvc->err_code = 0; + if ((asc_dvc->bus_type & + (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { + asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; + } + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, 0); + asc_dvc->bug_fix_cntl = 0; + asc_dvc->pci_fix_asyn_xfer = 0; + asc_dvc->pci_fix_asyn_xfer_always = 0; + /* asc_dvc->init_state initalized in AscInitGetConfig(). */ + asc_dvc->sdtr_done = 0; + asc_dvc->cur_total_qng = 0; + asc_dvc->is_in_int = 0; + asc_dvc->in_critical_cnt = 0; + asc_dvc->last_q_shortage = 0; + asc_dvc->use_tagged_qng = 0; + asc_dvc->no_scam = 0; + asc_dvc->unit_not_ready = 0; + asc_dvc->queue_full_or_busy = 0; + asc_dvc->redo_scam = 0; + asc_dvc->res2 = 0; + asc_dvc->host_init_sdtr_index = 0; + asc_dvc->cfg->can_tagged_qng = 0; + asc_dvc->cfg->cmd_qng_enabled = 0; + asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; + asc_dvc->init_sdtr = 0; + asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; + asc_dvc->scsi_reset_wait = 3; + asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); + asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; + asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; + asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | + ASC_LIB_VERSION_MINOR; + chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); + asc_dvc->cfg->chip_version = chip_version; + asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; + asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; + asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; + asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; + asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; + asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; + asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; + asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; + asc_dvc->max_sdtr_index = 7; + if ((asc_dvc->bus_type & ASC_IS_PCI) && + (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { + asc_dvc->bus_type = ASC_IS_PCI_ULTRA; + asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; + asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; + asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; + asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; + asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; + asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; + asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; + asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; + asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; + asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; + asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; + asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; + asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; + asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; + asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; + asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; + asc_dvc->max_sdtr_index = 15; + if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); + } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | + SEC_ENABLE_FILTER)); + } + } + if (asc_dvc->bus_type == ASC_IS_PCI) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); + } - asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; - if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { - AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); - asc_dvc->bus_type = ASC_IS_ISAPNP; - } + asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; + if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { + AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); + asc_dvc->bus_type = ASC_IS_ISAPNP; + } #ifdef CONFIG_ISA - if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { - asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base); - } + if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { + asc_dvc->cfg->isa_dma_channel = + (uchar)AscGetIsaDmaChannel(iop_base); + } #endif /* CONFIG_ISA */ - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->cur_dvc_qng[i] = 0; - asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; - asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L; - asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L; - asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; - } - return (warn_code); + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->cur_dvc_qng[i] = 0; + asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; + asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L; + asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L; + asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; + } + return (warn_code); } -STATIC ushort __init -AscInitFromEEP(ASC_DVC_VAR *asc_dvc) +static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc) { - ASCEEP_CONFIG eep_config_buf; - ASCEEP_CONFIG *eep_config; - PortAddr iop_base; - ushort chksum; - ushort warn_code; - ushort cfg_msw, cfg_lsw; - int i; - int write_eep = 0; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); - AscStopQueueExe(iop_base); - if ((AscStopChip(iop_base) == FALSE) || - (AscGetChipScsiCtrl(iop_base) != 0)) { - asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - if (AscIsChipHalted(iop_base) == FALSE) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - eep_config = (ASCEEP_CONFIG *) &eep_config_buf; - cfg_msw = AscGetChipCfgMsw(iop_base); - cfg_lsw = AscGetChipCfgLsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); - ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); - if (chksum == 0) { - chksum = 0xaa55; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - if (asc_dvc->cfg->chip_version == 3) { - if (eep_config->cfg_lsw != cfg_lsw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base); - } - if (eep_config->cfg_msw != cfg_msw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - } - } - } - eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; - eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; - ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", - eep_config->chksum); - if (chksum != eep_config->chksum) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == - ASC_CHIP_VER_PCI_ULTRA_3050 ) - { - ASC_DBG(1, -"AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); - eep_config->init_sdtr = 0xFF; - eep_config->disc_enable = 0xFF; - eep_config->start_motor = 0xFF; - eep_config->use_cmd_qng = 0; - eep_config->max_total_qng = 0xF0; - eep_config->max_tag_qng = 0x20; - eep_config->cntl = 0xBFFF; - ASC_EEP_SET_CHIP_ID(eep_config, 7); - eep_config->no_scam = 0; - eep_config->adapter_info[0] = 0; - eep_config->adapter_info[1] = 0; - eep_config->adapter_info[2] = 0; - eep_config->adapter_info[3] = 0; - eep_config->adapter_info[4] = 0; - /* Indicate EEPROM-less board. */ - eep_config->adapter_info[5] = 0xBB; - } else { - ASC_PRINT( -"AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); - write_eep = 1; - warn_code |= ASC_WARN_EEPROM_CHKSUM; - } - } - asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; - asc_dvc->cfg->disc_enable = eep_config->disc_enable; - asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; - asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); - asc_dvc->start_motor = eep_config->start_motor; - asc_dvc->dvc_cntl = eep_config->cntl; - asc_dvc->no_scam = eep_config->no_scam; - asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; - asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; - asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; - asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; - asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; - asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; - if (!AscTestExternalLram(asc_dvc)) { - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) { - eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; - } else { - eep_config->cfg_msw |= 0x0800; - cfg_msw |= 0x0800; - AscSetChipCfgMsw(iop_base, cfg_msw); - eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; - } - } else { - } - if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; - } - if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; - } - if (eep_config->max_tag_qng > eep_config->max_total_qng) { - eep_config->max_tag_qng = eep_config->max_total_qng; - } - if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { - eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; - } - asc_dvc->max_total_qng = eep_config->max_total_qng; - if ((eep_config->use_cmd_qng & eep_config->disc_enable) != - eep_config->use_cmd_qng) { - eep_config->disc_enable = eep_config->use_cmd_qng; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { - asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); - } - ASC_EEP_SET_CHIP_ID(eep_config, ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); - asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && - !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { - asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; - } + ASCEEP_CONFIG eep_config_buf; + ASCEEP_CONFIG *eep_config; + PortAddr iop_base; + ushort chksum; + ushort warn_code; + ushort cfg_msw, cfg_lsw; + int i; + int write_eep = 0; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); + AscStopQueueExe(iop_base); + if ((AscStopChip(iop_base) == FALSE) || + (AscGetChipScsiCtrl(iop_base) != 0)) { + asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; + AscResetChipAndScsiBus(asc_dvc); + DvcSleepMilliSecond((ASC_DCNT) + ((ushort)asc_dvc->scsi_reset_wait * 1000)); + } + if (AscIsChipHalted(iop_base) == FALSE) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + eep_config = (ASCEEP_CONFIG *)&eep_config_buf; + cfg_msw = AscGetChipCfgMsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); + ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); + if (chksum == 0) { + chksum = 0xaa55; + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + if (asc_dvc->cfg->chip_version == 3) { + if (eep_config->cfg_lsw != cfg_lsw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_lsw = + AscGetChipCfgLsw(iop_base); + } + if (eep_config->cfg_msw != cfg_msw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_msw = + AscGetChipCfgMsw(iop_base); + } + } + } + eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; + eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; + ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", + eep_config->chksum); + if (chksum != eep_config->chksum) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == + ASC_CHIP_VER_PCI_ULTRA_3050) { + ASC_DBG(1, + "AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); + eep_config->init_sdtr = 0xFF; + eep_config->disc_enable = 0xFF; + eep_config->start_motor = 0xFF; + eep_config->use_cmd_qng = 0; + eep_config->max_total_qng = 0xF0; + eep_config->max_tag_qng = 0x20; + eep_config->cntl = 0xBFFF; + ASC_EEP_SET_CHIP_ID(eep_config, 7); + eep_config->no_scam = 0; + eep_config->adapter_info[0] = 0; + eep_config->adapter_info[1] = 0; + eep_config->adapter_info[2] = 0; + eep_config->adapter_info[3] = 0; + eep_config->adapter_info[4] = 0; + /* Indicate EEPROM-less board. */ + eep_config->adapter_info[5] = 0xBB; + } else { + ASC_PRINT + ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); + write_eep = 1; + warn_code |= ASC_WARN_EEPROM_CHKSUM; + } + } + asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; + asc_dvc->cfg->disc_enable = eep_config->disc_enable; + asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; + asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); + asc_dvc->start_motor = eep_config->start_motor; + asc_dvc->dvc_cntl = eep_config->cntl; + asc_dvc->no_scam = eep_config->no_scam; + asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; + asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; + asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; + asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; + asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; + asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; + if (!AscTestExternalLram(asc_dvc)) { + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == + ASC_IS_PCI_ULTRA)) { + eep_config->max_total_qng = + ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = + ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; + } else { + eep_config->cfg_msw |= 0x0800; + cfg_msw |= 0x0800; + AscSetChipCfgMsw(iop_base, cfg_msw); + eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; + } + } else { + } + if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; + } + if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; + } + if (eep_config->max_tag_qng > eep_config->max_total_qng) { + eep_config->max_tag_qng = eep_config->max_total_qng; + } + if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { + eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; + } + asc_dvc->max_total_qng = eep_config->max_total_qng; + if ((eep_config->use_cmd_qng & eep_config->disc_enable) != + eep_config->use_cmd_qng) { + eep_config->disc_enable = eep_config->use_cmd_qng; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { + asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); + } + ASC_EEP_SET_CHIP_ID(eep_config, + ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); + asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && + !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { + asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; + } - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; - asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; - asc_dvc->cfg->sdtr_period_offset[i] = - (uchar) (ASC_DEF_SDTR_OFFSET | - (asc_dvc->host_init_sdtr_index << 4)); - } - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - if (write_eep) { - if ((i = AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type)) != - 0) { - ASC_PRINT1( -"AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", i); - } else { - ASC_PRINT("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); - } - } - return (warn_code); + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; + asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; + asc_dvc->cfg->sdtr_period_offset[i] = + (uchar)(ASC_DEF_SDTR_OFFSET | + (asc_dvc->host_init_sdtr_index << 4)); + } + eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); + if (write_eep) { + if ((i = + AscSetEEPConfig(iop_base, eep_config, + asc_dvc->bus_type)) != 0) { + ASC_PRINT1 + ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", + i); + } else { + ASC_PRINT + ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); + } + } + return (warn_code); } -STATIC ushort -AscInitMicroCodeVar( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) { - int i; - ushort warn_code; - PortAddr iop_base; - ASC_PADDR phy_addr; - ASC_DCNT phy_size; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - for (i = 0; i <= ASC_MAX_TID; i++) { - AscPutMCodeInitSDTRAtID(iop_base, i, - asc_dvc->cfg->sdtr_period_offset[i] -); - } + int i; + ushort warn_code; + PortAddr iop_base; + ASC_PADDR phy_addr; + ASC_DCNT phy_size; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + for (i = 0; i <= ASC_MAX_TID; i++) { + AscPutMCodeInitSDTRAtID(iop_base, i, + asc_dvc->cfg->sdtr_period_offset[i] + ); + } - AscInitQLinkVar(asc_dvc); - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, - ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); - - /* Align overrun buffer on an 8 byte boundary. */ - phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); - phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, - (uchar *) &phy_addr, 1); - phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, - (uchar *) &phy_size, 1); - - asc_dvc->cfg->mcode_date = - AscReadLramWord(iop_base, (ushort) ASCV_MC_DATE_W); - asc_dvc->cfg->mcode_version = - AscReadLramWord(iop_base, (ushort) ASCV_MC_VER_W); - - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - if (AscStartChip(iop_base) != 1) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } + AscInitQLinkVar(asc_dvc); + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, + ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); + + /* Align overrun buffer on an 8 byte boundary. */ + phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); + phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, + (uchar *)&phy_addr, 1); + phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, + (uchar *)&phy_size, 1); + + asc_dvc->cfg->mcode_date = + AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); + asc_dvc->cfg->mcode_version = + AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); + + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + if (AscStartChip(iop_base) != 1) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } - return (warn_code); + return (warn_code); } -STATIC int __init -AscTestExternalLram( - ASC_DVC_VAR *asc_dvc) +static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - ushort q_addr; - ushort saved_word; - int sta; - - iop_base = asc_dvc->iop_base; - sta = 0; - q_addr = ASC_QNO_TO_QADDR(241); - saved_word = AscReadLramWord(iop_base, q_addr); - AscSetChipLramAddr(iop_base, q_addr); - AscSetChipLramData(iop_base, 0x55AA); - DvcSleepMilliSecond(10); - AscSetChipLramAddr(iop_base, q_addr); - if (AscGetChipLramData(iop_base) == 0x55AA) { - sta = 1; - AscWriteLramWord(iop_base, q_addr, saved_word); - } - return (sta); + PortAddr iop_base; + ushort q_addr; + ushort saved_word; + int sta; + + iop_base = asc_dvc->iop_base; + sta = 0; + q_addr = ASC_QNO_TO_QADDR(241); + saved_word = AscReadLramWord(iop_base, q_addr); + AscSetChipLramAddr(iop_base, q_addr); + AscSetChipLramData(iop_base, 0x55AA); + DvcSleepMilliSecond(10); + AscSetChipLramAddr(iop_base, q_addr); + if (AscGetChipLramData(iop_base) == 0x55AA) { + sta = 1; + AscWriteLramWord(iop_base, q_addr, saved_word); + } + return (sta); } -STATIC int __init -AscWriteEEPCmdReg( - PortAddr iop_base, - uchar cmd_reg -) +static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) { - uchar read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPCmd(iop_base, cmd_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPCmd(iop_base); - if (read_back == cmd_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } + uchar read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPCmd(iop_base, cmd_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPCmd(iop_base); + if (read_back == cmd_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } } -STATIC int __init -AscWriteEEPDataReg( - PortAddr iop_base, - ushort data_reg -) +static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) { - ushort read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPData(iop_base, data_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPData(iop_base); - if (read_back == data_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } + ushort read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPData(iop_base, data_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPData(iop_base); + if (read_back == data_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } } -STATIC void __init -AscWaitEEPRead(void) +static void __init AscWaitEEPRead(void) { - DvcSleepMilliSecond(1); - return; + DvcSleepMilliSecond(1); + return; } -STATIC void __init -AscWaitEEPWrite(void) +static void __init AscWaitEEPWrite(void) { - DvcSleepMilliSecond(20); - return; + DvcSleepMilliSecond(20); + return; } -STATIC ushort __init -AscReadEEPWord( - PortAddr iop_base, - uchar addr) +static ushort __init AscReadEEPWord(PortAddr iop_base, uchar addr) { - ushort read_wval; - uchar cmd_reg; - - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - cmd_reg = addr | ASC_EEP_CMD_READ; - AscWriteEEPCmdReg(iop_base, cmd_reg); - AscWaitEEPRead(); - read_wval = AscGetChipEEPData(iop_base); - AscWaitEEPRead(); - return (read_wval); + ushort read_wval; + uchar cmd_reg; + + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + cmd_reg = addr | ASC_EEP_CMD_READ; + AscWriteEEPCmdReg(iop_base, cmd_reg); + AscWaitEEPRead(); + read_wval = AscGetChipEEPData(iop_base); + AscWaitEEPRead(); + return (read_wval); } -STATIC ushort __init -AscWriteEEPWord( - PortAddr iop_base, - uchar addr, - ushort word_val) +static ushort __init +AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) { - ushort read_wval; - - read_wval = AscReadEEPWord(iop_base, addr); - if (read_wval != word_val) { - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); - AscWaitEEPRead(); - AscWriteEEPDataReg(iop_base, word_val); - AscWaitEEPRead(); - AscWriteEEPCmdReg(iop_base, - (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr)); - AscWaitEEPWrite(); - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - return (AscReadEEPWord(iop_base, addr)); - } - return (read_wval); + ushort read_wval; + + read_wval = AscReadEEPWord(iop_base, addr); + if (read_wval != word_val) { + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); + AscWaitEEPRead(); + AscWriteEEPDataReg(iop_base, word_val); + AscWaitEEPRead(); + AscWriteEEPCmdReg(iop_base, + (uchar)((uchar)ASC_EEP_CMD_WRITE | addr)); + AscWaitEEPWrite(); + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + return (AscReadEEPWord(iop_base, addr)); + } + return (read_wval); } -STATIC ushort __init -AscGetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type) +static ushort __init +AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - ushort wval; - ushort sum; - ushort *wbuf; - int cfg_beg; - int cfg_end; - int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; - int s_addr; - - wbuf = (ushort *) cfg_buf; - sum = 0; - /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); - sum += *wbuf; - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - wval = AscReadEEPWord( iop_base, ( uchar )s_addr ) ; - if (s_addr <= uchar_end_in_config) { - /* - * Swap all char fields - must unswap bytes already swapped - * by AscReadEEPWord(). - */ - *wbuf = le16_to_cpu(wval); - } else { - /* Don't swap word field at the end - cntl field. */ - *wbuf = wval; - } - sum += wval; /* Checksum treats all EEPROM data as words. */ - } - /* - * Read the checksum word which will be compared against 'sum' - * by the caller. Word field already swapped. - */ - *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); - return (sum); + ushort wval; + ushort sum; + ushort *wbuf; + int cfg_beg; + int cfg_end; + int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; + int s_addr; + + wbuf = (ushort *)cfg_buf; + sum = 0; + /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + sum += *wbuf; + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + wval = AscReadEEPWord(iop_base, (uchar)s_addr); + if (s_addr <= uchar_end_in_config) { + /* + * Swap all char fields - must unswap bytes already swapped + * by AscReadEEPWord(). + */ + *wbuf = le16_to_cpu(wval); + } else { + /* Don't swap word field at the end - cntl field. */ + *wbuf = wval; + } + sum += wval; /* Checksum treats all EEPROM data as words. */ + } + /* + * Read the checksum word which will be compared against 'sum' + * by the caller. Word field already swapped. + */ + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + return (sum); } -STATIC int __init -AscSetEEPConfigOnce( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type) +static int __init +AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - int n_error; - ushort *wbuf; - ushort word; - ushort sum; - int s_addr; - int cfg_beg; - int cfg_end; - int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; - - - wbuf = (ushort *) cfg_buf; - n_error = 0; - sum = 0; - /* Write two config words; AscWriteEEPWord() will swap bytes. */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - sum += *wbuf; - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - if (s_addr <= uchar_end_in_config) { - /* - * This is a char field. Swap char fields before they are - * swapped again by AscWriteEEPWord(). - */ - word = cpu_to_le16(*wbuf); - if (word != AscWriteEEPWord( iop_base, (uchar) s_addr, word)) { - n_error++; - } - } else { - /* Don't swap word field at the end - cntl field. */ - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - sum += *wbuf; /* Checksum calculated from word values. */ - } - /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ - *wbuf = sum; - if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) { - n_error++; - } + int n_error; + ushort *wbuf; + ushort word; + ushort sum; + int s_addr; + int cfg_beg; + int cfg_end; + int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; + + wbuf = (ushort *)cfg_buf; + n_error = 0; + sum = 0; + /* Write two config words; AscWriteEEPWord() will swap bytes. */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + sum += *wbuf; + if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { + n_error++; + } + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + if (s_addr <= uchar_end_in_config) { + /* + * This is a char field. Swap char fields before they are + * swapped again by AscWriteEEPWord(). + */ + word = cpu_to_le16(*wbuf); + if (word != + AscWriteEEPWord(iop_base, (uchar)s_addr, word)) { + n_error++; + } + } else { + /* Don't swap word field at the end - cntl field. */ + if (*wbuf != + AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { + n_error++; + } + } + sum += *wbuf; /* Checksum calculated from word values. */ + } + /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ + *wbuf = sum; + if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) { + n_error++; + } - /* Read EEPROM back again. */ - wbuf = (ushort *) cfg_buf; - /* - * Read two config words; Byte-swapping done by AscReadEEPWord(). - */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { - n_error++; - } - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - if (s_addr <= uchar_end_in_config) { - /* - * Swap all char fields. Must unswap bytes already swapped - * by AscReadEEPWord(). - */ - word = le16_to_cpu(AscReadEEPWord(iop_base, (uchar) s_addr)); - } else { - /* Don't swap word field at the end - cntl field. */ - word = AscReadEEPWord(iop_base, (uchar) s_addr); - } - if (*wbuf != word) { - n_error++; - } - } - /* Read checksum; Byte swapping not needed. */ - if (AscReadEEPWord(iop_base, (uchar) s_addr) != sum) { - n_error++; - } - return (n_error); + /* Read EEPROM back again. */ + wbuf = (ushort *)cfg_buf; + /* + * Read two config words; Byte-swapping done by AscReadEEPWord(). + */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) { + n_error++; + } + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + if (s_addr <= uchar_end_in_config) { + /* + * Swap all char fields. Must unswap bytes already swapped + * by AscReadEEPWord(). + */ + word = + le16_to_cpu(AscReadEEPWord + (iop_base, (uchar)s_addr)); + } else { + /* Don't swap word field at the end - cntl field. */ + word = AscReadEEPWord(iop_base, (uchar)s_addr); + } + if (*wbuf != word) { + n_error++; + } + } + /* Read checksum; Byte swapping not needed. */ + if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) { + n_error++; + } + return (n_error); } -STATIC int __init -AscSetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type -) +static int __init +AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - int retry; - int n_error; - - retry = 0; - while (TRUE) { - if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, - bus_type)) == 0) { - break; - } - if (++retry > ASC_EEP_MAX_RETRY) { - break; - } - } - return (n_error); + int retry; + int n_error; + + retry = 0; + while (TRUE) { + if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, + bus_type)) == 0) { + break; + } + if (++retry > ASC_EEP_MAX_RETRY) { + break; + } + } + return (n_error); } -STATIC void -AscAsyncFix( - ASC_DVC_VAR *asc_dvc, - uchar tid_no, - ASC_SCSI_INQUIRY *inq) +static void +AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - uchar dvc_type; - ASC_SCSI_BIT_ID_TYPE tid_bits; - - dvc_type = ASC_INQ_DVC_TYPE(inq); - tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); - - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) - { - if (!(asc_dvc->init_sdtr & tid_bits)) - { - if ((dvc_type == TYPE_ROM) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "HP ", 3) == 0)) - { - asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; - } - asc_dvc->pci_fix_asyn_xfer |= tid_bits; - if ((dvc_type == TYPE_PROCESSOR) || - (dvc_type == TYPE_SCANNER) || - (dvc_type == TYPE_ROM) || - (dvc_type == TYPE_TAPE)) - { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } - - if (asc_dvc->pci_fix_asyn_xfer & tid_bits) - { - AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - } - } - return; + uchar dvc_type; + ASC_SCSI_BIT_ID_TYPE tid_bits; + + dvc_type = ASC_INQ_DVC_TYPE(inq); + tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); + + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { + if (!(asc_dvc->init_sdtr & tid_bits)) { + if ((dvc_type == TYPE_ROM) && + (AscCompareString((uchar *)inq->vendor_id, + (uchar *)"HP ", 3) == 0)) { + asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; + } + asc_dvc->pci_fix_asyn_xfer |= tid_bits; + if ((dvc_type == TYPE_PROCESSOR) || + (dvc_type == TYPE_SCANNER) || + (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { + AscSetRunChipSynRegAtID(asc_dvc->iop_base, + tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); + } + } + } + return; } -STATIC int -AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) +static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) { - if ((inq->add_len >= 32) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "QUANTUM XP34301", 15) == 0) && - (AscCompareString((uchar *) inq->product_rev_level, - (uchar *) "1071", 4) == 0)) - { - return 0; - } - return 1; + if ((inq->add_len >= 32) && + (AscCompareString((uchar *)inq->vendor_id, + (uchar *)"QUANTUM XP34301", 15) == 0) && + (AscCompareString((uchar *)inq->product_rev_level, + (uchar *)"1071", 4) == 0)) { + return 0; + } + return 1; } -STATIC void -AscInquiryHandling(ASC_DVC_VAR *asc_dvc, - uchar tid_no, ASC_SCSI_INQUIRY *inq) +static void +AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); - ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; - - orig_init_sdtr = asc_dvc->init_sdtr; - orig_use_tagged_qng = asc_dvc->use_tagged_qng; - - asc_dvc->init_sdtr &= ~tid_bit; - asc_dvc->cfg->can_tagged_qng &= ~tid_bit; - asc_dvc->use_tagged_qng &= ~tid_bit; - - if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) { - if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) { - asc_dvc->init_sdtr |= tid_bit; - } - if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && - ASC_INQ_CMD_QUEUE(inq)) { - if (AscTagQueuingSafe(inq)) { - asc_dvc->use_tagged_qng |= tid_bit; - asc_dvc->cfg->can_tagged_qng |= tid_bit; - } - } - } - if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { - AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, - asc_dvc->use_tagged_qng); - AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, - asc_dvc->cfg->can_tagged_qng); - - asc_dvc->max_dvc_qng[tid_no] = - asc_dvc->cfg->max_tag_qng[tid_no]; - AscWriteLramByte(asc_dvc->iop_base, - (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no), - asc_dvc->max_dvc_qng[tid_no]); - } - if (orig_init_sdtr != asc_dvc->init_sdtr) { - AscAsyncFix(asc_dvc, tid_no, inq); - } - return; + ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); + ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; + + orig_init_sdtr = asc_dvc->init_sdtr; + orig_use_tagged_qng = asc_dvc->use_tagged_qng; + + asc_dvc->init_sdtr &= ~tid_bit; + asc_dvc->cfg->can_tagged_qng &= ~tid_bit; + asc_dvc->use_tagged_qng &= ~tid_bit; + + if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) { + if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) { + asc_dvc->init_sdtr |= tid_bit; + } + if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && + ASC_INQ_CMD_QUEUE(inq)) { + if (AscTagQueuingSafe(inq)) { + asc_dvc->use_tagged_qng |= tid_bit; + asc_dvc->cfg->can_tagged_qng |= tid_bit; + } + } + } + if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { + AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, + asc_dvc->use_tagged_qng); + AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, + asc_dvc->cfg->can_tagged_qng); + + asc_dvc->max_dvc_qng[tid_no] = + asc_dvc->cfg->max_tag_qng[tid_no]; + AscWriteLramByte(asc_dvc->iop_base, + (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no), + asc_dvc->max_dvc_qng[tid_no]); + } + if (orig_init_sdtr != asc_dvc->init_sdtr) { + AscAsyncFix(asc_dvc, tid_no, inq); + } + return; } -STATIC int -AscCompareString( - uchar *str1, - uchar *str2, - int len -) +static int AscCompareString(uchar *str1, uchar *str2, int len) { - int i; - int diff; + int i; + int diff; - for (i = 0; i < len; i++) { - diff = (int) (str1[i] - str2[i]); - if (diff != 0) - return (diff); - } - return (0); + for (i = 0; i < len; i++) { + diff = (int)(str1[i] - str2[i]); + if (diff != 0) + return (diff); + } + return (0); } -STATIC uchar -AscReadLramByte( - PortAddr iop_base, - ushort addr -) +static uchar AscReadLramByte(PortAddr iop_base, ushort addr) { - uchar byte_data; - ushort word_data; - - if (isodd_word(addr)) { - AscSetChipLramAddr(iop_base, addr - 1); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar) ((word_data >> 8) & 0xFF); - } else { - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar) (word_data & 0xFF); - } - return (byte_data); + uchar byte_data; + ushort word_data; + + if (isodd_word(addr)) { + AscSetChipLramAddr(iop_base, addr - 1); + word_data = AscGetChipLramData(iop_base); + byte_data = (uchar)((word_data >> 8) & 0xFF); + } else { + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + byte_data = (uchar)(word_data & 0xFF); + } + return (byte_data); } -STATIC ushort -AscReadLramWord( - PortAddr iop_base, - ushort addr -) + +static ushort AscReadLramWord(PortAddr iop_base, ushort addr) { - ushort word_data; + ushort word_data; - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - return (word_data); + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + return (word_data); } #if CC_VERY_LONG_SG_LIST -STATIC ASC_DCNT -AscReadLramDWord( - PortAddr iop_base, - ushort addr -) +static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) { - ushort val_low, val_high; - ASC_DCNT dword_data; - - AscSetChipLramAddr(iop_base, addr); - val_low = AscGetChipLramData(iop_base); - val_high = AscGetChipLramData(iop_base); - dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; - return (dword_data); + ushort val_low, val_high; + ASC_DCNT dword_data; + + AscSetChipLramAddr(iop_base, addr); + val_low = AscGetChipLramData(iop_base); + val_high = AscGetChipLramData(iop_base); + dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; + return (dword_data); } #endif /* CC_VERY_LONG_SG_LIST */ -STATIC void -AscWriteLramWord( - PortAddr iop_base, - ushort addr, - ushort word_val -) +static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) { - AscSetChipLramAddr(iop_base, addr); - AscSetChipLramData(iop_base, word_val); - return; + AscSetChipLramAddr(iop_base, addr); + AscSetChipLramData(iop_base, word_val); + return; } -STATIC void -AscWriteLramByte( - PortAddr iop_base, - ushort addr, - uchar byte_val -) +static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) { - ushort word_data; - - if (isodd_word(addr)) { - addr--; - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0x00FF; - word_data |= (((ushort) byte_val << 8) & 0xFF00); - } else { - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0xFF00; - word_data |= ((ushort) byte_val & 0x00FF); - } - AscWriteLramWord(iop_base, addr, word_data); - return; + ushort word_data; + + if (isodd_word(addr)) { + addr--; + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0x00FF; + word_data |= (((ushort)byte_val << 8) & 0xFF00); + } else { + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0xFF00; + word_data |= ((ushort)byte_val & 0x00FF); + } + AscWriteLramWord(iop_base, addr, word_data); + return; } /* @@ -12841,30 +11628,26 @@ AscWriteLramByte( * The source data is assumed to be in little-endian order in memory * and is maintained in little-endian order when written to LRAM. */ -STATIC void -AscMemWordCopyPtrToLram( - PortAddr iop_base, - ushort s_addr, - uchar *s_buffer, - int words -) +static void +AscMemWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int words) { - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - /* - * On a little-endian system the second argument below - * produces a little-endian ushort which is written to - * LRAM in little-endian order. On a big-endian system - * the second argument produces a big-endian ushort which - * is "transparently" byte-swapped by outpw() and written - * in little-endian order to LRAM. - */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 1] << 8) | s_buffer[i]); - } - return; + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + /* + * On a little-endian system the second argument below + * produces a little-endian ushort which is written to + * LRAM in little-endian order. On a big-endian system + * the second argument produces a big-endian ushort which + * is "transparently" byte-swapped by outpw() and written + * in little-endian order to LRAM. + */ + outpw(iop_base + IOP_RAM_DATA, + ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); + } + return; } /* @@ -12873,24 +11656,18 @@ AscMemWordCopyPtrToLram( * The source data is assumed to be in little-endian order in memory * and is maintained in little-endian order when writen to LRAM. */ -STATIC void -AscMemDWordCopyPtrToLram( - PortAddr iop_base, - ushort s_addr, - uchar *s_buffer, - int dwords -) +static void +AscMemDWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int dwords) { - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 4 * dwords; i += 4) { - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ - } - return; + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 4 * dwords; i += 4) { + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ + } + return; } /* @@ -12899,61 +11676,46 @@ AscMemDWordCopyPtrToLram( * The source data is assumed to be in little-endian order in LRAM * and is maintained in little-endian order when written to memory. */ -STATIC void -AscMemWordCopyPtrFromLram( - PortAddr iop_base, - ushort s_addr, - uchar *d_buffer, - int words -) +static void +AscMemWordCopyPtrFromLram(PortAddr iop_base, + ushort s_addr, uchar *d_buffer, int words) { - int i; - ushort word; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - word = inpw(iop_base + IOP_RAM_DATA); - d_buffer[i] = word & 0xff; - d_buffer[i + 1] = (word >> 8) & 0xff; - } - return; + int i; + ushort word; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + word = inpw(iop_base + IOP_RAM_DATA); + d_buffer[i] = word & 0xff; + d_buffer[i + 1] = (word >> 8) & 0xff; + } + return; } -STATIC ASC_DCNT -AscMemSumLramWord( - PortAddr iop_base, - ushort s_addr, - int words -) +static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) { - ASC_DCNT sum; - int i; + ASC_DCNT sum; + int i; - sum = 0L; - for (i = 0; i < words; i++, s_addr += 2) { - sum += AscReadLramWord(iop_base, s_addr); - } - return (sum); + sum = 0L; + for (i = 0; i < words; i++, s_addr += 2) { + sum += AscReadLramWord(iop_base, s_addr); + } + return (sum); } -STATIC void -AscMemWordSetLram( - PortAddr iop_base, - ushort s_addr, - ushort set_wval, - int words -) +static void +AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) { - int i; + int i; - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++) { - AscSetChipLramData(iop_base, set_wval); - } - return; + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++) { + AscSetChipLramData(iop_base, set_wval); + } + return; } - /* * --- Adv Library Functions */ @@ -12961,1076 +11723,2112 @@ AscMemWordSetLram( /* a_mcode.h */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc3550_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, 0x01, 0x00, 0x48, 0xe4, - 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, - 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6, - 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00, 0x00, 0xec, 0x85, 0xf0, - 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, - 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80, - 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, - 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, - 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54, - 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00, 0x3e, 0x00, 0x80, 0x00, - 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, - 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55, - 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0, 0x03, 0xf7, 0x06, 0xf7, - 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, - 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0, - 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, - 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, - 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0, - 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, - 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, - 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15, - 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, - 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, - 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, - 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x9e, 0x00, 0xa8, 0x00, - 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, - 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08, - 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x06, 0x12, - 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, - 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47, - 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55, 0x14, 0x56, 0x77, 0x57, - 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, - 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xcf, - 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, - 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b, 0x02, 0xfe, 0xd4, 0x0c, - 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, - 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02, - 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02, 0xfe, 0x46, 0xf0, 0xfe, - 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, - 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18, - 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, - 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, - 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd, - 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x17, 0x06, - 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, - 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f, - 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe, 0x69, 0x10, 0x17, 0x06, - 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, - 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40, - 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0x99, 0x01, - 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, - 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b, - 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0, 0xfe, 0x56, 0x03, 0xfe, - 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, - 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04, - 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40, 0x01, 0x0e, 0xac, 0x75, - 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, - 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4, - 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe, 0x0a, 0xf0, 0xfe, 0x7a, - 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, - 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c, - 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3, 0x0a, 0xca, 0x01, 0x0e, - 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, - 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f, - 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2b, 0xff, 0x02, - 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, - 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, - 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d, 0xfe, 0x2a, 0x13, 0x2f, - 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, - 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12, - 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, - 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, - 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, - 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a, 0xfe, 0x70, 0x12, 0x49, - 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, - 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12, - 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05, 0x11, 0xfe, 0xe3, 0x00, - 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, - 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08, - 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01, 0x86, 0x24, 0x06, 0x12, - 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, - 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe, - 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13, 0x47, 0x01, 0xa7, 0x26, - 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, - 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c, - 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x14, - 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, - 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04, - 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68, 0x06, 0x11, 0x9a, 0x01, - 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, - 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe, - 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07, 0x8d, 0x81, 0x02, 0x22, - 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, - 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32, - 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15, 0xfe, 0x1b, 0x00, 0x01, - 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, - 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d, - 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, - 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, - 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02, - 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x77, 0xfe, 0xca, - 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, - 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1, - 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f, 0x40, 0x12, 0x58, 0x01, - 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, - 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, - 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a, 0xfe, 0x2a, 0x12, 0xfe, - 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, - 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe, - 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x39, 0x18, 0x3a, - 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, - 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80, - 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x7a, 0x08, 0x8d, - 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, - 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c, - 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe, 0x52, 0x12, 0xfe, 0x2c, - 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, - 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe, - 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xb5, 0xfe, - 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, - 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33, - 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a, 0xfe, 0x74, 0x18, 0x1c, - 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, - 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe, - 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc, 0xfe, 0x83, 0x80, 0xfe, - 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, - 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf, - 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e, 0x79, 0x56, 0x68, 0x57, - 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, - 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39, - 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x10, 0x58, 0xfe, - 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, - 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe, - 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08, 0x11, 0x9b, 0x09, 0x04, - 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, - 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12, - 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9, 0x14, 0x7a, 0x01, 0x33, - 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, - 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10, - 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x84, 0x05, 0xcb, 0x1c, - 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, - 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca, - 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe, 0x22, 0x00, 0x02, 0x5a, - 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, - 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10, - 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00, 0x2a, 0x13, 0xfe, 0x4e, - 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, - 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48, - 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xdb, 0x10, 0x11, 0xfe, - 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, - 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42, - 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c, 0x09, 0x04, 0x0b, 0xfe, - 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, - 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, - 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x02, 0x29, - 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, - 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe, - 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01, 0xe8, 0x59, 0x11, 0x2d, - 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, - 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe, - 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, - 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, - 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00, - 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa, 0xab, 0x70, 0x05, 0x6b, - 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, - 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01, - 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e, 0x1d, 0xfe, 0xce, 0x45, - 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, - 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d, - 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, - 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, - 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e, - 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12, 0xce, 0x1e, 0x2d, 0x47, - 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, - 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02, - 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, - 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, - 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01, - 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, - 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, - 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24, - 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, - 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, - 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04, - 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xe1, - 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, - 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d, - 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01, 0xe8, 0x11, 0xfe, 0xe9, - 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, - 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe, - 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80, 0x40, 0x12, 0x20, 0x63, - 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, - 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe, - 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x24, 0x69, 0x12, 0xc9, - 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, - 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe, - 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c, 0x46, 0x1e, 0x20, 0xed, - 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, - 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d, - 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46, 0xfa, 0xef, 0xfe, 0x42, - 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, - 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, - 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e, 0x10, 0x07, 0x7e, 0x45, - 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, - 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe, - 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b, 0xfe, 0x48, 0x12, 0x07, - 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, - 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe, - 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b, 0x01, 0x08, 0x8c, 0x43, - 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, - 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04, - 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe, 0xc6, 0x10, 0x1e, 0x58, - 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, - 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1, - 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0xfe, - 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, - 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1, - 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e, 0x58, 0xfe, 0x1f, 0x40, - 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, - 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39, - 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06, 0x12, 0xcd, 0x02, 0x5b, - 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, - 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe, - 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, - 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, - 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01, - 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44, 0x01, 0x08, 0x1f, 0xa2, - 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, - 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda, - 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1, 0x05, 0xc6, 0x28, 0x84, - 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, - 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02, - 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06, 0x21, 0x44, 0x01, 0xfe, - 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, - 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05, - 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xd8, 0x14, 0x02, 0x5c, - 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, - 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01, - 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0xfe, 0xff, 0x7f, - 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, - 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, - 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58, 0x03, 0x0a, 0x50, 0x01, - 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, - 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27, - 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, - 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, - 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, - 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe, 0xcc, 0x12, 0x49, 0x04, - 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, - 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83, - 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c, 0x13, 0x06, 0xfe, 0x56, - 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, - 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4, - 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90, 0x01, 0xba, 0xfe, 0x4e, - 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, - 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c, - 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba, 0xfe, 0x9c, 0x14, 0xb7, - 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, - 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe, - 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x0b, 0x01, - 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, - 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08, - 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89, 0x4a, 0x01, 0x08, 0x03, - 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, - 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe, - 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd, 0x01, 0x43, 0x1e, 0xcd, - 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, - 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88, - 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3, 0x88, 0x03, 0x0a, 0x42, - 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, - 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17, - 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, - 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, - 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10, - 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58, 0x05, 0xfe, 0x66, 0x01, - 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, - 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6, - 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17, 0x10, 0x71, 0xfe, 0x83, - 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, - 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, - 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71, 0xfe, 0x30, 0xbc, 0xfe, - 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, - 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02, - 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc, 0xfe, 0x1d, 0xf7, 0x4f, - 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, - 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63, - 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14, 0x06, 0x37, 0x95, 0xa9, - 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, - 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c, - 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x3c, 0x8a, 0x0a, - 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, - 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f, - 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xf6, 0xfe, 0xd6, 0xf0, - 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, - 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f, - 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68, 0xc8, 0xfe, 0x48, 0x55, - 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, - 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42, - 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01, 0x0e, 0x73, 0x75, 0x03, - 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, - 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b, - 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05, 0xfe, 0x94, 0x00, 0xfe, - 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, - 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe, - 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1b, 0xfe, 0x5a, - 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, - 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14, - 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9, 0x03, 0x25, 0xfe, 0xca, - 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00, +static unsigned char _adv_asc3550_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, + 0x01, 0x00, 0x48, 0xe4, + 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff, + 0x28, 0x0e, 0x9e, 0xe7, + 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, + 0x55, 0xf0, 0x01, 0xf6, + 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00, + 0x00, 0xec, 0x85, 0xf0, + 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0, + 0x86, 0xf0, 0xb4, 0x00, + 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, + 0xaa, 0x18, 0x02, 0x80, + 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40, + 0x00, 0x57, 0x01, 0xea, + 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80, + 0x03, 0xe6, 0xb6, 0x00, + 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, + 0x02, 0x4a, 0xb9, 0x54, + 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00, + 0x3e, 0x00, 0x80, 0x00, + 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, + 0x74, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, + 0x4c, 0x1c, 0xbb, 0x55, + 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0, + 0x03, 0xf7, 0x06, 0xf7, + 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08, + 0x30, 0x13, 0x64, 0x15, + 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, + 0x04, 0xea, 0x5d, 0xf0, + 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, + 0xcc, 0x00, 0x20, 0x01, + 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13, + 0x40, 0x13, 0x30, 0x1c, + 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xa7, 0xf0, + 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, + 0xa4, 0x00, 0xb5, 0x00, + 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a, + 0x14, 0x0e, 0x02, 0x10, + 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, + 0x10, 0x15, 0x14, 0x15, + 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, + 0x91, 0x44, 0x0a, 0x45, + 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58, + 0x83, 0x59, 0x05, 0xe6, + 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, + 0x02, 0xfa, 0x03, 0xfa, + 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00, + 0x9e, 0x00, 0xa8, 0x00, + 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, + 0x7a, 0x01, 0xc0, 0x01, + 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, + 0x69, 0x08, 0xba, 0x08, + 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10, + 0xf1, 0x10, 0x06, 0x12, + 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14, + 0x8a, 0x15, 0xc6, 0x17, + 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, + 0x0e, 0x47, 0x48, 0x47, + 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55, + 0x14, 0x56, 0x77, 0x57, + 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c, + 0xf0, 0x29, 0x02, 0xfe, + 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, + 0xfe, 0x80, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xcf, + 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67, + 0x0b, 0x3c, 0x2a, 0xfe, + 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, + 0xfe, 0xf0, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b, + 0x02, 0xfe, 0xd4, 0x0c, + 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, + 0x1c, 0x05, 0xfe, 0xa6, + 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, + 0xf0, 0xfe, 0x86, 0x02, + 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02, + 0xfe, 0x46, 0xf0, 0xfe, + 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe, + 0x44, 0x02, 0xfe, 0x44, + 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, + 0xa0, 0x17, 0x06, 0x18, + 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe, + 0x1e, 0x1c, 0xfe, 0xe9, + 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7, + 0x0a, 0x6b, 0x01, 0x9e, + 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, + 0x01, 0x82, 0xfe, 0xbd, + 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, + 0x58, 0x1c, 0x17, 0x06, + 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21, + 0xfe, 0x94, 0x02, 0xfe, + 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, + 0x01, 0xfe, 0x54, 0x0f, + 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe, + 0x69, 0x10, 0x17, 0x06, + 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05, + 0xf6, 0xc7, 0x01, 0xfe, + 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, + 0x02, 0x29, 0x0a, 0x40, + 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41, + 0x58, 0x0a, 0x99, 0x01, + 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29, + 0x2a, 0x46, 0xfe, 0x02, + 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, + 0x01, 0xfe, 0x07, 0x4b, + 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0, + 0xfe, 0x56, 0x03, 0xfe, + 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10, + 0xfe, 0x9f, 0xf0, 0xfe, + 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, + 0x1c, 0xeb, 0x09, 0x04, + 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40, + 0x01, 0x0e, 0xac, 0x75, + 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2, + 0xfe, 0x82, 0xf0, 0xfe, + 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, + 0x32, 0x1f, 0xfe, 0xb4, + 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe, + 0x0a, 0xf0, 0xfe, 0x7a, + 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c, + 0x01, 0x33, 0x8f, 0xfe, + 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, + 0xf7, 0xfe, 0x48, 0x1c, + 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3, + 0x0a, 0xca, 0x01, 0x0e, + 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14, + 0x2c, 0x01, 0x33, 0x8f, + 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, + 0xfe, 0x3c, 0x04, 0x1f, + 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, + 0x12, 0x2b, 0xff, 0x02, + 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f, + 0x22, 0x30, 0x2e, 0xd5, + 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, + 0xfe, 0x4c, 0x54, 0x64, + 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d, + 0xfe, 0x2a, 0x13, 0x2f, + 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, + 0xd3, 0xfa, 0xef, 0x86, + 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, + 0x1d, 0xfe, 0x1c, 0x12, + 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, + 0x70, 0x0c, 0x02, 0x22, + 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92, + 0x01, 0x33, 0x02, 0x29, + 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, + 0x80, 0xfe, 0x31, 0xe4, + 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a, + 0xfe, 0x70, 0x12, 0x49, + 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe, + 0x80, 0x05, 0xfe, 0x31, + 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, + 0x28, 0xfe, 0x42, 0x12, + 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05, + 0x11, 0xfe, 0xe3, 0x00, + 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe, + 0x64, 0x05, 0x83, 0x24, + 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, + 0x09, 0x48, 0x01, 0x08, + 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01, + 0x86, 0x24, 0x06, 0x12, + 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47, + 0x01, 0xa7, 0x14, 0x92, + 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, + 0x02, 0x22, 0x05, 0xfe, + 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13, + 0x47, 0x01, 0xa7, 0x26, + 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f, + 0x01, 0xfe, 0xaa, 0x14, + 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, + 0x05, 0x50, 0xb4, 0x0c, + 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a, + 0x13, 0x01, 0xfe, 0x14, + 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c, + 0xff, 0x02, 0x00, 0x57, + 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, + 0x72, 0x06, 0x49, 0x04, + 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68, + 0x06, 0x11, 0x9a, 0x01, + 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06, + 0x01, 0xa7, 0xec, 0x72, + 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, + 0xfe, 0x0a, 0xf0, 0xfe, + 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07, + 0x8d, 0x81, 0x02, 0x22, + 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00, + 0x01, 0x08, 0x15, 0x00, + 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, + 0x00, 0x02, 0xfe, 0x32, + 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15, + 0xfe, 0x1b, 0x00, 0x01, + 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, + 0x08, 0x15, 0x06, 0x01, + 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, + 0x9a, 0x81, 0x4b, 0x1d, + 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca, + 0x45, 0xfe, 0x32, 0x12, + 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, + 0xfe, 0x32, 0x07, 0x8d, + 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, + 0x06, 0x15, 0x19, 0x02, + 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x77, 0xfe, 0xca, + 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07, + 0x10, 0xfe, 0x0e, 0x12, + 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, + 0x83, 0xe7, 0xc4, 0xa1, + 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f, + 0x40, 0x12, 0x58, 0x01, + 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, + 0x51, 0x83, 0xfb, 0xfe, + 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, + 0xfe, 0x40, 0x50, 0xfe, + 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a, + 0xfe, 0x2a, 0x12, 0xfe, + 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f, + 0x85, 0x01, 0xa8, 0xfe, + 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, + 0x18, 0x57, 0xfb, 0xfe, + 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, + 0x0c, 0x39, 0x18, 0x3a, + 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e, + 0x11, 0x65, 0xfe, 0x48, + 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, + 0xdd, 0xb8, 0xfe, 0x80, + 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0, + 0xfe, 0x7a, 0x08, 0x8d, + 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9, + 0x10, 0x61, 0x04, 0x06, + 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, + 0x12, 0xfe, 0x2e, 0x1c, + 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe, + 0x52, 0x12, 0xfe, 0x2c, + 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe, + 0x08, 0xfe, 0x8a, 0x10, + 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, + 0x24, 0x0a, 0xab, 0xfe, + 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe, + 0x1c, 0x12, 0xb5, 0xfe, + 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb, + 0x1c, 0x06, 0x16, 0x9d, + 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, + 0x14, 0x92, 0x01, 0x33, + 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a, + 0xfe, 0x74, 0x18, 0x1c, + 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b, + 0x01, 0xe6, 0x1e, 0x27, + 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, + 0x09, 0x04, 0x6a, 0xfe, + 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc, + 0xfe, 0x83, 0x80, 0xfe, + 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63, + 0x27, 0xfe, 0x40, 0x59, + 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, + 0x7c, 0xbe, 0x54, 0xbf, + 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e, + 0x79, 0x56, 0x68, 0x57, + 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5, + 0xa2, 0x23, 0x0c, 0x7b, + 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, + 0x16, 0xd7, 0x79, 0x39, + 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53, + 0xfe, 0x10, 0x58, 0xfe, + 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04, + 0x19, 0x16, 0xd7, 0x09, + 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, + 0xfe, 0x10, 0x90, 0xfe, + 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08, + 0x11, 0x9b, 0x09, 0x04, + 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08, + 0xfe, 0x0c, 0x58, 0xfe, + 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, + 0x0b, 0xfe, 0x1a, 0x12, + 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9, + 0x14, 0x7a, 0x01, 0x33, + 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39, + 0xfe, 0xed, 0x19, 0xbf, + 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, + 0x34, 0xfe, 0x74, 0x10, + 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a, + 0x84, 0x05, 0xcb, 0x1c, + 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1, + 0xf0, 0xfe, 0xc4, 0x0a, + 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, + 0xce, 0xf0, 0xfe, 0xca, + 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe, + 0x22, 0x00, 0x02, 0x5a, + 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a, + 0xfe, 0xd0, 0xf0, 0xfe, + 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, + 0x4c, 0xfe, 0x10, 0x10, + 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00, + 0x2a, 0x13, 0xfe, 0x4e, + 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1, + 0x16, 0x32, 0x2a, 0x73, + 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, + 0x32, 0x8c, 0xfe, 0x48, + 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe, + 0xdb, 0x10, 0x11, 0xfe, + 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0, + 0x22, 0x30, 0x2e, 0xd8, + 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, + 0x45, 0x0f, 0xfe, 0x42, + 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c, + 0x09, 0x04, 0x0b, 0xfe, + 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28, + 0x00, 0x21, 0xfe, 0xa6, + 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, + 0xfe, 0xe2, 0x10, 0x01, + 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d, + 0x01, 0x6f, 0x02, 0x29, + 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10, + 0x01, 0x86, 0x3e, 0x0b, + 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, + 0x3e, 0x0b, 0x0f, 0xfe, + 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01, + 0xe8, 0x59, 0x11, 0x2d, + 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09, + 0x04, 0x0b, 0x84, 0x3e, + 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, + 0x09, 0x04, 0x1b, 0xfe, + 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe, + 0x1c, 0x1c, 0xfe, 0x9d, + 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f, + 0xfe, 0x15, 0x00, 0xfe, + 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, + 0x0f, 0xfe, 0x47, 0x00, + 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa, + 0xab, 0x70, 0x05, 0x6b, + 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe, + 0x1c, 0x42, 0x59, 0x01, + 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, + 0x00, 0x37, 0x97, 0x01, + 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e, + 0x1d, 0xfe, 0xce, 0x45, + 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75, + 0x57, 0x05, 0x51, 0xfe, + 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, + 0x46, 0x09, 0x04, 0x1d, + 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a, + 0x99, 0x01, 0x0e, 0xfe, + 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51, + 0xfe, 0xee, 0x14, 0xee, + 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, + 0x13, 0x02, 0x29, 0x1e, + 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12, + 0xce, 0x1e, 0x2d, 0x47, + 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06, + 0x12, 0x4d, 0x01, 0xfe, + 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, + 0xf0, 0x0d, 0xfe, 0x02, + 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05, + 0xf6, 0xfe, 0x34, 0x01, + 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13, + 0xaf, 0xfe, 0x02, 0xea, + 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, + 0x05, 0xfe, 0x38, 0x01, + 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01, + 0x0c, 0xfe, 0x62, 0x01, + 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06, + 0x03, 0x23, 0x03, 0x1e, + 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, + 0x71, 0x13, 0xfe, 0x24, + 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03, + 0xdc, 0xfe, 0x73, 0x57, + 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe, + 0x80, 0x5d, 0x03, 0xfe, + 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, + 0x75, 0x03, 0x09, 0x04, + 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13, + 0xfe, 0x1e, 0x80, 0xe1, + 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e, + 0x90, 0xa3, 0xfe, 0x3c, + 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, + 0x16, 0x2f, 0x07, 0x2d, + 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01, + 0xe8, 0x11, 0xfe, 0xe9, + 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe, + 0x1e, 0x1c, 0xfe, 0x14, + 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, + 0x09, 0x04, 0x4f, 0xfe, + 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80, + 0x40, 0x12, 0x20, 0x63, + 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08, + 0x1c, 0x05, 0xfe, 0xac, + 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, + 0xfe, 0xb0, 0x00, 0xfe, + 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, + 0x24, 0x69, 0x12, 0xc9, + 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe, + 0x90, 0x4d, 0xfe, 0x91, + 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, + 0xfe, 0x90, 0x4d, 0xfe, + 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c, + 0x46, 0x1e, 0x20, 0xed, + 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea, + 0x70, 0xfe, 0x14, 0x1c, + 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, + 0xfe, 0x07, 0xe6, 0x1d, + 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46, + 0xfa, 0xef, 0xfe, 0x42, + 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0, + 0xfe, 0x36, 0x12, 0xf0, + 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, + 0x3d, 0x75, 0x07, 0x10, + 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e, + 0x10, 0x07, 0x7e, 0x45, + 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74, + 0xfe, 0x01, 0xec, 0x97, + 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, + 0x27, 0x01, 0xda, 0xfe, + 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b, + 0xfe, 0x48, 0x12, 0x07, + 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16, + 0xfe, 0x3e, 0x11, 0x07, + 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, + 0x11, 0x07, 0x19, 0xfe, + 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b, + 0x01, 0x08, 0x8c, 0x43, + 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11, + 0x7e, 0x02, 0x29, 0x2b, + 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, + 0xfc, 0x10, 0x09, 0x04, + 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe, + 0xc6, 0x10, 0x1e, 0x58, + 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c, + 0x54, 0x18, 0x55, 0x23, + 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, + 0xa5, 0xc0, 0x38, 0xc1, + 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe, + 0x05, 0xfa, 0x4e, 0xfe, + 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, + 0x0c, 0x56, 0x18, 0x57, + 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, + 0x00, 0x56, 0xfe, 0xa1, + 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e, + 0x58, 0xfe, 0x1f, 0x40, + 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56, + 0x31, 0x57, 0xfe, 0x44, + 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, + 0x8a, 0x50, 0x05, 0x39, + 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06, + 0x12, 0xcd, 0x02, 0x5b, + 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44, + 0x2f, 0x07, 0x9b, 0x21, + 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, + 0x39, 0x68, 0x3a, 0xfe, + 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c, + 0x51, 0xfe, 0x8e, 0x51, + 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b, + 0x01, 0x08, 0x25, 0x32, + 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, + 0x3b, 0x02, 0x44, 0x01, + 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44, + 0x01, 0x08, 0x1f, 0xa2, + 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c, + 0x00, 0x28, 0x84, 0x49, + 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, + 0x78, 0x3d, 0xfe, 0xda, + 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1, + 0x05, 0xc6, 0x28, 0x84, + 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, + 0x14, 0xfe, 0x03, 0x17, + 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, + 0xfe, 0xaa, 0x14, 0x02, + 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06, + 0x21, 0x44, 0x01, 0xfe, + 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87, + 0xfe, 0x4a, 0xf4, 0x0b, + 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, + 0x85, 0x02, 0x5b, 0x05, + 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, + 0xd8, 0x14, 0x02, 0x5c, + 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1, + 0x01, 0x08, 0x23, 0x72, + 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, + 0x12, 0x5e, 0x2b, 0x01, + 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, + 0x1c, 0xfe, 0xff, 0x7f, + 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, + 0x57, 0x48, 0x8b, 0x1c, + 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, + 0x00, 0x57, 0x48, 0x8b, + 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58, + 0x03, 0x0a, 0x50, 0x01, + 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00, + 0x54, 0xfe, 0x00, 0xf4, + 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, + 0x03, 0x7c, 0x63, 0x27, + 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08, + 0xfe, 0x82, 0x4a, 0xfe, + 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe, + 0x42, 0x48, 0x5f, 0x60, + 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, + 0x1f, 0xfe, 0xa2, 0x14, + 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe, + 0xcc, 0x12, 0x49, 0x04, + 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe, + 0xe8, 0x13, 0x3b, 0x13, + 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, + 0xa1, 0xff, 0x02, 0x83, + 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c, + 0x13, 0x06, 0xfe, 0x56, + 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe, + 0x64, 0x00, 0x17, 0x93, + 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, + 0xc8, 0x00, 0x8e, 0xe4, + 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90, + 0x01, 0xba, 0xfe, 0x4e, + 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0, + 0xfe, 0x60, 0x14, 0xfe, + 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, + 0xfe, 0x22, 0x13, 0x1c, + 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba, + 0xfe, 0x9c, 0x14, 0xb7, + 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba, + 0xfe, 0x9c, 0x14, 0xb7, + 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, + 0xfe, 0xb4, 0x56, 0xfe, + 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26, + 0xe5, 0x15, 0x0b, 0x01, + 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89, + 0x49, 0x01, 0x08, 0x03, + 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, + 0x15, 0x06, 0x01, 0x08, + 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89, + 0x4a, 0x01, 0x08, 0x03, + 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc, + 0xfe, 0x49, 0xf4, 0x00, + 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, + 0x08, 0x2f, 0x07, 0xfe, + 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd, + 0x01, 0x43, 0x1e, 0xcd, + 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e, + 0xed, 0x88, 0x07, 0x10, + 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, + 0x80, 0x01, 0x0e, 0x88, + 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3, + 0x88, 0x03, 0x0a, 0x42, + 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e, + 0xfe, 0x80, 0x80, 0xf2, + 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, + 0x01, 0x82, 0x03, 0x17, + 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, + 0xfe, 0x24, 0x1c, 0xfe, + 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0, + 0x91, 0x1d, 0x66, 0xfe, + 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, + 0xda, 0x10, 0x17, 0x10, + 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58, + 0x05, 0xfe, 0x66, 0x01, + 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, + 0xfe, 0x3c, 0x50, 0x66, + 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, + 0x40, 0x16, 0xfe, 0xb6, + 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17, + 0x10, 0x71, 0xfe, 0x83, + 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90, + 0xfe, 0x62, 0x16, 0xfe, + 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, + 0xfe, 0x98, 0xe7, 0x00, + 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71, + 0xfe, 0x30, 0xbc, 0xfe, + 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, + 0xc5, 0x90, 0xfe, 0x9a, + 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, + 0x42, 0x10, 0xfe, 0x02, + 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc, + 0xfe, 0x1d, 0xf7, 0x4f, + 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f, + 0x47, 0xfe, 0x83, 0x58, + 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, + 0xfe, 0xdd, 0x00, 0x63, + 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14, + 0x06, 0x37, 0x95, 0xa9, + 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e, + 0x18, 0x1c, 0x1a, 0x5d, + 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, + 0xe1, 0x10, 0x78, 0x2c, + 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42, + 0x13, 0x3c, 0x8a, 0x0a, + 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01, + 0xe3, 0xfe, 0x00, 0xcc, + 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, + 0x0e, 0xf2, 0x01, 0x6f, + 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, + 0xf6, 0xfe, 0xd6, 0xf0, + 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe, + 0x15, 0x00, 0x59, 0x76, + 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, + 0x11, 0x2d, 0x01, 0x6f, + 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68, + 0xc8, 0xfe, 0x48, 0x55, + 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a, + 0x99, 0x01, 0x0e, 0xf0, + 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, + 0x75, 0x03, 0x0a, 0x42, + 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01, + 0x0e, 0x73, 0x75, 0x03, + 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00, + 0xfe, 0x3a, 0x45, 0x5b, + 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, + 0xfe, 0x02, 0xe6, 0x1b, + 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05, + 0xfe, 0x94, 0x00, 0xfe, + 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02, + 0xe6, 0x2c, 0xfe, 0x4e, + 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, + 0x03, 0x07, 0x7a, 0xfe, + 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, + 0x07, 0x1b, 0xfe, 0x5a, + 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d, + 0x24, 0x2c, 0xdc, 0x07, + 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, + 0x9f, 0xad, 0x03, 0x14, + 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9, + 0x03, 0x25, 0xfe, 0xca, + 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a, + 0x00, 0x00, }; -STATIC unsigned short _adv_asc3550_size = - sizeof(_adv_asc3550_buf); /* 0x13AD */ -STATIC ADV_DCNT _adv_asc3550_chksum = - 0x04D52DDDUL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */ +static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc38C0800_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4, 0x01, 0x00, 0x48, 0xe4, - 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, - 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, - 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0, 0x18, 0xf4, 0x08, 0x00, - 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, - 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00, - 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13, 0xba, 0x13, 0x18, 0x40, - 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, - 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01, - 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12, 0x08, 0x12, 0x02, 0x4a, - 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, - 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, - 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d, 0x06, 0x13, 0x4c, 0x1c, - 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, - 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, - 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa, 0x05, 0x00, 0x34, 0x00, - 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, - 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54, - 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, - 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, - 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03, - 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13, 0x12, 0x13, 0x24, 0x14, - 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, - 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55, - 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0, 0x04, 0xf8, - 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, - 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01, - 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08, 0x68, 0x08, 0x69, 0x08, - 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, - 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14, - 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18, 0xca, 0x18, 0xe6, 0x19, - 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, - 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xd6, - 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, - 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d, 0x02, 0xfe, 0xc8, 0x0d, - 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, - 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02, - 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02, 0xfe, 0x46, 0xf0, 0xfe, - 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, - 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14, - 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, - 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, - 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd, - 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x18, 0x06, - 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, - 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, - 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe, 0x69, 0x10, 0x18, 0x06, - 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, - 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, - 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, - 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, - 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x40, 0x1c, 0x1c, - 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, - 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02, - 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13, 0x21, 0x22, 0xa3, 0xb7, - 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, - 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27, - 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe, 0x06, 0xf0, 0xfe, 0xc8, - 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, - 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19, - 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x74, 0x01, 0xaf, 0x8c, - 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, - 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, - 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d, 0xfe, 0x3c, 0x04, 0x3b, - 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, - 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe, - 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0x4f, 0x79, 0x2a, - 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, - 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe, - 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x08, 0x13, 0x32, 0x07, - 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, - 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6, - 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36, 0x02, 0x2b, 0xfe, 0x42, - 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, - 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c, - 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28, 0x17, 0xfe, 0x90, 0x05, - 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, - 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48, - 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0x12, 0xfe, 0xe3, 0x00, - 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, - 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02, - 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2, 0x08, 0x53, 0x05, 0xcb, - 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, - 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, - 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb, 0x03, 0x5c, 0x28, 0xfe, - 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, - 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, - 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62, 0x12, 0x03, 0x45, 0x28, - 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, - 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2, - 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01, 0xfe, 0xcc, 0x15, 0x1d, - 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, - 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb, - 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, - 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, - 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01, - 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38, 0x12, 0x08, 0x05, 0x1a, - 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, - 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe, - 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b, 0xfe, 0x09, 0x6f, 0xba, - 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, - 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01, - 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe, 0x2c, 0x90, 0xfe, 0xae, - 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, - 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe, - 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b, 0x37, 0x01, 0xb3, 0xb8, - 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, - 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c, - 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d, 0x14, 0x3e, 0xfe, 0x4a, - 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, - 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe, - 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, - 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, - 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e, - 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe, 0x9a, 0x08, 0xc6, 0xfe, - 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, - 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12, - 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e, 0x1c, 0x02, 0xfe, 0x18, - 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, - 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7, - 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18, 0xfe, 0xf1, 0x18, 0xfe, - 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, - 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5, - 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18, 0x0b, 0xb6, 0xfe, 0xbf, - 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, - 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5, - 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15, 0x9d, 0x01, 0x36, 0x10, - 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, - 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe, - 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0x08, 0x05, - 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, - 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49, - 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18, 0x8f, 0xfe, 0xe3, 0x54, - 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, - 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b, - 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00, 0xad, 0xfe, 0x01, 0x59, - 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, - 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b, - 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63, 0x02, 0x4a, 0x08, 0x05, - 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, - 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a, - 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29, 0x61, 0x0c, 0x7f, 0x14, - 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, - 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef, - 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40, 0xe4, 0x08, 0x05, 0x1f, - 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, - 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05, - 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19, 0x81, 0x50, 0xfe, 0x10, - 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, - 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c, - 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7, 0x08, 0x05, 0x0a, 0xfe, - 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, - 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed, - 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe, 0x00, 0xff, 0x35, 0xfe, - 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, - 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe, - 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, - 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, - 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0, - 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea, 0x0b, 0x10, 0x58, 0xfe, - 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, - 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34, - 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20, 0x0c, 0x1c, 0x34, 0x94, - 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, - 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33, - 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24, 0x33, 0x31, 0xdf, 0xbc, - 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, - 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28, - 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x44, 0xfe, 0x28, 0x00, - 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, - 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10, - 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xac, - 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, - 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08, - 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05, 0x1a, 0xfe, 0x58, 0x12, - 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, - 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10, - 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10, 0xfe, 0x13, 0x00, 0xfe, - 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, - 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe, - 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0, 0xb4, 0x15, 0xfe, 0x31, - 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, - 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75, - 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x44, 0x48, - 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d, - 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0xce, 0x47, 0xfe, 0xad, - 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, - 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06, - 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe, 0x3a, 0x01, 0x56, 0xfe, - 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, - 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, - 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13, 0x15, 0x1a, 0x39, 0xa0, - 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, - 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12, - 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12, 0x22, 0x9f, 0xb7, 0x13, - 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, - 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc, - 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21, 0xfe, 0x00, 0xcc, 0x04, - 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, - 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe, - 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x0a, 0xfe, 0x3c, 0x50, - 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, - 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01, - 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, - 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, - 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79, - 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, - - 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, - 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52, - 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc, 0x0f, 0x44, 0x11, 0x0f, - 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, - 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, - 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x04, 0x42, - 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, - 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f, - 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, - 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, - 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14, - 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d, 0xfe, 0x01, 0xec, 0xa2, - 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, - 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07, - 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17, 0xfe, 0x32, 0x12, 0x07, - 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, - 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d, - 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d, 0x32, 0x07, 0xa6, 0xfe, - 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, - 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03, - 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21, 0x0c, 0x7f, 0x0c, 0x80, - 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, - 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f, - 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40, 0x88, 0x9b, 0x2e, 0x9c, - 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, - 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61, - 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50, - 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, - 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d, - 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23, 0x72, 0x01, 0xaf, 0x1e, - 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, - 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19, - 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, - 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, - 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8, - 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53, 0x05, 0x1f, 0x35, 0xa9, - 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, - 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35, - 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x03, 0x5c, 0xc1, 0x0c, - 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, - 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1, - 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a, 0xf4, 0x06, 0xea, 0x32, - 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, - 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13, - 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0, 0x13, 0x1c, 0xfe, 0xd0, - 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, - 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f, - 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, - 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, - 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03, - 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52, 0xfe, 0x00, 0x7d, 0xfe, - 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, - 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01, - 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, - 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, - 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee, - 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c, 0x30, 0xfe, 0x78, 0x10, - 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, - 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00, - 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28, 0x10, 0x69, 0x06, 0xfe, - 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, - 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe, - 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4, 0x9e, 0xfe, 0xf3, 0x10, - 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, - 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, - 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d, 0xf4, 0x00, 0xe9, 0x91, - 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, - 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76, - 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x19, 0x01, 0x0b, - 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, - 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8, - 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, - 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, - 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06, - 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e, 0x07, 0x11, 0xae, 0x09, - 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, - 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e, - 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x4c, - 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, - 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, - 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4, 0x17, 0xad, 0x9a, 0x1b, - 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, - 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe, - 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, - 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, - 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75, - 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x2e, 0x97, 0xfe, 0x5a, - 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, - 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe, - 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xcb, 0x97, 0xfe, 0x92, - 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, - 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d, - 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x9a, 0x5b, 0x41, 0xfe, - 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, - 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39, - 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04, 0xfe, 0x7e, 0x18, 0x1e, - 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, - 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09, - 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, - 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, - 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14, - 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c, 0xe7, 0x0a, 0x10, 0xfe, - 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, - 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b, - 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77, 0x13, 0xa3, 0x04, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, - 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09, - 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe, 0x1c, 0x19, 0x03, 0xfe, - 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, - 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b, - 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe, 0x08, 0x10, 0x03, 0xfe, - 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, - 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00, - 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19, 0x04, 0x07, 0x7e, 0xfe, - 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, - 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07, - 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59, 0xa9, 0xb8, 0x04, 0x15, - 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, - 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0, - 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00, +static unsigned char _adv_asc38C0800_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4, + 0x01, 0x00, 0x48, 0xe4, + 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff, + 0x1c, 0x0f, 0x00, 0xf6, + 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, + 0x09, 0xe7, 0x55, 0xf0, + 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0, + 0x18, 0xf4, 0x08, 0x00, + 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6, + 0x86, 0xf0, 0xb1, 0xf0, + 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, + 0x3c, 0x00, 0xbb, 0x00, + 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13, + 0xba, 0x13, 0x18, 0x40, + 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01, + 0x6e, 0x01, 0x74, 0x01, + 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, + 0xc0, 0x00, 0x01, 0x01, + 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12, + 0x08, 0x12, 0x02, 0x4a, + 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, + 0x5d, 0xf0, 0x02, 0xfa, + 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, + 0x68, 0x01, 0x6a, 0x01, + 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d, + 0x06, 0x13, 0x4c, 0x1c, + 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00, + 0x0f, 0x00, 0x47, 0x00, + 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, + 0x4e, 0x1c, 0x10, 0x44, + 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa, + 0x05, 0x00, 0x34, 0x00, + 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b, + 0x42, 0x0c, 0x12, 0x0f, + 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, + 0x00, 0x4e, 0x42, 0x54, + 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xb8, 0xf0, + 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00, + 0x19, 0x00, 0x33, 0x00, + 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, + 0xe7, 0x00, 0xe2, 0x03, + 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13, + 0x12, 0x13, 0x24, 0x14, + 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c, + 0x36, 0x1c, 0x08, 0x44, + 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, + 0x3a, 0x55, 0x83, 0x55, + 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, + 0x0c, 0xf0, 0x04, 0xf8, + 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00, + 0xa8, 0x00, 0xaa, 0x00, + 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, + 0xc4, 0x01, 0xc6, 0x01, + 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08, + 0x68, 0x08, 0x69, 0x08, + 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10, + 0xed, 0x10, 0xf1, 0x10, + 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, + 0x1e, 0x13, 0x46, 0x14, + 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18, + 0xca, 0x18, 0xe6, 0x19, + 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c, + 0xf0, 0x2b, 0x02, 0xfe, + 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, + 0xfe, 0x84, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x11, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xd6, + 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99, + 0x0a, 0x42, 0x2c, 0xfe, + 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, + 0xfe, 0xf4, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d, + 0x02, 0xfe, 0xc8, 0x0d, + 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, + 0x1c, 0x03, 0xfe, 0xa6, + 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, + 0xf0, 0xfe, 0x8a, 0x02, + 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02, + 0xfe, 0x46, 0xf0, 0xfe, + 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe, + 0x48, 0x02, 0xfe, 0x44, + 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, + 0xaa, 0x18, 0x06, 0x14, + 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe, + 0x1e, 0x1c, 0xfe, 0xe9, + 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce, + 0x09, 0x70, 0x01, 0xa8, + 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, + 0x01, 0x87, 0xfe, 0xbd, + 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, + 0x58, 0x1c, 0x18, 0x06, + 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23, + 0xfe, 0x98, 0x02, 0xfe, + 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, + 0x01, 0xfe, 0x48, 0x10, + 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe, + 0x69, 0x10, 0x18, 0x06, + 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05, + 0xf6, 0xce, 0x01, 0xfe, + 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, + 0x82, 0x16, 0x02, 0x2b, + 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10, + 0xfe, 0x41, 0x58, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe, + 0x82, 0x16, 0x02, 0x2b, + 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, + 0xfe, 0x77, 0x57, 0xfe, + 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7, + 0xfe, 0x40, 0x1c, 0x1c, + 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48, + 0x03, 0xfe, 0x11, 0xf0, + 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, + 0xfe, 0x11, 0x00, 0x02, + 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13, + 0x21, 0x22, 0xa3, 0xb7, + 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16, + 0x12, 0xd1, 0x1c, 0xd9, + 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, + 0xfe, 0xe4, 0x00, 0x27, + 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe, + 0x06, 0xf0, 0xfe, 0xc8, + 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03, + 0x70, 0x28, 0x17, 0xfe, + 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, + 0xf9, 0x2c, 0x99, 0x19, + 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, + 0x74, 0x01, 0xaf, 0x8c, + 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e, + 0x8d, 0x51, 0x64, 0x79, + 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, + 0xfe, 0x6a, 0x02, 0x02, + 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d, + 0xfe, 0x3c, 0x04, 0x3b, + 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02, + 0x00, 0x10, 0x01, 0x0b, + 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, + 0xfe, 0x4c, 0x44, 0xfe, + 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, + 0xda, 0x4f, 0x79, 0x2a, + 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b, + 0xfe, 0x2a, 0x13, 0x32, + 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, + 0x54, 0x6b, 0xda, 0xfe, + 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe, + 0x08, 0x13, 0x32, 0x07, + 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d, + 0x08, 0x05, 0x06, 0x4d, + 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, + 0x2d, 0x12, 0xfe, 0xe6, + 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36, + 0x02, 0x2b, 0xfe, 0x42, + 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, + 0xfe, 0x87, 0x80, 0xfe, + 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, + 0x07, 0x19, 0xfe, 0x7c, + 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28, + 0x17, 0xfe, 0x90, 0x05, + 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe, + 0xa0, 0x00, 0x28, 0xfe, + 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, + 0x34, 0xfe, 0x89, 0x48, + 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05, + 0x12, 0xfe, 0xe3, 0x00, + 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe, + 0x70, 0x05, 0x88, 0x25, + 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, + 0x09, 0x48, 0xff, 0x02, + 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2, + 0x08, 0x53, 0x05, 0xcb, + 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08, + 0x05, 0x1b, 0xfe, 0x22, + 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, + 0x0d, 0x00, 0x01, 0x36, + 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb, + 0x03, 0x5c, 0x28, 0xfe, + 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53, + 0x05, 0x1f, 0xfe, 0x02, + 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, + 0x01, 0x4b, 0x12, 0xfe, + 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62, + 0x12, 0x03, 0x45, 0x28, + 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe, + 0x43, 0x48, 0xc4, 0xcc, + 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, + 0x6e, 0x41, 0x01, 0xb2, + 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01, + 0xfe, 0xcc, 0x15, 0x1d, + 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03, + 0x45, 0xc1, 0x0c, 0x45, + 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, + 0xe2, 0x00, 0x27, 0xdb, + 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07, + 0xfe, 0x06, 0xf0, 0xfe, + 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12, + 0x16, 0x19, 0x01, 0x0b, + 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, + 0xfe, 0x99, 0xa4, 0x01, + 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38, + 0x12, 0x08, 0x05, 0x1a, + 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, + 0x0b, 0x16, 0x00, 0x01, + 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, + 0xe2, 0x6c, 0x58, 0xbe, + 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b, + 0xfe, 0x09, 0x6f, 0xba, + 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27, + 0xfe, 0x54, 0x07, 0x1c, + 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, + 0x07, 0x02, 0x24, 0x01, + 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe, + 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a, + 0x37, 0x22, 0x20, 0x07, + 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, + 0xfe, 0x06, 0x10, 0xfe, + 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b, + 0x37, 0x01, 0xb3, 0xb8, + 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a, + 0x50, 0xfe, 0x44, 0x51, + 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, + 0x14, 0x5f, 0xfe, 0x0c, + 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d, + 0x14, 0x3e, 0xfe, 0x4a, + 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x0c, 0x60, 0x14, + 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, + 0xfe, 0x44, 0x90, 0xfe, + 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, + 0x0c, 0x5e, 0x14, 0x5f, + 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e, + 0x14, 0x3c, 0x21, 0x0c, + 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, + 0x27, 0xdd, 0xfe, 0x9e, + 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe, + 0x9a, 0x08, 0xc6, 0xfe, + 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08, + 0x95, 0x86, 0x02, 0x24, + 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, + 0x06, 0xfe, 0x10, 0x12, + 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e, + 0x1c, 0x02, 0xfe, 0x18, + 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe, + 0x2c, 0x1c, 0xfe, 0xaa, + 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, + 0xde, 0x09, 0xfe, 0xb7, + 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18, + 0xfe, 0xf1, 0x18, 0xfe, + 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, + 0x14, 0x59, 0xfe, 0x95, + 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, + 0xfe, 0xf0, 0x08, 0xb5, + 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18, + 0x0b, 0xb6, 0xfe, 0xbf, + 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, + 0x12, 0xc2, 0xfe, 0xd2, + 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, + 0x06, 0x17, 0x85, 0xc5, + 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15, + 0x9d, 0x01, 0x36, 0x10, + 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe, + 0x98, 0x80, 0xfe, 0x19, + 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, + 0xfe, 0x44, 0x54, 0xbe, + 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08, + 0x02, 0x4a, 0x08, 0x05, + 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e, + 0x9c, 0x3c, 0xfe, 0x6c, + 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, + 0x3b, 0x40, 0x03, 0x49, + 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18, + 0x8f, 0xfe, 0xe3, 0x54, + 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe, + 0xda, 0x09, 0xfe, 0x8b, + 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, + 0x0a, 0x3a, 0x49, 0x3b, + 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00, + 0xad, 0xfe, 0x01, 0x59, + 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a, + 0x49, 0x8f, 0xfe, 0xe3, + 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, + 0x4a, 0x3a, 0x49, 0x3b, + 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63, + 0x02, 0x4a, 0x08, 0x05, + 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62, + 0xb7, 0xfe, 0x03, 0xa1, + 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, + 0xfe, 0x86, 0x91, 0x6a, + 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29, + 0x61, 0x0c, 0x7f, 0x14, + 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62, + 0x9b, 0x2e, 0x9c, 0x3c, + 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, + 0xfa, 0x3c, 0x01, 0xef, + 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40, + 0xe4, 0x08, 0x05, 0x1f, + 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, + 0x03, 0x5e, 0x29, 0x5f, + 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, + 0xf4, 0x09, 0x08, 0x05, + 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19, + 0x81, 0x50, 0xfe, 0x10, + 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe, + 0x08, 0x09, 0x12, 0xa6, + 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, + 0x08, 0x09, 0xfe, 0x0c, + 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7, + 0x08, 0x05, 0x0a, 0xfe, + 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1, + 0xf0, 0xe2, 0x15, 0x7e, + 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, + 0x57, 0x3d, 0xfe, 0xed, + 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe, + 0x00, 0xff, 0x35, 0xfe, + 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18, + 0x1e, 0x19, 0x8a, 0x03, + 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, + 0xfe, 0xd1, 0xf0, 0xfe, + 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42, + 0x10, 0xfe, 0xce, 0xf0, + 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b, + 0x10, 0xfe, 0x22, 0x00, + 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, + 0x02, 0x65, 0xfe, 0xd0, + 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea, + 0x0b, 0x10, 0x58, 0xfe, + 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe, + 0x12, 0x00, 0x2c, 0x0f, + 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, + 0x0c, 0xbc, 0x17, 0x34, + 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20, + 0x0c, 0x1c, 0x34, 0x94, + 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01, + 0x4b, 0xfe, 0xdb, 0x10, + 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, + 0x89, 0xf0, 0x24, 0x33, + 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24, + 0x33, 0x31, 0xdf, 0xbc, + 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49, + 0x17, 0xfe, 0x2c, 0x0d, + 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, + 0x12, 0x55, 0xfe, 0x28, + 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, + 0x44, 0xfe, 0x28, 0x00, + 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26, + 0x0f, 0x64, 0x12, 0x2f, + 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, + 0x0a, 0xfe, 0xb4, 0x10, + 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82, + 0xfe, 0x34, 0x46, 0xac, + 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a, + 0x37, 0x01, 0xf5, 0x01, + 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, + 0xfe, 0x2e, 0x03, 0x08, + 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05, + 0x1a, 0xfe, 0x58, 0x12, + 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, + 0xfe, 0x50, 0x0d, 0xfe, + 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, + 0xfe, 0xa9, 0x10, 0x10, + 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10, + 0xfe, 0x13, 0x00, 0xfe, + 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe, + 0x24, 0x00, 0x8c, 0xb5, + 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, + 0xfe, 0x9d, 0x41, 0xfe, + 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0, + 0xb4, 0x15, 0xfe, 0x31, + 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06, + 0xec, 0xd0, 0xfc, 0x44, + 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, + 0x4b, 0x91, 0xfe, 0x75, + 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01, + 0x0e, 0xfe, 0x44, 0x48, + 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41, + 0xfe, 0x41, 0x58, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, + 0x2e, 0x03, 0x09, 0x5d, + 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, + 0xce, 0x47, 0xfe, 0xad, + 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13, + 0x59, 0x13, 0x9f, 0x13, + 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, + 0xe0, 0x0e, 0x0f, 0x06, + 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe, + 0x3a, 0x01, 0x56, 0xfe, + 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec, + 0x20, 0x4f, 0xfe, 0x05, + 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, + 0x48, 0xf4, 0x0d, 0xfe, + 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13, + 0x15, 0x1a, 0x39, 0xa0, + 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff, + 0x0c, 0xfe, 0x60, 0x01, + 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, + 0x06, 0x13, 0x2f, 0x12, + 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12, + 0x22, 0x9f, 0xb7, 0x13, + 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39, + 0xa0, 0xb4, 0xfe, 0xd9, + 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, + 0xc3, 0xfe, 0x03, 0xdc, + 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21, + 0xfe, 0x00, 0xcc, 0x04, + 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13, + 0xfe, 0x1c, 0x80, 0x07, + 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, + 0xfe, 0x0c, 0x90, 0xfe, + 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, + 0x0a, 0xfe, 0x3c, 0x50, + 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4, + 0x16, 0x08, 0x05, 0x1b, + 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, + 0xfe, 0x2c, 0x13, 0x01, + 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90, + 0x0c, 0xfe, 0x64, 0x01, + 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03, + 0x80, 0x8d, 0xfe, 0x01, + 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, + 0x22, 0x20, 0xfb, 0x79, + 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, + 0x03, 0xfe, 0xae, 0x00, + + 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, + 0xb2, 0x00, 0xfe, 0x09, + 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, + 0x45, 0x0f, 0x46, 0x52, + 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc, + 0x0f, 0x44, 0x11, 0x0f, + 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4, + 0x25, 0x11, 0x13, 0x20, + 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, + 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, + 0x18, 0x1c, 0x04, 0x42, + 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe, + 0xf5, 0x13, 0x04, 0x01, + 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, + 0x13, 0x32, 0x07, 0x2f, + 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe, + 0x41, 0x48, 0xfe, 0x45, + 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, + 0x07, 0x11, 0xac, 0x09, + 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, + 0x82, 0x4e, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d, + 0xfe, 0x01, 0xec, 0xa2, + 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79, + 0x2a, 0x01, 0xe3, 0xfe, + 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, + 0xfe, 0x48, 0x12, 0x07, + 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17, + 0xfe, 0x32, 0x12, 0x07, + 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07, + 0x1f, 0xfe, 0x12, 0x12, + 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, + 0x94, 0x4b, 0x04, 0x2d, + 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d, + 0x32, 0x07, 0xa6, 0xfe, + 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05, + 0x5a, 0xfe, 0x72, 0x12, + 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, + 0xfe, 0x26, 0x13, 0x03, + 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21, + 0x0c, 0x7f, 0x0c, 0x80, + 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c, + 0x3c, 0xfe, 0x04, 0x55, + 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, + 0x91, 0x10, 0x03, 0x3f, + 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40, + 0x88, 0x9b, 0x2e, 0x9c, + 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1, + 0x56, 0x0c, 0x5e, 0x14, + 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, + 0x03, 0x60, 0x29, 0x61, + 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44, + 0x50, 0xfe, 0xc6, 0x50, + 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d, + 0x29, 0x3e, 0xfe, 0x40, + 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, + 0x2d, 0x01, 0x0b, 0x1d, + 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23, + 0x72, 0x01, 0xaf, 0x1e, + 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe, + 0x0a, 0x55, 0x35, 0xfe, + 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, + 0x02, 0x72, 0xfe, 0x19, + 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34, + 0x1d, 0xe8, 0x33, 0x31, + 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01, + 0x0b, 0x1c, 0x34, 0x1d, + 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, + 0x33, 0x31, 0xfe, 0xe8, + 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53, + 0x05, 0x1f, 0x35, 0xa9, + 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda, + 0x14, 0x01, 0xaf, 0x8c, + 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, + 0x03, 0x45, 0x28, 0x35, + 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, + 0x03, 0x5c, 0xc1, 0x0c, + 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02, + 0x89, 0x01, 0x0b, 0x1c, + 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, + 0xfe, 0x42, 0x58, 0xf1, + 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a, + 0xf4, 0x06, 0xea, 0x32, + 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d, + 0x01, 0x0b, 0x26, 0x89, + 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, + 0x26, 0xfe, 0xd4, 0x13, + 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0, + 0x13, 0x1c, 0xfe, 0xd0, + 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10, + 0x0f, 0x71, 0xff, 0x02, + 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, + 0x00, 0x5c, 0x04, 0x0f, + 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56, + 0xfe, 0x00, 0x5c, 0x04, + 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff, + 0x02, 0x00, 0x57, 0x52, + 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, + 0x87, 0x04, 0xfe, 0x03, + 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52, + 0xfe, 0x00, 0x7d, 0xfe, + 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e, + 0x14, 0x5f, 0x57, 0x3f, + 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, + 0x5a, 0x8d, 0x04, 0x01, + 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d, + 0xfe, 0x96, 0x15, 0x33, + 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8, + 0x0a, 0xfe, 0xc1, 0x59, + 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, + 0x21, 0x69, 0x1a, 0xee, + 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c, + 0x30, 0xfe, 0x78, 0x10, + 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae, + 0x98, 0xfe, 0x30, 0x00, + 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, + 0x98, 0xfe, 0x64, 0x00, + 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28, + 0x10, 0x69, 0x06, 0xfe, + 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00, + 0x18, 0x59, 0x0f, 0x06, + 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, + 0x43, 0xf4, 0x9f, 0xfe, + 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4, + 0x9e, 0xfe, 0xf3, 0x10, + 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00, + 0x17, 0xfe, 0x4d, 0xe4, + 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, + 0x17, 0xfe, 0x4d, 0xe4, + 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d, + 0xf4, 0x00, 0xe9, 0x91, + 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a, + 0x04, 0x16, 0x06, 0x01, + 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, + 0x0b, 0x26, 0xf3, 0x76, + 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, + 0x16, 0x19, 0x01, 0x0b, + 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01, + 0x0b, 0x26, 0xb1, 0x76, + 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, + 0xfe, 0x48, 0x13, 0xb8, + 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01, + 0xec, 0xfe, 0x27, 0x01, + 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32, + 0x07, 0xfe, 0xe3, 0x00, + 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, + 0x22, 0xd4, 0x07, 0x06, + 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e, + 0x07, 0x11, 0xae, 0x09, + 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01, + 0x0e, 0x8e, 0xfe, 0x80, + 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, + 0x09, 0x48, 0x01, 0x0e, + 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80, + 0x80, 0xfe, 0x80, 0x4c, + 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, + 0x09, 0x5d, 0x01, 0x87, + 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, + 0x19, 0xde, 0xfe, 0x24, + 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4, + 0x17, 0xad, 0x9a, 0x1b, + 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde, + 0x16, 0xfe, 0xda, 0x10, + 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, + 0x18, 0x58, 0x03, 0xfe, + 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30, + 0xf4, 0x06, 0xfe, 0x3c, + 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f, + 0x97, 0xfe, 0x38, 0x17, + 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, + 0x10, 0x18, 0x11, 0x75, + 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, + 0x2e, 0x97, 0xfe, 0x5a, + 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19, + 0xfe, 0x98, 0xe7, 0x00, + 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, + 0xfe, 0x30, 0xbc, 0xfe, + 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, + 0xcb, 0x97, 0xfe, 0x92, + 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe, + 0x42, 0x10, 0xfe, 0x02, + 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, + 0x03, 0xa1, 0xfe, 0x1d, + 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, + 0x9a, 0x5b, 0x41, 0xfe, + 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7, + 0x11, 0x12, 0xfe, 0xdd, + 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, + 0x17, 0x15, 0x06, 0x39, + 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04, + 0xfe, 0x7e, 0x18, 0x1e, + 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef, + 0x12, 0xfe, 0xe1, 0x10, + 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, + 0x13, 0x42, 0x92, 0x09, + 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, + 0xf0, 0xfe, 0x00, 0xcc, + 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, + 0x0e, 0xfe, 0x80, 0x4c, + 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, + 0x24, 0x12, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c, + 0xe7, 0x0a, 0x10, 0xfe, + 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92, + 0x08, 0x54, 0x1b, 0x37, + 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, + 0x90, 0x3a, 0xce, 0x3b, + 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77, + 0x13, 0xa3, 0x04, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49, + 0x44, 0x17, 0xfe, 0xe8, + 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, + 0x5d, 0x01, 0xa8, 0x09, + 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe, + 0x1c, 0x19, 0x03, 0xfe, + 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9, + 0x6b, 0xfe, 0x2e, 0x19, + 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, + 0xfe, 0x0b, 0x00, 0x6b, + 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe, + 0x08, 0x10, 0x03, 0xfe, + 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff, + 0x04, 0x68, 0x54, 0xe7, + 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, + 0x1a, 0xf4, 0xfe, 0x00, + 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19, + 0x04, 0x07, 0x7e, 0xfe, + 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, + 0x07, 0x1a, 0xfe, 0x5a, + 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, + 0x25, 0x6d, 0xe5, 0x07, + 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59, + 0xa9, 0xb8, 0x04, 0x15, + 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe, + 0x40, 0x5c, 0x04, 0x1c, + 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, + 0xf7, 0xfe, 0x82, 0xf0, + 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00, }; -STATIC unsigned short _adv_asc38C0800_size = - sizeof(_adv_asc38C0800_buf); /* 0x14E1 */ -STATIC ADV_DCNT _adv_asc38C0800_chksum = - 0x050D3FD8UL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */ +static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc38C1600_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0, 0x18, 0xe4, 0x01, 0x00, - 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, - 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0, - 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00, 0x98, 0x57, 0x01, 0xe6, - 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, - 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0, - 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01, 0x06, 0x13, 0x0c, 0x1c, - 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, - 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea, - 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x04, 0x13, 0xbb, 0x55, - 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c, - 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, - 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, - 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48, - 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x06, 0x00, - 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, - 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0, - 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, - 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, - 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16, - 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, - 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, - 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c, - 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x42, 0x1d, 0x08, 0x44, - 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, - 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, - 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0xa8, 0x00, 0xaa, 0x00, - 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, - 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d, - 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10, 0xf3, 0x10, 0x06, 0x12, - 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, - 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xe8, - 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, - 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d, 0x05, 0xfe, 0x08, 0x0f, - 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, - 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90, - 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8, 0x02, 0xfe, 0x46, 0xf0, - 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, - 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07, - 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, 0x1c, 0xf5, 0xfe, 0x1e, - 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, - 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe, - 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x1c, - 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, - 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01, - 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09, 0x1a, 0x31, 0xfe, 0x69, - 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, - 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51, - 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, - 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, - 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30, - 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0, 0xfe, 0xe4, 0x01, 0xfe, - 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, - 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f, - 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05, 0x70, 0x37, 0xfe, 0x48, - 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, - 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe, - 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32, 0x15, 0xfe, 0xe4, 0x00, - 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, - 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b, - 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xfe, 0x46, 0x1c, - 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, - 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77, - 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, - 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, - 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01, - 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25, 0xee, 0xfe, 0x4c, 0x44, - 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, - 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe, - 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10, 0x13, 0x34, 0xfe, 0x4c, - 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, - 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f, - 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f, 0xfe, 0xa4, 0x0e, 0x05, - 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, - 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46, - 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04, 0xfe, 0x87, 0x83, 0xfe, - 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, - 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06, - 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda, 0x05, 0xd0, 0x54, 0x01, - 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, - 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, - 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01, 0x38, 0xfe, 0x4a, 0xf0, - 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, - 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0, - 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe, 0x1c, 0x00, 0x4d, 0x01, - 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, - 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, - 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13, 0x03, 0xb6, 0x1e, 0xfe, - 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, - 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68, - 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x03, 0x9a, 0x1e, 0xfe, - 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, - 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00, - 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17, 0xfe, 0xea, 0x06, 0x01, - 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, - 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae, - 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a, 0x1e, 0xfe, 0x1a, 0x12, - 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, - 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6, - 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x17, 0xfe, - 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, - 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05, - 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0x9c, 0x32, 0x5f, - 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, - 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29, - 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, - 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, - 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13, - 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, - 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, - 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c, - 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x53, 0x63, 0x4e, - 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, - 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c, - 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe, 0x1e, 0xfe, 0x99, 0x58, - 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, - 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a, - 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40, 0x01, 0x0c, 0x61, 0x65, - 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, - 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e, - 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e, 0x01, 0xfe, 0xfe, 0x1e, - 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, - 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b, - 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04, 0xfe, 0x9f, 0x83, 0x33, - 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, - 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e, - 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90, 0x04, 0xfe, 0xc0, 0x93, - 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, - 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, - 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5, - 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, - 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41, - 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07, 0xfe, 0x14, 0x12, 0x01, - 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, - 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe, - 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe, 0x92, 0x10, 0xc4, 0xf6, - 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, - 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0, - 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07, 0x1b, 0xbf, 0xd4, 0x5b, - 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, - 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74, - 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78, 0x0f, 0x4d, 0x01, 0xfe, - 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, - 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21, - 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe, 0x83, 0x83, 0xfe, 0xc9, - 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, - 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b, - 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0x10, - 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, - 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64, - 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97, 0x10, 0x98, 0x91, 0x6c, - 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, - 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, - 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x01, 0x0c, - 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, - 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe, - 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb, 0x01, 0x0c, 0x06, 0x0d, - 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, - 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e, - 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, - 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, - 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51, - 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe, 0x76, 0x10, 0xac, 0xfe, - 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, - 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92, - 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2, 0x0c, 0xfe, 0x3e, 0x10, - 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, - 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94, - 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3, 0xfe, 0xcc, 0xf0, 0xef, - 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, - 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5, - 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32, 0x2f, 0xfe, 0x3e, 0x0d, - 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, - 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99, - 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8, 0x9c, 0x2f, 0xfe, 0x8c, - 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, - 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13, - 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b, 0xfe, 0xda, 0x0e, 0x0a, - 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, - 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85, - 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe, 0xcc, 0x10, 0x01, 0xa7, - 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, - 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2, - 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x40, 0x15, - 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, - 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe, - 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, - 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, - 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19, - 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19, 0xfe, 0x41, 0x00, 0xa2, - 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, - 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c, - 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01, 0xfe, 0xd4, 0x11, 0x05, - 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, - 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56, - 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01, 0x0c, 0x06, 0x28, 0xfe, - 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, - 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe, - 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x05, - 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, - 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b, - 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe, 0xf0, 0x1a, 0x03, 0xfe, - 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, - 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b, - 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02, 0xea, 0xe7, 0x53, 0x92, - 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, - 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e, - 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02, 0x26, 0x02, 0x21, 0x96, - 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, - 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe, - 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe, 0x00, 0xcc, 0x02, 0xfe, - 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, - 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80, - 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe, 0x1d, 0x80, 0x04, 0xfe, - 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, - 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, - 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09, 0x56, 0xfb, 0x01, 0xfe, - 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, - 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e, - 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe, 0x96, 0x90, 0x04, 0xfe, - 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, - 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01, - 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40, 0x21, 0x2c, 0xfe, 0x00, - 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, - 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, - 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10, 0x66, 0x10, 0x55, 0x10, - 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, - 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, - 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, - 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, - 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47, - 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01, 0xa7, 0x90, 0x34, 0x60, - 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, - 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, - 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, - 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, - 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e, - 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01, 0xf4, 0xfe, 0xdd, 0x10, - 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, - 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23, - 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09, 0x24, 0xfe, 0x12, 0x12, - 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, - 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43, - 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80, 0x13, 0x01, 0x0c, 0x06, - 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, - 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10, - 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49, 0x88, 0x20, 0x6e, 0x01, - 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, - 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe, - 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, 0xe5, - 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, - 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50, - 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x68, 0x3b, - 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, - 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25, - 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01, 0xa6, 0x23, 0x3f, 0x1b, - 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, - 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01, - 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, - 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, - 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08, - 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03, 0xb6, 0x1e, 0x83, 0x01, - 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, - 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82, - 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e, 0x05, 0x72, 0xfe, 0xc0, - 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, - 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd, - 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe, 0xe8, 0x14, 0x01, 0xa6, - 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, - 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, - 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd, 0x09, - 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, - 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72, - 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0xc0, 0x19, 0x05, - 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, - 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32, - 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0xfe, 0xff, - 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, - 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, - 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e, 0x02, 0x13, 0x58, 0xff, - 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, - 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54, - 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07, 0x7c, 0x3a, 0x0b, 0x0e, - 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, - 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe, - 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77, 0x02, 0x01, 0xc6, 0xfe, - 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, - 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe, - 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12, 0x48, 0xfe, 0x08, 0x17, - 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, - 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55, - 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x1c, 0x63, 0x13, - 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, - 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60, - 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8, 0x00, 0x1c, 0x95, 0x13, - 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, - 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b, - 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x49, - 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, - 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13, - 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xbe, 0xfe, 0x03, - 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, - 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9, - 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, - 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, - 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e, - 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10, 0xfe, 0x40, 0x5a, 0x23, - 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, - 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, - 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe, 0x43, 0x48, 0x2d, 0x93, - 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, - 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0, - 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa, 0x18, 0x45, 0xfe, 0x1c, - 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, - 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01, - 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe, 0x7e, 0x01, 0xfe, 0xc8, - 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, - 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14, - 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, - 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, - 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1, - 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01, 0x08, 0x02, 0x50, 0x02, - 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, - 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe, - 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17, 0x74, 0x5f, 0xcc, 0x01, - 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, - 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, - 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13, 0x16, 0xfe, 0x64, 0x1a, - 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, - 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, - 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa, 0xfe, 0x80, 0xe7, 0x1a, - 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, - 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80, - 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x0a, - 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, - 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3, - 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe, 0xf4, 0x1a, 0xfe, 0xfa, - 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, - 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07, - 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x24, 0xb1, 0xfe, - 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, - 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1, - 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe, 0xaf, 0x19, 0xfe, 0x98, - 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, - 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04, - 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a, 0x7c, 0x12, 0xfe, 0x0f, - 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, - 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe, - 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee, 0x1b, 0xfe, 0x36, 0x14, - 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, - 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45, - 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe, 0x39, 0xf0, 0x75, 0x26, - 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, - 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13, - 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, - 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, - 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01, - 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14, 0x56, - 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, - 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80, - 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, - 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, - 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44, - 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09, 0x1a, 0xa4, 0x0a, 0x67, - 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, - 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b, - 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10, 0xfe, 0x4e, 0xe4, 0xfe, - 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, - 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1, - 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, - 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, - 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8, - 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe, 0x1a, 0x10, 0x09, 0x0d, - 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, - 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08, - 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e, 0xfe, 0x82, 0xf0, 0xfe, - 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, - 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82, - 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86, 0x83, 0x33, 0x0b, 0x0e, - 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, - 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80, - 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04, 0xfe, 0x99, 0x83, 0xfe, - 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, - 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, - 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x08, 0x90, 0x04, - 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, - 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, - 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x3c, 0x90, 0x04, - 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, - 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00, +static unsigned char _adv_asc38C1600_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0, + 0x18, 0xe4, 0x01, 0x00, + 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00, + 0x07, 0x17, 0xc0, 0x5f, + 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, + 0x85, 0xf0, 0x86, 0xf0, + 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00, + 0x98, 0x57, 0x01, 0xe6, + 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d, + 0x38, 0x54, 0x32, 0xf0, + 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, + 0x00, 0xe6, 0xb1, 0xf0, + 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01, + 0x06, 0x13, 0x0c, 0x1c, + 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12, + 0xb9, 0x54, 0x00, 0x80, + 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, + 0x03, 0xe6, 0x01, 0xea, + 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, + 0x04, 0x13, 0xbb, 0x55, + 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00, + 0xbb, 0x00, 0xc0, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, + 0x4c, 0x1c, 0x4e, 0x1c, + 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00, + 0x24, 0x01, 0x3c, 0x01, + 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x7c, 0x01, + 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, + 0x6e, 0x1e, 0x02, 0x48, + 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7, + 0x03, 0xfc, 0x06, 0x00, + 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a, + 0x30, 0x1c, 0x38, 0x1c, + 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, + 0x5d, 0xf0, 0xa7, 0xf0, + 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00, + 0x33, 0x00, 0x34, 0x00, + 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, + 0x79, 0x01, 0x3c, 0x09, + 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, + 0x40, 0x16, 0x50, 0x16, + 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc, + 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00, + 0x9c, 0x00, 0xa4, 0x00, + 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, + 0xe9, 0x09, 0x5c, 0x0c, + 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, + 0x42, 0x1d, 0x08, 0x44, + 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54, + 0x83, 0x55, 0x83, 0x59, + 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, + 0x4b, 0xf4, 0x04, 0xf8, + 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, + 0xa8, 0x00, 0xaa, 0x00, + 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01, + 0x7a, 0x01, 0x82, 0x01, + 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, + 0x68, 0x08, 0x10, 0x0d, + 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10, + 0xf3, 0x10, 0x06, 0x12, + 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c, + 0xf0, 0x35, 0x05, 0xfe, + 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, + 0xfe, 0x88, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x13, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xe8, + 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d, + 0x0d, 0x51, 0x37, 0xfe, + 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, + 0xfe, 0xf8, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d, + 0x05, 0xfe, 0x08, 0x0f, + 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe, + 0x28, 0x1c, 0x03, 0xfe, + 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, + 0x48, 0xf0, 0xfe, 0x90, + 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8, + 0x02, 0xfe, 0x46, 0xf0, + 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0, + 0xfe, 0x4e, 0x02, 0xfe, + 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, + 0x0d, 0xa2, 0x1c, 0x07, + 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, + 0x1c, 0xf5, 0xfe, 0x1e, + 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, + 0xde, 0x0a, 0x81, 0x01, + 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, + 0x81, 0x01, 0x5c, 0xfe, + 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, + 0xfe, 0x58, 0x1c, 0x1c, + 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02, + 0x2b, 0xfe, 0x9e, 0x02, + 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, + 0x00, 0x47, 0xb8, 0x01, + 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09, + 0x1a, 0x31, 0xfe, 0x69, + 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe, + 0x1e, 0x1e, 0x20, 0x2c, + 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, + 0x44, 0x15, 0x56, 0x51, + 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57, + 0x01, 0x18, 0x09, 0x00, + 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01, + 0x18, 0xfe, 0xc8, 0x54, + 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, + 0xfe, 0x02, 0xe8, 0x30, + 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0, + 0xfe, 0xe4, 0x01, 0xfe, + 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe, + 0x26, 0xf0, 0xfe, 0x66, + 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, + 0xef, 0x10, 0xfe, 0x9f, + 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05, + 0x70, 0x37, 0xfe, 0x48, + 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26, + 0x21, 0xb9, 0xc7, 0x20, + 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, + 0xe1, 0x2a, 0xeb, 0xfe, + 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32, + 0x15, 0xfe, 0xe4, 0x00, + 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41, + 0xfe, 0x06, 0xf0, 0xfe, + 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, + 0x03, 0x81, 0x1e, 0x1b, + 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05, + 0xea, 0xfe, 0x46, 0x1c, + 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, + 0xfe, 0x48, 0x1c, 0x75, + 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, + 0xe1, 0x01, 0x18, 0x77, + 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42, + 0x8f, 0xfe, 0x70, 0x02, + 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04, + 0x16, 0xfe, 0x4a, 0x04, + 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, + 0x02, 0x00, 0x10, 0x01, + 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25, + 0xee, 0xfe, 0x4c, 0x44, + 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54, + 0x7b, 0xec, 0x60, 0x8d, + 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, + 0x0c, 0x06, 0x28, 0xfe, + 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10, + 0x13, 0x34, 0xfe, 0x4c, + 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54, + 0x13, 0x01, 0x0c, 0x06, + 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, + 0x28, 0xf9, 0x1f, 0x7f, + 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f, + 0xfe, 0xa4, 0x0e, 0x05, + 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe, + 0x9c, 0x93, 0x3a, 0x0b, + 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, + 0x7d, 0x1d, 0xfe, 0x46, + 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04, + 0xfe, 0x87, 0x83, 0xfe, + 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98, + 0x13, 0x0f, 0xfe, 0x20, + 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, + 0x12, 0x01, 0x38, 0x06, + 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda, + 0x05, 0xd0, 0x54, 0x01, + 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe, + 0x50, 0x12, 0x5e, 0xff, + 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, + 0x00, 0x10, 0x2f, 0xfe, + 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01, + 0x38, 0xfe, 0x4a, 0xf0, + 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe, + 0x21, 0x00, 0xf1, 0x2e, + 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, + 0x10, 0x2f, 0xfe, 0xd0, + 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe, + 0x1c, 0x00, 0x4d, 0x01, + 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06, + 0x28, 0xfe, 0x24, 0x12, + 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, + 0x0d, 0x00, 0x01, 0x42, + 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13, + 0x03, 0xb6, 0x1e, 0xfe, + 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17, + 0xfe, 0x72, 0x06, 0x0a, + 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, + 0x19, 0x16, 0xfe, 0x68, + 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66, + 0x03, 0x9a, 0x1e, 0xfe, + 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12, + 0x48, 0xfe, 0x92, 0x06, + 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, + 0x58, 0xff, 0x02, 0x00, + 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17, + 0xfe, 0xea, 0x06, 0x01, + 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16, + 0xfe, 0xe0, 0x06, 0x15, + 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, + 0x01, 0x84, 0xfe, 0xae, + 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a, + 0x1e, 0xfe, 0x1a, 0x12, + 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, + 0x43, 0x48, 0x62, 0x80, + 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, + 0x36, 0xfe, 0x02, 0xf6, + 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e, + 0xd0, 0x0d, 0x17, 0xfe, + 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20, + 0x9e, 0x15, 0x82, 0x01, + 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, + 0x57, 0x10, 0xe6, 0x05, + 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84, + 0xfe, 0x9c, 0x32, 0x5f, + 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c, + 0xfe, 0x0a, 0xf0, 0xfe, + 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, + 0xaf, 0xa0, 0x05, 0x29, + 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14, + 0x00, 0x01, 0x08, 0x14, + 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, + 0x14, 0x00, 0x05, 0xfe, + 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, + 0x12, 0xfe, 0x30, 0x13, + 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, + 0x01, 0x08, 0x14, 0x00, + 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a, + 0x78, 0x4f, 0x0f, 0xfe, + 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, + 0x28, 0x48, 0xfe, 0x6c, + 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32, + 0x12, 0x53, 0x63, 0x4e, + 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, + 0x6c, 0x08, 0xaf, 0xa0, + 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, + 0x05, 0xed, 0xfe, 0x9c, + 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe, + 0x1e, 0xfe, 0x99, 0x58, + 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a, + 0x22, 0x6b, 0x01, 0x0c, + 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, + 0x1e, 0x47, 0x2c, 0x7a, + 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40, + 0x01, 0x0c, 0x61, 0x65, + 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a, + 0x16, 0xfe, 0x08, 0x50, + 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, + 0x01, 0xfe, 0xce, 0x1e, + 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e, + 0x01, 0xfe, 0xfe, 0x1e, + 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a, + 0x10, 0x01, 0x0c, 0x06, + 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, + 0x10, 0x6a, 0x22, 0x6b, + 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04, + 0xfe, 0x9f, 0x83, 0x33, + 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93, + 0x3a, 0x0b, 0xfe, 0xc6, + 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, + 0x01, 0xfe, 0xce, 0x1e, + 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90, + 0x04, 0xfe, 0xc0, 0x93, + 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e, + 0x10, 0x4b, 0x22, 0x4c, + 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, + 0x4e, 0x11, 0x2f, 0xfe, + 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b, + 0x3c, 0x37, 0x88, 0xf5, + 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a, + 0xd3, 0xfe, 0x42, 0x0a, + 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, + 0x05, 0x29, 0x01, 0x41, + 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07, + 0xfe, 0x14, 0x12, 0x01, + 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe, + 0x2e, 0x1c, 0x05, 0xfe, + 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, + 0xfe, 0x2c, 0x1c, 0xfe, + 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe, + 0x92, 0x10, 0xc4, 0xf6, + 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe, + 0xe7, 0x10, 0xfe, 0x2b, + 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, + 0xac, 0xfe, 0xd2, 0xf0, + 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07, + 0x1b, 0xbf, 0xd4, 0x5b, + 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75, + 0x5e, 0x32, 0x1f, 0x7f, + 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, + 0x05, 0x70, 0xfe, 0x74, + 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78, + 0x0f, 0x4d, 0x01, 0xfe, + 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06, + 0x0d, 0x2b, 0xfe, 0xe2, + 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, + 0xfe, 0x88, 0x13, 0x21, + 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe, + 0x83, 0x83, 0xfe, 0xc9, + 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04, + 0x91, 0x04, 0xfe, 0x84, + 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, + 0xfe, 0xcb, 0x57, 0x0b, + 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03, + 0x6a, 0x3b, 0x6b, 0x10, + 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30, + 0x20, 0x6e, 0xdb, 0x64, + 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, + 0xfe, 0x04, 0xfa, 0x64, + 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97, + 0x10, 0x98, 0x91, 0x6c, + 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91, + 0x4b, 0x7e, 0x4c, 0x01, + 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, + 0x58, 0xfe, 0x91, 0x58, + 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24, + 0x1b, 0x40, 0x01, 0x0c, + 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f, + 0xfe, 0x10, 0x90, 0x04, + 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, + 0x79, 0x0b, 0x0e, 0xfe, + 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb, + 0x01, 0x0c, 0x06, 0x0d, + 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe, + 0x0c, 0x58, 0xfe, 0x8d, + 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, + 0x83, 0x33, 0x0b, 0x0e, + 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, + 0x19, 0xfe, 0x19, 0x41, + 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42, + 0x19, 0xfe, 0x44, 0x00, + 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, + 0x4c, 0xfe, 0x0c, 0x51, + 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe, + 0x76, 0x10, 0xac, 0xfe, + 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03, + 0xe3, 0x23, 0x07, 0xfe, + 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, + 0xcc, 0x0c, 0x1f, 0x92, + 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2, + 0x0c, 0xfe, 0x3e, 0x10, + 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70, + 0xfe, 0xcb, 0xf0, 0xfe, + 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, + 0xf4, 0x0c, 0x19, 0x94, + 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3, + 0xfe, 0xcc, 0xf0, 0xef, + 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe, + 0x4e, 0x11, 0x2f, 0xfe, + 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, + 0x3c, 0x37, 0x88, 0xf5, + 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32, + 0x2f, 0xfe, 0x3e, 0x0d, + 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f, + 0xd2, 0x9f, 0xd3, 0x9f, + 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, + 0xc5, 0x75, 0xd7, 0x99, + 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8, + 0x9c, 0x2f, 0xfe, 0x8c, + 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe, + 0x42, 0x00, 0x05, 0x70, + 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, + 0x0d, 0xfe, 0x44, 0x13, + 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b, + 0xfe, 0xda, 0x0e, 0x0a, + 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa, + 0x10, 0x01, 0xfe, 0xf4, + 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, + 0x15, 0x56, 0x01, 0x85, + 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe, + 0xcc, 0x10, 0x01, 0xa7, + 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04, + 0xfe, 0x99, 0x83, 0xfe, + 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, + 0x43, 0x00, 0xfe, 0xa2, + 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, + 0x00, 0x1d, 0x40, 0x15, + 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05, + 0xfe, 0x3a, 0x03, 0x01, + 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, + 0x76, 0x06, 0x12, 0xfe, + 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c, + 0xfe, 0x9d, 0xf0, 0xfe, + 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01, + 0x0c, 0x61, 0x12, 0x44, + 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, + 0xfe, 0x2e, 0x10, 0x19, + 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19, + 0xfe, 0x41, 0x00, 0xa2, + 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b, + 0xea, 0x4f, 0xfe, 0x04, + 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, + 0x35, 0xfe, 0x12, 0x1c, + 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01, + 0xfe, 0xd4, 0x11, 0x05, + 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe, + 0xce, 0x45, 0x31, 0x51, + 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, + 0x67, 0xfe, 0x98, 0x56, + 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01, + 0x0c, 0x06, 0x28, 0xfe, + 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba, + 0xfe, 0xfa, 0x14, 0xfe, + 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, + 0xfe, 0xe0, 0x14, 0xfe, + 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47, + 0xfe, 0xad, 0x13, 0x05, + 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20, + 0xe7, 0xfe, 0x08, 0x1c, + 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, + 0x48, 0x55, 0xa5, 0x3b, + 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe, + 0xf0, 0x1a, 0x03, 0xfe, + 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02, + 0xec, 0xe7, 0x53, 0x00, + 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, + 0x01, 0xfe, 0x62, 0x1b, + 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02, + 0xea, 0xe7, 0x53, 0x92, + 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03, + 0xfe, 0x38, 0x01, 0x23, + 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, + 0x01, 0x01, 0xfe, 0x1e, + 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02, + 0x26, 0x02, 0x21, 0x96, + 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5, + 0xc3, 0xfe, 0xe1, 0x10, + 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, + 0xfe, 0x03, 0xdc, 0xfe, + 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe, + 0x00, 0xcc, 0x02, 0xfe, + 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, + 0x0f, 0xfe, 0x1c, 0x80, + 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, + 0x0f, 0xfe, 0x1e, 0x80, + 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe, + 0x1d, 0x80, 0x04, 0xfe, + 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee, + 0x1e, 0xac, 0xfe, 0x14, + 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, + 0x1f, 0xfe, 0x30, 0xf4, + 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09, + 0x56, 0xfb, 0x01, 0xfe, + 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01, + 0xfe, 0x00, 0x1d, 0x15, + 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, + 0x22, 0x1b, 0xfe, 0x1e, + 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe, + 0x96, 0x90, 0x04, 0xfe, + 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66, + 0x01, 0x01, 0x0c, 0x06, + 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, + 0x0e, 0x77, 0xfe, 0x01, + 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40, + 0x21, 0x2c, 0xfe, 0x00, + 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, + 0x06, 0x58, 0x03, 0xfe, + 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, + 0x03, 0xfe, 0xb2, 0x00, + 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10, + 0x66, 0x10, 0x55, 0x10, + 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91, + 0x54, 0x2b, 0xfe, 0x88, + 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, + 0x91, 0x54, 0x2b, 0xfe, + 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe, + 0x00, 0x40, 0x8d, 0x2c, + 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe, + 0x12, 0x1c, 0x75, 0xfe, + 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, + 0x14, 0xfe, 0x0e, 0x47, + 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01, + 0xa7, 0x90, 0x34, 0x60, + 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80, + 0x09, 0x56, 0xfe, 0x34, + 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, + 0xfe, 0x45, 0x48, 0x01, + 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89, + 0x09, 0x1a, 0xa5, 0x0a, + 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4, + 0xfe, 0x14, 0x56, 0xfe, + 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, + 0xec, 0xb8, 0xfe, 0x9e, + 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01, + 0xf4, 0xfe, 0xdd, 0x10, + 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48, + 0x12, 0x09, 0x0d, 0xfe, + 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, + 0x13, 0x09, 0xfe, 0x23, + 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09, + 0x24, 0xfe, 0x12, 0x12, + 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08, + 0xae, 0x41, 0x02, 0x32, + 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, + 0x35, 0x32, 0x01, 0x43, + 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80, + 0x13, 0x01, 0x0c, 0x06, + 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, + 0xe5, 0x55, 0xb0, 0xfe, + 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, + 0xfe, 0xb6, 0x0e, 0x10, + 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49, + 0x88, 0x20, 0x6e, 0x01, + 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5, + 0x55, 0xfe, 0x04, 0xfa, + 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, + 0xfe, 0x40, 0x56, 0xfe, + 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe, + 0x44, 0x55, 0xfe, 0xe5, + 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10, + 0x68, 0x22, 0x69, 0x01, + 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, + 0x6b, 0xfe, 0x2c, 0x50, + 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6, + 0x50, 0x03, 0x68, 0x3b, + 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe, + 0x40, 0x50, 0xfe, 0xc2, + 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, + 0x16, 0x3d, 0x27, 0x25, + 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01, + 0xa6, 0x23, 0x3f, 0x1b, + 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c, + 0xfe, 0x0a, 0x55, 0x31, + 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, + 0x51, 0x05, 0x72, 0x01, + 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08, + 0x2a, 0x3c, 0x16, 0xc0, + 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b, + 0xfe, 0x66, 0x15, 0x05, + 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, + 0x2b, 0x3d, 0x01, 0x08, + 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03, + 0xb6, 0x1e, 0x83, 0x01, + 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46, + 0x07, 0x90, 0x3f, 0x01, + 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, + 0x01, 0x43, 0x09, 0x82, + 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e, + 0x05, 0x72, 0xfe, 0xc0, + 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e, + 0x32, 0x01, 0x08, 0x17, + 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, + 0x3d, 0x27, 0x25, 0xbd, + 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe, + 0xe8, 0x14, 0x01, 0xa6, + 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe, + 0x0e, 0x12, 0x01, 0x43, + 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, + 0x01, 0x08, 0x17, 0x73, + 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, + 0x27, 0x25, 0xbd, 0x09, + 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe, + 0xb6, 0x14, 0x86, 0xa8, + 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, + 0x82, 0x4e, 0x05, 0x72, + 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, + 0xfe, 0xc0, 0x19, 0x05, + 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f, + 0xcc, 0x01, 0x08, 0x26, + 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, + 0xcc, 0x15, 0x5e, 0x32, + 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, + 0xad, 0x23, 0xfe, 0xff, + 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, + 0x00, 0x57, 0x52, 0xad, + 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, + 0x02, 0x00, 0x57, 0x52, + 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e, + 0x02, 0x13, 0x58, 0xff, + 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01, + 0x5c, 0x0a, 0x55, 0x01, + 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, + 0xff, 0x03, 0x00, 0x54, + 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07, + 0x7c, 0x3a, 0x0b, 0x0e, + 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19, + 0xfe, 0x1a, 0xf7, 0x00, + 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, + 0xda, 0x6d, 0x02, 0xfe, + 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77, + 0x02, 0x01, 0xc6, 0xfe, + 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27, + 0x25, 0xbe, 0x01, 0x08, + 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, + 0x03, 0x9a, 0x1e, 0xfe, + 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12, + 0x48, 0xfe, 0x08, 0x17, + 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26, + 0x17, 0x4d, 0x13, 0x07, + 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, + 0xff, 0x02, 0x83, 0x55, + 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80, + 0x17, 0x1c, 0x63, 0x13, + 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64, + 0x00, 0xb0, 0xfe, 0x80, + 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, + 0x53, 0x07, 0xfe, 0x60, + 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8, + 0x00, 0x1c, 0x95, 0x13, + 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3, + 0xfe, 0x43, 0xf4, 0x96, + 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, + 0xf4, 0x94, 0xf6, 0x8b, + 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe, + 0xda, 0x17, 0x62, 0x49, + 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80, + 0x71, 0x50, 0x26, 0xfe, + 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, + 0x58, 0x02, 0x50, 0x13, + 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27, + 0x25, 0xbe, 0xfe, 0x03, + 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9, + 0x0a, 0x01, 0x08, 0x16, + 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, + 0x01, 0x08, 0x16, 0xa9, + 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01, + 0x08, 0x16, 0xa9, 0x27, + 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83, + 0x01, 0x38, 0x06, 0x24, + 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, + 0x78, 0x03, 0x9a, 0x1e, + 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10, + 0xfe, 0x40, 0x5a, 0x23, + 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c, + 0x80, 0x48, 0xfe, 0xaa, + 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, + 0xfe, 0xac, 0x1d, 0xfe, + 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe, + 0x43, 0x48, 0x2d, 0x93, + 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4, + 0x36, 0xfe, 0x34, 0xf4, + 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, + 0x28, 0x10, 0xfe, 0xc0, + 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa, + 0x18, 0x45, 0xfe, 0x1c, + 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c, + 0x19, 0xfe, 0x04, 0xf4, + 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, + 0x21, 0xfe, 0x7f, 0x01, + 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe, + 0x7e, 0x01, 0xfe, 0xc8, + 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa, + 0x21, 0xfe, 0x81, 0x01, + 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, + 0x13, 0x0d, 0x02, 0x14, + 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17, + 0xfe, 0x82, 0x19, 0x14, + 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01, + 0x08, 0x02, 0x14, 0x07, + 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, + 0x01, 0x08, 0x17, 0xc1, + 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01, + 0x08, 0x02, 0x50, 0x02, + 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74, + 0x14, 0x12, 0x01, 0x08, + 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, + 0x08, 0x17, 0x74, 0xfe, + 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17, + 0x74, 0x5f, 0xcc, 0x01, + 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4, + 0xfe, 0x49, 0xf4, 0x00, + 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, + 0x02, 0x00, 0x10, 0x2f, + 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13, + 0x16, 0xfe, 0x64, 0x1a, + 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c, + 0x61, 0x07, 0x44, 0x02, + 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, + 0x13, 0x0a, 0x9d, 0x01, + 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa, + 0xfe, 0x80, 0xe7, 0x1a, + 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02, + 0x0a, 0x5a, 0x01, 0x18, + 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, + 0x7e, 0x1e, 0xfe, 0x80, + 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18, + 0xfe, 0x80, 0x4c, 0x0a, + 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf, + 0xfe, 0x19, 0xde, 0xfe, + 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, + 0x2a, 0x1c, 0xfa, 0xb3, + 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe, + 0xf4, 0x1a, 0xfe, 0xfa, + 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24, + 0xfe, 0x18, 0x58, 0x03, + 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, + 0xfe, 0x30, 0xf4, 0x07, + 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, + 0xf7, 0x24, 0xb1, 0xfe, + 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b, + 0xfe, 0xba, 0x10, 0x1c, + 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, + 0x1d, 0xf7, 0x54, 0xb1, + 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe, + 0xaf, 0x19, 0xfe, 0x98, + 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c, + 0x1a, 0x87, 0x8b, 0x0f, + 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, + 0xfe, 0x32, 0x90, 0x04, + 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a, + 0x7c, 0x12, 0xfe, 0x0f, + 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14, + 0x31, 0x02, 0xc9, 0x2b, + 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, + 0x6a, 0xfe, 0x19, 0xfe, + 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee, + 0x1b, 0xfe, 0x36, 0x14, + 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, + 0xfe, 0x80, 0xe7, 0x1a, + 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, + 0x30, 0xfe, 0x12, 0x45, + 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe, + 0x39, 0xf0, 0x75, 0x26, + 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03, + 0xe3, 0x23, 0x07, 0xfe, + 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, + 0x56, 0xfe, 0x3c, 0x13, + 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a, + 0x01, 0x18, 0xcb, 0xfe, + 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16, + 0xfe, 0x00, 0xcc, 0xcb, + 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, + 0xfe, 0x80, 0x4c, 0x01, + 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24, + 0x12, 0xfe, 0x14, 0x56, + 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7, + 0x0d, 0x19, 0xfe, 0x15, + 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, + 0x83, 0xfe, 0x18, 0x80, + 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38, + 0x90, 0xfe, 0xba, 0x90, + 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02, + 0x21, 0xb9, 0x88, 0x20, + 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, + 0x18, 0xfe, 0x49, 0x44, + 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09, + 0x1a, 0xa4, 0x0a, 0x67, + 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4, + 0x1d, 0x7b, 0xfe, 0x52, + 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, + 0x4e, 0xe4, 0xdd, 0x7b, + 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10, + 0xfe, 0x4e, 0xe4, 0xfe, + 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24, + 0xfe, 0x08, 0x10, 0x03, + 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, + 0x68, 0x54, 0xfe, 0xf1, + 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, + 0xfe, 0x1a, 0xf4, 0xfe, + 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02, + 0x09, 0x92, 0xfe, 0x5a, + 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, + 0x5a, 0xf0, 0xfe, 0xc8, + 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe, + 0x1a, 0x10, 0x09, 0x0d, + 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02, + 0x1f, 0x93, 0x01, 0x42, + 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, + 0xfe, 0x14, 0xf0, 0x08, + 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e, + 0xfe, 0x82, 0xf0, 0xfe, + 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x18, + 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, + 0x80, 0x04, 0xfe, 0x82, + 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86, + 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x04, + 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, + 0x80, 0x04, 0xfe, 0x80, + 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04, + 0xfe, 0x99, 0x83, 0xfe, + 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86, + 0x83, 0xfe, 0xce, 0x47, + 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, + 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x08, 0x90, 0x04, + 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04, + 0xfe, 0x8a, 0x93, 0x79, + 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, + 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x3c, 0x90, 0x04, + 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80, + 0x04, 0xfe, 0x83, 0x83, + 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00, }; -STATIC unsigned short _adv_asc38C1600_size = - sizeof(_adv_asc38C1600_buf); /* 0x1673 */ -STATIC ADV_DCNT _adv_asc38C1600_chksum = - 0x0604EF77UL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ +static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ /* a_init.c */ /* @@ -14049,340 +13847,340 @@ STATIC ADV_DCNT _adv_asc38C1600_chksum = * on big-endian platforms so char fields read as words are actually being * unswapped on big-endian platforms. */ -STATIC ADVEEP_3550_CONFIG -Default_3550_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ - 0x0000, /* cfg_msw */ - 0xFFFF, /* disc_enable */ - 0xFFFF, /* wdtr_able */ - 0xFFFF, /* sdtr_able */ - 0xFFFF, /* start_motor */ - 0xFFFF, /* tagqng_able */ - 0xFFFF, /* bios_scan */ - 0, /* scam_tolerant */ - 7, /* adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* termination */ - 0, /* reserved1 */ - 0xFFE7, /* bios_ctrl */ - 0xFFFF, /* ultra_able */ - 0, /* reserved2 */ - ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ +static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ + 0x0000, /* cfg_msw */ + 0xFFFF, /* disc_enable */ + 0xFFFF, /* wdtr_able */ + 0xFFFF, /* sdtr_able */ + 0xFFFF, /* start_motor */ + 0xFFFF, /* tagqng_able */ + 0xFFFF, /* bios_scan */ + 0, /* scam_tolerant */ + 7, /* adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* termination */ + 0, /* reserved1 */ + 0xFFE7, /* bios_ctrl */ + 0xFFFF, /* ultra_able */ + 0, /* reserved2 */ + ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ }; -STATIC ADVEEP_3550_CONFIG -ADVEEP_3550_Config_Field_IsChar __initdata = { - 0, /* cfg_lsw */ - 0, /* cfg_msw */ - 0, /* -disc_enable */ - 0, /* wdtr_able */ - 0, /* sdtr_able */ - 0, /* start_motor */ - 0, /* tagqng_able */ - 0, /* bios_scan */ - 0, /* scam_tolerant */ - 1, /* adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* termination */ - 1, /* reserved1 */ - 0, /* bios_ctrl */ - 0, /* ultra_able */ - 0, /* reserved2 */ - 1, /* max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ +static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = { + 0, /* cfg_lsw */ + 0, /* cfg_msw */ + 0, /* -disc_enable */ + 0, /* wdtr_able */ + 0, /* sdtr_able */ + 0, /* start_motor */ + 0, /* tagqng_able */ + 0, /* bios_scan */ + 0, /* scam_tolerant */ + 1, /* adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* termination */ + 1, /* reserved1 */ + 0, /* bios_ctrl */ + 0, /* ultra_able */ + 0, /* reserved2 */ + 1, /* max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ }; -STATIC ADVEEP_38C0800_CONFIG -Default_38C0800_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x4444, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x4444, /* 13 sdtr_speed2 */ - 0x4444, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x4444, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x4444, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x4444, /* 13 sdtr_speed2 */ + 0x4444, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x4444, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C0800_CONFIG -ADVEEP_38C0800_Config_Field_IsChar __initdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C1600_CONFIG -Default_38C1600_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x5555, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x5555, /* 13 sdtr_speed2 */ - 0x5555, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x5555, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x5555, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x5555, /* 13 sdtr_speed2 */ + 0x5555, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x5555, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C1600_CONFIG -ADVEEP_38C1600_Config_Field_IsChar __initdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; /* @@ -14393,136 +14191,128 @@ ADVEEP_38C1600_Config_Field_IsChar __initdata = { * For a non-fatal error return a warning code. If there are no warnings * then 0 is returned. */ -STATIC int __init -AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) { - ushort warn_code; - AdvPortAddr iop_base; - uchar pci_cmd_reg; - int status; - - warn_code = 0; - asc_dvc->err_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * PCI Command Register - * - * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes - * I/O Space Control, Memory Space Control and Bus Master Control bits. - */ - - if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) - { - pci_cmd_reg |= AscPCICmdRegBits_BusMastering; - - DvcAdvWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, pci_cmd_reg); - - if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) - { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * PCI Latency Timer - * - * If the "latency timer" register is 0x20 or above, then we don't need - * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it - * comes up less than 0x20). - */ - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { - DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20); - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) - { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * Save the state of the PCI Configuration Command Register - * "Parity Error Response Control" Bit. If the bit is clear (0), - * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore - * DMA parity errors. - */ - asc_dvc->cfg->control_flag = 0; - if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) - & AscPCICmdRegBits_ParErrRespCtrl)) == 0) - { - asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; - } + ushort warn_code; + AdvPortAddr iop_base; + uchar pci_cmd_reg; + int status; + + warn_code = 0; + asc_dvc->err_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * PCI Command Register + * + * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes + * I/O Space Control, Memory Space Control and Bus Master Control bits. + */ + + if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister)) + & AscPCICmdRegBits_BusMastering) + != AscPCICmdRegBits_BusMastering) { + pci_cmd_reg |= AscPCICmdRegBits_BusMastering; + + DvcAdvWritePCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister, + pci_cmd_reg); + + if (((DvcAdvReadPCIConfigByte + (asc_dvc, AscPCIConfigCommandRegister)) + & AscPCICmdRegBits_BusMastering) + != AscPCICmdRegBits_BusMastering) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } - asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | - ADV_LIB_VERSION_MINOR; - asc_dvc->cfg->chip_version = - AdvGetChipVersion(iop_base, asc_dvc->bus_type); + /* + * PCI Latency Timer + * + * If the "latency timer" register is 0x20 or above, then we don't need + * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it + * comes up less than 0x20). + */ + if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { + DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, + 0x20); + if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < + 0x20) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } - ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", - (ushort) AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), - (ushort) ADV_CHIP_ID_BYTE); + /* + * Save the state of the PCI Configuration Command Register + * "Parity Error Response Control" Bit. If the bit is clear (0), + * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore + * DMA parity errors. + */ + asc_dvc->cfg->control_flag = 0; + if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) + & AscPCICmdRegBits_ParErrRespCtrl)) == 0) { + asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; + } - ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", - (ushort) AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), - (ushort) ADV_CHIP_ID_WORD); + asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | + ADV_LIB_VERSION_MINOR; + asc_dvc->cfg->chip_version = + AdvGetChipVersion(iop_base, asc_dvc->bus_type); + + ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", + (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), + (ushort)ADV_CHIP_ID_BYTE); + + ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", + (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), + (ushort)ADV_CHIP_ID_WORD); + + /* + * Reset the chip to start and allow register writes. + */ + if (AdvFindSignature(iop_base) == 0) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return ADV_ERROR; + } else { + /* + * The caller must set 'chip_type' to a valid setting. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && + asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && + asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Reset the chip to start and allow register writes. - */ - if (AdvFindSignature(iop_base) == 0) - { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return ADV_ERROR; - } - else { - /* - * The caller must set 'chip_type' to a valid setting. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && - asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && - asc_dvc->chip_type != ADV_CHIP_ASC38C1600) - { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - /* - * Reset Chip. - */ - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_WR_IO_REG); - - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - if ((status = AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - if ((status = AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } else - { - if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } - warn_code |= status; - } + /* + * Reset Chip. + */ + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_RESET); + DvcSleepMilliSecond(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); + + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + if ((status = + AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + if ((status = + AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } else { + if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } + warn_code |= status; + } - return warn_code; + return warn_code; } /* @@ -14535,574 +14325,563 @@ AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc3550_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able = 0, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC3550. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550) - { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - ushort bios_version, major, minor; - - bios_version = bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM)/2]; - major = (bios_version >> 12) & 0xF; - minor = (bios_version >> 8) & 0xF; - if (major < 3 || (major == 3 && minor == 1)) - { - /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ - AdvReadWordLram(iop_base, 0x120, wdtr_able); - } else - { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - } - } - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc3550_size; i++) - { - if (_adv_asc3550_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[i + 3] << 8) | - _adv_asc3550_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc3550_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[i + 2] << 8) | - _adv_asc3550_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | - _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc3550_expanded_size = word; - - /* - * Clear the rest of ASC-3550 Internal RAM (8KB). - */ - for (; word < ADV_3550_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc3550_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc3550_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read and save microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC3550. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO - * threshold of 128 bytes. This register is only accessible to the host. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - START_CTL_EMFU | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID - * bitmask. These values determine the maximum SDTR speed negotiated - * with a device. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - * - * 4-bit speed SDTR speed name - * =========== =============== - * 0000b (0x0) SDTR disabled - * 0001b (0x1) 5 Mhz - * 0010b (0x2) 10 Mhz - * 0011b (0x3) 20 Mhz (Ultra) - * 0100b (0x4) 40 Mhz (LVD/Ultra2) - * 0101b (0x5) 80 Mhz (LVD2/Ultra3) - * 0110b (0x6) Undefined - * . - * 1111b (0xF) Undefined - */ - word = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) - { - /* Set Ultra speed for TID 'tid'. */ - word |= (0x3 << (4 * (tid % 4))); - } else - { - /* Set Fast speed for TID 'tid'. */ - word |= (0x2 << (4 * (tid % 4))); - } - if (tid == 3) /* Check if done with sdtr_speed1. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); - word = 0; - } else if (tid == 7) /* Check if done with sdtr_speed2. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); - word = 0; - } else if (tid == 11) /* Check if done with sdtr_speed3. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); - word = 0; - } else if (tid == 15) /* Check if done with sdtr_speed4. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); - /* End of loop. */ - } - } - - /* - * Set microcode operating variable for the disconnect per TID bitmask. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int j; + int adv_asc3550_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able = 0, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC3550. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550) { + asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) { + ushort bios_version, major, minor; + + bios_version = + bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2]; + major = (bios_version >> 12) & 0xF; + minor = (bios_version >> 8) & 0xF; + if (major < 3 || (major == 3 && minor == 1)) { + /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ + AdvReadWordLram(iop_base, 0x120, wdtr_able); + } else { + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + } + } + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If all three connectors are in use, return an error. - */ - if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || - (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) - { - asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; - return ADV_ERROR; - } + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + /* Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc3550_size; i++) { + if (_adv_asc3550_buf[i] == 0xff) { + for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf + [i + + 3] << 8) | + _adv_asc3550_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc3550_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf[i + + 2] + << 8) | + _adv_asc3550_buf[i + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); + word++; + } + } - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc3550_expanded_size = word; + + /* + * Clear the rest of ASC-3550 Internal RAM (8KB). + */ + for (; word < ADV_3550_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * If this is a differential board and a single-ended device - * is attached to one of the connectors, return an error. - */ - if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) - { - asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; - return ADV_ERROR; - } + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * If automatic termination control is enabled, then set the - * termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting - * then 'termination' was set-up in AdvInitFrom3550EEPROM() and - * is ready to be 'ored' into SCSI_CFG1. - */ - if (asc_dvc->cfg->termination == 0) - { - /* - * The software always controls termination by setting TERM_CTL_SEL. - * If TERM_CTL_SEL were set to 0, the hardware would set termination. - */ - asc_dvc->cfg->termination |= TERM_CTL_SEL; - - switch(scsi_cfg1 & CABLE_DETECT) - { - /* TERM_CTL_H: on, TERM_CTL_L: on */ - case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF: - asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); - break; - - /* TERM_CTL_H: on, TERM_CTL_L: off */ - case 0x1: case 0x5: case 0x9: case 0xA: case 0xC: - asc_dvc->cfg->termination |= TERM_CTL_H; - break; - - /* TERM_CTL_H: off, TERM_CTL_L: off */ - case 0x2: case 0x6: - break; - } - } + for (word = 0; word < adv_asc3550_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } - /* - * Clear any set TERM_CTL_H and TERM_CTL_L bits. - */ - scsi_cfg1 &= ~TERM_CTL; + if (sum != _adv_asc3550_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Invert the TERM_CTL_H and TERM_CTL_L bits and then - * set 'scsi_cfg1'. The TERM_POL bit does not need to be - * referenced, because the hardware internally inverts - * the Termination High and Low bits if TERM_POL is set. - */ - scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set filter value and possibly modified termination control - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, - FLTR_DISABLE | scsi_cfg1); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read and save microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC3550. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-3550 has 8KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_8KB); + /* + * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO + * threshold of 128 bytes. This register is only accessible to the host. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + START_CTL_EMFU | READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID + * bitmask. These values determine the maximum SDTR speed negotiated + * with a device. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + * + * 4-bit speed SDTR speed name + * =========== =============== + * 0000b (0x0) SDTR disabled + * 0001b (0x1) 5 Mhz + * 0010b (0x2) 10 Mhz + * 0011b (0x3) 20 Mhz (Ultra) + * 0100b (0x4) 40 Mhz (LVD/Ultra2) + * 0101b (0x5) 80 Mhz (LVD2/Ultra3) + * 0110b (0x6) Undefined + * . + * 1111b (0xF) Undefined + */ + word = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) { + /* Set Ultra speed for TID 'tid'. */ + word |= (0x3 << (4 * (tid % 4))); + } else { + /* Set Fast speed for TID 'tid'. */ + word |= (0x2 << (4 * (tid % 4))); + } + if (tid == 3) { /* Check if done with sdtr_speed1. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); + word = 0; + } else if (tid == 7) { /* Check if done with sdtr_speed2. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); + word = 0; + } else if (tid == 11) { /* Check if done with sdtr_speed3. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); + word = 0; + } else if (tid == 15) { /* Check if done with sdtr_speed4. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); + /* End of loop. */ + } + } - /* - * Build carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * Set microcode operating variable for the disconnect per TID bitmask. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If all three connectors are in use, return an error. + */ + if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || + (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) { + asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; + return ADV_ERROR; + } - do { - /* - * Get physical address of the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + /* + * If this is a differential board and a single-ended device + * is attached to one of the connectors, return an error. + */ + if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) { + asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; + return ADV_ERROR; + } - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * If automatic termination control is enabled, then set the + * termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting + * then 'termination' was set-up in AdvInitFrom3550EEPROM() and + * is ready to be 'ored' into SCSI_CFG1. + */ + if (asc_dvc->cfg->termination == 0) { + /* + * The software always controls termination by setting TERM_CTL_SEL. + * If TERM_CTL_SEL were set to 0, the hardware would set termination. + */ + asc_dvc->cfg->termination |= TERM_CTL_SEL; + + switch (scsi_cfg1 & CABLE_DETECT) { + /* TERM_CTL_H: on, TERM_CTL_L: on */ + case 0x3: + case 0x7: + case 0xB: + case 0xD: + case 0xE: + case 0xF: + asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); + break; + + /* TERM_CTL_H: on, TERM_CTL_L: off */ + case 0x1: + case 0x5: + case 0x9: + case 0xA: + case 0xC: + asc_dvc->cfg->termination |= TERM_CTL_H; + break; + + /* TERM_CTL_H: off, TERM_CTL_L: off */ + case 0x2: + case 0x6: + break; + } + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + /* + * Clear any set TERM_CTL_H and TERM_CTL_L bits. + */ + scsi_cfg1 &= ~TERM_CTL; + + /* + * Invert the TERM_CTL_H and TERM_CTL_L bits and then + * set 'scsi_cfg1'. The TERM_POL bit does not need to be + * referenced, because the hardware internally inverts + * the Termination High and Low bits if TERM_POL is set. + */ + scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set filter value and possibly modified termination control + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, + FLTR_DISABLE | scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-3550 has 8KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_8KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * Set RISC ICQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + do { + /* + * Get physical address of the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + buf_size -= sizeof(ADV_CARR_T); - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC IRQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + carrp++; + } + while (buf_size > 0); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -15115,619 +14894,610 @@ AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc38C0800_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) - { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (RAM Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ - - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) - { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) != PRE_TEST_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - } - - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ - - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) - { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; - } - - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C0800_size; i++) - { - if (_adv_asc38C0800_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[i + 3] << 8) | - _adv_asc38C0800_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C0800_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[i + 2] << 8) | - _adv_asc38C0800_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | - _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C0800_expanded_size = word; - - /* - * Clear the rest of ASC-38C0800 Internal RAM (16KB). - */ - for (; word < ADV_38C0800_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i); - - ASC_DBG2(1, - "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n", - (ulong) sum, (ulong) _adv_asc38C0800_chksum); - - if (sum != _adv_asc38C0800_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C0800. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] - * bits for the default FIFO threshold. - * - * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. - * - * For DMA Errata #4 set the BC_THRESH_ENB bit. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int j; + int adv_asc38C0800_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * RAM BIST (RAM Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ + + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + } - /* - * All kind of combinations of devices attached to one of four connectors - * are acceptable except HVD device attached. For example, LVD device can - * be attached to SE connector while SE device attached to LVD connector. - * If LVD device attached to SE connector, it only runs up to Ultra speed. - * - * If an HVD device is attached to one of LVD connectors, return an error. - * However, there is no way to detect HVD device attached to SE connectors. - */ - if (scsi_cfg1 & HVD) - { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ + + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - /* - * If either SE or LVD automatic termination control is enabled, then - * set the termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting then - * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to - * be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) - { - /* SE automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_SE) - { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: case 0x2: case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - /* TERM_SE_HI: on, TERM_SE_LO: off */ - case 0x0: - asc_dvc->cfg->termination |= TERM_SE_HI; - break; - } - } + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + * + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + + /* Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc38C0800_size; i++) { + if (_adv_asc38C0800_buf[i] == 0xff) { + for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf + [i + + 3] << 8) | + _adv_asc38C0800_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc38C0800_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf + [i + + 2] << 8) | + _adv_asc38C0800_buf[i + + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2])); + word++; + } + } - if ((asc_dvc->cfg->termination & TERM_LVD) == 0) - { - /* LVD automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_LVD) - { - /* TERM_LVD_HI: on, TERM_LVD_LO: on */ - case 0x4: case 0x8: case 0xC: - asc_dvc->cfg->termination |= TERM_LVD; - break; - - /* TERM_LVD_HI: off, TERM_LVD_LO: off */ - case 0x0: - break; - } - } + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc38C0800_expanded_size = word; + + /* + * Clear the rest of ASC-38C0800 Internal RAM (16KB). + */ + for (; word < ADV_38C0800_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * Clear any set TERM_SE and TERM_LVD bits. - */ - scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); + for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } + ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i); - /* - * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits - * and set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); + ASC_DBG2(1, + "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n", + (ulong)sum, (ulong)_adv_asc38C0800_chksum); - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control and reset DIS_TERM_DRV - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + if (sum != _adv_asc38C0800_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C0800 has 16KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_16KB); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC38C0800. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); + + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] + * bits for the default FIFO threshold. + * + * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. + * + * For DMA Errata #4 set the BC_THRESH_ENB bit. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | + READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + /* + * All kind of combinations of devices attached to one of four connectors + * are acceptable except HVD device attached. For example, LVD device can + * be attached to SE connector while SE device attached to LVD connector. + * If LVD device attached to SE connector, it only runs up to Ultra speed. + * + * If an HVD device is attached to one of LVD connectors, return an error. + * However, there is no way to detect HVD device attached to SE connectors. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * If either SE or LVD automatic termination control is enabled, then + * set the termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting then + * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to + * be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; + + /* TERM_SE_HI: on, TERM_SE_LO: off */ + case 0x0: + asc_dvc->cfg->termination |= TERM_SE_HI; + break; + } + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + if ((asc_dvc->cfg->termination & TERM_LVD) == 0) { + /* LVD automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_LVD) { + /* TERM_LVD_HI: on, TERM_LVD_LO: on */ + case 0x4: + case 0x8: + case 0xC: + asc_dvc->cfg->termination |= TERM_LVD; + break; + + /* TERM_LVD_HI: off, TERM_LVD_LO: off */ + case 0x0: + break; + } + } - /* - * Set RISC ICQ physical address start value. - * carr_pa is LE, must be native before write - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + /* + * Clear any set TERM_SE and TERM_LVD bits. + */ + scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); + + /* + * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); + + /* + * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits + * and set possibly modified termination control bits in the Microcode + * SCSI_CFG1 Register Value. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control and reset DIS_TERM_DRV + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C0800 has 16KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build the carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + do { + /* + * Get physical address for the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + buf_size -= sizeof(ADV_CARR_T); - /* - * Set RISC IRQ physical address start value. - * - * carr_pa is LE, must be native before write * - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + carrp++; + } + while (buf_size > 0); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + * carr_pa is LE, must be native before write + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + * + * carr_pa is LE, must be native before write * + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -15740,630 +15510,617 @@ AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - long word; - int j; - int adv_asc38C1600_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; - uchar max_cmd[ASC_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) - { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ - - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) - { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) != PRE_TEST_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - } - - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ - - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) - { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; - } - - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - /* - * Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C1600_size; i++) - { - if (_adv_asc38C1600_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[i + 3] << 8) | - _adv_asc38C1600_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C1600_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[i + 2] << 8) | - _adv_asc38C1600_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | - _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C1600_expanded_size = word; - - /* - * Clear the rest of ASC-38C1600 Internal RAM (32KB). - */ - for (; word < ADV_38C1600_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc38C1600_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C1600. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * If the BIOS control flag AIPP (Asynchronous Information - * Phase Protection) disable bit is not set, then set the firmware - * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable - * AIPP checking and encoding. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_ENABLE_AIPP; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], - * and START_CTL_TH [3:2]. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + long word; + int j; + int adv_asc38C1600_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; + uchar max_cmd[ASC_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Calculate SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - * - * Each ASC-38C1600 function has only two cable detect bits. - * The bus mode override bits are in IOPB_SOFT_OVER_WR. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If the cable is reversed all of the SCSI_CTRL register signals - * will be set. Check for and return an error if this condition is - * found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * RAM BIST (Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ + + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + } - /* - * Each ASC-38C1600 function has two connectors. Only an HVD device - * can not be connected to either connector. An LVD device or SE device - * may be connected to either connecor. If an SE device is connected, - * then at most Ultra speed (20 Mhz) can be used on both connectors. - * - * If an HVD device is attached, return an error. - */ - if (scsi_cfg1 & HVD) - { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ + + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - /* - * Each function in the ASC-38C1600 uses only the SE cable detect and - * termination because there are two connectors for each function. Each - * function may use either LVD or SE mode. Corresponding the SE automatic - * termination control EEPROM bits are used for each function. Each - * function has its own EEPROM. If SE automatic control is enabled for - * the function, then set the termination value based on a table listed - * in a_condor.h. - * - * If manual termination is specified in the EEPROM for the function, - * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is - * ready to be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) - { - /* SE automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_SE) - { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: case 0x2: case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - case 0x0: - if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) - { - /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ - } - else - { - /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ - asc_dvc->cfg->termination |= TERM_SE_HI; - } - break; - } - } + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + * + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + + /* + * Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc38C1600_size; i++) { + if (_adv_asc38C1600_buf[i] == 0xff) { + for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf + [i + + 3] << 8) | + _adv_asc38C1600_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc38C1600_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf + [i + + 2] << 8) | + _adv_asc38C1600_buf[i + + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); + word++; + } + } - /* - * Clear any set TERM_SE bits. - */ - scsi_cfg1 &= ~TERM_SE; + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc38C1600_expanded_size = word; + + /* + * Clear the rest of ASC-38C1600 Internal RAM (32KB). + */ + for (; word < ADV_38C1600_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * Invert the TERM_SE bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * Clear Big Endian and Terminator Polarity bits and set possibly - * modified termination control bits in the Microcode SCSI_CFG1 - * Register Value. - * - * Big Endian bit is not used even on big endian machines. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); + for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + if (sum != _adv_asc38C1600_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C1600 has 32KB internal memory. - * - * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come - * out a special 16K Adv Library and Microcode version. After the issue - * resolved, we should turn back to the 32K support. Both a_condor.h and - * mcode.sas files also need to be updated. - * - * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - * BIOS_EN | RAM_SZ_32KB); - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, BIOS_EN | RAM_SZ_16KB); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC38C1600. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); + + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * If the BIOS control flag AIPP (Asynchronous Information + * Phase Protection) disable bit is not set, then set the firmware + * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable + * AIPP checking and encoding. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_ENABLE_AIPP; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], + * and START_CTL_TH [3:2]. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Calculate SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + * + * Each ASC-38C1600 function has only two cable detect bits. + * The bus mode override bits are in IOPB_SOFT_OVER_WR. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If the cable is reversed all of the SCSI_CTRL register signals + * will be set. Check for and return an error if this condition is + * found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + /* + * Each ASC-38C1600 function has two connectors. Only an HVD device + * can not be connected to either connector. An LVD device or SE device + * may be connected to either connecor. If an SE device is connected, + * then at most Ultra speed (20 Mhz) can be used on both connectors. + * + * If an HVD device is attached, return an error. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - /* - * Set RISC ICQ physical address start value. Initialize the - * COMMA register to the same value otherwise the RISC will - * prematurely detect a command is available. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(asc_dvc->icq_sp->carr_pa)); + /* + * Each function in the ASC-38C1600 uses only the SE cable detect and + * termination because there are two connectors for each function. Each + * function may use either LVD or SE mode. Corresponding the SE automatic + * termination control EEPROM bits are used for each function. Each + * function has its own EEPROM. If SE automatic control is enabled for + * the function, then set the termination value based on a table listed + * in a_condor.h. + * + * If manual termination is specified in the EEPROM for the function, + * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is + * ready to be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; + + case 0x0: + if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) { + /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ + } else { + /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ + asc_dvc->cfg->termination |= TERM_SE_HI; + } + break; + } + } - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + /* + * Clear any set TERM_SE bits. + */ + scsi_cfg1 &= ~TERM_SE; + + /* + * Invert the TERM_SE bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); + + /* + * Clear Big Endian and Terminator Polarity bits and set possibly + * modified termination control bits in the Microcode SCSI_CFG1 + * Register Value. + * + * Big Endian bit is not used even on big endian machines. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control bits in the Microcode + * SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C1600 has 32KB internal memory. + * + * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come + * out a special 16K Adv Library and Microcode version. After the issue + * resolved, we should turn back to the 32K support. Both a_condor.h and + * mcode.sas files also need to be updated. + * + * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + * BIOS_EN | RAM_SZ_32KB); + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build the carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + do { + /* + * Get physical address for the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * Set RISC IRQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + buf_size -= sizeof(ADV_CARR_T); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * per TID microcode operating variables. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + carrp++; + } + while (buf_size > 0); + + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. Initialize the + * COMMA register to the same value otherwise the RISC will + * prematurely detect a command is available. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(asc_dvc->icq_sp->carr_pa)); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * per TID microcode operating variables. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -16378,164 +16135,146 @@ AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_3550_CONFIG eep_config; - int i; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_3550_CONFIG eep_config; + int i; - iop_base = asc_dvc->iop_base; + iop_base = asc_dvc->iop_base; - warn_code = 0; + warn_code = 0; - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_3550_EEPROM_Config + i); - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet3550EEPConfig(iop_base, &eep_config); - } - /* - * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_able = eep_config.sdtr_able; - asc_dvc->ultra_able = eep_config.ultra_able; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_3550_EEPROM_Config + i); + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + + AdvSet3550EEPConfig(iop_base, &eep_config); + } + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_able = eep_config.sdtr_able; + asc_dvc->ultra_able = eep_config.ultra_able; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination == 0) - { - asc_dvc->cfg->termination = 0; /* auto termination */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination == 1) - { - asc_dvc->cfg->termination = TERM_CTL_SEL; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination == 2) - { - asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination == 3) - { - asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; - } else - { - /* - * The EEPROM 'termination' field contains a bad value. Use - * automatic termination instead. - */ - asc_dvc->cfg->termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - return warn_code; + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination == 0) { + asc_dvc->cfg->termination = 0; /* auto termination */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination == 1) { + asc_dvc->cfg->termination = TERM_CTL_SEL; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination == 2) { + asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination == 3) { + asc_dvc->cfg->termination = + TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; + } else { + /* + * The EEPROM 'termination' field contains a bad value. Use + * automatic termination instead. + */ + asc_dvc->cfg->termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + return warn_code; } /* @@ -16550,225 +16289,195 @@ AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_38C0800_CONFIG eep_config; - int i; - uchar tid, termination; - ushort sdtr_speed = 0; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_38C0800_CONFIG eep_config; + int i; + uchar tid, termination; + ushort sdtr_speed = 0; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - iop_base = asc_dvc->iop_base; + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_38C0800_EEPROM_Config + i); + } - warn_code = 0; + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_38C0800_EEPROM_Config + i); - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet38C0800EEPConfig(iop_base, &eep_config); - } - /* - * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. - */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - if (tid == 0) - { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) - { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) - { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) - { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ADV_MAX_TID) - { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + AdvSet38C0800EEPConfig(iop_base, &eep_config); + } + /* + * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ADV_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination_se == 0) - { - termination = 0; /* auto termination for SE */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) - { - termination = 0; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) - { - termination = TERM_SE_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) - { - termination = TERM_SE; - } else - { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - if (eep_config.termination_lvd == 0) - { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) - { - asc_dvc->cfg->termination = termination; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) - { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) - { - asc_dvc->cfg->termination = - termination | TERM_LVD; - } else - { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - return warn_code; + return warn_code; } /* @@ -16783,265 +16492,240 @@ AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_38C1600_CONFIG eep_config; - int i; - uchar tid, termination; - ushort sdtr_speed = 0; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_38C1600_CONFIG eep_config; + int i; + uchar tid, termination; + ushort sdtr_speed = 0; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - iop_base = asc_dvc->iop_base; + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) { + if (i == 1 + && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) != + 0) { + /* + * Set Function 1 EEPROM Word 0 MSB + * + * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11) + * EEPROM bits. + * + * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and + * old Mac system booting problem. The Expansion ROM must + * be disabled in Function 1 for these systems. + * + */ + *((uchar *)&eep_config + i) = + ((* + ((uchar *)&Default_38C1600_EEPROM_Config + + + i)) & + (~ + (((ADV_EEPROM_BIOS_ENABLE | + ADV_EEPROM_INTAB) >> 8) & 0xFF))); + + /* + * Set the INTAB (bit 11) if the GPIO 0 input indicates + * the Function 1 interrupt line is wired to INTA. + * + * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: + * 1 - Function 1 interrupt line wired to INT A. + * 0 - Function 1 interrupt line wired to INT B. + * + * Note: Adapter boards always have Function 0 wired to INTA. + * Put all 5 GPIO bits in input mode and then read + * their input values. + */ + AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, + 0); + if (AdvReadByteRegister + (iop_base, IOPB_GPIO_DATA) & 0x01) { + /* Function 1 interrupt wired to INTA; Set EEPROM bit. */ + *((uchar *)&eep_config + i) |= + ((ADV_EEPROM_INTAB >> 8) & 0xFF); + } + } else { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_38C1600_EEPROM_Config + + i); + } + } - warn_code = 0; + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) - { - if (i == 1 && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) != 0) - { - /* - * Set Function 1 EEPROM Word 0 MSB - * - * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11) - * EEPROM bits. - * - * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and - * old Mac system booting problem. The Expansion ROM must - * be disabled in Function 1 for these systems. - * - */ - *((uchar *) &eep_config + i) = - ((*((uchar *) &Default_38C1600_EEPROM_Config + i)) & - (~(((ADV_EEPROM_BIOS_ENABLE | ADV_EEPROM_INTAB) >> 8) & - 0xFF))); - - /* - * Set the INTAB (bit 11) if the GPIO 0 input indicates - * the Function 1 interrupt line is wired to INTA. - * - * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: - * 1 - Function 1 interrupt line wired to INT A. - * 0 - Function 1 interrupt line wired to INT B. - * - * Note: Adapter boards always have Function 0 wired to INTA. - * Put all 5 GPIO bits in input mode and then read - * their input values. - */ - AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0); - if (AdvReadByteRegister(iop_base, IOPB_GPIO_DATA) & 0x01) - { - /* Function 1 interrupt wired to INTA; Set EEPROM bit. */ - *((uchar *) &eep_config + i) |= - ((ADV_EEPROM_INTAB >> 8) & 0xFF); - } - } - else - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_38C1600_EEPROM_Config + i); - } - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet38C1600EEPConfig(iop_base, &eep_config); - } + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->ppr_able = 0; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. - */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - if (tid == 0) - { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) - { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) - { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) - { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ASC_MAX_TID) - { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } + AdvSet38C1600EEPConfig(iop_base, &eep_config); + } - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->ppr_able = 0; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ASC_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ASC_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ASC_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination_se == 0) - { - termination = 0; /* auto termination for SE */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) - { - termination = 0; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) - { - termination = TERM_SE_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) - { - termination = TERM_SE; - } else - { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ASC_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ASC_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - if (eep_config.termination_lvd == 0) - { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) - { - asc_dvc->cfg->termination = termination; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) - { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) - { - asc_dvc->cfg->termination = - termination | TERM_LVD; - } else - { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - return warn_code; + return warn_code; } /* @@ -17049,45 +16733,42 @@ AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init +static ushort __init AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *) &ADVEEP_3550_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* @@ -17095,46 +16776,42 @@ AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init -AdvGet38C0800EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C0800_CONFIG *cfg_buf) +static ushort __init +AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *) &ADVEEP_38C0800_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* @@ -17142,81 +16819,74 @@ AdvGet38C0800EEPConfig(AdvPortAddr iop_base, * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init -AdvGet38C1600EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C1600_CONFIG *cfg_buf) +static ushort __init +AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort*) &ADVEEP_38C1600_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* * Read the EEPROM from specified location */ -STATIC ushort __init -AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) +static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) { - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_READ | eep_word_addr); - AdvWaitEEPCmd(iop_base); - return AdvReadWordRegister(iop_base, IOPW_EE_DATA); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_READ | eep_word_addr); + AdvWaitEEPCmd(iop_base); + return AdvReadWordRegister(iop_base, IOPW_EE_DATA); } /* * Wait for EEPROM command to complete */ -STATIC void __init -AdvWaitEEPCmd(AdvPortAddr iop_base) +static void __init AdvWaitEEPCmd(AdvPortAddr iop_base) { - int eep_delay_ms; - - for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) - { - if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) - { - break; - } - DvcSleepMilliSecond(1); - } - if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0) - { - ASC_ASSERT(0); - } - return; + int eep_delay_ms; + + for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { + if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & + ASC_EEP_CMD_DONE) { + break; + } + DvcSleepMilliSecond(1); + } + if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == + 0) { + ASC_ASSERT(0); + } + return; } /* @@ -17225,201 +16895,202 @@ AdvWaitEEPCmd(AdvPortAddr iop_base) void __init AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { - ushort *wbuf; - ushort addr, chksum; - ushort *charfields; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_3550_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort addr, chksum; + ushort *charfields; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ void __init -AdvSet38C0800EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C0800_CONFIG *cfg_buf) +AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_38C0800_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ void __init -AdvSet38C1600EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C1600_CONFIG *cfg_buf) +AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_38C1600_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* a_advlib.c */ @@ -17444,126 +17115,120 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure * host IC error. */ -STATIC int -AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, - ADV_SCSI_REQ_Q *scsiq) +static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - ulong last_int_level; - AdvPortAddr iop_base; - ADV_DCNT req_size; - ADV_PADDR req_paddr; - ADV_CARR_T *new_carrp; - - ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ - - /* - * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. - */ - if (scsiq->target_id > ADV_MAX_TID) - { - scsiq->host_status = QHSTA_M_INVALID_DEVICE; - scsiq->done_status = QD_WITH_ERROR; - return ADV_ERROR; - } - - iop_base = asc_dvc->iop_base; - - last_int_level = DvcEnterCritical(); - - /* - * Allocate a carrier ensuring at least one carrier always - * remains on the freelist and initialize fields. - */ - if ((new_carrp = asc_dvc->carr_freelist) == NULL) - { - DvcLeaveCritical(last_int_level); - return ADV_BUSY; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); - asc_dvc->carr_pending_cnt++; - - /* - * Set the carrier to be a stopper by setting 'next_vpa' - * to the stopper value. The current stopper will be changed - * below to point to the new stopper. - */ - new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Clear the ADV_SCSI_REQ_Q done flag. - */ - scsiq->a_flag &= ~ADV_SCSIQ_DONE; - - req_size = sizeof(ADV_SCSI_REQ_Q); - req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *) scsiq, - (ADV_SDCNT *) &req_size, ADV_IS_SCSIQ_FLAG); - - ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr); - ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); - - /* Wait for assertion before making little-endian */ - req_paddr = cpu_to_le32(req_paddr); - - /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ - scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); - scsiq->scsiq_rptr = req_paddr; + ulong last_int_level; + AdvPortAddr iop_base; + ADV_DCNT req_size; + ADV_PADDR req_paddr; + ADV_CARR_T *new_carrp; + + ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ + + /* + * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. + */ + if (scsiq->target_id > ADV_MAX_TID) { + scsiq->host_status = QHSTA_M_INVALID_DEVICE; + scsiq->done_status = QD_WITH_ERROR; + return ADV_ERROR; + } - scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); - /* - * Every ADV_CARR_T.carr_pa is byte swapped to little-endian - * order during initialization. - */ - scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; - - /* - * Use the current stopper to send the ADV_SCSI_REQ_Q command to - * the microcode. The newly allocated stopper will become the new - * stopper. - */ - asc_dvc->icq_sp->areq_vpa = req_paddr; + iop_base = asc_dvc->iop_base; - /* - * Set the 'next_vpa' pointer for the old stopper to be the - * physical address of the new stopper. The RISC can only - * follow physical addresses. - */ - asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; + last_int_level = DvcEnterCritical(); - /* - * Set the host adapter stopper pointer to point to the new carrier. - */ - asc_dvc->icq_sp = new_carrp; - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - /* - * Tickle the RISC to tell it to read its Command Queue Head pointer. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_a' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - /* - * Notify the RISC a carrier is ready by writing the physical - * address of the new carrier stopper to the COMMA register. - */ - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(new_carrp->carr_pa)); - } + /* + * Allocate a carrier ensuring at least one carrier always + * remains on the freelist and initialize fields. + */ + if ((new_carrp = asc_dvc->carr_freelist) == NULL) { + DvcLeaveCritical(last_int_level); + return ADV_BUSY; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); + asc_dvc->carr_pending_cnt++; + + /* + * Set the carrier to be a stopper by setting 'next_vpa' + * to the stopper value. The current stopper will be changed + * below to point to the new stopper. + */ + new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Clear the ADV_SCSI_REQ_Q done flag. + */ + scsiq->a_flag &= ~ADV_SCSIQ_DONE; + + req_size = sizeof(ADV_SCSI_REQ_Q); + req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq, + (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG); + + ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr); + ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); + + /* Wait for assertion before making little-endian */ + req_paddr = cpu_to_le32(req_paddr); + + /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ + scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); + scsiq->scsiq_rptr = req_paddr; + + scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); + /* + * Every ADV_CARR_T.carr_pa is byte swapped to little-endian + * order during initialization. + */ + scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; + + /* + * Use the current stopper to send the ADV_SCSI_REQ_Q command to + * the microcode. The newly allocated stopper will become the new + * stopper. + */ + asc_dvc->icq_sp->areq_vpa = req_paddr; + + /* + * Set the 'next_vpa' pointer for the old stopper to be the + * physical address of the new stopper. The RISC can only + * follow physical addresses. + */ + asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; + + /* + * Set the host adapter stopper pointer to point to the new carrier. + */ + asc_dvc->icq_sp = new_carrp; + + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + /* + * Tickle the RISC to tell it to read its Command Queue Head pointer. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_a' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_NOP); + } + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + /* + * Notify the RISC a carrier is ready by writing the physical + * address of the new carrier stopper to the COMMA register. + */ + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(new_carrp->carr_pa)); + } - DvcLeaveCritical(last_int_level); + DvcLeaveCritical(last_int_level); - return ADV_SUCCESS; + return ADV_SUCCESS; } /* @@ -17575,42 +17240,39 @@ AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC * may be hung which requires driver recovery. */ -STATIC int -AdvResetSB(ADV_DVC_VAR *asc_dvc) +static int AdvResetSB(ADV_DVC_VAR *asc_dvc) { - int status; - - /* - * Send the SCSI Bus Reset idle start idle command which asserts - * the SCSI Bus Reset signal. - */ - status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_START, 0L); - if (status != ADV_TRUE) - { - return status; - } - - /* - * Delay for the specified SCSI Bus Reset hold time. - * - * The hold time delay is done on the host because the RISC has no - * microsecond accurate timer. - */ - DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US); + int status; + + /* + * Send the SCSI Bus Reset idle start idle command which asserts + * the SCSI Bus Reset signal. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); + if (status != ADV_TRUE) { + return status; + } - /* - * Send the SCSI Bus Reset end idle command which de-asserts - * the SCSI Bus Reset signal and purges any pending requests. - */ - status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_END, 0L); - if (status != ADV_TRUE) - { - return status; - } + /* + * Delay for the specified SCSI Bus Reset hold time. + * + * The hold time delay is done on the host because the RISC has no + * microsecond accurate timer. + */ + DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US); + + /* + * Send the SCSI Bus Reset end idle command which de-asserts + * the SCSI Bus Reset signal and purges any pending requests. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); + if (status != ADV_TRUE) { + return status; + } - DvcSleepMilliSecond((ADV_DCNT) asc_dvc->scsi_reset_wait * 1000); + DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000); - return status; + return status; } /* @@ -17620,99 +17282,89 @@ AdvResetSB(ADV_DVC_VAR *asc_dvc) * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. */ -STATIC int -AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) +static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) { - int status; - ushort wdtr_able, sdtr_able, tagqng_able; - ushort ppr_able = 0; - uchar tid, max_cmd[ADV_MAX_TID + 1]; - AdvPortAddr iop_base; - ushort bios_sig; - - iop_base = asc_dvc->iop_base; - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - } - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * Force the AdvInitAsc3550/38C0800Driver() function to - * perform a SCSI Bus Reset by clearing the BIOS signature word. - * The initialization functions assumes a SCSI Bus Reset is not - * needed if the BIOS signature word is present. - */ - AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); - - /* - * Stop chip and reset it. - */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG); - - /* - * Reset Adv Library error code, if any, and try - * re-initializing the chip. - */ - asc_dvc->err_code = 0; - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - status = AdvInitAsc38C1600Driver(asc_dvc); - } - else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - status = AdvInitAsc38C0800Driver(asc_dvc); - } else - { - status = AdvInitAsc3550Driver(asc_dvc); - } + int status; + ushort wdtr_able, sdtr_able, tagqng_able; + ushort ppr_able = 0; + uchar tid, max_cmd[ADV_MAX_TID + 1]; + AdvPortAddr iop_base; + ushort bios_sig; + + iop_base = asc_dvc->iop_base; + + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + } + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* Translate initialization return value to status value. */ - if (status == 0) - { - status = ADV_TRUE; - } else - { - status = ADV_FALSE; - } + /* + * Force the AdvInitAsc3550/38C0800Driver() function to + * perform a SCSI Bus Reset by clearing the BIOS signature word. + * The initialization functions assumes a SCSI Bus Reset is not + * needed if the BIOS signature word is present. + */ + AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); + + /* + * Stop chip and reset it. + */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); + DvcSleepMilliSecond(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); + + /* + * Reset Adv Library error code, if any, and try + * re-initializing the chip. + */ + asc_dvc->err_code = 0; + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + status = AdvInitAsc38C1600Driver(asc_dvc); + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + status = AdvInitAsc38C0800Driver(asc_dvc); + } else { + status = AdvInitAsc3550Driver(asc_dvc); + } - /* - * Restore the BIOS signature word. - */ - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + /* Translate initialization return value to status value. */ + if (status == 0) { + status = ADV_TRUE; + } else { + status = ADV_FALSE; + } - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - } - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } + /* + * Restore the BIOS signature word. + */ + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + } + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - return status; + return status; } /* @@ -17734,158 +17386,151 @@ AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) * ADV_TRUE(1) - interrupt was pending * ADV_FALSE(0) - no interrupt was pending */ -STATIC int -AdvISR(ADV_DVC_VAR *asc_dvc) +static int AdvISR(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - uchar int_stat; - ushort target_bit; - ADV_CARR_T *free_carrp; - ADV_VADDR irq_next_vpa; - int flags; - ADV_SCSI_REQ_Q *scsiq; - - flags = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - - /* Reading the register clears the interrupt. */ - int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); - - if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | - ADV_INTR_STATUS_INTRC)) == 0) - { - DvcLeaveCritical(flags); - return ADV_FALSE; - } + AdvPortAddr iop_base; + uchar int_stat; + ushort target_bit; + ADV_CARR_T *free_carrp; + ADV_VADDR irq_next_vpa; + int flags; + ADV_SCSI_REQ_Q *scsiq; - /* - * Notify the driver of an asynchronous microcode condition by - * calling the ADV_DVC_VAR.async_callback function. The function - * is passed the microcode ASC_MC_INTRB_CODE byte value. - */ - if (int_stat & ADV_INTR_STATUS_INTRB) - { - uchar intrb_code; - - AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && - asc_dvc->carr_pending_cnt != 0) - { - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } - } - } - - if (asc_dvc->async_callback != 0) - { - (*asc_dvc->async_callback)(asc_dvc, intrb_code); - } - } + flags = DvcEnterCritical(); - /* - * Check if the IRQ stopper carrier contains a completed request. - */ - while (((irq_next_vpa = - le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) - { - /* - * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. - * The RISC will have set 'areq_vpa' to a virtual address. - * - * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr - * field to the carrier ADV_CARR_T.areq_vpa field. The conversion - * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' - * in AdvExeScsiQueue(). - */ - scsiq = (ADV_SCSI_REQ_Q *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); - - /* - * Request finished with good status and the queue was not - * DMAed to host memory by the firmware. Set all status fields - * to indicate good status. - */ - if ((irq_next_vpa & ASC_RQ_GOOD) != 0) - { - scsiq->done_status = QD_NO_ERROR; - scsiq->host_status = scsiq->scsi_status = 0; - scsiq->data_cnt = 0L; - } - - /* - * Advance the stopper pointer to the next carrier - * ignoring the lower four bits. Free the previous - * stopper carrier. - */ - free_carrp = asc_dvc->irq_sp; - asc_dvc->irq_sp = (ADV_CARR_T *) - ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); - - free_carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = free_carrp; - asc_dvc->carr_pending_cnt--; - - ASC_ASSERT(scsiq != NULL); - target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); - - /* - * Clear request microcode control flag. - */ - scsiq->cntl = 0; - - /* - * If the command that completed was a SCSI INQUIRY and - * LUN 0 was sent the command, then process the INQUIRY - * command information for the device. - * - * Note: If data returned were either VPD or CmdDt data, - * don't process the INQUIRY command information for - * the device, otherwise may erroneously set *_able bits. - */ - if (scsiq->done_status == QD_NO_ERROR && - scsiq->cdb[0] == INQUIRY && - scsiq->target_lun == 0 && - (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) - == ADV_INQ_RTN_STD_INQUIRY_DATA) - { - AdvInquiryHandling(asc_dvc, scsiq); - } - - /* - * Notify the driver of the completed request by passing - * the ADV_SCSI_REQ_Q pointer to its callback function. - */ - scsiq->a_flag |= ADV_SCSIQ_DONE; - (*asc_dvc->isr_callback)(asc_dvc, scsiq); - /* - * Note: After the driver callback function is called, 'scsiq' - * can no longer be referenced. - * - * Fall through and continue processing other completed - * requests... - */ - - /* - * Disable interrupts again in case the driver inadvertently - * enabled interrupts in its callback function. - * - * The DvcEnterCritical() return value is ignored, because - * the 'flags' saved when AdvISR() was first entered will be - * used to restore the interrupt flag on exit. - */ - (void) DvcEnterCritical(); - } - DvcLeaveCritical(flags); - return ADV_TRUE; + iop_base = asc_dvc->iop_base; + + /* Reading the register clears the interrupt. */ + int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); + + if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | + ADV_INTR_STATUS_INTRC)) == 0) { + DvcLeaveCritical(flags); + return ADV_FALSE; + } + + /* + * Notify the driver of an asynchronous microcode condition by + * calling the ADV_DVC_VAR.async_callback function. The function + * is passed the microcode ASC_MC_INTRB_CODE byte value. + */ + if (int_stat & ADV_INTR_STATUS_INTRB) { + uchar intrb_code; + + AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); + + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && + asc_dvc->carr_pending_cnt != 0) { + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + AdvWriteByteRegister(iop_base, + IOPB_TICKLE, + ADV_TICKLE_NOP); + } + } + } + + if (asc_dvc->async_callback != 0) { + (*asc_dvc->async_callback) (asc_dvc, intrb_code); + } + } + + /* + * Check if the IRQ stopper carrier contains a completed request. + */ + while (((irq_next_vpa = + le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { + /* + * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. + * The RISC will have set 'areq_vpa' to a virtual address. + * + * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr + * field to the carrier ADV_CARR_T.areq_vpa field. The conversion + * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' + * in AdvExeScsiQueue(). + */ + scsiq = (ADV_SCSI_REQ_Q *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); + + /* + * Request finished with good status and the queue was not + * DMAed to host memory by the firmware. Set all status fields + * to indicate good status. + */ + if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { + scsiq->done_status = QD_NO_ERROR; + scsiq->host_status = scsiq->scsi_status = 0; + scsiq->data_cnt = 0L; + } + + /* + * Advance the stopper pointer to the next carrier + * ignoring the lower four bits. Free the previous + * stopper carrier. + */ + free_carrp = asc_dvc->irq_sp; + asc_dvc->irq_sp = (ADV_CARR_T *) + ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); + + free_carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = free_carrp; + asc_dvc->carr_pending_cnt--; + + ASC_ASSERT(scsiq != NULL); + target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); + + /* + * Clear request microcode control flag. + */ + scsiq->cntl = 0; + + /* + * If the command that completed was a SCSI INQUIRY and + * LUN 0 was sent the command, then process the INQUIRY + * command information for the device. + * + * Note: If data returned were either VPD or CmdDt data, + * don't process the INQUIRY command information for + * the device, otherwise may erroneously set *_able bits. + */ + if (scsiq->done_status == QD_NO_ERROR && + scsiq->cdb[0] == INQUIRY && + scsiq->target_lun == 0 && + (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) + == ADV_INQ_RTN_STD_INQUIRY_DATA) { + AdvInquiryHandling(asc_dvc, scsiq); + } + + /* + * Notify the driver of the completed request by passing + * the ADV_SCSI_REQ_Q pointer to its callback function. + */ + scsiq->a_flag |= ADV_SCSIQ_DONE; + (*asc_dvc->isr_callback) (asc_dvc, scsiq); + /* + * Note: After the driver callback function is called, 'scsiq' + * can no longer be referenced. + * + * Fall through and continue processing other completed + * requests... + */ + + /* + * Disable interrupts again in case the driver inadvertently + * enabled interrupts in its callback function. + * + * The DvcEnterCritical() return value is ignored, because + * the 'flags' saved when AdvISR() was first entered will be + * used to restore the interrupt flag on exit. + */ + (void)DvcEnterCritical(); + } + DvcLeaveCritical(flags); + return ADV_TRUE; } /* @@ -17902,71 +17547,67 @@ AdvISR(ADV_DVC_VAR *asc_dvc) * ADV_FALSE - command failed * ADV_ERROR - command timed out */ -STATIC int +static int AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, - ushort idle_cmd, - ADV_DCNT idle_cmd_parameter) + ushort idle_cmd, ADV_DCNT idle_cmd_parameter) { - ulong last_int_level; - int result; - ADV_DCNT i, j; - AdvPortAddr iop_base; - - last_int_level = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - - /* - * Clear the idle command status which is set by the microcode - * to a non-zero value to indicate when the command is completed. - * The non-zero result is one of the IDLE_CMD_STATUS_* values - * defined in a_advlib.h. - */ - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort) 0); - - /* - * Write the idle command value after the idle command parameter - * has been written to avoid a race condition. If the order is not - * followed, the microcode may process the idle command before the - * parameters have been written to LRAM. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, - cpu_to_le32(idle_cmd_parameter)); - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); - - /* - * Tickle the RISC to tell it to process the idle command. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_b' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } + ulong last_int_level; + int result; + ADV_DCNT i, j; + AdvPortAddr iop_base; + + last_int_level = DvcEnterCritical(); + + iop_base = asc_dvc->iop_base; + + /* + * Clear the idle command status which is set by the microcode + * to a non-zero value to indicate when the command is completed. + * The non-zero result is one of the IDLE_CMD_STATUS_* values + * defined in a_advlib.h. + */ + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); + + /* + * Write the idle command value after the idle command parameter + * has been written to avoid a race condition. If the order is not + * followed, the microcode may process the idle command before the + * parameters have been written to LRAM. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, + cpu_to_le32(idle_cmd_parameter)); + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); + + /* + * Tickle the RISC to tell it to process the idle command. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_b' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); + } - /* Wait for up to 100 millisecond for the idle command to timeout. */ - for (i = 0; i < SCSI_WAIT_100_MSEC; i++) - { - /* Poll once each microsecond for command completion. */ - for (j = 0; j < SCSI_US_PER_MSEC; j++) - { - AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, result); - if (result != 0) - { - DvcLeaveCritical(last_int_level); - return result; - } - DvcDelayMicroSecond(asc_dvc, (ushort) 1); - } - } + /* Wait for up to 100 millisecond for the idle command to timeout. */ + for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { + /* Poll once each microsecond for command completion. */ + for (j = 0; j < SCSI_US_PER_MSEC; j++) { + AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, + result); + if (result != 0) { + DvcLeaveCritical(last_int_level); + return result; + } + DvcDelayMicroSecond(asc_dvc, (ushort)1); + } + } - ASC_ASSERT(0); /* The idle command should never timeout. */ - DvcLeaveCritical(last_int_level); - return ADV_ERROR; + ASC_ASSERT(0); /* The idle command should never timeout. */ + DvcLeaveCritical(last_int_level); + return ADV_ERROR; } /* @@ -17976,179 +17617,1415 @@ AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, * microcode operating variables that affect WDTR, SDTR, and Tag * Queuing. */ -STATIC void -AdvInquiryHandling( - ADV_DVC_VAR *asc_dvc, - ADV_SCSI_REQ_Q *scsiq) +static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - AdvPortAddr iop_base; - uchar tid; - ADV_SCSI_INQUIRY *inq; - ushort tidmask; - ushort cfg_word; + AdvPortAddr iop_base; + uchar tid; + ADV_SCSI_INQUIRY *inq; + ushort tidmask; + ushort cfg_word; + + /* + * AdvInquiryHandling() requires up to INQUIRY information Byte 7 + * to be available. + * + * If less than 8 bytes of INQUIRY information were requested or less + * than 8 bytes were transferred, then return. cdb[4] is the request + * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the + * microcode to the transfer residual count. + */ + + if (scsiq->cdb[4] < 8 || + (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) { + return; + } - /* - * AdvInquiryHandling() requires up to INQUIRY information Byte 7 - * to be available. - * - * If less than 8 bytes of INQUIRY information were requested or less - * than 8 bytes were transferred, then return. cdb[4] is the request - * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the - * microcode to the transfer residual count. - */ - - if (scsiq->cdb[4] < 8 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) - { - return; - } + iop_base = asc_dvc->iop_base; + tid = scsiq->target_id; - iop_base = asc_dvc->iop_base; - tid = scsiq->target_id; + inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; - inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; + /* + * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. + */ + if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) { + return; + } else { + /* + * INQUIRY Byte 7 Handling + * + * Use a device's INQUIRY byte 7 to determine whether it + * supports WDTR, SDTR, and Tag Queuing. If the feature + * is enabled in the EEPROM and the device supports the + * feature, then enable it in the microcode. + */ - /* - * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. - */ - if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) - { - return; - } else - { - /* - * INQUIRY Byte 7 Handling - * - * Use a device's INQUIRY byte 7 to determine whether it - * supports WDTR, SDTR, and Tag Queuing. If the feature - * is enabled in the EEPROM and the device supports the - * feature, then enable it in the microcode. - */ - - tidmask = ADV_TID_TO_TIDMASK(tid); - - /* - * Wide Transfers - * - * If the EEPROM enabled WDTR for the device and the device - * supports wide bus (16 bit) transfers, then turn on the - * device's 'wdtr_able' bit and write the new value to the - * microcode. - */ - if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) - { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - - /* - * Clear the microcode "SDTR negotiation" and "WDTR - * negotiation" done indicators for the target to cause - * it to negotiate with the new setting set above. - * WDTR when accepted causes the target to enter - * asynchronous mode, so SDTR must be negotiated. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); - } - } - - /* - * Synchronous Transfers - * - * If the EEPROM enabled SDTR for the device and the device - * supports synchronous transfers, then turn on the device's - * 'sdtr_able' bit. Write the new value to the microcode. - */ - if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) - { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); - - /* - * Clear the microcode "SDTR negotiation" done indicator - * for the target to cause it to negotiate with the new - * setting set above. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - } - } - /* - * If the Inquiry data included enough space for the SPI-3 - * Clocking field, then check if DT mode is supported. - */ - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 && - (scsiq->cdb[4] >= 57 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) - { - /* - * PPR (Parallel Protocol Request) Capable - * - * If the device supports DT mode, then it must be PPR capable. - * The PPR message will be used in place of the SDTR and WDTR - * messages to negotiate synchronous speed and offset, transfer - * width, and protocol options. - */ - if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) - { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, asc_dvc->ppr_able); - asc_dvc->ppr_able |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, asc_dvc->ppr_able); - } - } - - /* - * If the EEPROM enabled Tag Queuing for the device and the - * device supports Tag Queueing, then turn on the device's - * 'tagqng_enable' bit in the microcode and set the microcode - * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' - * value. - * - * Tag Queuing is disabled for the BIOS which runs in polled - * mode and would see no benefit from Tag Queuing. Also by - * disabling Tag Queuing in the BIOS devices with Tag Queuing - * bugs will at least work with the BIOS. - */ - if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); - - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - asc_dvc->max_dvc_qng); - } - } + tidmask = ADV_TID_TO_TIDMASK(tid); + + /* + * Wide Transfers + * + * If the EEPROM enabled WDTR for the device and the device + * supports wide bus (16 bit) transfers, then turn on the + * device's 'wdtr_able' bit and write the new value to the + * microcode. + */ + if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) { + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) == 0) { + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + cfg_word); + + /* + * Clear the microcode "SDTR negotiation" and "WDTR + * negotiation" done indicators for the target to cause + * it to negotiate with the new setting set above. + * WDTR when accepted causes the target to enter + * asynchronous mode, so SDTR must be negotiated. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, + cfg_word); + } + } + + /* + * Synchronous Transfers + * + * If the EEPROM enabled SDTR for the device and the device + * supports synchronous transfers, then turn on the device's + * 'sdtr_able' bit. Write the new value to the microcode. + */ + if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) { + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) == 0) { + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + cfg_word); + + /* + * Clear the microcode "SDTR negotiation" done indicator + * for the target to cause it to negotiate with the new + * setting set above. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + } + } + /* + * If the Inquiry data included enough space for the SPI-3 + * Clocking field, then check if DT mode is supported. + */ + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 && + (scsiq->cdb[4] >= 57 || + (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) { + /* + * PPR (Parallel Protocol Request) Capable + * + * If the device supports DT mode, then it must be PPR capable. + * The PPR message will be used in place of the SDTR and WDTR + * messages to negotiate synchronous speed and offset, transfer + * width, and protocol options. + */ + if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) { + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, + asc_dvc->ppr_able); + asc_dvc->ppr_able |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, + asc_dvc->ppr_able); + } + } + + /* + * If the EEPROM enabled Tag Queuing for the device and the + * device supports Tag Queueing, then turn on the device's + * 'tagqng_enable' bit in the microcode and set the microcode + * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' + * value. + * + * Tag Queuing is disabled for the BIOS which runs in polled + * mode and would see no benefit from Tag Queuing. Also by + * disabling Tag Queuing in the BIOS devices with Tag Queuing + * bugs will at least work with the BIOS. + */ + if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) { + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + cfg_word); + + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + asc_dvc->max_dvc_qng); + } + } } + MODULE_LICENSE("Dual BSD/GPL"); +static struct Scsi_Host *__devinit +advansys_board_found(int iop, struct device *dev, int bus_type) +{ + struct Scsi_Host *shost; + struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp = NULL; + ADV_DVC_VAR *adv_dvc_varp = NULL; + adv_sgblk_t *sgp = NULL; + int share_irq = FALSE; + int iolen = 0; + ADV_PADDR pci_memory_address; + int warn_code, err_code; + int ret; + + /* + * Adapter found. + * + * Register the adapter, get its configuration, and + * initialize it. + */ + ASC_DBG(2, "advansys_board_found: scsi_register()\n"); + shost = scsi_register(&driver_template, sizeof(asc_board_t)); + + if (!shost) + return NULL; + + /* Save a pointer to the Scsi_Host of each board found. */ + asc_host[asc_board_count++] = shost; + + /* Initialize private per board data */ + boardp = ASC_BOARDP(shost); + memset(boardp, 0, sizeof(asc_board_t)); + boardp->id = asc_board_count - 1; + + /* Initialize spinlock. */ + spin_lock_init(&boardp->lock); + + /* + * Handle both narrow and wide boards. + * + * If a Wide board was detected, set the board structure + * wide board flag. Set-up the board structure based on + * the board type. + */ +#ifdef CONFIG_PCI + if (bus_type == ASC_IS_PCI && + (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW || + pdev->device == PCI_DEVICE_ID_38C0800_REV1 || + pdev->device == PCI_DEVICE_ID_38C1600_REV1)) { + boardp->flags |= ASC_IS_WIDE_BOARD; + } +#endif /* CONFIG_PCI */ + + if (ASC_NARROW_BOARD(boardp)) { + ASC_DBG(1, "advansys_board_found: narrow board\n"); + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + asc_dvc_varp->bus_type = bus_type; + asc_dvc_varp->drv_ptr = boardp; + asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; + asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; + asc_dvc_varp->iop_base = iop; + asc_dvc_varp->isr_callback = asc_isr_callback; + } else { + ASC_DBG(1, "advansys_board_found: wide board\n"); + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + adv_dvc_varp->drv_ptr = boardp; + adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; + adv_dvc_varp->isr_callback = adv_isr_callback; + adv_dvc_varp->async_callback = adv_async_callback; +#ifdef CONFIG_PCI + if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) { + ASC_DBG(1, "advansys_board_found: ASC-3550\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; + } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) { + ASC_DBG(1, "advansys_board_found: ASC-38C0800\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; + } else { + ASC_DBG(1, "advansys_board_found: ASC-38C1600\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; + } +#endif /* CONFIG_PCI */ + + /* + * Map the board's registers into virtual memory for + * PCI slave access. Only memory accesses are used to + * access the board's registers. + * + * Note: The PCI register base address is not always + * page aligned, but the address passed to ioremap() + * must be page aligned. It is guaranteed that the + * PCI register base address will not cross a page + * boundary. + */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + iolen = ADV_3550_IOLEN; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + iolen = ADV_38C0800_IOLEN; + } else { + iolen = ADV_38C1600_IOLEN; + } +#ifdef CONFIG_PCI + pci_memory_address = pci_resource_start(pdev, 1); + ASC_DBG1(1, + "advansys_board_found: pci_memory_address: 0x%lx\n", + (ulong)pci_memory_address); + if ((boardp->ioremap_addr = + ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) { + ASC_PRINT3 + ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n", + boardp->id, pci_memory_address, iolen); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + ASC_DBG1(1, + "advansys_board_found: ioremap_addr: 0x%lx\n", + (ulong)boardp->ioremap_addr); + adv_dvc_varp->iop_base = (AdvPortAddr) + (boardp->ioremap_addr + + (pci_memory_address - (pci_memory_address & PAGE_MASK))); + ASC_DBG1(1, + "advansys_board_found: iop_base: 0x%lx\n", + adv_dvc_varp->iop_base); +#endif /* CONFIG_PCI */ + + /* + * Even though it isn't used to access wide boards, other + * than for the debug line below, save I/O Port address so + * that it can be reported. + */ + boardp->ioport = iop; + + ASC_DBG2(1, + "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", + (ushort)inp(iop + 1), (ushort)inpw(iop)); + } + +#ifdef CONFIG_PROC_FS + /* + * Allocate buffer for printing information from + * /proc/scsi/advansys/[0...]. + */ + if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { + ASC_PRINT3 + ("advansys_board_found: board %d: kmalloc(%d, %d) returned NULL\n", + boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } +#endif /* CONFIG_PROC_FS */ + + if (ASC_NARROW_BOARD(boardp)) { + asc_dvc_varp->cfg->dev = dev; + /* + * Set the board bus type and PCI IRQ before + * calling AscInitGetConfig(). + */ + switch (asc_dvc_varp->bus_type) { +#ifdef CONFIG_ISA + case ASC_IS_ISA: + shost->unchecked_isa_dma = TRUE; + share_irq = FALSE; + break; + case ASC_IS_VL: + shost->unchecked_isa_dma = FALSE; + share_irq = FALSE; + break; + case ASC_IS_EISA: + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; + break; +#endif /* CONFIG_ISA */ +#ifdef CONFIG_PCI + case ASC_IS_PCI: + shost->irq = asc_dvc_varp->irq_no = pdev->irq; + asc_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; + break; +#endif /* CONFIG_PCI */ + default: + ASC_PRINT2 + ("advansys_board_found: board %d: unknown adapter type: %d\n", + boardp->id, asc_dvc_varp->bus_type); + shost->unchecked_isa_dma = TRUE; + share_irq = FALSE; + break; + } + } else { + adv_dvc_varp->cfg->dev = dev; + /* + * For Wide boards set PCI information before calling + * AdvInitGetConfig(). + */ +#ifdef CONFIG_PCI + shost->irq = adv_dvc_varp->irq_no = pdev->irq; + adv_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; +#endif /* CONFIG_PCI */ + } + + /* + * Read the board configuration. + */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * NOTE: AscInitGetConfig() may change the board's + * bus_type value. The bus_type value should no + * longer be used. If the bus_type field must be + * referenced only use the bit-wise AND operator "&". + */ + ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n"); + switch (ret = AscInitGetConfig(asc_dvc_varp)) { + case 0: /* No error */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_PRINT1 + ("AscInitGetConfig: board %d: I/O port address modified\n", + boardp->id); + break; + case ASC_WARN_AUTO_CONFIG: + ASC_PRINT1 + ("AscInitGetConfig: board %d: I/O port increment switch enabled\n", + boardp->id); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_PRINT1 + ("AscInitGetConfig: board %d: EEPROM checksum error\n", + boardp->id); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_PRINT1 + ("AscInitGetConfig: board %d: IRQ modified\n", + boardp->id); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_PRINT1 + ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", + boardp->id); + break; + default: + ASC_PRINT2 + ("AscInitGetConfig: board %d: unknown warning: 0x%x\n", + boardp->id, ret); + break; + } + if ((err_code = asc_dvc_varp->err_code) != 0) { + ASC_PRINT3 + ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, asc_dvc_varp->err_code); + } + } else { + ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n"); + if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { + ASC_PRINT2 + ("AdvInitGetConfig: board %d: warning: 0x%x\n", + boardp->id, ret); + } + if ((err_code = adv_dvc_varp->err_code) != 0) { + ASC_PRINT2 + ("AdvInitGetConfig: board %d error: err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + } + } + + if (err_code != 0) { +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Save the EEPROM configuration so that it can be displayed + * from /proc/scsi/advansys/[0...]. + */ + if (ASC_NARROW_BOARD(boardp)) { + + ASCEEP_CONFIG *ep; + + /* + * Set the adapter's target id bit in the 'init_tidmask' field. + */ + boardp->init_tidmask |= + ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id); + + /* + * Save EEPROM settings for the board. + */ + ep = &boardp->eep_config.asc_eep; + + ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; + ep->disc_enable = asc_dvc_varp->cfg->disc_enable; + ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; + ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed); + ep->start_motor = asc_dvc_varp->start_motor; + ep->cntl = asc_dvc_varp->dvc_cntl; + ep->no_scam = asc_dvc_varp->no_scam; + ep->max_total_qng = asc_dvc_varp->max_total_qng; + ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id); + /* 'max_tag_qng' is set to the same value for every device. */ + ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0]; + ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0]; + ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1]; + ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2]; + ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; + ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; + ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; + + /* + * Modify board configuration. + */ + ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n"); + switch (ret = AscInitSetConfig(asc_dvc_varp)) { + case 0: /* No error. */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_PRINT1 + ("AscInitSetConfig: board %d: I/O port address modified\n", + boardp->id); + break; + case ASC_WARN_AUTO_CONFIG: + ASC_PRINT1 + ("AscInitSetConfig: board %d: I/O port increment switch enabled\n", + boardp->id); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_PRINT1 + ("AscInitSetConfig: board %d: EEPROM checksum error\n", + boardp->id); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_PRINT1 + ("AscInitSetConfig: board %d: IRQ modified\n", + boardp->id); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_PRINT1 + ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n", + boardp->id); + break; + default: + ASC_PRINT2 + ("AscInitSetConfig: board %d: unknown warning: 0x%x\n", + boardp->id, ret); + break; + } + if (asc_dvc_varp->err_code != 0) { + ASC_PRINT3 + ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, asc_dvc_varp->err_code); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Finish initializing the 'Scsi_Host' structure. + */ + /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ + if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { + shost->irq = asc_dvc_varp->irq_no; + } + } else { + ADVEEP_3550_CONFIG *ep_3550; + ADVEEP_38C0800_CONFIG *ep_38C0800; + ADVEEP_38C1600_CONFIG *ep_38C1600; + + /* + * Save Wide EEP Configuration Information. + */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ep_3550 = &boardp->eep_config.adv_3550_eep; + + ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; + ep_3550->max_host_qng = adv_dvc_varp->max_host_qng; + ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_3550->termination = adv_dvc_varp->cfg->termination; + ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable; + ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_3550->wdtr_able = adv_dvc_varp->wdtr_able; + ep_3550->sdtr_able = adv_dvc_varp->sdtr_able; + ep_3550->ultra_able = adv_dvc_varp->ultra_able; + ep_3550->tagqng_able = adv_dvc_varp->tagqng_able; + ep_3550->start_motor = adv_dvc_varp->start_motor; + ep_3550->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_3550->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_3550->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_3550->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; + + ep_38C0800->adapter_scsi_id = + adv_dvc_varp->chip_scsi_id; + ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng; + ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_38C0800->termination_lvd = + adv_dvc_varp->cfg->termination; + ep_38C0800->disc_enable = + adv_dvc_varp->cfg->disc_enable; + ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able; + ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; + ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; + ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; + ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; + ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C0800->start_motor = adv_dvc_varp->start_motor; + ep_38C0800->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_38C0800->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_38C0800->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_38C0800->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } else { + ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; + + ep_38C1600->adapter_scsi_id = + adv_dvc_varp->chip_scsi_id; + ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng; + ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_38C1600->termination_lvd = + adv_dvc_varp->cfg->termination; + ep_38C1600->disc_enable = + adv_dvc_varp->cfg->disc_enable; + ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able; + ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; + ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; + ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; + ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; + ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C1600->start_motor = adv_dvc_varp->start_motor; + ep_38C1600->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_38C1600->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_38C1600->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_38C1600->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } + + /* + * Set the adapter's target id bit in the 'init_tidmask' field. + */ + boardp->init_tidmask |= + ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); + + /* + * Finish initializing the 'Scsi_Host' structure. + */ + shost->irq = adv_dvc_varp->irq_no; + } + + /* + * Channels are numbered beginning with 0. For AdvanSys one host + * structure supports one channel. Multi-channel boards have a + * separate host structure for each channel. + */ + shost->max_channel = 0; + if (ASC_NARROW_BOARD(boardp)) { + shost->max_id = ASC_MAX_TID + 1; + shost->max_lun = ASC_MAX_LUN + 1; + + shost->io_port = asc_dvc_varp->iop_base; + boardp->asc_n_io_port = ASC_IOADR_GAP; + shost->this_id = asc_dvc_varp->cfg->chip_scsi_id; + + /* Set maximum number of queues the adapter can handle. */ + shost->can_queue = asc_dvc_varp->max_total_qng; + } else { + shost->max_id = ADV_MAX_TID + 1; + shost->max_lun = ADV_MAX_LUN + 1; + + /* + * Save the I/O Port address and length even though + * I/O ports are not used to access Wide boards. + * Instead the Wide boards are accessed with + * PCI Memory Mapped I/O. + */ + shost->io_port = iop; + boardp->asc_n_io_port = iolen; + + shost->this_id = adv_dvc_varp->chip_scsi_id; + + /* Set maximum number of queues the adapter can handle. */ + shost->can_queue = adv_dvc_varp->max_host_qng; + } + + /* + * 'n_io_port' currently is one byte. + * + * Set a value to 'n_io_port', but never referenced it because + * it may be truncated. + */ + shost->n_io_port = boardp->asc_n_io_port <= 255 ? + boardp->asc_n_io_port : 255; + + /* + * Following v1.3.89, 'cmd_per_lun' is no longer needed + * and should be set to zero. + * + * But because of a bug introduced in v1.3.89 if the driver is + * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level + * SCSI function 'allocate_device' will panic. To allow the driver + * to work as a module in these kernels set 'cmd_per_lun' to 1. + * + * Note: This is wrong. cmd_per_lun should be set to the depth + * you want on untagged devices always. + #ifdef MODULE + */ + shost->cmd_per_lun = 1; +/* #else + shost->cmd_per_lun = 0; +#endif */ + + /* + * Set the maximum number of scatter-gather elements the + * adapter can handle. + */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * Allow two commands with 'sg_tablesize' scatter-gather + * elements to be executed simultaneously. This value is + * the theoretical hardware limit. It may be decreased + * below. + */ + shost->sg_tablesize = + (((asc_dvc_varp->max_total_qng - 2) / 2) * + ASC_SG_LIST_PER_Q) + 1; + } else { + shost->sg_tablesize = ADV_MAX_SG_LIST; + } + + /* + * The value of 'sg_tablesize' can not exceed the SCSI + * mid-level driver definition of SG_ALL. SG_ALL also + * must not be exceeded, because it is used to define the + * size of the scatter-gather table in 'struct asc_sg_head'. + */ + if (shost->sg_tablesize > SG_ALL) { + shost->sg_tablesize = SG_ALL; + } + + ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize); + + /* BIOS start address. */ + if (ASC_NARROW_BOARD(boardp)) { + shost->base = ((ulong) + AscGetChipBiosAddress(asc_dvc_varp-> + iop_base, + asc_dvc_varp->bus_type)); + } else { + /* + * Fill-in BIOS board variables. The Wide BIOS saves + * information in LRAM that is used by the driver. + */ + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_SIGNATURE, boardp->bios_signature); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_VERSION, boardp->bios_version); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_CODESEG, boardp->bios_codeseg); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_CODELEN, boardp->bios_codelen); + + ASC_DBG2(1, + "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n", + boardp->bios_signature, boardp->bios_version); + + ASC_DBG2(1, + "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n", + boardp->bios_codeseg, boardp->bios_codelen); + + /* + * If the BIOS saved a valid signature, then fill in + * the BIOS code segment base address. + */ + if (boardp->bios_signature == 0x55AA) { + /* + * Convert x86 realmode code segment to a linear + * address by shifting left 4. + */ + shost->base = ((ulong)boardp->bios_codeseg << 4); + } else { + shost->base = 0; + } + } + + /* + * Register Board Resources - I/O Port, DMA, IRQ + */ + + /* + * Register I/O port range. + * + * For Wide boards the I/O ports are not used to access + * the board, but request the region anyway. + * + * 'shost->n_io_port' is not referenced, because it may be truncated. + */ + ASC_DBG2(2, + "advansys_board_found: request_region port 0x%lx, len 0x%x\n", + (ulong)shost->io_port, boardp->asc_n_io_port); + if (request_region(shost->io_port, boardp->asc_n_io_port, + "advansys") == NULL) { + ASC_PRINT3 + ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n", + boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* Register DMA Channel for Narrow boards. */ + shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ +#ifdef CONFIG_ISA + if (ASC_NARROW_BOARD(boardp)) { + /* Register DMA channel for ISA bus. */ + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; + if ((ret = + request_dma(shost->dma_channel, "advansys")) != 0) { + ASC_PRINT3 + ("advansys_board_found: board %d: request_dma() %d failed %d\n", + boardp->id, shost->dma_channel, ret); + release_region(shost->io_port, + boardp->asc_n_io_port); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + AscEnableIsaDma(shost->dma_channel); + } + } +#endif /* CONFIG_ISA */ + + /* Register IRQ Number. */ + ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq); + /* + * If request_irq() fails with the IRQF_DISABLED flag set, + * then try again without the IRQF_DISABLED flag set. This + * allows IRQ sharing to work even with other drivers that + * do not set the IRQF_DISABLED flag. + * + * If IRQF_DISABLED is not set, then interrupts are enabled + * before the driver interrupt function is called. + */ + if (((ret = request_irq(shost->irq, advansys_interrupt, + IRQF_DISABLED | (share_irq == + TRUE ? + IRQF_SHARED : + 0), "advansys", boardp)) != 0) + && + ((ret = + request_irq(shost->irq, advansys_interrupt, + (share_irq == TRUE ? IRQF_SHARED : 0), + "advansys", boardp)) != 0)) { + if (ret == -EBUSY) { + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n", + boardp->id, shost->irq); + } else if (ret == -EINVAL) { + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n", + boardp->id, shost->irq); + } else { + ASC_PRINT3 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n", + boardp->id, shost->irq, ret); + } + release_region(shost->io_port, boardp->asc_n_io_port); + iounmap(boardp->ioremap_addr); + if (shost->dma_channel != NO_ISA_DMA) { + free_dma(shost->dma_channel); + } +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Initialize board RISC chip and enable interrupts. + */ + if (ASC_NARROW_BOARD(boardp)) { + ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n"); + warn_code = AscInitAsc1000Driver(asc_dvc_varp); + err_code = asc_dvc_varp->err_code; + + if (warn_code || err_code) { + ASC_PRINT4 + ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, warn_code, err_code); + } + } else { + ADV_CARR_T *carrp; + int req_cnt = 0; + adv_req_t *reqp = NULL; + int sg_cnt = 0; + + /* + * Allocate buffer carrier structures. The total size + * is about 4 KB, so allocate all at once. + */ + carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC); + ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", (ulong)carrp); + + if (carrp == NULL) { + goto kmalloc_error; + } + + /* + * Allocate up to 'max_host_qng' request structures for + * the Wide board. The total size is about 16 KB, so + * allocate all at once. If the allocation fails decrement + * and try again. + */ + for (req_cnt = adv_dvc_varp->max_host_qng; + req_cnt > 0; req_cnt--) { + + reqp = (adv_req_t *) + kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); + + ASC_DBG3(1, + "advansys_board_found: reqp 0x%lx, req_cnt %d, bytes %lu\n", + (ulong)reqp, req_cnt, + (ulong)sizeof(adv_req_t) * req_cnt); + + if (reqp != NULL) { + break; + } + } + if (reqp == NULL) { + goto kmalloc_error; + } + + /* + * Allocate up to ADV_TOT_SG_BLOCK request structures for + * the Wide board. Each structure is about 136 bytes. + */ + boardp->adv_sgblkp = NULL; + for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { + + sgp = (adv_sgblk_t *) + kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); + + if (sgp == NULL) { + break; + } + + sgp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgp; + + } + ASC_DBG3(1, + "advansys_board_found: sg_cnt %d * %u = %u bytes\n", + sg_cnt, sizeof(adv_sgblk_t), + (unsigned)(sizeof(adv_sgblk_t) * sg_cnt)); + + /* + * If no request structures or scatter-gather structures could + * be allocated, then return an error. Otherwise continue with + * initialization. + */ + kmalloc_error: + if (carrp == NULL) { + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() carrier buffer.\n", + boardp->id); + err_code = ADV_ERROR; + } else if (reqp == NULL) { + kfree(carrp); + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() adv_req_t buffer.\n", + boardp->id); + err_code = ADV_ERROR; + } else if (boardp->adv_sgblkp == NULL) { + kfree(carrp); + kfree(reqp); + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n", + boardp->id); + err_code = ADV_ERROR; + } else { + + /* Save carrier buffer pointer. */ + boardp->orig_carrp = carrp; + + /* + * Save original pointer for kfree() in case the + * driver is built as a module and can be unloaded. + */ + boardp->orig_reqp = reqp; + + adv_dvc_varp->carrier_buf = carrp; + + /* + * Point 'adv_reqp' to the request structures and + * link them together. + */ + req_cnt--; + reqp[req_cnt].next_reqp = NULL; + for (; req_cnt > 0; req_cnt--) { + reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; + } + boardp->adv_reqp = &reqp[0]; + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc3550Driver()\n"); + warn_code = AdvInitAsc3550Driver(adv_dvc_varp); + } else if (adv_dvc_varp->chip_type == + ADV_CHIP_ASC38C0800) { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc38C0800Driver()\n"); + warn_code = + AdvInitAsc38C0800Driver(adv_dvc_varp); + } else { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc38C1600Driver()\n"); + warn_code = + AdvInitAsc38C1600Driver(adv_dvc_varp); + } + err_code = adv_dvc_varp->err_code; + + if (warn_code || err_code) { + ASC_PRINT3 + ("advansys_board_found: board %d error: warn 0x%x, error 0x%x\n", + boardp->id, warn_code, err_code); + } + } + } + + if (err_code != 0) { + release_region(shost->io_port, boardp->asc_n_io_port); + if (ASC_WIDE_BOARD(boardp)) { + iounmap(boardp->ioremap_addr); + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; + if (boardp->orig_reqp) { + kfree(boardp->orig_reqp); + boardp->orig_reqp = boardp->adv_reqp = NULL; + } + while ((sgp = boardp->adv_sgblkp) != NULL) { + boardp->adv_sgblkp = sgp->next_sgblkp; + kfree(sgp); + } + } + if (shost->dma_channel != NO_ISA_DMA) { + free_dma(shost->dma_channel); + } +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + free_irq(shost->irq, boardp); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + ASC_DBG_PRT_SCSI_HOST(2, shost); + + return shost; +} + +/* + * advansys_detect() + * + * Detect function for AdvanSys adapters. + * + * Argument is a pointer to the host driver's scsi_hosts entry. + * + * Return number of adapters found. + * + * Note: Because this function is called during system initialization + * it must not call SCSI mid-level functions including scsi_malloc() + * and scsi_free(). + */ +static int __init advansys_detect(struct scsi_host_template *tpnt) +{ + static int detect_called = ASC_FALSE; + int iop; + int bus; + int ioport = 0; + struct device *dev = NULL; +#ifdef CONFIG_PCI + int pci_init_search = 0; + struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; + int pci_card_cnt_max = 0; + int pci_card_cnt = 0; + struct pci_dev *pdev = NULL; + int pci_device_id_cnt = 0; + unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { + PCI_DEVICE_ID_ASP_1200A, + PCI_DEVICE_ID_ASP_ABP940, + PCI_DEVICE_ID_ASP_ABP940U, + PCI_DEVICE_ID_ASP_ABP940UW, + PCI_DEVICE_ID_38C0800_REV1, + PCI_DEVICE_ID_38C1600_REV1 + }; +#endif /* CONFIG_PCI */ + + if (detect_called == ASC_FALSE) { + detect_called = ASC_TRUE; + } else { + printk + ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); + return 0; + } + + ASC_DBG(1, "advansys_detect: begin\n"); + + asc_board_count = 0; + + /* + * If I/O port probing has been modified, then verify and + * clean-up the 'asc_ioport' list. + */ + if (asc_iopflag == ASC_TRUE) { + for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { + ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n", + ioport, asc_ioport[ioport]); + if (asc_ioport[ioport] != 0) { + for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; + iop++) { + if (_asc_def_iop_base[iop] == + asc_ioport[ioport]) { + break; + } + } + if (iop == ASC_IOADR_TABLE_MAX_IX) { + printk + ("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", + asc_ioport[ioport]); + asc_ioport[ioport] = 0; + } + } + } + ioport = 0; + } + + for (bus = 0; bus < ASC_NUM_BUS; bus++) { + + ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", + bus, asc_bus_name[bus]); + iop = 0; + + while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { + + ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", + asc_board_count); + + switch (asc_bus[bus]) { + case ASC_IS_ISA: + case ASC_IS_VL: +#ifdef CONFIG_ISA + if (asc_iopflag == ASC_FALSE) { + iop = + AscSearchIOPortAddr(iop, + asc_bus[bus]); + } else { + /* + * ISA and VL I/O port scanning has either been + * eliminated or limited to selected ports on + * the LILO command line, /etc/lilo.conf, or + * by setting variables when the module was loaded. + */ + ASC_DBG(1, + "advansys_detect: I/O port scanning modified\n"); + ioport_try_again: + iop = 0; + for (; ioport < ASC_NUM_IOPORT_PROBE; + ioport++) { + if ((iop = + asc_ioport[ioport]) != 0) { + break; + } + } + if (iop) { + ASC_DBG1(1, + "advansys_detect: probing I/O port 0x%x...\n", + iop); + if (!request_region + (iop, ASC_IOADR_GAP, + "advansys")) { + printk + ("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", + iop); + /* Don't try this I/O port twice. */ + asc_ioport[ioport] = 0; + goto ioport_try_again; + } else if (AscFindSignature(iop) + == ASC_FALSE) { + printk + ("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", + iop); + /* Don't try this I/O port twice. */ + release_region(iop, + ASC_IOADR_GAP); + asc_ioport[ioport] = 0; + goto ioport_try_again; + } else { + /* + * If this isn't an ISA board, then it must be + * a VL board. If currently looking an ISA + * board is being looked for then try for + * another ISA board in 'asc_ioport'. + */ + if (asc_bus[bus] == + ASC_IS_ISA + && + (AscGetChipVersion + (iop, + ASC_IS_ISA) & + ASC_CHIP_VER_ISA_BIT) + == 0) { + /* + * Don't clear 'asc_ioport[ioport]'. Try + * this board again for VL. Increment + * 'ioport' past this board. + */ + ioport++; + release_region + (iop, + ASC_IOADR_GAP); + goto ioport_try_again; + } + } + /* + * This board appears good, don't try the I/O port + * again by clearing its value. Increment 'ioport' + * for the next iteration. + */ + asc_ioport[ioport++] = 0; + } + } +#endif /* CONFIG_ISA */ + break; + + case ASC_IS_EISA: +#ifdef CONFIG_ISA + iop = AscSearchIOPortAddr(iop, asc_bus[bus]); +#endif /* CONFIG_ISA */ + break; + + case ASC_IS_PCI: +#ifdef CONFIG_PCI + if (pci_init_search == 0) { + int i, j; + + pci_init_search = 1; + + /* Find all PCI cards. */ + while (pci_device_id_cnt < + ASC_PCI_DEVICE_ID_CNT) { + if ((pdev = + pci_find_device + (PCI_VENDOR_ID_ASP, + pci_device_id + [pci_device_id_cnt], + pdev)) == NULL) { + pci_device_id_cnt++; + } else { + if (pci_enable_device + (pdev) == 0) { + pci_devicep + [pci_card_cnt_max++] + = pdev; + } + } + } + + /* + * Sort PCI cards in ascending order by PCI Bus, Slot, + * and Device Number. + */ + for (i = 0; i < pci_card_cnt_max - 1; + i++) { + for (j = i + 1; + j < pci_card_cnt_max; + j++) { + if ((pci_devicep[j]-> + bus->number < + pci_devicep[i]-> + bus->number) + || + ((pci_devicep[j]-> + bus->number == + pci_devicep[i]-> + bus->number) + && + (pci_devicep[j]-> + devfn < + pci_devicep[i]-> + devfn))) { + pdev = + pci_devicep + [i]; + pci_devicep[i] = + pci_devicep + [j]; + pci_devicep[j] = + pdev; + } + } + } + + pci_card_cnt = 0; + } else { + pci_card_cnt++; + } + + if (pci_card_cnt == pci_card_cnt_max) { + iop = 0; + } else { + pdev = pci_devicep[pci_card_cnt]; + + ASC_DBG2(2, + "advansys_detect: devfn %d, bus number %d\n", + pdev->devfn, + pdev->bus->number); + iop = pci_resource_start(pdev, 0); + ASC_DBG2(1, + "advansys_detect: vendorID %X, deviceID %X\n", + pdev->vendor, + pdev->device); + ASC_DBG2(2, + "advansys_detect: iop %X, irqLine %d\n", + iop, pdev->irq); + } + if (pdev) + dev = &pdev->dev; + +#endif /* CONFIG_PCI */ + break; + + default: + ASC_PRINT1 + ("advansys_detect: unknown bus type: %d\n", + asc_bus[bus]); + break; + } + ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); + + /* + * Adapter not found, try next bus type. + */ + if (iop == 0) { + break; + } + + advansys_board_found(iop, dev, asc_bus[bus]); + } + } + + ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", + asc_board_count); + return asc_board_count; +} + +/* + * advansys_release() + * + * Release resources allocated for a single AdvanSys adapter. + */ +static int advansys_release(struct Scsi_Host *shost) +{ + asc_board_t *boardp; + + ASC_DBG(1, "advansys_release: begin\n"); + boardp = ASC_BOARDP(shost); + free_irq(shost->irq, boardp); + if (shost->dma_channel != NO_ISA_DMA) { + ASC_DBG(1, "advansys_release: free_dma()\n"); + free_dma(shost->dma_channel); + } + release_region(shost->io_port, boardp->asc_n_io_port); + if (ASC_WIDE_BOARD(boardp)) { + adv_sgblk_t *sgp = NULL; + + iounmap(boardp->ioremap_addr); + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; + if (boardp->orig_reqp) { + kfree(boardp->orig_reqp); + boardp->orig_reqp = boardp->adv_reqp = NULL; + } + while ((sgp = boardp->adv_sgblkp) != NULL) { + boardp->adv_sgblkp = sgp->next_sgblkp; + kfree(sgp); + } + } +#ifdef CONFIG_PROC_FS + ASC_ASSERT(boardp->prtbuf != NULL); + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + ASC_DBG(1, "advansys_release: end\n"); + return 0; +} + #ifdef CONFIG_PCI /* PCI Devices supported by this driver */ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { } + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {} }; + MODULE_DEVICE_TABLE(pci, advansys_pci_tbl); #endif /* CONFIG_PCI */ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 286ab83..a055a96 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2284,9 +2284,12 @@ static void ahd_linux_set_period(struct scsi_target *starget, int period) if (period < 8) period = 8; if (period < 10) { - ppr_options |= MSG_EXT_PPR_DT_REQ; - if (period == 8) - ppr_options |= MSG_EXT_PPR_IU_REQ; + if (spi_max_width(starget)) { + ppr_options |= MSG_EXT_PPR_DT_REQ; + if (period == 8) + ppr_options |= MSG_EXT_PPR_IU_REQ; + } else + period = 10; } dt = ppr_options & MSG_EXT_PPR_DT_REQ; @@ -2365,7 +2368,7 @@ static void ahd_linux_set_dt(struct scsi_target *starget, int dt) printf("%s: %s DT\n", ahd_name(ahd), dt ? "enabling" : "disabling"); #endif - if (dt) { + if (dt && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_DT_REQ; if (!width) ahd_linux_set_width(starget, 1); @@ -2447,7 +2450,7 @@ static void ahd_linux_set_iu(struct scsi_target *starget, int iu) iu ? "enabling" : "disabling"); #endif - if (iu) { + if (iu && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_IU_REQ; ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */ } @@ -2487,7 +2490,7 @@ static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) rdstrm ? "enabling" : "disabling"); #endif - if (rdstrm) + if (rdstrm && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_RD_STRM; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2523,7 +2526,7 @@ static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) wrflow ? "enabling" : "disabling"); #endif - if (wrflow) + if (wrflow && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_WR_FLOW; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2567,7 +2570,7 @@ static void ahd_linux_set_rti(struct scsi_target *starget, int rti) rti ? "enabling" : "disabling"); #endif - if (rti) + if (rti && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_RTI; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2603,7 +2606,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) pcomp ? "Enable" : "Disable"); #endif - if (pcomp) { + if (pcomp && spi_max_width(starget)) { uint8_t precomp; if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { @@ -2647,7 +2650,7 @@ static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; unsigned long flags; - if (hold) + if (hold && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_HOLD_MCS; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 1803ab6..2e9c38f 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2317,8 +2317,13 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period) if (period < 9) period = 9; /* 12.5ns is our minimum */ - if (period == 9) - ppr_options |= MSG_EXT_PPR_DT_REQ; + if (period == 9) { + if (spi_max_width(starget)) + ppr_options |= MSG_EXT_PPR_DT_REQ; + else + /* need wide for DT and need DT for 12.5 ns */ + period = 10; + } ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); @@ -2381,7 +2386,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) unsigned long flags; struct ahc_syncrate *syncrate; - if (dt) { + if (dt && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_DT_REQ; if (!width) ahc_linux_set_width(starget, 1); diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index ab00aec..63bcde2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -586,7 +586,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, goto Err; } asd_ha->pcidev = dev; - asd_ha->sas_ha.pcidev = asd_ha->pcidev; + asd_ha->sas_ha.dev = &asd_ha->pcidev->dev; asd_ha->sas_ha.lldd_ha = asd_ha; asd_ha->name = asd_dev->name; @@ -605,8 +605,6 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, goto Err_free; } - - err = asd_dev->setup(asd_ha); if (err) goto Err_free; diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig index d006a8c..7236143 100644 --- a/drivers/scsi/arm/Kconfig +++ b/drivers/scsi/arm/Kconfig @@ -74,15 +74,6 @@ config SCSI_CUMANA_1 This enables support for the Cumana SCSI I card. If you have an Acorn system with one of these, say Y. If unsure, say N. -config SCSI_ECOSCSI - tristate "EcoScsi support (EXPERIMENTAL)" - depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI - select SCSI_SPI_ATTRS - help - This enables support for the EcoSCSI card -- a small card that sits - in the Econet socket. If you have an Acorn system with one of these, - say Y. If unsure, say N. - config SCSI_OAK1 tristate "Oak SCSI support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI diff --git a/drivers/scsi/arm/Makefile b/drivers/scsi/arm/Makefile index e8db179..16c3e86 100644 --- a/drivers/scsi/arm/Makefile +++ b/drivers/scsi/arm/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_SCSI_ACORNSCSI_3) += acornscsi_mod.o queue.o msgqueue.o obj-$(CONFIG_SCSI_ARXESCSI) += arxescsi.o fas216.o queue.o msgqueue.o obj-$(CONFIG_SCSI_CUMANA_1) += cumana_1.o obj-$(CONFIG_SCSI_CUMANA_2) += cumana_2.o fas216.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_ECOSCSI) += ecoscsi.o obj-$(CONFIG_SCSI_OAK1) += oak.o obj-$(CONFIG_SCSI_POWERTECSCSI) += powertec.o fas216.o queue.o msgqueue.o obj-$(CONFIG_SCSI_EESOXSCSI) += eesox.o fas216.o queue.o msgqueue.o diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c deleted file mode 100644 index 5265a98..0000000 --- a/drivers/scsi/arm/ecoscsi.c +++ /dev/null @@ -1,166 +0,0 @@ -#define AUTOSENSE -/* #define PSEUDO_DMA */ - -/* - * EcoSCSI Generic NCR5380 driver - * - * Copyright 1995, Russell King - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -#include <linux/module.h> -#include <linux/signal.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/blkdev.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include "../scsi.h" -#include <scsi/scsi_host.h> - -#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) - -#define NCR5380_local_declare() void __iomem *_base -#define NCR5380_setup(host) _base = priv(host)->base - -#define NCR5380_read(reg) ({ writeb(reg | 8, _base); readb(_base + 4); }) -#define NCR5380_write(reg, value) ({ writeb(reg | 8, _base); writeb(value, _base + 4); }) - -#define NCR5380_intr ecoscsi_intr -#define NCR5380_queue_command ecoscsi_queue_command -#define NCR5380_proc_info ecoscsi_proc_info - -#define NCR5380_implementation_fields \ - void __iomem *base - -#include "../NCR5380.h" - -#define ECOSCSI_PUBLIC_RELEASE 1 - -/* - * Function : ecoscsi_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -void ecoscsi_setup(char *str, int *ints) -{ -} - -const char * ecoscsi_info (struct Scsi_Host *spnt) -{ - return ""; -} - -#define BOARD_NORMAL 0 -#define BOARD_NCR53C400 1 - -#include "../NCR5380.c" - -static struct scsi_host_template ecoscsi_template = { - .module = THIS_MODULE, - .name = "Serial Port EcoSCSI NCR5380", - .proc_name = "ecoscsi", - .info = ecoscsi_info, - .queuecommand = ecoscsi_queue_command, - .eh_abort_handler = NCR5380_abort, - .eh_bus_reset_handler = NCR5380_bus_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING -}; - -static struct Scsi_Host *host; - -static int __init ecoscsi_init(void) -{ - void __iomem *_base; - int ret; - - if (!request_mem_region(0x33a0000, 4096, "ecoscsi")) { - ret = -EBUSY; - goto out; - } - - _base = ioremap(0x33a0000, 4096); - if (!_base) { - ret = -ENOMEM; - goto out_release; - } - - NCR5380_write(MODE_REG, 0x20); /* Is it really SCSI? */ - if (NCR5380_read(MODE_REG) != 0x20) /* Write to a reg. */ - goto out_unmap; - - NCR5380_write(MODE_REG, 0x00); /* it back. */ - if (NCR5380_read(MODE_REG) != 0x00) - goto out_unmap; - - host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); - if (!host) { - ret = -ENOMEM; - goto out_unmap; - } - - priv(host)->base = _base; - host->irq = IRQ_NONE; - - NCR5380_init(host, 0); - - printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", host->host_no); - NCR5380_print_options(host); - printk("\n"); - - scsi_add_host(host, NULL); /* XXX handle failure */ - scsi_scan_host(host); - return 0; - - out_unmap: - iounmap(_base); - out_release: - release_mem_region(0x33a0000, 4096); - out: - return ret; -} - -static void __exit ecoscsi_exit(void) -{ - scsi_remove_host(host); - NCR5380_exit(host); - scsi_host_put(host); - release_mem_region(0x33a0000, 4096); - return 0; -} - -module_init(ecoscsi_init); -module_exit(ecoscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 7829ab1..a21455d 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2216,11 +2216,13 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) static int iscsi_tcp_slave_configure(struct scsi_device *sdev) { + blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); blk_queue_dma_alignment(sdev->request_queue, 0); return 0; } static struct scsi_host_template iscsi_sht = { + .module = THIS_MODULE, .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 4d85ce1..5606d1e 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -596,9 +596,16 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, nop->cmdsn = cpu_to_be32(session->cmdsn); if (hdr->itt != RESERVED_ITT) { hdr->itt = build_itt(mtask->itt, conn->id, session->age); + /* + * TODO: We always use immediate, so we never hit this. + * If we start to send tmfs or nops as non-immediate then + * we should start checking the cmdsn numbers for mgmt tasks. + */ if (conn->c_stage == ISCSI_CONN_STARTED && - !(hdr->opcode & ISCSI_OP_IMMEDIATE)) + !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { + session->queued_cmdsn++; session->cmdsn++; + } } if (session->tt->init_mgmt_task) @@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) /* * Check for iSCSI window and take care of CmdSN wrap-around */ - if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) { - debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n", - session->max_cmdsn, session->cmdsn); + if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { + debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " + "CmdSN %u/%u\n", session->exp_cmdsn, + session->max_cmdsn, session->cmdsn, + session->queued_cmdsn); return -ENOSPC; } return 0; @@ -722,11 +731,6 @@ check_mgmt: /* process command queue */ while (!list_empty(&conn->xmitqueue)) { - rc = iscsi_check_cmdsn_window_closed(conn); - if (rc) { - spin_unlock_bh(&conn->session->lock); - return rc; - } /* * iscsi tcp may readd the task to the xmitqueue to send * write data @@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) goto fault; } - /* - * We check this here and in data xmit, because if we get to the point - * that this check is hitting the window then we have enough IO in - * flight and enough IO waiting to be transmitted it is better - * to let the scsi/block layer queue up. - */ if (iscsi_check_cmdsn_window_closed(conn)) { reason = FAILURE_WINDOW_CLOSED; goto reject; @@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) reason = FAILURE_OOM; goto reject; } + session->queued_cmdsn++; + sc->SCp.phase = session->age; sc->SCp.ptr = (char *)ctask; @@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, if (!sc) return; - if (ctask->state != ISCSI_TASK_PENDING) + if (ctask->state == ISCSI_TASK_PENDING) + /* + * cmd never made it to the xmit thread, so we should not count + * the cmd in the sequencing + */ + conn->session->queued_cmdsn--; + else conn->session->tt->cleanup_cmd_task(conn, ctask); iscsi_ctask_mtask_cleanup(ctask); @@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, session->state = ISCSI_STATE_FREE; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->cmds_max = cmds_max; - session->cmdsn = initial_cmdsn; + session->queued_cmdsn = session->cmdsn = initial_cmdsn; session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; @@ -1473,6 +1479,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) struct iscsi_session *session = iscsi_hostdata(shost->hostdata); struct module *owner = cls_session->transport->owner; + iscsi_unblock_session(cls_session); scsi_remove_host(shost); iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); @@ -1615,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) kfree(conn->persistent_address); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); - if (session->leadconn == conn) { + if (session->leadconn == conn) session->leadconn = NULL; - /* no connections exits.. reset sequencing */ - session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; - } spin_unlock_bh(&session->lock); kfifo_free(conn->mgmtqueue); @@ -1649,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STARTED; session->state = ISCSI_STATE_LOGGED_IN; + session->queued_cmdsn = session->cmdsn; switch(conn->stop_stage) { case STOP_CONN_RECOVER: diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index ced2de3..5e573ef 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -382,7 +382,7 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev, struct ata_port *ap; ata_host_init(&found_dev->sata_dev.ata_host, - &ha->pcidev->dev, + ha->dev, sata_port_info.flags, &sas_sata_ops); ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host, @@ -448,10 +448,10 @@ static void sas_disc_task_done(struct sas_task *task) * @task: the task to be executed * @buffer: pointer to buffer to do I/O * @size: size of @buffer - * @pci_dma_dir: PCI_DMA_... + * @dma_dir: DMA direction. DMA_xxx */ static int sas_execute_task(struct sas_task *task, void *buffer, int size, - int pci_dma_dir) + enum dma_data_direction dma_dir) { int res = 0; struct scatterlist *scatter = NULL; @@ -461,7 +461,7 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, struct sas_internal *i = to_sas_internal(task->dev->port->ha->core.shost->transportt); - if (pci_dma_dir != PCI_DMA_NONE) { + if (dma_dir != DMA_NONE) { scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); if (!scatter) goto out; @@ -474,11 +474,11 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, task->scatter = scatter; task->num_scatter = num_scatter; task->total_xfer_len = size; - task->data_dir = pci_dma_dir; + task->data_dir = dma_dir; task->task_done = sas_disc_task_done; - if (pci_dma_dir != PCI_DMA_NONE && + if (dma_dir != DMA_NONE && sas_protocol_ata(task->task_proto)) { - task->num_scatter = pci_map_sg(task->dev->port->ha->pcidev, + task->num_scatter = dma_map_sg(task->dev->port->ha->dev, task->scatter, task->num_scatter, task->data_dir); @@ -565,9 +565,9 @@ static int sas_execute_task(struct sas_task *task, void *buffer, int size, } } ex_err: - if (pci_dma_dir != PCI_DMA_NONE) { + if (dma_dir != DMA_NONE) { if (sas_protocol_ata(task->task_proto)) - pci_unmap_sg(task->dev->port->ha->pcidev, + dma_unmap_sg(task->dev->port->ha->dev, task->scatter, task->num_scatter, task->data_dir); kfree(scatter); @@ -628,11 +628,11 @@ static void sas_get_ata_command_set(struct domain_device *dev) * @features: the features register * @buffer: pointer to buffer to do I/O * @size: size of @buffer - * @pci_dma_dir: PCI_DMA_... + * @dma_dir: DMA direction. DMA_xxx */ static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, u8 features, void *buffer, int size, - int pci_dma_dir) + enum dma_data_direction dma_dir) { int res = 0; struct sas_task *task; @@ -652,7 +652,7 @@ static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, task->ata_task.fis.device = d2h_fis->device; task->ata_task.retry_count = 1; - res = sas_execute_task(task, buffer, size, pci_dma_dir); + res = sas_execute_task(task, buffer, size, dma_dir); sas_free_task(task); out: @@ -707,7 +707,7 @@ static int sas_discover_sata_dev(struct domain_device *dev) } res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); if (res) goto out_err; @@ -720,13 +720,13 @@ static int sas_discover_sata_dev(struct domain_device *dev) goto cont1; res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, ATA_FEATURE_PUP_STBY_SPIN_UP, - NULL, 0, PCI_DMA_NONE); + NULL, 0, DMA_NONE); if (res) goto cont1; schedule_timeout_interruptible(5*HZ); /* More time? */ res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); if (res) goto out_err; } diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 6ac9f61..7ef0afc 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -22,7 +22,6 @@ * */ -#include <linux/pci.h> #include <linux/scatterlist.h> #include <scsi/scsi_host.h> #include <scsi/scsi_eh.h> @@ -170,7 +169,7 @@ int sas_notify_lldd_dev_found(struct domain_device *dev) if (res) { printk("sas: driver on pcidev %s cannot handle " "device %llx, error:%d\n", - pci_name(sas_ha->pcidev), + sas_ha->dev->bus_id, SAS_ADDR(dev->sas_addr), res); } } diff --git a/drivers/scsi/libsas/sas_dump.c b/drivers/scsi/libsas/sas_dump.c index f1246d2..bf34a23 100644 --- a/drivers/scsi/libsas/sas_dump.c +++ b/drivers/scsi/libsas/sas_dump.c @@ -56,7 +56,7 @@ void sas_dprint_phye(int phyid, enum phy_event pe) void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he) { - SAS_DPRINTK("ha %s: %s event\n", pci_name(sas_ha->pcidev), + SAS_DPRINTK("ha %s: %s event\n", sas_ha->dev->bus_id, sas_hae_str[he]); } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index b500f0c..8727436 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -507,14 +507,21 @@ static int sas_dev_present_in_domain(struct asd_sas_port *port, int sas_smp_get_phy_events(struct sas_phy *phy) { int res; + u8 *req; + u8 *resp; struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); struct domain_device *dev = sas_find_dev_by_rphy(rphy); - u8 *req = alloc_smp_req(RPEL_REQ_SIZE); - u8 *resp = kzalloc(RPEL_RESP_SIZE, GFP_KERNEL); - if (!resp) + req = alloc_smp_req(RPEL_REQ_SIZE); + if (!req) return -ENOMEM; + resp = alloc_smp_resp(RPEL_RESP_SIZE); + if (!resp) { + kfree(req); + return -ENOMEM; + } + req[1] = SMP_REPORT_PHY_ERR_LOG; req[9] = phy->number; @@ -1879,7 +1886,7 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, struct request *req) { struct domain_device *dev; - int ret, type = rphy->identify.device_type; + int ret, type; struct request *rsp = req->next_rq; if (!rsp) { @@ -1888,12 +1895,13 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, return -EINVAL; } - /* seems aic94xx doesn't support */ + /* no rphy means no smp target support (ie aic94xx host) */ if (!rphy) { printk("%s: can we send a smp request to a host?\n", __FUNCTION__); return -EINVAL; } + type = rphy->identify.device_type; if (type != SAS_EDGE_EXPANDER_DEVICE && type != SAS_FANOUT_EXPANDER_DEVICE) { diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 1612f92..0f2a9f5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -91,18 +91,20 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; + int size = ha->nvram_size; + char *nvram_cache = ha->nvram; - if (!capable(CAP_SYS_ADMIN) || off != 0) + if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; + if (off + count > size) { + size -= off; + count = size; + } - /* Read NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->nvram_base, - ha->nvram_size); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + /* Read NVRAM data from cache. */ + memcpy(buf, &nvram_cache[off], count); - return ha->nvram_size; + return count; } static ssize_t @@ -144,6 +146,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); + ha->isp_ops->read_nvram(ha, (uint8_t *)&ha->nvram, ha->nvram_base, + count); spin_unlock_irqrestore(&ha->hardware_lock, flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -298,18 +302,20 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; + int size = ha->vpd_size; + char *vpd_cache = ha->vpd; - if (!capable(CAP_SYS_ADMIN) || off != 0) + if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; + if (off + count > size) { + size -= off; + count = size; + } - /* Read NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops->read_nvram(ha, (uint8_t *)buf, ha->vpd_base, - ha->vpd_size); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + /* Read NVRAM data from cache. */ + memcpy(buf, &vpd_cache[off], count); - return ha->vpd_size; + return count; } static ssize_t @@ -327,6 +333,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); return count; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 0c9f36c..27ae3a5 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2340,10 +2340,14 @@ typedef struct scsi_qla_host { uint8_t serial2; /* NVRAM configuration data */ +#define MAX_NVRAM_SIZE 4096 +#define VPD_OFFSET MAX_NVRAM_SIZE / 2 uint16_t nvram_size; uint16_t nvram_base; + void *nvram; uint16_t vpd_size; uint16_t vpd_base; + void *vpd; uint16_t loop_reset_delay; uint8_t retry_count; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5ec798c..374abe1 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1461,8 +1461,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) uint16_t cnt; uint8_t *dptr1, *dptr2; init_cb_t *icb = ha->init_cb; - nvram_t *nv = (nvram_t *)ha->request_ring; - uint8_t *ptr = (uint8_t *)ha->request_ring; + nvram_t *nv = ha->nvram; + uint8_t *ptr = ha->nvram; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; rval = QLA_SUCCESS; @@ -1480,8 +1480,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) chksum += *ptr++; DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); - DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, - ha->nvram_size)); + DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || @@ -3500,7 +3499,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; - nv = (struct nvram_24xx *)ha->request_ring; + nv = ha->nvram; /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(struct nvram_24xx); @@ -3512,7 +3511,12 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->vpd_base = FA_NVRAM_VPD1_ADDR; } - /* Get NVRAM data and calculate checksum. */ + /* Get VPD data into cache */ + ha->vpd = ha->nvram + VPD_OFFSET; + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, + ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); + + /* Get NVRAM data into cache and calculate checksum. */ dptr = (uint32_t *)nv; ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, ha->nvram_size); @@ -3520,8 +3524,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) chksum += le32_to_cpu(*dptr++); DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); - DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, - ha->nvram_size)); + DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b8f226a..50539da 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1068,7 +1068,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) * values. */ if (resid && - ((unsigned)(cp->request_bufflen - resid) < + ((unsigned)(scsi_bufflen(cp) - resid) < cp->underflow)) { DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): Mid-layer underflow " @@ -1076,7 +1076,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) "error status.\n", ha->host_no, cp->device->channel, cp->device->id, cp->device->lun, resid, - cp->request_bufflen)); + scsi_bufflen(cp))); cp->result = DID_ERROR << 16 | lscsi_status; } diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 19c44f0..e2ea739 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -154,6 +154,9 @@ static struct { {"EMC", "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, + {"easyRAID", "16P", NULL, BLIST_NOREPORTLUN}, + {"easyRAID", "X6P", NULL, BLIST_NOREPORTLUN}, + {"easyRAID", "F8", NULL, BLIST_NOREPORTLUN}, {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36}, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index da63c54..21c075d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -654,7 +654,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, int bytes, int requeue) { - request_queue_t *q = cmd->device->request_queue; + struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; unsigned long flags; @@ -818,7 +818,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) { int result = cmd->result; int this_count = cmd->request_bufflen; - request_queue_t *q = cmd->device->request_queue; + struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; int clear_errors = 1; struct scsi_sense_hdr sshdr; @@ -1038,7 +1038,7 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_KILL; } -static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, +static int scsi_issue_flush_fn(struct request_queue *q, struct gendisk *disk, sector_t *error_sector) { struct scsi_device *sdev = q->queuedata; @@ -1340,7 +1340,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, /* * Kill a request for a dead device */ -static void scsi_kill_request(struct request *req, request_queue_t *q) +static void scsi_kill_request(struct request *req, struct request_queue *q) { struct scsi_cmnd *cmd = req->special; struct scsi_device *sdev = cmd->device; @@ -2119,7 +2119,7 @@ EXPORT_SYMBOL(scsi_target_resume); int scsi_internal_device_block(struct scsi_device *sdev) { - request_queue_t *q = sdev->request_queue; + struct request_queue *q = sdev->request_queue; unsigned long flags; int err = 0; @@ -2159,7 +2159,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block); int scsi_internal_device_unblock(struct scsi_device *sdev) { - request_queue_t *q = sdev->request_queue; + struct request_queue *q = sdev->request_queue; int err; unsigned long flags; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 424d557..e21c714 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -814,7 +814,7 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector) return ret; } -static void sd_prepare_flush(request_queue_t *q, struct request *rq) +static void sd_prepare_flush(struct request_queue *q, struct request *rq) { memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd_type = REQ_TYPE_BLOCK_PC; @@ -1285,7 +1285,7 @@ got_data: */ int hard_sector = sector_size; sector_t sz = (sdkp->capacity/2) * (hard_sector/256); - request_queue_t *queue = sdp->request_queue; + struct request_queue *queue = sdp->request_queue; sector_t mb = sz; blk_queue_hardsect_size(queue, hard_sector); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index e7b6a7f..902eb11 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -624,7 +624,7 @@ static void get_sectorsize(struct scsi_cd *cd) unsigned char *buffer; int the_result, retries = 3; int sector_size; - request_queue_t *queue; + struct request_queue *queue; buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 15a5145..3db2232 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -2033,7 +2033,7 @@ static struct pci_device_id sym2_id_table[] __devinitdata = { { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C875, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C1510, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, /* new */ + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI<<8, 0xffff00, 0UL }, /* new */ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C895A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C875A, diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index cad426c..aad4012 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -33,7 +33,6 @@ #include <linux/keyboard.h> #include <linux/init.h> #include <linux/pm.h> -#include <linux/pm_legacy.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -401,9 +400,9 @@ irqreturn_t rs_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void do_softint(void *private) +static void do_softint(struct work_struct *work) { - struct m68k_serial *info = (struct m68k_serial *) private; + struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); struct tty_struct *tty; tty = info->tty; @@ -425,9 +424,9 @@ static void do_softint(void *private) * do_serial_hangup() -> tty->hangup() -> rs_hangup() * */ -static void do_serial_hangup(void *private) +static void do_serial_hangup(struct work_struct *work) { - struct m68k_serial *info = (struct m68k_serial *) private; + struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue_hangup); struct tty_struct *tty; tty = info->tty; @@ -1324,59 +1323,6 @@ static void show_serial_version(void) printk("MC68328 serial driver version 1.00\n"); } -#ifdef CONFIG_PM_LEGACY -/* Serial Power management - * The console (currently fixed at line 0) is a special case for power - * management because the kernel is so chatty. The console will be - * explicitly disabled my our power manager as the last minute, so we won't - * mess with it here. - */ -static struct pm_dev *serial_pm[NR_PORTS]; - -static int serial_pm_callback(struct pm_dev *dev, pm_request_t request, void *data) -{ - struct m68k_serial *info = (struct m68k_serial *)dev->data; - - if(info == NULL) - return -1; - - /* special case for line 0 - pm restores it */ - if(info->line == 0) - return 0; - - switch (request) { - case PM_SUSPEND: - shutdown(info); - break; - - case PM_RESUME: - startup(info); - break; - } - return 0; -} - -void shutdown_console(void) -{ - struct m68k_serial *info = &m68k_soft[0]; - - /* HACK: wait a bit for any pending printk's to be dumped */ - { - int i = 10000; - while(i--); - } - - shutdown(info); -} - -void startup_console(void) -{ - struct m68k_serial *info = &m68k_soft[0]; - startup(info); -} -#endif /* CONFIG_PM_LEGACY */ - - static const struct tty_operations rs_ops = { .open = rs_open, .close = rs_close, @@ -1444,8 +1390,8 @@ rs68328_init(void) info->event = 0; info->count = 0; info->blocked_open = 0; - INIT_WORK(&info->tqueue, do_softint, info); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + INIT_WORK(&info->tqueue, do_softint); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); info->line = i; @@ -1467,11 +1413,6 @@ rs68328_init(void) IRQ_FLG_STD, "M68328_UART", NULL)) panic("Unable to attach 68328 serial interrupt\n"); -#ifdef CONFIG_PM_LEGACY - serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); - if (serial_pm[i]) - serial_pm[i]->data = info; -#endif } local_irq_restore(flags); return 0; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 0b3ec38..2f5a5ac 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2650,8 +2650,9 @@ static int __devinit serial8250_probe(struct platform_device *dev) ret = serial8250_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " - "(IO%lx MEM%lx IRQ%d): %d\n", i, - p->iobase, p->mapbase, p->irq, ret); + "(IO%lx MEM%llx IRQ%d): %d\n", i, + p->iobase, (unsigned long long)p->mapbase, + p->irq, ret); } } return 0; diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 947c205..150cad5 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -151,8 +151,9 @@ static int __init parse_options(struct early_serial8250_device *device, char *op #else port->membase = ioremap(port->mapbase, 64); if (!port->membase) { - printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", - __FUNCTION__, port->mapbase); + printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", + __FUNCTION__, + (unsigned long long)port->mapbase); return -ENOMEM; } #endif @@ -175,9 +176,10 @@ static int __init parse_options(struct early_serial8250_device *device, char *op device->baud); } - printk(KERN_INFO "Early serial console at %s 0x%lx (options '%s')\n", + printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n", mmio ? "MMIO" : "I/O port", - mmio ? port->mapbase : (unsigned long) port->iobase, + mmio ? (unsigned long long) port->mapbase + : (unsigned long long) port->iobase, device->options); return 0; } diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 6d7d616..5e48587 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -976,7 +976,6 @@ enum pci_board_num_t { pbn_oxsemi, pbn_intel_i960, pbn_sgi_ioc3, - pbn_nec_nile4, pbn_computone_4, pbn_computone_6, pbn_computone_8, @@ -1443,18 +1442,6 @@ static struct pciserial_board pci_boards[] __devinitdata = { }, /* - * NEC Vrc-5074 (Nile 4) builtin UART. - */ - [pbn_nec_nile4] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 520833, - .uart_offset = 8 << 3, - .reg_shift = 3, - .first_offset = 0x300, - }, - - /* * Computone - uses IOMEM. */ [pbn_computone_4] = { @@ -2345,13 +2332,6 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_1_115200 }, - /* - * NEC Vrc-5074 (Nile 4) builtin UART. - */ - { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_nec_nile4 }, - { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_2_115200 }, diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 18f6297..64ff6a5 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -88,21 +88,17 @@ config SERIAL_8250_PCI depends on SERIAL_8250 && PCI default SERIAL_8250 help - Say Y here if you have PCI serial ports. - - To compile this driver as a module, choose M here: the module - will be called 8250_pci. + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. config SERIAL_8250_PNP tristate "8250/16550 PNP device support" if EMBEDDED depends on SERIAL_8250 && PNP default SERIAL_8250 help - Say Y here if you have serial ports described by PNPBIOS or ACPI. - These are typically ports built into the system board. - - To compile this driver as a module, choose M here: the module - will be called 8250_pnp. + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. config SERIAL_8250_HP300 tristate @@ -1195,7 +1191,7 @@ config SERIAL_VR41XX config SERIAL_VR41XX_CONSOLE bool "Enable NEC VR4100 series Serial Interface Unit console" - depends on SERIAL_VR41XX + depends on SERIAL_VR41XX=y select SERIAL_CORE_CONSOLE help If you have a NEC VR4100 series processor and you want to use diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index 00924fe..4d643c9 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -74,10 +74,6 @@ #include <asm/io.h> #include <asm/irq.h> -#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #define MPSC_NUM_CTLRS 2 /* @@ -97,9 +93,8 @@ #define MPSC_TXBE_SIZE dma_get_cache_alignment() #define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE) -#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + \ - MPSC_TXR_SIZE + MPSC_TXB_SIZE + \ - dma_get_cache_alignment() /* for alignment */) +#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + MPSC_TXR_SIZE \ + + MPSC_TXB_SIZE + dma_get_cache_alignment() /* for alignment */) /* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */ struct mpsc_rx_desc { @@ -270,8 +265,8 @@ struct mpsc_port_info *mpsc_device_remove(int index); #define SDMA_DESC_CMDSTAT_EI (1<<23) #define SDMA_DESC_CMDSTAT_O (1<<31) -#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \ - SDMA_DESC_CMDSTAT_EI) +#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O \ + | SDMA_DESC_CMDSTAT_EI) #define SDMA_SDC_RFT (1<<0) #define SDMA_SDC_SFM (1<<1) @@ -295,10 +290,10 @@ struct mpsc_port_info *mpsc_device_remove(int index); #define SDMA_1_CAUSE_TXBUF (1<<10) #define SDMA_1_CAUSE_TXEND (1<<11) -#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \ - SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR) -#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \ - SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND) +#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR \ + | SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR) +#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND \ + | SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND) /* SDMA Interrupt registers */ #define SDMA_INTR_CAUSE 0x0000 @@ -312,11 +307,11 @@ struct mpsc_port_info *mpsc_device_remove(int index); * Define how this driver is known to the outside (we've been assigned a * range on the "Low-density serial ports" major). */ -#define MPSC_MAJOR 204 -#define MPSC_MINOR_START 44 -#define MPSC_DRIVER_NAME "MPSC" -#define MPSC_DEV_NAME "ttyMM" -#define MPSC_VERSION "1.00" +#define MPSC_MAJOR 204 +#define MPSC_MINOR_START 44 +#define MPSC_DRIVER_NAME "MPSC" +#define MPSC_DEV_NAME "ttyMM" +#define MPSC_VERSION "1.00" static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS]; static struct mpsc_shared_regs mpsc_shared_regs; @@ -332,8 +327,7 @@ static void mpsc_release_port(struct uart_port *port); * ****************************************************************************** */ -static void -mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src) +static void mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src) { u32 v; @@ -349,11 +343,9 @@ mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src) writel(readl(pi->brg_base + BRG_BTR) & 0xffff0000, pi->brg_base + BRG_BTR); - return; } -static void -mpsc_brg_enable(struct mpsc_port_info *pi) +static void mpsc_brg_enable(struct mpsc_port_info *pi) { u32 v; @@ -363,11 +355,9 @@ mpsc_brg_enable(struct mpsc_port_info *pi) if (pi->mirror_regs) pi->BRG_BCR_m = v; writel(v, pi->brg_base + BRG_BCR); - return; } -static void -mpsc_brg_disable(struct mpsc_port_info *pi) +static void mpsc_brg_disable(struct mpsc_port_info *pi) { u32 v; @@ -377,21 +367,19 @@ mpsc_brg_disable(struct mpsc_port_info *pi) if (pi->mirror_regs) pi->BRG_BCR_m = v; writel(v, pi->brg_base + BRG_BCR); - return; } -static inline void -mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud) +/* + * To set the baud, we adjust the CDV field in the BRG_BCR reg. + * From manual: Baud = clk / ((CDV+1)*2) ==> CDV = (clk / (baud*2)) - 1. + * However, the input clock is divided by 16 in the MPSC b/c of how + * 'MPSC_MMCRH' was set up so we have to divide the 'clk' used in our + * calculation by 16 to account for that. So the real calculation + * that accounts for the way the mpsc is set up is: + * CDV = (clk / (baud*2*16)) - 1 ==> CDV = (clk / (baud << 5)) - 1. + */ +static void mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud) { - /* - * To set the baud, we adjust the CDV field in the BRG_BCR reg. - * From manual: Baud = clk / ((CDV+1)*2) ==> CDV = (clk / (baud*2)) - 1. - * However, the input clock is divided by 16 in the MPSC b/c of how - * 'MPSC_MMCRH' was set up so we have to divide the 'clk' used in our - * calculation by 16 to account for that. So the real calculation - * that accounts for the way the mpsc is set up is: - * CDV = (clk / (baud*2*16)) - 1 ==> CDV = (clk / (baud << 5)) - 1. - */ u32 cdv = (pi->port.uartclk / (baud << 5)) - 1; u32 v; @@ -403,8 +391,6 @@ mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud) pi->BRG_BCR_m = v; writel(v, pi->brg_base + BRG_BCR); mpsc_brg_enable(pi); - - return; } /* @@ -415,13 +401,12 @@ mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud) ****************************************************************************** */ -static void -mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size) +static void mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size) { u32 v; pr_debug("mpsc_sdma_burstsize[%d]: burst_size: %d\n", - pi->port.line, burst_size); + pi->port.line, burst_size); burst_size >>= 3; /* Divide by 8 b/c reg values are 8-byte chunks */ @@ -436,11 +421,9 @@ mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size) writel((readl(pi->sdma_base + SDMA_SDC) & (0x3 << 12)) | (v << 12), pi->sdma_base + SDMA_SDC); - return; } -static void -mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size) +static void mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size) { pr_debug("mpsc_sdma_init[%d]: burst_size: %d\n", pi->port.line, burst_size); @@ -448,11 +431,9 @@ mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size) writel((readl(pi->sdma_base + SDMA_SDC) & 0x3ff) | 0x03f, pi->sdma_base + SDMA_SDC); mpsc_sdma_burstsize(pi, burst_size); - return; } -static inline u32 -mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask) +static u32 mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask) { u32 old, v; @@ -475,15 +456,14 @@ mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask) return old & 0xf; } -static inline void -mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask) +static void mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask) { u32 v; pr_debug("mpsc_sdma_intr_unmask[%d]: mask: 0x%x\n", pi->port.line,mask); - v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m : - readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); + v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m + : readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); mask &= 0xf; if (pi->port.line) @@ -493,41 +473,35 @@ mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask) if (pi->mirror_regs) pi->shared_regs->SDMA_INTR_MASK_m = v; writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK); - return; } -static inline void -mpsc_sdma_intr_ack(struct mpsc_port_info *pi) +static void mpsc_sdma_intr_ack(struct mpsc_port_info *pi) { pr_debug("mpsc_sdma_intr_ack[%d]: Acknowledging IRQ\n", pi->port.line); if (pi->mirror_regs) pi->shared_regs->SDMA_INTR_CAUSE_m = 0; - writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE + - pi->port.line); - return; + writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE + + pi->port.line); } -static inline void -mpsc_sdma_set_rx_ring(struct mpsc_port_info *pi, struct mpsc_rx_desc *rxre_p) +static void mpsc_sdma_set_rx_ring(struct mpsc_port_info *pi, + struct mpsc_rx_desc *rxre_p) { pr_debug("mpsc_sdma_set_rx_ring[%d]: rxre_p: 0x%x\n", - pi->port.line, (u32) rxre_p); + pi->port.line, (u32)rxre_p); writel((u32)rxre_p, pi->sdma_base + SDMA_SCRDP); - return; } -static inline void -mpsc_sdma_set_tx_ring(struct mpsc_port_info *pi, struct mpsc_tx_desc *txre_p) +static void mpsc_sdma_set_tx_ring(struct mpsc_port_info *pi, + struct mpsc_tx_desc *txre_p) { writel((u32)txre_p, pi->sdma_base + SDMA_SFTDP); writel((u32)txre_p, pi->sdma_base + SDMA_SCTDP); - return; } -static inline void -mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val) +static void mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val) { u32 v; @@ -539,46 +513,40 @@ mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val) wmb(); writel(v, pi->sdma_base + SDMA_SDCM); wmb(); - return; } -static inline uint -mpsc_sdma_tx_active(struct mpsc_port_info *pi) +static uint mpsc_sdma_tx_active(struct mpsc_port_info *pi) { return readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_TXD; } -static inline void -mpsc_sdma_start_tx(struct mpsc_port_info *pi) +static void mpsc_sdma_start_tx(struct mpsc_port_info *pi) { struct mpsc_tx_desc *txre, *txre_p; /* If tx isn't running & there's a desc ready to go, start it */ if (!mpsc_sdma_tx_active(pi)) { - txre = (struct mpsc_tx_desc *)(pi->txr + - (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + txre = (struct mpsc_tx_desc *)(pi->txr + + (pi->txr_tail * MPSC_TXRE_SIZE)); + dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, + DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); + (ulong)txre + MPSC_TXRE_SIZE); #endif if (be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O) { - txre_p = (struct mpsc_tx_desc *)(pi->txr_p + - (pi->txr_tail * - MPSC_TXRE_SIZE)); + txre_p = (struct mpsc_tx_desc *) + (pi->txr_p + (pi->txr_tail * MPSC_TXRE_SIZE)); mpsc_sdma_set_tx_ring(pi, txre_p); mpsc_sdma_cmd(pi, SDMA_SDCM_STD | SDMA_SDCM_TXD); } } - - return; } -static inline void -mpsc_sdma_stop(struct mpsc_port_info *pi) +static void mpsc_sdma_stop(struct mpsc_port_info *pi) { pr_debug("mpsc_sdma_stop[%d]: Stopping SDMA\n", pi->port.line); @@ -593,8 +561,6 @@ mpsc_sdma_stop(struct mpsc_port_info *pi) /* Disable interrupts */ mpsc_sdma_intr_mask(pi, 0xf); mpsc_sdma_intr_ack(pi); - - return; } /* @@ -605,8 +571,7 @@ mpsc_sdma_stop(struct mpsc_port_info *pi) ****************************************************************************** */ -static void -mpsc_hw_init(struct mpsc_port_info *pi) +static void mpsc_hw_init(struct mpsc_port_info *pi) { u32 v; @@ -628,8 +593,7 @@ mpsc_hw_init(struct mpsc_port_info *pi) v = (v & ~0xf0f) | 0x100; pi->shared_regs->MPSC_TCRR_m = v; writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR); - } - else { + } else { v = readl(pi->shared_regs->mpsc_routing_base + MPSC_MRR); v &= ~0x1c7; writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR); @@ -646,7 +610,7 @@ mpsc_hw_init(struct mpsc_port_info *pi) /* Put MPSC in UART mode & enabel Tx/Rx egines */ writel(0x000004c4, pi->mpsc_base + MPSC_MMCRL); - /* No preamble, 16x divider, low-latency, */ + /* No preamble, 16x divider, low-latency, */ writel(0x04400400, pi->mpsc_base + MPSC_MMCRH); if (pi->mirror_regs) { @@ -663,12 +627,9 @@ mpsc_hw_init(struct mpsc_port_info *pi) writel(0, pi->mpsc_base + MPSC_CHR_8); writel(0, pi->mpsc_base + MPSC_CHR_9); writel(0, pi->mpsc_base + MPSC_CHR_10); - - return; } -static inline void -mpsc_enter_hunt(struct mpsc_port_info *pi) +static void mpsc_enter_hunt(struct mpsc_port_info *pi) { pr_debug("mpsc_enter_hunt[%d]: Hunting...\n", pi->port.line); @@ -677,20 +638,16 @@ mpsc_enter_hunt(struct mpsc_port_info *pi) pi->mpsc_base + MPSC_CHR_2); /* Erratum prevents reading CHR_2 so just delay for a while */ udelay(100); - } - else { + } else { writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_EH, - pi->mpsc_base + MPSC_CHR_2); + pi->mpsc_base + MPSC_CHR_2); while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_EH) udelay(10); } - - return; } -static inline void -mpsc_freeze(struct mpsc_port_info *pi) +static void mpsc_freeze(struct mpsc_port_info *pi) { u32 v; @@ -703,11 +660,9 @@ mpsc_freeze(struct mpsc_port_info *pi) if (pi->mirror_regs) pi->MPSC_MPCR_m = v; writel(v, pi->mpsc_base + MPSC_MPCR); - return; } -static inline void -mpsc_unfreeze(struct mpsc_port_info *pi) +static void mpsc_unfreeze(struct mpsc_port_info *pi) { u32 v; @@ -720,11 +675,9 @@ mpsc_unfreeze(struct mpsc_port_info *pi) writel(v, pi->mpsc_base + MPSC_MPCR); pr_debug("mpsc_unfreeze[%d]: Unfrozen\n", pi->port.line); - return; } -static inline void -mpsc_set_char_length(struct mpsc_port_info *pi, u32 len) +static void mpsc_set_char_length(struct mpsc_port_info *pi, u32 len) { u32 v; @@ -737,11 +690,9 @@ mpsc_set_char_length(struct mpsc_port_info *pi, u32 len) if (pi->mirror_regs) pi->MPSC_MPCR_m = v; writel(v, pi->mpsc_base + MPSC_MPCR); - return; } -static inline void -mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len) +static void mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len) { u32 v; @@ -756,11 +707,9 @@ mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len) if (pi->mirror_regs) pi->MPSC_MPCR_m = v; writel(v, pi->mpsc_base + MPSC_MPCR); - return; } -static inline void -mpsc_set_parity(struct mpsc_port_info *pi, u32 p) +static void mpsc_set_parity(struct mpsc_port_info *pi, u32 p) { u32 v; @@ -775,7 +724,6 @@ mpsc_set_parity(struct mpsc_port_info *pi, u32 p) if (pi->mirror_regs) pi->MPSC_CHR_2_m = v; writel(v, pi->mpsc_base + MPSC_CHR_2); - return; } /* @@ -786,8 +734,7 @@ mpsc_set_parity(struct mpsc_port_info *pi, u32 p) ****************************************************************************** */ -static void -mpsc_init_hw(struct mpsc_port_info *pi) +static void mpsc_init_hw(struct mpsc_port_info *pi) { pr_debug("mpsc_init_hw[%d]: Initializing\n", pi->port.line); @@ -796,12 +743,9 @@ mpsc_init_hw(struct mpsc_port_info *pi) mpsc_sdma_init(pi, dma_get_cache_alignment()); /* burst a cacheline */ mpsc_sdma_stop(pi); mpsc_hw_init(pi); - - return; } -static int -mpsc_alloc_ring_mem(struct mpsc_port_info *pi) +static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi) { int rc = 0; @@ -812,11 +756,10 @@ mpsc_alloc_ring_mem(struct mpsc_port_info *pi) if (!dma_supported(pi->port.dev, 0xffffffff)) { printk(KERN_ERR "MPSC: Inadequate DMA support\n"); rc = -ENXIO; - } - else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev, - MPSC_DMA_ALLOC_SIZE, &pi->dma_region_p, GFP_KERNEL)) - == NULL) { - + } else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev, + MPSC_DMA_ALLOC_SIZE, + &pi->dma_region_p, GFP_KERNEL)) + == NULL) { printk(KERN_ERR "MPSC: Can't alloc Desc region\n"); rc = -ENOMEM; } @@ -825,23 +768,19 @@ mpsc_alloc_ring_mem(struct mpsc_port_info *pi) return rc; } -static void -mpsc_free_ring_mem(struct mpsc_port_info *pi) +static void mpsc_free_ring_mem(struct mpsc_port_info *pi) { pr_debug("mpsc_free_ring_mem[%d]: Freeing ring mem\n", pi->port.line); if (pi->dma_region) { dma_free_noncoherent(pi->port.dev, MPSC_DMA_ALLOC_SIZE, - pi->dma_region, pi->dma_region_p); + pi->dma_region, pi->dma_region_p); pi->dma_region = NULL; - pi->dma_region_p = (dma_addr_t) NULL; + pi->dma_region_p = (dma_addr_t)NULL; } - - return; } -static void -mpsc_init_rings(struct mpsc_port_info *pi) +static void mpsc_init_rings(struct mpsc_port_info *pi) { struct mpsc_rx_desc *rxre; struct mpsc_tx_desc *txre; @@ -859,8 +798,8 @@ mpsc_init_rings(struct mpsc_port_info *pi) * Descriptors & buffers are multiples of cacheline size and must be * cacheline aligned. */ - dp = ALIGN((u32) pi->dma_region, dma_get_cache_alignment()); - dp_p = ALIGN((u32) pi->dma_region_p, dma_get_cache_alignment()); + dp = ALIGN((u32)pi->dma_region, dma_get_cache_alignment()); + dp_p = ALIGN((u32)pi->dma_region_p, dma_get_cache_alignment()); /* * Partition dma region into rx ring descriptor, rx buffers, @@ -871,8 +810,8 @@ mpsc_init_rings(struct mpsc_port_info *pi) dp += MPSC_RXR_SIZE; dp_p += MPSC_RXR_SIZE; - pi->rxb = (u8 *) dp; - pi->rxb_p = (u8 *) dp_p; + pi->rxb = (u8 *)dp; + pi->rxb_p = (u8 *)dp_p; dp += MPSC_RXB_SIZE; dp_p += MPSC_RXB_SIZE; @@ -883,8 +822,8 @@ mpsc_init_rings(struct mpsc_port_info *pi) dp += MPSC_TXR_SIZE; dp_p += MPSC_TXR_SIZE; - pi->txb = (u8 *) dp; - pi->txb_p = (u8 *) dp_p; + pi->txb = (u8 *)dp; + pi->txb_p = (u8 *)dp_p; pi->txr_head = 0; pi->txr_tail = 0; @@ -900,10 +839,9 @@ mpsc_init_rings(struct mpsc_port_info *pi) rxre->bufsize = cpu_to_be16(MPSC_RXBE_SIZE); rxre->bytecnt = cpu_to_be16(0); - rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | - SDMA_DESC_CMDSTAT_EI | - SDMA_DESC_CMDSTAT_F | - SDMA_DESC_CMDSTAT_L); + rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O + | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F + | SDMA_DESC_CMDSTAT_L); rxre->link = cpu_to_be32(dp_p + MPSC_RXRE_SIZE); rxre->buf_ptr = cpu_to_be32(bp_p); @@ -933,19 +871,19 @@ mpsc_init_rings(struct mpsc_port_info *pi) } txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */ - dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, - DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)pi->dma_region, + MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)pi->dma_region, - (ulong)pi->dma_region + MPSC_DMA_ALLOC_SIZE); + (ulong)pi->dma_region + + MPSC_DMA_ALLOC_SIZE); #endif return; } -static void -mpsc_uninit_rings(struct mpsc_port_info *pi) +static void mpsc_uninit_rings(struct mpsc_port_info *pi) { pr_debug("mpsc_uninit_rings[%d]: Uninitializing rings\n",pi->port.line); @@ -963,12 +901,9 @@ mpsc_uninit_rings(struct mpsc_port_info *pi) pi->txb_p = NULL; pi->txr_head = 0; pi->txr_tail = 0; - - return; } -static int -mpsc_make_ready(struct mpsc_port_info *pi) +static int mpsc_make_ready(struct mpsc_port_info *pi) { int rc; @@ -993,8 +928,7 @@ mpsc_make_ready(struct mpsc_port_info *pi) ****************************************************************************** */ -static inline int -mpsc_rx_intr(struct mpsc_port_info *pi) +static int mpsc_rx_intr(struct mpsc_port_info *pi) { struct mpsc_rx_desc *rxre; struct tty_struct *tty = pi->port.info->tty; @@ -1007,21 +941,24 @@ mpsc_rx_intr(struct mpsc_port_info *pi) rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, + DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); + (ulong)rxre + MPSC_RXRE_SIZE); #endif /* * Loop through Rx descriptors handling ones that have been completed. */ - while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) & SDMA_DESC_CMDSTAT_O)){ + while (!((cmdstat = be32_to_cpu(rxre->cmdstat)) + & SDMA_DESC_CMDSTAT_O)) { bytes_in = be16_to_cpu(rxre->bytecnt); /* Following use of tty struct directly is deprecated */ - if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) { + if (unlikely(tty_buffer_request_room(tty, bytes_in) + < bytes_in)) { if (tty->low_latency) tty_flip_buffer_push(tty); /* @@ -1031,11 +968,12 @@ mpsc_rx_intr(struct mpsc_port_info *pi) } bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)bp, MPSC_RXBE_SIZE, + DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)bp, - (ulong)bp + MPSC_RXBE_SIZE); + (ulong)bp + MPSC_RXBE_SIZE); #endif /* @@ -1046,8 +984,9 @@ mpsc_rx_intr(struct mpsc_port_info *pi) * we'll assume there is no data in the buffer. * If there is...it gets lost. */ - if (unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | - SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) { + if (unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR + | SDMA_DESC_CMDSTAT_FR + | SDMA_DESC_CMDSTAT_OR))) { pi->port.icount.rx++; @@ -1056,11 +995,11 @@ mpsc_rx_intr(struct mpsc_port_info *pi) if (uart_handle_break(&pi->port)) goto next_frame; - } - else if (cmdstat & SDMA_DESC_CMDSTAT_FR)/* Framing */ + } else if (cmdstat & SDMA_DESC_CMDSTAT_FR) { pi->port.icount.frame++; - else if (cmdstat & SDMA_DESC_CMDSTAT_OR) /* Overrun */ + } else if (cmdstat & SDMA_DESC_CMDSTAT_OR) { pi->port.icount.overrun++; + } cmdstat &= pi->port.read_status_mask; @@ -1080,12 +1019,12 @@ mpsc_rx_intr(struct mpsc_port_info *pi) goto next_frame; } - if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR | - SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) && - !(cmdstat & pi->port.ignore_status_mask)) - + if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR + | SDMA_DESC_CMDSTAT_FR + | SDMA_DESC_CMDSTAT_OR))) + && !(cmdstat & pi->port.ignore_status_mask)) { tty_insert_flip_char(tty, *bp, flag); - else { + } else { for (i=0; i<bytes_in; i++) tty_insert_flip_char(tty, *bp++, TTY_NORMAL); @@ -1095,29 +1034,29 @@ mpsc_rx_intr(struct mpsc_port_info *pi) next_frame: rxre->bytecnt = cpu_to_be16(0); wmb(); - rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | - SDMA_DESC_CMDSTAT_EI | - SDMA_DESC_CMDSTAT_F | - SDMA_DESC_CMDSTAT_L); + rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O + | SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F + | SDMA_DESC_CMDSTAT_L); wmb(); - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, + DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); + (ulong)rxre + MPSC_RXRE_SIZE); #endif /* Advance to next descriptor */ pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1); - rxre = (struct mpsc_rx_desc *)(pi->rxr + - (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + rxre = (struct mpsc_rx_desc *) + (pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE)); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, + DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, - (ulong)rxre + MPSC_RXRE_SIZE); + (ulong)rxre + MPSC_RXRE_SIZE); #endif - rc = 1; } @@ -1129,42 +1068,38 @@ next_frame: return rc; } -static inline void -mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) +static void mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) { struct mpsc_tx_desc *txre; - txre = (struct mpsc_tx_desc *)(pi->txr + - (pi->txr_head * MPSC_TXRE_SIZE)); + txre = (struct mpsc_tx_desc *)(pi->txr + + (pi->txr_head * MPSC_TXRE_SIZE)); txre->bytecnt = cpu_to_be16(count); txre->shadow = txre->bytecnt; wmb(); /* ensure cmdstat is last field updated */ - txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F | - SDMA_DESC_CMDSTAT_L | ((intr) ? - SDMA_DESC_CMDSTAT_EI - : 0)); + txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F + | SDMA_DESC_CMDSTAT_L + | ((intr) ? SDMA_DESC_CMDSTAT_EI : 0)); wmb(); - dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, + DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); + (ulong)txre + MPSC_TXRE_SIZE); #endif - - return; } -static inline void -mpsc_copy_tx_data(struct mpsc_port_info *pi) +static void mpsc_copy_tx_data(struct mpsc_port_info *pi) { struct circ_buf *xmit = &pi->port.info->xmit; u8 *bp; u32 i; /* Make sure the desc ring isn't full */ - while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES) < - (MPSC_TXR_ENTRIES - 1)) { + while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES) + < (MPSC_TXR_ENTRIES - 1)) { if (pi->port.x_char) { /* * Ideally, we should use the TCS field in @@ -1178,11 +1113,11 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi) *bp = pi->port.x_char; pi->port.x_char = 0; i = 1; - } - else if (!uart_circ_empty(xmit) && !uart_tx_stopped(&pi->port)){ - i = min((u32) MPSC_TXBE_SIZE, - (u32) uart_circ_chars_pending(xmit)); - i = min(i, (u32) CIRC_CNT_TO_END(xmit->head, xmit->tail, + } else if (!uart_circ_empty(xmit) + && !uart_tx_stopped(&pi->port)) { + i = min((u32)MPSC_TXBE_SIZE, + (u32)uart_circ_chars_pending(xmit)); + i = min(i, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE); memcpy(bp, &xmit->buf[xmit->tail], i); @@ -1190,27 +1125,25 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&pi->port); - } - else /* All tx data copied into ring bufs */ + } else { /* All tx data copied into ring bufs */ return; + } - dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE, + DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, - (ulong)bp + MPSC_TXBE_SIZE); + (ulong)bp + MPSC_TXBE_SIZE); #endif mpsc_setup_tx_desc(pi, i, 1); /* Advance to next descriptor */ pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1); } - - return; } -static inline int -mpsc_tx_intr(struct mpsc_port_info *pi) +static int mpsc_tx_intr(struct mpsc_port_info *pi) { struct mpsc_tx_desc *txre; int rc = 0; @@ -1219,14 +1152,15 @@ mpsc_tx_intr(struct mpsc_port_info *pi) spin_lock_irqsave(&pi->tx_lock, iflags); if (!mpsc_sdma_tx_active(pi)) { - txre = (struct mpsc_tx_desc *)(pi->txr + - (pi->txr_tail * MPSC_TXRE_SIZE)); + txre = (struct mpsc_tx_desc *)(pi->txr + + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE, + DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); + (ulong)txre + MPSC_TXRE_SIZE); #endif while (!(be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O)) { @@ -1238,14 +1172,14 @@ mpsc_tx_intr(struct mpsc_port_info *pi) if (pi->txr_head == pi->txr_tail) break; - txre = (struct mpsc_tx_desc *)(pi->txr + - (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, - DMA_FROM_DEVICE); + txre = (struct mpsc_tx_desc *)(pi->txr + + (pi->txr_tail * MPSC_TXRE_SIZE)); + dma_cache_sync(pi->port.dev, (void *)txre, + MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, - (ulong)txre + MPSC_TXRE_SIZE); + (ulong)txre + MPSC_TXRE_SIZE); #endif } @@ -1262,8 +1196,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) * the interrupt, then handle any completed Rx/Tx descriptors. When done * handling those descriptors, we restart the Rx/Tx engines if they're stopped. */ -static irqreturn_t -mpsc_sdma_intr(int irq, void *dev_id) +static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id) { struct mpsc_port_info *pi = dev_id; ulong iflags; @@ -1290,8 +1223,7 @@ mpsc_sdma_intr(int irq, void *dev_id) * ****************************************************************************** */ -static uint -mpsc_tx_empty(struct uart_port *port) +static uint mpsc_tx_empty(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; ulong iflags; @@ -1304,21 +1236,18 @@ mpsc_tx_empty(struct uart_port *port) return rc; } -static void -mpsc_set_mctrl(struct uart_port *port, uint mctrl) +static void mpsc_set_mctrl(struct uart_port *port, uint mctrl) { /* Have no way to set modem control lines AFAICT */ - return; } -static uint -mpsc_get_mctrl(struct uart_port *port) +static uint mpsc_get_mctrl(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 mflags, status; - status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m : - readl(pi->mpsc_base + MPSC_CHR_10); + status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m + : readl(pi->mpsc_base + MPSC_CHR_10); mflags = 0; if (status & 0x1) @@ -1329,19 +1258,16 @@ mpsc_get_mctrl(struct uart_port *port) return mflags | TIOCM_DSR; /* No way to tell if DSR asserted */ } -static void -mpsc_stop_tx(struct uart_port *port) +static void mpsc_stop_tx(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; pr_debug("mpsc_stop_tx[%d]\n", port->line); mpsc_freeze(pi); - return; } -static void -mpsc_start_tx(struct uart_port *port) +static void mpsc_start_tx(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; unsigned long iflags; @@ -1355,42 +1281,45 @@ mpsc_start_tx(struct uart_port *port) spin_unlock_irqrestore(&pi->tx_lock, iflags); pr_debug("mpsc_start_tx[%d]\n", port->line); - return; } -static void -mpsc_start_rx(struct mpsc_port_info *pi) +static void mpsc_start_rx(struct mpsc_port_info *pi) { pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line); - /* Issue a Receive Abort to clear any receive errors */ - writel(MPSC_CHR_2_RA, pi->mpsc_base + MPSC_CHR_2); if (pi->rcv_data) { mpsc_enter_hunt(pi); mpsc_sdma_cmd(pi, SDMA_SDCM_ERD); } - return; } -static void -mpsc_stop_rx(struct uart_port *port) +static void mpsc_stop_rx(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; pr_debug("mpsc_stop_rx[%d]: Stopping...\n", port->line); + if (pi->mirror_regs) { + writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA, + pi->mpsc_base + MPSC_CHR_2); + /* Erratum prevents reading CHR_2 so just delay for a while */ + udelay(100); + } else { + writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA, + pi->mpsc_base + MPSC_CHR_2); + + while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA) + udelay(10); + } + mpsc_sdma_cmd(pi, SDMA_SDCM_AR); - return; } -static void -mpsc_enable_ms(struct uart_port *port) +static void mpsc_enable_ms(struct uart_port *port) { - return; /* Not supported */ } -static void -mpsc_break_ctl(struct uart_port *port, int ctl) +static void mpsc_break_ctl(struct uart_port *port, int ctl) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; ulong flags; @@ -1403,12 +1332,9 @@ mpsc_break_ctl(struct uart_port *port, int ctl) pi->MPSC_CHR_1_m = v; writel(v, pi->mpsc_base + MPSC_CHR_1); spin_unlock_irqrestore(&pi->port.lock, flags); - - return; } -static int -mpsc_startup(struct uart_port *port) +static int mpsc_startup(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 flag = 0; @@ -1426,20 +1352,19 @@ mpsc_startup(struct uart_port *port) flag = IRQF_SHARED; if (request_irq(pi->port.irq, mpsc_sdma_intr, flag, - "mpsc-sdma", pi)) + "mpsc-sdma", pi)) printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n", - pi->port.irq); + pi->port.irq); mpsc_sdma_intr_unmask(pi, 0xf); - mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p + - (pi->rxr_posn * MPSC_RXRE_SIZE))); + mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p + + (pi->rxr_posn * MPSC_RXRE_SIZE))); } return rc; } -static void -mpsc_shutdown(struct uart_port *port) +static void mpsc_shutdown(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; @@ -1447,11 +1372,9 @@ mpsc_shutdown(struct uart_port *port) mpsc_sdma_stop(pi); free_irq(pi->port.irq, pi); - return; } -static void -mpsc_set_termios(struct uart_port *port, struct ktermios *termios, +static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; @@ -1508,12 +1431,11 @@ mpsc_set_termios(struct uart_port *port, struct ktermios *termios, mpsc_set_baudrate(pi, baud); /* Characters/events to read */ - pi->rcv_data = 1; pi->port.read_status_mask = SDMA_DESC_CMDSTAT_OR; if (termios->c_iflag & INPCK) - pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE | - SDMA_DESC_CMDSTAT_FR; + pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE + | SDMA_DESC_CMDSTAT_FR; if (termios->c_iflag & (BRKINT | PARMRK)) pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_BR; @@ -1522,8 +1444,8 @@ mpsc_set_termios(struct uart_port *port, struct ktermios *termios, pi->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE | - SDMA_DESC_CMDSTAT_FR; + pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE + | SDMA_DESC_CMDSTAT_FR; if (termios->c_iflag & IGNBRK) { pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_BR; @@ -1532,32 +1454,32 @@ mpsc_set_termios(struct uart_port *port, struct ktermios *termios, pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_OR; } - /* Ignore all chars if CREAD not set */ - if (!(termios->c_cflag & CREAD)) + if ((termios->c_cflag & CREAD)) { + if (!pi->rcv_data) { + pi->rcv_data = 1; + mpsc_start_rx(pi); + } + } else if (pi->rcv_data) { + mpsc_stop_rx(port); pi->rcv_data = 0; - else - mpsc_start_rx(pi); + } spin_unlock_irqrestore(&pi->port.lock, flags); - return; } -static const char * -mpsc_type(struct uart_port *port) +static const char *mpsc_type(struct uart_port *port) { pr_debug("mpsc_type[%d]: port type: %s\n", port->line,MPSC_DRIVER_NAME); return MPSC_DRIVER_NAME; } -static int -mpsc_request_port(struct uart_port *port) +static int mpsc_request_port(struct uart_port *port) { /* Should make chip/platform specific call */ return 0; } -static void -mpsc_release_port(struct uart_port *port) +static void mpsc_release_port(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; @@ -1566,18 +1488,13 @@ mpsc_release_port(struct uart_port *port) mpsc_free_ring_mem(pi); pi->ready = 0; } - - return; } -static void -mpsc_config_port(struct uart_port *port, int flags) +static void mpsc_config_port(struct uart_port *port, int flags) { - return; } -static int -mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) +static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; int rc = 0; @@ -1603,22 +1520,22 @@ mpsc_verify_port(struct uart_port *port, struct serial_struct *ser) } static struct uart_ops mpsc_pops = { - .tx_empty = mpsc_tx_empty, - .set_mctrl = mpsc_set_mctrl, - .get_mctrl = mpsc_get_mctrl, - .stop_tx = mpsc_stop_tx, - .start_tx = mpsc_start_tx, - .stop_rx = mpsc_stop_rx, - .enable_ms = mpsc_enable_ms, - .break_ctl = mpsc_break_ctl, - .startup = mpsc_startup, - .shutdown = mpsc_shutdown, - .set_termios = mpsc_set_termios, - .type = mpsc_type, - .release_port = mpsc_release_port, - .request_port = mpsc_request_port, - .config_port = mpsc_config_port, - .verify_port = mpsc_verify_port, + .tx_empty = mpsc_tx_empty, + .set_mctrl = mpsc_set_mctrl, + .get_mctrl = mpsc_get_mctrl, + .stop_tx = mpsc_stop_tx, + .start_tx = mpsc_start_tx, + .stop_rx = mpsc_stop_rx, + .enable_ms = mpsc_enable_ms, + .break_ctl = mpsc_break_ctl, + .startup = mpsc_startup, + .shutdown = mpsc_shutdown, + .set_termios = mpsc_set_termios, + .type = mpsc_type, + .release_port = mpsc_release_port, + .request_port = mpsc_request_port, + .config_port = mpsc_config_port, + .verify_port = mpsc_verify_port, }; /* @@ -1630,8 +1547,7 @@ static struct uart_ops mpsc_pops = { */ #ifdef CONFIG_SERIAL_MPSC_CONSOLE -static void -mpsc_console_write(struct console *co, const char *s, uint count) +static void mpsc_console_write(struct console *co, const char *s, uint count) { struct mpsc_port_info *pi = &mpsc_ports[co->index]; u8 *bp, *dp, add_cr = 0; @@ -1660,8 +1576,7 @@ mpsc_console_write(struct console *co, const char *s, uint count) if (add_cr) { *(dp++) = '\r'; add_cr = 0; - } - else { + } else { *(dp++) = *s; if (*(s++) == '\n') { /* add '\r' after '\n' */ @@ -1673,11 +1588,12 @@ mpsc_console_write(struct console *co, const char *s, uint count) count--; } - dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE, + DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, - (ulong)bp + MPSC_TXBE_SIZE); + (ulong)bp + MPSC_TXBE_SIZE); #endif mpsc_setup_tx_desc(pi, i, 0); pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1); @@ -1690,11 +1606,9 @@ mpsc_console_write(struct console *co, const char *s, uint count) } spin_unlock_irqrestore(&pi->tx_lock, iflags); - return; } -static int __init -mpsc_console_setup(struct console *co, char *options) +static int __init mpsc_console_setup(struct console *co, char *options) { struct mpsc_port_info *pi; int baud, bits, parity, flow; @@ -1723,17 +1637,16 @@ mpsc_console_setup(struct console *co, char *options) } static struct console mpsc_console = { - .name = MPSC_DEV_NAME, - .write = mpsc_console_write, - .device = uart_console_device, - .setup = mpsc_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &mpsc_reg, + .name = MPSC_DEV_NAME, + .write = mpsc_console_write, + .device = uart_console_device, + .setup = mpsc_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &mpsc_reg, }; -static int __init -mpsc_late_console_init(void) +static int __init mpsc_late_console_init(void) { pr_debug("mpsc_late_console_init: Enter\n"); @@ -1755,43 +1668,40 @@ late_initcall(mpsc_late_console_init); * ****************************************************************************** */ -static void -mpsc_resource_err(char *s) +static void mpsc_resource_err(char *s) { printk(KERN_WARNING "MPSC: Platform device resource error in %s\n", s); - return; } -static int -mpsc_shared_map_regs(struct platform_device *pd) +static int mpsc_shared_map_regs(struct platform_device *pd) { struct resource *r; if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_ROUTING_BASE_ORDER)) && request_mem_region(r->start, - MPSC_ROUTING_REG_BLOCK_SIZE, "mpsc_routing_regs")) { - + MPSC_ROUTING_BASE_ORDER)) + && request_mem_region(r->start, + MPSC_ROUTING_REG_BLOCK_SIZE, + "mpsc_routing_regs")) { mpsc_shared_regs.mpsc_routing_base = ioremap(r->start, - MPSC_ROUTING_REG_BLOCK_SIZE); + MPSC_ROUTING_REG_BLOCK_SIZE); mpsc_shared_regs.mpsc_routing_base_p = r->start; - } - else { + } else { mpsc_resource_err("MPSC routing base"); return -ENOMEM; } if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_SDMA_INTR_BASE_ORDER)) && request_mem_region(r->start, - MPSC_SDMA_INTR_REG_BLOCK_SIZE, "sdma_intr_regs")) { - + MPSC_SDMA_INTR_BASE_ORDER)) + && request_mem_region(r->start, + MPSC_SDMA_INTR_REG_BLOCK_SIZE, + "sdma_intr_regs")) { mpsc_shared_regs.sdma_intr_base = ioremap(r->start, MPSC_SDMA_INTR_REG_BLOCK_SIZE); mpsc_shared_regs.sdma_intr_base_p = r->start; - } - else { + } else { iounmap(mpsc_shared_regs.mpsc_routing_base); release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, - MPSC_ROUTING_REG_BLOCK_SIZE); + MPSC_ROUTING_REG_BLOCK_SIZE); mpsc_resource_err("SDMA intr base"); return -ENOMEM; } @@ -1799,18 +1709,17 @@ mpsc_shared_map_regs(struct platform_device *pd) return 0; } -static void -mpsc_shared_unmap_regs(void) +static void mpsc_shared_unmap_regs(void) { if (!mpsc_shared_regs.mpsc_routing_base) { iounmap(mpsc_shared_regs.mpsc_routing_base); release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, - MPSC_ROUTING_REG_BLOCK_SIZE); + MPSC_ROUTING_REG_BLOCK_SIZE); } if (!mpsc_shared_regs.sdma_intr_base) { iounmap(mpsc_shared_regs.sdma_intr_base); release_mem_region(mpsc_shared_regs.sdma_intr_base_p, - MPSC_SDMA_INTR_REG_BLOCK_SIZE); + MPSC_SDMA_INTR_REG_BLOCK_SIZE); } mpsc_shared_regs.mpsc_routing_base = NULL; @@ -1818,19 +1727,17 @@ mpsc_shared_unmap_regs(void) mpsc_shared_regs.mpsc_routing_base_p = 0; mpsc_shared_regs.sdma_intr_base_p = 0; - - return; } -static int -mpsc_shared_drv_probe(struct platform_device *dev) +static int mpsc_shared_drv_probe(struct platform_device *dev) { struct mpsc_shared_pdata *pdata; int rc = -ENODEV; if (dev->id == 0) { - if (!(rc = mpsc_shared_map_regs(dev))) { - pdata = (struct mpsc_shared_pdata *)dev->dev.platform_data; + if (!(rc = mpsc_shared_map_regs(dev))) { + pdata = (struct mpsc_shared_pdata *) + dev->dev.platform_data; mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; @@ -1847,8 +1754,7 @@ mpsc_shared_drv_probe(struct platform_device *dev) return rc; } -static int -mpsc_shared_drv_remove(struct platform_device *dev) +static int mpsc_shared_drv_remove(struct platform_device *dev) { int rc = -ENODEV; @@ -1869,7 +1775,7 @@ static struct platform_driver mpsc_shared_driver = { .probe = mpsc_shared_drv_probe, .remove = mpsc_shared_drv_remove, .driver = { - .name = MPSC_SHARED_NAME, + .name = MPSC_SHARED_NAME, }, }; @@ -1881,55 +1787,51 @@ static struct platform_driver mpsc_shared_driver = { ****************************************************************************** */ static struct uart_driver mpsc_reg = { - .owner = THIS_MODULE, - .driver_name = MPSC_DRIVER_NAME, - .dev_name = MPSC_DEV_NAME, - .major = MPSC_MAJOR, - .minor = MPSC_MINOR_START, - .nr = MPSC_NUM_CTLRS, - .cons = MPSC_CONSOLE, + .owner = THIS_MODULE, + .driver_name = MPSC_DRIVER_NAME, + .dev_name = MPSC_DEV_NAME, + .major = MPSC_MAJOR, + .minor = MPSC_MINOR_START, + .nr = MPSC_NUM_CTLRS, + .cons = MPSC_CONSOLE, }; -static int -mpsc_drv_map_regs(struct mpsc_port_info *pi, struct platform_device *pd) +static int mpsc_drv_map_regs(struct mpsc_port_info *pi, + struct platform_device *pd) { struct resource *r; - if ((r = platform_get_resource(pd, IORESOURCE_MEM, MPSC_BASE_ORDER)) && - request_mem_region(r->start, MPSC_REG_BLOCK_SIZE, "mpsc_regs")){ - + if ((r = platform_get_resource(pd, IORESOURCE_MEM, MPSC_BASE_ORDER)) + && request_mem_region(r->start, MPSC_REG_BLOCK_SIZE, + "mpsc_regs")) { pi->mpsc_base = ioremap(r->start, MPSC_REG_BLOCK_SIZE); pi->mpsc_base_p = r->start; - } - else { + } else { mpsc_resource_err("MPSC base"); - return -ENOMEM; + goto err; } if ((r = platform_get_resource(pd, IORESOURCE_MEM, - MPSC_SDMA_BASE_ORDER)) && request_mem_region(r->start, - MPSC_SDMA_REG_BLOCK_SIZE, "sdma_regs")) { - + MPSC_SDMA_BASE_ORDER)) + && request_mem_region(r->start, + MPSC_SDMA_REG_BLOCK_SIZE, "sdma_regs")) { pi->sdma_base = ioremap(r->start,MPSC_SDMA_REG_BLOCK_SIZE); pi->sdma_base_p = r->start; - } - else { + } else { mpsc_resource_err("SDMA base"); if (pi->mpsc_base) { iounmap(pi->mpsc_base); pi->mpsc_base = NULL; } - return -ENOMEM; + goto err; } if ((r = platform_get_resource(pd,IORESOURCE_MEM,MPSC_BRG_BASE_ORDER)) - && request_mem_region(r->start, MPSC_BRG_REG_BLOCK_SIZE, - "brg_regs")) { - + && request_mem_region(r->start, + MPSC_BRG_REG_BLOCK_SIZE, "brg_regs")) { pi->brg_base = ioremap(r->start, MPSC_BRG_REG_BLOCK_SIZE); pi->brg_base_p = r->start; - } - else { + } else { mpsc_resource_err("BRG base"); if (pi->mpsc_base) { iounmap(pi->mpsc_base); @@ -1939,14 +1841,15 @@ mpsc_drv_map_regs(struct mpsc_port_info *pi, struct platform_device *pd) iounmap(pi->sdma_base); pi->sdma_base = NULL; } - return -ENOMEM; + goto err; } - return 0; + +err: + return -ENOMEM; } -static void -mpsc_drv_unmap_regs(struct mpsc_port_info *pi) +static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi) { if (!pi->mpsc_base) { iounmap(pi->mpsc_base); @@ -1968,13 +1871,10 @@ mpsc_drv_unmap_regs(struct mpsc_port_info *pi) pi->mpsc_base_p = 0; pi->sdma_base_p = 0; pi->brg_base_p = 0; - - return; } -static void -mpsc_drv_get_platform_data(struct mpsc_port_info *pi, - struct platform_device *pd, int num) +static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, + struct platform_device *pd, int num) { struct mpsc_pdata *pdata; @@ -2009,12 +1909,9 @@ mpsc_drv_get_platform_data(struct mpsc_port_info *pi, pi->shared_regs = &mpsc_shared_regs; pi->port.irq = platform_get_irq(pd, 0); - - return; } -static int -mpsc_drv_probe(struct platform_device *dev) +static int mpsc_drv_probe(struct platform_device *dev) { struct mpsc_port_info *pi; int rc = -ENODEV; @@ -2030,47 +1927,46 @@ mpsc_drv_probe(struct platform_device *dev) if (!(rc = mpsc_make_ready(pi))) { spin_lock_init(&pi->tx_lock); if (!(rc = uart_add_one_port(&mpsc_reg, - &pi->port))) + &pi->port))) { rc = 0; - else { - mpsc_release_port( - (struct uart_port *)pi); + } else { + mpsc_release_port((struct uart_port *) + pi); mpsc_drv_unmap_regs(pi); } - } - else + } else { mpsc_drv_unmap_regs(pi); + } } } return rc; } -static int -mpsc_drv_remove(struct platform_device *dev) +static int mpsc_drv_remove(struct platform_device *dev) { pr_debug("mpsc_drv_exit: Removing MPSC %d\n", dev->id); if (dev->id < MPSC_NUM_CTLRS) { uart_remove_one_port(&mpsc_reg, &mpsc_ports[dev->id].port); - mpsc_release_port((struct uart_port *)&mpsc_ports[dev->id].port); + mpsc_release_port((struct uart_port *) + &mpsc_ports[dev->id].port); mpsc_drv_unmap_regs(&mpsc_ports[dev->id]); return 0; - } - else + } else { return -ENODEV; + } } static struct platform_driver mpsc_driver = { .probe = mpsc_drv_probe, .remove = mpsc_drv_remove, .driver = { - .name = MPSC_CTLR_NAME, + .name = MPSC_CTLR_NAME, }, }; -static int __init -mpsc_drv_init(void) +static int __init mpsc_drv_init(void) { int rc; @@ -2085,24 +1981,21 @@ mpsc_drv_init(void) platform_driver_unregister(&mpsc_shared_driver); uart_unregister_driver(&mpsc_reg); } - } - else + } else { uart_unregister_driver(&mpsc_reg); + } } return rc; - } -static void __exit -mpsc_drv_exit(void) +static void __exit mpsc_drv_exit(void) { platform_driver_unregister(&mpsc_driver); platform_driver_unregister(&mpsc_shared_driver); uart_unregister_driver(&mpsc_reg); memset(mpsc_ports, 0, sizeof(mpsc_ports)); memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs)); - return; } module_init(mpsc_drv_init); diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c index 1d9d728..2012537 100644 --- a/drivers/serial/sb1250-duart.c +++ b/drivers/serial/sb1250-duart.c @@ -25,6 +25,7 @@ #define SUPPORT_SYSRQ #endif +#include <linux/compiler.h> #include <linux/console.h> #include <linux/delay.h> #include <linux/errno.h> @@ -103,8 +104,6 @@ struct sbd_duart { static struct sbd_duart sbd_duarts[DUART_MAX_CHIP]; -#define __unused __attribute__((__unused__)) - /* * Reading and writing SB1250 DUART registers. @@ -204,12 +203,12 @@ static int sbd_receive_drain(struct sbd_port *sport) return loops; } -static int __unused sbd_transmit_ready(struct sbd_port *sport) +static int __maybe_unused sbd_transmit_ready(struct sbd_port *sport) { return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY; } -static int __unused sbd_transmit_drain(struct sbd_port *sport) +static int __maybe_unused sbd_transmit_drain(struct sbd_port *sport) { int loops = 10000; @@ -664,7 +663,7 @@ static void sbd_release_port(struct uart_port *uport) static int sbd_map_port(struct uart_port *uport) { - static const char *err = KERN_ERR "sbd: Cannot map MMIO\n"; + const char *err = KERN_ERR "sbd: Cannot map MMIO\n"; struct sbd_port *sport = to_sport(uport); struct sbd_duart *duart = sport->duart; @@ -691,8 +690,7 @@ static int sbd_map_port(struct uart_port *uport) static int sbd_request_port(struct uart_port *uport) { - static const char *err = KERN_ERR - "sbd: Unable to reserve MMIO resource\n"; + const char *err = KERN_ERR "sbd: Unable to reserve MMIO resource\n"; struct sbd_duart *duart = to_sport(uport)->duart; int map_guard; int ret = 0; @@ -755,7 +753,7 @@ static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser) } -static struct uart_ops sbd_ops = { +static const struct uart_ops sbd_ops = { .tx_empty = sbd_tx_empty, .set_mctrl = sbd_set_mctrl, .get_mctrl = sbd_get_mctrl, diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9c57486..030a606 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -626,7 +626,7 @@ static int uart_get_info(struct uart_state *state, tmp.hub6 = port->hub6; tmp.io_type = port->iotype; tmp.iomem_reg_shift = port->regshift; - tmp.iomem_base = (void *)port->mapbase; + tmp.iomem_base = (void *)(unsigned long)port->mapbase; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -1666,10 +1666,11 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) return 0; mmio = port->iotype >= UPIO_MEM; - ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d", + ret = sprintf(buf, "%d: uart:%s %s%08llX irq:%d", port->line, uart_type(port), mmio ? "mmio:0x" : "port:", - mmio ? port->mapbase : (unsigned long) port->iobase, + mmio ? (unsigned long long)port->mapbase + : (unsigned long long) port->iobase, port->irq); if (port->type == PORT_UNKNOWN) { @@ -2069,7 +2070,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) case UPIO_TSI: case UPIO_DWAPB: snprintf(address, sizeof(address), - "MMIO 0x%lx", port->mapbase); + "MMIO 0x%llx", (unsigned long long)port->mapbase); break; default: strlcpy(address, "*unknown*", sizeof(address)); diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 1deb576..b8f91e0 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -1043,8 +1043,9 @@ static int __devinit serial_txx9_probe(struct platform_device *dev) ret = serial_txx9_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " - "(IO%x MEM%lx IRQ%d): %d\n", i, - p->iobase, p->mapbase, p->irq, ret); + "(IO%x MEM%llx IRQ%d): %d\n", i, + p->iobase, (unsigned long long)p->mapbase, + p->irq, ret); } } return 0; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 672cd10..053fca4 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -12,6 +12,7 @@ * Modified to support multiple serial ports. Stuart Menefy (May 2000). * Modified to support SecureEdge. David McCullough (2002) * Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003). + * Removed SH7300 support (Jul 2007). * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -289,13 +290,7 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag) #endif #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -/* SH7300 doesn't use RTS/CTS */ -static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) -{ - sci_out(port, SCFCR, 0); -} -#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) +#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) static void sci_init_pins_scif(struct uart_port* port, unsigned int cflag) { unsigned int fcr_val = 0; diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 247fb66..cf75466 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -9,6 +9,7 @@ * Modified to support multiple serial ports. Stuart Menefy (May 2000). * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003). * Modified to support H8/300 Series Yoshinori Sato (Feb 2004). + * Removed SH7300 support (Jul 2007). */ #include <linux/serial_core.h> #include <asm/io.h> @@ -23,13 +24,10 @@ #endif #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7708) -# define SCSPTR 0xffffff7c /* 8 bit */ -# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCI_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) +#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ + defined(CONFIG_CPU_SUBTYPE_SH7707) || \ + defined(CONFIG_CPU_SUBTYPE_SH7708) || \ + defined(CONFIG_CPU_SUBTYPE_SH7709) # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ @@ -73,11 +71,6 @@ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH7300) -# define SCPCR 0xA4050116 /* 16 bit SCIF */ -# define SCPDR 0xA4050136 /* 16 bit SCIF */ -# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ # define SCI_NPORTS 2 @@ -86,12 +79,6 @@ # define PBCR 0xa4050102 # define SCSCR_INIT(port) 0x3B # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH73180) -# define SCPDR 0xA4050138 /* 16 bit SCIF */ -# define SCSPTR2 SCPDR -# define SCIF_ORER 0x0001 /* overrun error bit */ -# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7343) # define SCSPTR0 0xffe00010 /* 16 bit SCIF */ # define SCSPTR1 0xffe10010 /* 16 bit SCIF */ @@ -230,7 +217,7 @@ #define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ #define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) +#if defined(CONFIG_CPU_SUBTYPE_SH7705) #define SCIF_ORER 0x0200 #define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) #define SCIF_RFDC_MASK 0x007f @@ -259,7 +246,7 @@ # define SCxSR_ERRORS(port) SCIF_ERRORS # define SCxSR_RDxF(port) SCIF_RDF # define SCxSR_TDxE(port) SCIF_TDFE -#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) +#if defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCxSR_ORER(port) SCIF_ORER #else # define SCxSR_ORER(port) 0x0000 @@ -267,13 +254,13 @@ # define SCxSR_FER(port) SCIF_FER # define SCxSR_PER(port) SCIF_PER # define SCxSR_BRK(port) SCIF_BRK -#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) +#if defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCxSR_RDxF_CLEAR(port) (sci_in(port,SCxSR)&0xfffc) # define SCxSR_ERROR_CLEAR(port) (sci_in(port,SCxSR)&0xfd73) # define SCxSR_TDxE_CLEAR(port) (sci_in(port,SCxSR)&0xffdf) # define SCxSR_BREAK_CLEAR(port) (sci_in(port,SCxSR)&0xffe3) #else -/* SH7705 can also use this, clearing is same between 7705 and 7709 and 7300 */ +/* SH7705 can also use this, clearing is same between 7705 and 7709 */ # define SCxSR_RDxF_CLEAR(port) 0x00fc # define SCxSR_ERROR_CLEAR(port) 0x0073 # define SCxSR_TDxE_CLEAR(port) 0x00df @@ -375,8 +362,7 @@ CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size) #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) -#elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \ - defined(CONFIG_CPU_SUBTYPE_SH7705) +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) #define SCIF_FNS(name, scif_offset, scif_size) \ CPU_SCIF_FNS(name, scif_offset, scif_size) #else @@ -402,8 +388,7 @@ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \ - defined(CONFIG_CPU_SUBTYPE_SH7705) +#if defined(CONFIG_CPU_SUBTYPE_SH7705) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) @@ -485,16 +470,10 @@ static const struct __attribute__((packed)) { }; #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7708) -static inline int sci_rxd_in(struct uart_port *port) -{ - if (port->mapbase == 0xfffffe80) - return ctrl_inb(SCSPTR)&0x01 ? 1 : 0; /* SCI */ - return 1; -} -#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) +#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \ + defined(CONFIG_CPU_SUBTYPE_SH7707) || \ + defined(CONFIG_CPU_SUBTYPE_SH7708) || \ + defined(CONFIG_CPU_SUBTYPE_SH7709) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffffe80) @@ -562,18 +541,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7300) -static inline int sci_rxd_in(struct uart_port *port) -{ - if (port->mapbase == 0xa4430000) - return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */ - return 1; -} -#elif defined(CONFIG_CPU_SUBTYPE_SH73180) -static inline int sci_rxd_in(struct uart_port *port) -{ - return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */ -} #elif defined(CONFIG_CPU_SUBTYPE_SH7343) static inline int sci_rxd_in(struct uart_port *port) { @@ -721,8 +688,7 @@ static inline int sci_rxd_in(struct uart_port *port) * -- Mitch Davis - 15 Jul 2000 */ -#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \ - defined(CONFIG_CPU_SUBTYPE_SH7780) || \ +#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 85309ac..6fd51b0 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -65,7 +65,9 @@ static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { }, }; +#ifdef CONFIG_SERIAL_VR41XX_CONSOLE static uint8_t lsr_break_flag[SIU_PORTS_MAX]; +#endif #define siu_read(port, offset) readb((port)->membase + (offset)) #define siu_write(port, offset, value) writeb((value), (port)->membase + (offset)) @@ -782,7 +784,7 @@ static void siu_console_write(struct console *con, const char *s, unsigned count siu_write(port, UART_IER, ier); } -static int siu_console_setup(struct console *con, char *options) +static int __init siu_console_setup(struct console *con, char *options) { struct uart_port *port; int baud = 9600; @@ -800,7 +802,8 @@ static int siu_console_setup(struct console *con, char *options) port->membase = ioremap(port->mapbase, siu_port_size(port)); } - vr41xx_select_siu_interface(SIU_INTERFACE_RS232C); + if (port->type == PORT_VR41XX_SIU) + vr41xx_select_siu_interface(SIU_INTERFACE_RS232C); if (options != NULL) uart_parse_options(options, &baud, &parity, &bits, &flow); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b05de30..e84d215 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -200,6 +200,8 @@ static DEFINE_MUTEX(board_lock); * platforms may not be able to use spi_register_board_info though, and * this is exported so that for example a USB or parport based adapter * driver could add devices (which it would learn about out-of-band). + * + * Returns the new device, or NULL. */ struct spi_device *spi_new_device(struct spi_master *master, struct spi_board_info *chip) @@ -208,7 +210,20 @@ struct spi_device *spi_new_device(struct spi_master *master, struct device *dev = master->cdev.dev; int status; - /* NOTE: caller did any chip->bus_num checks necessary */ + /* NOTE: caller did any chip->bus_num checks necessary. + * + * Also, unless we change the return value convention to use + * error-or-pointer (not NULL-or-pointer), troubleshootability + * suggests syslogged diagnostics are best here (ugh). + */ + + /* Chipselects are numbered 0..max; validate. */ + if (chip->chip_select >= master->num_chipselect) { + dev_err(dev, "cs%d > max %d\n", + chip->chip_select, + master->num_chipselect); + return NULL; + } if (!spi_master_get(master)) return NULL; @@ -236,10 +251,10 @@ struct spi_device *spi_new_device(struct spi_master *master, proxy->controller_state = NULL; proxy->dev.release = spidev_release; - /* drivers may modify this default i/o setup */ + /* drivers may modify this initial i/o setup */ status = master->setup(proxy); if (status < 0) { - dev_dbg(dev, "can't %s %s, status %d\n", + dev_err(dev, "can't %s %s, status %d\n", "setup", proxy->dev.bus_id, status); goto fail; } @@ -249,7 +264,7 @@ struct spi_device *spi_new_device(struct spi_master *master, */ status = device_register(&proxy->dev); if (status < 0) { - dev_dbg(dev, "can't %s %s, status %d\n", + dev_err(dev, "can't %s %s, status %d\n", "add", proxy->dev.bus_id, status); goto fail; } @@ -306,7 +321,6 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) static void scan_boardinfo(struct spi_master *master) { struct boardinfo *bi; - struct device *dev = master->cdev.dev; mutex_lock(&board_lock); list_for_each_entry(bi, &board_list, list) { @@ -316,17 +330,9 @@ static void scan_boardinfo(struct spi_master *master) for (n = bi->n_board_info; n > 0; n--, chip++) { if (chip->bus_num != master->bus_num) continue; - /* some controllers only have one chip, so they - * might not use chipselects. otherwise, the - * chipselects are numbered 0..max. + /* NOTE: this relies on spi_new_device to + * issue diagnostics when given bogus inputs */ - if (chip->chip_select >= master->num_chipselect - && master->num_chipselect) { - dev_dbg(dev, "cs%d > max %d\n", - chip->chip_select, - master->num_chipselect); - continue; - } (void) spi_new_device(master, chip); } } @@ -419,8 +425,17 @@ int spi_register_master(struct spi_master *master) if (!dev) return -ENODEV; + /* even if it's just one always-selected device, there must + * be at least one chipselect + */ + if (master->num_chipselect == 0) + return -EINVAL; + /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num < 0) { + /* FIXME switch to an IDR based scheme, something like + * I2C now uses, so we can't run out of "dynamic" IDs + */ master->bus_num = atomic_dec_return(&dyn_bus_id); dynamic = 1; } diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 3295cfc..0c16a2b 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -39,6 +39,7 @@ struct mpc83xx_spi_reg { }; /* SPI Controller mode register definitions */ +#define SPMODE_LOOP (1 << 30) #define SPMODE_CI_INACTIVEHIGH (1 << 29) #define SPMODE_CP_BEGIN_EDGECLK (1 << 28) #define SPMODE_DIV16 (1 << 27) @@ -153,12 +154,18 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) len = len - 1; /* mask out bits we are going to set */ - regval &= ~0x38ff0000; + regval &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH + | SPMODE_LEN(0xF) | SPMODE_DIV16 + | SPMODE_PM(0xF) | SPMODE_REV | SPMODE_LOOP); if (spi->mode & SPI_CPHA) regval |= SPMODE_CP_BEGIN_EDGECLK; if (spi->mode & SPI_CPOL) regval |= SPMODE_CI_INACTIVEHIGH; + if (!(spi->mode & SPI_LSB_FIRST)) + regval |= SPMODE_REV; + if (spi->mode & SPI_LOOP) + regval |= SPMODE_LOOP; regval |= SPMODE_LEN(len); @@ -176,6 +183,8 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) regval |= SPMODE_PM(pm); } + /* Turn off SPI unit prior changing mode */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); if (mpc83xx_spi->activate_cs) mpc83xx_spi->activate_cs(spi->chip_select, pol); @@ -231,6 +240,14 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } else return -EINVAL; + if (mpc83xx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) { + mpc83xx_spi->tx_shift = 0; + if (bits_per_word <= 8) + mpc83xx_spi->rx_shift = 8; + else + mpc83xx_spi->rx_shift = 0; + } + /* nsecs = (clock period)/2 */ if (!hz) hz = spi->max_speed_hz; @@ -245,17 +262,22 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); - /* Mask out bits_per_wordgth */ - regval &= 0xff0fffff; + /* mask out bits we are going to set */ + regval &= ~(SPMODE_LEN(0xF) | SPMODE_REV); regval |= SPMODE_LEN(bits_per_word); + if (!(spi->mode & SPI_LSB_FIRST)) + regval |= SPMODE_REV; + /* Turn off SPI unit prior changing mode */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); return 0; } /* the spi->mode bits understood by this driver: */ -#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) +#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_LOOP) static int mpc83xx_spi_setup(struct spi_device *spi) { diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 7071ff8..5cf4812 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -28,7 +28,7 @@ #include <asm/hardware.h> #include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-spi.h> +#include <asm/plat-s3c24xx/regs-spi.h> #include <asm/arch/spi.h> struct s3c24xx_spi { diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 38b60ad..630f781 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -55,9 +55,16 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; -/* Bit masks for spi_device.mode management */ -#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL) - +/* Bit masks for spi_device.mode management. Note that incorrect + * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other + * devices on a shared bus: CS_HIGH, because this device will be + * active when it shouldn't be; 3WIRE, because when active it won't + * behave as it should. + * + * REVISIT should changing those two modes be privileged? + */ +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) struct spidev_data { struct device dev; diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index befff5f..ac49b15 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SISUSBVGA) += misc/ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/ obj-$(CONFIG_USB_USS720) += misc/ +obj-$(CONFIG_USB_IOWARRIOR) += misc/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 25f63f1..b6bd05e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -18,9 +18,17 @@ #include "hcd.h" /* for usbcore internals */ #include "usb.h" +struct api_context { + struct completion done; + int status; +}; + static void usb_api_blocking_completion(struct urb *urb) { - complete((struct completion *)urb->context); + struct api_context *ctx = urb->context; + + ctx->status = urb->status; + complete(&ctx->done); } @@ -32,20 +40,21 @@ static void usb_api_blocking_completion(struct urb *urb) */ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { - struct completion done; + struct api_context ctx; unsigned long expire; int retval; - int status = urb->status; - init_completion(&done); - urb->context = &done; + init_completion(&ctx.done); + urb->context = &ctx; urb->actual_length = 0; retval = usb_submit_urb(urb, GFP_NOIO); if (unlikely(retval)) goto out; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&done, expire)) { + if (!wait_for_completion_timeout(&ctx.done, expire)) { + usb_kill_urb(urb); + retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); dev_dbg(&urb->dev->dev, "%s timed out on ep%d%s len=%d/%d\n", @@ -54,11 +63,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) usb_pipein(urb->pipe) ? "in" : "out", urb->actual_length, urb->transfer_buffer_length); - - usb_kill_urb(urb); - retval = status == -ENOENT ? -ETIMEDOUT : status; } else - retval = status; + retval = ctx.status; out: if (actual_length) *actual_length = urb->actual_length; @@ -411,15 +417,22 @@ int usb_sg_init ( * Some systems need to revert to PIO when DMA is temporarily * unavailable. For their sakes, both transfer_buffer and * transfer_dma are set when possible. However this can only - * work on systems without HIGHMEM, since DMA buffers located - * in high memory are not directly addressable by the CPU for - * PIO ... so when HIGHMEM is in use, transfer_buffer is NULL + * work on systems without: + * + * - HIGHMEM, since DMA buffers located in high memory are + * not directly addressable by the CPU for PIO; + * + * - IOMMU, since dma_map_sg() is allowed to use an IOMMU to + * make virtually discontiguous buffers be "dma-contiguous" + * so that PIO and DMA need diferent numbers of URBs. + * + * So when HIGHMEM or IOMMU are in use, transfer_buffer is NULL * to prevent stale pointers and to help spot bugs. */ if (dma) { io->urbs [i]->transfer_dma = sg_dma_address (sg + i); len = sg_dma_len (sg + i); -#ifdef CONFIG_HIGHMEM +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU) io->urbs[i]->transfer_buffer = NULL; #else io->urbs[i]->transfer_buffer = diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index aa21b38..b7917c5 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -30,18 +30,40 @@ static const struct usb_device_id usb_quirk_list[] = { /* HP 5300/5370C scanner */ { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */ + { USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Benq S2W 3300U */ { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Canon, Inc. CanoScan N1240U/LiDE30 */ + { USB_DEVICE(0x04a9, 0x220e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Canon, Inc. CanoScan N650U/N656U */ + { USB_DEVICE(0x04a9, 0x2206), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Canon, Inc. CanoScan 1220U */ + { USB_DEVICE(0x04a9, 0x2207), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Canon, Inc. CanoScan N670U/N676U/LiDE 20 */ + { USB_DEVICE(0x04a9, 0x220d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* old Cannon scanner */ + { USB_DEVICE(0x04a9, 0x2220), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Seiko Epson Corp. Perfection 1200 */ { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Seiko Epson Corp. Perfection 660 */ + { USB_DEVICE(0x04b8, 0x0114), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Epson Perfection 1260 Photo */ + { USB_DEVICE(0x04b8, 0x011d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Seiko Epson Corp - Perfection 1670 */ { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* EPSON Perfection 2480 */ + { USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Seiko Epson Corp.*/ + { USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Samsung ML-2510 Series printer */ { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Elsa MicroLink 56k (V.250) */ { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Ultima Electronics Corp.*/ { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, + /* Agfa Snapscan1212u */ + { USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, /* Umax [hex] Astra 3400U */ { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index d18901b..c6760ae 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -50,7 +50,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen, return -EINVAL; /* fill buffer from src[] until null descriptor ptr */ - for (; 0 != *src; src++) { + for (; NULL != *src; src++) { unsigned len = (*src)->bLength; if (len > buflen) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 6042364..3aa46cf 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -71,7 +71,7 @@ ep_matches ( u16 max; /* endpoint already claimed? */ - if (0 != ep->driver_data) + if (NULL != ep->driver_data) return 0; /* only support ep0 for portable CONTROL traffic */ diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index a337673..593e235 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1723,7 +1723,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) size += sizeof (struct rndis_packet_msg_type); size -= size % dev->out_ep->maxpacket; - if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { + skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); + if (skb == NULL) { DEBUG (dev, "no rx skb\n"); goto enomem; } diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index e60745ff..173004f 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -964,7 +964,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) } if (len > sizeof (dev->rbuf)) req->buf = kmalloc(len, GFP_ATOMIC); - if (req->buf == 0) { + if (req->buf == NULL) { req->buf = dev->rbuf; return -ENOMEM; } @@ -1394,7 +1394,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) dev->setup_abort = 0; if (dev->state == STATE_DEV_UNCONNECTED) { #ifdef CONFIG_USB_GADGET_DUALSPEED - if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) { + if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == NULL) { spin_unlock(&dev->lock); ERROR (dev, "no high speed config??\n"); return -EINVAL; diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 700dda8..4b27d12 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1299,7 +1299,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == 0) /* control */ + if (ep->desc == NULL) /* control */ start_ep0(ep, req); else { if (request && !ep->busy) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 63b9521..72b4ebb 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -93,8 +93,6 @@ static const char driver_name [] = "pxa2xx_udc"; static const char ep0name [] = "ep0"; -// #define DISABLE_TEST_MODE - #ifdef CONFIG_ARCH_IXP4XX /* cpu-specific register addresses are compiled in to this code */ @@ -113,17 +111,6 @@ static const char ep0name [] = "ep0"; #define SIZE_STR "" #endif -#ifdef DISABLE_TEST_MODE -/* (mode == 0) == no undocumented chip tweaks - * (mode & 1) == double buffer bulk IN - * (mode & 2) == double buffer bulk OUT - * ... so mode = 3 (or 7, 15, etc) does it for both - */ -static ushort fifo_mode = 0; -module_param(fifo_mode, ushort, 0); -MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode"); -#endif - /* --------------------------------------------------------------------------- * endpoint related parts of the api to the usb controller hardware, * used by gadget driver; and the inner talker-to-hardware core. @@ -1252,23 +1239,6 @@ static void udc_enable (struct pxa2xx_udc *dev) UDC_RES2 = 0x00; } -#ifdef DISABLE_TEST_MODE - /* "test mode" seems to have become the default in later chip - * revs, preventing double buffering (and invalidating docs). - * this EXPERIMENT enables it for bulk endpoints by tweaking - * undefined/reserved register bits (that other drivers clear). - * Belcarra code comments noted this usage. - */ - if (fifo_mode & 1) { /* IN endpoints */ - UDC_RES1 |= USIR0_IR1|USIR0_IR6; - UDC_RES2 |= USIR1_IR11; - } - if (fifo_mode & 2) { /* OUT endpoints */ - UDC_RES1 |= USIR0_IR2|USIR0_IR7; - UDC_RES2 |= USIR1_IR12; - } -#endif - /* enable suspend/resume and reset irqs */ udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index a2e6e3f..fcfe869 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -653,7 +653,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) result = usb_ep_enable (ep, d); if (result == 0) { ep->driver_data = dev; - if (source_sink_start_ep (ep, gfp_flags) != 0) { + if (source_sink_start_ep(ep, gfp_flags) + != NULL) { dev->in_ep = ep; continue; } @@ -667,7 +668,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) result = usb_ep_enable (ep, d); if (result == 0) { ep->driver_data = dev; - if (source_sink_start_ep (ep, gfp_flags) != 0) { + if (source_sink_start_ep(ep, gfp_flags) + != NULL) { dev->out_ep = ep; continue; } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index e831cb7..33f6ee5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -356,7 +356,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { + if (!port->tty || !port->tty->termios) { dbg("%s - no tty structures", __FUNCTION__); return; } @@ -526,50 +526,35 @@ static void cp2101_set_termios (struct usb_serial_port *port, return; } cflag = port->tty->termios->c_cflag; - - /* Check that they really want us to change something */ - if (old_termios) { - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(port->tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) { - dbg("%s - nothing to change...", __FUNCTION__); - return; - } - - old_cflag = old_termios->c_cflag; - } + old_cflag = old_termios->c_cflag; + baud = tty_get_baud_rate(port->tty); /* If the baud rate is to be updated*/ - if ((cflag & CBAUD) != (old_cflag & CBAUD)) { - switch (cflag & CBAUD) { - /* - * The baud rates which are commented out below - * appear to be supported by the device - * but are non-standard - */ - case B0: baud = 0; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - /*case B7200: baud = 7200; break;*/ - case B9600: baud = 9600; break; - /*ase B14400: baud = 14400; break;*/ - case B19200: baud = 19200; break; - /*case B28800: baud = 28800; break;*/ - case B38400: baud = 38400; break; - /*case B55854: baud = 55054; break;*/ - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - /*case B127117: baud = 127117; break;*/ - case B230400: baud = 230400; break; - case B460800: baud = 460800; break; - case B921600: baud = 921600; break; - /*case B3686400: baud = 3686400; break;*/ + if (baud != tty_termios_baud_rate(old_termios)) { + switch (baud) { + case 0: + case 600: + case 1200: + case 1800: + case 2400: + case 4800: + case 7200: + case 9600: + case 14400: + case 19200: + case 28800: + case 38400: + case 55854: + case 57600: + case 115200: + case 127117: + case 230400: + case 460800: + case 921600: + case 3686400: + break; default: - dev_err(&port->dev, "cp2101 driver does not " - "support the baudrate requested\n"); + baud = 9600; break; } diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 976f54e..dab2e66 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -433,38 +433,38 @@ struct digi_port { /* Local Function Declarations */ -static void digi_wakeup_write( struct usb_serial_port *port ); +static void digi_wakeup_write(struct usb_serial_port *port); static void digi_wakeup_write_lock(struct work_struct *work); -static int digi_write_oob_command( struct usb_serial_port *port, - unsigned char *buf, int count, int interruptible ); -static int digi_write_inb_command( struct usb_serial_port *port, - unsigned char *buf, int count, unsigned long timeout ); -static int digi_set_modem_signals( struct usb_serial_port *port, - unsigned int modem_signals, int interruptible ); -static int digi_transmit_idle( struct usb_serial_port *port, - unsigned long timeout ); +static int digi_write_oob_command(struct usb_serial_port *port, + unsigned char *buf, int count, int interruptible); +static int digi_write_inb_command(struct usb_serial_port *port, + unsigned char *buf, int count, unsigned long timeout); +static int digi_set_modem_signals(struct usb_serial_port *port, + unsigned int modem_signals, int interruptible); +static int digi_transmit_idle(struct usb_serial_port *port, + unsigned long timeout); static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); -static void digi_set_termios( struct usb_serial_port *port, - struct ktermios *old_termios ); -static void digi_break_ctl( struct usb_serial_port *port, int break_state ); -static int digi_ioctl( struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg ); -static int digi_tiocmget( struct usb_serial_port *port, struct file *file ); -static int digi_tiocmset( struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear ); -static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ); -static void digi_write_bulk_callback( struct urb *urb ); -static int digi_write_room( struct usb_serial_port *port ); -static int digi_chars_in_buffer( struct usb_serial_port *port ); -static int digi_open( struct usb_serial_port *port, struct file *filp ); -static void digi_close( struct usb_serial_port *port, struct file *filp ); -static int digi_startup_device( struct usb_serial *serial ); -static int digi_startup( struct usb_serial *serial ); -static void digi_shutdown( struct usb_serial *serial ); -static void digi_read_bulk_callback( struct urb *urb ); -static int digi_read_inb_callback( struct urb *urb ); -static int digi_read_oob_callback( struct urb *urb ); +static void digi_set_termios(struct usb_serial_port *port, + struct ktermios *old_termios); +static void digi_break_ctl(struct usb_serial_port *port, int break_state); +static int digi_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg); +static int digi_tiocmget(struct usb_serial_port *port, struct file *file); +static int digi_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear); +static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count); +static void digi_write_bulk_callback(struct urb *urb); +static int digi_write_room(struct usb_serial_port *port); +static int digi_chars_in_buffer(struct usb_serial_port *port); +static int digi_open(struct usb_serial_port *port, struct file *filp); +static void digi_close(struct usb_serial_port *port, struct file *filp); +static int digi_startup_device(struct usb_serial *serial); +static int digi_startup(struct usb_serial *serial); +static void digi_shutdown(struct usb_serial *serial); +static void digi_read_bulk_callback(struct urb *urb); +static int digi_read_inb_callback(struct urb *urb); +static int digi_read_oob_callback(struct urb *urb); /* Statics */ @@ -576,9 +576,9 @@ static struct usb_serial_driver digi_acceleport_4_device = { * with the equivalent code. */ -static inline long cond_wait_interruptible_timeout_irqrestore( +static long cond_wait_interruptible_timeout_irqrestore( wait_queue_head_t *q, long timeout, - spinlock_t *lock, unsigned long flags ) + spinlock_t *lock, unsigned long flags) { DEFINE_WAIT(wait); @@ -600,18 +600,16 @@ static inline long cond_wait_interruptible_timeout_irqrestore( static void digi_wakeup_write_lock(struct work_struct *work) { - struct digi_port *priv = - container_of(work, struct digi_port, dp_wakeup_work); + struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work); struct usb_serial_port *port = priv->dp_port; unsigned long flags; - - spin_lock_irqsave( &priv->dp_port_lock, flags ); - digi_wakeup_write( port ); - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); + digi_wakeup_write(port); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); } -static void digi_wakeup_write( struct usb_serial_port *port ) +static void digi_wakeup_write(struct usb_serial_port *port) { tty_wakeup(port->tty); } @@ -628,8 +626,8 @@ static void digi_wakeup_write( struct usb_serial_port *port ) * returned by usb_submit_urb. */ -static int digi_write_oob_command( struct usb_serial_port *port, - unsigned char *buf, int count, int interruptible ) +static int digi_write_oob_command(struct usb_serial_port *port, + unsigned char *buf, int count, int interruptible) { int ret = 0; @@ -638,49 +636,37 @@ static int digi_write_oob_command( struct usb_serial_port *port, struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); unsigned long flags = 0; + dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count); -dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count ); - - spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); - - while( count > 0 ) { - - while( oob_port->write_urb->status == -EINPROGRESS - || oob_priv->dp_write_urb_in_use ) { + spin_lock_irqsave(&oob_priv->dp_port_lock, flags); + while(count > 0) { + while(oob_port->write_urb->status == -EINPROGRESS + || oob_priv->dp_write_urb_in_use) { cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, - &oob_priv->dp_port_lock, flags ); - if( interruptible && signal_pending(current) ) { - return( -EINTR ); - } - spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); + &oob_priv->dp_port_lock, flags); + if (interruptible && signal_pending(current)) + return -EINTR; + spin_lock_irqsave(&oob_priv->dp_port_lock, flags); } /* len must be a multiple of 4, so commands are not split */ - len = min(count, oob_port->bulk_out_size ); - if( len > 4 ) + len = min(count, oob_port->bulk_out_size); + if (len > 4) len &= ~3; - - memcpy( oob_port->write_urb->transfer_buffer, buf, len ); + memcpy(oob_port->write_urb->transfer_buffer, buf, len); oob_port->write_urb->transfer_buffer_length = len; oob_port->write_urb->dev = port->serial->dev; - - if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) { + if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) { oob_priv->dp_write_urb_in_use = 1; count -= len; buf += len; } - - } - - spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); - - if( ret ) { - err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, - ret ); } - - return( ret ); + spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags); + if (ret) + err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret); + return ret; } @@ -697,63 +683,58 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co * error returned by digi_write. */ -static int digi_write_inb_command( struct usb_serial_port *port, - unsigned char *buf, int count, unsigned long timeout ) +static int digi_write_inb_command(struct usb_serial_port *port, + unsigned char *buf, int count, unsigned long timeout) { - int ret = 0; int len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; unsigned long flags = 0; + dbg("digi_write_inb_command: TOP: port=%d, count=%d", + priv->dp_port_num, count); -dbg( "digi_write_inb_command: TOP: port=%d, count=%d", priv->dp_port_num, -count ); - - if( timeout ) + if (timeout) timeout += jiffies; else timeout = ULONG_MAX; - spin_lock_irqsave( &priv->dp_port_lock, flags ); - - while( count > 0 && ret == 0 ) { - - while( (port->write_urb->status == -EINPROGRESS - || priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) { + spin_lock_irqsave(&priv->dp_port_lock, flags); + while(count > 0 && ret == 0) { + while((port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) { cond_wait_interruptible_timeout_irqrestore( &port->write_wait, DIGI_RETRY_TIMEOUT, - &priv->dp_port_lock, flags ); - if( signal_pending(current) ) { - return( -EINTR ); - } - spin_lock_irqsave( &priv->dp_port_lock, flags ); + &priv->dp_port_lock, flags); + if (signal_pending(current)) + return -EINTR; + spin_lock_irqsave(&priv->dp_port_lock, flags); } /* len must be a multiple of 4 and small enough to */ /* guarantee the write will send buffered data first, */ /* so commands are in order with data and not split */ - len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len ); - if( len > 4 ) + len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len); + if (len > 4) len &= ~3; /* write any buffered data first */ - if( priv->dp_out_buf_len > 0 ) { + if (priv->dp_out_buf_len > 0) { data[0] = DIGI_CMD_SEND_DATA; data[1] = priv->dp_out_buf_len; - memcpy( data+2, priv->dp_out_buf, - priv->dp_out_buf_len ); - memcpy( data+2+priv->dp_out_buf_len, buf, len ); + memcpy(data + 2, priv->dp_out_buf, + priv->dp_out_buf_len); + memcpy(data + 2 + priv->dp_out_buf_len, buf, len); port->write_urb->transfer_buffer_length - = priv->dp_out_buf_len+2+len; + = priv->dp_out_buf_len + 2 + len; } else { - memcpy( data, buf, len ); + memcpy(data, buf, len); port->write_urb->transfer_buffer_length = len; } port->write_urb->dev = port->serial->dev; - if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { + if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; count -= len; @@ -761,16 +742,12 @@ count ); } } + spin_unlock_irqrestore(&priv->dp_port_lock, flags); - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - - if( ret ) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, - ret, priv->dp_port_num ); - } - - return( ret ); - + if (ret) + err("%s: usb_submit_urb failed, ret=%d, port=%d", + __FUNCTION__, ret, priv->dp_port_num); + return ret; } @@ -784,8 +761,8 @@ count ); * returned by usb_submit_urb. */ -static int digi_set_modem_signals( struct usb_serial_port *port, - unsigned int modem_signals, int interruptible ) +static int digi_set_modem_signals(struct usb_serial_port *port, + unsigned int modem_signals, int interruptible) { int ret; @@ -796,60 +773,47 @@ static int digi_set_modem_signals( struct usb_serial_port *port, unsigned long flags = 0; -dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", -port_priv->dp_port_num, modem_signals ); + dbg("digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", + port_priv->dp_port_num, modem_signals); - spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); - spin_lock( &port_priv->dp_port_lock ); + spin_lock_irqsave(&oob_priv->dp_port_lock, flags); + spin_lock(&port_priv->dp_port_lock); - while( oob_port->write_urb->status == -EINPROGRESS - || oob_priv->dp_write_urb_in_use ) { - spin_unlock( &port_priv->dp_port_lock ); + while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) { + spin_unlock(&port_priv->dp_port_lock); cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, - &oob_priv->dp_port_lock, flags ); - if( interruptible && signal_pending(current) ) { - return( -EINTR ); - } - spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); - spin_lock( &port_priv->dp_port_lock ); + &oob_priv->dp_port_lock, flags); + if (interruptible && signal_pending(current)) + return -EINTR; + spin_lock_irqsave(&oob_priv->dp_port_lock, flags); + spin_lock(&port_priv->dp_port_lock); } - data[0] = DIGI_CMD_SET_DTR_SIGNAL; data[1] = port_priv->dp_port_num; - data[2] = (modem_signals&TIOCM_DTR) ? - DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; + data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; data[3] = 0; - data[4] = DIGI_CMD_SET_RTS_SIGNAL; data[5] = port_priv->dp_port_num; - data[6] = (modem_signals&TIOCM_RTS) ? - DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; + data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; data[7] = 0; oob_port->write_urb->transfer_buffer_length = 8; oob_port->write_urb->dev = port->serial->dev; - if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) { + if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) { oob_priv->dp_write_urb_in_use = 1; port_priv->dp_modem_signals = (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) | (modem_signals&(TIOCM_DTR|TIOCM_RTS)); } - - spin_unlock( &port_priv->dp_port_lock ); - spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); - - if( ret ) { - err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, - ret ); - } - - return( ret ); - + spin_unlock(&port_priv->dp_port_lock); + spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags); + if (ret) + err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret); + return ret; } - /* * Digi Transmit Idle * @@ -862,203 +826,182 @@ port_priv->dp_port_num, modem_signals ); * port at a time, so its ok. */ -static int digi_transmit_idle( struct usb_serial_port *port, - unsigned long timeout ) +static int digi_transmit_idle(struct usb_serial_port *port, + unsigned long timeout) { - int ret; unsigned char buf[2]; struct digi_port *priv = usb_get_serial_port_data(port); unsigned long flags = 0; - - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_transmit_idle = 0; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); buf[0] = DIGI_CMD_TRANSMIT_IDLE; buf[1] = 0; timeout += jiffies; - if( (ret=digi_write_inb_command( port, buf, 2, timeout-jiffies )) != 0 ) - return( ret ); + if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0) + return ret; - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); - while( time_before(jiffies, timeout) && !priv->dp_transmit_idle ) { + while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) { cond_wait_interruptible_timeout_irqrestore( &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT, - &priv->dp_port_lock, flags ); - if( signal_pending(current) ) { - return( -EINTR ); - } - spin_lock_irqsave( &priv->dp_port_lock, flags ); + &priv->dp_port_lock, flags); + if (signal_pending(current)) + return -EINTR; + spin_lock_irqsave(&priv->dp_port_lock, flags); } - priv->dp_transmit_idle = 0; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - - return( 0 ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + return 0; } -static void digi_rx_throttle( struct usb_serial_port *port ) +static void digi_rx_throttle(struct usb_serial_port *port) { - unsigned long flags; struct digi_port *priv = usb_get_serial_port_data(port); -dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num ); + dbg("digi_rx_throttle: TOP: port=%d", priv->dp_port_num); /* stop receiving characters by not resubmitting the read urb */ - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_throttled = 1; priv->dp_throttle_restart = 0; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - + spin_unlock_irqrestore(&priv->dp_port_lock, flags); } -static void digi_rx_unthrottle( struct usb_serial_port *port ) +static void digi_rx_unthrottle(struct usb_serial_port *port) { - int ret = 0; unsigned long flags; struct digi_port *priv = usb_get_serial_port_data(port); -dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); + dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num); - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); /* turn throttle off */ priv->dp_throttled = 0; priv->dp_throttle_restart = 0; /* restart read chain */ - if( priv->dp_throttle_restart ) { + if (priv->dp_throttle_restart) { port->read_urb->dev = port->serial->dev; - ret = usb_submit_urb( port->read_urb, GFP_ATOMIC ); + ret = usb_submit_urb(port->read_urb, GFP_ATOMIC); } - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - - if( ret ) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, - ret, priv->dp_port_num ); - } + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + if (ret) + err("%s: usb_submit_urb failed, ret=%d, port=%d", + __FUNCTION__, ret, priv->dp_port_num); } -static void digi_set_termios( struct usb_serial_port *port, - struct ktermios *old_termios ) +static void digi_set_termios(struct usb_serial_port *port, + struct ktermios *old_termios) { struct digi_port *priv = usb_get_serial_port_data(port); - unsigned int iflag = port->tty->termios->c_iflag; - unsigned int cflag = port->tty->termios->c_cflag; + struct tty_struct *tty = port->tty; + unsigned int iflag = tty->termios->c_iflag; + unsigned int cflag = tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int old_cflag = old_termios->c_cflag; unsigned char buf[32]; unsigned int modem_signals; int arg,ret; int i = 0; + speed_t baud; - -dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag ); + dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag); /* set baud rate */ - if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { - + if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) { arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ - if( (old_cflag&CBAUD) == B0 ) { + if ((old_cflag&CBAUD) == B0) { /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; - if( !(port->tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &port->tty->flags) ) { + if (!(tty->termios->c_cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) modem_signals |= TIOCM_RTS; - } - digi_set_modem_signals( port, modem_signals, 1 ); + digi_set_modem_signals(port, modem_signals, 1); } - - switch( (cflag&CBAUD) ) { + switch (baud) { /* drop DTR and RTS on transition to B0 */ - case B0: digi_set_modem_signals( port, 0, 1 ); break; - case B50: arg = DIGI_BAUD_50; break; - case B75: arg = DIGI_BAUD_75; break; - case B110: arg = DIGI_BAUD_110; break; - case B150: arg = DIGI_BAUD_150; break; - case B200: arg = DIGI_BAUD_200; break; - case B300: arg = DIGI_BAUD_300; break; - case B600: arg = DIGI_BAUD_600; break; - case B1200: arg = DIGI_BAUD_1200; break; - case B1800: arg = DIGI_BAUD_1800; break; - case B2400: arg = DIGI_BAUD_2400; break; - case B4800: arg = DIGI_BAUD_4800; break; - case B9600: arg = DIGI_BAUD_9600; break; - case B19200: arg = DIGI_BAUD_19200; break; - case B38400: arg = DIGI_BAUD_38400; break; - case B57600: arg = DIGI_BAUD_57600; break; - case B115200: arg = DIGI_BAUD_115200; break; - case B230400: arg = DIGI_BAUD_230400; break; - case B460800: arg = DIGI_BAUD_460800; break; - default: - dbg( "digi_set_termios: can't handle baud rate 0x%x", - (cflag&CBAUD) ); - break; + case 0: digi_set_modem_signals(port, 0, 1); break; + case 50: arg = DIGI_BAUD_50; break; + case 75: arg = DIGI_BAUD_75; break; + case 110: arg = DIGI_BAUD_110; break; + case 150: arg = DIGI_BAUD_150; break; + case 200: arg = DIGI_BAUD_200; break; + case 300: arg = DIGI_BAUD_300; break; + case 600: arg = DIGI_BAUD_600; break; + case 1200: arg = DIGI_BAUD_1200; break; + case 1800: arg = DIGI_BAUD_1800; break; + case 2400: arg = DIGI_BAUD_2400; break; + case 4800: arg = DIGI_BAUD_4800; break; + case 9600: arg = DIGI_BAUD_9600; break; + case 19200: arg = DIGI_BAUD_19200; break; + case 38400: arg = DIGI_BAUD_38400; break; + case 57600: arg = DIGI_BAUD_57600; break; + case 115200: arg = DIGI_BAUD_115200; break; + case 230400: arg = DIGI_BAUD_230400; break; + case 460800: arg = DIGI_BAUD_460800; break; + default: + arg = DIGI_BAUD_9600; + baud = 9600; + break; } - - if( arg != -1 ) { + if (arg != -1) { buf[i++] = DIGI_CMD_SET_BAUD_RATE; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } - } - /* set parity */ - if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { - - if( (cflag&PARENB) ) { - if( (cflag&PARODD) ) + if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) { + if (cflag&PARENB) { + if (cflag&PARODD) arg = DIGI_PARITY_ODD; else arg = DIGI_PARITY_EVEN; } else { arg = DIGI_PARITY_NONE; } - buf[i++] = DIGI_CMD_SET_PARITY; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; - } - /* set word size */ - if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { - + if ((cflag&CSIZE) != (old_cflag&CSIZE)) { arg = -1; - - switch( (cflag&CSIZE) ) { + switch (cflag&CSIZE) { case CS5: arg = DIGI_WORD_SIZE_5; break; case CS6: arg = DIGI_WORD_SIZE_6; break; case CS7: arg = DIGI_WORD_SIZE_7; break; case CS8: arg = DIGI_WORD_SIZE_8; break; default: - dbg( "digi_set_termios: can't handle word size %d", - (cflag&CSIZE) ); + dbg("digi_set_termios: can't handle word size %d", + (cflag&CSIZE)); break; } - if( arg != -1 ) { + if (arg != -1) { buf[i++] = DIGI_CMD_SET_WORD_SIZE; buf[i++] = priv->dp_port_num; buf[i++] = arg; @@ -1068,9 +1011,9 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol } /* set stop bits */ - if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { + if ((cflag&CSTOPB) != (old_cflag&CSTOPB)) { - if( (cflag&CSTOPB) ) + if ((cflag&CSTOPB)) arg = DIGI_STOP_BITS_2; else arg = DIGI_STOP_BITS_1; @@ -1083,18 +1026,15 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol } /* set input flow control */ - if( (iflag&IXOFF) != (old_iflag&IXOFF) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { - + if ((iflag&IXOFF) != (old_iflag&IXOFF) + || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) { arg = 0; - - if( (iflag&IXOFF) ) + if (iflag&IXOFF) arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF; else arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF; - if( (cflag&CRTSCTS) ) { - + if (cflag&CRTSCTS) { arg |= DIGI_INPUT_FLOW_CONTROL_RTS; /* On USB-4 it is necessary to assert RTS prior */ @@ -1107,43 +1047,37 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol } else { arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS; } - buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; - } /* set output flow control */ - if( (iflag&IXON) != (old_iflag&IXON) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { - + if ((iflag&IXON) != (old_iflag&IXON) + || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) { arg = 0; - - if( (iflag&IXON) ) + if (iflag&IXON) arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; else arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; - if( (cflag&CRTSCTS) ) { + if (cflag&CRTSCTS) { arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS; } else { arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; - port->tty->hw_stopped = 0; + tty->hw_stopped = 0; } buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; - } /* set receive enable/disable */ - if( (cflag&CREAD) != (old_cflag&CREAD) ) { - - if( (cflag&CREAD) ) + if ((cflag&CREAD) != (old_cflag&CREAD)) { + if (cflag&CREAD) arg = DIGI_ENABLE; else arg = DIGI_DISABLE; @@ -1152,32 +1086,26 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; - } - - if( (ret=digi_write_oob_command( port, buf, i, 1 )) != 0 ) - dbg( "digi_set_termios: write oob failed, ret=%d", ret ); + if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0) + dbg("digi_set_termios: write oob failed, ret=%d", ret); } -static void digi_break_ctl( struct usb_serial_port *port, int break_state ) +static void digi_break_ctl(struct usb_serial_port *port, int break_state) { - unsigned char buf[4]; - buf[0] = DIGI_CMD_BREAK_CONTROL; buf[1] = 2; /* length */ buf[2] = break_state ? 1 : 0; buf[3] = 0; /* pad */ - - digi_write_inb_command( port, buf, 4, 0 ); - + digi_write_inb_command(port, buf, 4, 0); } -static int digi_tiocmget( struct usb_serial_port *port, struct file *file ) +static int digi_tiocmget(struct usb_serial_port *port, struct file *file) { struct digi_port *priv = usb_get_serial_port_data(port); unsigned int val; @@ -1185,15 +1113,15 @@ static int digi_tiocmget( struct usb_serial_port *port, struct file *file ) dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num); - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); val = priv->dp_modem_signals; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); return val; } -static int digi_tiocmset( struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear ) +static int digi_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear) { struct digi_port *priv = usb_get_serial_port_data(port); unsigned int val; @@ -1201,41 +1129,34 @@ static int digi_tiocmset( struct usb_serial_port *port, struct file *file, dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num); - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); val = (priv->dp_modem_signals & ~clear) | set; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - return digi_set_modem_signals( port, val, 1 ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + return digi_set_modem_signals(port, val, 1); } -static int digi_ioctl( struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg ) +static int digi_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) { - struct digi_port *priv = usb_get_serial_port_data(port); - -dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd ); + dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd); switch (cmd) { - case TIOCMIWAIT: /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* TODO */ - return( 0 ); - + return 0; case TIOCGICOUNT: /* return count of modemline transitions */ /* TODO */ return 0; - } - - return( -ENOIOCTLCMD ); + return -ENOIOCTLCMD; } - -static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ) +static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count) { int ret,data_len,new_len; @@ -1243,35 +1164,29 @@ static int digi_write( struct usb_serial_port *port, const unsigned char *buf, i unsigned char *data = port->write_urb->transfer_buffer; unsigned long flags = 0; - -dbg( "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", -priv->dp_port_num, count, in_interrupt() ); + dbg("digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", + priv->dp_port_num, count, in_interrupt()); /* copy user data (which can sleep) before getting spin lock */ - count = min( count, port->bulk_out_size-2 ); - count = min( 64, count); + count = min(count, port->bulk_out_size-2); + count = min(64, count); /* be sure only one write proceeds at a time */ /* there are races on the port private buffer */ /* and races to check write_urb->status */ - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); /* wait for urb status clear to submit another urb */ - if( port->write_urb->status == -EINPROGRESS - || priv->dp_write_urb_in_use ) { - + if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) { /* buffer data if count is 1 (probably put_char) if possible */ - if( count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE ) { + if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) { priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; new_len = 1; } else { new_len = 0; } - - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - - return( new_len ); - + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + return new_len; } /* allow space for any buffered data and for new data, up to */ @@ -1279,9 +1194,9 @@ priv->dp_port_num, count, in_interrupt() ); new_len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len); data_len = new_len + priv->dp_out_buf_len; - if( data_len == 0 ) { - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - return( 0 ); + if (data_len == 0) { + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + return 0; } port->write_urb->transfer_buffer_length = data_len+2; @@ -1291,32 +1206,29 @@ priv->dp_port_num, count, in_interrupt() ); *data++ = data_len; /* copy in buffered data first */ - memcpy( data, priv->dp_out_buf, priv->dp_out_buf_len ); + memcpy(data, priv->dp_out_buf, priv->dp_out_buf_len); data += priv->dp_out_buf_len; /* copy in new data */ - memcpy( data, buf, new_len ); + memcpy(data, buf, new_len); - if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { + if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { priv->dp_write_urb_in_use = 1; ret = new_len; priv->dp_out_buf_len = 0; } /* return length of new data written, or error */ - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - if( ret < 0 ) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, - ret, priv->dp_port_num ); - } - -dbg( "digi_write: returning %d", ret ); - return( ret ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + if (ret < 0) + err("%s: usb_submit_urb failed, ret=%d, port=%d", + __FUNCTION__, ret, priv->dp_port_num); + dbg("digi_write: returning %d", ret); + return ret; } - -static void digi_write_bulk_callback( struct urb *urb ) +static void digi_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; @@ -1326,153 +1238,136 @@ static void digi_write_bulk_callback( struct urb *urb ) int ret = 0; int status = urb->status; - - dbg("digi_write_bulk_callback: TOP, urb status=%d", status); + dbg("digi_write_bulk_callback: TOP, urb->status=%d", status); /* port and serial sanity check */ - if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { + if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) { err("%s: port or port->private is NULL, status=%d", __FUNCTION__, status); return; } serial = port->serial; - if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) { + if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) { err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, status); return; } /* handle oob callback */ - if( priv->dp_port_num == serial_priv->ds_oob_port_num ) { - dbg( "digi_write_bulk_callback: oob callback" ); - spin_lock( &priv->dp_port_lock ); + if (priv->dp_port_num == serial_priv->ds_oob_port_num) { + dbg("digi_write_bulk_callback: oob callback"); + spin_lock(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; - wake_up_interruptible( &port->write_wait ); - spin_unlock( &priv->dp_port_lock ); + wake_up_interruptible(&port->write_wait); + spin_unlock(&priv->dp_port_lock); return; } /* try to send any buffered data on this port, if it is open */ - spin_lock( &priv->dp_port_lock ); + spin_lock(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; - if( port->open_count && port->write_urb->status != -EINPROGRESS - && priv->dp_out_buf_len > 0 ) { - + if (port->open_count && port->write_urb->status != -EINPROGRESS + && priv->dp_out_buf_len > 0) { *((unsigned char *)(port->write_urb->transfer_buffer)) = (unsigned char)DIGI_CMD_SEND_DATA; *((unsigned char *)(port->write_urb->transfer_buffer)+1) = (unsigned char)priv->dp_out_buf_len; - - port->write_urb->transfer_buffer_length - = priv->dp_out_buf_len+2; + port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2; port->write_urb->dev = serial->dev; - - memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf, - priv->dp_out_buf_len ); - - if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { + memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf, + priv->dp_out_buf_len); + if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) { priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; } - } - /* wake up processes sleeping on writes immediately */ - digi_wakeup_write( port ); - + digi_wakeup_write(port); /* also queue up a wakeup at scheduler time, in case we */ /* lost the race in write_chan(). */ schedule_work(&priv->dp_wakeup_work); - spin_unlock( &priv->dp_port_lock ); - - if( ret ) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, - ret, priv->dp_port_num ); - } - + spin_unlock(&priv->dp_port_lock); + if (ret) + err("%s: usb_submit_urb failed, ret=%d, port=%d", + __FUNCTION__, ret, priv->dp_port_num); } - -static int digi_write_room( struct usb_serial_port *port ) +static int digi_write_room(struct usb_serial_port *port) { int room; struct digi_port *priv = usb_get_serial_port_data(port); unsigned long flags = 0; + spin_lock_irqsave(&priv->dp_port_lock, flags); - spin_lock_irqsave( &priv->dp_port_lock, flags ); - - if( port->write_urb->status == -EINPROGRESS - || priv->dp_write_urb_in_use ) + if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) room = 0; else room = port->bulk_out_size - 2 - priv->dp_out_buf_len; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - -dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room ); - return( room ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + dbg("digi_write_room: port=%d, room=%d", priv->dp_port_num, room); + return room; } - -static int digi_chars_in_buffer( struct usb_serial_port *port ) +static int digi_chars_in_buffer(struct usb_serial_port *port) { struct digi_port *priv = usb_get_serial_port_data(port); - if( port->write_urb->status == -EINPROGRESS - || priv->dp_write_urb_in_use ) { -dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 ); - /* return( port->bulk_out_size - 2 ); */ - return( 256 ); + if (port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use) { + dbg("digi_chars_in_buffer: port=%d, chars=%d", + priv->dp_port_num, port->bulk_out_size - 2); + /* return(port->bulk_out_size - 2); */ + return 256; } else { -dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_out_buf_len ); - return( priv->dp_out_buf_len ); + dbg("digi_chars_in_buffer: port=%d, chars=%d", + priv->dp_port_num, priv->dp_out_buf_len); + return priv->dp_out_buf_len; } } -static int digi_open( struct usb_serial_port *port, struct file *filp ) +static int digi_open(struct usb_serial_port *port, struct file *filp) { - int ret; unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); struct ktermios not_termios; unsigned long flags = 0; - -dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); + dbg("digi_open: TOP: port=%d, open_count=%d", + priv->dp_port_num, port->open_count); /* be sure the device is started up */ - if( digi_startup_device( port->serial ) != 0 ) - return( -ENXIO ); + if (digi_startup_device(port->serial) != 0) + return -ENXIO; - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); /* don't wait on a close in progress for non-blocking opens */ - if( priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - return( -EAGAIN ); + if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) { + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + return -EAGAIN; } /* wait for a close in progress to finish */ - while( priv->dp_in_close ) { + while(priv->dp_in_close) { cond_wait_interruptible_timeout_irqrestore( &priv->dp_close_wait, DIGI_RETRY_TIMEOUT, - &priv->dp_port_lock, flags ); - if( signal_pending(current) ) { - return( -EINTR ); - } - spin_lock_irqsave( &priv->dp_port_lock, flags ); + &priv->dp_port_lock, flags); + if (signal_pending(current)) + return -EINTR; + spin_lock_irqsave(&priv->dp_port_lock, flags); } - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); /* read modem signals automatically whenever they change */ buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; @@ -1486,23 +1381,22 @@ dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_cou buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[7] = 0; - if( (ret=digi_write_oob_command( port, buf, 8, 1 )) != 0 ) - dbg( "digi_open: write oob failed, ret=%d", ret ); + if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0) + dbg("digi_open: write oob failed, ret=%d", ret); /* set termios settings */ not_termios.c_cflag = ~port->tty->termios->c_cflag; not_termios.c_iflag = ~port->tty->termios->c_iflag; - digi_set_termios( port, ¬_termios ); + digi_set_termios(port, ¬_termios); /* set DTR and RTS */ - digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS, 1 ); - - return( 0 ); + digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1); + return 0; } -static void digi_close( struct usb_serial_port *port, struct file *filp ) +static void digi_close(struct usb_serial_port *port, struct file *filp) { DEFINE_WAIT(wait); int ret; @@ -1511,40 +1405,37 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) struct digi_port *priv = usb_get_serial_port_data(port); unsigned long flags = 0; - -dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); - + dbg("digi_close: TOP: port=%d, open_count=%d", + priv->dp_port_num, port->open_count); /* if disconnected, just clear flags */ if (!usb_get_intfdata(port->serial->interface)) goto exit; /* do cleanup only after final close on this port */ - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_in_close = 1; - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); /* tell line discipline to process only XON/XOFF */ tty->closing = 1; /* wait for output to drain */ - if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { - tty_wait_until_sent( tty, DIGI_CLOSE_TIMEOUT ); - } + if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) + tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT); /* flush driver and line discipline buffers */ - if( tty->driver->flush_buffer ) - tty->driver->flush_buffer( tty ); + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); tty_ldisc_flush(tty); if (port->serial->dev) { /* wait for transmit idle */ - if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { - digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT ); + if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) { + digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); } - /* drop DTR and RTS */ - digi_set_modem_signals( port, 0, 0 ); + digi_set_modem_signals(port, 0, 0); /* disable input flow control */ buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; @@ -1576,8 +1467,8 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[19] = 0; - if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 ) - dbg( "digi_close: write oob failed, ret=%d", ret ); + if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0) + dbg("digi_close: write oob failed, ret=%d", ret); /* wait for final commands on oob port to complete */ prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE); @@ -1587,17 +1478,14 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co /* shutdown any outstanding bulk writes */ usb_kill_urb(port->write_urb); } - tty->closing = 0; - exit: - spin_lock_irqsave( &priv->dp_port_lock, flags ); + spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_write_urb_in_use = 0; priv->dp_in_close = 0; - wake_up_interruptible( &priv->dp_close_wait ); - spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - -dbg( "digi_close: done" ); + wake_up_interruptible(&priv->dp_close_wait); + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + dbg("digi_close: done"); } @@ -1608,155 +1496,136 @@ dbg( "digi_close: done" ); * urbs initialized. Returns 0 if successful, non-zero error otherwise. */ -static int digi_startup_device( struct usb_serial *serial ) +static int digi_startup_device(struct usb_serial *serial) { - int i,ret = 0; struct digi_serial *serial_priv = usb_get_serial_data(serial); struct usb_serial_port *port; - /* be sure this happens exactly once */ - spin_lock( &serial_priv->ds_serial_lock ); - if( serial_priv->ds_device_started ) { - spin_unlock( &serial_priv->ds_serial_lock ); - return( 0 ); + spin_lock(&serial_priv->ds_serial_lock); + if (serial_priv->ds_device_started) { + spin_unlock(&serial_priv->ds_serial_lock); + return 0; } serial_priv->ds_device_started = 1; - spin_unlock( &serial_priv->ds_serial_lock ); + spin_unlock(&serial_priv->ds_serial_lock); /* start reading from each bulk in endpoint for the device */ /* set USB_DISABLE_SPD flag for write bulk urbs */ - for( i=0; i<serial->type->num_ports+1; i++ ) { - + for (i = 0; i < serial->type->num_ports + 1; i++) { port = serial->port[i]; - port->write_urb->dev = port->serial->dev; - - if( (ret=usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0 ) { - err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, - ret, i ); + if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) { + err("%s: usb_submit_urb failed, ret=%d, port=%d", + __FUNCTION__, ret, i); break; } - } - - return( ret ); - + return ret; } -static int digi_startup( struct usb_serial *serial ) +static int digi_startup(struct usb_serial *serial) { int i; struct digi_port *priv; struct digi_serial *serial_priv; - -dbg( "digi_startup: TOP" ); + dbg("digi_startup: TOP"); /* allocate the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ - for( i=0; i<serial->type->num_ports+1; i++ ) { - + for(i = 0; i < serial->type->num_ports + 1; i++) { /* allocate port private structure */ - priv = kmalloc( sizeof(struct digi_port), - GFP_KERNEL ); - if( priv == (struct digi_port *)0 ) { - while( --i >= 0 ) - kfree( usb_get_serial_port_data(serial->port[i]) ); - return( 1 ); /* error */ + priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); + if (priv == NULL) { + while (--i >= 0) + kfree(usb_get_serial_port_data(serial->port[i])); + return 1; /* error */ } /* initialize port private structure */ - spin_lock_init( &priv->dp_port_lock ); + spin_lock_init(&priv->dp_port_lock); priv->dp_port_num = i; priv->dp_out_buf_len = 0; priv->dp_write_urb_in_use = 0; priv->dp_modem_signals = 0; - init_waitqueue_head( &priv->dp_modem_change_wait ); + init_waitqueue_head(&priv->dp_modem_change_wait); priv->dp_transmit_idle = 0; - init_waitqueue_head( &priv->dp_transmit_idle_wait ); + init_waitqueue_head(&priv->dp_transmit_idle_wait); priv->dp_throttled = 0; priv->dp_throttle_restart = 0; - init_waitqueue_head( &priv->dp_flush_wait ); + init_waitqueue_head(&priv->dp_flush_wait); priv->dp_in_close = 0; - init_waitqueue_head( &priv->dp_close_wait ); + init_waitqueue_head(&priv->dp_close_wait); INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); priv->dp_port = serial->port[i]; - /* initialize write wait queue for this port */ - init_waitqueue_head( &serial->port[i]->write_wait ); + init_waitqueue_head(&serial->port[i]->write_wait); usb_set_serial_port_data(serial->port[i], priv); } /* allocate serial private structure */ - serial_priv = kmalloc( sizeof(struct digi_serial), - GFP_KERNEL ); - if( serial_priv == (struct digi_serial *)0 ) { - for( i=0; i<serial->type->num_ports+1; i++ ) - kfree( usb_get_serial_port_data(serial->port[i]) ); - return( 1 ); /* error */ + serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); + if (serial_priv == NULL) { + for (i = 0; i < serial->type->num_ports + 1; i++) + kfree(usb_get_serial_port_data(serial->port[i])); + return 1; /* error */ } /* initialize serial private structure */ - spin_lock_init( &serial_priv->ds_serial_lock ); + spin_lock_init(&serial_priv->ds_serial_lock); serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; serial_priv->ds_device_started = 0; usb_set_serial_data(serial, serial_priv); - return( 0 ); - + return 0; } -static void digi_shutdown( struct usb_serial *serial ) +static void digi_shutdown(struct usb_serial *serial) { - int i; - - -dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() ); + dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt()); /* stop reads and writes on all ports */ - for( i=0; i<serial->type->num_ports+1; i++ ) { + for (i = 0; i < serial->type->num_ports + 1; i++) { usb_kill_urb(serial->port[i]->read_urb); usb_kill_urb(serial->port[i]->write_urb); } /* free the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ - for( i=0; i<serial->type->num_ports+1; i++ ) - kfree( usb_get_serial_port_data(serial->port[i]) ); - kfree( usb_get_serial_data(serial) ); + for(i = 0; i < serial->type->num_ports + 1; i++) + kfree(usb_get_serial_port_data(serial->port[i])); + kfree(usb_get_serial_data(serial)); } -static void digi_read_bulk_callback( struct urb *urb ) +static void digi_read_bulk_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct digi_port *priv; struct digi_serial *serial_priv; int ret; int status = urb->status; - -dbg( "digi_read_bulk_callback: TOP" ); + dbg("digi_read_bulk_callback: TOP"); /* port sanity check, do not resubmit if port is not valid */ - if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { + if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { err("%s: port or port->private is NULL, status=%d", __FUNCTION__, status); return; } - if( port->serial == NULL - || (serial_priv=usb_get_serial_data(port->serial)) == NULL ) { + if (port->serial == NULL || + (serial_priv=usb_get_serial_data(port->serial)) == NULL) { err("%s: serial is bad or serial->private is NULL, status=%d", - __FUNCTION__, status); + __FUNCTION__, status); return; } @@ -1768,24 +1637,23 @@ dbg( "digi_read_bulk_callback: TOP" ); } /* handle oob or inb callback, do not resubmit if error */ - if( priv->dp_port_num == serial_priv->ds_oob_port_num ) { - if( digi_read_oob_callback( urb ) != 0 ) + if (priv->dp_port_num == serial_priv->ds_oob_port_num) { + if (digi_read_oob_callback(urb) != 0) return; } else { - if( digi_read_inb_callback( urb ) != 0 ) + if (digi_read_inb_callback(urb) != 0) return; } /* continue read */ urb->dev = port->serial->dev; - if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) { - err("%s: failed resubmitting urb, ret=%d, port=%d", __FUNCTION__, - ret, priv->dp_port_num ); + if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) { + err("%s: failed resubmitting urb, ret=%d, port=%d", + __FUNCTION__, ret, priv->dp_port_num); } } - /* * Digi Read INB Callback * @@ -1796,7 +1664,7 @@ dbg( "digi_read_bulk_callback: TOP" ); * throttled, and -1 if the sanity checks failed. */ -static int digi_read_inb_callback( struct urb *urb ) +static int digi_read_inb_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; @@ -1812,72 +1680,67 @@ static int digi_read_inb_callback( struct urb *urb ) /* do not process callbacks on closed ports */ /* but do continue the read chain */ - if( port->open_count == 0 ) - return( 0 ); + if (port->open_count == 0) + return 0; /* short/multiple packet check */ - if( urb->actual_length != len + 2 ) { - err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, " + if (urb->actual_length != len + 2) { + err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, " "port=%d, opcode=%d, len=%d, actual_length=%d, " - "port_status=%d", __FUNCTION__, status, priv->dp_port_num, + "status=%d", __FUNCTION__, status, priv->dp_port_num, opcode, len, urb->actual_length, port_status); - return( -1 ); + return -1; } - spin_lock( &priv->dp_port_lock ); + spin_lock(&priv->dp_port_lock); /* check for throttle; if set, do not resubmit read urb */ /* indicate the read chain needs to be restarted on unthrottle */ throttled = priv->dp_throttled; - if( throttled ) + if (throttled) priv->dp_throttle_restart = 1; /* receive data */ - if( opcode == DIGI_CMD_RECEIVE_DATA ) { - + if (opcode == DIGI_CMD_RECEIVE_DATA) { /* get flag from port_status */ flag = 0; /* overrun is special, not associated with a char */ - if (port_status & DIGI_OVERRUN_ERROR) { - tty_insert_flip_char( tty, 0, TTY_OVERRUN ); - } + if (port_status & DIGI_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); /* break takes precedence over parity, */ /* which takes precedence over framing errors */ - if (port_status & DIGI_BREAK_ERROR) { + if (port_status & DIGI_BREAK_ERROR) flag = TTY_BREAK; - } else if (port_status & DIGI_PARITY_ERROR) { + else if (port_status & DIGI_PARITY_ERROR) flag = TTY_PARITY; - } else if (port_status & DIGI_FRAMING_ERROR) { + else if (port_status & DIGI_FRAMING_ERROR) flag = TTY_FRAME; - } /* data length is len-1 (one byte of len is port_status) */ --len; len = tty_buffer_request_room(tty, len); - if( len > 0 ) { + if (len > 0) { /* Hot path */ - if(flag == TTY_NORMAL) + if (flag == TTY_NORMAL) tty_insert_flip_string(tty, data, len); else { for(i = 0; i < len; i++) tty_insert_flip_char(tty, data[i], flag); } - tty_flip_buffer_push( tty ); + tty_flip_buffer_push(tty); } } + spin_unlock(&priv->dp_port_lock); - spin_unlock( &priv->dp_port_lock ); - - if( opcode == DIGI_CMD_RECEIVE_DISABLE ) { - dbg("%s: got RECEIVE_DISABLE", __FUNCTION__ ); - } else if( opcode != DIGI_CMD_RECEIVE_DATA ) { - dbg("%s: unknown opcode: %d", __FUNCTION__, opcode ); - } + if (opcode == DIGI_CMD_RECEIVE_DISABLE) + dbg("%s: got RECEIVE_DISABLE", __FUNCTION__); + else if (opcode != DIGI_CMD_RECEIVE_DATA) + dbg("%s: unknown opcode: %d", __FUNCTION__, opcode); - return( throttled ? 1 : 0 ); + return(throttled ? 1 : 0); } @@ -1891,7 +1754,7 @@ static int digi_read_inb_callback( struct urb *urb ) * -1 if the sanity checks failed. */ -static int digi_read_oob_callback( struct urb *urb ) +static int digi_read_oob_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; @@ -1900,87 +1763,75 @@ static int digi_read_oob_callback( struct urb *urb ) int opcode, line, status, val; int i; - -dbg( "digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num, -urb->actual_length ); + dbg("digi_read_oob_callback: port=%d, len=%d", + priv->dp_port_num, urb->actual_length); /* handle each oob command */ - for( i=0; i<urb->actual_length-3; ) { - + for(i = 0; i < urb->actual_length - 3;) { opcode = ((unsigned char *)urb->transfer_buffer)[i++]; line = ((unsigned char *)urb->transfer_buffer)[i++]; status = ((unsigned char *)urb->transfer_buffer)[i++]; val = ((unsigned char *)urb->transfer_buffer)[i++]; -dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", -opcode, line, status, val ); + dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", + opcode, line, status, val); - if( status != 0 || line >= serial->type->num_ports ) + if (status != 0 || line >= serial->type->num_ports) continue; port = serial->port[line]; - if ((priv=usb_get_serial_port_data(port)) == NULL ) + if ((priv=usb_get_serial_port_data(port)) == NULL) return -1; - if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) { - - spin_lock( &priv->dp_port_lock ); - + if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { + spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ - if( val & DIGI_READ_INPUT_SIGNALS_CTS ) { + if (val & DIGI_READ_INPUT_SIGNALS_CTS) { priv->dp_modem_signals |= TIOCM_CTS; /* port must be open to use tty struct */ - if( port->open_count - && port->tty->termios->c_cflag & CRTSCTS ) { + if (port->open_count + && port->tty->termios->c_cflag & CRTSCTS) { port->tty->hw_stopped = 0; - digi_wakeup_write( port ); + digi_wakeup_write(port); } } else { priv->dp_modem_signals &= ~TIOCM_CTS; /* port must be open to use tty struct */ - if( port->open_count - && port->tty->termios->c_cflag & CRTSCTS ) { + if (port->open_count + && port->tty->termios->c_cflag & CRTSCTS) { port->tty->hw_stopped = 1; } } - if( val & DIGI_READ_INPUT_SIGNALS_DSR ) + if (val & DIGI_READ_INPUT_SIGNALS_DSR) priv->dp_modem_signals |= TIOCM_DSR; else priv->dp_modem_signals &= ~TIOCM_DSR; - if( val & DIGI_READ_INPUT_SIGNALS_RI ) + if (val & DIGI_READ_INPUT_SIGNALS_RI) priv->dp_modem_signals |= TIOCM_RI; else priv->dp_modem_signals &= ~TIOCM_RI; - if( val & DIGI_READ_INPUT_SIGNALS_DCD ) + if (val & DIGI_READ_INPUT_SIGNALS_DCD) priv->dp_modem_signals |= TIOCM_CD; else priv->dp_modem_signals &= ~TIOCM_CD; - wake_up_interruptible( &priv->dp_modem_change_wait ); - spin_unlock( &priv->dp_port_lock ); - - } else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) { - - spin_lock( &priv->dp_port_lock ); + wake_up_interruptible(&priv->dp_modem_change_wait); + spin_unlock(&priv->dp_port_lock); + } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) { + spin_lock(&priv->dp_port_lock); priv->dp_transmit_idle = 1; - wake_up_interruptible( &priv->dp_transmit_idle_wait ); - spin_unlock( &priv->dp_port_lock ); - - } else if( opcode == DIGI_CMD_IFLUSH_FIFO ) { - - wake_up_interruptible( &priv->dp_flush_wait ); - + wake_up_interruptible(&priv->dp_transmit_idle_wait); + spin_unlock(&priv->dp_port_lock); + } else if (opcode == DIGI_CMD_IFLUSH_FIFO) { + wake_up_interruptible(&priv->dp_flush_wait); } - } - - return( 0 ); + return 0; } - -static int __init digi_init (void) +static int __init digi_init(void) { int retval; retval = usb_serial_register(&digi_acceleport_2_device); @@ -2002,12 +1853,11 @@ failed_acceleport_2_device: return retval; } - static void __exit digi_exit (void) { - usb_deregister (&digi_driver); - usb_serial_deregister (&digi_acceleport_2_device); - usb_serial_deregister (&digi_acceleport_4_device); + usb_deregister(&digi_driver); + usb_serial_deregister(&digi_acceleport_2_device); + usb_serial_deregister(&digi_acceleport_4_device); } @@ -2015,8 +1865,8 @@ module_init(digi_init); module_exit(digi_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index dd42f57..2ecb1d2 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -2366,9 +2366,8 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa int status; unsigned char number = edge_port->port->number - edge_port->port->serial->minor; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d", edge_port->port->number, baudRate); return 0; @@ -2461,18 +2460,16 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue); - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && - (regNum == MCR))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteMCR && + regNum == MCR) { dbg("SendCmdWriteUartReg - Not writing to MCR Register"); return 0; } - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && - (regNum == LCR))) { + if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteLCR && + regNum == LCR) { dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); return 0; } diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 2a3fabc..e08c9bb 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -184,21 +184,21 @@ struct mct_u232_private { * we do not know how to support. We ignore them for the moment. * XXX Rate-limit the error message, it's user triggerable. */ -static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) +static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value) { if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { switch (value) { - case B300: return 0x01; - case B600: return 0x02; /* this one not tested */ - case B1200: return 0x03; - case B2400: return 0x04; - case B4800: return 0x06; - case B9600: return 0x08; - case B19200: return 0x09; - case B38400: return 0x0a; - case B57600: return 0x0b; - case B115200: return 0x0c; + case 300: return 0x01; + case 600: return 0x02; /* this one not tested */ + case 1200: return 0x03; + case 2400: return 0x04; + case 4800: return 0x06; + case 9600: return 0x08; + case 19200: return 0x09; + case 38400: return 0x0a; + case 57600: return 0x0b; + case 115200: return 0x0c; default: err("MCT USB-RS232: unsupported baudrate request 0x%x," " using default of B9600", value); @@ -206,27 +206,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) } } else { switch (value) { - case B300: value = 300; break; - case B600: value = 600; break; - case B1200: value = 1200; break; - case B2400: value = 2400; break; - case B4800: value = 4800; break; - case B9600: value = 9600; break; - case B19200: value = 19200; break; - case B38400: value = 38400; break; - case B57600: value = 57600; break; - case B115200: value = 115200; break; - default: - err("MCT USB-RS232: unsupported baudrate request 0x%x," - " using default of B9600", value); - value = 9600; + case 300: break; + case 600: break; + case 1200: break; + case 2400: break; + case 4800: break; + case 9600: break; + case 19200: break; + case 38400: break; + case 57600: break; + case 115200: break; + default: + err("MCT USB-RS232: unsupported baudrate request 0x%x," + " using default of B9600", value); + value = 9600; } return 115200/value; } } static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port, - int value) + speed_t value) { __le32 divisor; int rc; @@ -634,7 +634,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port, mct_u232_set_modem_ctrl(serial, control_state); } - mct_u232_set_baud_rate(serial, port, cflag & CBAUD); + mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty)); if ((cflag & CBAUD) == B0 ) { dbg("%s: baud is B0", __FUNCTION__); diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h index a61bac8..aae10c8 100644 --- a/drivers/usb/serial/mct_u232.h +++ b/drivers/usb/serial/mct_u232.h @@ -79,7 +79,7 @@ * and "Intel solution". They are the regular MCT and "Sitecom" for us. * This is pointless to document in the header, see the code for the bits. */ -static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value); +static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value); /* * Line Control Register (LCR) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0794ccd..0bb8de4 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -45,7 +45,7 @@ enum devicetype { DEVICE_INSTALLER = 2, }; -int sierra_set_power_state(struct usb_device *udev, __u16 swiState) +static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) { int result; dev_dbg(&udev->dev, "%s", "SET POWER STATE"); @@ -60,7 +60,7 @@ int sierra_set_power_state(struct usb_device *udev, __u16 swiState) return result; } -int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) +static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) { int result; dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH"); @@ -75,7 +75,8 @@ int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) return result; } -int sierra_probe(struct usb_interface *iface, const struct usb_device_id *id) +static int sierra_probe(struct usb_interface *iface, + const struct usb_device_id *id) { int result; struct usb_device *udev; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a366565..9bf01a5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = { static int debug; static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ -static spinlock_t table_lock; +static DEFINE_MUTEX(table_lock); static LIST_HEAD(usb_serial_driver_list); struct usb_serial *usb_serial_get_by_index(unsigned index) { struct usb_serial *serial; - spin_lock(&table_lock); + mutex_lock(&table_lock); serial = serial_table[index]; if (serial) kref_get(&serial->kref); - spin_unlock(&table_lock); + mutex_unlock(&table_lock); return serial; } @@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po dbg("%s %d", __FUNCTION__, num_ports); *minor = 0; - spin_lock(&table_lock); + mutex_lock(&table_lock); for (i = 0; i < SERIAL_TTY_MINORS; ++i) { if (serial_table[i]) continue; @@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po serial_table[i] = serial; serial->port[j++]->number = i; } - spin_unlock(&table_lock); + mutex_unlock(&table_lock); return serial; } - spin_unlock(&table_lock); + mutex_unlock(&table_lock); return NULL; } @@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref) void usb_serial_put(struct usb_serial *serial) { - spin_lock(&table_lock); + mutex_lock(&table_lock); kref_put(&serial->kref, destroy_serial); - spin_unlock(&table_lock); + mutex_unlock(&table_lock); } /***************************************************************************** @@ -1077,16 +1077,17 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) struct usb_serial_port *port; int i, r = 0; - if (serial) { - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (port) - kill_traffic(port); - } + if (!serial) /* device has been disconnected */ + return 0; + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (port) + kill_traffic(port); } if (serial->type->suspend) - serial->type->suspend(serial, message); + r = serial->type->suspend(serial, message); return r; } @@ -1128,7 +1129,6 @@ static int __init usb_serial_init(void) return -ENOMEM; /* Initialize our global data */ - spin_lock_init(&table_lock); for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a624e72..d8d008d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -320,6 +320,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Milinevsky Dmitry <niam.niam@gmail.com> */ +UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100, + "NIKON", + "NIKON DSC D50", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Reported by Andreas Bockhold <andreas@bockionline.de> */ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, "NIKON", @@ -1357,6 +1364,20 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Jeremy Katz <katzj@redhat.com>: + * The Blackberry Pearl can run in two modes; a usb-storage only mode + * and a mode that allows access via mass storage and to its database. + * The berry_charge module will set the device to dual mode and thus we + * should ignore its native mode if that module is built + */ +#ifdef CONFIG_USB_BERRY_CHARGE +UNUSUAL_DEV( 0x0fca, 0x0006, 0x0001, 0x0001, + "RIM", + "Blackberry Pearl", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), +#endif + /* Reported by Michael Stattmann <michael@stattmann.com> */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 564cc9b..5216c11 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1571,7 +1571,14 @@ config FB_PM3 config FB_AU1100 bool "Au1100 LCD Driver" - depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y + depends on (FB = y) && MIPS && SOC_AU1100 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer driver for the AMD Au1100 SOC. It can drive + various panels and CRTs by passing in kernel cmd line option + au1100fb:panel=<name>. config FB_AU1200 bool "Au1200 LCD Driver" @@ -1638,18 +1645,6 @@ config FB_MAXINE DECstation series (Personal DECstation 5000/20, /25, /33, /50, Codename "Maxine"). -config FB_TX3912 - bool "TMPTX3912/PR31700 frame buffer support" - depends on (FB = y) && NINO - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core - see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>. - - Say Y here to enable kernel support for the on-board framebuffer. - config FB_G364 bool "G364 frame buffer support" depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 518933d..06eec7b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -103,7 +103,6 @@ obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o -obj-$(CONFIG_FB_TX3912) += tx3912fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 61a8bf1..eedb828 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -138,17 +138,6 @@ static struct pixclock arc_clocks[] = { { 41250, 42083, VIDC_CTRL_DIV1, VID_CTL_24MHz }, /* 24.000MHz */ }; -#ifdef CONFIG_ARCH_A5K -static struct pixclock a5k_clocks[] = { - { 117974, 120357, VIDC_CTRL_DIV3, VID_CTL_25MHz }, /* 8.392MHz */ - { 78649, 80238, VIDC_CTRL_DIV2, VID_CTL_25MHz }, /* 12.588MHz */ - { 58987, 60178, VIDC_CTRL_DIV1_5, VID_CTL_25MHz }, /* 16.588MHz */ - { 55000, 56111, VIDC_CTRL_DIV2, VID_CTL_36MHz }, /* 18.000MHz */ - { 39325, 40119, VIDC_CTRL_DIV1, VID_CTL_25MHz }, /* 25.175MHz */ - { 27500, 28055, VIDC_CTRL_DIV1, VID_CTL_36MHz }, /* 36.000MHz */ -}; -#endif - static struct pixclock * acornfb_valid_pixrate(struct fb_var_screeninfo *var) { @@ -163,15 +152,6 @@ acornfb_valid_pixrate(struct fb_var_screeninfo *var) pixclock < arc_clocks[i].max_clock) return arc_clocks + i; -#ifdef CONFIG_ARCH_A5K - if (machine_is_a5k()) { - for (i = 0; i < ARRAY_SIZE(a5k_clocks); i++) - if (pixclock > a5k_clocks[i].min_clock && - pixclock < a5k_clocks[i].max_clock) - return a5k_clocks + i; - } -#endif - return NULL; } diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index b0b2e40..718b9f8 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -279,90 +279,91 @@ static void __devinit bw2_do_default_mode(struct bw2_par *par, } } -struct all_info { - struct fb_info info; - struct bw2_par par; -}; - -static int __devinit bw2_init_one(struct of_device *op) +static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct bw2_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 1); + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; + + sbusfb_fill_var(&info->var, dp->node, 1); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); + info->var.xres); - all->info.var.red.length = all->info.var.green.length = - all->info.var.blue.length = all->info.var.bits_per_pixel; - all->info.var.red.offset = all->info.var.green.offset = - all->info.var.blue.offset = 0; + info->var.red.length = info->var.green.length = + info->var.blue.length = info->var.bits_per_pixel; + info->var.red.offset = info->var.green.offset = + info->var.blue.offset = 0; - all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, - sizeof(struct bw2_regs), "bw2 regs"); + par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, + sizeof(struct bw2_regs), "bw2 regs"); + if (!par->regs) + goto out_release_fb; if (!of_find_property(dp, "width", NULL)) - bw2_do_default_mode(&all->par, &all->info, &linebytes); + bw2_do_default_mode(par, info, &linebytes); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &bw2_ops; + info->flags = FBINFO_DEFAULT; + info->fbops = &bw2_ops; - all->info.screen_base = - of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram"); - all->info.par = &all->par; + info->screen_base = of_ioremap(&op->resource[0], 0, + par->fbsize, "bw2 ram"); + if (!info->screen_base) + goto out_unmap_regs; - bw2_blank(0, &all->info); + bw2_blank(0, info); - bw2_init_fix(&all->info, linebytes); + bw2_init_fix(info, linebytes); - err= register_framebuffer(&all->info); - if (err < 0) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct bw2_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_unmap_screen; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: bwtwo at %lx:%lx\n", - dp->full_name, - all->par.which_io, all->par.physbase); + dp->full_name, par->which_io, par->physbase); return 0; -} -static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_unmap_screen: + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs)); + +out_release_fb: + framebuffer_release(info); - return bw2_init_one(op); +out_err: + return err; } static int __devexit bw2_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct bw2_par *par = info->par; - unregister_framebuffer(&all->info); + unregister_framebuffer(info); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs)); - of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs)); + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index b071bb6..41f6dbf 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -448,81 +448,79 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { { .size = 0 } }; -struct all_info { - struct fb_info info; - struct cg14_par par; -}; - -static void cg14_unmap_regs(struct of_device *op, struct all_info *all) +static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, + struct cg14_par *par) { - if (all->par.regs) + if (par->regs) of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg14_regs)); - if (all->par.clut) + par->regs, sizeof(struct cg14_regs)); + if (par->clut) of_iounmap(&op->resource[0], - all->par.clut, sizeof(struct cg14_clut)); - if (all->par.cursor) + par->clut, sizeof(struct cg14_clut)); + if (par->cursor) of_iounmap(&op->resource[0], - all->par.cursor, sizeof(struct cg14_cursor)); - if (all->info.screen_base) + par->cursor, sizeof(struct cg14_cursor)); + if (info->screen_base) of_iounmap(&op->resource[1], - all->info.screen_base, all->par.fbsize); + info->screen_base, par->fbsize); } -static int __devinit cg14_init_one(struct of_device *op) +static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg14_par *par; int is_8mb, linebytes, i, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); if (!strcmp(dp->parent->name, "sbus") || !strcmp(dp->parent->name, "sbi")) { - all->par.physbase = op->resource[0].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->iospace = op->resource[0].flags & IORESOURCE_BITS; } else { - all->par.physbase = op->resource[1].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[1].start; + par->iospace = op->resource[0].flags & IORESOURCE_BITS; } - all->par.regs = of_ioremap(&op->resource[0], 0, - sizeof(struct cg14_regs), "cg14 regs"); - all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1, - sizeof(struct cg14_clut), "cg14 clut"); - all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, - sizeof(struct cg14_cursor), "cg14 cursor"); + par->regs = of_ioremap(&op->resource[0], 0, + sizeof(struct cg14_regs), "cg14 regs"); + par->clut = of_ioremap(&op->resource[0], CG14_CLUT1, + sizeof(struct cg14_clut), "cg14 clut"); + par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, + sizeof(struct cg14_cursor), "cg14 cursor"); - all->info.screen_base = of_ioremap(&op->resource[1], 0, - all->par.fbsize, "cg14 ram"); + info->screen_base = of_ioremap(&op->resource[1], 0, + par->fbsize, "cg14 ram"); - if (!all->par.regs || !all->par.clut || !all->par.cursor || - !all->info.screen_base) - cg14_unmap_regs(op, all); + if (!par->regs || !par->clut || !par->cursor || !info->screen_base) + goto out_unmap_regs; is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) == (8 * 1024 * 1024)); - BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)); + BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map)); - memcpy(&all->par.mmap_map, &__cg14_mmap_map, - sizeof(all->par.mmap_map)); + memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map)); for (i = 0; i < CG14_MMAP_ENTRIES; i++) { - struct sbus_mmap_map *map = &all->par.mmap_map[i]; + struct sbus_mmap_map *map = &par->mmap_map[i]; if (!map->size) break; @@ -536,59 +534,55 @@ static int __devinit cg14_init_one(struct of_device *op) map->size *= 2; } - all->par.mode = MDI_8_PIX; - all->par.ramsize = (is_8mb ? 0x800000 : 0x400000); + par->mode = MDI_8_PIX; + par->ramsize = (is_8mb ? 0x800000 : 0x400000); - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - all->info.fbops = &cg14_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->fbops = &cg14_ops; - __cg14_reset(&all->par); + __cg14_reset(par); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - cg14_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } - fb_set_cmap(&all->info.cmap, &all->info); + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - cg14_init_fix(&all->info, linebytes, dp); + fb_set_cmap(&info->cmap, info); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - cg14_unmap_regs(op, all); - kfree(all); - return err; - } + cg14_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: cgfourteen at %lx:%lx, %dMB\n", dp->full_name, - all->par.iospace, all->par.physbase, - all->par.ramsize >> 20); + par->iospace, par->physbase, + par->ramsize >> 20); return 0; -} -static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + cg14_unmap_regs(op, info, par); - return cg14_init_one(op); +out_err: + return err; } static int __devexit cg14_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg14_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - cg14_unmap_regs(op, all); + cg14_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index f042428..5741b46 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -353,104 +353,102 @@ static void __devinit cg3_do_default_mode(struct cg3_par *par) } } -struct all_info { - struct fb_info info; - struct cg3_par par; -}; - -static int __devinit cg3_init_one(struct of_device *op) +static int __devinit cg3_probe(struct of_device *op, + const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg3_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; + + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; if (!strcmp(dp->name, "cgRDI")) - all->par.flags |= CG3_FLAG_RDI; - if (all->par.flags & CG3_FLAG_RDI) - cg3_rdi_maybe_fixup_var(&all->info.var, dp); + par->flags |= CG3_FLAG_RDI; + if (par->flags & CG3_FLAG_RDI) + cg3_rdi_maybe_fixup_var(&info->var, dp); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET, - sizeof(struct cg3_regs), "cg3 regs"); + par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET, + sizeof(struct cg3_regs), "cg3 regs"); + if (!par->regs) + goto out_release_fb; - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &cg3_ops; - all->info.screen_base = - of_ioremap(&op->resource[0], CG3_RAM_OFFSET, - all->par.fbsize, "cg3 ram"); - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT; + info->fbops = &cg3_ops; + info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET, + par->fbsize, "cg3 ram"); + if (!info->screen_base) + goto out_unmap_regs; - cg3_blank(0, &all->info); + cg3_blank(0, info); if (!of_find_property(dp, "width", NULL)) - cg3_do_default_mode(&all->par); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return -ENOMEM; - } - fb_set_cmap(&all->info.cmap, &all->info); - - cg3_init_fix(&all->info, linebytes, dp); - - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } + cg3_do_default_mode(par); + + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_screen; + + fb_set_cmap(&info->cmap, info); - dev_set_drvdata(&op->dev, all); + cg3_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + dev_set_drvdata(&op->dev, info); printk("%s: cg3 at %lx:%lx\n", - dp->full_name, all->par.which_io, all->par.physbase); + dp->full_name, par->which_io, par->physbase); return 0; -} -static int __devinit cg3_probe(struct of_device *dev, - const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_screen: + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs)); + +out_release_fb: + framebuffer_release(info); - return cg3_init_one(op); +out_err: + return err; } static int __devexit cg3_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg3_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs)); + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 4dad23a..87c7471 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -653,135 +653,120 @@ static void cg6_chip_init(struct fb_info *info) sbus_writel(info->var.yres - 1, &fbc->clipmaxy); } -struct all_info { - struct fb_info info; - struct cg6_par par; -}; - -static void cg6_unmap_regs(struct of_device *op, struct all_info *all) +static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, + struct cg6_par *par) { - if (all->par.fbc) - of_iounmap(&op->resource[0], all->par.fbc, 4096); - if (all->par.tec) - of_iounmap(&op->resource[0], - all->par.tec, sizeof(struct cg6_tec)); - if (all->par.thc) - of_iounmap(&op->resource[0], - all->par.thc, sizeof(struct cg6_thc)); - if (all->par.bt) - of_iounmap(&op->resource[0], - all->par.bt, sizeof(struct bt_regs)); - if (all->par.fhc) - of_iounmap(&op->resource[0], - all->par.fhc, sizeof(u32)); - - if (all->info.screen_base) - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); + if (par->fbc) + of_iounmap(&op->resource[0], par->fbc, 4096); + if (par->tec) + of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec)); + if (par->thc) + of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc)); + if (par->bt) + of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs)); + if (par->fhc) + of_iounmap(&op->resource[0], par->fhc, sizeof(u32)); + + if (info->screen_base) + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); } -static int __devinit cg6_init_one(struct of_device *op) +static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg6_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); if (of_find_property(dp, "dblbuf", NULL)) - all->par.fbsize *= 4; + par->fbsize *= 4; - all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, + par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, 4096, "cgsix fbc"); - all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, + par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, sizeof(struct cg6_tec), "cgsix tec"); - all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, + par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, sizeof(struct cg6_thc), "cgsix thc"); - all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, + par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, sizeof(struct bt_regs), "cgsix dac"); - all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, + par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, sizeof(u32), "cgsix fhc"); - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; - all->info.fbops = &cg6_ops; - - all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, - all->par.fbsize, "cgsix ram"); - if (!all->par.fbc || !all->par.tec || !all->par.thc || - !all->par.bt || !all->par.fhc || !all->info.screen_base) { - cg6_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + info->fbops = &cg6_ops; - all->info.par = &all->par; + info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, + par->fbsize, "cgsix ram"); + if (!par->fbc || !par->tec || !par->thc || + !par->bt || !par->fhc || !info->screen_base) + goto out_unmap_regs; - all->info.var.accel_flags = FB_ACCELF_TEXT; + info->var.accel_flags = FB_ACCELF_TEXT; - cg6_bt_init(&all->par); - cg6_chip_init(&all->info); - cg6_blank(0, &all->info); + cg6_bt_init(par); + cg6_chip_init(info); + cg6_blank(0, info); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - cg6_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - fb_set_cmap(&all->info.cmap, &all->info); - cg6_init_fix(&all->info, linebytes); + fb_set_cmap(&info->cmap, info); + cg6_init_fix(info, linebytes); - err = register_framebuffer(&all->info); - if (err < 0) { - cg6_unmap_regs(op, all); - fb_dealloc_cmap(&all->info.cmap); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: CGsix [%s] at %lx:%lx\n", - dp->full_name, - all->info.fix.id, - all->par.which_io, all->par.physbase); + dp->full_name, info->fix.id, + par->which_io, par->physbase); return 0; -} -static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + cg6_unmap_regs(op, info, par); - return cg6_init_one(op); +out_err: + return err; } static int __devexit cg6_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg6_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - cg6_unmap_regs(op, all); + cg6_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index f48e8c5..6796ba6 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -24,6 +24,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fb.h> +#include <linux/pm.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/console.h> @@ -458,7 +459,7 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (state.event == pdev->dev.power.power_state.event) return 0; - if (state.event != PM_SUSPEND_MEM) + if (state.event != PM_EVENT_SUSPEND) goto done; acquire_console_sem(); diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index a6828d0..96979c3 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -133,8 +133,8 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, if ((yres < 400) == (f->height <= 8)) c += 1000; - if (!(font_w & (1 << (f->width - 1))) || - !(font_w & (1 << (f->height - 1)))) + if ((font_w & (1 << (f->width - 1))) && + (font_h & (1 << (f->height - 1)))) c += 1000; if (c > cc) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 215ac57..0740272 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -244,8 +244,17 @@ static void fb_set_logo(struct fb_info *info, u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; u8 fg = 1, d; - if (fb_get_color_depth(&info->var, &info->fix) == 3) + switch (fb_get_color_depth(&info->var, &info->fix)) { + case 1: + fg = 1; + break; + case 2: + fg = 3; + break; + default: fg = 7; + break; + } if (info->fix.visual == FB_VISUAL_MONO01 || info->fix.visual == FB_VISUAL_MONO10) @@ -564,21 +573,6 @@ int fb_prepare_logo(struct fb_info *info, int rotate) depth = 4; } - if (depth >= 8) { - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - fb_logo.needs_truepalette = 1; - break; - case FB_VISUAL_DIRECTCOLOR: - fb_logo.needs_directpalette = 1; - fb_logo.needs_cmapreset = 1; - break; - case FB_VISUAL_PSEUDOCOLOR: - fb_logo.needs_cmapreset = 1; - break; - } - } - /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); @@ -604,6 +598,22 @@ int fb_prepare_logo(struct fb_info *info, int rotate) else fb_logo.depth = 1; + + if (fb_logo.depth > 4 && depth > 4) { + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + fb_logo.needs_truepalette = 1; + break; + case FB_VISUAL_DIRECTCOLOR: + fb_logo.needs_directpalette = 1; + fb_logo.needs_cmapreset = 1; + break; + case FB_VISUAL_PSEUDOCOLOR: + fb_logo.needs_cmapreset = 1; + break; + } + } + return fb_prepare_extra_logos(info, fb_logo.logo->height, yres); } diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 3f6c98f..4b520b5 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -371,6 +371,8 @@ struct ffb_par { unsigned long fbsize; int board_type; + + u32 pseudo_palette[16]; }; static void FFBFifo(struct ffb_par *par, int n) @@ -900,75 +902,67 @@ ffb_init_fix(struct fb_info *info) info->fix.accel = FB_ACCEL_SUN_CREATOR; } -struct all_info { - struct fb_info info; - struct ffb_par par; - u32 pseudo_palette[16]; -}; - -static int ffb_init_one(struct of_device *op) +static int __devinit ffb_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; struct ffb_fbc __iomem *fbc; struct ffb_dac __iomem *dac; - struct all_info *all; - int err; + struct fb_info *info; + struct ffb_par *par; u32 dac_pnum, dac_rev, dac_mrev; + int err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev); - spin_lock_init(&all->par.lock); - all->par.fbc = of_ioremap(&op->resource[2], 0, - sizeof(struct ffb_fbc), "ffb fbc"); - if (!all->par.fbc) { - kfree(all); - return -ENOMEM; - } + err = -ENOMEM; + if (!info) + goto out_err; - all->par.dac = of_ioremap(&op->resource[1], 0, - sizeof(struct ffb_dac), "ffb dac"); - if (!all->par.dac) { - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - kfree(all); - return -ENOMEM; - } + par = info->par; + + spin_lock_init(&par->lock); + par->fbc = of_ioremap(&op->resource[2], 0, + sizeof(struct ffb_fbc), "ffb fbc"); + if (!par->fbc) + goto out_release_fb; + + par->dac = of_ioremap(&op->resource[1], 0, + sizeof(struct ffb_dac), "ffb dac"); + if (!par->dac) + goto out_unmap_fbc; - all->par.rop_cache = FFB_ROP_NEW; - all->par.physbase = op->resource[0].start; + par->rop_cache = FFB_ROP_NEW; + par->physbase = op->resource[0].start; /* Don't mention copyarea, so SCROLL_REDRAW is always * used. It is the fastest on this chip. */ - all->info.flags = (FBINFO_DEFAULT | - /* FBINFO_HWACCEL_COPYAREA | */ - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT); - all->info.fbops = &ffb_ops; - all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF; - all->info.par = &all->par; - all->info.pseudo_palette = all->pseudo_palette; - - sbusfb_fill_var(&all->info.var, dp->node, 32); - all->par.fbsize = PAGE_ALIGN(all->info.var.xres * - all->info.var.yres * - 4); - ffb_fixup_var_rgb(&all->info.var); - - all->info.var.accel_flags = FB_ACCELF_TEXT; + info->flags = (FBINFO_DEFAULT | + /* FBINFO_HWACCEL_COPYAREA | */ + FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_IMAGEBLIT); + + info->fbops = &ffb_ops; + + info->screen_base = (char *) par->physbase + FFB_DFB24_POFF; + info->pseudo_palette = par->pseudo_palette; + + sbusfb_fill_var(&info->var, dp->node, 32); + par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4); + ffb_fixup_var_rgb(&info->var); + + info->var.accel_flags = FB_ACCELF_TEXT; if (!strcmp(dp->name, "SUNW,afb")) - all->par.flags |= FFB_FLAG_AFB; + par->flags |= FFB_FLAG_AFB; - all->par.board_type = of_getintprop_default(dp, "board_type", 0); + par->board_type = of_getintprop_default(dp, "board_type", 0); - fbc = all->par.fbc; + fbc = par->fbc; if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); - dac = all->par.dac; + dac = par->dac; upa_writel(FFB_DAC_DID, &dac->type); dac_pnum = upa_readl(&dac->value); dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; @@ -985,76 +979,70 @@ static int ffb_init_one(struct of_device *op) * cursor logic. We identify Pacifica 1 as not Pacifica 2, the * latter having a part number value of 0x236e. */ - if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { - all->par.flags &= ~FFB_FLAG_INVCURSOR; + if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { + par->flags &= ~FFB_FLAG_INVCURSOR; } else { if (dac_mrev < 3) - all->par.flags |= FFB_FLAG_INVCURSOR; + par->flags |= FFB_FLAG_INVCURSOR; } - ffb_switch_from_graph(&all->par); + ffb_switch_from_graph(par); /* Unblank it just to be sure. When there are multiple * FFB/AFB cards in the system, or it is not the OBP * chosen console, it will have video outputs off in * the DAC. */ - ffb_blank(0, &all->info); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - printk(KERN_ERR "ffb: Could not allocate color map.\n"); - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], - all->par.dac, sizeof(struct ffb_dac)); - kfree(all); - return -ENOMEM; - } + ffb_blank(0, info); - ffb_init_fix(&all->info); - - err = register_framebuffer(&all->info); - if (err < 0) { - printk(KERN_ERR "ffb: Could not register framebuffer.\n"); - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], - all->par.dac, sizeof(struct ffb_dac)); - kfree(all); - return err; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_dac; + + ffb_init_fix(info); - dev_set_drvdata(&op->dev, all); + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + dev_set_drvdata(&op->dev, info); printk("%s: %s at %016lx, type %d, " "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", dp->full_name, - ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), - all->par.physbase, all->par.board_type, + ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), + par->physbase, par->board_type, dac_pnum, dac_rev, dac_mrev); return 0; -} -static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_dac: + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + +out_unmap_fbc: + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + +out_release_fb: + framebuffer_release(info); - return ffb_init_one(op); +out_err: + return err; } static int __devexit ffb_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct ffb_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac)); + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac)); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index a814b6c..7608429 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -8,6 +8,21 @@ config FB_GEODE Say 'Y' here to allow you to select framebuffer drivers for the AMD Geode family of processors. +config FB_GEODE_LX + tristate "AMD Geode LX framebuffer support (EXPERIMENTAL)" + depends on FB && FB_GEODE + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the display controller integrated into the + AMD Geode LX processors. + + To compile this driver as a module, choose M here: the module will + be called lxfb. + + If unsure, say N. + config FB_GEODE_GX tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile index f896565..957304b 100644 --- a/drivers/video/geode/Makefile +++ b/drivers/video/geode/Makefile @@ -2,6 +2,8 @@ obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o obj-$(CONFIG_FB_GEODE_GX) += gxfb.o +obj-$(CONFIG_FB_GEODE_LX) += lxfb.o gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o gxfb-objs := gxfb_core.o display_gx.o video_gx.o +lxfb-objs := lxfb_core.o lxfb_ops.o diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h new file mode 100644 index 0000000..6c227f9 --- /dev/null +++ b/drivers/video/geode/lxfb.h @@ -0,0 +1,199 @@ +#ifndef _LXFB_H_ +#define _LXFB_H_ + +#include <linux/fb.h> + +#define OUTPUT_CRT 0x01 +#define OUTPUT_PANEL 0x02 + +struct lxfb_par { + int output; + int panel_width; + int panel_height; + + void __iomem *gp_regs; + void __iomem *dc_regs; + void __iomem *df_regs; +}; + +static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) +{ + return (((xres * (bpp >> 3)) + 7) & ~7); +} + +void lx_set_mode(struct fb_info *); +void lx_get_gamma(struct fb_info *, unsigned int *, int); +void lx_set_gamma(struct fb_info *, unsigned int *, int); +unsigned int lx_framebuffer_size(void); +int lx_blank_display(struct fb_info *, int); +void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, + unsigned int, unsigned int); + +/* MSRS */ + +#define MSR_LX_GLD_CONFIG 0x48002001 +#define MSR_LX_GLCP_DOTPLL 0x4c000015 +#define MSR_LX_DF_PADSEL 0x48000011 +#define MSR_LX_DC_SPARE 0x80000011 +#define MSR_LX_DF_GLCONFIG 0x48002001 + +#define MSR_LX_GLIU0_P2D_RO0 0x10000029 + +#define GLCP_DOTPLL_RESET (1 << 0) +#define GLCP_DOTPLL_BYPASS (1 << 15) +#define GLCP_DOTPLL_HALFPIX (1 << 24) +#define GLCP_DOTPLL_LOCK (1 << 25) + +#define DF_CONFIG_OUTPUT_MASK 0x38 +#define DF_OUTPUT_PANEL 0x08 +#define DF_OUTPUT_CRT 0x00 +#define DF_SIMULTANEOUS_CRT_AND_FP (1 << 15) + +#define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF +#define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F + +#define DC_SPARE_DISABLE_CFIFO_HGO 0x00000800 +#define DC_SPARE_VFIFO_ARB_SELECT 0x00000400 +#define DC_SPARE_WM_LPEN_OVRD 0x00000200 +#define DC_SPARE_LOAD_WM_LPEN_MASK 0x00000100 +#define DC_SPARE_DISABLE_INIT_VID_PRI 0x00000080 +#define DC_SPARE_DISABLE_VFIFO_WM 0x00000040 +#define DC_SPARE_DISABLE_CWD_CHECK 0x00000020 +#define DC_SPARE_PIX8_PAN_FIX 0x00000010 +#define DC_SPARE_FIRST_REQ_MASK 0x00000002 + +/* Registers */ + +#define DC_UNLOCK 0x00 +#define DC_UNLOCK_CODE 0x4758 + +#define DC_GENERAL_CFG 0x04 +#define DC_GCFG_DFLE (1 << 0) +#define DC_GCFG_VIDE (1 << 3) +#define DC_GCFG_VGAE (1 << 7) +#define DC_GCFG_CMPE (1 << 5) +#define DC_GCFG_DECE (1 << 6) +#define DC_GCFG_FDTY (1 << 17) + +#define DC_DISPLAY_CFG 0x08 +#define DC_DCFG_TGEN (1 << 0) +#define DC_DCFG_GDEN (1 << 3) +#define DC_DCFG_VDEN (1 << 4) +#define DC_DCFG_TRUP (1 << 6) +#define DC_DCFG_DCEN (1 << 24) +#define DC_DCFG_PALB (1 << 25) +#define DC_DCFG_VISL (1 << 27) + +#define DC_DCFG_16BPP 0x0 + +#define DC_DCFG_DISP_MODE_MASK 0x00000300 +#define DC_DCFG_DISP_MODE_8BPP 0x00000000 +#define DC_DCFG_DISP_MODE_16BPP 0x00000100 +#define DC_DCFG_DISP_MODE_24BPP 0x00000200 +#define DC_DCFG_DISP_MODE_32BPP 0x00000300 + + +#define DC_ARB_CFG 0x0C + +#define DC_FB_START 0x10 +#define DC_CB_START 0x14 +#define DC_CURSOR_START 0x18 + +#define DC_DV_TOP 0x2C +#define DC_DV_TOP_ENABLE (1 << 0) + +#define DC_LINE_SIZE 0x30 +#define DC_GRAPHICS_PITCH 0x34 +#define DC_H_ACTIVE_TIMING 0x40 +#define DC_H_BLANK_TIMING 0x44 +#define DC_H_SYNC_TIMING 0x48 +#define DC_V_ACTIVE_TIMING 0x50 +#define DC_V_BLANK_TIMING 0x54 +#define DC_V_SYNC_TIMING 0x58 +#define DC_FB_ACTIVE 0x5C + +#define DC_PAL_ADDRESS 0x70 +#define DC_PAL_DATA 0x74 + +#define DC_PHY_MEM_OFFSET 0x84 + +#define DC_DV_CTL 0x88 +#define DC_DV_LINE_SIZE_MASK 0x00000C00 +#define DC_DV_LINE_SIZE_1024 0x00000000 +#define DC_DV_LINE_SIZE_2048 0x00000400 +#define DC_DV_LINE_SIZE_4096 0x00000800 +#define DC_DV_LINE_SIZE_8192 0x00000C00 + + +#define DC_GFX_SCALE 0x90 +#define DC_IRQ_FILT_CTL 0x94 + + +#define DC_IRQ 0xC8 +#define DC_IRQ_MASK (1 << 0) +#define DC_VSYNC_IRQ_MASK (1 << 1) +#define DC_IRQ_STATUS (1 << 20) +#define DC_VSYNC_IRQ_STATUS (1 << 21) + +#define DC_GENLCK_CTRL 0xD4 +#define DC_GENLCK_ENABLE (1 << 18) +#define DC_GC_ALPHA_FLICK_ENABLE (1 << 25) +#define DC_GC_FLICKER_FILTER_ENABLE (1 << 24) +#define DC_GC_FLICKER_FILTER_MASK (0x0F << 28) + +#define DC_COLOR_KEY 0xB8 +#define DC_CLR_KEY_ENABLE (1 << 24) + + +#define DC3_DV_LINE_SIZE_MASK 0x00000C00 +#define DC3_DV_LINE_SIZE_1024 0x00000000 +#define DC3_DV_LINE_SIZE_2048 0x00000400 +#define DC3_DV_LINE_SIZE_4096 0x00000800 +#define DC3_DV_LINE_SIZE_8192 0x00000C00 + +#define DF_VIDEO_CFG 0x0 +#define DF_VCFG_VID_EN (1 << 0) + +#define DF_DISPLAY_CFG 0x08 + +#define DF_DCFG_CRT_EN (1 << 0) +#define DF_DCFG_HSYNC_EN (1 << 1) +#define DF_DCFG_VSYNC_EN (1 << 2) +#define DF_DCFG_DAC_BL_EN (1 << 3) +#define DF_DCFG_CRT_HSYNC_POL (1 << 8) +#define DF_DCFG_CRT_VSYNC_POL (1 << 9) +#define DF_DCFG_GV_PAL_BYP (1 << 21) + +#define DF_DCFG_CRT_SYNC_SKW_INIT 0x10000 +#define DF_DCFG_CRT_SYNC_SKW_MASK 0x1c000 + +#define DF_DCFG_PWR_SEQ_DLY_INIT 0x80000 +#define DF_DCFG_PWR_SEQ_DLY_MASK 0xe0000 + +#define DF_MISC 0x50 + +#define DF_MISC_GAM_BYPASS (1 << 0) +#define DF_MISC_DAC_PWRDN (1 << 10) +#define DF_MISC_A_PWRDN (1 << 11) + +#define DF_PAR 0x38 +#define DF_PDR 0x40 +#define DF_ALPHA_CONTROL_1 0xD8 +#define DF_VIDEO_REQUEST 0x120 + +#define DF_PANEL_TIM1 0x400 +#define DF_DEFAULT_TFT_PMTIM1 0x0 + +#define DF_PANEL_TIM2 0x408 +#define DF_DEFAULT_TFT_PMTIM2 0x08000000 + +#define DF_FP_PM 0x410 +#define DF_FP_PM_P (1 << 24) + +#define DF_DITHER_CONTROL 0x418 +#define DF_DEFAULT_TFT_DITHCTL 0x00000070 +#define GP_BLT_STATUS 0x44 +#define GP_BS_BLT_BUSY (1 << 0) +#define GP_BS_CB_EMPTY (1 << 4) + +#endif diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c new file mode 100644 index 0000000..5e30b40 --- /dev/null +++ b/drivers/video/geode/lxfb_core.c @@ -0,0 +1,621 @@ +/* + * Geode LX framebuffer driver. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.) + * + * 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 the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/console.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/uaccess.h> + +#include "lxfb.h" + +static char *mode_option; +static int noclear, nopanel, nocrt; +static int fbsize; + +/* Most of these modes are sorted in ascending order, but + * since the first entry in this table is the "default" mode, + * we try to make it something sane - 640x480-60 is sane + */ + +const struct fb_videomode geode_modedb[] __initdata = { + /* 640x480-60 */ + { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x400-70 */ + { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2, + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-70 */ + { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-72 */ + { NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-75 */ + { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-85 */ + { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-90 */ + { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-100 */ + { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-60 */ + { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-56 */ + { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-60 */ + { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-70 */ + { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-72 */ + { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-75 */ + { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-85 */ + { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-90 */ + { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-100 */ + { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-60 */ + { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-60 */ + { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-70 */ + { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-72 */ + { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-75 */ + { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-85 */ + { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-90 */ + { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-100 */ + { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-60 */ + { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-60 */ + { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-70 */ + { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-72 */ + { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-75 */ + { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-85 */ + { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-90 */ + { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-100 */ + { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-60 */ + { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-60 */ + { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-70 */ + { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-72 */ + { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-75 */ + { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-85 */ + { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-90 */ + { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-100 */ + { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-60 */ + { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-60 */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-70 */ + { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-72 */ + { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-75 */ + { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-85 */ + { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-90 */ + { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-100 */ + { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-60 */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-60 */ + { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-70 */ + { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-72 */ + { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-75 */ + { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-85 */ + { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, +}; + +static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + if (var->xres > 1920 || var->yres > 1440) + return -EINVAL; + + if (var->bits_per_pixel == 32) { + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else if (var->bits_per_pixel == 16) { + var->red.offset = 11; var->red.length = 5; + var->green.offset = 5; var->green.length = 6; + var->blue.offset = 0; var->blue.length = 5; + } else if (var->bits_per_pixel == 8) { + var->red.offset = 0; var->red.length = 8; + var->green.offset = 0; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else + return -EINVAL; + + var->transp.offset = 0; var->transp.length = 0; + + /* Enough video memory? */ + if ((lx_get_pitch(var->xres, var->bits_per_pixel) * var->yres) + > info->fix.smem_len) + return -EINVAL; + + return 0; +} + +static int lxfb_set_par(struct fb_info *info) +{ + if (info->var.bits_per_pixel > 8) { + info->fix.visual = FB_VISUAL_TRUECOLOR; + fb_dealloc_cmap(&info->cmap); + } else { + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0); + } + + info->fix.line_length = lx_get_pitch(info->var.xres, + info->var.bits_per_pixel); + + lx_set_mode(info); + return 0; +} + +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int lxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Truecolor has hardware independent palette */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *pal = info->pseudo_palette; + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = chan_to_field(red, &info->var.red); + v |= chan_to_field(green, &info->var.green); + v |= chan_to_field(blue, &info->var.blue); + + pal[regno] = v; + } else { + if (regno >= 256) + return -EINVAL; + + lx_set_palette_reg(info, regno, red, green, blue); + } + + return 0; +} + +static int lxfb_blank(int blank_mode, struct fb_info *info) +{ + return lx_blank_display(info, blank_mode); +} + + +static int __init lxfb_map_video_memory(struct fb_info *info, + struct pci_dev *dev) +{ + struct lxfb_par *par = info->par; + int ret; + + ret = pci_enable_device(dev); + + if (ret) + return ret; + + ret = pci_request_region(dev, 0, "lxfb-framebuffer"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 1, "lxfb-gp"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 2, "lxfb-vg"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 3, "lxfb-vip"); + + if (ret) + return ret; + + info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_len = fbsize ? fbsize : lx_framebuffer_size(); + + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); + + ret = -ENOMEM; + + if (info->screen_base == NULL) + return ret; + + par->gp_regs = ioremap(pci_resource_start(dev, 1), + pci_resource_len(dev, 1)); + + if (par->gp_regs == NULL) + return ret; + + par->dc_regs = ioremap(pci_resource_start(dev, 2), + pci_resource_len(dev, 2)); + + if (par->dc_regs == NULL) + return ret; + + par->df_regs = ioremap(pci_resource_start(dev, 3), + pci_resource_len(dev, 3)); + + if (par->df_regs == NULL) + return ret; + + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_PHY_MEM_OFFSET); + + writel(0, par->dc_regs + DC_UNLOCK); + + dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n", + info->fix.smem_len / 1024, info->fix.smem_start); + + return 0; +} + +static struct fb_ops lxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = lxfb_check_var, + .fb_set_par = lxfb_set_par, + .fb_setcolreg = lxfb_setcolreg, + .fb_blank = lxfb_blank, + /* No HW acceleration for now. */ + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static struct fb_info * __init lxfb_init_fbinfo(struct device *dev) +{ + struct lxfb_par *par; + struct fb_info *info; + + /* Alloc enough space for the pseudo palette. */ + info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16, + dev); + if (!info) + return NULL; + + par = info->par; + + strcpy(info->fix.id, "Geode LX"); + + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type_aux = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.accel = FB_ACCEL_NONE; + + info->var.nonstd = 0; + info->var.activate = FB_ACTIVATE_NOW; + info->var.height = -1; + info->var.width = -1; + info->var.accel_flags = 0; + info->var.vmode = FB_VMODE_NONINTERLACED; + + info->fbops = &lxfb_ops; + info->flags = FBINFO_DEFAULT; + info->node = -1; + + info->pseudo_palette = (void *)par + sizeof(struct lxfb_par); + + info->var.grayscale = 0; + + return info; +} + +static int __init lxfb_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct lxfb_par *par; + struct fb_info *info; + int ret; + + struct fb_videomode *modedb_ptr; + int modedb_size; + + info = lxfb_init_fbinfo(&pdev->dev); + + if (info == NULL) + return -ENOMEM; + + par = info->par; + + ret = lxfb_map_video_memory(info, pdev); + + if (ret < 0) { + dev_err(&pdev->dev, + "failed to map frame buffer or controller registers\n"); + goto err; + } + + /* Set up the desired outputs */ + + par->output = 0; + par->output |= (nopanel) ? 0 : OUTPUT_PANEL; + par->output |= (nocrt) ? 0 : OUTPUT_CRT; + + /* Set up the mode database */ + + modedb_ptr = (struct fb_videomode *) geode_modedb; + modedb_size = ARRAY_SIZE(geode_modedb); + + ret = fb_find_mode(&info->var, info, mode_option, + modedb_ptr, modedb_size, NULL, 16); + + if (ret == 0 || ret == 4) { + dev_err(&pdev->dev, "could not find valid video mode\n"); + ret = -EINVAL; + goto err; + } + + /* Clear the screen of garbage, unless noclear was specified, + * in which case we assume the user knows what he is doing */ + + if (!noclear) + memset_io(info->screen_base, 0, info->fix.smem_len); + + /* Set the mode */ + + lxfb_check_var(&info->var, info); + lxfb_set_par(info); + + if (register_framebuffer(info) < 0) { + ret = -EINVAL; + goto err; + } + pci_set_drvdata(pdev, info); + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + return 0; + +err: + if (info->screen_base) { + iounmap(info->screen_base); + pci_release_region(pdev, 0); + } + if (par->gp_regs) { + iounmap(par->gp_regs); + pci_release_region(pdev, 1); + } + if (par->dc_regs) { + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + } + if (par->df_regs) { + iounmap(par->df_regs); + pci_release_region(pdev, 3); + } + + if (info) + framebuffer_release(info); + + return ret; +} + +static void lxfb_remove(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct lxfb_par *par = info->par; + + unregister_framebuffer(info); + + iounmap(info->screen_base); + pci_release_region(pdev, 0); + + iounmap(par->gp_regs); + pci_release_region(pdev, 1); + + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + + iounmap(par->df_regs); + pci_release_region(pdev, 3); + + pci_set_drvdata(pdev, NULL); + framebuffer_release(info); +} + +static struct pci_device_id lxfb_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, lxfb_id_table); + +static struct pci_driver lxfb_driver = { + .name = "lxfb", + .id_table = lxfb_id_table, + .probe = lxfb_probe, + .remove = lxfb_remove, +}; + +#ifndef MODULE +static int __init lxfb_setup(char *options) +{ + char *opt; + + if (!options || !*options) + return 0; + + while (1) { + char *opt = strsep(&options, ","); + + if (opt == NULL) + break; + + if (!*opt) + continue; + + if (!strncmp(opt, "fbsize:", 7)) + fbsize = simple_strtoul(opt+7, NULL, 0); + else if (!strcmp(opt, "noclear")) + noclear = 1; + else if (!strcmp(opt, "nopanel")) + nopanel = 1; + else if (!strcmp(opt, "nocrt")) + nocrt = 1; + else + mode_option = opt; + } + + return 0; +} +#endif + +static int __init lxfb_init(void) +{ +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("lxfb", &option)) + return -ENODEV; + + lxfb_setup(option); +#endif + return pci_register_driver(&lxfb_driver); +} +static void __exit lxfb_cleanup(void) +{ + pci_unregister_driver(&lxfb_driver); +} + +module_init(lxfb_init); +module_exit(lxfb_cleanup); + +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); + +module_param(fbsize, int, 0); +MODULE_PARM_DESC(fbsize, "video memory size"); + +MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c new file mode 100644 index 0000000..4fbc99b --- /dev/null +++ b/drivers/video/geode/lxfb_ops.c @@ -0,0 +1,536 @@ +/* Geode LX framebuffer driver + * + * Copyright (C) 2006-2007, Advanced Micro Devices,Inc. + * + * 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 the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/uaccess.h> +#include <linux/delay.h> + +#include "lxfb.h" + +/* TODO + * Support panel scaling + * Add acceleration + * Add support for interlacing (TV out) + * Support compression + */ + +/* This is the complete list of PLL frequencies that we can set - + * we will choose the closest match to the incoming clock. + * freq is the frequency of the dotclock * 1000 (for example, + * 24823 = 24.983 Mhz). + * pllval is the corresponding PLL value +*/ + +static const struct { + unsigned int pllval; + unsigned int freq; +} pll_table[] = { + { 0x000031AC, 24923 }, + { 0x0000215D, 25175 }, + { 0x00001087, 27000 }, + { 0x0000216C, 28322 }, + { 0x0000218D, 28560 }, + { 0x000010C9, 31200 }, + { 0x00003147, 31500 }, + { 0x000010A7, 33032 }, + { 0x00002159, 35112 }, + { 0x00004249, 35500 }, + { 0x00000057, 36000 }, + { 0x0000219A, 37889 }, + { 0x00002158, 39168 }, + { 0x00000045, 40000 }, + { 0x00000089, 43163 }, + { 0x000010E7, 44900 }, + { 0x00002136, 45720 }, + { 0x00003207, 49500 }, + { 0x00002187, 50000 }, + { 0x00004286, 56250 }, + { 0x000010E5, 60065 }, + { 0x00004214, 65000 }, + { 0x00001105, 68179 }, + { 0x000031E4, 74250 }, + { 0x00003183, 75000 }, + { 0x00004284, 78750 }, + { 0x00001104, 81600 }, + { 0x00006363, 94500 }, + { 0x00005303, 97520 }, + { 0x00002183, 100187 }, + { 0x00002122, 101420 }, + { 0x00001081, 108000 }, + { 0x00006201, 113310 }, + { 0x00000041, 119650 }, + { 0x000041A1, 129600 }, + { 0x00002182, 133500 }, + { 0x000041B1, 135000 }, + { 0x00000051, 144000 }, + { 0x000041E1, 148500 }, + { 0x000062D1, 157500 }, + { 0x000031A1, 162000 }, + { 0x00000061, 169203 }, + { 0x00004231, 172800 }, + { 0x00002151, 175500 }, + { 0x000052E1, 189000 }, + { 0x00000071, 192000 }, + { 0x00003201, 198000 }, + { 0x00004291, 202500 }, + { 0x00001101, 204750 }, + { 0x00007481, 218250 }, + { 0x00004170, 229500 }, + { 0x00006210, 234000 }, + { 0x00003140, 251182 }, + { 0x00006250, 261000 }, + { 0x000041C0, 278400 }, + { 0x00005220, 280640 }, + { 0x00000050, 288000 }, + { 0x000041E0, 297000 }, + { 0x00002130, 320207 } +}; + + +static void lx_set_dotpll(u32 pllval) +{ + u32 dotpll_lo, dotpll_hi; + int i; + + rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + + if ((dotpll_lo & GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) + return; + + dotpll_hi = pllval; + dotpll_lo &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX); + dotpll_lo |= GLCP_DOTPLL_RESET; + + wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + + /* Wait 100us for the PLL to lock */ + + udelay(100); + + /* Now, loop for the lock bit */ + + for (i = 0; i < 1000; i++) { + rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + if (dotpll_lo & GLCP_DOTPLL_LOCK) + break; + } + + /* Clear the reset bit */ + + dotpll_lo &= ~GLCP_DOTPLL_RESET; + wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); +} + +/* Set the clock based on the frequency specified by the current mode */ + +static void lx_set_clock(struct fb_info *info) +{ + unsigned int diff, min, best = 0; + unsigned int freq, i; + + freq = (unsigned int) (0x3b9aca00 / info->var.pixclock); + + min = abs(pll_table[0].freq - freq); + + for (i = 0; i < ARRAY_SIZE(pll_table); i++) { + diff = abs(pll_table[i].freq - freq); + if (diff < min) { + min = diff; + best = i; + } + } + + lx_set_dotpll(pll_table[best].pllval & 0x7FFF); +} + +static void lx_graphics_disable(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + unsigned int val, gcfg; + + /* Note: This assumes that the video is in a quitet state */ + + writel(0, par->df_regs + DF_ALPHA_CONTROL_1); + writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 32); + writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 64); + + /* Turn off the VGA and video enable */ + val = readl (par->dc_regs + DC_GENERAL_CFG) & + ~(DC_GCFG_VGAE | DC_GCFG_VIDE); + + writel(val, par->dc_regs + DC_GENERAL_CFG); + + val = readl(par->df_regs + DF_VIDEO_CFG) & ~DF_VCFG_VID_EN; + writel(val, par->df_regs + DF_VIDEO_CFG); + + writel( DC_IRQ_MASK | DC_VSYNC_IRQ_MASK | + DC_IRQ_STATUS | DC_VSYNC_IRQ_STATUS, + par->dc_regs + DC_IRQ); + + val = readl(par->dc_regs + DC_GENLCK_CTRL) & ~DC_GENLCK_ENABLE; + writel(val, par->dc_regs + DC_GENLCK_CTRL); + + val = readl(par->dc_regs + DC_COLOR_KEY) & ~DC_CLR_KEY_ENABLE; + writel(val & ~DC_CLR_KEY_ENABLE, par->dc_regs + DC_COLOR_KEY); + + /* We don't actually blank the panel, due to the long latency + involved with bringing it back */ + + val = readl(par->df_regs + DF_MISC) | DF_MISC_DAC_PWRDN; + writel(val, par->df_regs + DF_MISC); + + /* Turn off the display */ + + val = readl(par->df_regs + DF_DISPLAY_CFG); + writel(val & ~(DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN | + DF_DCFG_DAC_BL_EN), par->df_regs + DF_DISPLAY_CFG); + + gcfg = readl(par->dc_regs + DC_GENERAL_CFG); + gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Turn off the TGEN */ + val = readl(par->dc_regs + DC_DISPLAY_CFG); + val &= ~DC_DCFG_TGEN; + writel(val, par->dc_regs + DC_DISPLAY_CFG); + + /* Wait 1000 usecs to ensure that the TGEN is clear */ + udelay(1000); + + /* Turn off the FIFO loader */ + + gcfg &= ~DC_GCFG_DFLE; + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Lastly, wait for the GP to go idle */ + + do { + val = readl(par->gp_regs + GP_BLT_STATUS); + } while ((val & GP_BS_BLT_BUSY) || !(val & GP_BS_CB_EMPTY)); +} + +static void lx_graphics_enable(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + u32 temp, config; + + /* Set the video request register */ + writel(0, par->df_regs + DF_VIDEO_REQUEST); + + /* Set up the polarities */ + + config = readl(par->df_regs + DF_DISPLAY_CFG); + + config &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK | + DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL); + + config |= (DF_DCFG_CRT_SYNC_SKW_INIT | DF_DCFG_PWR_SEQ_DLY_INIT | + DF_DCFG_GV_PAL_BYP); + + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + config |= DF_DCFG_CRT_HSYNC_POL; + + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + config |= DF_DCFG_CRT_VSYNC_POL; + + if (par->output & OUTPUT_PANEL) { + u32 msrlo, msrhi; + + writel(DF_DEFAULT_TFT_PMTIM1, + par->df_regs + DF_PANEL_TIM1); + writel(DF_DEFAULT_TFT_PMTIM2, + par->df_regs + DF_PANEL_TIM2); + writel(DF_DEFAULT_TFT_DITHCTL, + par->df_regs + DF_DITHER_CONTROL); + + msrlo = DF_DEFAULT_TFT_PAD_SEL_LOW; + msrhi = DF_DEFAULT_TFT_PAD_SEL_HIGH; + + wrmsr(MSR_LX_DF_PADSEL, msrlo, msrhi); + } + + if (par->output & OUTPUT_CRT) { + config |= DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN; + } + + writel(config, par->df_regs + DF_DISPLAY_CFG); + + /* Turn the CRT dacs back on */ + + if (par->output & OUTPUT_CRT) { + temp = readl(par->df_regs + DF_MISC); + temp &= ~(DF_MISC_DAC_PWRDN | DF_MISC_A_PWRDN); + writel(temp, par->df_regs + DF_MISC); + } + + /* Turn the panel on (if it isn't already) */ + + if (par->output & OUTPUT_PANEL) { + temp = readl(par->df_regs + DF_FP_PM); + + if (!(temp & 0x09)) + writel(temp | DF_FP_PM_P, par->df_regs + DF_FP_PM); + } + + temp = readl(par->df_regs + DF_MISC); + temp = readl(par->df_regs + DF_DISPLAY_CFG); +} + +unsigned int lx_framebuffer_size(void) +{ + unsigned int val; + + /* The frame buffer size is reported by a VSM in VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (1MB units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFE; + return (val << 20); +} + +void lx_set_mode(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + u64 msrval; + + unsigned int max, dv, val, size; + + unsigned int gcfg, dcfg; + int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; + int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; + + /* Unlock the DC registers */ + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); + + lx_graphics_disable(info); + + lx_set_clock(info); + + /* Set output mode */ + + rdmsrl(MSR_LX_DF_GLCONFIG, msrval); + msrval &= ~DF_CONFIG_OUTPUT_MASK; + + if (par->output & OUTPUT_PANEL) { + msrval |= DF_OUTPUT_PANEL; + + if (par->output & OUTPUT_CRT) + msrval |= DF_SIMULTANEOUS_CRT_AND_FP; + else + msrval &= ~DF_SIMULTANEOUS_CRT_AND_FP; + } else { + msrval |= DF_OUTPUT_CRT; + } + + wrmsrl(MSR_LX_DF_GLCONFIG, msrval); + + /* Clear the various buffers */ + /* FIXME: Adjust for panning here */ + + writel(0, par->dc_regs + DC_FB_START); + writel(0, par->dc_regs + DC_CB_START); + writel(0, par->dc_regs + DC_CURSOR_START); + + /* FIXME: Add support for interlacing */ + /* FIXME: Add support for scaling */ + + val = readl(par->dc_regs + DC_GENLCK_CTRL); + val &= ~(DC_GC_ALPHA_FLICK_ENABLE | + DC_GC_FLICKER_FILTER_ENABLE | DC_GC_FLICKER_FILTER_MASK); + + /* Default scaling params */ + + writel((0x4000 << 16) | 0x4000, par->dc_regs + DC_GFX_SCALE); + writel(0, par->dc_regs + DC_IRQ_FILT_CTL); + writel(val, par->dc_regs + DC_GENLCK_CTRL); + + /* FIXME: Support compression */ + + if (info->fix.line_length > 4096) + dv = DC_DV_LINE_SIZE_8192; + else if (info->fix.line_length > 2048) + dv = DC_DV_LINE_SIZE_4096; + else if (info->fix.line_length > 1024) + dv = DC_DV_LINE_SIZE_2048; + else + dv = DC_DV_LINE_SIZE_1024; + + max = info->fix.line_length * info->var.yres; + max = (max + 0x3FF) & 0xFFFFFC00; + + writel(max | DC_DV_TOP_ENABLE, par->dc_regs + DC_DV_TOP); + + val = readl(par->dc_regs + DC_DV_CTL) & ~DC_DV_LINE_SIZE_MASK; + writel(val | dv, par->dc_regs + DC_DV_CTL); + + size = info->var.xres * (info->var.bits_per_pixel >> 3); + + writel(info->fix.line_length >> 3, par->dc_regs + DC_GRAPHICS_PITCH); + writel((size + 7) >> 3, par->dc_regs + DC_LINE_SIZE); + + /* Set default watermark values */ + + rdmsrl(MSR_LX_DC_SPARE, msrval); + + msrval &= ~(DC_SPARE_DISABLE_CFIFO_HGO | DC_SPARE_VFIFO_ARB_SELECT | + DC_SPARE_LOAD_WM_LPEN_MASK | DC_SPARE_WM_LPEN_OVRD | + DC_SPARE_DISABLE_INIT_VID_PRI | DC_SPARE_DISABLE_VFIFO_WM); + msrval |= DC_SPARE_DISABLE_VFIFO_WM | DC_SPARE_DISABLE_INIT_VID_PRI; + wrmsrl(MSR_LX_DC_SPARE, msrval); + + gcfg = DC_GCFG_DFLE; /* Display fifo enable */ + gcfg |= 0xB600; /* Set default priority */ + gcfg |= DC_GCFG_FDTY; /* Set the frame dirty mode */ + + dcfg = DC_DCFG_VDEN; /* Enable video data */ + dcfg |= DC_DCFG_GDEN; /* Enable graphics */ + dcfg |= DC_DCFG_TGEN; /* Turn on the timing generator */ + dcfg |= DC_DCFG_TRUP; /* Update timings immediately */ + dcfg |= DC_DCFG_PALB; /* Palette bypass in > 8 bpp modes */ + dcfg |= DC_DCFG_VISL; + dcfg |= DC_DCFG_DCEN; /* Always center the display */ + + /* Set the current BPP mode */ + + switch (info->var.bits_per_pixel) { + case 8: + dcfg |= DC_DCFG_DISP_MODE_8BPP; + break; + + case 16: + dcfg |= DC_DCFG_DISP_MODE_16BPP | DC_DCFG_16BPP; + break; + + case 32: + case 24: + dcfg |= DC_DCFG_DISP_MODE_24BPP; + break; + } + + /* Now - set up the timings */ + + hactive = info->var.xres; + hblankstart = hactive; + hsyncstart = hblankstart + info->var.right_margin; + hsyncend = hsyncstart + info->var.hsync_len; + hblankend = hsyncend + info->var.left_margin; + htotal = hblankend; + + vactive = info->var.yres; + vblankstart = vactive; + vsyncstart = vblankstart + info->var.lower_margin; + vsyncend = vsyncstart + info->var.vsync_len; + vblankend = vsyncend + info->var.upper_margin; + vtotal = vblankend; + + writel((hactive - 1) | ((htotal - 1) << 16), + par->dc_regs + DC_H_ACTIVE_TIMING); + writel((hblankstart - 1) | ((hblankend - 1) << 16), + par->dc_regs + DC_H_BLANK_TIMING); + writel((hsyncstart - 1) | ((hsyncend - 1) << 16), + par->dc_regs + DC_H_SYNC_TIMING); + + writel((vactive - 1) | ((vtotal - 1) << 16), + par->dc_regs + DC_V_ACTIVE_TIMING); + + writel((vblankstart - 1) | ((vblankend - 1) << 16), + par->dc_regs + DC_V_BLANK_TIMING); + + writel((vsyncstart - 1) | ((vsyncend - 1) << 16), + par->dc_regs + DC_V_SYNC_TIMING); + + writel( (info->var.xres - 1) << 16 | (info->var.yres - 1), + par->dc_regs + DC_FB_ACTIVE); + + /* And re-enable the graphics output */ + lx_graphics_enable(info); + + /* Write the two main configuration registers */ + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); + writel(0, par->dc_regs + DC_ARB_CFG); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Lock the DC registers */ + writel(0, par->dc_regs + DC_UNLOCK); +} + +void lx_set_palette_reg(struct fb_info *info, unsigned regno, + unsigned red, unsigned green, unsigned blue) +{ + struct lxfb_par *par = info->par; + int val; + + /* Hardware palette is in RGB 8-8-8 format. */ + + val = (red << 8) & 0xff0000; + val |= (green) & 0x00ff00; + val |= (blue >> 8) & 0x0000ff; + + writel(regno, par->dc_regs + DC_PAL_ADDRESS); + writel(val, par->dc_regs + DC_PAL_DATA); +} + +int lx_blank_display(struct fb_info *info, int blank_mode) +{ + struct lxfb_par *par = info->par; + u32 dcfg, fp_pm; + int blank, hsync, vsync; + + /* CRT power saving modes. */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + blank = 0; hsync = 1; vsync = 1; + break; + case FB_BLANK_NORMAL: + blank = 1; hsync = 1; vsync = 1; + break; + case FB_BLANK_VSYNC_SUSPEND: + blank = 1; hsync = 1; vsync = 0; + break; + case FB_BLANK_HSYNC_SUSPEND: + blank = 1; hsync = 0; vsync = 1; + break; + case FB_BLANK_POWERDOWN: + blank = 1; hsync = 0; vsync = 0; + break; + default: + return -EINVAL; + } + + dcfg = readl(par->df_regs + DF_DISPLAY_CFG); + dcfg &= ~(DF_DCFG_DAC_BL_EN + | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN); + if (!blank) + dcfg |= DF_DCFG_DAC_BL_EN; + if (hsync) + dcfg |= DF_DCFG_HSYNC_EN; + if (vsync) + dcfg |= DF_DCFG_VSYNC_EN; + writel(dcfg, par->df_regs + DF_DISPLAY_CFG); + + /* Power on/off flat panel */ + + if (par->output & OUTPUT_PANEL) { + fp_pm = readl(par->df_regs + DF_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~DF_FP_PM_P; + else + fp_pm |= DF_FP_PM_P; + writel(fp_pm, par->df_regs + DF_FP_PM); + } + + return 0; +} diff --git a/drivers/video/leo.c b/drivers/video/leo.c index a038aa5..45b9a5d 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -525,130 +525,123 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) var->transp.length = 0; } -struct all_info { - struct fb_info info; - struct leo_par par; -}; - -static void leo_unmap_regs(struct of_device *op, struct all_info *all) +static void leo_unmap_regs(struct of_device *op, struct fb_info *info, + struct leo_par *par) { - if (all->par.lc_ss0_usr) - of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000); - if (all->par.ld_ss0) - of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000); - if (all->par.ld_ss1) - of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000); - if (all->par.lx_krn) - of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000); - if (all->par.cursor) + if (par->lc_ss0_usr) + of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000); + if (par->ld_ss0) + of_iounmap(&op->resource[0], par->ld_ss0, 0x1000); + if (par->ld_ss1) + of_iounmap(&op->resource[0], par->ld_ss1, 0x1000); + if (par->lx_krn) + of_iounmap(&op->resource[0], par->lx_krn, 0x1000); + if (par->cursor) of_iounmap(&op->resource[0], - all->par.cursor, sizeof(struct leo_cursor)); - if (all->info.screen_base) - of_iounmap(&op->resource[0], all->info.screen_base, 0x800000); + par->cursor, sizeof(struct leo_cursor)); + if (info->screen_base) + of_iounmap(&op->resource[0], info->screen_base, 0x800000); } -static int __devinit leo_init_one(struct of_device *op) +static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct leo_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct leo_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; - sbusfb_fill_var(&all->info.var, dp->node, 32); - leo_fixup_var_rgb(&all->info.var); + sbusfb_fill_var(&info->var, dp->node, 32); + leo_fixup_var_rgb(&info->var); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.lc_ss0_usr = + par->lc_ss0_usr = of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR, 0x1000, "leolc ss0usr"); - all->par.ld_ss0 = + par->ld_ss0 = of_ioremap(&op->resource[0], LEO_OFF_LD_SS0, 0x1000, "leold ss0"); - all->par.ld_ss1 = + par->ld_ss1 = of_ioremap(&op->resource[0], LEO_OFF_LD_SS1, 0x1000, "leold ss1"); - all->par.lx_krn = + par->lx_krn = of_ioremap(&op->resource[0], LEO_OFF_LX_KRN, 0x1000, "leolx krn"); - all->par.cursor = + par->cursor = of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR, sizeof(struct leo_cursor), "leolx cursor"); - all->info.screen_base = + info->screen_base = of_ioremap(&op->resource[0], LEO_OFF_SS0, 0x800000, "leo ram"); - if (!all->par.lc_ss0_usr || - !all->par.ld_ss0 || - !all->par.ld_ss1 || - !all->par.lx_krn || - !all->par.cursor || - !all->info.screen_base) { - leo_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (!par->lc_ss0_usr || + !par->ld_ss0 || + !par->ld_ss1 || + !par->lx_krn || + !par->cursor || + !info->screen_base) + goto out_unmap_regs; - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - all->info.fbops = &leo_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->fbops = &leo_ops; - leo_init_wids(&all->info); - leo_init_hw(&all->info); + leo_init_wids(info); + leo_init_hw(info); - leo_blank(0, &all->info); + leo_blank(0, info); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - leo_unmap_regs(op, all); - kfree(all); - return -ENOMEM;; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - leo_init_fix(&all->info, dp); + leo_init_fix(info, dp); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - leo_unmap_regs(op, all); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: leo at %lx:%lx\n", dp->full_name, - all->par.which_io, all->par.physbase); + par->which_io, par->physbase); return 0; -} -static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + leo_unmap_regs(op, info, par); + framebuffer_release(info); - return leo_init_one(op); +out_err: + return err; } static int __devexit leo_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct leo_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - leo_unmap_regs(op, all); + leo_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 637b78b..5849606 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -255,107 +255,95 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no info->fix.accel = FB_ACCEL_SUN_CGTHREE; } -struct all_info { - struct fb_info info; - struct p9100_par par; -}; - -static int __devinit p9100_init_one(struct of_device *op) +static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct p9100_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); /* This is the framebuffer and the only resource apps can mmap. */ - all->par.physbase = op->resource[2].start; - all->par.which_io = op->resource[2].flags & IORESOURCE_BITS; - - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; - - linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); - - all->par.regs = of_ioremap(&op->resource[0], 0, - sizeof(struct p9100_regs), "p9100 regs"); - if (!all->par.regs) { - kfree(all); - return -ENOMEM; - } + par->physbase = op->resource[2].start; + par->which_io = op->resource[2].flags & IORESOURCE_BITS; - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &p9100_ops; - all->info.screen_base = of_ioremap(&op->resource[2], 0, - all->par.fbsize, "p9100 ram"); - if (!all->info.screen_base) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - kfree(all); - return -ENOMEM; - } - all->info.par = &all->par; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; - p9100_blank(0, &all->info); + linebytes = of_getintprop_default(dp, "linebytes", info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], - all->info.screen_base, all->par.fbsize); - kfree(all); - return -ENOMEM; - } + par->regs = of_ioremap(&op->resource[0], 0, + sizeof(struct p9100_regs), "p9100 regs"); + if (!par->regs) + goto out_release_fb; - p9100_init_fix(&all->info, linebytes, dp); - - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } - fb_set_cmap(&all->info.cmap, &all->info); + info->flags = FBINFO_DEFAULT; + info->fbops = &p9100_ops; + info->screen_base = of_ioremap(&op->resource[2], 0, + par->fbsize, "p9100 ram"); + if (!info->screen_base) + goto out_unmap_regs; + + p9100_blank(0, info); + + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_screen; - dev_set_drvdata(&op->dev, all); + p9100_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + fb_set_cmap(&info->cmap, info); + + dev_set_drvdata(&op->dev, info); printk("%s: p9100 at %lx:%lx\n", dp->full_name, - all->par.which_io, all->par.physbase); + par->which_io, par->physbase); return 0; -} -static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_screen: + of_iounmap(&op->resource[2], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs)); + +out_release_fb: + framebuffer_release(info); - return p9100_init_one(op); +out_err: + return err; } static int __devexit p9100_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct p9100_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs)); + of_iounmap(&op->resource[2], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index ed34260..8a4c647 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -474,6 +474,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, { unsigned long flags; unsigned long irqen; + void __iomem *regs = fbi->io; local_irq_save(flags); @@ -483,9 +484,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, fbi->palette_ready = 1; /* enable IRQ */ - irqen = readl(S3C2410_LCDINTMSK); + irqen = readl(regs + S3C2410_LCDINTMSK); irqen &= ~S3C2410_LCDINT_FRSYNC; - writel(irqen, S3C2410_LCDINTMSK); + writel(irqen, regs + S3C2410_LCDINTMSK); } local_irq_restore(flags); @@ -680,6 +681,7 @@ static inline void modify_gpio(void __iomem *reg, static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) { unsigned long flags; + void __iomem *regs = fbi->io; /* Initialise LCD with values from haret */ @@ -694,25 +696,25 @@ static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) local_irq_restore(flags); - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); - writel(fbi->regs.lcdcon2, S3C2410_LCDCON2); - writel(fbi->regs.lcdcon3, S3C2410_LCDCON3); - writel(fbi->regs.lcdcon4, S3C2410_LCDCON4); - writel(fbi->regs.lcdcon5, S3C2410_LCDCON5); + writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); + writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); + writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); + writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); + writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); s3c2410fb_set_lcdaddr(fbi); dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); - writel(mach_info->lpcsel, S3C2410_LPCSEL); + writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); - dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL)); + dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); /* ensure temporary palette disabled */ - writel(0x00, S3C2410_TPAL); + writel(0x00, regs + S3C2410_TPAL); /* Enable video by setting the ENVID bit to 1 */ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); + writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); return 0; } @@ -720,6 +722,7 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) { unsigned int i; unsigned long ent; + void __iomem *regs = fbi->io; fbi->palette_ready = 0; @@ -727,14 +730,14 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR) continue; - writel(ent, S3C2410_TFTPAL(i)); + writel(ent, regs + S3C2410_TFTPAL(i)); /* it seems the only way to know exactly * if the palette wrote ok, is to check * to see if the value verifies ok */ - if (readw(S3C2410_TFTPAL(i)) == ent) + if (readw(regs + S3C2410_TFTPAL(i)) == ent) fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR; else fbi->palette_ready = 1; /* retry */ @@ -744,14 +747,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) { struct s3c2410fb_info *fbi = dev_id; - unsigned long lcdirq = readl(S3C2410_LCDINTPND); + void __iomem *regs = fbi->io; + unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); if (lcdirq & S3C2410_LCDINT_FRSYNC) { if (fbi->palette_ready) s3c2410fb_write_palette(fbi); - writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND); - writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND); + writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); + writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); } return IRQ_HANDLED; @@ -764,9 +768,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) struct s3c2410fb_info *info; struct fb_info *fbinfo; struct s3c2410fb_hw *mregs; + struct resource *res; int ret; int irq; int i; + int size; u32 lcdcon1; mach_info = pdev->dev.platform_data; @@ -788,11 +794,32 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) return -ENOMEM; } - info = fbinfo->par; info->fb = fbinfo; info->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "failed to get memory registersn"); + ret = -ENXIO; + goto dealloc_fb; + } + + size = (res->end - res->start)+1; + info->mem = request_mem_region(res->start, size, pdev->name); + if (info->mem == NULL) { + dev_err(&pdev->dev, "failed to get memory region\n"); + ret = -ENOENT; + goto dealloc_fb; + } + + info->io = ioremap(res->start, size); + if (info->io == NULL) { + dev_err(&pdev->dev, "ioremap() of registers failed\n"); + ret = -ENXIO; + goto release_mem; + } + platform_set_drvdata(pdev, fbinfo); dprintk("devinit\n"); @@ -803,8 +830,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) /* Stop the video and unset ENVID if set */ info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; - lcdcon1 = readl(S3C2410_LCDCON1); - writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1); + lcdcon1 = readl(info->io + S3C2410_LCDCON1); + writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); info->mach_info = pdev->dev.platform_data; @@ -855,19 +882,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) for (i = 0; i < 256; i++) info->palette_buffer[i] = PALETTE_BUFF_CLEAR; - if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) { - ret = -EBUSY; - goto dealloc_fb; - } - - - dprintk("got LCD region\n"); - ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); if (ret) { dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); ret = -EBUSY; - goto release_mem; + goto release_regs; } info->clk = clk_get(NULL, "lcd"); @@ -889,6 +908,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) ret = -ENOMEM; goto release_clock; } + dprintk("got video memory\n"); ret = s3c2410fb_init_registers(info); @@ -916,8 +936,11 @@ release_clock: clk_put(info->clk); release_irq: free_irq(irq,info); +release_regs: + iounmap(info->io); release_mem: - release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); + release_resource(info->mem); + kfree(info->mem); dealloc_fb: framebuffer_release(fbinfo); return ret; @@ -935,7 +958,7 @@ static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi) local_irq_save(flags); fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); + writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1); local_irq_restore(flags); } @@ -962,7 +985,10 @@ static int s3c2410fb_remove(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); free_irq(irq,info); - release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); + + release_resource(info->mem); + kfree(info->mem); + iounmap(info->io); unregister_framebuffer(fbinfo); return 0; diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index f3f8a8e..17c7915 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -30,6 +30,9 @@ struct s3c2410fb_info { struct device *dev; struct clk *clk; + struct resource *mem; + void __iomem *io; + struct s3c2410fb_mach_info *mach_info; /* raw memory addresses */ diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 34ef859..963a454 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -190,17 +190,6 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, EXPORT_SYMBOL(sbusfb_ioctl_helper); #ifdef CONFIG_COMPAT -struct fbcmap32 { - int index; /* first element (0 origin) */ - int count; - u32 red; - u32 green; - u32 blue; -}; - -#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) -#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) - static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct fbcmap32 __user *argp = (void __user *)arg; @@ -223,20 +212,6 @@ static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long (unsigned long)p); } -struct fbcursor32 { - short set; /* what to set, choose from the list above */ - short enable; /* cursor on/off */ - struct fbcurpos pos; /* cursor position */ - struct fbcurpos hot; /* cursor hot spot */ - struct fbcmap32 cmap; /* color map info */ - struct fbcurpos size; /* cursor bit map size */ - u32 image; /* cursor image bits */ - u32 mask; /* cursor mask bits */ -}; - -#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) -#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) - static int fbiogscursor(struct fb_info *info, unsigned long arg) { struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 5a99669..e5a9ddb 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -345,88 +345,82 @@ tcx_init_fix(struct fb_info *info, int linebytes) info->fix.accel = FB_ACCEL_SUN_TCX; } -struct all_info { - struct fb_info info; - struct tcx_par par; -}; - -static void tcx_unmap_regs(struct of_device *op, struct all_info *all) +static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, + struct tcx_par *par) { - if (all->par.tec) + if (par->tec) of_iounmap(&op->resource[7], - all->par.tec, sizeof(struct tcx_tec)); - if (all->par.thc) + par->tec, sizeof(struct tcx_tec)); + if (par->thc) of_iounmap(&op->resource[9], - all->par.thc, sizeof(struct tcx_thc)); - if (all->par.bt) + par->thc, sizeof(struct tcx_thc)); + if (par->bt) of_iounmap(&op->resource[8], - all->par.bt, sizeof(struct bt_regs)); - if (all->par.cplane) + par->bt, sizeof(struct bt_regs)); + if (par->cplane) of_iounmap(&op->resource[4], - all->par.cplane, all->par.fbsize * sizeof(u32)); - if (all->info.screen_base) + par->cplane, par->fbsize * sizeof(u32)); + if (info->screen_base) of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); + info->screen_base, par->fbsize); } static int __devinit tcx_init_one(struct of_device *op) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct tcx_par *par; int linebytes, i, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.lowdepth = + spin_lock_init(&par->lock); + + par->lowdepth = (of_find_property(dp, "tcx-8-bit", NULL) != NULL); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.tec = of_ioremap(&op->resource[7], 0, + par->tec = of_ioremap(&op->resource[7], 0, sizeof(struct tcx_tec), "tcx tec"); - all->par.thc = of_ioremap(&op->resource[9], 0, + par->thc = of_ioremap(&op->resource[9], 0, sizeof(struct tcx_thc), "tcx thc"); - all->par.bt = of_ioremap(&op->resource[8], 0, + par->bt = of_ioremap(&op->resource[8], 0, sizeof(struct bt_regs), "tcx dac"); - all->info.screen_base = of_ioremap(&op->resource[0], 0, - all->par.fbsize, "tcx ram"); - if (!all->par.tec || !all->par.thc || - !all->par.bt || !all->info.screen_base) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } - - memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map)); - if (!all->par.lowdepth) { - all->par.cplane = of_ioremap(&op->resource[4], 0, - all->par.fbsize * sizeof(u32), + info->screen_base = of_ioremap(&op->resource[0], 0, + par->fbsize, "tcx ram"); + if (!par->tec || !par->thc || + !par->bt || !info->screen_base) + goto out_unmap_regs; + + memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map)); + if (!par->lowdepth) { + par->cplane = of_ioremap(&op->resource[4], 0, + par->fbsize * sizeof(u32), "tcx cplane"); - if (!all->par.cplane) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (!par->cplane) + goto out_unmap_regs; } else { - all->par.mmap_map[1].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[4].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[5].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[6].size = SBUS_MMAP_EMPTY; + par->mmap_map[1].size = SBUS_MMAP_EMPTY; + par->mmap_map[4].size = SBUS_MMAP_EMPTY; + par->mmap_map[5].size = SBUS_MMAP_EMPTY; + par->mmap_map[6].size = SBUS_MMAP_EMPTY; } - all->par.physbase = 0; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = 0; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; for (i = 0; i < TCX_MMAP_ENTRIES; i++) { int j; @@ -444,53 +438,54 @@ static int __devinit tcx_init_one(struct of_device *op) j = i; break; }; - all->par.mmap_map[i].poff = op->resource[j].start; + par->mmap_map[i].poff = op->resource[j].start; } - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &tcx_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT; + info->fbops = &tcx_ops; /* Initialize brooktree DAC. */ - sbus_writel(0x04 << 24, &all->par.bt->addr); /* color planes */ - sbus_writel(0xff << 24, &all->par.bt->control); - sbus_writel(0x05 << 24, &all->par.bt->addr); - sbus_writel(0x00 << 24, &all->par.bt->control); - sbus_writel(0x06 << 24, &all->par.bt->addr); /* overlay plane */ - sbus_writel(0x73 << 24, &all->par.bt->control); - sbus_writel(0x07 << 24, &all->par.bt->addr); - sbus_writel(0x00 << 24, &all->par.bt->control); - - tcx_reset(&all->info); - - tcx_blank(FB_BLANK_UNBLANK, &all->info); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + sbus_writel(0x04 << 24, &par->bt->addr); /* color planes */ + sbus_writel(0xff << 24, &par->bt->control); + sbus_writel(0x05 << 24, &par->bt->addr); + sbus_writel(0x00 << 24, &par->bt->control); + sbus_writel(0x06 << 24, &par->bt->addr); /* overlay plane */ + sbus_writel(0x73 << 24, &par->bt->control); + sbus_writel(0x07 << 24, &par->bt->addr); + sbus_writel(0x00 << 24, &par->bt->control); + + tcx_reset(info); - fb_set_cmap(&all->info.cmap, &all->info); - tcx_init_fix(&all->info, linebytes); + tcx_blank(FB_BLANK_UNBLANK, info); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - tcx_unmap_regs(op, all); - kfree(all); - return err; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; + + fb_set_cmap(&info->cmap, info); + tcx_init_fix(info, linebytes); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: TCX at %lx:%lx, %s\n", dp->full_name, - all->par.which_io, + par->which_io, op->resource[0].start, - all->par.lowdepth ? "8-bit only" : "24-bit depth"); + par->lowdepth ? "8-bit only" : "24-bit depth"); return 0; + +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + tcx_unmap_regs(op, info, par); + +out_err: + return err; } static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match) @@ -502,14 +497,15 @@ static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id static int __devexit tcx_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct tcx_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - tcx_unmap_regs(op, all); + tcx_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 89facb7..d292a37 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -849,7 +849,7 @@ tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image) u32 *palette = ((u32 *)info->pseudo_palette); unsigned long pos, line_length, i, j; const unsigned char *data; - void *regs_base, *fb_base; + void __iomem *regs_base, *fb_base; dx = image->dx; dy = image->dy; diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c deleted file mode 100644 index e6f7c78..0000000 --- a/drivers/video/tx3912fb.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * drivers/video/tx3912fb.c - * - * Copyright (C) 1999 Harald Koerfgen - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/pm.h> -#include <linux/fb.h> -#include <asm/io.h> -#include <asm/bootinfo.h> -#include <asm/uaccess.h> -#include <asm/tx3912.h> -#include <video/tx3912.h> - -/* - * Frame buffer, palette and console structures - */ -static struct fb_info fb_info; -static u32 cfb8[16]; - -static struct fb_fix_screeninfo tx3912fb_fix __initdata = { - .id = "tx3912fb", - .smem_len = ((240 * 320)/2), - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 1, - .ypanstep = 1, - .ywrapstep = 1, - .accel = FB_ACCEL_NONE, -}; - -static struct fb_var_screeninfo tx3912fb_var = { - .xres = 240, - .yres = 320, - .xres_virtual = 240, - .yres_virtual = 320, - .bits_per_pixel =4, - .red = { 0, 4, 0 }, /* ??? */ - .green = { 0, 4, 0 }, - .blue = { 0, 4, 0 }, - .activate = FB_ACTIVATE_NOW, - .width = -1, - .height = -1, - .pixclock = 20000, - .left_margin = 64, - .right_margin = 64, - .upper_margin = 32, - .lower_margin = 32, - .hsync_len = 64, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, -}; - -/* - * Interface used by the world - */ -int tx3912fb_init(void); - -static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info); - -/* - * Macros - */ -#define get_line_length(xres_virtual, bpp) \ - (u_long) (((int) xres_virtual * (int) bpp + 7) >> 3) - -/* - * Frame buffer operations structure used by console driver - */ -static struct fb_ops tx3912fb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = tx3912fb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - -static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - /* - * Memory limit - */ - line_length = - get_line_length(var->xres_virtual, var->bits_per_pixel); - if ((line_length * var->yres_virtual) > info->fix.smem_len) - return -ENOMEM; - - return 0; -} - -static int tx3912fb_set_par(struct fb_info *info) -{ - u_long tx3912fb_paddr = 0; - - /* Disable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Set start address for DMA transfer */ - outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3); - - /* Set end address for DMA transfer */ - outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4); - - /* Set the pixel depth */ - switch (info->var.bits_per_pixel) { - case 1: - /* Monochrome */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_MONO10; - break; - case 4: - /* 4-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 8: - /* 8-bit color */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 2: - default: - /* 2-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - break; - } - - /* Enable the video clock */ - outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK, - TX3912_CLK_CTRL); - - /* Unfreeze video logic and enable DF toggle */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | - TX3912_VIDEO_CTRL1_DFMODE) - , TX3912_VIDEO_CTRL1); - udelay(200); - - /* Enable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) | - (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - - info->fix.line_length = get_line_length(var->xres_virtual, - var->bits_per_pixel); -} - -/* - * Set a single color register - */ -static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno > 255) - return 1; - - if (regno < 16) - ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xe000) >> 8) - | ((green & 0xe000) >> 11) - | ((blue & 0xc000) >> 14); - return 0; -} - -int __init tx3912fb_setup(char *options); - -/* - * Initialization of the framebuffer - */ -int __init tx3912fb_init(void) -{ - u_long tx3912fb_paddr = 0; - int size = (info->var.bits_per_pixel == 8) ? 256 : 16; - char *option = NULL; - - if (fb_get_options("tx3912fb", &option)) - return -ENODEV; - tx3912fb_setup(option); - - /* Disable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Set start address for DMA transfer */ - outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3); - - /* Set end address for DMA transfer */ - outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4); - - /* Set the pixel depth */ - switch (tx3912fb_var.bits_per_pixel) { - case 1: - /* Monochrome */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_MONO10; - break; - case 4: - /* 4-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR; - tx3912fb_fix.grayscale = 1; - break; - case 8: - /* 8-bit color */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 2: - default: - /* 2-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_PSEUDOCOLOR; - tx3912fb_fix.grayscale = 1; - break; - } - - /* Enable the video clock */ - outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK, - TX3912_CLK_CTRL); - - /* Unfreeze video logic and enable DF toggle */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | TX3912_VIDEO_CTRL1_DFMODE), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Clear the framebuffer */ - memset((void *) tx3912fb_fix.smem_start, 0xff, tx3912fb_fix.smem_len); - udelay(200); - - /* Enable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) | - (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - - /* - * Memory limit - */ - tx3912fb_fix.line_length = - get_line_length(tx3912fb_var.xres_virtual, tx3912fb_var.bits_per_pixel); - if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len) - return -ENOMEM; - - fb_info.fbops = &tx3912fb_ops; - fb_info.var = tx3912fb_var; - fb_info.fix = tx3912fb_fix; - fb_info.pseudo_palette = cfb8; - fb_info.flags = FBINFO_DEFAULT; - - /* Clear the framebuffer */ - memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len); - udelay(200); - - fb_alloc_cmap(&info->cmap, size, 0); - - if (register_framebuffer(&fb_info) < 0) - return -1; - - printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n", - fb_info.node, (u_int) (fb_info.fix.smem_len >> 10)); - return 0; -} - -int __init tx3912fb_setup(char *options) -{ - char *this_opt; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep(&options, ","))) { - if (!strncmp(options, "bpp:", 4)) - tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0); - } - return 0; -} - -module_init(tx3912fb_init); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 1d29a89..6ef9733 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -79,7 +79,7 @@ /* * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures */ -static struct fb_fix_screeninfo xilinx_fb_fix __initdata = { +static struct fb_fix_screeninfo xilinx_fb_fix = { .id = "Xilinx", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, @@ -88,7 +88,7 @@ static struct fb_fix_screeninfo xilinx_fb_fix __initdata = { .accel = FB_ACCEL_NONE }; -static struct fb_var_screeninfo xilinx_fb_var __initdata = { +static struct fb_var_screeninfo xilinx_fb_var = { .xres = XRES, .yres = YRES, .xres_virtual = XRES_VIRTUAL, @@ -212,11 +212,6 @@ xilinxfb_drv_probe(struct device *dev) pdev = to_platform_device(dev); pdata = pdev->dev.platform_data; - if (pdata == NULL) { - printk(KERN_ERR "Couldn't find platform data.\n"); - return -EFAULT; - } - drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { printk(KERN_ERR "Couldn't allocate device private record\n"); @@ -258,11 +253,9 @@ xilinxfb_drv_probe(struct device *dev) xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); /* Turn on the display */ - if (pdata->rotate_screen) { - drvdata->reg_ctrl_default = REG_CTRL_ENABLE | REG_CTRL_ROTATE; - } else { - drvdata->reg_ctrl_default = REG_CTRL_ENABLE; - } + drvdata->reg_ctrl_default = REG_CTRL_ENABLE; + if (pdata && pdata->rotate_screen) + drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); /* Fill struct fb_info */ @@ -281,8 +274,10 @@ xilinxfb_drv_probe(struct device *dev) } drvdata->info.flags = FBINFO_DEFAULT; - xilinx_fb_var.height = pdata->screen_height_mm; - xilinx_fb_var.width = pdata->screen_width_mm; + if (pdata) { + xilinx_fb_var.height = pdata->screen_height_mm; + xilinx_fb_var.width = pdata->screen_width_mm; + } drvdata->info.var = xilinx_fb_var; /* Register new frame buffer */ diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 763bc73..4b69664 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -85,7 +85,7 @@ static struct { }; struct ds1wm_data { - void *map; + void __iomem *map; int bus_shift; /* # of shifts to calc register offsets */ struct platform_device *pdev; struct ds1wm_platform_data *pdata; diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 9e943fb..227d53b 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -782,8 +782,8 @@ static int process_msg(void) msg->u.watch.vec = split(body, msg->hdr.len, &msg->u.watch.vec_size); if (IS_ERR(msg->u.watch.vec)) { - kfree(msg); err = PTR_ERR(msg->u.watch.vec); + kfree(msg); goto out; } |