1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* asm/floppy.h: Sparc specific parts of the Floppy driver. 3 * 4 * Copyright (C) 1995 David S. Miller (davem@davemloft.net) 5 */ 6 7 #ifndef __ASM_SPARC_FLOPPY_H 8 #define __ASM_SPARC_FLOPPY_H 9 10 #include <linux/of.h> 11 #include <linux/of_device.h> 12 13 #include <asm/pgtable.h> 14 #include <asm/idprom.h> 15 #include <asm/oplib.h> 16 #include <asm/auxio.h> 17 #include <asm/setup.h> 18 #include <asm/page.h> 19 #include <asm/irq.h> 20 21 /* We don't need no stinkin' I/O port allocation crap. */ 22 #undef release_region 23 #undef request_region 24 #define release_region(X, Y) do { } while(0) 25 #define request_region(X, Y, Z) (1) 26 27 /* References: 28 * 1) Netbsd Sun floppy driver. 29 * 2) NCR 82077 controller manual 30 * 3) Intel 82077 controller manual 31 */ 32 struct sun_flpy_controller { 33 volatile unsigned char status_82072; /* Main Status reg. */ 34 #define dcr_82072 status_82072 /* Digital Control reg. */ 35 #define status1_82077 status_82072 /* Auxiliary Status reg. 1 */ 36 37 volatile unsigned char data_82072; /* Data fifo. */ 38 #define status2_82077 data_82072 /* Auxiliary Status reg. 2 */ 39 40 volatile unsigned char dor_82077; /* Digital Output reg. */ 41 volatile unsigned char tapectl_82077; /* What the? Tape control reg? */ 42 43 volatile unsigned char status_82077; /* Main Status Register. */ 44 #define drs_82077 status_82077 /* Digital Rate Select reg. */ 45 46 volatile unsigned char data_82077; /* Data fifo. */ 47 volatile unsigned char ___unused; 48 volatile unsigned char dir_82077; /* Digital Input reg. */ 49 #define dcr_82077 dir_82077 /* Config Control reg. */ 50 }; 51 52 /* You'll only ever find one controller on a SparcStation anyways. */ 53 static struct sun_flpy_controller *sun_fdc = NULL; 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 /* XXX This isn't really correct. XXX */ 83 #define get_dma_residue(x) (0) 84 85 #define FLOPPY0_TYPE 4 86 #define FLOPPY1_TYPE 0 87 88 /* Super paranoid... */ 89 #undef HAVE_DISABLE_HLT 90 91 /* Here is where we catch the floppy driver trying to initialize, 92 * therefore this is where we call the PROM device tree probing 93 * routine etc. on the Sparc. 94 */ 95 #define FDC1 sun_floppy_init() 96 97 #define N_FDC 1 98 #define N_DRIVE 8 99 100 /* No 64k boundary crossing problems on the Sparc. */ 101 #define CROSS_64KB(a,s) (0) 102 103 /* Routines unique to each controller type on a Sun. */ 104 static void sun_set_dor(unsigned char value, int fdc_82077) 105 { 106 if (fdc_82077) 107 sun_fdc->dor_82077 = value; 108 } 109 110 static unsigned char sun_read_dir(void) 111 { 112 return sun_fdc->dir_82077; 113 } 114 115 static unsigned char sun_82072_fd_inb(int port) 116 { 117 udelay(5); 118 switch(port & 7) { 119 default: 120 printk("floppy: Asked to read unknown port %d\n", port); 121 panic("floppy: Port bolixed."); 122 case 4: /* FD_STATUS */ 123 return sun_fdc->status_82072 & ~STATUS_DMA; 124 case 5: /* FD_DATA */ 125 return sun_fdc->data_82072; 126 case 7: /* FD_DIR */ 127 return sun_read_dir(); 128 } 129 panic("sun_82072_fd_inb: How did I get here?"); 130 } 131 132 static void sun_82072_fd_outb(unsigned char value, int port) 133 { 134 udelay(5); 135 switch(port & 7) { 136 default: 137 printk("floppy: Asked to write to unknown port %d\n", port); 138 panic("floppy: Port bolixed."); 139 case 2: /* FD_DOR */ 140 sun_set_dor(value, 0); 141 break; 142 case 5: /* FD_DATA */ 143 sun_fdc->data_82072 = value; 144 break; 145 case 7: /* FD_DCR */ 146 sun_fdc->dcr_82072 = value; 147 break; 148 case 4: /* FD_STATUS */ 149 sun_fdc->status_82072 = value; 150 break; 151 } 152 return; 153 } 154 155 static unsigned char sun_82077_fd_inb(int port) 156 { 157 udelay(5); 158 switch(port & 7) { 159 default: 160 printk("floppy: Asked to read unknown port %d\n", port); 161 panic("floppy: Port bolixed."); 162 case 0: /* FD_STATUS_0 */ 163 return sun_fdc->status1_82077; 164 case 1: /* FD_STATUS_1 */ 165 return sun_fdc->status2_82077; 166 case 2: /* FD_DOR */ 167 return sun_fdc->dor_82077; 168 case 3: /* FD_TDR */ 169 return sun_fdc->tapectl_82077; 170 case 4: /* FD_STATUS */ 171 return sun_fdc->status_82077 & ~STATUS_DMA; 172 case 5: /* FD_DATA */ 173 return sun_fdc->data_82077; 174 case 7: /* FD_DIR */ 175 return sun_read_dir(); 176 } 177 panic("sun_82077_fd_inb: How did I get here?"); 178 } 179 180 static void sun_82077_fd_outb(unsigned char value, int port) 181 { 182 udelay(5); 183 switch(port & 7) { 184 default: 185 printk("floppy: Asked to write to unknown port %d\n", port); 186 panic("floppy: Port bolixed."); 187 case 2: /* FD_DOR */ 188 sun_set_dor(value, 1); 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 case 3: /* FD_TDR */ 200 sun_fdc->tapectl_82077 = value; 201 break; 202 } 203 return; 204 } 205 206 /* For pseudo-dma (Sun floppy drives have no real DMA available to 207 * them so we must eat the data fifo bytes directly ourselves) we have 208 * three state variables. doing_pdma tells our inline low-level 209 * assembly floppy interrupt entry point whether it should sit and eat 210 * bytes from the fifo or just transfer control up to the higher level 211 * floppy interrupt c-code. I tried very hard but I could not get the 212 * pseudo-dma to work in c-code without getting many overruns and 213 * underruns. If non-zero, doing_pdma encodes the direction of 214 * the transfer for debugging. 1=read 2=write 215 */ 216 217 /* Common routines to all controller types on the Sparc. */ 218 static inline void virtual_dma_init(void) 219 { 220 /* nothing... */ 221 } 222 223 static inline void sun_fd_disable_dma(void) 224 { 225 doing_pdma = 0; 226 pdma_base = NULL; 227 } 228 229 static inline void sun_fd_set_dma_mode(int mode) 230 { 231 switch(mode) { 232 case DMA_MODE_READ: 233 doing_pdma = 1; 234 break; 235 case DMA_MODE_WRITE: 236 doing_pdma = 2; 237 break; 238 default: 239 printk("Unknown dma mode %d\n", mode); 240 panic("floppy: Giving up..."); 241 } 242 } 243 244 static inline void sun_fd_set_dma_addr(char *buffer) 245 { 246 pdma_vaddr = buffer; 247 } 248 249 static inline void sun_fd_set_dma_count(int length) 250 { 251 pdma_size = length; 252 } 253 254 static inline void sun_fd_enable_dma(void) 255 { 256 pdma_base = pdma_vaddr; 257 pdma_areasize = pdma_size; 258 } 259 260 int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler); 261 262 static int sun_fd_request_irq(void) 263 { 264 static int once = 0; 265 266 if (!once) { 267 once = 1; 268 return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt); 269 } else { 270 return 0; 271 } 272 } 273 274 static struct linux_prom_registers fd_regs[2]; 275 276 static int sun_floppy_init(void) 277 { 278 struct platform_device *op; 279 struct device_node *dp; 280 struct resource r; 281 char state[128]; 282 phandle fd_node; 283 phandle tnode; 284 int num_regs; 285 286 use_virtual_dma = 1; 287 288 /* Forget it if we aren't on a machine that could possibly 289 * ever have a floppy drive. 290 */ 291 if (sparc_cpu_model != sun4m) { 292 /* We certainly don't have a floppy controller. */ 293 goto no_sun_fdc; 294 } 295 /* Well, try to find one. */ 296 tnode = prom_getchild(prom_root_node); 297 fd_node = prom_searchsiblings(tnode, "obio"); 298 if (fd_node != 0) { 299 tnode = prom_getchild(fd_node); 300 fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo"); 301 } else { 302 fd_node = prom_searchsiblings(tnode, "fd"); 303 } 304 if (fd_node == 0) { 305 goto no_sun_fdc; 306 } 307 308 /* The sun4m lets us know if the controller is actually usable. */ 309 if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) { 310 if(!strcmp(state, "disabled")) { 311 goto no_sun_fdc; 312 } 313 } 314 num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs)); 315 num_regs = (num_regs / sizeof(fd_regs[0])); 316 prom_apply_obio_ranges(fd_regs, num_regs); 317 memset(&r, 0, sizeof(r)); 318 r.flags = fd_regs[0].which_io; 319 r.start = fd_regs[0].phys_addr; 320 sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); 321 322 /* Look up irq in platform_device. 323 * We try "SUNW,fdtwo" and "fd" 324 */ 325 op = NULL; 326 for_each_node_by_name(dp, "SUNW,fdtwo") { 327 op = of_find_device_by_node(dp); 328 if (op) 329 break; 330 } 331 if (!op) { 332 for_each_node_by_name(dp, "fd") { 333 op = of_find_device_by_node(dp); 334 if (op) 335 break; 336 } 337 } 338 if (!op) 339 goto no_sun_fdc; 340 341 FLOPPY_IRQ = op->archdata.irqs[0]; 342 343 /* Last minute sanity check... */ 344 if (sun_fdc->status_82072 == 0xff) { 345 sun_fdc = NULL; 346 goto no_sun_fdc; 347 } 348 349 sun_fdops.fd_inb = sun_82077_fd_inb; 350 sun_fdops.fd_outb = sun_82077_fd_outb; 351 fdc_status = &sun_fdc->status_82077; 352 353 if (sun_fdc->dor_82077 == 0x80) { 354 sun_fdc->dor_82077 = 0x02; 355 if (sun_fdc->dor_82077 == 0x80) { 356 sun_fdops.fd_inb = sun_82072_fd_inb; 357 sun_fdops.fd_outb = sun_82072_fd_outb; 358 fdc_status = &sun_fdc->status_82072; 359 } 360 } 361 362 /* Success... */ 363 allowed_drive_mask = 0x01; 364 return (int) sun_fdc; 365 366 no_sun_fdc: 367 return -1; 368 } 369 370 static int sparc_eject(void) 371 { 372 set_dor(0x00, 0xff, 0x90); 373 udelay(500); 374 set_dor(0x00, 0x6f, 0x00); 375 udelay(500); 376 return 0; 377 } 378 379 #define fd_eject(drive) sparc_eject() 380 381 #define EXTRA_FLOPPY_PARAMS 382 383 static DEFINE_SPINLOCK(dma_spin_lock); 384 385 #define claim_dma_lock() \ 386 ({ unsigned long flags; \ 387 spin_lock_irqsave(&dma_spin_lock, flags); \ 388 flags; \ 389 }) 390 391 #define release_dma_lock(__flags) \ 392 spin_unlock_irqrestore(&dma_spin_lock, __flags); 393 394 #endif /* !(__ASM_SPARC_FLOPPY_H) */ 395