mac_scsi.c 14 KB

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