Commit c9b1ca0d authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

[PATCH] Mac/m68k NCR5380 SCSI updates

Mac/m68k NCR5380 SCSI updates (forward port of Ray Knight's changes in 2.4.x):
  - Forward port of pseudo-DMA from 2.2.20
  - Move SCSI host template definition from mac_scsi.h to mac_scsi.c
parent bc3e61c7
...@@ -25,26 +25,10 @@ ...@@ -25,26 +25,10 @@
* 1+ (800) 334-5454 * 1+ (800) 334-5454
*/ */
/*
* Options :
*
* PARITY - enable parity checking. Not supported.
*
* SCSI2 - enable support for SCSI-II tagged queueing. Untested.
*
* USLEEP - enable support for devices that don't disconnect. Untested.
*/
/* /*
* $Log: mac_NCR5380.c,v $ * $Log: mac_NCR5380.c,v $
*/ */
#define AUTOSENSE
#if 0
#define PSEUDO_DMA
#endif
#include <linux/types.h> #include <linux/types.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/ctype.h> #include <linux/ctype.h>
...@@ -56,6 +40,7 @@ ...@@ -56,6 +40,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/interrupt.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -80,33 +65,28 @@ ...@@ -80,33 +65,28 @@
#define RESET_BOOT #define RESET_BOOT
#define DRIVER_SETUP #define DRIVER_SETUP
/*
* BUG can be used to trigger a strange code-size related hang on 2.1 kernels
*/
#ifdef BUG
#undef RESET_BOOT
#undef DRIVER_SETUP
#endif
#define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI ); #define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI );
#define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI ); #define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI );
extern void via_scsi_clear(void);
#ifdef RESET_BOOT #ifdef RESET_BOOT
static void mac_scsi_reset_boot(struct Scsi_Host *instance); static void mac_scsi_reset_boot(struct Scsi_Host *instance);
#endif #endif
static char macscsi_read(struct Scsi_Host *instance, int reg);
static void macscsi_write(struct Scsi_Host *instance, int reg, int value);
static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg);
static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value);
static int setup_called = 0;
static int setup_can_queue = -1; static int setup_can_queue = -1;
static int setup_cmd_per_lun = -1; static int setup_cmd_per_lun = -1;
static int setup_sg_tablesize = -1; static int setup_sg_tablesize = -1;
static int setup_use_pdma = -1;
#ifdef SUPPORT_TAGS #ifdef SUPPORT_TAGS
static int setup_use_tagged_queuing = -1; static int setup_use_tagged_queuing = -1;
#endif #endif
static int setup_hostid = -1; static int setup_hostid = -1;
static int polled_scsi_on = 0;
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, /* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
* need ten times the standard value... */ * need ten times the standard value... */
...@@ -123,44 +103,27 @@ static volatile unsigned char *mac_scsi_drq = NULL; ...@@ -123,44 +103,27 @@ static volatile unsigned char *mac_scsi_drq = NULL;
static volatile unsigned char *mac_scsi_nodrq = NULL; static volatile unsigned char *mac_scsi_nodrq = NULL;
/* /*
* Function : mac_scsi_setup(char *str, int *ints) * Function : mac_scsi_setup(char *str)
* *
* Purpose : booter command line initialization of the overrides array, * Purpose : booter command line initialization of the overrides array,
* *
* Inputs : str - unused, ints - array of integer parameters with ints[0] * Inputs : str - comma delimited list of options
* equal to the number of ints.
* *
*/ */
static int __init mac_scsi_setup(char *str, int *ints) { static int __init mac_scsi_setup(char *str) {
#ifdef DRIVER_SETUP #ifdef DRIVER_SETUP
/* Format of mac5380 parameter is: int ints[7];
* mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
* Negative values mean don't change.
*/
/* Grmbl... the standard parameter parsing can't handle negative numbers (void)get_options( str, ARRAY_SIZE(ints), ints);
* :-( So let's do it ourselves!
*/
int i = ints[0]+1, fact;
while( str && (isdigit(*str) || *str == '-') && i <= 10) {
if (*str == '-')
fact = -1, ++str;
else
fact = 1;
ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
if ((str = strchr( str, ',' )) != NULL)
++str;
}
ints[0] = i-1;
if (ints[0] < 1) { if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
printk( "mac_scsi_setup: no arguments!\n" ); printk(KERN_WARNING "scsi: <mac5380>"
return 0; " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
return 0;
} }
if (ints[0] >= 1) { if (ints[0] >= 1) {
if (ints[1] > 0) if (ints[1] > 0)
/* no limits on this, just > 0 */ /* no limits on this, just > 0 */
...@@ -183,25 +146,31 @@ static int __init mac_scsi_setup(char *str, int *ints) { ...@@ -183,25 +146,31 @@ static int __init mac_scsi_setup(char *str, int *ints) {
if (ints[4] >= 0 && ints[4] <= 7) if (ints[4] >= 0 && ints[4] <= 7)
setup_hostid = ints[4]; setup_hostid = ints[4];
else if (ints[4] > 7) else if (ints[4] > 7)
printk( "mac_scsi_setup: invalid host ID %d !\n", ints[4] ); printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
} }
#ifdef SUPPORT_TAGS #ifdef SUPPORT_TAGS
if (ints[0] >= 5) { if (ints[0] >= 5) {
if (ints[5] >= 0) if (ints[5] >= 0)
setup_use_tagged_queuing = !!ints[5]; setup_use_tagged_queuing = !!ints[5];
} }
if (ints[0] == 6) {
if (ints[6] >= 0)
setup_use_pdma = ints[6];
}
#else
if (ints[0] == 5) {
if (ints[5] >= 0)
setup_use_pdma = ints[5];
}
#endif #endif
#endif #endif
return 1; return 1;
} }
__setup("mac5380=", mac_scsi_setup); __setup("mac5380=", mac_scsi_setup);
#if 0
#define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
#define MAC_IRQ(card) ((card)->irq)
#endif
/* /*
* XXX: status debug * XXX: status debug
*/ */
...@@ -221,93 +190,89 @@ static struct Scsi_Host *default_instance; ...@@ -221,93 +190,89 @@ static struct Scsi_Host *default_instance;
int macscsi_detect(Scsi_Host_Template * tpnt) int macscsi_detect(Scsi_Host_Template * tpnt)
{ {
int count = 0;
static int called = 0; static int called = 0;
int flags = 0;
struct Scsi_Host *instance; struct Scsi_Host *instance;
if (!MACH_IS_MAC || called) if (!MACH_IS_MAC || called)
return( 0 ); return( 0 );
if (macintosh_config->scsi_type != MAC_SCSI_OLD) if (macintosh_config->scsi_type != MAC_SCSI_OLD)
return( 0 ); return( 0 );
tpnt->proc_name = "mac5380";
/* setup variables */ /* setup variables */
tpnt->can_queue = tpnt->can_queue =
(setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE; (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
tpnt->cmd_per_lun = tpnt->cmd_per_lun =
(setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN; (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
tpnt->sg_tablesize = tpnt->sg_tablesize =
(setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE; (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
if (setup_hostid >= 0) if (setup_hostid >= 0)
tpnt->this_id = setup_hostid; tpnt->this_id = setup_hostid;
else { else {
/* use 7 as default */ /* use 7 as default */
tpnt->this_id = 7; tpnt->this_id = 7;
} }
#ifdef SUPPORT_TAGS #ifdef SUPPORT_TAGS
if (setup_use_tagged_queuing < 0) if (setup_use_tagged_queuing < 0)
setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; setup_use_tagged_queuing = USE_TAGGED_QUEUING;
#endif #endif
#if 0 /* loop over multiple adapters (Powerbooks ??) */ /* Once we support multiple 5380s (e.g. DuoDock) we'll do
for (count = 0; count < mac_num_scsi; count++) { something different here */
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
default_instance = instance;
if (macintosh_config->ident == MAC_MODEL_IIFX) {
mac_scsi_regp = via1+0x8000;
mac_scsi_drq = via1+0xE000;
mac_scsi_nodrq = via1+0xC000;
/* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
flags = FLAG_NO_PSEUDO_DMA;
} else {
mac_scsi_regp = via1+0x10000;
mac_scsi_drq = via1+0x6000;
mac_scsi_nodrq = via1+0x12000;
}
if (! setup_use_pdma)
flags = FLAG_NO_PSEUDO_DMA;
instance->io_port = (unsigned long) mac_scsi_regp;
instance->irq = IRQ_MAC_SCSI;
#ifdef RESET_BOOT
mac_scsi_reset_boot(instance);
#endif #endif
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
if(instance == NULL) NCR5380_init(instance, flags);
continue;
default_instance = instance;
if (macintosh_config->ident == MAC_MODEL_IIFX) {
mac_scsi_regp = via1+0x8000;
mac_scsi_drq = via1+0xE000;
mac_scsi_nodrq = via1+0xC000;
} else {
mac_scsi_regp = via1+0x10000;
mac_scsi_drq = via1+0x6000;
mac_scsi_nodrq = via1+0x12000;
}
instance->n_io_port = 255;
instance->io_port = (unsigned long) mac_scsi_regp; ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
instance->irq = IRQ_MAC_SCSI;
#ifdef RESET_BOOT if (instance->irq != IRQ_NONE)
mac_scsi_reset_boot(instance); if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
#endif "ncr5380", NCR5380_intr)) {
printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
}
NCR5380_init(instance, 0); printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
if (instance->irq == IRQ_NONE)
instance->n_io_port = 255; printk (KERN_INFO "s disabled");
else
((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; printk (KERN_INFO " %d", instance->irq);
printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
if (instance->irq != IRQ_NONE) instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) { printk(KERN_INFO "\nscsi%d:", instance->host_no);
printk("scsi%d: IRQ%d not free, interrupts disabled\n", NCR5380_print_options(instance);
instance->host_no, instance->irq); printk("\n");
instance->irq = IRQ_NONE;
}
printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
if (instance->irq == IRQ_NONE)
printk ("s disabled");
else
printk (" %d", instance->irq);
printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
printk("\nscsi%d:", instance->host_no);
NCR5380_print_options(instance);
printk("\n");
#if 0 /* multiple adapters */
}
#endif
called = 1; called = 1;
return 1; return 1;
} }
int macscsi_release (struct Scsi_Host *shpnt) int macscsi_release (struct Scsi_Host *shpnt)
...@@ -335,10 +300,10 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) ...@@ -335,10 +300,10 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
* with the queues, interrupts, or locks necessary here. * with the queues, interrupts, or locks necessary here.
*/ */
printk( "Macintosh SCSI: resetting the SCSI bus..." ); printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
mac_disable_irq(IRQ_MAC_SCSI); mac_disable_irq(IRQ_MAC_SCSI);
/* get in phase */ /* get in phase */
NCR5380_write( TARGET_COMMAND_REG, NCR5380_write( TARGET_COMMAND_REG,
...@@ -356,207 +321,22 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) ...@@ -356,207 +321,22 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
barrier(); barrier();
/* switch on SCSI IRQ again */ /* switch on SCSI IRQ again */
mac_enable_irq(IRQ_MAC_SCSI); mac_enable_irq(IRQ_MAC_SCSI);
printk( " done\n" ); printk(KERN_INFO " done\n" );
} }
#endif #endif
const char * macscsi_info (struct Scsi_Host *spnt) { const char * macscsi_info (struct Scsi_Host *spnt) {
return ""; return "";
}
void restore_irq(struct pt_regs *regs)
{
unsigned long flags;
local_save_flags(flags);
flags = (flags & ~0x0700) | (regs->sr & 0x0700);
local_irq_restore(flags);
}
/*
* pseudo-DMA transfer functions, copied and modified from Russel King's
* ARM 5380 driver (cumana_1)
*
* Work in progress (sort of), didn't work last time I checked, don't use!
*/
#ifdef NOT_EFFICIENT
#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
#define STAT(p) inb((p)+1)
#define IN(p) inb((p))
#define OUT(v,p) outb((v), (p))
#else
#if 0
#define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
#else
#define CTRL(p,v) (*ctrl = (v))
#endif
#define STAT(p) (p[1<<4])
#define IN(p) (*(p))
#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
#define OUT(v,p) (*(p) = (v))
#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
#endif
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
#define H(v) (((v)>>16)|((v) & 0xffff0000))
#define ioaddr(v) (v)
static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
int len)
{
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
int oldctrl = *ctrl;
unsigned long *laddr;
#ifdef NOT_EFFICIENT
int iobase = instance->io_port;
int dma_io = mac_scsi_nodrq;
#else
volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq);
#endif
if(!len) return 0;
CTRL(iobase, 0x02);
laddr = (unsigned long *)addr;
while(len >= 32)
{
int status;
unsigned long v;
status = STAT(iobase);
if(status & 0x80)
goto end;
if(!(status & 0x40))
continue;
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
len -= 32;
if(len == 0)
break;
}
addr = (unsigned char *)laddr;
CTRL(iobase, 0x12);
while(len > 0)
{
int status;
status = STAT(iobase);
if(status & 0x80)
goto end;
if(status & 0x40)
{
OUT(*addr++, dma_io);
if(--len == 0)
break;
}
status = STAT(iobase);
if(status & 0x80)
goto end;
if(status & 0x40)
{
OUT(*addr++, dma_io);
if(--len == 0)
break;
}
}
end:
CTRL(iobase, oldctrl|0x40);
return len;
}
static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
int len)
{
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
int oldctrl = *ctrl;
unsigned long *laddr;
#ifdef NOT_EFFICIENT
int iobase = instance->io_port;
int dma_io = mac_scsi_nodrq;
#else
volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq);
#endif
if(!len) return 0;
CTRL(iobase, 0x00);
laddr = (unsigned long *)addr;
while(len >= 32)
{
int status;
status = STAT(iobase);
if(status & 0x80)
goto end;
if(!(status & 0x40))
continue;
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
len -= 32;
if(len == 0)
break;
}
addr = (unsigned char *)laddr;
CTRL(iobase, 0x10);
while(len > 0)
{
int status;
status = STAT(iobase);
if(status & 0x80)
goto end;
if(status & 0x40)
{
*addr++ = IN(dma_io);
if(--len == 0)
break;
}
status = STAT(iobase);
if(status & 0x80)
goto end;
if(status & 0x40)
{
*addr++ = IN(dma_io);
if(--len == 0)
break;
}
}
end:
CTRL(iobase, oldctrl|0x40);
return len;
} }
#undef STAT
#undef CTRL
#undef IN
#undef OUT
/* /*
* NCR 5380 register access functions * NCR 5380 register access functions
*/ */
#ifdef ORIG /* Debug versions
#if 0
#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
#else
#define CTRL(p,v) (*ctrl = (v)) #define CTRL(p,v) (*ctrl = (v))
#endif
static char macscsi_read(struct Scsi_Host *instance, int reg) static char macscsi_read(struct Scsi_Host *instance, int reg)
{ {
...@@ -565,11 +345,7 @@ static char macscsi_read(struct Scsi_Host *instance, int reg) ...@@ -565,11 +345,7 @@ static char macscsi_read(struct Scsi_Host *instance, int reg)
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
CTRL(iobase, 0); CTRL(iobase, 0);
#if 0 i = in_8(iobase + (reg<<4));
i = inb(iobase + 64 + reg);
#else
i = inb(iobase + reg<<4);
#endif
CTRL(iobase, 0x40); CTRL(iobase, 0x40);
return i; return i;
...@@ -581,86 +357,244 @@ static void macscsi_write(struct Scsi_Host *instance, int reg, int value) ...@@ -581,86 +357,244 @@ static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
CTRL(iobase, 0); CTRL(iobase, 0);
#if 0 out_8(value, iobase + (reg<<4));
outb(value, iobase + 64 + reg);
#else
outb(value, iobase + reg<<4);
#endif
CTRL(iobase, 0x40); CTRL(iobase, 0x40);
} }
*/
#undef CTRL /* Fast versions */
static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
#else
static char macscsi_read(struct Scsi_Host *instance, int reg)
{ {
return( mac_scsi_regp[reg << 4] ); return in_8(instance->io_port + (reg<<4));
} }
static void macscsi_write(struct Scsi_Host *instance, int reg, int value) static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
{ {
mac_scsi_regp[reg << 4] = value; out_8(value, instance->io_port + (reg<<4));
} }
#endif
#include "NCR5380.c"
/*
* Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
* reentering NCR5380_print_status seems to have ugly side effects
*/
void scsi_mac_debug (void) /*
Pseudo-DMA: (Ove Edlund)
The code attempts to catch bus errors that occur if one for example
"trips over the cable".
XXX: Since bus errors in the PDMA routines never happen on my
computer, the bus error code is untested.
If the code works as intended, a bus error results in Pseudo-DMA
beeing disabled, meaning that the driver switches to slow handshake.
If bus errors are NOT extremely rare, this has to be changed.
*/
#define CP_IO_TO_MEM(s,d,len) \
__asm__ __volatile__ \
(" cmp.w #4,%2\n" \
" bls 8f\n" \
" move.w %1,%%d0\n" \
" neg.b %%d0\n" \
" and.w #3,%%d0\n" \
" sub.w %%d0,%2\n" \
" bra 2f\n" \
" 1: move.b (%0),(%1)+\n" \
" 2: dbf %%d0,1b\n" \
" move.w %2,%%d0\n" \
" lsr.w #5,%%d0\n" \
" bra 4f\n" \
" 3: move.l (%0),(%1)+\n" \
"31: move.l (%0),(%1)+\n" \
"32: move.l (%0),(%1)+\n" \
"33: move.l (%0),(%1)+\n" \
"34: move.l (%0),(%1)+\n" \
"35: move.l (%0),(%1)+\n" \
"36: move.l (%0),(%1)+\n" \
"37: move.l (%0),(%1)+\n" \
" 4: dbf %%d0,3b\n" \
" move.w %2,%%d0\n" \
" lsr.w #2,%%d0\n" \
" and.w #7,%%d0\n" \
" bra 6f\n" \
" 5: move.l (%0),(%1)+\n" \
" 6: dbf %%d0,5b\n" \
" and.w #3,%2\n" \
" bra 8f\n" \
" 7: move.b (%0),(%1)+\n" \
" 8: dbf %2,7b\n" \
" moveq.l #0, %2\n" \
" 9: \n" \
".section .fixup,\"ax\"\n" \
" .even\n" \
"90: moveq.l #1, %2\n" \
" jra 9b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,90b\n" \
" .long 3b,90b\n" \
" .long 31b,90b\n" \
" .long 32b,90b\n" \
" .long 33b,90b\n" \
" .long 34b,90b\n" \
" .long 35b,90b\n" \
" .long 36b,90b\n" \
" .long 37b,90b\n" \
" .long 5b,90b\n" \
" .long 7b,90b\n" \
".previous" \
: "=a"(s), "=a"(d), "=d"(len) \
: "0"(s), "1"(d), "2"(len) \
: "d0")
static int macscsi_pread (struct Scsi_Host *instance,
unsigned char *dst, int len)
{ {
unsigned long flags; unsigned char *d;
NCR5380_local_declare(); volatile unsigned char *s;
if (default_instance) { NCR5380_local_declare();
#if 0 NCR5380_setup(instance);
NCR5380_setup(default_instance);
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) s = mac_scsi_drq+0x60;
#endif d = dst;
local_irq_save(flags);
NCR5380_print_status(default_instance); /* These conditions are derived from MacOS */
local_irq_restore(flags);
} while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
#if 0 && !(NCR5380_read(STATUS_REG) & SR_REQ))
polled_scsi_on = 1; ;
#endif if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
&& (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
printk(KERN_ERR "Error in macscsi_pread\n");
return -1;
}
CP_IO_TO_MEM(s, d, len);
if (len != 0) {
printk(KERN_NOTICE "Bus error in macscsi_pread\n");
return -1;
}
return 0;
} }
/*
* Helper function for interrupt trouble. More ugly side effects here.
*/
void scsi_mac_polled (void)
#define CP_MEM_TO_IO(s,d,len) \
__asm__ __volatile__ \
(" cmp.w #4,%2\n" \
" bls 8f\n" \
" move.w %0,%%d0\n" \
" neg.b %%d0\n" \
" and.w #3,%%d0\n" \
" sub.w %%d0,%2\n" \
" bra 2f\n" \
" 1: move.b (%0)+,(%1)\n" \
" 2: dbf %%d0,1b\n" \
" move.w %2,%%d0\n" \
" lsr.w #5,%%d0\n" \
" bra 4f\n" \
" 3: move.l (%0)+,(%1)\n" \
"31: move.l (%0)+,(%1)\n" \
"32: move.l (%0)+,(%1)\n" \
"33: move.l (%0)+,(%1)\n" \
"34: move.l (%0)+,(%1)\n" \
"35: move.l (%0)+,(%1)\n" \
"36: move.l (%0)+,(%1)\n" \
"37: move.l (%0)+,(%1)\n" \
" 4: dbf %%d0,3b\n" \
" move.w %2,%%d0\n" \
" lsr.w #2,%%d0\n" \
" and.w #7,%%d0\n" \
" bra 6f\n" \
" 5: move.l (%0)+,(%1)\n" \
" 6: dbf %%d0,5b\n" \
" and.w #3,%2\n" \
" bra 8f\n" \
" 7: move.b (%0)+,(%1)\n" \
" 8: dbf %2,7b\n" \
" moveq.l #0, %2\n" \
" 9: \n" \
".section .fixup,\"ax\"\n" \
" .even\n" \
"90: moveq.l #1, %2\n" \
" jra 9b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,90b\n" \
" .long 3b,90b\n" \
" .long 31b,90b\n" \
" .long 32b,90b\n" \
" .long 33b,90b\n" \
" .long 34b,90b\n" \
" .long 35b,90b\n" \
" .long 36b,90b\n" \
" .long 37b,90b\n" \
" .long 5b,90b\n" \
" .long 7b,90b\n" \
".previous" \
: "=a"(s), "=a"(d), "=d"(len) \
: "0"(s), "1"(d), "2"(len) \
: "d0")
static int macscsi_pwrite (struct Scsi_Host *instance,
unsigned char *src, int len)
{ {
unsigned long flags; unsigned char *s;
NCR5380_local_declare(); volatile unsigned char *d;
struct Scsi_Host *instance;
NCR5380_local_declare();
#if 0 NCR5380_setup(instance);
for (instance = first_instance; instance && (instance->hostt ==
the_template); instance = instance->next) s = src;
if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) { d = mac_scsi_drq;
#else
instance = default_instance; /* These conditions are derived from MacOS */
#endif
NCR5380_setup(instance); while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) && (!(NCR5380_read(STATUS_REG) & SR_REQ)
{ || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
printk("SCSI poll\n"); ;
local_irq_save(flags); if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
NCR5380_intr(IRQ_MAC_SCSI, instance, NULL); printk(KERN_ERR "Error in macscsi_pwrite\n");
local_irq_restore(flags); return -1;
} }
#if 0
} CP_MEM_TO_IO(s, d, len);
#endif
if (len != 0) {
printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
return -1;
}
return 0;
} }
/* These control the behaviour of the generic 5380 core */
#define AUTOSENSE
#define PSEUDO_DMA
#include "NCR5380.c"
static Scsi_Host_Template driver_template = {
.proc_name = "Mac5380",
.proc_info = macscsi_proc_info,
.name = "Macintosh NCR5380 SCSI",
.detect = macscsi_detect,
.release = macscsi_release,
.info = macscsi_info,
.queuecommand = macscsi_queue_command,
.eh_abort_handler = macscsi_abort,
.eh_bus_reset_handler = macscsi_bus_reset,
.eh_device_reset_handler = macscsi_device_reset,
.eh_host_reset_handler = macscsi_host_reset,
.can_queue = CAN_QUEUE,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = CMD_PER_LUN,
.unchecked_isa_dma = 0,
.use_clustering = DISABLE_CLUSTERING
};
static Scsi_Host_Template driver_template = MAC_NCR5380;
#include "scsi_module.c" #include "scsi_module.c"
...@@ -29,16 +29,9 @@ ...@@ -29,16 +29,9 @@
#ifndef MAC_NCR5380_H #ifndef MAC_NCR5380_H
#define MAC_NCR5380_H #define MAC_NCR5380_H
#define MACSCSI_PUBLIC_RELEASE 1 #define MACSCSI_PUBLIC_RELEASE 2
#ifndef ASM #ifndef ASM
int macscsi_abort (Scsi_Cmnd *);
int macscsi_detect (Scsi_Host_Template *);
int macscsi_release (struct Scsi_Host *);
const char *macscsi_info (struct Scsi_Host *);
int macscsi_reset(Scsi_Cmnd *, unsigned int);
int macscsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int macscsi_proc_info (char *buffer, char **start, off_t offset, int macscsi_proc_info (char *buffer, char **start, off_t offset,
int length, int hostno, int inout); int length, int hostno, int inout);
...@@ -64,22 +57,6 @@ int macscsi_proc_info (char *buffer, char **start, off_t offset, ...@@ -64,22 +57,6 @@ int macscsi_proc_info (char *buffer, char **start, off_t offset,
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
#define MAC_NCR5380 { \
.name = "Macintosh NCR5380 SCSI", \
.detect = macscsi_detect, \
.release = macscsi_release, /* Release */ \
.info = macscsi_info, \
.queuecommand = macscsi_queue_command, \
.abort = macscsi_abort, \
.reset = macscsi_reset, \
.can_queue = CAN_QUEUE, /* can queue */ \
.this_id = 7, /* id */ \
.sg_tablesize = SG_ALL, /* sg_tablesize */ \
.cmd_per_lun = CMD_PER_LUN, /* cmd per lun */ \
.unchecked_isa_dma = 0, /* unchecked_isa_dma */ \
.use_clustering = DISABLE_CLUSTERING \
}
#ifndef HOSTS_C #ifndef HOSTS_C
#define NCR5380_implementation_fields \ #define NCR5380_implementation_fields \
...@@ -94,10 +71,15 @@ int macscsi_proc_info (char *buffer, char **start, off_t offset, ...@@ -94,10 +71,15 @@ int macscsi_proc_info (char *buffer, char **start, off_t offset,
#define NCR5380_read(reg) macscsi_read(_instance, reg) #define NCR5380_read(reg) macscsi_read(_instance, reg)
#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value) #define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
#define NCR5380_pread macscsi_pread
#define NCR5380_pwrite macscsi_pwrite
#define NCR5380_intr macscsi_intr #define NCR5380_intr macscsi_intr
#define NCR5380_queue_command macscsi_queue_command #define NCR5380_queue_command macscsi_queue_command
#define NCR5380_abort macscsi_abort #define NCR5380_abort macscsi_abort
#define NCR5380_reset macscsi_reset #define NCR5380_bus_reset macscsi_bus_reset
#define NCR5380_device_reset macscsi_device_reset
#define NCR5380_host_reset macscsi_host_reset
#define NCR5380_proc_info macscsi_proc_info #define NCR5380_proc_info macscsi_proc_info
#define BOARD_NORMAL 0 #define BOARD_NORMAL 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment