You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(6) |
Sep
(2) |
Oct
(43) |
Nov
(4) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(78) |
Feb
(97) |
Mar
(29) |
Apr
(2) |
May
(22) |
Jun
(38) |
Jul
(11) |
Aug
(27) |
Sep
(40) |
Oct
(2) |
Nov
(17) |
Dec
(8) |
2002 |
Jan
|
Feb
(2) |
Mar
(1) |
Apr
(480) |
May
(456) |
Jun
(12) |
Jul
|
Aug
(1) |
Sep
|
Oct
(18) |
Nov
(3) |
Dec
(6) |
2003 |
Jan
|
Feb
(18) |
Mar
(1) |
Apr
|
May
(6) |
Jun
(147) |
Jul
(7) |
Aug
(3) |
Sep
(235) |
Oct
(10) |
Nov
(2) |
Dec
(1) |
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: ? <uns...@us...> - 2002-05-30 01:20:30
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv29750 Modified Files: vaxsgec.c Log Message: Set CSR4 before requesting a Tx poll Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- vaxsgec.c 28 May 2002 20:16:19 -0000 1.9 +++ vaxsgec.c 30 May 2002 01:20:24 -0000 1.10 @@ -133,6 +133,7 @@ if ((regs->sg_nicsr5 & SG_NICSR5_TS) != SG_NICSR5_TS_RUN) { + writereg(®s->sg_nicsr4, virt_to_phys(& lp->tx_ring [lp->tx_old]) & 0xffffff); writereg(®s->sg_nicsr1,SG_NICSR1_TXPD); #ifdef VAX_SGEC_DEBUG printk ("%s: retrigger CSR1 (CSR5 is %ld)\n", |
From: ? <uns...@us...> - 2002-05-29 03:37:44
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/char In directory usw-pr-cvs1:/tmp/cvs-serv31994/drivers/char Modified Files: Makefile tty_io.c Added Files: vxt2694.c sc26c94.c sc26c94.h Log Message: First attempt at a real serial driver for the SC26C94 in the VXT2000. --- NEW FILE --- /* * The platform-specific bits of a driver for the SC26C94 based serial interface * in the VXT2000. * * 2002 Uns Lider */ /* TODO: * Properly configure the I/O output ports * Figure out how to use incoming flow control signals * Hooks for LKxxx keyboard */ /* channel A is the serial port channel B is the unused "J5" channel C is the keyboard (but its I/O ports are borrowed by channel A) channel D is the mouse */ #include <linux/types.h> #include <linux/delay.h> #include <asm/system.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/tty.h> #include <linux/serial.h> #include <linux/generic_serial.h> #include <linux/console.h> #include <asm/io.h> #include <linux/ioport.h> #include "sc26c94.h" #define VXT2694_PHYS_ADDR 0x200A0000 volatile int *vxt2694_addr = NULL; /* * callbacks for sc26c94.c */ static u8 readreg(struct sc26c94 *quart, int reg) { return vxt2694_addr[reg]; } static void writereg(struct sc26c94 *quart, int reg, u8 value) { vxt2694_addr[reg]=value; } static void set_handshake(struct sc26c94 *quart, int channel, int ready) { if(channel != SC26C94_PORT_A) { return; } sc26c94_write_io(quart, SC26C94_PORT_C, 2, ready); } static int get_handshake(struct sc26c94 *quart, int channel) { if(channel != SC26C94_PORT_A) { return 1; } return 1; /* don't know what port this is on! */ } static void set_flow(struct sc26c94 *quart, int channel, int on) { if(channel != SC26C94_PORT_A) { return; } sc26c94_write_io(quart, SC26C94_PORT_A, 2, on); } static int get_flow(struct sc26c94 *quart, int channel) { if(channel != SC26C94_PORT_A) { return 1; } return sc26c94_read_io(quart, SC26C94_PORT_A, 0); } static int get_cd(struct sc26c94 *quart, int channel) { if(channel != SC26C94_PORT_A) { return 1; } return 1; /* don't know what port this is on! */ } /* since channel B is unused, we are free to program timer A/B to an arbitrary value and use that as the brg */ /* at 3.6864MHz clock, a timer value of 2 (the minimum value) would result in 1 edge per 2/3.6864e6 sec, 1 cycle per 4/3.6864e6 sec. that would result in a bit period of 64/3.6864e6, or a baud rate of 3.6864e6/64=57600 bps. so the baud rate for a given timer value is equal to 115200 divided by the timer value. */ static void set_speed_acr(struct sc26c94 *quart, u8 bit7) { quart->writereg(quart, SC26C94_REG_CSRa, 0xcc); quart->acr[0] &= ~128; quart->acr[0] |= bit7; quart->writereg(quart, SC26C94_REG_ACRab, quart->acr[0]); } static void set_speed_timer(struct sc26c94 *quart, int bps) { u16 ctval; int a, b, c; ctval = 115200 / bps; a = abs(bps - (115200 / (ctval - 1))); b = abs(bps - (115200 / ctval)); c = abs(bps - (115200 / (ctval + 1))); if(a < b) { ctval--; } else if(c < b) { ctval++; } quart->writereg(quart, SC26C94_REG_CSRa, 0xdd); quart->writereg(quart, SC26C94_REG_CTUab, (ctval & 0xff00) >> 8); quart->writereg(quart, SC26C94_REG_CTLab, ctval & 0x00ff); } static int set_speed(struct sc26c94 *quart, int channel, int bps) { if(channel != SC26C94_PORT_A) { return 0; } if(bps > 57600) { switch(bps) { case 115200: set_speed_acr(quart, 1); case 230400: set_speed_acr(quart, 0); default: return -1; } } else { set_speed_timer(quart, bps); } return 0; } struct sc26c94 the_quart = { {{0},{0},{0},{0}}, readreg, writereg, set_handshake, get_handshake, set_flow, get_flow, get_cd, set_speed, NULL }; static int vxt2694_open(struct tty_struct *tty, struct file *filp) { return sc26c94_open(&the_quart, tty, filp); } /* * initialization code */ struct tty_driver tty_driver; struct tty_driver callout_driver; int vxt2694_init() { int irq; int error; #if 0 printk("vxt2694_init\n"); mdelay(1000); /* let TxFIFO drain before messing with UART */ #endif if(vxt2694_addr == NULL) vxt2694_addr = ioremap(VXT2694_PHYS_ADDR, 256); sc26c94_init_chip(&the_quart); /* turn the timer interrupt(?) back on */ sc26c94_set_io_dir(&the_quart, SC26C94_PORT_D, 1, 2); the_quart.acr[1] = 0x60; writereg(&the_quart, SC26C94_REG_ACRcd, 0x60); writereg(&the_quart, SC26C94_REG_CTUcd, 0x48); writereg(&the_quart, SC26C94_REG_CTLcd, 0); (void) readreg(&the_quart, SC26C94_CREG_STARTCTcd); /* turn the serial console port back on */ writereg(&the_quart, SC26C94_REG_CRa, SC26C94_CR_TX_ON); sc26c94_write_mr(&the_quart, SC26C94_PORT_A, 1, SC26C94_MR1_PAR_NONE | SC26C94_MR1_CSIZE_8); /* set up the BRG */ the_quart.acr[0] = 0x60; writereg(&the_quart, SC26C94_REG_ACRab, 0x60); set_speed(&the_quart, SC26C94_PORT_A, 9600); sc26c94_init_chanstructs(&the_quart); writereg(&the_quart, SC26C94_REG_IVR, 0x42); irq = 0x42; if(irq!=0) { request_irq(irq, sc29c94_interrupt, SA_INTERRUPT, "sc29c94", &the_quart); } #if 0 writereg(&the_quart, SC26C94_REG_IMRab, 0xff); #endif sc26c94_init_drivers(&tty_driver, &callout_driver); tty_driver.open = vxt2694_open; #if 1 if ((error = tty_register_driver(&tty_driver))) { printk(KERN_ERR "Couldn't register sc29c94 driver, error = %d\n", error); } if ((error = tty_register_driver(&callout_driver))) { printk(KERN_ERR "Couldn't register sc29c94 callout driver, error = %d\n", error); } #endif printk("sc26c94: interrupt vector %d\n",irq); return 0; } /* * console stuff */ static void vxt_console_write(struct console *co, const char *str, unsigned count) { unsigned long flags; save_flags(flags); cli(); while(count--) { if(*str == '\n') sc26c94_immediate_putc(&the_quart, SC26C94_PORT_A, '\r'); sc26c94_immediate_putc(&the_quart, SC26C94_PORT_A, *str++); } restore_flags(flags); } static int vxt_console_wait_key(struct console *co) { unsigned long flags; int c; save_flags(flags); cli(); c=sc26c94_immediate_getc(&the_quart, SC26C94_PORT_A); restore_flags(flags); return c; } static kdev_t vxt_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); } static int __init vxt_console_setup(struct console *co, char *options) { #if 0 vxt2694_init(); co->cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; writereg(&the_quart, SC26C94_REG_CRa, SC26C94_CR_TX_ON); writereg(&the_quart, SC26C94_REG_CRa, SC26C94_CR_RX_ON); #endif /* this is called really early in kernel initialization, so we can't do a full vxt2694_init. but that's ok because all we'll be calling is the _immediate_putc and _immediate_getc */ vxt2694_addr = ioremap(VXT2694_PHYS_ADDR, 256); return 0; } static struct console sercons = { name: "ttyS", write: vxt_console_write, device: vxt_console_device, wait_key: vxt_console_wait_key, setup: vxt_console_setup, flags: CON_PRINTBUFFER, index: 0, }; void __init vxt_serial_console_init(void) { register_console(&sercons); } --- NEW FILE --- /* * The portable bits of a driver for the SC26C94 "QUART" (Quad UART). * * 2002 Uns Lider * some parts are based on vme_scc.c */ /* TODO: * need a way to wake up open() if we're blocking for a status line change */ #include <linux/module.h> #include <linux/types.h> #include <linux/delay.h> #include <asm/system.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/tty.h> #include <linux/serial.h> #include <linux/generic_serial.h> #include "sc26c94.h" static void disable_tx_ints(void *ptr); static void disable_rx_ints(void *ptr); static void modify_imr(struct sc26c94 *quart, int whichimr, u8 andmask, u8 ormask); /* * functions for doing types of register access beyond a basic write/read. */ void sc26c94_command(struct sc26c94 *quart, int channel, int command) { quart->writereg(quart, SC26C94_REGCHAN(SC26C94_REG_CR, channel), (command&15) << 4); udelay(2); /* The standard clock is 3.68MHz. This delay is sufficient for any clock >2.5MHz. */ } /* * sc26c94_read_mr and sc26c94_write_mr read and write a mode register. * Each channel has three mode registers. However, each channel uses only one * address to access all three registers. */ static void sc26c94_seek_mr(struct sc26c94 *quart, int channel, int index) { switch(channel) { case 0: return sc26c94_command(quart, channel, SC26C94_CMD_MR0); case 1: return sc26c94_command(quart, channel, SC26C94_CMD_MR1); case 2: /* There's no SC26C94_CMD_MR2. However, the pointer is incremented automatically every time the MR is accessed. Instead of using SC26C94_CMD_MR1 and then incrementing it, we just assume that it's at MR0 and increment it repeatedly. The pointer will not auto-increment beyond MR2. This way, we avoid the 2uS delay associated with using a command. */ (void)quart->readreg(quart, SC26C94_REGCHAN(SC26C94_REG_MR, channel)); (void)quart->readreg(quart, SC26C94_REGCHAN(SC26C94_REG_MR, channel)); return; } } int sc26c94_read_mr(struct sc26c94 *quart, int channel, int index) { sc26c94_seek_mr(quart, channel, index); return quart->readreg(quart, SC26C94_REGCHAN(SC26C94_REG_MR, channel)); } void sc26c94_write_mr(struct sc26c94 *quart, int channel, int index, int value) { sc26c94_seek_mr(quart, channel, index); quart->writereg(quart, SC26C94_REGCHAN(SC26C94_REG_MR, channel), value); } #if 0 /* * interrupt autoprobing support. * on platforms that make full use of the 2694's interrupt vector features, the * boot rom has programmed a write-only register in the 2694 to tell it what * vector to use. this probing can be used to determine what value has been * programmed. * the machine-specific driver needs to invoke these functions to do its probe. * first it should save any state (baud rates, etc) that it doesn't want * destroyed. * then it should call sc26c94_prepare_interrupt. this will get the chip ready * to send an interrupt; basically everything but actually triggering it. * then, after turning on the interrupt probing, it should call * sc26c94_cause_interrupt, then turn off the interrupt probing. * once it's done that, it can restore the state that was destroyed. * the point of separating _prepare and _cause is to keep the time window of the * actual probe as small as possible, to maximize accuracy. */ /* * The interrupt autoprobing does not work, at least on the VXT. So we don't use * it. * The problem is, the 2694 fires a billion interrupts at the CPU, unless the * interrupt handler clears the interrupt. During the autoprobe, the processor * ends up spending all its time in the stray interrupt handler, and never gets * around to returning to the driver code that would clear the interrupt! */ int sc26c94_prepare_interrupt(struct sc26c94 *quart) { int i; /* Just to be nice, if there are characters in the Tx buffer, wait for them to be printed before we screw everything up. */ for(i = 0; i < 100; i++) { if(quart->readreg(quart, SC26C94_REG_SRa) & SC26C94_SR_TXRDY) break; udelay(10); } /* First disable all the interrupts and turn off all the channels -- wouldn't want _two_ interrupts coming in ;-) */ quart->writereg(quart, SC26C94_REG_IMRab, 0); quart->writereg(quart, SC26C94_REG_IMRcd, 0); /* Set the threshold to allow all interrupts. Use the full IVR value as the interrupt vector. */ quart->writereg(quart, SC26C94_REG_ICR, SC26C94_IVC_IVR); /* Entice the transmitter to set TxRDY */ sc26c94_command(quart, SC26C94_PORT_A, SC26C94_CMD_RESET_TX); sc26c94_write_mr(quart, SC26C94_PORT_A, 2, 0); quart->writereg(quart, SC26C94_REG_CRa, SC26C94_CR_TX_ON); /* Wait for TxRDY to actually go high */ for(i = 0; i < 100; i++) { if(quart->readreg(quart, SC26C94_REG_ISRab) & SC26C94_ISR_TXa) break; udelay(10); } #if 0 printk("SC26C94_REG_ISRab=%x\n",quart->readreg(quart, SC26C94_REG_ISRab)); #endif if(i == 100) return -1; return 0; } int sc26c94_cause_interrupt(struct sc26c94 *quart) { int i; /* OK, TxRDY is high, now enable the interrupt-on-TxRDY! */ quart->writereg(quart, SC26C94_REG_IMRab, SC26C94_ISR_TXa); #if 1 /* for some wonderful reason i don't think this is generating an interrupt, so what the hell, enable all the other interrupts too */ quart->writereg(quart, SC26C94_REG_IMRab, 0xff); #endif /* wait until the interrupt has actually been sent */ for(i = 0; i < 100; i++) { if(SC26C94_CIR_TYPE(quart->readreg(quart, SC26C94_REG_CIR)) != SC26C94_CIR_NONE) break; udelay(10); } /* now disable the interrupt again */ quart->writereg(quart, SC26C94_REG_IMRab, 0); /* clear the interrupt, too (why not?) */ for(i=0;i<100;i++) quart->writereg(quart, SC26C94_CREG_UPDATE_CIR, 0); #if 0 printk("foo %d %x\n",i,quart->readreg(quart, SC26C94_REG_CIR)); mdelay(1000); #endif if(i == 100) return -1; return 0; } #endif /* * immediate putc and getc. the getc is blocking; the putc does not return until * the character has actually been handed to the uart. these are for console use * only; they are way ill-behaved for anything else. the normal, buffered getc * and putc are handled by generic_serial. */ void sc26c94_immediate_putc(struct sc26c94 *quart, int channel, unsigned char c) { unsigned long flags; save_flags(flags); cli(); /* right now, we don't limit the amount of time that we'll spend waiting for the uart to become ready, so we could conceivably sit here forever if the uart state has been corrupted */ while((quart->readreg(quart, (SC26C94_REGCHAN(SC26C94_REG_SR, channel))) & SC26C94_SR_TXRDY) == 0) ; quart->writereg(quart, SC26C94_REGCHAN(SC26C94_REG_THR, channel), c); restore_flags(flags); } unsigned char sc26c94_immediate_getc(struct sc26c94 *quart, int channel) { unsigned long flags; unsigned char c; save_flags(flags); cli(); while((quart->readreg(quart, (SC26C94_REGCHAN(SC26C94_REG_SR, channel))) & SC26C94_SR_RXRDY) == 0) ; c = quart->readreg(quart, SC26C94_REGCHAN(SC26C94_REG_RHR, channel)); restore_flags(flags); return c; } /* * read and write I/O pins */ static u8 io_bits[] = {SC26C94_IO_0a, SC26C94_IO_1a, SC26C94_IO_2a, SC26C94_IO_3a}; int sc26c94_read_io(struct sc26c94 *quart, int channum, int ionum) { int ipr_reg = (channum < SC26C94_PORT_C) ? SC26C94_REG_IPRab : SC26C94_REG_IPRcd; int ipr = quart->readreg(quart, ipr_reg); if((channum & 1) != 0) ipr >>= 2; return (ipr & io_bits[ionum & 3]) ? 1 : 0; } void sc26c94_write_io(struct sc26c94 *quart, int channum, int ionum, int val) { int opr_reg = (channum < SC26C94_PORT_C) ? SC26C94_REG_OPRab : SC26C94_REG_OPRcd; int opr; unsigned long flags; val = val ? 0 : io_bits[ionum & 3]; if((channum & 1) != 0) val <<= 2; save_flags(flags); cli(); opr = quart->readreg(quart, opr_reg); quart->writereg(quart, opr_reg, opr | val); restore_flags(flags); } void sc26c94_set_io_dir(struct sc26c94 *quart, int channum, int ionum, int val) { static int regnum[]={SC26C94_REG_IOPCRa, SC26C94_REG_IOPCRb, SC26C94_REG_IOPCRc, SC26C94_REG_IOPCRd}; /* can't use SC26C94_REGCHAN here */ u8 mask = 3; mask <<= (ionum & 3) * 2; val &= 3; val <<= (ionum & 3) * 2; quart->iopcr[channum & 3] &= ~mask; quart->iopcr[channum & 3] |= val; quart->writereg(quart, regnum[channum & 3], quart->iopcr[channum & 3]); } static void endis_delta_int(struct sc26c94 *quart, int channum, int ionum, int on) { int acrnum = (channum < SC26C94_PORT_C) ? 0 : 1; u8 mask = 1; on &= 1; if(ionum != 0) { on <<= 1; mask <<= 1; } if((channum & 1) != 0) { on <<= 2; mask <<= 2; } quart->acr[acrnum] &= ~mask; quart->acr[acrnum] |= on; quart->writereg(quart, (acrnum == 0) ? SC26C94_REG_ACRab : SC26C94_REG_ACRcd, quart->acr[acrnum]); } void sc26c94_register_delta_int(struct sc26c94 *quart, int channum, int ionum, void (*handler)(struct sc26c94 *quart, void *data, int state), void *data) { endis_delta_int(quart, channum, ionum, 0); quart->delta_handlers[channum & 3][ionum & 1].handler = handler; quart->delta_handlers[channum & 3][ionum & 1].data = data; endis_delta_int(quart, channum, ionum, 1); } void sc26c94_unregister_delta_int(struct sc26c94 *quart, int channum, int ionum) { endis_delta_int(quart, channum, ionum, 0); quart->delta_handlers[channum & 3][ionum & 1].handler = NULL; } /* * interrupt top half * on some platforms we are able to get tx and rx interrupts separately, and * also to get separate interrupts by channel. we don't take advantage of this. * we use a single interrupt vector for all events, and when we get an * interrupt, we take action to clear _all_ outstanding interrupt conditions. * since the quart will tell us what the highest-priority outstanding interrupt * is, we don't have to waste time polling every possible source. */ static inline void interrupt_tx(struct sc26c94 *quart, int channum, int size) { struct sc26c94_chan *chan=&(quart->chans[channum]); int chars, i; /* if we have any xon/xoff characters queued, shove them out first */ if(chan->xchar) { quart->writereg(quart, SC26C94_REG_GTHR, chan->xchar); chan->xchar=0; size--; if(size == 0) return; } chars = chan->gs.xmit_cnt; if(chars > size) chars = size; if(chan->gs.xmit_cnt < 0 || !chan->gs.tty || chan->gs.tty->stopped || chan->gs.tty->hw_stopped) chars = 0; for(i = 0; i < chars; i++) { quart->writereg(quart, SC26C94_REG_GTHR, chan->gs.xmit_buf[chan->gs.xmit_tail]); chan->gs.xmit_tail++; chan->gs.xmit_tail &= (SERIAL_XMIT_SIZE-1); } chan->gs.xmit_cnt-=chars; if(chars == 0 || chan->gs.xmit_cnt == 0) disable_tx_ints(chan); if(chan->gs.tty && chan->gs.xmit_cnt <= chan->gs.wakeup_chars) { if ((chan->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && chan->gs.tty->ldisc.write_wakeup) (chan->gs.tty->ldisc.write_wakeup)(chan->gs.tty); wake_up_interruptible(&chan->gs.tty->write_wait); } } static inline void interrupt_rx(struct sc26c94 *quart, int channum, int size, int e) { struct sc26c94_chan *chan=&(quart->chans[channum]); struct tty_flip_buffer *flip; int chars, i; u8 sr; if(!chan->gs.tty) { disable_rx_ints(chan); return; } flip=&(chan->gs.tty->flip); chars = size; if(chars > TTY_FLIPBUF_SIZE - flip->count) chars = TTY_FLIPBUF_SIZE - flip->count; for(i = 0; i < chars; i++) { if(e) { sr = quart->readreg(quart, SC26C94_REGCHAN(SC26C94_REG_SR, channum)); if(sr & SC26C94_SR_BRK) { *(flip->flag_buf_ptr++) = TTY_BREAK; } else if(sr & SC26C94_SR_FRAME) { *(flip->flag_buf_ptr++) = TTY_FRAME; } else if(sr & SC26C94_SR_PARITY) { *(flip->flag_buf_ptr++) = TTY_PARITY; } else if(sr & SC26C94_SR_OVER) { /* technically this one isn't associated with the fifo character */ *(flip->flag_buf_ptr++) = TTY_OVERRUN; } else { *(flip->flag_buf_ptr++) = 0; } sc26c94_command(quart, channum, SC26C94_CMD_RESET_ERR); } else { *(flip->flag_buf_ptr++) = 0; } *(flip->char_buf_ptr++) = quart->readreg(quart, SC26C94_REG_GRHR); } flip->count+=chars; /* uhh. so what happens at this point if we filled the entire flip buffer but there are still more characters in the fifo? will we loop infinitely? */ tty_flip_buffer_push(chan->gs.tty); } static inline void interrupt_state(struct sc26c94 *quart, int channum) { u8 ipcr = quart->readreg(quart, (channum < SC26C94_PORT_C) ? SC26C94_REG_IPCRab : SC26C94_REG_IPCRcd); u8 deltamask, statemask; int thischan = (channum < SC26C94_PORT_C) ? SC26C94_PORT_B : SC26C94_PORT_D; int thisio = 1; void (*handler)(struct sc26c94 *quart, void *data, int state); void *data; /* at this point, up to 4 pins may have changed state, but we cleared the whole interrupt by reading the ipcr */ for(deltamask = SC26C94_IPCR_DELTA1b, statemask = SC26C94_IPCR_STATE1b; statemask != 0; deltamask >>= 1, statemask >>= 1) { if((ipcr & deltamask) != 0) { handler = quart->delta_handlers[thischan][thisio].handler; data = quart->delta_handlers[thischan][thisio].data; handler(quart, data, (ipcr & statemask) ? 1 : 0); } thisio--; if(thisio < 0) { thisio = 1; thischan--; } } } static inline void interrupt_break(struct sc26c94 *quart, int channum) { printk("sc26c94: unexpected interrupt_break\n"); sc26c94_command(quart, channum, SC26C94_CMD_RESET_BCI); } static inline void interrupt_ct(struct sc26c94 *quart, int channum) { printk("sc26c94: unexpected interrupt_ct\n"); modify_imr(quart, 0, ~SC26C94_ISR_CT, 0); modify_imr(quart, 1, ~SC26C94_ISR_CT, 0); } void sc29c94_interrupt(int vector, void *data, struct pt_regs *fp) { struct sc26c94 *quart = data; u8 cir, size, chan; #if 1 printk("%%"); #endif for(;;) { cir = quart->readreg(quart, SC26C94_REG_CIR); size = SC26C94_CIR_SIZE(cir); chan = SC26C94_CIR_CHAN(cir); switch(SC26C94_CIR_TYPE(cir)) { case SC26C94_CIR_NONE: return; case SC26C94_CIR_TX1: case SC26C94_CIR_TX2: interrupt_tx(quart, chan, size); break; case SC26C94_CIR_RX: interrupt_rx(quart, chan, size, 0); break; case SC26C94_CIR_RXE: interrupt_rx(quart, chan, size, 1); break; case SC26C94_CIR_STATE: interrupt_state(quart, chan); break; case SC26C94_CIR_BRK: interrupt_break(quart, chan); break; case SC26C94_CIR_CT: interrupt_ct(quart, chan); break; default: /* can never happen */ break; } /* we've just finished handing 1 interrupt source. now clear it and go back and see if there are any more. */ quart->writereg(quart, SC26C94_CREG_UPDATE_CIR, 0); } } /* * callbacks for generic_serial */ static void modify_imr(struct sc26c94 *quart, int whichimr, u8 andmask, u8 ormask) { int imr_reg = (whichimr == 0) ? SC26C94_REG_IMRab : SC26C94_REG_IMRcd; quart->imr[whichimr & 1] &= andmask; quart->imr[whichimr & 1] |= ormask; quart->writereg(quart, imr_reg, quart->imr[whichimr & 1]); } static void disable_tx_ints(void *ptr) { struct sc26c94_chan *chan = ptr; struct sc26c94 *quart = chan->quart; u8 imr_bit = ((chan->channel & 1) != 0) ? SC26C94_ISR_TXb : SC26C94_ISR_TXa; modify_imr(quart, (chan->channel < SC26C94_PORT_C) ? 0 : 1, ~imr_bit, 0); } static void enable_tx_ints(void *ptr) { struct sc26c94_chan *chan = ptr; struct sc26c94 *quart = chan->quart; u8 imr_bit = ((chan->channel & 1) != 0) ? SC26C94_ISR_TXb : SC26C94_ISR_TXa; modify_imr(quart, (chan->channel < SC26C94_PORT_C) ? 0 : 1, 255, imr_bit); } static void disable_rx_ints(void *ptr) { struct sc26c94_chan *chan = ptr; struct sc26c94 *quart = chan->quart; u8 imr_bit = ((chan->channel & 1) != 0) ? SC26C94_ISR_RXb : SC26C94_ISR_RXa; modify_imr(quart, (chan->channel < SC26C94_PORT_C) ? 0 : 1, ~imr_bit, 0); } static void enable_rx_ints(void *ptr) { struct sc26c94_chan *chan = ptr; struct sc26c94 *quart = chan->quart; u8 imr_bit = ((chan->channel & 1) != 0) ? SC26C94_ISR_RXb : SC26C94_ISR_RXa; modify_imr(quart, (chan->channel < SC26C94_PORT_C) ? 0 : 1, 255, imr_bit); } static int get_CD(void *ptr) { struct sc26c94_chan *chan = ptr; return chan->quart->get_cd(chan->quart, chan->channel); } static void shutdown_port(void *ptr) { struct sc26c94_chan *chan = ptr; chan->gs.flags &= ~GS_ACTIVE; if (chan->gs.tty && chan->gs.tty->termios->c_cflag & HUPCL) chan->quart->set_handshake(chan->quart, chan->channel, 0); } static int set_real_termios(void *ptr) { struct sc26c94_chan *chan = ptr; unsigned int cflag; unsigned long flags; u8 foo; if (!chan->gs.tty || !chan->gs.tty->termios) return 0; cflag = chan->gs.tty->termios->c_cflag; if(chan->gs.baud == 0) { chan->quart->set_handshake(chan->quart, chan->channel, 0); } else { if(chan->quart->set_speed(chan->quart, chan->channel, chan->gs.baud) != 0) printk("Could not set serial speed\n"); chan->quart->set_handshake(chan->quart, chan->channel, 1); } if (cflag & CLOCAL) { chan->gs.flags &= ~ASYNC_CHECK_CD; } else { chan->gs.flags |= ASYNC_CHECK_CD; } foo = (cflag & CSIZE) >> 4; if((cflag & PARENB) == 0) foo |= SC26C94_MR1_PAR_NONE; if(cflag & PARODD) foo |= SC26C94_MR1_PARODD; save_flags(flags); cli(); sc26c94_write_mr(chan->quart, chan->channel, 1, foo); foo = (cflag & CSTOPB) ? SC26C94_MR2_STOP_2000 : SC26C94_MR2_STOP_1000; sc26c94_write_mr(chan->quart, chan->channel, 2, foo); restore_flags(flags); return 0; } static int chars_in_buffer(void *ptr) { struct sc26c94_chan *chan = ptr; u8 sr; sr=chan->quart->readreg(chan->quart, SC26C94_REGCHAN(SC26C94_REG_SR, chan->channel)); return (sr & SC26C94_SR_TXEMT) ? 0 : 1; } /* uhh. what are hungup and close really for? */ static void hungup(void *ptr) { disable_tx_ints(ptr); disable_rx_ints(ptr); MOD_DEC_USE_COUNT; } static void closefu(void *ptr) { disable_tx_ints(ptr); disable_rx_ints(ptr); } /* * callbacks for tty_driver */ int sc26c94_open(struct sc26c94 *quart, struct tty_struct *tty, struct file *filp) { struct sc26c94_chan *chan; int retval, line; line = MINOR(tty->device); if(line < 0 || line >= 4) return -ENODEV; chan = &(quart->chans[line]); tty->driver_data = chan; chan->gs.tty = tty; if(!chan->gs.count) MOD_INC_USE_COUNT; chan->gs.count++; retval = gs_init_port(&chan->gs); if(retval) { chan->gs.count--; if(!chan->gs.count) MOD_DEC_USE_COUNT; return retval; } chan->gs.flags |= GS_ACTIVE; /* uhh. shouldn't there be a way to open the port without glitching these pins? */ quart->set_handshake(quart, 4, 1); quart->set_flow(quart, 4, 1); retval = gs_block_til_ready(chan, filp); if(retval) return retval; if((chan->gs.count == 1) && (chan->gs.flags & ASYNC_SPLIT_TERMIOS)) { if (tty->driver.subtype == SERIAL_TYPE_NORMAL) { *tty->termios = chan->gs.normal_termios; } else { *tty->termios = chan->gs.callout_termios; } set_real_termios(chan); } chan->gs.session = current->session; chan->gs.pgrp = current->pgrp; return 0; } static void send_xchar(struct sc26c94_chan *chan, char c) { chan->xchar = c; if(c) enable_tx_ints(chan); } static void sc26c94_throttle(struct tty_struct *tty) { struct sc26c94_chan *chan = (struct sc26c94_chan *)tty->driver_data; if(tty->termios->c_cflag & CRTSCTS) chan->quart->set_flow(chan->quart, chan->channel, 0); if(I_IXOFF(tty)) send_xchar(chan, STOP_CHAR(tty)); } static void sc26c94_unthrottle(struct tty_struct *tty) { struct sc26c94_chan *chan = (struct sc26c94_chan *)tty->driver_data; if(tty->termios->c_cflag & CRTSCTS) chan->quart->set_flow(chan->quart, chan->channel, 0); if(I_IXOFF(tty)) send_xchar(chan, START_CHAR(tty)); } static int sc26c94_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; } static void sc26c94_break_ctl(struct tty_struct *tty, int break_state) { struct sc26c94_chan *chan = (struct sc26c94_chan *)tty->driver_data; unsigned long flags; save_flags(flags); cli(); sc26c94_command(chan->quart, chan->channel, break_state ? SC26C94_CMD_BREAK_ON : SC26C94_CMD_BREAK_OFF); restore_flags(flags); } /* * initialization code */ static struct real_driver real_driver = { disable_tx_ints, enable_tx_ints, disable_rx_ints, enable_rx_ints, get_CD, shutdown_port, set_real_termios, chars_in_buffer, closefu, hungup, NULL }; /* this stuff is used by the tty_driver somehow */ static struct tty_struct *table[4] = { NULL, }; static struct termios * termios[4]; static struct termios * termios_locked[4]; static int refcount; void sc26c94_init_drivers(struct tty_driver *tty_driver, struct tty_driver *callout_driver) { memset(tty_driver, 0, sizeof(struct tty_driver)); tty_driver->magic = TTY_DRIVER_MAGIC; tty_driver->name = "ttyS"; tty_driver->major = TTY_MAJOR; tty_driver->minor_start = 64; tty_driver->num = 2; tty_driver->type = TTY_DRIVER_TYPE_SERIAL; tty_driver->subtype = SERIAL_TYPE_NORMAL; tty_driver->init_termios = tty_std_termios; tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_driver->flags = TTY_DRIVER_REAL_RAW; tty_driver->refcount = &refcount; tty_driver->table = table; tty_driver->termios = termios; tty_driver->termios_locked = termios_locked; /* tty_driver->open = sc26c94_open; */ tty_driver->close = gs_close; tty_driver->write = gs_write; tty_driver->put_char = gs_put_char; tty_driver->flush_chars = gs_flush_chars; tty_driver->write_room = gs_write_room; tty_driver->chars_in_buffer = gs_chars_in_buffer; tty_driver->flush_buffer = gs_flush_buffer; tty_driver->ioctl = sc26c94_ioctl; tty_driver->throttle = sc26c94_throttle; tty_driver->unthrottle = sc26c94_unthrottle; tty_driver->set_termios = gs_set_termios; tty_driver->stop = gs_stop; tty_driver->start = gs_start; tty_driver->hangup = gs_hangup; tty_driver->break_ctl = sc26c94_break_ctl; memcpy(callout_driver, tty_driver, sizeof(struct tty_driver)); callout_driver->name = "cua"; callout_driver->major = TTYAUX_MAJOR; callout_driver->subtype = SERIAL_TYPE_CALLOUT; /* at this point, tty_driver and callout_driver are ready to be tty_register_driver()'d (after adding .open) */ } void sc26c94_init_chanstructs(struct sc26c94 *quart) { struct sc26c94_chan *chan; int i; for(i = 0; i < 4; i++) { chan = &(quart->chans[i]); chan->quart = quart; chan->channel = i; chan->xchar = 0; chan->gs.callout_termios = tty_std_termios; chan->gs.normal_termios = tty_std_termios; chan->gs.close_delay = HZ/2; chan->gs.closing_wait = 30 * HZ; chan->gs.rd = &real_driver; #ifdef NEW_WRITE_LOCKING chan->gs.port_write_sem = MUTEX; #endif init_waitqueue_head(&chan->gs.open_wait); init_waitqueue_head(&chan->gs.close_wait); } } void sc26c94_init_chip(struct sc26c94 *quart) { int i; modify_imr(quart, 0, 0, 0); modify_imr(quart, 1, 0, 0); for(i = SC26C94_PORT_A; i <= SC26C94_PORT_D; i++) { sc26c94_command(quart, i, SC26C94_CMD_RESET_TX); sc26c94_command(quart, i, SC26C94_CMD_RESET_RX); sc26c94_write_mr(quart, i, 0, 0); sc26c94_write_mr(quart, i, 1, 0); sc26c94_write_mr(quart, i, 2, 0); quart->writereg(quart, SC26C94_REGCHAN(SC26C94_REG_BCR, i), 0); } /* On the VXT, the counter/timers must be stopped AFTER we have done any sc26c94_command()'s we're going to do. for some reason it looks like udelay() will hang if we call it with the second timer stopped */ /* btw, these might not actually stop the C/T, see datasheet p.17 */ (void) quart->readreg(quart, SC26C94_CREG_STOPCTab); (void) quart->readreg(quart, SC26C94_CREG_STOPCTcd); /* IOPCR and BCR registers aren't numbered the same way as the others, so we can't use SC26C94_REGCHAN() with them */ quart->writereg(quart, SC26C94_REG_IOPCRa, 0); quart->writereg(quart, SC26C94_REG_IOPCRb, 0); quart->writereg(quart, SC26C94_REG_IOPCRc, 0); quart->writereg(quart, SC26C94_REG_IOPCRd, 0); quart->iopcr[0] = 0; quart->iopcr[1] = 0; quart->iopcr[2] = 0; quart->iopcr[3] = 0; quart->writereg(quart, SC26C94_REG_BCRa, 0); quart->writereg(quart, SC26C94_REG_BCRb, 0); quart->writereg(quart, SC26C94_REG_BCRc, 0); quart->writereg(quart, SC26C94_REG_BCRd, 0); quart->writereg(quart, SC26C94_REG_ICR, SC26C94_IVC_IVR); quart->writereg(quart, SC26C94_REG_ACRab, 0); quart->writereg(quart, SC26C94_REG_ACRcd, 0); quart->acr[0] = 0; quart->acr[1] = 0; /* Enable the main mask for the I/O port change interrupts. Don't worry, those interrupts aren't actually enabled until they're turned on in the ACR. */ modify_imr(quart, 0, 0, SC26C94_ISR_IO); modify_imr(quart, 1, 0, SC26C94_ISR_IO); } --- NEW FILE --- /* * Registers */ /* channels A and B */ #define SC26C94_REG_MRa 0 /* Mode Register, actually 3 registers (rw) */ #define SC26C94_REG_SRa 1 /* Status Register (r) */ #define SC26C94_REG_CSRa 1 /* Clock Select Register (w) */ #define SC26C94_REG_CRa 2 /* Command Register (w) */ #define SC26C94_REG_RHRa 3 /* Receive Holding Register (RxFIFO) (r) */ #define SC26C94_REG_THRa 3 /* Transmit Holding Register (TxFIFO) (w) */ #define SC26C94_REG_IPCRab 4 /* Input Port Change Register (r) */ #define SC26C94_REG_ACRab 4 /* Auxiliary Control Register (w) */ #define SC26C94_REG_ISRab 5 /* Interrupt Status Register (r) */ #define SC26C94_REG_IMRab 5 /* Interrupt Mask Register (w) */ #define SC26C94_REG_CTUab 6 /* Counter/Timer high-order byte (rw) */ #define SC26C94_REG_CTLab 7 /* Counter/Timer low-order byte (rw) */ #define SC26C94_REG_MRb 8 /* Mode Register, actually 3 registers (rw) */ #define SC26C94_REG_SRb 9 /* Status Register (r) */ #define SC26C94_REG_CSRb 9 /* Clock Select Register (w) */ #define SC26C94_REG_CRb 10 /* Command Register (w) */ #define SC26C94_REG_RHRb 11 /* Receive Holding Register (RxFIFO) (r) */ #define SC26C94_REG_THRb 11 /* Transmit Holding Register (TxFIFO) (w) */ #define SC26C94_REG_OPRab 12 /* Output Port Register (rw) */ #define SC26C94_REG_IPRab 13 /* Input Port Register (r) */ #define SC26C94_REG_IOPCRa 13 /* I/O Port Control Register (w) */ #define SC26C94_CREG_STARTCTab 14 /* Start Counter command (r) */ #define SC26C94_REG_IOPCRb 14 /* I/O Port Control Register (w) */ #define SC26C94_CREG_STOPCTab 15 /* Stop Counter command (r) */ #define SC26C94_REG_BCRa 32 /* interrupt Bidding Control Register (rw) */ #define SC26C94_REG_BCRb 33 /* interrupt Bidding Control Register (rw) */ /* channels C and D */ #define SC26C94_REG_MRc 16 /* Mode Register, actually 3 registers (rw) */ #define SC26C94_REG_SRc 17 /* Status Register (r) */ #define SC26C94_REG_CSRc 17 /* Clock Select Register (w) */ #define SC26C94_REG_CRc 18 /* Command Register (w) */ #define SC26C94_REG_RHRc 19 /* Receive Holding Register (RxFIFO) (r) */ #define SC26C94_REG_THRc 19 /* Transmit Holding Register (TxFIFO) (w) */ #define SC26C94_REG_IPCRcd 20 /* Input Port Change Register (r) */ #define SC26C94_REG_ACRcd 20 /* Auxiliary Control Register (w) */ #define SC26C94_REG_ISRcd 21 /* Interrupt Status Register (r) */ #define SC26C94_REG_IMRcd 21 /* Interrupt Mask Register (w) */ #define SC26C94_REG_CTUcd 22 /* Counter/Timer high-order byte (rw) */ #define SC26C94_REG_CTLcd 23 /* Counter/Timer low-order byte (rw) */ #define SC26C94_REG_MRd 24 /* Mode Register, actually 3 registers (rw) */ #define SC26C94_REG_SRd 25 /* Status Register (r) */ #define SC26C94_REG_CSRd 25 /* Clock Select Register (w) */ #define SC26C94_REG_CRd 26 /* Command Register (w) */ #define SC26C94_REG_RHRd 27 /* Receive Holding Register (RxFIFO) (r) */ #define SC26C94_REG_THRd 27 /* Transmit Holding Register (TxFIFO) (w) */ #define SC26C94_REG_OPRcd 28 /* Output Port Register (rw) */ #define SC26C94_REG_IPRcd 29 /* Input Port Register (r) */ #define SC26C94_REG_IOPCRc 29 /* I/O Port Control Register (w) */ #define SC26C94_CREG_STARTCTcd 30 /* Start Counter command (r) */ #define SC26C94_REG_IOPCRd 30 /* I/O Port Control Register (w) */ #define SC26C94_CREG_STOPCTcd 31 /* Stop Counter command (r) */ #define SC26C94_REG_BCRc 34 /* interrupt Bidding Control Register (rw) */ #define SC26C94_REG_BCRd 35 /* interrupt Bidding Control Register (rw) */ /* global */ #define SC26C94_CREG_POWER_DOWN 36 /* Power Down (w) */ #define SC26C94_CREG_POWER_UP 37 /* Power Up (w) */ #define SC26C94_CREG_DIS_DACKN 38 /* Disable DACKN (w) */ #define SC26C94_CREG_EN_DACKN 39 /* Enable DACKN (w) */ #define SC26C94_REG_CIR 40 /* Current Interrupt Register (r) */ #define SC26C94_REG_GICR 41 /* Global Interrupting Channel Register (r) */ #define SC26C94_REG_IVR 41 /* Interrupt Vector Register (w) */ #define SC26C94_REG_GIBCR 42 /* Global Interrupt Byte Count Register (r) */ #define SC26C94_CREG_UPDATE_CIR 42 /* Update CIR (w) */ #define SC26C94_REG_GRHR 43 /* Global Receive Holding Reg (RxFIFO) (r) */ #define SC26C94_REG_GTHR 43 /* Global Transmit Holding Reg (TxFIFO) (w) */ #define SC26C94_REG_ICR 44 /* Interrupt Control Register (ICR) (rw) */ #define SC26C94_REG_BRGRATE 45 /* BRG Rate (w) */ #define SC26C94_CREG_CLK_DIV2 46 /* Set X1/CLK divide by two (w) */ #define SC26C94_CREG_CLK_NORM 47 /* Set X1/CLK normal (w) */ #define SC26C94_REG_TEST 57 /* Test Mode (rw) */ #define SC26C94_REGCHAN(x,y) (x ## a + ((y & 3) << 3)) /* * Command Register commands */ #define SC26C94_CMD_MR1 1 /* Set MR pointer to MR1 */ #define SC26C94_CMD_RESET_RX 2 /* Reset the receiver */ #define SC26C94_CMD_RESET_TX 3 /* Reset the transmitter */ #define SC26C94_CMD_RESET_ERR 4 /* Clear the error status */ #define SC26C94_CMD_RESET_BCI 5 /* Clear the break detect change ISR bit */ #define SC26C94_CMD_BREAK_ON 6 /* Start sending a break */ #define SC26C94_CMD_BREAK_OFF 7 /* Stop sending a break */ #define SC26C94_CMD_RTSN_ON 8 /* Assert RTSN */ #define SC26C94_CMD_RTSN_OFF 9 /* Negate RTSN */ #define SC26C94_CMD_TIMEOUT_ON 10 /* Enable timeout mode */ #define SC26C94_CMD_MR0 11 /* Set MR pointer to MR0 */ #define SC26C94_CMD_TIMEOUT_OFF 12 /* Disable timeout mode */ /* * register formats */ #define SC26C94_IVC_IVR 0 /* Use the full IVC value as interrupt vector */ #define SC26C94_IVC_CHAN 1 /* Use IVC and channel number to make vector */ #define SC26C94_IVC_TYPE_CHAN 2 /* Use IVC, channel, and type to make vector */ #define SC26C94_IVC_INHIBIT 3 /* Use a vector of 0xff */ #define SC26C94_ISR_IO 128 /* I/O Port Change */ #define SC26C94_ISR_BRKb 64 /* Delta BREAKb */ #define SC26C94_ISR_RXb 32 /* RxRDY/FFULLb */ #define SC26C94_ISR_TXb 16 /* TxRDYb */ #define SC26C94_ISR_CT 8 /* Counter Ready */ #define SC26C94_ISR_BRKa 4 /* Delta BREAKa */ #define SC26C94_ISR_RXa 2 /* RxRDY/FFULLa */ #define SC26C94_ISR_TXa 1 /* TxRDYa */ #define SC26C94_CIR_CHAN(x) (x & 3) #define SC26C94_CIR_TYPE(x) ((x >> 2) & 7) #define SC26C94_CIR_SIZE(x) ((x >> 5) & 7) #define SC26C94_CIR_NONE 0 /* No Interrupt */ #define SC26C94_CIR_STATE 1 /* Change of State */ #define SC26C94_CIR_TX1 2 /* Transmit available */ #define SC26C94_CIR_RX 3 /* Receive available, no error */ #define SC26C94_CIR_BRK 4 /* Receiver break change */ #define SC26C94_CIR_CT 5 /* Counter/Timer */ #define SC26C94_CIR_TX2 6 /* Transmit available (alternate encoding) */ #define SC26C94_CIR_RXE 7 /* Receive available, with errors */ #define SC26C94_SR_BRK 128 /* Received Break */ #define SC26C94_SR_FRAME 64 /* Framing Error */ #define SC26C94_SR_PARITY 32 /* Parity Error */ #define SC26C94_SR_OVER 16 /* Overrun Error */ #define SC26C94_SR_TXEMT 8 /* Tx Empty */ #define SC26C94_SR_TXRDY 4 /* Tx Ready */ #define SC26C94_SR_RXFULL 2 /* Rx Full */ #define SC26C94_SR_RXRDY 1 /* Rx Ready */ #define SC26C94_CR_TX_OFF 8 /* Disable Tx */ #define SC26C94_CR_TX_ON 4 /* Enable Tx */ #define SC26C94_CR_RX_OFF 2 /* Disable Tx */ #define SC26C94_CR_RX_ON 1 /* Enable Rx */ #define SC26C94_MR1_RXRTS 128 /* RxRTS Control */ #define SC26C94_MR1_RXINT1 64 /* RxINT1 Select */ #define SC26C94_MR1_ERRMODE 32 /* Char/Block Error Mode */ #define SC26C94_MR1_PAR_MASK 24 /* Parity Mode */ #define SC26C94_MR1_PAR_WITH 0 /* With Parity */ #define SC26C94_MR1_PAR_FORCE 8 /* Force Parity */ #define SC26C94_MR1_PAR_NONE 16 /* No Parity */ #define SC26C94_MR1_PAR_WAKE 24 /* Wake-Up Mode */ #define SC26C94_MR1_PARODD 4 /* Parity Type (1=odd) */ #define SC26C94_MR1_CSIZE_MASK 1 /*Bits per Character */ #define SC26C94_MR1_CSIZE_5 0 #define SC26C94_MR1_CSIZE_6 1 #define SC26C94_MR1_CSIZE_7 2 #define SC26C94_MR1_CSIZE_8 3 #define SC26C94_MR2_MODE_MASK 192 /* Channel Mode: */ #define SC26C94_MR2_MODE_NORM 0 /* Normal */ #define SC26C94_MR2_MODE_ECHO 64 /* Auto-echo */ #define SC26C94_MR2_MODE_LLOOP 128 /* Local loop */ #define SC26C94_MR2_MODE_RLOOP 192 /* Remote loop */ #define SC26C94_MR2_TXRTS 32 /* TxRTS Control */ #define SC26C94_MR2_TXCTS 16 /* TxCTS Control */ #define SC26C94_MR2_STOP_MASK 15 /*Stop Bit Length: */ #define SC26C94_MR2_STOP_1000 7 /* 1.000 */ #define SC26C94_MR2_STOP_2000 15 /* 2.000 */ #define SC26C94_IO_3b 128 #define SC26C94_IO_2b 64 #define SC26C94_IO_3a 32 #define SC26C94_IO_2a 16 #define SC26C94_IO_1b 8 #define SC26C94_IO_0b 4 #define SC26C94_IO_1a 2 #define SC26C94_IO_0a 1 #define SC26C94_IOPCR_INPUT 0 #define SC26C94_IOPCR_OUTPUT 1 #define SC26C94_IOPCR_CLOCK1 2 /* TxC or RxC, 16x or 1x, or C/T, dep on port */ #define SC26C94_IOPCR_CLOCK2 3 /* TxC or RxC, 16x or 1x, depending on port */ #define SC26C94_IPCR_DELTA1b 128 #define SC26C94_IPCR_DELTA0b 64 #define SC26C94_IPCR_DELTA1a 32 #define SC26C94_IPCR_DELTA0a 16 #define SC26C94_IPCR_STATE1b 8 #define SC26C94_IPCR_STATE0b 4 #define SC26C94_IPCR_STATE1a 2 #define SC26C94_IPCR_STATE0a 1 /* * */ #define SC26C94_PORT_A 0 #define SC26C94_PORT_B 1 #define SC26C94_PORT_C 2 #define SC26C94_PORT_D 3 /* * */ struct sc26c94_chan { struct sc26c94 *quart; int channel; struct gs_port gs; char xchar; }; struct sc26c94 { struct sc26c94_chan chans[4]; /* We do all register I/O through these function calls. It may be a bit slower than doing it directly, but it should be worth it from a portability standpoint. */ u8 (*readreg)(struct sc26c94 *quart, int register); void (*writereg)(struct sc26c94 *quart, int register, u8 value); /* The 2694 does not have dedicated pins for DTR and so forth. It does have generic I/O pins, though. Since different machines may implement (or not implement) this functionality using different I/O pins, we call back to the platform-specific code to handle this. The set_ routines are used to send status to the peer, the get_ routines are used to get the peer's status. The _handshake routines deal with DTR/DSR, the _flow routines deal with RTS/CTS. These routines may be called with interrupts on, so they will need to disable interrupts if appropriate. */ void (*set_handshake)(struct sc26c94 *quart, int channel, int ready); int (*get_handshake)(struct sc26c94 *quart, int channel); void (*set_flow)(struct sc26c94 *quart, int channel, int on); int (*get_flow)(struct sc26c94 *quart, int channel); /* is this used? */ int (*get_cd)(struct sc26c94 *quart, int channel); /* It is not possible on the 2694 to set all the channels to arbitrary baud rates independently of one another. The baud rate chosen for one channel affects the set of available baud rates on other channels. (See the data sheet for full details.) On a given machine, some channels may be dedicated to a keyboard or mouse interface, while others may be unused. By giving these channels a more limited selection of baud rates, the other channels can have a larger selection. So we leave it to the platform-specific code to decide how to manage the baud-rate generators. */ int (*set_speed)(struct sc26c94 *quart, int channel, int bps); /* platform-specific code can point machdep to a struct that stores i/o addresses or whatever */ void *machdep; /* shadow copies of the write-only registers */ u8 iopcr[4]; u8 acr[2]; u8 imr[2]; /* interrupt handlers for the change-of-state detectors for the i/o pins. indexed as delta_handlers[channel][ionum] */ struct { void (*handler)(struct sc26c94 *quart, void *data, int state); void *data; } delta_handlers[4][2]; }; /* * */ void sc26c94_command(struct sc26c94 *quart, int channel, int command); int sc26c94_read_mr(struct sc26c94 *quart, int channel, int index); void sc26c94_write_mr(struct sc26c94 *quart, int channel, int index, int value); int sc26c94_prepare_interrupt(struct sc26c94 *quart); int sc26c94_cause_interrupt(struct sc26c94 *quart); void sc26c94_immediate_putc(struct sc26c94 *quart, int channel, unsigned char c); unsigned char sc26c94_immediate_getc(struct sc26c94 *quart, int channel); int sc26c94_read_io(struct sc26c94 *quart, int channum, int ionum); void sc26c94_write_io(struct sc26c94 *quart, int channum, int ionum, int val); void sc26c94_set_io_dir(struct sc26c94 *quart, int channum, int ionum, int val); void sc26c94_register_delta_int(struct sc26c94 *quart, int channum, int ionum, void (*handler)(struct sc26c94 *quart, void *data, int state), void *data); void sc26c94_unregister_delta_int(struct sc26c94 *quart, int channum, int ionum); void sc29c94_interrupt(int vector, void *data, struct pt_regs *fp); int sc26c94_open(struct sc26c94 *quart, struct tty_struct *tty, struct file *filp); void sc26c94_init_drivers(struct tty_driver *tty_driver, struct tty_driver *callout_driver); void sc26c94_init_chanstructs(struct sc26c94 *quart); void sc26c94_init_chip(struct sc26c94 *quart); Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/char/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Makefile 11 Apr 2002 13:30:51 -0000 1.2 +++ Makefile 29 May 2002 03:37:39 -0000 1.3 @@ -211,6 +211,7 @@ obj-$(CONFIG_H8) += h8.o obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_DZ) += dz.o +obj-$(CONFIG_VXT2694) += sc26c94.o vxt2694.o generic_serial.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o Index: tty_io.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/char/tty_io.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- tty_io.c 11 Apr 2002 13:30:59 -0000 1.5 +++ tty_io.c 29 May 2002 03:37:39 -0000 1.6 @@ -2378,4 +2378,7 @@ #ifdef CONFIG_A2232 a2232board_init(); #endif +#ifdef CONFIG_VXT2694 + vxt2694_init(); +#endif } |
From: ? <uns...@us...> - 2002-05-29 03:37:44
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel In directory usw-pr-cvs1:/tmp/cvs-serv31994/arch/vax/kernel Modified Files: cpu_vxt.c Log Message: First attempt at a real serial driver for the SC26C94 in the VXT2000. Index: cpu_vxt.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/cpu_vxt.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- cpu_vxt.c 22 May 2002 23:16:25 -0000 1.5 +++ cpu_vxt.c 29 May 2002 03:37:40 -0000 1.6 @@ -25,10 +25,11 @@ void vxt_init_devices(void); const char *vxt_cpu_type_str(void); +#ifndef CONFIG_VXT2694 void vxt_putchar(int c); int vxt_getchar(void); void init_vxt_console(unsigned long phys_addr); - +#endif struct vxt_machine_vector { struct vax_mv mv; @@ -44,8 +45,13 @@ ka4x_prom_putchar, /* pre_vm_putchar */ ka4x_prom_getchar, /* pre_vm_getchar */ +#ifndef CONFIG_VXT2694 vxt_putchar, /* post_vm_putchar */ vxt_getchar, /* post_vm_getchar */ +#else + NULL, + NULL, +#endif NULL, /* console_init */ @@ -67,11 +73,18 @@ mv_vxt.sidex = *(unsigned int *)SOC_SIDEX_ADDR; } +#ifdef CONFIG_VXT2694 +extern void vxt_serial_console_init(void); +#endif void vxt_post_vm_init(void) { +#ifndef CONFIG_VXT2694 init_vxt_console(0x200A0000); register_console(&vax_console); +#else + vxt_serial_console_init(); +#endif } @@ -93,6 +106,7 @@ are intended as a quick way to get post-VM output on the VXT2000 in serial console mode until there's a proper driver. */ +#ifndef CONFIG_VXT2694 volatile int *vxt2694_addr = NULL; void vxt_putchar(int c) @@ -120,4 +134,4 @@ vxt2694_addr = ioremap(phys_addr, 256); } - +#endif |
From: ? <uns...@us...> - 2002-05-29 03:37:43
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax In directory usw-pr-cvs1:/tmp/cvs-serv31994/arch/vax Modified Files: config.in Log Message: First attempt at a real serial driver for the SC26C94 in the VXT2000. Index: config.in =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/config.in,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- config.in 25 Apr 2002 08:46:20 -0000 1.12 +++ config.in 29 May 2002 03:37:39 -0000 1.13 @@ -162,6 +162,7 @@ if [ "$CONFIG_SERIAL" = "y" ]; then bool 'DZ11 Serial Support' CONFIG_DZ bool 'CPU register-based Serial Console Support' CONFIG_SERIAL_MTPR + bool 'SC26C94 Serial Support (for VXT2000)' CONFIG_VXT2694 bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS |
From: ? <uns...@us...> - 2002-05-29 03:37:43
|
Update of /cvsroot/linux-vax/kernel-2.4/include/linux In directory usw-pr-cvs1:/tmp/cvs-serv31994/include/linux Modified Files: tty.h Log Message: First attempt at a real serial driver for the SC26C94 in the VXT2000. Index: tty.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/include/linux/tty.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- tty.h 9 Apr 2002 12:44:17 -0000 1.2 +++ tty.h 29 May 2002 03:37:40 -0000 1.3 @@ -367,6 +367,7 @@ extern int espserial_init(void); extern int macserial_init(void); extern int a2232board_init(void); +extern int vxt2694_init(void); extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, const char *routine); |
From: Richard B. <rb...@us...> - 2002-05-29 03:02:54
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/vsbus In directory usw-pr-cvs1:/tmp/cvs-serv22990/drivers/vsbus Modified Files: vsbus.c Log Message: Fixed vsbus autodetect for KA55 cpu. It uses a different CPU register arrangement. Now correctly detects Dz console device. Index: vsbus.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/vsbus/vsbus.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- vsbus.c 4 Feb 2002 22:56:50 -0000 1.8 +++ vsbus.c 29 May 2002 03:02:50 -0000 1.9 @@ -14,6 +14,7 @@ #include <asm/mv.h> #include <asm/ka43.h> +#include <asm/ka55.h> extern struct vax_mv mv_ka46; extern struct vax_mv mv_ka55; @@ -23,45 +24,72 @@ unsigned char vs_enabled; } sys_vs; +struct ka55_cpu_regs *ka55_cpu; + +int is_ka46(void) { return (mv==&mv_ka46); } + +int is_ka55(void) { return (mv==&mv_ka55); } + int vsbus_setup(void) { unsigned long irqs; - if (!is_ka55()) + if (!is_ka55()){ sys_vs.vs_cpu_ptr=(void *)ioremap(VSA_BASE_REGS, 128); - else + sys_vs.vs_mask=sys_vs.vs_cpu_ptr->vc_intreq; + } + else { sys_vs.vs_cpu_ptr=(void *)ioremap(VSA_KA55_BASE_REGS,128); - sys_vs.vs_mask=sys_vs.vs_cpu_ptr->vc_intreq; + ka55_cpu = (struct ka55_cpu_regs *)sys_vs.vs_cpu_ptr; + sys_vs.vs_mask=ka55_cpu->intreq; + } irqs=probe_irq_on(); - sys_vs.vs_cpu_ptr->vc_intmsk=0; - sys_vs.vs_cpu_ptr->vc_intclr=0xFF; - mdelay(1000); - sys_vs.vs_mask=sys_vs.vs_cpu_ptr->vc_intreq; + if (!is_ka55()) { + sys_vs.vs_cpu_ptr->vc_intmsk=0; + sys_vs.vs_cpu_ptr->vc_intclr=0xFF; + mdelay(1000); + sys_vs.vs_mask=sys_vs.vs_cpu_ptr->vc_intreq; - /* switch off all interrupts for now */ - sys_vs.vs_cpu_ptr->vc_intmsk=0; /*~sys_vs.vs_mask;*/ + /* switch off all interrupts for now */ + sys_vs.vs_cpu_ptr->vc_intmsk=0; /*~sys_vs.vs_mask;*/ + } + else { + ka55_cpu->intmsk = 0; + ka55_cpu->intclr = 0xff; + mdelay(1000); + sys_vs.vs_mask=ka55_cpu->intreq; + } probe_irq_off(irqs); return 0; } int vsbus_enable_int(int bit_nr) { - sys_vs.vs_cpu_ptr->vc_intmsk|=1<<bit_nr; + if (!is_ka55()) + sys_vs.vs_cpu_ptr->vc_intmsk|=1<<bit_nr; + else + ka55_cpu->intmsk|=1<<bit_nr; sys_vs.vs_enabled |= 1<< bit_nr; return 0; } int vsbus_clear_int(int bit_nr) { - sys_vs.vs_cpu_ptr->vc_intclr=1<<bit_nr; + if(!is_ka55()) + sys_vs.vs_cpu_ptr->vc_intclr=1<<bit_nr; + else + ka55_cpu->intclr=1<<bit_nr; return 0; } int vsbus_disable_int(int bit_nr) { - sys_vs.vs_cpu_ptr->vc_intmsk&=~(1<<bit_nr); + if (!is_ka55()) + sys_vs.vs_cpu_ptr->vc_intmsk&=~(1<<bit_nr); + else + ka55_cpu->intmsk&=~(1<<bit_nr); sys_vs.vs_enabled &= ~(1<<bit_nr); return 0; } @@ -69,8 +97,13 @@ int vsbus_probe_irq_on(void) { printk("vsbus: probing set mask ~%2X\n", sys_vs.vs_mask); - sys_vs.vs_cpu_ptr->vc_intmsk = 0; //~sys_vs.vs_mask; - sys_vs.vs_cpu_ptr->vc_intclr=0xff; + if (!is_ka55()){ + sys_vs.vs_cpu_ptr->vc_intmsk = 0; //~sys_vs.vs_mask; + sys_vs.vs_cpu_ptr->vc_intclr=0xff; + } else { + ka55_cpu->intmsk=0; + ka55_cpu->intclr=0xff; + } return 0; } @@ -78,14 +111,15 @@ { unsigned char x, y; - x=sys_vs.vs_cpu_ptr->vc_intreq; + if (!is_ka55()) + x=sys_vs.vs_cpu_ptr->vc_intreq; + else + x=ka55_cpu->intreq; y = x & ~sys_vs.vs_mask; printk("vsbus: probe returning %2X, %2X\n", x, ffs(y)); - sys_vs.vs_cpu_ptr->vc_intmsk = sys_vs.vs_enabled; + if(!is_ka55()) + sys_vs.vs_cpu_ptr->vc_intmsk = sys_vs.vs_enabled; + else + ka55_cpu->intmsk=sys_vs.vs_enabled; return ffs(y)-1; } - -int is_ka46(void) { return (mv==&mv_ka46); } - -int is_ka55(void) { return (mv==&mv_ka55); } - |
From: Richard B. <rb...@us...> - 2002-05-29 03:02:54
|
Update of /cvsroot/linux-vax/kernel-2.4/include/asm-vax In directory usw-pr-cvs1:/tmp/cvs-serv22990/include/asm Added Files: ka55.h Log Message: Fixed vsbus autodetect for KA55 cpu. It uses a different CPU register arrangement. Now correctly detects Dz console device. --- NEW FILE --- /* * $Id: ka55.h,v 1.1 2002/05/29 03:02:50 rbbanks Exp $ * * Definitions for KA55 CPU (VAXstation 3100m85). * */ #ifndef __VAX_KA55_H #define __VAX_KA55_H #ifndef __ASSEMBLY__ struct ka55_cpu_regs { unsigned long hltcod; /* byte 0-3 Halt Code Register */ unsigned long pad1; unsigned char intmsk; /* byte 8 Interrupt Mask */ unsigned char pad2; unsigned char pad3; unsigned char pad4; unsigned char intreq; /* byte 12 Interrupt request register */ #define intclr intreq unsigned short pad5; unsigned char pad6; unsigned short diagdsp; unsigned short pad7; unsigned long parctl; /* byte 20-23 Parity Control Register */ unsigned short pad8; unsigned short pad9; unsigned short diagtimu; unsigned short diagtme; /* byte 30-31 Diagnostic time register */ }; #endif /* __ASSEMBLY */ #endif /* __VAX_KA55_H */ |
From: ? <uns...@us...> - 2002-05-28 20:16:22
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv28350 Modified Files: vaxsgec.c Log Message: Small setup_sgec change from Christoph Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- vaxsgec.c 28 May 2002 18:41:37 -0000 1.8 +++ vaxsgec.c 28 May 2002 20:16:19 -0000 1.9 @@ -277,7 +277,7 @@ cp_to_buf ((char *) lp->card_mem->tx_buf[entry], buf_setup, sizeof (buf_setup)); lp->tx_ring[entry].bufsize = sizeof (buf_setup); - lp->tx_ring[entry].flags1 = SG_TD1_DT_SETUP | SG_TD1_IC; + lp->tx_ring[entry].flags1 = SG_TD1_DT_SETUP /* | SG_TD1_IC */; #ifdef VAX_SGEC_DEBUG_BUFFERS { |
From: ? <uns...@us...> - 2002-05-28 18:41:46
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv10694 Modified Files: vaxsgec.c vaxsgec.h Log Message: Many SGEC driver changes and fixes from Christoph's vaxsgec.cvs-diff.2002-05-27 Now it can sometimes send packets, but is not yet consistently working. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- vaxsgec.c 26 May 2002 07:58:36 -0000 1.7 +++ vaxsgec.c 28 May 2002 18:41:37 -0000 1.8 @@ -30,16 +30,17 @@ /* use #undef to turn these off */ #define VAX_SGEC_DEBUG +#undef VAX_SGEC_DEBUG_LVL2 #define VAX_SGEC_DEBUG_BUFFERS #define VAX_SGEC_AUTOPROBE_IRQ + #include "vaxsgec.h" #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+TX_RING_MASK-lp->tx_new:\ lp->tx_old - lp->tx_new-1) - static inline void writereg(volatile unsigned long *regptr, unsigned long value) { *regptr = value; @@ -53,17 +54,7 @@ static inline void sgec_stop(volatile struct sgec_regs *regs) { writecsr6(regs, regs->sg_nicsr6 & ~(SG_NICSR6_ST|SG_NICSR6_SR)); - udelay(100); /* allow card to change */ -} - -/* Load the CSR registers */ -static void load_csrs(struct sgec_private *lp) -{ - volatile struct sgec_regs *regs = lp->regs; - - writereg(®s->sg_nicsr3, virt_to_phys(lp->rx_ring)); - writereg(®s->sg_nicsr4, virt_to_phys(lp->tx_ring)); - writecsr6(regs, SG_NICSR6_MBO|SG_NICSR6_IE|SG_NICSR6_BL_8|SG_NICSR6_ST|SG_NICSR6_SR|SG_NICSR6_DC); + udelay(100); /* allow card to change and to "dropping out" interrupts */ } static inline void cp_to_buf(void *to, const void *from, __kernel_size_t len) @@ -85,12 +76,11 @@ /* Lock out other processes while setting up hardware */ netif_stop_queue(dev); - lp->rx_new = lp->tx_new = 0; - lp->rx_old = lp->tx_old = 0; + lp->rx_new = lp->rx_old = 0; + lp->tx_new = lp->tx_old = 0; - /* clear all descriptors */ - memset((void *)lp->rx_ring, 0, sizeof(lp->rx_ring)); - memset((void *)lp->tx_ring, 0, sizeof(lp->tx_ring)); + /* clear all buffers and descriptors */ + memset ((void *) lp->card_mem, 0x00, sizeof (struct sgec_shared_mem)); /* Setup the Tx ring entries */ for (i = 0; i < TX_RING_SIZE; i++) { @@ -101,15 +91,16 @@ lp->tx_ring[i].bufaddr = leptr; #ifdef VAX_SGEC_DEBUG if (i < 3) - printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->tx_buf[i]); + printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, + (int) lp->card_mem->tx_buf[i]); #endif } i = TX_RING_SIZE; /* one after last for chaining ! */ /* normal fill already done, now we define the ring */ - lp->tx_ring[i].tx_err = SG_TDR_OWN; + lp->tx_ring[i].tx_err = SG_TDR_OWN; lp->tx_ring[i].flags1 = SG_TD1_CA; /* chain to ring */ lp->tx_ring[i].bufsize = 0; - lp->tx_ring[i].bufaddr = virt_to_phys (lp->tx_ring); + lp->tx_ring[i].bufaddr = virt_to_phys (& lp->tx_ring [0]) & 0xffffff; /* Setup the Rx ring entries */ #ifdef VAX_SGEC_DEBUG @@ -120,9 +111,11 @@ lp->rx_ring[i].framelen = SG_FR_OWN; lp->rx_ring[i].bufsize = RX_BUFF_SIZE; lp->rx_ring[i].bufaddr = leptr; + #ifdef VAX_SGEC_DEBUG if (i < 3) - printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->rx_buf[i]); + printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, + (int) lp->card_mem->rx_buf[i]); #endif } /* take one after last element for ring chaining */ @@ -130,59 +123,205 @@ lp->rx_ring[i].framelen = SG_FR_OWN; lp->rx_ring[i].flags1 = SG_R1_CAD; lp->rx_ring[i].bufsize = RX_BUFF_SIZE; - lp->rx_ring[i].bufaddr = virt_to_phys (lp->rx_ring); + lp->rx_ring[i].bufaddr = virt_to_phys (& lp->rx_ring [0]) & 0xffffff; + } -static void kick_sgec(volatile struct sgec_regs *regs) +static void kick_sgec(volatile struct sgec_private * lp) { - if((regs->sg_nicsr5 & SG_NICSR5_TS) != SG_NICSR5_TS_RUN) - writereg(®s->sg_nicsr1,SG_NICSR1_TXPD); + volatile struct sgec_regs *regs = lp->regs; + + if ((regs->sg_nicsr5 & SG_NICSR5_TS) != SG_NICSR5_TS_RUN) + { + writereg(®s->sg_nicsr1,SG_NICSR1_TXPD); +#ifdef VAX_SGEC_DEBUG + printk ("%s: retrigger CSR1 (CSR5 is %ld)\n", + __FUNCTION__, (regs->sg_nicsr5 & SG_NICSR5_TS) >> 24); +#endif + } } -static int init_restart_sgec(struct sgec_private *lp) +static int reset_sgec (struct net_device *dev) { + struct sgec_private *lp = (struct sgec_private *) dev->priv; volatile struct sgec_regs *regs = lp->regs; + unsigned long v; int i; - int oldvect; #ifdef VAX_SGEC_DEBUG - printk("init_restart_sgec\n"); + printk("%s: entry\n", __FUNCTION__); #endif udelay(100); - oldvect = regs->sg_nicsr6; - writecsr6(regs, SG_NICSR6_RE); /* reset card */ - + /* do chip reset */ + writecsr6 (regs, SG_NICSR6_RE); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10 /* ms */ * HZ) / 1000); + /* Wait for the sgec to complete initialization */ for (i = 0; (i < 100) && !(regs->sg_nicsr5 & SG_NICSR5_ID); i++) { #ifdef VAX_SGEC_DEBUG - printk("SGEC restarted maybe %d\n", i); + printk("SGEC restarted, loop %d\n", i); #endif - udelay(10); + udelay(1000); } if(regs->sg_nicsr5 & SG_NICSR5_SF) { - printk("SGEC selftest failed after %d ticks, csr5=%4.4lx.\n", i, regs->sg_nicsr5); + printk("SGEC selftest failed after %d ticks, csr5=%4.4lx.\n", + i, regs->sg_nicsr5); return -1; } if (i == 100) { -#ifdef VAX_SGEC_DEBUG - printk("SGEC unopened after %d ticks, csr5=%4.4lx.\n", i, regs->sg_nicsr5); -#endif + printk("SGEC unopened after %d ticks, csr5=%4.4lx.\n", + i, regs->sg_nicsr5); return -1; } #ifdef VAX_SGEC_DEBUG printk("SGEC restarted\n"); #endif + /* + * IRQ setup + */ + v = SG_NICSR0_IPL14 | + (dev->irq & SG_NICSR0_IV_MASK) | SG_NICSR0_MBO; + i = 10; + do + { + if (i-- == 0) + { + printk ("Failing setting CSR0 (0x%08lx)!\n", + regs->sg_nicsr0); + /* further ignore error here XXX CP */ + } + writereg (& regs->sg_nicsr0, v); + } while (v != regs->sg_nicsr0); + if (i == 0) + { + printk ("SGEC: CSR0 IRQ setup FAILED !\n"); + return -1; + } + + writereg(®s->sg_nicsr3, + virt_to_phys(& lp->rx_ring [0]) & 0xffffff); + writereg(®s->sg_nicsr4, + virt_to_phys(& lp->tx_ring [0]) & 0xffffff); + +#ifdef VAX_SGEC_DEBUG + printk ("%s: done well\n", __FUNCTION__); +#endif + + return 0; +} + +static int setup_csr6 (struct net_device *dev) +{ + struct sgec_private *lp = (struct sgec_private *) dev->priv; + volatile struct sgec_regs *regs = lp->regs; + unsigned long csr6; + +#ifdef VAX_SGEC_DEBUG + printk ("%s: entry\n", __FUNCTION__); +#endif + /* for changes of the SG_NICSR6_AF_xxx stop RX */ + writecsr6(regs, regs->sg_nicsr6 & ~SG_NICSR6_SR); + udelay (20); + + /* generate fix CSR6 part */ + csr6 = SG_NICSR6_MBO | SG_NICSR6_IE | SG_NICSR6_BL_8 | + SG_NICSR6_ST | SG_NICSR6_SR | SG_NICSR6_DC; + + /* generate flags dependent part */ + if (dev->flags & IFF_PROMISC) + csr6 |= SG_NICSR6_AF_PROM; + + /* update CSR6 */ + writecsr6(regs, csr6); - writecsr6(regs, SG_NICSR6_IE | SG_NICSR6_BL_8|SG_NICSR6_ST|SG_NICSR6_SR|SG_NICSR6_DC); - kick_sgec(regs); return 0; } +static int setup_sgec (struct net_device *dev) +{ + struct sgec_private *lp = (struct sgec_private *)dev->priv; + u_int8_t buf_setup [128]; + int entry; + unsigned long flags; + +#ifdef VAX_SGEC_DEBUG + printk ("\n\n< SETUP >\n%s: entry\n", __FUNCTION__); +#endif + + spin_lock_irqsave (&lp->lock, flags); + + if (TX_BUFFS_AVAIL <= 0) + { + netif_stop_queue(dev); + + /* no buffers free, how to handle .... */ + spin_unlock_irqrestore (&lp->lock, flags); + return 1; + } + + /* create setup buffer */ + memset (buf_setup, 0xffu, sizeof (buf_setup)); + memcpy (buf_setup, dev->dev_addr, 6); + + /* TODO: add other multicast mac addresses or filters */ + + entry = lp->tx_new; + + cp_to_buf ((char *) lp->card_mem->tx_buf[entry], + buf_setup, sizeof (buf_setup)); + lp->tx_ring[entry].bufsize = sizeof (buf_setup); + lp->tx_ring[entry].flags1 = SG_TD1_DT_SETUP | SG_TD1_IC; + +#ifdef VAX_SGEC_DEBUG_BUFFERS + { + int i; + + printk("rx["); + for (i=0; i < RX_RING_SIZE; i++){ + if (i == lp->rx_new) + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "_" : "X"); + else + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "." : "1"); + } + printk("]\n"); + printk("tx["); + for (i=0; i < TX_RING_SIZE; i++){ + if (i == lp->tx_new) + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); + else + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); + } + printk("]\n"); + } +#endif + + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; + + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + + /* Now pass frame to transmitter */ + lp->tx_ring[entry].tx_err = SG_TDR_OWN; + + /* Kick the SGEC: transmit now */ + kick_sgec (lp); + + spin_unlock_irqrestore (&lp->lock, flags); + + dev->trans_start = jiffies; + return 0; +} static int sgec_rx(struct net_device *dev) { @@ -191,63 +330,75 @@ unsigned char bits; int len = 0; struct sk_buff *skb = 0; - int i; #ifdef VAX_SGEC_DEBUG printk("sgec_rx\n"); #endif #ifdef VAX_SGEC_DEBUG_BUFFERS - printk("["); - for (i=0; i < RX_RING_SIZE; i++){ - if (i == lp->rx_new) - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); - else - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + { + int i; + + printk(" rx["); + for (i=0; i < RX_RING_SIZE; i++){ + if (i == lp->rx_new) + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); + else + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + } + printk("]\n"); } - printk("]"); #endif - for (rd=&lp->rx_ring[lp->rx_new]; - !((bits = rd->framelen) & SG_FR_OWN); - rd=&lp->rx_ring[lp->rx_new]){ - - /* check for incomplete frame */ - if ((bits & SG_R0_POK) == 0) { - lp->stats.rx_over_errors++; - lp->stats.rx_errors++; - } - else if (bits & SG_R0_ERR) { - /* only count last frame as the error */ + while (! (lp->rx_ring [lp->rx_new].framelen & SG_FR_OWN)) + { + rd = & lp->rx_ring[lp->rx_new]; + bits = rd->flags0; + /* + * check for incomplete frame + */ + if (bits & SG_R0_ERR) { + /* only count last frame as the error */ if (bits & SG_R0_FFO) lp->stats.rx_fifo_errors++; /* was _BUF */ if (bits & SG_R0_CRC) lp->stats.rx_crc_errors++; if (bits & SG_R0_OFL) lp->stats.rx_over_errors++; if (bits & SG_R0_FRA) lp->stats.rx_frame_errors++; if (bits & SG_R0_LNG) lp->stats.rx_errors++; /* was _EOP */ +#ifdef VAX_SGEC_DEBUG + printk (" SG_R0_ERR (0x%04x)\n", bits); +#endif } else { len = rd->framelen; skb = dev_alloc_skb((unsigned int)len + 2); if (skb == 0) { - printk("%s: SGEC Deferring Packet\n", dev->name); + printk(" %s: SGEC Deferring Packet\n", dev->name); lp->stats.rx_dropped++; - //rd->mblength = 0; rd->framelen = SG_FR_OWN; - lp->rx_new =(lp->rx_new+1) & RX_RING_MASK; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; return 0; - } + } +#ifdef VAX_SGEC_DEBUG + printk (" fetching frame from ring buffer (len = %d)\n", len); +#endif lp->stats.rx_bytes += len; skb->dev = dev; - skb_reserve(skb,2); /*16 byte align */ + skb_reserve(skb,2); /* 16 byte align */ skb_put(skb, len); /* make room */ cp_from_buf(skb->data, (char *) lp->card_mem->rx_buf[lp->rx_new], len); skb->protocol = eth_type_trans(skb,dev); +#ifdef VAX_SGEC_DEBUG_LVL2 + printk (" passing up to linux\n", __FUNCTION__); +#endif netif_rx(skb); dev->last_rx=jiffies; lp->stats.rx_packets++; } +#ifdef VAX_SGEC_DEBUG_LVL2 + printk (" freeing rx frame\n", __FUNCTION__); +#endif rd->framelen = SG_FR_OWN; lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; } @@ -257,79 +408,106 @@ static void sgec_tx(struct net_device *dev) { struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; - volatile struct sgec_tx_desc *td; - int i, j; - j = lp->tx_old; #ifdef VAX_SGEC_DEBUG - printk ("sgec_tx\n"); + printk ("sgec_tx: "); #endif spin_lock(&lp->lock); - for (i = j; i != lp->tx_new; i = j) { - td = &lp->tx_ring[i]; #ifdef VAX_SGEC_DEBUG - printk ("sgec_tx: td->flags1 = %d\n",td->flags1); + printk ("%d (tx_err=0x%04x, flags0=0x%04x, flags1=0x%04x, size=%d)\n", + lp->tx_old, + lp->tx_ring [lp->tx_old].tx_err, + lp->tx_ring [lp->tx_old].flags0, + lp->tx_ring [lp->tx_old].flags1, + lp->tx_ring [lp->tx_old].bufsize); #endif - /* If we hit a packet not owned by us, stop */ - if (!(td->flags1 & SG_FR_OWN)) - break; - /* if (td->tmd1_bits & SG_T0_ERR) { - status = td->misc; - lp->stats.tx_errors++; - if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; - if (status & LE_T3_LCOL) lp->stats.tx_window_errors++; - if (status & LE_T3_CLOS) { - lp->stats.tx_carrier_errors++; - printk("%s: Carrier Lost", dev->name); - sgec_stop(regs); - sgec_init_ring(dev); - load_csrs(lp); - init_restart_sgec(lp); - goto out; +#ifdef VAX_SGEC_DEBUG_BUFFERS + { + int i; + + printk(" tx["); + for (i=0; i < TX_RING_SIZE; i++){ + if (i == lp->tx_new) + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); + else + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); } - */ - /* Buffer errors and underflows turn off the - * transmitter, restart the adapter. - */ - /* if (status & (LE_T3_BUF | LE_T3_UFL)) { - lp->stats.tx_fifo_errors++; - printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", dev->name); - sgec_stop(regs); - sgec_init_ring(dev); - load_csrs(lp); - init_restart_sgec(lp); - goto out; + printk("]\n"); + } +#endif + + /* + * for the TX problems work with this + */ + /* do TX cleaning */ + if (lp->tx_ring [lp->tx_old].tx_err & SG_TDR_OWN) + { +#if 1 /* def VAX_SGEC_DEBUG */ + printk (" **** cleaning ...\n"); +#endif + lp->tx_ring [lp->tx_old].tx_err = 0; + } + + while (! (lp->tx_ring [lp->tx_old].tx_err & SG_TDR_OWN)) + { + if (lp->tx_old == lp->tx_new) + { +#ifdef VAX_SGEC_DEBUG + printk (" old == new\n"); +#endif + break; } - } else - */ - if ((td->flags1 & SG_TD1_POK) == SG_TD1_POK) { + +#ifdef VAX_SGEC_DEBUG + printk (" tx_err=0x%04x, flags0=0x%04x, flags1=0x%04x\n", + lp->tx_ring [lp->tx_old].tx_err, + lp->tx_ring [lp->tx_old].flags0, + lp->tx_ring [lp->tx_old].flags1); +#endif + if ((lp->tx_ring [lp->tx_old].flags1 & SG_TD1_DT) == SG_TD1_DT_SETUP) + { + /* do nothing */ + } + else if (lp->tx_ring [lp->tx_old].flags1 & SG_TD1_LS) { /* * So we don't count the packet more than once. */ - td->flags1 &= ~(SG_TD1_POK); - - /* * One collision before packet was sent. - if (td->flags1 & SG_T1_EONE) +#if 0 /* + * no collision detection in this first driver steps + * further flags are not correct and SG_TD1_CC provides a number + * of collisions + */ + + /* One collision before packet was sent. */ + if (td->flags0 & SG_T0_LC) lp->stats.collisions++; - * More than one collision, be optimistic. - * sgec can tell us exactly how many... - if (td->tmd1_bits & LE_T1_EMORE) - lp->stats.collisions += 2; - */ + /* More than one collision, be optimistic. */ + /* sgec can tell us exactly how many... */ + if (td->flags0 & SG_T0_EC) + lp->stats.collisions += 2; /* TODO: use _CC */ +#endif lp->stats.tx_packets++; } - j = (j + 1) & TX_RING_MASK; + lp->tx_old = (lp->tx_old + 1) & TX_RING_MASK; } - lp->tx_old = j; - out: - if (netif_queue_stopped(dev) && - TX_BUFFS_AVAIL > 0) - netif_wake_queue(dev); + + if (TX_BUFFS_AVAIL > 0) + netif_wake_queue (dev); + /* rekick the TX, if there are unsent frames in buffer */ + if (lp->tx_new != lp->tx_old) + { +#ifdef VAX_SGEC_DEBUG + printk (" start kick_sgec()\n"); +#endif + kick_sgec (lp); + } + spin_unlock(&lp->lock); } @@ -341,19 +519,24 @@ unsigned long csr5; #ifdef VAX_SGEC_DEBUG - printk("sgec: interrupt!\n"); + printk("sgec: interrupt ... "); #endif csr5 = sg_regs->sg_nicsr5; - +#ifdef VAX_SGEC_DEBUG + printk ("csr5=0x%08lx ... ", csr5); +#endif if ((csr5 & SG_NICSR5_IS) == 0) { /* Hmmm, not for us... */ +#ifdef VAX_SGEC_DEBUG + printk ("forget it!\n"); +#endif return; } writereg(&sg_regs->sg_nicsr5, csr5); /* clear interrupt */ #ifdef VAX_SGEC_DEBUG - printk("sgec: ... And it's for us!\n"); + printk("for us!\n"); #endif #ifdef CONFIG_VSBUS @@ -364,38 +547,6 @@ if (csr5 & SG_NICSR5_TI) sgec_tx(dev); } -struct net_device *last_dev = 0; - -static void make_setup_frame(struct net_device *dev) -{ - struct sgec_private *lp = (struct sgec_private *) dev->priv; - - memset((void *)lp->card_mem->setup_frame,0xff,sizeof(lp->card_mem->setup_frame)); - memcpy((void *)lp->card_mem->setup_frame,dev->dev_addr,6); - - /* we should load the rest of the frame with multicast addresses */ - -#if 0 - entry = lp->tx_new & TX_RING_MASK; - ib->tx_ring[entry].flags1 = len; - cp_to_buf((char *) lp->sgec_mem->tx_buf[entry], skb->data, skblen); - ib->tx_ring[entry].flags1 = SG_TDR_OWN | SG_TD1_POK; /* (LE_T1_POK | LE_T1_OWN);*/ - lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; - if (TX_BUFFS_AVAIL <= 0) - netif_stop_queue(dev); - kick_sgec(regs); /* we don't need to TXPD if it's already going, right? */ - - /* from tulip */ - tp->tx_buffers[0].skb = NULL; - tp->tx_buffers[0].mapping = mapping; - /* Put the setup frame on the Tx list. */ - tp->tx_ring[0].length = cpu_to_le32(0x08000000 | 192); - tp->tx_ring[0].buffer1 = cpu_to_le32(mapping); - tp->tx_ring[0].status = cpu_to_le32(DescOwned); - tp->cur_tx++; - -#endif -} static int sgec_open(struct net_device *dev) { @@ -404,11 +555,9 @@ int status = 0; #ifdef VAX_SGEC_DEBUG - printk("sgec_open\n"); + printk("sgec_open (irq=0x%02x)\n", dev->irq); #endif - last_dev = dev; - /* Associate IRQ with sgec_interrupt */ if (request_irq(dev->irq, &sgec_interrupt, 0, lp->name, dev)) { printk("SGEC: Can't get irq %d\n", dev->irq); @@ -430,21 +579,22 @@ lp->filter[3] = 0; sgec_init_ring(dev); - /*load_csrs(lp);*/ - make_setup_frame(dev); - - /* put packet in queue */ - netif_start_queue(dev); + status = reset_sgec (dev); - load_csrs(lp); - status = init_restart_sgec(lp); + setup_csr6 (dev); + setup_sgec (dev); - /* - * if (!status) - * MOD_INC_USE_COUNT; - */ + /* put packet in queue */ + netif_start_queue(dev); +#if 0 /* no module support at the moment */ + if (!status) + MOD_INC_USE_COUNT; +#endif +#ifdef VAX_SGEC_DEBUG + printk ("return code of %s() = %d\n", __FUNCTION__, status); +#endif return status; } @@ -458,37 +608,18 @@ #endif netif_stop_queue(dev); +#if 0 /* XXX CP, perhaps removable */ del_timer_sync(&lp->multicast_timer); +#endif /* 0 */ sgec_stop(regs); free_irq(dev->irq, (void *) dev); - /* - MOD_DEC_USE_COUNT; - */ - return 0; -} - -static inline int sgec_reset(struct net_device *dev) -{ - struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; - int status; -#ifdef VAX_SGEC_DEBUG - printk("sgec_reset\n"); -#endif - - sgec_stop(regs); - - sgec_init_ring(dev); - load_csrs(lp); - dev->trans_start = jiffies; - status = init_restart_sgec(lp); -#ifdef VAX_SGEC_DEBUG - printk("SGEC restart=%d\n", status); +#if 0 /* no module support at the moment */ + MOD_DEC_USE_COUNT; #endif - return status; + return 0; } static void sgec_tx_timeout(struct net_device *dev) @@ -498,73 +629,78 @@ printk(KERN_ERR "%s: transmit timed out, status %04lx, reset\n", dev->name, regs->sg_nicsr6); - sgec_reset(dev); + sgec_stop(regs); + + sgec_init_ring(dev); + reset_sgec (dev); + setup_csr6 (dev); + + setup_sgec (dev); + netif_wake_queue(dev); } static int sgec_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; int skblen = skb->len; int len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; int entry; + unsigned long flags; #ifdef VAX_SGEC_DEBUG_BUFFERS int i; #endif #ifdef VAX_SGEC_DEBUG - printk ("sgec_start_xmit: data length %d\n",len); + printk ("\n\n< SEND >\nsgec_start_xmit: data length %d\n", len); #endif - skblen = skb->len; - len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; - - spin_lock_irq(&lp->lock); + spin_lock_irqsave(&lp->lock, flags); lp->stats.tx_bytes += len; - entry = lp->tx_new & TX_RING_MASK; + entry = lp->tx_new; cp_to_buf((char *) lp->card_mem->tx_buf[entry], skb->data, skblen); lp->tx_ring[entry].bufsize = len; lp->tx_ring[entry].flags1 = SG_TD1_POK | SG_TD1_IC; - - /* Clear the slack of the packet, do I need this? */ - /* For a firewall its a good idea - AC */ -/* - if (len != skblen) - memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); - */ - /* Now, give the packet to the card */ - lp->tx_ring[entry].tx_err = SG_TDR_OWN; - lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; - - if (TX_BUFFS_AVAIL <= 0) - netif_stop_queue(dev); + /* do we need to clear the slack of the packet? */ + #ifdef VAX_SGEC_DEBUG_BUFFERS printk("rx["); for (i=0; i < RX_RING_SIZE; i++){ if (i == lp->rx_new) - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "_" : "X"); + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "_" : "X"); else - printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? "." : "1"); + printk("%s",lp->rx_ring[i].framelen & SG_FR_OWN ? + "." : "1"); } printk("]\n"); printk("tx["); for (i=0; i < TX_RING_SIZE; i++){ if (i == lp->tx_new) - printk("%s",lp->tx_ring[i].flags1 & SG_TDR_OWN ? "_" : "X"); + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "_" : "X"); else - printk("%s",lp->tx_ring[i].flags1 & SG_TDR_OWN ? "." : "1"); + printk("%s",lp->tx_ring[i].tx_err & SG_TDR_OWN ? + "." : "1"); } printk("]\n"); #endif + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; + + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + + /* Now, give the packet to the card */ + lp->tx_ring[entry].tx_err = SG_TDR_OWN; + /* Kick the SGEC: transmit now */ - kick_sgec(regs); + kick_sgec(lp); - spin_unlock_irq(&lp->lock); + spin_unlock_irqrestore (&lp->lock, flags); dev->trans_start = jiffies; dev_kfree_skb(skb); @@ -636,8 +772,6 @@ static void sgec_set_multicast(struct net_device *dev) { - struct sgec_private *lp = (struct sgec_private *) dev->priv; - volatile struct sgec_regs *regs = lp->regs; #ifdef VAX_SGEC_DEBUG printk("sgec_set_multicast\n"); @@ -646,37 +780,28 @@ if (!netif_running(dev)) return; +#if 0 /* XXX CP: REMOVABLE CODE, TX queue needs not to be empty ! */ if (lp->tx_old != lp->tx_new) { mod_timer(&lp->multicast_timer, jiffies + 4); netif_wake_queue(dev); return; } +#endif netif_stop_queue(dev); - sgec_stop(regs); - - sgec_init_ring(dev); +#if 0 /* for test do not use multicast + TODO: setup flags, load multicast, etc..... + */ +#endif - if (dev->flags & IFF_PROMISC) { - lp->mode |= SG_NICSR6_AF_PROM; - } else { - lp->mode &= ~SG_NICSR6_AF_PROM; - sgec_load_multicast(dev); - } - load_csrs(lp); - init_restart_sgec(lp); - writecsr6(regs, regs->sg_nicsr6 & lp->mode); /* turn on-off multicast */ + /* no reset csr6 with the new flag dependent stuff ! */ + setup_csr6 (dev); + setup_sgec (dev); + netif_wake_queue(dev); } -static void sgec_set_multicast_retry(unsigned long _opaque) -{ - struct net_device *dev = (struct net_device *) _opaque; - - sgec_set_multicast(dev); -} - static int read_esar(unsigned char dev_addr[]) { unsigned int *esar; @@ -709,13 +834,7 @@ struct sgec_private *lp; volatile struct sgec_regs *regs; int ret; - unsigned long sgec_phys_addr; - - if(!strcmp(mv->cpu_type_str(),"VXT2000")) { /* erm */ - sgec_phys_addr=VXT_SGECADDR; - } else { - sgec_phys_addr=SGECADDR; - } + unsigned long sgec_phys_addr=SGECADDR; if (version_printed++ == 0) printk(version); @@ -742,15 +861,18 @@ each (plus 128 bytes).. over 128KB */ /* At present, until we figure out the address extension * parity control bit, ask for memory in the DMA zone */ + /* 2^6 = 64x4KB = 256KB */ - dev->mem_start = __get_free_pages(GFP_DMA, /*4*/ 6); + dev->mem_start = __get_free_pages(GFP_DMA, 6); if (!dev->mem_start) { /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */ return -ENOMEM; } dev->mem_end = dev->mem_start + sizeof (struct sgec_shared_mem); lp->card_mem = (volatile struct sgec_shared_mem *)(dev->mem_start); - + lp->rx_ring = (struct sgec_rx_desc *) & lp->card_mem->rx_ring_mem [0]; + lp->tx_ring = (struct sgec_tx_desc *) & lp->card_mem->tx_ring_mem [0]; + regs = (struct sgec_regs *) ioremap(sgec_phys_addr, 0x20 /* 0x8 */); dev->base_addr = (unsigned long) regs; if(dev->base_addr == 0) @@ -778,6 +900,8 @@ sgec_stop(regs); + dev->irq = 0; + #ifndef VAX_SGEC_AUTOPROBE_IRQ dev->irq=SGECVEC; printk("Using hardcoded SGEC interrupt vector %d\n", dev->irq); @@ -787,18 +911,13 @@ printk("Autoprobing SGEC interrupt vector..."); autoirq_setup(0); + #ifdef CONFIG_VSBUS vsbus_probe_irq_on(); #endif /* CONFIG_VSBUS */ #endif /* VAX_SGEC_AUTOPROBE_IRQ */ -#if 0 - sgec_init_ring(dev); - load_csrs(lp); - make_setup_frame(dev); - kick_sgec(regs); - udelay(1000); -#endif + /* should do something here to cause an interrupt */ #ifdef VAX_SGEC_AUTOPROBE_IRQ #ifdef CONFIG_VSBUS @@ -814,22 +933,15 @@ printk(" probed IRQ %d, vsbus %d\n", dev->irq, lp->vsbus_int); } else { dev->irq=SGECVEC; - dev->irq=0x80; - printk(" failed to detect IRQ line - assuming 0x%x.\n", dev->irq); + /* 0x80 is probably not the best vector but it's where the sgec + is ending up after we reset it, so force it there for now */ + dev->irq = 0x80; + printk(" failed to detect IRQ line - assuming 0x%x.\n", + dev->irq); } #endif /* VAX_SGEC_AUTOPROBE_IRQ */ ether_setup(dev); - - /* does anyone know what this really is supposed to do? */ - /* We cannot sleep if the chip is busy during a - * multicast list update event, because such events - * can occur from interrupts (ex. IPv6). So we - * use a timer to try again later when necessary. -DaveM - */ - init_timer(&lp->multicast_timer); - lp->multicast_timer.data = (unsigned long) dev; - lp->multicast_timer.function = &sgec_set_multicast_retry; #ifdef MODULE /* Index: vaxsgec.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- vaxsgec.h 26 May 2002 07:58:37 -0000 1.3 +++ vaxsgec.h 28 May 2002 18:41:37 -0000 1.4 @@ -162,7 +162,6 @@ */ /* The registers. */ #define SGECADDR 0x20008000 -#define VXT_SGECADDR 0x20000000 /* 20008000 would probably work too due to address aliasing, but 20000000 is probably more "right" */ /* The IDPROM. */ #define QBUS_NISA_ROM 0x20084000 /* 3100/85 */ #define VSBUS_NISA_ROM 0x27800000 /* 3100/90 (?) */ @@ -249,9 +248,14 @@ /* This is how our shared memory block is laid out */ struct sgec_shared_mem { + struct sgec_rx_desc rx_ring_mem [RX_RING_SIZE + 2]; /* desc in DMA mem */ + struct sgec_tx_desc tx_ring_mem [TX_RING_SIZE + 2]; /* desc in DMA mem */ + /* padding */ + char __padding [PAGE_SIZE - + (sizeof (struct sgec_rx_desc) * (RX_RING_SIZE + 2) + + sizeof (struct sgec_tx_desc) * (TX_RING_SIZE + 2))]; char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE]; /* packet storage */ char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE]; /* packet storage */ - u_int8_t setup_frame[128]; /* setup frame/packet */ }; struct sgec_private { @@ -264,8 +268,8 @@ unsigned short rx_len; /* receive len and high addr */ unsigned short tx_ptr; /* transmit descriptor addr */ unsigned short tx_len; /* transmit len and high addr */ - struct sgec_rx_desc rx_ring[RX_RING_SIZE]; - struct sgec_tx_desc tx_ring[TX_RING_SIZE]; + struct sgec_rx_desc * rx_ring; + struct sgec_tx_desc * tx_ring; volatile struct sgec_shared_mem *card_mem; /* virtual addr of shared memory block */ unsigned char vsbus_int; spinlock_t lock; @@ -274,5 +278,4 @@ struct net_device_stats stats; struct net_device *dev; /* Backpointer */ struct sgec_private *next_module; - struct timer_list multicast_timer; }; |
From: Kenn H. <ke...@us...> - 2002-05-27 19:59:06
|
Update of /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel In directory usw-pr-cvs1:/tmp/cvs-serv20975/kernel Modified Files: cpu_ka46.c Log Message: Fix boot lockup with VS4000/60 Index: cpu_ka46.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel/cpu_ka46.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- cpu_ka46.c 20 May 2002 01:09:49 -0000 1.5 +++ cpu_ka46.c 27 May 2002 19:59:03 -0000 1.6 @@ -79,7 +79,6 @@ mv_ka46.sidex = *(unsigned int *)RIGEL_SIDEX_ADDR; __mtpr(PR_ACCS,2); /* Enable floating points */ - printk("ka46: enabled floating point\n"); } void ka46_post_vm_init(void) |
From: Kenn H. <ke...@us...> - 2002-05-27 19:58:17
|
Update of /cvsroot/linux-vax/kernel-2.5/arch/vax In directory usw-pr-cvs1:/tmp/cvs-serv20735 Modified Files: Makefile Log Message: Clean stuff from vax/boot/tools in make clean Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/Makefile,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- Makefile 20 May 2002 00:33:33 -0000 1.3 +++ Makefile 27 May 2002 19:58:11 -0000 1.4 @@ -153,6 +153,7 @@ archclean: rm -f vmlinux.* vmlinux cd $(TOPDIR)/arch/vax ; rm -f *.out TEST.BIN TEST.SYS header.bin + cd $(TOPDIR)/arch/vax/boot/tools ; rm -f setcmdline showcmdline archmrproper: |
From: Kenn H. <ke...@us...> - 2002-05-27 19:56:10
|
Update of /cvsroot/linux-vax/kernel-2.5 In directory usw-pr-cvs1:/tmp/cvs-serv19658 Added Files: README.cvs-tags Log Message: Descriptions of CVS tags applied to the kernel-2.5 tree. Please keep this up to date as tags are applied and removed. --- NEW FILE --- Module kernel-2.5 Branch: MAIN Mainline development This branch holds the Linux/VAX development work. Various tags will be added on this branch as interesting things happen (like a particular feature being implemented, or when a binary release is made). Tags on this branch: pre-2_5_x-import These tags get applied just before importing a new Linus tree. This way, if the import screws up, or leaves a broken kernel, it's easy to revert to a working kernel. post-2_5_x-import These tags get applied just after a new Linus tree is imported, and his changes get merged successfully with ours (at least as far as getting a clean compile, if possible). kh-20020527 Initial working build on 2.5 tree. Boots fine using NFS root on my VS4000/60. (Nothing else is guaranteed). Branch: linux-2_5 Vendor branch for official Linus kernels This branch is a "vendor" branch in CVS terminology. We use it to hold pristine "Linus" kernel trees. The only tags on this branch will be the ones for each Linus tree. Tags on this branch: linux-2_5-vax Erroneous initial import (contained VAX code, but missing net/core directory). You shouldn't need to use this tag. I may rename or remove it, in fact... linus_2_5_0 Official 2.5.0 kernel tree as released by Linus linus_2_5_1 Official 2.5.1 kernel tree as released by Linus ... ... linus_2_5_16 Official 2.5.16 kernel tree as released by Linus |
From: ? <uns...@us...> - 2002-05-26 07:58:40
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv12992 Modified Files: vaxsgec.c vaxsgec.h Log Message: Fixes to sgec_init_ring, sgec_rx, sgec_start_xmit, vax_sgec_init Based on Christoph's patch Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- vaxsgec.c 26 May 2002 02:02:20 -0000 1.6 +++ vaxsgec.c 26 May 2002 07:58:36 -0000 1.7 @@ -79,9 +79,6 @@ static void sgec_init_ring(struct net_device *dev) { struct sgec_private *lp = (struct sgec_private *) dev->priv; -#if 0 - volatile char *ib = lp->init_block; -#endif unsigned long leptr; int i; @@ -91,24 +88,28 @@ lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; - /* Copy the ethernet address to the sgec init block. - * XXX bit 0 of the physical address registers has to be zero - */ -#if 0 - memset(ib, 0xff, 128); - memcpy(ib, dev->dev_addr, 6); -#endif + /* clear all descriptors */ + memset((void *)lp->rx_ring, 0, sizeof(lp->rx_ring)); + memset((void *)lp->tx_ring, 0, sizeof(lp->tx_ring)); /* Setup the Tx ring entries */ for (i = 0; i < TX_RING_SIZE; i++) { leptr = virt_to_phys(lp->card_mem->tx_buf[i]) & 0xffffff; - lp->tx_ring[i].tx_err = SG_TDR_OWN; - lp->tx_ring[i].flags1 = SG_TD1_CA; + lp->tx_ring[i].tx_err = 0; /* was SG_TDR_OWN */ + lp->tx_ring[i].flags1 = 0; /* was SG_TD1_CA */ + lp->tx_ring[i].bufsize = 0; /* filled by sender */ + lp->tx_ring[i].bufaddr = leptr; #ifdef VAX_SGEC_DEBUG if (i < 3) printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->tx_buf[i]); #endif } + i = TX_RING_SIZE; /* one after last for chaining ! */ + /* normal fill already done, now we define the ring */ + lp->tx_ring[i].tx_err = SG_TDR_OWN; + lp->tx_ring[i].flags1 = SG_TD1_CA; /* chain to ring */ + lp->tx_ring[i].bufsize = 0; + lp->tx_ring[i].bufaddr = virt_to_phys (lp->tx_ring); /* Setup the Rx ring entries */ #ifdef VAX_SGEC_DEBUG @@ -116,11 +117,20 @@ #endif for (i = 0; i < RX_RING_SIZE; i++) { leptr = virt_to_phys(lp->card_mem->rx_buf[i]) & 0xffffff; + lp->rx_ring[i].framelen = SG_FR_OWN; + lp->rx_ring[i].bufsize = RX_BUFF_SIZE; + lp->rx_ring[i].bufaddr = leptr; #ifdef VAX_SGEC_DEBUG if (i < 3) printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->card_mem->rx_buf[i]); #endif } + /* take one after last element for ring chaining */ + i = RX_RING_SIZE; + lp->rx_ring[i].framelen = SG_FR_OWN; + lp->rx_ring[i].flags1 = SG_R1_CAD; + lp->rx_ring[i].bufsize = RX_BUFF_SIZE; + lp->rx_ring[i].bufaddr = virt_to_phys (lp->rx_ring); } static void kick_sgec(volatile struct sgec_regs *regs) @@ -181,10 +191,13 @@ unsigned char bits; int len = 0; struct sk_buff *skb = 0; - -#ifdef VAX_SGEC_DEBUG_BUFFERS int i; +#ifdef VAX_SGEC_DEBUG + printk("sgec_rx\n"); +#endif + +#ifdef VAX_SGEC_DEBUG_BUFFERS printk("["); for (i=0; i < RX_RING_SIZE; i++){ if (i == lp->rx_new) @@ -195,28 +208,23 @@ printk("]"); #endif -#ifdef VAX_SGEC_DEBUG - printk("sgec_rx\n"); -#endif - for (rd=&lp->rx_ring[lp->rx_new]; !((bits = rd->framelen) & SG_FR_OWN); rd=&lp->rx_ring[lp->rx_new]){ - /* - * check for incomplete frame - if ((bits & SG_R0_POK) != SG_R0_POK) { - lp->stats.rx_over_errors ++; - lp->stats_rx_errors++; + /* check for incomplete frame */ + if ((bits & SG_R0_POK) == 0) { + lp->stats.rx_over_errors++; + lp->stats.rx_errors++; } else if (bits & SG_R0_ERR) { - * only count last frame as the error - if (bits & SG_R0_BUF) lp->stats.rx_fifo_errors++; + /* only count last frame as the error */ + if (bits & SG_R0_FFO) lp->stats.rx_fifo_errors++; /* was _BUF */ if (bits & SG_R0_CRC) lp->stats.rx_crc_errors++; if (bits & SG_R0_OFL) lp->stats.rx_over_errors++; if (bits & SG_R0_FRA) lp->stats.rx_frame_errors++; - if (bits & SG_R0_EOP) lp->stats.rx_errors++; - } else { */ + if (bits & SG_R0_LNG) lp->stats.rx_errors++; /* was _EOP */ + } else { len = rd->framelen; skb = dev_alloc_skb((unsigned int)len + 2); if (skb == 0) { @@ -226,7 +234,7 @@ rd->framelen = SG_FR_OWN; lp->rx_new =(lp->rx_new+1) & RX_RING_MASK; return 0; - /* } */ + } lp->stats.rx_bytes += len; skb->dev = dev; skb_reserve(skb,2); /*16 byte align */ @@ -240,9 +248,7 @@ dev->last_rx=jiffies; lp->stats.rx_packets++; } - // rd->mblength=0; - rd->framelen = len; - rd->framelen &= SG_FR_OWN; + rd->framelen = SG_FR_OWN; lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; } return 0; @@ -519,9 +525,9 @@ lp->stats.tx_bytes += len; entry = lp->tx_new & TX_RING_MASK; - lp->tx_ring[entry].flags1 = len; - cp_to_buf((char *) lp->card_mem->tx_buf[entry], skb->data, skblen); + lp->tx_ring[entry].bufsize = len; + lp->tx_ring[entry].flags1 = SG_TD1_POK | SG_TD1_IC; /* Clear the slack of the packet, do I need this? */ /* For a firewall its a good idea - AC */ @@ -530,7 +536,7 @@ memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); */ /* Now, give the packet to the card */ - lp->tx_ring[entry].flags1 = SG_TDR_OWN | SG_TD1_POK; /* (LE_T1_POK | LE_T1_OWN);*/ + lp->tx_ring[entry].tx_err = SG_TDR_OWN; lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; if (TX_BUFFS_AVAIL <= 0) @@ -736,15 +742,16 @@ each (plus 128 bytes).. over 128KB */ /* At present, until we figure out the address extension * parity control bit, ask for memory in the DMA zone */ + /* 2^6 = 64x4KB = 256KB */ dev->mem_start = __get_free_pages(GFP_DMA, /*4*/ 6); if (!dev->mem_start) { /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */ return -ENOMEM; } - dev->mem_end = dev->mem_start + 65536; + dev->mem_end = dev->mem_start + sizeof (struct sgec_shared_mem); lp->card_mem = (volatile struct sgec_shared_mem *)(dev->mem_start); - regs = (struct sgec_regs *) ioremap(sgec_phys_addr, 0x8); + regs = (struct sgec_regs *) ioremap(sgec_phys_addr, 0x20 /* 0x8 */); dev->base_addr = (unsigned long) regs; if(dev->base_addr == 0) printk("vaxsgec.c: memory remap failed\n"); @@ -814,6 +821,7 @@ ether_setup(dev); + /* does anyone know what this really is supposed to do? */ /* We cannot sleep if the chip is busy during a * multicast list update event, because such events * can occur from interrupts (ex. IPv6). So we Index: vaxsgec.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- vaxsgec.h 26 May 2002 02:02:20 -0000 1.2 +++ vaxsgec.h 26 May 2002 07:58:37 -0000 1.3 @@ -118,6 +118,7 @@ #define SG_R0_OFL 0x0400 /* buffer overflow */ #define SG_R0_FSG 0x0200 /* first segment */ #define SG_R0_LSG 0x0100 /* last segment */ +#define SG_R0_POK 0x0300 /* first and last segments set */ #define SG_R0_LNG 0x0080 /* frame too long */ #define SG_R0_COL 0x0040 /* collision seen */ #define SG_R0_EFT 0x0020 /* etherenet frame type */ |
From: ? <uns...@us...> - 2002-05-26 02:02:25
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv25913 Modified Files: vaxsgec.c vaxsgec.h Log Message: The Tx and Rx ring sizes need to be an exponent of 2 since we use bitwise-AND to implement modular arithmetic on them. Also fixed Tx and Rx comments in the header file were backwards. Both based on Christoph's patch. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- vaxsgec.c 23 May 2002 20:34:15 -0000 1.5 +++ vaxsgec.c 26 May 2002 02:02:20 -0000 1.6 @@ -36,7 +36,7 @@ #include "vaxsgec.h" #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ - lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\ + lp->tx_old+TX_RING_MASK-lp->tx_new:\ lp->tx_old - lp->tx_new-1) @@ -224,7 +224,7 @@ lp->stats.rx_dropped++; //rd->mblength = 0; rd->framelen = SG_FR_OWN; - lp->rx_new =(lp->rx_new+1) & RX_RING_MOD_MASK; + lp->rx_new =(lp->rx_new+1) & RX_RING_MASK; return 0; /* } */ lp->stats.rx_bytes += len; @@ -243,7 +243,7 @@ // rd->mblength=0; rd->framelen = len; rd->framelen &= SG_FR_OWN; - lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MASK; } return 0; } @@ -316,7 +316,7 @@ */ lp->stats.tx_packets++; } - j = (j + 1) & TX_RING_MOD_MASK; + j = (j + 1) & TX_RING_MASK; } lp->tx_old = j; out: @@ -370,11 +370,11 @@ /* we should load the rest of the frame with multicast addresses */ #if 0 - entry = lp->tx_new & TX_RING_MOD_MASK; + entry = lp->tx_new & TX_RING_MASK; ib->tx_ring[entry].flags1 = len; cp_to_buf((char *) lp->sgec_mem->tx_buf[entry], skb->data, skblen); ib->tx_ring[entry].flags1 = SG_TDR_OWN | SG_TD1_POK; /* (LE_T1_POK | LE_T1_OWN);*/ - lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; if (TX_BUFFS_AVAIL <= 0) netif_stop_queue(dev); kick_sgec(regs); /* we don't need to TXPD if it's already going, right? */ @@ -518,7 +518,7 @@ lp->stats.tx_bytes += len; - entry = lp->tx_new & TX_RING_MOD_MASK; + entry = lp->tx_new & TX_RING_MASK; lp->tx_ring[entry].flags1 = len; cp_to_buf((char *) lp->card_mem->tx_buf[entry], skb->data, skblen); @@ -531,7 +531,7 @@ */ /* Now, give the packet to the card */ lp->tx_ring[entry].flags1 = SG_TDR_OWN | SG_TD1_POK; /* (LE_T1_POK | LE_T1_OWN);*/ - lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; + lp->tx_new = (lp->tx_new + 1) & TX_RING_MASK; if (TX_BUFFS_AVAIL <= 0) netif_stop_queue(dev); Index: vaxsgec.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- vaxsgec.h 23 May 2002 16:11:02 -0000 1.1 +++ vaxsgec.h 26 May 2002 02:02:20 -0000 1.2 @@ -106,7 +106,7 @@ /* NICSR15: monitor command */ -/* transmit descriptor flags */ +/* Receive descriptor bits */ #define SG_FR_OWN 0x8000 /* We own the descriptor */ #define SG_R0_ERR 0x8000 /* an error occurred */ #define SG_R0_LEN 0x4000 /* length error */ @@ -129,7 +129,7 @@ #define SG_R1_VAD 0x40 /* virtual address */ #define SG_R1_VPA 0x20 /* virtual/physical PTE address */ -/* Receive descriptor bits */ +/* Transmit descriptor bits */ #define SG_TDR_OWN 0x8000 /* SGEC owns this descriptor */ #define SG_TD0_ES 0x8000 /* an error has occurred */ #define SG_TD0_TO 0x4000 /* transmit watchdog timeout */ @@ -189,15 +189,11 @@ #define SG_CSR14 56 #define SG_CSR15 60 -/* must be an even number of receive/transmit descriptors */ -#define RXDESCS 30 /* no of receive descriptors */ -#define TXDESCS 60 /* no of transmit descriptors */ - -#define TX_RING_SIZE 60 -#define TX_RING_MOD_MASK 59 - -#define RX_RING_SIZE 30 -#define RX_RING_MOD_MASK 29 +/* Tx and Rx ring size must be an exponent of 2 */ +#define TX_RING_SIZE 64 +#define TX_RING_MASK (TX_RING_SIZE - 1) +#define RX_RING_SIZE 32 +#define RX_RING_MASK (TX_RING_SIZE - 1) #define PKT_BUF_SZ 1536 #define RX_BUFF_SIZE PKT_BUF_SZ |
From: Kenn H. <ke...@us...> - 2002-05-24 00:06:11
|
Update of /cvsroot/linux-vax/kernel-2.5/net/core In directory usw-pr-cvs1:/tmp/cvs-serv26604 Added Files: Makefile datagram.c dev.c dev_mcast.c dst.c dv.c filter.c iovec.c neighbour.c netfilter.c profile.c rtnetlink.c scm.c skbuff.c sock.c sysctl_net_core.c utils.c Log Message: Get net/core files back in again. Hopefully this doesn't give us too much grief when import future Linus trees. |
From: ? <uns...@us...> - 2002-05-23 20:34:18
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv24728 Modified Files: vaxsgec.c Log Message: The memory area we're using for buffers needs to be about 136K. But we were only allocating 64K for it. Now we allocate 256K. Also fixed a harmless printk typo. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- vaxsgec.c 23 May 2002 19:12:08 -0000 1.4 +++ vaxsgec.c 23 May 2002 20:34:15 -0000 1.5 @@ -136,7 +136,7 @@ int oldvect; #ifdef VAX_SGEC_DEBUG - printk("init_restart_sgec\n", i); + printk("init_restart_sgec\n"); #endif udelay(100); @@ -732,9 +732,11 @@ spin_lock_init(&lp->lock); /* Need a block of 64KB */ + /* erm.. the way we have it set up, we need 90 buffers at 1536 bytes + each (plus 128 bytes).. over 128KB */ /* At present, until we figure out the address extension * parity control bit, ask for memory in the DMA zone */ - dev->mem_start = __get_free_pages(GFP_DMA, 4); + dev->mem_start = __get_free_pages(GFP_DMA, /*4*/ 6); if (!dev->mem_start) { /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */ return -ENOMEM; |
From: ? <uns...@us...> - 2002-05-23 19:12:14
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv594 Modified Files: vaxsgec.c Log Message: Actually tell the SGEC where the buffers are. Also changed the interrupt detection a bit. It's hardcoded to 0x80 for now. It's not quite at the "sending correct packets" point but at least now we have the SGEC sending us interrupts. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- vaxsgec.c 23 May 2002 17:20:08 -0000 1.3 +++ vaxsgec.c 23 May 2002 19:12:08 -0000 1.4 @@ -61,6 +61,8 @@ { volatile struct sgec_regs *regs = lp->regs; + writereg(®s->sg_nicsr3, virt_to_phys(lp->rx_ring)); + writereg(®s->sg_nicsr4, virt_to_phys(lp->tx_ring)); writecsr6(regs, SG_NICSR6_MBO|SG_NICSR6_IE|SG_NICSR6_BL_8|SG_NICSR6_ST|SG_NICSR6_SR|SG_NICSR6_DC); } @@ -97,28 +99,6 @@ memcpy(ib, dev->dev_addr, 6); #endif - /* Setup the initialization block */ - - /* Setup rx descriptor pointer */ - - /* Calculate the physical address of the first receive descriptor */ - leptr = virt_to_phys(lp->rx_ring); - lp->rx_len = (RX_BUFF_SIZE << 13) | (leptr >> 16); - lp->rx_ptr = leptr; - -#ifdef VAX_SGEC_DEBUG - printk("RX ptr: %8.8lx(%p)\n", leptr, lp->rx_ring); -#endif - /* Setup tx descriptor pointer */ - - /* Calculate the physical address of the first transmit descriptor */ - leptr = virt_to_phys(lp->tx_ring); - lp->tx_len = (TX_BUFF_SIZE << 13) | (leptr >> 16); - lp->tx_ptr = leptr; - -#ifdef VAX_SGEC_DEBUG - printk("TX ptr: %8.8lx(%p)\nTX rings:\n", leptr, lp->tx_ring); -#endif /* Setup the Tx ring entries */ for (i = 0; i < TX_RING_SIZE; i++) { leptr = virt_to_phys(lp->card_mem->tx_buf[i]) & 0xffffff; @@ -153,15 +133,15 @@ { volatile struct sgec_regs *regs = lp->regs; int i; -#if 0 - int reg; + int oldvect; + +#ifdef VAX_SGEC_DEBUG + printk("init_restart_sgec\n", i); #endif udelay(100); -#if 0 - reg = regs->sg_nicsr6; -#endif + oldvect = regs->sg_nicsr6; writecsr6(regs, SG_NICSR6_RE); /* reset card */ /* Wait for the sgec to complete initialization */ @@ -380,15 +360,16 @@ struct net_device *last_dev = 0; -static void make_setup_frame(void) +static void make_setup_frame(struct net_device *dev) { -#if 0 - /* create a setup frame and load it into the queue */ - memset(lp->sgec_mem->setup_frame,0xff,sizeof(lp->sgec_mem->setup_frame)); - memcpy(lp->sgec_mem->setup_frame,dev->dev_addr,6); - lp->sgec_mem->rxbuf[0] = NULL; - lp->sgec_mem->rxbuf + struct sgec_private *lp = (struct sgec_private *) dev->priv; + + memset((void *)lp->card_mem->setup_frame,0xff,sizeof(lp->card_mem->setup_frame)); + memcpy((void *)lp->card_mem->setup_frame,dev->dev_addr,6); + /* we should load the rest of the frame with multicast addresses */ + +#if 0 entry = lp->tx_new & TX_RING_MOD_MASK; ib->tx_ring[entry].flags1 = len; cp_to_buf((char *) lp->sgec_mem->tx_buf[entry], skb->data, skblen); @@ -407,8 +388,6 @@ tp->tx_ring[0].status = cpu_to_le32(DescOwned); tp->cur_tx++; - outl(tp->rx_ring_dma, ioaddr + CSR3); - outl(tp->tx_ring_dma, ioaddr + CSR4); #endif } @@ -445,13 +424,14 @@ lp->filter[3] = 0; sgec_init_ring(dev); + /*load_csrs(lp);*/ + make_setup_frame(dev); - load_csrs(lp); - - make_setup_frame(); /* put packet in queue */ + netif_start_queue(dev); + load_csrs(lp); status = init_restart_sgec(lp); /* @@ -717,8 +697,6 @@ return 0; } -static volatile void *base_addr=NULL; - static int __init vax_sgec_init(struct net_device *dev) { static unsigned version_printed = 0; @@ -761,21 +739,27 @@ /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */ return -ENOMEM; } - dev->mem_end = dev->mem_start + 65536; + lp->card_mem = (volatile struct sgec_shared_mem *)(dev->mem_start); - base_addr=ioremap(sgec_phys_addr, 0x8); - if(base_addr == 0) + regs = (struct sgec_regs *) ioremap(sgec_phys_addr, 0x8); + dev->base_addr = (unsigned long) regs; + if(dev->base_addr == 0) printk("vaxsgec.c: memory remap failed\n"); - dev->base_addr=(unsigned long)base_addr; - - lp->card_mem = (volatile struct sgec_shared_mem *)(dev->mem_start); - - /* need something meaningful in here */ - dev->irq = 0; + lp->regs = regs; + lp->name = sgecstr; + lp->dev = dev; - regs = (struct sgec_regs *) base_addr; + /* Fill the dev fields */ + dev->open = &sgec_open; + dev->stop = &sgec_close; + dev->hard_start_xmit = &sgec_start_xmit; + dev->tx_timeout = &sgec_tx_timeout; + dev->watchdog_timeo = 5*HZ; + dev->get_stats = &sgec_get_stats; + dev->set_multicast_list = &sgec_set_multicast; + dev->dma = 0; if(read_esar(dev->dev_addr) != 0) printk("vaxsgec: read_esar failed\n"); @@ -783,20 +767,31 @@ dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); + sgec_stop(regs); + +#ifndef VAX_SGEC_AUTOPROBE_IRQ + dev->irq=SGECVEC; + printk("Using hardcoded SGEC interrupt vector %d\n", dev->irq); +#endif + #ifdef VAX_SGEC_AUTOPROBE_IRQ -#ifndef CONFIG_VAX_4000HC printk("Autoprobing SGEC interrupt vector..."); autoirq_setup(0); #ifdef CONFIG_VSBUS vsbus_probe_irq_on(); #endif /* CONFIG_VSBUS */ +#endif /* VAX_SGEC_AUTOPROBE_IRQ */ - sgec_stop(regs); - writereg(®s->sg_nicsr6, SG_NICSR6_RE|SG_NICSR6_IE); - writereg(®s->sg_nicsr1,1); /* uh. well this ought to cause an interrupt, right? */ +#if 0 + sgec_init_ring(dev); + load_csrs(lp); + make_setup_frame(dev); + kick_sgec(regs); udelay(1000); +#endif +#ifdef VAX_SGEC_AUTOPROBE_IRQ #ifdef CONFIG_VSBUS lp->vsbus_int=vsbus_probe_irq_report(); #endif /* CONFIG_VSBUS */ @@ -805,37 +800,15 @@ #ifdef CONFIG_VSBUS vsbus_clear_int(lp->vsbus_int); #endif /* CONFIG_VSBUS */ -#else /* CONFIG_VAX_4000HC */ - dev->irq=SGECVEC; - lp->vsbus_int=1; -#endif /* CONFIG_VAX_4000HC */ - if (dev->irq) - printk(" probed IRQ %d, vsbus %d\n", dev->irq, lp->vsbus_int); - else - { - dev->irq=SGECVEC; - printk(" failed to detect IRQ line - assuming 0x%x.\n", dev->irq); - } - -#else /* VAX_SGEC_AUTOPROBE_IRQ */ - dev->irq=SGECVEC; - printk("Using SGEC interrupt vector %d\n", dev->irq); + if (dev->irq) { + printk(" probed IRQ %d, vsbus %d\n", dev->irq, lp->vsbus_int); + } else { + dev->irq=SGECVEC; + dev->irq=0x80; + printk(" failed to detect IRQ line - assuming 0x%x.\n", dev->irq); + } #endif /* VAX_SGEC_AUTOPROBE_IRQ */ - - /* Fill the dev fields */ - dev->open = &sgec_open; - dev->stop = &sgec_close; - dev->hard_start_xmit = &sgec_start_xmit; - dev->tx_timeout = &sgec_tx_timeout; - dev->watchdog_timeo = 5*HZ; - dev->get_stats = &sgec_get_stats; - dev->set_multicast_list = &sgec_set_multicast; - dev->dma = 0; - - lp->regs = regs; - lp->name = sgecstr; - lp->dev = dev; ether_setup(dev); |
From: ? <uns...@us...> - 2002-05-23 17:20:11
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv30771 Modified Files: vaxsgec.c Log Message: Split the ESAR reading to a separate function and try to make it work properly for different machines. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- vaxsgec.c 23 May 2002 16:20:44 -0000 1.2 +++ vaxsgec.c 23 May 2002 17:20:08 -0000 1.3 @@ -691,6 +691,32 @@ sgec_set_multicast(dev); } +static int read_esar(unsigned char dev_addr[]) +{ + unsigned int *esar; + unsigned long esar_phys_addr; + int shiftage; + int i; + + if(!strcmp(mv->cpu_type_str(),"VXT2000")) { /* erm */ + esar_phys_addr=VXT_NISA_ROM; + shiftage=0; + } else { + esar_phys_addr=QBUS_NISA_ROM; + shiftage=8; + } + + esar=(unsigned int *)ioremap(esar_phys_addr, 0x80); + if(esar == NULL) + return -1; + + for (i = 0; i < 6; i++) + dev_addr[i] = (esar[i] >> shiftage) & 0xff; + + iounmap(esar); + return 0; +} + static volatile void *base_addr=NULL; static int __init vax_sgec_init(struct net_device *dev) @@ -698,17 +724,13 @@ static unsigned version_printed = 0; struct sgec_private *lp; volatile struct sgec_regs *regs; - int i, ret; - unsigned char *esar; + int ret; unsigned long sgec_phys_addr; - unsigned long esar_phys_addr; if(!strcmp(mv->cpu_type_str(),"VXT2000")) { /* erm */ sgec_phys_addr=VXT_SGECADDR; - esar_phys_addr=VXT_NISA_ROM; } else { sgec_phys_addr=SGECADDR; - esar_phys_addr=QBUS_NISA_ROM; } if (version_printed++ == 0) @@ -755,23 +777,11 @@ regs = (struct sgec_regs *) base_addr; - /* FIXME: deal with failure here */ - esar=ioremap(esar_phys_addr, 0x80); - - /* 3rd byte contains address part in 3100/85 -RB */ - /* Note that 660 board types use a different position */ - /* Copy the ethernet address to the device structure, later to the - * sgec initialization block so the card gets it every time it's - * (re)initialized. - */ - printk("Ethernet address in ROM: "); - for (i = 0; i < 6; i++) { - dev->dev_addr[i] = esar[i*4]; /* uh. this is right for the vxt but wrong for other machines. fix it later */ - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - } - - /* Don't need this any more */ - iounmap(esar); + if(read_esar(dev->dev_addr) != 0) + printk("vaxsgec: read_esar failed\n"); + printk("Ethernet address in ROM: %02X:%02X:%02X:%02X:%02X:%02X\n", + dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], + dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); #ifdef VAX_SGEC_AUTOPROBE_IRQ #ifndef CONFIG_VAX_4000HC |
From: ? <uns...@us...> - 2002-05-23 16:33:16
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv7294 Added Files: vaxsgec.h Log Message: Split the #define's from vaxsgec.c off to a header file. (From Richard Banks's latest version) --- NEW FILE --- /* * vaxsgec.h - Header file for vaxsgec.c * * Created by Richard Banks * */ #define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ /* SGEC bit definitions */ /* NICSR0: */ #define SG_NICSR0_IPL 0xc0000000 /* interrupt priority level: */ #define SG_NICSR0_IPL14 0x00000000 /* 0x14 */ #define SG_NICSR0_IPL15 0x40000000 /* 0x15 */ #define SG_NICSR0_IPL16 0x80000000 /* 0x16 */ #define SG_NICSR0_IPL17 0xc0000000 /* 0x17 */ #define SG_NICSR0_SA 0x20000000 /* sync(1)/async mode */ #define SG_NICSR0_MBO 0x1fff0003 /* must be set to one on write */ #define SG_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */ /* NICSR1: */ #define SG_NICSR1_TXPD 0xffffffff /* transmit polling demand */ /* NICSR2: */ #define SG_NICSR2_RXPD 0xffffffff /* receive polling demand */ /* NICSR3: RX descriptor list address */ /* NICSR4: TX descriptor list address */ /* NICSR5: */ #define SG_NICSR5_ID 0x80000000 /* init done */ #define SG_NICSR5_SF 0x40000000 /* self-test failed */ #define SG_NICSR5_SS 0x3c000000 /* self-test status field */ #define SG_NICSR5_TS 0x03000000 /* transmission state: */ #define SG_NICSR5_TS_STOP 0x00000000 /* stopped */ #define SG_NICSR5_TS_RUN 0x01000000 /* running */ #define SG_NICSR5_TS_SUSP 0x02000000 /* suspended */ #define SG_NICSR5_RS 0x00c00000 /* reception state: */ #define SG_NICSR5_RS_STOP 0x00000000 /* stopped */ #define SG_NICSR5_RS_RUN 0x00400000 /* running */ #define SG_NICSR5_RS_SUSP 0x00800000 /* suspended */ #define SG_NICSR5_OM 0x00060000 /* operating mode: */ #define SG_NICSR5_OM_NORM 0x00000000 /* normal */ #define SG_NICSR5_OM_ILBK 0x00020000 /* internal loopback */ #define SG_NICSR5_OM_ELBK 0x00040000 /* external loopback */ #define SG_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */ #define SG_NICSR5_DN 0x00010000 /* virtual CSR access done */ #define SG_NICSR5_MBO 0x0038ff00 /* must be one */ #define SG_NICSR5_BO 0x00000080 /* boot message received */ #define SG_NICSR5_TW 0x00000040 /* transmit watchdog timeout */ #define SG_NICSR5_RW 0x00000020 /* receive watchdog timeout */ #define SG_NICSR5_ME 0x00000010 /* memory error */ #define SG_NICSR5_RU 0x00000008 /* receive buffer unavailable */ #define SG_NICSR5_RI 0x00000004 /* receiver interrupt */ #define SG_NICSR5_TI 0x00000002 /* transmitter interrupt */ #define SG_NICSR5_IS 0x00000001 /* interrupt summary */ /* NICSR6: */ #define SG_NICSR6_RE 0x80000000 /* reset */ #define SG_NICSR6_IE 0x40000000 /* interrupt enable */ #define SG_NICSR6_MBO 0x01e7f000 /* must be one */ #define SG_NICSR6_BL 0x1e000000 /* burst limit mask */ #define SG_NICSR6_BL_8 0x10000000 /* 8 longwords */ #define SG_NICSR6_BL_4 0x08000000 /* 4 longwords */ #define SG_NICSR6_BL_2 0x04000000 /* 2 longwords */ #define SG_NICSR6_BL_1 0x02000000 /* 1 longword */ #define SG_NICSR6_BE 0x00100000 /* boot message enable */ #define SG_NICSR6_SE 0x00080000 /* single cycle enable */ #define SG_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */ #define SG_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */ #define SG_NICSR6_OM 0x00000300 /* operating mode: */ #define SG_NICSR6_OM_NORM 0x00000000 /* normal */ #define SG_NICSR6_OM_ILBK 0x00000100 /* internal loopback */ #define SG_NICSR6_OM_ELBK 0x00000200 /* external loopback */ #define SG_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */ #define SG_NICSR6_DC 0x00000080 /* disable data chaining */ #define SG_NICSR6_FC 0x00000040 /* force collision mode */ #define SG_NICSR6_PB 0x00000008 /* pass bad frames */ #define SG_NICSR6_AF 0x00000006 /* address filtering mode: */ #define SG_NICSR6_AF_NORM 0x00000000 /* normal filtering */ #define SG_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */ #define SG_NICSR6_AF_ALLM 0x00000004 /* all multicasts */ /* NICSR7: system page table base address */ /* NICSR8: reserved */ /* NICSR9: */ #define SG_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */ #define SG_VNICSR9_TT 0x0000ffff /* transmitter timeout */ /* NICSR10: */ #define SG_VNICSR10_RN 0x001f0000 /* SGEC version */ #define SG_VNICSR10_MFC 0x0000ffff /* missed frame counter */ /* NICSR11: boot message verification (low) (v) */ /* NICSR12: boot message verification (high) (v) */ /* NICSR13: boot message processor (v) */ /* NICSR14: diagnostic breakpoint (v) */ /* NICSR15: monitor command */ /* transmit descriptor flags */ #define SG_FR_OWN 0x8000 /* We own the descriptor */ #define SG_R0_ERR 0x8000 /* an error occurred */ #define SG_R0_LEN 0x4000 /* length error */ #define SG_R0_DAT 0x3000 /* data type (next 3 are subtypes) */ #define SG_R0_DAT_NORM 0x0000 /* normal frame */ #define SG_R0_DAT_INLB 0x1000 /* internal loop back */ #define SG_R0_DAT_EXLB 0x2000 /* external loop back */ #define SG_R0_FRA 0x0800 /* runt frame */ #define SG_R0_OFL 0x0400 /* buffer overflow */ #define SG_R0_FSG 0x0200 /* first segment */ #define SG_R0_LSG 0x0100 /* last segment */ #define SG_R0_LNG 0x0080 /* frame too long */ #define SG_R0_COL 0x0040 /* collision seen */ #define SG_R0_EFT 0x0020 /* etherenet frame type */ #define SG_R0_TNV 0x0008 /* address translation not valid */ #define SG_R0_DRB 0x0004 /* saw some dribbling bits */ #define SG_R0_CRC 0x0002 /* CRC error */ #define SG_R0_FFO 0x0001 /* fifo overflow */ #define SG_R1_CAD 0x80 /* chain address */ #define SG_R1_VAD 0x40 /* virtual address */ #define SG_R1_VPA 0x20 /* virtual/physical PTE address */ /* Receive descriptor bits */ #define SG_TDR_OWN 0x8000 /* SGEC owns this descriptor */ #define SG_TD0_ES 0x8000 /* an error has occurred */ #define SG_TD0_TO 0x4000 /* transmit watchdog timeout */ #define SG_TD0_LE 0x1000 /* length error */ #define SG_TD0_LO 0x0800 /* loss of carrier */ #define SG_TD0_NC 0x0400 /* no carrier */ #define SG_TD0_LC 0x0200 /* late collision */ #define SG_TD0_EC 0x0100 /* excessive collisions */ #define SG_TD0_HF 0x0080 /* heartbeat fail */ #define SG_TD0_CC 0x0078 /* collision count mask */ #define SG_TD0_TN 0x0004 /* address translation invalid */ #define SG_TD0_UF 0x0002 /* underflow */ #define SG_TD0_DE 0x0001 /* transmission deferred */ #define SG_TD1_CA 0x8000 /* chain address */ #define SG_TD1_VA 0x4000 /* virtual address */ #define SG_TD1_DT 0x3000 /* data type: */ #define SG_TD1_DT_NORM 0x0000 /* normal transmit frame */ #define SG_TD1_DT_SETUP 0x2000 /* setup frame */ #define SG_TD1_DT_DIAG 0x3000 /* diagnostic frame */ #define SG_TD1_AC 0x0800 /* CRC disable */ #define SG_TD1_FS 0x0400 /* first segment */ #define SG_TD1_LS 0x0200 /* last segment */ #define SG_TD1_POK 0x0600 /* packet OK to send - first and last segment set */ #define SG_TD1_IC 0x0100 /* interrupt on completion */ #define SG_TD1_VT 0x0080 /* virtual(1)/phys PTE address */ /* * Adresses. */ /* The registers. */ #define SGECADDR 0x20008000 #define VXT_SGECADDR 0x20000000 /* 20008000 would probably work too due to address aliasing, but 20000000 is probably more "right" */ /* The IDPROM. */ #define QBUS_NISA_ROM 0x20084000 /* 3100/85 */ #define VSBUS_NISA_ROM 0x27800000 /* 3100/90 (?) */ #define VXT_NISA_ROM 0x200c4000 /* VXT2000 */ /* The interrupt vector. */ #define SGECVEC 0x41 /* 3100/85 */ #define OTHER_SGECVEC 0x108 /* 4000/60 (?) */ /* register offsets */ #define SG_CSR0 0 #define SG_CSR1 4 #define SG_CSR2 8 #define SG_CSR3 12 #define SG_CSR4 16 #define SG_CSR5 20 #define SG_CSR6 24 #define SG_CSR7 28 #define SG_CSR8 32 #define SG_CSR9 36 #define SG_CSR10 40 #define SG_CSR11 44 #define SG_CSR12 48 #define SG_CSR13 52 #define SG_CSR14 56 #define SG_CSR15 60 /* must be an even number of receive/transmit descriptors */ #define RXDESCS 30 /* no of receive descriptors */ #define TXDESCS 60 /* no of transmit descriptors */ #define TX_RING_SIZE 60 #define TX_RING_MOD_MASK 59 #define RX_RING_SIZE 30 #define RX_RING_MOD_MASK 29 #define PKT_BUF_SZ 1536 #define RX_BUFF_SIZE PKT_BUF_SZ #define TX_BUFF_SIZE PKT_BUF_SZ #define BUF_OFFSET_CPU (offsetof(struct sgec_shared_mem, rx_buf)) #define BUF_OFFSET_LNC BUF_OFFSET_CPU /* SGEC CSRs */ struct sgec_regs { unsigned long sg_nicsr0; /* vector address, IPL, sync mode */ unsigned long sg_nicsr1; /* TX poll demand */ unsigned long sg_nicsr2; /* RX poll demand */ unsigned long sg_nicsr3; /* RX descriptor list address */ unsigned long sg_nicsr4; /* TX descriptor list address */ unsigned long sg_nicsr5; /* SGEC status */ unsigned long sg_nicsr6; /* SGEC command/mode */ unsigned long sg_nicsr7; /* system page table base address */ unsigned long sg_nivcsr8; /* reserved virtual CSR */ unsigned long sg_nivcsr9; /* watchdog timers (virtual) */ unsigned long sg_nivcsr10; /* revision, missed frame count (v) */ unsigned long sg_nivcsr11; /* boot message verification (low) (v) */ unsigned long sg_nivcsr12; /* boot message verification (high) (v) */ unsigned long sg_nivcsr13; /* boot message processor (v) */ unsigned long sg_nivcsr14; /* diagnostic breakpoint (v) */ unsigned long sg_nicsr15; /* monitor command */ }; /* Receive descriptor */ struct sgec_rx_desc{ unsigned short flags0; /* descriptor flags */ unsigned short framelen; /* frame length */ unsigned char unused[3]; /* unused */ unsigned char flags1; /* more descriptor flags */ short page_offset; /* buffer page offset */ short bufsize; /* buffer size */ unsigned long bufaddr; /* buffer address */ }; /* Transmit descriptor */ struct sgec_tx_desc { unsigned short flags0; /* descriptor flags */ unsigned short tx_err; /* Count of transmit errors (or TDR counter?) */ unsigned char unused[2]; /* unused */ unsigned short flags1; /* more descriptor flags */ short pageoffset; /* offset of buffer in page */ short bufsize; /* length of data buffer */ unsigned long bufaddr; /* address of data buffer */ }; /* This is how our shared memory block is laid out */ struct sgec_shared_mem { char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE]; /* packet storage */ char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE]; /* packet storage */ u_int8_t setup_frame[128]; /* setup frame/packet */ }; struct sgec_private { char *name; volatile struct sgec_regs *regs; /* location of registers */ unsigned short mode; /* Pre-set mode (reg. 15) */ unsigned char phys_addr[6]; /* Physical ethernet address */ unsigned short filter[4]; /* Multicast filter. */ unsigned short rx_ptr; /* receive descriptor addr */ unsigned short rx_len; /* receive len and high addr */ unsigned short tx_ptr; /* transmit descriptor addr */ unsigned short tx_len; /* transmit len and high addr */ struct sgec_rx_desc rx_ring[RX_RING_SIZE]; struct sgec_tx_desc tx_ring[TX_RING_SIZE]; volatile struct sgec_shared_mem *card_mem; /* virtual addr of shared memory block */ unsigned char vsbus_int; spinlock_t lock; int rx_new, tx_new; int rx_old, tx_old; struct net_device_stats stats; struct net_device *dev; /* Backpointer */ struct sgec_private *next_module; struct timer_list multicast_timer; }; |
From: ? <uns...@us...> - 2002-05-23 16:20:48
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net In directory usw-pr-cvs1:/tmp/cvs-serv9369 Modified Files: vaxsgec.c Log Message: Merge Richard Banks's latest vaxsgec.c with my own changes. It still does not drive the SGEC correctly, but it's getting there. This driver is currently "half LANCE driver, half SGEC driver". These changes bring it closer to being an SGEC driver. Index: vaxsgec.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxsgec.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- vaxsgec.c 4 Sep 2001 03:17:17 -0000 1.1 +++ vaxsgec.c 23 May 2002 16:20:44 -0000 1.2 @@ -1,18 +1,20 @@ /* * SGEC ethernet driver. Reported as EZA0 etc by VAX Console. * - * SGEC stands for Second Generation Ethernet Card, and is the - * replacement for the LANCE adapters in the MicroVaxen. - * * Loosely adapted from vaxlance.c by Dave Airlie * by Richard Banks, Aug 2001 * */ [...1107 lines suppressed...] - /* lp->ll is the location of the registers for card */ - lp->ll = ll; - + lp->regs = regs; lp->name = sgecstr; - - /* busmaster_regval (CSR3) should be zero according to the PMAD-AA - * specification. - */ - lp->busmaster_regval = 0; lp->dev = dev; ether_setup(dev); @@ -1098,6 +895,3 @@ } #endif - - - |
From: Kenn H. <ke...@us...> - 2002-05-22 23:16:28
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel In directory usw-pr-cvs1:/tmp/cvs-serv21295 Modified Files: cpu_vxt.c Log Message: Try initializing VSBUS for VXT machines. Might work... Index: cpu_vxt.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/cpu_vxt.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- cpu_vxt.c 22 May 2002 00:36:31 -0000 1.4 +++ cpu_vxt.c 22 May 2002 23:16:25 -0000 1.5 @@ -18,9 +18,11 @@ #include <asm/simple_io.h> #include <asm/vaxcpu.h> #include <asm/clock.h> /* for clock_init routines */ +#include <asm/vsa.h> void vxt_pre_vm_init(void); void vxt_post_vm_init(void); +void vxt_init_devices(void); const char *vxt_cpu_type_str(void); void vxt_putchar(int c); @@ -51,7 +53,7 @@ NULL, /* halt */ NULL, /* mcheck - machine check */ - NULL, /* init_devices */ + vxt_init_devices, /* init_devices */ vxt_cpu_type_str, generic_clock_init, @@ -70,6 +72,14 @@ { init_vxt_console(0x200A0000); register_console(&vax_console); +} + + +void vxt_init_devices(void) +{ +#ifdef CONFIG_VSBUS + vsbus_setup(); +#endif /* CONFIG_VSBUS */ } |
From: Kenn H. <ke...@us...> - 2002-05-22 00:36:36
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel In directory usw-pr-cvs1:/tmp/cvs-serv6277 Modified Files: cpu_vxt.c Log Message: Quick fix for VXT console output Index: cpu_vxt.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/cpu_vxt.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- cpu_vxt.c 20 May 2002 09:28:31 -0000 1.3 +++ cpu_vxt.c 22 May 2002 00:36:31 -0000 1.4 @@ -12,6 +12,7 @@ #include <linux/types.h> /* For NULL */ #include <linux/kernel.h> /* For printk */ +#include <asm/io.h> #include <asm/mtpr.h> #include <asm/mv.h> #include <asm/simple_io.h> @@ -22,6 +23,10 @@ void vxt_post_vm_init(void); const char *vxt_cpu_type_str(void); +void vxt_putchar(int c); +int vxt_getchar(void); +void init_vxt_console(unsigned long phys_addr); + struct vxt_machine_vector { struct vax_mv mv; @@ -37,8 +42,8 @@ ka4x_prom_putchar, /* pre_vm_putchar */ ka4x_prom_getchar, /* pre_vm_getchar */ - dz11_putchar, /* post_vm_putchar */ - dz11_getchar, /* post_vm_getchar */ + vxt_putchar, /* post_vm_putchar */ + vxt_getchar, /* post_vm_getchar */ NULL, /* console_init */ @@ -63,14 +68,46 @@ void vxt_post_vm_init(void) { - - init_dz11_console(0x200A0000, 3); - dz_serial_console_init(0, 0); + init_vxt_console(0x200A0000); + register_console(&vax_console); } const char *vxt_cpu_type_str(void) { return "VXT2000"; +} + +/************************************************************************/ +/* These functions do I/O through the first channel of a 2694 quad UART. They + are intended as a quick way to get post-VM output on the VXT2000 in serial + console mode until there's a proper driver. */ + +volatile int *vxt2694_addr = NULL; + +void vxt_putchar(int c) +{ + /* wait for TxRDY */ + while((vxt2694_addr[1] & 4) == 0) + ; + + /* send the character */ + vxt2694_addr[3] = c & 0xff; +} + +int vxt_getchar(void) +{ + /* Not yet implemented */ + asm("halt"); + return 0; +} + +void init_vxt_console(unsigned long phys_addr) +{ + if (vxt2694_addr != NULL) { + return; + } + + vxt2694_addr = ioremap(phys_addr, 256); } |
From: Kenn H. <ke...@us...> - 2002-05-20 00:58:33
|
Update of /cvsroot/linux-vax/kernel-2.5/drivers/acorn In directory usw-pr-cvs1:/tmp/cvs-serv29094/drivers/acorn Removed Files: .cvsignore Log Message: Reconciling our tree with the pristine Linus 2.5 tree. This backs out the VAX-related code checked in by Andy. I'll be checking that code back in as a separate check-in on the truck shortly. --- .cvsignore DELETED --- |
From: Kenn H. <ke...@us...> - 2002-05-20 00:57:50
|
Update of /cvsroot/linux-vax/kernel-2.5/drivers/net/skfp In directory usw-pr-cvs1:/tmp/cvs-serv29094/drivers/net/skfp Removed Files: .cvsignore Log Message: Reconciling our tree with the pristine Linus 2.5 tree. This backs out the VAX-related code checked in by Andy. I'll be checking that code back in as a separate check-in on the truck shortly. --- .cvsignore DELETED --- |
From: Kenn H. <ke...@us...> - 2002-05-20 00:57:50
|
Update of /cvsroot/linux-vax/kernel-2.5/drivers/net/hamradio/soundmodem In directory usw-pr-cvs1:/tmp/cvs-serv29094/drivers/net/hamradio/soundmodem Removed Files: .cvsignore Log Message: Reconciling our tree with the pristine Linus 2.5 tree. This backs out the VAX-related code checked in by Andy. I'll be checking that code back in as a separate check-in on the truck shortly. --- .cvsignore DELETED --- |