Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Mar 2001 15:27:05 +0000
From:      Graham Wheeler <gram@cequrux.com>
To:        freebsd-hackers@freebsd.org
Subject:   Getting ISA device settings from kernel
Message-ID:  <3AC4A5C9.35FE775B@cequrux.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------C3174E352F60362AEE6C8205
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi all

I had some code that worked on FreeBSD 3.4 to configure ISA devices.
In order to get the ISA device settings, I used the kvm library, and
started off by extracting the name lists for _isa_devtab_tty, 
_isa_devtab_bio, and _isa_devtab_net.

I used to just give up if kvm_nlist returned a non-zero number. On
FreeBSD 4.2 this is happening. Checking the manpage, I see that this
could be that there are invalid values, so I changed the check to 
only give up of the return value is negative. The code now gets past the
kvm_nlist, but fails on the first kvm_read that follows (which uses the
n_value returned by kvm_nlist as the offset field).

Is there a different mechanism in 4.2 to do the kind of stuff I'm 
trying to do? Should the code still work?

I've attached the code in case anyone wants to look at it.

TIA
gram
-- 
Dr Graham Wheeler                        E-mail: gram@cequrux.com
Director, Research and Development       WWW:    http://www.cequrux.com
CEQURUX Technologies                     Phone:  +27(21)423-6065
Firewalls/VPN Specialists                Fax:    +27(21)424-3656
--------------C3174E352F60362AEE6C8205
Content-Type: text/plain; charset=us-ascii;
 name="kernel.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="kernel.h"

//--------------------------------------------------------------------
//
// FreeBSD kernel configuration class
//
// (c) 1997, 1998 - CEQURUX Technologies.
//
// All Rights Reserved. Duplication or use without the
// express written permission of CEQURUX Technologies
// is prohibited.
//
// Written by Graham Wheeler.
//
//--------------------------------------------------------------------


#ifndef KERNEL_H
#define KERNEL_H

#include "regversion.h"

#define kernel_hdr_id	HVERSION("$Id$")

#include "debug.h"
#include "isa_device.h"

class Device;
class DeviceTable;

class KernelConfig
{
    TRACE(KernelConfig)
    DeviceTable *ttyd;
    DeviceTable *biod;
    DeviceTable *netd;
    Device *GetDevice(const char *name, int unit = -1);
    int DeviceDriverDetected(const char *name, int unit = -1);
    int DeviceEnabled(const char *name, int unit = -1);
    int DeviceDetected(const char *name, int unit = -1);
    const char *GetDetectedDevice(char typecode, int unit = -1);
    const char *GetEnabledDevice(char typecode, int unit = -1);
public:
    KernelConfig();
    ~KernelConfig();
    void Write(FILE *fp);
    void Read(FILE *fp);
    void Dump(FILE *fp);
    void Dump();

    int NumDetectedSerialPorts();
    int NumEnabledSerialPorts();
    int NumDetectedParallelPorts();
    int NumEnabledParallelPorts();

    const char *GetDetectedSerialPort(int unit);
    const char *GetEnabledSerialPort(int unit);
    const char *GetDetectedParallelPort(int unit);
    const char *GetEnabledParallelPort(int unit);
    const char *GetDetectedIDE();
    const char *GetEnabledIDE();
    const char *GetDetectedSCSI();
    const char *GetEnabledSCSI();
    const char *GetConfiguredSCSI();
    const char *GetDetectedNetCard(int unit);
    const char *GetEnabledNetCard(int unit);
    const char *GetConfiguredNetCard(int unit);
    const char *GetDetectedCDROM();
    const char *GetEnabledCDROM();
    const char *GetConfiguredCDROM();
    const char *GetDetectedTape();
    const char *GetEnabledTape();
    const char *GetConfiguredTape();

