diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/sc/init.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/sc/init.c')
-rw-r--r-- | drivers/isdn/sc/init.c | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c new file mode 100644 index 000000000000..efefedea37b9 --- /dev/null +++ b/drivers/isdn/sc/init.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /* | ||
2 | * This software may be used and distributed according to the terms | ||
3 | * of the GNU General Public License, incorporated herein by reference. | ||
4 | * | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include "includes.h" | ||
12 | #include "hardware.h" | ||
13 | #include "card.h" | ||
14 | |||
15 | MODULE_DESCRIPTION("ISDN4Linux: Driver for Spellcaster card"); | ||
16 | MODULE_AUTHOR("Spellcaster Telecommunications Inc."); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | board *sc_adapter[MAX_CARDS]; | ||
20 | int cinst; | ||
21 | |||
22 | static char devname[] = "scX"; | ||
23 | const char version[] = "2.0b1"; | ||
24 | |||
25 | const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" }; | ||
26 | |||
27 | /* insmod set parameters */ | ||
28 | static unsigned int io[] = {0,0,0,0}; | ||
29 | static unsigned char irq[] = {0,0,0,0}; | ||
30 | static unsigned long ram[] = {0,0,0,0}; | ||
31 | static int do_reset = 0; | ||
32 | |||
33 | module_param_array(io, int, NULL, 0); | ||
34 | module_param_array(irq, int, NULL, 0); | ||
35 | module_param_array(ram, int, NULL, 0); | ||
36 | module_param(do_reset, bool, 0); | ||
37 | |||
38 | static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 }; | ||
39 | #define MAX_IRQS 10 | ||
40 | |||
41 | extern irqreturn_t interrupt_handler(int, void *, struct pt_regs *); | ||
42 | extern int sndpkt(int, int, int, struct sk_buff *); | ||
43 | extern int command(isdn_ctrl *); | ||
44 | extern int indicate_status(int, int, ulong, char*); | ||
45 | extern int reset(int); | ||
46 | |||
47 | int identify_board(unsigned long, unsigned int); | ||
48 | |||
49 | int irq_supported(int irq_x) | ||
50 | { | ||
51 | int i; | ||
52 | for(i=0 ; i < MAX_IRQS ; i++) { | ||
53 | if(sup_irq[i] == irq_x) | ||
54 | return 1; | ||
55 | } | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int __init sc_init(void) | ||
60 | { | ||
61 | int b = -1; | ||
62 | int i, j; | ||
63 | int status = -ENODEV; | ||
64 | |||
65 | unsigned long memsize = 0; | ||
66 | unsigned long features = 0; | ||
67 | isdn_if *interface; | ||
68 | unsigned char channels; | ||
69 | unsigned char pgport; | ||
70 | unsigned long magic; | ||
71 | int model; | ||
72 | int last_base = IOBASE_MIN; | ||
73 | int probe_exhasted = 0; | ||
74 | |||
75 | #ifdef MODULE | ||
76 | pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s Loaded\n", version); | ||
77 | #else | ||
78 | pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s\n", version); | ||
79 | #endif | ||
80 | pr_info("Copyright (C) 1996 SpellCaster Telecommunications Inc.\n"); | ||
81 | |||
82 | while(b++ < MAX_CARDS - 1) { | ||
83 | pr_debug("Probing for adapter #%d\n", b); | ||
84 | /* | ||
85 | * Initialize reusable variables | ||
86 | */ | ||
87 | model = -1; | ||
88 | magic = 0; | ||
89 | channels = 0; | ||
90 | pgport = 0; | ||
91 | |||
92 | /* | ||
93 | * See if we should probe for IO base | ||
94 | */ | ||
95 | pr_debug("I/O Base for board %d is 0x%x, %s probe\n", b, io[b], | ||
96 | io[b] == 0 ? "will" : "won't"); | ||
97 | if(io[b]) { | ||
98 | /* | ||
99 | * No, I/O Base has been provided | ||
100 | */ | ||
101 | for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { | ||
102 | if(!request_region(io[b] + i * 0x400, 1, "sc test")) { | ||
103 | pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400); | ||
104 | io[b] = 0; | ||
105 | break; | ||
106 | } else | ||
107 | release_region(io[b] + i * 0x400, 1); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * Confirm the I/O Address with a test | ||
112 | */ | ||
113 | if(io[b] == 0) { | ||
114 | pr_debug("I/O Address 0x%x is in use.\n"); | ||
115 | continue; | ||
116 | } | ||
117 | |||
118 | outb(0x18, io[b] + 0x400 * EXP_PAGE0); | ||
119 | if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { | ||
120 | pr_debug("I/O Base 0x%x fails test\n"); | ||
121 | continue; | ||
122 | } | ||
123 | } | ||
124 | else { | ||
125 | /* | ||
126 | * Yes, probe for I/O Base | ||
127 | */ | ||
128 | if(probe_exhasted) { | ||
129 | pr_debug("All probe addresses exhasted, skipping\n"); | ||
130 | continue; | ||
131 | } | ||
132 | pr_debug("Probing for I/O...\n"); | ||
133 | for (i = last_base ; i <= IOBASE_MAX ; i += IOBASE_OFFSET) { | ||
134 | int found_io = 1; | ||
135 | if (i == IOBASE_MAX) { | ||
136 | probe_exhasted = 1; /* No more addresses to probe */ | ||
137 | pr_debug("End of Probes\n"); | ||
138 | } | ||
139 | last_base = i + IOBASE_OFFSET; | ||
140 | pr_debug(" checking 0x%x...", i); | ||
141 | for ( j = 0 ; j < MAX_IO_REGS - 1 ; j++) { | ||
142 | if(!request_region(i + j * 0x400, 1, "sc test")) { | ||
143 | pr_debug("Failed\n"); | ||
144 | found_io = 0; | ||
145 | break; | ||
146 | } else | ||
147 | release_region(i + j * 0x400, 1); | ||
148 | } | ||
149 | |||
150 | if(found_io) { | ||
151 | io[b] = i; | ||
152 | outb(0x18, io[b] + 0x400 * EXP_PAGE0); | ||
153 | if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { | ||
154 | pr_debug("Failed by test\n"); | ||
155 | continue; | ||
156 | } | ||
157 | pr_debug("Passed\n"); | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | if(probe_exhasted) { | ||
162 | continue; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * See if we should probe for shared RAM | ||
168 | */ | ||
169 | if(do_reset) { | ||
170 | pr_debug("Doing a SAFE probe reset\n"); | ||
171 | outb(0xFF, io[b] + RESET_OFFSET); | ||
172 | msleep_interruptible(10000); | ||
173 | } | ||
174 | pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], | ||
175 | ram[b] == 0 ? "will" : "won't"); | ||
176 | |||
177 | if(ram[b]) { | ||
178 | /* | ||
179 | * No, the RAM base has been provided | ||
180 | * Just look for a signature and ID the | ||
181 | * board model | ||
182 | */ | ||
183 | if(request_region(ram[b], SRAM_PAGESIZE, "sc test")) { | ||
184 | pr_debug("request_region for RAM base 0x%x succeeded\n", ram[b]); | ||
185 | model = identify_board(ram[b], io[b]); | ||
186 | release_region(ram[b], SRAM_PAGESIZE); | ||
187 | } | ||
188 | } | ||
189 | else { | ||
190 | /* | ||
191 | * Yes, probe for free RAM and look for | ||
192 | * a signature and id the board model | ||
193 | */ | ||
194 | for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { | ||
195 | pr_debug("Checking RAM address 0x%x...\n", i); | ||
196 | if(request_region(i, SRAM_PAGESIZE, "sc test")) { | ||
197 | pr_debug(" check_region succeeded\n"); | ||
198 | model = identify_board(i, io[b]); | ||
199 | release_region(i, SRAM_PAGESIZE); | ||
200 | if (model >= 0) { | ||
201 | pr_debug(" Identified a %s\n", | ||
202 | boardname[model]); | ||
203 | ram[b] = i; | ||
204 | break; | ||
205 | } | ||
206 | pr_debug(" Unidentifed or inaccessible\n"); | ||
207 | continue; | ||
208 | } | ||
209 | pr_debug(" request failed\n"); | ||
210 | } | ||
211 | } | ||
212 | /* | ||
213 | * See if we found free RAM and the board model | ||
214 | */ | ||
215 | if(!ram[b] || model < 0) { | ||
216 | /* | ||
217 | * Nope, there was no place in RAM for the | ||
218 | * board, or it couldn't be identified | ||
219 | */ | ||
220 | pr_debug("Failed to find an adapter at 0x%x\n", ram[b]); | ||
221 | continue; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Set the board's magic number, memory size and page register | ||
226 | */ | ||
227 | switch(model) { | ||
228 | case PRI_BOARD: | ||
229 | channels = 23; | ||
230 | magic = 0x20000; | ||
231 | memsize = 0x100000; | ||
232 | features = PRI_FEATURES; | ||
233 | break; | ||
234 | |||
235 | case BRI_BOARD: | ||
236 | case POTS_BOARD: | ||
237 | channels = 2; | ||
238 | magic = 0x60000; | ||
239 | memsize = 0x10000; | ||
240 | features = BRI_FEATURES; | ||
241 | break; | ||
242 | } | ||
243 | switch(ram[b] >> 12 & 0x0F) { | ||
244 | case 0x0: | ||
245 | pr_debug("RAM Page register set to EXP_PAGE0\n"); | ||
246 | pgport = EXP_PAGE0; | ||
247 | break; | ||
248 | |||
249 | case 0x4: | ||
250 | pr_debug("RAM Page register set to EXP_PAGE1\n"); | ||
251 | pgport = EXP_PAGE1; | ||
252 | break; | ||
253 | |||
254 | case 0x8: | ||
255 | pr_debug("RAM Page register set to EXP_PAGE2\n"); | ||
256 | pgport = EXP_PAGE2; | ||
257 | break; | ||
258 | |||
259 | case 0xC: | ||
260 | pr_debug("RAM Page register set to EXP_PAGE3\n"); | ||
261 | pgport = EXP_PAGE3; | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | pr_debug("RAM base address doesn't fall on 16K boundary\n"); | ||
266 | continue; | ||
267 | } | ||
268 | |||
269 | pr_debug("current IRQ: %d b: %d\n",irq[b],b); | ||
270 | |||
271 | /* | ||
272 | * Make sure we got an IRQ | ||
273 | */ | ||
274 | if(!irq[b]) { | ||
275 | /* | ||
276 | * No interrupt could be used | ||
277 | */ | ||
278 | pr_debug("Failed to acquire an IRQ line\n"); | ||
279 | continue; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Horray! We found a board, Make sure we can register | ||
284 | * it with ISDN4Linux | ||
285 | */ | ||
286 | interface = kmalloc(sizeof(isdn_if), GFP_KERNEL); | ||
287 | if (interface == NULL) { | ||
288 | /* | ||
289 | * Oops, can't malloc isdn_if | ||
290 | */ | ||
291 | continue; | ||
292 | } | ||
293 | memset(interface, 0, sizeof(isdn_if)); | ||
294 | |||
295 | interface->owner = THIS_MODULE; | ||
296 | interface->hl_hdrlen = 0; | ||
297 | interface->channels = channels; | ||
298 | interface->maxbufsize = BUFFER_SIZE; | ||
299 | interface->features = features; | ||
300 | interface->writebuf_skb = sndpkt; | ||
301 | interface->writecmd = NULL; | ||
302 | interface->command = command; | ||
303 | strcpy(interface->id, devname); | ||
304 | interface->id[2] = '0' + cinst; | ||
305 | |||
306 | /* | ||
307 | * Allocate the board structure | ||
308 | */ | ||
309 | sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); | ||
310 | if (sc_adapter[cinst] == NULL) { | ||
311 | /* | ||
312 | * Oops, can't alloc memory for the board | ||
313 | */ | ||
314 | kfree(interface); | ||
315 | continue; | ||
316 | } | ||
317 | memset(sc_adapter[cinst], 0, sizeof(board)); | ||
318 | spin_lock_init(&sc_adapter[cinst]->lock); | ||
319 | |||
320 | if(!register_isdn(interface)) { | ||
321 | /* | ||
322 | * Oops, couldn't register for some reason | ||
323 | */ | ||
324 | kfree(interface); | ||
325 | kfree(sc_adapter[cinst]); | ||
326 | continue; | ||
327 | } | ||
328 | |||
329 | sc_adapter[cinst]->card = interface; | ||
330 | sc_adapter[cinst]->driverId = interface->channels; | ||
331 | strcpy(sc_adapter[cinst]->devicename, interface->id); | ||
332 | sc_adapter[cinst]->nChannels = channels; | ||
333 | sc_adapter[cinst]->ramsize = memsize; | ||
334 | sc_adapter[cinst]->shmem_magic = magic; | ||
335 | sc_adapter[cinst]->shmem_pgport = pgport; | ||
336 | sc_adapter[cinst]->StartOnReset = 1; | ||
337 | |||
338 | /* | ||
339 | * Allocate channels status structures | ||
340 | */ | ||
341 | sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); | ||
342 | if (sc_adapter[cinst]->channel == NULL) { | ||
343 | /* | ||
344 | * Oops, can't alloc memory for the channels | ||
345 | */ | ||
346 | indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ | ||
347 | kfree(interface); | ||
348 | kfree(sc_adapter[cinst]); | ||
349 | continue; | ||
350 | } | ||
351 | memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels); | ||
352 | |||
353 | /* | ||
354 | * Lock down the hardware resources | ||
355 | */ | ||
356 | sc_adapter[cinst]->interrupt = irq[b]; | ||
357 | if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler, | ||
358 | SA_INTERRUPT, interface->id, NULL)) | ||
359 | { | ||
360 | kfree(sc_adapter[cinst]->channel); | ||
361 | indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ | ||
362 | kfree(interface); | ||
363 | kfree(sc_adapter[cinst]); | ||
364 | continue; | ||
365 | |||
366 | } | ||
367 | sc_adapter[cinst]->iobase = io[b]; | ||
368 | for(i = 0 ; i < MAX_IO_REGS - 1 ; i++) { | ||
369 | sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400; | ||
370 | request_region(sc_adapter[cinst]->ioport[i], 1, | ||
371 | interface->id); | ||
372 | pr_debug("Requesting I/O Port %#x\n", | ||
373 | sc_adapter[cinst]->ioport[i]); | ||
374 | } | ||
375 | sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2; | ||
376 | request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1, | ||
377 | interface->id); | ||
378 | pr_debug("Requesting I/O Port %#x\n", | ||
379 | sc_adapter[cinst]->ioport[IRQ_SELECT]); | ||
380 | sc_adapter[cinst]->rambase = ram[b]; | ||
381 | request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE, | ||
382 | interface->id); | ||
383 | |||
384 | pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n", | ||
385 | sc_adapter[cinst]->devicename, | ||
386 | sc_adapter[cinst]->driverId, | ||
387 | boardname[model], channels, irq[b], io[b], ram[b]); | ||
388 | |||
389 | /* | ||
390 | * reset the adapter to put things in motion | ||
391 | */ | ||
392 | reset(cinst); | ||
393 | |||
394 | cinst++; | ||
395 | status = 0; | ||
396 | } | ||
397 | if (status) | ||
398 | pr_info("Failed to find any adapters, driver unloaded\n"); | ||
399 | return status; | ||
400 | } | ||
401 | |||
402 | static void __exit sc_exit(void) | ||
403 | { | ||
404 | int i, j; | ||
405 | |||
406 | for(i = 0 ; i < cinst ; i++) { | ||
407 | pr_debug("Cleaning up after adapter %d\n", i); | ||
408 | /* | ||
409 | * kill the timers | ||
410 | */ | ||
411 | del_timer(&(sc_adapter[i]->reset_timer)); | ||
412 | del_timer(&(sc_adapter[i]->stat_timer)); | ||
413 | |||
414 | /* | ||
415 | * Tell I4L we're toast | ||
416 | */ | ||
417 | indicate_status(i, ISDN_STAT_STOP, 0, NULL); | ||
418 | indicate_status(i, ISDN_STAT_UNLOAD, 0, NULL); | ||
419 | |||
420 | /* | ||
421 | * Release shared RAM | ||
422 | */ | ||
423 | release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE); | ||
424 | |||
425 | /* | ||
426 | * Release the IRQ | ||
427 | */ | ||
428 | FREE_IRQ(sc_adapter[i]->interrupt, NULL); | ||
429 | |||
430 | /* | ||
431 | * Reset for a clean start | ||
432 | */ | ||
433 | outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]); | ||
434 | |||
435 | /* | ||
436 | * Release the I/O Port regions | ||
437 | */ | ||
438 | for(j = 0 ; j < MAX_IO_REGS - 1; j++) { | ||
439 | release_region(sc_adapter[i]->ioport[j], 1); | ||
440 | pr_debug("Releasing I/O Port %#x\n", | ||
441 | sc_adapter[i]->ioport[j]); | ||
442 | } | ||
443 | release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1); | ||
444 | pr_debug("Releasing I/O Port %#x\n", | ||
445 | sc_adapter[i]->ioport[IRQ_SELECT]); | ||
446 | |||
447 | /* | ||
448 | * Release any memory we alloced | ||
449 | */ | ||
450 | kfree(sc_adapter[i]->channel); | ||
451 | kfree(sc_adapter[i]->card); | ||
452 | kfree(sc_adapter[i]); | ||
453 | } | ||
454 | pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n"); | ||
455 | } | ||
456 | |||
457 | int identify_board(unsigned long rambase, unsigned int iobase) | ||
458 | { | ||
459 | unsigned int pgport; | ||
460 | unsigned long sig; | ||
461 | DualPortMemory *dpm; | ||
462 | RspMessage rcvmsg; | ||
463 | ReqMessage sndmsg; | ||
464 | HWConfig_pl hwci; | ||
465 | int x; | ||
466 | |||
467 | pr_debug("Attempting to identify adapter @ 0x%x io 0x%x\n", | ||
468 | rambase, iobase); | ||
469 | |||
470 | /* | ||
471 | * Enable the base pointer | ||
472 | */ | ||
473 | outb(rambase >> 12, iobase + 0x2c00); | ||
474 | |||
475 | switch(rambase >> 12 & 0x0F) { | ||
476 | case 0x0: | ||
477 | pgport = iobase + PG0_OFFSET; | ||
478 | pr_debug("Page Register offset is 0x%x\n", PG0_OFFSET); | ||
479 | break; | ||
480 | |||
481 | case 0x4: | ||
482 | pgport = iobase + PG1_OFFSET; | ||
483 | pr_debug("Page Register offset is 0x%x\n", PG1_OFFSET); | ||
484 | break; | ||
485 | |||
486 | case 0x8: | ||
487 | pgport = iobase + PG2_OFFSET; | ||
488 | pr_debug("Page Register offset is 0x%x\n", PG2_OFFSET); | ||
489 | break; | ||
490 | |||
491 | case 0xC: | ||
492 | pgport = iobase + PG3_OFFSET; | ||
493 | pr_debug("Page Register offset is 0x%x\n", PG3_OFFSET); | ||
494 | break; | ||
495 | default: | ||
496 | pr_debug("Invalid rambase 0x%lx\n", rambase); | ||
497 | return -1; | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * Try to identify a PRI card | ||
502 | */ | ||
503 | outb(PRI_BASEPG_VAL, pgport); | ||
504 | msleep_interruptible(1000); | ||
505 | sig = readl(rambase + SIG_OFFSET); | ||
506 | pr_debug("Looking for a signature, got 0x%x\n", sig); | ||
507 | if(sig == SIGNATURE) | ||
508 | return PRI_BOARD; | ||
509 | |||
510 | /* | ||
511 | * Try to identify a PRI card | ||
512 | */ | ||
513 | outb(BRI_BASEPG_VAL, pgport); | ||
514 | msleep_interruptible(1000); | ||
515 | sig = readl(rambase + SIG_OFFSET); | ||
516 | pr_debug("Looking for a signature, got 0x%x\n", sig); | ||
517 | if(sig == SIGNATURE) | ||
518 | return BRI_BOARD; | ||
519 | |||
520 | return -1; | ||
521 | |||
522 | /* | ||
523 | * Try to spot a card | ||
524 | */ | ||
525 | sig = readl(rambase + SIG_OFFSET); | ||
526 | pr_debug("Looking for a signature, got 0x%x\n", sig); | ||
527 | if(sig != SIGNATURE) | ||
528 | return -1; | ||
529 | |||
530 | dpm = (DualPortMemory *) rambase; | ||
531 | |||
532 | memset(&sndmsg, 0, MSG_LEN); | ||
533 | sndmsg.msg_byte_cnt = 3; | ||
534 | sndmsg.type = cmReqType1; | ||
535 | sndmsg.class = cmReqClass0; | ||
536 | sndmsg.code = cmReqHWConfig; | ||
537 | memcpy_toio(&(dpm->req_queue[dpm->req_head++]), &sndmsg, MSG_LEN); | ||
538 | outb(0, iobase + 0x400); | ||
539 | pr_debug("Sent HWConfig message\n"); | ||
540 | /* | ||
541 | * Wait for the response | ||
542 | */ | ||
543 | x = 0; | ||
544 | while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { | ||
545 | set_current_state(TASK_INTERRUPTIBLE); | ||
546 | schedule_timeout(1); | ||
547 | x++; | ||
548 | } | ||
549 | if(x == 100) { | ||
550 | pr_debug("Timeout waiting for response\n"); | ||
551 | return -1; | ||
552 | } | ||
553 | |||
554 | memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN); | ||
555 | pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status); | ||
556 | memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl)); | ||
557 | pr_debug("Hardware Config: Interface: %s, RAM Size: %d, Serial: %s\n" | ||
558 | " Part: %s, Rev: %s\n", | ||
559 | hwci.st_u_sense ? "S/T" : "U", hwci.ram_size, | ||
560 | hwci.serial_no, hwci.part_no, hwci.rev_no); | ||
561 | |||
562 | if(!strncmp(PRI_PARTNO, hwci.part_no, 6)) | ||
563 | return PRI_BOARD; | ||
564 | if(!strncmp(BRI_PARTNO, hwci.part_no, 6)) | ||
565 | return BRI_BOARD; | ||
566 | |||
567 | return -1; | ||
568 | } | ||
569 | |||
570 | module_init(sc_init); | ||
571 | module_exit(sc_exit); | ||