in include/asm/floppy_64.h [548:764]
static unsigned long __init sun_floppy_init(void)
{
static int initialized = 0;
struct device_node *dp;
struct platform_device *op;
const char *prop;
char state[128];
if (initialized)
return sun_floppy_types[0];
initialized = 1;
op = NULL;
for_each_node_by_name(dp, "SUNW,fdtwo") {
if (!of_node_name_eq(dp->parent, "sbus"))
continue;
op = of_find_device_by_node(dp);
if (op)
break;
}
if (op) {
floppy_op = op;
FLOPPY_IRQ = op->archdata.irqs[0];
} else {
struct device_node *ebus_dp;
void __iomem *auxio_reg;
const char *state_prop;
unsigned long config;
dp = NULL;
for_each_node_by_name(ebus_dp, "ebus") {
for (dp = ebus_dp->child; dp; dp = dp->sibling) {
if (ebus_fdthree_p(dp))
goto found_fdthree;
}
}
found_fdthree:
if (!dp)
return 0;
op = of_find_device_by_node(dp);
if (!op)
return 0;
state_prop = of_get_property(op->dev.of_node, "status", NULL);
if (state_prop && !strncmp(state_prop, "disabled", 8))
return 0;
FLOPPY_IRQ = op->archdata.irqs[0];
/* Make sure the high density bit is set, some systems
* (most notably Ultra5/Ultra10) come up with it clear.
*/
auxio_reg = (void __iomem *) op->resource[2].start;
writel(readl(auxio_reg)|0x2, auxio_reg);
sun_floppy_dev = &op->dev;
spin_lock_init(&sun_pci_fd_ebus_dma.lock);
/* XXX ioremap */
sun_pci_fd_ebus_dma.regs = (void __iomem *)
op->resource[1].start;
if (!sun_pci_fd_ebus_dma.regs)
return 0;
sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
EBUS_DMA_FLAG_TCI_DISABLE);
sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
sun_pci_fd_ebus_dma.client_cookie = NULL;
sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
strcpy(sun_pci_fd_ebus_dma.name, "floppy");
if (ebus_dma_register(&sun_pci_fd_ebus_dma))
return 0;
/* XXX ioremap */
sun_fdc = (struct sun_flpy_controller *) op->resource[0].start;
sun_fdops.fd_inb = sun_pci_fd_inb;
sun_fdops.fd_outb = sun_pci_fd_outb;
can_use_virtual_dma = 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_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;
/*
* 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).
*/
config = 0;
for (dp = ebus_dp->child; dp; dp = dp->sibling) {
if (of_node_name_eq(dp, "ecpp")) {
struct platform_device *ecpp_op;
ecpp_op = of_find_device_by_node(dp);
if (ecpp_op)
config = ecpp_op->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 sure 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);
config = sun_floppy_types[0];
sun_floppy_types[0] = sun_floppy_types[1];
sun_floppy_types[1] = config;
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];
}
prop = of_get_property(op->dev.of_node, "status", NULL);
if (prop && !strncmp(state, "disabled", 8))
return 0;
/*
* We cannot do of_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 *)
(op->resource[0].start +
((op->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_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];
}