18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Derived partially from asm-sparc/floppy.h, which is:
58c2ecf20Sopenharmony_ci *     Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Sun3x version 2/4/2000 Sam Creasey (sammy@sammy.net)
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef __ASM_SUN3X_FLOPPY_H
118c2ecf20Sopenharmony_ci#define __ASM_SUN3X_FLOPPY_H
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
148c2ecf20Sopenharmony_ci#include <asm/page.h>
158c2ecf20Sopenharmony_ci#include <asm/irq.h>
168c2ecf20Sopenharmony_ci#include <asm/sun3x.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* default interrupt vector */
198c2ecf20Sopenharmony_ci#define SUN3X_FDC_IRQ 0x40
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* some constants */
228c2ecf20Sopenharmony_ci#define FCR_TC 0x1
238c2ecf20Sopenharmony_ci#define FCR_EJECT 0x2
248c2ecf20Sopenharmony_ci#define FCR_MTRON 0x4
258c2ecf20Sopenharmony_ci#define FCR_DSEL1 0x8
268c2ecf20Sopenharmony_ci#define FCR_DSEL0 0x10
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* We don't need no stinkin' I/O port allocation crap. */
298c2ecf20Sopenharmony_ci#undef release_region
308c2ecf20Sopenharmony_ci#undef request_region
318c2ecf20Sopenharmony_ci#define release_region(X, Y)	do { } while(0)
328c2ecf20Sopenharmony_ci#define request_region(X, Y, Z)	(1)
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistruct sun3xflop_private {
358c2ecf20Sopenharmony_ci	volatile unsigned char *status_r;
368c2ecf20Sopenharmony_ci	volatile unsigned char *data_r;
378c2ecf20Sopenharmony_ci	volatile unsigned char *fcr_r;
388c2ecf20Sopenharmony_ci	volatile unsigned char *fvr_r;
398c2ecf20Sopenharmony_ci	unsigned char fcr;
408c2ecf20Sopenharmony_ci} sun3x_fdc;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* Super paranoid... */
438c2ecf20Sopenharmony_ci#undef HAVE_DISABLE_HLT
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/* Routines unique to each controller type on a Sun. */
468c2ecf20Sopenharmony_cistatic unsigned char sun3x_82072_fd_inb(int port)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	static int once = 0;
498c2ecf20Sopenharmony_ci//	udelay(5);
508c2ecf20Sopenharmony_ci	switch(port & 7) {
518c2ecf20Sopenharmony_ci	default:
528c2ecf20Sopenharmony_ci		pr_crit("floppy: Asked to read unknown port %d\n", port);
538c2ecf20Sopenharmony_ci		panic("floppy: Port bolixed.");
548c2ecf20Sopenharmony_ci	case 4: /* FD_STATUS */
558c2ecf20Sopenharmony_ci		return (*sun3x_fdc.status_r) & ~STATUS_DMA;
568c2ecf20Sopenharmony_ci	case 5: /* FD_DATA */
578c2ecf20Sopenharmony_ci		return (*sun3x_fdc.data_r);
588c2ecf20Sopenharmony_ci	case 7: /* FD_DIR */
598c2ecf20Sopenharmony_ci		/* ugly hack, I can't find a way to actually detect the disk */
608c2ecf20Sopenharmony_ci		if(!once) {
618c2ecf20Sopenharmony_ci			once = 1;
628c2ecf20Sopenharmony_ci			return 0x80;
638c2ecf20Sopenharmony_ci		}
648c2ecf20Sopenharmony_ci		return 0;
658c2ecf20Sopenharmony_ci	};
668c2ecf20Sopenharmony_ci	panic("sun_82072_fd_inb: How did I get here?");
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void sun3x_82072_fd_outb(unsigned char value, int port)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci//	udelay(5);
728c2ecf20Sopenharmony_ci	switch(port & 7) {
738c2ecf20Sopenharmony_ci	default:
748c2ecf20Sopenharmony_ci		pr_crit("floppy: Asked to write to unknown port %d\n", port);
758c2ecf20Sopenharmony_ci		panic("floppy: Port bolixed.");
768c2ecf20Sopenharmony_ci	case 2: /* FD_DOR */
778c2ecf20Sopenharmony_ci		/* Oh geese, 82072 on the Sun has no DOR register,
788c2ecf20Sopenharmony_ci		 * so we make do with taunting the FCR.
798c2ecf20Sopenharmony_ci		 *
808c2ecf20Sopenharmony_ci		 * ASSUMPTIONS:  There will only ever be one floppy
818c2ecf20Sopenharmony_ci		 *               drive attached to a Sun controller
828c2ecf20Sopenharmony_ci		 *               and it will be at drive zero.
838c2ecf20Sopenharmony_ci		 */
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	{
868c2ecf20Sopenharmony_ci		unsigned char fcr = sun3x_fdc.fcr;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		if(value & 0x10) {
898c2ecf20Sopenharmony_ci			fcr |= (FCR_DSEL0 | FCR_MTRON);
908c2ecf20Sopenharmony_ci		} else
918c2ecf20Sopenharmony_ci			fcr &= ~(FCR_DSEL0 | FCR_MTRON);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci		if(fcr != sun3x_fdc.fcr) {
958c2ecf20Sopenharmony_ci			*(sun3x_fdc.fcr_r) = fcr;
968c2ecf20Sopenharmony_ci			sun3x_fdc.fcr = fcr;
978c2ecf20Sopenharmony_ci		}
988c2ecf20Sopenharmony_ci	}
998c2ecf20Sopenharmony_ci		break;
1008c2ecf20Sopenharmony_ci	case 5: /* FD_DATA */
1018c2ecf20Sopenharmony_ci		*(sun3x_fdc.data_r) = value;
1028c2ecf20Sopenharmony_ci		break;
1038c2ecf20Sopenharmony_ci	case 7: /* FD_DCR */
1048c2ecf20Sopenharmony_ci		*(sun3x_fdc.status_r) = value;
1058c2ecf20Sopenharmony_ci		break;
1068c2ecf20Sopenharmony_ci	case 4: /* FD_STATUS */
1078c2ecf20Sopenharmony_ci		*(sun3x_fdc.status_r) = value;
1088c2ecf20Sopenharmony_ci		break;
1098c2ecf20Sopenharmony_ci	};
1108c2ecf20Sopenharmony_ci	return;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciasmlinkage irqreturn_t sun3xflop_hardint(int irq, void *dev_id)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	register unsigned char st;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#undef TRACE_FLPY_INT
1198c2ecf20Sopenharmony_ci#define NO_FLOPPY_ASSEMBLER
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci#ifdef TRACE_FLPY_INT
1228c2ecf20Sopenharmony_ci	static int calls=0;
1238c2ecf20Sopenharmony_ci	static int bytes=0;
1248c2ecf20Sopenharmony_ci	static int dma_wait=0;
1258c2ecf20Sopenharmony_ci#endif
1268c2ecf20Sopenharmony_ci	if(!doing_pdma) {
1278c2ecf20Sopenharmony_ci		floppy_interrupt(irq, dev_id);
1288c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci//	pr_info("doing pdma\n");// st %x\n", sun_fdc->status_82072);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci#ifdef TRACE_FLPY_INT
1348c2ecf20Sopenharmony_ci	if(!calls)
1358c2ecf20Sopenharmony_ci		bytes = virtual_dma_count;
1368c2ecf20Sopenharmony_ci#endif
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	{
1398c2ecf20Sopenharmony_ci		register int lcount;
1408c2ecf20Sopenharmony_ci		register char *lptr;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci		for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
1438c2ecf20Sopenharmony_ci		    lcount; lcount--, lptr++) {
1448c2ecf20Sopenharmony_ci/*			st=fd_inb(virtual_dma_port+4) & 0x80 ;  */
1458c2ecf20Sopenharmony_ci			st = *(sun3x_fdc.status_r);
1468c2ecf20Sopenharmony_ci/*			if(st != 0xa0)                  */
1478c2ecf20Sopenharmony_ci/*				break;                  */
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci			if((st & 0x80) == 0) {
1508c2ecf20Sopenharmony_ci				virtual_dma_count = lcount;
1518c2ecf20Sopenharmony_ci				virtual_dma_addr = lptr;
1528c2ecf20Sopenharmony_ci				return IRQ_HANDLED;
1538c2ecf20Sopenharmony_ci			}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci			if((st & 0x20) == 0)
1568c2ecf20Sopenharmony_ci				break;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci			if(virtual_dma_mode)
1598c2ecf20Sopenharmony_ci/*				fd_outb(*lptr, virtual_dma_port+5); */
1608c2ecf20Sopenharmony_ci				*(sun3x_fdc.data_r) = *lptr;
1618c2ecf20Sopenharmony_ci			else
1628c2ecf20Sopenharmony_ci/*				*lptr = fd_inb(virtual_dma_port+5); */
1638c2ecf20Sopenharmony_ci				*lptr = *(sun3x_fdc.data_r);
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci		virtual_dma_count = lcount;
1678c2ecf20Sopenharmony_ci		virtual_dma_addr = lptr;
1688c2ecf20Sopenharmony_ci/*		st = fd_inb(virtual_dma_port+4);   */
1698c2ecf20Sopenharmony_ci		st = *(sun3x_fdc.status_r);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci#ifdef TRACE_FLPY_INT
1738c2ecf20Sopenharmony_ci	calls++;
1748c2ecf20Sopenharmony_ci#endif
1758c2ecf20Sopenharmony_ci//	pr_info("st=%02x\n", st);
1768c2ecf20Sopenharmony_ci	if(st == 0x20)
1778c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1788c2ecf20Sopenharmony_ci	if(!(st & 0x20)) {
1798c2ecf20Sopenharmony_ci		virtual_dma_residue += virtual_dma_count;
1808c2ecf20Sopenharmony_ci		virtual_dma_count=0;
1818c2ecf20Sopenharmony_ci		doing_pdma = 0;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci#ifdef TRACE_FLPY_INT
1848c2ecf20Sopenharmony_ci		pr_info("count=%x, residue=%x calls=%d bytes=%x dma_wait=%d\n",
1858c2ecf20Sopenharmony_ci			virtual_dma_count, virtual_dma_residue, calls, bytes,
1868c2ecf20Sopenharmony_ci			dma_wait);
1878c2ecf20Sopenharmony_ci		calls = 0;
1888c2ecf20Sopenharmony_ci		dma_wait=0;
1898c2ecf20Sopenharmony_ci#endif
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		floppy_interrupt(irq, dev_id);
1928c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#ifdef TRACE_FLPY_INT
1978c2ecf20Sopenharmony_ci	if(!virtual_dma_count)
1988c2ecf20Sopenharmony_ci		dma_wait++;
1998c2ecf20Sopenharmony_ci#endif
2008c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic int sun3xflop_request_irq(void)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	static int once = 0;
2068c2ecf20Sopenharmony_ci	int error;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	if(!once) {
2098c2ecf20Sopenharmony_ci		once = 1;
2108c2ecf20Sopenharmony_ci		error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
2118c2ecf20Sopenharmony_ci				    0, "floppy", NULL);
2128c2ecf20Sopenharmony_ci		return ((error == 0) ? 0 : -1);
2138c2ecf20Sopenharmony_ci	} else return 0;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic void __init floppy_set_flags(int *ints,int param, int param2);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic int sun3xflop_init(void)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	if(FLOPPY_IRQ < 0x40)
2218c2ecf20Sopenharmony_ci		FLOPPY_IRQ = SUN3X_FDC_IRQ;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	sun3x_fdc.status_r = (volatile unsigned char *)SUN3X_FDC;
2248c2ecf20Sopenharmony_ci	sun3x_fdc.data_r  = (volatile unsigned char *)(SUN3X_FDC+1);
2258c2ecf20Sopenharmony_ci	sun3x_fdc.fcr_r = (volatile unsigned char *)SUN3X_FDC_FCR;
2268c2ecf20Sopenharmony_ci	sun3x_fdc.fvr_r = (volatile unsigned char *)SUN3X_FDC_FVR;
2278c2ecf20Sopenharmony_ci	sun3x_fdc.fcr = 0;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* Last minute sanity check... */
2308c2ecf20Sopenharmony_ci	if(*sun3x_fdc.status_r == 0xff) {
2318c2ecf20Sopenharmony_ci		return -1;
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	*sun3x_fdc.fvr_r = FLOPPY_IRQ;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	*sun3x_fdc.fcr_r = FCR_TC;
2378c2ecf20Sopenharmony_ci	udelay(10);
2388c2ecf20Sopenharmony_ci	*sun3x_fdc.fcr_r = 0;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/* Success... */
2418c2ecf20Sopenharmony_ci	floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
2428c2ecf20Sopenharmony_ci	allowed_drive_mask = 0x01;
2438c2ecf20Sopenharmony_ci	return (int) SUN3X_FDC;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci/* I'm not precisely sure this eject routine works */
2478c2ecf20Sopenharmony_cistatic int sun3x_eject(void)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	if(MACH_IS_SUN3X) {
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci		sun3x_fdc.fcr |= (FCR_DSEL0 | FCR_EJECT);
2528c2ecf20Sopenharmony_ci		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
2538c2ecf20Sopenharmony_ci		udelay(10);
2548c2ecf20Sopenharmony_ci		sun3x_fdc.fcr &= ~(FCR_DSEL0 | FCR_EJECT);
2558c2ecf20Sopenharmony_ci		*(sun3x_fdc.fcr_r) = sun3x_fdc.fcr;
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return 0;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci#define fd_eject(drive) sun3x_eject()
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci#endif /* !(__ASM_SUN3X_FLOPPY_H) */
264