#!/usr/bin/python -tt import os import fcntl import struct from ctypes import * CLASS_UNSPEC, CLASS_OTHER, CLASS_NETWORK, CLASS_SCSI, CLASS_MOUSE, \ CLASS_AUDIO, CLASS_VIDEO = range(7) OPROMMAXPARAM = 4096 # /* Maximum size of oprom_array. */ OPROMGETOPT = 0x20004F01 OPROMSETOPT = 0x20004F02 OPROMNXTOPT = 0x20004F03 OPROMSETOPT2 = 0x20004F04 OPROMNEXT = 0x20004F05 OPROMCHILD = 0x20004F06 OPROMGETPROP = 0x20004F07 OPROMNXTPROP = 0x20004F08 OPROMU2P = 0x20004F09 OPROMGETCONS = 0x20004F0A OPROMGETFBNAME = 0x20004F0B OPROMGETBOOTARGS = 0x20004F0C # Linux extensions # Arguments in oprom_array: OPROMSETCUR = 0x20004FF0 # int node - Sets current node OPROMPCI2NODE = 0x20004FF1 # int pci_bus, pci_devfn - Sets current node to PCI device's node OPROMPATH2NODE = 0x20004FF2 # char path[] - Set current node from fully qualified PROM path MAX_VAL = 4096-128-4 #class OpenPromIO(Structure): # """ struct openpromio # { # u_int oprom_size; /* Actual size of the oprom_array. */ # char oprom_array[1]; /* Holds property names and values. */ # }; # """ # _fields_ = [ # ('oprom_size', c_uint), # # FIXME: this is not right... # #('oprom_array', c_char_p) # ('oprom_array', POINTER(c_int)) # ] # #openpromio = OpenPromIO() from decorator import decorator @decorator def trace(f, *args, **kw): r = None try: r = f(*args, **kw) finally: print "%s(%s, %s) = %s" % (f.func_name, str(args[1:])[1:-2], kw, r) return r class OpenProm(object): dev = '/dev/openprom' def __init__(self): self.promfd = open(self.dev) @trace def get_sibling(self, node): """ static int prom_getsibling(int node) { DECL_OP(sizeof(int)); if (node == -1) return 0; *(int *)op->oprom_array = node; if (ioctl (promfd, OPROMNEXT, op) < 0) return 0; prom_current_node = *(int *)op->oprom_array; return *(int *)op->oprom_array; } """ if node == -1: print "Invalid sibling requested" return 0 args = struct.pack('II', sizeof(c_int), node) print "ioctl(%r, %s, %r)" % (self.promfd, 'OPROMNEXT', args) result = fcntl.ioctl(self.promfd, OPROMNEXT, args) oprom_size, oprom_array = struct.unpack('II', result) assert oprom_size == 4 assert oprom_array return oprom_array @trace def get_property(self, prop): """ static char *prom_getproperty(char *prop, int *lenp) { DECL_OP(MAX_VAL); strcpy (op->oprom_array, prop); if (ioctl (promfd, OPROMGETPROP, op) < 0) return 0; if (lenp) *lenp = op->oprom_size; return op->oprom_array; } """ args = struct.pack('I%ds' % len(prop), MAX_VAL, prop) print "ioctl(%r, %s, %r)" % (self.promfd, 'OPROMGETPROP', args) results = fcntl.ioctl(self.promfd, OPROMGETPROP, args) print "results = %r" % results oprom_size, oprom_array = struct.unpack('I%ds' % len(prop), results) return oprom_size, oprom_array @trace def get_child(self, node): if node in (None, -1): print "Invalid child requested" return None args = struct.pack('II', sizeof(c_int), node) print "ioctl(%r, %s, %r)" % (self.promfd, 'OPROMCHILD', args) results = fcntl.ioctl(self.promfd, OPROMCHILD, args) oprom_size, oprom_array = struct.unpack('II', results) print "oprom_size =", oprom_size print "oprom_array =", oprom_array return oprom_array @trace def walk(self, node, sbus, ebus, probe_class, devlist): nsbus = sbus nebus = ebus type = None port = None module = None dev_class = CLASS_UNSPEC; depth = -1 width = 1152 height = 900 freq = 0 sense = -1 size, prop = self.get_property('device_type') print "size = %r, prop = %r" % (size, prop) if size <= 0: prop = None while probe_class in (CLASS_NETWORK, CLASS_UNSPEC): if not prop or prop != 'network': break size, prop = self.get_property('name') if not prop or size <= 0: size, prop = self.get_property('device_type') break # umm, do we need to do this?? # while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') prop++; if not sbus: print "no sbus; skipping..." size, prop = self.get_property('device_type') break if prop == 'hme': type = "Sun Happy Meal Ethernet" module = "sunhme" dev_class = CLASS_NETWORK elif prop == 'le': type = "Sun Lance Ethernet" module = "sunlance" dev_class = CLASS_NETWORK elif prop == 'qe': size, prop = self.get_property('channel#') if prop and size == 4 and prop[0]: print "TODO: goto next" type = "Sun Quad Ethernet" module = "sunqe" dev_class = CLASS_NETWORK elif prop in ('mlanai', 'myri'): type = "MyriCOM MyriNET Gigabit Ethernet" module = "myri_sbus" dev_class = CLASS_NETWORK size, prop = self.get_property('device_type') break while probe_class in (CLASS_SCSI, CLASS_UNSPEC): is_scsi = prop == 'scsi' size, prop = self.get_property('name') if not prop or size <= 0: print "no prop or size..." size, prop = self.get_property('device_type') break #while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') prop++; if not sbus: print "no sbus.. breaking" size, prop = self.get_property('device_type') break if not is_scsi and prop == 'soc' and prop == 'socal': print "soc/socal" size, prop = self.get_property('device_type') break print "Probing SCSI devices" if prop == 'soc': type = "Sun SPARCStorage Array" module = "fc4:soc:pluto" dev_class = CLASS_SCSI elif prop == 'socal': type = "Sun Enterprise Network Array" module = "fc4:socal:fcal" dev_class = CLASS_SCSI elif prop == 'esp': type = "Sun Enhanced SCSI Processor (ESP)" module = "esp" dev_class = CLASS_SCSI elif prop == 'fas': type = "Sun Swift (ESP)" module = "esp" dev_class = CLASS_SCSI elif prop == 'ptisp': type = "Performance Technologies ISP" module = "qlogicpti" dev_class = CLASS_SCSI elif prop == 'isp': type = "QLogic ISP" module = "qlogicpti" dev_class = CLASS_SCSI size, prop = self.get_property('device_type') while probe_class in (CLASS_AUDIO, CLASS_UNSPEC): size, prop = self.get_property('name') if not prop or size <= 0: print "no prop" size, prop = self.get_property('device_type') break if ',' in prop: print "Splitting up by comma" prop = prop.split(',')[1] print "prop =", prop if prop == 'audio': type = "AMD7930" module = "amd7930" dev_class = CLASS_AUDIO elif prop == 'CS4231': if ebus: type = "CS4231 EB2 DMA (PCI)" else: type = "CS4231 APC DMA (SBUS)" module = "cs4231" dev_class = CLASS_AUDIO elif prop == 'DBRIe': type = "SS10/SS20 DBRI" module = "dbri" dev_class = CLASS_AUDIO size, prop = self.get_property('device_type') break while probe_class in (CLASS_VIDEO, CLASS_UNSPEC): if not prop or prop != 'display': print "prop not a display" break size, prop = self.get_property('name') if not prop or size <= 0: print "no prop" size, prop = self.get_property('device_type') break print "Probing video devices..." #while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') prop++; if not sbus and prop not in ('ffb', 'afb', 'cgfourteen'): print "not ffb, afb, cgfourteen, etc..." size, prop = self.get_property('device_type') break if prop == "bwtwo": type = "Sun Monochrome (bwtwo)" depth = 1 elif prop == "cgthree": type = "Sun Color3 (cgthree)" depth = 8 elif prop == "cgeight": type = "Sun CG8/RasterOps" depth = 8 elif prop == "cgtwelve": type = "Sun GS (cgtwelve)" depth = 24 elif prop == "gt": type = "Sun Graphics Tower" depth = 24 elif prop == "mgx": size, prop = self.get_property("fb_size"); if prop and size == 4 and prop == 0x400000: type = "Quantum 3D MGXplus with 4M VRAM" else: type = "Quantum 3D MGXplus" depth = 24 elif prop == "cgsix": chiprev = 0 vmsize = 0 size, prop = self.get_property("chiprev") if prop and size == 4: chiprev = prop size, prop = self.get_property("montype") if prop and size == 4: sense = prop size, prop = self.get_property("vfreq") if prop and size == 4: freq = prop size, prop = self.get_property("vmsize") if prop and size == 4: vmsize = prop if chiprev == 0: type = "Sun Unknown GX" elif chiprev in range(1, 5): type = "Sun Double width GX" elif chiprev in range(5, 10): type = "Sun Single width GX" elif chiprev == 11: if vmsize == 2: type = "Sun Turbo GX with 1M VSIMM" elif vmsize == 4: type = "Sun Turbo GX Plus" else: type = "Sun Turbo GX" depth = 8 elif prop == "cgfourteen": size = 0 s, prop = self.get_property("vfreq") if prop and s == 4: freq = prop s, prop = self.get_property("reg") if prop and not (s % 12) and s > 0: size = prop + s - 4 if size == 0x400000: type = "Sun SX with 4M VSIMM" elif size == 0x800000: type = "Sun SX with 8M VSIMM" else: type = "Sun SX" depth = 24 elif prop == "leo": size, prop = self.get_property("model"); if prop and size > 0 and '501-2503' not in prop: type = "Sun Turbo ZX" else: type = "Sun ZX or Turbo ZX" depth = 24 elif prop == "tcx": print "TODO" #if (prom_getbool("tcx-8-bit")) { # type = "Sun TCX (8bit)"; # depth = 8; #} else { # type = "Sun TCX (S24)"; # depth = 24; #} elif prop == "afb": btype = 0; size, prop = self.get_property("vfreq") if prop and size == 4: freq = prop size, prop = self.get_property("board_type"); if prop and size == 4: btype = prop if btype == 3: type = "Sun Elite3D-M6 Horizontal" else: type = "Sun Elite3D" depth = 24 elif prop == "ffb": btype = 0 size, prop = self.get_property("vfreq"); if prop and size == 4: freq = prop size, prop = self.get_property("board_type") if prop and size == 4: btype = prop if btype == 0x08: type="Sun FFB 67MHz Creator" elif btype == 0x0b: type="Sun FFB 67MHz Creator 3D" elif btype == 0x1b: type="Sun FFB 75MHz Creator 3D" elif btype in (0x20, 0x28): type="Sun FFB2 Vertical Creator" elif btype in (0x23, 0x2b): type="Sun FFB2 Vertical Creator 3D" elif btype == 0x30: type="Sun FFB2+ Vertical Creator" elif btype == 0x33: type="Sun FFB2+ Vertical Creator 3D" elif btype in (0x40, 0x48): type="Sun FFB2 Horizontal Creator" elif btype in (0x43, 0x4b): type="Sun FFB2 Horizontal Creator 3D" else: type = "Sun FFB" depth = 24 if type: size, prop = self.get_property("width") if prop and size == 4: width = prop size, prop = self.get_property("height") if (prop and size == 4): height = prop size, prop = self.get_property("device_type") break if type: print "TODO: create new dev!" """ struct sbusDevice *newDev; newDev=sbusNewDevice(NULL); if (depth != -1) { /* it's a video device */ newDev->width = width; newDev->height = height; newDev->freq = freq; newDev->monitor = sense; } newDev->desc = strdup(type); switch (depth) { case 1: newDev->class = CLASS_VIDEO; break; case 8: newDev->class = CLASS_VIDEO; break; case 24: newDev->class = CLASS_VIDEO; break; default: newDev->class = devClass; } if (newDev->class == CLASS_NETWORK) newDev->device = strdup("eth"); if (port) newDev->device = strdup(port); if (devlist) newDev->next = devlist; devlist = (struct device *)newDev; } """ size, prop = self.get_property('name') if prop and size > 0: if prop in ('sbus', 'sbi'): nsbus = 1 if prop == 'ebus': nebus = 1 nextnode = self.get_child(node) print "nextnode =", nextnode if nextnode: print "Walking children..." devlist = self.walk(nextnode, nsbus, nebus, probe_class, devlist) print "Done walking child" print "Getting sibling" nextnode = self.get_sibling(node) if nextnode: print "Walking sibling" devlist = self.walk(nextnode, sbus, ebus, probe_class, devlist) print "Done walking sibling" return devlist class SBusDevice(object): def __init__(self, dev_class, device, desc, next): self.dev_class = dev_class self.device = device self.desc = desc self.next = next class LsBus(object): def sbus_probe(self, probe_class, devlist): """ given a class to probe, returns a list of devices found which match """ if probe_class in (CLASS_MOUSE, CLASS_UNSPEC): if os.path.exists('/dev/sunmouse'): print "Found /dev/sunmouse" mousedev = SBusDevice(dev_class=CLASS_MOUSE, device='sunmouse', desc='Sun Mouse', next=devlist) devlist = mousedev if probe_class in (CLASS_UNSPEC, CLASS_OTHER, CLASS_NETWORK, CLASS_SCSI, CLASS_VIDEO, CLASS_AUDIO): prom = OpenProm() prom_root_node = prom.get_sibling(0) if not prom_root_node: print "No prom_root_node found!" return devlist print "Walking root_node: %r" % prom_root_node devlist = prom.walk(prom_root_node, 0, 0, probe_class, devlist) return devlist if __name__ == '__main__': devices = [] lsbus = LsBus() print lsbus.sbus_probe(CLASS_UNSPEC, devices)