Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
13b5ffa
Documentation
LICENSES
arch
block
certs
crypto
drivers
accessibility
acpi
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
clk
clocksource
comedi
connector
counter
cpufreq
cpuidle
crypto
cxl
dax
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fpga
fsi
gnss
gpio
gpu
greybus
hid
hsi
hv
hwmon
hwspinlock
hwtracing
i2c
i3c
idle
iio
infiniband
input
interconnect
iommu
ipack
irqchip
isdn
leds
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
most
mtd
mux
net
appletalk
arcnet
Kconfig
Makefile
arc-rawmode.c
arc-rimi.c
arcdevice.h
arcnet.c
capmode.c
com20020-isa.c
com20020-pci.c
com20020.c
com20020.h
com20020_cs.c
com9026.h
com90io.c
com90xx.c
rfc1051.c
rfc1201.c
bonding
caif
can
dsa
ethernet
fddi
fjes
hamradio
hippi
hyperv
ieee802154
ipa
ipvlan
mctp
mdio
netdevsim
pcs
phy
plip
ppp
slip
team
usb
vmxnet3
wan
wireguard
wireless
wwan
xen-netback
Kconfig
LICENSE.SRC
Makefile
Space.c
bareudp.c
dummy.c
eql.c
geneve.c
gtp.c
ifb.c
loopback.c
macsec.c
macvlan.c
macvtap.c
mdio.c
mhi_net.c
mii.c
net_failover.c
netconsole.c
nlmon.c
ntb_netdev.c
rionet.c
sb1000.c
sungem_phy.c
tap.c
thunderbolt.c
tun.c
veth.c
virtio_net.c
vrf.c
vsockmon.c
vxlan.c
xen-netfront.c
nfc
ntb
nubus
nvdimm
nvme
nvmem
of
opp
parisc
parport
pci
pcmcia
perf
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sh
siox
slimbus
soc
soundwire
spi
spmi
ssb
staging
target
tc
tee
thermal
thunderbolt
tty
uio
usb
vdpa
vfio
vhost
video
virt
virtio
visorbus
vlynq
vme
w1
watchdog
xen
zorro
Kconfig
Makefile
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
drivers
/
net
/
arcnet
/
com90io.c
Copy path
Blame
Blame
Latest commit
History
History
426 lines (351 loc) · 11.5 KB
Breadcrumbs
linux
/
drivers
/
net
/
arcnet
/
com90io.c
Top
File metadata and controls
Code
Blame
426 lines (351 loc) · 11.5 KB
Raw
/* * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers) * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares <mj@ucw.cz>. * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) * for sponsoring the further development of this driver. * * ********************** * * The original copyright of skeleton.c was as follows: * * skeleton.c Written 1993 by Donald Becker. * Copyright 1993 United States Government as represented by the * Director, National Security Agency. This software may only be used * and distributed according to the terms of the GNU General Public License as * modified by SRC, incorporated herein by reference. * * ********************** * * For more details, see drivers/net/arcnet.c * * ********************** */ #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/memblock.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include "arcdevice.h" #include "com9026.h" /* Internal function declarations */ static int com90io_found(struct net_device *dev); static void com90io_command(struct net_device *dev, int command); static int com90io_status(struct net_device *dev); static void com90io_setmask(struct net_device *dev, int mask); static int com90io_reset(struct net_device *dev, int really_reset); static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); /* Handy defines for ARCnet specific stuff */ /* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 16 /**************************************************************************** * * * IO-mapped operation routines * * * ****************************************************************************/ #undef ONE_AT_A_TIME_TX #undef ONE_AT_A_TIME_RX static u_char get_buffer_byte(struct net_device *dev, unsigned offset) { int ioaddr = dev->base_addr; arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI); arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); } #ifdef ONE_AT_A_TIME_TX static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum) { int ioaddr = dev->base_addr; arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI); arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA); } #endif static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) { int ioaddr = dev->base_addr; arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); while (length--) #ifdef ONE_AT_A_TIME_RX *(dest++) = get_buffer_byte(dev, offset++); #else *(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); #endif } static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) { int ioaddr = dev->base_addr; arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO); while (length--) #ifdef ONE_AT_A_TIME_TX put_buffer_byte(dev, offset++, *(dest++)); #else arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA); #endif } /* We cannot probe for an IO mapped card either, although we can check that * it's where we were told it was, and even autoirq */ static int __init com90io_probe(struct net_device *dev) { int ioaddr = dev->base_addr, status; unsigned long airqmask; if (BUGLVL(D_NORMAL)) { pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)"); pr_info("E-mail me if you actually test this driver, please!\n"); } if (!ioaddr) { arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n", ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) { arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n", ioaddr); goto err_out; } arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n", status); goto err_out; } arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status); arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n", status); status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if (status & RESETflag) { arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n", status); goto err_out; } arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag, ioaddr, COM9026_REG_RW_CONFIG); /* Read first loc'n of memory */ arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); arcnet_outb(0, ioaddr, COM9026_REG_W_ADDR_LO); status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); if (status != 0xd1) { arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n", status); goto err_out; } if (!dev->irq) { /* if we do this, we're sure to get an IRQ since the * card has just reset and the NORXflag is on until * we tell it to start receiving. */ airqmask = probe_irq_on(); arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK); udelay(1); arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n"); goto err_out; } } release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */ return com90io_found(dev); err_out: release_region(ioaddr, ARCNET_TOTAL_SIZE); return -ENODEV; } /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ static int __init com90io_found(struct net_device *dev) { struct arcnet_local *lp; int ioaddr = dev->base_addr; int err; /* Reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } /* Reserve the I/O region */ if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { free_irq(dev->irq, dev); return -EBUSY; } lp = netdev_priv(dev); lp->card_name = "COM90xx I/O"; lp->hw.command = com90io_command; lp->hw.status = com90io_status; lp->hw.intmask = com90io_setmask; lp->hw.reset = com90io_reset; lp->hw.owner = THIS_MODULE; lp->hw.copy_to_card = com90io_copy_to_card; lp->hw.copy_from_card = com90io_copy_from_card; lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag; arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG); /* get and check the station ID from offset 1 in shmem */ arcnet_set_addr(dev, get_buffer_byte(dev, 1)); err = register_netdev(dev); if (err) { arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag, ioaddr, COM9026_REG_RW_CONFIG); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); return err; } arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", dev->dev_addr[0], dev->base_addr, dev->irq); return 0; } /* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * * However, it does make sure the card is in a defined state. */ static int com90io_reset(struct net_device *dev, int really_reset) { struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS)); if (really_reset) { /* reset the card */ arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); } /* Set the thing to IO-mapped, 8-bit mode */ lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag; arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG); arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND); /* clear flags & end reset */ arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); /* verify that the ARCnet signature byte is present */ if (get_buffer_byte(dev, 0) != TESTvalue) { arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND); /* done! return success. */ return 0; } static void com90io_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND); } static int com90io_status(struct net_device *dev) { short ioaddr = dev->base_addr; return arcnet_inb(ioaddr, COM9026_REG_R_STATUS); } static void com90io_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK); } static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { TIME(dev, "put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { TIME(dev, "get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static int io; /* use the insmod io= irq= shmem= options */ static int irq; static char device[9]; /* use eg. device=arc1 to change name */ module_param_hw(io, int, ioport, 0); module_param_hw(irq, int, irq, 0); module_param_string(device, device, sizeof(device), 0); MODULE_LICENSE("GPL"); #ifndef MODULE static int __init com90io_setup(char *s) { int ints[4]; s = get_options(s, 4, ints); if (!ints[0]) return 0; switch (ints[0]) { default: /* ERROR */ pr_err("Too many arguments\n"); fallthrough; case 2: /* IRQ */ irq = ints[2]; fallthrough; case 1: /* IO address */ io = ints[1]; } if (*s) snprintf(device, sizeof(device), "%s", s); return 1; } __setup("com90io=", com90io_setup); #endif static struct net_device *my_dev; static int __init com90io_init(void) { struct net_device *dev; int err; dev = alloc_arcdev(device); if (!dev) return -ENOMEM; dev->base_addr = io; dev->irq = irq; if (dev->irq == 2) dev->irq = 9; err = com90io_probe(dev); if (err) { free_arcdev(dev); return err; } my_dev = dev; return 0; } static void __exit com90io_exit(void) { struct net_device *dev = my_dev; int ioaddr = dev->base_addr; unregister_netdev(dev); /* In case the old driver is loaded later, * set the thing back to MMAP mode */ arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag, ioaddr, COM9026_REG_RW_CONFIG); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); free_arcdev(dev); } module_init(com90io_init) module_exit(com90io_exit)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
You can’t perform that action at this time.