    const char *GetDescription(const char *dev);
    int GetPort(const char *dev, int unit = -1);
    int GetIRQ(const char *dev, int unit = -1);
    int GetDMA(const char *dev, int unit = -1);
    int GetMemBase(const char *dev, int unit = -1);
    void SetPort(int v, const char *dev, int unit = -1);
    void SetIRQ(int v, const char *dev, int unit = -1);
    void SetDMA(int v, const char *dev, int unit = -1);
    void SetMemBase(int v, const char *dev, int unit = -1);
    void Enable(int v, const char *dev, int unit = -1);
    int Commit(char *kernel = 0);
    int GetNetDevList(char **&list);
    int GetEnabledNetDevList(char **&list);

    int GetNumDevices();
    struct isa_device &GetDevice(int n, char *name, int nsiz);
};

int GetNetDevList(char **&list);
int GetEnabledNetDevList(char **&list);

#endif



--------------C3174E352F60362AEE6C8205
Content-Type: text/plain; charset=us-ascii;
 name="kernel.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="kernel.cc"

/* $Id$	*/
#ifdef __FreeBSD__
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>
#include <nlist.h>
#include <paths.h>
#include <unistd.h>
#include <fcntl.h>
#include <a.out.h>
#include <kvm.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <syslog.h>
#include <ctype.h>
#include <assert.h>

#include "debug.h"
#include "strutil.h"
#include "release.h"
#include "bsddev.h"
#include "kernel.h"

MAKE_CH_VERSION(kernel, "$Id$");

#define PageSize()		getpagesize()

static int GetDevList(DeviceTable *devtbl, char **&list);
static int GetEnabledDevList(DeviceTable *devtbl, char **&list);

class Device
{
    TRACE(Device)
    friend class DeviceTable;
    friend class KernelConfig;
    friend int GetNetDevList(char **&list);

    char *name;
    struct isa_device d;
protected:
    friend int GetDevList(DeviceTable *devtbl, char **&list);
    friend int GetEnabledDevList(DeviceTable *devtbl, char **&list);
    Device(const char *name_in, struct isa_device &d_in)
	: d(d_in)
    {
        PRECONDITION(name_in != 0);
	int l = strlen(name_in)+1;
	name = new char[l];
	MemAssert(name, DeviceName);
	STRLCPY(name, name_in, l);
    }
    ~Device()
    {
	delete [] name;
    }
    struct isa_device &GetStruct()
    {
        return d;
    }
    void Write(FILE *fp, char *tblname);
    void Read(char *buff);
    void Dump(FILE *fp);
    void Dump()
    {
	Dump(stdout);
    }
    const char *Description();
    int ID() const
    {
	return d.id_id;
    }
    char *Name() const
    {
	return name;
    }
    int Unit() const
    {
	return d.id_unit;
    }
    int Port() const
    {
	return d.id_iobase;
    }
    int Interrupt() const
    {
	int vec = 0, shf = d.id_irq;
	while (shf>>=1, shf != 0) vec++;
	return vec;
    }
    int DMAChannel() const
    {
	return d.id_drq;
    }
    int MemBase() const
    {
	if (d.id_msize)
	    return (int)d.id_maddr;
	return 0;
    }
    int Enabled() const
    {
	return d.id_enabled;
    }
    int Detected() const
    {
#if __FreeBSD_version<400000
	return d.id_alive;
#else
	// XXX In FreeBSD 4.2, this would be:
	//
	//	return (d.id_device->state >= DS_ALIVE);
	//
	// However, we would have to get the struct device stuff out of the
	// kernel, as without doing so d.id_device will just be a junk 
	// pointer. I'm not sure at present how to do this, so for now
	// I'm treating this the same as Enabled().
	return Enabled();
#endif
    }
    int Flags() const
    {
	return d.id_flags;
    }

