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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [message/] [i2o/] [i2o_config.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
/*
2
 * I2O Configuration Interface Driver
3
 *
4
 * (C) Copyright 1999   Red Hat Software
5
 *
6
 * Written by Alan Cox, Building Number Three Ltd
7
 *
8
 * Modified 04/20/1999 by Deepak Saxena
9
 *   - Added basic ioctl() support
10
 * Modified 06/07/1999 by Deepak Saxena
11
 *   - Added software download ioctl (still testing)
12
 * Modified 09/10/1999 by Auvo Häkkinen
13
 *   - Changes to i2o_cfg_reply(), ioctl_parms()
14
 *   - Added ioct_validate()
15
 * Modified 09/30/1999 by Taneli Vähäkangas
16
 *   - Fixed ioctl_swdl()
17
 * Modified 10/04/1999 by Taneli Vähäkangas
18
 *   - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
19
 * Modified 11/18/199 by Deepak Saxena
20
 *   - Added event managmenet support
21
 *
22
 * This program is free software; you can redistribute it and/or
23
 * modify it under the terms of the GNU General Public License
24
 * as published by the Free Software Foundation; either version
25
 * 2 of the License, or (at your option) any later version.
26
 */
27
 
28
#include <linux/module.h>
29
#include <linux/kernel.h>
30
#include <linux/pci.h>
31
#include <linux/i2o.h>
32
#include <linux/errno.h>
33
#include <linux/init.h>
34
#include <linux/slab.h>
35
#include <linux/miscdevice.h>
36
#include <linux/mm.h>
37
#include <linux/spinlock.h>
38
#include <linux/smp_lock.h>
39
 
40
#include <asm/uaccess.h>
41
#include <asm/io.h>
42
 
43
static int i2o_cfg_context = -1;
44
static void *page_buf;
45
static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
46
struct wait_queue *i2o_wait_queue;
47
 
48
#define MODINC(x,y) ((x) = ((x) + 1) % (y))
49
 
50
struct i2o_cfg_info
51
{
52
        struct file* fp;
53
        struct fasync_struct *fasync;
54
        struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
55
        u16             q_in;           // Queue head index
56
        u16             q_out;          // Queue tail index
57
        u16             q_len;          // Queue length
58
        u16             q_lost;         // Number of lost events
59
        u32             q_id;           // Event queue ID...used as tx_context
60
        struct  i2o_cfg_info *next;
61
};
62
static struct i2o_cfg_info *open_files = NULL;
63
static int i2o_cfg_info_id = 0;
64
 
65
static int ioctl_getiops(unsigned long);
66
static int ioctl_gethrt(unsigned long);
67
static int ioctl_getlct(unsigned long);
68
static int ioctl_parms(unsigned long, unsigned int);
69
static int ioctl_html(unsigned long);
70
static int ioctl_swdl(unsigned long);
71
static int ioctl_swul(unsigned long);
72
static int ioctl_swdel(unsigned long);
73
static int ioctl_validate(unsigned long);
74
static int ioctl_evt_reg(unsigned long, struct file *);
75
static int ioctl_evt_get(unsigned long, struct file *);
76
static int cfg_fasync(int, struct file*, int);
77
 
78
/*
79
 *      This is the callback for any message we have posted. The message itself
80
 *      will be returned to the message pool when we return from the IRQ
81
 *
82
 *      This runs in irq context so be short and sweet.
83
 */
84
static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
85
{
86
        u32 *msg = (u32 *)m;
87
 
88
        if (msg[0] & MSG_FAIL) {
89
                u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);
90
 
91
                printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
92
 
93
                /* Release the preserved msg frame by resubmitting it as a NOP */
94
 
95
                preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
96
                preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0;
97
                preserved_msg[2] = 0;
98
                i2o_post_message(c, msg[7]);
99
        }
100
 
101
        if (msg[4] >> 24)  // ReqStatus != SUCCESS
102
                i2o_report_status(KERN_INFO,"i2o_config", msg);
103
 
104
        if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
105
        {
106
                struct i2o_cfg_info *inf;
107
 
108
                for(inf = open_files; inf; inf = inf->next)
109
                        if(inf->q_id == msg[3])
110
                                break;
111
 
112
                //
113
                // If this is the case, it means that we're getting
114
                // events for a file descriptor that's been close()'d
115
                // w/o the user unregistering for events first.
116
                // The code currently assumes that the user will 
117
                // take care of unregistering for events before closing
118
                // a file.
119
                // 
120
                // TODO: 
121
                // Should we track event registartion and deregister
122
                // for events when a file is close()'d so this doesn't
123
                // happen? That would get rid of the search through
124
                // the linked list since file->private_data could point
125
                // directly to the i2o_config_info data structure...but
126
                // it would mean having all sorts of tables to track
127
                // what each file is registered for...I think the
128
                // current method is simpler. - DS
129
                //                      
130
                if(!inf)
131
                        return;
132
 
133
                inf->event_q[inf->q_in].id.iop = c->unit;
134
                inf->event_q[inf->q_in].id.tid = m->target_tid;
135
                inf->event_q[inf->q_in].id.evt_mask = msg[4];
136
 
137
                //
138
                // Data size = msg size - reply header
139
                //
140
                inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
141
                if(inf->event_q[inf->q_in].data_size)
142
                        memcpy(inf->event_q[inf->q_in].evt_data,
143
                                (unsigned char *)(msg + 5),
144
                                inf->event_q[inf->q_in].data_size);
145
 
146
                spin_lock(&i2o_config_lock);
147
                MODINC(inf->q_in, I2O_EVT_Q_LEN);
148
                if(inf->q_len == I2O_EVT_Q_LEN)
149
                {
150
                        MODINC(inf->q_out, I2O_EVT_Q_LEN);
151
                        inf->q_lost++;
152
                }
153
                else
154
                {
155
                        // Keep I2OEVTGET on another CPU from touching this
156
                        inf->q_len++;
157
                }
158
                spin_unlock(&i2o_config_lock);
159
 
160
 
161
//              printk(KERN_INFO "File %p w/id %d has %d events\n",
162
//                      inf->fp, inf->q_id, inf->q_len);        
163
 
164
                kill_fasync(&inf->fasync, SIGIO, POLL_IN);
165
        }
166
 
167
        return;
168
}
169
 
170
/*
171
 *      Each of these describes an i2o message handler. They are
172
 *      multiplexed by the i2o_core code
173
 */
174
 
175
struct i2o_handler cfg_handler=
176
{
177
        i2o_cfg_reply,
178
        NULL,
179
        NULL,
180
        NULL,
181
        "Configuration",
182
        0,
183
        0xffffffff      // All classes
184
};
185
 
186
static ssize_t cfg_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
187
{
188
        printk(KERN_INFO "i2o_config write not yet supported\n");
189
 
190
        return 0;
191
}
192
 
193
 
194
static ssize_t cfg_read(struct file *file, char *buf, size_t count, loff_t *ptr)
195
{
196
        return 0;
197
}
198
 
199
/*
200
 * IOCTL Handler
201
 */
202
static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
203
        unsigned long arg)
204
{
205
        int ret;
206
 
207
        switch(cmd)
208
        {
209
                case I2OGETIOPS:
210
                        ret = ioctl_getiops(arg);
211
                        break;
212
 
213
                case I2OHRTGET:
214
                        ret = ioctl_gethrt(arg);
215
                        break;
216
 
217
                case I2OLCTGET:
218
                        ret = ioctl_getlct(arg);
219
                        break;
220
 
221
                case I2OPARMSET:
222
                        ret = ioctl_parms(arg, I2OPARMSET);
223
                        break;
224
 
225
                case I2OPARMGET:
226
                        ret = ioctl_parms(arg, I2OPARMGET);
227
                        break;
228
 
229
                case I2OSWDL:
230
                        ret = ioctl_swdl(arg);
231
                        break;
232
 
233
                case I2OSWUL:
234
                        ret = ioctl_swul(arg);
235
                        break;
236
 
237
                case I2OSWDEL:
238
                        ret = ioctl_swdel(arg);
239
                        break;
240
 
241
                case I2OVALIDATE:
242
                        ret = ioctl_validate(arg);
243
                        break;
244
 
245
                case I2OHTML:
246
                        ret = ioctl_html(arg);
247
                        break;
248
 
249
                case I2OEVTREG:
250
                        ret = ioctl_evt_reg(arg, fp);
251
                        break;
252
 
253
                case I2OEVTGET:
254
                        ret = ioctl_evt_get(arg, fp);
255
                        break;
256
 
257
                default:
258
                        ret = -EINVAL;
259
        }
260
 
261
        return ret;
262
}
263
 
