📄 floppy.h
字号:
} dcsr |= EBUS_DCSR_EN_CNT | EBUS_DCSR_TC; /* * For EBus WRITE means to system memory, which is * READ for us. */ if (mode == DMA_MODE_WRITE) { dcsr &= ~(EBUS_DCSR_WRITE); sun_pci_dma_direction = PCI_DMA_TODEVICE; } else { dcsr |= EBUS_DCSR_WRITE; sun_pci_dma_direction = PCI_DMA_FROMDEVICE; } writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);}static void sun_pci_fd_set_dma_count(int length){ sun_pci_dma_len = length; writel(length, &sun_pci_fd_ebus_dma->dbcr);}static void sun_pci_fd_set_dma_addr(char *buffer){ unsigned int addr; addr = sun_pci_dma_addr = pci_map_single(sun_pci_ebus_dev, buffer, sun_pci_dma_len, sun_pci_dma_direction); writel(addr, &sun_pci_fd_ebus_dma->dacr);}static unsigned int sun_pci_get_dma_residue(void){ unsigned int dcsr, res; res = readl(&sun_pci_fd_ebus_dma->dbcr); if (res != 0) { dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); sun_pci_fd_reset_dma(); writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); } return res;}static void sun_pci_fd_enable_irq(void){ unsigned int dcsr; dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); dcsr |= EBUS_DCSR_INT_EN; writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);}static void sun_pci_fd_disable_irq(void){ unsigned int dcsr; dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); dcsr &= ~(EBUS_DCSR_INT_EN); writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);}static int sun_pci_fd_request_irq(void){ int err; err = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ, "floppy", sun_fdc); if (err) return -1; sun_pci_fd_enable_irq(); return 0;}static void sun_pci_fd_free_irq(void){ sun_pci_fd_disable_irq(); free_irq(FLOPPY_IRQ, sun_fdc);}static int sun_pci_fd_eject(int drive){ return -EINVAL;}/* * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI, * even if this is configured using DS1, thus looks like /dev/fd1 with * the cabling used in Ultras. */#define DOR (port + 2)#define MSR (port + 4)#define FIFO (port + 5)static void sun_pci_fd_out_byte(unsigned long port, unsigned char val, unsigned long reg){ unsigned char status; int timeout = 1000; while (!((status = inb(MSR)) & 0x80) && --timeout) udelay(100); outb(val, reg);}static unsigned char sun_pci_fd_sensei(unsigned long port){ unsigned char result[2] = { 0x70, 0x00 }; unsigned char status; int i = 0; sun_pci_fd_out_byte(port, 0x08, FIFO); do { int timeout = 1000; while (!((status = inb(MSR)) & 0x80) && --timeout) udelay(100); if (!timeout) break; if ((status & 0xf0) == 0xd0) result[i++] = inb(FIFO); else break; } while (i < 2); return result[0];}static void sun_pci_fd_reset(unsigned long port){ unsigned char mask = 0x00; unsigned char status; int timeout = 10000; outb(0x80, MSR); do { status = sun_pci_fd_sensei(port); if ((status & 0xc0) == 0xc0) mask |= 1 << (status & 0x03); else udelay(100); } while ((mask != 0x0f) && --timeout);}static int sun_pci_fd_test_drive(unsigned long port, int drive){ unsigned char status, data; int timeout = 1000; int ready; sun_pci_fd_reset(port); data = (0x10 << drive) | 0x0c | drive; sun_pci_fd_out_byte(port, data, DOR); sun_pci_fd_out_byte(port, 0x07, FIFO); sun_pci_fd_out_byte(port, drive & 0x03, FIFO); do { udelay(100); status = sun_pci_fd_sensei(port); } while (((status & 0xc0) == 0x80) && --timeout); if (!timeout) ready = 0; else ready = (status & 0x10) ? 0 : 1; sun_pci_fd_reset(port); return ready;}#undef FIFO#undef MSR#undef DOR#endif /* CONFIG_PCI */static unsigned long __init sun_floppy_init(void){ char state[128]; struct sbus_bus *bus; struct sbus_dev *sdev = NULL; static int initialized = 0; if (initialized) return sun_floppy_types[0]; initialized = 1; for_all_sbusdev (sdev, bus) { if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) break; } if(sdev) { floppy_sdev = sdev; FLOPPY_IRQ = sdev->irqs[0]; } else {#ifdef CONFIG_PCI struct linux_ebus *ebus; struct linux_ebus_device *edev = 0; unsigned long config = 0; unsigned long auxio_reg; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if (!strcmp(edev->prom_name, "fdthree")) goto ebus_done; } } ebus_done: if (!edev) return 0; prom_getproperty(edev->prom_node, "status", state, sizeof(state)); if(!strncmp(state, "disabled", 8)) return 0; sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start; FLOPPY_IRQ = edev->irqs[0]; /* Make sure the high density bit is set, some systems * (most notably Ultra5/Ultra10) come up with it clear. */ auxio_reg = edev->resource[2].start; writel(readl(auxio_reg)|0x2, auxio_reg); sun_pci_ebus_dev = ebus->self; sun_pci_fd_ebus_dma = (struct linux_ebus_dma *) edev->resource[1].start; sun_pci_fd_reset_dma(); sun_fdops.fd_inb = sun_pci_fd_inb; sun_fdops.fd_outb = sun_pci_fd_outb; use_virtual_dma = 0; sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma; sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma; sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode; sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr; sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count; sun_fdops.get_dma_residue = sun_pci_get_dma_residue; sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq; sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq; sun_fdops.fd_request_irq = sun_pci_fd_request_irq; sun_fdops.fd_free_irq = sun_pci_fd_free_irq; sun_fdops.fd_eject = sun_pci_fd_eject; fdc_status = (unsigned long) &sun_fdc->status_82077; FLOPPY_MOTOR_MASK = 0xf0; /* * XXX: Find out on which machines this is really needed. */ if (1) { sun_pci_broken_drive = 1; sun_fdops.fd_outb = sun_pci_fd_broken_outb; } allowed_drive_mask = 0; if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0)) sun_floppy_types[0] = 4; if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1)) sun_floppy_types[1] = 4; /* * Find NS87303 SuperIO config registers (through ecpp). */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if (!strcmp(edev->prom_name, "ecpp")) { config = edev->resource[1].start; goto config_done; } } } config_done: /* * Sanity check, is this really the NS87303? */ switch (config & 0x3ff) { case 0x02e: case 0x15c: case 0x26e: case 0x398: break; default: config = 0; } if (!config) return sun_floppy_types[0]; /* Enable PC-AT mode. */ ns87303_modify(config, ASC, 0, 0xc0);#ifdef PCI_FDC_SWAP_DRIVES /* * If only Floppy 1 is present, swap drives. */ if (!sun_floppy_types[0] && sun_floppy_types[1]) { /* * Set the drive exchange bit in FCR on NS87303, * make shure other bits are sane before doing so. */ ns87303_modify(config, FER, FER_EDM, 0); ns87303_modify(config, ASC, ASC_DRV2_SEL, 0); ns87303_modify(config, FCR, 0, FCR_LDE); cfg = sun_floppy_types[0]; sun_floppy_types[0] = sun_floppy_types[1]; sun_floppy_types[1] = cfg; if (sun_pci_broken_drive != -1) { sun_pci_broken_drive = 1 - sun_pci_broken_drive; sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb; } }#endif /* PCI_FDC_SWAP_DRIVES */ return sun_floppy_types[0];#else return 0;#endif } prom_getproperty(sdev->prom_node, "status", state, sizeof(state)); if(!strncmp(state, "disabled", 8)) return 0; /* * We cannot do sbus_ioremap here: it does request_region, * which the generic floppy driver tries to do once again. * But we must use the sdev resource values as they have * had parent ranges applied. */ sun_fdc = (struct sun_flpy_controller *) (sdev->resource[0].start + ((sdev->resource[0].flags & 0x1ffUL) << 32UL)); /* Last minute sanity check... */ if(sbus_readb(&sun_fdc->status1_82077) == 0xff) { sun_fdc = (struct sun_flpy_controller *)-1; return 0; } sun_fdops.fd_inb = sun_82077_fd_inb; sun_fdops.fd_outb = sun_82077_fd_outb; can_use_virtual_dma = use_virtual_dma = 1; sun_fdops.fd_enable_dma = sun_fd_enable_dma; sun_fdops.fd_disable_dma = sun_fd_disable_dma; sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode; sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr; sun_fdops.fd_set_dma_count = sun_fd_set_dma_count; sun_fdops.get_dma_residue = sun_get_dma_residue; sun_fdops.fd_enable_irq = sun_fd_enable_irq; sun_fdops.fd_disable_irq = sun_fd_disable_irq; sun_fdops.fd_request_irq = sun_fd_request_irq; sun_fdops.fd_free_irq = sun_fd_free_irq; sun_fdops.fd_eject = sun_fd_eject; fdc_status = (unsigned long) &sun_fdc->status_82077; /* Success... */ allowed_drive_mask = 0x01; sun_floppy_types[0] = 4; sun_floppy_types[1] = 0; return sun_floppy_types[0];}#endif /* !(__ASM_SPARC64_FLOPPY_H) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -