Skip to content

Commit

Permalink
Merge pull request #1338 from ghaerr/eth
Browse files Browse the repository at this point in the history
[kernel] First pass at allowing multiple NIC device drivers in kernel
  • Loading branch information
ghaerr committed Jun 20, 2022
2 parents cee618a + 26a9cd5 commit 6ce5756
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 70 deletions.
4 changes: 4 additions & 0 deletions elks/arch/i86/drivers/char/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ include $(BASEDIR)/Makefile-rules

OBJS = init.o mem.o ntty.o meta.o tcpdev.o pty.o lp.o

ifeq ($(CONFIG_ETH), y)
OBJS += eth.o
endif

ifeq ($(CONFIG_ARCH_8018X), y)
CONIO = 8018x
SERIAL = template
Expand Down
123 changes: 123 additions & 0 deletions elks/arch/i86/drivers/char/eth.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* ELKS Ethernet char device driver
* June 2022 Greg Haerr
*/

#include <linuxmt/init.h>
#include <linuxmt/major.h>
#include <linuxmt/errno.h>
#include <linuxmt/kernel.h>
#include <linuxmt/sched.h>

/* character devices and their minor numbers */
extern struct file_operations ne2k_fops; /* 0 CONFIG_ETH_NE2K */
extern struct file_operations wd_fops; /* 1 CONFIG_ETH_WD */
extern struct file_operations el3_fops; /* 2 CONFIG_ETH_EL3 */

#define MAX_ETHS 3

struct eth {
struct file_operations *ops;
};
static struct eth eths[MAX_ETHS];

/* return file_operations pointer from minor number */
static struct file_operations *get_ops(dev_t dev)
{
struct eth *eth = &eths[0];
unsigned short minor = MINOR(dev);

do {
if ((eth - eths) == minor)
return eth->ops;
} while (++eth < &eths[MAX_ETHS]);

return NULL;
}

static int eth_open(struct inode *inode, struct file *file)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return -ENODEV;

printk("ETH open pid %d\n", current->pid);
return ops->open(inode, file);
}

static void eth_release(struct inode *inode, struct file *file)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return;

printk("ETH close pid %d\n", current->pid);
ops->release(inode, file);
}

static size_t eth_write(struct inode *inode, struct file *file, char *data, size_t len)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return -ENODEV;
return ops->write(inode, file, data, len);
}

static size_t eth_read(struct inode *inode, struct file *file, char *data, size_t len)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return -ENODEV;
return ops->read(inode, file, data, len);
}

static int eth_ioctl(struct inode *inode, struct file *file, int cmd, char *arg)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return -ENODEV;
return ops->ioctl(inode, file, cmd, arg);
}

static int eth_select(struct inode *inode, struct file *file, int sel_type)
{
struct file_operations *ops = get_ops(inode->i_rdev);

if (!ops)
return -ENODEV;
return ops->select(inode, file, sel_type);
}

static struct file_operations eth_fops = {
NULL, /* lseek */
eth_read,
eth_write,
NULL, /* readdir */
eth_select,
eth_ioctl,
eth_open,
eth_release
};

void /*INITPROC*/ eth_init(void)
{
register_chrdev(ETH_MAJOR, "eth", &eth_fops);

#ifdef CONFIG_ETH_NE2K
eths[0].ops = &ne2k_fops;
ne2k_drv_init();
#endif
#ifdef CONFIG_ETH_WD
eths[1].ops = &wd_fops;
wd_drv_init();
#endif
#ifdef CONFIG_ETH_EL3
eths[2].ops = &el3_fops;
el3_drv_init();
#endif
}
2 changes: 1 addition & 1 deletion elks/arch/i86/drivers/net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ include $(BASEDIR)/Makefile-rules
#########################################################################
# Specific rules.

OBJS = net_drv.o
OBJS =
ifeq ($(CONFIG_ETH_NE2K), y)
OBJS += ne2k-asm.o ne2k.o
endif
Expand Down
30 changes: 12 additions & 18 deletions elks/arch/i86/drivers/net/el3.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ int net_port = EL3_PORT; /* default IO PORT, changed by netport= in /bootopts */
struct netif_stat netif_stat =
{ 0, 0, 0, 0, 0, 0, {0x52, 0x54, 0x00, 0x12, 0x34, 0x57}}; /* QEMU default + 1 */
static int ioaddr; // FIXME remove later
static int usecount = 0;
static unsigned char usecount;

struct wait_queue rxwait;
struct wait_queue txwait;
static struct wait_queue rxwait;
static struct wait_queue txwait;

static word_t el3_id_port;

static struct file_operations el3_fops =
struct file_operations el3_fops =
{
NULL, /* lseek */
el3_read,
Expand All @@ -136,20 +136,7 @@ static struct file_operations el3_fops =
};

void el3_drv_init( void ) {
int err;

ioaddr = net_port; // temporary
err = request_irq(net_irq, el3_int, INT_GENERIC);
if (err) {
printk("eth: Cannot allocate IRQ %d for EL3: %i\n",
net_irq, err);
return;
}
err = register_chrdev(ETH_MAJOR, "eth", &el3_fops);
if (err) {
printk("eth: device registration error: %i\n", err);
return;
}

// May want to probe before requesting the IRQ & device, but
// then we need a tiny probe routine, not the whole shebang.
Expand Down Expand Up @@ -524,6 +511,8 @@ static void el3_release(struct inode *inode, struct file *file)

/* But we explicitly zero the IRQ line select anyway */
outw(0x0f00, ioaddr + WN0_IRQ);

free_irq(net_irq);
}
return;
}
Expand Down Expand Up @@ -608,14 +597,19 @@ static void el3_down( void )