264
int ioctl_getiops(unsigned long arg)
265
{
266
        u8 *user_iop_table = (u8*)arg;
267
        struct i2o_controller *c = NULL;
268
        int i;
269
        u8 foo[MAX_I2O_CONTROLLERS];
270
 
271
        if(!access_ok(VERIFY_WRITE, user_iop_table,  MAX_I2O_CONTROLLERS))
272
                return -EFAULT;
273
 
274
        for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
275
        {
276
                c = i2o_find_controller(i);
277
                if(c)
278
                {
279
                        foo[i] = 1;
280
                        i2o_unlock_controller(c);
281
                }
282
                else
283
                {
284
                        foo[i] = 0;
285
                }
286
        }
287
 
288
        __copy_to_user(user_iop_table, foo, MAX_I2O_CONTROLLERS);
289
        return 0;
290
}
291
 
292
int ioctl_gethrt(unsigned long arg)
293
{
294
        struct i2o_controller *c;
295
        struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
296
        struct i2o_cmd_hrtlct kcmd;
297
        i2o_hrt *hrt;
298
        int len;
299
        u32 reslen;
300
        int ret = 0;
301
 
302
        if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
303
                return -EFAULT;
304
 
305
        if(get_user(reslen, kcmd.reslen) < 0)
306
                return -EFAULT;
307
 
308
        if(kcmd.resbuf == NULL)
309
                return -EFAULT;
310
 
311
        c = i2o_find_controller(kcmd.iop);
312
        if(!c)
313
                return -ENXIO;
314
 
315
        hrt = (i2o_hrt *)c->hrt;
316
 
317
        i2o_unlock_controller(c);
318
 
319
        len = 8 + ((hrt->entry_len * hrt->num_entries) << 2);
320
 
321
        /* We did a get user...so assuming mem is ok...is this bad? */
322
        put_user(len, kcmd.reslen);
323
        if(len > reslen)
324
                ret = -ENOBUFS;
325
        if(copy_to_user(kcmd.resbuf, (void*)hrt, len))
326
                ret = -EFAULT;
327
 
328
        return ret;
329
}
330
 
331
int ioctl_getlct(unsigned long arg)
332
{
333
        struct i2o_controller *c;
334
        struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
335
        struct i2o_cmd_hrtlct kcmd;
336
        i2o_lct *lct;
337
        int len;
338
        int ret = 0;
339
        u32 reslen;
340
 
341
        if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
342
                return -EFAULT;
343
 
344
        if(get_user(reslen, kcmd.reslen) < 0)
345
                return -EFAULT;
346
 
347
        if(kcmd.resbuf == NULL)
348
                return -EFAULT;
349
 
350
        c = i2o_find_controller(kcmd.iop);
351
        if(!c)
352
                return -ENXIO;
353
 
354
        lct = (i2o_lct *)c->lct;
355
        i2o_unlock_controller(c);
356
 
357
        len = (unsigned int)lct->table_size << 2;
358
        put_user(len, kcmd.reslen);
359
        if(len > reslen)
360
                ret = -ENOBUFS;
361
        else if(copy_to_user(kcmd.resbuf, (void*)lct, len))
362
                ret = -EFAULT;
363
 
364
        return ret;
365
}
366
 