    void Port(int v)
    {
#ifdef DEBUG
	fprintf(stderr, "Set %s%d port to %X\n", Name(), Unit(), v);
#endif
	d.id_iobase = v;
    }
    void Interrupt(int v)
    {
#ifdef DEBUG
	int oldv = v;
#endif
	int i;
	if (v)
	{
	    i = 1;
	    while (v-- > 0)
		i <<= 1;
	}
	else i = 0;
	d.id_irq = i;
#ifdef DEBUG
	fprintf(stderr, "Set %s%d interrupt to %d\n", Name(), Unit(), oldv);
#endif
    }
    void DMAChannel(int v)
    {
#ifdef DEBUG
	fprintf(stderr, "Set %s%d DMA channel to %d\n", Name(), Unit(), v);
#endif
	d.id_drq = v;
    }
    void MemBase(int v)
    {
	d.id_maddr = (char*)v;
    }
    void Enable()
    {
	d.id_enabled = 1;
    }
    void Disable()
    {
	d.id_enabled = 0;
    }
    void Flags(int v)
    {
	d.id_flags = v;
    }
    void Commit(int fd, struct isa_device &newd)
    {
	int changed = 0;
#ifdef DEBUG
	Device junk(Name(), newd);
	fprintf(stderr, "Commit device %s%d, fd %d\n", Name(), Unit(), fd);
	fprintf(stderr, "\tcurrent: enbl %d port %X irq %d drq %d mem %X\n",
		newd.id_enabled, newd.id_iobase, newd.id_irq, newd.id_drq,
		newd.id_maddr);
	fprintf(stderr, "\tnew:     enbl %d port %X irq %d drq %d mem %X\n",
		d.id_enabled, d.id_iobase, d.id_irq, d.id_drq, d.id_maddr);
#endif
	if (d.id_enabled != newd.id_enabled)
	    { newd.id_enabled = d.id_enabled; changed = 1; }
	if (newd.id_irq != (u_short)-1 && d.id_irq != newd.id_irq)
	    { newd.id_irq = d.id_irq; changed = 1; }
	if (newd.id_drq >= 0 && d.id_drq != newd.id_drq)
	    { newd.id_drq = d.id_drq; changed = 1; }
	if (newd.id_iobase >= 0 && d.id_iobase != newd.id_iobase)
	    { newd.id_iobase = d.id_iobase; changed = 1; }
	if (newd.id_maddr != (caddr_t)-1 && d.id_maddr != newd.id_maddr)
	    { newd.id_maddr = d.id_maddr; changed = 1; }
	if (changed)
	{
#ifdef DEBUG
	    fprintf(stderr, "\n\nNOW:\n"); Dump(stderr);
#endif
	    u_long pos = lseek(fd, (off_t)0, SEEK_CUR) -
				sizeof(struct isa_device);
	    if (lseek(fd, -(off_t)sizeof(struct isa_device), SEEK_CUR) != pos)
	    {
		syslog(LOG_INFO, "lseek: %m");
		return;
	    }
            if (write(fd, (char*)&newd, sizeof(newd))<0)
		syslog(LOG_INFO, "write: %m");
	}
    }
};
    
const char *Device::Description()
{
    return DeviceDescription(name);
}

void Device::Write(FILE *fp, char *tblname)
{
    PRECONDITION(fp != 0);
    fprintf(fp, "%s:%s:%d:%d:%X:%d:%X:%d:%d:%d\n",
	tblname, Name(), ID(), Unit(), Port(), Interrupt(),
	MemBase(), DMAChannel(), Flags(), Enabled());
}

void Device::Read(char *buff)
{
    int n_port, n_irq, n_base, n_dma, n_flags, n_enbl;
    if (sscanf(buff, "%X:%d:%X:%d:%d:%d",
		&n_port, &n_irq, &n_base, &n_dma, &n_flags, &n_enbl) == 6)
    {
	Port(n_port);
	Interrupt(n_irq);
	MemBase(n_base);
	DMAChannel(n_dma);
	Flags(n_flags);
	if (n_enbl)
	    Enable();
	else
	    Disable();
    }
}

void Device::Dump(FILE *fp)
{
    PRECONDITION(fp != 0);
    fprintf(fp, "Name: %s  ID: %d  Unit: %d", Name(), ID(), Unit());
    if (Enabled() || Detected())
    {
	fprintf(fp, " (%s%s)",
		(Enabled()?" enabled ":""),
		(Detected() ? " detected ":""));
    }
    fprintf(fp, "\n");
    fprintf(fp, "Description: %s\n", Description());
    if (Port())
	fprintf(fp, "I/O Port: %X\n", Port());
    if (Interrupt())
	fprintf(fp, "Interrupt: %d\n", Interrupt());
    if (DMAChannel()>0)
	fprintf(fp, "DMA Channel: %d\n", DMAChannel());
    if (MemBase())
	fprintf(fp, "Memory Base Address: %X\n", MemBase());
}

