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>