367
static int ioctl_parms(unsigned long arg, unsigned int type)
368
{
369
        int ret = 0;
370
        struct i2o_controller *c;
371
        struct i2o_cmd_psetget *cmd = (struct i2o_cmd_psetget*)arg;
372
        struct i2o_cmd_psetget kcmd;
373
        u32 reslen;
374
        u8 *ops;
375
        u8 *res;
376
        int len;
377
 
378
        u32 i2o_cmd = (type == I2OPARMGET ?
379
                                I2O_CMD_UTIL_PARAMS_GET :
380
                                I2O_CMD_UTIL_PARAMS_SET);
381
 
382
        if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
383
                return -EFAULT;
384
 
385
        if(get_user(reslen, kcmd.reslen))
386
                return -EFAULT;
387
 
388
        c = i2o_find_controller(kcmd.iop);
389
        if(!c)
390
                return -ENXIO;
391
 
392
        ops = (u8*)kmalloc(kcmd.oplen, GFP_KERNEL);
393
        if(!ops)
394
        {
395
                i2o_unlock_controller(c);
396
                return -ENOMEM;
397
        }
398
 
399
        if(copy_from_user(ops, kcmd.opbuf, kcmd.oplen))
400
        {
401
                i2o_unlock_controller(c);
402
                kfree(ops);
403
                return -EFAULT;
404
        }
405
 
406
        /*
407
         * It's possible to have a _very_ large table
408
         * and that the user asks for all of it at once...
409
         */
410
        res = (u8*)kmalloc(65536, GFP_KERNEL);
411
        if(!res)
412
        {
413
                i2o_unlock_controller(c);
414
                kfree(ops);
415
                return -ENOMEM;
416
        }
417
 
418
        len = i2o_issue_params(i2o_cmd, c, kcmd.tid,
419
                                ops, kcmd.oplen, res, 65536);
420
        i2o_unlock_controller(c);
421
        kfree(ops);
422
 
423
        if (len < 0) {
424
                kfree(res);
425
                return -EAGAIN;
426
        }
427
 
428
        put_user(len, kcmd.reslen);
429
        if(len > reslen)
430
                ret = -ENOBUFS;
431
        else if(copy_to_user(kcmd.resbuf, res, len))
432
                ret = -EFAULT;
433
 
434
        kfree(res);
435
 
436
        return ret;
437
}
438
 
439
int ioctl_html(unsigned long arg)
440
{
441
        struct i2o_html *cmd = (struct i2o_html*)arg;
442
        struct i2o_html kcmd;
443
        struct i2o_controller *c;
444
        u8 *res = NULL;
445
        void *query = NULL;
446
        int ret = 0;
447
        int token;
448
        u32 len;
449
        u32 reslen;
450
        u32 msg[MSG_FRAME_SIZE];
451
 
452
        if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_html)))
453
        {
454
                printk(KERN_INFO "i2o_config: can't copy html cmd\n");
455
                return -EFAULT;
456
        }
457
 
458
        if(get_user(reslen, kcmd.reslen) < 0)
459
        {
460
                printk(KERN_INFO "i2o_config: can't copy html reslen\n");
461
                return -EFAULT;
462
        }
463
 
464
        if(!kcmd.resbuf)
465
        {
466
                printk(KERN_INFO "i2o_config: NULL html buffer\n");
467
                return -EFAULT;
468
        }
469
 
470
        c = i2o_find_controller(kcmd.iop);
471
        if(!c)
472
                return -ENXIO;
473
 
474
        if(kcmd.qlen) /* Check for post data */