//----------------------------------------------------------------------

class DeviceTable
{
    TRACE(DeviceTable)
    Device **d;
    int ndevs;
    char *name;
public:
    DeviceTable(char *name_in);
    Device *Get(const char *name_in, int unitnum = -1);
    void Write(FILE *fp);
    void Read(const char *buff);
    void Dump(FILE *fp);
    void Dump();
    inline char *Name() const
    {
	return name;
    }
    inline int NumDevs() const
    {
	return ndevs;
    }
    inline Device *Get(int idx) const
    {
	return d[idx];
    }
    int Commit(char *kernel = 0);
    ~DeviceTable();
};

DeviceTable::DeviceTable(char *name_in)
    : d(0), ndevs(0)
{
    PRECONDITION(name_in != 0);
    Device *devs[80];
    char errb[_POSIX2_LINE_MAX];
    int l = strlen(name_in)+1;
    name = new char[l];
    MemAssert(name, DeviceTableName);
    STRLCPY(name, name_in, l);
    kvm_t *kd = kvm_openfiles(0,0,0,O_RDONLY,errb);
    struct nlist nl[2];
    nl[0].n_name = name_in;
    nl[1].n_name = 0;
    if (kd==0 || kvm_nlist(kd, nl) == -1 || nl[0].n_type == 0)
	return;
    // Loop through the devices in the table...
    struct isa_device buf;
    for (u_long pos = nl[0].n_value; ; pos += sizeof(buf))
    {
	if (kvm_read(kd, pos, &buf, sizeof(buf)) < 0 || buf.id_id == 0)
	    break;

	// get the driver entry...
    	struct isa_driver dbuf;
	if (buf.id_driver == 0 ||
	    kvm_read(kd, (u_long)buf.id_driver, &dbuf, sizeof(dbuf))<0)
		break;
	else
	{
	    // get the driver name...
    	    char nbuf[8];
	    if (kvm_read(kd, (u_long)dbuf.name, nbuf, sizeof(nbuf)) < 0)
		break;
	    else
	    {
		assert(ndevs < 80);
		nbuf[7] = 0;
		buf.id_maddr = (char*)(((int)buf.id_maddr) & 0xFFFFF);
		devs[ndevs++] = new Device(nbuf, buf);
		MemAssert(devs[ndevs-1], Device);
	    }
	}
    }
    kvm_close(kd);
    d = new Device*[ndevs];
    MemAssert(d, DeviceTable);
    for (int i = 0; i < ndevs; i++)
    {
	d[i] = devs[i];
#ifdef DEBUG
	d[i]->Dump(stderr);
#endif
    }
}

DeviceTable::~DeviceTable()
{
    for (int i = 0; i < ndevs; i++)
	delete d[i];
    delete [] name;
    delete [] d;
}

Device *DeviceTable::Get(const char *name_in, int unitnum)
{
    PRECONDITION(name_in  != 0);
    Device *rtn = 0;
    for (int i = 0; i < ndevs; i++)
	if (strncmp(name_in, d[i]->Name(), 4)==0)
	{
	    if (unitnum < 0)
	    {
		if (d[i]->Unit() == 0) return d[i]; // found the best match
		if (rtn == 0 || d[i]->Unit() < rtn->Unit())
		    rtn = d[i]; // keep next lowest match
	    }
	    else if (unitnum == d[i]->Unit()) // found the exact match
	        return d[i];
	}
    return rtn; // return 0 or lowest match if unitnum was negative
}

void DeviceTable::Write(FILE *fp)
{
    PRECONDITION(fp != 0);
    for (int i = 0; i < ndevs; i++)
	d[i]->Write(fp, Name());
}

