⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmp.c

📁 IEE1394 火线接口驱动 for linux
💻 C
字号:
/* -*- c-basic-offset: 8 -*- * * cmp.c - Connection Management Procedures * Copyright (C) 2001 Kristian H鴊sberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* TODO * ---- * * - Implement IEC61883-1 output plugs and connection management. *   This should probably be part of the general subsystem, as it could *   be shared with dv1394. * * - Add IEC61883 unit directory when loading this module.  This *   requires a run-time changeable config rom. */#include <linux/module.h>#include <linux/list.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/wait.h>#include "hosts.h"#include "highlevel.h"#include "ieee1394.h"#include "ieee1394_core.h"#include "cmp.h"struct plug {	union {		struct cmp_pcr pcr;		quadlet_t quadlet;	} u;	void (*update)(struct cmp_pcr *plug, void *data);	void *data;};struct cmp_host {	struct hpsb_host *host;	union {		struct cmp_mpr ompr;		quadlet_t ompr_quadlet;	} u;	struct plug opcr[2];	union {		struct cmp_mpr impr;		quadlet_t impr_quadlet;	} v;	struct plug ipcr[2];};enum {	CMP_P2P_CONNECTION,	CMP_BC_CONNECTION};#define CSR_PCR_MAP      0x900#define CSR_PCR_MAP_END  0x9fcstatic struct hpsb_highlevel cmp_highlevel;struct cmp_pcr *cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,		  void (*update)(struct cmp_pcr *pcr, void *data),		  void *data){	struct cmp_host *ch;	struct plug *plug;	ch = hpsb_get_hostinfo(&cmp_highlevel, host);	if (opcr_number >= ch->u.ompr.nplugs ||	    ch->opcr[opcr_number].update != NULL)		return NULL;	plug = &ch->opcr[opcr_number];	plug->u.pcr.online = 1;	plug->u.pcr.bcast_count = 0;	plug->u.pcr.p2p_count = 0;	plug->u.pcr.overhead = 0;	plug->u.pcr.payload = payload;	plug->update = update;	plug->data = data;	return &plug->u.pcr;}void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr){	struct cmp_host *ch;	struct plug *plug;	ch = hpsb_get_hostinfo(&cmp_highlevel, host);	plug = (struct plug *)opcr;	if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();	plug->u.pcr.online = 0;	plug->update = NULL;}static void reset_plugs(struct cmp_host *ch){	int i;	ch->u.ompr.non_persistent_ext = 0xff;	for (i = 0; i < ch->u.ompr.nplugs; i++) {		ch->opcr[i].u.pcr.bcast_count = 0;		ch->opcr[i].u.pcr.p2p_count = 0;		ch->opcr[i].u.pcr.overhead = 0;	}}static void cmp_add_host(struct hpsb_host *host){	struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch));	if (ch == NULL) {		HPSB_ERR("Failed to allocate cmp_host");		return;	}	ch->host = host;	ch->u.ompr.rate = IEEE1394_SPEED_100;	ch->u.ompr.bcast_channel_base = 63;	ch->u.ompr.nplugs = 2;	reset_plugs(ch);}static void cmp_host_reset(struct hpsb_host *host){	struct cmp_host *ch;	ch = hpsb_get_hostinfo(&cmp_highlevel, host);	if (ch == NULL) {		HPSB_ERR("cmp: Tried to reset unknown host");		return;	}	reset_plugs(ch);}static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,		    u64 addr, size_t length, u16 flags){	int csraddr = addr - CSR_REGISTER_BASE;	int plug;	struct cmp_host *ch;		if (length != 4)		return RCODE_TYPE_ERROR;	ch = hpsb_get_hostinfo(&cmp_highlevel, host);	if (csraddr == 0x900) {		*buf = cpu_to_be32(ch->u.ompr_quadlet);		return RCODE_COMPLETE;   	}	else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {		plug = (csraddr - 0x904) / 4;		*buf = cpu_to_be32(ch->opcr[plug].u.quadlet);		return RCODE_COMPLETE;	}	else if (csraddr < 0x980) {		return RCODE_ADDRESS_ERROR;	}	else if (csraddr == 0x980) {		*buf = cpu_to_be32(ch->v.impr_quadlet);		return RCODE_COMPLETE;   	}	else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {		plug = (csraddr - 0x984) / 4;		*buf = cpu_to_be32(ch->ipcr[plug].u.quadlet);		return RCODE_COMPLETE;	}	else		return RCODE_ADDRESS_ERROR;}static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,		    u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags){	int csraddr = addr - CSR_REGISTER_BASE;	int plug;	struct cmp_host *ch;	ch = hpsb_get_hostinfo(&cmp_highlevel, host);		if (extcode != EXTCODE_COMPARE_SWAP) 		return RCODE_TYPE_ERROR;		if (csraddr == 0x900) {		/* FIXME: Ignore writes to bits 30-31 and 0-7 */		*store = cpu_to_be32(ch->u.ompr_quadlet);		if (arg == cpu_to_be32(ch->u.ompr_quadlet))			ch->u.ompr_quadlet = be32_to_cpu(data);		return RCODE_COMPLETE;	}	if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {		plug = (csraddr - 0x904) / 4;		*store = cpu_to_be32(ch->opcr[plug].u.quadlet);		if (arg == *store)			ch->opcr[plug].u.quadlet = be32_to_cpu(data);		if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet &&		    ch->opcr[plug].update != NULL)			ch->opcr[plug].update(&ch->opcr[plug].u.pcr,					      ch->opcr[plug].data);		return RCODE_COMPLETE;	}	else if (csraddr < 0x980) {		return RCODE_ADDRESS_ERROR;	}	else if (csraddr == 0x980) {		/* FIXME: Ignore writes to bits 24-31 and 0-7 */		*store = cpu_to_be32(ch->u.ompr_quadlet);		if (arg == cpu_to_be32(ch->u.ompr_quadlet))			ch->u.ompr_quadlet = be32_to_cpu(data);		return RCODE_COMPLETE;	}	else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {		plug = (csraddr - 0x984) / 4;		*store = cpu_to_be32(ch->ipcr[plug].u.quadlet);		if (arg == *store)			ch->ipcr[plug].u.quadlet = be32_to_cpu(data);		if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet &&		    ch->ipcr[plug].update != NULL)			ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr,					      ch->ipcr[plug].data);		return RCODE_COMPLETE;	}	else		return RCODE_ADDRESS_ERROR;}static struct hpsb_highlevel cmp_highlevel = {	.name =		"cmp",	.add_host =	cmp_add_host,        .host_reset =	cmp_host_reset,};static struct hpsb_address_ops pcr_ops = {	.read =	pcr_read,        .lock =	pcr_lock,};/* Module interface */MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");MODULE_DESCRIPTION("Connection Management Procedures (CMP)");MODULE_SUPPORTED_DEVICE("cmp");MODULE_LICENSE("GPL");EXPORT_SYMBOL(cmp_register_opcr);EXPORT_SYMBOL(cmp_unregister_opcr);static int __init cmp_init_module (void){	hpsb_register_highlevel (&cmp_highlevel);	hpsb_register_addrspace(&cmp_highlevel, &pcr_ops,				CSR_REGISTER_BASE + CSR_PCR_MAP,				CSR_REGISTER_BASE + CSR_PCR_MAP_END);	HPSB_INFO("Loaded CMP driver");	return 0;}static void __exit cmp_exit_module (void){        hpsb_unregister_highlevel(&cmp_highlevel);	HPSB_INFO("Unloaded CMP driver");}module_init(cmp_init_module);module_exit(cmp_exit_module);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -