mac_scsi.c 14 KB

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