mac_scsi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Generic Macintosh NCR5380 driver
  3.  *
  4.  * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
  5.  *
  6.  * derived in part from:
  7.  */
  8. /*
  9.  * Generic Generic NCR5380 driver
  10.  *
  11.  * Copyright 1995, Russell King
  12.  *
  13.  * ALPHA RELEASE 1.
  14.  *
  15.  * For more information, please consult
  16.  *
  17.  * NCR 5380 Family
  18.  * SCSI Protocol Controller
  19.  * Databook
  20.  *
  21.  * NCR Microelectronics
  22.  * 1635 Aeroplaza Drive
  23.  * Colorado Springs, CO 80916
  24.  * 1+ (719) 578-3400
  25.  * 1+ (800) 334-5454
  26.  */
  27. /*
  28.  * Options :
  29.  *
  30.  * PARITY - enable parity checking.  Not supported.
  31.  *
  32.  * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
  33.  *
  34.  * USLEEP - enable support for devices that don't disconnect.  Untested.
  35.  */
  36. /*
  37.  * $Log: mac_NCR5380.c,v $
  38.  */
  39. #define AUTOSENSE
  40. #if 0
  41. #define PSEUDO_DMA
  42. #endif
  43. #include <linux/types.h>
  44. #include <linux/stddef.h>
  45. #include <linux/ctype.h>
  46. #include <linux/delay.h>
  47. #include <linux/module.h>
  48. #include <linux/signal.h>
  49. #include <linux/sched.h>
  50. #include <linux/ioport.h>
  51. #include <linux/init.h>
  52. #include <linux/blk.h>
  53. #include <asm/io.h>
  54. #include <asm/irq.h>
  55. #include <asm/system.h>
  56. #include <asm/macintosh.h>
  57. #include <asm/macints.h>
  58. #include <asm/machw.h>
  59. #include <asm/mac_via.h>
  60. #include "scsi.h"
  61. #include "hosts.h"
  62. #include "mac_scsi.h"
  63. #include "NCR5380.h"
  64. #include "constants.h"
  65. #if 0
  66. #define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION)
  67. #else
  68. #define NDEBUG (NDEBUG_ABORT)
  69. #endif
  70. #define RESET_BOOT
  71. #define DRIVER_SETUP
  72. /*
  73.  * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
  74.  */
  75. #ifdef BUG
  76. #undef RESET_BOOT
  77. #undef DRIVER_SETUP
  78. #endif
  79. #define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI ); 
  80. #define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI );
  81. #ifdef RESET_BOOT
  82. static void mac_scsi_reset_boot(struct Scsi_Host *instance);
  83. #endif
  84. static char macscsi_read(struct Scsi_Host *instance, int reg);
  85. static void macscsi_write(struct Scsi_Host *instance, int reg, int value);
  86. static int setup_can_queue = -1;
  87. static int setup_cmd_per_lun = -1;
  88. static int setup_sg_tablesize = -1;
  89. #ifdef SUPPORT_TAGS
  90. static int setup_use_tagged_queuing = -1;
  91. #endif
  92. static int setup_hostid = -1;
  93. static int polled_scsi_on = 0;
  94. /* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
  95.  * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
  96.  * need ten times the standard value... */
  97. #define TOSHIBA_DELAY
  98. #ifdef TOSHIBA_DELAY
  99. #define AFTER_RESET_DELAY (5*HZ/2)
  100. #else
  101. #define AFTER_RESET_DELAY (HZ/2)
  102. #endif
  103. static volatile unsigned char *mac_scsi_regp = NULL;
  104. static volatile unsigned char *mac_scsi_drq  = NULL;
  105. static volatile unsigned char *mac_scsi_nodrq = NULL;
  106. /*
  107.  * Function : mac_scsi_setup(char *str, int *ints)
  108.  *
  109.  * Purpose : booter command line initialization of the overrides array,
  110.  *
  111.  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  112.  * equal to the number of ints.
  113.  *
  114.  */
  115. static int __init mac_scsi_setup(char *str, int *ints) {
  116. #ifdef DRIVER_SETUP
  117. /* Format of mac5380 parameter is:
  118.  *   mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
  119.  * Negative values mean don't change.
  120.  */
  121. /* Grmbl... the standard parameter parsing can't handle negative numbers
  122.  * :-( So let's do it ourselves!
  123.  */
  124. int i = ints[0]+1, fact;
  125. while( str && (isdigit(*str) || *str == '-') && i <= 10) {
  126. if (*str == '-')
  127. fact = -1, ++str;
  128. else
  129. fact = 1;
  130. ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
  131. if ((str = strchr( str, ',' )) != NULL)
  132. ++str;
  133. }
  134. ints[0] = i-1;
  135. if (ints[0] < 1) {
  136. printk( "mac_scsi_setup: no arguments!n" );
  137. return 0;
  138. }
  139. if (ints[0] >= 1) {
  140. if (ints[1] > 0)
  141. /* no limits on this, just > 0 */
  142. setup_can_queue = ints[1];
  143. }
  144. if (ints[0] >= 2) {
  145. if (ints[2] > 0)
  146. setup_cmd_per_lun = ints[2];
  147. }
  148. if (ints[0] >= 3) {
  149. if (ints[3] >= 0) {
  150. setup_sg_tablesize = ints[3];
  151. /* Must be <= SG_ALL (255) */
  152. if (setup_sg_tablesize > SG_ALL)
  153. setup_sg_tablesize = SG_ALL;
  154. }
  155. }
  156. if (ints[0] >= 4) {
  157. /* Must be between 0 and 7 */
  158. if (ints[4] >= 0 && ints[4] <= 7)
  159. setup_hostid = ints[4];
  160. else if (ints[4] > 7)
  161. printk( "mac_scsi_setup: invalid host ID %d !n", ints[4] );
  162. }
  163. #ifdef SUPPORT_TAGS
  164. if (ints[0] >= 5) {
  165. if (ints[5] >= 0)
  166. setup_use_tagged_queuing = !!ints[5];
  167. }
  168. #endif
  169. #endif
  170. return 1; 
  171. }
  172. __setup("mac5380=", mac_scsi_setup);
  173. #if 0
  174. #define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
  175. #define MAC_IRQ(card)     ((card)->irq)
  176. #endif
  177. /*
  178.  * XXX: status debug
  179.  */
  180. static struct Scsi_Host *default_instance;
  181. /*
  182.  * Function : int macscsi_detect(Scsi_Host_Template * tpnt)
  183.  *
  184.  * Purpose : initializes mac NCR5380 driver based on the
  185.  * command line / compile time port and irq definitions.
  186.  *
  187.  * Inputs : tpnt - template for this SCSI adapter.
  188.  *
  189.  * Returns : 1 if a host adapter was found, 0 if not.
  190.  *
  191.  */
  192.  
  193. int macscsi_detect(Scsi_Host_Template * tpnt)
  194. {
  195.     int count = 0;
  196.     static int called = 0;
  197.     struct Scsi_Host *instance;
  198.     if (!MACH_IS_MAC || called)
  199. return( 0 );
  200.     if (macintosh_config->scsi_type != MAC_SCSI_OLD)
  201.  return( 0 );
  202.     tpnt->proc_name = "mac5380";
  203.     /* setup variables */
  204.     tpnt->can_queue =
  205.       (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
  206.     tpnt->cmd_per_lun =
  207.       (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
  208.     tpnt->sg_tablesize = 
  209.       (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
  210.     if (setup_hostid >= 0)
  211.       tpnt->this_id = setup_hostid;
  212.     else {
  213.       /* use 7 as default */
  214.       tpnt->this_id = 7;
  215.     }
  216. #ifdef SUPPORT_TAGS
  217. if (setup_use_tagged_queuing < 0)
  218. setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
  219. #endif
  220. #if 0 /* loop over multiple adapters (Powerbooks ??) */
  221.     for (count = 0; count < mac_num_scsi; count++) {
  222. #endif
  223.         instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  224.         if(instance == NULL)
  225.          continue;
  226. default_instance = instance;
  227. if (macintosh_config->ident == MAC_MODEL_IIFX) {
  228. mac_scsi_regp  = via1+0x8000;
  229. mac_scsi_drq   = via1+0xE000;
  230. mac_scsi_nodrq = via1+0xC000;
  231. } else {
  232. mac_scsi_regp  = via1+0x10000;
  233. mac_scsi_drq   = via1+0x6000;
  234. mac_scsi_nodrq = via1+0x12000;
  235. }
  236.         instance->io_port = (unsigned long) mac_scsi_regp;
  237. instance->irq = IRQ_MAC_SCSI;
  238. #ifdef RESET_BOOT
  239. mac_scsi_reset_boot(instance);
  240. #endif
  241. NCR5380_init(instance, 0);
  242. instance->n_io_port = 255;
  243.         ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
  244. if (instance->irq != IRQ_NONE)
  245.     if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) {
  246. printk("scsi%d: IRQ%d not free, interrupts disabledn",
  247.     instance->host_no, instance->irq);
  248. instance->irq = IRQ_NONE;
  249.     }
  250. printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
  251. if (instance->irq == IRQ_NONE)
  252.     printk ("s disabled");
  253. else
  254.     printk (" %d", instance->irq);
  255. printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
  256.     instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
  257. printk("nscsi%d:", instance->host_no);
  258. NCR5380_print_options(instance);
  259. printk("n");
  260. #if 0 /* multiple adapters */
  261.     }
  262. #endif
  263.     called = 1;
  264.     return 1;
  265. }
  266. int macscsi_release (struct Scsi_Host *shpnt)
  267. {
  268. if (shpnt->irq != IRQ_NONE)
  269. free_irq (shpnt->irq, NCR5380_intr);
  270. return 0;
  271. }
  272. #ifdef RESET_BOOT
  273. /*
  274.  * Our 'bus reset on boot' function
  275.  */
  276. static void mac_scsi_reset_boot(struct Scsi_Host *instance)
  277. {
  278. unsigned long end;
  279. NCR5380_local_declare();
  280. NCR5380_setup(instance);
  281. /*
  282.  * Do a SCSI reset to clean up the bus during initialization. No messing
  283.  * with the queues, interrupts, or locks necessary here.
  284.  */
  285. printk( "Macintosh SCSI: resetting the SCSI bus..." );
  286. /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
  287.         mac_disable_irq(IRQ_MAC_SCSI);
  288. /* get in phase */
  289. NCR5380_write( TARGET_COMMAND_REG,
  290.       PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
  291. /* assert RST */
  292. NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
  293. /* The min. reset hold time is 25us, so 40us should be enough */
  294. udelay( 50 );
  295. /* reset RST and interrupt */
  296. NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
  297. NCR5380_read( RESET_PARITY_INTERRUPT_REG );
  298. for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
  299. barrier();
  300. /* switch on SCSI IRQ again */
  301.         mac_enable_irq(IRQ_MAC_SCSI);
  302. printk( " donen" );
  303. }
  304. #endif
  305. const char * macscsi_info (struct Scsi_Host *spnt) {
  306.     return "";
  307. }
  308. void restore_irq(struct pt_regs *regs)
  309. {
  310. unsigned long flags;
  311. save_flags(flags);
  312. flags = (flags & ~0x0700) | (regs->sr & 0x0700);
  313. restore_flags(flags);
  314. }
  315. /*
  316.  * pseudo-DMA transfer functions, copied and modified from Russel King's
  317.  * ARM 5380 driver (cumana_1)
  318.  *
  319.  * Work in progress (sort of), didn't work last time I checked, don't use!
  320.  */
  321. #ifdef NOT_EFFICIENT
  322. #define CTRL(p,v)     outb(*ctrl = (v), (p) - 577)
  323. #define STAT(p)       inb((p)+1)
  324. #define IN(p)         inb((p))
  325. #define OUT(v,p)      outb((v), (p))
  326. #else
  327. #if 0
  328. #define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
  329. #else
  330. #define CTRL(p,v) (*ctrl = (v))
  331. #endif
  332. #define STAT(p) (p[1<<4])
  333. #define IN(p) (*(p))
  334. #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
  335. #define OUT(v,p) (*(p) = (v))
  336. #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
  337. #endif
  338. #define L(v) (((v)<<16)|((v) & 0x0000ffff))
  339. #define H(v) (((v)>>16)|((v) & 0xffff0000))
  340. #define ioaddr(v) (v)
  341. static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
  342.               int len)
  343. {
  344.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  345.   int oldctrl = *ctrl;
  346.   unsigned long *laddr;
  347. #ifdef NOT_EFFICIENT
  348.   int iobase = instance->io_port;
  349.   int dma_io = mac_scsi_nodrq;
  350. #else
  351.   volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
  352.   volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq);
  353. #endif
  354.   if(!len) return 0;
  355.   CTRL(iobase, 0x02);
  356.   laddr = (unsigned long *)addr;
  357.   while(len >= 32)
  358.   {
  359.     int status;
  360.     unsigned long v;
  361.     status = STAT(iobase);
  362.     if(status & 0x80)
  363.       goto end;
  364.     if(!(status & 0x40))
  365.       continue;
  366.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  367.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  368.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  369.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  370.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  371.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  372.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  373.     v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
  374.     len -= 32;
  375.     if(len == 0)
  376.       break;
  377.   }
  378.   addr = (unsigned char *)laddr;
  379.   CTRL(iobase, 0x12);
  380.   while(len > 0)
  381.   {
  382.     int status;
  383.     status = STAT(iobase);
  384.     if(status & 0x80)
  385.       goto end;
  386.     if(status & 0x40)
  387.     {
  388.       OUT(*addr++, dma_io);
  389.       if(--len == 0)
  390.         break;
  391.     }
  392.     status = STAT(iobase);
  393.     if(status & 0x80)
  394.       goto end;
  395.     if(status & 0x40)
  396.     {
  397.       OUT(*addr++, dma_io);
  398.       if(--len == 0)
  399.         break;
  400.     }
  401.   }
  402. end:
  403.   CTRL(iobase, oldctrl|0x40);
  404.   return len;
  405. }
  406. static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
  407.               int len)
  408. {
  409.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  410.   int oldctrl = *ctrl;
  411.   unsigned long *laddr;
  412. #ifdef NOT_EFFICIENT
  413.   int iobase = instance->io_port;
  414.   int dma_io = mac_scsi_nodrq;
  415. #else
  416.   volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
  417.   volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq);
  418. #endif
  419.   if(!len) return 0;
  420.   CTRL(iobase, 0x00);
  421.   laddr = (unsigned long *)addr;
  422.   while(len >= 32)
  423.   {
  424.     int status;
  425.     status = STAT(iobase);
  426.     if(status & 0x80)
  427.       goto end;
  428.     if(!(status & 0x40))
  429.       continue;
  430.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  431.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  432.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  433.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  434.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  435.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  436.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  437.     *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
  438.     len -= 32;
  439.     if(len == 0)
  440.       break;
  441.   }
  442.   addr = (unsigned char *)laddr;
  443.   CTRL(iobase, 0x10);
  444.   while(len > 0)
  445.   {
  446.     int status;
  447.     status = STAT(iobase);
  448.     if(status & 0x80)
  449.       goto end;
  450.     if(status & 0x40)
  451.     {
  452.       *addr++ = IN(dma_io);
  453.       if(--len == 0)
  454.         break;
  455.     }
  456.     status = STAT(iobase);
  457.     if(status & 0x80)
  458.       goto end;
  459.     if(status & 0x40)
  460.     {
  461.       *addr++ = IN(dma_io);
  462.       if(--len == 0)
  463.         break;
  464.     }
  465.   }
  466. end:
  467.   CTRL(iobase, oldctrl|0x40);
  468.   return len;
  469. }
  470. #undef STAT
  471. #undef CTRL
  472. #undef IN
  473. #undef OUT
  474. /*
  475.  * NCR 5380 register access functions
  476.  */
  477. #ifdef ORIG
  478. #if 0
  479. #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
  480. #else
  481. #define CTRL(p,v) (*ctrl = (v))
  482. #endif
  483. static char macscsi_read(struct Scsi_Host *instance, int reg)
  484. {
  485.   int iobase = instance->io_port;
  486.   int i;
  487.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  488.   CTRL(iobase, 0);
  489. #if 0
  490.   i = inb(iobase + 64 + reg);
  491. #else
  492.   i = inb(iobase + reg<<4);
  493. #endif
  494.   CTRL(iobase, 0x40);
  495.   return i;
  496. }
  497. static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
  498. {
  499.   int iobase = instance->io_port;
  500.   int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  501.   CTRL(iobase, 0);
  502. #if 0
  503.   outb(value, iobase + 64 + reg);
  504. #else
  505.   outb(value, iobase + reg<<4);
  506. #endif
  507.   CTRL(iobase, 0x40);
  508. }
  509. #undef CTRL
  510. #else
  511. static char macscsi_read(struct Scsi_Host *instance, int reg)
  512. {
  513. return( mac_scsi_regp[reg << 4] );
  514. }
  515. static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
  516. {
  517. mac_scsi_regp[reg << 4] = value;
  518. }
  519. #endif
  520. #include "NCR5380.c"
  521. /*
  522.  * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 
  523.  * reentering NCR5380_print_status seems to have ugly side effects
  524.  */
  525. void scsi_mac_debug (void)
  526. {
  527. unsigned long flags;
  528. NCR5380_local_declare();
  529. if (default_instance) {
  530. #if 0
  531. NCR5380_setup(default_instance);
  532. if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
  533. #endif
  534. save_flags(flags);
  535. cli();
  536. NCR5380_print_status(default_instance);
  537. restore_flags(flags);
  538. }
  539. #if 0
  540. polled_scsi_on = 1;
  541. #endif
  542. }
  543. /*
  544.  * Helper function for interrupt trouble. More ugly side effects here.
  545.  */
  546. void scsi_mac_polled (void)
  547. {
  548. unsigned long flags;
  549. NCR5380_local_declare();
  550. struct Scsi_Host *instance;
  551. #if 0
  552. for (instance = first_instance; instance && (instance->hostt == 
  553.     the_template); instance = instance->next)
  554.     if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) {
  555. #else
  556. instance = default_instance;
  557. #endif
  558. NCR5380_setup(instance);
  559. if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
  560. {
  561. printk("SCSI polln");
  562. save_flags(flags);
  563. cli();
  564. NCR5380_intr(IRQ_MAC_SCSI, instance, NULL);
  565. restore_flags(flags);
  566. }
  567. #if 0
  568.     }
  569. #endif
  570. }
  571. static Scsi_Host_Template driver_template = MAC_NCR5380;
  572. #include "scsi_module.c"