OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ieee1394/] [cmp.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* -*- c-basic-offset: 8 -*-
2
 *
3
 * cmp.c - Connection Management Procedures
4
 * Copyright (C) 2001 Kristian Høgsberg
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 */
20
 
21
/* TODO
22
 * ----
23
 *
24
 * - Implement IEC61883-1 output plugs and connection management.
25
 *   This should probably be part of the general subsystem, as it could
26
 *   be shared with dv1394.
27
 *
28
 * - Add IEC61883 unit directory when loading this module.  This
29
 *   requires a run-time changeable config rom.
30
 */
31
 
32
#include <linux/module.h>
33
#include <linux/list.h>
34
#include <linux/sched.h>
35
#include <linux/types.h>
36
#include <linux/wait.h>
37
 
38
#include "hosts.h"
39
#include "highlevel.h"
40
#include "ieee1394.h"
41
#include "ieee1394_core.h"
42
#include "cmp.h"
43
 
44
struct plug {
45
        union {
46
                struct cmp_pcr pcr;
47
                quadlet_t quadlet;
48
        } u;
49
        void (*update)(struct cmp_pcr *plug, void *data);
50
        void *data;
51
};
52
 
53
struct cmp_host {
54
        struct hpsb_host *host;
55
 
56
        union {
57
                struct cmp_mpr ompr;
58
                quadlet_t ompr_quadlet;
59
        } u;
60
        struct plug opcr[2];
61
 
62
        union {
63
                struct cmp_mpr impr;
64
                quadlet_t impr_quadlet;
65
        } v;
66
        struct plug ipcr[2];
67
};
68
 
69
enum {
70
        CMP_P2P_CONNECTION,
71
        CMP_BC_CONNECTION
72
};
73
 
74
#define CSR_PCR_MAP      0x900
75
#define CSR_PCR_MAP_END  0x9fc
76
 
77
static struct hpsb_highlevel cmp_highlevel;
78
 
79
struct cmp_pcr *
80
cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
81
                  void (*update)(struct cmp_pcr *pcr, void *data),
82
                  void *data)
83
{
84
        struct cmp_host *ch;
85
        struct plug *plug;
86
 
87
        ch = hpsb_get_hostinfo(&cmp_highlevel, host);
88
 
89
        if (opcr_number >= ch->u.ompr.nplugs ||
90
            ch->opcr[opcr_number].update != NULL)
91
                return NULL;
92
 
93
        plug = &ch->opcr[opcr_number];
94
        plug->u.pcr.online = 1;
95
        plug->u.pcr.bcast_count = 0;
96
        plug->u.pcr.p2p_count = 0;
97
        plug->u.pcr.overhead = 0;
98
        plug->u.pcr.payload = payload;
99
        plug->update = update;
100
        plug->data = data;
101
 
102
        return &plug->u.pcr;
103
}
104
 
105
void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr)
106
{
107
        struct cmp_host *ch;
108
        struct plug *plug;
109
 
110
        ch = hpsb_get_hostinfo(&cmp_highlevel, host);
111
        plug = (struct plug *)opcr;
112
        if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();
113
 
114
        plug->u.pcr.online = 0;
115
        plug->update = NULL;
116
}
117
 
118
static void reset_plugs(struct cmp_host *ch)
119
{
120
        int i;
121
 
122
        ch->u.ompr.non_persistent_ext = 0xff;
123
        for (i = 0; i < ch->u.ompr.nplugs; i++) {
124
                ch->opcr[i].u.pcr.bcast_count = 0;
125
                ch->opcr[i].u.pcr.p2p_count = 0;
126
                ch->opcr[i].u.pcr.overhead = 0;
127
        }
128
}
129
 
130
static void cmp_add_host(struct hpsb_host *host)
131
{
132
        struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch));
133
 
134
        if (ch == NULL) {
135
                HPSB_ERR("Failed to allocate cmp_host");
136
                return;
137
        }
138
 
139
        ch->host = host;
140
        ch->u.ompr.rate = IEEE1394_SPEED_100;
141
        ch->u.ompr.bcast_channel_base = 63;
142
        ch->u.ompr.nplugs = 2;
143
 
144
        reset_plugs(ch);
145
}
146
 
147
static void cmp_host_reset(struct hpsb_host *host)
148
{
149
        struct cmp_host *ch;
150
 
151
        ch = hpsb_get_hostinfo(&cmp_highlevel, host);
152
        if (ch == NULL) {
153
                HPSB_ERR("cmp: Tried to reset unknown host");
154
                return;
155
        }
156
 
157
        reset_plugs(ch);
158
}
159
 
160
static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
161
                    u64 addr, size_t length, u16 flags)
