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
);