void DeviceTable::Read(const char *buff)
{
    PRECONDITION(buff != 0);
    char *s = strchr(buff, ':');
    if (s)
    {
	*s++ = 0;
	int id = atoi(s);
        s = strchr(s, ':');
	if (s)
	{
	    int unit = atoi(s+1);
	    s = strchr(s+1, ':');
	    if (s)
	    {
		for (int i = 0; i < ndevs; i++)
	        {
	            if (d[i]->ID() == id && d[i]->Unit() == unit &&
		        strcmp(buff, d[i]->Name()) == 0)
			    d[i]->Read(s+1);
		}
	    }
	}
    }
}

void DeviceTable::Dump(FILE *fp)
{
    PRECONDITION(fp != 0);
    fprintf(fp, "Table: %s\n\n", Name());
    for (int i = 0; i < ndevs; i++)
	d[i]->Dump(fp);
    fprintf(fp, "\n\n");
}

void DeviceTable::Dump()
{
    Dump(stdout);
}

int DeviceTable::Commit(char *kernel)
{
    if (kernel == 0) kernel = (char*) getbootfile();
    u_long flags, entry;
    int f;
    struct exec es;
    struct stat fst;
    struct nlist nl[2];
    nl[0].n_name = name;
    nl[1].n_name = 0;
    if (nlist(kernel, nl) != 0) return -1;
    else if (nl[0].n_type == 0) return -1;
    else if (stat(kernel, &fst) < 0) return -1;
    else flags = fst.st_flags;
    if (chflags(kernel, (u_long)0)<0) return -1;
    else if ((f = open(kernel, O_RDWR)) <= 0) return -1;
    else if (read(f, &es, sizeof(es)) <= 0) return -1;
    else entry = es.a_entry;
    u_long pos = nl[0].n_value + PageSize() - entry;
    if (lseek(f, (off_t)pos, SEEK_SET) != pos)
        return -1;
#ifdef DEBUG
    fprintf(stderr, "\n\n\n\nCOMMIT DEVICE TABLE %s (pos %d)\n\n", name, pos);
#endif
    for (;;)
    {
	struct isa_device buf;
#ifdef DEBUG
	fprintf(stderr, "reading entry at pos %d\n", lseek(f, (off_t)0, SEEK_CUR));
#endif
	int res = read(f, (char*)&buf, sizeof(buf));
	if (res<=0) { syslog(LOG_INFO, "read: %m"); break; }
	if (buf.id_id == 0) break;
#ifdef DEBUG
	fprintf(stderr, "Attempting to commit device with id %d, unit %d\n", 
		buf.id_id, buf.id_unit);
#endif
	for (int i = 0; i < ndevs; i++)
	{
	    if (d[i]->ID() == buf.id_id && d[i]->Unit() == buf.id_unit)
	    {
		d[i]->Commit(f, buf);
		break;
	    }
	}
#ifdef DEBUG
	if (i>=ndevs) fprintf(stderr, "No device with ID %d found!\n", buf.id_id);
#endif
    }
    if (chflags(kernel, flags) < 0)
	return -1;
    close(f);
    return 0;
}

//----------------------------------------------------------------------

KernelConfig::KernelConfig()
{
    ttyd = new DeviceTable("_isa_devtab_tty");
    biod = new DeviceTable("_isa_devtab_bio");
    netd = new DeviceTable("_isa_devtab_net");
    MemAssert(ttyd && biod && netd, DeviceTables);
}

KernelConfig::~KernelConfig()
{
    delete ttyd;
    delete biod;
    delete netd;
}

void KernelConfig::Write(FILE *fp)
{
    PRECONDITION(fp != 0);
    ttyd->Write(fp);
    biod->Write(fp);
    netd->Write(fp);
}

void KernelConfig::Read(FILE *fp)
{
    PRECONDITION(fp != 0);
    int ttyd_len = strlen(ttyd->Name());
    int biod_len = strlen(biod->Name());
    int netd_len = strlen(netd->Name());
    while (!feof(fp))
    {
	char buff[128];
	if (fgets(buff, sizeof(buff), fp) == 0) break;
	if (strncmp(ttyd->Name(), buff, ttyd_len) == 0)
	    ttyd->Read(buff+ttyd_len+1);
	else if (strncmp(biod->Name(), buff, biod_len) == 0)
	    biod->Read(buff+biod_len+1);
	else if (strncmp(netd->Name(), buff, netd_len) == 0)
	    netd->Read(buff+netd_len+1);
    }
}