475
        {
476
                query = kmalloc(kcmd.qlen, GFP_KERNEL);
477
                if(!query)
478
                {
479
                        i2o_unlock_controller(c);
480
                        return -ENOMEM;
481
                }
482
                if(copy_from_user(query, kcmd.qbuf, kcmd.qlen))
483
                {
484
                        i2o_unlock_controller(c);
485
                        printk(KERN_INFO "i2o_config: could not get query\n");
486
                        kfree(query);
487
                        return -EFAULT;
488
                }
489
        }
490
 
491
        res = kmalloc(65536, GFP_KERNEL);
492
        if(!res)
493
        {
494
                i2o_unlock_controller(c);
495
                kfree(query);
496
                return -ENOMEM;
497
        }
498
 
499
        msg[1] = (I2O_CMD_UTIL_CONFIG_DIALOG << 24)|HOST_TID<<12|kcmd.tid;
500
        msg[2] = i2o_cfg_context;
501
        msg[3] = 0;
502
        msg[4] = kcmd.page;
503
        msg[5] = 0xD0000000|65536;
504
        msg[6] = virt_to_bus(res);
505
        if(!kcmd.qlen) /* Check for post data */
506
                msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5;
507
        else
508
        {
509
                msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
510
                msg[5] = 0x50000000|65536;
511
                msg[7] = 0xD4000000|(kcmd.qlen);
512
                msg[8] = virt_to_bus(query);
513
        }
514
        /*
515
        Wait for a considerable time till the Controller
516
        does its job before timing out. The controller might
517
        take more time to process this request if there are
518
        many devices connected to it.
519
        */
520
        token = i2o_post_wait_mem(c, msg, 9*4, 400, query, res);
521
        if(token < 0)
522
        {
523
                printk(KERN_DEBUG "token = %#10x\n", token);
524
                i2o_unlock_controller(c);
525
 
526
                if(token != -ETIMEDOUT)
527
                {
528
                        kfree(res);
529
                        if(kcmd.qlen) kfree(query);
530
                }
531
 
532
                return token;
533
        }
534
        i2o_unlock_controller(c);
535
 
536
        len = strnlen(res, 65536);
537
        put_user(len, kcmd.reslen);
538
        if(len > reslen)
539
                ret = -ENOMEM;
540
        if(copy_to_user(kcmd.resbuf, res, len))
541
                ret = -EFAULT;
542
 
543
        kfree(res);
544
        if(kcmd.qlen)
545
                kfree(query);
546
 
547
        return ret;
548
}
549
 
550
int ioctl_swdl(unsigned long arg)
551
{
552
        struct i2o_sw_xfer kxfer;
553
        struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg;
554
        unsigned char maxfrag = 0, curfrag = 1;
555
        unsigned char *buffer;
556
        u32 msg[9];
557
        unsigned int status = 0, swlen = 0, fragsize = 8192;
558
        struct i2o_controller *c;
559
 
560
        if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
561
                return -EFAULT;
562
 
563
        if(get_user(swlen, kxfer.swlen) < 0)
564
                return -EFAULT;
565
 
566
        if(get_user(maxfrag, kxfer.maxfrag) < 0)
567
                return -EFAULT;
568
 
569
        if(get_user(curfrag, kxfer.curfrag) < 0)
570
                return -EFAULT;
571
 
572
        if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
573
 
574
        if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
575
                return -EFAULT;
576
 
577
        c = i2o_find_controller(kxfer.iop);
578
        if(!c)
579
                return -ENXIO;
580
 
581
        buffer=kmalloc(fragsize, GFP_KERNEL);
582
        if (buffer==NULL)
583
        {
584
                i2o_unlock_controller(c);
585
                return -ENOMEM;
586
        }
587
        __copy_from_user(buffer, kxfer.buf, fragsize);
588
 
589
        msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
590
        msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
591
        msg[2]= (u32)cfg_handler.context;
592
        msg[3]= 0;
593
        msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) |
