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