home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / scsi / atari_scsi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-07  |  21.8 KB  |  745 lines

  1. /*
  2.  * atari_scsi.c -- Device dependant functions for the Atari generic SCSI port
  3.  *
  4.  * Copyright 1994 Roman Hodek
  5.  *   EMail: rnhodek@cip.informatik.uni-erlangen.de (Internet)
  6.  *      or: Roman_Hodek@n.maus.de (MausNet, NO mail > 16 KB!)
  7.  *
  8.  *   Loosely based on the work of Robert De Vries' team and added:
  9.  *    - working real DMA
  10.  *    - Falcon support (untested yet!)   ++bjoern fixed and now it works
  11.  *    - lots of extensions and bug fixes.
  12.  *
  13.  * This file is subject to the terms and conditions of the GNU General Public
  14.  * License.  See the file README.legal in the main directory of this archive
  15.  * for more details.
  16.  *
  17.  */
  18.  
  19.  
  20. /**************************************************************************/
  21. /*                                                                        */
  22. /* Notes for Falcon SCSI:                                                 */
  23. /* ----------------------                                                 */
  24. /*                                                                        */
  25. /* Since the Falcon SCSI uses the ST-DMA chip, that is shared among       */
  26. /* several device drivers, locking and unlocking the access to this       */
  27. /* chip is required. But locking is not possible from an interrupt,       */
  28. /* since it puts the process to sleep if the lock is not available.       */
  29. /* This prevents "late" locking of the DMA chip, i.e. locking it just     */
  30. /* before using it, since in case of disconnection-reconnection           */
  31. /* commands, the DMA is started from the reselection interrupt.           */
  32. /*                                                                        */
  33. /* Two possible schemes for ST-DMA-locking would be:                      */
  34. /*  1) The lock is taken for each command separately and disconnecting    */
  35. /*     is forbidden (i.e. can_queue = 1).                                 */
  36. /*  2) The DMA chip is locked when the first command comes in and         */
  37. /*     released when the last command is finished and all queues are      */
  38. /*     empty.                                                             */
  39. /* The first alternative would result in bad performance, since the       */
  40. /* interleaving of commands would not be used. The second is unfair to    */
  41. /* other drivers using the ST-DMA, because the queues will seldom be      */
  42. /* totally empty if there is a lot of disk traffic.                       */
  43. /*                                                                        */
  44. /* For this reasons I decided to employ a more elaborate scheme:          */
  45. /*  - First, we give up the lock everytime we can (for fairness), this    */
  46. /*    means every time a command finishes and there are no other commands */
  47. /*    on the disconnected queue.                                          */
  48. /*  - If there are others waiting to lock the DMA chip, we stop           */
  49. /*    issueing commands, i.e. moving them onto the issue queue.           */
  50. /*    Because of that, the disconnected queue will run empty in a         */
  51. /*    while. Instead we go to sleep on a 'fairness_queue'.                */
  52. /*  - If the lock is released, all processes waiting on the fairness      */
  53. /*    queue will be woken. The first of them trys to re-lock the DMA,     */
  54. /*    the others wait for the first to finish this task. After that,      */
  55. /*    they can all run on and do their commands...                        */
  56. /* This sounds complicated (and it is it :-(), but it seems to be a       */
  57. /* good compromise between fairness and performance: As long as noone     */
  58. /* else wants to work with the ST-DMA chip, SCSI can go along as          */
  59. /* usual. If now someone else comes, this behaviour is changed to a       */
  60. /* "fairness mode": just already initiated commands are finished and      */
  61. /* then the lock is released. The other one waiting will probably win     */
  62. /* the race for locking the DMA, since it was waiting for longer. And     */
  63. /* after it has finished, SCSI can go ahead again. Finally: I hope I      */
  64. /* have not produced any deadlock possibilites!                           */
  65. /*                                                                        */
  66. /**************************************************************************/
  67.  
  68.  
  69.  
  70. #include <linux/config.h>
  71.  
  72. #ifdef CONFIG_ATARI_SCSI
  73.  
  74. /* #define NDEBUG (NDEBUG_DMA) */
  75.  
  76. #define AUTOSENSE
  77. /* For the Atari version, use only polled IO or REAL_DMA */
  78. #define    REAL_DMA
  79.  
  80. #if I_HAVE_OVERRUNS == 1 || I_HAVE_OVERRUNS == 2
  81. #define    READ_OVERRUNS
  82. #endif
  83.  
  84. #include <linux/stddef.h>
  85. #include <linux/interrupt.h>
  86. #include <linux/bootinfo.h>
  87. #include <linux/atarihw.h>
  88. #include <linux/atariints.h>
  89. #include "../block/blk.h"
  90. #include "scsi.h"
  91. #include "hosts.h"
  92. #include "atari_scsi.h"
  93. #include "NCR5380.h"
  94. #include "constants.h"
  95. #include <linux/atari_stdma.h>
  96.  
  97.  
  98. #define    IS_A_TT()    (boot_info.bi_atari.model == ATARI_TT)
  99.  
  100. #define    SCSI_DMA_WRITE_P(elt,val)                                    \
  101.     __asm__ __volatile__ ( "movepl %0,%1@(0)" : : "d" (val),        \
  102.                                "a" (&tt_scsi_dma.elt) );
  103.  
  104. #define    SCSI_DMA_READ_P(elt) ({                                            \
  105.     unsigned long __val;                                                \
  106.     __asm__ __volatile__ ( "movepl %1@(0),%0"                            \
  107.                            : "=d" (__val) : "a" (&tt_scsi_dma.elt));    \
  108.     __val; })
  109.  
  110. #define    SCSI_DMA_SETADR(adr)                    \
  111.     do {                                        \
  112.         unsigned long __adr = (adr);            \
  113.         st_dma.dma_lo = (unsigned char)__adr;    \
  114.         __adr >>= 8;                            \
  115.         st_dma.dma_md = (unsigned char)__adr;    \
  116.         __adr >>= 8;                            \
  117.         st_dma.dma_hi = (unsigned char)__adr;    \
  118.     } while(0)
  119.  
  120. #define    SCSI_DMA_GETADR() ({                    \
  121.     unsigned long    __adr;                        \
  122.     __adr = st_dma.dma_lo;                        \
  123.     __asm__ __volatile__ ("nop");                \
  124.     __adr |= (st_dma.dma_md & 0xff) << 8;        \
  125.     __adr |= (st_dma.dma_hi & 0xff) << 16;        \
  126.     __adr;                                        \
  127. })
  128.  
  129.  
  130.  
  131. /***************************** Prototypes *****************************/
  132.  
  133. static void scsi_dma_buserr( struct intframe *fp, void *data);
  134. static void scsi_tt_intr( struct intframe *fp, void *data);
  135. static void scsi_falcon_intr( struct intframe *fp, void *data);
  136. static void atari_scsi_fetch_restbytes( void );
  137. static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
  138.                                              hostdata );
  139. static void falcon_get_lock( void );
  140. static long atari_scsi_dma_residual( struct Scsi_Host *instance );
  141. static unsigned long atari_dma_xfer_len( unsigned long wanted_len );
  142. static unsigned char atari_scsi_tt_reg_read( unsigned char reg );
  143. static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value
  144.                                      );
  145. static unsigned char atari_scsi_falcon_reg_read( unsigned char reg );
  146. static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char
  147.                                          value );
  148.  
  149. /************************* End of Prototypes **************************/
  150.  
  151.  
  152. static struct Scsi_Host *atari_scsi_host = NULL;
  153. static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
  154. static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
  155.  
  156. #ifdef REAL_DMA
  157. static unsigned long    atari_dma_residual, atari_dma_startaddr;
  158. static short            atari_dma_active;
  159. #endif
  160.  
  161.  
  162. #if defined(REAL_DMA)
  163.  
  164. static void scsi_dma_buserr (struct intframe *fp, void *data)
  165.  
  166. {
  167.     if (tt_scsi_dma.dma_ctrl & 0x80) {
  168.         printk( "SCSI DMA caused bus error near 0x%08lx\n",
  169.                 SCSI_DMA_READ_P( dma_addr_hi ));
  170.         panic( "SCSI DMA bus error -- bad DMA programming!" );
  171.     }
  172.     else {
  173.         /* Under normal circumstances we never should get to this point,
  174.          * since both interrupts are triggered simultaneosly and the 5380
  175.          * int has more priotity. When this irq is handled, that DMA
  176.          * interrupt is cleared. So a warning message is printed here.
  177.          */
  178.         printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
  179.     }
  180. }
  181.  
  182. #endif
  183.  
  184. #undef    LOST_INTR
  185.  
  186. #ifdef LOST_INTR
  187. extern volatile unsigned long intr_count;
  188. unsigned long curr_intr_count;
  189.  
  190. #define    CHECK_ICNT(pos) do {                    \
  191.  if (intr_count != curr_intr_count) {            \
  192.      printk( "INTR_COUNT changed before " pos    \
  193.              ": curr_cnt=%lu intr_cnt=%lu\n",    \
  194.              curr_intr_count, intr_count );        \
  195.  }                                                \
  196. } while( 0 )
  197.  
  198. #else
  199.  
  200. #define    CHECK_ICNT(pos)
  201.  
  202. #endif
  203.  
  204.  
  205. static void scsi_tt_intr (struct intframe *fp, void *data)
  206.  
  207. {    int                dma_stat;
  208.     unsigned long    flags;
  209. #ifdef LOST_INTR
  210.     unsigned long    prev_intr_count;
  211.  
  212.     prev_intr_count = curr_intr_count;
  213.     curr_intr_count = intr_count;
  214. #endif
  215.     
  216. #ifdef REAL_DMA
  217.  
  218.     dma_stat = tt_scsi_dma.dma_ctrl;
  219.  
  220. #if (NDEBUG & NDEBUG_INTR)
  221.     printk( "scsi%d: NCR5380 interupt, DMA status = %02x\n",
  222.             atari_scsi_host->host_no, dma_stat & 0xff );
  223. #endif
  224.  
  225.     /* Look if it was the DMA that has interrupted: First possibility
  226.      * is that a bus error occured...
  227.      */
  228.     if (dma_stat & 0x80) {
  229.         printk( "SCSI DMA caused bus error near 0x%08lx\n",
  230.                 SCSI_DMA_READ_P( dma_addr_hi ));
  231.         panic( "SCSI DMA bus error -- bad DMA programming!" );
  232.     }
  233.  
  234.     /* If the DMA is active but not finished, we have the the case
  235.      * that some other 5380 interrupt occured within the DMA transfer.
  236.      * This means we have residual bytes, if the desired end address
  237.      * is not yet reached. Maybe we have to fetch some bytes from the
  238.      * rest data register, too. The residual must be calculated from
  239.      * the address pointer, not the counter register, because only the
  240.      * addr reg counts bytes not yet written and pending in the rest
  241.      * data reg!
  242.      */
  243.     if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
  244.         atari_dma_residual =
  245.             ((struct NCR5380_hostdata *)(atari_scsi_host->hostdata))->dma_len -
  246.                 (SCSI_DMA_READ_P( dma_addr_hi ) - atari_dma_startaddr);
  247. #if (NDEBUG & NDEBUG_DMA)
  248.         printk( "SCSI DMA: There are %ld residual bytes.\n",
  249.                 atari_dma_residual );
  250. #endif
  251.         atari_scsi_fetch_restbytes();
  252.         tt_scsi_dma.dma_ctrl = 0;
  253.     }
  254.  
  255.     /* If the DMA is finished, fetch the rest bytes and turn it off */
  256.     if (dma_stat & 0x40) {
  257.         atari_dma_residual = 0;
  258.         atari_scsi_fetch_restbytes();
  259.         tt_scsi_dma.dma_ctrl = 0;
  260.     }
  261.  
  262. #endif /* REAL_DMA */
  263.     
  264.     /* If we got this interrupt, we don't need the other one any more */
  265.     tt_mfp.int_pn_b = (unsigned char)~0x80;
  266.  
  267.     CHECK_ICNT("calling NCR5380_intr");
  268.  
  269.     save_flags(flags);
  270.     NCR5380_intr( 0 );
  271.     restore_flags(flags);
  272.  
  273. #ifdef LOST_INTR
  274.     CHECK_ICNT("returning, after NCR5380_intr");
  275.     curr_intr_count = prev_intr_count;
  276. #endif
  277. }
  278.  
  279.  
  280. static void scsi_falcon_intr (struct intframe *fp, void *data)
  281.  
  282. {    int                dma_stat;
  283.     unsigned long    flags;
  284. #ifdef LOST_INTR
  285.     unsigned long    prev_intr_count;
  286.  
  287.     prev_intr_count = curr_intr_count;
  288.     curr_intr_count = intr_count;
  289. #endif
  290.     
  291. #ifdef REAL_DMA
  292.  
  293.     /* Turn off DMA and select sector counter register before
  294.      * accessing the status register (Atari recommendation!)
  295.      */
  296.     st_dma.dma_mode_status = 0x90;
  297.     dma_stat = st_dma.dma_mode_status;
  298.  
  299.     /* Bit 0 indicates some error in the DMA process... don't know
  300.      * what happened exactly (no further docu).
  301.      */
  302.     if (!(dma_stat & 0x01)) {
  303.         /* DMA error */
  304.         printk( "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR() );
  305.     }
  306.  
  307.     /* If the DMA was active, but now bit 1 is not clear, it is some
  308.      * other 5380 interrupt that finishes the DMA transfer. We have to
  309.      * calculate the number of residual bytes and give a warning if
  310.      * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
  311.      */
  312.     if (atari_dma_active && (dma_stat & 0x02)) {
  313.         unsigned long    transferred;
  314.  
  315.         transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
  316.         /* The ST-DMA address is incremented in 2-byte steps, but the
  317.          * data are written only in 16-byte chunks. If the number of
  318.          * transferred bytes is not divisible by 16, the remainder is
  319.          * lost somewhere in outer space.
  320.          */
  321.         if (transferred & 15)
  322.             printk( "SCSI DMA error: %ld bytes lost in ST-DMA fifo :-((\n",
  323.                     transferred & 15 );
  324.  
  325.         atari_dma_residual =
  326.             ((struct NCR5380_hostdata *)(atari_scsi_host->hostdata))->dma_len -
  327.                 transferred;
  328. #if (NDEBUG & NDEBUG_DMA)
  329.         printk( "SCSI DMA: There are %ld residual bytes.\n",
  330.                 atari_dma_residual );
  331. #endif
  332.     }
  333.     else
  334.         atari_dma_residual = 0;
  335.     atari_dma_active = 0;
  336.     
  337. #endif /* REAL_DMA */
  338.  
  339.     CHECK_ICNT("calling NCR5380_intr");
  340.  
  341.     save_flags(flags);
  342.     NCR5380_intr( 0 );
  343.     restore_flags(flags);
  344.  
  345. #ifdef LOST_INTR
  346.     CHECK_ICNT("returning, after NCR5380_intr");
  347.     curr_intr_count = prev_intr_count;
  348. #endif
  349. }
  350.  
  351.  
  352. static void atari_scsi_fetch_restbytes( void )
  353.  
  354. {    int        nr;
  355.     char    *src, *dst;
  356.  
  357.     /* fetch rest bytes in the DMA register */
  358.     dst = (char *)SCSI_DMA_READ_P( dma_addr_hi );
  359.     if ((nr = ((long)dst & 3))) {
  360.         /* there are 'nr' bytes left for the last long address before the
  361.            DMA pointer */
  362.         dst = (char *)( (unsigned long)dst & ~3 );
  363. #if (NDEBUG & NDEBUG_DMA)
  364.         printk( "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
  365.                 nr, (long)dst );
  366. #endif
  367.         dst = (char *)PTOV(dst);  /* The content of the DMA pointer
  368.                                    * is a physical address! */
  369. #if (NDEBUG & NDEBUG_DMA)
  370.         printk( " = virt addr 0x%08lx\n", (long)dst );
  371. #endif
  372.         for( src = (char *)&tt_scsi_dma.dma_restdata; nr > 0; --nr )
  373.             *dst++ = *src++;
  374.     }
  375. }
  376.  
  377.  
  378. static int                    falcon_got_lock = 0;
  379. static struct wait_queue    *falcon_fairness_wait = NULL;
  380. static int                    falcon_trying_lock = 0;
  381. static struct wait_queue    *falcon_try_wait = NULL;
  382.  
  383. /* This function releases the lock on the DMA chip if there is no
  384.  * connected command and the disconnected queue is empty. On
  385.  * releasing, instances of falcon_get_lock are awoken, that put
  386.  * themselves to sleep for fairness. They can now try to get the lock
  387.  * again (but others waiting longer more probably will win).
  388.  */
  389.  
  390. static void
  391. falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
  392.  
  393. {
  394.     if (IS_A_TT()) return;
  395.     
  396.     if (falcon_got_lock &&
  397.         !hostdata->disconnected_queue &&
  398.         !hostdata->issue_queue &&
  399.         !hostdata->connected) {
  400.  
  401.         unsigned long    oldflags;
  402.  
  403.         save_flags(oldflags);
  404.         cli();
  405.         
  406.         falcon_got_lock = 0;
  407.         stdma_release();
  408.         wake_up( &falcon_fairness_wait );
  409.  
  410.         restore_flags(oldflags);
  411.     }
  412. }
  413.  
  414. /* This function manages the locking of the ST-DMA.
  415.  * If the DMA isn't locked already for SCSI, it trys to lock it by
  416.  * calling stdma_lock(). But if the DMA is locked by the SCSI code and
  417.  * there are other drivers waiting for the chip, we do not issue the
  418.  * command immediatly but wait on 'falcon_fairness_queue'. We will be
  419.  * waked up when the DMA is unlocked by some SCSI interrupt. After that
  420.  * we try to get the lock again.
  421.  * But we must be prepared that more then one instance of
  422.  * falcon_get_lock() is waiting on the fairness queue. They should not
  423.  * try all at once to call stdma_lock(), one is enough! For that, the
  424.  * first one sets 'falcon_trying_lock', others that see that variable
  425.  * set wait on the queue 'falcon_try_wait'.
  426.  * Complicated, complicated.... Sigh...
  427.  */
  428.  
  429. static void falcon_get_lock( void )
  430.  
  431. {
  432.     unsigned long    oldflags;
  433.     
  434.     if (IS_A_TT()) return;
  435.  
  436.     save_flags(oldflags);
  437.     cli();
  438.     
  439.     while( falcon_got_lock && stdma_others_waiting() )
  440.         sleep_on( &falcon_fairness_wait );
  441.  
  442.     if (!falcon_got_lock) {
  443.         if (!falcon_trying_lock) {
  444.             falcon_trying_lock = 1;
  445.             stdma_lock( scsi_falcon_intr, 0 );
  446.             falcon_got_lock = 1;
  447.             falcon_trying_lock = 0;
  448.             wake_up( &falcon_try_wait );
  449.         }
  450.         else {
  451.             sleep_on( &falcon_try_wait );
  452.         }
  453.     }    
  454.  
  455.     restore_flags(oldflags);
  456. }
  457.  
  458.  
  459. /* This is the wrapper function for NCR5380_queue_command(). It just
  460.  * trys to get the lock on the ST-DMA (see above) and then calls the
  461.  * original function.
  462.  */
  463.  
  464. int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
  465.  
  466. {
  467.     falcon_get_lock();
  468.     return( NCR5380_queue_command( cmd, done ) );
  469. }
  470.  
  471.  
  472.                    
  473. int atari_scsi_detect (int hostno)
  474.  
  475. {    static int called = 0;
  476.     struct Scsi_Host *instance;
  477.  
  478.     if (boot_info.machtype != MACH_ATARI || called)
  479.         return( 0 );
  480.     
  481.     atari_scsi_reg_read  = IS_A_TT() ? atari_scsi_tt_reg_read :
  482.                                        atari_scsi_falcon_reg_read;
  483.     atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
  484.                                        atari_scsi_falcon_reg_write;
  485.  
  486.     instance = scsi_register (hostno, sizeof (struct NCR5380_hostdata));
  487.     atari_scsi_host = instance;
  488.  
  489.     NCR5380_init (instance);
  490.     instance->irq = 0;    /* not needed, but tested in NCR5380.c */
  491.  
  492.     if (IS_A_TT()) {
  493.         
  494.         add_isr( IRQ_TT_MFP_SCSI, scsi_tt_intr, 0, NULL);
  495.         tt_mfp.active_edge |= 0x80;        /* SCSI int on L->H */
  496.         tt_mfp.int_en_a |= 0x80;        /* enabled */
  497.         tt_mfp.int_mk_a |= 0x80;        /* not masked */
  498. #ifdef REAL_DMA
  499.         /* On the TT, we got a second interrupt for DMA ready and DMA buserror.
  500.          * Since on DMA ready we get a "normal" interrupt, too, the service
  501.          * routine for the second int just checks for buserrs.
  502.          */
  503.         add_isr( IRQ_TT_MFP_SCSIDMA, scsi_dma_buserr, 0, NULL);
  504.         tt_mfp.active_edge &= ~0x20;    /* DMA int on H->L */
  505.         tt_mfp.int_en_b |= 0x80;        /* enabled */
  506.         tt_mfp.int_mk_b |= 0x80;        /* not masked */
  507.  
  508.         tt_scsi_dma.dma_ctrl = 0;
  509.         atari_dma_residual = 0;
  510. #endif /* REAL_DMA */
  511.  
  512.     }
  513.     else { /* ! IS_A_TT */
  514.         
  515.         /* Nothing to do for the interrupt: the ST-DMA is initialized
  516.          * already by atari_init_INTS()
  517.          */
  518.  
  519. #ifdef REAL_DMA
  520.         atari_dma_residual = 0;
  521.         atari_dma_active = 0;
  522. #endif
  523.  
  524.         /* Falcon's ST-DMA can work only in lower 16 MB, so
  525.          * unchecked_isa_dma has to be set. But... the high level
  526.          * codes allocates lots (!) of memory for buffers if this is
  527.          * done. So the values for sg_tablesize and cmd_per_lun get
  528.          * lowered a bit (you can leave this out if you have 16MB of
  529.          * ST-Ram).
  530.          */
  531.         atari_scsi_host->unchecked_isa_dma =
  532.         atari_scsi_host->hostt->unchecked_isa_dma = 1;
  533. #if I_HAVE_OVERRUNS == 3
  534.         atari_scsi_host->sg_tablesize =
  535.         atari_scsi_host->hostt->sg_tablesize = SG_NONE;
  536. #else
  537.         atari_scsi_host->sg_tablesize =
  538.         atari_scsi_host->hostt->sg_tablesize = 8;
  539. #endif
  540.         atari_scsi_host->hostt->cmd_per_lun = 8;
  541.     }
  542.     
  543.     printk( "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCATTERGATHER=%d",
  544.             instance->host_no, instance->hostt->can_queue,
  545.             instance->hostt->cmd_per_lun,
  546.             instance->hostt->sg_tablesize );
  547.     NCR5380_print_options (instance);
  548.     printk ("\n");
  549.  
  550.     called = 1;
  551.  
  552.     return( 1 );
  553. }
  554.  
  555. int atari_scsi_reset( Scsi_Cmnd *cmd )
  556.  
  557. {    int        rv;
  558.     
  559.     /* For doing the reset, SCSI interrupts must be disabled first,
  560.      * since the 5380 raises its IRQ line while _RST is active and we
  561.      * can't disable interrupts completely, since we need the timer.
  562.      */
  563.     
  564.     if (IS_A_TT())
  565.         tt_mfp.int_en_a &= ~0x80;
  566.     else
  567.         mfp.int_en_b &= ~0x80;
  568.     
  569.     rv = NCR5380_reset( cmd );
  570.  
  571.     /* Re-enable ints and abort a maybe active DMA transfer */
  572.     if (IS_A_TT()) {
  573. #ifdef REAL_DMA
  574.         tt_scsi_dma.dma_ctrl = 0;
  575. #endif /* REAL_DMA */
  576.         tt_mfp.int_en_a |= 0x80;
  577.     }
  578.     else {
  579. #ifdef REAL_DMA
  580.         st_dma.dma_mode_status = 0x90;
  581.         atari_dma_active = 0;
  582. #endif /* REAL_DMA */
  583.         mfp.int_en_b |= 0x80;
  584.     }
  585.  
  586.     return( rv );
  587. }
  588.  
  589.     
  590. const char * atari_scsi_info( void )
  591.  
  592. {    /* atari_scsi_detect() is verbose enough... */
  593.     static const char string[] = "";
  594.     return string;
  595. }
  596.  
  597.  
  598. #if defined(REAL_DMA) || defined(REAL_DMA_POLL) || defined(PSEUDO_DMA)
  599.  
  600. unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
  601.                                     unsigned long count, int dir )
  602. {
  603.     unsigned long addr = VTOP( data ),
  604.                   cando = atari_dma_xfer_len( count );
  605.  
  606. #if (NDEBUG & NDEBUG_DMA)
  607.     printk ("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, cando = %ld, dir = %d\n",
  608.             instance->host_no, data, addr, count, cando, dir);
  609. #endif
  610.  
  611.     atari_dma_startaddr = addr;    /* Needed for calculating residual later. */
  612.   
  613.     if (dir)
  614.         /* write: push any dirty cache out before sending it to the
  615.          * peripheral. (Must be done before DMA setup, since at least the
  616.          * ST-DMA begins to fill internal buffers right after setup.
  617.          */
  618.         cache_push( addr, cando );
  619.     else
  620.         /* read: invalidate any cache, may be altered after DMA without CPU
  621.          * knowledge
  622.          */
  623.         cache_clear( addr, cando );
  624.  
  625.     if (cando == 0)
  626.         printk( "SCSI warning: DMA programed for 0 bytes !\n" );
  627.  
  628.     if (IS_A_TT()) {
  629.     
  630.         tt_scsi_dma.dma_ctrl = dir;
  631.         SCSI_DMA_WRITE_P( dma_addr_hi, addr );
  632.         SCSI_DMA_WRITE_P( dma_cnt_hi, cando );
  633.         tt_scsi_dma.dma_ctrl = dir | 2;
  634.     }
  635.     else { /* ! IS_A_TT */
  636.   
  637.         /* set address */
  638.         SCSI_DMA_SETADR( addr );
  639.  
  640.         /* toggle direction bit to clear FIFO and set DMA direction */
  641.         dir <<= 8;
  642.         st_dma.dma_mode_status = 0x90 | dir;
  643.         st_dma.dma_mode_status = 0x90 | (dir ^ 0x100);
  644.         st_dma.dma_mode_status = 0x90 | dir;
  645.         st_dma.fdc_acces_seccount = cando >> 9;
  646.  
  647.         st_dma.dma_mode_status = 0x10 | dir;
  648.         /* need not restore value of dir, only boolean value is tested */
  649.         atari_dma_active = 1;
  650.     }
  651.     
  652.     return( cando );
  653. }
  654.  
  655.  
  656. static long atari_scsi_dma_residual( struct Scsi_Host *instance )
  657.  
  658. {
  659.     return( atari_dma_residual );
  660. }
  661.  
  662. /* This function calculates the number of bytes that can be transferred
  663.  * via DMA. On the TT, this is arbitrary, but on the Falcon we have to use
  664.  * the ST-DMA chip. There are only multiples of 512 bytes possible and
  665.  * max. 256*512 bytes :-( This means also, that defining READ_OVERRUNS is
  666.  * not possible, since that would require to program the DMA for n*512 - 2
  667.  * bytes.
  668.  */
  669.  
  670. static unsigned long atari_dma_xfer_len( unsigned long wanted_len )
  671.  
  672. {
  673.     unsigned long    possible_len;
  674.  
  675.     if (IS_A_TT())
  676.         /* TT SCSI DMA can transfer arbitrary #bytes */
  677.         return( wanted_len );
  678.     
  679.     /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
  680.      * 255*512 bytes, but this should be enough)
  681.      */
  682.     possible_len =wanted_len & ~0x1ff;
  683.     if (possible_len > 255*512)
  684.         possible_len = 255*512;
  685.  
  686. #if (NDEBUG & NDEBUG_DMA)
  687.     if (possible_len != wanted_len)
  688.         printk( "Sorry, must cut DMA transfer size to %ld bytes instead of %ld\n",
  689.                 possible_len, wanted_len );
  690. #endif
  691.  
  692.     return( possible_len );
  693. }
  694.  
  695.  
  696. #endif    /* REAL_DMA || REAL_DMA_POLL || PSEUDO_DMA */
  697.  
  698.  
  699. /* NCR5380 register access functions
  700.  *
  701.  * There are seperate functions for TT and Falcon, because the access
  702.  * methods are quite different. The calling macros NCR5380_read and
  703.  * NCR5380_write call these functions via function pointers.
  704.  */
  705.  
  706. static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
  707.  
  708. {
  709.     return( tt_scsi_regp[reg * 2] );
  710. }
  711.  
  712. static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
  713.  
  714. {
  715.     tt_scsi_regp[reg * 2] = value;
  716. }
  717.  
  718. static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
  719.  
  720. {
  721.     dma_wd.dma_mode_status= (u_short)(0x88 + reg);
  722.     return( (u_char)dma_wd.fdc_acces_seccount );
  723. }
  724.  
  725. static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
  726.  
  727. {
  728.     dma_wd.dma_mode_status = (u_short)(0x88 + reg);
  729.     dma_wd.fdc_acces_seccount = (u_short)value;
  730. }
  731.  
  732.  
  733. #include "atari_NCR5380.c"
  734.  
  735. #endif /* CONFIG_ATARI_*_SCSI */
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.