1/*
2 * 68k mac 53c9[46] scsi driver
3 *
4 * copyright (c) 1998, David Weis weisd3458@uni.edu
5 *
6 * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98
7 *
8 * based loosely on cyber_esp.c
9 */
10
11/* these are unused for now */
12#define myreadl(addr) (*(volatile unsigned int *) (addr))
13#define mywritel(b, addr) ((*(volatile unsigned int *) (addr)) = (b))
14
15
16#include <linux/kernel.h>
17#include <linux/delay.h>
18#include <linux/types.h>
19#include <linux/ctype.h>
20#include <linux/string.h>
21#include <linux/slab.h>
22#include <linux/blkdev.h>
23#include <linux/proc_fs.h>
24#include <linux/stat.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27
28#include "scsi.h"
29#include <scsi/scsi_host.h>
30#include "NCR53C9x.h"
31
32#include <asm/io.h>
33
34#include <asm/setup.h>
35#include <asm/irq.h>
36#include <asm/macints.h>
37#include <asm/machw.h>
38#include <asm/mac_via.h>
39
40#include <asm/pgtable.h>
41
42#include <asm/macintosh.h>
43
44/* #define DEBUG_MAC_ESP */
45
46extern void esp_handle(struct NCR_ESP *esp);
47extern void mac_esp_intr(int irq, void *dev_id);
48
49static int  dma_bytes_sent(struct NCR_ESP * esp, int fifo_count);
50static int  dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp);
51static void dma_dump_state(struct NCR_ESP * esp);
52static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length);
53static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length);
54static void dma_ints_off(struct NCR_ESP * esp);
55static void dma_ints_on(struct NCR_ESP * esp);
56static int  dma_irq_p(struct NCR_ESP * esp);
57static int  dma_irq_p_quick(struct NCR_ESP * esp);
58static void dma_led_off(struct NCR_ESP * esp);
59static void dma_led_on(struct NCR_ESP *esp);
60static int  dma_ports_p(struct NCR_ESP *esp);
61static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write);
62static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write);
63
64static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev);
65static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev);
66
67static volatile unsigned char cmd_buffer[16];
68				/* This is where all commands are put
69				 * before they are transferred to the ESP chip
70				 * via PIO.
71				 */
72
73static int esp_initialized = 0;
74
75static int setup_num_esps = -1;
76static int setup_disconnect = -1;
77static int setup_nosync = -1;
78static int setup_can_queue = -1;
79static int setup_cmd_per_lun = -1;
80static int setup_sg_tablesize = -1;
81#ifdef SUPPORT_TAGS
82static int setup_use_tagged_queuing = -1;
83#endif
84static int setup_hostid = -1;
85
86/*
87 * Experimental ESP inthandler; check macints.c to make sure dev_id is
88 * set up properly!
89 */
90
91void mac_esp_intr(int irq, void *dev_id)
92{
93	struct NCR_ESP *esp = (struct NCR_ESP *) dev_id;
94	int irq_p = 0;
95
96	/* Handle the one ESP interrupt showing at this IRQ level. */
97	if(((esp)->irq & 0xff) == irq) {
98	/*
99	 * Debug ..
100	 */
101		irq_p = esp->dma_irq_p(esp);
102	 	printk("mac_esp: irq_p %x current %p disconnected %p\n",
103	 		irq_p, esp->current_SC, esp->disconnected_SC);
104
105		/*
106		 * Mac: if we're here, it's an ESP interrupt for sure!
107		 */
108		if((esp->current_SC || esp->disconnected_SC)) {
109			esp->dma_ints_off(esp);
110
111			ESPIRQ(("I%d(", esp->esp_id));
112			esp_handle(esp);
113			ESPIRQ((")"));
114
115			esp->dma_ints_on(esp);
116		}
117	}
118}
119
120/*
121 * Debug hooks; use for playing with the interrupt flag testing and interrupt
122 * acknowledge on the various machines
123 */
124
125void scsi_esp_polled(int irq, void *dev_id)
126{
127	if (esp_initialized == 0)
128		return;
129
130	mac_esp_intr(irq, dev_id);
131}
132
133void fake_intr(int irq, void *dev_id)
134{
135#ifdef DEBUG_MAC_ESP
136	printk("mac_esp: got irq\n");
137#endif
138
139	mac_esp_intr(irq, dev_id);
140}
141
142irqreturn_t fake_drq(int irq, void *dev_id)
143{
144	printk("mac_esp: got drq\n");
145	return IRQ_HANDLED;
146}
147
148#define DRIVER_SETUP
149
150/*
151 * Function : mac_esp_setup(char *str)
152 *
153 * Purpose : booter command line initialization of the overrides array,
154 *
155 * Inputs : str - parameters, separated by commas.
156 *
157 * Currently unused in the new driver; need to add settable parameters to the
158 * detect function.
159 *
160 */
161
162static int __init mac_esp_setup(char *str) {
163#ifdef DRIVER_SETUP
164	/* Format of mac53c9x parameter is:
165	 *   mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
166	 * Negative values mean don't change.
167	 */
168
169	char *this_opt;
170	long opt;
171
172	this_opt = strsep (&str, ",");
173	if(this_opt) {
174		opt = simple_strtol( this_opt, NULL, 0 );
175
176		if (opt >= 0 && opt <= 2)
177			setup_num_esps = opt;
178		else if (opt > 2)
179			printk( "mac_esp_setup: invalid number of hosts %ld !\n", opt );
180
181		this_opt = strsep (&str, ",");
182	}
183	if(this_opt) {
184		opt = simple_strtol( this_opt, NULL, 0 );
185
186		if (opt > 0)
187			setup_disconnect = opt;
188
189		this_opt = strsep (&str, ",");
190	}
191	if(this_opt) {
192		opt = simple_strtol( this_opt, NULL, 0 );
193
194		if (opt >= 0)
195			setup_nosync = opt;
196
197		this_opt = strsep (&str, ",");
198	}
199	if(this_opt) {
200		opt = simple_strtol( this_opt, NULL, 0 );
201
202		if (opt > 0)
203			setup_can_queue = opt;
204
205		this_opt = strsep (&str, ",");
206	}
207	if(this_opt) {
208		opt = simple_strtol( this_opt, NULL, 0 );
209
210		if (opt > 0)
211			setup_cmd_per_lun = opt;
212
213		this_opt = strsep (&str, ",");
214	}
215	if(this_opt) {
216		opt = simple_strtol( this_opt, NULL, 0 );
217
218		if (opt >= 0) {
219			setup_sg_tablesize = opt;
220			/* Must be <= SG_ALL (255) */
221			if (setup_sg_tablesize > SG_ALL)
222				setup_sg_tablesize = SG_ALL;
223		}
224
225		this_opt = strsep (&str, ",");
226	}
227	if(this_opt) {
228		opt = simple_strtol( this_opt, NULL, 0 );
229
230		/* Must be between 0 and 7 */
231		if (opt >= 0 && opt <= 7)
232			setup_hostid = opt;
233		else if (opt > 7)
234			printk( "mac_esp_setup: invalid host ID %ld !\n", opt);
235
236		this_opt = strsep (&str, ",");
237	}
238#ifdef SUPPORT_TAGS
239	if(this_opt) {
240		opt = simple_strtol( this_opt, NULL, 0 );
241		if (opt >= 0)
242			setup_use_tagged_queuing = !!opt;
243	}
244#endif
245#endif
246	return 1;
247}
248
249__setup("mac53c9x=", mac_esp_setup);
250
251
252/*
253 * ESP address 'detection'
254 */
255
256unsigned long get_base(int chip_num)
257{
258	/*
259	 * using the chip_num and mac model, figure out where the
260	 * chips are mapped
261	 */
262
263	unsigned long io_base = 0x50f00000;
264	unsigned int second_offset = 0x402;
265	unsigned long scsi_loc = 0;
266
267	switch (macintosh_config->scsi_type) {
268
269	/* 950, 900, 700 */
270	case MAC_SCSI_QUADRA2:
271		scsi_loc =  io_base + 0xf000 + ((chip_num == 0) ? 0 : second_offset);
272		break;
273
274	/* av's */
275	case MAC_SCSI_QUADRA3:
276		scsi_loc = io_base + 0x18000 + ((chip_num == 0) ? 0 : second_offset);
277		break;
278
279	/* most quadra/centris models are like this */
280	case MAC_SCSI_QUADRA:
281		scsi_loc = io_base + 0x10000;
282		break;
283
284	default:
285		printk("mac_esp: get_base: hit default!\n");
286		scsi_loc = io_base + 0x10000;
287		break;
288
289	} /* switch */
290
291	printk("mac_esp: io base at 0x%lx\n", scsi_loc);
292
293	return scsi_loc;
294}
295
296/*
297 * Model dependent ESP setup
298 */
299
300int mac_esp_detect(struct scsi_host_template * tpnt)
301{
302	int quick = 0;
303	int chipnum, chipspresent = 0;
304
305	if (esp_initialized > 0)
306		return -ENODEV;
307
308	/* what do we have in this machine... */
309	if (MACHW_PRESENT(MAC_SCSI_96)) {
310		chipspresent ++;
311	}
312
313	if (MACHW_PRESENT(MAC_SCSI_96_2)) {
314		chipspresent ++;
315	}
316
317	/* number of ESPs present ? */
318	if (setup_num_esps >= 0) {
319	  if (chipspresent >= setup_num_esps)
320	    chipspresent = setup_num_esps;
321	  else
322	    printk("mac_esp_detect: num_hosts detected %d setup %d \n",
323		   chipspresent, setup_num_esps);
324	}
325
326	/* TODO: add disconnect / nosync flags */
327
328	/* setup variables */
329	tpnt->can_queue =
330	  (setup_can_queue > 0) ? setup_can_queue : 7;
331	tpnt->cmd_per_lun =
332	  (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1;
333	tpnt->sg_tablesize =
334	  (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL;
335
336	if (setup_hostid >= 0)
337	  tpnt->this_id = setup_hostid;
338	else {
339	  /* use 7 as default */
340	  tpnt->this_id = 7;
341	}
342
343#ifdef SUPPORT_TAGS
344	if (setup_use_tagged_queuing < 0)
345		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
346#endif
347
348	for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
349		struct NCR_ESP * esp;
350
351		esp = esp_allocate(tpnt, NULL, 0);
352		esp->eregs = (struct ESP_regs *) get_base(chipnum);
353
354		esp->dma_irq_p = &esp_dafb_dma_irq_p;
355		if (chipnum == 0) {
356
357			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
358				/* most machines except those below :-) */
359				quick = 1;
360				esp->dma_irq_p = &esp_iosb_dma_irq_p;
361			} else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) {
362				/* mostly av's */
363				quick = 0;
364			} else {
365				/* q950, 900, 700 */
366				quick = 1;
367				out_be32(0xf9800024, 0x1d1);
368				esp->dregs = (void *) 0xf9800024;
369			}
370
371		} else { /* chipnum */
372
373			quick = 1;
374			out_be32(0xf9800028, 0x1d1);
375			esp->dregs = (void *) 0xf9800028;
376
377		} /* chipnum == 0 */
378
379		/* use pio for command bytes; pio for message/data: TBI */
380		esp->do_pio_cmds = 1;
381
382		/* Set the command buffer */
383		esp->esp_command = (volatile unsigned char*) cmd_buffer;
384		esp->esp_command_dvma = (__u32) cmd_buffer;
385
386		/* various functions */
387		esp->dma_bytes_sent = &dma_bytes_sent;
388		esp->dma_can_transfer = &dma_can_transfer;
389		esp->dma_dump_state = &dma_dump_state;
390		esp->dma_init_read = NULL;
391		esp->dma_init_write = NULL;
392		esp->dma_ints_off = &dma_ints_off;
393		esp->dma_ints_on = &dma_ints_on;
394
395		esp->dma_ports_p = &dma_ports_p;
396
397
398		/* Optional functions */
399		esp->dma_barrier = NULL;
400		esp->dma_drain = NULL;
401		esp->dma_invalidate = NULL;
402		esp->dma_irq_entry = NULL;
403		esp->dma_irq_exit = NULL;
404		esp->dma_led_on = NULL;
405		esp->dma_led_off = NULL;
406		esp->dma_poll = NULL;
407		esp->dma_reset = NULL;
408
409		/* SCSI chip speed */
410		/* below esp->cfreq = 40000000; */
411
412
413		if (quick) {
414			/* 'quick' means there's handshake glue logic like in the 5380 case */
415			esp->dma_setup = &dma_setup_quick;
416		} else {
417			esp->dma_setup = &dma_setup;
418		}
419
420		if (chipnum == 0) {
421
422			esp->irq = IRQ_MAC_SCSI;
423
424			request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp->ehost);
425
426			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
427				esp->cfreq = 16500000;
428			} else {
429				esp->cfreq = 25000000;
430			}
431
432
433		} else { /* chipnum == 1 */
434
435			esp->irq = IRQ_MAC_SCSIDRQ;
436
437			esp->cfreq = 25000000;
438
439		}
440
441		if (quick) {
442			printk("esp: using quick version\n");
443		}
444
445		printk("esp: addr at 0x%p\n", esp->eregs);
446
447		esp->scsi_id = 7;
448		esp->diff = 0;
449
450		esp_initialize(esp);
451
452	} /* for chipnum */
453
454	if (chipspresent)
455		printk("\nmac_esp: %d esp controllers found\n", chipspresent);
456
457	esp_initialized = chipspresent;
458
459	return chipspresent;
460}
461
462static int mac_esp_release(struct Scsi_Host *shost)
463{
464	if (shost->irq)
465		free_irq(shost->irq, NULL);
466	if (shost->io_port && shost->n_io_port)
467		release_region(shost->io_port, shost->n_io_port);
468	scsi_unregister(shost);
469	return 0;
470}
471
472/*
473 * I've been wondering what this is supposed to do, for some time. Talking
474 * to Allen Briggs: These machines have an extra register someplace where the
475 * DRQ pin of the ESP can be monitored. That isn't useful for determining
476 * anything else (such as reselect interrupt or other magic) though.
477 * Maybe make the semantics should be changed like
478 * if (esp->current_SC)
479 *	... check DRQ flag ...
480 * else
481 *	... disconnected, check pending VIA interrupt ...
482 *
483 * There's a problem with using the dabf flag or mac_irq_pending() here: both
484 * seem to return 1 even though no interrupt is currently pending, resulting
485 * in esp_exec_cmd() holding off the next command, and possibly infinite loops
486 * in esp_intr().
487 * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we
488 * use simple PIO. The DRQ status will be important when implementing pseudo
489 * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or
490 * 'hardware handshake' mode upon DRQ).
491 * If you plan on changing this (i.e. to save the esp_status register access in
492 * favor of a VIA register access or a shadow register for the IFR), make sure
493 * to try a debug version of this first to monitor what registers would be a good
494 * indicator of the ESP interrupt.
495 */
496
497static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
498{
499	unsigned int ret;
500	int sreg = esp_read(esp->eregs->esp_status);
501
502#ifdef DEBUG_MAC_ESP
503	printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n",
504		readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI));
505#endif
506
507	sreg &= ESP_STAT_INTR;
508
509	/*
510	 * maybe working; this is essentially what's used for iosb_dma_irq_p
511	 */
512	if (sreg)
513		return 1;
514	else
515		return 0;
516
517	/*
518	 * didn't work ...
519	 */
520
521}
522
523/*
524 * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless
525 * of the actual ESP status.
526 */
527
528static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
529{
530	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
531	int sreg = esp_read(esp->eregs->esp_status);
532
533#ifdef DEBUG_MAC_ESP
534	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n",
535		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI),
536		sreg, esp->current_SC, esp->disconnected_SC);
537#endif
538
539	sreg &= ESP_STAT_INTR;
540
541	if (sreg)
542		return (sreg);
543	else
544		return 0;
545}
546
547/*
548 * This seems to be OK for PIO at least ... usually 0 after PIO.
549 */
550
551static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count)
552{
553
554#ifdef DEBUG_MAC_ESP
555	printk("mac_esp: dma bytes sent = %x\n", fifo_count);
556#endif
557
558	return fifo_count;
559}
560
561/*
562 * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo)
563 * is ever implemented. Returning 0 here will use PIO.
564 */
565
566static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp)
567{
568	unsigned long sz = sp->SCp.this_residual;
569
570#ifdef DEBUG_MAC_ESP
571	printk("mac_esp: pio to transfer = %ld\n", sz);
572#endif
573
574	sz = 0;
575	return sz;
576}
577
578/*
579 * Not yet ...
580 */
581
582static void dma_dump_state(struct NCR_ESP * esp)
583{
584#ifdef DEBUG_MAC_ESP
585	printk("mac_esp: dma_dump_state: called\n");
586#endif
587}
588
589/*
590 * DMA setup: should be used to set up the ESP transfer count for pseudo
591 * DMA transfers; need a DRQ transfer function to do the actual transfer
592 */
593
594static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length)
595{
596	printk("mac_esp: dma_init_read\n");
597}
598
599
600static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length)
601{
602	printk("mac_esp: dma_init_write\n");
603}
604
605
606static void dma_ints_off(struct NCR_ESP * esp)
607{
608	disable_irq(esp->irq);
609}
610
611
612static void dma_ints_on(struct NCR_ESP * esp)
613{
614	enable_irq(esp->irq);
615}
616
617/*
618 * generic dma_irq_p(), unused
619 */
620
621static int dma_irq_p(struct NCR_ESP * esp)
622{
623	int i = esp_read(esp->eregs->esp_status);
624
625#ifdef DEBUG_MAC_ESP
626	printk("mac_esp: dma_irq_p status %d\n", i);
627#endif
628
629	return (i & ESP_STAT_INTR);
630}
631
632static int dma_irq_p_quick(struct NCR_ESP * esp)
633{
634	/*
635	 * Copied from iosb_dma_irq_p()
636	 */
637	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
638	int sreg = esp_read(esp->eregs->esp_status);
639
640#ifdef DEBUG_MAC_ESP
641	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n",
642		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI),
643		sreg, esp->current_SC, esp->disconnected_SC);
644#endif
645
646	sreg &= ESP_STAT_INTR;
647
648	if (sreg)
649		return (sreg);
650	else
651		return 0;
652
653}
654
655static void dma_led_off(struct NCR_ESP * esp)
656{
657#ifdef DEBUG_MAC_ESP
658	printk("mac_esp: dma_led_off: called\n");
659#endif
660}
661
662
663static void dma_led_on(struct NCR_ESP * esp)
664{
665#ifdef DEBUG_MAC_ESP
666	printk("mac_esp: dma_led_on: called\n");
667#endif
668}
669
670
671static int dma_ports_p(struct NCR_ESP * esp)
672{
673	return 0;
674}
675
676
677static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write)
678{
679
680#ifdef DEBUG_MAC_ESP
681	printk("mac_esp: dma_setup\n");
682#endif
683
684	if (write) {
685		dma_init_read(esp, (char *) addr, count);
686	} else {
687		dma_init_write(esp, (char *) addr, count);
688	}
689}
690
691
692static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write)
693{
694#ifdef DEBUG_MAC_ESP
695	printk("mac_esp: dma_setup_quick\n");
696#endif
697}
698
699static struct scsi_host_template driver_template = {
700	.proc_name		= "mac_esp",
701	.name			= "Mac 53C9x SCSI",
702	.detect			= mac_esp_detect,
703	.slave_alloc		= esp_slave_alloc,
704	.slave_destroy		= esp_slave_destroy,
705	.release		= mac_esp_release,
706	.info			= esp_info,
707	.queuecommand		= esp_queue,
708	.eh_abort_handler	= esp_abort,
709	.eh_bus_reset_handler	= esp_reset,
710	.can_queue		= 7,
711	.this_id		= 7,
712	.sg_tablesize		= SG_ALL,
713	.cmd_per_lun		= 1,
714	.use_clustering		= DISABLE_CLUSTERING
715};
716
717
718#include "scsi_module.c"
719
720MODULE_LICENSE("GPL");
721