mac_scsi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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. * $Log: mac_NCR5380.c,v $
  29. */
  30. #include <linux/types.h>
  31. #include <linux/stddef.h>
  32. #include <linux/ctype.h>
  33. #include <linux/delay.h>
  34. #include <linux/module.h>
  35. #include <linux/signal.h>
  36. #include <linux/ioport.h>
  37. #include <linux/init.h>
  38. #include <linux/blkdev.h>
  39. #include <linux/interrupt.h>
  40. #include <asm/io.h>
  41. #include <asm/irq.h>
  42. #include <asm/system.h>
  43. #include <asm/macintosh.h>
  44. #include <asm/macints.h>
  45. #include <asm/mac_via.h>
  46. #include "scsi.h"
  47. #include <scsi/scsi_host.h>
  48. #include "mac_scsi.h"
  49. /* These control the behaviour of the generic 5380 core */
  50. #define AUTOSENSE
  51. #define PSEUDO_DMA
  52. #include "NCR5380.h"
  53. #if 0
  54. #define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION)
  55. #else
  56. #define NDEBUG (NDEBUG_ABORT)
  57. #endif
  58. #define RESET_BOOT
  59. #define DRIVER_SETUP
  60. extern void via_scsi_clear(void);
  61. #ifdef RESET_BOOT
  62. static void mac_scsi_reset_boot(struct Scsi_Host *instance);
  63. #endif
  64. static int setup_called = 0;
  65. static int setup_can_queue = -1;
  66. static int setup_cmd_per_lun = -1;
  67. static int setup_sg_tablesize = -1;
  68. static int setup_use_pdma = -1;
  69. #ifdef SUPPORT_TAGS
  70. static int setup_use_tagged_queuing = -1;
  71. #endif
  72. static int setup_hostid = -1;
  73. /* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
  74. * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
  75. * need ten times the standard value... */
  76. #define TOSHIBA_DELAY
  77. #ifdef TOSHIBA_DELAY
  78. #define AFTER_RESET_DELAY (5*HZ/2)
  79. #else
  80. #define AFTER_RESET_DELAY (HZ/2)
  81. #endif
  82. static volatile unsigned char *mac_scsi_regp = NULL;
  83. static volatile unsigned char *mac_scsi_drq = NULL;
  84. static volatile unsigned char *mac_scsi_nodrq = NULL;
  85. /*
  86. * NCR 5380 register access functions
  87. */
  88. #if 0
  89. /* Debug versions */
  90. #define CTRL(p,v) (*ctrl = (v))
  91. static char macscsi_read(struct Scsi_Host *instance, int reg)
  92. {
  93. int iobase = instance->io_port;
  94. int i;
  95. int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  96. CTRL(iobase, 0);
  97. i = in_8(iobase + (reg<<4));
  98. CTRL(iobase, 0x40);
  99. return i;
  100. }
  101. static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
  102. {
  103. int iobase = instance->io_port;
  104. int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  105. CTRL(iobase, 0);
  106. out_8(iobase + (reg<<4), value);
  107. CTRL(iobase, 0x40);
  108. }
  109. #else
  110. /* Fast versions */
  111. static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
  112. {
  113. return in_8(instance->io_port + (reg<<4));
  114. }
  115. static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
  116. {
  117. out_8(instance->io_port + (reg<<4), value);
  118. }
  119. #endif
  120. /*
  121. * Function : mac_scsi_setup(char *str)
  122. *
  123. * Purpose : booter command line initialization of the overrides array,
  124. *
  125. * Inputs : str - comma delimited list of options
  126. *
  127. */
  128. static int __init mac_scsi_setup(char *str) {
  129. #ifdef DRIVER_SETUP
  130. int ints[7];
  131. (void)get_options( str, ARRAY_SIZE(ints), ints);
  132. if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
  133. printk(KERN_WARNING "scsi: <mac5380>"
  134. " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
  135. printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
  136. return 0;
  137. }
  138. if (ints[0] >= 1) {
  139. if (ints[1] > 0)
  140. /* no limits on this, just > 0 */
  141. setup_can_queue = ints[1];
  142. }
  143. if (ints[0] >= 2) {
  144. if (ints[2] > 0)
  145. setup_cmd_per_lun = ints[2];
  146. }
  147. if (ints[0] >= 3) {
  148. if (ints[3] >= 0) {
  149. setup_sg_tablesize = ints[3];
  150. /* Must be <= SG_ALL (255) */
  151. if (setup_sg_tablesize > SG_ALL)
  152. setup_sg_tablesize = SG_ALL;
  153. }
  154. }
  155. if (ints[0] >= 4) {
  156. /* Must be between 0 and 7 */
  157. if (ints[4] >= 0 && ints[4] <= 7)
  158. setup_hostid = ints[4];
  159. else if (ints[4] > 7)
  160. printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
  161. }
  162. #ifdef SUPPORT_TAGS
  163. if (ints[0] >= 5) {
  164. if (ints[5] >= 0)
  165. setup_use_tagged_queuing = !!ints[5];
  166. }
  167. if (ints[0] == 6) {
  168. if (ints[6] >= 0)
  169. setup_use_pdma = ints[6];
  170. }
  171. #else
  172. if (ints[0] == 5) {
  173. if (ints[5] >= 0)
  174. setup_use_pdma = ints[5];
  175. }
  176. #endif /* SUPPORT_TAGS */
  177. #endif /* DRIVER_SETUP */
  178. return 1;
  179. }
  180. __setup("mac5380=", mac_scsi_setup);
  181. /*
  182. * If you want to find the instance with (k)gdb ...
  183. */
  184. #if NDEBUG
  185. static struct Scsi_Host *default_instance;
  186. #endif
  187. /*
  188. * Function : int macscsi_detect(struct scsi_host_template * tpnt)
  189. *
  190. * Purpose : initializes mac NCR5380 driver based on the
  191. * command line / compile time port and irq definitions.
  192. *
  193. * Inputs : tpnt - template for this SCSI adapter.
  194. *
  195. * Returns : 1 if a host adapter was found, 0 if not.
  196. *
  197. */
  198. int macscsi_detect(struct scsi_host_template * tpnt)
  199. {
  200. static int called = 0;
  201. int flags = 0;
  202. struct Scsi_Host *instance;
  203. if (!MACH_IS_MAC || called)
  204. return( 0 );
  205. if (macintosh_config->scsi_type != MAC_SCSI_OLD)
  206. return( 0 );
  207. /* setup variables */
  208. tpnt->can_queue =
  209. (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
  210. tpnt->cmd_per_lun =
  211. (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
  212. tpnt->sg_tablesize =
  213. (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
  214. if (setup_hostid >= 0)
  215. tpnt->this_id = setup_hostid;
  216. else {
  217. /* use 7 as default */
  218. tpnt->this_id = 7;
  219. }
  220. #ifdef SUPPORT_TAGS
  221. if (setup_use_tagged_queuing < 0)
  222. setup_use_tagged_queuing = USE_TAGGED_QUEUING;
  223. #endif
  224. /* Once we support multiple 5380s (e.g. DuoDock) we'll do
  225. something different here */
  226. instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
  227. #if NDEBUG
  228. default_instance = instance;
  229. #endif
  230. if (macintosh_config->ident == MAC_MODEL_IIFX) {
  231. mac_scsi_regp = via1+0x8000;
  232. mac_scsi_drq = via1+0xE000;
  233. mac_scsi_nodrq = via1+0xC000;
  234. /* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
  235. flags = FLAG_NO_PSEUDO_DMA;
  236. } else {
  237. mac_scsi_regp = via1+0x10000;
  238. mac_scsi_drq = via1+0x6000;
  239. mac_scsi_nodrq = via1+0x12000;
  240. }
  241. if (! setup_use_pdma)
  242. flags = FLAG_NO_PSEUDO_DMA;
  243. instance->io_port = (unsigned long) mac_scsi_regp;
  244. instance->irq = IRQ_MAC_SCSI;
  245. #ifdef RESET_BOOT
  246. mac_scsi_reset_boot(instance);
  247. #endif
  248. NCR5380_init(instance, flags);
  249. instance->n_io_port = 255;
  250. ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
  251. if (instance->irq != SCSI_IRQ_NONE)
  252. if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
  253. "ncr5380", instance)) {
  254. printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
  255. instance->host_no, instance->irq);
  256. instance->irq = SCSI_IRQ_NONE;
  257. }
  258. printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
  259. if (instance->irq == SCSI_IRQ_NONE)
  260. printk (KERN_INFO "s disabled");
  261. else
  262. printk (KERN_INFO " %d", instance->irq);
  263. printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
  264. instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
  265. printk(KERN_INFO "\nscsi%d:", instance->host_no);
  266. NCR5380_print_options(instance);
  267. printk("\n");
  268. called = 1;
  269. return 1;
  270. }
  271. int macscsi_release (struct Scsi_Host *shpnt)
  272. {
  273. if (shpnt->irq != SCSI_IRQ_NONE)
  274. free_irq(shpnt->irq, shpnt);
  275. NCR5380_exit(shpnt);
  276. return 0;
  277. }
  278. #ifdef RESET_BOOT
  279. /*
  280. * Our 'bus reset on boot' function
  281. */
  282. static void mac_scsi_reset_boot(struct Scsi_Host *instance)
  283. {
  284. unsigned long end;
  285. NCR5380_local_declare();
  286. NCR5380_setup(instance);
  287. /*
  288. * Do a SCSI reset to clean up the bus during initialization. No messing
  289. * with the queues, interrupts, or locks necessary here.
  290. */
  291. printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
  292. /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
  293. disable_irq(IRQ_MAC_SCSI);
  294. /* get in phase */
  295. NCR5380_write( TARGET_COMMAND_REG,
  296. PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
  297. /* assert RST */
  298. NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
  299. /* The min. reset hold time is 25us, so 40us should be enough */
  300. udelay( 50 );
  301. /* reset RST and interrupt */
  302. NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
  303. NCR5380_read( RESET_PARITY_INTERRUPT_REG );
  304. for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
  305. barrier();
  306. /* switch on SCSI IRQ again */
  307. enable_irq(IRQ_MAC_SCSI);
  308. printk(KERN_INFO " done\n" );
  309. }
  310. #endif
  311. const char * macscsi_info (struct Scsi_Host *spnt) {
  312. return "";
  313. }
  314. /*
  315. Pseudo-DMA: (Ove Edlund)
  316. The code attempts to catch bus errors that occur if one for example
  317. "trips over the cable".
  318. XXX: Since bus errors in the PDMA routines never happen on my
  319. computer, the bus error code is untested.
  320. If the code works as intended, a bus error results in Pseudo-DMA
  321. beeing disabled, meaning that the driver switches to slow handshake.
  322. If bus errors are NOT extremely rare, this has to be changed.
  323. */
  324. #define CP_IO_TO_MEM(s,d,len) \
  325. __asm__ __volatile__ \
  326. (" cmp.w #4,%2\n" \
  327. " bls 8f\n" \
  328. " move.w %1,%%d0\n" \
  329. " neg.b %%d0\n" \
  330. " and.w #3,%%d0\n" \
  331. " sub.w %%d0,%2\n" \
  332. " bra 2f\n" \
  333. " 1: move.b (%0),(%1)+\n" \
  334. " 2: dbf %%d0,1b\n" \
  335. " move.w %2,%%d0\n" \
  336. " lsr.w #5,%%d0\n" \
  337. " bra 4f\n" \
  338. " 3: move.l (%0),(%1)+\n" \
  339. "31: move.l (%0),(%1)+\n" \
  340. "32: move.l (%0),(%1)+\n" \
  341. "33: move.l (%0),(%1)+\n" \
  342. "34: move.l (%0),(%1)+\n" \
  343. "35: move.l (%0),(%1)+\n" \
  344. "36: move.l (%0),(%1)+\n" \
  345. "37: move.l (%0),(%1)+\n" \
  346. " 4: dbf %%d0,3b\n" \
  347. " move.w %2,%%d0\n" \
  348. " lsr.w #2,%%d0\n" \
  349. " and.w #7,%%d0\n" \
  350. " bra 6f\n" \
  351. " 5: move.l (%0),(%1)+\n" \
  352. " 6: dbf %%d0,5b\n" \
  353. " and.w #3,%2\n" \
  354. " bra 8f\n" \
  355. " 7: move.b (%0),(%1)+\n" \
  356. " 8: dbf %2,7b\n" \
  357. " moveq.l #0, %2\n" \
  358. " 9: \n" \
  359. ".section .fixup,\"ax\"\n" \
  360. " .even\n" \
  361. "90: moveq.l #1, %2\n" \
  362. " jra 9b\n" \
  363. ".previous\n" \
  364. ".section __ex_table,\"a\"\n" \
  365. " .align 4\n" \
  366. " .long 1b,90b\n" \
  367. " .long 3b,90b\n" \
  368. " .long 31b,90b\n" \
  369. " .long 32b,90b\n" \
  370. " .long 33b,90b\n" \
  371. " .long 34b,90b\n" \
  372. " .long 35b,90b\n" \
  373. " .long 36b,90b\n" \
  374. " .long 37b,90b\n" \
  375. " .long 5b,90b\n" \
  376. " .long 7b,90b\n" \
  377. ".previous" \
  378. : "=a"(s), "=a"(d), "=d"(len) \
  379. : "0"(s), "1"(d), "2"(len) \
  380. : "d0")
  381. static int macscsi_pread (struct Scsi_Host *instance,
  382. unsigned char *dst, int len)
  383. {
  384. unsigned char *d;
  385. volatile unsigned char *s;
  386. NCR5380_local_declare();
  387. NCR5380_setup(instance);
  388. s = mac_scsi_drq+0x60;
  389. d = dst;
  390. /* These conditions are derived from MacOS */
  391. while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
  392. && !(NCR5380_read(STATUS_REG) & SR_REQ))
  393. ;
  394. if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
  395. && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
  396. printk(KERN_ERR "Error in macscsi_pread\n");
  397. return -1;
  398. }
  399. CP_IO_TO_MEM(s, d, len);
  400. if (len != 0) {
  401. printk(KERN_NOTICE "Bus error in macscsi_pread\n");
  402. return -1;
  403. }
  404. return 0;
  405. }
  406. #define CP_MEM_TO_IO(s,d,len) \
  407. __asm__ __volatile__ \
  408. (" cmp.w #4,%2\n" \
  409. " bls 8f\n" \
  410. " move.w %0,%%d0\n" \
  411. " neg.b %%d0\n" \
  412. " and.w #3,%%d0\n" \
  413. " sub.w %%d0,%2\n" \
  414. " bra 2f\n" \
  415. " 1: move.b (%0)+,(%1)\n" \
  416. " 2: dbf %%d0,1b\n" \
  417. " move.w %2,%%d0\n" \
  418. " lsr.w #5,%%d0\n" \
  419. " bra 4f\n" \
  420. " 3: move.l (%0)+,(%1)\n" \
  421. "31: move.l (%0)+,(%1)\n" \
  422. "32: move.l (%0)+,(%1)\n" \
  423. "33: move.l (%0)+,(%1)\n" \
  424. "34: move.l (%0)+,(%1)\n" \
  425. "35: move.l (%0)+,(%1)\n" \
  426. "36: move.l (%0)+,(%1)\n" \
  427. "37: move.l (%0)+,(%1)\n" \
  428. " 4: dbf %%d0,3b\n" \
  429. " move.w %2,%%d0\n" \
  430. " lsr.w #2,%%d0\n" \
  431. " and.w #7,%%d0\n" \
  432. " bra 6f\n" \
  433. " 5: move.l (%0)+,(%1)\n" \
  434. " 6: dbf %%d0,5b\n" \
  435. " and.w #3,%2\n" \
  436. " bra 8f\n" \
  437. " 7: move.b (%0)+,(%1)\n" \
  438. " 8: dbf %2,7b\n" \
  439. " moveq.l #0, %2\n" \
  440. " 9: \n" \
  441. ".section .fixup,\"ax\"\n" \
  442. " .even\n" \
  443. "90: moveq.l #1, %2\n" \
  444. " jra 9b\n" \
  445. ".previous\n" \
  446. ".section __ex_table,\"a\"\n" \
  447. " .align 4\n" \
  448. " .long 1b,90b\n" \
  449. " .long 3b,90b\n" \
  450. " .long 31b,90b\n" \
  451. " .long 32b,90b\n" \
  452. " .long 33b,90b\n" \
  453. " .long 34b,90b\n" \
  454. " .long 35b,90b\n" \
  455. " .long 36b,90b\n" \
  456. " .long 37b,90b\n" \
  457. " .long 5b,90b\n" \
  458. " .long 7b,90b\n" \
  459. ".previous" \
  460. : "=a"(s), "=a"(d), "=d"(len) \
  461. : "0"(s), "1"(d), "2"(len) \
  462. : "d0")
  463. static int macscsi_pwrite (struct Scsi_Host *instance,
  464. unsigned char *src, int len)
  465. {
  466. unsigned char *s;
  467. volatile unsigned char *d;
  468. NCR5380_local_declare();
  469. NCR5380_setup(instance);
  470. s = src;
  471. d = mac_scsi_drq;
  472. /* These conditions are derived from MacOS */
  473. while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
  474. && (!(NCR5380_read(STATUS_REG) & SR_REQ)
  475. || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
  476. ;
  477. if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
  478. printk(KERN_ERR "Error in macscsi_pwrite\n");
  479. return -1;
  480. }
  481. CP_MEM_TO_IO(s, d, len);
  482. if (len != 0) {
  483. printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
  484. return -1;
  485. }
  486. return 0;
  487. }
  488. #include "NCR5380.c"
  489. static struct scsi_host_template driver_template = {
  490. .proc_name = "Mac5380",
  491. .proc_info = macscsi_proc_info,
  492. .name = "Macintosh NCR5380 SCSI",
  493. .detect = macscsi_detect,
  494. .release = macscsi_release,
  495. .info = macscsi_info,
  496. .queuecommand = macscsi_queue_command,
  497. .eh_abort_handler = macscsi_abort,
  498. .eh_bus_reset_handler = macscsi_bus_reset,
  499. .can_queue = CAN_QUEUE,
  500. .this_id = 7,
  501. .sg_tablesize = SG_ALL,
  502. .cmd_per_lun = CMD_PER_LUN,
  503. .use_clustering = DISABLE_CLUSTERING
  504. };
  505. #include "scsi_module.c"