594
                (((u32)maxfrag)<<8) | (((u32)curfrag));
595
        msg[5]= swlen;
596
        msg[6]= kxfer.sw_id;
597
        msg[7]= (0xD0000000 | fragsize);
598
        msg[8]= virt_to_bus(buffer);
599
 
600
//      printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
601
        status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL);
602
 
603
        i2o_unlock_controller(c);
604
        if(status != -ETIMEDOUT)
605
                kfree(buffer);
606
 
607
        if (status != I2O_POST_WAIT_OK)
608
        {
609
                // it fails if you try and send frags out of order
610
                // and for some yet unknown reasons too
611
                printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
612
                return status;
613
        }
614
 
615
        return 0;
616
}
617
 
618
int ioctl_swul(unsigned long arg)
619
{
620
        struct i2o_sw_xfer kxfer;
621
        struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg;
622
        unsigned char maxfrag = 0, curfrag = 1;
623
        unsigned char *buffer;
624
        u32 msg[9];
625
        unsigned int status = 0, swlen = 0, fragsize = 8192;
626
        struct i2o_controller *c;
627
 
628
        if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
629
                return -EFAULT;
630
 
631
        if(get_user(swlen, kxfer.swlen) < 0)
632
                return -EFAULT;
633
 
634
        if(get_user(maxfrag, kxfer.maxfrag) < 0)
635
                return -EFAULT;
636
 
637
        if(get_user(curfrag, kxfer.curfrag) < 0)
638
                return -EFAULT;
639
 
640
        if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
641
 
642
        if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
643
                return -EFAULT;
644
 
645
        c = i2o_find_controller(kxfer.iop);
646
        if(!c)
647
                return -ENXIO;
648
 
649
        buffer=kmalloc(fragsize, GFP_KERNEL);
650
        if (buffer==NULL)
651
        {
652
                i2o_unlock_controller(c);
653
                return -ENOMEM;
654
        }
655
 
656
        msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
657
        msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
658
        msg[2]= (u32)cfg_handler.context;
659
        msg[3]= 0;
660
        msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag;
661
        msg[5]= swlen;
662
        msg[6]= kxfer.sw_id;
663
        msg[7]= (0xD0000000 | fragsize);
664
        msg[8]= virt_to_bus(buffer);
665
 
666
//      printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
667
        status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL);
668
        i2o_unlock_controller(c);
669
 
670
        if (status != I2O_POST_WAIT_OK)
671
        {
672
                if(status != -ETIMEDOUT)
673
                        kfree(buffer);
674
                printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
675
                return status;
676
        }
677
 
678
        __copy_to_user(kxfer.buf, buffer, fragsize);
679
        kfree(buffer);
680
 
681
        return 0;
682
}
683
 
684
int ioctl_swdel(unsigned long arg)
685
{
686
        struct i2o_controller *c;
687
        struct i2o_sw_xfer kxfer, *pxfer = (struct i2o_sw_xfer *)arg;
688
        u32 msg[7];
689
        unsigned int swlen;
690
        int token;
691
 
692
        if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
693
                return -EFAULT;
694
 
695
        if (get_user(swlen, kxfer.swlen) < 0)
696
                return -EFAULT;
697
 
698
        c = i2o_find_controller(kxfer.iop);
699
        if (!c)
700
                return -ENXIO;
701
 
702
        msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
703
        msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID;
704
        msg[2] = (u32)i2o_cfg_context;
705
        msg[3] = 0;
706
        msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16;
707
        msg[5] = swlen;
708
        msg[6] = kxfer.sw_id;
709
 
710
        token = i2o_post_wait(c, msg, sizeof(msg), 10);
711
        i2o_unlock_controller(c);
712
 
713
        if (token != I2O_POST_WAIT_OK)
714
        {
715
                printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token);
716
                return -ETIMEDOUT;
717
        }
718
 
719
        return 0;
