This is support for all SysKonnect Token Ring cards, specifically
SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect TR4/16(+) PCI
(SK-4590), SysKonnect TR4/16 PCI (SK-4591) adapters.
+ It also supports Compaq PCI Token Ring adapters and Proteon ISA
+ Token Ring adapters (1392 and 1392+).
If you have such an adapter and would like to use it, say Y or M and
read the Token-Ring mini-HOWTO, available via FTP (user: anonymous)
Now just setup the device via ifconfig and set and routes you may have. After
this you are ready to start sending some tokens.
+Parameters:
+The driver supports the usual parameters irq and dma (for ISA-adapters only).
+Additional, there is a parameter for setting the connection speed (4 MBits/sec
+or 16 MBit/sec). Default is 16, use "rate=4" to force 4 MBit.
+
Errata:
For anyone wondering where to pick up the SysKonnect adapters please browse
to http://www.syskonnect.com
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 15
-EXTRAVERSION = pre13
+EXTRAVERSION = pre14
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_swift, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(init_new_context, swift_init_new_context, BTFIXUPCALL_NORM);
+#if 1
+ /* If granular flushes are ever cured and reenabled in
+ * swift.S, revert this setting back to non-global iommu
+ * cache flushes. -DaveM
+ */
+ flush_page_for_dma_global = 1;
+#else
flush_page_for_dma_global = 0;
+#endif
/* Are you now convinced that the Swift is one of the
* biggest VLSI abortions of all time? Bravo Fujitsu!
swift_flush_page_to_ram:
sethi %hi(0x2000), %o0
1: subcc %o0, 0x10, %o0
- sta %g0, [%o0] ASI_M_TXTC_TAG
+ add %o0, %o0, %o1
sta %g0, [%o0] ASI_M_DATAC_TAG
bne 1b
- nop
+ sta %g0, [%o1] ASI_M_TXTC_TAG
retl
nop
#else
nop
ldx [%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7
wr %g0, %o7, %pcr
- wr %g0, %g0, %pic
+
+ /* Blackbird errata workaround. See commentary in
+ * smp.c:smp_percpu_timer_interrupt() for more
+ * information.
+ */
+ ba,pt %xcc, 99f
+ nop
+ .align 64
+99: wr %g0, %g0, %pic
+ rd %pic, %g0
+
1: b,pt %xcc, ret_sys_call
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
sparc_exit: rdpr %otherwin, %g1
/* Setup "Linux Current Register", thanks Sun 8-) */
wr %g0, 0x1, %pcr
- wr %g6, 0x0, %pic
+
+ /* Blackbird errata workaround. See commentary in
+ * smp.c:smp_percpu_timer_interrupt() for more
+ * information.
+ */
+ ba,pt %xcc, 99f
+ nop
+ .align 64
+99: wr %g6, %g0, %pic
+ rd %pic, %g0
#endif
mov 1, %g5
}
if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
/*
* Locked down tlb entry 63.
*/
+
tte = spitfire_get_dtlb_data(63);
res = PROM_TRUE;
goto done;
smp_processor_id(), data0, data1, data2, target);
#endif
again:
+ /* Ok, this is the real Spitfire Errata #54.
+ * One must read back from a UDB internal register
+ * after writes to the UDB interrupt dispatch, but
+ * before the membar Sync for that write.
+ * So we use the high UDB control register (ASI 0x7f,
+ * ADDR 0x20) for the dummy read. -DaveM
+ */
__asm__ __volatile__("
wrpr %0, %1, %%pstate
wr %%g0, %2, %%asi
stxa %5, [0x60] %%asi
membar #Sync
stxa %%g0, [%6] %%asi
+ membar #Sync
+ mov 0x20, %%g1
+ ldxa [%%g1] 0x7f, %%g0
membar #Sync"
: /* No outputs */
: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
- "r" (data0), "r" (data1), "r" (data2), "r" (target));
+ "r" (data0), "r" (data1), "r" (data2), "r" (target)
+ : "g1");
/* NOTE: PSTATE_IE is still clear. */
stuck = 100000;
sethi %hi(TLBTEMP_ENT1), %o3
rdpr %pstate, %g3
wrpr %g3, PSTATE_IE, %pstate
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %o4
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %o5
+ stxa %g0, [%o5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %o5
stxa %o0, [%o2] ASI_DMMU
stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS
membar #Sync
add %o3, (TLBTEMP_ENTSZ), %o3
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g5
+ stxa %g0, [%g5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %g5
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g7
+ stxa %g0, [%g7] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7
stxa %o1, [%o2] ASI_DMMU
stxa %g2, [%o3] ASI_DTLB_DATA_ACCESS
sethi %hi(TLBTEMP_ENT2), %o3
rdpr %pstate, %g3
wrpr %g3, PSTATE_IE, %pstate
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g5
+ stxa %g0, [%g5] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_TAG_READ, %g5
+
+ /* Spitfire Errata #32 workaround */
+ mov 0x8, %g7
+ stxa %g0, [%g7] ASI_DMMU
+ flush %g6
+
ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7
stxa %o0, [%o2] ASI_DMMU
stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS
/* Now fixup OBP's idea about where we really are mapped. */
prom_printf("Remapping the kernel... ");
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR;
phys_page += ((unsigned long)&prom_boot_page -
(unsigned long)&empty_zero_page);
: "memory");
tte_vaddr = (unsigned long) &empty_zero_page;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63);
remap_func = (void *) ((unsigned long) &prom_remap -
(unsigned long) &prom_boot_page);
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR,
(unsigned long) &empty_zero_page,
prom_get_mmu_ihandle());
/* Only DTLB must be checked for VPTE entries. */
for(i = 0; i < 63; i++) {
- unsigned long tag = spitfire_get_dtlb_tag(i);
+ unsigned long tag;
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
+ tag = spitfire_get_dtlb_tag(i);
if(((tag & ~(PAGE_MASK)) == 0) &&
((tag & (PAGE_MASK)) >= prom_reserved_base)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
for(i = 0; i < 63; i++) {
unsigned long data;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
data = spitfire_get_dtlb_data(i);
if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
- unsigned long tag = spitfire_get_dtlb_tag(i);
+ unsigned long tag;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ tag = spitfire_get_dtlb_tag(i);
if(save_p) {
prom_dtlb[dtlb_seen].tlb_ent = i;
prom_dtlb[dtlb_seen].tlb_tag = tag;
for(i = 0; i < 63; i++) {
unsigned long data;
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
data = spitfire_get_itlb_data(i);
if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
- unsigned long tag = spitfire_get_itlb_tag(i);
+ unsigned long tag;
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ tag = spitfire_get_itlb_tag(i);
if(save_p) {
prom_itlb[itlb_seen].tlb_ent = i;
prom_itlb[itlb_seen].tlb_tag = tag;
: "=r" (pstate)
: "i" (PSTATE_IE));
for(i = 0; i < 64; i++) {
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
: /* no outputs */
spitfire_put_dtlb_data(i, 0x0UL);
membar("#Sync");
}
+
+ /* Spitfire Errata #32 workaround */
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "flush %%g6"
+ : /* No outputs */
+ : "r" (0),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+
if(!(spitfire_get_itlb_data(i) & _PAGE_L)) {
__asm__ __volatile__("stxa %%g0, [%0] %1"
: /* no outputs */
__flush_tlb_range: /* %o0=(ctx&0x3ff), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT,
* %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start)
*/
-#define TLB_MAGIC 206 /* Students, do you know how I calculated this? -DaveM */
+#define TLB_MAGIC 207 /* Students, do you know how I calculated this? -DaveM */
/*IC3*/ cmp %o5, %o4
be,pt %xcc, __flush_tlb_page
srlx %o5, 13, %g5
wrpr %g1, PSTATE_IE, %pstate
mov TLB_TAG_ACCESS, %g3
mov (62 << 3), %g2
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
1: ldxa [%g2] ASI_ITLB_TAG_READ, %o4
and %o4, 0x3ff, %o5
cmp %o5, %o0
wrpr %g1, 0x0, %pstate
4: stxa %g0, [%g3] ASI_IMMU
stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS
+ flush %g6
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ba,pt %xcc, 2b
- flush %g6
+ nop
+
5: stxa %g0, [%g3] ASI_DMMU
/*IC9*/ stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS
+ flush %g6
+
+ /* Spitfire Errata #32 workaround. */
+ mov 0x8, %o4
+ stxa %g0, [%o4] ASI_DMMU
+ flush %g6
+
ba,pt %xcc, 3b
- flush %g6
+ nop
.align 32
__flush_tlb_mm_slow:
clr %l6
99: retry
+ .data
+
+errata32_hwbug:
+ .xword 0
+
+ .text
+
/* These two are not performance critical... */
.globl xcall_flush_tlb_all
xcall_flush_tlb_all:
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
clr %g2
clr %g3
1: ldxa [%g3] ASI_DTLB_DATA_ACCESS, %g4
and %g4, _PAGE_L, %g5
brnz,pn %g5, 2f
mov TLB_TAG_ACCESS, %g7
+
stxa %g0, [%g7] ASI_DMMU
membar #Sync
-
stxa %g0, [%g3] ASI_DTLB_DATA_ACCESS
membar #Sync
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
2: ldxa [%g3] ASI_ITLB_DATA_ACCESS, %g4
and %g4, _PAGE_L, %g5
brnz,pn %g5, 2f
mov TLB_TAG_ACCESS, %g7
+
stxa %g0, [%g7] ASI_IMMU
membar #Sync
-
stxa %g0, [%g3] ASI_ITLB_DATA_ACCESS
+ membar #Sync
+
+ /* Spitfire Errata #32 workaround. */
+ sethi %hi(errata32_hwbug), %g4
+ stx %g0, [%g4 + %lo(errata32_hwbug)]
+
2: add %g2, 1, %g2
cmp %g2, 63
ble,pt %icc, 1b
static void update_attr(int currcons)
{
attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
- video_erase_char = (build_attr(currcons, color, 1, 0, 0, decscnm) << 8) | ' ';
+ video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
}
/* Note: inverting the screen twice should revert to the original state */
{
if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
return;
-
- disable_bh(CONSOLE_BH);
-
if (deccm) {
if (currcons == sel_cons)
clear_selection();
sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
} else
hide_cursor(currcons);
-
- enable_bh(CONSOLE_BH);
}
static void set_origin(int currcons)
himask = hi_font_mask;
charmask = himask ? 0x1ff : 0xff;
- disable_bh(CONSOLE_BH);
-
/* undraw cursor first */
if (IS_FG)
hide_cursor(currcons);
+ disable_bh(CONSOLE_BH);
while (!tty->stopped && count) {
enable_bh(CONSOLE_BH);
if (from_user)
void gs_shutdown_port (struct gs_port *port)
{
long flags;
-
+ func_enter();
if (!(port->flags & ASYNC_INITIALIZED))
return;
port->flags &= ~ASYNC_INITIALIZED;
restore_flags (flags);
+ func_exit();
}
*
* Revision history:
* $Log: sx.c,v $
+ * Revision 1.32 2000/03/07 90:00:00 wolff,pvdl
+ * - Fixed some sx_dprintk typos
+ * - added detection for an invalid board/module configuration
+ *
+ * Revision 1.31 2000/03/06 12:00:00 wolff,pvdl
+ * - Added support for EISA
+ *
* Revision 1.30 2000/01/21 17:43:06 wolff
* - Added support for SX+
*
* */
-#define RCS_ID "$Id: sx.c,v 1.30 2000/01/21 17:43:06 wolff Exp $"
-#define RCS_REV "$Revision: 1.30 $"
+#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.32 $"
#include <linux/module.h>
static int sx_init_board (struct sx_board *board);
static int sx_init_portstructs (int nboards, int nports);
static int sx_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
static int sx_fw_open(struct inode *inode, struct file *filp);
static INT sx_fw_release(struct inode *inode, struct file *filp);
static int sx_init_drivers(void);
int sx_maxints = 100;
/* These are the only open spaces in my computer. Yours may have more
- or less.... */
+ or less.... -- REW
+ duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
+*/
int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
0xc8000, 0xd8000, 0xe8000};
int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
- 0xc8000, 0xd8000, 0xe8000};
+ 0xc8000, 0xd8000, 0xe8000, 0xa0000};
#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
#ifndef TWO_ZERO
#ifdef MODULE
+MODULE_PARM(sx_probe_addrs, "i");
+MODULE_PARM(si_probe_addrs, "i");
MODULE_PARM(sx_poll, "i");
MODULE_PARM(sx_slowpoll, "i");
MODULE_PARM(sx_maxints, "i");
printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
return 0;
}
+ } else if (IS_EISA_BOARD(board)) {
+ outb(board->irq<<4, board->eisa_base+0xc02);
} else {
/* Gory details of the SI/ISA board */
write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
{
if (IS_SX_BOARD (board)) {
write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+ } else if (IS_EISA_BOARD(board)) {
+ write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
+ outb((board->irq<<4)|4, board->eisa_base+0xc02);
} else {
/* Don't bug me about the clear_set.
I haven't the foggiest idea what it's about -- REW */
write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) |
SX_CONF_BUSEN |
SX_CONF_HOSTIRQ);
+ } else if (IS_EISA_BOARD(board)) {
+ inb(board->eisa_base+0xc03);
} else {
switch (board->irq) {
case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
return module_type >> 4;
}
+static void sx_reconfigure_port(struct sx_port *port)
+{
+ if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
+ if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+ printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+ }
+ } else {
+ sx_dprintk (SX_DEBUG_TERMIOS,
+ "sx: Not sending reconfigure: port isn't open (%02x).\n",
+ sx_read_channel_byte (port, hi_hstat));
+ }
+}
static void sx_setsignals (struct sx_port *port, int dtr, int rts)
{
sx_write_channel_byte (port, hi_txoff, STOP_CHAR (port->gs.tty));
sx_write_channel_byte (port, hi_rxoff, STOP_CHAR (port->gs.tty));
- if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
- if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
- printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
- }
- } else {
- sx_dprintk (SX_DEBUG_TERMIOS,
- "sx: Not sending reconfigure: port isn't open (%02x).\n",
- sx_read_channel_byte (port, hi_hstat));
- }
-
+ sx_reconfigure_port(port);
/* Tell line discipline whether we will do input cooking */
if(I_OTHER(port->gs.tty)) {
sx_write_board_word (board, cc_int_pending, 0);
if (IS_SX_BOARD (board)) {
write_sx_byte (board, SX_RESET_IRQ, 1);
+ } else if (IS_EISA_BOARD(board)) {
+ inb(board->eisa_base+0xc03);
+ write_sx_word(board, 8, 0);
} else {
write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
port->gs.flags &= ~ GS_ACTIVE;
if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
sx_setsignals (port, 0, 0);
+ sx_reconfigure_port(port);
}
func_exit();
board = &boards[arg];
break;
case SXIO_GET_TYPE:
- rc = -1; /* If we manage to miss one, return error. */
+ rc = -ENOENT; /* If we manage to miss one, return error. */
if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
+ if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
break;
case SXIO_DO_RAMTEST:
Get_user(ival, (unsigned int *) arg);
sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
((ival & TIOCM_RTS) ? 1 : -1));
+ sx_reconfigure_port(port);
}
break;
case TIOCMBIC:
Get_user(ival, (unsigned int *) arg);
sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
((ival & TIOCM_RTS) ? 0 : -1));
+ sx_reconfigure_port(port);
}
break;
case TIOCMSET:
Get_user(ival, (unsigned int *) arg);
sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
((ival & TIOCM_RTS) ? 1 : 0));
+ sx_reconfigure_port(port);
}
break;
chans=0;
break;
}
- if (IS_SI_BOARD(board) && (mod_compat_type(type) == 4)) {
+ if ((IS_EISA_BOARD(board) ||
+ IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
printk (KERN_ERR "sx: This is an invalid configuration.\n"
"Don't use SXDCs on an SI/XIO adapter.\n");
chans=0;
if (sx_debug & SX_DEBUG_PROBE)
my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8);
- for (i=0;i<8;i++) {
- if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
- return 0;
+ if (!IS_EISA_BOARD(board)) {
+ for (i=0;i<8;i++) {
+ if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+ return 0;
+ }
}
}
unsigned int t;
#define CNTRL_REG_OFFSET 0x50
-#define CNTRL_REG_GOODVALUE 0x00260000
+#define CNTRL_REG_GOODVALUE 0x18260000
pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
{
int i;
int found = 0;
+ int eisa_slot;
struct sx_board *board;
#ifdef CONFIG_PCI
for (i=0;i<NR_SX_ADDRS;i++) {
board = &boards[found];
board->hw_base = sx_probe_addrs[i];
+ board->base2 =
board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
board->flags &= ~SX_BOARD_TYPE;
board->flags |= SX_ISA_BOARD;
for (i=0;i<NR_SI_ADDRS;i++) {
board = &boards[found];
board->hw_base = si_probe_addrs[i];
+ board->base2 =
board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
board->flags &= ~SX_BOARD_TYPE;
board->flags |= SI_ISA_BOARD;
}
}
+ sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
+ for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
+ {
+ if((inb(eisa_slot+0xc80)==0x4d) &&
+ (inb(eisa_slot+0xc81)==0x98))
+ {
+ sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
+ "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
+
+ board = &boards[found];
+ board->eisa_base = eisa_slot;
+ board->flags &= ~SX_BOARD_TYPE;
+ board->flags |= SI_EISA_BOARD;
+
+ board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
+ board->base2 =
+ board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+
+ sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %x\n", board->hw_base);
+ sx_dprintk(SX_DEBUG_PROBE, "base: %x\n", board->base);
+ board->irq = inb(board->eisa_base+0xc02)>>4;
+ sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+
+ probe_si(board);
+
+ found++;
+ }
+ }
if (found) {
printk (KERN_INFO "sx: total of %d boards detected.\n", found);
func_exit();
}
#endif
-
-
-
-
-/*
- * Anybody who knows why this doesn't work for me, please tell me -- REW.
- * Snatched from scsi.c (fixed one spelling error):
- * Overrides for Emacs so that we follow Linus' tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
unsigned int base;
unsigned int base2;
unsigned int hw_base;
+ int eisa_base;
int port_base; /* Number of the first port */
struct sx_port *ports;
int nports;
#define SX_PCI_BOARD 0x00000004
#define SX_CFPCI_BOARD 0x00000008
#define SX_CFISA_BOARD 0x00000010
+#define SI_EISA_BOARD 0x00000020
#define SX_BOARD_PRESENT 0x00001000
#define SX_BOARD_INITIALIZED 0x00002000
#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
+#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
+
#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
#define SERIAL_TYPE_NORMAL 1
#define SI2_EISA_OFF 0x42
#define SI2_EISA_VAL 0x01
+#define SI2_EISA_WINDOW_LEN 0x10000
/*****************************************************************************
*********************************** **********************************
/* Skip I/O spaces */
if(!(dev->base_address[i]&PCI_BASE_ADDRESS_SPACE))
{
- memptr=dev->base_address[i]&~3;
+ memptr=dev->base_address[i]&~15;
break;
}
}
fi
tristate 'Apricot Xen-II on board Ethernet' CONFIG_APRICOT
tristate 'CS89x0 support' CONFIG_CS89x0
- tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+ fi
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
if [ "$CONFIG_DEC_ELCP" != "y" ]; then
if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
bool 'WAN drivers' CONFIG_WAN_DRIVERS
if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
- dep_tristate 'Sangoma WANPIPE(tm) multi-prot cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS
+ dep_tristate 'Sangoma WANPIPE(tm) multi-port cards: (select M not Y !)' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS
+ if [ "$CONFIG_INET" != "n" ]; then
if [ "$CONFIG_VENDOR_SANGOMA" != "n" ]; then
- int ' Maximum number of cards' CONFIG_WANPIPE_CARDS 1
- #bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25
- bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
- bool ' WANPIPE PPP support' CONFIG_WANPIPE_PPP
- bool ' WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
- fi
+ int ' Maximum number of cards' CONFIG_WANPIPE_CARDS 1
+ #bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25
+ bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
+ bool ' WANPIPE PPP support' CONFIG_WANPIPE_PPP
+ bool ' WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
+ fi
+ fi
fi
fi
/* void enableReceive(struct device* dev);
*/
-static int arlan_command(struct device * dev, int command);
#define ARLAN_STR_SIZE 0x2ff0
return "type A672T";
}
}
+#ifdef ARLAN_DEBUGING
static void arlan_print_diagnostic_info(struct device *dev)
{
return 0; /* no errors */
}
+#endif
#ifdef ARLAN_PROC_INTERFACE
#ifdef ARLAN_PROC_SHM_DUMP
{num , #nam, &(arlan_conf[card].nam), \
sizeof(int), 0600, NULL, &proc_dointvec}
+#ifdef ARLAN_DEBUGING
+
+#define ARLAN_PROC_DEBUG_ENTRIES {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
+ sizeof(int), 0600, NULL, &proc_dointvec},\
+ {49, "debug", &arlan_debug, \
+ sizeof(int), 0600, NULL, &proc_dointvec},
+#else
+#define ARLAN_PROC_DEBUG_ENTRIES
+#endif
+
#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
CTBLN(1,cardNo,spreadingCode),\
CTBLN(45,cardNo,radioType),\
CTBLN(46,cardNo,writeEEPROM),\
CTBLN(47,cardNo,writeRadioType),\
- {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
- sizeof(int), 0600, NULL, &proc_dointvec},\
- {49, "debug", &arlan_debug, \
- sizeof(int), 0600, NULL, &proc_dointvec},\
+ ARLAN_PROC_DEBUG_ENTRIES\
CTBLN(50,cardNo,in_speed),\
CTBLN(51,cardNo,out_speed),\
CTBLN(52,cardNo,in_speed10),\
};
#endif
-static int mmtu = 1234;
+
+// static int mmtu = 1234;
static ctl_table arlan_root_table[] =
{
};
/* Make sure that /proc/sys/dev is there */
-static ctl_table arlan_device_root_table[] =
-{
- {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
- {0}
-};
+//static ctl_table arlan_device_root_table[] =
+//{
+// {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
+// {0}
+//};
static int radioNodeId = radioNodeIdUNKNOWN;
static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
static char *siteName = siteNameUNKNOWN;
-static int irq = irqUNKNOWN;
static int mem = memUNKNOWN;
-static int arlan_debug = debugUNKNOWN;
+int arlan_debug = debugUNKNOWN;
static int probe = probeUNKNOWN;
static int numDevices = numDevicesUNKNOWN;
-static int testMemory = testMemoryUNKNOWN;
static int spreadingCode = spreadingCodeUNKNOWN;
static int channelNumber = channelNumberUNKNOWN;
static int channelSet = channelSetUNKNOWN;
static int systemId = systemIdUNKNOWN;
static int registrationMode = registrationModeUNKNOWN;
-static int txScrambled = 1;
static int keyStart = 0;
-static int mdebug = 0;
static int tx_delay_ms = 0;
static int retries = 5;
static int async = 1;
static int tx_queue_len = 1;
+static int arlan_EEPROM_bad = 0;
+int arlan_entry_and_exit_debug = 0;
+
+#ifdef ARLAN_DEBUGING
+
static int arlan_entry_debug = 0;
static int arlan_exit_debug = 0;
-static int arlan_entry_and_exit_debug = 0;
-static int arlan_EEPROM_bad = 0;
+static int testMemory = testMemoryUNKNOWN;
+static int irq = irqUNKNOWN;
+static int txScrambled = 1;
+static int mdebug = 0;
+#endif
#if LINUX_VERSION_CODE > 0x20100
MODULE_PARM(irq, "i");
}
else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
{
+ priv->under_reset=1;
+ dev->tbusy = 1;
+
arlan_drop_tx(dev);
if (priv->tx_command_given || priv->rx_command_given)
{
printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
};
+ dev->tbusy = 1;
if (arlan_debug & ARLAN_DEBUG_RESET)
printk(KERN_ERR "%s: Doing chip reset\n", dev->name);
priv->lastReset = jiffies;
{
priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;
priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+ priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR;
priv->card_polling_interval = HZ / 10;
priv->tx_command_given = 0;
priv->under_config = 0;
- if (dev->tbusy || !dev->start)
- {
- dev->tbusy = 0;
- dev->start = 1;
- mark_bh(NET_BH);
- };
}
else
{
WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);
WRITESHMB(arlan->commandParameter[0], conf->rxParameter);
arlan_interrupt_lancpu(dev);
- priv->rx_command_given;
+ priv->rx_command_given = 0; // mnjah, bad
priv->last_rx_time = arlan_time();
priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;
priv->card_polling_interval = 1;
else
priv->card_polling_interval = 2;
}
+ else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR)
+ {
+ if ( !registrationBad(dev) && (dev->tbusy || !dev->start) )
+ {
+ priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR;
+
+ dev->tbusy = 0;
+ dev->start = 1;
+ mark_bh(NET_BH);
+ };
+ }
else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)
{
if (!test_and_set_bit(0, (void *) &priv->tx_command_given))
add_timer(&priv->timer);
}
-
+#ifdef ARLAN_DEBUGING
static void arlan_print_registers(struct device *dev, int line)
ARLAN_DEBUG_EXIT("arlan_print_registers");
}
+#endif
static int arlan_hw_tx(struct device *dev, char *buf, int length)
volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
+// if (check_mem_region(virt_to_phys((void *)memaddr),0x2000 )){
+// // printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",virt_to_phys((void*)memaddr));
+// return -ENODEV;
+// };
memcpy_fromio(tempBuf, arlan->textRegion, 29);
tempBuf[30] = 0;
/* check for card at this address */
- if (0 != strncmp(tempBuf, probeText, 29))
+ if (0 != strncmp(tempBuf, probeText, 29)){
+// not release_mem_region(virt_to_phys((void*)memaddr),0x2000);
return -ENODEV;
+ }
// printk(KERN_INFO "arlan found at 0x%x \n",memaddr);
ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
if (mem != 0 && numDevices == 1) /* Check a single specified location. */
{
- if (arlan_probe_here(dev, mem) == 0)
+ if (arlan_probe_here(dev, (int) phys_to_virt( mem) ) == 0)
return 0;
else
return -ENODEV;
}
- for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000)
+ for (m = (int)phys_to_virt(lastFoundAt) + 0x2000; m <= (int)phys_to_virt(0xDE000); m += 0x2000)
{
if (arlan_probe_here(dev, m) == 0)
{
found++;
- lastFoundAt = m;
+ lastFoundAt = (int)virt_to_phys((void*)m);
break;
}
probed++;
ARLAN_DEBUG_ENTRY("arlan_find_devices");
if (mem != 0 && numDevices == 1) /* Check a single specified location. */
return 1;
- for (m = 0xc000; m <= 0xDE000; m += 0x2000)
+ for (m =(int) phys_to_virt(0xc0000); m <=(int) phys_to_virt(0xDE000); m += 0x2000)
{
if (arlan_check_fingerprint(m) == 0)
found++;
printk(KERN_CRIT "init_etherdev failed ");
return 0;
}
+
+ memset(dev->priv,0,sizeof(struct arlan_private));
+
((struct arlan_private *) dev->priv)->conf =
kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL);
dev->set_multicast_list = arlan_set_multicast;
dev->change_mtu = arlan_change_mtu;
dev->set_mac_address = arlan_mac_addr;
+ dev->tbusy = 1;
+ dev->start = 0;
+
((struct arlan_private *) dev->priv)->irq_test_done = 0;
arlan_device[num] = dev;
((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]);
if (arlan_check_fingerprint(memaddr))
return -ENODEV;
- printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr);
+ printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, (int) virt_to_phys((void*)memaddr));
if (!arlan_allocate_device(arlans_found, dev))
return -1;
return ret;
arlan = ((struct arlan_private *) dev->priv)->card;
-
if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev))
{
printk(KERN_ERR "%s: unable to get IRQ %d .\n",
dev->name, dev->irq);
return -EAGAIN;
}
- arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+
priv->bad = 0;
priv->lastReset = 0;
dev->tbusy = 1;
priv->txOffset = 0;
dev->interrupt = 0;
- dev->start = 1;
+ dev->start = 0;
dev->tx_queue_len = tx_queue_len;
- init_timer(&priv->timer);
- priv->timer.expires = jiffies + HZ / 10;
- priv->timer.data = (unsigned long) dev;
- priv->timer.function = &arlan_registration_timer; /* timer handler */
priv->interrupt_processing_active = 0;
priv->command_lock = 0;
- add_timer(&priv->timer);
priv->card_lock = MUTEX;
myATOMIC_INIT(priv->card_users, 1); /* damn 2.0.33 */
priv->registrationLastSeen = jiffies;
priv->txLast = 0;
priv->tx_command_given = 0;
-
+ priv->rx_command_given = 0;
+
priv->reRegisterExp = 1;
priv->nof_tx = 0;
priv->nof_tx_ack = 0;
priv->Conf->registrationInterrupts = 1;
dev->tbusy = 0;
+ init_timer(&priv->timer);
+ priv->timer.expires = jiffies + HZ / 10;
+ priv->timer.data = (unsigned long) dev;
+ priv->timer.function = &arlan_registration_timer; /* timer handler */
+
+ arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+ udelay(200000);
+ dev->tbusy = 0;
+ dev->start = 1;
+ add_timer(&priv->timer);
MOD_INC_USE_COUNT;
#ifdef CONFIG_PROC_FS
}
ARLAN_DEBUG_ENTRY("arlan_close");
+ del_timer(&priv->timer);
+
+ arlan_command(dev, ARLAN_COMMAND_POWERDOWN);
+
IFDEBUG(ARLAN_DEBUG_STARTUP)
printk(KERN_NOTICE "%s: Closing device\n", dev->name);
priv->open_time = 0;
dev->tbusy = 1;
dev->start = 0;
- del_timer(&priv->timer);
free_irq(dev->irq, dev);
-
MOD_DEC_USE_COUNT;
ARLAN_DEBUG_EXIT("arlan_close");
return 0;
}
-
+#ifdef ARLAN_DEBUGING
static long alignLong(volatile u_char * ptr)
{
long ret;
memcpy_fromio(&ret, (void *) ptr, 4);
return ret;
}
-
+#endif
/*
* Get the current statistics.
}
if (probe)
arlan_probe_everywhere(arlan_device[i]);
+// arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
}
printk(KERN_INFO "Arlan driver %s\n", arlan_version);
ARLAN_DEBUG_EXIT("init_module");
{
if (arlan_device[i])
{
+ arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
+
+// release_mem_region(virt_to_phys(arlan_device[i]->mem_start), 0x2000 );
unregister_netdev(arlan_device[i]);
if (arlan_device[i]->priv)
{
#include <linux/etherdevice.h>
-#define DEBUG 1
+//#define ARLAN_DEBUGING 1
#define ARLAN_PROC_INTERFACE
#define MAX_ARLANS 4 /* not more than 4 ! */
#endif
extern struct device *arlan_device[MAX_ARLANS];
-static int arlan_debug;
-static char * siteName;
-static int arlan_entry_debug;
-static int arlan_exit_debug;
-static int arlan_entry_and_exit_debug;
-static int testMemory;
-static const char* arlan_version;
+extern int arlan_debug;
+extern char * siteName;
+extern int arlan_entry_debug;
+extern int arlan_exit_debug;
+extern int arlan_entry_and_exit_debug;
+extern int testMemory;
+extern const char* arlan_version;
+extern int arlan_command(struct device * dev, int command);
#define SIDUNKNOWN -1
#define radioNodeIdUNKNOWN -1
#define IFDEBUG( L ) if ( (L) & arlan_debug )
#define ARLAN_FAKE_HDR_LEN 12
-#ifdef DEBUG
+#ifdef ARLAN_DEBUGING
+ #define DEBUG 1
#define ARLAN_ENTRY_EXIT_DEBUGING 1
#define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
#else
-#define ARLAN_COMMAND_RX 0x00001
-#define ARLAN_COMMAND_NOOP 0x00002
-#define ARLAN_COMMAND_NOOPINT 0x00004
-#define ARLAN_COMMAND_TX 0x00008
-#define ARLAN_COMMAND_CONF 0x00010
-#define ARLAN_COMMAND_RESET 0x00020
-#define ARLAN_COMMAND_TX_ABORT 0x00040
-#define ARLAN_COMMAND_RX_ABORT 0x00080
-#define ARLAN_COMMAND_POWERDOWN 0x00100
-#define ARLAN_COMMAND_POWERUP 0x00200
-#define ARLAN_COMMAND_SLOW_POLL 0x00400
-#define ARLAN_COMMAND_ACTIVATE 0x00800
-#define ARLAN_COMMAND_INT_ACK 0x01000
-#define ARLAN_COMMAND_INT_ENABLE 0x02000
-#define ARLAN_COMMAND_WAIT_NOW 0x04000
-#define ARLAN_COMMAND_LONG_WAIT_NOW 0x08000
-#define ARLAN_COMMAND_STANDBY 0x10000
-#define ARLAN_COMMAND_INT_RACK 0x20000
-#define ARLAN_COMMAND_INT_RENABLE 0x40000
-#define ARLAN_COMMAND_CONF_WAIT 0x80000
+#define ARLAN_COMMAND_RX 0x000001
+#define ARLAN_COMMAND_NOOP 0x000002
+#define ARLAN_COMMAND_NOOPINT 0x000004
+#define ARLAN_COMMAND_TX 0x000008
+#define ARLAN_COMMAND_CONF 0x000010
+#define ARLAN_COMMAND_RESET 0x000020
+#define ARLAN_COMMAND_TX_ABORT 0x000040
+#define ARLAN_COMMAND_RX_ABORT 0x000080
+#define ARLAN_COMMAND_POWERDOWN 0x000100
+#define ARLAN_COMMAND_POWERUP 0x000200
+#define ARLAN_COMMAND_SLOW_POLL 0x000400
+#define ARLAN_COMMAND_ACTIVATE 0x000800
+#define ARLAN_COMMAND_INT_ACK 0x001000
+#define ARLAN_COMMAND_INT_ENABLE 0x002000
+#define ARLAN_COMMAND_WAIT_NOW 0x004000
+#define ARLAN_COMMAND_LONG_WAIT_NOW 0x008000
+#define ARLAN_COMMAND_STANDBY 0x010000
+#define ARLAN_COMMAND_INT_RACK 0x020000
+#define ARLAN_COMMAND_INT_RENABLE 0x040000
+#define ARLAN_COMMAND_CONF_WAIT 0x080000
+#define ARLAN_COMMAND_TBUSY_CLEAR 0x100000
#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\
| ARLAN_COMMAND_RX_ABORT\
| ARLAN_COMMAND_CONF)
#include <linux/kmod.h>
#endif
+#ifndef CONFIG_PROC_FS
+#error For now, COMX really needs the /proc filesystem
+#endif
+
#include "comx.h"
#include "syncppp.h"
return -EFAULT;
return (0);
case DGRS_SETFILTER:
+ if (!suser())
+ return -EPERM;
if (ioc.port > privN->bcomm->bc_nports)
return -EINVAL;
if (ioc.filter >= NFILTERS)
priv->intrcnt = 0;
for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
{
- rmb(); /* gcc 2.95 needs this */
+ barrier(); /* gcc 2.95 needs this */
if (priv->intrcnt >= 2)
break;
}
break;
case HDLCDRVCTL_CALIBRATE:
+ if (!suser())
+ return -EACCES;
bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8;
return 0;
break;
case HDLCDRVCTL_CALIBRATE:
+ if(!suser())
+ return -EPERM;
s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
return 0;
pc->nibble = nl->nibble;
break;
case PLIP_SET_TIMEOUT:
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
nl->trigger = pc->trigger;
nl->nibble = pc->nibble;
break;
printk("RCioctl: cmd = 0x%x\n", cmd);
#endif
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
switch (cmd) {
case RCU_PROTOCOL_REV:
case RCU_COMMAND:
{
-#ifdef LINUX_2_1
if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
return -EFAULT;
-#else
- int error;
- error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
- if (error) {
- return error;
- }
- memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
-#endif
#ifdef RCDEBUG
printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
RCUD_DEFAULT -> rc = 0x11223344;
break;
}
-#ifdef LINUX_2_1
- copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
-#else
- memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
-#endif
+ if(copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser)))
+ return -EFAULT;
break;
} /* RCU_COMMAND */
}
case SIOCDEVRESINSTATS:
{
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
DP( printk("%s: SIOCDEVRESINSTATS\n",dev->name); )
lp->in_stats.all_rx_number = 0;
lp->in_stats.bad_rx_number = 0;
* - SysKonnect TR4/16(+) ISA (SK-4190)
* - SysKonnect TR4/16(+) PCI (SK-4590)
* - SysKonnect TR4/16 PCI (SK-4591)
+ * - Compact TR PCI adapters
+ * - Proteon TR ISA adapters (1392, 1392+)
*
* Sources:
* - The hardware related parts of this driver are take from
* as samples for some tasks.
*
* Maintainer(s):
- * JS Jay Schulist jschlst@samba.anu.edu.au
+ * retired: JS Jay Schulist jschlst@samba.anu.edu.au
* CG Christoph Goos cgoos@syskonnect.de
* AF Adam Fritzler mid@auk.cx
*
+ * Contributor(s):
+ * AB Alexander Bech Initiated Proteon works
+ *
* Modification History:
* 29-Aug-97 CG Created
* 04-Apr-98 CG Fixed problems caused by tok_timer_check
* 21-Sep-99 AF Added multicast changes recommended by
* Jochen Friedrich <jochen@nwe.de> (untested)
* Added detection of compatible Compaq PCI card
+ * 04-Jan-2000 CG Fixed tx-send/release synchronization
+ * 04-Mar-2000 CG Added detection/init of Proteon ISA card
+ * 05-Mar-2000 CG Added line speed setting (parameter "rate")
*
* To do:
- * 1. Selectable 16 Mbps or 4Mbps
+ * 1. Selectable 16 Mbps or 4Mbps (CG: done)
* 2. Multi/Broadcast packet handling (might be done)
*
*/
-static const char *version = "sktr.c: v1.01 08/29/97 by Christoph Goos\n";
+static const char *version = "sktr.c: v1.02 08/29/97 by Christoph Goos\n";
#ifdef MODULE
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int sktr_portlist[] __initdata = {
- 0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,
+ 0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
+ 0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.
+ 0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.
+ 0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.
+ 0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.
0
};
0
};
+static unsigned short proteon_irqlist[] = {
+ 7, 6, 5, 4, 3, 12, 11, 10, 9,
+ 0
+};
+static int proteon_dmalist[] __initdata = {
+ 5, 6, 7,
+ 0
+};
+
+
/* Card names */
static char *pci_cardname = "SK NET TR 4/16 PCI\0";
static char *isa_cardname = "SK NET TR 4/16 ISA\0";
+static char *proteon_cardname = "Proteon 1392\0";
static char *AdapterName;
+static int AdapterNum = 0;
+
+#ifdef MODULE
+static int rate[SKTR_MAX_ADAPTERS] = { SPEED_16, };
+#endif
+
/* Use 0 for production, 1 for verification, 2 for debug, and
* 3 for very verbose debug.
*/
static void sktr_init_net_local(struct device *dev);
static void sktr_init_opb(struct net_local *tp);
static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int sktr_isa_chk_card(struct device *dev, int ioaddr);
+static int sktr_isa_chk_card(struct device *dev, int ioaddr,
+ int *cardtype);
static int sktr_isa_chk_ioaddr(int ioaddr);
+static int prot_isa_chk_ioaddr(int ioaddr);
/* "O" */
static int sktr_open(struct device *dev);
static void sktr_open_adapter(struct device *dev);
static int sktr_reset_adapter(struct device *dev);
static void sktr_reset_interrupt(struct device *dev);
static void sktr_ring_status_irq(struct device *dev);
+static void sktr_reg_setup(struct device *dev);
+static void prot_reg_setup(struct device *dev);
/* "S" */
static int sktr_send_packet(struct sk_buff *skb, struct device *dev);
static void sktr_set_multicast_list(struct device *dev);
}
/*
- * Detect and setup the ISA SysKonnect TR cards.
+ * Detect and setup the ISA Proteon and SysKonnect TR cards.
*/
-__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
+__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr,
+int *cardtype))
{
int i, err;
unsigned long flags;
+ unsigned short *irqlist;
+ int *dmalist;
+
+ err = prot_isa_chk_ioaddr(ioaddr);
+ if (err < 0) {
+ err = sktr_isa_chk_ioaddr(ioaddr);
+ if(err < 0)
+ return (-ENODEV);
+ AdapterName = isa_cardname;
+ *cardtype = SK_ISA;
+ irqlist = sktr_irqlist;
+ dmalist = sktr_dmalist;
+ } else {
+ AdapterName = proteon_cardname;
+ *cardtype = PROT_ISA;
+ irqlist = proteon_irqlist;
+ dmalist = proteon_dmalist;
+ }
- err = sktr_isa_chk_ioaddr(ioaddr);
- if(err < 0)
- return (-ENODEV);
if(virt_to_bus((void*)((unsigned long)dev->priv+sizeof(struct net_local)))
> ISA_MAX_ADDRESS)
return (-EAGAIN);
}
- AdapterName = isa_cardname;
-
/* Grab the region so that no one else tries to probe our ioports. */
request_region(ioaddr, SKTR_IO_EXTENT, AdapterName);
dev->base_addr = ioaddr;
/* Autoselect IRQ and DMA if dev->irq == 0 */
if(dev->irq == 0)
{
- for(i = 0; sktr_irqlist[i] != 0; i++)
+ for(i = 0; irqlist[i] != 0; i++)
{
- dev->irq = sktr_irqlist[i];
+ dev->irq = irqlist[i];
err = request_irq(dev->irq, &sktr_interrupt, 0, AdapterName, dev);
if(!err)
break;
}
- if(sktr_irqlist[i] == 0)
+ if(irqlist[i] == 0)
{
printk("%s: AutoSelect no IRQ available\n", dev->name);
return (-EAGAIN);
/* Always allocate the DMA channel after IRQ and clean up on failure */
if(dev->dma == 0)
{
- for(i = 0; sktr_dmalist[i] != 0; i++)
+ for(i = 0; dmalist[i] != 0; i++)
{
- dev->dma = sktr_dmalist[i];
+ dev->dma = dmalist[i];
err = request_dma(dev->dma, AdapterName);
if(!err)
break;
err = sktr_pci_chk_card(dev);
if(err < 0)
{
- err = sktr_isa_chk_card(dev, ioaddr);
+ err = sktr_isa_chk_card(dev, ioaddr, &DeviceType);
if(err < 0)
return (-ENODEV);
- DeviceType = SK_ISA;
}
/* Setup this devices private information structure */
return (-ENOMEM);
memset(tp, 0, sizeof(struct net_local));
tp->DeviceType = DeviceType;
+ if(DeviceType == SK_ISA || DeviceType == PROT_ISA)
+ tp->BusType = BUS_TYPE_ISA;
+ else
+ tp->BusType = BUS_TYPE_PCI;
+ tp->DataRate = rate[AdapterNum];
+ AdapterNum++;
dev->priv = tp;
dev->init = sktr_init_card;
return (0);
}
+/*
+ * This function tests if a proteon adapter is really installed at the
+ * given I/O address. Return negative if no adapter at IO addr.
+ */
+__initfunc(static int prot_isa_chk_ioaddr(int ioaddr))
+{
+ unsigned char chk1, chk2;
+ int i;
+
+ chk1 = inb(ioaddr + 0x1f); /* Get Proteon ID reg 1 */
+ if (chk1 != 0x1f)
+ return (-1);
+ chk1 = inb(ioaddr + 0x1e) & 0x07; /* Get Proteon ID reg 0 */
+ for (i=0; i<16; i++) {
+ chk2 = inb(ioaddr + 0x1e) & 0x07;
+ if (((chk1 + 1) & 0x07) != chk2)
+ return (-1);
+ chk1 = chk2;
+ }
+ return (0);
+}
+
/*
* Open/initialize the board. This is called sometime after
* booting when the 'ifconfig' program is run.
err = sktr_chipset_init(dev);
if(err)
{
- printk(KERN_INFO "%s: Chipset initialization error\n",
+ printk("%s: Chipset initialization error\n",
dev->name);
return (-1);
}
return;
}
+/* setup non-standard registers for SK ISA adapters */
+static void sktr_reg_setup(struct device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned char PosReg, Tmp;
+ int i;
+ unsigned short *irqlist;
+
+ irqlist = sktr_irqlist;
+ PosReg = 0;
+ for(i = 0; irqlist[i] != 0; i++)
+ {
+ if(irqlist[i] == dev->irq)
+ break;
+ }
+
+ /* Choose default cycle time, 500 nsec */
+ PosReg |= CYCLE_TIME << 2;
+ PosReg |= i << 4;
+ i = dev->dma - 5;
+ PosReg |= i;
+
+ if(tp->DataRate == SPEED_4)
+ PosReg |= LINE_SPEED_BIT;
+ else
+ PosReg &= ~LINE_SPEED_BIT;
+
+ outb(PosReg, dev->base_addr + POSREG);
+ Tmp = inb(dev->base_addr + POSREG);
+ if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
+ printk("%s: POSREG error\n", dev->name);
+
+ return;
+}
+
+/* setup non-standard registers for Proteon ISA adapters */
+static void prot_reg_setup(struct device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned char PosReg;
+ int i;
+ unsigned short *irqlist;
+
+ /* Proteon reset sequence */
+ outb(0, dev->base_addr + 0x11);
+ mdelay(20);
+ outb(0x04, dev->base_addr + 0x11);
+ mdelay(20);
+ outb(0, dev->base_addr + 0x11);
+ mdelay(100);
+
+ /* set control/status reg */
+ PosReg = inb(dev->base_addr + 0x11);
+ PosReg |= 0x78;
+ PosReg &= 0xf9;
+ if(tp->DataRate == SPEED_4)
+ PosReg |= 0x20;
+ else
+ PosReg &= ~0x20;
+
+ outb(PosReg, dev->base_addr + 0x11);
+ outb(0xff, dev->base_addr + 0x12);
+ irqlist = proteon_irqlist;
+ for(i = 0; irqlist[i] != 0; i++)
+ {
+ if(irqlist[i] == dev->irq)
+ break;
+ }
+
+ PosReg = i;
+ i = (7 - dev->dma) << 4;
+ PosReg |= i;
+ outb(PosReg, dev->base_addr + 0x13);
+
+ return;
+}
+
/*
* Initialize the chipset
*/
static int sktr_chipset_init(struct device *dev)
{
struct net_local *tp = (struct net_local *)dev->priv;
- unsigned char PosReg, Tmp;
- int i, err;
+ int err;
sktr_init_ipb(tp);
sktr_init_opb(tp);
/* Set pos register: selects irq and dma channel.
* Only for ISA bus adapters.
*/
- if(dev->dma > 0)
- {
- PosReg = 0;
- for(i = 0; sktr_irqlist[i] != 0; i++)
- {
- if(sktr_irqlist[i] == dev->irq)
- break;
- }
-
- /* Choose default cycle time, 500 nsec */
- PosReg |= CYCLE_TIME << 2;
- PosReg |= i << 4;
- i = dev->dma - 5;
- PosReg |= i;
-
- if(tp->DataRate == SPEED_4)
- PosReg |= LINE_SPEED_BIT;
- else
- PosReg &= ~LINE_SPEED_BIT;
-
- outb(PosReg, dev->base_addr + POSREG);
- Tmp = inb(dev->base_addr + POSREG);
- if((Tmp & ~CYCLE_TIME) != (PosReg & ~CYCLE_TIME))
- printk(KERN_INFO "%s: POSREG error\n", dev->name);
- }
+ if (tp->DeviceType == SK_ISA)
+ sktr_reg_setup(dev);
+ else if (tp->DeviceType == PROT_ISA)
+ prot_reg_setup(dev);
err = sktr_reset_adapter(dev);
- if(err < 0)
+ if(err < 0) {
+ printk("sktr_reset_adapter failed\n");
return (-1);
+ }
err = sktr_bringup_diags(dev);
- if(err < 0)
+ if(err < 0) {
+ printk("sktr_bringup_diag failed\n");
return (-1);
+ }
err = sktr_init_adapter(dev);
- if(err < 0)
+ if(err < 0) {
+ printk("sktr_init_adapter failed\n");
return (-1);
+ }
return (0);
}
tp->LobeWireFaultLogged = 0;
tp->LastOpenStatus = 0;
tp->MaxPacketSize = DEFAULT_PACKET_SIZE;
+ tp->Sending = 0;
skb_queue_head_init(&tp->SendSkbQueue);
- tp->QueueSkb = MAX_TX_QUEUE;
+ atomic_set(&tp->QueueSkb, MAX_TX_QUEUE);
/* Create circular chain of transmit lists */
for (i = 0; i < TPL_NUM; i++)
skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
/* data unreachable for DMA ? then use local buffer */
- if(tp->DeviceType == SK_ISA &&
+ if(tp->BusType == BUS_TYPE_ISA &&
virt_to_bus(tp->Rpl[i].Skb->data) +
tp->MaxPacketSize > ISA_MAX_ADDRESS)
{
tp->Rpl[i].SkbStat = SKB_DATA_COPY;
- tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
+ tp->Rpl[i].FragList[0].DataAddr =
+ htonl(virt_to_bus(
+ tp->LocalRxBuffers[i]));
tp->Rpl[i].MData = tp->LocalRxBuffers[i];
}
else /* DMA directly in skb->data */
return (1);
}
- if(tp->QueueSkb == 0)
+ if(atomic_read(&tp->QueueSkb) == 0)
return (1); /* Return with tbusy set: queue full */
- tp->QueueSkb--;
+ atomic_dec(&tp->QueueSkb);
skb_queue_tail(&tp->SendSkbQueue, skb);
sktr_hardware_send_packet(dev, tp);
- if(tp->QueueSkb > 0)
+ if(atomic_read(&tp->QueueSkb) > 0)
dev->tbusy = 0;
return (0);
struct sk_buff *skb;
int i;
+ tp->Sending = 1;
for(;;)
{
/* Try to get a free TPL from the chain.
*/
if(tp->TplFree->NextTPLPtr->BusyFlag) /* No free TPL */
{
- printk(KERN_INFO "%s: No free TPL\n", dev->name);
+ // printk("%s: No free TPL\n", dev->name);
+ tp->Sending = 0;
return;
}
/* Send first buffer from queue */
skb = skb_dequeue(&tp->SendSkbQueue);
- if(skb == NULL)
+ if(skb == NULL) {
+ tp->Sending = 0;
return;
+ }
- tp->QueueSkb++;
+ atomic_inc(&tp->QueueSkb);
/* Is buffer reachable for Busmaster-DMA? */
- if(tp->DeviceType == SK_ISA &&
+ if(tp->BusType == BUS_TYPE_ISA &&
virt_to_bus((void*)(((long) skb->data) + skb->len))
> ISA_MAX_ADDRESS)
{
tp->LastSendTime = jiffies;
tpl = tp->TplFree; /* Get the "free" TPL */
+ tpl->Status = 0; /* set to INVALID */
tpl->BusyFlag = 1; /* Mark TPL as busy */
tp->TplFree = tpl->NextTPLPtr;
sktr_exec_sifcmd(dev, CMD_TX_VALID);
}
+ tp->Sending = 0;
return;
}
sktr_chk_outstanding_cmds(dev);
if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
- && (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy))
+ && (atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE ||
+ tp->TplFree != tp->TplBusy))
{
/* Anything to send, but stalled to long */
tp->LastSendTime = jiffies;
if(!sktr_chk_ssb(tp, irq_type))
{
- printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
+ printk(KERN_DEBUG "%s: DATA LATE occurred\n",
+ dev->name);
break;
}
break;
default:
- printk(KERN_INFO "Unknown Token Ring IRQ\n");
+ printk(KERN_DEBUG "Unknown Token Ring IRQ\n");
break;
}
else /* The adapter did not open. */
{
if(ssb_parm_0 & NODE_ADDR_ERROR)
- printk(KERN_INFO "%s: Node address error\n",
+ printk("%s: Node address error\n",
dev->name);
if(ssb_parm_0 & LIST_SIZE_ERROR)
- printk(KERN_INFO "%s: List size error\n",
+ printk("%s: List size error\n",
dev->name);
if(ssb_parm_0 & BUF_SIZE_ERROR)
- printk(KERN_INFO "%s: Buffer size error\n",
+ printk("%s: Buffer size error\n",
dev->name);
if(ssb_parm_0 & TX_BUF_COUNT_ERROR)
- printk(KERN_INFO "%s: Tx buffer count error\n",
+ printk("%s: Tx buffer count error\n",
dev->name);
if(ssb_parm_0 & INVALID_OPEN_OPTION)
- printk(KERN_INFO "%s: Invalid open option\n",
+ printk("%s: Invalid open option\n",
dev->name);
if(ssb_parm_0 & OPEN_ERROR)
{
if(!tp->LobeWireFaultLogged)
{
tp->LobeWireFaultLogged = 1;
- printk(KERN_INFO "%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
+ printk("%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
}
tp->ReOpenInProgress = 1;
tp->AdapterOpenFlag = 0;
return;
case PHYSICAL_INSERTION:
- printk(KERN_INFO "%s: %s Physical insertion.\n", dev->name, open_err);
+ printk("%s: %s Physical insertion.\n", dev->name, open_err);
break;
case ADDRESS_VERIFICATION:
- printk(KERN_INFO "%s: %s Address verification.\n", dev->name, open_err);
+ printk("%s: %s Address verification.\n", dev->name, open_err);
break;
case PARTICIPATION_IN_RING_POLL:
- printk(KERN_INFO "%s: %s Participation in ring poll.\n", dev->name, open_err);
+ printk("%s: %s Participation in ring poll.\n", dev->name, open_err);
break;
case REQUEST_INITIALISATION:
- printk(KERN_INFO "%s: %s Request initialisation.\n", dev->name, open_err);
+ printk("%s: %s Request initialisation.\n", dev->name, open_err);
break;
case FULLDUPLEX_CHECK:
- printk(KERN_INFO "%s: %s Full duplex check.\n", dev->name, open_err);
+ printk("%s: %s Full duplex check.\n", dev->name, open_err);
break;
default:
- printk(KERN_INFO "%s: %s Unknown open phase\n", dev->name, open_err);
+ printk("%s: %s Unknown open phase\n", dev->name, open_err);
break;
}
switch(ssb_parm_0 & OPEN_ERROR_CODES_MASK)
{
case OPEN_FUNCTION_FAILURE:
- printk(KERN_INFO "%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
+ printk("%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
tp->LastOpenStatus =
OPEN_FUNCTION_FAILURE;
break;
case OPEN_SIGNAL_LOSS:
- printk(KERN_INFO "%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
+ printk("%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_SIGNAL_LOSS;
break;
case OPEN_TIMEOUT:
- printk(KERN_INFO "%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
+ printk("%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_TIMEOUT;
break;
case OPEN_RING_FAILURE:
- printk(KERN_INFO "%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
+ printk("%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_RING_FAILURE;
break;
case OPEN_RING_BEACONING:
- printk(KERN_INFO "%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
+ printk("%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_RING_BEACONING;
break;
case OPEN_DUPLICATE_NODEADDR:
- printk(KERN_INFO "%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
+ printk("%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_DUPLICATE_NODEADDR;
break;
case OPEN_REQUEST_INIT:
- printk(KERN_INFO "%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
+ printk("%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_REQUEST_INIT;
break;
case OPEN_REMOVE_RECEIVED:
- printk(KERN_INFO "%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
+ printk("%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
tp->LastOpenStatus =
OPEN_REMOVE_RECEIVED;
break;
case OPEN_FULLDUPLEX_SET:
- printk(KERN_INFO "%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
+ printk("%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
tp->LastOpenStatus =
OPEN_FULLDUPLEX_SET;
break;
default:
- printk(KERN_INFO "%s: %s Unknown open err code", dev->name, code_err);
+ printk("%s: %s Unknown open err code", dev->name, code_err);
tp->LastOpenStatus =
OPEN_FUNCTION_FAILURE;
break;
do {
retry_cnt--;
if(sktr_debug > 3)
- printk(KERN_INFO "BUD-Status: \n");
+ printk("BUD-Status: \n");
loop_cnt = BUD_MAX_LOOPCNT; /* maximum: three seconds*/
do { /* Inspect BUD results */
loop_cnt--;
Status &= STS_MASK;
if(sktr_debug > 3)
- printk(KERN_INFO " %04X \n", Status);
+ printk(" %04X \n", Status);
/* BUD successfully completed */
if(Status == STS_INITIALIZE)
return (1);
/* Error preventing completion of BUD */
if(retry_cnt > 0)
{
- printk(KERN_INFO "%s: Adapter Software Reset.\n",
+ printk("%s: Adapter Software Reset.\n",
dev->name);
sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);
sktr_wait(HALF_SECOND);
Status = inw(ioaddr + SIFSTS);
Status &= STS_ERROR_MASK; /* Hardware error occurred! */
- printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
+ printk("%s: Bring Up Diagnostics Error (%04X) occurred\n",
dev->name, Status);
return (-1);
/* First: fill up statistics */
if(tp->ssb.Parm[0] & SIGNAL_LOSS)
{
- printk(KERN_INFO "%s: Signal Loss\n", dev->name);
+ printk("%s: Signal Loss\n", dev->name);
tp->MacStat.line_errors++;
}
/* Adapter is closed, but initialized */
if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT)
{
- printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n",
+ printk("%s: Lobe Wire Fault, Reopen Adapter\n",
dev->name);
tp->MacStat.line_errors++;
}
if(tp->ssb.Parm[0] & RING_RECOVERY)
- printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+ printk("%s: Ring Recovery\n", dev->name);
/* Counter overflow: read error log */
if(tp->ssb.Parm[0] & COUNTER_OVERFLOW)
{
- printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+ printk("%s: Counter Overflow\n", dev->name);
sktr_exec_cmd(dev, OC_READ_ERROR_LOG);
}
/* Adapter is closed, but initialized */
if(tp->ssb.Parm[0] & REMOVE_RECEIVED)
- printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n",
+ printk("%s: Remove Received, Reopen Adapter\n",
dev->name);
/* Adapter is closed, but initialized */
if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR)
- printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n",
+ printk("%s: Auto Removal Error, Reopen Adapter\n",
dev->name);
if(tp->ssb.Parm[0] & HARD_ERROR)
- printk(KERN_INFO "%s: Hard Error\n", dev->name);
+ printk("%s: Hard Error\n", dev->name);
if(tp->ssb.Parm[0] & SOFT_ERROR)
- printk(KERN_INFO "%s: Soft Error\n", dev->name);
+ printk("%s: Soft Error\n", dev->name);
if(tp->ssb.Parm[0] & TRANSMIT_BEACON)
- printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+ printk("%s: Transmit Beacon\n", dev->name);
if(tp->ssb.Parm[0] & SINGLE_STATION)
- printk(KERN_INFO "%s: Single Station\n", dev->name);
+ printk("%s: Single Station\n", dev->name);
/* Check if adapter has been closed */
if(tp->ssb.Parm[0] & ADAPTER_CLOSED)
{
- printk(KERN_INFO "%s: Adapter closed (Reopening),"
+ printk("%s: Adapter closed (Reopening),"
"QueueSkb %d, CurrentRingStat %x\n",
- dev->name, tp->QueueSkb, tp->CurrentRingStatus);
+ dev->name, atomic_read(&tp->QueueSkb),
+ tp->CurrentRingStatus);
tp->AdapterOpenFlag = 0;
sktr_open_adapter(dev);
}
switch(AdapterCheckBlock[0])
{
case DIO_PARITY:
- printk(KERN_INFO "%s: DIO parity error\n", dev->name);
+ printk("%s: DIO parity error\n", dev->name);
break;
case DMA_READ_ABORT:
- printk(KERN_INFO "%s DMA read operation aborted:\n",
+ printk("%s DMA read operation aborted:\n",
dev->name);
switch (AdapterCheckBlock[1])
{
case 0:
- printk(KERN_INFO "Timeout\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Timeout\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
case 1:
- printk(KERN_INFO "Parity error\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Parity error\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
case 2:
- printk(KERN_INFO "Bus error\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Bus error\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
default:
- printk(KERN_INFO "Unknown error.\n");
+ printk("Unknown error.\n");
break;
}
break;
case DMA_WRITE_ABORT:
- printk(KERN_INFO "%s: DMA write operation aborted: \n",
+ printk("%s: DMA write operation aborted: \n",
dev->name);
switch (AdapterCheckBlock[1])
{
case 0:
- printk(KERN_INFO "Timeout\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Timeout\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
case 1:
- printk(KERN_INFO "Parity error\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Parity error\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
case 2:
- printk(KERN_INFO "Bus error\n");
- printk(KERN_INFO "Address: %04X %04X\n",
+ printk("Bus error\n");
+ printk("Address: %04X %04X\n",
AdapterCheckBlock[2],
AdapterCheckBlock[3]);
break;
default:
- printk(KERN_INFO "Unknown error.\n");
+ printk("Unknown error.\n");
break;
}
break;
sktr_read_ram(dev, (unsigned char *)&adapterram,
(unsigned short)SWAPB(tp->intptrs.AdapterRAMPtr), 2);
- printk(KERN_INFO "%s: Adapter RAM size: %d K\n",
+ printk("%s: Adapter RAM size: %d K\n",
dev->name, SWAPB(adapterram));
return;
sktr_write_tpl_status(tpl, 0); /* Clear VALID bit */
tpl->BusyFlag = 0; /* "free" TPL */
- printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
+ printk("Cancel tx (%08lXh).\n", (unsigned long)tpl);
dev_kfree_skb(tpl->Skb);
}
skb = skb_dequeue(&tp->SendSkbQueue);
if(skb == NULL)
break;
- tp->QueueSkb++;
+ atomic_inc(&tp->QueueSkb);
dev_kfree_skb(skb);
}
if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED))
{
- printk(KERN_INFO "%s: (DA=%08lX not recognized)",
+ printk("%s: (DA=%08lX not recognized)",
dev->name,
*(unsigned long *)&tpl->MData[2+2]);
}
}
dev->tbusy = 0;
- if(tp->QueueSkb < MAX_TX_QUEUE)
+ if(atomic_read(&tp->QueueSkb) < MAX_TX_QUEUE && !tp->Sending)
sktr_hardware_send_packet(dev, tp);
return;
skb_put(rpl->Skb, tp->MaxPacketSize);
/* Data unreachable for DMA ? then use local buffer */
- if(tp->DeviceType == SK_ISA &&
+ if(tp->BusType == BUS_TYPE_ISA &&
virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize
> ISA_MAX_ADDRESS)
{
rpl->SkbStat = SKB_DATA_COPY;
- rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
+ rpl->FragList[0].DataAddr =
+ htonl(virt_to_bus(
+ tp->LocalRxBuffers[rpl->RPLIndex]));
rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
}
else
#ifdef MODULE
static struct device* dev_sktr[SKTR_MAX_ADAPTERS];
-static int io[SKTR_MAX_ADAPTERS] = { 0, 0 };
-static int irq[SKTR_MAX_ADAPTERS] = { 0, 0 };
-static int mem[SKTR_MAX_ADAPTERS] = { 0, 0 };
+static int io[SKTR_MAX_ADAPTERS] = { 0, };
+static int irq[SKTR_MAX_ADAPTERS] = { 0, };
+static int dma[SKTR_MAX_ADAPTERS] = { 0, };
MODULE_PARM(io, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
+MODULE_PARM(rate, "1-" __MODULE_STRING(SKTR_MAX_ADAPTERS) "i");
int init_module(void)
{
for(i = 0; i < SKTR_MAX_ADAPTERS; i++)
{
- irq[i] = 0;
- mem[i] = 0;
dev_sktr[i] = NULL;
dev_sktr[i] = init_trdev(dev_sktr[i], 0);
if(dev_sktr[i] == NULL)
dev_sktr[i]->base_addr = io[i];
dev_sktr[i]->irq = irq[i];
- dev_sktr[i]->mem_start = mem[i];
+ dev_sktr[i]->dma = dma[i];
dev_sktr[i]->init = &sktr_probe;
if(register_trdev(dev_sktr[i]) != 0)
#define TR_RCF_LONGEST_FRAME_MASK 0x0070
#define TR_RCF_FRAME4K 0x0030
+/* DeviceType values */
#define SK_ISA 0
#define SK_PCI 1
+#define PROT_ISA 2
+
+/* BusType values */
+#define BUS_TYPE_PCI 0
+#define BUS_TYPE_ISA 1
/*------------------------------------------------------------------*/
/* Bit order for adapter communication with DMA */
unsigned short CMDqueue;
unsigned int DeviceType;
+ unsigned int BusType;
unsigned long AdapterOpenFlag:1;
unsigned long AdapterVirtOpenFlag:1;
unsigned long LobeWireFaultLogged:1;
unsigned long ReOpenInProgress:1;
unsigned long Sleeping:1;
+ unsigned long Sending:1;
unsigned long LastOpenStatus;
unsigned short CurrentRingStatus;
unsigned long LastSendTime;
struct sk_buff_head SendSkbQueue;
- unsigned short QueueSkb;
+ atomic_t QueueSkb;
struct tr_statistics MacStat; /* MAC statistics structure */
h=(struct ppp_header *)skb->data;
if(sp->pp_flags&PP_CISCO)
{
- h->address = CISCO_MULTICAST;
+ h->address = CISCO_UNICAST;
h->control = 0;
}
else
};
/* Globals */
-char *tw_driver_version="1.0.000";
+char *tw_driver_version="1.1.000";
TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
int tw_device_extension_count = 0;
command_packet->status = 0;
command_packet->flags = 0;
- if ((srb->cmnd[0] == WRITE_6) || (srb->cmnd[0] == WRITE_10)) {
+ if (srb->cmnd[0] == WRITE_10) {
if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
command_packet->flags = 1;
}
-u32 SCRIPT[] = {
+static u32 SCRIPT[] = {
/*
};
#define A_NCR53c7xx_msg_abort 0x00000000
-u32 A_NCR53c7xx_msg_abort_used[] = {
+static u32 A_NCR53c7xx_msg_abort_used[] __attribute((unused)) = {
0x00000249,
};
#define A_NCR53c7xx_msg_reject 0x00000000
-u32 A_NCR53c7xx_msg_reject_used[] = {
+static u32 A_NCR53c7xx_msg_reject_used[] __attribute((unused)) = {
0x00000172,
};
#define A_NCR53c7xx_sink 0x00000000
-u32 A_NCR53c7xx_sink_used[] = {
+static u32 A_NCR53c7xx_sink_used[] __attribute((unused)) = {
0x00000233,
0x00000239,
0x0000023f,
};
#define A_NCR53c7xx_zero 0x00000000
-u32 A_NCR53c7xx_zero_used[] = {
+static u32 A_NCR53c7xx_zero_used[] __attribute((unused)) = {
0x0000022f,
0x00000245,
};
#define A_NOP_insn 0x00000000
-u32 A_NOP_insn_used[] = {
+static u32 A_NOP_insn_used[] __attribute((unused)) = {
0x00000010,
};
#define A_addr_reconnect_dsa_head 0x00000000
-u32 A_addr_reconnect_dsa_head_used[] = {
+static u32 A_addr_reconnect_dsa_head_used[] __attribute((unused)) = {
0x000001a7,
};
#define A_addr_scratch 0x00000000
-u32 A_addr_scratch_used[] = {
+static u32 A_addr_scratch_used[] __attribute((unused)) = {
0x00000004,
0x0000001b,
0x00000046,
};
#define A_addr_temp 0x00000000
-u32 A_addr_temp_used[] = {
+static u32 A_addr_temp_used[] __attribute((unused)) = {
0x00000025,
0x00000034,
};
#define A_dmode_memory_to_memory 0x00000000
-u32 A_dmode_memory_to_memory_used[] = {
+static u32 A_dmode_memory_to_memory_used[] __attribute((unused)) = {
0x00000005,
0x0000001c,
0x00000027,
};
#define A_dmode_memory_to_ncr 0x00000000
-u32 A_dmode_memory_to_ncr_used[] = {
+static u32 A_dmode_memory_to_ncr_used[] __attribute((unused)) = {
0x00000000,
0x00000017,
0x00000030,
};
#define A_dmode_ncr_to_memory 0x00000000
-u32 A_dmode_ncr_to_memory_used[] = {
+static u32 A_dmode_ncr_to_memory_used[] __attribute((unused)) = {
0x00000022,
0x00000064,
0x00000070,
};
#define A_dsa_check_reselect 0x00000000
-u32 A_dsa_check_reselect_used[] = {
+static u32 A_dsa_check_reselect_used[] __attribute((unused)) = {
0x000001bd,
};
#define A_dsa_cmdout 0x00000048
-u32 A_dsa_cmdout_used[] = {
+static u32 A_dsa_cmdout_used[] __attribute((unused)) = {
0x00000094,
};
#define A_dsa_cmnd 0x00000038
-u32 A_dsa_cmnd_used[] = {
+static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
};
#define A_dsa_datain 0x00000054
-u32 A_dsa_datain_used[] = {
+static u32 A_dsa_datain_used[] __attribute((unused)) = {
0x000000bb,
};
#define A_dsa_dataout 0x00000050
-u32 A_dsa_dataout_used[] = {
+static u32 A_dsa_dataout_used[] __attribute((unused)) = {
0x000000a5,
};
#define A_dsa_end 0x00000070
-u32 A_dsa_end_used[] = {
+static u32 A_dsa_end_used[] __attribute((unused)) = {
};
#define A_dsa_fields_start 0x00000000
-u32 A_dsa_fields_start_used[] = {
+static u32 A_dsa_fields_start_used[] __attribute((unused)) = {
};
#define A_dsa_msgin 0x00000058
-u32 A_dsa_msgin_used[] = {
+static u32 A_dsa_msgin_used[] __attribute((unused)) = {
0x00000188,
};
#define A_dsa_msgout 0x00000040
-u32 A_dsa_msgout_used[] = {
+static u32 A_dsa_msgout_used[] __attribute((unused)) = {
0x00000086,
};
#define A_dsa_msgout_other 0x00000068
-u32 A_dsa_msgout_other_used[] = {
+static u32 A_dsa_msgout_other_used[] __attribute((unused)) = {
0x00000180,
};
#define A_dsa_next 0x00000030
-u32 A_dsa_next_used[] = {
+static u32 A_dsa_next_used[] __attribute((unused)) = {
0x0000005c,
};
#define A_dsa_restore_pointers 0x00000000
-u32 A_dsa_restore_pointers_used[] = {
+static u32 A_dsa_restore_pointers_used[] __attribute((unused)) = {
0x0000012e,
};
#define A_dsa_save_data_pointer 0x00000000
-u32 A_dsa_save_data_pointer_used[] = {
+static u32 A_dsa_save_data_pointer_used[] __attribute((unused)) = {
0x00000115,
};
#define A_dsa_select 0x0000003c
-u32 A_dsa_select_used[] = {
+static u32 A_dsa_select_used[] __attribute((unused)) = {
0x00000081,
};
#define A_dsa_status 0x00000060
-u32 A_dsa_status_used[] = {
+static u32 A_dsa_status_used[] __attribute((unused)) = {
0x00000184,
};
#define A_dsa_temp_addr_array_value 0x00000000
-u32 A_dsa_temp_addr_array_value_used[] = {
+static u32 A_dsa_temp_addr_array_value_used[] __attribute((unused)) = {
};
#define A_dsa_temp_addr_dsa_value 0x00000000
-u32 A_dsa_temp_addr_dsa_value_used[] = {
+static u32 A_dsa_temp_addr_dsa_value_used[] __attribute((unused)) = {
0x00000003,
};
#define A_dsa_temp_addr_new_value 0x00000000
-u32 A_dsa_temp_addr_new_value_used[] = {
+static u32 A_dsa_temp_addr_new_value_used[] __attribute((unused)) = {
};
#define A_dsa_temp_addr_next 0x00000000
-u32 A_dsa_temp_addr_next_used[] = {
+static u32 A_dsa_temp_addr_next_used[] __attribute((unused)) = {
0x00000015,
0x0000004e,
};
#define A_dsa_temp_addr_residual 0x00000000
-u32 A_dsa_temp_addr_residual_used[] = {
+static u32 A_dsa_temp_addr_residual_used[] __attribute((unused)) = {
0x0000002a,
0x00000039,
};
#define A_dsa_temp_addr_saved_pointer 0x00000000
-u32 A_dsa_temp_addr_saved_pointer_used[] = {
+static u32 A_dsa_temp_addr_saved_pointer_used[] __attribute((unused)) = {
0x00000026,
0x00000033,
};
#define A_dsa_temp_addr_saved_residual 0x00000000
-u32 A_dsa_temp_addr_saved_residual_used[] = {
+static u32 A_dsa_temp_addr_saved_residual_used[] __attribute((unused)) = {
0x0000002b,
0x00000038,
};
#define A_dsa_temp_lun 0x00000000
-u32 A_dsa_temp_lun_used[] = {
+static u32 A_dsa_temp_lun_used[] __attribute((unused)) = {
0x0000004b,
};
#define A_dsa_temp_next 0x00000000
-u32 A_dsa_temp_next_used[] = {
+static u32 A_dsa_temp_next_used[] __attribute((unused)) = {
0x0000001a,
};
#define A_dsa_temp_sync 0x00000000
-u32 A_dsa_temp_sync_used[] = {
+static u32 A_dsa_temp_sync_used[] __attribute((unused)) = {
0x00000053,
};
#define A_dsa_temp_target 0x00000000
-u32 A_dsa_temp_target_used[] = {
+static u32 A_dsa_temp_target_used[] __attribute((unused)) = {
0x00000040,
};
#define A_int_debug_break 0x03000000
-u32 A_int_debug_break_used[] = {
+static u32 A_int_debug_break_used[] __attribute((unused)) = {
0x00000217,
};
#define A_int_debug_panic 0x030b0000
-u32 A_int_debug_panic_used[] = {
+static u32 A_int_debug_panic_used[] __attribute((unused)) = {
0x000001e8,
0x000001f8,
};
#define A_int_err_check_condition 0x00030000
-u32 A_int_err_check_condition_used[] = {
+static u32 A_int_err_check_condition_used[] __attribute((unused)) = {
0x00000194,
};
#define A_int_err_no_phase 0x00040000
-u32 A_int_err_no_phase_used[] = {
+static u32 A_int_err_no_phase_used[] __attribute((unused)) = {
};
#define A_int_err_selected 0x00010000
-u32 A_int_err_selected_used[] = {
+static u32 A_int_err_selected_used[] __attribute((unused)) = {
0x000001da,
};
#define A_int_err_unexpected_phase 0x00000000
-u32 A_int_err_unexpected_phase_used[] = {
+static u32 A_int_err_unexpected_phase_used[] __attribute((unused)) = {
0x0000008c,
0x00000092,
0x0000009a,
};
#define A_int_err_unexpected_reselect 0x00020000
-u32 A_int_err_unexpected_reselect_used[] = {
+static u32 A_int_err_unexpected_reselect_used[] __attribute((unused)) = {
0x000001ba,
};
#define A_int_msg_1 0x01020000
-u32 A_int_msg_1_used[] = {
+static u32 A_int_msg_1_used[] __attribute((unused)) = {
0x0000010e,
0x00000110,
};
#define A_int_msg_sdtr 0x01010000
-u32 A_int_msg_sdtr_used[] = {
+static u32 A_int_msg_sdtr_used[] __attribute((unused)) = {
0x0000016c,
};
#define A_int_msg_wdtr 0x01000000
-u32 A_int_msg_wdtr_used[] = {
+static u32 A_int_msg_wdtr_used[] __attribute((unused)) = {
0x00000160,
};
#define A_int_norm_aborted 0x02040000
-u32 A_int_norm_aborted_used[] = {
+static u32 A_int_norm_aborted_used[] __attribute((unused)) = {
0x0000024d,
};
#define A_int_norm_command_complete 0x02020000
-u32 A_int_norm_command_complete_used[] = {
+static u32 A_int_norm_command_complete_used[] __attribute((unused)) = {
};
#define A_int_norm_disconnected 0x02030000
-u32 A_int_norm_disconnected_used[] = {
+static u32 A_int_norm_disconnected_used[] __attribute((unused)) = {
};
#define A_int_norm_reselect_complete 0x02010000
-u32 A_int_norm_reselect_complete_used[] = {
+static u32 A_int_norm_reselect_complete_used[] __attribute((unused)) = {
};
#define A_int_norm_reset 0x02050000
-u32 A_int_norm_reset_used[] = {
+static u32 A_int_norm_reset_used[] __attribute((unused)) = {
};
#define A_int_norm_select_complete 0x02000000
-u32 A_int_norm_select_complete_used[] = {
+static u32 A_int_norm_select_complete_used[] __attribute((unused)) = {
};
#define A_int_test_1 0x04000000
-u32 A_int_test_1_used[] = {
+static u32 A_int_test_1_used[] __attribute((unused)) = {
0x000001fd,
};
#define A_int_test_2 0x04010000
-u32 A_int_test_2_used[] = {
+static u32 A_int_test_2_used[] __attribute((unused)) = {
0x00000215,
};
#define A_int_test_3 0x04020000
-u32 A_int_test_3_used[] = {
+static u32 A_int_test_3_used[] __attribute((unused)) = {
};
#define A_msg_buf 0x00000000
-u32 A_msg_buf_used[] = {
+static u32 A_msg_buf_used[] __attribute((unused)) = {
0x00000102,
0x0000014e,
0x00000158,
};
#define A_reconnect_dsa_head 0x00000000
-u32 A_reconnect_dsa_head_used[] = {
+static u32 A_reconnect_dsa_head_used[] __attribute((unused)) = {
0x0000006c,
0x00000074,
0x000001a0,
};
#define A_reselected_identify 0x00000000
-u32 A_reselected_identify_used[] = {
+static u32 A_reselected_identify_used[] __attribute((unused)) = {
0x00000045,
0x0000019c,
};
#define A_reselected_tag 0x00000000
-u32 A_reselected_tag_used[] = {
+static u32 A_reselected_tag_used[] __attribute((unused)) = {
};
#define A_schedule 0x00000000
-u32 A_schedule_used[] = {
+static u32 A_schedule_used[] __attribute((unused)) = {
0x0000007e,
0x00000192,
0x000001e2,
};
#define A_test_dest 0x00000000
-u32 A_test_dest_used[] = {
+static u32 A_test_dest_used[] __attribute((unused)) = {
0x000001fb,
};
#define A_test_src 0x00000000
-u32 A_test_src_used[] = {
+static u32 A_test_src_used[] __attribute((unused)) = {
0x000001fa,
};
#define Ent_test_2 0x000007f8
#define Ent_test_2_msgout 0x00000810
#define Ent_wait_reselect 0x00000654
-u32 LABELPATCHES[] = {
+static u32 LABELPATCHES[] __attribute((unused)) = {
0x00000008,
0x0000000a,
0x00000013,
0x00000243,
};
-struct {
+static struct {
u32 offset;
void *address;
-} EXTERNAL_PATCHES[] = {
+} EXTERNAL_PATCHES[] __attribute((unused)) = {
};
-u32 INSTRUCTIONS = 301;
-u32 PATCHES = 81;
-u32 EXTERNAL_PATCHES_LEN = 0;
+static u32 INSTRUCTIONS __attribute((unused)) = 301;
+static u32 PATCHES __attribute((unused)) = 81;
+static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0;
will often result in the machine crashing or spontaneously rebooting
during startup. Examples of machines that need this are the
Dell PowerEdge 6300 machines.
+
+ "aic7xxx=seltime:2" - This option controls how long the card waits
+ during a device selection sequence for the device to respond.
+ The original SCSI spec says that this "should be" 256ms. This
+ is generally not required with modern devices. However, some
+ very old SCSI I devices need the full 256ms. Most modern devices
+ can run fine with only 64ms. The default for this option is
+ 64ms. If you need to change this option, then use the following
+ table to set the proper value in the example above:
+ 0 - 256ms
+ 1 - 128ms
+ 2 - 64ms
+ 3 - 32ms
"aic7xxx=panic_on_abort" - This option is for debugging and will cause
the driver to panic the linux kernel and freeze the system the first
Web sites
------------------------------
- http://people.redhat.com/dledford/aic7xxx.html
- - Primary web site maintained by Doug Ledford.
+ http://people.redhat.com/dledford/
+ - My web site, also the primary aic7xxx site with several related
+ pages.
Dean W. Gehnert
deang@teleport.com
$Revision: 3.0 $
-Modified by Doug Ledford 1998-9
+Modified by Doug Ledford 1998-2000
+
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-#define AIC7XXX_C_VERSION "5.1.23"
+#define AIC7XXX_C_VERSION "5.1.28"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
"Adaptec AHA-394X Ultra SCSI host adapter", /* AIC_7882 */
"Adaptec AHA-398X Ultra SCSI host adapter", /* AIC_7883 */
"Adaptec AHA-2944 Ultra SCSI host adapter", /* AIC_7884 */
+ "Adaptec AHA-2940UW Pro Ultra SCSI host adapter", /* AIC_7887 */
"Adaptec AIC-7895 Ultra SCSI host adapter", /* AIC_7895 */
"Adaptec AIC-7890/1 Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AHA-293X Ultra2 SCSI host adapter", /* AIC_7890 */
* and what flags weren't. This way, I could clean up the flag usage on
* a use by use basis. Doug Ledford
*/
+ AHC_MOTHERBOARD = 0x00020000,
+ AHC_NO_STPWEN = 0x00040000,
AHC_RESET_DELAY = 0x00080000,
AHC_A_SCANNED = 0x00100000,
AHC_B_SCANNED = 0x00200000,
/*
* So that we can set how long each device is given as a selection timeout.
* The table of values goes like this:
- * 0 - 256ms
- * 1 - 128ms
- * 2 - 64ms
- * 3 - 32ms
+ * 0 - 256ms
+ * 1 - 128ms
+ * 2 - 64ms
+ * 3 - 32ms
* We default to 64ms because it's fast. Some old SCSI-I devices need a
* longer time. The final value has to be left shifted by 3, hence 0x10
* is the final value.
***************************************************************************/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-static inline void
-mdelay(int milliseconds)
-{
- int i;
-
- for(i=0; i<milliseconds; i++)
- udelay(1000);
-}
-
static inline int
time_after_eq(unsigned long a, unsigned long b)
{
if(p->maddr)
{
writeb(val, p->maddr + port);
+ mb(); /* locked operation in order to force ordering */
+ readb(p->maddr + HCNTRL); /* dummy read to flush the write */
}
else
{
outb(val, p->base + port);
+ mb(); /* locked operation in order to force ordering */
+ inb(p->base + HCNTRL); /* dummy read to flush the write */
}
- mb();
#else
outb(val, p->base + port);
#endif
}
}
aic_outb(p, (instr.integer & 0xff), SEQRAM);
- udelay(50);
aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM);
- udelay(50);
aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM);
- udelay(50);
aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM);
- udelay(50);
+ udelay(10);
break;
default:
printk("\n");
}
-/*+F*************************************************************************
- * Function:
- * aic7xxx_delay
- *
- * Description:
- * Delay for specified amount of time. We use mdelay because the timer
- * interrupt is not guaranteed to be enabled. This will cause an
- * infinite loop since jiffies (clock ticks) is not updated.
- *-F*************************************************************************/
-static void
-aic7xxx_delay(int seconds)
-{
- mdelay(seconds * 1000);
-}
-
/*+F*************************************************************************
* Function:
* aic7xxx_info
p->needwdtr_copy &= ~(1<<tindex);
p->needsdtr &= ~(1<<tindex);
p->needsdtr_copy &= ~(1<<tindex);
+ /*
+ * This is needed to work around a sequencer bug for now. Regardless
+ * of the controller in use, if we have a Quantum drive, we need to
+ * limit the speed to 80MByte/sec. As soon as I get a fixed version
+ * of the sequencer, this code will get yanked.
+ */
+ if(!strncmp(buffer + 8, "QUANTUM", 7) &&
+ p->transinfo[tindex].goal_options )
+ {
+ p->transinfo[tindex].goal_period =
+ MAX(p->transinfo[tindex].goal_period, 10);
+ p->transinfo[tindex].goal_options = 0;
+ }
}
/*
* Get the INQUIRY checksum. We use this on Ultra 160/m
while ( (aic_inb(p, SCSISEQ) & SCSIRSTO) == 0)
mdelay(5);
- mdelay(10);
+ /*
+ * Some of the new Ultra2 chipsets need a longer delay after a chip
+ * reset than just the init setup creates, so we have to delay here
+ * before we go into a reset in order to make the chips happy.
+ */
+ if (p->features & AHC_ULTRA2)
+ mdelay(250);
+ else
+ mdelay(50);
/* Turn off the bus reset. */
aic_outb(p, 0, SCSISEQ);
- mdelay(5);
+ mdelay(10);
aic7xxx_clear_intstat(p);
/* Re-enable reset interrupts. */
case CHECK_CONDITION:
if ( !(scb->flags & SCB_SENSE) )
{
- /*
- * XXX - How do we save the residual (if there is one).
- */
- if ( hscb->residual_SG_segment_count != 0 )
- aic7xxx_calculate_residual(p, scb);
/*
* Send a sense command to the requesting target.
}
break;
+ case WIDE_RESIDUE:
+ {
+ unsigned char resid_sgcnt, index;
+ unsigned char scb_index = aic_inb(p, SCB_TAG);
+ unsigned int cur_addr, resid_dcnt;
+ unsigned int native_addr, native_length;
+ int i;
+
+ if(scb_index > p->scb_data->numscbs)
+ {
+ printk(WARN_LEAD "invalid scb_index during WIDE_RESIDUE.\n",
+ p->host_no, -1, -1, -1);
+ /*
+ * XXX: Add error handling here
+ */
+ break;
+ }
+ scb = p->scb_data->scb_array[scb_index];
+ if(!(scb->flags & SCB_ACTIVE) || (scb->cmd == NULL))
+ {
+ printk(WARN_LEAD "invalid scb during WIDE_RESIDUE flags:0x%x "
+ "scb->cmd:0x%x\n", p->host_no, CTL_OF_SCB(scb),
+ scb->flags, (unsigned int)scb->cmd);
+ break;
+ }
+
+ /*
+ * We have a valid scb to use on this WIDE_RESIDUE message, so
+ * we need to walk the sg list looking for this particular sg
+ * segment, then see if we happen to be at the very beginning of
+ * the segment. If we are, then we have to back things up to
+ * the previous segment. If not, then we simply need to remove
+ * one byte from this segments address and add one to the byte
+ * count.
+ */
+ cur_addr = aic_inb(p, SHADDR) | (aic_inb(p, SHADDR + 1) << 8) |
+ (aic_inb(p, SHADDR + 2) << 16) | (aic_inb(p, SHADDR + 3) << 24);
+ resid_sgcnt = aic_inb(p, SCB_RESID_SGCNT);
+ resid_dcnt = aic_inb(p, SCB_RESID_DCNT) |
+ (aic_inb(p, SCB_RESID_DCNT + 1) << 8) |
+ (aic_inb(p, SCB_RESID_DCNT + 2) << 24);
+ index = scb->sg_count - (resid_sgcnt + 1);
+ native_addr = le32_to_cpu(scb->sg_list[index].address);
+ native_length = le32_to_cpu(scb->sg_list[index].length);
+ /*
+ * Make sure this is a valid sg_seg for the given pointer
+ */
+ if(cur_addr < native_addr ||
+ cur_addr > (native_addr + native_length))
+ {
+ printk(WARN_LEAD "invalid cur_addr:0x%x during WIDE_RESIDUE\n",
+ p->host_no, CTL_OF_SCB(scb), cur_addr);
+ if(index > 0)
+ printk(WARN_LEAD " sg_address[-1]:0x%x sg_length[-1]:%d\n",
+ p->host_no, CTL_OF_SCB(scb),
+ le32_to_cpu(scb->sg_list[index - 1].address),
+ le32_to_cpu(scb->sg_list[index - 1].length));
+ printk(WARN_LEAD " sg_address:0x%x sg_length:%d\n",
+ p->host_no, CTL_OF_SCB(scb),
+ native_addr, native_length);
+ if(resid_sgcnt > 1)
+ printk(WARN_LEAD " sg_address[1]:0x%x sg_length[1]:%d\n",
+ p->host_no, CTL_OF_SCB(scb),
+ le32_to_cpu(scb->sg_list[index + 1].address),
+ le32_to_cpu(scb->sg_list[index + 1].length));
+ break;
+ }
+
+ /*
+ * If our current address matches the sg_seg->address then we
+ * have to back up the sg array to the previous segment and set
+ * it up to have only one byte of transfer left to go.
+ */
+ if(cur_addr == native_addr)
+ {
+ if(index == 0)
+ {
+ printk(WARN_LEAD "bogus WIDE_RESIDUE message, no data has been "
+ "transferred.\n", p->host_no, CTL_OF_SCB(scb));
+ break;
+ }
+ resid_sgcnt++;
+ index--;
+ cur_addr = le32_to_cpu(scb->sg_list[index].address) +
+ le32_to_cpu(scb->sg_list[index].length) - 1;
+ native_addr = aic_inb(p, SG_NEXT) | (aic_inb(p, SG_NEXT + 1) << 8)
+ | (aic_inb(p, SG_NEXT + 2) << 16) | (aic_inb(p, SG_NEXT + 3) << 24);
+ native_addr -= SG_SIZEOF;
+ aic_outb(p, resid_sgcnt, SG_COUNT);
+ aic_outb(p, resid_sgcnt, SCB_RESID_SGCNT);
+ aic_outb(p, native_addr & 0xff, SG_NEXT);
+ aic_outb(p, (native_addr >> 8) & 0xff, SG_NEXT + 1);
+ aic_outb(p, (native_addr >> 16) & 0xff, SG_NEXT + 2);
+ aic_outb(p, (native_addr >> 24) & 0xff, SG_NEXT + 3);
+ aic_outb(p, 1, SCB_RESID_DCNT);
+ aic_outb(p, 0, SCB_RESID_DCNT + 1);
+ aic_outb(p, 0, SCB_RESID_DCNT + 2);
+ aic_outb(p, 1, HCNT);
+ aic_outb(p, 0, HCNT + 1);
+ aic_outb(p, 0, HCNT + 2);
+ aic_outb(p, cur_addr & 0xff, HADDR);
+ aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+ aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+ aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+ /*
+ * The sequencer actually wants to find the new address and byte
+ * count in the SHCNT and SHADDR register sets. These registers
+ * are a shadow of the regular HCNT and HADDR registers. On the
+ * Ultra2 controllers, these registers are read only and the way
+ * we have to set their values is to put the values we want into
+ * the HCNT and HADDR registers and then output PRELOADEN into
+ * the DFCNTRL register which causes the card to latch the current
+ * values in the HADDR and HCNT registers and drop it through to
+ * the shadow registers. On older cards we copy them directly
+ * across by hand.
+ */
+ if(p->features & AHC_ULTRA2)
+ {
+ aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+ i=0;
+ udelay(1);
+ while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+ {
+ aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+ udelay(1);
+ }
+ }
+ else
+ {
+ aic_outb(p, 1, STCNT);
+ aic_outb(p, 0, STCNT + 1);
+ aic_outb(p, 0, STCNT + 2);
+ aic_outb(p, cur_addr & 0xff, SHADDR);
+ aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+ aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+ aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+ }
+ }
+ else
+ {
+ /*
+ * Back the data pointer up by one and add one to the remaining
+ * byte count. Then store that in the HCNT and HADDR registers.
+ */
+ cur_addr--;
+ resid_dcnt++;
+ aic_outb(p, resid_dcnt & 0xff, SCB_RESID_DCNT);
+ aic_outb(p, (resid_dcnt >> 8) & 0xff, SCB_RESID_DCNT + 1);
+ aic_outb(p, (resid_dcnt >> 16) & 0xff, SCB_RESID_DCNT + 2);
+ aic_outb(p, resid_dcnt & 0xff, HCNT);
+ aic_outb(p, (resid_dcnt >> 8) & 0xff, HCNT + 1);
+ aic_outb(p, (resid_dcnt >> 16) & 0xff, HCNT + 2);
+ aic_outb(p, cur_addr & 0xff, HADDR);
+ aic_outb(p, (cur_addr >> 8) & 0xff, HADDR + 1);
+ aic_outb(p, (cur_addr >> 16) & 0xff, HADDR + 2);
+ aic_outb(p, (cur_addr >> 24) & 0xff, HADDR + 3);
+ if(p->features & AHC_ULTRA2)
+ {
+ aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+ i=0;
+ udelay(1);
+ while(((aic_inb(p, SSTAT0) & SDONE) != 0) && (i++ < 1000))
+ {
+ aic_outb(p, aic_inb(p, DMAPARAMS), DFCNTRL);
+ udelay(1);
+ }
+ }
+ else
+ {
+ aic_outb(p, resid_dcnt & 0xff, STCNT);
+ aic_outb(p, (resid_dcnt >> 8) & 0xff, STCNT + 1);
+ aic_outb(p, (resid_dcnt >> 16) & 0xff, STCNT + 2);
+ aic_outb(p, cur_addr & 0xff, SHADDR);
+ aic_outb(p, (cur_addr >> 8) & 0xff, SHADDR + 1);
+ aic_outb(p, (cur_addr >> 16) & 0xff, SHADDR + 2);
+ aic_outb(p, (cur_addr >> 24) & 0xff, SHADDR + 3);
+ }
+ }
+ }
+ break;
+
+
#if AIC7XXX_NOT_YET
case TRACEPOINT:
{
}
}
/*
- * Restarting the sequencer will stop the selection and make sure devices
- * are allowed to reselect in.
+ * Keep the sequencer from trying to restart any selections
*/
aic_outb(p, 0, SCSISEQ);
+ /*
+ * Make sure the data bits on the bus are released
+ */
+ if(p->features & AHC_WIDE)
+ aic_outb(p, 0, SCSIBUSH);
+ aic_outb(p, 0, SCSIBUSL);
+ /*
+ * Clear the target id bit from the SCSI bus
+ */
+ if(p->features & AHC_ULTRA2)
+ aic_outb(p, aic_inb(p, SCSIID_ULTRA2) & 0x0f, SCSIID_ULTRA2);
+ else
+ aic_outb(p, aic_inb(p, SCSIID) & 0x0f, SCSIID);
+
+ /*
+ * Delay for the selection timeout delay period then stop the selection
+ */
+ udelay(301);
aic_outb(p, CLRSELINGO, CLRSINT0);
+ /*
+ * Clear out all the interrupt status bits
+ */
aic_outb(p, aic_inb(p, SIMODE1) & ~(ENREQINIT|ENBUSFREE), SIMODE1);
p->flags &= ~AHC_HANDLING_REQINITS;
aic_outb(p, CLRSELTIMEO | CLRBUSFREE, CLRSINT1);
aic_outb(p, CLRSCSIINT, CLRINT);
+ /*
+ * Restarting the sequencer will stop the selection and make sure devices
+ * are allowed to reselect in.
+ */
restart_sequencer(p);
unpause_sequencer(p, TRUE);
}
if(!p)
return;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
- spin_lock_irqsave(&io_request_lock, cpu_flags);
if(test_and_set_bit(AHC_IN_ISR_BIT, &p->flags))
{
return;
}
+ spin_lock_irqsave(&io_request_lock, cpu_flags);
do
{
aic7xxx_isr(irq, dev_id, regs);
#undef CLOCK_PULSE
}
+#define CLOCK_PULSE(p) \
+ do { \
+ int limit = 0; \
+ do { \
+ mb(); \
+ pause_sequencer(p); /* This is just to generate some PCI */ \
+ /* traffic so the PCI read is flushed */ \
+ /* it shouldn't be needed, but some */ \
+ /* chipsets do indeed appear to need */ \
+ /* something to force PCI reads to get */ \
+ /* flushed */ \
+ udelay(1); /* Do nothing */ \
+ } while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)); \
+ } while(0)
+
/*+F*************************************************************************
* Function:
* acquire_seeprom
static int
acquire_seeprom(struct aic7xxx_host *p)
{
- int wait;
/*
* Request access of the memory port. When access is
* should be no contention.
*/
aic_outb(p, SEEMS, SEECTL);
- wait = 1000; /* 1000 msec = 1 second */
- while ((wait > 0) && ((aic_inb(p, SEECTL) & SEERDY) == 0))
- {
- wait--;
- mdelay(1); /* 1 msec */
- }
+ CLOCK_PULSE(p);
if ((aic_inb(p, SEECTL) & SEERDY) == 0)
{
aic_outb(p, 0, SEECTL);
static void
release_seeprom(struct aic7xxx_host *p)
{
+ /*
+ * Make sure the SEEPROM is ready before we release it.
+ */
+ CLOCK_PULSE(p);
aic_outb(p, 0, SEECTL);
}
};
struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
-#define CLOCK_PULSE(p) \
- { \
- int limit = 0; \
- while (((aic_inb(p, SEECTL) & SEERDY) == 0) && (++limit < 1000)) \
- { \
- mb(); \
- pause_sequencer(p); /* This is just to generate some PCI */ \
- /* so the PCI read is flushed */ \
- udelay(10); /* Do nothing */ \
- } \
- }
-
/*
* Request access of the memory port.
*/
}
return (1);
-#undef CLOCK_PULSE
}
/*+F*************************************************************************
{
unsigned char brdctl, value;
+ /*
+ * Make sure the SEEPROM is ready before we access it
+ */
+ CLOCK_PULSE(p);
if (p->features & AHC_ULTRA2)
{
brdctl = BRDRW_ULTRA2;
aic_outb(p, brdctl, BRDCTL);
- udelay(4);
- return(aic_inb(p, BRDCTL));
+ CLOCK_PULSE(p);
+ value = aic_inb(p, BRDCTL);
+ CLOCK_PULSE(p);
+ return(value);
}
brdctl = BRDRW;
if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) ||
brdctl |= BRDCS;
}
aic_outb(p, brdctl, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
value = aic_inb(p, BRDCTL);
+ CLOCK_PULSE(p);
aic_outb(p, 0, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
return (value);
}
{
unsigned char brdctl;
+ /*
+ * Make sure the SEEPROM is ready before we access it
+ */
+ CLOCK_PULSE(p);
if (p->features & AHC_ULTRA2)
{
brdctl = value;
aic_outb(p, brdctl, BRDCTL);
- udelay(4);
+ CLOCK_PULSE(p);
brdctl |= BRDSTB_ULTRA2;
aic_outb(p, brdctl, BRDCTL);
- udelay(4);
+ CLOCK_PULSE(p);
brdctl &= ~BRDSTB_ULTRA2;
aic_outb(p, brdctl, BRDCTL);
- udelay(4);
+ CLOCK_PULSE(p);
read_brdctl(p);
+ CLOCK_PULSE(p);
}
else
{
}
brdctl = BRDSTB | BRDCS;
aic_outb(p, brdctl, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
brdctl |= value;
aic_outb(p, brdctl, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
brdctl &= ~BRDSTB;
aic_outb(p, brdctl, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
brdctl &= ~BRDCS;
aic_outb(p, brdctl, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
}
}
unsigned char brdctl;
aic_outb(p, BRDRW | BRDCS, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
aic_outb(p, 0, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
brdctl = aic_inb(p, BRDCTL);
- udelay(1);
+ CLOCK_PULSE(p);
*int_50 = !(brdctl & BRDDAT5);
*ext_present = !(brdctl & BRDDAT6);
*eeprom = (aic_inb(p, SPIOCAP) & EEPROM);
}
+#undef CLOCK_PULSE
+
+/*+F*************************************************************************
+ * Function:
+ * aic2940_uwpro_cable_detect
+ *
+ * Description:
+ * Detect the cables that are present on the 2940-UWPro cards
+ *
+ * NOTE: This functions assumes the SEEPROM will have already been aquired
+ * prior to invocation of this function.
+ *-F*************************************************************************/
+static void
+aic2940_uwpro_wide_cable_detect(struct aic7xxx_host *p, int *int_68,
+ int *ext_68, int *eeprom)
+{
+ unsigned char brdctl;
+
+ /*
+ * First read the status of our cables. Set the rom bank to
+ * 0 since the bank setting serves as a multiplexor for the
+ * cable detection logic. BRDDAT5 controls the bank switch.
+ */
+ write_brdctl(p, 0);
+
+ /*
+ * Now we read the state of the internal 68 connector. BRDDAT6
+ * is don't care, BRDDAT7 is internal 68. The cable is
+ * present if the bit is 0
+ */
+ brdctl = read_brdctl(p);
+ *int_68 = !(brdctl & BRDDAT7);
+
+ /*
+ * Set the bank bit in brdctl and then read the external cable state
+ * and the EEPROM status
+ */
+ write_brdctl(p, BRDDAT5);
+ brdctl = read_brdctl(p);
+
+ *ext_68 = !(brdctl & BRDDAT6);
+ *eeprom = !(brdctl & BRDDAT7);
+
+ /*
+ * We're done, the calling function will release the SEEPROM for us
+ */
+}
+
/*+F*************************************************************************
* Function:
* aic787x_cable_detect
max_target = 8;
aic_outb(p, SEEMS | SEECS, SEECTL);
sxfrctl1 &= ~STPWEN;
- if ( (p->adapter_control & CFAUTOTERM) ||
- (p->features & AHC_NEW_AUTOTERM) )
+ /*
+ * The termination/cable detection logic is split into three distinct
+ * groups. Ultra2 and later controllers, 2940UW-Pro controllers, and
+ * older 7850, 7860, 7870, 7880, and 7895 controllers. Each has its
+ * own unique way of detecting their cables and writing the results
+ * back to the card.
+ */
+ if (p->features & AHC_ULTRA2)
{
- if ( (p->adapter_control & CFAUTOTERM) &&
- !(p->features & AHC_NEW_AUTOTERM) )
- {
- printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
- p->host_no);
- printk(KERN_INFO "(scsi%d) Please verify driver detected settings are "
- "correct.\n", p->host_no);
- printk(KERN_INFO "(scsi%d) If not, then please properly set the device "
- "termination\n", p->host_no);
- printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting CTRL-A "
- "when prompted\n", p->host_no);
- printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
- }
- /* Configure auto termination. */
-
- if (p->features & AHC_NEW_AUTOTERM)
- {
- if (aic7xxx_override_term == -1)
- aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
- &enableLVD_low, &enableLVD_high,
- &eprom_present);
- if (!(p->adapter_control & CFSEAUTOTERM))
- {
- enableSE_low = (p->adapter_control & CFSTERM);
- enableSE_high = (p->adapter_control & CFWSTERM);
- }
- if (!(p->adapter_control & CFAUTOTERM))
- {
- enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
- }
- internal50_present = 0;
- internal68_present = 1;
- external_present = 1;
- }
- else if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
- {
- aic787x_cable_detect(p, &internal50_present, &internal68_present,
- &external_present, &eprom_present);
- }
- else
+ /*
+ * As long as user hasn't overridden term settings, always check the
+ * cable detection logic
+ */
+ if (aic7xxx_override_term == -1)
{
- aic785x_cable_detect(p, &internal50_present, &external_present,
- &eprom_present);
+ aic7xxx_ultra2_term_detect(p, &enableSE_low, &enableSE_high,
+ &enableLVD_low, &enableLVD_high,
+ &eprom_present);
}
- if (max_target <= 8)
- internal68_present = 0;
-
- if ( !(p->features & AHC_NEW_AUTOTERM) )
- {
- if (max_target > 8)
- {
- printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
- "Ext-68 %s)\n", p->host_no,
- internal50_present ? "YES" : "NO",
- internal68_present ? "YES" : "NO",
- external_present ? "YES" : "NO");
- }
- else
- {
- printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
- p->host_no,
- internal50_present ? "YES" : "NO",
- external_present ? "YES" : "NO");
- }
- }
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
- eprom_present ? "is" : "is not");
-
/*
- * Now set the termination based on what we found. BRDDAT6
- * controls wide termination enable.
- * Flash Enable = BRDDAT7
- * SE High Term Enable = BRDDAT6
- * SE Low Term Enable = BRDDAT5 (7890)
- * LVD High Term Enable = BRDDAT4 (7890)
+ * If the user is overriding settings, then they have been preserved
+ * to here as fake adapter_control entries. Parse them and allow
+ * them to override the detected settings (if we even did detection).
*/
- if ( !(p->features & AHC_NEW_AUTOTERM) &&
- (internal50_present && internal68_present && external_present) )
- {
- printk(KERN_INFO "(scsi%d) Illegal cable configuration!! Only two\n",
- p->host_no);
- printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
- "in use at a time!\n", p->host_no);
- /*
- * Force termination (low and high byte) on. This is safer than
- * leaving it completely off, especially since this message comes
- * most often from motherboard controllers that don't even have 3
- * connectors, but instead are failing the cable detection.
- */
- internal50_present = external_present = 0;
- enableSE_high = enableSE_low = 1;
- }
-
- if ((max_target > 8) &&
- ((external_present == 0) || (internal68_present == 0) ||
- (enableSE_high != 0)))
+ if (!(p->adapter_control & CFSEAUTOTERM))
{
- brddat |= BRDDAT6;
- p->flags |= AHC_TERM_ENB_SE_HIGH;
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
- p->host_no);
+ enableSE_low = (p->adapter_control & CFSTERM);
+ enableSE_high = (p->adapter_control & CFWSTERM);
}
-
- if ( (((internal50_present ? 1 : 0) +
- (internal68_present ? 1 : 0) +
- (external_present ? 1 : 0)) <= 1) ||
- (enableSE_low != 0) )
+ if (!(p->adapter_control & CFAUTOTERM))
{
- if (p->features & AHC_NEW_AUTOTERM)
- brddat |= BRDDAT5;
- else
- sxfrctl1 |= STPWEN;
- p->flags |= AHC_TERM_ENB_SE_LOW;
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
- p->host_no);
+ enableLVD_low = enableLVD_high = (p->adapter_control & CFLVDSTERM);
}
+ /*
+ * Now take those settings that we have and translate them into the
+ * values that must be written into the registers.
+ *
+ * Flash Enable = BRDDAT7
+ * Secondary High Term Enable = BRDDAT6
+ * Secondary Low Term Enable = BRDDAT5
+ * LVD/Primary High Term Enable = BRDDAT4
+ * LVD/Primary Low Term Enable = STPWEN bit in SXFRCTL1
+ */
if (enableLVD_low != 0)
{
sxfrctl1 |= STPWEN;
p->flags |= AHC_TERM_ENB_LVD;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n",
- p->host_no);
+ printk(KERN_INFO "(scsi%d) LVD/Primary Low byte termination "
+ "Enabled\n", p->host_no);
}
if (enableLVD_high != 0)
{
brddat |= BRDDAT4;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n",
- p->host_no);
+ printk(KERN_INFO "(scsi%d) LVD/Primary High byte termination "
+ "Enabled\n", p->host_no);
}
- }
- else
- {
- if (p->adapter_control & CFSTERM)
+
+ if (enableSE_low != 0)
{
- if (p->features & AHC_NEW_AUTOTERM)
- brddat |= BRDDAT5;
- else
- sxfrctl1 |= STPWEN;
+ brddat |= BRDDAT5;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
- p->host_no);
+ printk(KERN_INFO "(scsi%d) Secondary Low byte termination "
+ "Enabled\n", p->host_no);
}
- if (p->adapter_control & CFWSTERM)
+ if (enableSE_high != 0)
{
brddat |= BRDDAT6;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
- p->host_no);
+ printk(KERN_INFO "(scsi%d) Secondary High byte termination "
+ "Enabled\n", p->host_no);
}
}
- aic_outb(p, sxfrctl1, SXFRCTL1);
- write_brdctl(p, brddat);
- release_seeprom(p);
- }
-}
+ else if (p->features & AHC_NEW_AUTOTERM)
+ {
+ /*
+ * The 50 pin connector termination is controlled by STPWEN in the
+ * SXFRCTL1 register. Since the Adaptec docs typically say the
+ * controller is not allowed to be in the middle of a cable and
+ * this is the only connection on that stub of the bus, there is
+ * no need to even check for narrow termination, it's simply
+ * always on.
+ */
+ sxfrctl1 |= STPWEN;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) Narrow channel termination Enabled\n",
+ p->host_no);
-/*+F*************************************************************************
- * Function:
- * detect_maxscb
- *
- * Description:
- * Detects the maximum number of SCBs for the controller and returns
- * the count and a mask in p (p->maxscbs, p->qcntmask).
- *-F*************************************************************************/
+ if (p->adapter_control & CFAUTOTERM)
+ {
+ aic2940_uwpro_wide_cable_detect(p, &internal68_present,
+ &external_present,
+ &eprom_present);
+ printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+ "Ext-68 %s)\n", p->host_no,
+ "Don't Care",
+ internal68_present ? "YES" : "NO",
+ external_present ? "YES" : "NO");
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+ eprom_present ? "is" : "is not");
+ if (internal68_present && external_present)
+ {
+ brddat = 0;
+ p->flags &= ~AHC_TERM_ENB_SE_HIGH;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) Wide channel termination Disabled\n",
+ p->host_no);
+ }
+ else
+ {
+ brddat = BRDDAT6;
+ p->flags |= AHC_TERM_ENB_SE_HIGH;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+ p->host_no);
+ }
+ }
+ else
+ {
+ /*
+ * The termination of the Wide channel is done more like normal
+ * though, and the setting of this termination is done by writing
+ * either a 0 or 1 to BRDDAT6 of the BRDDAT register
+ */
+ if (p->adapter_control & CFWSTERM)
+ {
+ brddat = BRDDAT6;
+ p->flags |= AHC_TERM_ENB_SE_HIGH;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) Wide channel termination Enabled\n",
+ p->host_no);
+ }
+ else
+ {
+ brddat = 0;
+ }
+ }
+ }
+ else
+ {
+ if (p->adapter_control & CFAUTOTERM)
+ {
+ if (p->flags & AHC_MOTHERBOARD)
+ {
+ printk(KERN_INFO "(scsi%d) Warning - detected auto-termination\n",
+ p->host_no);
+ printk(KERN_INFO "(scsi%d) Please verify driver detected settings "
+ "are correct.\n", p->host_no);
+ printk(KERN_INFO "(scsi%d) If not, then please properly set the "
+ "device termination\n", p->host_no);
+ printk(KERN_INFO "(scsi%d) in the Adaptec SCSI BIOS by hitting "
+ "CTRL-A when prompted\n", p->host_no);
+ printk(KERN_INFO "(scsi%d) during machine bootup.\n", p->host_no);
+ }
+ /* Configure auto termination. */
+
+ if ( (p->chip & AHC_CHIPID_MASK) >= AHC_AIC7870 )
+ {
+ aic787x_cable_detect(p, &internal50_present, &internal68_present,
+ &external_present, &eprom_present);
+ }
+ else
+ {
+ aic785x_cable_detect(p, &internal50_present, &external_present,
+ &eprom_present);
+ }
+
+ if (max_target <= 8)
+ internal68_present = 0;
+
+ if (max_target > 8)
+ {
+ printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Int-68 %s, "
+ "Ext-68 %s)\n", p->host_no,
+ internal50_present ? "YES" : "NO",
+ internal68_present ? "YES" : "NO",
+ external_present ? "YES" : "NO");
+ }
+ else
+ {
+ printk(KERN_INFO "(scsi%d) Cables present (Int-50 %s, Ext-50 %s)\n",
+ p->host_no,
+ internal50_present ? "YES" : "NO",
+ external_present ? "YES" : "NO");
+ }
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) EEPROM %s present.\n", p->host_no,
+ eprom_present ? "is" : "is not");
+
+ /*
+ * Now set the termination based on what we found. BRDDAT6
+ * controls wide termination enable.
+ * Flash Enable = BRDDAT7
+ * SE High Term Enable = BRDDAT6
+ */
+ if (internal50_present && internal68_present && external_present)
+ {
+ printk(KERN_INFO "(scsi%d) Illegal cable configuration!! Only two\n",
+ p->host_no);
+ printk(KERN_INFO "(scsi%d) connectors on the SCSI controller may be "
+ "in use at a time!\n", p->host_no);
+ /*
+ * Force termination (low and high byte) on. This is safer than
+ * leaving it completely off, especially since this message comes
+ * most often from motherboard controllers that don't even have 3
+ * connectors, but instead are failing the cable detection.
+ */
+ internal50_present = external_present = 0;
+ enableSE_high = enableSE_low = 1;
+ }
+
+ if ((max_target > 8) &&
+ ((external_present == 0) || (internal68_present == 0)) )
+ {
+ brddat |= BRDDAT6;
+ p->flags |= AHC_TERM_ENB_SE_HIGH;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+ p->host_no);
+ }
+
+ if ( ((internal50_present ? 1 : 0) +
+ (internal68_present ? 1 : 0) +
+ (external_present ? 1 : 0)) <= 1 )
+ {
+ sxfrctl1 |= STPWEN;
+ p->flags |= AHC_TERM_ENB_SE_LOW;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+ p->host_no);
+ }
+ }
+ else /* p->adapter_control & CFAUTOTERM */
+ {
+ if (p->adapter_control & CFSTERM)
+ {
+ sxfrctl1 |= STPWEN;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n",
+ p->host_no);
+ }
+
+ if (p->adapter_control & CFWSTERM)
+ {
+ brddat |= BRDDAT6;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n",
+ p->host_no);
+ }
+ }
+ }
+
+ aic_outb(p, sxfrctl1, SXFRCTL1);
+ write_brdctl(p, brddat);
+ release_seeprom(p);
+ }
+}
+
+/*+F*************************************************************************
+ * Function:
+ * detect_maxscb
+ *
+ * Description:
+ * Detects the maximum number of SCBs for the controller and returns
+ * the count and a mask in p (p->maxscbs, p->qcntmask).
+ *-F*************************************************************************/
static void
detect_maxscb(struct aic7xxx_host *p)
{
unsigned char term, scsi_conf;
struct Scsi_Host *host;
- /*
- * Lock out other contenders for our i/o space.
- */
- request_region(p->base, MAXREG - MINREG, "aic7xxx");
-
-
host = p->host;
p->scb_data->maxscbs = AIC7XXX_MAXSCB;
printk("VLB slot %d\n", p->pci_device_fn);
break;
default:
- printk("PCI %d/%d\n", PCI_SLOT(p->pci_device_fn),
+ printk("PCI %d/%d/%d\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
PCI_FUNC(p->pci_device_fn));
break;
}
}
aic_outb(p, 0, SEQ_FLAGS);
+ /*
+ * We are starting to do real work on the card....it's possible we could
+ * generate some spurious interrupts at this point, especially in the
+ * event of a PCI error or some such. If there are other devices already
+ * registered on the same interrupt as us, this could cause the machine
+ * to lock up. So, we disable the interrupt this card is on until we
+ * finish our card setup. We only need to do this for modules, if we are
+ * compiled into the kernel then interrupts are already off during this
+ * part of the code.
+ */
+#ifdef MODULE
+ disable_irq(p->irq);
+#endif
+
detect_maxscb(p);
#endif
if ( (aic7xxx_stpwlev >> p->instance) & 0x01 )
{
- devconfig |= 0x02;
+ devconfig |= STPWLEVEL;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("(scsi%d) Force setting STPWLEV bit\n", p->host_no);
+ printk("(scsi%d) Force setting STPWLEVEL bit\n", p->host_no);
}
else
{
- devconfig &= ~0x02;
+ devconfig &= ~STPWLEVEL;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("(scsi%d) Force clearing STPWLEV bit\n", p->host_no);
+ printk("(scsi%d) Force clearing STPWLEVEL bit\n", p->host_no);
}
#if LINUX_KERNEL_VERSION > KERNEL_VERSION(2,1,92)
pci_write_config_byte(p->pdev, DEVCONFIG, devconfig);
}
}
- /*
- * Clear out any possible pending interrupts.
- */
- aic7xxx_clear_intstat(p);
-
/*
* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels
*/
aic_outb(p, (scsi_conf & ENSPCHK) | aic7xxx_seltime | term |
ENSTIMER | ACTNEGEN, SXFRCTL1);
aic_outb(p, 0, SIMODE0);
- aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
+ /*
+ * If we are a cardbus adapter then don't enable SCSI reset detection.
+ * We shouldn't likely be sharing SCSI busses with someone else, and
+ * if we don't have a cable currently plugged into the controller then
+ * we won't have a power source for the SCSI termination, which means
+ * we'll see infinite incoming bus resets.
+ */
+ if(p->flags & AHC_NO_STPWEN)
+ aic_outb(p, ENSELTIMO | ENSCSIPERR, SIMODE1);
+ else
+ aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
aic_outb(p, 0, SCSIRATE);
if ( p->features & AHC_ULTRA2)
aic_outb(p, 0, SCSIOFFSET);
{
printk("(scsi%d) Unable to allocate hardware SCB array; "
"failing detection.\n", p->host_no);
+ aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+ enable_irq(p->irq);
+#endif
p->irq = 0;
return(0);
}
p->next = first_aic7xxx;
first_aic7xxx = p;
- /*
- * Clear out any possible pending interrupts, again.
- */
- aic7xxx_clear_intstat(p);
-
/*
* Allocate the first set of scbs for this controller. This is to stream-
* line code elsewhere in the driver. If we have to check for the existence
printk(KERN_INFO "(scsi%d) Resetting channel%s\n", p->host_no, channel);
}
- /*
- * Some of the new Ultra2 chipsets need a longer delay after a chip
- * reset than just the init setup creates, so we have to delay here
- * before we go into a reset in order to make the chips happy.
- */
- if (p->features & AHC_ULTRA2)
- mdelay(250);
aic7xxx_reset_current_bus(p);
/*
- * Delay for the reset delay.
+ * Delay for the reset delay by setting the timer, this will delay
+ * future commands sent to any devices.
*/
- if (!reset_delay)
- aic7xxx_delay(AIC7XXX_RESET_DELAY);
+ p->flags |= AHC_RESET_DELAY;
+ for(i=0; i<MAX_TARGETS; i++)
+ {
+ p->dev_expires[i] = jiffies + (4 * HZ);
+ p->dev_timer_active |= (0x01 << i);
+ }
+ p->dev_timer.expires = p->dev_expires[p->scsi_id];
+ add_timer(&p->dev_timer);
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
}
else
{
"the no_reset\n", p->host_no);
printk(KERN_INFO "(scsi%d) option unless you have a verifiable need "
"for it.\n", p->host_no);
- printk(KERN_INFO "(scsi%d) The no_reset option is known to break some "
- "systems,\n", p->host_no);
- printk(KERN_INFO "(scsi%d) and is not supported by the driver author\n",
- p->host_no);
- aic7xxx_delay(AIC7XXX_RESET_DELAY);
}
}
{
printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
"controller.\n", p->host_no, p->irq);
+ aic_outb(p, 0, SIMODE1);
+#ifdef MODULE
+ enable_irq(p->irq);
+#endif
p->irq = 0;
return (0);
}
+ if(aic_inb(p, INTSTAT) & INT_PEND)
+ printk(INFO_LEAD "spurious interrupt during configuration, cleared.\n",
+ p->host_no, -1, -1 , -1);
+ aic7xxx_clear_intstat(p);
+
+#ifdef MODULE
+ enable_irq(p->irq);
+#endif
+
unpause_sequencer(p, /* unpause_always */ TRUE);
return (found);
* In the future, we may call this function as a last resort for
* error handling. Let's be nice and not do any unecessary delays.
*/
- wait = 1000; /* 1 second (1000 * 1 msec) */
+ wait = 1000; /* 1 msec (1000 * 1 msec) */
while (--wait && !(aic_inb(p, HCNTRL) & CHIPRSTACK))
{
- mdelay(1); /* 1 msec */
+ udelay(1); /* 1 usec */
}
pause_sequencer(p);
template->sg_tablesize = AIC7XXX_MAX_SG;
-#if defined(__i386__) || defined(__alpha__)
-#ifdef CONFIG_PCI
- /*
- * PCI-bus chipset probe.
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
- if (pci_present())
- {
- if (pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82450GX,
- NULL))
- aic7xxx_no_probe = 1;
- if (pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82451NX,
- NULL))
- aic7xxx_no_probe = 1;
- }
-#else
-#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
- if (pcibios_present())
- {
- unsigned char pci_bus, pci_devfn;
- if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82450GX,
- 0, &pci_bus, &pci_devfn)) )
- aic7xxx_no_probe = 1;
- if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82451NX,
- 0, &pci_bus, &pci_devfn)) )
- aic7xxx_no_probe = 1;
- }
-#endif /* LINUX_VERSION_CODE */
-#endif /* CONFIG_PCI */
- /*
- * EISA/VL-bus card signature probe.
- */
- slot = MINSLOT;
- while ( (slot <= MAXSLOT) &&
- !(aic7xxx_no_probe) )
- {
- base = SLOTBASE(slot) + MINREG;
-
- if (check_region(base, MAXREG - MINREG))
- {
- /*
- * Some other driver has staked a
- * claim to this i/o region already.
- */
- slot++;
- continue; /* back to the beginning of the for loop */
- }
- flags = 0;
- type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
- if (type == -1)
- {
- slot++;
- continue;
- }
- temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
- if (temp_p == NULL)
- {
- printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
- slot++;
- continue; /* back to the beginning of the while loop */
- }
- /*
- * Pause the card preserving the IRQ type. Allow the operator
- * to override the IRQ trigger.
- */
- if (aic7xxx_irq_trigger == 1)
- hcntrl = IRQMS; /* Level */
- else if (aic7xxx_irq_trigger == 0)
- hcntrl = 0; /* Edge */
- else
- hcntrl = inb(base + HCNTRL) & IRQMS; /* Default */
- memset(temp_p, 0, sizeof(struct aic7xxx_host));
- temp_p->unpause = hcntrl | INTEN;
- temp_p->pause = hcntrl | PAUSE | INTEN;
- temp_p->base = base;
- temp_p->mbase = 0;
- temp_p->maddr = 0;
- temp_p->pci_bus = 0;
- temp_p->pci_device_fn = slot;
- aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
- while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
- if (aic7xxx_chip_reset(temp_p) == -1)
- temp_p->irq = 0;
- else
- temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
- temp_p->flags |= AHC_PAGESCBS;
-
- switch (temp_p->irq)
- {
- case 9:
- case 10:
- case 11:
- case 12:
- case 14:
- case 15:
- break;
-
- default:
- printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
- "level %d, ignoring.\n", temp_p->irq);
- kfree(temp_p);
- slot++;
- continue; /* back to the beginning of the while loop */
- }
-
- /*
- * We are commited now, everything has been checked and this card
- * has been found, now we just set it up
- */
-
- /*
- * Insert our new struct into the list at the end
- */
- if (list_p == NULL)
- {
- list_p = current_p = temp_p;
- }
- else
- {
- current_p = list_p;
- while (current_p->next != NULL)
- current_p = current_p->next;
- current_p->next = temp_p;
- }
-
- switch (type)
- {
- case 0:
- temp_p->board_name_index = 2;
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at EISA %d\n",
- board_names[2], slot);
- /* FALLTHROUGH */
- case 1:
- {
- temp_p->chip = AHC_AIC7770 | AHC_EISA;
- temp_p->features |= AHC_AIC7770_FE;
- temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
-
- /*
- * Get the primary channel information. Right now we don't
- * do anything with this, but someday we will be able to inform
- * the mid-level SCSI code which channel is primary.
- */
- if (temp_p->board_name_index == 0)
- {
- temp_p->board_name_index = 3;
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at EISA %d\n",
- board_names[3], slot);
- }
- if (temp_p->bios_control & CHANNEL_B_PRIMARY)
- {
- temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
- }
-
- if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
- {
- temp_p->flags &= ~AHC_BIOS_ENABLED;
- }
- else
- {
- temp_p->flags &= ~AHC_USEDEFAULTS;
- temp_p->flags |= AHC_BIOS_ENABLED;
- if ( (temp_p->bios_control & 0x20) == 0 )
- {
- temp_p->bios_address = 0xcc000;
- temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
- }
- else
- {
- temp_p->bios_address = 0xd0000;
- temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
- }
- }
- temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
- temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
- if (temp_p->features & AHC_WIDE)
- {
- temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
- temp_p->scsi_id_b = temp_p->scsi_id;
- }
- else
- {
- temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
- temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
- }
- aic7xxx_load_seeprom(temp_p, &sxfrctl1);
- break;
- }
-
- case 2:
- case 3:
- temp_p->chip = AHC_AIC7770 | AHC_VL;
- temp_p->features |= AHC_AIC7770_FE;
- if (type == 2)
- temp_p->flags |= AHC_BIOS_ENABLED;
- else
- temp_p->flags &= ~AHC_BIOS_ENABLED;
- if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
- sxfrctl1 = STPWEN;
- aic7xxx_load_seeprom(temp_p, &sxfrctl1);
- temp_p->board_name_index = 4;
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at VLB %d\n",
- board_names[2], slot);
- switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
- {
- case 0x00:
- temp_p->bios_address = 0xe0000;
- break;
- case 0x20:
- temp_p->bios_address = 0xc8000;
- break;
- case 0x40:
- temp_p->bios_address = 0xd0000;
- break;
- case 0x60:
- temp_p->bios_address = 0xd8000;
- break;
- default:
- break; /* can't get here */
- }
- break;
-
- default: /* Won't get here. */
- break;
- }
- if (aic7xxx_verbose & VERBOSE_PROBE2)
- {
- printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
- (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
- temp_p->irq,
- (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
- printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
- (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
- }
-
- /*
- * Set the FIFO threshold and the bus off time.
- */
- hostconf = aic_inb(temp_p, HOSTCONF);
- aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
- aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
- slot++;
- found++;
- }
-
-#endif /* defined(__i386__) || defined(__alpha__) */
-
#ifdef CONFIG_PCI
/*
* PCI-bus probe.
AHC_AIC7860_FE, 7,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
- AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
AHC_AIC7860_FE, 7,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AHC_AIC7860,
AHC_AIC7860_FE, 8,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AHC_AIC7870,
- AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE, 9,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+ AHC_AIC7870_FE, 9,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AHC_AIC7870,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE, 10,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7870_FE, 13,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7880, AHC_AIC7880,
- AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 14,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED | AHC_MOTHERBOARD,
+ AHC_AIC7880_FE, 14,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7881, AHC_AIC7880,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 15,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7887, AHC_AIC7880,
- AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 18,
+ AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE | AHC_NEW_AUTOTERM, 19,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7888, AHC_AIC7880,
AHC_PAGESCBS | AHC_BIOS_ENABLED, AHC_AIC7880_FE, 18,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7895, AHC_AIC7895,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7895_FE, 19,
+ AHC_AIC7895_FE, 20,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7890_FE, 20,
+ AHC_AIC7890_FE, 21,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7890B, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7890_FE, 20,
+ AHC_AIC7890_FE, 21,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2930U2, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7890_FE, 21,
+ AHC_AIC7890_FE, 22,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7890_FE, 22,
+ AHC_AIC7890_FE, 23,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7896, AHC_AIC7896,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 23,
+ AHC_AIC7896_FE, 24,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3940U2, AHC_AIC7896,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 24,
+ AHC_AIC7896_FE, 25,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7896_FE, 25,
+ AHC_AIC7896_FE, 26,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
- AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7860_FE, 26,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_NO_STPWEN,
+ AHC_AIC7860_FE, 27,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892A, AHC_AIC7892,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7892_FE, 27,
+ AHC_AIC7892_FE, 28,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892B, AHC_AIC7892,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7892_FE, 27,
+ AHC_AIC7892_FE, 28,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892D, AHC_AIC7892,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7892_FE, 27,
+ AHC_AIC7892_FE, 28,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7892P, AHC_AIC7892,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
- AHC_AIC7892_FE, 27,
+ AHC_AIC7892_FE, 28,
32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899A, AHC_AIC7899,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7899_FE, 28,
+ AHC_AIC7899_FE, 29,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899B, AHC_AIC7899,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7899_FE, 28,
+ AHC_AIC7899_FE, 29,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899D, AHC_AIC7899,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7899_FE, 28,
+ AHC_AIC7899_FE, 29,
32, C56_66 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_7899P, AHC_AIC7899,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
- AHC_AIC7899_FE, 28,
+ AHC_AIC7899_FE, 29,
32, C56_66 },
};
if ( temp_p == NULL )
continue;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at PCI %d/%d\n",
+ printk("aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
- PCI_SLOT(temp_p->pdev->devfn),
- PCI_FUNC(temp_p->pdev->devfn));
+ temp_p->pci_bus,
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
pci_read_config_word(pdev, PCI_COMMAND, &command);
if (aic7xxx_verbose & VERBOSE_PROBE2)
{
if ( temp_p == NULL )
continue;
if (aic7xxx_verbose & VERBOSE_PROBE2)
- printk("aic7xxx: <%s> at PCI %d/%d\n",
+ printk("aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
#endif /* AIC7XXX_STRICT_PCI_SETUP */
#endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
+ if(check_region(temp_p->base, MAXREG - MINREG))
+ {
+ printk("aic7xxx: <%s> at PCI %d/%d/%d\n",
+ board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
+ printk("aic7xxx: I/O ports already in use, ignoring.\n");
+ kfree(temp_p);
+ temp_p = NULL;
+ continue;
+ }
+
temp_p->unpause = INTEN;
temp_p->pause = temp_p->unpause | PAUSE;
if ( ((temp_p->base == 0) &&
(temp_p->mbase == 0)) ||
(temp_p->irq == 0) )
{
- printk("aic7xxx: <%s> at PCI %d/%d\n",
+ printk("aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
/*
* OK.....we failed our test....go back to programmed I/O
*/
- printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
+ printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
}
#endif
+ /*
+ * Lock out other contenders for our i/o space.
+ */
+ request_region(temp_p->base, MAXREG - MINREG, "aic7xxx");
+
/*
* We HAVE to make sure the first pause_sequencer() and all other
* subsequent I/O that isn't PCI config space I/O takes place
/*
* Get current termination setting
*/
- sxfrctl1 = aic_inb(temp_p, SXFRCTL1) & STPWEN;
+ sxfrctl1 = aic_inb(temp_p, SXFRCTL1);
if (aic7xxx_chip_reset(temp_p) == -1)
{
+ release_region(temp_p->base, MAXREG - MINREG);
kfree(temp_p);
temp_p = NULL;
continue;
}
+ /*
+ * Very quickly put the term setting back into the register since
+ * the chip reset may cause odd things to happen. This is to keep
+ * LVD busses with lots of drives from draining the power out of
+ * the diffsense line before we get around to running the
+ * configure_termination() function. Also restore the STPWLEVEL
+ * bit of DEVCONFIG
+ */
+ aic_outb(temp_p, sxfrctl1, SXFRCTL1);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
+ pcibios_write_config_dword(temp_p->pci_bus, temp_p->pci_device_fn,
+ DEVCONFIG, devconfig);
+#else
+ pci_write_config_dword(temp_p->pdev, DEVCONFIG, devconfig);
+#endif
+ sxfrctl1 &= STPWEN;
/*
* We need to set the CHNL? assignments before loading the SEEPROM
}
else if (aic_inb(temp_p, DSCOMMAND0) & RAMPSM_ULTRA2)
{
- printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
+ printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
printk("aic7xxx: external SCB RAM detected, "
}
else if (devconfig & RAMPSM)
{
- printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
+ printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d/%d\n",
board_names[aic_pdevs[i].board_name_index],
+ temp_p->pci_bus,
PCI_SLOT(temp_p->pci_device_fn),
PCI_FUNC(temp_p->pci_device_fn));
printk("aic7xxx: external SCB RAM detected, "
} /* for PCI_DEVICES */
} /* PCI BIOS present */
#endif CONFIG_PCI
+
+#if defined(__i386__) || defined(__alpha__)
+ /*
+ * EISA/VL-bus card signature probe.
+ */
+ slot = MINSLOT;
+ while ( (slot <= MAXSLOT) &&
+ !(aic7xxx_no_probe) )
+ {
+ base = SLOTBASE(slot) + MINREG;
+
+ if (check_region(base, MAXREG - MINREG))
+ {
+ /*
+ * Some other driver has staked a
+ * claim to this i/o region already.
+ */
+ slot++;
+ continue; /* back to the beginning of the for loop */
+ }
+ flags = 0;
+ type = aic7xxx_probe(slot, base + AHC_HID0, &flags);
+ if (type == -1)
+ {
+ slot++;
+ continue;
+ }
+ temp_p = kmalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC);
+ if (temp_p == NULL)
+ {
+ printk(KERN_WARNING "aic7xxx: Unable to allocate device space.\n");
+ slot++;
+ continue; /* back to the beginning of the while loop */
+ }
+ /*
+ * Lock out other contenders for our i/o space.
+ */
+ request_region(base, MAXREG - MINREG, "aic7xxx");
+
+ /*
+ * Pause the card preserving the IRQ type. Allow the operator
+ * to override the IRQ trigger.
+ */
+ if (aic7xxx_irq_trigger == 1)
+ hcntrl = IRQMS; /* Level */
+ else if (aic7xxx_irq_trigger == 0)
+ hcntrl = 0; /* Edge */
+ else
+ hcntrl = inb(base + HCNTRL) & IRQMS; /* Default */
+ memset(temp_p, 0, sizeof(struct aic7xxx_host));
+ temp_p->unpause = hcntrl | INTEN;
+ temp_p->pause = hcntrl | PAUSE | INTEN;
+ temp_p->base = base;
+ temp_p->mbase = 0;
+ temp_p->maddr = 0;
+ temp_p->pci_bus = 0;
+ temp_p->pci_device_fn = slot;
+ aic_outb(temp_p, hcntrl | PAUSE, HCNTRL);
+ while( (aic_inb(temp_p, HCNTRL) & PAUSE) == 0 ) ;
+ if (aic7xxx_chip_reset(temp_p) == -1)
+ temp_p->irq = 0;
+ else
+ temp_p->irq = aic_inb(temp_p, INTDEF) & 0x0F;
+ temp_p->flags |= AHC_PAGESCBS;
+
+ switch (temp_p->irq)
+ {
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 14:
+ case 15:
+ break;
+
+ default:
+ printk(KERN_WARNING "aic7xxx: Host adapter uses unsupported IRQ "
+ "level %d, ignoring.\n", temp_p->irq);
+ kfree(temp_p);
+ release_region(base, MAXREG - MINREG);
+ slot++;
+ continue; /* back to the beginning of the while loop */
+ }
+
+ /*
+ * We are commited now, everything has been checked and this card
+ * has been found, now we just set it up
+ */
+
+ /*
+ * Insert our new struct into the list at the end
+ */
+ if (list_p == NULL)
+ {
+ list_p = current_p = temp_p;
+ }
+ else
+ {
+ current_p = list_p;
+ while (current_p->next != NULL)
+ current_p = current_p->next;
+ current_p->next = temp_p;
+ }
+
+ switch (type)
+ {
+ case 0:
+ temp_p->board_name_index = 2;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk("aic7xxx: <%s> at EISA %d\n",
+ board_names[2], slot);
+ /* FALLTHROUGH */
+ case 1:
+ {
+ temp_p->chip = AHC_AIC7770 | AHC_EISA;
+ temp_p->features |= AHC_AIC7770_FE;
+ temp_p->bios_control = aic_inb(temp_p, HA_274_BIOSCTRL);
+
+ /*
+ * Get the primary channel information. Right now we don't
+ * do anything with this, but someday we will be able to inform
+ * the mid-level SCSI code which channel is primary.
+ */
+ if (temp_p->board_name_index == 0)
+ {
+ temp_p->board_name_index = 3;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk("aic7xxx: <%s> at EISA %d\n",
+ board_names[3], slot);
+ }
+ if (temp_p->bios_control & CHANNEL_B_PRIMARY)
+ {
+ temp_p->flags |= AHC_CHANNEL_B_PRIMARY;
+ }
+
+ if ((temp_p->bios_control & BIOSMODE) == BIOSDISABLED)
+ {
+ temp_p->flags &= ~AHC_BIOS_ENABLED;
+ }
+ else
+ {
+ temp_p->flags &= ~AHC_USEDEFAULTS;
+ temp_p->flags |= AHC_BIOS_ENABLED;
+ if ( (temp_p->bios_control & 0x20) == 0 )
+ {
+ temp_p->bios_address = 0xcc000;
+ temp_p->bios_address += (0x4000 * (temp_p->bios_control & 0x07));
+ }
+ else
+ {
+ temp_p->bios_address = 0xd0000;
+ temp_p->bios_address += (0x8000 * (temp_p->bios_control & 0x06));
+ }
+ }
+ temp_p->adapter_control = aic_inb(temp_p, SCSICONF) << 8;
+ temp_p->adapter_control |= aic_inb(temp_p, SCSICONF + 1);
+ if (temp_p->features & AHC_WIDE)
+ {
+ temp_p->scsi_id = temp_p->adapter_control & HWSCSIID;
+ temp_p->scsi_id_b = temp_p->scsi_id;
+ }
+ else
+ {
+ temp_p->scsi_id = (temp_p->adapter_control >> 8) & HSCSIID;
+ temp_p->scsi_id_b = temp_p->adapter_control & HSCSIID;
+ }
+ aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+ break;
+ }
+
+ case 2:
+ case 3:
+ temp_p->chip = AHC_AIC7770 | AHC_VL;
+ temp_p->features |= AHC_AIC7770_FE;
+ if (type == 2)
+ temp_p->flags |= AHC_BIOS_ENABLED;
+ else
+ temp_p->flags &= ~AHC_BIOS_ENABLED;
+ if (aic_inb(temp_p, SCSICONF) & TERM_ENB)
+ sxfrctl1 = STPWEN;
+ aic7xxx_load_seeprom(temp_p, &sxfrctl1);
+ temp_p->board_name_index = 4;
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ printk("aic7xxx: <%s> at VLB %d\n",
+ board_names[2], slot);
+ switch( aic_inb(temp_p, STATUS_2840) & BIOS_SEL )
+ {
+ case 0x00:
+ temp_p->bios_address = 0xe0000;
+ break;
+ case 0x20:
+ temp_p->bios_address = 0xc8000;
+ break;
+ case 0x40:
+ temp_p->bios_address = 0xd0000;
+ break;
+ case 0x60:
+ temp_p->bios_address = 0xd8000;
+ break;
+ default:
+ break; /* can't get here */
+ }
+ break;
+
+ default: /* Won't get here. */
+ break;
+ }
+ if (aic7xxx_verbose & VERBOSE_PROBE2)
+ {
+ printk(KERN_INFO "aic7xxx: BIOS %sabled, IO Port 0x%lx, IRQ %d (%s)\n",
+ (temp_p->flags & AHC_USEDEFAULTS) ? "dis" : "en", temp_p->base,
+ temp_p->irq,
+ (temp_p->pause & IRQMS) ? "level sensitive" : "edge triggered");
+ printk(KERN_INFO "aic7xxx: Extended translation %sabled.\n",
+ (temp_p->flags & AHC_EXTEND_TRANS_A) ? "en" : "dis");
+ }
+
+ /*
+ * Set the FIFO threshold and the bus off time.
+ */
+ hostconf = aic_inb(temp_p, HOSTCONF);
+ aic_outb(temp_p, hostconf & DFTHRSH, BUSSPD);
+ aic_outb(temp_p, (hostconf << 2) & BOFF, BUSTIME);
+ slot++;
+ found++;
+ }
+
+#endif /* defined(__i386__) || defined(__alpha__) */
+
/*
* Now, we re-order the probed devices by BIOS address and BUS class.
* In general, we follow this algorithm to make the adapters show up
(scb->flags & SCB_WAITINGQ) ? "WAITINGQ" : "Sent" );
}
}
-#endif
sti();
+#else
+ spin_unlock_irq(&io_request_lock);
+#endif
for(;;) barrier();
}
0x84, 0x8e, 0x90, 0x95, 0x97, 0x97, 0x9a, 0x9a, 0x9c, 0x9f,
0xe0, 0xf1, 0xf4, 0xfc} },
};
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
#ifdef CONFIG_PCI
static struct register_ranges cards_ns[] = {
{ 0, {0,} }, /* none */
{ 6, {0x04, 0x08, 0x0c, 0x1b, 0x30, 0x34, 0x3c, 0x43, 0xdc, 0xe3,
0xff, 0xff} }
};
+#endif
#endif
chip = p->chip & AHC_CHIPID_MASK;
/*
break;
case AHC_PCI:
default:
- printk("PCI %d/%d.\n", PCI_SLOT(p->pci_device_fn),
+ printk("PCI %d/%d/%d.\n", p->pci_bus, PCI_SLOT(p->pci_device_fn),
PCI_FUNC(p->pci_device_fn));
break;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
#ifdef CONFIG_PCI
{
unsigned char temp;
j <= cards_ns[chip].range_val[ i * 2 + 1 ] ;
j++)
{
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
- pci_read_config_byte(p->pdev, j, &temp);
-#else
pcibios_read_config_byte(p->pci_bus, p->pci_device_fn, j, &temp);
-#endif
printk("%02x:%02x ", j, temp);
if(++k == 13)
{
if(k != 0)
printk("\n");
#endif /* CONFIG_PCI */
+#endif
/*
* Now the registers on the card....
}
if(k != 0)
printk("\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
if (p->flags & AHC_SEEPROM_FOUND)
{
unsigned short *sc1;
printk(" ");
}
}
+#endif
/*
* If this was an Ultra2 controller, then we just hosed the card in terms
mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/
mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */
mask EXTENDED_MSG 0x40|SEQINT /* Extended message received */
- mask ABORT_REQUESTED 0x50|SEQINT /* Reconect of aborted SCB */
+ mask WIDE_RESIDUE 0x50|SEQINT /* need kernel to back up */
+ /* the SG array for us */
mask REJECT_MSG 0x60|SEQINT /* Reject message received */
mask BAD_STATUS 0x70|SEQINT /* Bad status from target */
mask RESIDUAL 0x80|SEQINT /* Residual byte count != 0 */
and SCSIID, OID; /* Clear old target */
or SCSIID, A;
}
+ mov SCSIDATL, ALLZEROS; /* clear out the latched */
+ /* data register, this */
+ /* fixes a bug on some */
+ /* controllers where the */
+ /* last byte written to */
+ /* this register can leak */
+ /* onto the data bus at */
+ /* bad times, such as during */
+ /* selection timeouts */
mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
/*
if ((p->features & AHC_ULTRA2) != 0) {
bmov HADDR, SHADDR, 4;
bmov HCNT, SCB_RESID_DCNT, 3;
+ } else {
+ bmov STCNT, SCB_RESID_DCNT, 3;
}
- bmov STCNT, SCB_RESID_DCNT, 3;
} else {
mvi DINDEX, STCNT;
mvi SCB_RESID_DCNT call bcopy_3;
}
data_phase_inbounds:
/* If we are the last SG block, tell the hardware. */
-if ((p->features & AHC_ULTRA2) == 0) {
cmp SG_COUNT,0x01 jne data_phase_wideodd;
- and DMAPARAMS, ~WIDEODD;
-}
+ if ((p->features & AHC_ULTRA2) == 0) {
+ and DMAPARAMS, ~WIDEODD;
+ } else {
+ mvi SG_CACHEPTR, LAST_SEG;
+ }
data_phase_wideodd:
if ((p->features & AHC_ULTRA2) != 0) {
mov SINDEX, ALLONES;
test SSTAT0, SDONE jnz data_phase_dma_done;
test SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
data_phase_dma_phasemis:
- test SSTAT0,SDONE jnz . + 2;
+ test SSTAT0,SDONE jnz data_phase_dma_done;
clr SINDEX; /* Remember the phasemiss */
} else {
mov DMAPARAMS call dma;
test SSTAT1, REQINIT jz .;
test SSTAT1,PHASEMIS jz data_phase_loop;
+/* This drops the last SG segment down to the shadow layer for us */
if ((p->features & AHC_ULTRA2) != 0) {
mov DFCNTRL, DMAPARAMS;
- test SSTAT0, SDONE jnz .;
+ test SSTAT0, SDONE jnz .;
}
data_phase_finish:
mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
test SSTAT0, SDONE jnz .;
p_command_dma_loop:
- test SSTAT0, DMADONE jnz p_command_ultra2_dma_done;
+ test SSTAT0, SDONE jnz p_command_ultra2_dma_done;
test SSTAT1,PHASEMIS jz p_command_dma_loop; /* ie. underrun */
p_command_ultra2_dma_done:
and DFCNTRL, ~HDMAEN;
cmp A,MSG_EXTENDED je mesgin_extended;
cmp A,MSG_MESSAGE_REJECT je mesgin_reject;
cmp A,MSG_NOOP je mesgin_done;
+ cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_wide_residue;
rej_mesgin:
/*
mvi INTSTAT, REJECT_MSG;
jmp mesgin_done;
+/*
+ * Wide Residue. We handle the simple cases, but pass of the one hard case
+ * to the kernel (when the residue byte happened to cause us to advance our
+ * sg element array, so we know have to back that advance out).
+ */
+mesgin_wide_residue:
+ mvi ARG_1 call inb_next; /* ACK the wide_residue and get */
+ /* the size byte */
+/*
+ * See if we'll ignore this wide residue (because it's an overrun byte)
+ */
+ test SCB_RESID_SGCNT,0xff jnz wide_residue_int;
+ test SCB_RESID_DCNT[0],0xff jnz wide_residue_int;
+ test SCB_RESID_DCNT[1],0xff jnz wide_residue_int;
+ test SCB_RESID_DCNT[2],0xff jnz wide_residue_int;
+ jmp mesgin_done;
+
+wide_residue_int:
+/*
+ * In order for this to be reliable, we have to do all sorts of horrible
+ * magic in terms of resetting the datafifo and reloading the shadow layer
+ * with the correct new values (so that a subsequent save data pointers
+ * message will do the right thing). We let the kernel do that work.
+ */
+ mvi INTSTAT,WIDE_RESIDUE;
+ jmp mesgin_done;
+
/*
* [ ADD MORE MESSAGE HANDLING HERE ]
*/
* before continuing.
*/
test SSTAT1, REQINIT jz inb_next_wait;
- test SSTAT1, SCSIPERR jnz inb_next_wait;
+ test SSTAT1, SCSIPERR jnz .;
and LASTPHASE, PHASE_MASK, SCSISIGI;
cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
inb_first:
size += sprintf(BLS, " SCSI Adapter: %s\n",
board_names[p->board_name_index]);
if (p->flags & AHC_TWIN)
- size += sprintf(BLS, " Twin Channel\n");
+ size += sprintf(BLS, " Twin Channel Controller ");
else
{
char *channel = "";
ultra = "Ultra-2 LVD/SE ";
else if (p->features & AHC_ULTRA)
ultra = "Ultra ";
- size += sprintf(BLS, " %s%sController%s\n",
+ size += sprintf(BLS, " %s%sController%s ",
ultra, wide, channel);
}
+ switch(p->chip & ~AHC_CHIPID_MASK)
+ {
+ case AHC_VL:
+ size += sprintf(BLS, "at VLB slot %d\n", p->pci_device_fn);
+ break;
+ case AHC_EISA:
+ size += sprintf(BLS, "at EISA slot %d\n", p->pci_device_fn);
+ break;
+ default:
+ size += sprintf(BLS, "at PCI %d/%d/%d\n", p->pci_bus,
+ PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
+ break;
+ }
if( !(p->maddr) )
{
size += sprintf(BLS, " Programmed I/O Base: %lx\n", p->base);
{
size += sprintf(BLS, " BIOS Memory Address: 0x%08x\n", p->bios_address);
}
- if( p->chip & AHC_PCI )
- {
- size += sprintf(BLS, " PCI Bus 0x%02x Device 0x%02x\n", p->pci_bus,
- p->pci_device_fn);
- }
size += sprintf(BLS, " Adapter SEEPROM Config: %s\n",
(p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
#define BRDRW 0x04
#define BRDRW_ULTRA2 0x02
#define BRDCTL1 0x02
-#define BRDSTB_ULTRA2 0x01
#define BRDCTL0 0x01
+#define BRDSTB_ULTRA2 0x01
#define SEECTL 0x1e
#define EXTARBACK 0x80
#define RESIDUAL 0x81
#define BAD_STATUS 0x71
#define REJECT_MSG 0x61
-#define ABORT_REQUESTED 0x51
+#define WIDE_RESIDUE 0x51
#define EXTENDED_MSG 0x41
#define NO_MATCH 0x31
#define NO_IDENT 0x21
#define TARGCRCENDEN 0x08
#define TARGCRCCNTEN 0x04
+#define QOUTCNT 0x9e
+
#define SCSIPHASE 0x9e
#define SP_STATUS 0x20
#define SP_COMMAND 0x10
#define SP_DATA_IN 0x02
#define SP_DATA_OUT 0x01
-#define QOUTCNT 0x9e
-
#define SFUNCT 0x9f
#define ALT_MODE 0x80
#define RD_DFTHRSH_63 0x03
#define RD_DFTHRSH_50 0x02
#define RD_DFTHRSH_25 0x01
-#define WR_DFTHRSH_MIN 0x00
#define RD_DFTHRSH_MIN 0x00
+#define WR_DFTHRSH_MIN 0x00
#define SG_CACHEPTR 0xfc
#define SG_USER_DATA 0xfc
#define LAST_SEG_DONE 0x01
+#define CMD_GROUP_CODE_SHIFT 0x05
+#define BUS_8_BIT 0x00
+#define QOUTFIFO_OFFSET 0x01
+#define CCSGRAM_MAXSEGS 0x10
#define CMD_GROUP2_BYTE_DELTA 0xfa
#define MAX_OFFSET_8BIT 0x0f
#define BUS_16_BIT 0x01
#define QINFIFO_OFFSET 0x02
#define CMD_GROUP5_BYTE_DELTA 0x0b
-#define CMD_GROUP_CODE_SHIFT 0x05
#define MAX_OFFSET_ULTRA2 0x7f
#define MAX_OFFSET_16BIT 0x08
-#define BUS_8_BIT 0x00
-#define QOUTFIFO_OFFSET 0x01
#define UNTAGGEDSCB_OFFSET 0x00
-#define CCSGRAM_MAXSEGS 0x10
#define SCB_LIST_NULL 0xff
#define SG_SIZEOF 0x08
#define CMD_GROUP4_BYTE_DELTA 0x04
0x12, 0x6a, 0x00, 0x00,
0xff, 0x6a, 0xd6, 0x09,
0xff, 0x6a, 0xdc, 0x09,
- 0x00, 0x65, 0x42, 0x59,
+ 0x00, 0x65, 0x44, 0x59,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x4e, 0xc8, 0x08,
0xbf, 0x60, 0xc0, 0x08,
- 0x60, 0x0b, 0x86, 0x68,
+ 0x60, 0x0b, 0x88, 0x68,
0x40, 0x00, 0x0e, 0x68,
0x08, 0x1f, 0x3e, 0x10,
- 0x60, 0x0b, 0x86, 0x68,
+ 0x60, 0x0b, 0x88, 0x68,
0x40, 0x00, 0x0e, 0x68,
0x08, 0x1f, 0x3e, 0x10,
0xff, 0x3e, 0x4a, 0x60,
0x00, 0x4d, 0x12, 0x70,
0x01, 0x4e, 0x9c, 0x18,
0xbf, 0x60, 0xc0, 0x08,
- 0x00, 0x6a, 0xa8, 0x5c,
+ 0x00, 0x6a, 0xbe, 0x5c,
0xff, 0x4e, 0xc8, 0x18,
- 0x02, 0x6a, 0xbe, 0x5b,
+ 0x02, 0x6a, 0xd4, 0x5b,
0xff, 0x52, 0x20, 0x09,
0x0d, 0x6a, 0x6a, 0x00,
- 0x00, 0x52, 0x34, 0x5c,
+ 0x00, 0x52, 0x4a, 0x5c,
0x03, 0xb0, 0x52, 0x31,
0xff, 0xb0, 0x52, 0x09,
0xff, 0xb1, 0x54, 0x09,
0xf0, 0xa1, 0xc8, 0x08,
0x0f, 0x05, 0x0a, 0x08,
0x00, 0x05, 0x0a, 0x00,
+ 0xff, 0x6a, 0x0c, 0x08,
0x5a, 0x6a, 0x00, 0x04,
0x12, 0x65, 0x02, 0x00,
0x31, 0x6a, 0xca, 0x00,
- 0x80, 0x37, 0x6e, 0x68,
+ 0x80, 0x37, 0x70, 0x68,
0xff, 0x65, 0xca, 0x18,
0xff, 0x37, 0xdc, 0x08,
0xff, 0x6e, 0xc8, 0x08,
- 0x00, 0x6c, 0x76, 0x78,
+ 0x00, 0x6c, 0x78, 0x78,
0x20, 0x01, 0x02, 0x00,
0x4c, 0x37, 0xc8, 0x28,
- 0x08, 0x1f, 0x7e, 0x78,
+ 0x08, 0x1f, 0x80, 0x78,
0x08, 0x37, 0x6e, 0x00,
0x08, 0x64, 0xc8, 0x00,
0x70, 0x64, 0xca, 0x18,
0xff, 0x6c, 0x0a, 0x08,
0x20, 0x64, 0xca, 0x18,
0xff, 0x6c, 0x08, 0x0c,
- 0x40, 0x0b, 0x0e, 0x69,
- 0x80, 0x0b, 0x00, 0x79,
+ 0x40, 0x0b, 0x10, 0x69,
+ 0x80, 0x0b, 0x02, 0x79,
0xa4, 0x6a, 0x06, 0x00,
0x40, 0x6a, 0x16, 0x00,
- 0x10, 0x03, 0xfc, 0x78,
+ 0x10, 0x03, 0xfe, 0x78,
0xff, 0x50, 0xc8, 0x08,
0x88, 0x6a, 0xcc, 0x00,
- 0x49, 0x6a, 0x24, 0x5c,
+ 0x49, 0x6a, 0x3a, 0x5c,
0x01, 0x6a, 0x26, 0x01,
0xff, 0x6a, 0xca, 0x08,
0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0x9c, 0x78,
+ 0x02, 0x0b, 0x9e, 0x78,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x06, 0xcc, 0x08,
0xff, 0x66, 0x32, 0x09,
0x01, 0x65, 0xca, 0x18,
- 0x80, 0x66, 0xaa, 0x78,
+ 0x80, 0x66, 0xac, 0x78,
0xff, 0x66, 0xa2, 0x08,
- 0x10, 0x03, 0x9a, 0x68,
+ 0x10, 0x03, 0x9c, 0x68,
0xfc, 0x65, 0xc8, 0x18,
- 0x00, 0x65, 0xb2, 0x48,
+ 0x00, 0x65, 0xb4, 0x48,
0xff, 0x6a, 0x32, 0x01,
0x01, 0x64, 0x18, 0x19,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x84, 0x6a, 0x06, 0x00,
0x08, 0x01, 0x02, 0x00,
- 0x02, 0x0b, 0xbc, 0x78,
+ 0x02, 0x0b, 0xbe, 0x78,
0xff, 0x06, 0xc8, 0x08,
0xff, 0x64, 0x32, 0x09,
0xff, 0x6a, 0xca, 0x08,
0x0b, 0x65, 0xca, 0x18,
0xff, 0x65, 0xc8, 0x08,
0x00, 0x8c, 0x18, 0x19,
- 0x02, 0x0b, 0xd8, 0x78,
- 0x01, 0x65, 0xde, 0x60,
+ 0x02, 0x0b, 0xda, 0x78,
+ 0x01, 0x65, 0xe0, 0x60,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x06, 0x32, 0x09,
0xff, 0x65, 0xca, 0x18,
- 0xff, 0x65, 0xd8, 0x68,
+ 0xff, 0x65, 0xda, 0x68,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x9a, 0x5c,
- 0x40, 0x51, 0xf0, 0x78,
+ 0x00, 0x65, 0xb0, 0x5c,
+ 0x40, 0x51, 0xf2, 0x78,
0xe4, 0x6a, 0x06, 0x00,
0x08, 0x01, 0x02, 0x00,
- 0x04, 0x6a, 0x56, 0x5b,
+ 0x04, 0x6a, 0x6c, 0x5b,
0x01, 0x50, 0xa0, 0x18,
- 0x00, 0x50, 0xf6, 0xe0,
+ 0x00, 0x50, 0xf8, 0xe0,
0xff, 0x6a, 0xa0, 0x08,
0xff, 0x6a, 0x3a, 0x01,
0x02, 0x6a, 0x22, 0x01,
- 0x40, 0x51, 0xfc, 0x68,
+ 0x40, 0x51, 0xfe, 0x68,
0xff, 0x6a, 0x06, 0x08,
0x00, 0x65, 0x0e, 0x40,
0x20, 0x6a, 0x16, 0x00,
0xf0, 0x19, 0x6e, 0x08,
0x08, 0x6a, 0x18, 0x00,
0x08, 0x11, 0x22, 0x00,
- 0x08, 0x6a, 0x66, 0x58,
+ 0x08, 0x6a, 0x68, 0x58,
0x08, 0x6a, 0x68, 0x00,
- 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x24, 0x41,
0x12, 0x6a, 0x00, 0x00,
0x40, 0x6a, 0x16, 0x00,
0xff, 0x3e, 0x20, 0x09,
0xff, 0xa1, 0x6e, 0x08,
0x08, 0x6a, 0x18, 0x00,
0x08, 0x11, 0x22, 0x00,
- 0x08, 0x6a, 0x66, 0x58,
+ 0x08, 0x6a, 0x68, 0x58,
0x80, 0x6a, 0x68, 0x00,
0x80, 0x36, 0x6c, 0x00,
- 0x00, 0x65, 0x08, 0x5c,
+ 0x00, 0x65, 0x1e, 0x5c,
0xff, 0x3d, 0xc8, 0x08,
- 0xbf, 0x64, 0x5a, 0x79,
- 0x80, 0x64, 0x20, 0x72,
- 0xa0, 0x64, 0x50, 0x72,
- 0xc0, 0x64, 0x48, 0x72,
- 0xe0, 0x64, 0x90, 0x72,
+ 0xbf, 0x64, 0x5c, 0x79,
+ 0x80, 0x64, 0x24, 0x72,
+ 0xa0, 0x64, 0x54, 0x72,
+ 0xc0, 0x64, 0x4c, 0x72,
+ 0xe0, 0x64, 0x94, 0x72,
0x01, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x24, 0x41,
0xf7, 0x11, 0x22, 0x08,
- 0x00, 0x65, 0x42, 0x59,
+ 0x00, 0x65, 0x44, 0x59,
0xff, 0x06, 0xd4, 0x08,
0xf7, 0x01, 0x02, 0x08,
- 0x09, 0x0c, 0x3c, 0x79,
+ 0x09, 0x0c, 0x3e, 0x79,
0x08, 0x0c, 0x0e, 0x68,
0x01, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0x26, 0x09,
0x03, 0xa9, 0x18, 0x31,
0x03, 0xa9, 0x10, 0x30,
0x08, 0x6a, 0xcc, 0x00,
- 0xa9, 0x6a, 0x1e, 0x5c,
- 0x00, 0x65, 0x7a, 0x41,
+ 0xa9, 0x6a, 0x34, 0x5c,
+ 0x00, 0x65, 0x7c, 0x41,
0xa8, 0x6a, 0x6a, 0x00,
0x79, 0x6a, 0x6a, 0x00,
- 0x40, 0x3d, 0x62, 0x69,
+ 0x40, 0x3d, 0x64, 0x69,
0x04, 0x35, 0x6a, 0x00,
- 0x00, 0x65, 0x78, 0x5b,
+ 0x00, 0x65, 0x8e, 0x5b,
0x80, 0x6a, 0xd4, 0x01,
- 0x10, 0x36, 0x4e, 0x69,
+ 0x10, 0x36, 0x50, 0x69,
0x10, 0x36, 0x6c, 0x00,
0x07, 0xac, 0x10, 0x31,
0x03, 0x8c, 0x10, 0x30,
0x05, 0xa3, 0x70, 0x30,
0x88, 0x6a, 0xcc, 0x00,
- 0xac, 0x6a, 0x16, 0x5c,
- 0x00, 0x65, 0x10, 0x5c,
+ 0xac, 0x6a, 0x2c, 0x5c,
+ 0x00, 0x65, 0x26, 0x5c,
0x38, 0x6a, 0xcc, 0x00,
- 0xa3, 0x6a, 0x1a, 0x5c,
- 0xff, 0x38, 0x8a, 0x69,
+ 0xa3, 0x6a, 0x30, 0x5c,
+ 0xff, 0x38, 0x8c, 0x69,
0x80, 0x02, 0x04, 0x00,
0xe7, 0x35, 0x6a, 0x08,
0x03, 0x69, 0x18, 0x31,
0xff, 0x6a, 0x10, 0x00,
0xff, 0x6a, 0x12, 0x00,
0xff, 0x6a, 0x14, 0x00,
- 0x01, 0x38, 0x8e, 0x61,
+ 0x01, 0x38, 0x92, 0x61,
0xbf, 0x35, 0x6a, 0x08,
+ 0x02, 0x6a, 0xf8, 0x01,
0xff, 0x69, 0xca, 0x08,
0xff, 0x35, 0x26, 0x09,
- 0x04, 0x0b, 0x92, 0x69,
- 0x04, 0x0b, 0x9e, 0x69,
- 0x10, 0x0c, 0x94, 0x79,
- 0x04, 0x0b, 0x9c, 0x69,
+ 0x04, 0x0b, 0x96, 0x69,
+ 0x04, 0x0b, 0xa2, 0x69,
+ 0x10, 0x0c, 0x98, 0x79,
+ 0x04, 0x0b, 0xa2, 0x69,
0xff, 0x6a, 0xca, 0x08,
- 0x00, 0x35, 0x60, 0x5b,
- 0x80, 0x02, 0xf2, 0x69,
- 0xff, 0x65, 0xe2, 0x79,
+ 0x00, 0x35, 0x76, 0x5b,
+ 0x80, 0x02, 0xf6, 0x69,
+ 0xff, 0x65, 0xe6, 0x79,
0xff, 0x38, 0x70, 0x18,
- 0xff, 0x38, 0xe2, 0x79,
- 0x80, 0xea, 0xbe, 0x61,
+ 0xff, 0x38, 0xe6, 0x79,
+ 0x80, 0xea, 0xc2, 0x61,
0xef, 0x38, 0xc8, 0x18,
0x80, 0x6a, 0xc8, 0x00,
- 0x00, 0x65, 0xb0, 0x49,
+ 0x00, 0x65, 0xb4, 0x49,
0x33, 0x38, 0xc8, 0x28,
0xff, 0x64, 0xd0, 0x09,
0x04, 0x39, 0xc0, 0x31,
0x09, 0x6a, 0xd6, 0x01,
- 0x80, 0xeb, 0xb6, 0x79,
+ 0x80, 0xeb, 0xba, 0x79,
0xf7, 0xeb, 0xd6, 0x09,
- 0x08, 0xeb, 0xba, 0x69,
+ 0x08, 0xeb, 0xbe, 0x69,
0x01, 0x6a, 0xd6, 0x01,
0x08, 0xe9, 0x10, 0x31,
0x03, 0x8c, 0x10, 0x30,
0x88, 0x6a, 0xcc, 0x00,
- 0x39, 0x6a, 0x1c, 0x5c,
+ 0x39, 0x6a, 0x32, 0x5c,
0x08, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x0d, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x9a, 0x5c,
- 0x88, 0x6a, 0x8a, 0x5c,
- 0x00, 0x65, 0x10, 0x5c,
+ 0x00, 0x65, 0xb0, 0x5c,
+ 0x88, 0x6a, 0xa0, 0x5c,
+ 0x00, 0x65, 0x26, 0x5c,
0xff, 0x6a, 0xc8, 0x08,
0x08, 0x39, 0x72, 0x18,
0x00, 0x3a, 0x74, 0x20,
- 0x01, 0x0c, 0xda, 0x79,
- 0x10, 0x0c, 0x7a, 0x79,
+ 0x01, 0x0c, 0xde, 0x79,
+ 0x10, 0x0c, 0x7c, 0x79,
0xff, 0x35, 0x26, 0x09,
- 0x04, 0x0b, 0xe0, 0x69,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x04, 0x0b, 0xe4, 0x69,
+ 0x00, 0x65, 0xfe, 0x59,
0x03, 0x08, 0x52, 0x31,
0xff, 0x38, 0x50, 0x09,
0xff, 0x08, 0x52, 0x09,
0xff, 0x09, 0x54, 0x09,
0xff, 0x0a, 0x56, 0x09,
0xff, 0x38, 0x50, 0x09,
- 0x00, 0x65, 0x22, 0x41,
- 0x00, 0x65, 0xfa, 0x59,
+ 0x00, 0x65, 0x24, 0x41,
+ 0x00, 0x65, 0xfe, 0x59,
0x7f, 0x02, 0x04, 0x08,
0xe1, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x22, 0x41,
- 0x04, 0x93, 0x10, 0x6a,
+ 0x00, 0x65, 0x24, 0x41,
+ 0x04, 0x93, 0x14, 0x6a,
0xdf, 0x93, 0x26, 0x09,
- 0x20, 0x93, 0xfe, 0x69,
+ 0x20, 0x93, 0x02, 0x6a,
0x02, 0x93, 0x26, 0x01,
- 0x01, 0x94, 0x00, 0x7a,
- 0x01, 0x94, 0x00, 0x7a,
- 0x01, 0x94, 0x00, 0x7a,
- 0x01, 0x94, 0x00, 0x7a,
- 0x01, 0x94, 0x00, 0x7a,
- 0x01, 0x94, 0x00, 0x7a,
- 0x10, 0x94, 0x0e, 0x6a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x01, 0x94, 0x04, 0x7a,
+ 0x10, 0x94, 0x12, 0x6a,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0x12, 0x6a,
+ 0x08, 0x93, 0x16, 0x6a,
0xdf, 0x93, 0x26, 0x09,
- 0x20, 0x93, 0x16, 0x6a,
+ 0x20, 0x93, 0x1a, 0x6a,
0x03, 0x08, 0x52, 0x31,
0xff, 0x38, 0x50, 0x09,
0x12, 0x01, 0x02, 0x00,
0xff, 0x6a, 0xd4, 0x0c,
- 0x00, 0x65, 0x78, 0x5b,
+ 0x00, 0x65, 0x8e, 0x5b,
0x05, 0xb4, 0x10, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x03, 0x8c, 0x10, 0x30,
0x88, 0x6a, 0xcc, 0x00,
- 0xb4, 0x6a, 0x1a, 0x5c,
+ 0xb4, 0x6a, 0x30, 0x5c,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
- 0x00, 0x65, 0x10, 0x5c,
- 0x3d, 0x6a, 0x60, 0x5b,
+ 0x00, 0x65, 0x26, 0x5c,
+ 0x3d, 0x6a, 0x76, 0x5b,
0xac, 0x6a, 0x26, 0x01,
- 0x04, 0x0b, 0x36, 0x6a,
- 0x01, 0x0b, 0x3c, 0x6a,
- 0x10, 0x0c, 0x38, 0x7a,
+ 0x04, 0x0b, 0x3a, 0x6a,
+ 0x04, 0x0b, 0x40, 0x6a,
+ 0x10, 0x0c, 0x3c, 0x7a,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0x3e, 0x6a,
+ 0x08, 0x93, 0x42, 0x6a,
0xdf, 0x93, 0x26, 0x09,
- 0x20, 0x93, 0x42, 0x6a,
+ 0x20, 0x93, 0x46, 0x6a,
0x12, 0x01, 0x02, 0x00,
- 0x00, 0x65, 0x22, 0x41,
- 0x00, 0x65, 0x78, 0x5b,
+ 0x00, 0x65, 0x24, 0x41,
+ 0x00, 0x65, 0x8e, 0x5b,
0xff, 0x06, 0x44, 0x09,
- 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x24, 0x41,
0x10, 0x3d, 0x06, 0x00,
0xff, 0x34, 0xca, 0x08,
- 0x80, 0x65, 0x74, 0x62,
+ 0x80, 0x65, 0x78, 0x62,
0x0f, 0xa1, 0xca, 0x08,
0x07, 0xa1, 0xca, 0x08,
0x40, 0xa0, 0xc8, 0x08,
0x00, 0x65, 0xca, 0x00,
0x80, 0x65, 0xca, 0x00,
- 0x80, 0xa0, 0x64, 0x7a,
+ 0x80, 0xa0, 0x68, 0x7a,
0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0x76, 0x42,
- 0x20, 0xa0, 0x7c, 0x7a,
+ 0x00, 0x65, 0x7a, 0x42,
+ 0x20, 0xa0, 0x80, 0x7a,
0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0x08, 0x5c,
- 0xa0, 0x3d, 0x84, 0x62,
+ 0x00, 0x65, 0x1e, 0x5c,
+ 0xa0, 0x3d, 0x88, 0x62,
0x23, 0xa0, 0x0c, 0x08,
- 0x00, 0x65, 0x08, 0x5c,
- 0xa0, 0x3d, 0x84, 0x62,
- 0x00, 0xb9, 0x7c, 0x42,
- 0xff, 0x65, 0x7c, 0x62,
+ 0x00, 0x65, 0x1e, 0x5c,
+ 0xa0, 0x3d, 0x88, 0x62,
+ 0x00, 0xb9, 0x80, 0x42,
+ 0xff, 0x65, 0x80, 0x62,
0xa1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
- 0x10, 0x51, 0x84, 0x72,
+ 0x10, 0x51, 0x88, 0x72,
0x40, 0x6a, 0x18, 0x00,
0xff, 0x65, 0x0c, 0x08,
- 0x00, 0x65, 0x08, 0x5c,
- 0xa0, 0x3d, 0x4e, 0x72,
+ 0x00, 0x65, 0x1e, 0x5c,
+ 0xa0, 0x3d, 0x52, 0x72,
0x40, 0x6a, 0x18, 0x00,
0xff, 0x34, 0xa6, 0x08,
- 0x80, 0x34, 0x8c, 0x62,
+ 0x80, 0x34, 0x90, 0x62,
0x7f, 0xa0, 0x40, 0x09,
0x08, 0x6a, 0x68, 0x00,
- 0x00, 0x65, 0x22, 0x41,
- 0x64, 0x6a, 0x50, 0x5b,
- 0x80, 0x64, 0x00, 0x6b,
- 0x04, 0x64, 0xe2, 0x72,
- 0x02, 0x64, 0xe8, 0x72,
- 0x00, 0x6a, 0xaa, 0x72,
- 0x03, 0x64, 0xfc, 0x72,
- 0x01, 0x64, 0xde, 0x72,
- 0x07, 0x64, 0x3e, 0x73,
- 0x08, 0x64, 0xa6, 0x72,
+ 0x00, 0x65, 0x24, 0x41,
+ 0x64, 0x6a, 0x66, 0x5b,
+ 0x80, 0x64, 0x06, 0x6b,
+ 0x04, 0x64, 0xe8, 0x72,
+ 0x02, 0x64, 0xee, 0x72,
+ 0x00, 0x6a, 0xb0, 0x72,
+ 0x03, 0x64, 0x02, 0x73,
+ 0x01, 0x64, 0xe4, 0x72,
+ 0x07, 0x64, 0x44, 0x73,
+ 0x08, 0x64, 0xac, 0x72,
+ 0x23, 0x64, 0x48, 0x73,
0x11, 0x6a, 0x22, 0x01,
- 0x07, 0x6a, 0x42, 0x5b,
+ 0x07, 0x6a, 0x58, 0x5b,
0xff, 0x06, 0xd4, 0x08,
- 0x00, 0x65, 0x22, 0x41,
- 0xff, 0xa8, 0xae, 0x6a,
- 0xff, 0xa2, 0xc6, 0x7a,
+ 0x00, 0x65, 0x24, 0x41,
+ 0xff, 0xa8, 0xb4, 0x6a,
+ 0xff, 0xa2, 0xcc, 0x7a,
0x01, 0x6a, 0x6a, 0x00,
- 0x00, 0xb9, 0x34, 0x5c,
- 0xff, 0xa2, 0xc6, 0x7a,
+ 0x00, 0xb9, 0x4a, 0x5c,
+ 0xff, 0xa2, 0xcc, 0x7a,
0x71, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
- 0x40, 0x51, 0xc6, 0x62,
+ 0x40, 0x51, 0xcc, 0x62,
0x0d, 0x6a, 0x6a, 0x00,
- 0x00, 0xb9, 0x34, 0x5c,
+ 0x00, 0xb9, 0x4a, 0x5c,
0xff, 0x3e, 0x74, 0x09,
0xff, 0x90, 0x7c, 0x08,
0x00, 0x65, 0x50, 0x58,
- 0x00, 0x65, 0x34, 0x41,
- 0x20, 0xa0, 0xce, 0x6a,
+ 0x00, 0x65, 0x36, 0x41,
+ 0x20, 0xa0, 0xd4, 0x6a,
0xff, 0x37, 0xc8, 0x08,
- 0x00, 0x6a, 0xde, 0x5b,
- 0xff, 0x6a, 0xf4, 0x5b,
+ 0x00, 0x6a, 0xf4, 0x5b,
+ 0xff, 0x6a, 0x0a, 0x5c,
0xff, 0xf8, 0xc8, 0x08,
0xff, 0x4f, 0xc8, 0x08,
- 0x01, 0x6a, 0xde, 0x5b,
- 0x00, 0xb9, 0xf4, 0x5b,
+ 0x01, 0x6a, 0xf4, 0x5b,
+ 0x00, 0xb9, 0x0a, 0x5c,
0x01, 0x4f, 0x9e, 0x18,
0x02, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0xa2, 0x5c,
- 0x00, 0x65, 0x34, 0x41,
+ 0x00, 0x65, 0xb8, 0x5c,
+ 0x00, 0x65, 0x36, 0x41,
0x41, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x24, 0x41,
0x04, 0xa0, 0x40, 0x01,
- 0x00, 0x65, 0xba, 0x5c,
- 0x00, 0x65, 0x34, 0x41,
- 0x10, 0x36, 0xa6, 0x7a,
+ 0x00, 0x65, 0xd0, 0x5c,
+ 0x00, 0x65, 0x36, 0x41,
+ 0x10, 0x36, 0xac, 0x7a,
0x05, 0x38, 0x46, 0x31,
0x04, 0x14, 0x58, 0x31,
0x03, 0xa9, 0x60, 0x31,
0xa3, 0x6a, 0xcc, 0x00,
- 0x38, 0x6a, 0x1a, 0x5c,
+ 0x38, 0x6a, 0x30, 0x5c,
0xac, 0x6a, 0xcc, 0x00,
- 0x14, 0x6a, 0x1c, 0x5c,
- 0xa9, 0x6a, 0x1e, 0x5c,
- 0x00, 0x65, 0xa6, 0x42,
+ 0x14, 0x6a, 0x32, 0x5c,
+ 0xa9, 0x6a, 0x34, 0x5c,
+ 0x00, 0x65, 0xac, 0x42,
0xef, 0x36, 0x6c, 0x08,
- 0x00, 0x65, 0xa6, 0x42,
+ 0x00, 0x65, 0xac, 0x42,
0x0f, 0x64, 0xc8, 0x08,
0x07, 0x64, 0xc8, 0x08,
0x00, 0x37, 0x6e, 0x00,
0xff, 0x6a, 0xa4, 0x00,
- 0x00, 0x65, 0xae, 0x5b,
- 0xff, 0x51, 0x12, 0x73,
- 0x20, 0x36, 0x1c, 0x7b,
- 0x00, 0x90, 0x9c, 0x5b,
- 0x00, 0x65, 0x1e, 0x43,
+ 0x00, 0x65, 0xc4, 0x5b,
+ 0xff, 0x51, 0x18, 0x73,
+ 0x20, 0x36, 0x22, 0x7b,
+ 0x00, 0x90, 0xb2, 0x5b,
+ 0x00, 0x65, 0x24, 0x43,
0xff, 0x06, 0xd4, 0x08,
- 0x00, 0x65, 0x08, 0x5c,
- 0xe0, 0x3d, 0x38, 0x63,
- 0x20, 0x12, 0x38, 0x63,
- 0x51, 0x6a, 0x46, 0x5b,
- 0x00, 0x65, 0x96, 0x5b,
+ 0x00, 0x65, 0x1e, 0x5c,
+ 0xe0, 0x3d, 0x3e, 0x63,
+ 0x20, 0x12, 0x3e, 0x63,
+ 0x51, 0x6a, 0x5c, 0x5b,
+ 0x00, 0x65, 0xac, 0x5b,
0xff, 0x37, 0xc8, 0x08,
- 0x00, 0xa1, 0x30, 0x63,
- 0x04, 0xa0, 0x30, 0x7b,
+ 0x00, 0xa1, 0x36, 0x63,
+ 0x04, 0xa0, 0x36, 0x7b,
0xfb, 0xa0, 0x40, 0x09,
0x80, 0x36, 0x6c, 0x00,
- 0x80, 0xa0, 0xa6, 0x7a,
+ 0x80, 0xa0, 0xac, 0x7a,
0x7f, 0xa0, 0x40, 0x09,
- 0xff, 0x6a, 0x42, 0x5b,
- 0x00, 0x65, 0xa6, 0x42,
- 0x04, 0xa0, 0x36, 0x7b,
- 0x00, 0x65, 0xba, 0x5c,
- 0x00, 0x65, 0x38, 0x43,
- 0x00, 0x65, 0xa2, 0x5c,
+ 0xff, 0x6a, 0x58, 0x5b,
+ 0x00, 0x65, 0xac, 0x42,
+ 0x04, 0xa0, 0x3c, 0x7b,
+ 0x00, 0x65, 0xd0, 0x5c,
+ 0x00, 0x65, 0x3e, 0x43,
+ 0x00, 0x65, 0xb8, 0x5c,
0x31, 0x6a, 0x22, 0x01,
- 0x0c, 0x6a, 0x42, 0x5b,
- 0x00, 0x65, 0xa6, 0x42,
+ 0x0c, 0x6a, 0x58, 0x5b,
+ 0x00, 0x65, 0xac, 0x42,
0x61, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0xa6, 0x42,
+ 0x00, 0x65, 0xac, 0x42,
+ 0x51, 0x6a, 0x5c, 0x5b,
+ 0xff, 0xa8, 0x54, 0x6b,
+ 0xff, 0xa9, 0x54, 0x6b,
+ 0xff, 0xaa, 0x54, 0x6b,
+ 0xff, 0xab, 0x54, 0x6b,
+ 0x00, 0x65, 0xac, 0x42,
+ 0x51, 0x6a, 0x22, 0x01,
+ 0x00, 0x65, 0xac, 0x42,
0x10, 0x3d, 0x06, 0x00,
0xff, 0x65, 0x68, 0x0c,
0xff, 0x06, 0xd4, 0x08,
- 0x01, 0x0c, 0x48, 0x7b,
- 0x04, 0x0c, 0x48, 0x6b,
+ 0x01, 0x0c, 0x5e, 0x7b,
+ 0x04, 0x0c, 0x60, 0x6b,
0xe0, 0x03, 0x7a, 0x08,
- 0xe0, 0x3d, 0x5c, 0x63,
+ 0xe0, 0x3d, 0x72, 0x63,
0xff, 0x65, 0xcc, 0x08,
0xff, 0x12, 0xda, 0x0c,
0xff, 0x06, 0xd4, 0x0c,
0xff, 0x65, 0x0c, 0x08,
- 0x02, 0x0b, 0x58, 0x7b,
+ 0x02, 0x0b, 0x6e, 0x7b,
0xff, 0x6a, 0xd4, 0x0c,
0xd1, 0x6a, 0x22, 0x01,
- 0x00, 0x65, 0x22, 0x41,
+ 0x00, 0x65, 0x24, 0x41,
0xff, 0x65, 0x26, 0x09,
- 0x01, 0x0b, 0x70, 0x6b,
- 0x10, 0x0c, 0x62, 0x7b,
- 0x04, 0x0b, 0x6a, 0x6b,
+ 0x01, 0x0b, 0x86, 0x6b,
+ 0x10, 0x0c, 0x78, 0x7b,
+ 0x04, 0x0b, 0x80, 0x6b,
0xff, 0x6a, 0xca, 0x08,
- 0x04, 0x93, 0x6e, 0x6b,
- 0x01, 0x94, 0x6c, 0x7b,
- 0x10, 0x94, 0x6e, 0x6b,
+ 0x04, 0x93, 0x84, 0x6b,
+ 0x01, 0x94, 0x82, 0x7b,
+ 0x10, 0x94, 0x84, 0x6b,
0xc7, 0x93, 0x26, 0x09,
0xff, 0x99, 0xd4, 0x08,
- 0x38, 0x93, 0x72, 0x6b,
+ 0x38, 0x93, 0x88, 0x6b,
0xff, 0x6a, 0xd4, 0x0c,
- 0x80, 0x36, 0x76, 0x6b,
+ 0x80, 0x36, 0x8c, 0x6b,
0x21, 0x6a, 0x22, 0x05,
0xff, 0x65, 0x20, 0x09,
- 0xff, 0x51, 0x84, 0x63,
+ 0xff, 0x51, 0x9a, 0x63,
0xff, 0x37, 0xc8, 0x08,
- 0xa1, 0x6a, 0x90, 0x43,
+ 0xa1, 0x6a, 0xa6, 0x43,
0xff, 0x51, 0xc8, 0x08,
- 0xb9, 0x6a, 0x90, 0x43,
+ 0xb9, 0x6a, 0xa6, 0x43,
0xff, 0x90, 0xa4, 0x08,
- 0xff, 0xba, 0x94, 0x73,
+ 0xff, 0xba, 0xaa, 0x73,
0xff, 0xba, 0x20, 0x09,
0xff, 0x65, 0xca, 0x18,
- 0x00, 0x6c, 0x88, 0x63,
+ 0x00, 0x6c, 0x9e, 0x63,
0xff, 0x90, 0xca, 0x0c,
0xff, 0x6a, 0xca, 0x04,
- 0x20, 0x36, 0xa8, 0x7b,
- 0x00, 0x90, 0x7c, 0x5b,
- 0xff, 0x65, 0xa8, 0x73,
- 0xff, 0x52, 0xa6, 0x73,
+ 0x20, 0x36, 0xbe, 0x7b,
+ 0x00, 0x90, 0x92, 0x5b,
+ 0xff, 0x65, 0xbe, 0x73,
+ 0xff, 0x52, 0xbc, 0x73,
0xff, 0xba, 0xcc, 0x08,
0xff, 0x52, 0x20, 0x09,
0xff, 0x66, 0x74, 0x09,
0xff, 0x65, 0x20, 0x0d,
0xff, 0xba, 0x7e, 0x0c,
- 0x00, 0x6a, 0xa8, 0x5c,
+ 0x00, 0x6a, 0xbe, 0x5c,
0x0d, 0x6a, 0x6a, 0x00,
- 0x00, 0x51, 0x34, 0x44,
- 0xff, 0x3f, 0x02, 0x74,
+ 0x00, 0x51, 0x4a, 0x44,
+ 0xff, 0x3f, 0x18, 0x74,
0xff, 0x6a, 0xa2, 0x00,
- 0x00, 0x3f, 0x7c, 0x5b,
- 0xff, 0x65, 0x02, 0x74,
+ 0x00, 0x3f, 0x92, 0x5b,
+ 0xff, 0x65, 0x18, 0x74,
0x20, 0x36, 0x6c, 0x00,
- 0x20, 0xa0, 0xbc, 0x6b,
+ 0x20, 0xa0, 0xd2, 0x6b,
0xff, 0xb9, 0xa2, 0x0c,
0xff, 0x6a, 0xa2, 0x04,
0xff, 0x65, 0xa4, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
- 0x45, 0x6a, 0x28, 0x5c,
+ 0x45, 0x6a, 0x3e, 0x5c,
0x01, 0x6a, 0xd0, 0x01,
0x09, 0x6a, 0xd6, 0x01,
- 0x80, 0xeb, 0xc8, 0x7b,
+ 0x80, 0xeb, 0xde, 0x7b,
0x01, 0x6a, 0xd6, 0x01,
0x01, 0xe9, 0xa4, 0x34,
0x88, 0x6a, 0xcc, 0x00,
- 0x45, 0x6a, 0x28, 0x5c,
+ 0x45, 0x6a, 0x3e, 0x5c,
0x01, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x0d, 0x6a, 0x26, 0x01,
- 0x00, 0x65, 0x9a, 0x5c,
+ 0x00, 0x65, 0xb0, 0x5c,
0xff, 0x99, 0xa4, 0x0c,
0xff, 0x65, 0xa4, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
- 0x45, 0x6a, 0x28, 0x5c,
+ 0x45, 0x6a, 0x3e, 0x5c,
0x01, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x05,
0x88, 0x6a, 0xcc, 0x00,
- 0x45, 0x6a, 0x28, 0x5c,
+ 0x45, 0x6a, 0x3e, 0x5c,
0x01, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x01, 0x6a, 0x26, 0x05,
0x01, 0x65, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0xf8, 0x7b,
+ 0x80, 0xee, 0x0e, 0x7c,
0xff, 0x6a, 0xdc, 0x0d,
0xff, 0x65, 0x32, 0x09,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x9a, 0x44,
+ 0x00, 0x65, 0xb0, 0x44,
0xff, 0x37, 0xc8, 0x08,
- 0x00, 0x6a, 0xbe, 0x5b,
+ 0x00, 0x6a, 0xd4, 0x5b,
0xff, 0x52, 0xa2, 0x0c,
- 0x01, 0x0c, 0x08, 0x7c,
- 0x04, 0x0c, 0x08, 0x6c,
+ 0x01, 0x0c, 0x1e, 0x7c,
+ 0x04, 0x0c, 0x1e, 0x6c,
0xe0, 0x03, 0x06, 0x08,
0xe0, 0x03, 0x7a, 0x0c,
0xff, 0x8c, 0x10, 0x08,
0x00, 0x6c, 0xda, 0x24,
0xff, 0x65, 0xc8, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
- 0x41, 0x6a, 0x24, 0x5c,
+ 0x41, 0x6a, 0x3a, 0x5c,
0xff, 0x90, 0xe2, 0x09,
0x20, 0x6a, 0xd0, 0x01,
- 0x04, 0x35, 0x46, 0x7c,
+ 0x04, 0x35, 0x5c, 0x7c,
0x1d, 0x6a, 0xdc, 0x01,
- 0xdc, 0xee, 0x42, 0x64,
- 0x00, 0x65, 0x52, 0x44,
+ 0xdc, 0xee, 0x58, 0x64,
+ 0x00, 0x65, 0x68, 0x44,
0x01, 0x6a, 0xdc, 0x01,
0x20, 0xa0, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
- 0x80, 0xee, 0x4c, 0x7c,
+ 0x80, 0xee, 0x62, 0x7c,
0x19, 0x6a, 0xdc, 0x01,
- 0xd8, 0xee, 0x50, 0x64,
+ 0xd8, 0xee, 0x66, 0x64,
0xff, 0x6a, 0xdc, 0x09,
- 0x18, 0xee, 0x54, 0x6c,
+ 0x18, 0xee, 0x6a, 0x6c,
0xff, 0x6a, 0xd4, 0x0c,
0x88, 0x6a, 0xcc, 0x00,
- 0x41, 0x6a, 0x24, 0x5c,
+ 0x41, 0x6a, 0x3a, 0x5c,
0x20, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0xff, 0x35, 0x26, 0x09,
- 0x04, 0x35, 0x7e, 0x6c,
+ 0x04, 0x35, 0x94, 0x6c,
0xa0, 0x6a, 0xca, 0x00,
0x20, 0x65, 0xc8, 0x18,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
- 0x00, 0x65, 0x6a, 0x64,
+ 0x00, 0x65, 0x80, 0x64,
0x0a, 0x93, 0x26, 0x01,
- 0x00, 0x65, 0x9a, 0x5c,
- 0x04, 0x35, 0x76, 0x7b,
- 0xa0, 0x6a, 0x8a, 0x5c,
- 0x00, 0x65, 0x8c, 0x5c,
- 0x00, 0x65, 0x8c, 0x5c,
- 0x00, 0x65, 0x8c, 0x44,
+ 0x00, 0x65, 0xb0, 0x5c,
+ 0x04, 0x35, 0x8c, 0x7b,
+ 0xa0, 0x6a, 0xa0, 0x5c,
+ 0x00, 0x65, 0xa2, 0x5c,
+ 0x00, 0x65, 0xa2, 0x5c,
+ 0x00, 0x65, 0xa2, 0x44,
0xff, 0x65, 0xcc, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x0c,
- 0x08, 0x94, 0x9a, 0x7c,
+ 0x08, 0x94, 0xb0, 0x7c,
0xf7, 0x93, 0x26, 0x09,
- 0x08, 0x93, 0x9e, 0x6c,
+ 0x08, 0x93, 0xb4, 0x6c,
0xff, 0x6a, 0xd4, 0x0c,
0xff, 0x40, 0x74, 0x09,
0xff, 0x90, 0x80, 0x08,
0xff, 0x6a, 0x72, 0x05,
- 0xff, 0x40, 0xb6, 0x64,
- 0xff, 0x3f, 0xae, 0x64,
+ 0xff, 0x40, 0xcc, 0x64,
+ 0xff, 0x3f, 0xc4, 0x64,
0xff, 0x6a, 0xca, 0x04,
0xff, 0x3f, 0x20, 0x09,
0x01, 0x6a, 0x6a, 0x00,
- 0x00, 0xb9, 0x34, 0x5c,
+ 0x00, 0xb9, 0x4a, 0x5c,
0xff, 0xba, 0x7e, 0x0c,
0xff, 0x40, 0x20, 0x09,
0xff, 0xba, 0x80, 0x0c,
{ aic7xxx_patch4_func, 40, 4, 1 },
{ aic7xxx_patch8_func, 44, 3, 2 },
{ aic7xxx_patch0_func, 47, 3, 1 },
- { aic7xxx_patch9_func, 52, 7, 1 },
- { aic7xxx_patch4_func, 60, 3, 1 },
- { aic7xxx_patch8_func, 63, 2, 1 },
- { aic7xxx_patch1_func, 68, 60, 1 },
- { aic7xxx_patch8_func, 162, 1, 2 },
- { aic7xxx_patch0_func, 163, 2, 1 },
- { aic7xxx_patch2_func, 167, 3, 3 },
- { aic7xxx_patch8_func, 167, 2, 1 },
- { aic7xxx_patch0_func, 170, 2, 1 },
- { aic7xxx_patch8_func, 173, 1, 2 },
- { aic7xxx_patch0_func, 174, 1, 1 },
- { aic7xxx_patch2_func, 178, 1, 1 },
- { aic7xxx_patch2_func, 181, 3, 2 },
- { aic7xxx_patch0_func, 184, 5, 1 },
- { aic7xxx_patch2_func, 192, 2, 3 },
- { aic7xxx_patch8_func, 192, 1, 1 },
- { aic7xxx_patch0_func, 194, 3, 1 },
- { aic7xxx_patch10_func, 197, 2, 1 },
- { aic7xxx_patch8_func, 199, 7, 2 },
- { aic7xxx_patch0_func, 206, 1, 1 },
- { aic7xxx_patch2_func, 211, 14, 3 },
- { aic7xxx_patch10_func, 224, 1, 1 },
- { aic7xxx_patch0_func, 225, 9, 1 },
- { aic7xxx_patch8_func, 239, 2, 1 },
- { aic7xxx_patch8_func, 241, 1, 1 },
- { aic7xxx_patch10_func, 242, 6, 3 },
- { aic7xxx_patch2_func, 242, 2, 2 },
- { aic7xxx_patch0_func, 244, 4, 1 },
- { aic7xxx_patch8_func, 249, 1, 1 },
- { aic7xxx_patch8_func, 253, 19, 1 },
- { aic7xxx_patch2_func, 273, 3, 3 },
- { aic7xxx_patch10_func, 275, 1, 1 },
- { aic7xxx_patch0_func, 276, 5, 1 },
- { aic7xxx_patch10_func, 281, 1, 2 },
- { aic7xxx_patch0_func, 282, 9, 1 },
- { aic7xxx_patch11_func, 298, 1, 2 },
- { aic7xxx_patch0_func, 299, 1, 1 },
- { aic7xxx_patch5_func, 359, 1, 2 },
- { aic7xxx_patch0_func, 360, 1, 1 },
- { aic7xxx_patch3_func, 363, 1, 1 },
- { aic7xxx_patch2_func, 373, 3, 2 },
- { aic7xxx_patch0_func, 376, 5, 1 },
- { aic7xxx_patch11_func, 384, 1, 2 },
- { aic7xxx_patch0_func, 385, 1, 1 },
- { aic7xxx_patch6_func, 390, 1, 1 },
- { aic7xxx_patch1_func, 427, 3, 1 },
- { aic7xxx_patch10_func, 432, 11, 1 },
- { aic7xxx_patch2_func, 480, 7, 2 },
- { aic7xxx_patch0_func, 487, 8, 1 },
- { aic7xxx_patch2_func, 496, 4, 2 },
- { aic7xxx_patch0_func, 500, 6, 1 },
- { aic7xxx_patch2_func, 506, 4, 2 },
- { aic7xxx_patch0_func, 510, 3, 1 },
- { aic7xxx_patch12_func, 520, 10, 1 },
- { aic7xxx_patch2_func, 539, 17, 4 },
- { aic7xxx_patch13_func, 547, 4, 2 },
- { aic7xxx_patch0_func, 551, 2, 1 },
- { aic7xxx_patch0_func, 556, 33, 1 },
- { aic7xxx_patch12_func, 589, 4, 1 },
- { aic7xxx_patch6_func, 593, 2, 1 },
- { aic7xxx_patch6_func, 596, 9, 1 },
+ { aic7xxx_patch9_func, 53, 7, 1 },
+ { aic7xxx_patch4_func, 61, 3, 1 },
+ { aic7xxx_patch8_func, 64, 2, 1 },
+ { aic7xxx_patch1_func, 69, 60, 1 },
+ { aic7xxx_patch8_func, 163, 1, 2 },
+ { aic7xxx_patch0_func, 164, 2, 1 },
+ { aic7xxx_patch2_func, 168, 3, 4 },
+ { aic7xxx_patch8_func, 168, 2, 2 },
+ { aic7xxx_patch0_func, 170, 1, 1 },
+ { aic7xxx_patch0_func, 171, 2, 1 },
+ { aic7xxx_patch8_func, 174, 1, 2 },
+ { aic7xxx_patch0_func, 175, 1, 1 },
+ { aic7xxx_patch2_func, 179, 1, 1 },
+ { aic7xxx_patch2_func, 182, 3, 2 },
+ { aic7xxx_patch0_func, 185, 5, 1 },
+ { aic7xxx_patch2_func, 193, 2, 3 },
+ { aic7xxx_patch8_func, 193, 1, 1 },
+ { aic7xxx_patch0_func, 195, 3, 1 },
+ { aic7xxx_patch10_func, 199, 1, 2 },
+ { aic7xxx_patch0_func, 200, 1, 1 },
+ { aic7xxx_patch8_func, 201, 7, 2 },
+ { aic7xxx_patch0_func, 208, 1, 1 },
+ { aic7xxx_patch2_func, 213, 14, 3 },
+ { aic7xxx_patch10_func, 226, 1, 1 },
+ { aic7xxx_patch0_func, 227, 9, 1 },
+ { aic7xxx_patch8_func, 241, 2, 1 },
+ { aic7xxx_patch8_func, 243, 1, 1 },
+ { aic7xxx_patch10_func, 244, 6, 3 },
+ { aic7xxx_patch2_func, 244, 2, 2 },
+ { aic7xxx_patch0_func, 246, 4, 1 },
+ { aic7xxx_patch8_func, 251, 1, 1 },
+ { aic7xxx_patch8_func, 255, 19, 1 },
+ { aic7xxx_patch2_func, 275, 3, 3 },
+ { aic7xxx_patch10_func, 277, 1, 1 },
+ { aic7xxx_patch0_func, 278, 5, 1 },
+ { aic7xxx_patch10_func, 283, 1, 2 },
+ { aic7xxx_patch0_func, 284, 9, 1 },
+ { aic7xxx_patch11_func, 300, 1, 2 },
+ { aic7xxx_patch0_func, 301, 1, 1 },
+ { aic7xxx_patch5_func, 362, 1, 2 },
+ { aic7xxx_patch0_func, 363, 1, 1 },
+ { aic7xxx_patch3_func, 366, 1, 1 },
+ { aic7xxx_patch2_func, 376, 3, 2 },
+ { aic7xxx_patch0_func, 379, 5, 1 },
+ { aic7xxx_patch11_func, 387, 1, 2 },
+ { aic7xxx_patch0_func, 388, 1, 1 },
+ { aic7xxx_patch6_func, 393, 1, 1 },
+ { aic7xxx_patch1_func, 438, 3, 1 },
+ { aic7xxx_patch10_func, 443, 11, 1 },
+ { aic7xxx_patch2_func, 491, 7, 2 },
+ { aic7xxx_patch0_func, 498, 8, 1 },
+ { aic7xxx_patch2_func, 507, 4, 2 },
+ { aic7xxx_patch0_func, 511, 6, 1 },
+ { aic7xxx_patch2_func, 517, 4, 2 },
+ { aic7xxx_patch0_func, 521, 3, 1 },
+ { aic7xxx_patch12_func, 531, 10, 1 },
+ { aic7xxx_patch2_func, 550, 17, 4 },
+ { aic7xxx_patch13_func, 558, 4, 2 },
+ { aic7xxx_patch0_func, 562, 2, 1 },
+ { aic7xxx_patch0_func, 567, 33, 1 },
+ { aic7xxx_patch12_func, 600, 4, 1 },
+ { aic7xxx_patch6_func, 604, 2, 1 },
+ { aic7xxx_patch6_func, 607, 9, 1 },
};
{
tmport += 0x1f;
j = inb(tmport);
+ if((j&0x80)==0)
+ {
+ dev->in_int=0;
+ return;
+ }
tmpcip = dev->pciport;
if ((inb(tmpcip) & 0x08) != 0)
#ifdef CONFIG_SCSI_PLUTO_MODULE
#define SD_EXTRA_DEVS 40
#else
-#define SD_EXTRA_DEVS 4
+#define SD_EXTRA_DEVS 16
#endif
#define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 2
+#define SR_EXTRA_DEVS 4
#define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
#endif
*
* Linux MegaRAID device driver
*
- * Copyright 1999 American Megatrends Inc.
+ * Copyright 1998 American Megatrends Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version : 1.07
+ * Version : 1.04
*
* Description: Linux device driver for AMI MegaRAID controller
*
* The addtional 32 bit field for 64bit address in the newly defined
* mailbox64 structure is set to 0 at this point.
*
- * Version 1.05
- * Changed the queing implementation for handling SCBs and completed
- * commands.
- * Added spinlocks in the interrupt service routine to enable the dirver
- * function in the SMP environment.
- * Fixed the problem of unnecessary aborts in the abort entry point, which
- * also enables the driver to handle large amount of I/O requests for
- * long duration of time.
- *
- * Version 1.07
- * Removed the usage of uaccess.h file for kernel versions less than
- * 2.0.36, as this file is not present in those versions.
- *
* BUGS:
* Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
* fails to detect the controller as a pci device on the system.
#define CRLFSTR "\n"
#define IOCTL_CMD_NEW 0x81
-#define MEGARAID_VERSION "v107 (December 22, 1999)"
-
+#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
-#if LINUX_VERSION_CODE > 0x020024
#include <asm/uaccess.h>
-#endif
#include "sd.h"
#include "scsi.h"
#define MAX_SERBUF 160
#define COM_BASE 0x2f8
+#define ENQUEUE(obj,type,list,next) \
+{ type **node; long cpuflag; \
+ spin_lock_irqsave(&mega_lock,cpuflag);\
+ for(node=&(list); *node; node=(type **)&(*node)->##next); \
+ (*node) = obj; \
+ (*node)->##next = NULL; \
+ spin_unlock_irqrestore(&mega_lock,cpuflag);\
+}
+
+/* a non-locking version (if we already have the lock) */
+#define ENQUEUE_NL(obj,type,list,next) \
+{ type **node; \
+ for(node=&(list); *node; node=(type **)&(*node)->##next); \
+ (*node) = obj; \
+ (*node)->##next = NULL; \
+}
+
+#define DEQUEUE(obj,type,list,next) \
+{ long cpuflag; \
+ spin_lock_irqsave(&mega_lock,cpuflag);\
+ if ((obj=list) != NULL) {\
+ list = (type *)(list)->##next; \
+ } \
+ spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
u32 RDINDOOR (mega_host_config * megaCfg)
{
u_char * mboxData,
mega_scb * scb,
int intr);
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
u32 * buffer, u32 * length);
static int mega_busyWaitMbox(mega_host_config *);
static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (mega_host_config *);
+static void mega_rundoneq (void);
static void mega_cmd_done (mega_host_config *, mega_scb *, int);
static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void mega_freeSgList(mega_host_config *megaCfg);
+static inline void freeSgList(mega_host_config *megaCfg);
static void mega_Convert8ldTo40ld( mega_RAIDINQ *inquiry,
mega_Enquiry3 *enquiry3,
megaRaidProductInfo *productInfo );
-
-
-
-#if LINUX_VERSION_CODE > 0x020100
-# include <asm/spinlock.h>
-# include <linux/smp.h>
-# define cpuid smp_processor_id()
-# if LINUX_VERSION_CODE < 0x020195
-# define DRIVER_LOCK_T unsigned long cpu_flags = 0;
-# define DRIVER_LOCK_INIT(p) \
- spin_lock_init(&p->mega_lock);
-# define DRIVER_LOCK(p) \
- if(!p->cpu_lock_count[cpuid]) { \
- spin_lock_irqsave(&p->mega_lock, cpu_flags); \
- p->cpu_lock_count[cpuid]++; \
- } else { \
- p->cpu_lock_count[cpuid]++; \
- }
-# define DRIVER_UNLOCK(p) \
- if(--p->cpu_lock_count[cpuid] == 0) \
- spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
-# define IO_LOCK(p) spin_lock_irqsave(&io_request_lock,cpu_flags);
-# define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
-# else
-# define DRIVER_LOCK_T
-# define DRIVER_LOCK_INIT(p)
-# define DRIVER_LOCK(p)
-# define DRIVER_UNLOCK(p)
-# define IO_LOCK_T unsigned long io_flags = 0;
-# define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
-# define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
-# endif
-#else
-# define cpuid 0
-# define DRIVER_LOCK_T long cpu_flags;
-# define DRIVER_LOCK_INIT(p)
-# define DRIVER_LOCK(p) \
- save_flags(cpu_flags); \
- cli();
-# define DRIVER_UNLOCK(p) \
- restore_flags(cpu_flags);
-# define IO_LOCK_T unsigned long io_flags = 0;
-# define IO_LOCK(p) DRIVER_LOCK(p)
-# define IO_UNLOCK(p) DRIVER_UNLOCK(p)
-# define le32_to_cpu(x) (x)
-# define cpu_to_le32(x) (x)
-#endif
-
/* set SERDEBUG to 1 to enable serial debugging */
#define SERDEBUG 0
#if SERDEBUG
/* Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
XX scsi id on each channel. Used for Madrona motherboard, where SAF_TE
processor id cannot be scanned */
-
static char *megaraid;
#if LINUX_VERSION_CODE > 0x20100
#ifdef MODULE
static mega_scb *pLastScb = NULL;
+/* Queue of pending/completed SCBs */
+static Scsi_Cmnd *qCompleted = NULL;
#if SERDEBUG
volatile static spinlock_t serial_lock;
#endif
+volatile static spinlock_t mega_lock;
struct proc_dir_entry proc_scsi_megaraid =
{
#define TRACE(A)
#endif
-static void callDone (Scsi_Cmnd * SCpnt)
+void callDone (Scsi_Cmnd * SCpnt)
{
if (SCpnt->result) {
TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
* Free a SCB structure
*=======================
*/
-static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
{
-
- mega_scb *pScbtmp;
-
- if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
- return ;
- }
+ mega_scb **ppScb;
/* Unlink from pending queue */
-
- if(pScb == megaCfg->qPendingH) {
- if(megaCfg->qPendingH == megaCfg->qPendingT )
- megaCfg->qPendingH = megaCfg->qPendingT = NULL;
- else {
- megaCfg->qPendingH = megaCfg->qPendingH->next;
- }
- megaCfg->qPcnt--;
- }
- else {
- for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
- if (pScbtmp->next == pScb) {
- pScbtmp->next = pScb->next;
- if(pScb == megaCfg->qPendingT) {
- megaCfg->qPendingT = pScbtmp;
- }
- megaCfg->qPcnt--;
+ for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
+ if (*ppScb == pScb) {
+ *ppScb = pScb->next;
break;
}
}
- }
- /* Link back into free list */
+ /* Link back into list */
pScb->state = SCB_FREE;
pScb->SCpnt = NULL;
- if(megaCfg->qFreeH == (mega_scb *) NULL ) {
- megaCfg->qFreeH = megaCfg->qFreeT = pScb;
- }
- else {
- megaCfg->qFreeT->next = pScb;
- megaCfg->qFreeT = pScb;
- }
- megaCfg->qFreeT->next = NULL;
- megaCfg->qFcnt++;
-
+ pScb->next = megaCfg->qFree;
+ megaCfg->qFree = pScb;
}
/*===========================
* Allocate a SCB structure
*===========================
*/
-static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
{
mega_scb *pScb;
/* Unlink command from Free List */
- if ((pScb = megaCfg->qFreeH) != NULL) {
- megaCfg->qFreeH = pScb->next;
- megaCfg->qFcnt--;
+ if ((pScb = megaCfg->qFree) != NULL) {
+ megaCfg->qFree = pScb->next;
pScb->isrcount = jiffies;
pScb->next = NULL;
* Initialize SCB structures
*================================================
*/
-static int mega_initSCB (mega_host_config * megaCfg)
+static int initSCB (mega_host_config * megaCfg)
{
int idx;
- megaCfg->qFreeH = NULL;
- megaCfg->qFcnt = 0;
-#if DEBUG
-if(megaCfg->max_cmds >= MAX_COMMANDS) {
-printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
-}
-#endif
-
+ megaCfg->qFree = NULL;
for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
megaCfg->scbList[idx].idx = idx;
megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
GFP_ATOMIC | GFP_DMA);
if (megaCfg->scbList[idx].sgList == NULL) {
printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
- mega_freeSgList(megaCfg);
+ freeSgList(megaCfg);
return -1;
}
if (idx < MAX_COMMANDS) {
/* Link to free list */
- mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
+ freeSCB(megaCfg, &megaCfg->scbList[idx]);
}
}
return 0;
}
/* Run through the list of completed requests */
-static void mega_rundoneq (mega_host_config *megaCfg)
+static void mega_rundoneq ()
{
Scsi_Cmnd *SCpnt;
- while ((SCpnt = megaCfg->qCompletedH) != NULL) {
- megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
- megaCfg->qCcnt--;
+ while (1) {
+ DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ if (SCpnt == NULL)
+ return;
- SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
/* Callback */
callDone (SCpnt);
}
- megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
}
/*
- * Runs through the list of pending requests
- * Assumes that mega_lock spin_lock has been acquired.
- */
+ Runs through the list of pending requests
+ Assumes that mega_lock spin_lock has been acquired.
+*/
static void mega_runpendq(mega_host_config *megaCfg)
{
mega_scb *pScb;
/* Issue any pending commands to the card */
- for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
if (pScb->state == SCB_ACTIVE) {
- if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
- return;
+ megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
}
}
}
/* Add command to the list of completed requests */
-static void
-mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
int status)
{
int islogical;
}
SCpnt = pScb->SCpnt;
+ /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
pthru = &pScb->pthru;
mbox = (mega_mailbox *) &pScb->mboxData;
TRACE(("pScb->idx = ",pScb->idx));
TRACE(("pScb->state = ",pScb->state));
TRACE(("pScb->state = ",pScb->state));
- printk("megaraid:Problem...!\n");
+ printk("Problem...!\n");
while(1);
}
/* not IOCTL_CMD_NEW SCB, freeSCB()*/
/* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
* after copy data back to user space*/
- mega_freeSCB(megaCfg, pScb);
+ freeSCB(megaCfg, pScb);
/* Add Scsi_Command to end of completed queue */
- if( megaCfg->qCompletedH == NULL ) {
- megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
- }
- else {
- megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
- megaCfg->qCompletedT = SCpnt;
- }
- megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
- megaCfg->qCcnt++;
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
}
/*-------------------------------------------------------------------
if ( islogical ) {
lun = (SCpnt->target * 8) + lun;
+#if 1
if ( lun > FC_MAX_LOGICAL_DRIVES ){
SCpnt->result = (DID_BAD_TARGET << 16);
callDone (SCpnt);
return NULL;
}
+#endif
}
/*-----------------------------------------------------
*
case READ_CAPACITY:
case INQUIRY:
/* Allocate a SCB and initialize passthru */
- if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
case READ_10:
case WRITE_10:
/* Allocate a SCB and initialize mailbox */
- if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
}
/* Calculate Scatter-Gather info */
- mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+ mbox->numsgelements = build_sglist (megaCfg, pScb,
(u32 *) & mbox->xferaddr,
(u32 *) & seg);
*-----------------------------------------------------*/
else {
/* Allocate a SCB and initialize passthru */
- if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
pthru->cdblen = SCpnt->cmd_len;
memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
- pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+ pthru->numsgelements = build_sglist (megaCfg, pScb,
(u32 *) & pthru->dataxferaddr,
(u32 *) & pthru->dataxferlen);
unsigned char *data = (unsigned char *)SCpnt->request_buffer;
int i;
- if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
}
+#if 0
+ printk("\nBUF: ");
+ for (i=0;i<18;i++) {
+ printk(" %x",data[i]);
+ }
+ printk("......\n");
+#endif
+
mboxdata = (u8 *) & pScb->mboxData;
mbox = (mega_ioctl_mbox *) & pScb->mboxData;
mailbox = (mega_mailbox *) & pScb->mboxData;
mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
mailbox->xferaddr = virt_to_bus (pthru);
- pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
+ pthru->numsgelements = build_sglist (megaCfg, pScb,
(u32 *) & pthru->dataxferaddr,
(u32 *) & pthru->dataxferlen);
}
/* else normal (nonpassthru) command */
-#if LINUX_VERSION_CODE > 0x020024
-/*
- * usage of the function copy from user is used in case of data more than
- * 4KB. This is used only with adapters which supports more than 8 logical
- * drives. This feature is disabled on kernels earlier or same as 2.0.36
- * as the uaccess.h file is not available with those kernels.
- */
-
if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) {
/* use external data area for large xfers */
/* If cmnd[0] is set to IOCTL_CMD_NEW then *
copy_from_user(kern_area,user_area,xfer_size);
pScb->kern_area = kern_area;
}
-#endif
mbox->cmd = data[0];
mbox->channel = data[1];
}
else {
- mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
+ mbox->numsgelements = build_sglist (megaCfg, pScb,
(u32 *) & mbox->xferaddr,
(u32 *) & seg);
}
#endif
-#if DEBUG
-static unsigned int cum_time = 0;
-static unsigned int cum_time_cnt = 0;
-#endif
-
/*--------------------------------------------------------------------
* Interrupt service routine
*--------------------------------------------------------------------*/
static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
{
-#if LINUX_VERSION_CODE >= 0x20100
- IO_LOCK_T
-#endif
mega_host_config *megaCfg;
u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
- u32 dword=0;
+ u32 dword;
mega_mailbox *mbox;
mega_scb *pScb;
- u_char qCnt, qStatus;
- u_char completed[MAX_FIRMWARE_STATUS];
- Scsi_Cmnd *SCpnt;
+ long flags;
+ int qCnt, qStatus;
megaCfg = (mega_host_config *) devp;
mbox = (mega_mailbox *)tmpBox;
- if (megaCfg->host->irq == irq) {
+#if LINUX_VERSION_CODE >= 0x20100
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif
+
+ while (megaCfg->host->irq == irq) {
+
+ spin_lock_irqsave (&mega_lock, flags);
if (megaCfg->flag & IN_ISR) {
TRACE (("ISR called reentrantly!!\n"));
- printk ("ISR called reentrantly!!\n");
}
megaCfg->flag |= IN_ISR;
printk(KERN_WARNING "Error: mailbox busy in isr!\n");
}
+
/* Check if a valid interrupt is pending */
if (megaCfg->flag & BOARD_QUARTZ) {
dword = RDOUTDOOR (megaCfg);
if (dword != 0x10001234) {
/* Spurious interrupt */
megaCfg->flag &= ~IN_ISR;
- return;
+ spin_unlock_irqrestore (&mega_lock, flags);
+ break;
}
+ WROUTDOOR (megaCfg, dword);
+
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+ /* Acknowledge interrupt */
+ WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+ while (RDINDOOR (megaCfg) & 0x02);
}
else {
byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
if ((byte & VALID_INTR_BYTE) == 0) {
/* Spurious interrupt */
megaCfg->flag &= ~IN_ISR;
- return;
+ spin_unlock_irqrestore (&mega_lock, flags);
+ break;
}
WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
- }
- for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
-#if LINUX_VERSION_CODE >= 0x20100
- IO_LOCK;
-#endif
-
- qCnt = 0xff;
- while ((qCnt = megaCfg->mbox->numstatus) == 0xFF)
- ;
-
- qStatus = 0xff;
- while ((qStatus = megaCfg->mbox->status) == 0xFF)
- ;
-
- /* Get list of completed requests */
- for (idx = 0; idx<qCnt; idx++) {
- while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
- printk("p");
- }
- completed[idx] = sIdx;
- sIdx = 0xFF;
- }
-
- if (megaCfg->flag & BOARD_QUARTZ) {
- WROUTDOOR (megaCfg, dword);
/* Acknowledge interrupt */
- WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
- while (RDINDOOR (megaCfg) & 0x02);
- }
- else {
CLEAR_INTR (megaCfg->host->io_port);
}
-#if DEBUG
- if(qCnt >= MAX_FIRMWARE_STATUS) {
- printk("megaraid_isr: cmplt=%d ", qCnt);
- }
-#endif
+ qCnt = mbox->numstatus;
+ qStatus = mbox->status;
for (idx = 0; idx < qCnt; idx++) {
- sIdx = completed[idx];
- if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
+ sIdx = mbox->completed[idx];
+ if (sIdx > 0) {
pScb = &megaCfg->scbList[sIdx - 1];
/* ASSERT(pScb->state == SCB_ISSUED); */
#if DEBUG
if (((jiffies) - pScb->isrcount) > maxCmdTime) {
maxCmdTime = (jiffies) - pScb->isrcount;
- printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
+ printk("cmd time = %u\n", maxCmdTime);
}
#endif
-/*
- * Assuming that the scsi command, for which an abort request was received
- * earlier has completed.
- */
+
if (pScb->state == SCB_ABORTED) {
- SCpnt = pScb->SCpnt;
- }
- if (pScb->state == SCB_RESET) {
- SCpnt = pScb->SCpnt;
- mega_freeSCB (megaCfg, pScb);
- SCpnt->result = (DID_RESET << 16) ;
- if( megaCfg->qCompletedH == NULL ) {
- megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
- }
- else {
- megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
- megaCfg->qCompletedT = SCpnt;
- }
- megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
- megaCfg->qCcnt++;
- continue;
+ printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
}
if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW)
mega_cmd_done(megaCfg, pScb, qStatus);
}
- else {
- printk("megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
- for(;;);
- }
- }
- mega_rundoneq(megaCfg);
+ }
+ spin_unlock_irqrestore (&mega_lock, flags);
megaCfg->flag &= ~IN_ISR;
+
+ mega_rundoneq();
+
/* Loop through any pending requests */
+ spin_lock_irqsave(&mega_lock, flags);
mega_runpendq(megaCfg);
-#if LINUX_VERSION_CODE >= 0x20100
- IO_UNLOCK;
-#endif
+ spin_unlock_irqrestore(&mega_lock,flags);
}
+#if LINUX_VERSION_CODE >= 0x20100
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif
}
/*==================================================*/
mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
u_char byte;
u32 cmdDone;
+ Scsi_Cmnd *SCpnt;
u32 phys_mbox;
u8 retval=-1;
phys_mbox = virt_to_bus (megaCfg->mbox);
+#if 0
+ if (intr && mbox->busy) {
+ return 0;
+ }
+#endif
+
#if DEBUG
showMbox(pScb);
#endif
/* Wait until mailbox is free */
- if (mega_busyWaitMbox (megaCfg)) {
+ while (mega_busyWaitMbox (megaCfg)) {
printk("Blocked mailbox......!!\n");
udelay(1000);
/* Abort command */
if (pScb == NULL) {
- TRACE(("NULL pScb in megaIssue\n"));
printk("NULL pScb in megaIssue\n");
+ TRACE(("NULL pScb in megaIssue\n"));
}
- mega_cmd_done (megaCfg, pScb, 0x08);
+ SCpnt = pScb->SCpnt;
+ freeSCB(megaCfg, pScb);
+
+ SCpnt->result = (DID_ABORT << 16);
+ callDone(SCpnt);
return -1;
}
if (pScb) {
mega_cmd_done (megaCfg, pScb, mbox->status);
+ mega_rundoneq ();
}
WRINDOOR (megaCfg, phys_mbox | 0x2);
while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+
ENABLE_INTR (megaCfg->host->io_port);
CLEAR_INTR (megaCfg->host->io_port);
if (pScb) {
mega_cmd_done (megaCfg, pScb, mbox->status);
+ mega_rundoneq ();
}
else {
TRACE (("Error: NULL pScb!\n"));
}
+
}
enable_irq(megaCfg->host->irq);
retval=mbox->status;
}
-#if DEBUG
while (mega_busyWaitMbox (megaCfg)) {
printk("Blocked mailbox on exit......!\n");
udelay(1000);
}
-#endif
return retval;
}
/*-------------------------------------------------------------------
* Copies data to SGLIST
*-------------------------------------------------------------------*/
-static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
u32 * buffer, u32 * length)
{
struct scatterlist *sgList;
paddr = (paddr + 4 + 16) & 0xfffffff0;
/* Register mailbox area with the firmware */
- if (!(megaCfg->flag & BOARD_QUARTZ)) {
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ }
+ else {
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
u32 paddr;
u8 retval;
+ spin_lock_init (&mega_lock);
+
/* Initialize adapter inquiry mailbox*/
paddr = virt_to_bus (megaCfg->mega_buffer);
mbox = (mega_mailbox *) mboxData;
/*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/
megaCfg->host->max_lun = /* max lun */
(megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
- megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
megaCfg->numldrv = enquiry3Pnt->numLDrv;
megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
- if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
- megaCfg->host->can_queue = megaCfg->max_cmds;
+#if 0
+ int i;
+ printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
+ for (i = 0; i < megaCfg->numldrv; i++) {
+ printk ("%d: size: %d prop: %x state: %x\n", i,
+ enquiry3Pnt->lDrvSize[i],
+ enquiry3Pnt->lDrvProp[i],
+ enquiry3Pnt->lDrvState[i]);
+ }
- if (megaCfg->host->can_queue >= MAX_COMMANDS) {
- megaCfg->host->can_queue = MAX_COMMANDS-1;
+ printk (KERN_DEBUG "---- Physical drive info ----\n");
+ for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
+ if (i && !(i % 8))
+ printk ("\n");
+ printk ("%d: %x ", i, enquiry3Pnt->pDrvState[i]);
}
+ printk ("\n");
+#endif
#ifdef HP /* use HP firmware and bios version encoding */
sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
return 0;
}
-int mega_findCard (Scsi_Host_Template * pHostTmpl,
+int findCard (Scsi_Host_Template * pHostTmpl,
u16 pciVendor, u16 pciDev,
long flag)
{
#if LINUX_VERSION_CODE < 0x20100
while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
+
+#if 0
+ } /* keep auto-indenters happy */
+#endif
#else
struct pci_dev *pdev = pci_devices;
pcibios_read_config_word (pciBus, pciDevFun,
PCI_CONF_AMISIG,
&magic);
- if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
+ if (magic != AMI_SIGNATURE) {
pciIdx++;
continue; /* not an AMI board */
}
host->host_no, (u_int) megaBase, megaIrq);
/* Copy resource info into structure */
- megaCfg->qCompletedH = NULL;
- megaCfg->qCompletedT = NULL;
- megaCfg->qPendingH = NULL;
- megaCfg->qPendingT = NULL;
- megaCfg->qFreeH = NULL;
- megaCfg->qFreeT = NULL;
- megaCfg->qFcnt = 0;
- megaCfg->qPcnt = 0;
- megaCfg->qCcnt = 0;
+ megaCfg->qPending = NULL;
+ megaCfg->qFree = NULL;
megaCfg->flag = flag;
megaCfg->host = host;
megaCfg->base = megaBase;
mega_i_query_adapter (megaCfg);
/* Initialize SCBs */
- if (mega_initSCB (megaCfg)) {
+ if (initSCB (megaCfg)) {
scsi_unregister (host);
continue;
}
printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
- count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
- count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
- count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+ count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
+ count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
+ count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
return count;
}
release_region (megaCfg->host->io_port, 16);
}
- mega_freeSgList(megaCfg);
+ freeSgList(megaCfg);
scsi_unregister (pSHost);
return 0;
}
-static inline void mega_freeSgList(mega_host_config *megaCfg)
+static inline void freeSgList(mega_host_config *megaCfg)
{
int i;
*-----------------------------------------------------------------*/
int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
{
- DRIVER_LOCK_T
mega_host_config *megaCfg;
mega_scb *pScb;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
- DRIVER_LOCK(megaCfg);
if (!(megaCfg->flag & (1L << SCpnt->channel))) {
if (SCpnt->channel < SCpnt->host->max_channel)
/* If driver in abort or reset.. cancel this command */
if (megaCfg->flag & IN_ABORT) {
SCpnt->result = (DID_ABORT << 16);
- /* Add Scsi_Command to end of completed queue */
- if( megaCfg->qCompletedH == NULL ) {
- megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
- }
- else {
- megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
- megaCfg->qCompletedT = SCpnt;
- }
- megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
- megaCfg->qCcnt++;
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- DRIVER_UNLOCK(megaCfg);
+ spin_unlock_irqrestore(&mega_lock,flags);
return 0;
}
else if (megaCfg->flag & IN_RESET) {
SCpnt->result = (DID_RESET << 16);
- /* Add Scsi_Command to end of completed queue */
- if( megaCfg->qCompletedH == NULL ) {
- megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
- }
- else {
- megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
- megaCfg->qCompletedT = SCpnt;
- }
- megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
- megaCfg->qCcnt++;
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- DRIVER_UNLOCK(megaCfg);
+ spin_unlock_irqrestore(&mega_lock,flags);
return 0;
}
- megaCfg->flag |= IN_QUEUE;
/* Allocate and build a SCB request */
if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
/*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
/* Add SCB to the head of the pending queue */
- /* Add SCB to the head of the pending queue */
- if( megaCfg->qPendingH == NULL ) {
- megaCfg->qPendingH = megaCfg->qPendingT = pScb;
+ ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
+
+ /* Issue any pending command to the card if not in ISR */
+ if (!(megaCfg->flag & IN_ISR)) {
+ mega_runpendq(megaCfg);
}
else {
- megaCfg->qPendingT->next = pScb;
- megaCfg->qPendingT = pScb;
+ printk("IRQ pend...\n");
}
- megaCfg->qPendingT->next = NULL;
- megaCfg->qPcnt++;
- mega_runpendq(megaCfg);
-
-#if LINUX_VERSION_CODE > 0x020024
if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
{ /* user data from external user buffer */
char *user_area;
kfree(pScb->kern_area);
- mega_freeSCB(megaCfg, pScb);
+ freeSCB(megaCfg, pScb);
}
-#endif
+
}
- megaCfg->flag &= ~IN_QUEUE;
- DRIVER_UNLOCK(megaCfg);
+ spin_unlock_irqrestore(&mega_lock,flags);
return 0;
}
/*---------------------------------------------------------------------
* Abort a previous SCSI request
*---------------------------------------------------------------------*/
-int
-megaraid_abort (Scsi_Cmnd * SCpnt)
+int megaraid_abort (Scsi_Cmnd * SCpnt)
{
mega_host_config *megaCfg;
- int rc; //, idx;
+ int rc, idx;
+ long flags;
mega_scb *pScb;
- rc = SCSI_ABORT_NOT_RUNNING;
+ rc = SCSI_ABORT_SUCCESS;
+
+ spin_lock_irqsave (&mega_lock, flags);
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
megaCfg->flag |= IN_ABORT;
- for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
if (pScb->SCpnt == SCpnt) {
/* Found an aborting command */
#if DEBUG
showMbox(pScb);
#endif
-/*
- * If the command is queued to be issued to the firmware, abort the scsi cmd,
- * If the command is already aborted in a previous call to the _abort entry
- * point, return SCSI_ABORT_SNOOZE, suggesting a reset.
- * If the command is issued to the firmware, which might complete after
- * some time, we will mark the scb as aborted, and return to the mid layer,
- * that abort could not be done.
- * In the ISR, when this command actually completes, we will perform a normal
- * completion.
- *
- * Oct 27, 1999
- */
+ printk("Abort: %d %u\n",
+ SCpnt->timeout_per_command,
+ (uint)((jiffies) - pScb->isrcount));
switch(pScb->state) {
case SCB_ABORTED: /* Already aborted */
rc = SCSI_ABORT_SNOOZE;
break;
case SCB_ISSUED: /* Waiting on ISR result */
- rc = SCSI_ABORT_NOT_RUNNING;
+ rc = SCSI_ABORT_PENDING;
pScb->state = SCB_ABORTED;
break;
- case SCB_ACTIVE: /* still on the pending queue */
- mega_freeSCB (megaCfg, pScb);
- SCpnt->result = (DID_ABORT << 16) ;
- if( megaCfg->qCompletedH == NULL ) {
- megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
- }
- else {
- megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
- megaCfg->qCompletedT = SCpnt;
- }
- megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
- megaCfg->qCcnt++;
- rc = SCSI_ABORT_SUCCESS;
- break;
- default:
- printk("megaraid_abort: unknown command state!!\n");
- rc = SCSI_ABORT_NOT_RUNNING;
- break;
}
- break;
}
}
- megaCfg->flag &= ~IN_ABORT;
-
+#if 0
+ TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->lun));
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->SCpnt == SCpnt) {
+ ser_printk("** %d<%x> %c\n", pScb->SCpnt->pid, pScb->idx+1,
+ pScb->state == SCB_ACTIVE ? 'A' : 'I');
#if DEBUG
-if(megaCfg->flag & IN_QUEUE) printk("ma:flag is in queue\n");
-if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
+ showMbox(pScb);
#endif
+ }
+ }
+#endif
+
+ /*
+ * Walk list of SCBs for any that are still outstanding
+ */
+ for (idx = 0; idx < megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].state != SCB_FREE) {
+ if (megaCfg->scbList[idx].SCpnt == SCpnt) {
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
+
+ SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ }
+ }
+ }
-/*
- * This is required here to complete any completed requests to be communicated
- * over to the mid layer.
- * Calling just mega_rundoneq() did not work.
- */
-if(megaCfg->qCompletedH) {
- SCpnt = megaCfg->qCompletedH;
- megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
- megaCfg->qCcnt--;
-
- SCpnt->host_scribble = (unsigned char *) NULL ;
- /* Callback */
- callDone (SCpnt);
-}
- mega_rundoneq(megaCfg);
+ megaCfg->flag &= ~IN_ABORT;
+
+ spin_unlock_irqrestore (&mega_lock, flags);
+
+ mega_rundoneq();
return rc;
}
{
mega_host_config *megaCfg;
int idx;
- int rc;
- mega_scb *pScb;
+ long flags;
+
+ spin_lock_irqsave (&mega_lock, flags);
- rc = SCSI_RESET_NOT_RUNNING;
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
megaCfg->flag |= IN_RESET;
- printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
- SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
- SCpnt->lun, rstflags);
-
TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
SCpnt->lun));
for (idx = 0; idx < megaCfg->max_cmds; idx++) {
if (megaCfg->scbList[idx].state != SCB_FREE) {
SCpnt = megaCfg->scbList[idx].SCpnt;
- pScb = &megaCfg->scbList[idx];
if (SCpnt != NULL) {
- pScb->state = SCB_RESET;
- break;
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
+ SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
}
}
}
megaCfg->flag &= ~IN_RESET;
- mega_rundoneq(megaCfg);
- return rc;
+ spin_unlock_irqrestore (&mega_lock, flags);
+
+ mega_rundoneq();
+ return SCSI_RESET_PUNT;
}
/*-------------------------------------------------------------
#include "scsi_module.c"
#endif
+
#define IN_ISR 0x80000000L
#define IN_ABORT 0x40000000L
#define IN_RESET 0x20000000L
-#define IN_QUEUE 0x10000000L
#define BOARD_QUARTZ 0x08000000L
#define BOARD_40LD 0x04000000L
#define MEGA_CMD_TIMEOUT 10
-/* Feel free to fiddle with these.. max values are:
- SGLIST 0..26
- COMMANDS 0..253
- CMDPERLUN 0..63
-*/
-#define MAX_SGLIST 0x1A
-#define MAX_COMMANDS 127
+#define MAX_SGLIST 17
+#define MAX_COMMANDS 250
#define MAX_CMD_PER_LUN 63
-#define MAX_FIRMWARE_STATUS 46
#define MAX_LOGICAL_DRIVES 8
#define MAX_CHANNEL 5
#define PCI_CONF_IRQ_OFFSET 0x3c
#define PCI_CONF_AMISIG 0xa0
#define AMI_SIGNATURE 0x3344
-#define AMI_SIGNATURE_471 0xCCCC
#if LINUX_VERSION_CODE < 0x20100
#define MEGARAID \
u32 dataxferlen;
} mega_passthru;
-struct _mega_mailbox {
+typedef struct _mega_mailbox {
/* 0x0 */ u8 cmd;
/* 0x1 */ u8 cmdid;
/* 0x2 */ u16 numsectors;
/* 0x12 */ u8 completed[46];
u8 mraid_poll;
u8 mraid_ack;
- u8 pad[16]; /* for alignment purposes */
-}__attribute__((packed));
-typedef struct _mega_mailbox mega_mailbox;
+ u8 pad[16];
+} mega_mailbox;
typedef struct {
u32 xferSegment; /* for 64-bit controllers */
u32 flag;
u32 base;
- mega_scb *qFreeH;
- mega_scb *qFreeT;
- mega_scb *qPendingH;
- mega_scb *qPendingT;
-
- Scsi_Cmnd *qCompletedH;
- Scsi_Cmnd *qCompletedT;
- u32 qFcnt;
- u32 qPcnt;
- u32 qCcnt;
+ mega_scb *qFree;
+ mega_scb *qPending;
u32 nReads[FC_MAX_LOGICAL_DRIVES];
u32 nWrites[FC_MAX_LOGICAL_DRIVES];
case PHONE_CPT_STOP:
ixj_cpt_stop(board);
break;
+ case PHONE_QUERY_CODEC:
+ {
+ struct phone_codec_data pd;
+ int val;
+ int proto_size[] = {
+ -1,
+ 12, 10, 16, 9, 8, 48, 5,
+ 40, 40, 80, 40, 40
+ };
+ if(copy_from_user(&pd, (void *)arg, sizeof(pd)))
+ return -EFAULT;
+ if(pd.type<1 || pd.type>12)
+ return -EPROTONOSUPPORT;
+ if(pd.type<G729)
+ val=proto_size[pd.type];
+ else switch(j->baseframe.low)
+ {
+ case 0xA0:val=2*proto_size[pd.type];break;
+ case 0x50:val=proto_size[pd.type];break;
+ default:val=proto_size[pd.type]*3;break;
+ }
+ pd.buf_min=pd.buf_max=pd.buf_opt=val;
+ if(copy_to_user((void *)arg, &pd, sizeof(pd)))
+ return -EFAULT;
+ return 0;
+ }
case IXJCTL_DSP_IDLE:
idle(board);
break;
ixj_daa_cr4(board, arg | 0x02);
break;
case IXJCTL_PSTN_LINETEST:
+ case PHONE_PSTN_LINETEST:
retval = ixj_linetest(board);
break;
case IXJCTL_CID:
static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
{
- unsigned short *p;
-
- if (conp->vc_num != fg_console)
- return;
- p = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
-
+ unsigned short *p = (unsigned short *)
+ (conp->vc_origin + t * conp->vc_size_row);
while (count) {
scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
count--;
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
+ * AV: It can't be modified, but it fscking
+ * can be seeked by another process that shares
+ * the descriptor.
*/
- unsigned long version = inode->i_version;
+ unsigned long version = filp->f_version;
error = filldir(dirent, de->name,
de->name_len,
filp->f_pos, le32_to_cpu(de->inode));
if (error)
break;
- if (version != inode->i_version)
+ if (version != filp->f_version)
goto revalidate;
stored ++;
}
#define IOBASE_LEN 0x00300000 /* Length of the IO area */
#define IOBASE_END 0xfe300000
#define DVMA_VADDR 0xfff00000 /* Base area of the DVMA on suns */
-#define DVMA_LEN 0x00040000 /* Size of the DVMA address space */
-#define DVMA_END 0xfff40000
+#define DVMA_LEN 0x000c0000 /* Size of the DVMA address space */
+#define DVMA_END 0xfffc0000
/* IOMMU Mapping area, must be on a 16MB boundary! Note this
* doesn't count the DVMA areas, the prom lives between the
#define read_pcr(__p) __asm__ __volatile__("rd %%pcr, %0" : "=r" (__p))
#define write_pcr(__p) __asm__ __volatile__("wr %0, 0x0, %%pcr" : : "r" (__p));
#define read_pic(__p) __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-#define reset_pic() __asm__ __volatile__("wr %g0, 0x0, %pic");
+
+/* Blackbird errata workaround. See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define reset_pic() \
+ __asm__ __volatile__("ba,pt %xcc, 99f\n\t" \
+ ".align 64\n" \
+ "99:wr %g0, 0x0, %pic\n\t" \
+ "rd %pic, %g0")
#ifndef __ASSEMBLY__
WSS = 12
} phone_codec;
+struct phone_codec_data
+{
+ phone_codec type;
+ unsigned short buf_min, buf_opt, buf_max;
+};
+
+#define PHONE_QUERY_CODEC _IOWR ('q', 0xA7, struct phone_codec_data *)
+#define PHONE_PSTN_LINETEST _IO ('q', 0xA8)
+
+
/******************************************************************************
*
* The exception structure allows us to multiplex multiple events onto the
#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */
#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */
#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */
-#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Set the video overlay window */
+#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */
#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
for (q = sma->sem_pending; q; q = q->next) {
if (q->status == 1)
- return; /* wait for other process */
+ continue; /* this one was woken up before */
error = try_atomic_semop(sma, q->sops, q->nsops,
q->undo, q->pid, q->alter);
sin->sin_family = AF_INET;
sin->sin_port = skb->h.uh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
#ifdef CONFIG_IP_TRANSPARENT_PROXY
if (flags&MSG_PROXY)
{