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

📄 hal_5i2x.c

📁 CNC 的开放码,EMC2 V2.2.8版
💻 C
字号:
/*************************************************************************Copyright (C) 2007 John Kasunich <jmkasunich AT sourceforge DOT net>$RCSfile: hal_5i2x.c,v $$Author: jmkasunich $$Locker:  $$Revision: 1.4 $$State: Exp $$Date: 2007/07/16 02:43:39 $This is the driver for the Mesa Electronics 5i20 board.The board includes a user programable FPGA. This driverwill ultimately handle a wide range of FPGA configurations.*************************************************************************//*************************************************************************Installation of the driver (realtime only):first load the FPGA config:   bfload <bitfile> <boardnum>then load the actual driver:  insmod hal_5i2xusing halcmd:loadusr -w bfload <bitfile> <boardnum>loadrt hal_5i2xThe FPGA contains a 1024 byte RAM, and the RAM contains FPGA specificinfo that tells the driver what is in the FPGA (and thus what HAL stuffneeds to be exported).  The RAM is treated as a stream of bytes:pre-header: 4 bytes of 00, treated as no-careheader:	1 byte: protocol version (in case of future format changes		that make the RAM incompatible with older drivers)	1 byte: board ID, 1 for 5i20, 2 for 5i22blocks: each block starts with a code that identifies the type of	block it is and the code that parses it.  A code of zero means	the end of the data (no more blocks).  The main driver simply	calls an export function for each block, that function reads	the block content, and passes back a pointer to the first	byte of the following block.The space after the data is filled with zeros.  The last two bytesare a checksum, used to verify that the driver is actually talkingto a 5i2x board with a valid configuration in it.************************************************************************This program is free software; you can redistribute it and/ormodify it under the terms of version 2 of the GNU GeneralPublic License as published by the Free Software Foundation.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USATHE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FORANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISETO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable ofharming persons must have provisions for completely removing powerfrom all motors, etc, before persons enter any danger area.  Allmachinery must be designed to comply with local and national safetycodes, and the authors of this software can not, and do not, takeany responsibility for such compliance.This code was written as part of the EMC HAL project.  For moreinformation, go to www.linuxcnc.org.*************************************************************************/#ifndef RTAPI#error This is a realtime component only!#endif#include <linux/pci.h>#include "rtapi.h"			// RTAPI realtime OS API.#include "rtapi_app.h"			// RTAPI realtime module decls.#include "hal.h"			// HAL public API decls.#include "hal_5i2x.h"			// Hardware dependent defines.#ifndef MODULE#define MODULE#endif#ifdef MODULE// Module information.MODULE_AUTHOR("John Kasunich");MODULE_DESCRIPTION("Driver for Mesa Electronics 5i2x for EMC HAL");MODULE_LICENSE("GPL");#endif // MODULE/***************************************************************************                          config ROM defines***************************************************************************/#if 0  /* FIXME - this stuff is still up in the air *//* input options: regular or not-an-input */#define IN_MASK		0x1#define GPIN_NONE	0x0/* if GPIN, export p0-00.in and p0-00.in-not */#define GPIN		0x1/* output options: regular, open-collector, tri-state, or not-an-output */#define OUT_MASK	0xE#define GPOUT_NONE	0x0/* if GPOUT_REG, export p0-00.out and p0-00.invert */#define GPOUT_REG	0x2/* if GPOUT_OC, export p0-00.out and p0-00.invert */#define GPOUT_OC	0x4/* if GPOUT_TS, export p0-00.out, p0-00.invert, and p0-00.out-ena */#define GPOUT_TS	0x6/* if SPOUT_REG, export p0-00.invert */#define SPOUT_REG	0xA/* if SPOUT_OC, export p0-00.invert */#define SPOUT_OC	0xC#endif/*************************************************************************                          typedefs and defines*************************************************************************/// Vendor and device ID.#define M5I20_VENDOR_ID			0x10B5		// PLX.#define M5I20_DEVICE_ID			0x9030		// 9030 SMARTarget I/O Accelerator.#define M5I20_SUBSYS_VENDOR_ID		0x10B5		// PLX.#define M5I20_SUBSYS_DEVICE_ID		0x3131		// Mesa 5i20./* general I/O *//* add 4 for each group of 24 pins (one connector) */#define GPIO_DATA	0x1000#define GPIO_DIR	0x1100/*************************************************************************                                   Globals*************************************************************************/#define MAX_BOARDS	4int comp_id;	/* HAL component ID */static board_data_t *boards[MAX_BOARDS];/******************************************************************************                              Init and exit code ******************************************************************************/int rtapi_app_main(void){    int n, i, retval;    __u8 config_data[CFG_RAM_SIZE], *cfg_ptr, *end_ptr;    __u32 data;    __u16 checksum1, checksum2;    __u8 protocol_version;    __u8 board_code, block_code;    board_data_t *board;    struct pci_dev *pDev;    // Connect to the HAL.    comp_id = hal_init("hal_5i2x");    if (comp_id < 0) {	rtapi_print_msg(RTAPI_MSG_ERR, "5i2x: ERROR: hal_init() failed\n");	return(-1);    }    for ( n = 0 ; n < MAX_BOARDS ; n++ ) {	boards[n] = NULL;    }    pDev = NULL;    for ( n = 0 ; n < MAX_BOARDS ; n++ ) {	// Find a M5I20 card.	pDev = pci_find_device(M5I20_VENDOR_ID, M5I20_DEVICE_ID, pDev);	if ( pDev == NULL ) {	    /* no more boards */	    break;	}	/* FIXME: this code would probably detect ANY board using the	   PLX9030 bridge chip as if it was a 5i20 board.  It is also	   neccessary to check the subsystem ID.  Add that later... */	/* Allocate HAL memory for the board */	board = (board_data_t *)(hal_malloc(sizeof(board_data_t)));	if ( board == NULL ) {	    rtapi_print_msg(RTAPI_MSG_ERR, "5i2x: ERROR: hal_malloc() failed\n");	    rtapi_app_exit();	    return -1;	}	/* gather info about the board and save it */	board->pci_dev = pDev;	board->slot = PCI_SLOT(pDev->devfn);	board->num = n;	rtapi_print_msg(RTAPI_MSG_INFO,	     "5i2x: Board %d detected in Slot: %2x\n", board->num, board->slot);	/* region 5 is the 32 bit memory mapped region */	board->len = pci_resource_len(pDev, 5);	board->base = ioremap_nocache(pci_resource_start(pDev, 5), board->len);	if ( board->base == NULL ) {	    rtapi_print_msg(RTAPI_MSG_ERR,		"5i2x: ERROR: could not map board %d FPGA data\n", board->num );	    rtapi_app_exit();	    return -1;	} else {	    rtapi_print_msg(RTAPI_MSG_INFO,		"5i2x: board %d FPGA data mapped to %08lx, Len = %ld\n",		board->num, (long)board->base, (long)board->len);	}	/* read the configuration RAM */	i = 0;	while ( i < CFG_RAM_SIZE ) {	    data = ioread32(board->base+i);	    config_data[i++] = data & 0xFF;	    data >>= 8;	    config_data[i++] = data & 0xFF;	    data >>= 8;	    config_data[i++] = data & 0xFF;	    data >>= 8;	    config_data[i++] = data & 0xFF;	}	/* mask out first four bytes */	for ( i = 0 ; i < 4 ; i++ ) {	    config_data[i] = 0;	}	/* calculate the checksum */	/* we use a 16 bit variant on Adler32, it is more robust than	   a simple checksum, and simpler to compute than a real CRC */	checksum1 = 0;	checksum2 = 0;	for ( i = 0 ; i <= DATA_END_ADDR ; i++ ) {	    checksum1 += config_data[i];	    checksum1 = checksum1 % 251;	    checksum2 += checksum1;	    checksum2 = checksum2 % 251;	}	/* validate the checksum */	if (( checksum1 != config_data[CHECKSUM1_ADDR] ) ||	    ( checksum2 != config_data[CHECKSUM2_ADDR] )) {	    rtapi_print_msg(RTAPI_MSG_ERR,		"5i2x0: ERROR: board %d RAM checksum, is config loaded?\n",		board->num );	    rtapi_app_exit();	    return -1;	}	rtapi_print_msg(RTAPI_MSG_INFO,	    "5i2x: board %d checksum OK\n", board->num );	/* get header info and validate it */	protocol_version = config_data[PROTOCOL_VERSION_ADDR];	if (( protocol_version < MIN_PROTOCOL_VERSION ) ||	    ( protocol_version > MAX_PROTOCOL_VERSION )) {	    rtapi_print_msg(RTAPI_MSG_ERR,		"5i2x: ERROR: board %d data is version %d\n",		board->num, protocol_version );	    rtapi_print_msg(RTAPI_MSG_ERR,		"5i2x: ERROR: this driver works with version %d thru %d only\n",		MIN_PROTOCOL_VERSION, MAX_PROTOCOL_VERSION );	    rtapi_app_exit();	    return -1;	}	board_code = config_data[BOARD_CODE_ADDR];	if ( board_code == BOARD_CODE_5I20 ) {	    rtapi_print_msg(RTAPI_MSG_INFO,		"5i2x: board %d code says 5i20\n", board->num );	} else {	    rtapi_print_msg(RTAPI_MSG_ERR,		"5i2x: ERROR: board %d has unknown board code '%d'\n",		board->num, board_code );	    rtapi_app_exit();	    return -1;	}	/* point to first block of data */	cfg_ptr = &(config_data[DATA_START_ADDR]);	end_ptr = &(config_data[DATA_END_ADDR]);	/* loop thru all blocks, calling the appropriate export functions */	while (( cfg_ptr < end_ptr ) && ( *cfg_ptr > 0 )) {	    /* we have a block */	    block_code = *cfg_ptr;	    retval = -1;	    switch ( block_code ) {	    case GPIO:		rtapi_print("GPIO, code is %d, at %d\n", block_code, i );		retval = export_gpio(&cfg_ptr, board);		break;	    case STEPGEN_VEL_MODE:		rtapi_print("stepgen, code is %d, at %d\n", block_code, i );		retval = export_stepgen(&cfg_ptr, board);		break;	    default:		rtapi_print_msg(RTAPI_MSG_ERR,		    "5i2x: ERROR: board %d: unknown block code '%d' at %d\n",		    board->num, block_code, i );		rtapi_app_exit();		return -1;	    }	    if ( retval != 0 ) {		rtapi_print_msg(RTAPI_MSG_ERR,		    "5i2x: ERROR: export failed: board %d, block code '%d' cfg RAM addr %04x\n",		    board->num, block_code, i );		rtapi_app_exit();		return -1;	    }	}    }    if(n == 0){	/* No cards detected */	rtapi_print_msg(RTAPI_MSG_ERR, "5I2x: ERROR: No 5I20 card(s) detected\n");	rtapi_app_exit();	return(-1);    }    hal_ready(comp_id);    return(0);}void rtapi_app_exit(void){    int n;    hal_exit(comp_id);    for ( n = 0; n < MAX_BOARDS; n++ ) {	if ( boards[n] != NULL) {	    // Unmap board memory	    if ( boards[n]->base != NULL ) {		iounmap(boards[n]->base);	    }	}    }}

⌨️ 快捷键说明

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