162
{
163
        int csraddr = addr - CSR_REGISTER_BASE;
164
        int plug;
165
        struct cmp_host *ch;
166
 
167
        if (length != 4)
168
                return RCODE_TYPE_ERROR;
169
 
170
        ch = hpsb_get_hostinfo(&cmp_highlevel, host);
171
        if (csraddr == 0x900) {
172
                *buf = cpu_to_be32(ch->u.ompr_quadlet);
173
                return RCODE_COMPLETE;
174
        }
175
        else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
176
                plug = (csraddr - 0x904) / 4;
177
                *buf = cpu_to_be32(ch->opcr[plug].u.quadlet);
178
                return RCODE_COMPLETE;
179
        }
180
        else if (csraddr < 0x980) {
181
                return RCODE_ADDRESS_ERROR;
182
        }
183
        else if (csraddr == 0x980) {
184
                *buf = cpu_to_be32(ch->v.impr_quadlet);
185
                return RCODE_COMPLETE;
186
        }
187
        else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
188
                plug = (csraddr - 0x984) / 4;
189
                *buf = cpu_to_be32(ch->ipcr[plug].u.quadlet);
190
                return RCODE_COMPLETE;
191
        }
192
        else
193
                return RCODE_ADDRESS_ERROR;
194
}
195
 
196
static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
197
                    u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags)
198
{
199
        int csraddr = addr - CSR_REGISTER_BASE;
200
        int plug;
201
        struct cmp_host *ch;
202
 
203
        ch = hpsb_get_hostinfo(&cmp_highlevel, host);
204
 
205
        if (extcode != EXTCODE_COMPARE_SWAP)
206
                return RCODE_TYPE_ERROR;
207
 
208
        if (csraddr == 0x900) {
209
                /* FIXME: Ignore writes to bits 30-31 and 0-7 */
210
                *store = cpu_to_be32(ch->u.ompr_quadlet);
211
                if (arg == cpu_to_be32(ch->u.ompr_quadlet))
212
                        ch->u.ompr_quadlet = be32_to_cpu(data);
213
 
214
                return RCODE_COMPLETE;
215
        }
216
        if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
217
                plug = (csraddr - 0x904) / 4;
218
                *store = cpu_to_be32(ch->opcr[plug].u.quadlet);
219
 
220
                if (arg == *store)
221
                        ch->opcr[plug].u.quadlet = be32_to_cpu(data);
222
 
223
                if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet &&
224
                    ch->opcr[plug].update != NULL)
225
                        ch->opcr[plug].update(&ch->opcr[plug].u.pcr,
226
                                              ch->opcr[plug].data);
227
 
228
                return RCODE_COMPLETE;
229
        }
230
        else if (csraddr < 0x980) {
231
                return RCODE_ADDRESS_ERROR;
232
        }
233
        else if (csraddr == 0x980) {
234
                /* FIXME: Ignore writes to bits 24-31 and 0-7 */
235
                *store = cpu_to_be32(ch->u.ompr_quadlet);
236
                if (arg == cpu_to_be32(ch->u.ompr_quadlet))
237
                        ch->u.ompr_quadlet = be32_to_cpu(data);
238
 
239
                return RCODE_COMPLETE;
240
        }
241
        else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
242
                plug = (csraddr - 0x984) / 4;
243
                *store = cpu_to_be32(ch->ipcr[plug].u.quadlet);
244
 
245
                if (arg == *store)
246
                        ch->ipcr[plug].u.quadlet = be32_to_cpu(data);
247
 
248
                if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet &&
249
                    ch->ipcr[plug].update != NULL)
250
                        ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr,
251
                                              ch->ipcr[plug].data);
252
 
253
                return RCODE_COMPLETE;
254
        }
255
        else
256
                return RCODE_ADDRESS_ERROR;
257
}
258
 
259
 
260
static struct hpsb_highlevel cmp_highlevel = {
261
        .name =         "cmp",
262
        .add_host =     cmp_add_host,
263
        .host_reset =   cmp_host_reset,
264
};
265
 
266
static struct hpsb_address_ops pcr_ops = {
267
        .read = pcr_read,
268
        .lock = pcr_lock,
269
};
270
 
271
/* Module interface */
272
 
273
MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
274
MODULE_DESCRIPTION("Connection Management Procedures (CMP)");
275
MODULE_SUPPORTED_DEVICE("cmp");
276
MODULE_LICENSE("GPL");
277
 
278
EXPORT_SYMBOL(cmp_register_opcr);
279
EXPORT_SYMBOL(cmp_unregister_opcr);
280
 
281
static int __init cmp_init_module (void)
282
{
283
        hpsb_register_highlevel (&cmp_highlevel);
284
 
285
        hpsb_register_addrspace(&cmp_highlevel, &pcr_ops,
286
                                CSR_REGISTER_BASE + CSR_PCR_MAP,
287
                                CSR_REGISTER_BASE + CSR_PCR_MAP_END);
288
 
289
        HPSB_INFO("Loaded CMP driver");
290
 
291
        return 0;
292
}
293
 
294
static void __exit cmp_exit_module (void)
295
{
296
        hpsb_unregister_highlevel(&cmp_highlevel);
297
 
298
        HPSB_INFO("Unloaded CMP driver");
299
}
300
 
301
module_init(cmp_init_module);
302
module_exit(cmp_exit_module);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.