nubus.c revision 1.9 1 /* $NetBSD: nubus.c,v 1.9 1995/04/12 14:57:40 briggs Exp $ */
2
3 /*-
4 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
5 * Michael L. Finch, Bradley A. Grantham, and
6 * Lawrence A. Kesteloot
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the Alice Group.
20 * 4. The names of the Alice Group or any of its members may not be used
21 * to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <machine/cpu.h>
39
40 #include <sys/device.h>
41 #include "nubus.h"
42
43
44 /* TODO:
45 be able to do "memcpy"s from the board, then i won't
46 have to fill in structures by hand.
47
48 get rid of extra crap calls that are useless
49
50 I think the directory stuff is bogus, I need to find
51 that other magic resource that tells me fancy stuff,
52 I could be wrong.
53
54
55 */
56
57
58 struct dir *getRsrcByNum(struct slot *Slot,struct dir *p,int num,struct dir *out,int max);
59 int print_rsrcinfo(struct slot *Slot,struct dir *p);
60 char *GetStringInfo(struct slot *Slot,unsigned char *data1,char *space,int len);
61 int printTree(struct slot *Slot,struct dir *root);
62 long GetLongInfo(struct slot *,unsigned char *data);
63 int FindMagic(unsigned long *data);
64 int GetHeader(struct slot *Slot,unsigned long pos);
65 unsigned char *IncPtr(struct slot *Slot,unsigned char *p,int size);
66 char GetByteInfo(struct slot *Slot,unsigned char *data);
67 int GetRsrcs(struct slot *Slot,unsigned char *p,struct dir *Dir,int maxdir);
68 unsigned char *getDataAtRsrc(struct slot *Slot,struct dir *p,int num);
69 short GetShortInfo(struct slot *Slot,unsigned char *data);
70
71 /* this is the main I used in macos to get stuff out */
72 #if 0
73 main()
74 {
75
76 unsigned long *rawImage;
77 struct imagedata image;
78 struct dir *Dir;
79 struct dir dirSpace[15];
80 struct dir dirSpace2[10];
81 unsigned long length;
82 unsigned long offset;
83 unsigned long nextoffset;
84 int pos,i;
85 unsigned char *data;
86 struct slot Slot;
87
88 // firstHeader=(char *)0xbfffff-40;
89
90 data=(char *)SLOTADDR-100;
91
92 for(i=0;i<100;i++)
93 if (Slot.size=FindMagic( (long *)(data+i) ) )
94 {
95 /* printf("magic found at i=%d\n",i); */
96 GetHeader(&Slot,SLOTADDR-100+i);
97 break;
98 }
99
100
101
102
103 printf("main directory\n");
104 print_rsrcinfo(&Slot,Slot.mainDir );
105
106 Dir=getRsrcByNum(&Slot,Slot.mainDir,128,dirSpace,15);
107
108 printf("image directory\n");
109 print_rsrcinfo(&Slot,Dir);
110
111 printTree(&Slot,Slot.mainDir);
112
113 // get image param stuff
114 Dir=getRsrcByNum(&Slot,Dir,128,dirSpace2,10);
115
116 /* hopefully video mode params */
117 rawImage=getDataAtRsrc(&Slot,Dir,1);
118
119 image.whatTheHellIsThis=GetLongInfo(&Slot,rawImage);
120 rawImage=IncPtr(&Slot,rawImage,4);
121
122 image.offset=GetLongInfo(&Slot,rawImage);
123 rawImage=IncPtr(&Slot,rawImage,4);
124
125 image.rowbytes=GetShortInfo(&Slot,rawImage);
126 rawImage=IncPtr(&Slot,rawImage,2);
127
128 image.top=GetShortInfo(&Slot,rawImage);
129 rawImage=IncPtr(&Slot,rawImage,2);
130
131 image.left=GetShortInfo(&Slot,rawImage);
132 rawImage=IncPtr(&Slot,rawImage,2);
133
134 image.bottom=GetShortInfo(&Slot,rawImage);
135 rawImage=IncPtr(&Slot,rawImage,2);
136
137 image.right=GetShortInfo(&Slot,rawImage);
138 rawImage=IncPtr(&Slot,rawImage,2);
139
140 image.version=GetShortInfo(&Slot,rawImage);
141 rawImage=IncPtr(&Slot,rawImage,2);
142
143 image.packType=GetShortInfo(&Slot,rawImage);
144 rawImage=IncPtr(&Slot,rawImage,2);
145
146 image.packSize=GetShortInfo(&Slot,rawImage);
147 rawImage=IncPtr(&Slot,rawImage,2);
148
149 image.hRes=GetLongInfo(&Slot,rawImage);
150 rawImage=IncPtr(&Slot,rawImage,4);
151
152 image.vRes=GetLongInfo(&Slot,rawImage);
153 rawImage=IncPtr(&Slot,rawImage,4);
154
155 image.pixelType=GetShortInfo(&Slot,rawImage);
156 rawImage=IncPtr(&Slot,rawImage,2);
157
158 image.pixelSize=GetShortInfo(&Slot,rawImage);
159 rawImage=IncPtr(&Slot,rawImage,2);
160
161
162 }
163 #endif /* main */
164
165 int GetHeader(struct slot *Slot,unsigned long pos)
166 {
167 /* the pos passed in is the pos that the magic testvalue was found at */
168 unsigned char *p;
169 unsigned char *dirBase;
170
171 switch (Slot->size)
172 {
173 case 1: /* char */
174 pos-=14;
175 break;
176 case 2:
177 pos-=28;
178 break;
179 case 4:
180 pos-=56;
181 break;
182 }
183
184 p=(unsigned char *)pos;
185
186 Slot->head.offset=(0xff000000 | (unsigned long) GetLongInfo(Slot,p));
187 p=IncPtr(Slot,p,4);
188
189 Slot->head.length=GetLongInfo(Slot,p);
190 p=IncPtr(Slot,p,4);
191
192 Slot->head.crc=GetLongInfo(Slot,p);
193 p=IncPtr(Slot,p,4);
194
195 Slot->head.romrev=GetByteInfo(Slot,p);
196 p=IncPtr(Slot,p,1);
197
198 Slot->head.format=GetByteInfo(Slot,p);
199 p=IncPtr(Slot,p,1);
200
201 Slot->head.tst=GetLongInfo(Slot,p);
202 p=IncPtr(Slot,p,4);
203
204 Slot->head.reserved=GetByteInfo(Slot,p);
205 p=IncPtr(Slot,p,1);
206
207 /* byte lanes should be used instead of size, this hasn't bitten me yet */
208 Slot->head.bytelane=GetByteInfo(Slot,p);
209 p=IncPtr(Slot,p,1);
210
211 dirBase=(unsigned char *)(pos+Slot->head.offset*Slot->size);
212 GetRsrcs(Slot,dirBase,Slot->mainDir,15);
213 return 0;
214 }
215
216
217 printTree(struct slot *Slot,struct dir *root)
218 {
219 struct dir *b;
220 unsigned char *c;
221 struct dir *d;
222 unsigned char *e;
223 struct dir *f;
224 unsigned char *g;
225 struct dir *h;
226 unsigned char *i;
227 unsigned char *j;
228 unsigned char *k;
229 struct dir bSpace[15];
230 struct dir cSpace[15];
231 struct dir dSpace[15];
232 struct dir fSpace[15];
233 struct dir hSpace[15];
234 char space[40];
235 /* to get a good idea of what is happening here you should get the
236 "slots" program from apple dts, it is so cool. Its the next
237 best thing to actual docs, which i didn't have...
238 */
239
240 b=getRsrcByNum(Slot,root,1,bSpace,15);
241 c=getDataAtRsrc(Slot,b,2);
242 d=getRsrcByNum(Slot,b,0x24,dSpace,15);
243
244 e=getDataAtRsrc(Slot,d,1);
245
246 f=getRsrcByNum(Slot,root,0x80,fSpace,15);
247 g=getDataAtRsrc(Slot,f,2);
248 j=getDataAtRsrc(Slot,f,0x0a);
249 k=getDataAtRsrc(Slot,f,0x0b);
250
251 h=getRsrcByNum(Slot,root,0xa0,hSpace,15);
252 i=getDataAtRsrc(Slot,h,2);
253
254 printf("A\n");
255 print_rsrcinfo(Slot,root);
256
257 printf("B\n");
258 print_rsrcinfo(Slot,b);
259
260 printf("C\n");
261 printf("%s\n",GetStringInfo(Slot,c,space,40));
262
263 printf("D\n");
264 print_rsrcinfo(Slot,d);
265
266 printf("E\n");
267 printf("%s\n",GetStringInfo(Slot,e,space,40));
268
269 printf("F\n");
270 print_rsrcinfo(Slot,f);
271
272
273 printf("g\n");
274 printf("%s\n",GetStringInfo(Slot,g,space,40));
275 printf("Video RAM Base %lx\n", GetLongInfo(Slot,j) );
276 printf("Video RAM Length %lx\n", GetLongInfo(Slot,k) );
277
278 printf("H\n");
279 print_rsrcinfo(Slot,h);
280
281 printf("I\n");
282 printf("%s\n",GetStringInfo(Slot,i,space,40));
283
284 }
285
286
287 print_rsrcinfo(struct slot *Slot,struct dir *p)
288 {
289 int i=0;
290 int failsafe=20;
291
292 if (p==NULL) return 1;
293 while(failsafe--)
294 {
295 printf("RSRC %02x :%06lx\n",p[i].rsrc,p[i].offset);
296 if (p[i].rsrc == 0xff) break;
297 i++;
298 }
299
300 }
301
302 struct dir *getRsrcByNum(struct slot *Slot,struct dir *p,int num,struct dir *out,int max)
303 {
304 int i=0;
305 int failsafe=20;
306 long nextoffset=0;
307 unsigned char *base;
308
309 if (p==NULL) return NULL;
310
311
312 base=getDataAtRsrc(Slot,p,num);
313
314 if (NULL==base) return NULL;
315
316 GetRsrcs(Slot,base,out,max);
317
318 return out;
319 }
320
321 char *GetStringInfo(struct slot *Slot,unsigned char *data,char *space,int len)
322 {
323 int i;
324 char *p=space;
325
326 if (NULL==data) return "";
327
328 for(i=0;(i<len) && *data;i++,p++)
329 {
330 *p=GetByteInfo(Slot,data);
331 data=IncPtr(Slot,data,1);
332 }
333 *p='\0';
334 return space;
335 }
336
337 long GetLongInfo(struct slot *Slot,unsigned char *data)
338 {
339 long ret=0;
340
341 switch (Slot->size)
342 {
343 case 1:
344 ret= (unsigned long)data[0]<<24 | (unsigned long)data[1]<<16 | (unsigned long)data[2]<<8 |data[3] ;
345 break;
346 case 2:
347 ret= (unsigned long)data[0]<<24 | (unsigned long)data[2]<<16 | (unsigned long)data[4]<<8 |data[6] ;
348 break;
349 case 4:
350 ret= (unsigned long)data[0]<<24 | (unsigned long)data[4]<<16 | (unsigned long)data[8]<<8 |data[12] ;
351 break;
352 }
353
354 return ret;
355 }
356
357 short GetShortInfo(struct slot *Slot,unsigned char *data)
358 {
359 short ret;
360
361 switch (Slot->size)
362 {
363 case 1:
364 ret= (unsigned long)data[0]<<8 |data[1] ;
365 break;
366 case 2:
367 ret= (unsigned long)data[0]<<8 |data[2] ;
368 break;
369 case 4:
370 ret= (unsigned long)data[0]<<8 |data[4] ;
371 break;
372 }
373
374 return ret;
375 }
376
377 char GetByteInfo(struct slot *Slot,unsigned char *data)
378 {
379 /* boring .... */
380 return data[0];
381 }
382
383
384 int FindMagic(unsigned long data[])
385 {
386 unsigned short *data2=(unsigned short *)data;
387 unsigned char *data3=(unsigned char *)data;
388
389
390 /* char data */
391 if (((data3[0] )== 0x5a) &&
392 ((data3[1] )== 0x93) &&
393 ((data3[2] )== 0x2b) &&
394 ((data3[3] )== 0xc7) )
395 return 1;
396
397 /* short data */
398
399 if (((data3[0] )== 0x5a) &&
400 ((data3[2] )== 0x93) &&
401 ((data3[4] )== 0x2b) &&
402 ((data3[6] )== 0xc7) )
403 return 2;
404
405 /* long data */
406 if (((data3[0] )== 0x5a) &&
407 ((data3[4] )== 0x93) &&
408 ((data3[8] )== 0x2b) &&
409 ((data3[12] )== 0xc7) )
410 return 4;
411
412
413 return 0;
414 }
415
416 unsigned char *IncPtr(struct slot *Slot,unsigned char *p,int size)
417 {
418 /* MF make this a macro someday */
419
420 unsigned char *tmp=p;
421
422 tmp=tmp+size*Slot->size;
423
424 return tmp;
425
426 }
427
428 int GetRsrcs(struct slot *Slot,unsigned char *p,struct dir *Dir,int maxdir)
429 {
430 int i=0;
431 /* MF if you alias memory here you will be fucked. */
432
433 if (p==NULL) return 1;
434
435 while(maxdir--)
436 {
437 long entry;
438
439 entry=GetLongInfo(Slot,p);
440
441 Dir[i].rsrc=(entry & 0xff000000) >> 24;
442 Dir[i].offset=entry & 0x00ffffff;
443 Dir[i].base=(unsigned long)p;
444 p=IncPtr(Slot,p,4);
445 if (Dir[i].rsrc==0xff)
446 break;
447 i++;
448 }
449
450 return 0;
451 }
452
453 unsigned char *getDataAtRsrc(struct slot *Slot,struct dir *p,int num)
454 {
455 int i=0;
456 int failsafe=num;
457 long nextoffset=0;
458 unsigned char *base;
459
460 if (p==NULL) return NULL;
461
462 while(failsafe--)
463 {
464 if (p[i].rsrc==num)
465 {
466 base= (unsigned char *)( (unsigned long)Slot->size*p[i].offset+
467 (unsigned long)p[i].base );
468 return base;
469 }
470 if (p[i].rsrc==0xff) return NULL;
471 i++;
472 }
473
474
475
476 return NULL;
477 }
478
479
480 int InitNubusSlot(unsigned long slotaddr,struct slot *newSlot)
481 {
482 int i=0;
483 struct slot Slot;
484 struct dir *b;
485 struct dir bSpace[5];
486 struct dir *d;
487 struct dir dSpace[5];
488 struct dir *f;
489 struct dir fSpace[5];
490 unsigned char *c;
491 unsigned char *e;
492 unsigned char *g;
493
494 unsigned long slotend;
495
496
497
498 slotend=slotaddr+NBMEMSIZE-1;
499
500 for(i=5;i<100;i++)
501 {
502 /* lets be quite clear here, if magic is not on the card, then
503 we will quite likely bus error, because we will read a long
504 word when there are only 3 bytes left on the card, unless
505 there is a card in the next slot that has readable memory starting
506 at 0, so more than likely we crash, ohh well.
507
508 The other day I heard (read) that the directory and the rest of
509 the card can be in different formats, to this I say FUCK! So
510 for the time being I will just assume the whole card is in the
511 same format, and let it crash most heiniously on bizzare cards
512 from hell, which I hear has lots of luke warm fresca on tap.
513 */
514 if (Slot.size=FindMagic( (unsigned long *)(slotend-i) ) )
515 {
516 GetHeader(&Slot,slotend-i);
517 break;
518 }
519 }
520
521 /* ohh ohh Mexico, i've never really been, but I'd sure like to go */
522 if (Slot.size)
523 {
524 b=getRsrcByNum(&Slot,Slot.mainDir,1,bSpace,5);
525 c=getDataAtRsrc(&Slot,b,2);
526 d=getRsrcByNum(&Slot,b,0x24,dSpace,5);
527 e=getDataAtRsrc(&Slot,d,1);
528 f=getRsrcByNum(&Slot,Slot.mainDir,0x80,fSpace,5);
529 g=getDataAtRsrc(&Slot,f,1);
530 GetStringInfo(&Slot,c,Slot.name,40);
531 /* printf("card is %s, ",Slot.name); */
532 GetStringInfo(&Slot,e,Slot.manufacturer,40);
533 /* printf("%s\n",Slot.manufacturer); */
534 /* info here is two long words (cat,type,drvrsw,drvrhw) */
535 Slot.type=(GetLongInfo(&Slot,g) & 0xffff0000) >> 16;
536 /* printf("type is %x\n",Slot.type); */
537
538 /* sounds so simple with the sun sinking low */
539
540 }
541 else
542 return 1;
543 /* this comment intentionally left meaningless */
544
545 *newSlot=Slot;
546 return 0;
547 }
548
549 struct imagedata *NUBUS_GetImageData(struct slot *Slot,
550 struct imagedata *Rimage)
551 {
552 struct imagedata image;
553 struct dir *Dir;
554 struct dir dirSpace[10];
555 struct dir dirSpace2[10];
556 unsigned char *rawImage;
557
558
559 Dir=getRsrcByNum(Slot,Slot->mainDir,128,dirSpace,10);
560 Dir=getRsrcByNum(Slot,Dir,128,dirSpace2,10);
561
562 rawImage=getDataAtRsrc(Slot,Dir,1);
563
564 /* this is self documenting code, WHAT THE HELL IS THIS? */
565 image.whatTheHellIsThis=GetLongInfo(Slot,rawImage);
566 rawImage=IncPtr(Slot,rawImage,4);
567
568 image.offset=GetLongInfo(Slot,rawImage);
569 rawImage=IncPtr(Slot,rawImage,4);
570
571 image.rowbytes=GetShortInfo(Slot,rawImage);
572 rawImage=IncPtr(Slot,rawImage,2);
573
574 image.top=GetShortInfo(Slot,rawImage);
575 rawImage=IncPtr(Slot,rawImage,2);
576
577 image.left=GetShortInfo(Slot,rawImage);
578 rawImage=IncPtr(Slot,rawImage,2);
579
580 image.bottom=GetShortInfo(Slot,rawImage);
581 rawImage=IncPtr(Slot,rawImage,2);
582
583 image.right=GetShortInfo(Slot,rawImage);
584 rawImage=IncPtr(Slot,rawImage,2);
585
586 image.version=GetShortInfo(Slot,rawImage);
587 rawImage=IncPtr(Slot,rawImage,2);
588
589 image.packType=GetShortInfo(Slot,rawImage);
590 rawImage=IncPtr(Slot,rawImage,2);
591
592 image.packSize=GetShortInfo(Slot,rawImage);
593 rawImage=IncPtr(Slot,rawImage,2);
594
595 image.hRes=GetLongInfo(Slot,rawImage);
596 rawImage=IncPtr(Slot,rawImage,4);
597
598 image.vRes=GetLongInfo(Slot,rawImage);
599 rawImage=IncPtr(Slot,rawImage,4);
600
601 image.pixelType=GetShortInfo(Slot,rawImage);
602 rawImage=IncPtr(Slot,rawImage,2);
603
604 image.pixelSize=GetShortInfo(Slot,rawImage);
605 rawImage=IncPtr(Slot,rawImage,2);
606
607 *Rimage=image;
608
609 return Rimage;
610 }
611
612 struct nubus_hw nubus_table[NUBUS_MAXSLOTS];
613
614 extern int
615 nubus_addr_to_slot(caddr_t addr)
616 {
617 int nubus_num;
618
619 for (nubus_num = 0 ; nubus_num < NUBUS_MAXSLOTS ; nubus_num++)
620 if (nubus_table[nubus_num].addr == addr)
621 return nubus_num;
622 return -1;
623 }
624
625 static void
626 find_nubus(void)
627 {
628 /* This functions sets up the array "nubus_table" which contains the
629 basic information about each card in the Nubus slot. When device
630 drivers are initialized later, they can look through this array to
631 see if their hardware is present and claim it. */
632
633 extern unsigned long NuBusBase;
634 register struct nubus_hw *nu;
635 int nubus_num;
636
637 for (nubus_num = 0; nubus_num < NUBUS_MAXSLOTS; nubus_num++)
638 nubus_table[nubus_num].found = 0; /* Empty */
639
640 /* LAK: For now we can only check 9..F because that's all we map
641 in locore.s. Eventually (i.e. near future) we should put THIS
642 function in locore.s before enabling the MMU and only map the
643 slots that have a card in them. Also, the next loop should go from
644 1 to 0xF inclusive (0 is "reserved") to cover all possible hardware.
645 Even if the MacII only has 9..F, it won't hurt us to probe 1..8 also. */
646 for (nubus_num = 0; nubus_num < 6; nubus_num++)
647 {
648 nu = nubus_table + nubus_num + 9;
649 nu->addr = (caddr_t)(NuBusBase + nubus_num * NBMEMSIZE);
650 nu->rom = nu->addr + NBROMOFFSET;
651
652 if(!badbaddr(nu->addr+NBMEMSIZE-1))
653 {
654 InitNubusSlot((unsigned long) nu->addr, &(nu->Slot));
655
656 nu->found = 1;
657 nu->claimed = 0; /* No driver has claimed this slot yet */
658
659 }
660 }
661 }
662
663 static int
664 nubus_print(aux, name)
665 void *aux;
666 char *name;
667 {
668 struct nubus_hw *nu = (struct nubus_hw *) aux;
669 int i;
670
671 if (name) {
672 i = nu - nubus_table;
673 printf ("%s: s:%d t:%d \"",
674 name, i, nu->Slot.type);
675 printf ("%s, ",nu->Slot.name);
676 printf ("%s\"",nu->Slot.manufacturer);
677 }
678 return(UNCONF);
679 }
680
681 static void
682 nubus_attach(parent, self, aux)
683 struct device *parent, *self;
684 void *aux;
685 {
686 register struct nubus_hw *nu;
687 int i;
688
689 printf("\n");
690
691 find_nubus();
692
693 for (i = 0; i < 6; i++) {
694 nu = nubus_table + i + 9;
695
696 if (!nu->found)
697 continue;
698
699 if (config_found(self, nu, nubus_print))
700 nu->claimed = 1;
701 }
702 }
703
704 extern int matchbyname();
705
706 struct cfdriver nubuscd =
707 { NULL, "nubus", matchbyname, nubus_attach,
708 DV_DULL, sizeof(struct device), 1, 0 };
709