Date: Sun, 09 Mar 1997 12:37:50 -0500 From: "Brian J. McGovern" <mcgovern@spoon.beta.com> To: hackers@freebsd.org Subject: Mapping shared memory... Message-ID: <199703091737.MAA17015@spoon.beta.com>
next in thread | raw e-mail | index | archive | help
*sigh* At least I'm making headway. I've looked at a couple of other drivers, to see how they handle getting shared memory mapped on a PCI card, and this is what I came up with... Can anybody let me know if this is right/wrong/there is a better way? Thanks. -Brian /* First, set up our memory window. Its 512 Kb in size. We're supposed to get the pointer to it from the config register specified as BASE_ADDR_2 */ czcontrol.window[board] = (unsigned char *) pmap_mapdev(pci_conf_read(config_id, CYZ_PCI_BASE_ADDR2), 0x80000); /* Next, we need to get the memory offset for the 9060 registers. Its supposed to be at BASE_ADDR_1 */ czcontrol.i9060[board] = (struct RUNTIME_9060 *) pmap_mapdev(pci_conf_read(config_id, CYZ_PCI_BASE_ADDR1), sizeof(struct RUNTIME_9060)); /* Next, we find the firmware structure, which is supposed to be at an offset of ID_ADDRESS from the base of the window defined above */ czcontrol.firmid[board] = (struct FIRM_ID *)(czcontrol.window[board] + ID_ADDRESS); For those of you who'd like a better context, heres the whole driver function to date: #include "cz.h" #if NCZ > 0 #include <unistd.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/reboot.h> #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/proc.h> #include <sys/conf.h> #include <sys/file.h> #include <sys/uio.h> #include <sys/kernel.h> #include <sys/syslog.h> #include <machine/clock.h> #include <vm/vm.h> #include <vm/pmap.h> #include <pci/pcivar.h> #include <dev/cz/cz.h> #include <dev/cz/lcz.h> #include <dev/cz/cyclomz.h> #include <dev/cz/zfwint.h> #include <dev/cz/zfirm.h> static char *cz_probe __P((pcici_t, pcidi_t)); static void cz_attach __P((pcici_t, int)); static void cz_intr __P((void *)); static u_long cz_count = 0; static struct pci_device cz_device={"cz", cz_probe, cz_attach, &cz_count, NULL}; DATA_SET(pcidevice_set, cz_device); #define MAX_BOARDS 4 void delay1ms(void); static struct czsoftc { unsigned long active_boards; unsigned char ports[MAX_BOARDS][MAX_CHAN]; pcici_t config_id[MAX_BOARDS]; int unit[MAX_BOARDS]; unsigned char *window[MAX_BOARDS]; unsigned char irq[MAX_BOARDS]; struct FIRM_ID *firmid[MAX_BOARDS]; struct CUSTOM_REG *custom_regs[MAX_BOARDS]; struct ZFW_CTRL *zfw_ctrl[MAX_BOARDS]; struct RUNTIME_9060 *i9060[MAX_BOARDS]; struct BOARD_CTRL *board_ctrl[MAX_BOARDS]; struct CH_CTRL *channel_ctrl[MAX_BOARDS][MAX_CHAN]; struct BUF_CTRL *buffer_ctrl[MAX_BOARDS][MAX_CHAN]; } czcontrol; static unsigned char first_probe = 1; static void cz_intr(void *token) { } static char *cz_probe(pcici_t config_id, pcidi_t device_id) { if (((device_id & 0xffff) != CYZ_VENDOR_ID) || (((device_id >> 16) != 0x200) && ((device_id >> 16) != 0x201))) return NULL; else return "Cyclades Cyclom-Zo Serial Adapter"; } void cz_attach(pcici_t config_id, int unit) { int i; unsigned long reg; vm_offset_t paddr; int board, port; if (first_probe == 1) { czcontrol.active_boards = 0L; for (board = 0; board < MAX_BOARDS; board++) { for (port = 0;port < MAX_CHAN; port++) { czcontrol.ports[board][port] = 0; czcontrol.channel_ctrl[board][port] = NULL; czcontrol.buffer_ctrl[board][port] = NULL; } czcontrol.zfw_ctrl[board] = NULL; czcontrol.i9060[board] = NULL; czcontrol.window[board] = NULL; czcontrol.irq[board] = 0; czcontrol.unit[board] = 0; czcontrol.firmid[board] = NULL; czcontrol.custom_regs[board] = NULL; czcontrol.board_ctrl[board] = NULL; } first_probe = 0; } czcontrol.active_boards++; board = czcontrol.active_boards - 1; czcontrol.config_id[board] = config_id; czcontrol.window[board] = (unsigned char *) pmap_mapdev(pci_conf_read(config_id, CYZ_PCI_BASE_ADDR2), 0x80000); czcontrol.i9060[board] = (struct RUNTIME_9060 *) pmap_mapdev(pci_conf_read(config_id, CYZ_PCI_BASE_ADDR1), sizeof(struct RUNTIME_9060)); czcontrol.firmid[board] = (struct FIRM_ID *)(czcontrol.window[board] + ID_ADDRESS); czcontrol.custom_regs[board] = (struct CUSTOM_REG *)czcontrol.window[board]; reg = czcontrol.i9060[board]->init_ctrl; reg |= (0x40000000); czcontrol.i9060[board]->init_ctrl = reg; DELAY(300); reg &= ~(0x40000000); czcontrol.i9060[board]->init_ctrl = reg; DELAY(300); czcontrol.i9060[board]->loc_addr_base = WIN_CREG; czcontrol.custom_regs[board]->cpu_stop = 0; czcontrol.i9060[board]->loc_addr_base = WIN_RAM; memcpy(czcontrol.window[board],zfw, zfw_SIZE); czcontrol.i9060[board]->loc_addr_base = WIN_CREG; czcontrol.custom_regs[board]->cpu_start = 0; czcontrol.i9060[board]->loc_addr_base = WIN_RAM; DELAY(1000); if (czcontrol.firmid[board]->signature == ZFIRM_ID) { czcontrol.zfw_ctrl[board] = (struct ZFW_CTRL *)(czcontrol.window[board] + czcontrol.firmid[board]->zfwctrl_addr); } else { czcontrol.active_boards = 0; printf("Board %d did not start properly. All boards shut down.\n",unit); return; } czcontrol.board_ctrl[board] = &czcontrol.zfw_ctrl[board]->board_ctrl; czcontrol.board_ctrl[board]->op_system = C_OS_BSD; czcontrol.board_ctrl[board]->dr_version - 0x001; i = czcontrol.board_ctrl[board]->n_channel; for (port=0;port < i;port++) { czcontrol.channel_ctrl[board][port] = (struct CH_CTRL *)(&czcontrol.zfw_ctrl[board]->ch_ctrl + sizeof(struct CH_CTRL)); czcontrol.buffer_ctrl[board][port] = (struct BUF_CTRL *)(&czcontrol.zfw_ctrl[board]->buf_ctrl + sizeof(struct BUF_CTRL)); czcontrol.ports[board][port] |= (1 << port); } } #endif /* NCZ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199703091737.MAA17015>