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 @@
* 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 $
*/
#define AUTOSENSE
#if 0
#define PSEUDO_DMA
#endif
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/ctype.h>
......@@ -56,6 +40,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/blk.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -80,33 +65,28 @@
#define RESET_BOOT
#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 DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI );
extern void via_scsi_clear(void);
#ifdef RESET_BOOT
static void mac_scsi_reset_boot(struct Scsi_Host *instance);
#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_cmd_per_lun = -1;
static int setup_sg_tablesize = -1;
static int setup_use_pdma = -1;
#ifdef SUPPORT_TAGS
static int setup_use_tagged_queuing = -1;
#endif
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,
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
* need ten times the standard value... */
......@@ -123,44 +103,27 @@ static volatile unsigned char *mac_scsi_drq = 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,
*
* Inputs : str - unused, ints - array of integer parameters with ints[0]
* equal to the number of ints.
* Inputs : str - comma delimited list of options
*
*/
static int __init mac_scsi_setup(char *str, int *ints) {
#ifdef DRIVER_SETUP
/* Format of mac5380 parameter is:
* mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
* Negative values mean don't change.
*/
static int __init mac_scsi_setup(char *str) {
#ifdef DRIVER_SETUP
int ints[7];
/* Grmbl... the standard parameter parsing can't handle negative numbers
* :-( 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;
(void)get_options( str, ARRAY_SIZE(ints), ints);
if (ints[0] < 1) {
printk( "mac_scsi_setup: no arguments!\n" );
return 0;
if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
printk(KERN_WARNING "scsi: <mac5380>"
" 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[1] > 0)
/* no limits on this, just > 0 */
......@@ -183,25 +146,31 @@ static int __init mac_scsi_setup(char *str, int *ints) {
if (ints[4] >= 0 && ints[4] <= 7)
setup_hostid = ints[4];
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[5] >= 0)
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
return 1;
return 1;
}
__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
*/
......@@ -221,93 +190,89 @@ static struct Scsi_Host *default_instance;
int macscsi_detect(Scsi_Host_Template * tpnt)
{
int count = 0;
static int called = 0;
int flags = 0;
struct Scsi_Host *instance;
if (!MACH_IS_MAC || called)
return( 0 );
if (macintosh_config->scsi_type != MAC_SCSI_OLD)
return( 0 );
tpnt->proc_name = "mac5380";
return( 0 );
/* setup variables */
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 =
(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 =
(setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
(setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
if (setup_hostid >= 0)
tpnt->this_id = setup_hostid;
tpnt->this_id = setup_hostid;
else {
/* use 7 as default */
tpnt->this_id = 7;
/* use 7 as default */
tpnt->this_id = 7;
}
#ifdef SUPPORT_TAGS
if (setup_use_tagged_queuing < 0)
setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
if (setup_use_tagged_queuing < 0)
setup_use_tagged_queuing = USE_TAGGED_QUEUING;
#endif
#if 0 /* loop over multiple adapters (Powerbooks ??) */
for (count = 0; count < mac_num_scsi; count++) {
/* Once we support multiple 5380s (e.g. DuoDock) we'll do
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
instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
if(instance == NULL)
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;
}
NCR5380_init(instance, flags);
instance->n_io_port = 255;
instance->io_port = (unsigned long) mac_scsi_regp;
instance->irq = IRQ_MAC_SCSI;
((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
#ifdef RESET_BOOT
mac_scsi_reset_boot(instance);
#endif
if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
"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);
instance->n_io_port = 255;
((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
if (instance->irq != IRQ_NONE)
if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) {
printk("scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
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
printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
if (instance->irq == IRQ_NONE)
printk (KERN_INFO "s disabled");
else
printk (KERN_INFO " %d", instance->irq);
printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
printk(KERN_INFO "\nscsi%d:", instance->host_no);
NCR5380_print_options(instance);
printk("\n");
called = 1;
return 1;
}
int macscsi_release (struct Scsi_Host *shpnt)
......@@ -335,10 +300,10 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
* 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 */
mac_disable_irq(IRQ_MAC_SCSI);
mac_disable_irq(IRQ_MAC_SCSI);
/* get in phase */
NCR5380_write( TARGET_COMMAND_REG,
......@@ -356,207 +321,22 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
barrier();
/* 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
const char * macscsi_info (struct Scsi_Host *spnt) {
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;
return "";
}
#undef STAT
#undef CTRL
#undef IN
#undef OUT
/*
* NCR 5380 register access functions
*/
#ifdef ORIG
#if 0
#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
#else
/* Debug versions
#define CTRL(p,v) (*ctrl = (v))
#endif
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;
CTRL(iobase, 0);
#if 0
i = inb(iobase + 64 + reg);
#else
i = inb(iobase + reg<<4);
#endif
i = in_8(iobase + (reg<<4));
CTRL(iobase, 0x40);
return i;
......@@ -581,86 +357,244 @@ static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
CTRL(iobase, 0);
#if 0
outb(value, iobase + 64 + reg);
#else
outb(value, iobase + reg<<4);
#endif
out_8(value, iobase + (reg<<4));
CTRL(iobase, 0x40);
}
*/
#undef CTRL
#else
static char macscsi_read(struct Scsi_Host *instance, int reg)
/* Fast versions */
static __inline__ 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;
NCR5380_local_declare();
if (default_instance) {
#if 0
NCR5380_setup(default_instance);
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
#endif
local_irq_save(flags);
NCR5380_print_status(default_instance);
local_irq_restore(flags);
}
#if 0
polled_scsi_on = 1;
#endif
unsigned char *d;
volatile unsigned char *s;
NCR5380_local_declare();
NCR5380_setup(instance);
s = mac_scsi_drq+0x60;
d = dst;
/* These conditions are derived from MacOS */
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
&& !(NCR5380_read(STATUS_REG) & SR_REQ))
;
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;
NCR5380_local_declare();
struct Scsi_Host *instance;
#if 0
for (instance = first_instance; instance && (instance->hostt ==
the_template); instance = instance->next)
if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) {
#else
instance = default_instance;
#endif
NCR5380_setup(instance);
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
{
printk("SCSI poll\n");
local_irq_save(flags);
NCR5380_intr(IRQ_MAC_SCSI, instance, NULL);
local_irq_restore(flags);
}
#if 0
}
#endif
unsigned char *s;
volatile unsigned char *d;
NCR5380_local_declare();
NCR5380_setup(instance);
s = src;
d = mac_scsi_drq;
/* These conditions are derived from MacOS */
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
&& (!(NCR5380_read(STATUS_REG) & SR_REQ)
|| (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
;
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
printk(KERN_ERR "Error in macscsi_pwrite\n");
return -1;
}
CP_MEM_TO_IO(s, d, len);
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"
......@@ -29,16 +29,9 @@
#ifndef MAC_NCR5380_H
#define MAC_NCR5380_H
#define MACSCSI_PUBLIC_RELEASE 1
#define MACSCSI_PUBLIC_RELEASE 2
#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 length, int hostno, int inout);
......@@ -64,22 +57,6 @@ int macscsi_proc_info (char *buffer, char **start, off_t offset,
#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
#define NCR5380_implementation_fields \
......@@ -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_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_queue_command macscsi_queue_command
#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 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