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