2 * SBUS bus-specific code.
4 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #ifdef HAVE_XORG_CONFIG_H
25 #include <xorg-config.h>
35 #include "xf86_OSlib.h"
40 #include "xf86sbusBus.h"
43 Bool sbusSlotClaimed
= FALSE
;
45 static int xf86nSbusInfo
;
48 CheckSbusDevice(const char *device
, int fbNum
)
51 struct fbgattr fbattr
;
54 fd
= open(device
, O_RDONLY
, 0);
57 memset(&fbattr
, 0, sizeof(fbattr
));
58 if (ioctl(fd
, FBIOGATTR
, &fbattr
) < 0) {
59 if (ioctl(fd
, FBIOGTYPE
, &fbattr
.fbtype
) < 0) {
65 for (i
= 0; sbusDeviceTable
[i
].devId
; i
++)
66 if (sbusDeviceTable
[i
].fbType
== fbattr
.fbtype
.fb_type
)
68 if (!sbusDeviceTable
[i
].devId
)
71 xnfrealloc(xf86SbusInfo
, sizeof(psdp
) * (++xf86nSbusInfo
+ 1));
72 xf86SbusInfo
[xf86nSbusInfo
] = NULL
;
73 xf86SbusInfo
[xf86nSbusInfo
- 1] = psdp
= xnfcalloc(sizeof(sbusDevice
), 1);
74 psdp
->devId
= sbusDeviceTable
[i
].devId
;
76 psdp
->device
= xnfstrdup(device
);
77 psdp
->width
= fbattr
.fbtype
.fb_width
;
78 psdp
->height
= fbattr
.fbtype
.fb_height
;
87 sbusDevicePtr psdp
, *psdpp
;
89 xf86SbusInfo
= malloc(sizeof(psdp
));
91 for (i
= 0; i
< 32; i
++) {
92 snprintf(fbDevName
, sizeof(fbDevName
), "/dev/fb%d", i
);
93 CheckSbusDevice(fbDevName
, i
);
95 if (sparcPromInit() >= 0) {
97 sparcPromAssignNodes();
99 for (psdpp
= xf86SbusInfo
; (psdp
= *psdpp
); psdpp
++) {
100 for (i
= 0; sbusDeviceTable
[i
].devId
; i
++)
101 if (sbusDeviceTable
[i
].devId
== psdp
->devId
)
102 psdp
->descr
= sbusDeviceTable
[i
].descr
;
104 * If we can use PROM information and found the PROM node for this
105 * device, we can tell more about the card.
107 if (useProm
&& psdp
->node
.node
) {
108 char *prop
, *promPath
;
109 int len
, chiprev
, vmsize
;
111 switch (psdp
->devId
) {
112 case SBUS_DEVICE_MGX
:
113 prop
= sparcPromGetProperty(&psdp
->node
, "fb_size", &len
);
114 if (prop
&& len
== 4 && *(int *) prop
== 0x400000)
115 psdp
->descr
= "Quantum 3D MGXplus with 4M VRAM";
117 case SBUS_DEVICE_CG6
:
120 prop
= sparcPromGetProperty(&psdp
->node
, "chiprev", &len
);
121 if (prop
&& len
== 4)
122 chiprev
= *(int *) prop
;
123 prop
= sparcPromGetProperty(&psdp
->node
, "vmsize", &len
);
124 if (prop
&& len
== 4)
125 vmsize
= *(int *) prop
;
131 psdp
->descr
= "Sun Double width GX";
138 psdp
->descr
= "Sun Single width GX";
143 psdp
->descr
= "Sun Turbo GX with 1M VSIMM";
146 psdp
->descr
= "Sun Turbo GX Plus";
149 psdp
->descr
= "Sun Turbo GX";
154 case SBUS_DEVICE_CG14
:
155 prop
= sparcPromGetProperty(&psdp
->node
, "reg", &len
);
157 if (prop
&& !(len
% 12) && len
> 0)
158 vmsize
= *(int *) (prop
+ len
- 4);
161 psdp
->descr
= "Sun SX with 4M VSIMM";
164 psdp
->descr
= "Sun SX with 8M VSIMM";
168 case SBUS_DEVICE_LEO
:
169 prop
= sparcPromGetProperty(&psdp
->node
, "model", &len
);
170 if (prop
&& len
> 0 && !strstr(prop
, "501-2503"))
171 psdp
->descr
= "Sun Turbo ZX";
173 case SBUS_DEVICE_TCX
:
174 if (sparcPromGetBool(&psdp
->node
, "tcx-8-bit"))
175 psdp
->descr
= "Sun TCX (8bit)";
177 psdp
->descr
= "Sun TCX (S24)";
179 case SBUS_DEVICE_FFB
:
180 prop
= sparcPromGetProperty(&psdp
->node
, "name", &len
);
182 prop
= sparcPromGetProperty(&psdp
->node
, "board_type", &len
);
183 if (prop
&& len
== 4)
184 chiprev
= *(int *) prop
;
185 if (strstr(prop
, "afb")) {
187 psdp
->descr
= "Sun|Elite3D-M6 Horizontal";
192 psdp
->descr
= "Sun FFB 67MHz Creator";
195 psdp
->descr
= "Sun FFB 67MHz Creator 3D";
198 psdp
->descr
= "Sun FFB 75MHz Creator 3D";
202 psdp
->descr
= "Sun FFB2 Vertical Creator";
206 psdp
->descr
= "Sun FFB2 Vertical Creator 3D";
209 psdp
->descr
= "Sun FFB2+ Vertical Creator";
212 psdp
->descr
= "Sun FFB2+ Vertical Creator 3D";
216 psdp
->descr
= "Sun FFB2 Horizontal Creator";
220 psdp
->descr
= "Sun FFB2 Horizontal Creator 3D";
227 xf86Msg(X_PROBED
, "SBUS:(0x%08x) %s", psdp
->node
.node
, psdp
->descr
);
228 promPath
= sparcPromNode2Pathname(&psdp
->node
);
230 xf86ErrorF(" at %s", promPath
);
235 xf86Msg(X_PROBED
, "SBUS: %s", psdp
->descr
);
243 * Parse a BUS ID string, and return the SBUS bus parameters if it was
244 * in the correct format for a SBUS bus id.
248 xf86ParseSbusBusString(const char *busID
, int *fbNum
)
251 * The format is assumed to be one of:
252 * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN
253 * "nameN", e.g. "cgsix0", which means Nth instance of card NAME
254 * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname
261 if (StringToBusType(busID
, &id
) != BUS_SBUS
)
265 if (!strncmp(id
, "fb", 2)) {
268 *fbNum
= atoi(id
+ 2);
272 sbusDevicePtr
*psdpp
;
275 for (i
= 0, len
= 0; sbusDeviceTable
[i
].devId
; i
++) {
276 len
= strlen(sbusDeviceTable
[i
].promName
);
277 if (!strncmp(sbusDeviceTable
[i
].promName
, id
, len
)
281 devId
= sbusDeviceTable
[i
].devId
;
285 for (psdpp
= xf86SbusInfo
; *psdpp
; ++psdpp
) {
286 if ((*psdpp
)->devId
!= devId
)
289 *fbNum
= (*psdpp
)->fbNum
;
298 if (sparcPromInit() >= 0) {
299 i
= sparcPromPathname2Node(id
);
302 sbusDevicePtr
*psdpp
;
304 for (psdpp
= xf86SbusInfo
; *psdpp
; ++psdpp
) {
305 if ((*psdpp
)->node
.node
== i
) {
306 *fbNum
= (*psdpp
)->fbNum
;
316 * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match.
320 xf86CompareSbusBusString(const char *busID
, int fbNum
)
324 if (xf86ParseSbusBusString(busID
, &iFbNum
)) {
325 return fbNum
== iFbNum
;
333 * Check if the slot requested is free. If it is already in use, return FALSE.
337 xf86CheckSbusSlot(int fbNum
)
342 for (i
= 0; i
< xf86NumEntities
; i
++) {
344 /* Check if this SBUS slot is taken */
345 if (p
->bus
.type
== BUS_SBUS
&& p
->bus
.id
.sbus
.fbNum
== fbNum
)
353 * If the slot requested is already in use, return -1.
354 * Otherwise, claim the slot for the screen requesting it.
358 xf86ClaimSbusSlot(sbusDevicePtr psdp
, DriverPtr drvp
, GDevPtr dev
, Bool active
)
364 if (xf86CheckSbusSlot(psdp
->fbNum
)) {
365 num
= xf86AllocateEntity();
366 p
= xf86Entities
[num
];
369 p
->bus
.type
= BUS_SBUS
;
370 xf86AddDevToEntity(num
, dev
);
371 p
->bus
.id
.sbus
.fbNum
= psdp
->fbNum
;
374 sbusSlotClaimed
= TRUE
;
382 xf86MatchSbusInstances(const char *driverName
, int sbusDevId
,
383 GDevPtr
* devList
, int numDevs
, DriverPtr drvp
,
387 sbusDevicePtr psdp
, *psdpp
;
388 int numClaimedInstances
= 0;
389 int allocatedInstances
= 0;
391 GDevPtr devBus
= NULL
;
393 int *retEntities
= NULL
;
399 Bool claimed
; /* BusID matches with a device section */
402 *foundEntities
= NULL
;
403 for (psdpp
= xf86SbusInfo
, psdp
= *psdpp
; psdp
; psdp
= *++psdpp
) {
404 if (psdp
->devId
!= sbusDevId
)
408 ++allocatedInstances
;
409 instances
= xnfrealloc(instances
,
410 allocatedInstances
* sizeof(struct Inst
));
411 instances
[allocatedInstances
- 1].sbus
= psdp
;
412 instances
[allocatedInstances
- 1].dev
= NULL
;
413 instances
[allocatedInstances
- 1].claimed
= FALSE
;
418 * This may be debatable, but if no SBUS devices with a matching vendor
419 * type is found, return zero now. It is probably not desirable to
420 * allow the config file to override this.
422 if (allocatedInstances
<= 0) {
427 if (sparcPromInit() >= 0)
430 if (xf86DoConfigure
&& xf86DoConfigurePass1
) {
434 for (i
= 0; i
< allocatedInstances
; i
++) {
436 pGDev
= xf86AddBusDeviceToConfigure(drvp
->driverName
, BUS_SBUS
,
437 instances
[i
].sbus
, -1);
440 * XF86Match???Instances() treat chipID and chipRev as
441 * overrides, so clobber them here.
443 pGDev
->chipID
= pGDev
->chipRev
= -1;
452 DebugF("%s instances found: %d\n", driverName
, allocatedInstances
);
454 for (i
= 0; i
< allocatedInstances
; i
++) {
455 char *promPath
= NULL
;
457 psdp
= instances
[i
].sbus
;
460 if (useProm
&& psdp
->node
.node
)
461 promPath
= sparcPromNode2Pathname(&psdp
->node
);
463 for (j
= 0; j
< numDevs
; j
++) {
464 if (devList
[j
]->busID
&& *devList
[j
]->busID
) {
465 if (xf86CompareSbusBusString(devList
[j
]->busID
, psdp
->fbNum
)) {
467 xf86MsgVerb(X_WARNING
, 0,
468 "%s: More than one matching Device section for "
469 "instance (BusID: %s) found: %s\n",
470 driverName
, devList
[j
]->identifier
,
477 if (!dev
&& !devBus
) {
480 "Assigning device section with no busID to SBUS:%s\n",
484 "Assigning device section with no busID to SBUS:fb%d\n",
489 xf86MsgVerb(X_WARNING
, 0,
490 "%s: More than one matching Device section "
491 "found: %s\n", driverName
,
492 devList
[j
]->identifier
);
496 dev
= devBus
; /* busID preferred */
497 if (!dev
&& psdp
->fd
!= -2) {
499 xf86MsgVerb(X_WARNING
, 0, "%s: No matching Device section "
500 "for instance (BusID SBUS:%s) found\n",
501 driverName
, promPath
);
504 xf86MsgVerb(X_WARNING
, 0, "%s: No matching Device section "
505 "for instance (BusID SBUS:fb%d) found\n",
506 driverName
, psdp
->fbNum
);
509 numClaimedInstances
++;
510 instances
[i
].claimed
= TRUE
;
511 instances
[i
].dev
= dev
;
516 DebugF("%s instances found: %d\n", driverName
, numClaimedInstances
);
519 * Of the claimed instances, check that another driver hasn't already
523 for (i
= 0; i
< allocatedInstances
&& numClaimedInstances
> 0; i
++) {
524 if (!instances
[i
].claimed
)
526 psdp
= instances
[i
].sbus
;
527 if (!xf86CheckSbusSlot(psdp
->fbNum
))
530 DebugF("%s: card at fb%d %08x is claimed by a Device section\n",
531 driverName
, psdp
->fbNum
, psdp
->node
.node
);
533 /* Allocate an entry in the lists to be returned */
535 retEntities
= xnfrealloc(retEntities
, numFound
* sizeof(int));
536 retEntities
[numFound
- 1]
537 = xf86ClaimSbusSlot(psdp
, drvp
, instances
[i
].dev
,
538 instances
[i
].dev
->active
? TRUE
: FALSE
);
542 *foundEntities
= retEntities
;
552 * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity.
555 xf86GetSbusInfoForEntity(int entityIndex
)
557 sbusDevicePtr
*psdpp
;
558 EntityPtr p
= xf86Entities
[entityIndex
];
560 if (entityIndex
>= xf86NumEntities
|| p
->bus
.type
!= BUS_SBUS
)
563 for (psdpp
= xf86SbusInfo
; *psdpp
!= NULL
; psdpp
++) {
564 if (p
->bus
.id
.sbus
.fbNum
== (*psdpp
)->fbNum
)
571 xf86GetEntityForSbusInfo(sbusDevicePtr psdp
)
575 for (i
= 0; i
< xf86NumEntities
; i
++) {
576 EntityPtr p
= xf86Entities
[i
];
578 if (p
->bus
.type
!= BUS_SBUS
)
581 if (p
->bus
.id
.sbus
.fbNum
== psdp
->fbNum
)
588 xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn
, sbusDevicePtr psdp
)
592 mode
= xnfcalloc(sizeof(DisplayModeRec
), 1);
593 mode
->name
= "current";
596 mode
->type
= M_T_BUILTIN
;
597 mode
->Clock
= 100000000;
598 mode
->HDisplay
= psdp
->width
;
599 mode
->HSyncStart
= psdp
->width
;
600 mode
->HSyncEnd
= psdp
->width
;
601 mode
->HTotal
= psdp
->width
;
602 mode
->VDisplay
= psdp
->height
;
603 mode
->VSyncStart
= psdp
->height
;
604 mode
->VSyncEnd
= psdp
->height
;
605 mode
->VTotal
= psdp
->height
;
606 mode
->SynthClock
= mode
->Clock
;
607 mode
->CrtcHDisplay
= mode
->HDisplay
;
608 mode
->CrtcHSyncStart
= mode
->HSyncStart
;
609 mode
->CrtcHSyncEnd
= mode
->HSyncEnd
;
610 mode
->CrtcHTotal
= mode
->HTotal
;
611 mode
->CrtcVDisplay
= mode
->VDisplay
;
612 mode
->CrtcVSyncStart
= mode
->VSyncStart
;
613 mode
->CrtcVSyncEnd
= mode
->VSyncEnd
;
614 mode
->CrtcVTotal
= mode
->VTotal
;
615 mode
->CrtcHAdjusted
= FALSE
;
616 mode
->CrtcVAdjusted
= FALSE
;
618 pScrn
->virtualX
= psdp
->width
;
619 pScrn
->virtualY
= psdp
->height
;
622 static DevPrivateKeyRec sbusPaletteKeyRec
;
623 #define sbusPaletteKey (&sbusPaletteKeyRec)
625 typedef struct _sbusCmap
{
627 CloseScreenProcPtr CloseScreen
;
629 unsigned char origRed
[16];
630 unsigned char origGreen
[16];
631 unsigned char origBlue
[16];
632 } sbusCmapRec
, *sbusCmapPtr
;
634 #define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \
635 dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey))
638 xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn
, int numColors
, int *indices
,
639 LOCO
* colors
, VisualPtr pVisual
)
643 struct fbcmap fbcmap
;
646 cmap
= SBUSCMAPPTR(pScrn
->pScreen
);
650 fbcmap
.index
= indices
[0];
651 fbcmap
.red
= data
= malloc(numColors
* 3);
654 fbcmap
.green
= data
+ numColors
;
655 fbcmap
.blue
= fbcmap
.green
+ numColors
;
656 for (i
= 0; i
< numColors
; i
++) {
658 if (fbcmap
.count
&& index
!= fbcmap
.index
+ fbcmap
.count
) {
659 ioctl(cmap
->psdp
->fd
, FBIOPUTCMAP
, &fbcmap
);
661 fbcmap
.index
= index
;
663 fbcmap
.red
[fbcmap
.count
] = colors
[index
].red
;
664 fbcmap
.green
[fbcmap
.count
] = colors
[index
].green
;
665 fbcmap
.blue
[fbcmap
.count
++] = colors
[index
].blue
;
667 ioctl(cmap
->psdp
->fd
, FBIOPUTCMAP
, &fbcmap
);
672 xf86SbusCmapCloseScreen(ScreenPtr pScreen
)
675 struct fbcmap fbcmap
;
677 cmap
= SBUSCMAPPTR(pScreen
);
678 if (cmap
->origCmapValid
) {
681 fbcmap
.red
= cmap
->origRed
;
682 fbcmap
.green
= cmap
->origGreen
;
683 fbcmap
.blue
= cmap
->origBlue
;
684 ioctl(cmap
->psdp
->fd
, FBIOPUTCMAP
, &fbcmap
);
686 pScreen
->CloseScreen
= cmap
->CloseScreen
;
688 return (*pScreen
->CloseScreen
) (pScreen
);
692 xf86SbusHandleColormaps(ScreenPtr pScreen
, sbusDevicePtr psdp
)
695 struct fbcmap fbcmap
;
696 unsigned char data
[2];
698 if (!dixRegisterPrivateKey(sbusPaletteKey
, PRIVATE_SCREEN
, 0))
699 FatalError("Cannot register sbus private key");
701 cmap
= xnfcalloc(1, sizeof(sbusCmapRec
));
702 dixSetPrivate(&pScreen
->devPrivates
, sbusPaletteKey
, cmap
);
706 fbcmap
.red
= cmap
->origRed
;
707 fbcmap
.green
= cmap
->origGreen
;
708 fbcmap
.blue
= cmap
->origBlue
;
709 if (ioctl(psdp
->fd
, FBIOGETCMAP
, &fbcmap
) >= 0)
710 cmap
->origCmapValid
= TRUE
;
716 if (pScreen
->whitePixel
== 0) {
724 ioctl(psdp
->fd
, FBIOPUTCMAP
, &fbcmap
);
725 cmap
->CloseScreen
= pScreen
->CloseScreen
;
726 pScreen
->CloseScreen
= xf86SbusCmapCloseScreen
;
727 return xf86HandleColormaps(pScreen
, 256, 8,
728 xf86SbusCmapLoadPalette
, NULL
, 0);
732 xf86SbusConfigure(void *busData
, sbusDevicePtr sBus
)
734 if (sBus
&& sBus
->fbNum
== ((sbusDevicePtr
) busData
)->fbNum
)
740 xf86SbusConfigureNewDev(void *busData
, sbusDevicePtr sBus
, GDevRec
* GDev
)
742 char *promPath
= NULL
;
744 sBus
= (sbusDevicePtr
) busData
;
745 GDev
->identifier
= sBus
->descr
;
746 if (sparcPromInit() >= 0) {
747 promPath
= sparcPromNode2Pathname(&sBus
->node
);
751 XNFasprintf(&GDev
->busID
, "SBUS:%s", promPath
);
755 XNFasprintf(&GDev
->busID
, "SBUS:fb%d", sBus
->fbNum
);