720
}
721
 
722
int ioctl_validate(unsigned long arg)
723
{
724
        int token;
725
        int iop = (int)arg;
726
        u32 msg[4];
727
        struct i2o_controller *c;
728
 
729
        c=i2o_find_controller(iop);
730
        if (!c)
731
                return -ENXIO;
732
 
733
        msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
734
        msg[1] = I2O_CMD_CONFIG_VALIDATE<<24 | HOST_TID<<12 | iop;
735
        msg[2] = (u32)i2o_cfg_context;
736
        msg[3] = 0;
737
 
738
        token = i2o_post_wait(c, msg, sizeof(msg), 10);
739
        i2o_unlock_controller(c);
740
 
741
        if (token != I2O_POST_WAIT_OK)
742
        {
743
                printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n",
744
                        token);
745
                return -ETIMEDOUT;
746
        }
747
 
748
        return 0;
749
}
750
 
751
static int ioctl_evt_reg(unsigned long arg, struct file *fp)
752
{
753
        u32 msg[5];
754
        struct i2o_evt_id *pdesc = (struct i2o_evt_id *)arg;
755
        struct i2o_evt_id kdesc;
756
        struct i2o_controller *iop;
757
        struct i2o_device *d;
758
 
759
        if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
760
                return -EFAULT;
761
 
762
        /* IOP exists? */
763
        iop = i2o_find_controller(kdesc.iop);
764
        if(!iop)
765
                return -ENXIO;
766
        i2o_unlock_controller(iop);
767
 
768
        /* Device exists? */
769
        for(d = iop->devices; d; d = d->next)
770
                if(d->lct_data.tid == kdesc.tid)
771
                        break;
772
 
773
        if(!d)
774
                return -ENODEV;
775
 
776
        msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
777
        msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid;
778
        msg[2] = (u32)i2o_cfg_context;
779
        msg[3] = (u32)fp->private_data;
780
        msg[4] = kdesc.evt_mask;
781
 
782
        i2o_post_this(iop, msg, 20);
783
 
784
        return 0;
785
}
786
 
