1 /****************************************************************************
3 * Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
5 * - All rights reserved -
7 * This code is provided "as is" without warranty of any kind, either
8 * expressed or implied, including but not limited to the liability
9 * concerning the freedom from material defects, the fitness for parti-
10 * cular purposes or the freedom of proprietary rights of third parties.
12 *****************************************************************************
13 * Module name.: cpcusb
14 *****************************************************************************
16 *****************************************************************************
17 * Project.....: Windows Driver Development Kit
18 * Filename....: sja2m16c.cpp
19 * Authors.....: (GU) Gerhard Uttenthaler
20 * (CS) Christian Schoett
21 *****************************************************************************
22 * Short descr.: converts baudrate between SJA1000 and M16C
23 *****************************************************************************
24 * Description.: handles the baudrate conversion from SJA1000 parameters to
26 *****************************************************************************
27 * Address : EMS Dr. Thomas Wuensche
30 * Tel. : +49-8441-490260
31 * Fax. : +49-8441-81860
32 * email: support@ems-wuensche.com
33 *****************************************************************************
35 *****************************************************************************
36 * Version Date Auth Remark
38 * 01.00 ?? GU - initial release
39 * 01.10 ?????????? CS - adapted to fit into the USB Windows driver
40 * 02.00 18.08.2004 GU - improved the baudrate calculating algorithm
41 * - implemented acceptance filtering
42 * 02.10 10.09.2004 CS - adapted to fit into the USB Windows driver
43 *****************************************************************************
45 *****************************************************************************
48 /****************************************************************************/
51 #include <linux/kernel.h>
52 #include <linux/errno.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/vmalloc.h>
56 #include <linux/module.h>
57 #include <linux/poll.h>
58 #include <linux/smp_lock.h>
59 #include <linux/completion.h>
60 #include <asm/uaccess.h>
61 #include <linux/usb.h>
69 /*********************************************************************/
70 int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
72 return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
78 /*********************************************************************/
79 int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
81 return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
86 /****************************************************************************
87 * Function.....: SJA1000_TO_M16C_BASIC_Params
89 * Task.........: This routine converts SJA1000 CAN btr parameters into M16C
90 * parameters based on the sample point and the error. In
91 * addition it converts the acceptance filter parameters to
92 * suit the M16C parameters
99 *****************************************************************************
101 *****************************************************************************
102 * 19.01.2005 CS - modifed the conversion of SJA1000 filter params into
103 * M16C params. Due to compatibility reasons with the
104 * older 82C200 CAN controller the SJA1000
105 ****************************************************************************/
106 int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
110 int *baudrate_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
111 int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
112 int baudrate_error_merk;
113 int clk, brp, pr, ph1, ph2;
114 int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
116 unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
117 unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
124 // we have to convert the parameters into M16C parameters
125 CPC_SJA1000_PARAMS_T * pParams;
127 // check if the type is CAN parameters and if we have to convert the given params
128 if (in->type != CPC_CMD_T_CAN_PRMS
129 || in->msg.canparams.cc_type != SJA1000)
132 (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
133 acc_code0 = pParams->acc_code0;
134 acc_code1 = pParams->acc_code1;
135 acc_code2 = pParams->acc_code2;
136 acc_code3 = pParams->acc_code3;
137 acc_mask0 = pParams->acc_mask0;
138 acc_mask1 = pParams->acc_mask1;
139 acc_mask2 = pParams->acc_mask2;
140 acc_mask3 = pParams->acc_mask3;
142 #ifdef _DEBUG_OUTPUT_CAN_PARAMS
143 info("acc_code0: %2.2Xh\n", acc_code0);
144 info("acc_code1: %2.2Xh\n", acc_code1);
145 info("acc_code2: %2.2Xh\n", acc_code2);
146 info("acc_code3: %2.2Xh\n", acc_code3);
147 info("acc_mask0: %2.2Xh\n", acc_mask0);
148 info("acc_mask1: %2.2Xh\n", acc_mask1);
149 info("acc_mask2: %2.2Xh\n", acc_mask2);
150 info("acc_mask3: %2.2Xh\n", acc_mask3);
155 (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
156 err("Could not allocate memory\n");
161 (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
162 err("Could not allocate memory\n");
163 vfree(baudrate_error);
166 memset(baudrate_error, 0xff, sizeof(baudrate_error));
167 memset(samplepoint_error, 0xff, sizeof(baudrate_error));
169 16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
171 100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
172 if (sjaBaudrate == 0) {
173 vfree(baudrate_error);
174 vfree(samplepoint_error);
178 #ifdef _DEBUG_OUTPUT_CAN_PARAMS
179 info("\nStarting SJA CAN params\n");
180 info("-------------------------\n");
181 info("TS1 : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
182 info("BTR0 : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
184 info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
186 info("Sample P: 0.%d\n", sjaSamplepoint);
190 c0con.bc0con.sam = SJA_SAM;
191 c1con.bc1con.sjw = SJA_SJW;
193 // calculate errors for all baudrates
195 for (clk = 0; clk < 5; clk++) {
196 for (brp = 0; brp < 16; brp++) {
197 for (pr = 0; pr < 8; pr++) {
198 for (ph1 = 0; ph1 < 8; ph1++) {
199 for (ph2 = 0; ph2 < 8; ph2++) {
200 baudrate_error[index] =
207 samplepoint_error[index] =
215 ("Baudrate : %d kBaud\n",
221 ("Baudrate Error: %d\n",
225 ("Sample P Error: %d\n",
240 // mark all baudrate_error entries which are outer limits
242 for (clk = 0; clk < 5; clk++) {
243 for (brp = 0; brp < 16; brp++) {
244 for (pr = 0; pr < 8; pr++) {
245 for (ph1 = 0; ph1 < 8; ph1++) {
246 for (ph2 = 0; ph2 < 8; ph2++) {
247 if ((baudrate_error[index]
249 BAUDRATE_TOLERANCE_PERCENT)
253 SAMPLEPOINT_TOLERANCE_PERCENT)
258 SAMPLEPOINT_UPPER_LIMIT))
277 ("Baudrate : %d kBaud\n",
282 ("Baudrate Error: %d\n",
286 ("Sample P Error: %d\n",
299 // find list of minimum of baudrate_error within unmarked entries
300 clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
301 baudrate_error_merk = 100;
303 for (clk = 0; clk < 5; clk++) {
304 for (brp = 0; brp < 16; brp++) {
305 for (pr = 0; pr < 8; pr++) {
306 for (ph1 = 0; ph1 < 8; ph1++) {
307 for (ph2 = 0; ph2 < 8; ph2++) {
308 if (baudrate_error[index]
331 ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
337 ("Baudrate : %d kBaud\n",
345 ("Baudrate Error: %d\n",
349 ("Sample P Error: %d\n",
362 if (baudrate_error_merk == 100) {
363 info("ERROR: Could not convert CAN init parameter\n");
364 vfree(baudrate_error);
365 vfree(samplepoint_error);
369 // setting m16c CAN parameter
370 c0con.bc0con.brp = brp_merk;
371 c0con.bc0con.pr = pr_merk;
372 c1con.bc1con.ph1 = ph1_merk;
373 c1con.bc1con.ph2 = ph2_merk;
375 #ifdef _DEBUG_OUTPUT_CAN_PARAMS
376 info("\nResulting M16C CAN params\n");
377 info("-------------------------\n");
378 info("clk : %2.2Xh\n", clk_merk);
379 info("ph1 : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
380 c1con.bc1con.ph2 + 1);
381 info("pr : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
382 c0con.bc0con.brp + 1);
383 info("sjw : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
385 info("co1 : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
386 info("Baudrate: %d.%dBaud\n",
387 baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
388 c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
389 baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
390 c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
391 info("Sample P: 0.%d\n",
392 samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
393 c1con.bc1con.ph1, c1con.bc1con.ph2));
399 out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
400 out->msg.canparams.cc_type = M16C_BASIC;
401 out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
402 out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
403 out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
404 out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
405 out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
406 out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
408 out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
410 // info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
411 tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
412 out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
413 (unsigned char) tmpAccCode;
414 out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
415 (unsigned char) (tmpAccCode >> 8);
417 // info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
418 out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
420 out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
423 // info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
424 tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
426 // info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
427 out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
428 (unsigned char) ~tmpAccMask;
429 out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
430 (unsigned char) ~(tmpAccMask >> 8);
432 // info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
433 out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
434 (unsigned char) tmpAccCode;
435 out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
436 (unsigned char) (tmpAccCode >> 8);
437 out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
438 out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
439 out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
440 (unsigned char) ~tmpAccMask;
441 out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
442 (unsigned char) ~(tmpAccMask >> 8);
443 out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
445 out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
447 vfree(baudrate_error);
448 vfree(samplepoint_error);