diff --git a/sys/i386/isa/pas.c b/sys/i386/isa/pas.c index e0bbbc08e041..02ec506d9b75 100644 --- a/sys/i386/isa/pas.c +++ b/sys/i386/isa/pas.c @@ -1,8 +1,38 @@ -/*- +/* + * Copyright (C) 1994 Poul-Henning Kamp + * + * All rights reserved. + * + * This file contains some material which are covered by the message after + * this message. + * + * The rest of this file is covered by the following clause: + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id$ + * + * This is a driver for the one particular kind of the "ProAudioSpectrum" + * card from MediaVision. To find out if your card is supported, you can + * either try out the driver, or you can look for a chip a little less than + * 1" square in one end of the card, with writing on it that say ...5380... + * + * Up to four of these cards can be in the same computer. If you have + * multiple cards, you need to set the "card-id" jumpers correspondingly. + * + * The driver uses no interrupts, so don't expect record-breaking performance. + * + * Poul-Henning Kamp + */ + +/* * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, * Michael L. Finch, Bradley A. Grantham, and * Lawrence A. Kesteloot - * Copyright (C) 1994 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,47 +61,67 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pas.c,v 1.8.2.1 1994/07/11 00:02:32 cgd Exp $ + * Was: Id: pas.c,v 1.8.2.1 1994/07/11 00:02:32 cgd Exp * - */ - -/* Modified for use with the pc532 by Phil Nelson, Feb 94. - * Modified for use with MediaVision ProAudioSpectrum type adapters - * under FreeBSD by Poul-Henning Kamp, + * Modified for use with the pc532 by Phil Nelson, Feb 94. */ #include "pas.h" #if NPAS > 0 -#include "types.h" + #include "param.h" #include "systm.h" -#include "conf.h" -#include "file.h" +#include "types.h" #include "buf.h" -#include "stat.h" -#include "uio.h" -#include "ioctl.h" -#include "cdio.h" -#include "errno.h" -#include "dkbad.h" -#include "disklabel.h" -#include "icu.h" -#include "i386/isa/isa.h" +#include "machine/cpufunc.h" #include "i386/isa/isa_device.h" #include #include #include "ic/ncr_5380.h" +/* + * Define this macro to disable the PSEUDO-DMA transfers. + */ +#undef NO_PAS16_PSEUDO_DMA + +/* + * This parameter determines how many byte we "insb" between each check for + * a change of phase. + */ + +#ifndef PAS16_PSEUDO_DMA_SIZE +# define PAS16_PSEUDO_DMA_SIZE 512 +#endif + +/* + * How many times we attempt to select a device. + */ +#ifndef ATTEMPT_SELECTION +# define ATTEMPT_SELECTION 5 +#endif /* ATTEMPT_SELECTION */ + +/* + * How many microseconds between each attempt. + */ +#ifndef SELECTION_DELAY +# define SELECTION_DELAY 10000 +#endif /* SELECTION_DELAY */ + +#ifndef PAS16_TIMEOUT +# define PAS16_TIMEOUT 1000000 +#endif /* PAS16_TIMEOUT */ /* What we need to debug the driver */ #ifdef PAS_DEBUG -static int pas_show_scsi_cmd(struct scsi_xfer *xs); -#define HERE() printf("<%d>",__LINE__) -#define ARGH() printf("[%d]",__LINE__) -#else /* PAS_DEBUG */ -#define HERE() /**/ -#define ARGH() /**/ +# if PAS_DEBUG == 0 +# undef PAS_DEBUG +# else + static int pas_show_scsi_cmd(struct scsi_xfer *xs); +# ifndef PAS_DEBUG_REQUEST_SENSE +# define PAS_DEBUG_REQUEST_SENSE +# endif +# endif #endif /* PAS_DEBUG */ #define SCSI_PHASE_DATA_OUT 0x0 @@ -83,61 +133,69 @@ static int pas_show_scsi_cmd(struct scsi_xfer *xs); #define SCSI_PHASE_MESSAGE_OUT 0x6 #define SCSI_PHASE_MESSAGE_IN 0x7 -#define SCSI_PHASE(x) ((x)&0x7) +#define SCSI_CUR_PHASE(x) ((x>>2)&0x7) #define SCSI_RET_SUCCESS 0 #define SCSI_RET_RETRY 1 #define SCSI_RET_DEVICE_DOWN 2 #define SCSI_RET_COMMAND_FAIL 3 + /* Our per device (card) structure */ static struct pas_softc { struct scsi_link sc_link; int mv_unit; u_short iobase; -#define sci_data(ptr) (ptr->iobase+0x0) -#define sci_icmd(ptr) (ptr->iobase+0x1) -#define sci_mode(ptr) (ptr->iobase+0x2) -#define sci_tcmd(ptr) (ptr->iobase+0x3) -#define sci_bus_csr(ptr) (ptr->iobase+0x2000) -#define sci_csr(ptr) (ptr->iobase+0x2001) -#define sci_idata(ptr) (ptr->iobase+0x2002) -#define sci_iack(ptr) (ptr->iobase+0x2003) -#define sci_pdmadata(ptr) (ptr->iobase+0x4000) -#define sci_pdmastat(ptr) (ptr->iobase+0x4001) +#define xor_0000 iobase + u_short xor_0001; + u_short xor_0002; + u_short xor_0003; + u_short xor_2000; + u_short xor_2001; + u_short xor_2002; + u_short xor_2003; + u_short xor_4000; + u_short xor_4001; + u_short xor_4003; } s_pas[NPAS]; -/* Our access to the 5380 chip */ +/* + * Register Access-macros use these + */ +#define r_csdr(ptr) (ptr->xor_0000) +#define w_odr(ptr) (ptr->xor_0000) +#define r_icr(ptr) (ptr->xor_0001) +#define w_icr(ptr) (ptr->xor_0001) +#define rw_mr(ptr) (ptr->xor_0002) +#define r_tcr(ptr) (ptr->xor_0003) +#define w_tcr(ptr) (ptr->xor_0003) +#define r_cscr(ptr) (ptr->xor_2000) +#define w_ser(ptr) (ptr->xor_2000) +#define r_bsr(ptr) (ptr->xor_2001) +#define w_sdsr(ptr) (ptr->xor_2001) +#define r_idr(ptr) (ptr->xor_2002) +#define w_sdtr(ptr) (ptr->xor_2002) +#define r_rpir(ptr) (ptr->xor_2003) +#define w_sdir(ptr) (ptr->xor_2003) +#define pas_data(ptr) (ptr->xor_4000) +#define pas_stat(ptr) (ptr->xor_4001) +#define R_PAS_STAT_DREQ 0x80 +#define pas_irq(ptr) (ptr->xor_4003) + +/* + * The actual macros used to access the chip + */ #define P_PAS struct pas_softc * #define R_PAS(ptr,foo) inb(foo(ptr)) #define W_PAS(ptr,foo,val) outb(foo(ptr),val) #define M_PAS(ptr,foo,opr,arg) outb(foo(ptr),R_PAS(ptr,foo) opr arg) -#define PSEUDO_DMA 0 -#if PSEUDO_DMA -/* -static int sci_pdma_out(P_PAS, int, int, u_char *); -*/ -#define sci_pdma_out sci_data_out -static int sci_pdma_in(P_PAS, int, int, u_char *); -#else /* PSEUDO_DMA */ -#define sci_pdma_out sci_data_out -#define sci_pdma_in sci_data_in -#endif /* PSEUDO_DMA */ - - - -static int pas_foo; -#define SCI_CLR_INTR(ptr) {pas_foo += R_PAS(ptr,sci_iack);} -#define SCI_PHASE_DISC 0 /* sort of ... */ -#define SCI_ACK(ptr,phase) {W_PAS(ptr,sci_tcmd,phase);} -#define SCSI_TIMEOUT_VAL 10000000 #define WAIT_FOR_NOT_REQ(ptr) { \ - int scsi_timeout = SCSI_TIMEOUT_VAL; \ - while ( (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \ - (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \ - (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \ + int scsi_timeout = PAS16_TIMEOUT; \ + while ( (R_PAS(ptr,r_cscr) & R_CSCR_REQ) && \ + (R_PAS(ptr,r_cscr) & R_CSCR_REQ) && \ + (R_PAS(ptr,r_cscr) & R_CSCR_REQ) && \ (--scsi_timeout) ); \ if (!scsi_timeout) { \ printf("scsi timeout--WAIT_FOR_NOT_REQ-- pas.c:%d.\n", __LINE__); \ @@ -145,44 +203,27 @@ static int pas_foo; } \ } #define WAIT_FOR_REQ(ptr) { \ - int scsi_timeout = SCSI_TIMEOUT_VAL; \ - while ( ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \ - ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \ - ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \ + int scsi_timeout = PAS16_TIMEOUT; \ + while ( ((R_PAS(ptr,r_cscr) & R_CSCR_REQ) == 0) && \ + ((R_PAS(ptr,r_cscr) & R_CSCR_REQ) == 0) && \ + ((R_PAS(ptr,r_cscr) & R_CSCR_REQ) == 0) && \ (--scsi_timeout) ); \ if (!scsi_timeout) { \ printf("scsi timeout--WAIT_FOR_REQ-- pas.c:%d.\n", __LINE__); \ goto scsi_timeout_error; \ } \ } -#define WAIT_FOR_BSY(ptr) { \ - int scsi_timeout = SCSI_TIMEOUT_VAL; \ - while ( ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \ - ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \ - ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \ - (--scsi_timeout) ); \ - if (!scsi_timeout) { \ - printf("scsi timeout--WAIT_FOR_BSY-- pas.c:%d.\n", __LINE__); \ - goto scsi_timeout_error; \ - } \ -} static u_int32 pas_adapter_info(int adapter_number); static void pas_minphys(struct buf *bp); static int32 pas_scsi_cmd(struct scsi_xfer *xs); - -static int pas_reset_target(int adapter, int target); -static int pas_poll(int adapter, int timeout); +static int pas_reset(int); static int pas_send_cmd(struct scsi_xfer *xs); static int scsi_req(P_PAS,int,int,u_char *,int, u_char *, int , int *, int *); - -static int scsi_group0(int adapter, int id, int lun, - int opcode, int addr, int len, - int flags, caddr_t databuf, int datalen); - -static int sci_data_out(P_PAS, int, int, u_char *); -static int sci_data_in(P_PAS, int, int, u_char *); +static int sci_data_out(P_PAS, int, int, u_char *); +static int sci_data_in(P_PAS, int, int, u_char *); +static int select_target(P_PAS, int); extern int pasprobe(struct isa_device *dev); extern int pasattach(struct isa_device *dev); @@ -196,7 +237,7 @@ struct scsi_adapter pas_adapter = { 0, /* open_target_lu() */ 0, /* close_target_lu() */ pas_adapter_info, /* adapter_info() */ -"pas", /* name */ + "pas", /* name */ { 0, 0 } /* spare[2] */ }; @@ -211,8 +252,8 @@ struct scsi_device pas_dev = { { 0, 0 } }; -static char *mv_type[] = { "?" "PAS","PAS+","CDPC","PAS16C","PAS16D" }; - +static char *mv_type[] = { + 0,0,0,0,0,0,"PAS+",0,0,0,0,0,"PAS16D",0,"CDPC","PAS16"}; int pasprobe(struct isa_device *dev) @@ -222,34 +263,40 @@ pasprobe(struct isa_device *dev) int unit = dev->id_unit; int i, j; + if(base & 3) { + printf("pas%d cannot operate on address %x.", unit,port); + printf(" Address must be a multiple of four.\n"); + return 0; + } /* Tell the PAS16 we want to talk to, where to listen */ outb(0x9a01,0xbc + unit); outb(0x9a01,base >> 2); - /* Various magic */ - outb(base+0x4000,0x30); - outb(base+0x4001,0x01); - outb(base+0xbc00,0x01); - + printf("%x: 0x803=%x 0xec03=%x 0xff88=%x\n", + base,inb(base^0x803),inb(base^0xec03),inb(base^0xfc00)); + /* Killer one */ - i = inb(base + 0x803); + i = inb(base ^ 0x803); if(i == 0xff) return 0; /* killer two */ - outb(base+0x803,i ^ 0xe0); - j = inb(base + 0x803); - outb(base+0x803,1); - if(i != j) return 0; - - /* killer three */ - if((0x03 & inb(base+0xec03)) != 0x03) return 0; + if((0x03 & inb(base^0xec03)) != 0x03) return 0; - /* killer four */ + /* killer three */ for(i=0;i<4;i++) { - if(inb(port) != 0xff || inb(port+0x2000) != 0xff) - return 1; + if(inb(port) != 0xff || inb(port^0x2000) != 0xff) + goto ok; } return 0; +ok: + /* killer four */ + i = inb(base ^ 0x803); + outb(base^0x803,i ^ 0xe0); + j = inb(base^0x803); + outb(base^0x803,1); + if(i != j) return 0; + + return 1; } static u_int32 @@ -261,47 +308,35 @@ pas_adapter_info(int adapter_number) int pasattach(struct isa_device *dev) { - int i,j; + int i,base=dev->id_iobase-0x1c00; struct pas_softc *ppas; - i = inb(dev->id_iobase - 0x1c00 + 0xFC00) >> 5; - if(i >= (sizeof mv_type / sizeof *mv_type)) - j=0; - else - j = i+1; - printf("pas%d: Type = %d <%s>\n",dev->id_unit,i,mv_type[j]); + i = inb(base^0xEC03) & 0x0f; + printf("pas%d: Type = %d <%s>\n",dev->id_unit,i,mv_type[i]); ppas = s_pas + dev->id_unit; ppas->sc_link.adapter_unit = dev->id_unit; ppas->sc_link.adapter_targ = 7; ppas->sc_link.adapter = &pas_adapter; ppas->sc_link.device = &pas_dev; ppas->iobase=dev->id_iobase; -#ifdef STILL_NO_INTR -/* As of yet we havn't bothered with interrupts, so don't bother */ - j = inb(dev->id_iobase - 0x1c00 + 0xf002); - switch (dev->id_irq) { - case IRQ2: i=1; break; - case IRQ3: i=2; break; - case IRQ4: i=3; break; - case IRQ5: i=4; break; - case IRQ6: i=5; break; - case IRQ7: i=6; break; - case IRQ10: i=7; break; - case IRQ11: i=8; break; - case IRQ12: i=9; break; - case IRQ14: i=10; break; - case IRQ15: i=11; break; - default: - printf("Intr %d unknown\n",dev->id_irq); - panic("brag!"); - } - printf("0xf002 irq%d code=%x, before %x,",dev->id_irq,i,j); - j &= 0x0f; - j |= (i << 4); - printf(" after= %x \n",j); - outb(dev->id_iobase - 0x1c00 + 0xf002,j); - outb(dev->id_iobase - 0x1c00 + 0x8003,0x4d); -#endif /* STILL_NO_INTR */ + ppas->xor_0001 = ppas->iobase^0x0001; + ppas->xor_0002 = ppas->iobase^0x0002; + ppas->xor_0003 = ppas->iobase^0x0003; + ppas->xor_2000 = ppas->iobase^0x2000; + ppas->xor_2001 = ppas->iobase^0x2001; + ppas->xor_2002 = ppas->iobase^0x2002; + ppas->xor_2003 = ppas->iobase^0x2003; + ppas->xor_4000 = ppas->iobase^0x4000; + ppas->xor_4001 = ppas->iobase^0x4001; + ppas->xor_4003 = ppas->iobase^0x4003; + + /* Various magic */ + outb(base^0x4000,0x30); + outb(base^0x4001,0x01); + outb(base^0xbc00,0x01); + outb(base^0x8003,0x4d); + scsi_attachdevs(&(ppas->sc_link)); + pas_reset(dev->id_unit); return 1; } @@ -336,30 +371,14 @@ pas_scsi_cmd(struct scsi_xfer *xs) printf("flags & SCSIRESET.\n"); if ( ! ( flags & SCSI_NOSLEEP ) ) { s = splbio(); - pas_reset_target(xs->sc_link->adapter_unit, - xs->sc_link->target); + pas_reset(xs->sc_link->adapter_unit); splx(s); return(SUCCESSFULLY_QUEUED); } else { - pas_reset_target(xs->sc_link->adapter_unit, xs->sc_link->target); - if (pas_poll(xs->sc_link->adapter_unit, xs->timeout)) { - return (HAD_ERROR); - } + pas_reset(xs->sc_link->adapter_unit); return (COMPLETE); } } - /* - * OK. Now that that's over with, let's pack up that - * SCSI puppy and send it off. If we can, we'll just - * queue and go; otherwise, we'll wait for the command - * to finish. - if ( ! ( flags & SCSI_NOSLEEP ) ) { - s = splbio(); - pas_send_cmd(xs); - splx(s); - return(SUCCESSFULLY_QUEUED); - } - */ r = pas_send_cmd(xs); xs->flags |= ITSDONE; @@ -380,7 +399,8 @@ pas_show_scsi_cmd(struct scsi_xfer *xs) if ( ! ( xs->flags & SCSI_RESET ) ) { printf("pas(%d:%d:%d) ", xs->sc_link->adapter_unit, xs->sc_link->target, xs->sc_link->lun); - printf("%d@%x, %d@%x <",xs->cmdlen,xs->cmd,xs->datalen,xs->data); + printf("%d@%x, %d@%x <",xs->cmdlen,(u_long)xs->cmd, + xs->datalen,(u_long)xs->data); while (i < xs->cmdlen) { if (i) printf(","); printf("%x",b[i++]); @@ -395,55 +415,21 @@ pas_show_scsi_cmd(struct scsi_xfer *xs) } #endif /* PAS_DEBUG */ -/* - * Actual chip control. - */ - -extern void -pasintr(int adapter) -{ - struct pas_softc *ppas = s_pas + adapter; - printf ("pasintr\n"); - SCI_CLR_INTR(ppas); - W_PAS(ppas,sci_mode,0x00); -} - -#if PHK -extern int -scsi_irq_intr(void) -{ - -/* if (R_PAS(ptr,sci_csr) != SCI_CSR_PHASE_MATCH) - printf("scsi_irq_intr called (not just phase match -- " - "csr = 0x%x, bus_csr = 0x%x).\n", - R_PAS(ptr,sci_csr), R_PAS(ptr,sci_bus_csr)); - pas_intr(0); */ - return 1; -} -#endif - static int -pas_reset_target(int adapter, int target) +pas_reset(int adapter) { struct pas_softc *ppas = s_pas + adapter; - W_PAS(ppas,sci_icmd,SCI_ICMD_TEST); - W_PAS(ppas,sci_icmd,SCI_ICMD_TEST | SCI_ICMD_RST); - DELAY(2500); - W_PAS(ppas,sci_icmd,0); + /* + * Reset Hold Time is 25 uSec + */ + W_PAS(ppas,w_icr,W_ICR_ASSERT_RST); + DELAY(25); + W_PAS(ppas,w_icr,0); - W_PAS(ppas,sci_mode,0); - W_PAS(ppas,sci_tcmd,SCI_PHASE_DISC); - W_PAS(ppas,sci_sel_enb,0); + W_PAS(ppas,rw_mr,0); + W_PAS(ppas,w_ser,0); - SCI_CLR_INTR(ppas); - SCI_CLR_INTR(ppas); - return 0; -} - -static int -pas_poll(int adapter, int timeout) -{ return 0; } @@ -453,6 +439,7 @@ pas_send_cmd(struct scsi_xfer *xs) P_PAS ptr = s_pas + xs->sc_link->adapter_unit; int s,sent,ret; int sense; + u_char cmd[6]; #ifdef PAS_DEBUG pas_show_scsi_cmd(xs); @@ -463,182 +450,281 @@ pas_send_cmd(struct scsi_xfer *xs) (u_char*)xs->cmd, xs->cmdlen, xs->data, xs->datalen, &sent, &ret); splx(s); -#ifdef PAS_DEBUG -HERE(); - printf("sent=%d,ret=%d,sense=%x ",sent,ret,sense); -#endif /* PAS_DEBUG */ switch (sense) { case 0x00: xs->error = XS_NOERROR; xs->resid = sent; -#ifdef PAS_DEBUG - printf("\n"); -#endif /* PAS_DEBUG */ return (COMPLETE); case 0x02: /* Check condition */ -#ifdef PAS_DEBUG - printf("check cond. targ= %d.\n", xs->sc_link->target); -#endif - spinwait(10); + +#ifdef PAS_DEBUG_REQUEST_SENSE + printf("pas%d, target%d: sent=%d,ret=%d,sense=%x check. cond.\n", + xs->sc_link->adapter_unit, xs->sc_link->target,sent,ret,sense); + printf("Cmd:<%x",((u_char*)(xs->cmd))[0]); + for(sent=1;sent < sizeof xs->cmdlen;sent++) { + printf(",%x",((u_char*)(xs->cmd))[sent]); + } + printf(">\n"); +#endif /* PAS_DEBUG_REQUEST_SENSE */ + cmd[0] = 3; + cmd[1] = xs->sc_link->lun<<5; + cmd[2] = 0; + cmd[3] = 0; + cmd[4] = sizeof xs->sense; + cmd[5] = 0; + + DELAY(10); s = splbio(); - scsi_group0(xs->sc_link->adapter_unit, - xs->sc_link->target, xs->sc_link->lun, - 0x3, 0x0, - sizeof(struct scsi_sense_data), - 0, (caddr_t) &(xs->sense), - sizeof(struct scsi_sense_data)); + scsi_req(ptr, xs->sc_link->target, xs->sc_link->lun, + cmd, sizeof cmd, + (caddr_t) &(xs->sense), sizeof xs->sense, + &sent, &ret); splx(s); +#ifdef PAS_DEBUG_REQUEST_SENSE + printf("Sense result: (sent=%d, ret=%d)\n",sent,ret); + printf("<%x",((u_char*)(&xs->sense))[0]); + for(sent=1;sent < sizeof xs->sense;sent++) { + printf(",%x",((u_char*)(&xs->sense))[sent]); + } + printf(">\n"); +#endif /* PAS_DEBUG_REQUEST_SENSE */ xs->error = XS_SENSE; return HAD_ERROR; case 0x08: /* Busy */ -ARGH(); xs->error = XS_BUSY; return HAD_ERROR; default: -ARGH(); xs->error = XS_DRIVER_STUFFUP; return HAD_ERROR; } } -static int -select_target(P_PAS ptr, u_char myid, u_char tid, int with_atn) -{ - register u_char bid, icmd; - int ret = SCSI_RET_RETRY; - if ((R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL))) - return ret; +/* + * Perform arbitration and selection. Figure 5-1, more or less. + */ - /* for our purposes.. */ +static int +select_target(P_PAS ptr, int tid) +{ + int myid = ptr->sc_link.adapter_targ; + int ret = SCSI_RET_RETRY; + int tries = ATTEMPT_SELECTION; + int delay = SELECTION_DELAY; + int i; + + /* + * Convert the ID's to bit-maps. + */ myid = 1 << myid; tid = 1 << tid; - W_PAS(ptr,sci_sel_enb,0); /* we don't want any interrupts. */ - W_PAS(ptr,sci_tcmd,0); /* get into a harmless state */ - W_PAS(ptr,sci_mode,0); /* get into a harmless state */ + /* + * Not documented, but clearly needed for now. + * XXX is this missing somewhere else, and this is just a hack ? + */ +loop: + W_PAS(ptr,w_tcr,0); - W_PAS(ptr,sci_odata,myid); - W_PAS(ptr,sci_mode,SCI_MODE_ARB); - /* AIP might not set if BSY went true after we checked */ - for (bid = 0; bid < 20; bid++) /* 20usec circa */ - if (R_PAS(ptr,sci_icmd) & SCI_ICMD_AIP) - break; - if ((R_PAS(ptr,sci_icmd) & SCI_ICMD_AIP) == 0) { -ARGH(); + /* + * Write ID Bit to Output Register. + */ + W_PAS(ptr,w_odr,myid); + + /* + * Set "ARBITRATE" Bit. + */ + W_PAS(ptr,rw_mr,RW_MR_ARBITRATE); + + /* + * Check "Arbitration in progress" Bit. + */ + for (i = 0; i < 20; i++) /* 20usec circa */ + if (R_PAS(ptr,r_icr) & R_ICR_ARBITRATION_IN_PROGRESS) + goto aip; + goto lost; + +aip: + /* + * Wait 2.2 usec Arbitration Delay. + */ + DELAY(2); + + /* + * Check "Lost Arbitration" Bit. + */ + if (R_PAS(ptr,r_icr) & R_ICR_LOST_ARBITRATION) goto lost; - } - spinwait(2 /* was 2 */); /* 2.2us arb delay */ - - if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) { -printf ("lost 1\n"); + /* + * Higher priority ID present ? + */ + if ((R_PAS(ptr,r_csdr) & ~myid) > myid) goto lost; - } - M_PAS(ptr,sci_mode,&, ~SCI_MODE_PAR_CHK); - bid = R_PAS(ptr,sci_data); - - if ((bid & ~myid) > myid) { -printf ("lost 2\n"); + /* + * Check "Lost Arbitration" Bit. + */ + if (R_PAS(ptr,r_icr) & R_ICR_LOST_ARBITRATION) goto lost; - } - if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) { -printf ("lost 3\n"); - goto lost; - } - /* Won arbitration, enter selection phase now */ - icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); - icmd |= SCI_ICMD_BSY; - W_PAS(ptr,sci_icmd,icmd); + /* + * Set "Assert SEL/". + */ + W_PAS(ptr,w_icr,W_ICR_ASSERT_SEL); - if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) { -printf ("nosel\n"); + /* + * Check "Lost Arbitration" Bit. + */ + if (R_PAS(ptr,r_icr) & R_ICR_LOST_ARBITRATION) { goto nosel; } - /* XXX a target that violates specs might still drive the bus XXX */ - /* XXX should put our id out, and after the delay check nothi XXX */ - /* XXX ng else is out there. XXX */ + /* + * Wait 1.2 usec minimum. (Bus Clear + Settle) + */ + DELAY(2); - DELAY(0); + /* + * Write Target and Initiator's ID bits to output Register. + */ + W_PAS(ptr,w_odr,myid|tid); - W_PAS(ptr,sci_tcmd,0); - W_PAS(ptr,sci_odata,myid|tid); - W_PAS(ptr,sci_sel_enb,0); + /* + * Set "Assert BSY/" + "Assert Data Bus". + */ + W_PAS(ptr,w_icr, + W_ICR_ASSERT_SEL | W_ICR_ASSERT_BSY | W_ICR_ASSERT_DATA_BUS); - M_PAS(ptr,sci_mode, &, ~SCI_MODE_ARB); /* 2 deskew delays, too */ - W_PAS(ptr,sci_mode,0); + /* + * Reset "ARBITRATE" Bit. + */ + W_PAS(ptr,rw_mr,0); + + /* + * Reset "Select Enable" Register. + */ + W_PAS(ptr,w_ser,0); - icmd |= SCI_ICMD_DATA; - icmd &= ~(SCI_ICMD_BSY); + /* + * Reset "Assert BSY/". + */ + W_PAS(ptr,w_icr, + W_ICR_ASSERT_SEL | W_ICR_ASSERT_DATA_BUS); - W_PAS(ptr,sci_icmd,icmd); - - /* bus settle delay, 400ns */ - DELAY(2); /* too much (was 2) ? */ - -/* M_PAS(ptr,sci_mode, |, SCI_MODE_PAR_CHK); */ - - { - register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ - while ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) { - if (--timeo > 0) { - DELAY(100); - } else { -ARGH(); - goto nodev; - } - } + /* + * "BSY/" Asserted within 250 msec ? + */ + for(i=0;i<250000;i+=100) { + if (R_PAS(ptr,r_cscr) & R_CSCR_BSY) + goto resp; + DELAY(100); } + goto nodev; +resp: + + /* + * Reset "Assert SEL/" + "Assert Data Bus". + */ + W_PAS(ptr,w_icr,0); - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); - W_PAS(ptr,sci_icmd,icmd); -/* ptr->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ return SCSI_RET_SUCCESS; + nodev: ret = SCSI_RET_DEVICE_DOWN; - W_PAS(ptr,sci_sel_enb,myid); + nosel: - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); - W_PAS(ptr,sci_icmd,icmd); + W_PAS(ptr,w_icr,0); + lost: - W_PAS(ptr,sci_mode,0); + W_PAS(ptr,rw_mr,0); + if(--tries) { + DELAY(delay); + goto loop; + } return ret; } +/* + * Figure 5-2. + */ +int PHK; static int sci_data_out(P_PAS ptr, int phase, int count, u_char *data) { register unsigned char icmd; - register int cnt=0; + register int cnt=0,zonk; -#ifdef PAS_DEBUG - printf("out%d@%x ",count,data); -#endif /* PAS_DEBUG */ - /* ..checks.. */ - - icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); -loop: - if (SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)) != phase) + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) return cnt; - WAIT_FOR_REQ(ptr); - icmd |= SCI_ICMD_DATA; - W_PAS(ptr,sci_icmd,icmd); - W_PAS(ptr,sci_odata, *data++); - icmd |= SCI_ICMD_ACK; - W_PAS(ptr,sci_icmd,icmd); + icmd = R_PAS(ptr,r_icr) & RW_ICR_MASK; - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); +#ifndef NO_PAS16_PSEUDO_DMA + /* + * The PAS16 has special provisions for doing pseudo-dma. + */ + + /* + * Don't use pseudo-dma unless we need much data. This way we avoid all + * the variable length stuff entirely. + * + * XXX something screws up for big transfers :-( + */ + + if(count >= 128 && count <= 8192) { + + M_PAS(ptr,rw_mr,|,RW_MR_DMA_MODE); + + W_PAS(ptr,w_icr,icmd | W_ICR_ASSERT_DATA_BUS); + + W_PAS(ptr,w_sdsr,0); + + while(count >= PAS16_PSEUDO_DMA_SIZE) { + zonk=0; + while(!(R_PAS(ptr,pas_stat) & R_PAS_STAT_DREQ)) + if (++zonk > 1000 || SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) + return cnt; + + outsb(pas_data(ptr),data,PAS16_PSEUDO_DMA_SIZE); + + data += PAS16_PSEUDO_DMA_SIZE; + cnt += PAS16_PSEUDO_DMA_SIZE; + count -= PAS16_PSEUDO_DMA_SIZE; + + } + + if(count) { + while(!(R_PAS(ptr,pas_stat) & R_PAS_STAT_DREQ)) + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) + return cnt; + outsb(pas_data(ptr),data,count); + cnt += count; + data += count; + } + + M_PAS(ptr,rw_mr,&,~RW_MR_DMA_MODE); + W_PAS(ptr,w_icr,icmd); + return cnt; + } +#endif /* NO_PAS16_PSEUDO_DMA */ +loop: + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) + return cnt; + + W_PAS(ptr,w_odr, *data); + WAIT_FOR_REQ(ptr); + icmd |= W_ICR_ASSERT_DATA_BUS; + W_PAS(ptr,w_icr,icmd); + icmd |= W_ICR_ASSERT_ACK; + W_PAS(ptr,w_icr,icmd); + + icmd &= ~(W_ICR_ASSERT_DATA_BUS|W_ICR_ASSERT_ACK); WAIT_FOR_NOT_REQ(ptr); - W_PAS(ptr,sci_icmd,icmd); + W_PAS(ptr,w_icr,icmd); ++cnt; + data++; if (--count > 0) goto loop; scsi_timeout_error: @@ -648,29 +734,70 @@ scsi_timeout_error: static int sci_data_in(P_PAS ptr, int phase, int count, u_char *data) { - register unsigned char icmd; - register int cnt=0; + unsigned char icmd; + int cnt=0; -#ifdef PAS_DEBUG - printf("in%d@%x ",count,data); -#endif /* PAS_DEBUG */ - /* ..checks.. */ + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) + return cnt; - icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); +#ifndef NO_PAS16_PSEUDO_DMA + /* + * The PAS16 has special provisions for doing pseudo-dma. + */ + + /* + * Don't use pseudo-dma unless we need much data. This way we avoid all + * the variable length stuff entirely. + */ + if(count >= 128) { + + M_PAS(ptr,rw_mr,|,RW_MR_DMA_MODE); + + W_PAS(ptr,w_sdir,0); + + while(count > PAS16_PSEUDO_DMA_SIZE) { + while(!(R_PAS(ptr,pas_stat) & R_PAS_STAT_DREQ)) ; + + insb(pas_data(ptr),data,PAS16_PSEUDO_DMA_SIZE); + + data += PAS16_PSEUDO_DMA_SIZE; + cnt += PAS16_PSEUDO_DMA_SIZE; + count -= PAS16_PSEUDO_DMA_SIZE; + + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) + return cnt; + } + + while(!(R_PAS(ptr,pas_stat) & R_PAS_STAT_DREQ)) ; + + insb(pas_data(ptr),data,count-1); + cnt += count-1; + data += count-1; + + while(!(R_PAS(ptr,pas_stat) & R_PAS_STAT_DREQ)) ; + while((R_PAS(ptr,r_cscr) & R_CSCR_REQ)); + *data = R_PAS(ptr,r_idr); + cnt++; + M_PAS(ptr,rw_mr,&,~RW_MR_DMA_MODE); + return cnt; + } +#endif /* NO_PAS16_PSEUDO_DMA */ + + icmd = R_PAS(ptr,r_icr) & RW_ICR_MASK; loop: - if (SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)) != phase) + if (SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)) != phase) return cnt; WAIT_FOR_REQ(ptr); - *data++ = R_PAS(ptr,sci_data); + *data++ = R_PAS(ptr,r_csdr); - icmd |= SCI_ICMD_ACK; - W_PAS(ptr,sci_icmd,icmd); + icmd |= W_ICR_ASSERT_ACK; + W_PAS(ptr,w_icr,icmd); + icmd &= ~W_ICR_ASSERT_ACK; - icmd &= ~SCI_ICMD_ACK; WAIT_FOR_NOT_REQ(ptr); - W_PAS(ptr,sci_icmd,icmd); + W_PAS(ptr,w_icr,icmd); ++cnt; if (--count > 0) goto loop; @@ -679,57 +806,23 @@ scsi_timeout_error: return cnt; } -#if PSEUDO_DMA - -static int -sci_pdma_in(P_PAS ptr, int phase, int count, u_char *data) -{ - register unsigned char icmd; - register int cnt=0; - -#ifdef PAS_DEBUG - printf("in%d@%x ",count,data); -#endif /* PAS_DEBUG */ - - WAIT_FOR_BSY(ptr); - M_PAS(ptr,sci_mode, |, SCI_MODE_DMA); - W_PAS(ptr,sci_dma_send, 0); - M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA); - -/* - while(R_PAS(ptr,sci_pdmastat) & 0x80) ; -*/ - - for(; cnt < count; cnt++) - *data++ = R_PAS(ptr,sci_pdmadata); - -scsi_timeout_error: - M_PAS(ptr,sci_mode, &, ~SCI_MODE_DMA); - M_PAS(ptr,sci_icmd, &, ~SCI_ICMD_DATA); - return cnt; -} -#endif /* PSEUDO_DMA */ static int cmd_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg) { int xfer=0, phase; -#ifdef PAS_DEBUG - printf("cmd_xfer called for 0x%x.\n", *data); -#endif /* PAS_DEBUG */ - - W_PAS(ptr,sci_icmd,0); + W_PAS(ptr,w_icr,0); while (1) { WAIT_FOR_REQ(ptr); - phase = SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)); + phase = SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)); switch (phase) { case SCSI_PHASE_CMD: - SCI_ACK(ptr,SCSI_PHASE_CMD); + W_PAS(ptr,w_tcr,SCSI_PHASE_CMD); xfer += sci_data_out(ptr, SCSI_PHASE_CMD, maxlen, data); return xfer; case SCSI_PHASE_DATA_IN: @@ -739,17 +832,17 @@ cmd_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg) printf("Data out phase in cmd_xfer?\n"); return 0; case SCSI_PHASE_STATUS: - SCI_ACK(ptr,SCSI_PHASE_STATUS); + W_PAS(ptr,w_tcr,SCSI_PHASE_STATUS); printf("status in cmd_xfer.\n"); sci_data_in(ptr, SCSI_PHASE_STATUS, 1, status); break; case SCSI_PHASE_MESSAGE_IN: - SCI_ACK(ptr,SCSI_PHASE_MESSAGE_IN); + W_PAS(ptr,w_tcr,SCSI_PHASE_MESSAGE_IN); printf("msgin in cmd_xfer.\n"); sci_data_in(ptr, SCSI_PHASE_MESSAGE_IN, 1, msg); break; case SCSI_PHASE_MESSAGE_OUT: - SCI_ACK(ptr,SCSI_PHASE_MESSAGE_OUT); + W_PAS(ptr,w_tcr,SCSI_PHASE_MESSAGE_OUT); sci_data_out(ptr, SCSI_PHASE_MESSAGE_OUT, 1, msg); break; default: @@ -766,7 +859,7 @@ data_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg) { int retlen = 0, xfer, phase; - W_PAS(ptr,sci_icmd,0); + W_PAS(ptr,w_icr,0); *status = 0; @@ -774,29 +867,29 @@ data_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg) WAIT_FOR_REQ(ptr); - phase = SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)); + phase = SCSI_CUR_PHASE(R_PAS(ptr,r_cscr)); switch (phase) { case SCSI_PHASE_CMD: printf("Command phase in data_xfer().\n"); return retlen; case SCSI_PHASE_DATA_IN: - SCI_ACK(ptr,SCSI_PHASE_DATA_IN); - xfer = sci_pdma_in (ptr, SCSI_PHASE_DATA_IN, maxlen, data); + W_PAS(ptr,w_tcr,SCSI_PHASE_DATA_IN); + xfer = sci_data_in (ptr, SCSI_PHASE_DATA_IN, maxlen, data); retlen += xfer; maxlen -= xfer; break; case SCSI_PHASE_DATA_OUT: - SCI_ACK(ptr,SCSI_PHASE_DATA_OUT); - xfer = sci_pdma_out (ptr, SCSI_PHASE_DATA_OUT, maxlen, data); + W_PAS(ptr,w_tcr,SCSI_PHASE_DATA_OUT); + xfer = sci_data_out (ptr, SCSI_PHASE_DATA_OUT, maxlen, data); retlen += xfer; maxlen -= xfer; break; case SCSI_PHASE_STATUS: - SCI_ACK(ptr,SCSI_PHASE_STATUS); + W_PAS(ptr,w_tcr,SCSI_PHASE_STATUS); sci_data_in(ptr, SCSI_PHASE_STATUS, 1, status); break; case SCSI_PHASE_MESSAGE_IN: - SCI_ACK(ptr,SCSI_PHASE_MESSAGE_IN); + W_PAS(ptr,w_tcr,SCSI_PHASE_MESSAGE_IN); sci_data_in(ptr, SCSI_PHASE_MESSAGE_IN, 1, msg); if (*msg == 0) { return retlen; @@ -805,7 +898,7 @@ data_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg) } break; case SCSI_PHASE_MESSAGE_OUT: - SCI_ACK(ptr,SCSI_PHASE_MESSAGE_OUT); + W_PAS(ptr,w_tcr,SCSI_PHASE_MESSAGE_OUT); sci_data_out(ptr, SCSI_PHASE_MESSAGE_OUT, 1, msg); break; default: @@ -824,15 +917,13 @@ scsi_req(P_PAS ptr, int target, int lun, u_char *cmd, int cmdlen, { /* Returns 0 on success, -1 on internal error, or the status byte */ int cmd_bytes_sent, r; - u_char stat, msg, c; + u_char stat, msg, c; *sent = 0; - if ( ( r = select_target(ptr, 7, target, 1) ) != SCSI_RET_SUCCESS) { - *ret = r; - SCI_CLR_INTR(ptr); + if ( ( r = select_target(ptr, target) ) != SCSI_RET_SUCCESS) { + *ret = r; switch (r) { case SCSI_RET_RETRY: -ARGH(); return 0x08; default: printf("select_target(target %d, lun %d) failed(%d).\n", @@ -844,10 +935,7 @@ ARGH(); c = 0x80 | lun; - if ((cmd_bytes_sent = cmd_xfer(ptr, cmdlen, cmd, &stat, &c)) - != cmdlen) { -ARGH(); - SCI_CLR_INTR(ptr); + if ((cmd_bytes_sent = cmd_xfer(ptr, cmdlen, cmd, &stat, &c)) != cmdlen) { *ret = SCSI_RET_COMMAND_FAIL; printf("Data underrun sending CCB (%d bytes of %d, sent).\n", cmd_bytes_sent, cmdlen); @@ -857,155 +945,7 @@ ARGH(); *sent=data_xfer(ptr, datalen, databuf, &stat, &msg); *ret = 0; -#ifdef PAS_DEBUG - printf("scsi_req,stat=0x%x ",stat); -#endif /* PAS_DEBUG */ return stat; } -static int -scsi_group0(int adapter, int id, int lun, - int opcode, int addr, int len, - int flags, caddr_t databuf, int datalen) -{ - P_PAS ptr = s_pas + adapter; - unsigned char cmd[6]; - int i,sent,ret; - - cmd[0] = opcode; /* Operation code */ - cmd[1] = (lun<<5) | ((addr>>16) & 0x1F); /* Lun & MSB of addr */ - cmd[2] = (addr >> 8) & 0xFF; /* addr */ - cmd[3] = addr & 0xFF; /* LSB of addr */ - cmd[4] = len; /* Allocation length */ - cmd[5] = flags; /* Link/Flag */ - - i = scsi_req(ptr, id, lun, cmd, 6, databuf, datalen, &sent, &ret); - - return i; -} - -/* pseudo-dma action */ - -#if 0 && PSEUDO_DMA - -static int pas_debug=1; -#define W1 *byte_data = *data++ -#define W4 *long_data = *((long*)data)++ - -int -sci_pdma_out(ptr, phase, count, data) - P_PAS ptr; - int phase; - int count; - u_char *data; -{ - register volatile long *long_data = sci_4byte_addr; - register volatile u_char *byte_data = sci_1byte_addr; - register int len = count, i; - -pas_debug=1; - - if (count < 128) - return sci_data_out(ptr, phase, count, data); - - WAIT_FOR_BSY(ptr); - M_PAS(ptr,sci_mode, |, SCI_MODE_DMA); - M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA); - W_PAS(ptr,sci_dma_send,0); - - while ( len >= 64 ) { - READY(1); W1; READY(1); W1; READY(1); W1; READY(1); W1; - READY(1); - W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4; - len -= 64; - } - while (len) { - READY(1); - W1; - len--; - } - i = TIMEOUT; - while ( ((R_PAS(ptr,sci_csr) & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) - == SCI_CSR_PHASE_MATCH) && --i); - if (!i) - printf("pas.c:%d: timeout waiting for SCI_CSR_DREQ.\n", __LINE__); - *byte_data = 0; -scsi_timeout_error: - M_PAS(ptr,sci_mode,&, ~SCI_MODE_DMA); - return count-len; -} - -#undef W1 -#undef W4 - -#define R4 *((long *)data)++ = *long_data -#define R1 *data++ = *byte_data - -int -sci_pdma_in(ptr, phase, count, data) - P_PAS ptr; - int phase; - int count; - u_char *data; -{ - register volatile long *long_data = sci_4byte_addr; - register volatile u_char *byte_data = sci_1byte_addr; - register int len = count, i; - -pas_debug=2; - if (count < 128) - return sci_data_in(ptr, phase, count, data); - -/* printf("Called sci_pdma_in(0x%x, 0x%x, %d, 0x%x.\n", ptr, phase, count, data); */ - - WAIT_FOR_BSY(ptr); - M_PAS(ptr,sci_mode, |, SCI_MODE_DMA); - M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA); - W_PAS(ptr,sci_irecv, 0); - - while (len >= 1024) { - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 256 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 384 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 512 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 640 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 768 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 896 */ - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /*1024 */ - len -= 1024; - } - while (len >= 128) { - READY(0); - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; - R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */ - len -= 128; - } - while (len) { - READY(0); - R1; - len--; - } -scsi_timeout_error: - M_PAS(ptr,sci_mode, &, ~SCI_MODE_DMA); - return count - len; -} -#undef R4 -#undef R1 -#endif #endif /* NPAS */