/* $NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $ */ /* public domain */ #include __KERNEL_RCSID(0, "$NetBSD: gayle.c,v 1.8 2015/01/16 23:34:11 phx Exp $"); /* * Gayle management - provide functions for use in the drivers that utilise * the chip. * * These overly complicated routines try to deal with a few variants of * Gayle chip that exists. */ #include #include #include #include #include /* #define GAYLE_DEBUG 1 */ struct gayle_tag { struct bus_space_tag gayle_io_bst; bus_space_tag_t gayle_io_t; bus_space_handle_t gayle_io_h; struct bus_space_tag gayle_isr_bst; bus_space_tag_t gayle_isr_t; bus_space_handle_t gayle_isr_h; }; typedef struct gayle_tag *gayle_tag_t; /* * Having these as static variables is ugly, but they don't fit into * driver's softc, as the chip might be utilised by many different drivers. * And since we can only have one Gayle per system it should be okay. */ static struct gayle_tag gayle; static gayle_tag_t gayle_t = NULL; /* * Any module that uses gayle should call gayle_init() before using anything * related to gayle. gayle_init() can be called multiple times. */ void gayle_init(void) { bus_addr_t gayle_vbase; if (gayle_t != NULL) return; #ifdef GAYLE_DEBUG aprint_normal("gayle: doing init\n"); #endif /* GAYLE_DEBUG */ gayle_t = &gayle; gayle_vbase = (bus_addr_t) __UNVOLATILE(ztwomap(GAYLE_REGS_BASE)); gayle_t->gayle_io_bst.base = gayle_vbase; gayle_t->gayle_io_bst.absm = &amiga_bus_stride_0x1000; gayle_t->gayle_io_t = &(gayle_t->gayle_io_bst); bus_space_map(gayle_t->gayle_io_t, 0, 0x4, 0, &gayle_t->gayle_io_h); /* * The A4000 variant of Gayle has interrupt status register at offset * +0x1000 from IDE registers. * XXX: in fact, on A4000 we should initialise only this part... */ if (is_a4000()) { gayle_t->gayle_isr_bst.base = (bus_addr_t) __UNVOLATILE(ztwomap( GAYLE_IDE_BASE_A4000+GAYLE_IDE_INTREQ_A4000)); gayle_t->gayle_isr_bst.absm = &amiga_bus_stride_1; gayle_t->gayle_isr_t = &(gayle_t->gayle_isr_bst); bus_space_map(gayle_t->gayle_isr_t, 0, 0x1, 0, &(gayle_t->gayle_isr_h)); } else { bus_space_subregion(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_INTREQ, 0x1, &(gayle_t->gayle_isr_h)); gayle_t->gayle_isr_bst = gayle_t->gayle_io_bst; gayle_t->gayle_isr_t = gayle_t->gayle_io_t; } } uint8_t gayle_intr_status(void) { uint8_t rv; rv = bus_space_read_1(gayle_t->gayle_isr_t, gayle_t->gayle_isr_h, 0); #ifdef GAYLE_DEBUG aprint_normal("gayle: intr status %x\n", rv); #endif /* GAYLE_DEBUG */ return rv; } uint8_t gayle_intr_enable_read(void) { uint8_t rv; rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_INTENA); #ifdef GAYLE_DEBUG aprint_normal("gayle: intr enable register read %x\n", rv); #endif /* GAYLE_DEBUG */ return rv; } void gayle_intr_enable_write(uint8_t val) { #ifdef GAYLE_DEBUG aprint_normal("gayle: intr enable register write %x\n", val); #endif /* GAYLE_DEBUG */ bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_INTENA, val); } void gayle_intr_enable_set(uint8_t bits) { uint8_t val; val = gayle_intr_enable_read(); gayle_intr_enable_write(val | bits); } void gayle_intr_ack(uint8_t val) { #ifdef GAYLE_DEBUG aprint_normal("gayle: intr ack write %x\n", val); #endif /* GAYLE_DEBUG */ bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_INTREQ, val); } uint8_t gayle_pcmcia_status_read(void) { uint8_t rv; rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_PCC_STATUS); #ifdef GAYLE_DEBUG aprint_normal("gayle: pcmcia status read %x\n", rv); #endif /* GAYLE_DEBUG */ return rv; } void gayle_pcmcia_status_write(uint8_t val) { #ifdef GAYLE_DEBUG aprint_normal("gayle: pcmcia status write %x\n", val); #endif /* GAYLE_DEBUG */ bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_PCC_STATUS, val); } void gayle_pcmcia_config_write(uint8_t val) { #ifdef GAYLE_DEBUG aprint_normal("gayle: pcmcia config write %x\n", val); #endif /* GAYLE_DEBUG */ bus_space_write_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_PCC_CONFIG, val); } uint8_t gayle_pcmcia_config_read(void) { uint8_t rv; rv = bus_space_read_1(gayle_t->gayle_io_t, gayle_t->gayle_io_h, GAYLE_PCC_CONFIG); #ifdef GAYLE_DEBUG aprint_normal("gayle: pcmcia config read %x\n", rv); #endif /* GAYLE_DEBUG */ return rv; }