static int el3_open(struct inode *inode, struct file *file)
{
int i;
int i, err;
char *mac_addr = (char *)&netif_stat.mac_addr;

if (!(netif_stat.if_status & NETIF_FOUND))
return(-EINVAL); // Does not exist
if (usecount++)
return(0); // Already open

err = request_irq(net_irq, el3_int, INT_GENERIC);
if (err) {
printk("eth: EL3 unable to use IRQ %d (errno %d)\n", net_irq, err);
return err;
}
EL3WINDOW(0); // TESTING ONLY
/* Activating the board - done in _init, repeat doesn't harm */
outw(ENABLE_ADAPTER, ioaddr + WN0_CONF_CTRL);
Expand Down
29 changes: 12 additions & 17 deletions elks/arch/i86/drivers/net/ne2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ int net_port = NE2K_PORT; /* default IO PORT, changed by netport= in /bootopts *
struct netif_stat netif_stat =
{ 0, 0, 0, 0, 0, 0, {0x52, 0x54, 0x00, 0x12, 0x34, 0x57}}; /* QEMU default + 1 */

static int usecount = 0;
struct wait_queue rxwait;
struct wait_queue txwait;
static unsigned char usecount;
static struct wait_queue rxwait;
static struct wait_queue txwait;

extern word_t _ne2k_next_pk;
extern word_t _ne2k_is_8bit;
Expand Down Expand Up @@ -306,6 +306,11 @@ static int ne2k_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static int ne2k_open(struct inode *inode, struct file *file)
{
if (usecount++ == 0) { // Don't initialize if already open
int err = request_irq(net_irq, ne2k_int, INT_GENERIC);
if (err) {
printk("eth: NE2K unable to use IRQ %d (errno %d)\n", net_irq, err);
return err;
}
ne2k_reset();
ne2k_init();
ne2k_start();
Expand All @@ -319,16 +324,17 @@ static int ne2k_open(struct inode *inode, struct file *file)

static void ne2k_release(struct inode *inode, struct file *file)
{
if (--usecount == 0)
if (--usecount == 0) {
ne2k_stop();

free_irq(net_irq);
}
}

/*
* Ethernet operations
*/

static struct file_operations ne2k_fops =
struct file_operations ne2k_fops =
{
NULL, /* lseek */
ne2k_read,
Expand Down Expand Up @@ -399,17 +405,6 @@ void ne2k_drv_init(void)
printk("eth: NE2K not found at 0x%x, irq %d\n", net_port, net_irq);
break;
}
err = request_irq(net_irq, ne2k_int, INT_GENERIC);
if (err) {
printk("eth: NE2K IRQ %d request error: %i\n", net_irq, err);
break;
}

err = register_chrdev(ETH_MAJOR, "eth", &ne2k_fops);
if (err) {
printk("eth: register error: %i\n", err);
break;
}

cprom = (byte_t *)prom;

Expand Down
17 changes: 0 additions & 17 deletions elks/arch/i86/drivers/net/net_drv.c

This file was deleted.

21 changes: 8 additions & 13 deletions elks/arch/i86/drivers/net/wd.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ static unsigned char current_rx_page = WD_FIRST_RX_PG;

static word_t wd_rx_stat(void);
static word_t wd_tx_stat(void);
static void wd_int(int irq, struct pt_regs * regs);

/*
* Get MAC
Expand Down Expand Up @@ -492,6 +493,11 @@ static int wd_open(struct inode * inode, struct file * file)
err = -EBUSY;
break;
}
err = request_irq(net_irq, wd_int, INT_GENERIC);
if (err) {
printk("eth: WD unable to use IRQ %d (errno %d)\n", net_irq, err);
break;
}
wd_reset();
wd_init();
if (INB(net_port + 14U) & 0x20U) /* enable IRQ on softcfg card */
Expand All @@ -510,14 +516,15 @@ static void wd_release(struct inode * inode, struct file * file)
{
wd_stop();
wd_term();
free_irq(net_irq);
wd_inuse = 0U;
}

/*
* Ethernet operations
*/

static struct file_operations wd_fops =
struct file_operations wd_fops =
{
NULL, /* lseek */
wd_read,
Expand Down Expand Up @@ -574,22 +581,10 @@ static void wd_int(int irq, struct pt_regs * regs)

void wd_drv_init(void)
{
int err;
unsigned u;
word_t hw_addr[6U];

do {
err = request_irq(net_irq, wd_int, INT_GENERIC);
if (err) {
printk("eth: WD IRQ %d request error: %i\n",
net_irq, err);
break;
}
err = register_chrdev(ETH_MAJOR, "eth", &wd_fops);
if (err) {
printk("eth: register error: %i\n", err);
break;
}
wd_get_hw_addr(hw_addr);
for (u = 0U; u < 6U; u++)
mac_addr[u] = (hw_addr[u] & 0xffU);
Expand Down
5 changes: 5 additions & 0 deletions elks/arch/i86/kernel/irq-8018x.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ int remap_irq(int irq)
return irq;
}

void disable_irq(unsigned int irq)
{
// TODO disable passed interrupt
}

// Get interrupt vector from IRQ
int irq_vector(int irq)
{
Expand Down
2 changes: 0 additions & 2 deletions elks/arch/i86/kernel/irq-8259.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ int irq_vector (int irq)
return irq + ((irq >= 8) ? 0x68 : 0x08);
}

#if 0
void disable_irq(unsigned int irq)
{
flag_t flags;
Expand All @@ -85,4 +84,3 @@ void disable_irq(unsigned int irq)
}
restore_flags(flags);
}
#endif
Loading

0 comments on commit 6ce5756

Please sign in to comment.