From 7ec2aee41a073f27f92c91d7abf9f3551d23ce40 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Wed, 9 Jan 2002 22:50:51 +0000 Subject: [PATCH] Fixed a simple bug in newpci.c WRT iobases. Jan Kok's new NLBConfig with fixes. This has been tested with build and run of a linuxbios and appears to work fine. --- src/lib/newpci.c | 8 +- util/config/NLBConfig.py | 919 +++++++++++++++++++++++---------------- 2 files changed, 545 insertions(+), 382 deletions(-) diff --git a/src/lib/newpci.c b/src/lib/newpci.c index c0b6410815..b73810fa1f 100644 --- a/src/lib/newpci.c +++ b/src/lib/newpci.c @@ -485,13 +485,19 @@ void compute_allocate_io(struct pci_bus *bus) printk_debug("DEVIO: Bus 0x%x, devfn 0x%x, reg 0x%x: " "iosize 0x%lx\n", curdev->bus->number, curdev->devfn, i, iosize); + // Make sure that iosize is a minimum + // size. + iosize = round(iosize, IO_ALIGN); + // io_base must be aligned to the io size. + io_base = round(io_base, iosize); + printk_debug(" rounded size %d base 0x%x\n", iosize, io_base); curdev->base_address[i] = io_base; // some chipsets allow us to set/clear the IO bit. // (e.g. VIA 82c686a.) So set it to be safe) curdev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO; printk_debug("-->set base to 0x%lx\n", io_base); - io_base += round(iosize, IO_ALIGN); + io_base += iosize; curdev->command |= PCI_COMMAND_IO; } } diff --git a/util/config/NLBConfig.py b/util/config/NLBConfig.py index a8aaa80172..2757fa0840 100644 --- a/util/config/NLBConfig.py +++ b/util/config/NLBConfig.py @@ -1,34 +1,49 @@ -#! /usr/bin/python +#!/usr/bin/env python + +# Usage: python NLBConfig.py configfile freebiospath + +# Based on the commands in the user-supplied configfile, and several other +# config files known to this program, this program generates a Makefile, +# Makefile.settings, crt0.S file, etc. in the target directory, which is +# specified by the 'target' command in the user's configfile. For more +# info, see .../freebios/Documentation/Config + +# $Id$ +# Author: +# Modified by Jan Kok to improve readability of Makefile, etc. import sys import os import re import string -debug = 0; +debug = 0 # device variables -superio_decls = ''; -superio_devices = []; -numsuperio = 0; +superio_decls = '' +superio_devices = [] +numsuperio = 0 # Architecture variables -arch = ''; -makebase = ''; -crt0base = ''; -ldscriptbase = ''; +arch = '' +makebase = '' +crt0base = '' +ldscriptbase = '' -makeoptions = {}; -makenooptions = {}; -# rule format. Key is the rule name. value is a list of lists. The first -# element of the list is the dependencies, the rest are actions. -makebaserules = {}; -treetop = ''; -outputdir = ''; +makeoptions = {} +makenooptions = {} -objectrules = []; -userrules = []; -userdefines = []; +# Key is the rule name. Value is a mkrule object. +makebaserules = {} + +# List of targets in the order defined by makerule commands. +makerule_targets = [] + +treetop = '' +target_dir = '' + +objectrules = [] +userdefines = [] # this is the absolute base rule, and so is very special. mainrulelist = "all" @@ -42,7 +57,8 @@ def add_main_rule_dependency(new_dependency): # and an optional rule (can be empty) for actually building # the object def addobject(object, sourcepath, rule, condition, variable): - objectrules.append([object, topify(sourcepath), rule, condition, variable]) + objectrules.append([object, topify(sourcepath), + rule, condition, variable]) # OK, let's face it, make sucks. # if you have a rule like this: @@ -50,30 +66,113 @@ def addobject(object, sourcepath, rule, condition, variable): # make won't apply the .c.o rule. Toy! def addobject_defaultrule(object, sourcepath, condition, variable): - defaultrule = "\t $(CC) -c $(CFLAGS) -o $@ $<" + # defaultrule = "\t $(CC) -c $(CFLAGS) -o $@ $<" + defaultrule = "\t@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CFLAGS) -o $@ $<" addobject(object, sourcepath, defaultrule, condition, variable) -# for all these functions, you need: -# the dir that the Config file is in -# the treetop (so make it global!) -# the name -# Functions used by commands -def top(dir, top_name): - command_vals['TOP'] = top_name -def target(dir, targ_name): - global outputdir - outputdir = os.path.join(config_dir(), targ_name) - if os.path.isdir(outputdir): - print 'Will place Makefile, crt0.S, ldscript.ld in ', outputdir - else: - print outputdir, 'is not a directory. ' - print ' I know I should make this, but I\'m too paranoid' - print ' To fix this, type' - print 'mkdir -p ', outputdir - print ' then run this program again' +# ----------------------------------------------------------------------------- +# Class for storing and printing make rules +# ----------------------------------------------------------------------------- + +class mkrule: + + # This defines the function mkrule(target, depends, action). + # It creates a makerule object and records it for later recall. + def __init__(self, target, depends, actions): + self.whence = current_config_file() + self.comments = [] # list of strings + self.target = target # string + self.depends = depends # string of dependency names + self.actions = actions # list of strings + if makebaserules.has_key(target): + print "===> Warning: makerule for target '%s' in file" % target + print current_config_file(), "is replacing previous definition in file" + print makebaserules[target].whence + else: + # Keep a list of targets so we can output the rules + # in the order that they are defined. + makerule_targets.append(target) + # I remember myself, therefore I am. + makebaserules[target] = self + + def adddepend(self, depend): + self.depends = self.depends + ' ' + depend + + def addaction(self, action): + self.actions.append(action) + + def write(self, file): + file.write("\n") + + if 1: # Put comments before target : dependencies line. + file.write("# from: %s\n" % self.whence) + for comment in self.comments: + file.write("# %s\n" % comment) + + # Write the target : dependencies line. + file.write("%s: %s\n" % (self.target, self.depends)) + + if 0: # Put comments after target : dependencies line, + # which causes them to be printed during make. + file.write("\t# from: %s\n" % self.whence) + for comment in self.comments: + file.write("\t# %s\n" % comment) + + # Write out the actions. + for action in self.actions: + file.write("\t%s\n" % action) + + +# ----------------------------------------------------------------------------- +# Command parsing functions +# ----------------------------------------------------------------------------- + +# Keep track of nested config files, for error reporting. +config_file_stack = [] +def current_config_file(): + return config_file_stack[-1] + +# The command being processed, for error reporting. +current_command = '' + +# Match a compiled pattern with a string, die if fails, return list of groups. +def match(pattern, string): + m = pattern.match(string) + if not m: + print "\nBad command syntax: ", current_command + print "in file", current_config_file() sys.exit(1) + return m.groups() +# A common pattern: +splitargs_re = re.compile(r'(\S*)\s*(.*)') + + +# ----------------------------------------------------------------------------- +# Command execution functions +# ----------------------------------------------------------------------------- + +# For all these functions, +# dir is the directory that the current Config file is in +# the second arg is the remainder of the command line (for most commands +# any comments are stripped off) + +# COMMAND: target +# target must be the first command in the file. This command may only be +# used once. target names the target directory for building this +# instance of the BIOS. The target directory will be $(TOP)/. +def target(dir, targ_name): + global target_dir + target_dir = os.path.join(os.path.dirname(current_config_file()), + targ_name) + if not os.path.isdir(target_dir): + print 'Creating directory', target_dir + os.makedirs(target_dir) + print 'Will place Makefile, crt0.S, etc. in ', target_dir + +# dir should be the path to a directory containing a Config file. +# If so, process the commands in that config file right now. def handleconfig(dir): file = os.path.join(dir, 'Config') print "Process config file: ", file @@ -81,34 +180,35 @@ def handleconfig(dir): doconfigfile(dir, file) else: print "===> Warning: %s not found" % file - - -def buildfullpath(type, name): - fullpath = os.path.join(type, name) - command_vals[type] = fullpath - return fullpath +# type is the command name, e.g. 'northbridge' +# name is the path arg that followed the command +# /src///Config is executed. def common_command_action(dir, type, name): - fullpath = buildfullpath(type, name) - realpath = os.path.join('src', fullpath) - # seems weird, eh? but config file are always done from - # treetop - realpath = os.path.join(treetop, realpath) + realpath = os.path.join(treetop, 'src', type, name) handleconfig(realpath) - return fullpath + return realpath +# COMMAND: arch +# is typically i386 or alpha. +# Set various variables and execute a make.base file. def set_arch(dir, my_arch): global arch, makebase, crt0base arch = my_arch - configpath = os.path.join(treetop, os.path.join("src/arch/", os.path.join(my_arch, "config"))) + configpath = os.path.join(treetop, "src/arch/", my_arch, "config") makebase = os.path.join(configpath, "make.base") crt0base = os.path.join(configpath, "crt0.base") print "Now Process the ", my_arch, " base files" if (debug): print "Makebase is :", makebase, ":" - makedefine(dir, "ARCH="+my_arch) + makedefine(dir, "ARCH="+my_arch) doconfigfile(treetop, makebase) +# COMMAND: dir +# Execute the config file at /Config +# If begins with "/", it is interpreted as relative to $TOP, +# otherwise it is interpreted as relative to the directory of the config +# file that invoked this dir command. def dir(base_dir, name): regexp = re.compile(r"^/(.*)") m = regexp.match(name) @@ -120,9 +220,22 @@ def dir(base_dir, name): fullpath = os.path.join(base_dir, name) handleconfig(fullpath) -def mainboard(dir, mainboard_name): - common_command_action(dir, 'mainboard', mainboard_name) +# The mainboard directory, as an absolute path. We need to remember this +# because the docipl command generates Makefile code that includes files +# from this directory. +mainboard_dir = None +# COMMAND: mainboard +# The second command in a top-level config file is the mainboard command. +# This command may only be used once. The mainboard command names a mainboard +# source directory to use. The file $(TOP)/src//Config +# is executed. +def mainboard(dir, mainboard_name): + global mainboard_dir + mainboard_dir = common_command_action(dir, 'mainboard', mainboard_name) + +# COMMAND: etherboot +# Execute the file $(TOP)/src/etherboot/Config and set some Makefile variables. def etherboot(dir, net_name): common_command_action(dir, 'etherboot', '') option(dir,'OLD_KERNEL_HACK') @@ -130,76 +243,78 @@ def etherboot(dir, net_name): option(dir,'TFTP_INITRD') option(dir,'PYRO_SERIAL') - +# COMMAND: keyboard ... # old legacy PC junk, which will be dying soon. def keyboard(dir, keyboard_name): if (debug): print "KEYBOARD" keyboard_dir = os.path.join(treetop, 'src', keyboard_name) - addobject_defaultrule('keyboard.o', keyboard_dir,'','OBJECTS') + addobject_defaultrule('keyboard.o', keyboard_dir, '', 'OBJECTS') +# COMMAND: cpu +# +# This command may only be used once for a given CPU name. Executes the +# config file $(TOP)/src/cpu//Config +# def cpu(dir, cpu_name): common_command_action(dir, 'cpu', cpu_name) +# COMMAND: northsouthbridge / +# +# This command may only be used once. Executes the config file +# $(TOP)/src/northsouthbridge///Config +# def northsouthbridge(dir, northsouthbridge_name): - fullpath = common_command_action(dir, 'northsouthbridge', - northsouthbridge_name) - command_vals["northbridge"] = [fullpath] - command_vals["southbridge"] = [fullpath] - + common_command_action(dir, 'northsouthbridge', northsouthbridge_name) +# COMMAND: northbridge / +# +# This command may only be used once. Executes the config file +# $(TOP)/src/northbridge///Config +# def northbridge(dir, northbridge_name): - fullpath = common_command_action(dir, 'northbridge', northbridge_name) - command_vals["northbridge"] = [fullpath] + common_command_action(dir, 'northbridge', northbridge_name) +# COMMAND: southbridge / +# +# This command may only be used once. Executes the config file +# $(TOP)/src/southbridge///Config +# def southbridge(dir, southbridge_name): - fullpath = common_command_action(dir, 'southbridge', southbridge_name) - command_vals["southbridge"] = [fullpath] + common_command_action(dir, 'southbridge', southbridge_name) -def pcibridge(dir, pcibridge_name): - common_command_action(dir, 'picbridge', picbridge_name) - -# I don't see a need yet to read in a config file for -# superio. Don't bother. +# COMMAND: superio +# +# This command may be used as many times as needed. +# I don't see a need yet to read in a config file for +# superio. Don't bother. +# def superio(dir, superio_name): # note that superio is w.r.t. treetop - buildfullpath('superio', superio_name) dir = os.path.join(treetop, 'src', 'superio', superio_name) - addobject_defaultrule('superio.o', dir,'','OBJECTS') + addobject_defaultrule('superio.o', dir, '', 'OBJECTS') +# COMMAND: nsuperio ... # commands are of the form: # superio_name [name=val]* def nsuperio(dir, superio_commands): - global superio_decls, superio_devices, numsuperio, outputdir - # need python code to bust this into separate words ... - wspc = string.whitespace - rest = "(.*)" - w = "[" + wspc + "]*" - name = "([^" + wspc + "]*)" - # break into name + commands - pat = name + w + rest + w - # print "pat :", pat, ":", rule - command_re = re.compile(pat) - m = command_re.match(superio_commands) + global superio_decls, superio_devices, numsuperio, target_dir # note that superio is w.r.t. treetop - superio_name = m.group(1); + (superio_name, rest) = match(splitargs_re, superio_commands) superio_decl_name = re.sub("/", "_", superio_name) - buildfullpath('superio', superio_name) dir = os.path.join(treetop, 'src', 'superio', superio_name) object="superio_%s.o" % superio_decl_name superio_source = dir + "/superio.c" - addobject_defaultrule(object, superio_source,'','OBJECTS') - addobject_defaultrule('nsuperio.o', "", '','OBJECTS') - rest = m.group(2) + addobject_defaultrule(object, superio_source, '', 'OBJECTS') + addobject_defaultrule('nsuperio.o', "", '', 'OBJECTS') + superio_cmds = ''; - m = command_re.match(rest) - cmd = m.group(1) - rest = m.group(2) + m = splitargs_re.match(rest) + (cmd, rest) = m.groups() while (cmd): superio_cmds = superio_cmds + ", ." + cmd - m = command_re.match(rest) - cmd = m.group(1) - rest = m.group(2) + m = splitargs_re.match(rest) + (cmd, rest) = m.groups() # now build the declaration decl = ''; decl = "extern struct superio_control superio_" @@ -215,205 +330,208 @@ def nsuperio(dir, superio_commands): numsuperio = numsuperio + 1 -# arg, what's a good way to do this ... -# basically raminit can have a whole list of files. That's why -# this is a list. -def raminit(dir, file): - ramfilelist = command_vals['mainboardinit'] - ramfilelist.append([file, '']) - print "Added ram init file: ", file +# A list of files for initializing a motherboard. +mainboardinit_files = [] -# A list of files for initializing a motherboard +# COMMAND: mainboardinit [] +# Include the assembly language .inc file at $(TOP)/src/ +# in the crt0.s file. def mainboardinit(dir, command): - wspc = string.whitespace - m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command); - file = m.group(1) - condition = m.group(3) - mainboardfilelist = command_vals['mainboardinit'] - mainboardfilelist.append([file, condition]) + (file, condition) = match(splitargs_re, command) + mainboardinit_files.append( (file, condition) ) print "Added mainboard init file: ", file +# COMMAND: raminit +# Include the assembly language .inc file at $(TOP)/src/ +# in the crt0.s file. This command is essentially a duplicate of mainboardinit. +def raminit(dir, file): + mainboardinit_files.append( (file, '') ) + print "Added ram init file: ", file -# A set of linker scripts needed by linuxBIOS. +# Set of files we build the linker script from. +ldscripts = [] + +# COMMAND: ldscript +# $(TOP)/src/ will be added to the Makefile variable +# LDSCRIPTS-1 if the is true or omitted. def ldscript(dir, command): - wspc = string.whitespace - m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command); - file = m.group(1) - condition = m.group(3) - ldscripts = command_vals['ldscripts'] - filepath = os.path.join(treetop, 'src'); - filepath = os.path.join(filepath, file); - ldscripts.append([filepath, condition]) + (file, condition) = match(splitargs_re, command) + filepath = os.path.join(treetop, 'src', file); + ldscripts.append( (filepath, condition) ) print "Added ldscript init file: ", filepath +# COMMAND: object [] +# +# is a pathname to a .c or .S file rooted at +# $(TOP)/. +# is a condition such as HAVE_PIRQ_TABLE. +# This command adds a rule to the Makefile for +# the target such that: +# 1) Basename of .o depends on $(TOP)/ +# 2) romimage has a dependency on the .o +# 3) includepath for compiling the .o includes the directory containing the +# source +# An alternative explanation: The basename of path-to-source, minus the +# .c or .S suffix, plus a .o suffix, is added to the OBJECTS-1 Makefile +# variable if the is true or omitted. The OBJECTS-1 list is +# used (by a makrule in $(TOP)/src/config/Config) to make linuxbios.a, +# thus these objects are linked in only if needed to satisfy some reference. +# def object(dir, command): - wspc = string.whitespace - m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command) - obj_name = m.group(1) - condition = m.group(3) - addobject_defaultrule(obj_name, dir, condition,'OBJECTS') + (obj_name, condition) = match(splitargs_re, command) + addobject_defaultrule(obj_name, dir, condition, 'OBJECTS') +# COMMAND: driver [] +# +# Similar to object command, but these objects go into the Makefile variable +# DRIVERS-1 if the is true or omitted, and the objects listed +# in DRIVERS-1 are always linked in (via $(TOP)/src/config/Config) to +# linuxbios.o +# def driver(dir, command): - wspc = string.whitespace - m = re.match("([^" + wspc + "]+)([" + wspc + "]([^" + wspc + "]*)|)", command) - obj_name = m.group(1) - condition = m.group(3) + (obj_name, condition) = match(splitargs_re, command) addobject_defaultrule(obj_name, dir, condition, 'DRIVERS') - -# for eventual user-defined rules. -# pattern is name : deps ; rule -# we'll look at adding rules later +# COMMAND: makerule : [] ; [] +# +# Lets you add make rules to the Makefile. +# +makerule_re = re.compile(r'([^:\s]+)\s*:\s*([^;]*?)\s*;\s*(.*)') def makerule(dir, rule): - wspc = string.whitespace - rest = "(.*)" - w = "[" + wspc + "]*" - cmd = "([^" + wspc + "]*)" - namepat = "([^;]*)" - pat = cmd + w + ":" + w + namepat + w + ";" + w + rest + w - # print "pat :", pat, ":", rule - command_re = re.compile(pat) - m = command_re.match(rule) - if (not m): - print "\nBadly formed rule: ", rule, "\n" - sys.exit() - rulename = m.group(1) - dependencies = m.group(2) - actions = m.group(3) - # print "rulename :", rulename, ": deps:", dependencies,":" - # print " actions ", actions - makebaserules[rulename] = [dependencies] - makebaserules[rulename].append(actions) + (target, dependencies, action) = match(makerule_re, rule) + # Each rule created by makerule will be printed to the Makefile + # with a comment which shows the config file from whence it came. + mkrule(target, dependencies, [action]) +# COMMAND: addaction +# +# Add an action to an existing rule designated by . +# def addaction(dir, rule): - wspc = string.whitespace - rest = "(.*)" - w = "[" + wspc + "]*" - namepat = "(.*)" - cmd = "([^" + wspc + "]*)" - pat = cmd + w + rest + w - # print "pat :", pat, ":", rule - command_re = re.compile(pat) - m = command_re.match(rule) - rulename = m.group(1) - actions = m.group(2) - # print "rulename :", rulename - # print " actions ", actions, "\n" - # print "rules[rulename]=", makebaserules[rulename], "\n" - makebaserules[rulename].append(actions) - -# add a dependency -def adddepend(dir, rule): - wspc = string.whitespace - rest = "(.*)" - w = "[" + wspc + "]*" - namepat = "(.*)" - cmd = "([^" + wspc + "]*)" - pat = cmd + w + rest + w - # print "pat :", pat, ":", rule - command_re = re.compile(pat) - m = command_re.match(rule) - rulename = m.group(1) - depend = m.group(2) - # print "rulename :", rulename - # print " depend ", depend - makebaserules[rulename][0] = makebaserules[rulename][0] + " " + depend + (target, action) = match(splitargs_re, rule) + if not makebaserules.has_key(target): + print "===> Warning: Need 'makerule %s ...' before addaction in %s" % (target, current_config_file()) + makebaserules[target].addaction(action) +# COMMAND: adddepend +# +# Add a dependency to an existing rule designated by . +# +def adddepend(dir, rule): + (target, depend) = match(splitargs_re, rule) + if not makebaserules.has_key(target): + print "===> Warning: Need 'makerule %s ...' before adddepend in %s" % (target, current_config_file()) + makebaserules[target].adddepend(depend) + +# COMMAND: makedefine +# is printed out to the Makefile. is usually of the form +# = def makedefine(dir, rule): userdefines.append(rule) +# Put "