File: /usr/src/linux/include/asm-sparc/floppy.h

1     /* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
2      *
3      * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
4      */
5     
6     #ifndef __ASM_SPARC_FLOPPY_H
7     #define __ASM_SPARC_FLOPPY_H
8     
9     #include <asm/page.h>
10     #include <asm/pgtable.h>
11     #include <asm/system.h>
12     #include <asm/idprom.h>
13     #include <asm/machines.h>
14     #include <asm/oplib.h>
15     #include <asm/auxio.h>
16     #include <asm/irq.h>
17     
18     /* We don't need no stinkin' I/O port allocation crap. */
19     #undef release_region
20     #undef check_region
21     #undef request_region
22     #define release_region(X, Y)	do { } while(0)
23     #define check_region(X, Y)	(0)
24     #define request_region(X, Y, Z)	(1)
25     
26     /* References:
27      * 1) Netbsd Sun floppy driver.
28      * 2) NCR 82077 controller manual
29      * 3) Intel 82077 controller manual
30      */
31     struct sun_flpy_controller {
32     	volatile unsigned char status_82072;  /* Main Status reg. */
33     #define dcr_82072              status_82072   /* Digital Control reg. */
34     #define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
35     
36     	volatile unsigned char data_82072;    /* Data fifo. */
37     #define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
38     
39     	volatile unsigned char dor_82077;     /* Digital Output reg. */
40     	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
41     
42     	volatile unsigned char status_82077;  /* Main Status Register. */
43     #define drs_82077              status_82077   /* Digital Rate Select reg. */
44     
45     	volatile unsigned char data_82077;    /* Data fifo. */
46     	volatile unsigned char ___unused;
47     	volatile unsigned char dir_82077;     /* Digital Input reg. */
48     #define dcr_82077              dir_82077      /* Config Control reg. */
49     };
50     
51     /* You'll only ever find one controller on a SparcStation anyways. */
52     static struct sun_flpy_controller *sun_fdc = NULL;
53     volatile unsigned char *fdc_status;
54     
55     struct sun_floppy_ops {
56     	unsigned char (*fd_inb)(int port);
57     	void (*fd_outb)(unsigned char value, int port);
58     };
59     
60     static struct sun_floppy_ops sun_fdops;
61     
62     #define fd_inb(port)              sun_fdops.fd_inb(port)
63     #define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
64     #define fd_enable_dma()           sun_fd_enable_dma()
65     #define fd_disable_dma()          sun_fd_disable_dma()
66     #define fd_request_dma()          (0) /* nothing... */
67     #define fd_free_dma()             /* nothing... */
68     #define fd_clear_dma_ff()         /* nothing... */
69     #define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
70     #define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
71     #define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
72     #define fd_enable_irq()           /* nothing... */
73     #define fd_disable_irq()          /* nothing... */
74     #define fd_cacheflush(addr, size) /* nothing... */
75     #define fd_request_irq()          sun_fd_request_irq()
76     #define fd_free_irq()             /* nothing... */
77     #if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
78     #define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
79     #define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
80     #endif
81     
82     #define FLOPPY_MOTOR_MASK         0x10
83     
84     /* XXX This isn't really correct. XXX */
85     #define get_dma_residue(x)        (0)
86     
87     #define FLOPPY0_TYPE  4
88     #define FLOPPY1_TYPE  0
89     
90     /* Super paranoid... */
91     #undef HAVE_DISABLE_HLT
92     
93     /* Here is where we catch the floppy driver trying to initialize,
94      * therefore this is where we call the PROM device tree probing
95      * routine etc. on the Sparc.
96      */
97     #define FDC1                      sun_floppy_init()
98     
99     static int FDC2=-1;
100     
101     #define N_FDC    1
102     #define N_DRIVE  8
103     
104     /* No 64k boundary crossing problems on the Sparc. */
105     #define CROSS_64KB(a,s) (0)
106     
107     /* Routines unique to each controller type on a Sun. */
108     static unsigned char sun_82072_fd_inb(int port)
109     {
110     	udelay(5);
111     	switch(port & 7) {
112     	default:
113     		printk("floppy: Asked to read unknown port %d\n", port);
114     		panic("floppy: Port bolixed.");
115     	case 4: /* FD_STATUS */
116     		return sun_fdc->status_82072 & ~STATUS_DMA;
117     	case 5: /* FD_DATA */
118     		return sun_fdc->data_82072;
119     	case 7: /* FD_DIR */
120     		return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0;
121     	};
122     	panic("sun_82072_fd_inb: How did I get here?");
123     }
124     
125     static void sun_82072_fd_outb(unsigned char value, int port)
126     {
127     	udelay(5);
128     	switch(port & 7) {
129     	default:
130     		printk("floppy: Asked to write to unknown port %d\n", port);
131     		panic("floppy: Port bolixed.");
132     	case 2: /* FD_DOR */
133     		/* Oh geese, 82072 on the Sun has no DOR register,
134     		 * the functionality is implemented via the AUXIO
135     		 * I/O register.  So we must emulate the behavior.
136     		 *
137     		 * ASSUMPTIONS:  There will only ever be one floppy
138     		 *               drive attached to a Sun controller
139     		 *               and it will be at drive zero.
140     		 */
141     		{
142     			unsigned bits = 0;
143     			if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
144     			if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
145     			set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
146     		}
147     		break;
148     	case 5: /* FD_DATA */
149     		sun_fdc->data_82072 = value;
150     		break;
151     	case 7: /* FD_DCR */
152     		sun_fdc->dcr_82072 = value;
153     		break;
154     	case 4: /* FD_STATUS */
155     		sun_fdc->status_82072 = value;
156     		break;
157     	};
158     	return;
159     }
160     
161     static unsigned char sun_82077_fd_inb(int port)
162     {
163     	udelay(5);
164     	switch(port & 7) {
165     	default:
166     		printk("floppy: Asked to read unknown port %d\n", port);
167     		panic("floppy: Port bolixed.");
168     	case 4: /* FD_STATUS */
169     		return sun_fdc->status_82077 & ~STATUS_DMA;
170     	case 5: /* FD_DATA */
171     		return sun_fdc->data_82077;
172     	case 7: /* FD_DIR */
173     		/* XXX: Is DCL on 0x80 in sun4m? */
174     		return sun_fdc->dir_82077;
175     	};
176     	panic("sun_82072_fd_inb: How did I get here?");
177     }
178     
179     static void sun_82077_fd_outb(unsigned char value, int port)
180     {
181     	udelay(5);
182     	switch(port & 7) {
183     	default:
184     		printk("floppy: Asked to write to unknown port %d\n", port);
185     		panic("floppy: Port bolixed.");
186     	case 2: /* FD_DOR */
187     		/* Happily, the 82077 has a real DOR register. */
188     		sun_fdc->dor_82077 = value;
189     		break;
190     	case 5: /* FD_DATA */
191     		sun_fdc->data_82077 = value;
192     		break;
193     	case 7: /* FD_DCR */
194     		sun_fdc->dcr_82077 = value;
195     		break;
196     	case 4: /* FD_STATUS */
197     		sun_fdc->status_82077 = value;
198     		break;
199     	};
200     	return;
201     }
202     
203     /* For pseudo-dma (Sun floppy drives have no real DMA available to
204      * them so we must eat the data fifo bytes directly ourselves) we have
205      * three state variables.  doing_pdma tells our inline low-level
206      * assembly floppy interrupt entry point whether it should sit and eat
207      * bytes from the fifo or just transfer control up to the higher level
208      * floppy interrupt c-code.  I tried very hard but I could not get the
209      * pseudo-dma to work in c-code without getting many overruns and
210      * underruns.  If non-zero, doing_pdma encodes the direction of
211      * the transfer for debugging.  1=read 2=write
212      */
213     char *pdma_vaddr;
214     unsigned long pdma_size;
215     volatile int doing_pdma = 0;
216     
217     /* This is software state */
218     char *pdma_base = 0;
219     unsigned long pdma_areasize;
220     
221     /* Common routines to all controller types on the Sparc. */
222     static __inline__ void virtual_dma_init(void)
223     {
224     	/* nothing... */
225     }
226     
227     static __inline__ void sun_fd_disable_dma(void)
228     {
229     	doing_pdma = 0;
230     	if (pdma_base) {
231     		mmu_unlockarea(pdma_base, pdma_areasize);
232     		pdma_base = 0;
233     	}
234     }
235     
236     static __inline__ void sun_fd_set_dma_mode(int mode)
237     {
238     	switch(mode) {
239     	case DMA_MODE_READ:
240     		doing_pdma = 1;
241     		break;
242     	case DMA_MODE_WRITE:
243     		doing_pdma = 2;
244     		break;
245     	default:
246     		printk("Unknown dma mode %d\n", mode);
247     		panic("floppy: Giving up...");
248     	}
249     }
250     
251     static __inline__ void sun_fd_set_dma_addr(char *buffer)
252     {
253     	pdma_vaddr = buffer;
254     }
255     
256     static __inline__ void sun_fd_set_dma_count(int length)
257     {
258     	pdma_size = length;
259     }
260     
261     static __inline__ void sun_fd_enable_dma(void)
262     {
263     	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
264     	pdma_base = pdma_vaddr;
265     	pdma_areasize = pdma_size;
266     }
267     
268     /* Our low-level entry point in arch/sparc/kernel/entry.S */
269     extern void floppy_hardint(int irq, void *unused, struct pt_regs *regs);
270     
271     static int sun_fd_request_irq(void)
272     {
273     	static int once = 0;
274     	int error;
275     
276     	if(!once) {
277     		once = 1;
278     		error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy");
279     		return ((error == 0) ? 0 : -1);
280     	} else return 0;
281     }
282     
283     static struct linux_prom_registers fd_regs[2];
284     
285     static int sun_floppy_init(void)
286     {
287     	char state[128];
288     	int tnode, fd_node, num_regs;
289     	struct resource r;
290     
291     	use_virtual_dma = 1;
292     	
293     	FLOPPY_IRQ = 11;
294     	/* Forget it if we aren't on a machine that could possibly
295     	 * ever have a floppy drive.
296     	 */
297     	if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) ||
298     	   ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
299     	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
300     		/* We certainly don't have a floppy controller. */
301     		goto no_sun_fdc;
302     	}
303     	/* Well, try to find one. */
304     	tnode = prom_getchild(prom_root_node);
305     	fd_node = prom_searchsiblings(tnode, "obio");
306     	if(fd_node != 0) {
307     		tnode = prom_getchild(fd_node);
308     		fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
309     	} else {
310     		fd_node = prom_searchsiblings(tnode, "fd");
311     	}
312     	if(fd_node == 0) {
313     		goto no_sun_fdc;
314     	}
315     
316     	/* The sun4m lets us know if the controller is actually usable. */
317     	if(sparc_cpu_model == sun4m) {
318     		prom_getproperty(fd_node, "status", state, sizeof(state));
319     		if(!strcmp(state, "disabled")) {
320     			goto no_sun_fdc;
321     		}
322     	}
323     	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
324     	num_regs = (num_regs / sizeof(fd_regs[0]));
325     	prom_apply_obio_ranges(fd_regs, num_regs);
326     	memset(&r, 0, sizeof(r));
327     	r.flags = fd_regs[0].which_io;
328     	r.start = fd_regs[0].phys_addr;
329     	sun_fdc = (struct sun_flpy_controller *)
330     	    sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
331     
332     	/* Last minute sanity check... */
333     	if(sun_fdc->status_82072 == 0xff) {
334     		sun_fdc = NULL;
335     		goto no_sun_fdc;
336     	}
337     
338             if(sparc_cpu_model == sun4c) {
339                     sun_fdops.fd_inb = sun_82072_fd_inb;
340                     sun_fdops.fd_outb = sun_82072_fd_outb;
341                     fdc_status = &sun_fdc->status_82072;
342                     /* printk("AUXIO @0x%p\n", auxio_register); */ /* P3 */
343             } else {
344                     sun_fdops.fd_inb = sun_82077_fd_inb;
345                     sun_fdops.fd_outb = sun_82077_fd_outb;
346                     fdc_status = &sun_fdc->status_82077;
347                     /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
348     	}
349     
350     	/* Success... */
351     	allowed_drive_mask = 0x01;
352     	return (int) sun_fdc;
353     
354     no_sun_fdc:
355     	return -1;
356     }
357     
358     static int sparc_eject(void)
359     {
360     	set_dor(0x00, 0xff, 0x90);
361     	udelay(500);
362     	set_dor(0x00, 0x6f, 0x00);
363     	udelay(500);
364     	return 0;
365     }
366     
367     #define fd_eject(drive) sparc_eject()
368     
369     #endif /* !(__ASM_SPARC_FLOPPY_H) */
370