787
static int ioctl_evt_get(unsigned long arg, struct file *fp)
788
{
789
        u32 id = (u32)fp->private_data;
790
        struct i2o_cfg_info *p = NULL;
791
        struct i2o_evt_get *uget = (struct i2o_evt_get*)arg;
792
        struct i2o_evt_get kget;
793
        unsigned long flags;
794
 
795
        for(p = open_files; p; p = p->next)
796
                if(p->q_id == id)
797
                        break;
798
 
799
        if(!p->q_len)
800
        {
801
                return -ENOENT;
802
                return 0;
803
        }
804
 
805
        memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
806
        MODINC(p->q_out, I2O_EVT_Q_LEN);
807
        spin_lock_irqsave(&i2o_config_lock, flags);
808
        p->q_len--;
809
        kget.pending = p->q_len;
810
        kget.lost = p->q_lost;
811
        spin_unlock_irqrestore(&i2o_config_lock, flags);
812
 
813
        if(copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
814
                return -EFAULT;
815
        return 0;
816
}
817
 
818
static int cfg_open(struct inode *inode, struct file *file)
819
{
820
        struct i2o_cfg_info *tmp =
821
                (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL);
822
        unsigned long flags;
823
 
824
        if(!tmp)
825
                return -ENOMEM;
826
 
827
        file->private_data = (void*)(i2o_cfg_info_id++);
828
        tmp->fp = file;
829
        tmp->fasync = NULL;
830
        tmp->q_id = (u32)file->private_data;
831
        tmp->q_len = 0;
832
        tmp->q_in = 0;
833
        tmp->q_out = 0;
834
        tmp->q_lost = 0;
835
        tmp->next = open_files;
836
 
837
        spin_lock_irqsave(&i2o_config_lock, flags);
838
        open_files = tmp;
839
        spin_unlock_irqrestore(&i2o_config_lock, flags);
840
 
841
        return 0;
842
}
843
 
844
static int cfg_release(struct inode *inode, struct file *file)
845
{
846
        u32 id = (u32)file->private_data;
847
        struct i2o_cfg_info *p1, *p2;
848
        unsigned long flags;
849
 
850
        lock_kernel();
851
        p1 = p2 = NULL;
852
 
853
        spin_lock_irqsave(&i2o_config_lock, flags);
854
        for(p1 = open_files; p1; )
855
        {
856
                if(p1->q_id == id)
857
                {
858
 
859
                        if(p1->fasync)
860
                                cfg_fasync(-1, file, 0);
861
                        if(p2)
862
                                p2->next = p1->next;
863
                        else
864
                                open_files = p1->next;
865
 
866
                        kfree(p1);
867
                        break;
868
                }
869
                p2 = p1;
870
                p1 = p1->next;
871
        }
872
        spin_unlock_irqrestore(&i2o_config_lock, flags);
873
        unlock_kernel();
874
 
875
        return 0;
876
}
877
 
878
static int cfg_fasync(int fd, struct file *fp, int on)
879
{
880
        u32 id = (u32)fp->private_data;
881
        struct i2o_cfg_info *p;
882
 
883
        for(p = open_files; p; p = p->next)
884
                if(p->q_id == id)
885
                        break;
886
 
887
        if(!p)
888
                return -EBADF;
889
 
890
        return fasync_helper(fd, fp, on, &p->fasync);
891
}
892
 
893
static struct file_operations config_fops =
894
{
895
        owner:          THIS_MODULE,
896
        llseek:         no_llseek,
897
        read:           cfg_read,
898
        write:          cfg_write,
899
        ioctl:          cfg_ioctl,
900
        open:           cfg_open,
901
        release:        cfg_release,
902
        fasync:         cfg_fasync,
903
};
904
 
905
static struct miscdevice i2o_miscdev = {
906
        I2O_MINOR,
907
        "i2octl",
908
        &config_fops
909
};
910
 
911
static int __init i2o_config_init(void)
912
{
913
        printk(KERN_INFO "I2O configuration manager v 0.04.\n");
914
        printk(KERN_INFO "  (C) Copyright 1999 Red Hat Software\n");
915
 
916
        if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
917
        {
918
                printk(KERN_ERR "i2o_config: no memory for page buffer.\n");
919
                return -ENOBUFS;
920
        }
921
        if(misc_register(&i2o_miscdev) < 0)
922
        {
923
                printk(KERN_ERR "i2o_config: can't register device.\n");
924
                kfree(page_buf);
925
                return -EBUSY;
926
        }
927
        /*
928
         *      Install our handler
929
         */
930
        if(i2o_install_handler(&cfg_handler)<0)
931
        {
932
                kfree(page_buf);
933
                printk(KERN_ERR "i2o_config: handler register failed.\n");
934
                misc_deregister(&i2o_miscdev);
935
                return -EBUSY;
936
        }
937
        /*
938
         *      The low 16bits of the transaction context must match this
939
         *      for everything we post. Otherwise someone else gets our mail
940
         */
941
        i2o_cfg_context = cfg_handler.context;
942
        return 0;
943
}
944
 
945
static void i2o_config_exit(void)
946
{
947
        misc_deregister(&i2o_miscdev);
948
 
949
        if(page_buf)
950
                kfree(page_buf);
951
        if(i2o_cfg_context != -1)
952
                i2o_remove_handler(&cfg_handler);
953
}
954
 
955
EXPORT_NO_SYMBOLS;
956
MODULE_AUTHOR("Red Hat Software");
957
MODULE_DESCRIPTION("I2O Configuration");
958
MODULE_LICENSE("GPL");
959
 
960
module_init(i2o_config_init);
961
module_exit(i2o_config_exit);

powered by: WebSVN 2.1.0

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