]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/finish.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / finish.c
1 /**************************************************************************/
2 /* File: finish.c - finalization of the driver operations                 */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
7 /* Funded by OCERA and FRESCOR IST projects                               */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
9 /*                                                                        */
10 /* LinCAN is free software; you can redistribute it and/or modify it      */
11 /* under terms of the GNU General Public License as published by the      */
12 /* Free Software Foundation; either version 2, or (at your option) any    */
13 /* later version.  LinCAN is distributed in the hope that it will be      */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
16 /* General Public License for more details. You should have received a    */
17 /* copy of the GNU General Public License along with LinCAN; see file     */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
19 /* Cambridge, MA 02139, USA.                                              */
20 /*                                                                        */
21 /* To allow use of LinCAN in the compact embedded systems firmware        */
22 /* and RT-executives (RTEMS for example), main authors agree with next    */
23 /* special exception:                                                     */
24 /*                                                                        */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce    */
27 /* an application image/executable, does not by itself cause the          */
28 /* resulting application image/executable to be covered by                */
29 /* the GNU General Public License.                                        */
30 /* This exception does not however invalidate any other reasons           */
31 /* why the executable file might be covered by the GNU Public License.    */
32 /* Publication of enhanced or derived LinCAN files is required although.  */
33 /**************************************************************************/
34
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/devcommon.h"
39 #include "../include/finish.h"
40 #include "../include/setup.h"
41
42
43 /**
44  * msgobj_done - destroys one CAN message object
45  * @obj: pointer to CAN message object structure
46  */
47 void msgobj_done(struct msgobj_t *obj)
48 {
49         int delayed=0;
50         if(obj->qends) {
51                 delayed=canqueue_ends_done_chip(obj->qends);
52                 if(delayed < 0)
53                         CANMSG("msgobj_done: problem with chip queue ends\n");
54         }
55
56         if((obj->hostchip) && (obj->object>0)) {
57                 if(obj->hostchip->msgobj[obj->object-1] == obj)
58                         obj->hostchip->msgobj[obj->object-1]=NULL;
59                 else
60                         CANMSG("msgobj_done: not registered in the canchip_t\n");
61                 obj->hostchip=NULL;
62         }
63
64         if((obj->minor>=0)) {
65                 if(objects_p[obj->minor] == obj)
66                         objects_p[obj->minor] = NULL;
67                 else
68                         CANMSG("msgobj_done: not registered as minor\n");
69         }
70
71         del_timer_sync(&obj->tx_timeout);
72
73         if(obj->qends) {
74                 /*delayed free could be required there in the future,
75                   actual use patter cannot generate such situation*/
76                 if(!delayed) {
77                         can_checked_free(obj->qends);
78                 }
79         }
80         obj->qends=NULL;
81 }
82
83
84 /**
85  * canchip_done - destroys one CAN chip representation
86  * @chip: pointer to CAN chip structure
87  */
88 void canchip_done(struct canchip_t *chip)
89 {
90
91         int i;
92         struct msgobj_t *obj;
93
94         if(chip->flags & CHIP_ATTACHED){
95                 chip->chipspecops->release_chip(chip);
96                 chip->flags &= ~CHIP_ATTACHED;
97         }
98
99         if((chip->hostdevice) && (chip->chip_idx>=0)) {
100                 if(chip->hostdevice->chip[chip->chip_idx] == chip)
101                         chip->hostdevice->chip[chip->chip_idx] = NULL;
102                 else
103                         CANMSG("canchip_done: not registered in hostdevice\n");
104         }
105
106         can_chip_free_irq(chip);
107
108         can_synchronize_irq(chip->chip_irq);
109
110         for(i=0; i<chip->max_objects; i++){
111                 if((obj=chip->msgobj[i])==NULL)
112                         continue;
113                 msgobj_done(obj);
114                 can_checked_free(obj);
115         }
116
117         can_checked_free(chip->chipspecops);
118         chip->chipspecops=NULL;
119
120 }
121
122 /**
123  * candevice_done - destroys representation of one CAN device/board
124  * @candev: pointer to CAN device/board structure
125  */
126 void candevice_done(struct candevice_t *candev)
127 {
128         int i;
129         struct canchip_t *chip;
130
131         for(i=0; i<candev->nr_all_chips; i++){
132                 if((chip=candev->chip[i])==NULL)
133                         continue;
134                 canchip_done(chip);
135                 can_checked_free(chip);
136
137         }
138         if(candev->flags & CANDEV_IO_RESERVED) {
139                 candev->hwspecops->release_io(candev);
140                 candev->flags &= ~CANDEV_IO_RESERVED;
141         }
142         if(candev->hwspecops->done_hw_data != NULL)
143                 candev->hwspecops->done_hw_data(candev);
144
145         can_checked_free(candev->hwspecops);
146         candev->hwspecops=NULL;
147 }
148
149 /**
150  * candevice_done - destroys representation of all CAN devices/boards
151  * @canhw: pointer to the root of all CAN hardware representation
152  */
153 void canhardware_done(struct canhardware_t *canhw)
154 {
155         int i;
156         struct candevice_t *candev;
157
158         for(i=0; i<canhw->nr_boards; i++){
159                 if((candev=canhw->candevice[i])==NULL)
160                         continue;
161                 candevice_done(candev);
162                 can_checked_free(candev);
163         }
164
165 }