FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/b004.c
1 /*
2 * FreeBSD device driver for B004-compatible Transputer boards.
3 *
4 * based on Linux version Copyright (C) 1993 by Christoph Niemann
5 *
6 * Rewritten for FreeBSD by
7 * Luigi Rizzo (luigi@iet.unipi.it) and
8 * Lorenzo Vicisano (l.vicisano@iet.unipi.it)
9 * Dipartimento di Ingegneria dell'Informazione
10 * Universita` di Pisa
11 * via Diotisalvi 2, 56126 Pisa, ITALY
12 * 14 september 1994
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Christoph Niemann,
25 * Luigi Rizzo and Lorenzo Vicisano - Dipartimento di Ingegneria
26 * dell'Informazione
27 * 4. The names of these contributors may not be used to endorse or promote
28 * products derived from this software without specific prior written
29 * permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * NOTE NOTE NOTE
43 * The assembler version is still under development.
44 */
45
46 /* #define USE_ASM */
47
48 #include "bqu.h"
49 #if NBQU > 0
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/proc.h>
54 #include <sys/uio.h>
55 #include <sys/conf.h>
56 #include <sys/kernel.h>
57 #ifdef DEVFS
58 #include <sys/devfsext.h>
59 #endif /*DEVFS*/
60
61 #include <machine/clock.h>
62
63 #include <i386/isa/b004.h>
64 #include <i386/isa/isa_device.h>
65
66 #define IOCTL_OUT(arg, ret) *(int*)arg = ret
67
68 #define B004PRI (PZERO+8)
69
70 #define B004_CHANCE 8
71
72 /*
73 * Define these symbols if you want to debug the code.
74 */
75 #undef B004_DEBUG
76 #undef B004_DEBUG_2
77
78 #ifdef B004_DEBUG
79 static u_char d_inb(u_int port);
80 static void d_outb(u_int port, u_char data);
81
82 #define out(port,data) d_outb(port, data)
83 #define in(a) d_inb(((u_int)a))
84 #else
85 #define out(port, data) outb(port,data)
86 #define in(port) inb(((u_int)port))
87 #endif B004_DEBUG
88
89 #ifdef B004_DEBUG
90 #define DEB(x) x
91 #define NO_DEB(x) /* */
92 #else
93 #define DEB(x) /* */
94 #define NO_DEB(x) x
95 #endif
96
97 #ifdef B004_DEBUG_2
98 #define DEB2(x) x
99 #else
100 #define DEB2(x)
101 #endif
102
103 static int bquprobe(struct isa_device *idp);
104 static int bquattach(struct isa_device *idp);
105
106
107 struct isa_driver bqudriver = {
108 bquprobe, bquattach, "bqu"
109 };
110
111 static d_open_t bquopen;
112 static d_close_t bquclose;
113 static d_read_t bquread;
114 static d_write_t bquwrite;
115 static d_ioctl_t bquioctl;
116 static d_select_t bquselect;
117
118 #define CDEV_MAJOR 8
119 static struct cdevsw bqu_cdevsw =
120 { bquopen, bquclose, bquread, bquwrite, /*8*/
121 bquioctl, nostop, nullreset, nodevtotty,/* tputer */
122 bquselect, nommap, NULL, "bqu", NULL, -1 };
123
124 static int b004_sleep; /* wait address */
125
126 static struct b004_struct b004_table[NBQU];
127
128 static int first_time=1;
129
130 /*
131 * At these addresses the driver will search for B004-compatible boards
132 */
133 static int
134 b004_base_addresses[B004_CHANCE] = {
135 /* 0x150, 0x170, 0x190, 0x200, 0x300, 0x320, 0x340, 0x360 */
136 0x150, 0x190, 0, 0, 0, 0, 0, 0
137 };
138
139 #ifdef B004_DEBUG
140 static void
141 d_outb(u_int port, u_char data)
142 {
143
144 printf("OUT 0x%x TO 0x%x\n",data,port);
145 outb(port,data);
146 }
147
148 static u_char
149 d_inb(u_int port)
150 {
151 u_char ap;
152 ap=inb(port);
153 printf("INPUT 0x%x FROM 0x%x\n",ap,port);
154 return(ap);
155 }
156 #endif
157
158 static int
159 detected(int base)
160 {
161 int i;
162 for(i=0;i<NBQU;i++)
163 if ((B004_F(i) & B004_EXIST) && (B004_BASE(i)==base)) return 1;
164 return (0);
165 }
166
167 #define b004_delay(a) DELAY(10000)
168
169 /*
170 * static void bqureset(): reset transputer network.
171 *
172 */
173
174 static void
175 bqureset( const int dev_min )
176 {
177 DEB(printf("B004 resetting transputer at link %d.\n", dev_min);)
178 out(B004_BASE(dev_min)+B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
179 b004_delay(dev_min);
180
181 out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
182 b004_delay(dev_min);
183
184 out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET);
185 b004_delay(dev_min);
186
187 out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
188 b004_delay(dev_min);
189
190 DEB(printf("B004 reset done.\n");)
191 }
192
193 /*
194 * static void bquanalyse(): switch transputer network to analyse mode.
195 *
196 */
197
198 static void
199 bquanalyse( const int dev_min )
200 {
201 DEB(printf("B004 analysing transputer at link %d.\n", dev_min);)
202
203 out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
204 b004_delay(dev_min);
205
206 out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_ASSERT_ANALYSE);
207 b004_delay(dev_min);
208
209 out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET);
210 b004_delay(dev_min);
211
212 out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
213 b004_delay(dev_min);
214
215 out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
216 b004_delay(dev_min);
217
218 DEB(printf("B004 switching to analyse-mode done.\n");)
219 }
220
221
222 /****************************************************************************
223 *
224 * int bquread() - read bytes from the link interface.
225 *
226 * At first, the driver checks if the link-interface is ready to send a byte
227 * to the PC. If not, this check is repeated up to B004_MAXTRY times.
228 * If the link-interface is not ready after this loop, the driver sleeps for
229 * an NO=1 ticks and then checks the link-interface again.
230 * If the interface is still not ready, repeats as above incrementing NO.
231 * Once almost one byte is read N0 is set to 1.
232 * If B004_TIMEOUT != 0 and the link-interface is not ready for more than
233 * B004_TIMEOUT ticks read aborts returnig with the number of bytes read
234 * or with an error if no byte was read.
235 *
236 * By default, B004_TIMEOUT is = 0 (read is blocking)
237 *
238 *****************************************************************************/
239
240 static int
241 bquread(dev_t dev, struct uio *uio, int flag)
242 {
243 unsigned int dev_min = minor(dev) & 7;
244
245 int timeout=B004_TIMEOUT(dev_min);
246 int Timeout=timeout;
247 int idr=B004_IDR(dev_min);
248 int isr=B004_ISR(dev_min);
249 char buffer[B004_MAX_BYTES];
250
251 if ( uio->uio_resid < 0) {
252 DEB(printf("B004: invalid count for reading = %d.\n", uio->uio_resid);)
253 return EINVAL;
254 }
255
256 while ( uio->uio_resid ) {
257 int sleep_ticks=0;
258 char *p, *last, *lim;
259 int i, end = min(B004_MAX_BYTES,uio->uio_resid);
260 lim= &buffer[end];
261 for (p= buffer; p<lim;) {
262 last=p;
263 /*** try to read as much as possible ***/
264 #ifdef USE_ASM
265 /* assembly code uses a very tight loop, with
266 * BX= data port, DX= address port, CX=count, ES:DI=p, AL=data, AH=1
267 * SI=retry counter
268 */
269 __asm__ (
270 "movl %1, %%edx\n\t" /* isr */
271 "movl %2, %%ebx\n\t" /* idr */
272 "movl %3, %%edi\n" /* p */
273 "movl %4, %%ecx\n\t" /* lim */
274 "subl %%edi, %%ecx\n\t"
275
276 "push %%es\n\t"
277 "movw %%ss, %%ax\n\t" /** prepare ES, DF for transfer */
278 "movw %%ax, %%es\n\t"
279 "cld\n\t"
280 "movb $1, %%ah\n\t"
281
282 "1:\tinb %%dx, %%al\n\t"
283 "testb %%ah, %%al\n\t"
284 "jz 2f\n\t"
285 "xchgl %%edx, %%ebx\n\t"
286 "insb\n\t"
287 "xchgl %%edx, %%ebx\n"
288 "2:\tloop 1b\n\t"
289
290 "pop %%es\n\t"
291 "movl %%edi, %0\n\t" /* store p */
292 : /* out */ "=g" (p)
293 : /* in */ "g" (isr), "g" (idr), "g" (p), "g" (lim)
294 : /* regs */ "eax", "ebx", "edx", "ecx", "edi");
295 #else
296 for (i=lim - p; i-- ;)
297 if (inb(isr)&B004_READBYTE) *p++ =(char) inb(idr);
298 #endif
299 if (last!=p) {
300 sleep_ticks = 0;
301 } else {
302 /*** no new data read, must sleep ***/
303 sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks);
304 if (Timeout) {
305 if (timeout <=0) {
306 DEB2(printf("Read : TIMEOUT OCCURRED XXXXXXXXXXX\n");)
307 break;
308 }
309 if (timeout < sleep_ticks) sleep_ticks=timeout;
310 timeout -= sleep_ticks;
311 }
312 DEB2(printf("Read: SLEEPING FOR %d TICKS XXXXX\n",sleep_ticks);)
313 if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH,
314 "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1;
315 }
316 }
317 if (p != buffer) {
318 uiomove((caddr_t)buffer, p - buffer, uio);
319 }
320 if( (Timeout) && (timeout <= 0) )
321 break;
322 }
323 return 0;
324 } /* bquread() */
325
326
327 /*
328 * int bquwrite() - write to the link interface.
329 */
330
331 static int
332 bquwrite(dev_t dev, struct uio *uio, int flag)
333 {
334 unsigned int dev_min = minor(dev) & 7;
335
336 int i, end;
337 int timeout=B004_TIMEOUT(dev_min);
338 int Timeout=timeout;
339 int odr=B004_ODR(dev_min);
340 int osr=B004_OSR(dev_min);
341 char buffer[B004_MAX_BYTES];
342
343 if ( uio->uio_resid < 0) {
344 DEB(printf("B004 invalid argument for writing: count = %d.\n", uio->uio_resid);)
345 return EINVAL;
346 }
347
348 while ( uio->uio_resid ) {
349 int sleep_ticks=0;
350 char *p, *last, *lim;
351 end = min(B004_MAX_BYTES,uio->uio_resid);
352 uiomove((caddr_t)buffer, end, uio);
353
354 lim= &buffer[end];
355 for (p= &buffer[0]; p<lim;) {
356 last=p;
357 #ifdef USE_ASM
358 /* assembly code uses a very tight loop, with
359 * BX= data port, DX= address port, CX=count, DS:SI=p, AL=data, AH=1
360 * DI= retry counter
361 * Unfortunately, C is almost as fast as this!
362 */
363 __asm__ (
364 "movl %1, %%edx\n\t" /* osr */
365 "movl %2, %%ebx\n\t" /* odr */
366 "movl %3, %%esi\n" /* p */
367 "movl %4, %%ecx\n\t" /* lim */
368 "subl %%esi, %%ecx\n\t"
369
370 "push %%ds\n\t"
371 "movw %%ss, %%ax\n\t" /** prepare DS, DF for transfer */
372 "movw %%ax, %%ds\n\t"
373 "cld\n\t"
374 "movb $1, %%ah\n\t"
375 "movw $100, %%di\n\t"
376
377 "1:\tinb %%dx, %%al\n\t"
378 "testb %%ah, %%al\n\t"
379 "jz 2f\n\t"
380 "xchgl %%edx, %%ebx\n\t"
381 "outsb\n\t"
382 "xchgl %%edx, %%ebx\n\t"
383 "loop 1b\n\t"
384 "jmp 3f\n"
385
386 "2:\tdec %%di\n\t"
387 "jnc 1b\n\t"
388
389 "3:\tpop %%ds\n"
390 "movl %%esi, %0\n\t" /* store p */
391 : /* out */ "=g" (p)
392 : /* in */ "g" (osr), "g" (odr), "g" (p), "g" (lim)
393 : /* regs */ "eax", "ebx", "edx", "ecx", "esi", "edi");
394 #else
395 for (i=lim - p; i-- ; ) {
396 if (inb(osr)&B004_WRITEBYTE) outb(odr, *p++);
397 }
398 #endif
399 if (p != last ) {
400 sleep_ticks=0;
401 } else {
402 sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks);
403 if (Timeout) {
404 if (timeout <=0) {
405 DEB2(printf("Write : TIMEOUT OCCURRED XXXXXXXXXXX\n");)
406 uio->uio_resid += (lim - p);
407 break;
408 }
409 if (timeout < sleep_ticks) sleep_ticks=timeout;
410 timeout -= sleep_ticks;
411 }
412 DEB2(printf("Write: SLEEPING FOR %d TICKS XXXXXXX\n",sleep_ticks);)
413 if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH,
414 "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1;
415 }
416 }
417 if( (Timeout) && (timeout <= 0) )
418 break;
419 }
420 return 0;
421 } /* bquwrite() */
422
423 /*
424 * int bquopen() -- open the link-device.
425 *
426 */
427
428 static int
429 bquopen(dev_t dev, int flags, int fmt, struct proc *p)
430 {
431 unsigned int dev_min = minor(dev) & 7;
432
433 if (dev_min >= NBQU) {
434 DEB(printf("B004 not opened, minor number >= %d.\n", NBQU);)
435 return ENXIO;
436 }
437 if ((B004_F(dev_min) & B004_EXIST) == 0) {
438 DEB(printf("B004 not opened, board %d does not exist.\n", dev_min);)
439 return ENXIO;
440 }
441 if (B004_F(dev_min) & B004_BUSY) {
442 DEB(printf("B004 not opened, board busy (minor = %d).\n", dev_min);)
443 return EBUSY;
444 }
445 B004_F(dev_min) |= B004_BUSY;
446 B004_TIMEOUT(dev_min) = 0;
447 DEB(printf( "B004 opened, minor = %d.\n", dev_min );)
448 return 0;
449 } /* bquopen() */
450
451
452 /*
453 * int b004close() -- close the link device.
454 */
455
456 static int
457 bquclose(dev_t dev, int flags, int fmt, struct proc *p)
458 {
459 unsigned int dev_min = minor(dev) & 7;
460
461 if (dev_min >= NBQU) {
462 DEB(printf("B004 not released, minor number >= %d.\n", NBQU);)
463 return ENXIO;
464 }
465 B004_F(dev_min) &= ~B004_BUSY;
466 DEB(printf("B004(%d) released.\n", dev_min );)
467 return 0;
468 }
469
470 static int
471 bquselect(dev_t dev, int rw, struct proc *p)
472 {
473 /* still unimplemented */
474 return(1);
475 }
476
477 /*
478 * int bquioctl()
479 *
480 * Supported functions:
481 * - reset
482 * - analyse
483 * - test error flag
484 * - set timeout
485 */
486
487 static int
488 bquioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
489 {
490 unsigned int dev_min = minor(dev) & 7;
491 int result = 0;
492
493 if (dev_min >= NBQU) {
494 DEB(printf("B004 ioctl exit, minor >= %d.\n", NBQU );)
495 return ENODEV;
496 }
497
498 if ((B004_F(dev_min) & B004_EXIST) == 0) {
499 DEB(printf("B004 ioctl exit, (B004_F & B004_EXIST) == 0.\n" );)
500 return ENODEV;
501 }
502
503 switch ( cmd ) {
504 case B004RESET: /* reset transputer */
505 bqureset(dev_min);
506 DEB(printf("B004 ioctl B004RESET, done\n" );)
507 break;
508 case B004WRITEABLE: /* can we write a byte to the C012 ? */
509 IOCTL_OUT (addr, ((in(B004_OSR(dev_min))&B004_WRITEBYTE) != 0 ));
510 break;
511 case B004READABLE: /* can we read a byte from C012 ? */
512 IOCTL_OUT (addr, ((in(B004_ISR(dev_min)) & B004_READBYTE) != 0 ));
513 break;
514 case B004ANALYSE: /* switch transputer to analyse mode */
515 bquanalyse(dev_min);
516 break;
517 case B004ERROR: /* test error-flag */
518 IOCTL_OUT (addr,
519 ((inb(B004_BASE(dev_min)+B004_ERROR_OFFSET) &
520 B004_TEST_ERROR) ? 0 : 1));
521 break;
522 case B004TIMEOUT: /* set, retrieve timeout for writing & reading*/
523 B004_TIMEOUT(dev_min) = *((int *)addr);
524 break;
525 default: result = EINVAL;
526 }
527 return result;
528 } /* bquioctl() */
529
530
531 static int
532 bquattach(struct isa_device *idp)
533 {
534 int unit = idp->id_unit;
535 struct b004_struct *bp;
536 int i;
537
538 #ifdef DEVFS
539 #define BQU_UID 66
540 #define BQU_GID 66
541 #define BQU_PERM 0600
542 bp = &b004_table[unit];
543 for ( i = 0; i < 8; i++) {
544 #ifdef NOTYET
545 /* if (we've done all the ports found) break; */
546 #endif
547 bp->devfs_token[i][0]=
548 devfs_add_devswf(&bqu_cdevsw, i, DV_CHR, BQU_UID,
549 BQU_GID, BQU_PERM, "ttyba%d", i);
550 bp->devfs_token[i][0]=
551 devfs_add_devswf(&bqu_cdevsw, i+64, DV_CHR, BQU_UID,
552 BQU_GID, BQU_PERM, "ttybb%d", i);
553 bp->devfs_token[i][0]=
554 devfs_add_devswf(&bqu_cdevsw, i+128, DV_CHR, BQU_UID,
555 BQU_GID, BQU_PERM, "ttybc%d", i);
556 bp->devfs_token[i][0]=
557 devfs_add_devswf(&bqu_cdevsw, i+192, DV_CHR, BQU_UID,
558 BQU_GID, BQU_PERM, "ttybd%d", unit);
559 }
560 #endif
561 return 1;
562 }
563
564 /*
565 * int bquprobe
566 *
567 * Initializes the driver. It tries to detect the hardware
568 * and sets up all relevant data-structures.
569 */
570
571 static int
572 bquprobe(struct isa_device *idp)
573 {
574 unsigned int test;
575 unsigned int dev_min = idp->id_unit;
576 int i,found = 0;
577 /* After a reset it should be possible to write a byte to
578 the B004. So let'S do a reset and then test the output status
579 register
580 */
581 #ifdef undef
582 printf(
583 "bquprobe::\nIOBASE 0x%x\nIRQ %d\nDRQ %d\nMSIZE %d\nUNIT %d\nFLAGS"
584 "x0%x\nALIVE %d\n",idp->id_iobase,idp->id_irq,
585 idp->id_drq,idp->id_msize,idp->id_unit,idp->id_flags,idp->id_alive);
586 #endif
587 if(first_time){
588 for(i=0;i<NBQU;i++) B004_F(i) &= ~B004_EXIST;
589 first_time=0;
590 }
591
592 if(dev_min >= NBQU) return (0); /* No more descriptors */
593 if ((idp->id_iobase < 0x100) || (idp->id_iobase >= 0x1000))
594 idp->id_iobase=0; /* Dangerous isa addres ) */
595
596 for (test = 0; (test < B004_CHANCE); test++) {
597 if((idp->id_iobase==0)&&((!b004_base_addresses[test])||
598 detected(b004_base_addresses[test])))
599 continue;
600 idp->id_iobase=b004_base_addresses[test];
601
602 DEB(printf("Probing device %d at address 0x%x\n",dev_min,
603 idp->id_iobase);
604 )
605 b004_delay(test);
606 B004_F(dev_min) = 0;
607 B004_TIMEOUT(dev_min) = B004_INIT_TIMEOUT;
608 B004_BASE(dev_min) = idp->id_iobase;
609 B004_ODR(dev_min) = B004_BASE(dev_min) + B004_ODR_OFFSET;
610 B004_ISR(dev_min) = B004_BASE(dev_min) + B004_ISR_OFFSET;
611 B004_OSR(dev_min) = B004_BASE(dev_min) + B004_OSR_OFFSET;
612 bqureset(dev_min);
613
614 for (i = 0; i < B004_MAXTRY; i++)
615 if ( in(B004_OSR(dev_min)) == B004_WRITEBYTE) {
616 B004_F(dev_min) |= B004_EXIST;
617 out(B004_BASE(dev_min) + B008_INT_OFFSET, 0);
618 b004_delay(test);
619 if (in(B004_BASE(dev_min) + B008_INT_OFFSET) & 0x0f == 0)
620 B004_BOARDTYPE(dev_min) = B008;
621 else
622 B004_BOARDTYPE(dev_min) = B004;
623 printf("bqu%d at 0x0%x (polling) is a B00%s\n",
624 dev_min,B004_IDR(dev_min),
625 (B004_BOARDTYPE(dev_min) == B004) ? "4" : "8");
626 found = 1;
627 break;
628 }
629 if(!found) {
630 idp->id_iobase=0;
631 }
632 else break;
633
634 }
635
636 if (!found){
637 DEB(printf("b004probe(): no B004-board found.\n"));
638 return (0);
639 }
640
641 idp->id_maddr=NULL;
642 idp->id_irq=0;
643 if(B004_BOARDTYPE(dev_min) == B004)
644 return(18);
645 else
646 return(20);
647 } /* bquprobe() */
648
649
650 static bqu_devsw_installed = 0;
651
652 static void
653 bqu_drvinit(void *unused)
654 {
655 dev_t dev;
656
657 if( ! bqu_devsw_installed ) {
658 dev = makedev(CDEV_MAJOR, 0);
659 cdevsw_add(&dev,&bqu_cdevsw, NULL);
660 bqu_devsw_installed = 1;
661 }
662 }
663
664 SYSINIT(bqudev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bqu_drvinit,NULL)
665
666
667 #endif /* NBQU */
Cache object: d0aaad90d48808f0d68d82dafa356c15
|