void KernelConfig::Dump(FILE *fp)
{
    PRECONDITION(fp != 0);
    ttyd->Dump(fp);
    biod->Dump(fp);
    netd->Dump(fp);
}

void KernelConfig::Dump()
{
    Dump(stdout);
}

Device *KernelConfig::GetDevice(const char *name, int unit)
{
    PRECONDITION(name != 0);
    Device *d;
    char nm[10];
    assert(strlen(name) < sizeof(nm));
    STRLCPY(nm, name, sizeof(nm));
    int l = strlen(nm);
    if (isdigit(nm[l-1])) { unit = nm[l-1]-'0'; nm[l-1] = 0; }
    if ((d = ttyd->Get(nm, unit)) != 0 ||
	(d = biod->Get(nm, unit)) != 0 ||
	(d = netd->Get(nm, unit)) != 0)
	    return d;
    return 0;
}

int KernelConfig::DeviceDriverDetected(const char *name, int unit)
{
    PRECONDITION(name != 0);
    Device *d = GetDevice(name, unit);;
    return d ? 1 : 0;
}

int KernelConfig::DeviceDetected(const char *name, int unit)
{
    PRECONDITION(name != 0);
    Device *d = GetDevice(name, unit);;
    return d ? d->Detected() : 0;
}

int KernelConfig::DeviceEnabled(const char *name, int unit)
{
    PRECONDITION(name != 0);
    Device *d = GetDevice(name, unit);
    return d ? d->Enabled() : 0;
}

int KernelConfig::NumDetectedSerialPorts()
{
    int rtn = 0;
    if (DeviceDetected("sio", 0)) rtn++;
    if (DeviceDetected("sio", 1)) rtn++;
    if (DeviceDetected("sio", 2)) rtn++;
    if (DeviceDetected("sio", 3)) rtn++;
    return rtn;
}

int KernelConfig::NumEnabledSerialPorts()
{
    int rtn = 0;
    if (DeviceEnabled("sio", 0)) rtn++;
    if (DeviceEnabled("sio", 1)) rtn++;
    if (DeviceEnabled("sio", 2)) rtn++;
    if (DeviceEnabled("sio", 3)) rtn++;
    return rtn;
}

int KernelConfig::NumDetectedParallelPorts()
{
    int rtn = 0;
    if (DeviceDetected("lpt", 0)) rtn++;
    if (DeviceDetected("lpt", 1)) rtn++;
    return rtn;
}

int KernelConfig::NumEnabledParallelPorts()
{
    int rtn = 0;
    if (DeviceEnabled("lpt", 0)) rtn++;
    if (DeviceEnabled("lpt", 1)) rtn++;
    return rtn;
}

const char *KernelConfig::GetDetectedSerialPort(int unit)
{
    return  DeviceDetected("sio", unit) ? "sio" : 0;
}

const char *KernelConfig::GetEnabledSerialPort(int unit)
{
    return DeviceEnabled("sio", unit) ? "sio" : 0;
}

const char *KernelConfig::GetDetectedParallelPort(int unit)
{
    return  DeviceDetected("lpt", unit) ? "lpt" : 0;
}

const char *KernelConfig::GetEnabledParallelPort(int unit)
{
    return DeviceEnabled("lpt", unit) ? "lpt" : 0;
}

const char *KernelConfig::GetDetectedDevice(char typecode, int unit)
{
    for (int i = 0; BSDKernelDevices[i][0]; i++)
        if (BSDKernelDevices[i][0][0] == typecode)
	    if (DeviceDetected(BSDKernelDevices[i][1], unit))
	        return BSDKernelDevices[i][1];
    return 0;
}

