home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / v1.1 / scsi / ncr53c40.9 / ncr53c40
Text File  |  1995-10-10  |  22KB  |  806 lines

  1. diff -u linux/arch/i386/config.in:1.1.1.2 linux/arch/i386/config.in:1.2.2.1
  2. --- linux/arch/i386/config.in:1.1.1.2    Fri Sep  9 16:49:48 1994
  3. +++ linux/arch/i386/config.in    Fri Sep  9 16:49:48 1994
  4. @@ -60,6 +60,7 @@
  5.  bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
  6.  bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
  7.  bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
  8. +bool 'NCR53c406 SCSI support' CONFIG_SCSI_NCR53C406 y
  9.  #bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
  10.  fi
  11.  
  12. diff -u linux/drivers/scsi/Makefile:1.1.1.1 linux/drivers/scsi/Makefile:1.2
  13. --- linux/drivers/scsi/Makefile:1.1.1.1    Fri Sep  9 16:49:52 1994
  14. +++ linux/drivers/scsi/Makefile    Fri Sep  9 16:49:52 1994
  15. @@ -122,6 +122,10 @@
  16.  SCSI_SRCS := $(SCSI_SRCS) ultrastor.c
  17.  endif
  18.  
  19. +ifdef CONFIG_SCSI_NCR53C406
  20. +SCSI_OBJS := $(SCSI_OBJS) NCR53c406.o
  21. +SCSI_SCRS := $(SCSI_SRCS) NCR53c406.c
  22. +endif
  23.  
  24.  
  25.  scsi.a: $(SCSI_OBJS)
  26. diff -u /dev/null linux/drivers/scsi/NCR53c406.c:1.1.2.5
  27. --- /dev/null    Fri Sep  9 16:49:52 1994
  28. +++ linux/drivers/scsi/NCR53c406.c    Fri Sep  9 16:49:52 1994
  29. @@ -0,0 +1,629 @@
  30. +/* 
  31. + *  NCR53c406.c
  32. + *  Low-level SCSI driver for NCR53c406a (Acculogic ISApport)
  33. + *  Copyright (C) 1994 Normunds Saumanis (saumanis@cps.msu.edu)
  34. + *
  35. + *  PIO mode support based on code from Qlogic FAS408 driver by
  36. + *  Tom Zerucha and Michael A. Griffith.
  37. + *
  38. + *  This program is free software; you can redistribute it and/or modify it
  39. + *  under the terms of the GNU General Public License as published by the
  40. + *  Free Software Foundation; either version 2, or (at your option) any
  41. + *  later version.
  42. + *
  43. + *  This program is distributed in the hope that it will be useful, but
  44. + *  WITHOUT ANY WARRANTY; without even the implied warranty of
  45. + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  46. + *  General Public License for more details.
  47. + *
  48. + */
  49. +
  50. +#ifndef _NCR53C406_C
  51. +#define _NCR53C406_C
  52. +
  53. +#define NCR53C406_DEBUG 0
  54. +#define VERBOSE_NCR53C406_DEBUG 0
  55. +
  56. +#define USE_BIOS 1
  57. +/* #define BIOS_ADDR 0xD8000 */ /* define this if autoprobe fails */
  58. +/* #define PORT_BASE 0x330 */ /* define this if autoprobe fails */
  59. +#define IRQ_LEV   11
  60. +#define DMA_CHAN  5
  61. +
  62. +/* Set either USE_DMA or USE_PIO, not both or neither! */
  63. +#define USE_DMA 0 
  64. +#define USE_PIO 1
  65. +
  66. +/* Default configuration */
  67. +#define C1_IMG   0x07        /*  ID=7 */
  68. +#define C2_IMG   0x40        /* FE */
  69. +#if USE_DMA
  70. +#define C3_IMG   0x01        /* TE */
  71. +#else
  72. +#define C3_IMG   0x00
  73. +#endif
  74. +#define C4_IMG   0x04        /* ANE */
  75. +#define C5_IMG   0xb6        /* AA PI SIE POL */
  76. +
  77. +#include <linux/errno.h>
  78. +#include <linux/ioport.h>
  79. +#include <linux/sched.h>
  80. +#include <asm/io.h>
  81. +#include <asm/dma.h>
  82. +#include "/linux/tools/version.h"
  83. +#include "../block/blk.h"
  84. +#include "scsi.h"
  85. +#include "hosts.h"
  86. +#include "sd.h"
  87. +
  88. +#include "NCR53c406.h"
  89. +
  90. +#define REG0 (outb(C4_IMG, CONFIG4))
  91. +#define REG1 (outb(C5_IMG, CONFIG5))
  92. +
  93. +#if NCR53C406_DEBUG
  94. +#define DEB(x) x
  95. +#else
  96. +#define DEB(x)
  97. +#endif
  98. +
  99. +#if VERBOSE_NCR53C406_DEBUG
  100. +#define VDEB(x) x
  101. +#else
  102. +#define VDEB(x)
  103. +#endif
  104. +
  105. +enum {
  106. +  data_out,
  107. +  data_in,
  108. +  command,
  109. +  status,
  110. +  message_out,
  111. +  message_in
  112. +};
  113. +
  114. +#if USE_BIOS
  115. +static void *bios_base = (void *)0;
  116. +#endif
  117. +static int   port_base = 0;
  118. +static int   irq_level = 0;
  119. +#if USE_DMA
  120. +static int   dma_chan = 0;
  121. +#endif
  122. +static Scsi_Cmnd         *current_SC       = NULL;
  123. +static int in_command = 0;
  124. +static int in_reset = 0;
  125. +
  126. +/* possible BIOS locations */
  127. +#if USE_BIOS
  128. +static void *addresses[] = {
  129. +  (void *)0xd8000,
  130. +  (void *)0xc8000
  131. +};
  132. +#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
  133. +#endif USE_BIOS
  134. +               
  135. +/* possible i/o port addresses */
  136. +static unsigned short ports[] = { 0x230, 0x330 };
  137. +#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
  138. +
  139. +/* possible interrupt channels */
  140. +static unsigned short ints[] = { 10, 11, 12, 15 };
  141. +
  142. +/* signatures for NCR 53c406a based controllers */
  143. +#if USE_BIOS
  144. +struct signature {
  145. +  char *signature;
  146. +  int  sig_offset;
  147. +  int  sig_length;
  148. +} signatures[] = {
  149. +  /*          1         2         3         4         5         6 */
  150. +  /* 123456789012345678901234567890123456789012345678901234567890 */
  151. +  { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
  152. +};
  153. +#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
  154. +#endif USE_BIOS
  155. +
  156. +#if (USE_DMA)
  157. +static __inline__ int 
  158. +NCR53c406_dma_setup (unsigned char *ptr, 
  159. +            unsigned int count, 
  160. +            unsigned char mode) {
  161. +  unsigned limit;
  162. +  DEB(printk("dma: before count=%d   ", count));
  163. +  if (dma_chan <=3) {
  164. +    if (count > 65536)
  165. +      count = 65536;
  166. +    limit = 65536 - (((unsigned) ptr) & 0xFFFF);
  167. +  } else {
  168. +    if (count > 65536 * 2) 
  169. +      count = 65536 * 2;
  170. +    limit = 65536* 2 - (((unsigned) ptr) & 0x1FFFF);
  171. +  }
  172. +  
  173. +  if (count > limit) count = limit;
  174. +  
  175. +  DEB(printk("after count=%d\n", count));
  176. +  if ((count & 1) || (((unsigned) ptr) & 1))
  177. +    panic ("NCR53c406 : attempted unaligned DMA transfer\n"); 
  178. +
  179. +  cli();
  180. +  disable_dma(dma_chan);
  181. +  clear_dma_ff(dma_chan);
  182. +  set_dma_addr(dma_chan, (long) ptr);
  183. +  set_dma_count(dma_chan, count);
  184. +  set_dma_mode(dma_chan, mode);
  185. +  enable_dma(dma_chan);
  186. +  sti();
  187. +
  188. +  return count;
  189. +}
  190. +     
  191. +static __inline__ int 
  192. +NCR53c406_dma_write(unsigned char *src, unsigned int count) {
  193. +  return NCR53c406_dma_setup (src, count, DMA_MODE_WRITE);
  194. +}
  195. +
  196. +static __inline__ int 
  197. +NCR53c406_dma_read(unsigned char *src, unsigned int count) {
  198. +  return NCR53c406_dma_setup (src, count, DMA_MODE_READ);
  199. +}
  200. +
  201. +static __inline__ int 
  202. +NCR53c406_dma_residual (void) {
  203. +  register int tmp;
  204. +
  205. +  cli();
  206. +  clear_dma_ff(dma_chan);
  207. +  tmp = get_dma_residue(dma_chan);
  208. +  sti();
  209. +
  210. +  return tmp;
  211. +}
  212. +#endif /* USE_DMA */
  213. +
  214. +#if USE_PIO
  215. +static __inline__ int NCR53c406_pio(unsigned char *request, 
  216. +                    unsigned int reqlen,
  217. +                    unsigned char mode ) 
  218. +{
  219. +  int    i,j;
  220. +  int    ilen;    /* incremental transfer length */
  221. +  
  222. +  j = 0;
  223. +  REG1;
  224. +  if (mode == DMA_MODE_READ) {    /* in */
  225. +    while (reqlen) {
  226. +      i = inb(PIO_STATUS);
  227. +      DEB(printk("pio_status=%x\n", i));
  228. +      j |= i & 0x40;
  229. +      switch( i & 0x1e ) {
  230. +      default:
  231. +      case 0x10:ilen=0;break;
  232. +      case 0x0:ilen=1;break;
  233. +      case 0x8:ilen=42;break;
  234. +      case 0xc:ilen=84;break;
  235. +      case 0xe:ilen=128;break;
  236. +      }
  237. +      if( !ilen ) {
  238. +    if( j ) 
  239. +      break;    /* core int && fifo empty */
  240. +    else
  241. +      continue;
  242. +      }
  243. +      if( ilen > reqlen ) 
  244. +    ilen = reqlen;
  245. +      cli();
  246. +      if( ilen > 3 ) {
  247. +    insl(PIO_FIFO,request,ilen>>2);
  248. +    request += ilen & 0xfc;
  249. +    reqlen -= ilen & 0xfc;
  250. +      }
  251. +      else while(ilen--) {
  252. +    *request++ = inb(PIO_FIFO);
  253. +    reqlen--;
  254. +      }
  255. +      sti();
  256. +    }
  257. +  }
  258. +  else {    /* out */
  259. +    while (!j && reqlen) {
  260. +      i = inb(PIO_STATUS);
  261. +      DEB(printk("pio_status=%x\n", i));
  262. +      j |= i & 0x40;
  263. +      switch( i & 0x1e ) {
  264. +      case 0x10:ilen=128;break;
  265. +      case 0x0:ilen=84;break;
  266. +      case 0x8:ilen=42;break;
  267. +      case 0xc:ilen=1;break;
  268. +      default:
  269. +      case 0xe:ilen=0;break;
  270. +      }
  271. +      if( !ilen )
  272. +    continue;
  273. +      if( ilen > reqlen ) 
  274. +    ilen = reqlen;
  275. +      cli();
  276. +      if( ilen > 3 ) {
  277. +    outsl(PIO_FIFO,request,ilen>>2);
  278. +    request += ilen & 0xfc;
  279. +    reqlen -= ilen & 0xfc;
  280. +      }
  281. +      else while(ilen--) {
  282. +    outb(*request++, PIO_FIFO);
  283. +    reqlen--;
  284. +      }
  285. +      sti();
  286. +    }
  287. +  }
  288. +  
  289. +  /* maybe return reqlen */
  290. +  return 0;
  291. +}
  292. +
  293. +static __inline__ int NCR53c406_pio_read(unsigned char *request, 
  294. +                     unsigned int reqlen) 
  295. +{
  296. +  return NCR53c406_pio (request, reqlen, DMA_MODE_READ);
  297. +}
  298. +
  299. +static __inline__ int NCR53c406_pio_write(unsigned char *request,
  300. +                      unsigned int reqlen) 
  301. +{
  302. +  return NCR53c406_pio (request, reqlen, DMA_MODE_WRITE);
  303. +}
  304. +#endif USE_PIO
  305. +
  306. +int 
  307. +NCR53c406_detect(Scsi_Host_Template * tpnt){
  308. +#ifndef PORT_BASE
  309. +  int i, j, k;
  310. +#endif
  311. +
  312. +#if USE_BIOS
  313. +  int ii, jj;
  314. +  bios_base = 0;
  315. +  /* look for a valid signature */
  316. +  for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++)
  317. +    for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++)
  318. +      if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset,
  319. +         (void *) signatures[jj].signature,
  320. +         (int) signatures[jj].sig_length))
  321. +    bios_base=addresses[ii];
  322. +
  323. +  if(!bios_base){
  324. +    printk("NCR53c406: BIOS signature not found\n");
  325. +    return 0;
  326. +  }
  327. +
  328. +  DEB(printk("NCR53c406 BIOS found at %X\n", (unsigned int) bios_base);)
  329. +#endif /* USE_BIOS */
  330. +
  331. +#ifdef PORT_BASE
  332. +  port_base = PORT_BASE;
  333. +  if (check_region(port_base, 0x10)) /* ports already snatched */
  334. +    port_base = 0;
  335. +#else  /* autodetect */
  336. +  port_base = 0;
  337. +  for(i=0;  i<PORT_COUNT && !port_base; i++){
  338. +    if(check_region(ports[i], 0x10)){
  339. +      DEB(printk("NCR53c406: port %x in use\n", ports[i]));
  340. +    }
  341. +    else {
  342. +      VDEB(printk("NCR53c406: port %x available\n", ports[i]));
  343. +      outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */
  344. +      k=0;
  345. +      for (j=0; j< 6; j++) {
  346. +    if((inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7) {
  347. +      VDEB(printk("NCR53c406: Sig register valid\n"));
  348. +      k++;
  349. +    }
  350. +      }
  351. +      if (k>3){
  352. +    VDEB(printk("port_base=%x\n", port_base));
  353. +    port_base = ports[i];
  354. +      }
  355. +    }
  356. +  }
  357. +#endif PORT_BASE
  358. +
  359. +  if(!port_base){        /* no ports found */
  360. +    printk("NCR53c406: no available ports found\n");
  361. +    return 0;
  362. +  }
  363. +
  364. +  DEB(printk("NCR 53c406a detected\n"));
  365. +  
  366. +  REG1;
  367. +#if (USE_DMA)
  368. +  outb(0x00, PIO_STATUS);
  369. +#else  /* USE_PIO */
  370. +  outb(0x01, PIO_STATUS);
  371. +#endif
  372. +  outb(0x00, PIO_FLAG);
  373. +
  374. +  outb(C4_IMG, CONFIG4);    /* REG0; */
  375. +  outb(C3_IMG, CONFIG3);
  376. +  outb(C2_IMG, CONFIG2);
  377. +  outb(C1_IMG, CONFIG1);
  378. +
  379. +  outb(0x05, CLKCONV);        /* clock conversion factor */
  380. +  outb(0x9C, SRTIMOUT);        /* Selection timeout */
  381. +  outb(0x05, SYNCPRD);        /*  */
  382. +  outb(0x00, SYNCOFF);        /* asynchronous mode */
  383. +
  384. +  DEB(printk("NCR53c406: using port_base %x\n", port_base));
  385. +  snarf_region(port_base, 0x10);
  386. +
  387. +  irq_level=IRQ_LEV;
  388. +
  389. +  if(request_irq(irq_level, NCR53c406_intr, SA_INTERRUPT, "NCR53c406a")){
  390. +    printk("NCR53c406: unable to allocate IRQ %d\n", irq_level);
  391. +    return 0;
  392. +  }
  393. +  DEB(printk("Allocated IRQ %d\n", irq_level));
  394. +
  395. +#if (USE_DMA)
  396. +  dma_chan = DMA_CHAN;
  397. +  if(request_dma(dma_chan, "NCR53c406a") != 0){
  398. +    printk("NCR53c406: unable to allocate DMA channel %d\n", dma_chan);
  399. +    return 0;
  400. +  }
  401. +
  402. +  DEB(printk("Allocated DMA channel %d\n", dma_chan));
  403. +#endif /* USE_DMA */
  404. +
  405. +  tpnt->present = 1;
  406. +  return 1;
  407. +}
  408. +
  409. +const char* 
  410. +NCR53c406_info(){
  411. +  printk("NCR53c406_info called\n");
  412. +  return ("This is NCR53c406 info function!\n");
  413. +}
  414. +
  415. +int 
  416. +NCR53c406_command(Scsi_Cmnd *SCpnt){
  417. +  printk("NCR53c406_command called\n");
  418. +  return 0;
  419. +}
  420. +
  421. +int 
  422. +NCR53c406_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){
  423. +  int i;
  424. +  unsigned int cmd_size = COMMAND_SIZE(SCpnt->cmnd[0]);
  425. +
  426. +  DEB(printk("NCR53c406_queue called\n"));
  427. +  DEB(printk("cmd=%02x   cmd size=%02x   target=%02x   lun=%02x   bufflen=%d\n", 
  428. +     SCpnt->cmnd[0],
  429. +     cmd_size,
  430. +     SCpnt->target, 
  431. +     SCpnt->lun,  
  432. +     SCpnt->request_bufflen));
  433. +  VDEB(for(i=0; i<cmd_size; i++)
  434. +    printk("cmd[%d]=%02x  ", i, SCpnt->cmnd[i]));
  435. +  VDEB(printk("\n"));
  436. +  in_command = 1;
  437. +  
  438. +  current_SC = SCpnt;
  439. +  current_SC->scsi_done = done;
  440. +  current_SC->SCp.phase = command;
  441. +  current_SC->SCp.Status = 0;
  442. +  current_SC->SCp.Message = 0;
  443. +  
  444. +  cli();
  445. +  REG0;
  446. +  outb(SCpnt->target, DEST_ID);    /* set destination */
  447. +  outb(FLUSH_FIFO, CMD_REG);    /* reset the fifos */
  448. +  
  449. +  for(i=0; i<cmd_size; i++){
  450. +    outb(SCpnt->cmnd[i], SCSI_FIFO);
  451. +  }
  452. +  outb(SELECT_NO_ATN, CMD_REG);
  453. +  sti(); 
  454. +  
  455. +  return 0;
  456. +}
  457. +
  458. +int
  459. +NCR53c406_abort(Scsi_Cmnd *SCpnt){
  460. +  DEB(printk("NCR53c406_abort called\n"));
  461. +  return SCSI_ABORT_SNOOZE;    /* Don't know how to abort */
  462. +}
  463. +
  464. +int 
  465. +NCR53c406_reset(Scsi_Cmnd *SCpnt){
  466. +  DEB(printk("NCR53c406_reset called\n"));
  467. +  cli();
  468. +  in_reset = 1;
  469. +  outb(C4_IMG, CONFIG4); /* Select reg set 0 */
  470. +  outb(FLUSH_FIFO, CMD_REG);
  471. +  outb(SCSI_RESET, CMD_REG);
  472. +  outb(SCSI_NOP | DMA_OP, CMD_REG);    /* required after reset */
  473. +  sti();
  474. +  return SCSI_RESET_PENDING;    /* should get an interrupt */
  475. +}
  476. +
  477. +int 
  478. +NCR53c406_biosparm(Scsi_Disk *disk, int dev, int* info_array){
  479. +  int size;
  480. +
  481. +  DEB(printk("NCR53c406_biosparm called\n"));
  482. +
  483. +  size = disk->capacity;
  484. +  info_array[0] = 64;   /* heads */
  485. +  info_array[1] = 32;   /* sectors */
  486. +  info_array[2] = size>>11;  /* cylinders */
  487. +  if (info_array[2] > 1024) {    /* big disk */
  488. +    info_array[0] = 255;
  489. +    info_array[1] = 63;
  490. +    info_array[2] = size / (255*63);
  491. +  }
  492. +  return 0;
  493. +}
  494. +
  495. +
  496. +static void 
  497. +NCR53c406_intr(int unused){
  498. +  unsigned char status, int_reg, seq_reg, fifo_size;
  499. +#if USE_PIO
  500. +  unsigned char pio_status; 
  501. +  struct scatterlist *sglist;
  502. +  unsigned int sgcount;
  503. +#endif
  504. +
  505. +  VDEB(int i;)
  506. +  DEB(printk("NCR53c406_intr called\n"));
  507. +
  508. +  cli();
  509. +#if USE_PIO
  510. +  REG1;
  511. +  pio_status = inb(PIO_STATUS);
  512. +#endif
  513. +  REG0;
  514. +  status = inb(STAT_REG);
  515. +  seq_reg = inb(SEQ_REG);
  516. +  int_reg = inb(INT_REG);
  517. +  fifo_size = inb(FIFO_FLAGS) & 0x1f;
  518. +  sti();
  519. +
  520. +#if NCR53C406_DEBUG
  521. +  printk("status=%02x   seq_reg=%02x   int_reg=%02x   fifo_size=%02x", 
  522. +     status, seq_reg, int_reg, fifo_size);
  523. +#if (USE_DMA)
  524. +  printk("\n");
  525. +#else
  526. +  printk("   pio=%02x\n", pio_status);
  527. +#endif /* USE_DMA */
  528. +#endif /* NCR53C406_DEBUG */
  529. +
  530. +  if((in_command || in_reset) && (int_reg & 0x80)){ /* SCSI reset intr */
  531. +    DEB(printk("Reset intr received\n"));
  532. +    in_command = 0;
  533. +    in_reset = 0;
  534. +    current_SC->result = DID_RESET << 16;
  535. +    current_SC->scsi_done(current_SC);
  536. +  }
  537. +  
  538. +  if(int_reg & 0x20){        /* Disconnect */
  539. +    if(in_command || in_reset){ /* target disconnected while in command*/
  540. +      DEB(printk("Disconnect intr received\n"));
  541. +      if(current_SC->SCp.phase != message_in){
  542. +    in_command = 0;
  543. +    in_reset = 0;
  544. +    current_SC->result = DID_NO_CONNECT << 16;
  545. +      }
  546. +      else{
  547. +    current_SC->result = (current_SC->SCp.Status & 0xff)
  548. +      | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16);
  549. +    in_command = 0;
  550. +      }
  551. +      if(current_SC->scsi_done)
  552. +    current_SC->scsi_done( current_SC );
  553. +    }
  554. +    else            /* Target disconnected on idle bus? */
  555. +      return;
  556. +  }
  557. +
  558. +  switch(status & 0x07){    /* scsi phase */
  559. +  case 0x00:            /* DATA-OUT */
  560. +    if(int_reg & 0x10){        /* Target requesting info transfer */
  561. +      DEB(printk("Data-Out phase\n"));
  562. +      outb(FLUSH_FIFO, CMD_REG);
  563. +      LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
  564. +#if (USE_DMA)
  565. +      NCR53c406_dma_write(current_SC->request_buffer, 
  566. +              current_SC->request_bufflen);
  567. +#endif USE_DMA
  568. +      outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
  569. +#if USE_PIO
  570. +      if (!current_SC->use_sg)
  571. +    NCR53c406_pio_write(current_SC->request_buffer, 
  572. +                current_SC->request_bufflen);
  573. +      else {            /* use s/g */
  574. +    sgcount = current_SC->use_sg;
  575. +    sglist = current_SC->request_buffer;
  576. +    while( sgcount-- ) {
  577. +      NCR53c406_pio_write(sglist->address, sglist->length);
  578. +      sglist++;
  579. +    }
  580. +      }
  581. +      REG0;
  582. +#endif USE_PIO
  583. +    }
  584. +    break;
  585. +
  586. +  case 0x01:            /* DATA-IN */
  587. +    DEB(printk("Data-In phase\n"));
  588. +    outb(FLUSH_FIFO, CMD_REG);
  589. +    LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */
  590. +#if (USE_DMA)
  591. +    NCR53c406_dma_read(current_SC->request_buffer, 
  592. +               current_SC->request_bufflen);
  593. +#endif USE_DMA
  594. +    outb(TRANSFER_INFO | DMA_OP, CMD_REG); 
  595. +#if USE_PIO
  596. +    if (!current_SC->use_sg)
  597. +      NCR53c406_pio_read(current_SC->request_buffer, 
  598. +             current_SC->request_bufflen);
  599. +    else {            /* use s/g */
  600. +      sgcount = current_SC->use_sg;
  601. +      sglist = current_SC->request_buffer;
  602. +      while( sgcount-- ) {
  603. +    NCR53c406_pio_read(sglist->address, sglist->length);
  604. +    sglist++;
  605. +      }
  606. +    } 
  607. +    REG0;
  608. +#endif USE_PIO
  609. +    break;
  610. +
  611. +  case 0x02:            /* COMMAND */
  612. +    DEB(printk("Command phase\n"));
  613. +    break;
  614. +
  615. +  case 0x03:            /* STATUS */
  616. +    current_SC->SCp.phase = status;
  617. +    DEB(printk("Status phase\n"));
  618. +#if VERBOSE_NCR53C406_DEBUG
  619. +    printk("request_buffer=");
  620. +    for(i=0; i<current_SC->request_bufflen && i<200; i++)
  621. +      printk("%02x ", *((unsigned char*)current_SC->request_buffer + i));
  622. +    printk("\n");
  623. +    printk("dma residue = %d\n", NCR53c406_dma_residual());
  624. +#endif
  625. +
  626. +    outb(FLUSH_FIFO, CMD_REG);
  627. +    outb(INIT_CMD_COMPLETE, CMD_REG);
  628. +    break;
  629. +
  630. +  case 0x04:            /* Reserved */
  631. +  case 0x05:            /* Reserved */
  632. +    DEB(printk("Reserved phase\n"));
  633. +    break;
  634. +
  635. +  case 0x06:            /* MESSAGE-OUT */
  636. +    DEB(printk("Message-Out phase\n"));
  637. +    outb(SET_ATN, CMD_REG);    /* Reject the message */
  638. +    outb(MSG_ACCEPT, CMD_REG);
  639. +    break;
  640. +
  641. +  case 0x07:            /* MESSAGE-IN */
  642. +    DEB(printk("Message-In phase\n"));
  643. +    current_SC->SCp.phase = message_in;
  644. +
  645. +    current_SC->SCp.Status = inb(SCSI_FIFO);    
  646. +    current_SC->SCp.Message = inb(SCSI_FIFO);
  647. +
  648. +    DEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f));
  649. +    DEB(printk("Status = %02x  Message = %02x\n", 
  650. +       current_SC->SCp.Status, current_SC->SCp.Message);)
  651. +
  652. +    outb(MSG_ACCEPT, CMD_REG);
  653. +    break;
  654. +  }
  655. +
  656. +}
  657. +
  658. +#endif _NCR53C406_C
  659. diff -u /dev/null linux/drivers/scsi/NCR53c406.h:1.1.2.3
  660. --- /dev/null    Fri Sep  9 16:49:52 1994
  661. +++ linux/drivers/scsi/NCR53c406.h    Fri Sep  9 16:49:52 1994
  662. @@ -0,0 +1,116 @@
  663. +#ifndef _NCR53C406_H
  664. +#define _NCR53C406_H
  665. +
  666. +/*
  667. + * NCR53c406.h
  668. + * 
  669. + * Copyright (C) 1994 Normunds Saumanis (saumanis@cps.msu.edu)
  670. + *
  671. + */
  672. +
  673. +#ifndef NULL
  674. +#define NULL 0
  675. +#endif
  676. +
  677. +/* NOTE:  scatter-gather support only works in PIO mode.
  678. +   Use SG_NONE if DMA mode is enabled!
  679. +*/
  680. +#define NCR53c406 { NULL, "NCR53c406a", NCR53c406_detect, NULL, \
  681. +             NCR53c406_info, NCR53c406_command, \
  682. +             NCR53c406_queue, NCR53c406_abort, \
  683. +             NCR53c406_reset, 0, NCR53c406_biosparm, \
  684. +             1, 7, SG_ALL /*SG_NONE*/, 1, 0, 1, DISABLE_CLUSTERING }
  685. +
  686. +
  687. +/* Control Register Set 0 */
  688. +#define TC_LSB        (port_base+0x00) /* transfer counter lsb     */
  689. +#define TC_MSB        (port_base+0x01) /* transfer counter msb    */
  690. +#define SCSI_FIFO    (port_base+0x02) /* scsi fifo register    */
  691. +#define CMD_REG        (port_base+0x03) /* command register        */
  692. +#define STAT_REG    (port_base+0x04) /* status register        */
  693. +#define DEST_ID        (port_base+0x04) /* selection/reselection bus id */
  694. +#define INT_REG        (port_base+0x05) /* interrupt status register    */
  695. +#define SRTIMOUT    (port_base+0x05) /* select/reselect timeout reg  */
  696. +#define SEQ_REG        (port_base+0x06) /* sequence step register    */
  697. +#define SYNCPRD        (port_base+0x06) /* synchronous transfer period  */
  698. +#define FIFO_FLAGS    (port_base+0x07) /* indicates # of bytes in fifo */
  699. +#define SYNCOFF        (port_base+0x07) /* synchronous offset register  */
  700. +#define CONFIG1        (port_base+0x08) /* configuration register    */
  701. +#define CLKCONV        (port_base+0x09) /* clock conversion reg    */
  702. +#define TESTREG        (port_base+0x0A) /* test mode register        */
  703. +#define CONFIG2        (port_base+0x0B) /* Configuration 2 Register     */
  704. +#define CONFIG3        (port_base+0x0C) /* Configuration 3 Register    */
  705. +#define CONFIG4        (port_base+0x0D) /* Configuration 4 Register     */
  706. +#define TC_HIGH        (port_base+0x0E) /* Transfer Counter High */
  707. +#define FIFO_BOTTOM    (port_base+0x0F) /* Reserve FIFO byte register   */
  708. +
  709. +/* Control Register Set 1 */
  710. +#define JUMPER_SENSE    (port_base+0x00) /* Jumper sense port reg (r/w) */
  711. +#define SRAM_PTR    (port_base+0x01) /* SRAM address pointer reg (r/w) */
  712. +#define SRAM_DATA    (port_base+0x02) /* SRAM data register (r/w) */
  713. +#define PIO_FIFO        (port_base+0x04) /* PIO FIFO registers (r/w) */
  714. +#define PIO_FIFO1       (port_base+0x05)
  715. +#define PIO_FIFO2       (port_base+0x06)
  716. +#define PIO_FIFO3       (port_base+0x07)
  717. +#define PIO_STATUS      (port_base+0x08) /* PIO status (r/w) */
  718. +#define ATA_CMD         (port_base+0x09) /* ATA command/status reg (r/w) */
  719. +#define ATA_ERR         (port_base+0x0A) /* ATA features/error register (r/w)*/
  720. +#define PIO_FLAG        (port_base+0x0B) /* PIO flag interrupt enable (r/w) */
  721. +#define CONFIG5         (port_base+0x0D) /* Configuration 5 register (r/w) */
  722. +#define SIGNATURE       (port_base+0x0E) /* Signature Register (r) */
  723. +#define CONFIG6         (port_base+0x0F) /* Configuration 6 register (r) */
  724. +
  725. +/* Commands */
  726. +#define DMA_OP               0x80
  727. +
  728. +#define SCSI_NOP             0x00
  729. +#define FLUSH_FIFO           0x01
  730. +#define CHIP_RESET           0x02
  731. +#define SCSI_RESET           0x03
  732. +#define RESELECT             0x40
  733. +#define SELECT_NO_ATN        0x41
  734. +#define SELECT_ATN           0x42
  735. +#define SELECT_ATN_STOP      0x43
  736. +#define ENABLE_SEL           0x44
  737. +#define DISABLE_SEL          0x45
  738. +#define SELECT_ATN3          0x46
  739. +#define RESELECT3            0x47
  740. +#define TRANSFER_INFO        0x10
  741. +#define INIT_CMD_COMPLETE    0x11
  742. +#define MSG_ACCEPT           0x12
  743. +#define TRANSFER_PAD         0x18
  744. +#define SET_ATN              0x1a
  745. +#define RESET_ATN            0x1b
  746. +#define SEND_MSG             0x20
  747. +#define SEND_STATUS          0x21
  748. +#define SEND_DATA            0x22
  749. +#define DISCONN_SEQ          0x23
  750. +#define TERMINATE_SEQ        0x24
  751. +#define TARG_CMD_COMPLETE    0x25
  752. +#define DISCONN              0x27
  753. +#define RECV_MSG             0x28
  754. +#define RECV_CMD             0x29
  755. +#define RECV_DATA            0x2a
  756. +#define RECV_CMD_SEQ         0x2b
  757. +#define TARGET_ABORT_DMA     0x04
  758. +
  759. +int NCR53c406_detect(Scsi_Host_Template *);
  760. +const char* NCR53c406_info(void);
  761. +
  762. +int NCR53c406_command(Scsi_Cmnd *);
  763. +int NCR53c406_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
  764. +int NCR53c406_abort(Scsi_Cmnd *);
  765. +int NCR53c406_reset(Scsi_Cmnd *);
  766. +int NCR53c406_biosparm(Disk *, int, int*);
  767. +
  768. +#ifdef _NCR53C406_C
  769. +static  void NCR53c406_intr(int);
  770. +#endif
  771. +
  772. +#define LOAD_DMA_COUNT(count) \
  773. +  outb(count & 0xff, TC_LSB); \
  774. +  outb((count >> 8) & 0xff, TC_MSB); \
  775. +  outb((count >> 16) & 0xff, TC_HIGH);
  776. +
  777. +#endif /* _NCR53C406_H */
  778. +
  779. diff -u linux/drivers/scsi/hosts.c:1.1.1.1 linux/drivers/scsi/hosts.c:1.2
  780. --- linux/drivers/scsi/hosts.c:1.1.1.1    Fri Sep  9 16:49:53 1994
  781. +++ linux/drivers/scsi/hosts.c    Fri Sep  9 16:49:53 1994
  782. @@ -83,8 +83,12 @@
  783.  #include "scsi_debug.h"
  784.  #endif
  785.  
  786. +#ifdef CONFIG_SCSI_NCR53C406
  787. +#include "NCR53c406.h"
  788. +#endif
  789. +
  790.  /*
  791. -static const char RCSid[] = "/cvs/linux/drivers/scsi/hosts.c,v 1.1.1.4 1994/09/07 20:00:51 root Exp";
  792. +static const char RCSid[] = "$Header: /junk/cvs/linux/drivers/scsi/hosts.c,v 1.2 1994/09/09 04:47:15 root Exp $";
  793.  */
  794.  
  795.  /*
  796. @@ -155,6 +159,9 @@
  797.  #endif
  798.  #ifdef CONFIG_SCSI_7000FASST
  799.      WD7000,
  800. +#endif
  801. +#ifdef CONFIG_SCSI_NCR53C406
  802. +    NCR53c406,
  803.  #endif
  804.  #ifdef CONFIG_SCSI_DEBUG
  805.      SCSI_DEBUG,
  806.