From 7acb77a6e7bddd4c4c5aa975bbf976927c013798 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 17 Jun 1997 13:20:30 +0000 Subject: Merge with 2.1.43. --- drivers/ap1000/ringbuf.c | 1 - drivers/block/genhd.c | 141 ++++++++++- drivers/block/ide.c | 40 ++- drivers/block/ide.h | 2 +- drivers/block/loop.c | 2 +- drivers/block/md.c | 5 +- drivers/char/Makefile | 3 + drivers/char/atarimouse.c | 2 +- drivers/char/console.c | 10 +- drivers/char/console_struct.h | 141 ----------- drivers/char/consolemap.c | 2 +- drivers/char/consolemap.h | 14 -- drivers/char/diacr.h | 8 - drivers/char/dsp56k.c | 7 +- drivers/char/fbmem.c | 2 +- drivers/char/kbd_kern.h | 141 ----------- drivers/char/keyboard.c | 37 ++- drivers/char/lp_m68k.c | 1 - drivers/char/mem.c | 97 +++---- drivers/char/misc.c | 4 +- drivers/char/pc_keyb.c | 448 +++++++++++++-------------------- drivers/char/pc_keyb.h | 107 ++++++++ drivers/char/rtc.c | 62 ++--- drivers/char/selection.c | 14 +- drivers/char/selection.h | 283 --------------------- drivers/char/softdog.c | 4 + drivers/char/sysrq.c | 248 ++++++++++++++++++ drivers/char/tga.c | 10 +- drivers/char/tty_io.c | 6 +- drivers/char/vc_screen.c | 4 +- drivers/char/vga.c | 10 +- drivers/char/vt.c | 8 +- drivers/char/vt_kern.h | 39 --- drivers/isdn/hisax/callc.c | 8 +- drivers/net/Config.in | 9 +- drivers/net/arcnet.c | 4 +- drivers/net/baycom.c | 12 +- drivers/net/defxx.c | 50 ++-- drivers/net/hdlcdrv.c | 22 +- drivers/net/net_init.c | 2 +- drivers/net/soundmodem/Makefile | 9 +- drivers/net/soundmodem/gentbl.c | 291 ++++++++++++++------- drivers/net/soundmodem/sm.c | 92 ++++++- drivers/net/soundmodem/sm.h | 63 +++-- drivers/net/soundmodem/sm_afsk1200.c | 249 +++++++++--------- drivers/net/soundmodem/sm_afsk2400_7.c | 297 ++++++++++++++++++++++ drivers/net/soundmodem/sm_afsk2400_8.c | 297 ++++++++++++++++++++++ drivers/net/soundmodem/sm_fsk9600.c | 236 +++++++++++++---- drivers/net/soundmodem/sm_hapn4800.c | 443 +++++++++++++++++++++++--------- drivers/net/soundmodem/sm_sbc.c | 326 +++++++++++++----------- drivers/net/soundmodem/sm_wss.c | 399 +++++++++++++++-------------- drivers/net/soundmodem/smdma.h | 210 ++++++++++++++++ drivers/pci/pci.c | 48 +++- drivers/sbus/char/bwtwo.c | 12 +- drivers/sbus/char/cgfourteen.c | 11 +- drivers/sbus/char/cgsix.c | 11 +- drivers/sbus/char/cgthree.c | 11 +- drivers/sbus/char/creator.c | 7 +- drivers/sbus/char/leo.c | 11 +- drivers/sbus/char/suncons.c | 12 +- drivers/sbus/char/sunfb.c | 12 +- drivers/sbus/char/sunkbd.c | 6 +- drivers/sbus/char/tcx.c | 11 +- drivers/sbus/char/vfc_dev.c | 2 +- drivers/sbus/char/weitek.c | 11 +- drivers/scsi/amiga7xx.c | 16 +- drivers/scsi/g_NCR5380.c | 5 +- drivers/scsi/script_asm.pl | 70 ++++-- drivers/sound/dmabuf.c | 2 + drivers/sound/soundcard.c | 2 +- 70 files changed, 3269 insertions(+), 1913 deletions(-) delete mode 100644 drivers/char/console_struct.h delete mode 100644 drivers/char/consolemap.h delete mode 100644 drivers/char/diacr.h delete mode 100644 drivers/char/kbd_kern.h create mode 100644 drivers/char/pc_keyb.h delete mode 100644 drivers/char/selection.h create mode 100644 drivers/char/sysrq.c delete mode 100644 drivers/char/vt_kern.h create mode 100644 drivers/net/soundmodem/sm_afsk2400_7.c create mode 100644 drivers/net/soundmodem/sm_afsk2400_8.c create mode 100644 drivers/net/soundmodem/smdma.h (limited to 'drivers') diff --git a/drivers/ap1000/ringbuf.c b/drivers/ap1000/ringbuf.c index b8bcbb541..ee33a03d4 100644 --- a/drivers/ap1000/ringbuf.c +++ b/drivers/ap1000/ringbuf.c @@ -318,7 +318,6 @@ struct inode_operations proc_ringbuf_inode_operations = { NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ - NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index ad0e79b1b..0217dcb52 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -380,7 +380,7 @@ check_table: && (q->sector & 63) == 1 && (q->end_sector & 63) == 63) { unsigned int heads = q->end_head + 1; - if (heads == 32 || heads == 64 || heads == 128) { + if (heads == 32 || heads == 64 || heads == 128 || heads == 255) { (void) ide_xlate_1024(dev, heads, " [PTBL]"); break; @@ -740,6 +740,141 @@ rdb_done: } #endif /* CONFIG_AMIGA_PARTITION */ +#ifdef CONFIG_ATARI_PARTITION +#include + +/* ++guenther: this should be settable by the user ("make config")?. + */ +#define ICD_PARTS + +static int atari_partition (struct gendisk *hd, kdev_t dev, + unsigned long first_sector) +{ + int minor = current_minor, m_lim = current_minor + hd->max_p; + struct buffer_head *bh; + struct rootsector *rs; + struct partition_info *pi; + ulong extensect; +#ifdef ICD_PARTS + int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ +#endif + + bh = bread (dev, 0, get_ptable_blocksize(dev)); + if (!bh) + { + printk (" unable to read block 0\n"); + return -1; + } + + rs = (struct rootsector *) bh->b_data; + pi = &rs->part[0]; + printk (" AHDI"); + for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++) + { + if (pi->flg & 1) + /* active partition */ + { + if (memcmp (pi->id, "XGM", 3) == 0) + /* extension partition */ + { + struct rootsector *xrs; + struct buffer_head *xbh; + ulong partsect; + +#ifdef ICD_PARTS + part_fmt = 1; +#endif + printk(" XGM<"); + partsect = extensect = pi->st; + while (1) + { + xbh = bread (dev, partsect / 2, 1024); + if (!xbh) + { + printk (" block %ld read failed\n", partsect); + brelse(bh); + return 0; + } + if (partsect & 1) + xrs = (struct rootsector *) &xbh->b_data[512]; + else + xrs = (struct rootsector *) &xbh->b_data[0]; + + /* ++roman: sanity check: bit 0 of flg field must be set */ + if (!(xrs->part[0].flg & 1)) { + printk( "\nFirst sub-partition in extended partition is not valid!\n" ); + break; + } + + add_partition(hd, minor, partsect + xrs->part[0].st, + xrs->part[0].siz); + + if (!(xrs->part[1].flg & 1)) { + /* end of linked partition list */ + brelse( xbh ); + break; + } + if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { + printk( "\nID of extended partition is not XGM!\n" ); + brelse( xbh ); + break; + } + + partsect = xrs->part[1].st + extensect; + brelse (xbh); + minor++; + if (minor >= m_lim) { + printk( "\nMaximum number of partitions reached!\n" ); + break; + } + } + printk(" >"); + } + else + { + /* we don't care about other id's */ + add_partition (hd, minor, pi->st, pi->siz); + } + } + } +#ifdef ICD_PARTS + if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */ + { + pi = &rs->icdpart[0]; + /* sanity check: no ICD format if first partition invalid */ + if (memcmp (pi->id, "GEM", 3) == 0 || + memcmp (pi->id, "BGM", 3) == 0 || + memcmp (pi->id, "LNX", 3) == 0 || + memcmp (pi->id, "SWP", 3) == 0 || + memcmp (pi->id, "RAW", 3) == 0 ) + { + printk(" ICD<"); + for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++) + { + /* accept only GEM,BGM,RAW,LNX,SWP partitions */ + if (pi->flg & 1 && + (memcmp (pi->id, "GEM", 3) == 0 || + memcmp (pi->id, "BGM", 3) == 0 || + memcmp (pi->id, "LNX", 3) == 0 || + memcmp (pi->id, "SWP", 3) == 0 || + memcmp (pi->id, "RAW", 3) == 0) ) + { + part_fmt = 2; + add_partition (hd, minor, pi->st, pi->siz); + } + } + printk(" >"); + } + } +#endif + brelse (bh); + + printk ("\n"); + + return 1; +} +#endif /* CONFIG_ATARI_PARTITION */ + static void check_partition(struct gendisk *hd, kdev_t dev) { static int first_time = 1; @@ -777,6 +912,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev) if(amiga_partition(hd, dev, first_sector)) return; #endif +#ifdef CONFIG_ATARI_PARTITION + if(atari_partition(hd, dev, first_sector)) + return; +#endif #ifdef CONFIG_SGI_PARTITION if(sgi_partition(hd, dev, first_sector)) return; diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 89759dd32..1b293c539 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 6.02 Mar 11, 1997 + * linux/drivers/block/ide.c Version 6.03 June 4, 1997 * * Copyright (C) 1994-1997 Linus Torvalds & authors (see below) */ @@ -280,6 +280,7 @@ * support HDIO_GETGEO for floppies * Version 6.02 fix ide_ack_intr() call * check partition table on floppies + * Version 6.03 handle bad status bit sequencing in ide_wait_stat() * * Some additional driver compile-time options are in ide.h * @@ -1044,27 +1045,24 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou byte stat; unsigned long flags; -test: - udelay(1); /* spec allows drive 400ns to change "BUSY" */ - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; /* fast exit for most frequent case */ - if (!(stat & BUSY_STAT)) { - ide_error(drive, "status error", stat); - return 1; - } - - save_flags(flags); - ide_sti(); - timeout += jiffies; - do { - if (!((stat = GET_STAT()) & BUSY_STAT)) { - restore_flags(flags); - goto test; + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ + if ((stat = GET_STAT()) & BUSY_STAT) { + save_flags(flags); + ide_sti(); + timeout += jiffies; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (jiffies > timeout) { + restore_flags(flags); + ide_error(drive, "status timeout", stat); + return 1; + } } - } while (jiffies <= timeout); - - restore_flags(flags); - ide_error(drive, "status timeout", GET_STAT()); + restore_flags(flags); + } + udelay(1); /* allow status to settle, then read it again */ + if (OK_STAT((stat = GET_STAT()), good, bad)) + return 0; + ide_error(drive, "status error", stat); return 1; } diff --git a/drivers/block/ide.h b/drivers/block/ide.h index 241a571ca..95724e6e9 100644 --- a/drivers/block/ide.h +++ b/drivers/block/ide.h @@ -134,7 +134,7 @@ typedef unsigned char byte; /* used everywhere */ #define BAD_W_STAT (BAD_R_STAT | WRERR_STAT) #define BAD_STAT (BAD_R_STAT | DRQ_STAT) #define DRIVE_READY (READY_STAT | SEEK_STAT) -#define DATA_READY (DRIVE_READY | DRQ_STAT) +#define DATA_READY (DRQ_STAT) /* * Some more useful definitions diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 212efece2..53fef9b74 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -318,7 +318,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) } lo->lo_inode = inode; - lo->lo_inode->i_count++; + atomic_inc(&lo->lo_inode->i_count); lo->transfer = NULL; figure_loop_size(lo); MOD_INC_USE_COUNT; diff --git a/drivers/block/md.c b/drivers/block/md.c index 078e1e1ee..12cb6dcf0 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -202,9 +202,10 @@ static int do_md_stop (int minor, struct inode *inode) { int i; - if (inode->i_count>1 || md_dev[minor].busy>1) /* ioctl : one open channel */ + if (atomic_read(&inode->i_count)>1 || md_dev[minor].busy>1) /* ioctl : one open channel */ { - printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, inode->i_count, md_dev[minor].busy); + printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, + atomic_read(&inode->i_count), md_dev[minor].busy); return -EBUSY; } diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d5a19d343..900cb935f 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -46,6 +46,9 @@ endif ifneq ($(ARCH),m68k) L_OBJS += pc_keyb.o defkeymap.o endif +ifdef CONFIG_MAGIC_SYSRQ +L_OBJS += sysrq.o +endif endif ifeq ($(CONFIG_ATARI_DSP56K),y) diff --git a/drivers/char/atarimouse.c b/drivers/char/atarimouse.c index 18debb66b..950cb1546 100644 --- a/drivers/char/atarimouse.c +++ b/drivers/char/atarimouse.c @@ -176,7 +176,7 @@ __initfunc(int atari_mouse_init(void)) #define MIN_THRESHOLD 1 #define MAX_THRESHOLD 20 /* more seems not reasonable... */ -void atari_mouse_setup( char *str, int *ints ) +__initfunc(void atari_mouse_setup( char *str, int *ints )) { if (ints[0] < 1) { printk( "atari_mouse_setup: no arguments!\n" ); diff --git a/drivers/char/console.c b/drivers/char/console.c index 56748c068..61ab64aac 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -125,11 +125,11 @@ unsigned long video_port_base; #include #include -#include "kbd_kern.h" -#include "vt_kern.h" -#include "consolemap.h" -#include "selection.h" -#include "console_struct.h" +#include +#include +#include +#include +#include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) diff --git a/drivers/char/console_struct.h b/drivers/char/console_struct.h deleted file mode 100644 index a73836ad4..000000000 --- a/drivers/char/console_struct.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * console_struct.h - * - * Data structure and defines shared between console.c, vga.c and tga.c - */ - -#define NPAR 16 - -struct vc_data { - unsigned long vc_screenbuf_size; - unsigned short vc_video_erase_char; /* Background erase character */ - unsigned char vc_attr; /* Current attributes */ - unsigned char vc_def_color; /* Default colors */ - unsigned char vc_color; /* Foreground & background */ - unsigned char vc_s_color; /* Saved foreground & background */ - unsigned char vc_ulcolor; /* Colour for underline mode */ - unsigned char vc_halfcolor; /* Colour for half intensity mode */ - unsigned long vc_origin; /* Used for EGA/VGA fast scroll */ - unsigned long vc_scr_end; /* Used for EGA/VGA fast scroll */ - unsigned long vc_pos; - unsigned long vc_x,vc_y; - unsigned long vc_top,vc_bottom; - unsigned long vc_state; - unsigned long vc_npar,vc_par[NPAR]; - unsigned long vc_video_mem_start; /* Start of video RAM */ - unsigned long vc_video_mem_end; /* End of video RAM (sort of) */ - unsigned long vc_saved_x; - unsigned long vc_saved_y; - /* mode flags */ - unsigned long vc_charset : 1; /* Character set G0 / G1 */ - unsigned long vc_s_charset : 1; /* Saved character set */ - unsigned long vc_disp_ctrl : 1; /* Display chars < 32? */ - unsigned long vc_toggle_meta : 1; /* Toggle high bit? */ - unsigned long vc_decscnm : 1; /* Screen Mode */ - unsigned long vc_decom : 1; /* Origin Mode */ - unsigned long vc_decawm : 1; /* Autowrap Mode */ - unsigned long vc_deccm : 1; /* Cursor Visible */ - unsigned long vc_decim : 1; /* Insert Mode */ - unsigned long vc_deccolm : 1; /* 80/132 Column Mode */ - /* attribute flags */ - unsigned long vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */ - unsigned long vc_underline : 1; - unsigned long vc_blink : 1; - unsigned long vc_reverse : 1; - unsigned long vc_s_intensity : 2; /* saved rendition */ - unsigned long vc_s_underline : 1; - unsigned long vc_s_blink : 1; - unsigned long vc_s_reverse : 1; - /* misc */ - unsigned long vc_ques : 1; - unsigned long vc_need_wrap : 1; - unsigned long vc_has_scrolled : 1; /* Info for unblank_screen */ - unsigned long vc_kmalloced : 1; /* kfree_s() needed */ - unsigned long vc_report_mouse : 2; - unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ - unsigned char vc_utf_count; - long vc_utf_char; - unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */ - unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ - unsigned short * vc_translate; - unsigned char vc_G0_charset; - unsigned char vc_G1_charset; - unsigned char vc_saved_G0; - unsigned char vc_saved_G1; - unsigned int vc_bell_pitch; /* Console bell pitch */ - unsigned int vc_bell_duration; /* Console bell duration */ - /* additional information is in vt_kern.h */ -}; - -struct vc { - struct vc_data *d; - - /* might add scrmem, vt_struct, kbd at some time, - to have everything in one place - the disadvantage - would be that vc_cons etc can no longer be static */ -}; - -extern struct vc vc_cons [MAX_NR_CONSOLES]; - -#define screenbuf_size (vc_cons[currcons].d->vc_screenbuf_size) -#define origin (vc_cons[currcons].d->vc_origin) -#define scr_end (vc_cons[currcons].d->vc_scr_end) -#define pos (vc_cons[currcons].d->vc_pos) -#define top (vc_cons[currcons].d->vc_top) -#define bottom (vc_cons[currcons].d->vc_bottom) -#define x (vc_cons[currcons].d->vc_x) -#define y (vc_cons[currcons].d->vc_y) -#define vc_state (vc_cons[currcons].d->vc_state) -#define npar (vc_cons[currcons].d->vc_npar) -#define par (vc_cons[currcons].d->vc_par) -#define ques (vc_cons[currcons].d->vc_ques) -#define attr (vc_cons[currcons].d->vc_attr) -#define saved_x (vc_cons[currcons].d->vc_saved_x) -#define saved_y (vc_cons[currcons].d->vc_saved_y) -#define translate (vc_cons[currcons].d->vc_translate) -#define G0_charset (vc_cons[currcons].d->vc_G0_charset) -#define G1_charset (vc_cons[currcons].d->vc_G1_charset) -#define saved_G0 (vc_cons[currcons].d->vc_saved_G0) -#define saved_G1 (vc_cons[currcons].d->vc_saved_G1) -#define utf (vc_cons[currcons].d->vc_utf) -#define utf_count (vc_cons[currcons].d->vc_utf_count) -#define utf_char (vc_cons[currcons].d->vc_utf_char) -#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start) -#define video_mem_end (vc_cons[currcons].d->vc_video_mem_end) -#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char) -#define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl) -#define toggle_meta (vc_cons[currcons].d->vc_toggle_meta) -#define decscnm (vc_cons[currcons].d->vc_decscnm) -#define decom (vc_cons[currcons].d->vc_decom) -#define decawm (vc_cons[currcons].d->vc_decawm) -#define deccm (vc_cons[currcons].d->vc_deccm) -#define decim (vc_cons[currcons].d->vc_decim) -#define deccolm (vc_cons[currcons].d->vc_deccolm) -#define need_wrap (vc_cons[currcons].d->vc_need_wrap) -#define has_scrolled (vc_cons[currcons].d->vc_has_scrolled) -#define kmalloced (vc_cons[currcons].d->vc_kmalloced) -#define report_mouse (vc_cons[currcons].d->vc_report_mouse) -#define color (vc_cons[currcons].d->vc_color) -#define s_color (vc_cons[currcons].d->vc_s_color) -#define def_color (vc_cons[currcons].d->vc_def_color) -#define foreground (color & 0x0f) -#define background (color & 0xf0) -#define charset (vc_cons[currcons].d->vc_charset) -#define s_charset (vc_cons[currcons].d->vc_s_charset) -#define intensity (vc_cons[currcons].d->vc_intensity) -#define underline (vc_cons[currcons].d->vc_underline) -#define blink (vc_cons[currcons].d->vc_blink) -#define reverse (vc_cons[currcons].d->vc_reverse) -#define s_intensity (vc_cons[currcons].d->vc_s_intensity) -#define s_underline (vc_cons[currcons].d->vc_s_underline) -#define s_blink (vc_cons[currcons].d->vc_s_blink) -#define s_reverse (vc_cons[currcons].d->vc_s_reverse) -#define ulcolor (vc_cons[currcons].d->vc_ulcolor) -#define halfcolor (vc_cons[currcons].d->vc_halfcolor) -#define tab_stop (vc_cons[currcons].d->vc_tab_stop) -#define palette (vc_cons[currcons].d->vc_palette) -#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch) -#define bell_duration (vc_cons[currcons].d->vc_bell_duration) - -#define vcmode (vt_cons[currcons]->vc_mode) -#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct)) diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index 878ac0d72..5b0e61fea 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -13,7 +13,7 @@ #include #include #include -#include "consolemap.h" +#include static unsigned short translations[][256] = { /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */ diff --git a/drivers/char/consolemap.h b/drivers/char/consolemap.h deleted file mode 100644 index 9aba19db3..000000000 --- a/drivers/char/consolemap.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * consolemap.h - * - * Interface between console.c, selection.c and consolemap.c - */ -#define LAT1_MAP 0 -#define GRAF_MAP 1 -#define IBMPC_MAP 2 -#define USER_MAP 3 - -extern int hashtable_contents_valid; -extern unsigned char inverse_translate(int glyph); -extern unsigned short *set_translate(int m); -extern int conv_uni_to_pc(long ucs); diff --git a/drivers/char/diacr.h b/drivers/char/diacr.h deleted file mode 100644 index 1c1a3ff05..000000000 --- a/drivers/char/diacr.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _DIACR_H -#define _DIACR_H -#include - -extern struct kbdiacr accent_table[]; -extern unsigned int accent_table_size; - -#endif /* _DIACR_H */ diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index ef97f7255..5928869e9 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -488,7 +488,7 @@ static int dsp56k_open(struct inode *inode, struct file *file) return 0; } -static void dsp56k_release(struct inode *inode, struct file *file) +static int dsp56k_release(struct inode *inode, struct file *file) { int dev = MINOR(inode->i_rdev) & 0x0f; @@ -501,12 +501,13 @@ static void dsp56k_release(struct inode *inode, struct file *file) break; default: printk("DSP56k driver: Unknown minor device: %d\n", dev); - return; + return -ENXIO; } #ifdef MODULE MOD_DEC_USE_COUNT; -#endif /* MODULE */ +#endif + return 0; } static struct file_operations dsp56k_fops = { diff --git a/drivers/char/fbmem.c b/drivers/char/fbmem.c index b267f84d3..7db3b5dba 100644 --- a/drivers/char/fbmem.c +++ b/drivers/char/fbmem.c @@ -222,7 +222,7 @@ fb_mmap(struct inode *inode, struct file *file, struct vm_area_struct * vma) vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/char/kbd_kern.h b/drivers/char/kbd_kern.h deleted file mode 100644 index 2d7dc1b7e..000000000 --- a/drivers/char/kbd_kern.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef _KBD_KERN_H -#define _KBD_KERN_H - -#include -#include - -extern int shift_state; - -extern char *func_table[MAX_NR_FUNC]; -extern char func_buf[]; -extern char *funcbufptr; -extern int funcbufsize, funcbufleft; - -/* - * kbd->xxx contains the VC-local things (flag settings etc..) - * - * Note: externally visible are LED_SCR, LED_NUM, LED_CAP defined in kd.h - * The code in KDGETLED / KDSETLED depends on the internal and - * external order being the same. - * - * Note: lockstate is used as index in the array key_map. - */ -struct kbd_struct { - - unsigned char lockstate; -/* 8 modifiers - the names do not have any meaning at all; - they can be associated to arbitrarily chosen keys */ -#define VC_SHIFTLOCK KG_SHIFT /* shift lock mode */ -#define VC_ALTGRLOCK KG_ALTGR /* altgr lock mode */ -#define VC_CTRLLOCK KG_CTRL /* control lock mode */ -#define VC_ALTLOCK KG_ALT /* alt lock mode */ -#define VC_SHIFTLLOCK KG_SHIFTL /* shiftl lock mode */ -#define VC_SHIFTRLOCK KG_SHIFTR /* shiftr lock mode */ -#define VC_CTRLLLOCK KG_CTRLL /* ctrll lock mode */ -#define VC_CTRLRLOCK KG_CTRLR /* ctrlr lock mode */ - unsigned char slockstate; /* for `sticky' Shift, Ctrl, etc. */ - - unsigned char ledmode:2; /* one 2-bit value */ -#define LED_SHOW_FLAGS 0 /* traditional state */ -#define LED_SHOW_IOCTL 1 /* only change leds upon ioctl */ -#define LED_SHOW_MEM 2 /* `heartbeat': peek into memory */ - - unsigned char ledflagstate:3; /* flags, not lights */ - unsigned char default_ledflagstate:3; -#define VC_SCROLLOCK 0 /* scroll-lock mode */ -#define VC_NUMLOCK 1 /* numeric lock mode */ -#define VC_CAPSLOCK 2 /* capslock mode */ - - unsigned char kbdmode:2; /* one 2-bit value */ -#define VC_XLATE 0 /* translate keycodes using keymap */ -#define VC_MEDIUMRAW 1 /* medium raw (keycode) mode */ -#define VC_RAW 2 /* raw (scancode) mode */ -#define VC_UNICODE 3 /* Unicode mode */ - - unsigned char modeflags:5; -#define VC_APPLIC 0 /* application key mode */ -#define VC_CKMODE 1 /* cursor key mode */ -#define VC_REPEAT 2 /* keyboard repeat */ -#define VC_CRLF 3 /* 0 - enter sends CR, 1 - enter sends CRLF */ -#define VC_META 4 /* 0 - meta, 1 - meta=prefix with ESC */ -}; - -extern struct kbd_struct kbd_table[]; - -extern int kbd_init(void); - -extern unsigned char getledstate(void); -extern void setledstate(struct kbd_struct *kbd, unsigned int led); - -extern int do_poke_blanked_console; - -extern inline void show_console(void) -{ - do_poke_blanked_console = 1; - mark_bh(CONSOLE_BH); -} - -extern inline void set_console(int nr) -{ - want_console = nr; - mark_bh(CONSOLE_BH); -} - -extern inline void set_leds(void) -{ - mark_bh(KEYBOARD_BH); -} - -extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag) -{ - return ((kbd->modeflags >> flag) & 1); -} - -extern inline int vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - return ((kbd->ledflagstate >> flag) & 1); -} - -extern inline void set_vc_kbd_mode(struct kbd_struct * kbd, int flag) -{ - kbd->modeflags |= 1 << flag; -} - -extern inline void set_vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - kbd->ledflagstate |= 1 << flag; -} - -extern inline void clr_vc_kbd_mode(struct kbd_struct * kbd, int flag) -{ - kbd->modeflags &= ~(1 << flag); -} - -extern inline void clr_vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - kbd->ledflagstate &= ~(1 << flag); -} - -extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag) -{ - kbd->lockstate ^= 1 << flag; -} - -extern inline void chg_vc_kbd_slock(struct kbd_struct * kbd, int flag) -{ - kbd->slockstate ^= 1 << flag; -} - -extern inline void chg_vc_kbd_mode(struct kbd_struct * kbd, int flag) -{ - kbd->modeflags ^= 1 << flag; -} - -extern inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) -{ - kbd->ledflagstate ^= 1 << flag; -} - -#define U(x) ((x) ^ 0xf000) - -#endif diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 0185c2bda..66523964a 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -17,8 +17,11 @@ * Modified to provide 'generic' keyboard support by Hamish Macdonald * Merge with the m68k keyboard driver and split-off of the PC low-level * parts by Geert Uytterhoeven, May 1997 + * + * 27-05-97: Added support for the Magic SysRq Key (Martin Mares) */ +#include #include #include #include @@ -30,9 +33,10 @@ #include #include -#include "kbd_kern.h" -#include "diacr.h" -#include "vt_kern.h" +#include +#include +#include +#include #define SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -82,7 +86,7 @@ static int dead_key_next = 0; * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. */ -/*static*/ int shift_state = 0; +int shift_state = 0; static int npadch = -1; /* -1 or number assembled on pad */ static unsigned char diacr = 0; static char rep = 0; /* flag telling character repeat */ @@ -140,8 +144,14 @@ const int NR_TYPES = SIZE(max_vals); static void put_queue(int); static unsigned char handle_diacr(unsigned char); -/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ -struct pt_regs * pt_regs; +/* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ +struct pt_regs * kbd_pt_regs; + +#ifdef CONFIG_MAGIC_SYSRQ +#define SYSRQ_KEY 0x54 +extern void handle_sysrq(int, struct pt_regs *, struct kbd_struct *, struct tty_struct *); +static int sysrq_pressed; +#endif /* * Many other routines do put_queue, but I think either @@ -223,6 +233,17 @@ void handle_scancode(unsigned char scancode) } else rep = test_and_set_bit(keycode, key_down); +#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ + if (keycode == SYSRQ_KEY) { + sysrq_pressed = !up_flag; + return; + } else if (sysrq_pressed) { + if (!up_flag) + handle_sysrq(keycode, kbd_pt_regs, kbd, tty); + return; + } +#endif + if (kbd->kbdmode == VC_MEDIUMRAW) { /* soon keycodes will require more than one byte */ put_queue(keycode + up_flag); @@ -346,8 +367,8 @@ static void caps_on(void) static void show_ptregs(void) { - if (pt_regs) - show_regs(pt_regs); + if (kbd_pt_regs) + show_regs(kbd_pt_regs); } static void hold(void) diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c index 17405c191..117dc3fe7 100644 --- a/drivers/char/lp_m68k.c +++ b/drivers/char/lp_m68k.c @@ -462,7 +462,6 @@ static struct file_operations lp_fops = { EXPORT_SYMBOL(lp_table); EXPORT_SYMBOL(lp_irq); EXPORT_SYMBOL(lp_interrupt); -EXPORT_SYMBOL(lp_init); EXPORT_SYMBOL(register_parallel); EXPORT_SYMBOL(unregister_parallel); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 56d537fb3..499132bf8 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -35,6 +35,33 @@ void isdn_init(void); void pcwatchdog_init(void); #endif +static long do_write_mem(struct file * file, + void *p, unsigned long realp, + const char * buf, unsigned long count) +{ + unsigned long written; + + written = 0; +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ + if (realp < PAGE_SIZE) { + unsigned long sz = PAGE_SIZE-realp; + if (sz > count) sz = count; + /* Hmm. Do something? */ + buf+=sz; + p+=sz; + count-=sz; + written+=sz; + } +#endif + if (copy_from_user(p, buf, count) < 0) + return -EFAULT; + written += count; + file->f_pos += written; + return count; +} + + /* * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. @@ -45,7 +72,7 @@ static long read_mem(struct inode * inode, struct file * file, unsigned long p = file->f_pos; unsigned long end_mem; unsigned long read; - + end_mem = __pa(high_memory); if (p >= end_mem) return 0; @@ -54,15 +81,22 @@ static long read_mem(struct inode * inode, struct file * file, read = 0; #if defined(__sparc__) || defined(__mc68000__) /* we don't have page 0 mapped on sparc and m68k.. */ - while (p < PAGE_SIZE && count > 0) { - put_user(0,buf); - buf++; - p++; - count--; - read++; + if (p < PAGE_SIZE) { + unsigned long sz = PAGE_SIZE-p; + if (sz > count) + sz = count; + if (sz > 0) { + if (clear_user(buf, sz)) + return -EFAULT; + buf += sz; + p += sz; + count -= sz; + read += sz; + } } #endif - copy_to_user(buf, __va(p), count); + if (copy_to_user(buf, __va(p), count) < 0) + return -EFAULT; read += count; file->f_pos += read; return read; @@ -73,35 +107,19 @@ static long write_mem(struct inode * inode, struct file * file, { unsigned long p = file->f_pos; unsigned long end_mem; - unsigned long written; end_mem = __pa(high_memory); if (p >= end_mem) return 0; if (count > end_mem - p) count = end_mem - p; - written = 0; -#if defined(__sparc__) || defined(__mc68000__) - /* we don't have page 0 mapped on sparc and m68k.. */ - while (p < PAGE_SIZE && count > 0) { - /* Hmm. Do something? */ - buf++; - p++; - count--; - written++; - } -#endif - copy_from_user(__va(p), buf, count); - written += count; - file->f_pos += written; - return count; + return do_write_mem(file,__va(p),p,buf,count); } static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_struct * vma) { unsigned long offset = vma->vm_offset; - if (offset & ~PAGE_MASK) return -ENXIO; #if defined(__i386__) @@ -117,7 +135,7 @@ static int mmap_mem(struct inode * inode, struct file * file, struct vm_area_str if (remap_page_range(vma->vm_start, offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } @@ -166,27 +184,12 @@ static long write_kmem(struct inode * inode, struct file * file, const char * buf, unsigned long count) { unsigned long p = file->f_pos; - unsigned long written; if (p >= (unsigned long) high_memory) return 0; if (count > (unsigned long) high_memory - p) count = (unsigned long) high_memory - p; - written = 0; -#if defined(__sparc__) || defined(__mc68000__) - /* we don't have page 0 mapped on sparc and m68k.. */ - while (p < PAGE_SIZE && count > 0) { - /* Hmm. Do something? */ - buf++; - p++; - count--; - written++; - } -#endif - copy_from_user((char *) p, buf, count); - written += count; - file->f_pos += written; - return count; + return do_write_mem(file,(void*)p,p,buf,count); } static long read_port(struct inode * inode, struct file * file, @@ -195,8 +198,11 @@ static long read_port(struct inode * inode, struct file * file, unsigned int i = file->f_pos; char * tmp = buf; + if (verify_area(VERIFY_WRITE,buf,count)) + return -EFAULT; while (count-- > 0 && i < 65536) { - put_user(inb(i),tmp); + if (__put_user(inb(i),tmp) < 0) + return -EFAULT; i++; tmp++; } @@ -210,9 +216,12 @@ static long write_port(struct inode * inode, struct file * file, unsigned int i = file->f_pos; const char * tmp = buf; + if (verify_area(VERIFY_READ,buf,count)) + return -EFAULT; while (count-- > 0 && i < 65536) { char c; - get_user(c, tmp); + if (__get_user(c, tmp)) + return -EFAULT; outb(c,i); i++; tmp++; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index d632e4788..ed06f6314 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -44,8 +44,8 @@ #include #endif -#include /* needed by selection.h */ -#include "selection.h" /* export its symbols */ +#include +#include #ifdef CONFIG_KERNELD #include #endif diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c index 2d075636f..9e3267aaf 100644 --- a/drivers/char/pc_keyb.c +++ b/drivers/char/pc_keyb.c @@ -1,20 +1,10 @@ /* * linux/drivers/char/pc_keyb.c * - * Written for linux by Johan Myreen as a translation from - * the assembly version by Linus (with diacriticals added) - * - * Some additional features added by Christoph Niemann (ChN), March 1993 - * - * Loadable keymaps by Risto Kankkunen, May 1993 - * - * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 - * Added decr/incr_console, dynamic keymaps, Unicode support, - * dynamic function/string keys, led setting, Sept 1994 - * `Sticky' modifier keys, 951006. - * 11-11-96: SAK should now work in the raw mode (Martin Mares) - * * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 + * See keyboard.c for the whole history. + * + * Major cleanup by Martin Mares, May 1997 */ #include @@ -24,89 +14,181 @@ #include #include #include +#include -#include +/* Some configuration switches are present in the include file... */ -/* - * Define these here, include/asm-mips/keyboard.h depends on them. - * - * keyboard controller registers - */ -#define KBD_STATUS_REG (unsigned int) 0x64 -#define KBD_CNTL_REG (unsigned int) 0x64 -#define KBD_DATA_REG (unsigned int) 0x60 -/* - * controller commands - */ -#define KBD_READ_MODE (unsigned int) 0x20 -#define KBD_WRITE_MODE (unsigned int) 0x60 -#define KBD_SELF_TEST (unsigned int) 0xAA -#define KBD_SELF_TEST2 (unsigned int) 0xAB -#define KBD_CNTL_ENABLE (unsigned int) 0xAE -/* - * keyboard commands - */ -#define KBD_ENABLE (unsigned int) 0xF4 -#define KBD_DISABLE (unsigned int) 0xF5 -#define KBD_RESET (unsigned int) 0xFF -/* - * keyboard replies - */ -#define KBD_ACK (unsigned int) 0xFA -#define KBD_POR (unsigned int) 0xAA -/* - * status register bits - */ -#define KBD_OBF (unsigned int) 0x01 -#define KBD_IBF (unsigned int) 0x02 -#define KBD_GTO (unsigned int) 0x40 -#define KBD_PERR (unsigned int) 0x80 -/* - * keyboard controller mode register bits - */ -#define KBD_EKI (unsigned int) 0x01 -#define KBD_SYS (unsigned int) 0x04 -#define KBD_DMS (unsigned int) 0x20 -#define KBD_KCC (unsigned int) 0x40 +#include "pc_keyb.h" #include +#include +#include +#include /* - * On non-x86 hardware we do a full keyboard controller - * initialization, in case the bootup software hasn't done - * it. On a x86, the BIOS will already have initialized the - * keyboard. + * In case we run on a non-x86 hardware we need to initialize both the keyboard + * controller and the keyboard. On a x86, the BIOS will already have initialized + * them. */ + #ifdef INIT_KBD -int initialize_kbd(void); -#endif -#include -#include +__initfunc(static int kbd_wait_for_input(void)) +{ + int n; + int status, data; + + n = KBD_TIMEOUT; + do { + status = kbd_inb(KBD_STATUS_REG); + /* + * Wait for input data to become available. This bit will + * then be cleared by the following read of the DATA + * register. + */ + + if (!(status & KBD_STAT_OBF)) + continue; + + data = kbd_inb(KBD_DATA_REG); + + /* + * Check to see if a timeout error has occurred. This means + * that transmission was started but did not complete in the + * normal time cycle. PERR is set when a parity error occurred + * in the last transmission. + */ + if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) { + continue; + } + return (data & 0xff); + } while (--n); + return -1; /* timed-out if fell through to here... */ +} + +__initfunc(static void kbd_write(int address, int data)) +{ + int status; + + do { + status = kbd_inb(KBD_STATUS_REG); + } while (status & KBD_STAT_IBF); + kbd_outb(data, address); +} + +__initfunc(static char *initialize_kbd2(void)) +{ + /* Flush any pending input. */ + + while (kbd_wait_for_input() != -1) + ; + + /* + * Test the keyboard interface. + * This seems to be the only way to get it going. + * If the test is successful a x55 is placed in the input buffer. + */ + + kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST); + if (kbd_wait_for_input() != 0x55) + return "Keyboard failed self test"; + + /* + * Perform a keyboard interface test. This causes the controller + * to test the keyboard clock and data lines. The results of the + * test are placed in the input buffer. + */ + + kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST); + if (kbd_wait_for_input() != 0x00) + return "Keyboard interface failed self test"; + + /* Enable the keyboard by allowing the keyboard clock to run. */ + + kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE); + + /* + * Reset keyboard. If the read times out + * then the assumption is that no keyboard is + * plugged into the machine. + * This defaults the keyboard to scan-code set 2. + */ + + kbd_write(KBD_DATA_REG, KBD_CMD_RESET); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Keyboard reset failed, no ACK"; + if (kbd_wait_for_input() != KBD_REPLY_POR) + return "Keyboard reset failed, no POR"; + + /* + * Set keyboard controller mode. During this, the keyboard should be + * in the disabled state. + */ + + kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Disable keyboard: no ACK"; + + kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE); + kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT + | KBD_MODE_SYS + | KBD_MODE_DISABLE_MOUSE + | KBD_MODE_KCC); + + kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Enable keyboard: no ACK"; + + /* + * Finally, set the typematic rate to maximum. + */ + + kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Set rate: no ACK"; + kbd_write(KBD_DATA_REG, 0x00); + if (kbd_wait_for_input() != KBD_REPLY_ACK) + return "Set rate: no ACK"; + + return NULL; +} + +__initfunc(void initialize_kbd(void)) +{ + unsigned long flags; + char *msg; + + save_flags(flags); cli(); + msg = initialize_kbd2(); + restore_flags(flags); + + if (msg) + printk(KERN_WARNING "initialize_kbd: %s\n", msg); +} -unsigned char kbd_read_mask = 0x01; /* modified by psaux.c */ +#endif /* INIT_KBD */ + +unsigned char kbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */ /* used only by send_data - set by keyboard_interrupt */ static volatile unsigned char reply_expected = 0; static volatile unsigned char acknowledge = 0; static volatile unsigned char resend = 0; -/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ +/* + * Wait for keyboard controller input buffer is empty. + */ + static inline void kb_wait(void) { int i; - for (i=0; i<0x100000; i++) - if ((kbd_inb_p(0x64) & 0x02) == 0) + for (i=0; i + */ + +/* + * Configuration Switches + */ + +#define KBD_REPORT_ERR /* Report keyboard errors */ +#define KBD_REPORT_UNKN /* Report unknown scan codes */ +#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged FOCUS-9000 keyboard */ +#define KBD_TIMEOUT 0x100000 /* Timeout for sending of commands */ + +/* + * Internal variables of the driver + */ + +extern unsigned char kbd_read_mask; +extern unsigned char aux_device_present; + +/* + * Keyboard Controller Registers + */ + +#define KBD_STATUS_REG 0x64 /* Status register (R) */ +#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ +#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ + +/* + * Keyboard Controller Commands + */ + +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ + +/* + * Keyboard Commands + */ + +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ + +/* + * Keyboard Replies + */ + +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ + +/* + * Status Register Bits + */ + +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ +#define KBD_STAT_PERR 0x80 /* Parity error */ + +#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) + +/* + * Controller Mode Register Bits + */ + +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generage IRQ1 */ +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ +#define KBD_MODE_RFU 0x80 + +/* + * Mouse Commands + */ + +#define AUX_SET_RES 0xE8 /* Set resolution */ +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ +#define AUX_SET_STREAM 0xEA /* Set stream mode */ +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ +#define AUX_RESET 0xFF /* Reset aux device */ diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 3235ebeaa..a8614999d 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -43,6 +43,7 @@ * this driver.) */ +#include #include #include #include @@ -156,10 +157,6 @@ static long rtc_read(struct inode *inode, struct file *file, char *buf, if (count < sizeof(unsigned long)) return -EINVAL; - retval = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long)); - if (retval) - return retval; - add_wait_queue(&rtc_wait, &wait); current->state = TASK_INTERRUPTIBLE; @@ -183,8 +180,7 @@ static long rtc_read(struct inode *inode, struct file *file, char *buf, data = rtc_irq_data; rtc_irq_data = 0; restore_flags(flags); - copy_to_user(buf, &data, sizeof(unsigned long)); - retval = sizeof(unsigned long); + retval = put_user(data, (unsigned long *)buf)) ?: sizeof(unsigned long); } current->state = TASK_RUNNING; @@ -198,6 +194,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { unsigned long flags; + struct rtc_time wtime; switch (cmd) { case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ @@ -254,18 +251,9 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * means "don't care" or "match all". Only the tm_hour, * tm_min, and tm_sec values are filled in. */ - int retval; - struct rtc_time alm_tm; - - retval = verify_area(VERIFY_WRITE, (struct rtc_time*)arg, sizeof(struct rtc_time)); - if (retval != 0 ) - return retval; - - get_rtc_alm_time(&alm_tm); - copy_to_user((struct rtc_time*)arg, &alm_tm, sizeof(struct rtc_time)); - - return 0; + get_rtc_alm_time(&wtime); + break; } case RTC_ALM_SET: /* Store a time into the alarm */ { @@ -278,11 +266,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned char hrs, min, sec; struct rtc_time alm_tm; - retval = verify_area(VERIFY_READ, (struct rtc_time*)arg, sizeof(struct rtc_time)); - if (retval != 0 ) - return retval; - - copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)); + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) + return -EFAULT; hrs = alm_tm.tm_hour; min = alm_tm.tm_min; @@ -315,16 +300,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } case RTC_RD_TIME: /* Read the time/date from RTC */ { - int retval; - struct rtc_time rtc_tm; - - retval = verify_area(VERIFY_WRITE, (struct rtc_time*)arg, sizeof(struct rtc_time)); - if (retval !=0 ) - return retval; - - get_rtc_time(&rtc_tm); - copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)); - return 0; + get_rtc_time(&wtime); + break; } case RTC_SET_TIME: /* Set the RTC */ { @@ -338,11 +315,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!suser()) return -EACCES; - retval = verify_area(VERIFY_READ, (struct rtc_time*)arg, sizeof(struct rtc_time)); - if (retval !=0 ) - return retval; - - copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)); + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) + return -EFAULT; yrs = rtc_tm.tm_year + 1900 + ARCFUDGE; mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ @@ -403,14 +377,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ { - int retval; - - retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long)); - if (retval != 0) - return retval; - - copy_to_user((unsigned long*)arg, &rtc_freq, sizeof(unsigned long)); - return 0; + return put_user(rtc_freq, (unsigned long *)arg); } case RTC_IRQP_SET: /* Set periodic IRQ rate. */ { @@ -451,6 +418,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: return -EINVAL; } + return copy_to_user(arg, &wtime, sizeof wtime) ? -EFAULT : 0; } /* @@ -536,11 +504,11 @@ __initfunc(int rtc_init(void)) { unsigned long flags; - printk("Real Time Clock Driver v%s\n", RTC_VERSION); + printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL)) { /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ - printk("rtc: IRQ %d is not free.\n", RTC_IRQ); + printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); return -EIO; } misc_register(&rtc_dev); diff --git a/drivers/char/selection.c b/drivers/char/selection.c index b3f6d1570..b34d73665 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -21,9 +21,9 @@ #include -#include "vt_kern.h" -#include "consolemap.h" -#include "selection.h" +#include +#include +#include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -101,9 +101,9 @@ int sel_loadlut(const unsigned long arg) } /* does screen address p correspond to character at LH/RH edge of screen? */ -static inline int atedge(const int p) +static inline int atedge(const int p, int size_row) { - return (!(p % video_size_row) || !((p + 2) % video_size_row)); + return (!(p % size_row) || !((p + 2) % size_row)); } /* constrain v such that v <= u */ @@ -227,9 +227,9 @@ int set_selection(const unsigned long arg, struct tty_struct *tty, int user) /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && - !atedge(new_sel_end) && isspace(sel_pos(new_sel_end))) { + !atedge(new_sel_end, size_row) && isspace(sel_pos(new_sel_end))) { for (pe = new_sel_end + 2; ; pe += 2) - if (!isspace(sel_pos(pe)) || atedge(pe)) + if (!isspace(sel_pos(pe)) || atedge(pe, size_row)) break; if (isspace(sel_pos(pe))) new_sel_end = pe; diff --git a/drivers/char/selection.h b/drivers/char/selection.h deleted file mode 100644 index 4ed656ff9..000000000 --- a/drivers/char/selection.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * selection.h - * - * Interface between console.c, tty_io.c, vt.c, vc_screen.c and selection.c - */ - -#include - -extern int sel_cons; - -extern void clear_selection(void); -extern int set_selection(const unsigned long arg, struct tty_struct *tty, int user); -extern int paste_selection(struct tty_struct *tty); -extern int sel_loadlut(const unsigned long arg); -extern int mouse_reporting(void); -extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); - -#ifdef CONFIG_FB_CONSOLE -extern unsigned long get_video_num_columns(unsigned int console); -extern unsigned long get_video_num_lines(unsigned int console); -extern unsigned long get_video_size_row(unsigned int console); -#else -#define get_video_num_columns(dummy) video_num_columns -#define get_video_num_lines(dummy) video_num_lines -#define get_video_size_row(dummy) video_size_row -#endif - -extern unsigned long video_num_columns; -extern unsigned long video_num_lines; -extern unsigned long video_size_row; -extern unsigned char video_type; -extern unsigned long video_mem_base; -extern unsigned long video_mem_term; -extern unsigned long video_screen_size; -extern unsigned short video_port_reg; -extern unsigned short video_port_val; - -extern int console_blanked; -extern int can_do_color; - -extern unsigned long video_font_height; -extern unsigned long video_scan_lines; -extern unsigned long default_font_height; -extern int video_font_is_default; - -extern unsigned char color_table[]; -extern int default_red[]; -extern int default_grn[]; -extern int default_blu[]; - -extern unsigned short __real_origin; -extern unsigned short __origin; -extern unsigned char has_wrapped; - -extern unsigned short *vc_scrbuf[MAX_NR_CONSOLES]; - -extern void do_unblank_screen(void); -extern unsigned short *screen_pos(int currcons, int w_offset, int viewed); -extern unsigned short screen_word(int currcons, int offset, int viewed); -extern int scrw2glyph(unsigned short scr_word); -extern void complement_pos(int currcons, int offset); -extern void invert_screen(int currcons, int offset, int count, int shift); - -#define reverse_video_char(a) (((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77)) -#define reverse_video_short(a) (((a) & 0x88ff) | \ - (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4)) -/* this latter line used to have masks 0xf000 and 0x0f00, but selection - requires a self-inverse operation; moreover, the old version looks wrong */ - -extern void getconsxy(int currcons, char *p); -extern void putconsxy(int currcons, char *p); - - -/* how to access screen memory */ - -#include - -#if defined(CONFIG_TGA_CONSOLE) - -extern int tga_blitc(unsigned int, unsigned long); -extern unsigned long video_mem_term; - -/* - * TGA console screen memory access - * - * TGA is *not* a character/attribute cell device; font bitmaps must be rendered - * to the screen pixels. - * - * We must test for an Alpha kernel virtual address that falls within - * the "shadow screen" memory. This condition indicates we really want - * to write to the screen, so, we do... :-) - * - * NOTE also: there's only *TWO* operations: to put/get a character/attribute. - * All the others needed by VGA support go away, as Not Applicable for TGA. - */ -static inline void scr_writew(unsigned short val, unsigned short * addr) -{ - /* - * always deposit the char/attr, then see if it was to "screen" mem. - * if so, then render the char/attr onto the real screen. - */ - *addr = val; - if ((unsigned long)addr < video_mem_term && - (unsigned long)addr >= video_mem_base) { - tga_blitc(val, (unsigned long) addr); - } -} - -static inline unsigned short scr_readw(unsigned short * addr) -{ - return *addr; -} - -#elif defined (CONFIG_SGI) - -#include "vt_kern.h" -#include -extern void newport_blitc(unsigned short, unsigned long); -extern void memsetw(void * s, unsigned short c, unsigned int count); -extern void memcpyw(unsigned short *to, unsigned short *from, unsigned int count); -extern unsigned long video_mem_term; - -static inline void scr_writew(unsigned short val, unsigned short * addr) -{ - /* always deposit the char/attr, then see if it was to "screen" mem. - * if so, then render the char/attr onto the real screen. - */ - if(*addr != val) { - *addr = val; - if ((unsigned long)addr < video_mem_term && - (unsigned long)addr >= video_mem_base && - vt_cons [fg_console]->vc_mode == KD_TEXT) - newport_blitc(val, (unsigned long) addr); - } -} - -static inline unsigned short scr_readw(unsigned short * addr) -{ - return *addr; -} - -#elif defined (CONFIG_VIDEO_G364) /* The G364 cards: same as above. */ - -extern void g364_blitc(unsigned short, unsigned long); -extern void g364_blitc_colour(unsigned short, unsigned long); -extern unsigned long video_mem_term; - -/* - * G364 console screen memory access - * - * G364 is *not* a character/attribute cell device; font bitmaps must be - * rendered to the screen pixels. - * - * The "unsigned short * addr" is *ALWAYS* a kernel virtual address, either - * of the VC's backing store, or the "shadow screen" memory where the screen - * contents are kept, as the G364 frame buffer is *not* char/attr cells. - * - * We must test for a Mips kernel virtual address that falls within - * the "shadow screen" memory. This condition indicates we really want - * to write to the screen, so, we do... :-) - * - * NOTE also: there's only *TWO* operations: to put/get a character/attribute. - * All the others needed by VGA support go away, as Not Applicable for G364. - */ -static inline void scr_writew(unsigned short val, unsigned short * addr) -{ - /* - * always deposit the char/attr, then see if it was to "screen" mem. - * if so, then render the char/attr onto the real screen. - */ - *addr = val; - if ((unsigned long)addr < video_mem_term && - (unsigned long)addr >= video_mem_base) { - if ((val & 0xff00) == 0x0700) - g364_blitc(val, (unsigned long) addr); /* B&W faster */ - else - g364_blitc_colour(val, (unsigned long) addr); - } -} - -static inline unsigned short scr_readw(unsigned short * addr) -{ - return *addr; -} - -#elif defined(CONFIG_SUN_CONSOLE) - -#include "vt_kern.h" -#include -extern int sun_blitc(unsigned int, unsigned long); -extern void memsetw(void * s, unsigned short c, unsigned int count); -extern void memcpyw(unsigned short *to, unsigned short *from, unsigned int count); -extern unsigned long video_mem_term; - -/* Basically the same as the TGA stuff. */ -static inline void scr_writew(unsigned short val, unsigned short * addr) -{ - /* - * always deposit the char/attr, then see if it was to "screen" mem. - * if so, then render the char/attr onto the real screen. - */ - if (*addr != val) { - *addr = val; - if ((unsigned long)addr < video_mem_term && - (unsigned long)addr >= video_mem_base && - vt_cons [fg_console]->vc_mode == KD_TEXT) - sun_blitc(val, (unsigned long) addr); - } -} - -static inline unsigned short scr_readw(unsigned short * addr) -{ - return *addr; -} - -#else - -/* - * normal VGA console access - * - */ - -#include - -/* - * NOTE: "(long) addr < 0" tests for an Alpha kernel virtual address; this - * indicates a VC's backing store; otherwise, it's a bus memory address, for - * the VGA's screen memory, so we do the Alpha "swizzle"... :-) - */ -static inline void scr_writeb(unsigned char val, unsigned char * addr) -{ - if ((long) addr < 0) - *addr = val; - else - writeb(val, (unsigned long) addr); -} - -static inline unsigned char scr_readb(unsigned char * addr) -{ - if ((long) addr < 0) - return *addr; - return readb((unsigned long) addr); -} - -static inline void scr_writew(unsigned short val, unsigned short * addr) -{ - if ((long) addr < 0) - *addr = val; - else - writew(val, (unsigned long) addr); -} - -static inline unsigned short scr_readw(unsigned short * addr) -{ - if ((long) addr < 0) - return *addr; - return readw((unsigned long) addr); -} - -#endif /* CONFIG_TGA_CONSOLE */ - -#if !defined(CONFIG_SUN_CONSOLE) && !defined(CONFIG_SGI) -static inline void memsetw(void * s, unsigned short c, unsigned int count) -{ - unsigned short * addr = (unsigned short *) s; - - count /= 2; - while (count) { - count--; - scr_writew(c, addr++); - } -} - -static inline void memcpyw(unsigned short *to, unsigned short *from, - unsigned int count) -{ - count /= 2; - while (count) { - count--; - scr_writew(scr_readw(from++), to++); - } -} -#endif /* !defined(CONFIG_SUN_CONSOLE) && !defined(CONFIG_SGI) */ diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c index d16227d83..2eda6ef10 100644 --- a/drivers/char/softdog.c +++ b/drivers/char/softdog.c @@ -42,6 +42,10 @@ static int soft_margin = TIMER_MARGIN; /* in seconds */ +#ifdef MODULE +MODULE_PARM(soft_margin,"i"); +#endif + /* * Our timer */ diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c new file mode 100644 index 000000000..e2044c086 --- /dev/null +++ b/drivers/char/sysrq.c @@ -0,0 +1,248 @@ +/* -*- linux-c -*- + * + * $Id: sysrq.c,v 1.2 1997/05/31 18:33:11 mj Exp $ + * + * Linux Magic System Request Key Hacks + * + * (c) 1997 Martin Mares + * based on ideas by Pavel Machek + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_APM +#include +#endif + +extern void wakeup_bdflush(int); +extern void reset_vc(unsigned int); +extern int console_loglevel; +extern struct vfsmount *vfsmntlist; + +#ifdef __sparc__ +extern void halt_now(void); +#endif + +/* Send a signal to all user processes */ + +static void send_sig_all(int sig, int even_init) +{ + struct task_struct *p; + + for_each_task(p) { + if (p->pid && p->mm != &init_mm) { /* Not swapper nor kernel thread */ + if (p->pid == 1 && even_init) /* Ugly hack to kill init */ + p->pid = 0x8000; + force_sig(sig, p); + } + } +} + +/* + * This function is called by the keyboard handler when SysRq is pressed + * and any other keycode arrives. + */ + +void handle_sysrq(int key, struct pt_regs *pt_regs, + struct kbd_struct *kbd, struct tty_struct *tty) +{ + int orig_log_level = console_loglevel; + + console_loglevel = 7; + printk(KERN_INFO "SysRq: "); + switch (key) { + case 19: /* R -- Reset raw mode */ + kbd->kbdmode = VC_XLATE; + printk("Keyboard mode set to XLATE\n"); + break; + case 30: /* A -- SAK */ + printk("SAK\n"); + do_SAK(tty); + reset_vc(fg_console); + break; + case 48: /* B -- boot immediately */ + printk("Resetting\n"); + machine_restart(NULL); + break; +#ifdef __sparc__ + case 35: /* H -- halt immediately */ + printk("Halting\n"); + halt_now(); + break; +#endif +#ifdef CONFIG_APM + case 24: /* O -- power off */ + printk("Power off\n"); + apm_set_power_state(APM_STATE_OFF); + break; +#endif + case 31: /* S -- emergency sync */ + printk("Emergency Sync\n"); + emergency_sync_scheduled = EMERG_SYNC; + wakeup_bdflush(0); + break; + case 22: /* U -- emergency remount R/O */ + printk("Emergency Remount R/O\n"); + emergency_sync_scheduled = EMERG_REMOUNT; + wakeup_bdflush(0); + break; + case 25: /* P -- show PC */ + printk("Show Regs\n"); + if (pt_regs) + show_regs(pt_regs); + break; + case 20: /* T -- show task info */ + printk("Show State\n"); + show_state(); + break; + case 50: /* M -- show memory info */ + printk("Show Memory\n"); + show_mem(); + break; + case 2 ... 11: /* 0-9 -- set console logging level */ + key -= 2; + if (key == 10) + key = 0; + orig_log_level = key; + printk("Log level set to %d\n", key); + break; + case 18: /* E -- terminate all user processes */ + printk("Terminate All Tasks\n"); + send_sig_all(SIGTERM, 0); + orig_log_level = 8; /* We probably have killed syslogd */ + break; + case 37: /* K -- kill all user processes */ + printk("Kill All Tasks\n"); + send_sig_all(SIGKILL, 0); + orig_log_level = 8; + break; + case 38: /* L -- kill all processes including init */ + printk("Kill ALL Tasks (even init)\n"); + send_sig_all(SIGKILL, 1); + orig_log_level = 8; + break; + default: /* Unknown: help */ + printk("unRaw sAk Boot " +#ifdef __sparc__ + "Halt " +#endif +#ifdef CONFIG_APM + "Off " +#endif + "Sync Unmount showPc showTasks showMem loglevel0-8 tErm Kill killalL\n"); + } + + console_loglevel = orig_log_level; +} + +/* Aux routines for the syncer */ + +static void all_files_read_only(void) /* Kill write permissions of all files */ +{ + struct file *file; + + for (file = inuse_filps; file; file = file->f_next) + if (file->f_inode && file->f_count && S_ISREG(file->f_inode->i_mode)) + file->f_mode &= ~2; +} + +static int is_local_disk(kdev_t dev) /* Guess if the device is a local hard drive */ +{ + unsigned int major = MAJOR(dev); + + switch (major) { + case IDE0_MAJOR: + case IDE1_MAJOR: + case IDE2_MAJOR: + case IDE3_MAJOR: + case SCSI_DISK_MAJOR: + return 1; + default: + return 0; + } +} + +static void go_sync(kdev_t dev, int remount_flag) +{ + printk(KERN_INFO "%sing device %04x ... ", + remount_flag ? "Remount" : "Sync", + dev); + + if (remount_flag) { /* Remount R/O */ + struct super_block *sb = get_super(dev); + struct vfsmount *vfsmnt; + int ret, flags; + + if (!sb) { + printk("Superblock not found\n"); + return; + } + if (sb->s_flags & MS_RDONLY) { + printk("R/O\n"); + return; + } + quota_off(dev, -1); + fsync_dev(dev); + flags = MS_RDONLY; + if (sb->s_op && sb->s_op->remount_fs) { + ret = sb->s_op->remount_fs(sb, &flags, NULL); + if (ret) + printk("error %d\n", ret); + else { + sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); + if ((vfsmnt = lookup_vfsmnt(sb->s_dev))) + vfsmnt->mnt_flags = sb->s_flags; + printk("OK\n"); + } + } else + printk("nothing to do\n"); + } else { + fsync_dev(dev); /* Sync only */ + printk("OK\n"); + } +} + +/* + * Emergency Sync or Unmount. We cannot do it directly, so we set a special + * flag and wake up the bdflush kernel thread which immediately calls this function. + * We process all mounted hard drives first to recover from crashed experimental + * block devices and malfunctional network filesystems. + */ + +int emergency_sync_scheduled; + +void do_emergency_sync(void) +{ + struct vfsmount *mnt; + int remount_flag; + + lock_kernel(); + remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); + emergency_sync_scheduled = 0; + + if (remount_flag) + all_files_read_only(); + + for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next) + if (is_local_disk(mnt->mnt_dev)) + go_sync(mnt->mnt_dev, remount_flag); + + for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next) + if (!is_local_disk(mnt->mnt_dev) && MAJOR(mnt->mnt_dev)) + go_sync(mnt->mnt_dev, remount_flag); + + unlock_kernel(); + printk(KERN_INFO "Done.\n"); +} diff --git a/drivers/char/tga.c b/drivers/char/tga.c index a85f4cba4..f4e7b48ab 100644 --- a/drivers/char/tga.c +++ b/drivers/char/tga.c @@ -33,11 +33,11 @@ #include #include -#include "kbd_kern.h" -#include "vt_kern.h" -#include "consolemap.h" -#include "selection.h" -#include "console_struct.h" +#include +#include +#include +#include +#include extern struct console vt_console_driver; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 12109e524..c08e44a27 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -77,9 +77,9 @@ #include #include -#include "kbd_kern.h" -#include "vt_kern.h" -#include "selection.h" +#include +#include +#include #ifdef CONFIG_KERNELD #include diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index cb91431dc..603250b81 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -31,9 +31,9 @@ #include #include #include +#include +#include #include -#include "vt_kern.h" -#include "selection.h" #undef attr #undef org diff --git a/drivers/char/vga.c b/drivers/char/vga.c index e82bbc083..afce24c98 100644 --- a/drivers/char/vga.c +++ b/drivers/char/vga.c @@ -72,11 +72,11 @@ unsigned long video_port_base; #include #include -#include "kbd_kern.h" -#include "vt_kern.h" -#include "consolemap.h" -#include "selection.h" -#include "console_struct.h" +#include +#include +#include +#include +#include #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ #define CAN_LOAD_PALETTE /* undefine if the user must not do this */ diff --git a/drivers/char/vt.c b/drivers/char/vt.c index b3e25c010..7b007f465 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -26,10 +26,10 @@ #include #include -#include "kbd_kern.h" -#include "vt_kern.h" -#include "diacr.h" -#include "selection.h" +#include +#include +#include +#include char vt_dont_switch = 0; extern struct tty_driver console_driver; diff --git a/drivers/char/vt_kern.h b/drivers/char/vt_kern.h deleted file mode 100644 index 1692f991c..000000000 --- a/drivers/char/vt_kern.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _VT_KERN_H -#define _VT_KERN_H - -/* - * this really is an extension of the vc_cons structure in console.c, but - * with information needed by the vt package - */ - -#include - -/* - * Presently, a lot of graphics programs do not restore the contents of - * the higher font pages. Defining this flag will avoid use of them, but - * will lose support for PIO_FONTRESET. Note that many font operations are - * not likely to work with these programs anyway; they need to be - * fixed. The linux/Documentation directory includes a code snippet - * to save and restore the text font. - */ -#define BROKEN_GRAPHICS_PROGRAMS 1 - -extern struct vt_struct { - int vc_num; /* The console number */ - unsigned char vc_mode; /* KD_TEXT, ... */ - unsigned char vc_kbdraw; - unsigned char vc_kbde0; - unsigned char vc_kbdleds; - struct vt_mode vt_mode; - int vt_pid; - int vt_newvt; - struct wait_queue *paste_wait; -} *vt_cons[MAX_NR_CONSOLES]; - -void (*kd_mksound)(unsigned int hz, unsigned int ticks); -int vc_allocate(unsigned int console); -int vc_cons_allocated(unsigned int console); -int vc_resize(unsigned long lines, unsigned long cols); -void vc_disallocate(unsigned int console); - -#endif /* _VT_KERN_H */ diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index dc29bdf79..91c868942 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 1.29 1997/04/23 20:09:49 fritz Exp $ +/* $Id: callc.c,v 1.30 1997/05/29 10:40:43 keil Exp $ * Author Karsten Keil (keil@temic-ech.spacenet.de) * based on the teles driver from Jan den Ouden @@ -7,6 +7,9 @@ * Fritz Elfert * * $Log: callc.c,v $ + * Revision 1.30 1997/05/29 10:40:43 keil + * chanp->impair was uninitialised + * * Revision 1.29 1997/04/23 20:09:49 fritz * Removed tmp, used by removed debugging code. * @@ -109,7 +112,7 @@ extern long mod_use_count_; #endif #endif /* MODULE */ -const char *l4_revision = "$Revision: 1.29 $"; +const char *l4_revision = "$Revision: 1.30 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -1504,6 +1507,7 @@ init_chan(int chan, struct IsdnCardState *csta, int hscx, chanp->debug = 0; chanp->Flags = 0; chanp->leased = 0; + chanp->impair = 0; init_is(chanp, ces); chanp->fi.fsm = &callcfsm; diff --git a/drivers/net/Config.in b/drivers/net/Config.in index e14c76a61..23befe03c 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -142,10 +142,15 @@ if [ "$CONFIG_NET_RADIO" != "n" ]; then bool 'Soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC bool 'Soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS bool 'Soundmodem support for 1200 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK1200 + bool 'Soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_7 + bool 'Soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8 bool 'Soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800 bool 'Soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600 - if [ "$CONFIG_M586" = "y" -o "$CONFIG_M686" = "y" ]; then - bool 'Soundmodem using floating point' CONFIG_SOUNDMODEM_FLOAT + if [ -f drivers/net/soundmodem/sm_afsk2666.c ]; then + bool 'Soundmodem support for 2666 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK2666 + fi + if [ -f drivers/net/soundmodem/sm_psk4800.c ]; then + bool 'Soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800 fi fi fi diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c index 7a8069fd6..c9f13150c 100644 --- a/drivers/net/arcnet.c +++ b/drivers/net/arcnet.c @@ -751,8 +751,8 @@ __initfunc(int arcnet_probe(struct device *dev)) * FIXME: grab all devices in one shot and eliminate the big static array. */ -static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata; -static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata; +static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = { 0 }; +static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = { 0 }; __initfunc(int arcnet_probe(struct device *dev)) { diff --git a/drivers/net/baycom.c b/drivers/net/baycom.c index 7569d66e7..74c041342 100644 --- a/drivers/net/baycom.c +++ b/drivers/net/baycom.c @@ -68,6 +68,7 @@ * History: * 0.1 26.06.96 Adapted from baycom.c and made network driver interface * 18.10.96 Changed to new user space access routines (copy_{to,from}_user) + * 0.3 26.04.96 init code/data tagged */ /*****************************************************************************/ @@ -89,7 +90,6 @@ #include #include #include -#include /* --------------------------------------------------------------------- */ @@ -133,6 +133,14 @@ extern inline int copy_to_user(void *to, const void *from, unsigned long n) } #endif +#if LINUX_VERSION_CODE >= 0x20123 +#include +#else +#define __init +#define __initdata +#define __initfunc(x) x +#endif + /* --------------------------------------------------------------------- */ #define BAYCOM_DEBUG @@ -1001,7 +1009,7 @@ MODULE_DESCRIPTION("Baycom ser12, par96 and picpar amateur radio modem driver"); #endif -int init_module(void) +__initfunc(int init_module(void)) { baycom_ports[0].mode = mode; baycom_ports[0].iobase = iobase; diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 659e71f32..b841a01bb 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -229,7 +229,11 @@ static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefa #define DYNAMIC_BUFFERS 1 #define SKBUFF_RX_COPYBREAK 200 -#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX) +/* + * NEW_SKB_SIZE = PI_RCV_DATA_K_SIZE_MAX+128 to allow 128 byte + * alignment for compatibility with old EISA boards. + */ +#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) /* Define global routines */ @@ -2944,6 +2948,12 @@ void dfx_rcv_init( bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP | ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN)); newskb = dev_alloc_skb(NEW_SKB_SIZE); + /* + * align to 128 bytes for compatibility with + * the old EISA boards. + */ + newskb->data = (char *)((unsigned long) + (newskb->data+127) & ~128); bp->descr_block_virt->rcv_data[i+j].long_1 = virt_to_bus(newskb->data); /* * p_rcv_buff_va is only used inside the @@ -3012,8 +3022,6 @@ void dfx_rcv_queue_process( u32 descr, pkt_len; /* FMC descriptor field and packet length */ struct sk_buff *skb; /* pointer to a sk_buff to hold incoming packet data */ - static int testing_dyn; - /* Service all consumed LLC receive frames */ p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data); @@ -3056,18 +3064,12 @@ void dfx_rcv_queue_process( newskb = dev_alloc_skb(NEW_SKB_SIZE); if (newskb){ rx_in_place = 1; -#define JES_TESTING -#ifdef JES_TESTING - if(testing_dyn++ < 5) - printk("Skipping a memcpy\n"); + + newskb->data = (char *)((unsigned long)(newskb->data+127) & ~128); skb = (struct sk_buff *)bp->p_rcv_buff_va[entry]; skb->data += RCV_BUFF_K_PADDING; bp->p_rcv_buff_va[entry] = (char *)newskb; bp->descr_block_virt->rcv_data[entry].long_1 = virt_to_bus(newskb->data); -#else - memcpy(newskb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3); - skb = newskb; -#endif } else skb = 0; } else @@ -3240,12 +3242,14 @@ int dfx_xmt_queue_pkt( p_xmt_descr = &(bp->descr_block_virt->xmt_data[prod]); /* - * Get pointer to auxiliary queue entry to contain information for this packet. + * Get pointer to auxiliary queue entry to contain information + * for this packet. * - * Note: The current xmt producer index will become the current xmt completion - * index when we complete this packet later on. So, we'll get the - * pointer to the next auxiliary queue entry now before we bump the - * producer index. + * Note: The current xmt producer index will become the + * current xmt completion index when we complete this + * packet later on. So, we'll get the pointer to the + * next auxiliary queue entry now before we bump the + * producer index. */ p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]); /* also bump producer index */ @@ -3290,15 +3294,15 @@ int dfx_xmt_queue_pkt( * Verify that descriptor is actually available * * Note: If descriptor isn't available, return 1 which tells - * the upper layer to requeue the packet for later - * transmission. + * the upper layer to requeue the packet for later + * transmission. * * We need to ensure that the producer never reaches the - * completion, except to indicate that the queue is empty. + * completion, except to indicate that the queue is empty. */ if (prod == bp->rcv_xmt_reg.index.xmt_comp) - return(1); /* requeue packet for later */ + return(1); /* requeue packet for later */ /* * Save info for this packet for xmt done indication routine @@ -3311,9 +3315,9 @@ int dfx_xmt_queue_pkt( * one (1) for each completed packet. * * Note: If this assumption changes and we're presented with - * an inconsistent number of transmit fragments for packet - * data, we'll need to modify this code to save the current - * transmit producer index. + * an inconsistent number of transmit fragments for packet + * data, we'll need to modify this code to save the current + * transmit producer index. */ p_xmt_drv_descr->p_skb = skb; diff --git a/drivers/net/hdlcdrv.c b/drivers/net/hdlcdrv.c index 467980406..666bf3858 100644 --- a/drivers/net/hdlcdrv.c +++ b/drivers/net/hdlcdrv.c @@ -32,6 +32,7 @@ * (copy_{to,from}_user) * 0.2 21.11.96 various small changes * 0.3 03.03.97 fixed (hopefully) IP not working with ax.25 as a module + * 0.4 16.04.97 init code/data tagged */ /*****************************************************************************/ @@ -119,6 +120,23 @@ extern __inline__ void dev_init_buffers(struct device *dev) /* --------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE >= 0x20123 +#include +#else +#define __init +#define __initdata +#define __initfunc(x) x +#endif + +/* --------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE < 0x20125 +#define test_and_set_bit set_bit +#define test_and_clear_bit clear_bit +#endif + +/* --------------------------------------------------------------------- */ + /* * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels @@ -998,10 +1016,10 @@ MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder"); /* --------------------------------------------------------------------- */ -int init_module(void) +__initfunc(int init_module(void)) { printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n"); - printk(KERN_INFO "hdlcdrv: version 0.3 compiled " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "hdlcdrv: version 0.4 compiled " __TIME__ " " __DATE__ "\n"); #if LINUX_VERSION_CODE < 0x20115 register_symtab(&hdlcdrv_syms); #endif diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 9d8e30761..ef15a14da 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -248,7 +248,7 @@ void fddi_setup(struct device *dev) #endif -#ifdef CONFIG_ATALK +#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) static int ltalk_change_mtu(struct device *dev, int mtu) { diff --git a/drivers/net/soundmodem/Makefile b/drivers/net/soundmodem/Makefile index 119118128..5259b724c 100644 --- a/drivers/net/soundmodem/Makefile +++ b/drivers/net/soundmodem/Makefile @@ -21,6 +21,12 @@ endif ifeq ($(CONFIG_SOUNDMODEM_AFSK1200),y) O_OBJS += sm_afsk1200.o endif +ifeq ($(CONFIG_SOUNDMODEM_AFSK2400_7),y) +O_OBJS += sm_afsk2400_7.o +endif +ifeq ($(CONFIG_SOUNDMODEM_AFSK2400_8),y) +O_OBJS += sm_afsk2400_8.o +endif ifeq ($(CONFIG_SOUNDMODEM_AFSK2666),y) O_OBJS += sm_afsk2666.o endif @@ -39,7 +45,8 @@ M_OBJS := $(O_TARGET) gentbl: gentbl.c $(HOSTCC) -Wall $< -o $@ -lm -TBLHDR := sm_tbl_afsk1200.h sm_tbl_afsk2666.h sm_tbl_psk4800.h +TBLHDR := sm_tbl_afsk1200.h sm_tbl_afsk2400_8.h +TBLHDR += sm_tbl_afsk2666.h sm_tbl_psk4800.h TBLHDR += sm_tbl_hapn4800.h sm_tbl_fsk9600.h $(TBLHDR): gentbl diff --git a/drivers/net/soundmodem/gentbl.c b/drivers/net/soundmodem/gentbl.c index d617865e3..cb8cb246f 100644 --- a/drivers/net/soundmodem/gentbl.c +++ b/drivers/net/soundmodem/gentbl.c @@ -31,27 +31,44 @@ /* -------------------------------------------------------------------- */ -#define OFFSCOSTABBITS 6 -#define OFFSCOSTABSIZE (1<>%d)&0x%x]\n\n", - 16-OFFSCOSTABBITS, OFFSCOSTABSIZE-1); + 16-nbits, (1<>%d)&0x%x]\n" + "#define SIN(x) COS((x)+0xc000)\n\n", 16-nbits, + (1<= 0; o--) { fprintf(f, "\t{\n"); for (i = 0; i < AFSK26_NUMCAR; i++) { j = cfreq[i]; fprintf(f, "\t\t{{ "); - for (l = AFSK26_DEMCORRLEN-1, - k = (j * o)/AFSK26_RXOVER; l >= 0; - l--, k = (k+j)&0xffffu) - fprintf(f, "%6d%s", (int) - (AFSK26_AMPL(i)* - window[l*AFSK26_RXOVER+o]* - cos(M_PI*k/32768.0)), - l ? ", " : " }, { "); - for (l = AFSK26_DEMCORRLEN-1, - k = (j * o)/AFSK26_RXOVER; l >= 0; - l--, k = (k+j)&0xffffu) - fprintf(f, "%6d%s", (int) - (AFSK26_AMPL(i)* - window[l*AFSK26_RXOVER+o]* - sin(M_PI*k/32768.0)), - l ? ", " : " }}"); + for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumi = 0; l >= 0; + l--, k = (k+j)&0xffffu) { + sumi += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* + cos(M_PI*k/32768.0)); + fprintf(f, "%6d%s", v, l ? ", " : " }, { "); + } + for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumq = 0; l >= 0; + l--, k = (k+j)&0xffffu) { + sumq += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* + sin(M_PI*k/32768.0)); + fprintf(f, "%6d%s", v, l ? ", " : " }}"); + } if (i < 1) fprintf(f, ","); - fprintf(f, "\n"); + fprintf(f, "\n#define AFSK26_DEM_SUM_I_%d_%d %d\n" + "#define AFSK26_DEM_SUM_Q_%d_%d %d\n", + AFSK26_RXOVER-1-o, i, sumi, AFSK26_RXOVER-1-o, i, sumq); } fprintf(f, "\t}%s\n", o ? "," : ""); } @@ -308,28 +340,6 @@ static void gentbl_afsk2666(FILE *f) /* -------------------------------------------------------------------- */ -#define COSTABBITS 8 - -static void gentbl_costab(FILE *f) -{ - int i; - - fprintf(f, "\n/*\n * more accurate cosine table\n */\n\n" - "static const short costab[%d] = {", (1<>%d)&0x%x]\n" - "#define SIN(x) COS((x)+0xc000)\n\n", 16-COSTABBITS, - (1<\n\n"); +} + /* -------------------------------------------------------------------- */ void main(int argc, char *argv[]) @@ -596,20 +690,23 @@ void main(int argc, char *argv[]) if (!(f = fopen("sm_tbl_afsk1200.h", "w"))) exit(1); gentbl_banner(f); - gentbl_offscostab(f); + gentbl_needs_config(f); + gentbl_offscostab(f, 6); + gentbl_costab(f, 6); gentbl_afsk1200(f); fclose(f); if (!(f = fopen("sm_tbl_afsk2666.h", "w"))) exit(1); gentbl_banner(f); - gentbl_offscostab(f); + gentbl_offscostab(f, 6); + gentbl_costab(f, 6); gentbl_afsk2666(f); fclose(f); if (!(f = fopen("sm_tbl_psk4800.h", "w"))) exit(1); gentbl_banner(f); gentbl_psk4800(f); - gentbl_costab(f); + gentbl_costab(f, 8); gentbl_atantab(f); fclose(f); if (!(f = fopen("sm_tbl_hapn4800.h", "w"))) @@ -622,6 +719,22 @@ void main(int argc, char *argv[]) gentbl_banner(f); gentbl_fsk9600(f); fclose(f); + if (!(f = fopen("sm_tbl_afsk2400_8.h", "w"))) + exit(1); + gentbl_banner(f); + gentbl_needs_config(f); + gentbl_offscostab(f, 6); + gentbl_costab(f, 6); + gentbl_afsk2400(f, 8000000); + fclose(f); + if (!(f = fopen("sm_tbl_afsk2400_7.h", "w"))) + exit(1); + gentbl_banner(f); + gentbl_needs_config(f); + gentbl_offscostab(f, 6); + gentbl_costab(f, 6); + gentbl_afsk2400(f, 7372800); + fclose(f); exit(0); } diff --git a/drivers/net/soundmodem/sm.c b/drivers/net/soundmodem/sm.c index d55bc0c04..ac1fbac48 100644 --- a/drivers/net/soundmodem/sm.c +++ b/drivers/net/soundmodem/sm.c @@ -38,6 +38,7 @@ * 18.10.96 Changed to new user space access routines (copy_{to,from}_user) * 0.4 21.01.97 Separately compileable soundcard/modem modules * 0.5 03.03.97 fixed LPT probing (check_lpt result was interpreted the wrong way round) + * 0.6 16.04.97 init code/data tagged */ /*****************************************************************************/ @@ -56,7 +57,6 @@ #include #include #include -#include #include "sm.h" /* --------------------------------------------------------------------- */ @@ -101,18 +101,32 @@ extern inline int copy_to_user(void *to, const void *from, unsigned long n) } #endif +#if LINUX_VERSION_CODE >= 0x20123 +#include +#else +#define __init +#define __initdata +#define __initfunc(x) x +#endif + /* --------------------------------------------------------------------- */ -const char sm_drvname[] = "soundmodem"; -static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "soundmodem: version 0.5 compiled " __TIME__ " " __DATE__ "\n"; +/*static*/ const char sm_drvname[] = "soundmodem"; +static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-1997 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "soundmodem: version 0.6 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ -const struct modem_tx_info *sm_modem_tx_table[] = { +/*static*/ const struct modem_tx_info *sm_modem_tx_table[] = { #ifdef CONFIG_SOUNDMODEM_AFSK1200 &sm_afsk1200_tx, #endif /* CONFIG_SOUNDMODEM_AFSK1200 */ +#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 + &sm_afsk2400_7_tx, +#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ +#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 + &sm_afsk2400_8_tx, +#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ #ifdef CONFIG_SOUNDMODEM_AFSK2666 &sm_afsk2666_tx, #endif /* CONFIG_SOUNDMODEM_AFSK2666 */ @@ -132,10 +146,16 @@ const struct modem_tx_info *sm_modem_tx_table[] = { NULL }; -const struct modem_rx_info *sm_modem_rx_table[] = { +/*static*/ const struct modem_rx_info *sm_modem_rx_table[] = { #ifdef CONFIG_SOUNDMODEM_AFSK1200 &sm_afsk1200_rx, #endif /* CONFIG_SOUNDMODEM_AFSK1200 */ +#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 + &sm_afsk2400_7_rx, +#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ +#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 + &sm_afsk2400_8_rx, +#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ #ifdef CONFIG_SOUNDMODEM_AFSK2666 &sm_afsk2666_rx, #endif /* CONFIG_SOUNDMODEM_AFSK2666 */ @@ -344,7 +364,7 @@ void sm_output_status(struct sm_state *sm) int invert_dcd = 0; int invert_ptt = 0; - int ptt = hdlcdrv_ptt(&sm->hdrv) ^ invert_ptt; + int ptt = /*hdlcdrv_ptt(&sm->hdrv)*/(sm->dma.ptt_cnt > 0) ^ invert_ptt; int dcd = (!!sm->hdrv.hdlcrx.dcd) ^ invert_dcd; if (sm->hdrv.ptt_out.flags & SP_SER) { @@ -457,9 +477,9 @@ static int sm_open(struct device *dev) return err; sm_output_open(sm); MOD_INC_USE_COUNT; - printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u\n", + printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u dma2 %u\n", sm_drvname, sm->hwdrv->hw_name, sm->mode_tx->name, - sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma); + sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma, sm->hdrv.ptt_out.dma2); return 0; } @@ -664,7 +684,56 @@ static int sm_ioctl(struct device *dev, struct ifreq *ifr, /* --------------------------------------------------------------------- */ +#ifdef __i386__ + +int sm_x86_capability = 0; + +__initfunc(static void i386_capability(void)) +{ + unsigned long flags; + unsigned long fl1; + union { + struct { + unsigned int ebx, edx, ecx; + } r; + unsigned char s[13]; + } id; + unsigned int eax; + + save_flags(flags); + flags |= 0x200000; + restore_flags(flags); + save_flags(flags); + fl1 = flags; + flags &= ~0x200000; + restore_flags(flags); + save_flags(flags); + if (!(fl1 & 0x200000) || (flags & 0x200000)) { + printk(KERN_WARNING "%s: cpu does not support CPUID\n", sm_drvname); + return; + } + __asm__ ("cpuid" : "=a" (eax), "=b" (id.r.ebx), "=c" (id.r.ecx), "=d" (id.r.edx) : + "0" (0)); + id.s[12] = 0; + if (eax < 1) { + printk(KERN_WARNING "%s: cpu (vendor string %s) does not support capability " + "list\n", sm_drvname, id.s); + return; + } + printk(KERN_INFO "%s: cpu: vendor string %s ", sm_drvname, id.s); + __asm__ ("cpuid" : "=a" (eax), "=d" (sm_x86_capability) : "0" (1) : "ebx", "ecx"); + printk("fam %d mdl %d step %d cap 0x%x\n", (eax >> 8) & 15, (eax >> 4) & 15, + eax & 15, sm_x86_capability); +} +#endif /* __i386__ */ + +/* --------------------------------------------------------------------- */ + +#ifdef MODULE +__initfunc(static int sm_init(void)) +#else /* MODULE */ __initfunc(int sm_init(void)) +#endif /* MODULE */ { int i, j, found = 0; char set_hw = 1; @@ -672,6 +741,9 @@ __initfunc(int sm_init(void)) char ifname[HDLCDRV_IFNAMELEN]; printk(sm_drvinfo); +#ifdef __i386__ + i386_capability(); +#endif /* __i386__ */ /* * register net devices */ @@ -745,7 +817,7 @@ MODULE_DESCRIPTION("Soundcard amateur radio modem driver"); #endif -int init_module(void) +__initfunc(int init_module(void)) { if (mode) { if (iobase == -1) diff --git a/drivers/net/soundmodem/sm.h b/drivers/net/soundmodem/sm.h index 2cce82992..25bbc8ba9 100644 --- a/drivers/net/soundmodem/sm.h +++ b/drivers/net/soundmodem/sm.h @@ -30,16 +30,11 @@ /* ---------------------------------------------------------------------- */ -#include #include #include #define SM_DEBUG -/* --------------------------------------------------------------------- */ - -#define DMA_MODE_AUTOINIT 0x10 - /* ---------------------------------------------------------------------- */ /* * Information that need to be kept for each board. @@ -56,6 +51,18 @@ struct sm_state { /* * Hardware (soundcard) access routines state */ + struct { + void *ibuf; + unsigned int ifragsz; + unsigned int ifragptr; + unsigned int i16bit; + void *obuf; + unsigned int ofragsz; + unsigned int ofragptr; + unsigned int o16bit; + int ptt_cnt; + } dma; + union { long hw[32/sizeof(long)]; } hw; @@ -101,9 +108,9 @@ struct modem_tx_info { unsigned int loc_storage; int srate; int bitrate; - unsigned int dmabuflenmodulo; - void (*modulator)(struct sm_state *, unsigned char *, int); - void (*init)(struct sm_state *); + void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int); + void (*modulator_s16)(struct sm_state *, short *, unsigned int); + void (*init)(struct sm_state *); }; struct modem_rx_info { @@ -111,10 +118,11 @@ struct modem_rx_info { unsigned int loc_storage; int srate; int bitrate; - unsigned int dmabuflenmodulo; + unsigned int overlap; unsigned int sperbit; - void (*demodulator)(struct sm_state *, unsigned char *, int); - void (*init)(struct sm_state *); + void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int); + void (*demodulator_s16)(struct sm_state *, const short *, unsigned int); + void (*init)(struct sm_state *); }; /* ---------------------------------------------------------------------- */ @@ -281,30 +289,41 @@ extern inline unsigned int lcm(unsigned int x, unsigned int y) */ -#if defined(SM_DEBUG) && (defined(CONFIG_M586) || defined(CONFIG_M686)) +#ifdef __i386__ + +extern int sm_x86_capability; + +#define HAS_RDTSC (sm_x86_capability & 0x10) /* * only do 32bit cycle counter arithmetic; we hope we won't overflow :-) * in fact, overflowing modems would require over 2THz clock speeds :-) */ -#define time_exec(var,cmd) \ -({ \ - unsigned int cnt1, cnt2, cnt3; \ - __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt3)); \ - cmd; \ - __asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt3)); \ - var = cnt2-cnt1; \ +#define time_exec(var,cmd) \ +({ \ + if (HAS_RDTSC) { \ + unsigned int cnt1, cnt2, cnt3; \ + __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt3)); \ + cmd; \ + __asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt3)); \ + var = cnt2-cnt1; \ + } else { \ + cmd; \ + } \ }) -#else /* defined(SM_DEBUG) && (defined(CONFIG_M586) || defined(CONFIG_M686)) */ + +#else /* __i386__ */ #define time_exec(var,cmd) cmd -#endif /* defined(SM_DEBUG) && (defined(CONFIG_M586) || defined(CONFIG_M686)) */ +#endif /* __i386__ */ /* --------------------------------------------------------------------- */ extern const struct modem_tx_info sm_afsk1200_tx; +extern const struct modem_tx_info sm_afsk2400_7_tx; +extern const struct modem_tx_info sm_afsk2400_8_tx; extern const struct modem_tx_info sm_afsk2666_tx; extern const struct modem_tx_info sm_psk4800_tx; extern const struct modem_tx_info sm_hapn4800_8_tx; @@ -315,6 +334,8 @@ extern const struct modem_tx_info sm_fsk9600_4_tx; extern const struct modem_tx_info sm_fsk9600_5_tx; extern const struct modem_rx_info sm_afsk1200_rx; +extern const struct modem_rx_info sm_afsk2400_7_rx; +extern const struct modem_rx_info sm_afsk2400_8_rx; extern const struct modem_rx_info sm_afsk2666_rx; extern const struct modem_rx_info sm_psk4800_rx; extern const struct modem_rx_info sm_hapn4800_8_rx; diff --git a/drivers/net/soundmodem/sm_afsk1200.c b/drivers/net/soundmodem/sm_afsk1200.c index 0519c5e79..64b20a57c 100644 --- a/drivers/net/soundmodem/sm_afsk1200.c +++ b/drivers/net/soundmodem/sm_afsk1200.c @@ -38,174 +38,176 @@ struct demod_state_afsk12 { int dcd_sum0, dcd_sum1, dcd_sum2; unsigned int dcd_time; unsigned char last_rxbit; - union { - signed char c[8]; - float f[8]; - } filt; }; struct mod_state_afsk12 { unsigned int shreg; unsigned char tx_bit; unsigned int bit_pll; + unsigned int dds_inc; + unsigned int txphase; }; /* --------------------------------------------------------------------- */ -static void modulator_1200(struct sm_state *sm, unsigned char *buf, int buflen) +static const int dds_inc[2] = { + AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE, + AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE +}; + +static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf, + unsigned int buflen) { struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); - static const int dds_inc[2] = { AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE, - AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE }; - int j, k; - - for (; buflen >= 8; buflen -= 8) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ - (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - k = dds_inc[st->tx_bit & 1]; - for (j = 0; j < 8; j++) { - *buf++ = OFFSCOS(st->bit_pll); - st->bit_pll += k; + + for (; buflen > 0; buflen--) { + if (!((st->txphase++) & 7)) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; } + st->dds_inc = dds_inc[st->tx_bit & 1]; + *buf++ = OFFSCOS(st->bit_pll); + st->bit_pll += st->dds_inc; } } /* --------------------------------------------------------------------- */ +static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); -/* - * should eventually move to an asm header file - */ - - -#if defined (CONFIG_SOUNDMODEM__AFSK1200_FP) && (defined(CONFIG_M586) || defined(CONFIG_M686)) - + for (; buflen > 0; buflen--) { + if (!((st->txphase++) & 7)) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; + } + st->dds_inc = dds_inc[st->tx_bit & 1]; + *buf++ = COS(st->bit_pll); + st->bit_pll += st->dds_inc; + } +} +/* --------------------------------------------------------------------- */ -#define ENV_STORAGE unsigned char fpu_save[108]; +extern __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum) +{ + int sum = -0x80 * csum; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); -#define ENV_SAVE asm("fsave %0;\n\tfninit;\n\t" : "=m" (*fpu_save) : : "memory"); -#define ENV_RESTORE asm("frstor %0;\n\t" : : "m" (*fpu_save)); + sum >>= 7; + return sum * sum; +} -static inline float convolution8(const float *st, const float *coeff) +extern __inline__ int convolution8_s16(const short *st, const int *coeff, int csum) { - float f; - - /* - * from Phil Karn, KA9Q's home page - */ - asm volatile ("flds (%1);\n\t" - "fmuls (%2);\n\t" - "flds 4(%1);\n\t" - "fmuls 4(%2);\n\t" - "flds 8(%1);\n\t" - "fmuls 8(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "flds 12(%1);\n\t" - "fmuls 12(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "flds 16(%1);\n\t" - "fmuls 16(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "flds 20(%1);\n\t" - "fmuls 20(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "flds 24(%1);\n\t" - "fmuls 24(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "flds 28(%1);\n\t" - "fmuls 28(%2);\n\t" - "fxch %%st(2);\n\t" - "faddp;\n\t" - "faddp;\n\t" - "fmul %%st(0),%%st;\n\t" : - "=t" (f) : - "r" (st), - "r" (coeff) : "memory"); - - return f; + int sum = 0; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); + + sum >>= 15; + return sum * sum; } -static inline int do_filter_1200(struct demod_state_afsk12 *st, unsigned char newval) +extern __inline__ int do_filter_1200_u8(const unsigned char *buf) { - float sum; - - memmove(st->filt.f+1, st->filt.f,sizeof(st->filt.f) - sizeof(st->filt.f[0])); - st->filt.f[0] = (((int)newval)-0x80); - - sum = convolution8(st->filt.f, afsk12_tx_lo_i_f); - sum += convolution8(st->filt.f, afsk12_tx_lo_q_f); - sum -= convolution8(st->filt.f, afsk12_tx_hi_i_f); - sum -= convolution8(st->filt.f, afsk12_tx_hi_q_f); + int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); + sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); + sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); + sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); return sum; } -#else /* defined (CONFIG_SOUNDMODEM__AFSK1200_FP) && (defined(CONFIG_M586) || defined(CONFIG_M686)) */ - -#define ENV_STORAGE -#define ENV_SAVE -#define ENV_RESTORE - -static inline void datamove8(signed char *st, unsigned char newval) +extern __inline__ int do_filter_1200_s16(const short *buf) { - memmove(st+1, st, 7); - *st = newval - 0x80; + int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); + sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); + sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); + sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); + return sum; } -static inline int convolution8(const signed char *st, const signed char *coeff) -{ - int sum = (st[0] * coeff[0]); - - sum += (st[1] * coeff[1]); - sum += (st[2] * coeff[2]); - sum += (st[3] * coeff[3]); - sum += (st[4] * coeff[4]); - sum += (st[5] * coeff[5]); - sum += (st[6] * coeff[6]); - sum += (st[7] * coeff[7]); +/* --------------------------------------------------------------------- */ - sum >>= 7; - return sum * sum; -} +static const int pll_corr[2] = { -0x1000, 0x1000 }; -static inline int do_filter_1200(struct demod_state_afsk12 *st, unsigned char newval) +static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) { + struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); + int j; int sum; + unsigned char newsample; - datamove8(st->filt.c, newval); - - sum = convolution8(st->filt.c, afsk12_tx_lo_i); - sum += convolution8(st->filt.c, afsk12_tx_lo_q); - sum -= convolution8(st->filt.c, afsk12_tx_hi_i); - sum -= convolution8(st->filt.c, afsk12_tx_hi_q); - return sum; + for (; buflen > 0; buflen--, buf++) { + sum = do_filter_1200_u8(buf); + st->dcd_shreg <<= 1; + st->bit_pll += 0x2000; + newsample = (sum > 0); + if (st->last_sample ^ newsample) { + st->last_sample = newsample; + st->dcd_shreg |= 1; + st->bit_pll += pll_corr + [st->bit_pll < 0x9000]; + j = 4 * hweight8(st->dcd_shreg & 0x38) + - hweight16(st->dcd_shreg & 0x7c0); + st->dcd_sum0 += j; + } + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 120; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->shreg >>= 1; + st->shreg |= (!(st->last_rxbit ^ + st->last_sample)) << 16; + st->last_rxbit = st->last_sample; + diag_trigger(sm); + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + } + diag_add(sm, (((int)*buf)-0x80) << 8, sum); + } } -#endif /* defined (CONFIG_SOUNDMODEM__AFSK1200_FP) && (defined(CONFIG_M586) || defined(CONFIG_M686)) */ - - /* --------------------------------------------------------------------- */ -static void demodulator_1200(struct sm_state *sm, unsigned char *buf, int buflen) +static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen) { struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; int j; int sum; unsigned char newsample; - ENV_STORAGE; - ENV_SAVE; for (; buflen > 0; buflen--, buf++) { - sum = do_filter_1200(st, *buf); + sum = do_filter_1200_s16(buf); st->dcd_shreg <<= 1; st->bit_pll += 0x2000; newsample = (sum > 0); @@ -240,9 +242,8 @@ static void demodulator_1200(struct sm_state *sm, unsigned char *buf, int buflen st->shreg = 0x10000; } } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); + diag_add(sm, *buf, sum); } - ENV_RESTORE; } /* --------------------------------------------------------------------- */ @@ -259,13 +260,13 @@ static void demod_init_1200(struct sm_state *sm) const struct modem_tx_info sm_afsk1200_tx = { "afsk1200", sizeof(struct mod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, AFSK12_SAMPLE_RATE/1200, modulator_1200, NULL + AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL }; const struct modem_rx_info sm_afsk1200_rx = { "afsk1200", sizeof(struct demod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, AFSK12_SAMPLE_RATE/1200, - AFSK12_SAMPLE_RATE/1200, demodulator_1200, demod_init_1200 + AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200, + demodulator_1200_u8, demodulator_1200_s16, demod_init_1200 }; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/soundmodem/sm_afsk2400_7.c b/drivers/net/soundmodem/sm_afsk2400_7.c new file mode 100644 index 000000000..36e0f328f --- /dev/null +++ b/drivers/net/soundmodem/sm_afsk2400_7.c @@ -0,0 +1,297 @@ +/*****************************************************************************/ + +/* + * sm_afsk2400_7.c -- soundcard radio modem driver, 2400 baud AFSK modem + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + */ + +/* + * This driver is intended to be compatible with TCM3105 modems + * overclocked to 7.3728MHz. The mark and space frequencies therefore + * lie at 3658 and 1996 Hz. + * Note that I do _not_ recommend the building of such links, I provide + * this only for the users who live in the coverage area of such + * a "legacy" link. + */ + +#include +#include "sm.h" +#include "sm_tbl_afsk2400_7.h" + +/* --------------------------------------------------------------------- */ + +struct demod_state_afsk24 { + unsigned int shreg; + unsigned int bit_pll; + unsigned char last_sample; + unsigned int dcd_shreg; + int dcd_sum0, dcd_sum1, dcd_sum2; + unsigned int dcd_time; + unsigned char last_rxbit; +}; + +struct mod_state_afsk24 { + unsigned int shreg; + unsigned char tx_bit; + unsigned int bit_pll; + unsigned int tx_seq; + unsigned int phinc; +}; + +/* --------------------------------------------------------------------- */ + +static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, + AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; + +static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) +{ + struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (st->tx_seq < 0x5555) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; + st->phinc = dds_inc[st->tx_bit & 1]; + } + st->tx_seq += 0x5555; + st->tx_seq &= 0xffff; + *buf = OFFSCOS(st->bit_pll); + st->bit_pll += st->phinc; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (st->tx_seq < 0x5555) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; + st->phinc = dds_inc[st->tx_bit & 1]; + } + st->tx_seq += 0x5555; + st->tx_seq &= 0xffff; + *buf = COS(st->bit_pll); + st->bit_pll += st->phinc; + } +} + +/* --------------------------------------------------------------------- */ + +extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) +{ + int sum = -0x80 * csum; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); + sum += (st[-8] * coeff[8]); + sum += (st[-9] * coeff[9]); + sum += (st[-10] * coeff[10]); + sum += (st[-11] * coeff[11]); + sum += (st[-12] * coeff[12]); + sum += (st[-13] * coeff[13]); + + sum >>= 7; + return sum * sum; +} + +extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) +{ + int sum = 0; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); + sum += (st[-8] * coeff[8]); + sum += (st[-9] * coeff[9]); + sum += (st[-10] * coeff[10]); + sum += (st[-11] * coeff[11]); + sum += (st[-12] * coeff[12]); + sum += (st[-13] * coeff[13]); + + sum >>= 15; + return sum * sum; +} + +extern __inline__ int do_filter_2400_u8(const unsigned char *buf) +{ + int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); + sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); + sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); + sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); + return sum; +} + +extern __inline__ int do_filter_2400_s16(const short *buf) +{ + int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); + sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); + sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); + sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); + return sum; +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + int j; + int sum; + unsigned char newsample; + + for (; buflen > 0; buflen--, buf++) { + sum = do_filter_2400_u8(buf); + st->dcd_shreg <<= 1; + st->bit_pll += AFSK24_BITPLL_INC; + newsample = (sum > 0); + if (st->last_sample ^ newsample) { + st->last_sample = newsample; + st->dcd_shreg |= 1; + if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) + st->bit_pll += AFSK24_BITPLL_INC/2; + else + st->bit_pll -= AFSK24_BITPLL_INC/2; + j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) + - hweight16(st->dcd_shreg & 0x1e0); + st->dcd_sum0 += j; + } + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 120; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->shreg >>= 1; + st->shreg |= (!(st->last_rxbit ^ + st->last_sample)) << 16; + st->last_rxbit = st->last_sample; + diag_trigger(sm); + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + } + diag_add(sm, (((int)*buf)-0x80) << 8, sum); + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + int j; + int sum; + unsigned char newsample; + + for (; buflen > 0; buflen--, buf++) { + sum = do_filter_2400_s16(buf); + st->dcd_shreg <<= 1; + st->bit_pll += AFSK24_BITPLL_INC; + newsample = (sum > 0); + if (st->last_sample ^ newsample) { + st->last_sample = newsample; + st->dcd_shreg |= 1; + if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) + st->bit_pll += AFSK24_BITPLL_INC/2; + else + st->bit_pll -= AFSK24_BITPLL_INC/2; + j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) + - hweight16(st->dcd_shreg & 0x1e0); + st->dcd_sum0 += j; + } + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 120; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->shreg >>= 1; + st->shreg |= (!(st->last_rxbit ^ + st->last_sample)) << 16; + st->last_rxbit = st->last_sample; + diag_trigger(sm); + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + } + diag_add(sm, *buf, sum); + } +} + +/* --------------------------------------------------------------------- */ + +static void demod_init_2400(struct sm_state *sm) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + + st->dcd_time = 120; + st->dcd_sum0 = 2; +} + +/* --------------------------------------------------------------------- */ + +const struct modem_tx_info sm_afsk2400_7_tx = { + "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, + modulator_2400_u8, modulator_2400_s16, NULL +}; + +const struct modem_rx_info sm_afsk2400_7_rx = { + "afsk2400_7", sizeof(struct demod_state_afsk24), + AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, + demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 +}; + +/* --------------------------------------------------------------------- */ diff --git a/drivers/net/soundmodem/sm_afsk2400_8.c b/drivers/net/soundmodem/sm_afsk2400_8.c new file mode 100644 index 000000000..8234815d6 --- /dev/null +++ b/drivers/net/soundmodem/sm_afsk2400_8.c @@ -0,0 +1,297 @@ +/*****************************************************************************/ + +/* + * sm_afsk2400_8.c -- soundcard radio modem driver, 2400 baud AFSK modem + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + */ + +/* + * This driver is intended to be compatible with TCM3105 modems + * overclocked to 8MHz. The mark and space frequencies therefore + * lie at 3970 and 2165 Hz. + * Note that I do _not_ recommend the building of such links, I provide + * this only for the users who live in the coverage area of such + * a "legacy" link. + */ + +#include +#include "sm.h" +#include "sm_tbl_afsk2400_8.h" + +/* --------------------------------------------------------------------- */ + +struct demod_state_afsk24 { + unsigned int shreg; + unsigned int bit_pll; + unsigned char last_sample; + unsigned int dcd_shreg; + int dcd_sum0, dcd_sum1, dcd_sum2; + unsigned int dcd_time; + unsigned char last_rxbit; +}; + +struct mod_state_afsk24 { + unsigned int shreg; + unsigned char tx_bit; + unsigned int bit_pll; + unsigned int tx_seq; + unsigned int phinc; +}; + +/* --------------------------------------------------------------------- */ + +static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, + AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; + +static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) +{ + struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (st->tx_seq < 0x5555) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; + st->phinc = dds_inc[st->tx_bit & 1]; + } + st->tx_seq += 0x5555; + st->tx_seq &= 0xffff; + *buf = OFFSCOS(st->bit_pll); + st->bit_pll += st->phinc; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (st->tx_seq < 0x5555) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; + st->shreg >>= 1; + st->phinc = dds_inc[st->tx_bit & 1]; + } + st->tx_seq += 0x5555; + st->tx_seq &= 0xffff; + *buf = COS(st->bit_pll); + st->bit_pll += st->phinc; + } +} + +/* --------------------------------------------------------------------- */ + +extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) +{ + int sum = -0x80 * csum; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); + sum += (st[-8] * coeff[8]); + sum += (st[-9] * coeff[9]); + sum += (st[-10] * coeff[10]); + sum += (st[-11] * coeff[11]); + sum += (st[-12] * coeff[12]); + sum += (st[-13] * coeff[13]); + + sum >>= 7; + return sum * sum; +} + +extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) +{ + int sum = 0; + + sum += (st[0] * coeff[0]); + sum += (st[-1] * coeff[1]); + sum += (st[-2] * coeff[2]); + sum += (st[-3] * coeff[3]); + sum += (st[-4] * coeff[4]); + sum += (st[-5] * coeff[5]); + sum += (st[-6] * coeff[6]); + sum += (st[-7] * coeff[7]); + sum += (st[-8] * coeff[8]); + sum += (st[-9] * coeff[9]); + sum += (st[-10] * coeff[10]); + sum += (st[-11] * coeff[11]); + sum += (st[-12] * coeff[12]); + sum += (st[-13] * coeff[13]); + + sum >>= 15; + return sum * sum; +} + +extern __inline__ int do_filter_2400_u8(const unsigned char *buf) +{ + int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); + sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); + sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); + sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); + return sum; +} + +extern __inline__ int do_filter_2400_s16(const short *buf) +{ + int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); + sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); + sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); + sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); + return sum; +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + int j; + int sum; + unsigned char newsample; + + for (; buflen > 0; buflen--, buf++) { + sum = do_filter_2400_u8(buf); + st->dcd_shreg <<= 1; + st->bit_pll += AFSK24_BITPLL_INC; + newsample = (sum > 0); + if (st->last_sample ^ newsample) { + st->last_sample = newsample; + st->dcd_shreg |= 1; + if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) + st->bit_pll += AFSK24_BITPLL_INC/2; + else + st->bit_pll -= AFSK24_BITPLL_INC/2; + j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) + - hweight16(st->dcd_shreg & 0x1e0); + st->dcd_sum0 += j; + } + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 120; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->shreg >>= 1; + st->shreg |= (!(st->last_rxbit ^ + st->last_sample)) << 16; + st->last_rxbit = st->last_sample; + diag_trigger(sm); + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + } + diag_add(sm, (((int)*buf)-0x80) << 8, sum); + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + int j; + int sum; + unsigned char newsample; + + for (; buflen > 0; buflen--, buf++) { + sum = do_filter_2400_s16(buf); + st->dcd_shreg <<= 1; + st->bit_pll += AFSK24_BITPLL_INC; + newsample = (sum > 0); + if (st->last_sample ^ newsample) { + st->last_sample = newsample; + st->dcd_shreg |= 1; + if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) + st->bit_pll += AFSK24_BITPLL_INC/2; + else + st->bit_pll -= AFSK24_BITPLL_INC/2; + j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) + - hweight16(st->dcd_shreg & 0x1e0); + st->dcd_sum0 += j; + } + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 120; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->shreg >>= 1; + st->shreg |= (!(st->last_rxbit ^ + st->last_sample)) << 16; + st->last_rxbit = st->last_sample; + diag_trigger(sm); + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + } + diag_add(sm, *buf, sum); + } +} + +/* --------------------------------------------------------------------- */ + +static void demod_init_2400(struct sm_state *sm) +{ + struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); + + st->dcd_time = 120; + st->dcd_sum0 = 2; +} + +/* --------------------------------------------------------------------- */ + +const struct modem_tx_info sm_afsk2400_8_tx = { + "afsk2400_8", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, + modulator_2400_u8, modulator_2400_s16, NULL +}; + +const struct modem_rx_info sm_afsk2400_8_rx = { + "afsk2400_8", sizeof(struct demod_state_afsk24), + AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, + demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 +}; + +/* --------------------------------------------------------------------- */ diff --git a/drivers/net/soundmodem/sm_fsk9600.c b/drivers/net/soundmodem/sm_fsk9600.c index 8fbf9d218..bc2fb53b1 100644 --- a/drivers/net/soundmodem/sm_fsk9600.c +++ b/drivers/net/soundmodem/sm_fsk9600.c @@ -45,6 +45,8 @@ struct mod_state_fsk96 { unsigned int shreg; unsigned long scram; unsigned char tx_bit; + unsigned char *txtbl; + unsigned int txphase; }; /* --------------------------------------------------------------------- */ @@ -62,30 +64,57 @@ struct mod_state_fsk96 { /* --------------------------------------------------------------------- */ -static void modulator_9600_4(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_9600_4_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) { struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 4; buflen -= 4) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - cp = fsk96_txfilt_4 + (st->tx_bit & 0xff); - for (j = 0; j < 4; j++, cp += 0x100) - *buf++ = *cp; + + for (; buflen > 0; buflen--) { + if (!st->txphase++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->scram = (st->scram << 1) | (st->scram & 1); + st->scram ^= !(st->shreg & 1); + st->shreg >>= 1; + if (st->scram & (SCRAM_TAP1 << 1)) + st->scram ^= SCRAM_TAPN << 1; + st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); + st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); + } + if (st->txphase >= 4) + st->txphase = 0; + *buf++ = *st->txtbl; + st->txtbl += 0x100; } } /* --------------------------------------------------------------------- */ -static void demodulator_9600_4(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_9600_4_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); + + for (; buflen > 0; buflen--) { + if (!st->txphase++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->scram = (st->scram << 1) | (st->scram & 1); + st->scram ^= !(st->shreg & 1); + st->shreg >>= 1; + if (st->scram & (SCRAM_TAP1 << 1)) + st->scram ^= SCRAM_TAPN << 1; + st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); + st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); + } + if (st->txphase >= 4) + st->txphase = 0; + *buf++ = ((*st->txtbl)-0x80) << 8; + st->txtbl += 0x100; + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_9600_4_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) { struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); static const int pll_corr[2] = { -0x1000, 0x1000 }; @@ -133,30 +162,105 @@ static void demodulator_9600_4(struct sm_state *sm, unsigned char *buf, int bufl /* --------------------------------------------------------------------- */ -static void modulator_9600_5(struct sm_state *sm, unsigned char *buf, int buflen) +static void demodulator_9600_4_s16(struct sm_state *sm, const short *buf, unsigned int buflen) +{ + struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); + static const int pll_corr[2] = { -0x1000, 0x1000 }; + unsigned char curbit; + unsigned int descx; + + for (; buflen > 0; buflen--, buf++) { + st->dcd_shreg <<= 1; + st->bit_pll += 0x4000; + curbit = (*buf >= 0); + if (st->last_sample ^ curbit) { + st->dcd_shreg |= 1; + st->bit_pll += pll_corr[st->bit_pll < 0xa000]; + st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - + !!(st->dcd_shreg & 0x10); + } + st->last_sample = curbit; + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 240; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->descram = (st->descram << 1) | curbit; + descx = st->descram ^ (st->descram >> 1); + descx ^= ((descx >> DESCRAM_TAPSH1) ^ + (descx >> DESCRAM_TAPSH2)); + st->shreg >>= 1; + st->shreg |= (!(descx & 1)) << 16; + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + diag_trigger(sm); + } + diag_add_one(sm, *buf); + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_9600_5_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) { struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 5; buflen -= 5) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - cp = fsk96_txfilt_5 + (st->tx_bit & 0xff); - for (j = 0; j < 5; j++, cp += 0x100) - *buf++ = *cp; + + for (; buflen > 0; buflen--) { + if (!st->txphase++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->scram = (st->scram << 1) | (st->scram & 1); + st->scram ^= !(st->shreg & 1); + st->shreg >>= 1; + if (st->scram & (SCRAM_TAP1 << 1)) + st->scram ^= SCRAM_TAPN << 1; + st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); + st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); + } + if (st->txphase >= 5) + st->txphase = 0; + *buf++ = *st->txtbl; + st->txtbl += 0x100; } } /* --------------------------------------------------------------------- */ -static void demodulator_9600_5(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_9600_5_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); + + for (; buflen > 0; buflen--) { + if (!st->txphase++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->scram = (st->scram << 1) | (st->scram & 1); + st->scram ^= !(st->shreg & 1); + st->shreg >>= 1; + if (st->scram & (SCRAM_TAP1 << 1)) + st->scram ^= SCRAM_TAPN << 1; + st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); + st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); + } + if (st->txphase >= 5) + st->txphase = 0; + *buf++ = ((*st->txtbl)-0x80)<<8; + st->txtbl += 0x100; + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_9600_5_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) { struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); static const int pll_corr[2] = { -0x1000, 0x1000 }; @@ -204,6 +308,54 @@ static void demodulator_9600_5(struct sm_state *sm, unsigned char *buf, int bufl /* --------------------------------------------------------------------- */ +static void demodulator_9600_5_s16(struct sm_state *sm, const short *buf, unsigned int buflen) +{ + struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); + static const int pll_corr[2] = { -0x1000, 0x1000 }; + unsigned char curbit; + unsigned int descx; + + for (; buflen > 0; buflen--, buf++) { + st->dcd_shreg <<= 1; + st->bit_pll += 0x3333; + curbit = (*buf >= 0); + if (st->last_sample ^ curbit) { + st->dcd_shreg |= 1; + st->bit_pll += pll_corr[st->bit_pll < 0x9999]; + st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - + hweight8(st->dcd_shreg & 0x70); + } + st->last_sample = curbit; + hdlcdrv_channelbit(&sm->hdrv, st->last_sample); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 240; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->descram = (st->descram << 1) | curbit; + descx = st->descram ^ (st->descram >> 1); + descx ^= ((descx >> DESCRAM_TAPSH1) ^ + (descx >> DESCRAM_TAPSH2)); + st->shreg >>= 1; + st->shreg |= (!(descx & 1)) << 16; + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + diag_trigger(sm); + } + diag_add_one(sm, *buf); + } +} + +/* --------------------------------------------------------------------- */ + static void demod_init_9600(struct sm_state *sm) { struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); @@ -215,25 +367,25 @@ static void demod_init_9600(struct sm_state *sm) /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_fsk9600_4_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600, 4, - modulator_9600_4, NULL + "fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600, + modulator_9600_4_u8, modulator_9600_4_s16, NULL }; const struct modem_rx_info sm_fsk9600_4_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 4, 4, - demodulator_9600_4, demod_init_9600 + "fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 1, 4, + demodulator_9600_4_u8, demodulator_9600_4_s16, demod_init_9600 }; /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_fsk9600_5_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600, 5, - modulator_9600_5, NULL + "fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600, + modulator_9600_5_u8, modulator_9600_5_s16, NULL }; const struct modem_rx_info sm_fsk9600_5_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 5, 5, - demodulator_9600_5, demod_init_9600 + "fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 1, 5, + demodulator_9600_5_u8, demodulator_9600_5_s16, demod_init_9600 }; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/soundmodem/sm_hapn4800.c b/drivers/net/soundmodem/sm_hapn4800.c index 9472d5e06..f6babcd9d 100644 --- a/drivers/net/soundmodem/sm_hapn4800.c +++ b/drivers/net/soundmodem/sm_hapn4800.c @@ -49,133 +49,290 @@ struct demod_state_hapn48 { unsigned int dcd_shreg; int dcd_sum0, dcd_sum1, dcd_sum2; unsigned int dcd_time; - int inphist[5]; int lvlhi, lvllo; }; struct mod_state_hapn48 { unsigned int shreg; unsigned char tx_bit; + unsigned int tx_seq; + const unsigned char *tbl; }; /* --------------------------------------------------------------------- */ -static void modulator_hapn4800_10(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_hapn4800_10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) { struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 10; buflen -= 10) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - cp = hapn48_txfilt_10 + (st->tx_bit & 0xf); - for (j = 0; j < 10; j++, cp += 0x10) - *buf++ = *cp; + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = ((st->tx_bit << 1) | + (st->tx_bit & 1)); + st->tx_bit ^= (!(st->shreg & 1)); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 10) + st->tx_seq = 0; + *buf = *st->tbl; + st->tbl += 0x10; } } /* --------------------------------------------------------------------- */ -static void modulator_hapn4800_8(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_hapn4800_10_s16(struct sm_state *sm, short *buf, unsigned int buflen) { struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 8; buflen -= 8) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - cp = hapn48_txfilt_8 + (st->tx_bit & 0xf); - for (j = 0; j < 8; j++, cp += 0x10) - *buf++ = *cp; + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = ((st->tx_bit << 1) | + (st->tx_bit & 1)); + st->tx_bit ^= (!(st->shreg & 1)); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 10) + st->tx_seq = 0; + *buf = ((*st->tbl)-0x80)<<8; + st->tbl += 0x10; } } /* --------------------------------------------------------------------- */ -static void modulator_hapn4800_pm10(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_hapn4800_8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) { struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 10; buflen -= 10) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - cp = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); - for (j = 0; j < 10; j++, cp += 0x10) - *buf++ = *cp; + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); + st->tx_bit ^= !(st->shreg & 1); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 8) + st->tx_seq = 0; + *buf = *st->tbl; + st->tbl += 0x10; } } /* --------------------------------------------------------------------- */ -static void modulator_hapn4800_pm8(struct sm_state *sm, unsigned char *buf, int buflen) +static void modulator_hapn4800_8_s16(struct sm_state *sm, short *buf, unsigned int buflen) { struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - int j; - const unsigned char *cp; - - for (; buflen >= 8; buflen -= 8) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - cp = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); - for (j = 0; j < 8; j++, cp += 0x10) - *buf++ = *cp; + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); + st->tx_bit ^= !(st->shreg & 1); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 8) + st->tx_seq = 0; + *buf = ((*st->tbl)-0x80)<<8; + st->tbl += 0x10; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_hapn4800_pm10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) +{ + struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = ((st->tx_bit << 1) | + (st->tx_bit & 1)); + st->tx_bit ^= (!(st->shreg & 1)); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 10) + st->tx_seq = 0; + *buf = *st->tbl; + st->tbl += 0x10; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_hapn4800_pm10_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = ((st->tx_bit << 1) | + (st->tx_bit & 1)); + st->tx_bit ^= (!(st->shreg & 1)); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 10) + st->tx_seq = 0; + *buf = ((*st->tbl)-0x80)<<8; + st->tbl += 0x10; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_hapn4800_pm8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) +{ + struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); + st->tx_bit ^= !(st->shreg & 1); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 8) + st->tx_seq = 0; + *buf = *st->tbl; + st->tbl += 0x10; + } +} + +/* --------------------------------------------------------------------- */ + +static void modulator_hapn4800_pm8_s16(struct sm_state *sm, short *buf, unsigned int buflen) +{ + struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); + + for (; buflen > 0; buflen--, buf++) { + if (!st->tx_seq++) { + if (st->shreg <= 1) + st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; + st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); + st->tx_bit ^= !(st->shreg & 1); + st->shreg >>= 1; + st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); + } + if (st->tx_seq >= 8) + st->tx_seq = 0; + *buf = ((*st->tbl)-0x80)<<8; + st->tbl += 0x10; + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_hapn4800_10_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) +{ + struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); + static const int pll_corr[2] = { -0x800, 0x800 }; + int curst, cursync; + int inv; + + for (; buflen > 0; buflen--, buf++) { + inv = ((int)(buf[-2])-0x80) << 8; + st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ + st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ + if (inv > st->lvlhi) + st->lvlhi = inv; + if (inv < st->lvllo) + st->lvllo = inv; + if (buflen & 1) + st->dcd_shreg <<= 1; + st->bit_pll += 0x199a; + curst = cursync = 0; + if (inv > st->lvlhi >> 1) { + curst = 1; + cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && + buf[-2] > buf[-0] && buf[-2] > buf[-4]); + } else if (inv < st->lvllo >> 1) { + curst = -1; + cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && + buf[-2] < buf[-0] && buf[-2] < buf[-4]); + } + if (cursync) { + st->dcd_shreg |= cursync; + st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu]; + st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - + hweight32(st->dcd_shreg & 0xe739ce70); + } + hdlcdrv_channelbit(&sm->hdrv, cursync); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 240; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->last_bit2 = st->last_bit; + if (curst < 0) + st->last_bit = 0; + else if (curst > 0) + st->last_bit = 1; + st->shreg >>= 1; + st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + diag_trigger(sm); + } + diag_add_one(sm, inv); } } /* --------------------------------------------------------------------- */ -static void demodulator_hapn4800_10(struct sm_state *sm, unsigned char *buf, int buflen) +static void demodulator_hapn4800_10_s16(struct sm_state *sm, const short *buf, unsigned int buflen) { struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); static const int pll_corr[2] = { -0x800, 0x800 }; int curst, cursync; + int inv; for (; buflen > 0; buflen--, buf++) { - st->inphist[4] = st->inphist[3]; - st->inphist[3] = st->inphist[2]; - st->inphist[2] = st->inphist[1]; - st->inphist[1] = st->inphist[0]; - st->inphist[0] = ((int)(*buf)-0x80) << 8; + inv = buf[-2]; st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (st->inphist[2] > st->lvlhi) - st->lvlhi = st->inphist[2]; - if (st->inphist[2] < st->lvllo) - st->lvllo = st->inphist[2]; + if (inv > st->lvlhi) + st->lvlhi = inv; + if (inv < st->lvllo) + st->lvllo = inv; if (buflen & 1) st->dcd_shreg <<= 1; st->bit_pll += 0x199a; curst = cursync = 0; - if (st->inphist[2] > st->lvlhi >> 1) { + if (inv > st->lvlhi >> 1) { curst = 1; - cursync = (st->inphist[2] > st->inphist[1] && - st->inphist[2] > st->inphist[3] && - st->inphist[2] > st->inphist[0] && - st->inphist[2] > st->inphist[4]); - } else if (st->inphist[2] < st->lvllo >> 1) { + cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && + buf[-2] > buf[-0] && buf[-2] > buf[-4]); + } else if (inv < st->lvllo >> 1) { curst = -1; - cursync = (st->inphist[2] < st->inphist[1] && - st->inphist[2] < st->inphist[3] && - st->inphist[2] < st->inphist[0] && - st->inphist[2] < st->inphist[4]); + cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && + buf[-2] < buf[-0] && buf[-2] < buf[-4]); } if (cursync) { st->dcd_shreg |= cursync; @@ -208,46 +365,104 @@ static void demodulator_hapn4800_10(struct sm_state *sm, unsigned char *buf, int } diag_trigger(sm); } - diag_add_one(sm, st->inphist[2]); + diag_add_one(sm, inv); + } +} + +/* --------------------------------------------------------------------- */ + +static void demodulator_hapn4800_8_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) +{ + struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); + static const int pll_corr[2] = { -0x800, 0x800 }; + int curst, cursync; + int inv; + + for (; buflen > 0; buflen--, buf++) { + inv = ((int)(buf[-2])-0x80) << 8; + st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ + st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ + if (inv > st->lvlhi) + st->lvlhi = inv; + if (inv < st->lvllo) + st->lvllo = inv; + if (buflen & 1) + st->dcd_shreg <<= 1; + st->bit_pll += 0x2000; + curst = cursync = 0; + if (inv > st->lvlhi >> 1) { + curst = 1; + cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && + buf[-2] > buf[-0] && buf[-2] > buf[-4]); + } else if (inv < st->lvllo >> 1) { + curst = -1; + cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && + buf[-2] < buf[-0] && buf[-2] < buf[-4]); + } + if (cursync) { + st->dcd_shreg |= cursync; + st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u]; + st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - + hweight32(st->dcd_shreg & 0xbbbbbbbb); + } + hdlcdrv_channelbit(&sm->hdrv, cursync); + if ((--st->dcd_time) <= 0) { + hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + + st->dcd_sum1 + + st->dcd_sum2) < 0); + st->dcd_sum2 = st->dcd_sum1; + st->dcd_sum1 = st->dcd_sum0; + st->dcd_sum0 = 2; /* slight bias */ + st->dcd_time = 240; + } + if (st->bit_pll >= 0x10000) { + st->bit_pll &= 0xffff; + st->last_bit2 = st->last_bit; + if (curst < 0) + st->last_bit = 0; + else if (curst > 0) + st->last_bit = 1; + st->shreg >>= 1; + st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; + if (st->shreg & 1) { + hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); + st->shreg = 0x10000; + } + diag_trigger(sm); + } + diag_add_one(sm, inv); } } /* --------------------------------------------------------------------- */ -static void demodulator_hapn4800_8(struct sm_state *sm, unsigned char *buf, int buflen) +static void demodulator_hapn4800_8_s16(struct sm_state *sm, const short *buf, unsigned int buflen) { struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); static const int pll_corr[2] = { -0x800, 0x800 }; int curst, cursync; + int inv; for (; buflen > 0; buflen--, buf++) { - st->inphist[4] = st->inphist[3]; - st->inphist[3] = st->inphist[2]; - st->inphist[2] = st->inphist[1]; - st->inphist[1] = st->inphist[0]; - st->inphist[0] = ((int)(*buf)-0x80) << 8; + inv = buf[-2]; st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (st->inphist[2] > st->lvlhi) - st->lvlhi = st->inphist[2]; - if (st->inphist[2] < st->lvllo) - st->lvllo = st->inphist[2]; + if (inv > st->lvlhi) + st->lvlhi = inv; + if (inv < st->lvllo) + st->lvllo = inv; if (buflen & 1) st->dcd_shreg <<= 1; st->bit_pll += 0x2000; curst = cursync = 0; - if (st->inphist[2] > st->lvlhi >> 1) { + if (inv > st->lvlhi >> 1) { curst = 1; - cursync = (st->inphist[2] > st->inphist[1] && - st->inphist[2] > st->inphist[3] && - st->inphist[2] > st->inphist[0] && - st->inphist[2] > st->inphist[4]); - } else if (st->inphist[2] < st->lvllo >> 1) { + cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && + buf[-2] > buf[-0] && buf[-2] > buf[-4]); + } else if (inv < st->lvllo >> 1) { curst = -1; - cursync = (st->inphist[2] < st->inphist[1] && - st->inphist[2] < st->inphist[3] && - st->inphist[2] < st->inphist[0] && - st->inphist[2] < st->inphist[4]); + cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && + buf[-2] < buf[-0] && buf[-2] < buf[-4]); } if (cursync) { st->dcd_shreg |= cursync; @@ -280,7 +495,7 @@ static void demodulator_hapn4800_8(struct sm_state *sm, unsigned char *buf, int } diag_trigger(sm); } - diag_add_one(sm, st->inphist[2]); + diag_add_one(sm, inv); } } @@ -297,51 +512,49 @@ static void demod_init_hapn4800(struct sm_state *sm) /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_hapn4800_8_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), - 38400, 4800, 8, modulator_hapn4800_8, NULL + "hapn4800", sizeof(struct mod_state_hapn48), 38400, 4800, + modulator_hapn4800_8_u8, modulator_hapn4800_8_s16, NULL }; const struct modem_rx_info sm_hapn4800_8_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), - 38400, 4800, 8, 8, demodulator_hapn4800_8, demod_init_hapn4800 + "hapn4800", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, + demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 }; /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_hapn4800_10_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), - 48000, 4800, 10, - modulator_hapn4800_10, NULL + "hapn4800", sizeof(struct mod_state_hapn48), 48000, 4800, + modulator_hapn4800_10_u8, modulator_hapn4800_10_s16, NULL }; const struct modem_rx_info sm_hapn4800_10_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), - 48000, 4800, 10, 10, demodulator_hapn4800_10, demod_init_hapn4800 + "hapn4800", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, + demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 }; /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_hapn4800_pm8_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), - 38400, 4800, 8, modulator_hapn4800_pm8, NULL + "hapn4800pm", sizeof(struct mod_state_hapn48), 38400, 4800, + modulator_hapn4800_pm8_u8, modulator_hapn4800_pm8_s16, NULL }; const struct modem_rx_info sm_hapn4800_pm8_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), - 38400, 4800, 8, 8, demodulator_hapn4800_8, demod_init_hapn4800 + "hapn4800pm", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, + demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 }; /* --------------------------------------------------------------------- */ const struct modem_tx_info sm_hapn4800_pm10_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), - 48000, 4800, 10, - modulator_hapn4800_pm10, NULL + "hapn4800pm", sizeof(struct mod_state_hapn48), 48000, 4800, + modulator_hapn4800_pm10_u8, modulator_hapn4800_pm10_s16, NULL }; const struct modem_rx_info sm_hapn4800_pm10_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), - 48000, 4800, 10, 10, demodulator_hapn4800_10, demod_init_hapn4800 + "hapn4800pm", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, + demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 }; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/soundmodem/sm_sbc.c b/drivers/net/soundmodem/sm_sbc.c index 1011dca97..2a2f874aa 100644 --- a/drivers/net/soundmodem/sm_sbc.c +++ b/drivers/net/soundmodem/sm_sbc.c @@ -26,12 +26,14 @@ */ #include +#include #include #include #include #include #include #include "sm.h" +#include "smdma.h" /* --------------------------------------------------------------------- */ @@ -81,12 +83,6 @@ struct sc_state_sbc { unsigned char revhi, revlo; unsigned char fmt[2]; unsigned int sr[2]; - unsigned int dmabuflen; - unsigned char *dmabuf; - unsigned char *dmabuf2; - unsigned char dmabufidx; - unsigned char dma2bufidx; - unsigned char ptt; }; #define SCSTATE ((struct sc_state_sbc *)(&sm->hw)) @@ -136,6 +132,7 @@ struct sc_state_sbc { #define SBC4_OUT8_AI 0xc6 #define SBC4_IN8_AI 0xce #define SBC4_MODE_UNS_MONO 0x00 +#define SBC4_MODE_SIGN_MONO 0x10 #define SBC4_OUT16_AI 0xb6 #define SBC4_IN16_AI 0xbe @@ -260,9 +257,8 @@ static int config_resources(struct device *dev, struct sm_state *sm, int fdx) realdma = inb(DSP_MIXER_DATA(dev->base_addr)); restore_flags(flags); if ((~realirq) & irqreg || (~realdma) & dmareg) { - printk(KERN_ERR "%s: sbc resource registers cannot be set; " - "PnP device and IRQ/DMA specified wrongly?\n", - sm_drvname); + printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device " + "and IRQ/DMA specified wrongly?\n", sm_drvname); return -EINVAL; } return 0; @@ -292,41 +288,31 @@ static void setup_dma_dsp(struct device *dev, struct sm_state *sm, int send) { SBC_HI_INPUT_AUTOINIT, SBC_HI_OUTPUT_AUTOINIT } }; static const unsigned char sbc4mode[2] = { SBC4_IN8_AI, SBC4_OUT8_AI }; - static const unsigned char dmamode[2] = { - DMA_MODE_READ | DMA_MODE_AUTOINIT, DMA_MODE_WRITE | DMA_MODE_AUTOINIT - }; static const unsigned char sbcskr[2] = { SBC_SPEAKER_OFF, SBC_SPEAKER_ON }; - unsigned long dmabufaddr = virt_to_bus(SCSTATE->dmabuf); + unsigned int nsamps; send = !!send; if (!reset_dsp(dev)) { printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); return; } - if ((dmabufaddr & 0xffff) + SCSTATE->dmabuflen > 0x10000) - panic("sm: DMA buffer violates DMA boundary!"); save_flags(flags); cli(); sbc_int_ack_8bit(dev); write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */ write_dsp(dev, SCSTATE->fmt[send]); write_dsp(dev, sbcskr[send]); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, dmamode[send]); - set_dma_addr(dev->dma, dmabufaddr); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - enable_dma(dev->dma); + nsamps = dma_setup(sm, send, dev->dma) - 1; sbc_int_ack_8bit(dev); if (SCSTATE->revhi >= 4) { write_dsp(dev, sbc4mode[send]); write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + write_dsp(dev, nsamps & 0xff); + write_dsp(dev, nsamps >> 8); } else { write_dsp(dev, SBC_BLOCKSIZE); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + write_dsp(dev, nsamps & 0xff); + write_dsp(dev, nsamps >> 8); write_dsp(dev, sbcmode[SCSTATE->fmt[send] >= 180][send]); /* hispeed mode if sample rate > 13kHz */ } @@ -339,53 +325,41 @@ static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)dev_id; struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char new_ptt; - unsigned char *buf; + unsigned int curfrag; if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) return; - new_ptt = hdlcdrv_ptt(&sm->hdrv); + cli(); sbc_int_ack_8bit(dev); - buf = SCSTATE->dmabuf; - if (SCSTATE->dmabufidx) - buf += SCSTATE->dmabuflen/2; - SCSTATE->dmabufidx = !SCSTATE->dmabufidx; + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag); + enable_dma(dev->dma); sm_int_freq(sm); sti(); - if (new_ptt && !SCSTATE->ptt) { - /* starting to transmit */ - disable_dma(dev->dma); - SCSTATE->dmabufidx = 0; - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf, SCSTATE->dmabuflen/2)); - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, SCSTATE->dmabuf, - SCSTATE->dmabuflen/2)); - setup_dma_dsp(dev, sm, 1); - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, SCSTATE->dmabuf + - SCSTATE->dmabuflen/2, - SCSTATE->dmabuflen/2)); - } else if (SCSTATE->ptt == 1 && !new_ptt) { + if (sm->dma.ptt_cnt <= 0) { + dma_receive(sm, curfrag); + if (hdlcdrv_ptt(&sm->hdrv)) { + /* starting to transmit */ + disable_dma(dev->dma); + dma_start_transmit(sm); + setup_dma_dsp(dev, sm, 1); + dma_transmit(sm); + } + } else if (dma_end_transmit(sm, curfrag)) { /* stopping transmission */ disable_dma(dev->dma); - SCSTATE->dmabufidx = 0; + sti(); + dma_init_receive(sm); setup_dma_dsp(dev, sm, 0); - SCSTATE->ptt = 0; - } else if (SCSTATE->ptt) { - SCSTATE->ptt--; - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, buf, SCSTATE->dmabuflen/2)); } else { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf, SCSTATE->dmabuflen/2)); + dma_transmit(sm); hdlcdrv_arbitrate(dev, &sm->hdrv); } - if (new_ptt) - SCSTATE->ptt = 2; sm_output_status(sm); hdlcdrv_transmitter(dev, &sm->hdrv); hdlcdrv_receiver(dev, &sm->hdrv); + } /* --------------------------------------------------------------------- */ @@ -393,6 +367,7 @@ static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs) static int sbc_open(struct device *dev, struct sm_state *sm) { int err; + unsigned int dmasz, u; if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) { printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", @@ -409,12 +384,17 @@ static int sbc_open(struct device *dev, struct sm_state *sm) /* * check if a card is available */ - if (!reset_dsp(dev)) + if (!reset_dsp(dev)) { + printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", + sm_drvname, dev->base_addr); return -ENODEV; + } write_dsp(dev, SBC_GET_REVISION); if (!read_dsp(dev, &SCSTATE->revhi) || !read_dsp(dev, &SCSTATE->revlo)) return -ENODEV; + printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, + SCSTATE->revhi, SCSTATE->revlo); if (SCSTATE->revhi < 2) { printk(KERN_ERR "%s: your card is an antiquity, at least DSP " "rev 2.00 required\n", sm_drvname); @@ -435,9 +415,19 @@ static int sbc_open(struct device *dev, struct sm_state *sm) /* * initialize some variables */ - if (!(SCSTATE->dmabuf = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) + dma_init_receive(sm); + dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; + if (sm->dma.i16bit) + dmasz <<= 1; + u = NUM_FRAGMENTS * sm->dma.ofragsz; + if (sm->dma.o16bit) + u <<= 1; + if (u > dmasz) + dmasz = u; + if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) return -ENOMEM; - SCSTATE->dmabufidx = SCSTATE->ptt = 0; + dma_init_transmit(sm); + dma_init_receive(sm); memset(&sm->m, 0, sizeof(sm->m)); memset(&sm->d, 0, sizeof(sm->d)); @@ -447,13 +437,13 @@ static int sbc_open(struct device *dev, struct sm_state *sm) sm->mode_rx->init(sm); if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree_s(sm->dma.obuf, dmasz); return -EBUSY; } if (request_irq(dev->irq, sbc_interrupt, SA_INTERRUPT, sm->hwdrv->hw_name, dev)) { free_dma(dev->dma); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree_s(sm->dma.obuf, dmasz); return -EBUSY; } request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name); @@ -475,7 +465,7 @@ static int sbc_close(struct device *dev, struct sm_state *sm) free_irq(dev->irq, dev); free_dma(dev->dma); release_region(dev->base_addr, SBC_EXTENT); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree(sm->dma.obuf); return 0; } @@ -486,7 +476,6 @@ static int sbc_sethw(struct device *dev, struct sm_state *sm, char *mode) char *cp = strchr(mode, '.'); const struct modem_tx_info **mtp = sm_modem_tx_table; const struct modem_rx_info **mrp; - int dv; if (!strcmp(mode, "off")) { sm->mode_tx = NULL; @@ -507,12 +496,16 @@ static int sbc_sethw(struct device *dev, struct sm_state *sm, char *mode) continue; if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100) continue; + if (!(*mtp)->modulator_u8) + continue; for (mrp = sm_modem_rx_table; *mrp; mrp++) { if ((*mrp)->loc_storage > sizeof(sm->d)) { printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", sm_drvname, (*mrp)->name, (*mrp)->loc_storage); continue; } + if (!(*mrp)->demodulator_u8) + continue; if ((*mrp)->name && !strcmp((*mrp)->name, cp) && (*mrp)->srate >= 5000 && (*mrp)->srate <= 44100) { sm->mode_tx = *mtp; @@ -521,11 +514,11 @@ static int sbc_sethw(struct device *dev, struct sm_state *sm, char *mode) sm->mode_rx->srate); SCSTATE->fmt[1] = 256-((1000000L+sm->mode_tx->srate/2)/ sm->mode_tx->srate); - dv = lcm(sm->mode_tx->dmabuflenmodulo, - sm->mode_rx->dmabuflenmodulo); - SCSTATE->dmabuflen = sm->mode_rx->srate/100+dv-1; - SCSTATE->dmabuflen /= dv; - SCSTATE->dmabuflen *= 2*dv; /* make sure DMA buf is even */ + sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; + sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; + if (sm->dma.ifragsz < sm->mode_rx->overlap) + sm->dma.ifragsz = sm->mode_rx->overlap; + sm->dma.i16bit = sm->dma.o16bit = 0; return 0; } } @@ -633,50 +626,61 @@ const struct hardware_info sm_hw_sbc = { static void setup_dma_fdx_dsp(struct device *dev, struct sm_state *sm) { unsigned long flags; - unsigned long dmabufaddr = virt_to_bus(SCSTATE->dmabuf); - unsigned long dmabuf2addr = virt_to_bus(SCSTATE->dmabuf2); + unsigned int isamps, osamps; if (!reset_dsp(dev)) { printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); return; } - if (((dmabufaddr & 0xffff) + SCSTATE->dmabuflen > 0x10000) || - ((dmabuf2addr & 0xffff) + 2*(SCSTATE->dmabuflen) > 0x10000)) - panic("sm: DMA buffer violates DMA boundary!"); save_flags(flags); cli(); sbc_int_ack_8bit(dev); sbc_int_ack_16bit(dev); /* should eventually change to set rates individually by SBC_SAMPLE_RATE_{IN/OUT} */ - write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */ - write_dsp(dev, SCSTATE->fmt[0]); + write_dsp(dev, SBC_SAMPLE_RATE_IN); + write_dsp(dev, SCSTATE->sr[0] >> 8); + write_dsp(dev, SCSTATE->sr[0] & 0xff); + write_dsp(dev, SBC_SAMPLE_RATE_OUT); + write_dsp(dev, SCSTATE->sr[1] >> 8); + write_dsp(dev, SCSTATE->sr[1] & 0xff); write_dsp(dev, SBC_SPEAKER_ON); - /* - * DMA channel 1 (8bit) does input (capture), - * DMA channel 2 (16bit) does output (playback) - */ - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->dma, dmabufaddr); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - set_dma_mode(sm->hdrv.ptt_out.dma2, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(sm->hdrv.ptt_out.dma2, dmabuf2addr); - set_dma_count(sm->hdrv.ptt_out.dma2, SCSTATE->dmabuflen); - enable_dma(dev->dma); - enable_dma(sm->hdrv.ptt_out.dma2); - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC4_IN8_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); - write_dsp(dev, SBC4_OUT16_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_dsp(dev, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + if (sm->dma.o16bit) { + /* + * DMA channel 1 (8bit) does input (capture), + * DMA channel 2 (16bit) does output (playback) + */ + isamps = dma_setup(sm, 0, dev->dma) - 1; + osamps = dma_setup(sm, 1, sm->hdrv.ptt_out.dma2) - 1; + sbc_int_ack_8bit(dev); + sbc_int_ack_16bit(dev); + write_dsp(dev, SBC4_IN8_AI); + write_dsp(dev, SBC4_MODE_UNS_MONO); + write_dsp(dev, isamps & 0xff); + write_dsp(dev, isamps >> 8); + write_dsp(dev, SBC4_OUT16_AI); + write_dsp(dev, SBC4_MODE_SIGN_MONO); + write_dsp(dev, osamps & 0xff); + write_dsp(dev, osamps >> 8); + } else { + /* + * DMA channel 1 (8bit) does output (playback), + * DMA channel 2 (16bit) does input (capture) + */ + isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; + osamps = dma_setup(sm, 1, dev->dma) - 1; + sbc_int_ack_8bit(dev); + sbc_int_ack_16bit(dev); + write_dsp(dev, SBC4_OUT8_AI); + write_dsp(dev, SBC4_MODE_UNS_MONO); + write_dsp(dev, osamps & 0xff); + write_dsp(dev, osamps >> 8); + write_dsp(dev, SBC4_IN16_AI); + write_dsp(dev, SBC4_MODE_SIGN_MONO); + write_dsp(dev, isamps & 0xff); + write_dsp(dev, isamps >> 8); + } + dma_init_receive(sm); + dma_init_transmit(sm); restore_flags(flags); } @@ -686,41 +690,58 @@ static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)dev_id; struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char *buf; - unsigned char *buf2; - unsigned char intsrc; + unsigned char intsrc, pbint = 0, captint = 0; + unsigned int ocfrag, icfrag; + unsigned long flags; if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) return; - buf = SCSTATE->dmabuf; - buf2 = SCSTATE->dmabuf2; + save_flags(flags); + cli(); outb(0x82, DSP_MIXER_ADDR(dev->base_addr)); intsrc = inb(DSP_MIXER_DATA(dev->base_addr)); if (intsrc & 0x01) { sbc_int_ack_8bit(dev); - if (SCSTATE->dmabufidx) - buf += SCSTATE->dmabuflen/2; - SCSTATE->dmabufidx = !SCSTATE->dmabufidx; + if (sm->dma.o16bit) { + captint = 1; + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + dma_ptr(sm, 0, dev->dma, &icfrag); + enable_dma(dev->dma); + } else { + pbint = 1; + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + dma_ptr(sm, 1, dev->dma, &ocfrag); + enable_dma(dev->dma); + } } if (intsrc & 0x02) { sbc_int_ack_16bit(dev); - if (SCSTATE->dma2bufidx) - buf2 += SCSTATE->dmabuflen/2; - SCSTATE->dma2bufidx = !SCSTATE->dma2bufidx; + if (sm->dma.o16bit) { + pbint = 1; + disable_dma(sm->hdrv.ptt_out.dma2); + clear_dma_ff(sm->hdrv.ptt_out.dma2); + dma_ptr(sm, 1, sm->hdrv.ptt_out.dma2, &ocfrag); + enable_dma(sm->hdrv.ptt_out.dma2); + } else { + captint = 1; + disable_dma(sm->hdrv.ptt_out.dma2); + clear_dma_ff(sm->hdrv.ptt_out.dma2); + dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag); + enable_dma(sm->hdrv.ptt_out.dma2); + } } + restore_flags(flags); sm_int_freq(sm); sti(); - if (intsrc & 0x02) { - if ((SCSTATE->ptt = hdlcdrv_ptt(&sm->hdrv))) - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, buf2, SCSTATE->dmabuflen/2)); - else - time_exec(sm->debug_vals.mod_cyc, - memset(buf2, 0x80, SCSTATE->dmabuflen/2)); + if (pbint) { + if (dma_end_transmit(sm, ocfrag)) + dma_clear_transmit(sm); + dma_transmit(sm); } - if (intsrc & 0x01) { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf, SCSTATE->dmabuflen/2)); + if (captint) { + dma_receive(sm, icfrag); hdlcdrv_arbitrate(dev, &sm->hdrv); } sm_output_status(sm); @@ -749,12 +770,17 @@ static int sbcfdx_open(struct device *dev, struct sm_state *sm) /* * check if a card is available */ - if (!reset_dsp(dev)) + if (!reset_dsp(dev)) { + printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", + sm_drvname, dev->base_addr); return -ENODEV; + } write_dsp(dev, SBC_GET_REVISION); if (!read_dsp(dev, &SCSTATE->revhi) || !read_dsp(dev, &SCSTATE->revlo)) return -ENODEV; + printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, + SCSTATE->revhi, SCSTATE->revlo); if (SCSTATE->revhi < 4) { printk(KERN_ERR "%s: at least DSP rev 4.00 required\n", sm_drvname); return -ENODEV; @@ -766,13 +792,14 @@ static int sbcfdx_open(struct device *dev, struct sm_state *sm) /* * initialize some variables */ - if (!(SCSTATE->dmabuf = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) + if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) return -ENOMEM; - if (!(SCSTATE->dmabuf2 = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { + kfree(sm->dma.ibuf); return -ENOMEM; } - SCSTATE->dmabufidx = SCSTATE->dma2bufidx = SCSTATE->ptt = 0; + dma_init_transmit(sm); + dma_init_receive(sm); memset(&sm->m, 0, sizeof(sm->m)); memset(&sm->d, 0, sizeof(sm->d)); @@ -782,20 +809,20 @@ static int sbcfdx_open(struct device *dev, struct sm_state *sm) sm->mode_rx->init(sm); if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); return -EBUSY; } if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); free_dma(dev->dma); return -EBUSY; } if (request_irq(dev->irq, sbcfdx_interrupt, SA_INTERRUPT, sm->hwdrv->hw_name, dev)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); free_dma(dev->dma); free_dma(sm->hdrv.ptt_out.dma2); return -EBUSY; @@ -821,8 +848,8 @@ static int sbcfdx_close(struct device *dev, struct sm_state *sm) free_dma(dev->dma); free_dma(sm->hdrv.ptt_out.dma2); release_region(dev->base_addr, SBC_EXTENT); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); return 0; } @@ -833,7 +860,6 @@ static int sbcfdx_sethw(struct device *dev, struct sm_state *sm, char *mode) char *cp = strchr(mode, '.'); const struct modem_tx_info **mtp = sm_modem_tx_table; const struct modem_rx_info **mrp; - int dv; if (!strcmp(mode, "off")) { sm->mode_tx = NULL; @@ -867,13 +893,25 @@ static int sbcfdx_sethw(struct device *dev, struct sm_state *sm, char *mode) sm->mode_rx = *mrp; SCSTATE->sr[0] = sm->mode_rx->srate; SCSTATE->sr[1] = sm->mode_tx->srate; - dv = lcm(sm->mode_tx->dmabuflenmodulo, - sm->mode_rx->dmabuflenmodulo); - if (dv & 1) - dv <<= 1; /* dmabuflen must be a multiple of 4 */ - SCSTATE->dmabuflen = sm->mode_rx->srate/100+dv-1; - SCSTATE->dmabuflen /= dv; - SCSTATE->dmabuflen *= 2*dv; /* make sure DMA buf is even */ + sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; + sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; + if (sm->dma.ifragsz < sm->mode_rx->overlap) + sm->dma.ifragsz = sm->mode_rx->overlap; + if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_u8) { + sm->dma.i16bit = 1; + sm->dma.o16bit = 0; + sm->dma.ifragsz <<= 1; + } else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_s16) { + sm->dma.i16bit = 0; + sm->dma.o16bit = 1; + sm->dma.ofragsz <<= 1; + } else { + printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, + sm->mode_rx->name, sm->mode_tx->name); + sm->mode_tx = NULL; + sm->mode_rx = NULL; + return -EINVAL; + } return 0; } } diff --git a/drivers/net/soundmodem/sm_wss.c b/drivers/net/soundmodem/sm_wss.c index 0123a9aa4..021ecc165 100644 --- a/drivers/net/soundmodem/sm_wss.c +++ b/drivers/net/soundmodem/sm_wss.c @@ -26,12 +26,14 @@ */ #include +#include #include #include #include #include #include #include "sm.h" +#include "smdma.h" /* --------------------------------------------------------------------- */ @@ -81,12 +83,6 @@ struct sc_state_wss { unsigned char revwss, revid, revv, revcid; unsigned char fmt[2]; unsigned char crystal; - unsigned int dmabuflen; - unsigned char *dmabuf; - unsigned char dmabufidx; - unsigned char ptt; - /* Full Duplex extensions */ - unsigned char *dmabuf2; }; #define SCSTATE ((struct sc_state_wss *)(&sm->hw)) @@ -156,8 +152,8 @@ static int wss_srate_index(int srate) /* --------------------------------------------------------------------- */ -static int wss_set_codec_fmt(struct device *dev, struct sm_state *sm, - unsigned char fmt, char fdx, char fullcalib) +static int wss_set_codec_fmt(struct device *dev, struct sm_state *sm, unsigned char fmt, + unsigned char fmt2, char fdx, char fullcalib) { unsigned long time; unsigned long flags; @@ -167,7 +163,7 @@ static int wss_set_codec_fmt(struct device *dev, struct sm_state *sm, /* Clock and data format register */ write_codec(dev, 0x48, fmt); if (SCSTATE->crystal) { - write_codec(dev, 0x5c, fmt & 0xf0); + write_codec(dev, 0x5c, fmt2 & 0xf0); /* MCE and interface config reg */ write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0)); } else @@ -306,7 +302,7 @@ static int wss_init_codec(struct device *dev, struct sm_state *sm, char fdx, write_codec(dev, 0x1d, 0x00); /* right out no att */ } - if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], fdx, 1)) + if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], SCSTATE->fmt[0], fdx, 1)) goto codec_err; write_codec(dev, 0, reg0); /* left input control */ @@ -345,18 +341,14 @@ static void setup_dma_wss(struct device *dev, struct sm_state *sm, int send) { unsigned long flags; static const unsigned char codecmode[2] = { 0x0e, 0x0d }; - static const unsigned char dmamode[2] = { - DMA_MODE_READ | DMA_MODE_AUTOINIT, - DMA_MODE_WRITE | DMA_MODE_AUTOINIT - }; unsigned char oldcodecmode; long abrt; - unsigned long dmabufaddr = virt_to_bus(SCSTATE->dmabuf); + unsigned char fmt; + unsigned int numsamps; - if ((dmabufaddr & 0xffffu) + SCSTATE->dmabuflen > 0x10000) - panic("%s: DMA buffer violates DMA boundary!", sm_drvname); send = !!send; - save_flags(flags); + fmt = SCSTATE->fmt[send]; + save_flags(flags); cli(); /* * perform the final DMA sequence to disable the codec request @@ -365,28 +357,18 @@ static void setup_dma_wss(struct device *dev, struct sm_state *sm, int send) write_codec(dev, 9, 0xc); /* disable codec */ wss_ack_int(dev); if (read_codec(dev, 11) & 0x10) { - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, dmamode[oldcodecmode & 1]); - set_dma_addr(dev->dma, dmabufaddr); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - enable_dma(dev->dma); + dma_setup(sm, oldcodecmode & 1, dev->dma); abrt = 0; while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000)); } - disable_dma(dev->dma); - if (read_codec(dev, 0x8) != SCSTATE->fmt[send]) - wss_set_codec_fmt(dev, sm, SCSTATE->fmt[send], 0, 0); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, dmamode[send]); - set_dma_addr(dev->dma, dmabufaddr); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - enable_dma(dev->dma); - write_codec(dev, 15, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_codec(dev, 14, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + if (read_codec(dev, 0x8) != fmt) + wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0); + numsamps = dma_setup(sm, send, dev->dma) - 1; + write_codec(dev, 15, numsamps & 0xff); + write_codec(dev, 14, numsamps >> 8); if (SCSTATE->crystal) { - write_codec(dev, 31, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_codec(dev, 30, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + write_codec(dev, 31, numsamps & 0xff); + write_codec(dev, 30, numsamps >> 8); } write_codec(dev, 9, codecmode[send]); restore_flags(flags); @@ -398,74 +380,45 @@ static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)dev_id; struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char new_ptt; - unsigned char *buf; - int dmares; + unsigned int curfrag; + unsigned int nums; if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || sm->hdrv.magic != HDLCDRV_MAGIC) return; - new_ptt = hdlcdrv_ptt(&sm->hdrv); cli(); wss_ack_int(dev); disable_dma(dev->dma); clear_dma_ff(dev->dma); - dmares = get_dma_residue(dev->dma); - if (dmares <= 0) - dmares = SCSTATE->dmabuflen; - buf = SCSTATE->dmabuf; - if (dmares > SCSTATE->dmabuflen/2) { - buf += SCSTATE->dmabuflen/2; - dmares -= SCSTATE->dmabuflen/2; - } -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || - dmares < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = dmares; -#endif /* SM_DEBUG */ - dmares--; - write_codec(dev, 15, dmares & 0xff); - write_codec(dev, 14, dmares >> 8); + nums = dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag) - 1; + write_codec(dev, 15, nums & 0xff); + write_codec(dev, 14, nums >> 8); if (SCSTATE->crystal) { - write_codec(dev, 31, dmares & 0xff); - write_codec(dev, 30, dmares >> 8); + write_codec(dev, 31, nums & 0xff); + write_codec(dev, 30, nums >> 8); } enable_dma(dev->dma); sm_int_freq(sm); sti(); - if (new_ptt && !SCSTATE->ptt) { - /* starting to transmit */ - disable_dma(dev->dma); - sti(); - SCSTATE->dmabufidx = 0; - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf, SCSTATE->dmabuflen/2)); - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, SCSTATE->dmabuf, - SCSTATE->dmabuflen/2)); - setup_dma_wss(dev, sm, 1); - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, SCSTATE->dmabuf + - SCSTATE->dmabuflen/2, - SCSTATE->dmabuflen/2)); - } else if (SCSTATE->ptt == 1 && !new_ptt) { + if (sm->dma.ptt_cnt <= 0) { + dma_receive(sm, curfrag); + if (hdlcdrv_ptt(&sm->hdrv)) { + /* starting to transmit */ + disable_dma(dev->dma); + dma_start_transmit(sm); + setup_dma_wss(dev, sm, 1); + dma_transmit(sm); + } + } else if (dma_end_transmit(sm, curfrag)) { /* stopping transmission */ disable_dma(dev->dma); sti(); - SCSTATE->dmabufidx = 0; + dma_init_receive(sm); setup_dma_wss(dev, sm, 0); - SCSTATE->ptt = 0; - } else if (SCSTATE->ptt) { - SCSTATE->ptt--; - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, buf, SCSTATE->dmabuflen/2)); } else { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf, SCSTATE->dmabuflen/2)); + dma_transmit(sm); hdlcdrv_arbitrate(dev, &sm->hdrv); } - if (new_ptt) - SCSTATE->ptt = 2; sm_output_status(sm); hdlcdrv_transmitter(dev, &sm->hdrv); hdlcdrv_receiver(dev, &sm->hdrv); @@ -475,6 +428,8 @@ static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs) static int wss_open(struct device *dev, struct sm_state *sm) { + unsigned int dmasz, u; + if (sizeof(sm->m) < sizeof(struct sc_state_wss)) { printk(KERN_ERR "sm wss: wss state too big: %d > %d\n", sizeof(struct sc_state_wss), sizeof(sm->m)); @@ -495,9 +450,19 @@ static int wss_open(struct device *dev, struct sm_state *sm) /* * initialize some variables */ - if (!(SCSTATE->dmabuf = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) + dma_init_receive(sm); + dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; + if (sm->dma.i16bit) + dmasz <<= 1; + u = NUM_FRAGMENTS * sm->dma.ofragsz; + if (sm->dma.o16bit) + u <<= 1; + if (u > dmasz) + dmasz = u; + if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) return -ENOMEM; - SCSTATE->dmabufidx = SCSTATE->ptt = 0; + dma_init_transmit(sm); + dma_init_receive(sm); memset(&sm->m, 0, sizeof(sm->m)); memset(&sm->d, 0, sizeof(sm->d)); @@ -507,13 +472,13 @@ static int wss_open(struct device *dev, struct sm_state *sm) sm->mode_rx->init(sm); if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree_s(sm->dma.obuf, dmasz); return -EBUSY; } if (request_irq(dev->irq, wss_interrupt, SA_INTERRUPT, sm->hwdrv->hw_name, dev)) { free_dma(dev->dma); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree_s(sm->dma.obuf, dmasz); return -EBUSY; } request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name); @@ -535,7 +500,7 @@ static int wss_close(struct device *dev, struct sm_state *sm) free_irq(dev->irq, dev); free_dma(dev->dma); release_region(dev->base_addr, WSS_EXTENT); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + kfree(sm->dma.obuf); return 0; } @@ -546,7 +511,7 @@ static int wss_sethw(struct device *dev, struct sm_state *sm, char *mode) char *cp = strchr(mode, '.'); const struct modem_tx_info **mtp = sm_modem_tx_table; const struct modem_rx_info **mrp; - int i, j, dv; + int i, j; if (!strcmp(mode, "off")) { sm->mode_tx = NULL; @@ -579,11 +544,57 @@ static int wss_sethw(struct device *dev, struct sm_state *sm, char *mode) sm->mode_rx = *mrp; SCSTATE->fmt[0] = j; SCSTATE->fmt[1] = i; - dv = lcm(sm->mode_tx->dmabuflenmodulo, - sm->mode_rx->dmabuflenmodulo); - SCSTATE->dmabuflen = sm->mode_rx->srate/100+dv-1; - SCSTATE->dmabuflen /= dv; - SCSTATE->dmabuflen *= 2*dv; /* make sure DMA buf is even */ + sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; + sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; + if (sm->dma.ifragsz < sm->mode_rx->overlap) + sm->dma.ifragsz = sm->mode_rx->overlap; + /* prefer same data format if possible to minimize switching times */ + sm->dma.i16bit = sm->dma.o16bit = 2; + if (sm->mode_rx->srate == sm->mode_tx->srate) { + if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_s16) + sm->dma.i16bit = sm->dma.o16bit = 1; + else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_u8) + sm->dma.i16bit = sm->dma.o16bit = 0; + } + if (sm->dma.i16bit == 2) { + if (sm->mode_rx->demodulator_s16) + sm->dma.i16bit = 1; + else if (sm->mode_rx->demodulator_u8) + sm->dma.i16bit = 0; + } + if (sm->dma.o16bit == 2) { + if (sm->mode_tx->modulator_s16) + sm->dma.o16bit = 1; + else if (sm->mode_tx->modulator_u8) + sm->dma.o16bit = 0; + } + if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { + printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, + sm->mode_rx->name, sm->mode_tx->name); + sm->mode_tx = NULL; + sm->mode_rx = NULL; + return -EINVAL; + } +#ifdef __BIG_ENDIAN + /* big endian 16bit only works on crystal cards... */ + if (sm->dma.i16bit) { + SCSTATE->fmt[0] |= 0xc0; + sm->dma.ifragsz <<= 1; + } + if (sm->dma.o16bit) { + SCSTATE->fmt[1] |= 0xc0; + sm->dma.ofragsz <<= 1; + } +#else /* __BIG_ENDIAN */ + if (sm->dma.i16bit) { + SCSTATE->fmt[0] |= 0x40; + sm->dma.ifragsz <<= 1; + } + if (sm->dma.o16bit) { + SCSTATE->fmt[1] |= 0x40; + sm->dma.ofragsz <<= 1; + } +#endif /* __BIG_ENDIAN */ return 0; } } @@ -663,12 +674,8 @@ static void setup_fdx_dma_wss(struct device *dev, struct sm_state *sm) unsigned long flags; unsigned char oldcodecmode, codecdma; long abrt; - unsigned long dmabufaddr1 = virt_to_bus(SCSTATE->dmabuf); - unsigned long dmabufaddr2 = virt_to_bus(SCSTATE->dmabuf2); - - if (((dmabufaddr1 & 0xffffu) + SCSTATE->dmabuflen > 0x10000) || - ((dmabufaddr2 & 0xffffu) + SCSTATE->dmabuflen > 0x10000)) - panic("%s: DMA buffer violates DMA boundary!", sm_drvname); + unsigned int osamps, isamps; + save_flags(flags); cli(); /* @@ -678,39 +685,19 @@ static void setup_fdx_dma_wss(struct device *dev, struct sm_state *sm) write_codec(dev, 9, 0); /* disable codec DMA */ wss_ack_int(dev); if ((codecdma = read_codec(dev, 11)) & 0x10) { - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->dma, dmabufaddr1); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - set_dma_mode(sm->hdrv.ptt_out.dma2, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(sm->hdrv.ptt_out.dma2, dmabufaddr2); - set_dma_count(sm->hdrv.ptt_out.dma2, SCSTATE->dmabuflen); - enable_dma(dev->dma); - enable_dma(sm->hdrv.ptt_out.dma2); + dma_setup(sm, 1, dev->dma); + dma_setup(sm, 0, sm->hdrv.ptt_out.dma2); abrt = 0; - while (((codecdma = read_codec(dev, 11)) & 0x10) || - ((++abrt) >= 0x10000)); + while (((codecdma = read_codec(dev, 11)) & 0x10) || ((++abrt) >= 0x10000)); } - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->dma, dmabufaddr1); - set_dma_count(dev->dma, SCSTATE->dmabuflen); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - set_dma_mode(sm->hdrv.ptt_out.dma2, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(sm->hdrv.ptt_out.dma2, dmabufaddr2); - set_dma_count(sm->hdrv.ptt_out.dma2, SCSTATE->dmabuflen); - enable_dma(dev->dma); - enable_dma(sm->hdrv.ptt_out.dma2); - write_codec(dev, 15, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_codec(dev, 14, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + wss_set_codec_fmt(dev, sm, SCSTATE->fmt[1], SCSTATE->fmt[0], 1, 1); + osamps = dma_setup(sm, 1, dev->dma) - 1; + isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; + write_codec(dev, 15, osamps & 0xff); + write_codec(dev, 14, osamps >> 8); if (SCSTATE->crystal) { - write_codec(dev, 31, ((SCSTATE->dmabuflen >> 1) - 1) & 0xff); - write_codec(dev, 30, ((SCSTATE->dmabuflen >> 1) - 1) >> 8); + write_codec(dev, 31, isamps & 0xff); + write_codec(dev, 30, isamps >> 8); } write_codec(dev, 9, 3); restore_flags(flags); @@ -722,68 +709,74 @@ static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)dev_id; struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char *buf1; - unsigned char *buf2; unsigned long flags; - int dmares1, dmares2; + unsigned char cry_int_src; + unsigned icfrag, ocfrag, isamps, osamps; if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || sm->hdrv.magic != HDLCDRV_MAGIC) return; save_flags(flags); cli(); - if (SCSTATE->crystal && (!(read_codec(dev, 0x18) & 0x20))) { - /* only regard Crystal Playback interrupts! */ + if (SCSTATE->crystal) { + /* Crystal has an essentially different interrupt handler! */ + cry_int_src = read_codec(dev, 0x18); wss_ack_int(dev); + if (cry_int_src & 0x10) { /* playback interrupt */ + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; + write_codec(dev, 15, osamps & 0xff); + write_codec(dev, 14, osamps >> 8); + enable_dma(dev->dma); + } + if (cry_int_src & 0x20) { /* capture interrupt */ + disable_dma(sm->hdrv.ptt_out.dma2); + clear_dma_ff(sm->hdrv.ptt_out.dma2); + isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; + write_codec(dev, 31, isamps & 0xff); + write_codec(dev, 30, isamps >> 8); + enable_dma(sm->hdrv.ptt_out.dma2); + } + restore_flags(flags); + sm_int_freq(sm); + sti(); + if (cry_int_src & 0x10) { + if (dma_end_transmit(sm, ocfrag)) + dma_clear_transmit(sm); + dma_transmit(sm); + } + if (cry_int_src & 0x20) { + dma_receive(sm, icfrag); + hdlcdrv_arbitrate(dev, &sm->hdrv); + } + sm_output_status(sm); + hdlcdrv_transmitter(dev, &sm->hdrv); + hdlcdrv_receiver(dev, &sm->hdrv); return; } wss_ack_int(dev); disable_dma(dev->dma); disable_dma(sm->hdrv.ptt_out.dma2); clear_dma_ff(dev->dma); - dmares1 = get_dma_residue(dev->dma); clear_dma_ff(sm->hdrv.ptt_out.dma2); - dmares2 = get_dma_residue(sm->hdrv.ptt_out.dma2); - if (dmares1 <= 0) - dmares1 = SCSTATE->dmabuflen; - buf1 = SCSTATE->dmabuf; - if (dmares1 > SCSTATE->dmabuflen/2) { - buf1 += SCSTATE->dmabuflen/2; - dmares1 -= SCSTATE->dmabuflen/2; - } - if (dmares2 <= 0) - dmares2 = SCSTATE->dmabuflen; - buf2 = SCSTATE->dmabuf2; - if (dmares2 > SCSTATE->dmabuflen/2) { - buf2 += SCSTATE->dmabuflen/2; - dmares2 -= SCSTATE->dmabuflen/2; - } -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || - dmares1 < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = dmares1; -#endif /* SM_DEBUG */ - dmares1--; - dmares2--; - write_codec(dev, 15, dmares1 & 0xff); - write_codec(dev, 14, dmares1 >> 8); + osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; + isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; + write_codec(dev, 15, osamps & 0xff); + write_codec(dev, 14, osamps >> 8); if (SCSTATE->crystal) { - write_codec(dev, 31, dmares2 & 0xff); - write_codec(dev, 30, dmares2 >> 8); + write_codec(dev, 31, isamps & 0xff); + write_codec(dev, 30, isamps >> 8); } enable_dma(dev->dma); enable_dma(sm->hdrv.ptt_out.dma2); restore_flags(flags); sm_int_freq(sm); sti(); - if ((SCSTATE->ptt = hdlcdrv_ptt(&sm->hdrv))) - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator(sm, buf1, SCSTATE->dmabuflen/2)); - else - time_exec(sm->debug_vals.mod_cyc, - memset(buf1, 0x80, SCSTATE->dmabuflen/2)); - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator(sm, buf2, SCSTATE->dmabuflen/2)); + if (dma_end_transmit(sm, ocfrag)) + dma_clear_transmit(sm); + dma_transmit(sm); + dma_receive(sm, icfrag); hdlcdrv_arbitrate(dev, &sm->hdrv); sm_output_status(sm); hdlcdrv_transmitter(dev, &sm->hdrv); @@ -809,13 +802,14 @@ static int wssfdx_open(struct device *dev, struct sm_state *sm) /* * initialize some variables */ - if (!(SCSTATE->dmabuf = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) + if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) return -ENOMEM; - if (!(SCSTATE->dmabuf2 = kmalloc(SCSTATE->dmabuflen, GFP_KERNEL | GFP_DMA))) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); + if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { + kfree(sm->dma.ibuf); return -ENOMEM; } - SCSTATE->dmabufidx = SCSTATE->ptt = 0; + dma_init_transmit(sm); + dma_init_receive(sm); memset(&sm->m, 0, sizeof(sm->m)); memset(&sm->d, 0, sizeof(sm->d)); @@ -825,20 +819,20 @@ static int wssfdx_open(struct device *dev, struct sm_state *sm) sm->mode_rx->init(sm); if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); return -EBUSY; } if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); free_dma(dev->dma); return -EBUSY; } if (request_irq(dev->irq, wssfdx_interrupt, SA_INTERRUPT, sm->hwdrv->hw_name, dev)) { - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); free_dma(dev->dma); free_dma(sm->hdrv.ptt_out.dma2); return -EBUSY; @@ -858,13 +852,14 @@ static int wssfdx_close(struct device *dev, struct sm_state *sm) * disable interrupts */ disable_dma(dev->dma); + disable_dma(sm->hdrv.ptt_out.dma2); write_codec(dev, 9, 0xc); /* disable codec */ free_irq(dev->irq, dev); free_dma(dev->dma); free_dma(sm->hdrv.ptt_out.dma2); release_region(dev->base_addr, WSS_EXTENT); - kfree_s(SCSTATE->dmabuf, SCSTATE->dmabuflen); - kfree_s(SCSTATE->dmabuf2, SCSTATE->dmabuflen); + kfree(sm->dma.ibuf); + kfree(sm->dma.obuf); return 0; } @@ -875,7 +870,7 @@ static int wssfdx_sethw(struct device *dev, struct sm_state *sm, char *mode) char *cp = strchr(mode, '.'); const struct modem_tx_info **mtp = sm_modem_tx_table; const struct modem_rx_info **mrp; - int i, dv; + int i; if (!strcmp(mode, "off")) { sm->mode_tx = NULL; @@ -907,11 +902,37 @@ static int wssfdx_sethw(struct device *dev, struct sm_state *sm, char *mode) sm->mode_tx = *mtp; sm->mode_rx = *mrp; SCSTATE->fmt[0] = SCSTATE->fmt[1] = i; - dv = lcm(sm->mode_tx->dmabuflenmodulo, - sm->mode_rx->dmabuflenmodulo); - SCSTATE->dmabuflen = sm->mode_rx->srate/100+dv-1; - SCSTATE->dmabuflen /= dv; - SCSTATE->dmabuflen *= 2*dv; /* make sure DMA buf is even */ + sm->dma.ifragsz = sm->dma.ofragsz = (sm->mode_rx->srate + 50)/100; + if (sm->dma.ifragsz < sm->mode_rx->overlap) + sm->dma.ifragsz = sm->mode_rx->overlap; + sm->dma.i16bit = sm->dma.o16bit = 2; + if (sm->mode_rx->demodulator_s16) { + sm->dma.i16bit = 1; + sm->dma.ifragsz <<= 1; +#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ + SCSTATE->fmt[0] |= 0xc0; +#else /* __BIG_ENDIAN */ + SCSTATE->fmt[0] |= 0x40; +#endif /* __BIG_ENDIAN */ + } else if (sm->mode_rx->demodulator_u8) + sm->dma.i16bit = 0; + if (sm->mode_tx->modulator_s16) { + sm->dma.o16bit = 1; + sm->dma.ofragsz <<= 1; +#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ + SCSTATE->fmt[1] |= 0xc0; +#else /* __BIG_ENDIAN */ + SCSTATE->fmt[1] |= 0x40; +#endif /* __BIG_ENDIAN */ + } else if (sm->mode_tx->modulator_u8) + sm->dma.o16bit = 0; + if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { + printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, + sm->mode_rx->name, sm->mode_tx->name); + sm->mode_tx = NULL; + sm->mode_rx = NULL; + return -EINVAL; + } return 0; } } diff --git a/drivers/net/soundmodem/smdma.h b/drivers/net/soundmodem/smdma.h new file mode 100644 index 000000000..27cea09e7 --- /dev/null +++ b/drivers/net/soundmodem/smdma.h @@ -0,0 +1,210 @@ +/*****************************************************************************/ + +/* + * smdma.h -- soundcard radio modem driver dma buffer routines. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + */ + +#ifndef _SMDMA_H +#define _SMDMA_H + +/* ---------------------------------------------------------------------- */ + +#include "sm.h" + +/* ---------------------------------------------------------------------- */ + +#define DMA_MODE_AUTOINIT 0x10 +#define NUM_FRAGMENTS 4 + +/* --------------------------------------------------------------------- */ +/* + * ===================== DMA buffer management =========================== + */ + +/* + * returns the number of samples per fragment + */ +extern __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr) +{ + if (send) { + disable_dma(dmanr); + clear_dma_ff(dmanr); + set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); + set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf)); + set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS); + enable_dma(dmanr); + if (sm->dma.o16bit) + return sm->dma.ofragsz/2; + return sm->dma.ofragsz; + } else { + disable_dma(dmanr); + clear_dma_ff(dmanr); + set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT); + set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf)); + set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS); + enable_dma(dmanr); + if (sm->dma.i16bit) + return sm->dma.ifragsz/2; + return sm->dma.ifragsz; + } +} + +/* --------------------------------------------------------------------- */ + +extern __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr, + unsigned int *curfrag) +{ + unsigned int dmaptr, sz, frg, offs; + + dmaptr = get_dma_residue(dmanr); + if (send) { + sz = sm->dma.ofragsz * NUM_FRAGMENTS; + if (dmaptr == 0 || dmaptr > sz) + dmaptr = sz; + dmaptr--; + frg = dmaptr / sm->dma.ofragsz; + offs = (dmaptr % sm->dma.ofragsz) + 1; + *curfrag = NUM_FRAGMENTS - 1 - frg; +#ifdef SM_DEBUG + if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) + sm->debug_vals.dma_residue = offs; +#endif /* SM_DEBUG */ + if (sm->dma.o16bit) + return offs/2; + return offs; + } else { + sz = sm->dma.ifragsz * NUM_FRAGMENTS; + if (dmaptr == 0 || dmaptr > sz) + dmaptr = sz; + dmaptr--; + frg = dmaptr / sm->dma.ifragsz; + offs = (dmaptr % sm->dma.ifragsz) + 1; + *curfrag = NUM_FRAGMENTS - 1 - frg; +#ifdef SM_DEBUG + if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) + sm->debug_vals.dma_residue = offs; +#endif /* SM_DEBUG */ + if (sm->dma.i16bit) + return offs/2; + return offs; + } +} + +/* --------------------------------------------------------------------- */ + +extern __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag) +{ + unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS; + + sm->dma.ofragptr = curfrag; + if (sm->dma.ptt_cnt <= 0) { + sm->dma.ptt_cnt = 0; + return 0; + } + sm->dma.ptt_cnt -= diff; + if (sm->dma.ptt_cnt <= 0) { + sm->dma.ptt_cnt = 0; + return -1; + } + return 0; +} + +extern __inline__ void dma_transmit(struct sm_state *sm) +{ + void *p; + + while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) { + p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz * + ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS); + if (sm->dma.o16bit) { + time_exec(sm->debug_vals.mod_cyc, + sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2)); + } else { + time_exec(sm->debug_vals.mod_cyc, + sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz)); + } + sm->dma.ptt_cnt++; + } +} + +extern __inline__ void dma_init_transmit(struct sm_state *sm) +{ + sm->dma.ofragptr = 0; + sm->dma.ptt_cnt = 0; +} + +extern __inline__ void dma_start_transmit(struct sm_state *sm) +{ + sm->dma.ofragptr = 0; + if (sm->dma.o16bit) { + time_exec(sm->debug_vals.mod_cyc, + sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2)); + } else { + time_exec(sm->debug_vals.mod_cyc, + sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz)); + } + sm->dma.ptt_cnt = 1; +} + +extern __inline__ void dma_clear_transmit(struct sm_state *sm) +{ + sm->dma.ptt_cnt = 0; + memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS); +} + +/* --------------------------------------------------------------------- */ + +extern __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag) +{ + void *p; + + while (sm->dma.ifragptr != curfrag) { + if (sm->dma.ifragptr) + p = (unsigned char *)sm->dma.ibuf + + sm->dma.ifragsz * sm->dma.ifragptr; + else { + p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz; + memcpy(p, sm->dma.ibuf, sm->dma.ifragsz); + } + if (sm->dma.o16bit) { + time_exec(sm->debug_vals.demod_cyc, + sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2)); + } else { + time_exec(sm->debug_vals.demod_cyc, + sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz)); + } + sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS; + } +} + +extern __inline__ void dma_init_receive(struct sm_state *sm) +{ + sm->dma.ifragptr = 0; +} + +/* --------------------------------------------------------------------- */ +#endif /* _SMDMA_H */ + + + diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2aae7a2db..7118164b6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -56,7 +56,9 @@ struct pci_dev_info dev_info[] = { DEVICE( ATI, ATI_68800, "68800AX"), DEVICE( ATI, ATI_215CT222, "215CT222"), DEVICE( ATI, ATI_210888CX, "210888CX"), + DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)"), DEVICE( ATI, ATI_210888GX, "210888GX"), + DEVICE( ATI, ATI_264VT, "Mach64 VT"), DEVICE( VLSI, VLSI_82C592, "82C592-FC1"), DEVICE( VLSI, VLSI_82C593, "82C593-FC1"), DEVICE( VLSI, VLSI_82C594, "82C594-AFC2"), @@ -76,6 +78,7 @@ struct pci_dev_info dev_info[] = { DEVICE( DEC, DEC_TULIP_FAST, "DC21140"), DEVICE( DEC, DEC_FDDI, "DEFPA"), DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), + DEVICE( DEC, DEC_21142, "DC21142"), DEVICE( DEC, DEC_21052, "DC21052"), DEVICE( DEC, DEC_21152, "DC21152"), DEVICE( CIRRUS, CIRRUS_7548, "GD 7548"), @@ -83,10 +86,14 @@ struct pci_dev_info dev_info[] = { DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434"), DEVICE( CIRRUS, CIRRUS_5436, "GD 5436"), + DEVICE( CIRRUS, CIRRUS_5446, "GD 5446"), + DEVICE( CIRRUS, CIRRUS_5464, "GD 5464"), DEVICE( CIRRUS, CIRRUS_6729, "CL 6729"), DEVICE( CIRRUS, CIRRUS_7542, "CL 7542"), DEVICE( CIRRUS, CIRRUS_7543, "CL 7543"), + DEVICE( CIRRUS, CIRRUS_7541, "CL 7541"), DEVICE( IBM, IBM_82G2675, "82G2675"), + DEVICE( IBM, IBM_82351, "82351"), DEVICE( WD, WD_7197, "WD 7197"), DEVICE( AMD, AMD_LANCE, "79C970"), DEVICE( AMD, AMD_SCSI, "53C974"), @@ -101,6 +108,7 @@ struct pci_dev_info dev_info[] = { DEVICE( CT, CT_65545, "65545"), DEVICE( CT, CT_65548, "65548"), DEVICE( CT, CT_65550, "65550"), + DEVICE( CT, CT_65554, "65554"), DEVICE( MIRO, MIRO_36050, "ZR36050"), DEVICE( FD, FD_36C70, "TMC-18C30"), DEVICE( SI, SI_6201, "6201"), @@ -112,7 +120,10 @@ struct pci_dev_info dev_info[] = { DEVICE( SI, SI_601, "85C601"), DEVICE( SI, SI_5511, "85C5511"), DEVICE( SI, SI_5513, "85C5513"), + DEVICE( SI, SI_5571, "5571"), + DEVICE( SI, SI_7001, "7001"), DEVICE( HP, HP_J2585A, "J2585A"), + DEVICE( HP, HP_J2585B, "J2585B"), DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)"), DEVICE( PCTECH, PCTECH_RZ1001, "RZ1001 (buggy?)"), DEVICE( DPT, DPT, "SmartCache/Raid"), @@ -128,6 +139,9 @@ struct pci_dev_info dev_info[] = { DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint"), DEVICE( OAK, OAK_OTI107, "OTI107"), DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI"), + DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle"), + DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle"), + DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven"), DEVICE( PROMISE, PROMISE_5300, "DC5030"), DEVICE( N9, N9_I128, "Imagine 128"), DEVICE( N9, N9_I128_2, "Imagine 128v2"), @@ -155,11 +169,13 @@ struct pci_dev_info dev_info[] = { DEVICE( ACC, ACC_2056, "2056"), DEVICE( WINBOND, WINBOND_83769, "W83769F"), DEVICE( WINBOND, WINBOND_82C105, "SL82C105"), + DEVICE( WINBOND, WINBOND_83C553, "W83C553"), DEVICE( 3COM, 3COM_3C590, "3C590 10bT"), DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX"), DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4"), DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII"), DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO"), + DEVICE( 3COM, 3COM_3C900COMBO,"3C900 10b Combo"), DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX"), DEVICE( AL, AL_M1445, "M1445"), DEVICE( AL, AL_M1449, "M1449"), @@ -171,18 +187,24 @@ struct pci_dev_info dev_info[] = { DEVICE( AL, AL_M4803, "M4803"), DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070"), DEVICE( ASP, ASP_ABP940, "ABP940"), + DEVICE( ASP, ASP_ABP940U, "ABP940U"), DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"), DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)"), DEVICE( IMS, IMS_8849, "8849"), DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"), + DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe"), DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)"), + DEVICE( AMCC, AMCC_S5933, "S5933"), DEVICE( INTERG, INTERG_1680, "IGA-1680"), DEVICE( INTERG, INTERG_1682, "IGA-1682"), DEVICE( REALTEK, REALTEK_8029, "8029"), DEVICE( INIT, INIT_320P, "320 P"), DEVICE( VIA, VIA_82C505, "VT 82C505"), DEVICE( VIA, VIA_82C561, "VT 82C561"), + DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo VP-1"), DEVICE( VIA, VIA_82C576, "VT 82C576 3V"), + DEVICE( VIA, VIA_82C585, "VT 82C585VP Apollo VP-1"), + DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo VP-1"), DEVICE( VIA, VIA_82C416, "VT 82C416MV"), DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), @@ -200,19 +222,22 @@ struct pci_dev_info dev_info[] = { DEVICE( VORTEX, VORTEX_GDT6555, "GDT 6555"), DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"), DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"), - DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"), DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"), DEVICE( FORE, FORE_PCA200E, "PCA-200E"), + DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"), DEVICE( PLX, PLX_9060, "PCI9060 i960 bridge"), DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410"), DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo"), DEVICE( VMIC, VMIC_VME, "VMIVME-7587"), DEVICE( DIGI, DIGI_RIGHTSWITCH, "RightSwitch SE-6"), DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"), + DEVICE( TOSHIBA, TOSHIBA_601, "Laptop"), DEVICE( ZEITNET, ZEITNET_1221, "1221"), DEVICE( ZEITNET, ZEITNET_1225, "1225"), + DEVICE( OMEGA, OMEGA_PCMCIA, "PCMCIA"), DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host"), DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host"), + DEVICE( ZORAN, ZORAN_36120, "ZR36120"), DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000"), DEVICE( RP, RP8OCTA, "RocketPort 8 Oct"), DEVICE( RP, RP8INTF, "RocketPort 8 Intf"), @@ -222,6 +247,8 @@ struct pci_dev_info dev_info[] = { DEVICE( CYCLADES, CYCLOM_Y_Hi, "Cyclom-Y above 1Mbyte"), DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclom-Z below 1Mbyte"), DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclom-Z above 1Mbyte"), + DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"), + DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"), DEVICE( OPTIBASE, OPTIBASE_FORGE, "MPEG Forge"), DEVICE( OPTIBASE, OPTIBASE_FUSION,"MPEG Fusion"), DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex"), @@ -230,6 +257,9 @@ struct pci_dev_info dev_info[] = { DEVICE( SYMPHONY, SYMPHONY_101, "82C101"), DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"), DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"), + DEVICE( 3DLABS, 3DLABS_DELTA, "GLINT Delta"), + DEVICE( 3DLABS, 3DLABS_PERMEDIA,"PERMEDIA"), + DEVICE( AVANCE, AVANCE_ALG2064, "ALG2064i"), DEVICE( AVANCE, AVANCE_2302, "ALG-2302"), DEVICE( S3, S3_ViRGE, "ViRGE"), DEVICE( S3, S3_TRIO, "Trio32/Trio64"), @@ -248,6 +278,8 @@ struct pci_dev_info dev_info[] = { DEVICE( INTEL, INTEL_82378, "82378IB"), DEVICE( INTEL, INTEL_82430, "82430ZX Aries"), BRIDGE( INTEL, INTEL_82434, "82434LX Mercury/Neptune", 0x00), + DEVICE( INTEL, INTEL_82092AA_0,"82092AA PCMCIA bridge"), + DEVICE( INTEL, INTEL_82092AA_1,"82092AA EIDE"), DEVICE( INTEL, INTEL_7116, "SAA7116"), DEVICE( INTEL, INTEL_82596, "82596"), DEVICE( INTEL, INTEL_82865, "82865"), @@ -255,15 +287,19 @@ struct pci_dev_info dev_info[] = { DEVICE( INTEL, INTEL_82437, "82437"), DEVICE( INTEL, INTEL_82371_0, "82371 Triton PIIX"), DEVICE( INTEL, INTEL_82371_1, "82371 Triton PIIX"), - DEVICE( INTEL, INTEL_430MX_0, "Triton I"), - DEVICE( INTEL, INTEL_430MX_1, "Triton I"), + DEVICE( INTEL, INTEL_82371MX, "430MX - 82371MX MPIIX"), + DEVICE( INTEL, INTEL_82437MX, "430MX - 82437MX MTSC"), DEVICE( INTEL, INTEL_82441, "82441FX Natoma"), DEVICE( INTEL, INTEL_82439, "82439HX Triton II"), DEVICE( INTEL, INTEL_82371SB_0,"82371SB Natoma/Triton II PIIX3"), DEVICE( INTEL, INTEL_82371SB_1,"82371SB Natoma/Triton II PIIX3"), DEVICE( INTEL, INTEL_82371SB_2,"82371SB Natoma/Triton II PIIX3"), DEVICE( INTEL, INTEL_82437VX, "82437VX Triton II"), + DEVICE( INTEL, INTEL_82439TX, "82439TX"), + DEVICE( INTEL, INTEL_82371AB_0,"82371AB PIIX4"), DEVICE( INTEL, INTEL_82371AB, "82371AB 430TX PIIX4"), + DEVICE( INTEL, INTEL_82371AB_2,"82371AB PIIX4"), + DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 Power Management"), DEVICE( INTEL, INTEL_P6, "Orion P6"), DEVICE( INTEL, INTEL_P6_2, "82450GX Orion P6"), DEVICE( KTI, KTI_ET32P2, "ET32P2"), @@ -508,6 +544,7 @@ const char *pci_strvendor(unsigned int vendor) case PCI_VENDOR_ID_BUSLOGIC: return "BusLogic"; case PCI_VENDOR_ID_OAK: return "OAK"; case PCI_VENDOR_ID_WINBOND2: return "Winbond"; + case PCI_VENDOR_ID_MOTOROLA: return "Motorola"; case PCI_VENDOR_ID_PROMISE: return "Promise Technology"; case PCI_VENDOR_ID_N9: return "Number Nine"; case PCI_VENDOR_ID_UMC: return "UMC"; @@ -531,6 +568,7 @@ const char *pci_strvendor(unsigned int vendor) case PCI_VENDOR_ID_CERN: return "CERN"; case PCI_VENDOR_ID_IMS: return "IMS"; case PCI_VENDOR_ID_TEKRAM2: return "Tekram"; + case PCI_VENDOR_ID_TUNDRA: return "Tundra"; case PCI_VENDOR_ID_AMCC: return "AMCC"; case PCI_VENDOR_ID_INTERG: return "Intergraphics"; case PCI_VENDOR_ID_REALTEK: return "Realtek"; @@ -547,10 +585,14 @@ const char *pci_strvendor(unsigned int vendor) case PCI_VENDOR_ID_MUTECH: return "Mutech"; case PCI_VENDOR_ID_TOSHIBA: return "Toshiba"; case PCI_VENDOR_ID_ZEITNET: return "ZeitNet"; + case PCI_VENDOR_ID_OMEGA: return "Omega Micro"; case PCI_VENDOR_ID_SPECIALIX: return "Specialix"; + case PCI_VENDOR_ID_ZORAN: return "Zoran"; case PCI_VENDOR_ID_COMPEX: return "Compex"; case PCI_VENDOR_ID_RP: return "Comtrol"; case PCI_VENDOR_ID_CYCLADES: return "Cyclades"; + case PCI_VENDOR_ID_3DFX: return "3Dfx"; + case PCI_VENDOR_ID_SIGMADES: return "Sigma Designs"; case PCI_VENDOR_ID_OPTIBASE: return "Optibase"; case PCI_VENDOR_ID_SYMPHONY: return "Symphony"; case PCI_VENDOR_ID_TEKRAM: return "Tekram"; diff --git a/drivers/sbus/char/bwtwo.c b/drivers/sbus/char/bwtwo.c index be68d09c9..ae81e1260 100644 --- a/drivers/sbus/char/bwtwo.c +++ b/drivers/sbus/char/bwtwo.c @@ -1,4 +1,4 @@ -/* $Id: bwtwo.c,v 1.13 1997/04/14 17:04:55 jj Exp $ +/* $Id: bwtwo.c,v 1.16 1997/06/04 08:27:26 davem Exp $ * bwtwo.c: bwtwo console driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -15,9 +15,11 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include + #include "fb.h" #include "cg_common.h" @@ -91,7 +93,7 @@ bwtwo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, vma->vm_page_prot, fb->space); if (r) return -EAGAIN; vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/cgfourteen.c b/drivers/sbus/char/cgfourteen.c index d42a4343c..2cb4c21c9 100644 --- a/drivers/sbus/char/cgfourteen.c +++ b/drivers/sbus/char/cgfourteen.c @@ -1,4 +1,4 @@ -/* $Id: cgfourteen.c,v 1.19 1997/04/14 17:04:57 jj Exp $ +/* $Id: cgfourteen.c,v 1.22 1997/06/04 08:27:27 davem Exp $ * cgfourteen.c: Sun SparcStation console support. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -23,9 +23,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #define CG14_MCR_INTENABLE_SHIFT 7 @@ -272,7 +273,7 @@ cg14_mmap (struct inode *inode, struct file *file, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/cgsix.c b/drivers/sbus/char/cgsix.c index 5f91c1308..e53fcf09e 100644 --- a/drivers/sbus/char/cgsix.c +++ b/drivers/sbus/char/cgsix.c @@ -1,4 +1,4 @@ -/* $Id: cgsix.c,v 1.27 1997/04/14 17:04:55 jj Exp $ +/* $Id: cgsix.c,v 1.30 1997/06/04 08:27:28 davem Exp $ * cgsix.c: cgsix frame buffer driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -15,9 +15,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #include "cg_common.h" @@ -296,7 +297,7 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/cgthree.c b/drivers/sbus/char/cgthree.c index ac1265c61..0e1446c0e 100644 --- a/drivers/sbus/char/cgthree.c +++ b/drivers/sbus/char/cgthree.c @@ -1,4 +1,4 @@ -/* $Id: cgthree.c,v 1.18 1997/04/16 17:51:09 jj Exp $ +/* $Id: cgthree.c,v 1.21 1997/06/04 08:27:29 davem Exp $ * cgtree.c: cg3 frame buffer driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -18,9 +18,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #include "cg_common.h" @@ -131,7 +132,7 @@ cg3_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/creator.c b/drivers/sbus/char/creator.c index 9bf72a3b9..4ff2caf31 100644 --- a/drivers/sbus/char/creator.c +++ b/drivers/sbus/char/creator.c @@ -15,9 +15,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" __initfunc(void creator_setup (fbinfo_t *fb, int slot, int con_node, unsigned long creator, int creator_io)) diff --git a/drivers/sbus/char/leo.c b/drivers/sbus/char/leo.c index b3ec23867..61e646e9f 100644 --- a/drivers/sbus/char/leo.c +++ b/drivers/sbus/char/leo.c @@ -1,4 +1,4 @@ -/* $Id: leo.c,v 1.15 1997/04/14 17:04:54 jj Exp $ +/* $Id: leo.c,v 1.18 1997/06/04 08:27:30 davem Exp $ * leo.c: SUNW,leo 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -17,9 +17,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #include "cg_common.h" @@ -221,7 +222,7 @@ leo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/suncons.c b/drivers/sbus/char/suncons.c index d1a2dfd45..1d3815dd3 100644 --- a/drivers/sbus/char/suncons.c +++ b/drivers/sbus/char/suncons.c @@ -1,4 +1,4 @@ -/* $Id: suncons.c,v 1.62 1997/05/02 22:32:32 davem Exp $ +/* $Id: suncons.c,v 1.63 1997/05/31 18:33:25 mj Exp $ * * suncons.c: Sun SparcStation console support. * @@ -76,11 +76,11 @@ #include #include -#include "../../char/kbd_kern.h" -#include "../../char/vt_kern.h" -#include "../../char/consolemap.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +#include +#include +#include +#include +#include #include "fb.h" diff --git a/drivers/sbus/char/sunfb.c b/drivers/sbus/char/sunfb.c index e803344bd..68856c9ee 100644 --- a/drivers/sbus/char/sunfb.c +++ b/drivers/sbus/char/sunfb.c @@ -1,4 +1,4 @@ -/* $Id: sunfb.c,v 1.22 1997/04/03 08:47:56 davem Exp $ +/* $Id: sunfb.c,v 1.23 1997/05/31 18:33:26 mj Exp $ * sunfb.c: Sun generic frame buffer support. * * Copyright (C) 1995, 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -33,11 +33,11 @@ #include #include -#include "../../char/kbd_kern.h" -#include "../../char/vt_kern.h" -#include "../../char/consolemap.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +#include +#include +#include +#include +#include #include "fb.h" diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index 8e398f345..1ddaaecd4 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -25,9 +25,9 @@ #include #include -#include "../../char/kbd_kern.h" -#include "../../char/diacr.h" -#include "../../char/vt_kern.h" +#include +#include +#include #define SIZE(x) (sizeof(x)/sizeof((x)[0])) diff --git a/drivers/sbus/char/tcx.c b/drivers/sbus/char/tcx.c index 2ecabda62..db66383ac 100644 --- a/drivers/sbus/char/tcx.c +++ b/drivers/sbus/char/tcx.c @@ -1,4 +1,4 @@ -/* $Id: tcx.c,v 1.12 1997/04/14 17:04:51 jj Exp $ +/* $Id: tcx.c,v 1.15 1997/06/04 08:27:32 davem Exp $ * tcx.c: SUNW,tcx 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -16,9 +16,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #include "cg_common.h" @@ -171,7 +172,7 @@ tcx_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 20e04258b..00cdfe35c 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -581,7 +581,7 @@ static int vfc_mmap(struct inode *inode, struct file *file, vma->vm_page_prot, dev->which_io); if(ret) return -EAGAIN; vma->vm_inode=inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } diff --git a/drivers/sbus/char/weitek.c b/drivers/sbus/char/weitek.c index 0fa0cb5fc..d2ac4d135 100644 --- a/drivers/sbus/char/weitek.c +++ b/drivers/sbus/char/weitek.c @@ -1,4 +1,4 @@ -/* $Id: weitek.c,v 1.9 1997/04/14 17:04:57 jj Exp $ +/* $Id: weitek.c,v 1.12 1997/06/04 08:27:34 davem Exp $ * weitek.c: Tadpole P9100/P9000 console driver * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) @@ -15,9 +15,10 @@ #include #include -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" +/* These must be included after asm/fbio.h */ +#include +#include +#include #include "fb.h" #include "cg_common.h" @@ -82,7 +83,7 @@ weitek_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma, page += map_size; } vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); return 0; } #endif diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 2e4b1aa3e..6edd01320 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -50,20 +50,20 @@ int amiga7xx_detect(Scsi_Host_Template *tpnt) #ifdef CONFIG_WARPENGINE_SCSI if ((key = zorro_find(MANUF_MACROSYSTEMS, PROD_WARP_ENGINE, 0, 0))) { - cd = zorro_get_board(key); - address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr, + cd = zorro_get_board(key); + address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr, cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL); - options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; + options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; clock = 50000000; /* 50MHz SCSI Clock */ - ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(address + 0x40000), - 0, IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC, DMA_NONE, + ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(address + 0x40000), + 0, IRQ_AMIGA_PORTS, DMA_NONE, options, clock); - zorro_config_board(key, 0); - num++; + zorro_config_board(key, 0); + num++; } #endif @@ -94,7 +94,7 @@ int amiga7xx_detect(Scsi_Host_Template *tpnt) clock = 50000000; /* 50MHz SCSI Clock */ ncr53c7xx_init(tpnt, 0, 710, (u32)(unsigned char *)(address+0x800000), - 0, IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC, DMA_NONE, + 0, IRQ_AMIGA_PORTS, DMA_NONE, options, clock); zorro_config_board(key, 0); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 5bffb2762..1e398a152 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -619,7 +619,10 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng struct Scsi_Host *scsi_ptr; Scsi_Cmnd *ptr; struct NCR5380_hostdata *hostdata; - +#ifdef NCR5380_STATS + Scsi_Device *dev; + extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; +#endif cli(); for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next) diff --git a/drivers/scsi/script_asm.pl b/drivers/scsi/script_asm.pl index 2599a966e..d99fcc950 100644 --- a/drivers/scsi/script_asm.pl +++ b/drivers/scsi/script_asm.pl @@ -1,4 +1,4 @@ -#! /usr/local/bin/perl +#!/usr/bin/perl -s # NCR 53c810 script assembler # Sponsored by @@ -10,6 +10,9 @@ # drew@Colorado.EDU # +1 (303) 786-7975 # +# Support for 53c710 (via -ncr7x0_family switch) added by Richard +# Hirst - 15th March 1997 +# # 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 @@ -74,7 +77,15 @@ $prefix = ''; # define all arrays having this prefix so we # and = 0x04_00_00_00 # add = 0x06_00_00_00 -%operators_810 = ( +if ($ncr7x0_family) { + %operators = ( + '|', 0x02_00_00_00, 'OR', 0x02_00_00_00, + '&', 0x04_00_00_00, 'AND', 0x04_00_00_00, + '+', 0x06_00_00_00 + ); +} +else { + %operators = ( 'SHL', 0x01_00_00_00, '|', 0x02_00_00_00, 'OR', 0x02_00_00_00, 'XOR', 0x03_00_00_00, @@ -83,11 +94,33 @@ $prefix = ''; # define all arrays having this prefix so we # Note : low bit of the operator bit should be set for add with # carry. '+', 0x06_00_00_00 -); - + ); +} # Table of register addresses -%registers_810 = ( + +if ($ncr7x0_family) { + %registers = ( + 'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3, + 'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7, + 'SFBR', 8, 'SIDL', 9, 'SBDL', 10, 'SBCL', 11, + 'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15, + 'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19, + 'CTEST0', 20, 'CTEST1', 21, 'CTEST2', 22, 'CTEST3', 23, + 'CTEST4', 24, 'CTEST5', 25, 'CTEST6', 26, 'CTEST7', 27, + 'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31, + 'DFIFO', 32, 'ISTAT', 33, 'CTEST8', 34, 'LCRC', 35, + 'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39, + 'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43, + 'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47, + 'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51, + 'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55, + 'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59, + 'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63, + ); +} +else { + %registers = ( 'SCNTL0', 0, 'SCNTL1', 1, 'SCNTL2', 2, 'SCNTL3', 3, 'SCID', 4, 'SXFER', 5, 'SDID', 6, 'GPREG', 7, 'SFBR', 8, 'SOCL', 9, 'SSID', 10, 'SBCL', 11, @@ -113,7 +146,8 @@ $prefix = ''; # define all arrays having this prefix so we 'SODL', 84, 'SBDL', 88, 'SCRATCHB0', 92, 'SCRATCHB1', 93, 'SCRATCHB2', 94, 'SCRATCHB3', 95 -); + ); +} # Parsing regular expressions $identifier = '[A-Za-z_][A-Za-z_0-9]*'; @@ -131,17 +165,22 @@ print STDERR "value regex = $value\n" if ($debug); $phase = join ('|', keys %scsi_phases); print STDERR "phase regex = $phase\n" if ($debug); -$register = join ('|', keys %registers_810); +$register = join ('|', keys %registers); -# yucky - since %operators_810 includes meta-characters which must +# yucky - since %operators includes meta-characters which must # be escaped, I can't use the join() trick I used for the register # regex -$operator = '\||OR|AND|XOR|\&|\+'; +if ($ncr7x0_family) { + $operator = '\||OR|AND|\&|\+'; +} +else { + $operator = '\||OR|AND|XOR|\&|\+'; +} # Global variables -%symbol_values = (%registers_810) ; # Traditional symbol table +%symbol_values = (%registers) ; # Traditional symbol table %symbol_references = () ; # Table of symbol references, where # the index is the symbol name, @@ -421,6 +460,7 @@ print STDERR "defined external $1 to $external\n" if ($debug_external); if ($1 =~ /^($identifier)\s*$/) { push (@entry, $1); } else { + die "$0 : syntax error in line $lineno : $_ expected ENTRY "; @@ -558,13 +598,13 @@ print STDERR "data8 source\n" if ($debug); # instruction. if (($src_reg eq undef) || ($src_reg eq $dst_reg)) { $code[$address] |= 0x38_00_00_00 | - ($registers_810{$dst_reg} << 16); + ($registers{$dst_reg} << 16); } elsif ($dst_reg =~ /SFBR/i) { $code[$address] |= 0x30_00_00_00 | - ($registers_810{$src_reg} << 16); + ($registers{$src_reg} << 16); } elsif ($src_reg =~ /SFBR/i) { $code[$address] |= 0x28_00_00_00 | - ($registers_810{$dst_reg} << 16); + ($registers{$dst_reg} << 16); } else { die "$0 : Illegal combination of registers in line $lineno : $_ @@ -573,10 +613,10 @@ print STDERR "data8 source\n" if ($debug); "; } - $code[$address] |= $operators_810{$op}; + $code[$address] |= $operators{$op}; &parse_value ($data8, 0, 1, 1); - $code[$address] |= $operators_810{$op}; + $code[$address] |= $operators{$op}; $code[$address + 1] = 0x00_00_00_00;# Reserved $address += 2; } else { diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index 38b7af597..54523d88f 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -802,6 +802,8 @@ DMAbuf_space_in_queue (int dev) */ max = dmap->max_fragments; + if (max > dmap->nbufs) + max = dmap->nbufs; len = dmap->qlen; if (audio_devs[dev]->d->local_qlen) diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index 088591b9d..957150f7b 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -327,7 +327,7 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) return -EAGAIN; vma->vm_inode = inode; - inode->i_count++; + atomic_inc(&inode->i_count); dmap->mapping_flags |= DMA_MAP_MAPPED; -- cgit v1.2.3