const char *KernelConfig::GetEnabledDevice(char typecode, int unit)
{
    for (int i = 0; BSDKernelDevices[i][0]; i++)
        if (BSDKernelDevices[i][0][0] == typecode)
	    if (DeviceDetected(BSDKernelDevices[i][1], unit))
	        if (DeviceEnabled(BSDKernelDevices[i][1], unit))
	            return BSDKernelDevices[i][1];
    for (int i = 0; BSDKernelDevices[i][0]; i++)
        if (BSDKernelDevices[i][0][0] == typecode)
	    if (DeviceEnabled(BSDKernelDevices[i][1], unit))
	        return BSDKernelDevices[i][1];
    return 0;
}

const char *KernelConfig::GetDetectedIDE()
{
    return GetDetectedDevice('w');
}

const char *KernelConfig::GetEnabledIDE()
{
    return GetEnabledDevice('w');
}

const char *KernelConfig::GetDetectedSCSI()
{
    return GetDetectedDevice('h');
}

const char *KernelConfig::GetEnabledSCSI()
{
    return GetEnabledDevice('h');
}

const char *KernelConfig::GetDetectedNetCard(int unit)
{
    return GetDetectedDevice('n', unit);
}

const char *KernelConfig::GetEnabledNetCard(int unit)
{
    return GetEnabledDevice('n', unit);
}

const char *KernelConfig::GetDetectedCDROM()
{
    return GetDetectedDevice('c');
}

const char *KernelConfig::GetEnabledCDROM()
{
    return GetEnabledDevice('c');
}

const char *KernelConfig::GetDetectedTape()
{
    return GetDetectedDevice('t');
}

const char *KernelConfig::GetEnabledTape()
{
    return GetEnabledDevice('t');
}

const char *KernelConfig::GetDescription(const char *dev)
{
    PRECONDITION(dev != 0);
    Device *d = GetDevice(dev);
    if (d) return d->Description();
    return "Unknown";
}

int KernelConfig::GetPort(const char *dev, int unit)
{
    PRECONDITION(dev != 0);
    Device *d = GetDevice(dev, unit);
    if (d) return d->Port();
    return 0;
}

int KernelConfig::GetIRQ(const char *dev, int unit)
{
    PRECONDITION(dev != 0);
    Device *d = GetDevice(dev, unit);
    if (d) return d->Interrupt();
    return 0;
}

int KernelConfig::GetDMA(const char *dev, int unit)
{
    PRECONDITION(dev != 0);
    Device *d = GetDevice(dev, unit);
    if (d) return d->DMAChannel();
    return -1;
}

int KernelConfig::GetMemBase(const char *dev, int unit)
{
    PRECONDITION(dev != 0);
    Device *d = GetDevice(dev, unit);
    if (d) return d->MemBase();
    return 0;
}

void KernelConfig::SetPort(int v, const char *dev, int unit)
{
    PRECONDITION(dev != 0);
#ifdef DEBUG
    fprintf(stderr, "SetPort(%d, %s, %d)\n", v, dev, unit);
#endif
    Device *d = GetDevice(dev, unit);
    if (d && d->Port()>0) d->Port(v);
}

void KernelConfig::SetIRQ(int v, const char *dev, int unit)
{
    PRECONDITION(dev != 0);
#ifdef DEBUG
    fprintf(stderr, "SetIRQ(%d, %s, %d)\n", v, dev, unit);
#endif
    Device *d = GetDevice(dev, unit);
    if (d && d->Interrupt()>0) d->Interrupt(v);
}

void KernelConfig::SetDMA(int v, const char *dev, int unit)
{
    PRECONDITION(dev != 0);
#ifdef DEBUG
    fprintf(stderr, "SetDMA(%d, %s, %d)\n", v, dev, unit);
#endif
    Device *d = GetDevice(dev, unit);
    if (d && d->DMAChannel()>=0) d->DMAChannel(v);
}

void KernelConfig::SetMemBase(int v, const char *dev, int unit)
{
    PRECONDITION(dev != 0);
#ifdef DEBUG
    fprintf(stderr, "SetMemBase(%d, %s, %d)\n", v, dev, unit);
#endif
    Device *d = GetDevice(dev, unit);
    if (d && d->MemBase()>0) d->MemBase(v);
}

void KernelConfig::Enable(int v, const char *dev, int unit)
{
    PRECONDITION(dev != 0);
#ifdef DEBUG
    fprintf(stderr, "Enable(%d, %s, %d)\n", v, dev, unit);
#endif
    Device *d = GetDevice(dev, unit);
    if (d)
	if (v) d->Enable(); else d->Disable();
}

int KernelConfig::Commit(char *kernel)
{
    char cmd[80];
    if (kernel == 0)
    {
        kernel = (char*)getbootfile();
        if (snprintf(cmd, sizeof(cmd), "cp %s %s.bak 2>/dev/null",
			kernel, kernel) >= (int)sizeof(cmd))
	    LogOverrun();
        system(cmd);
    }
    if (ttyd->Commit(kernel) == 0)
        if (biod->Commit(kernel) == 0)
            if (netd->Commit(kernel) == 0)
		return 0;
    return -1;
}

static int GetDevList(DeviceTable *devtbl, char **&list)
{
    int cnt = devtbl->NumDevs();
    if (cnt)
    {
	list = new char*[cnt];
	MemAssert(list, DevList);
	for (int i = 0, j = 0; i < cnt; i++)
	{
	    char *nm = devtbl->Get(i)->Name();
	    list[j] = new char[strlen(nm)+2];
	    MemAssert(list[j], DevListElt);
	    sprintf(list[j++], "%s%d", nm, devtbl->Get(i)->Unit());
	}
    }
    else list = 0;
    return cnt;
}

static int GetEnabledDevList(DeviceTable *devtbl, char **&list)
{
    int cnt = devtbl->NumDevs(), ecnt = 0;
    for (int i = 0; i < cnt; i++)
	if (devtbl->Get(i)->Enabled())
	    ecnt++;
    if (ecnt)
    {
	list = new char*[ecnt];
	MemAssert(list, DevList);
	for (int i = 0, j = 0; i < cnt; i++)
	{
	    if (devtbl->Get(i)->Enabled())
	    {
	        char *nm = devtbl->Get(i)->Name();
	        list[j] = new char[strlen(nm)+2];
		MemAssert(list[j], DevListElt);
		sprintf(list[j++], "%s%d", nm, devtbl->Get(i)->Unit());
	    }
	}
    }
    else list = 0;
    return ecnt;
}

// GetNetDevList - returns the number of configured network interfaces,
//	plus a list of their names. This is like GetIfaceList except
//	it gets the list from the kernel, not with netstat.

int KernelConfig::GetNetDevList(char **&list)
{
    return ::GetDevList(netd, list);
}

// This only returns the ones that are enabled 

int KernelConfig::GetEnabledNetDevList(char **&list)
{
    return ::GetEnabledDevList(netd, list);
}

int KernelConfig::GetNumDevices()
{
    return (ttyd->NumDevs()+biod->NumDevs()+netd->NumDevs());
}

struct isa_device &KernelConfig::GetDevice(int n, char *name, int nsiz)
{
    DeviceTable *tbl = 0;
    if (n < ttyd->NumDevs())
        tbl = ttyd;
    else
    {
        n -= ttyd->NumDevs();
        if (n < biod->NumDevs())
	    tbl = biod;
	else
	{
	    n -= biod->NumDevs();
	    tbl = netd;
	}
    }
    struct isa_device &rtn = tbl->Get(n)->GetStruct();
    if (name)
    {
	snprintf(name, nsiz-1, "%s%d", tbl->Get(n)->Name(), rtn.id_unit);
	name[nsiz-1] = 0;
    }
    return rtn;
}

//-------------------------------------------------------------------------
// same thing but globally accessible

int GetNetDevList(char **&list)
{
    DeviceTable *netd = new DeviceTable("_isa_devtab_net");
    MemAssert(netd, DeviceTable);
    int rtn = ::GetDevList(netd, list);
    delete netd;
    return rtn;
}

int GetEnabledNetDevList(char **&list)
{
    DeviceTable *netd = new DeviceTable("_isa_devtab_net");
    MemAssert(netd, DeviceTable);
    int rtn = ::GetEnabledDevList(netd, list);
    delete netd;
    return rtn;
}

#endif // __FreeBSD__

--------------C3174E352F60362AEE6C8205--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3AC4A5C9.35FE775B>