Newbusify ar(4).
This commit is contained in:
parent
4c773ee5aa
commit
1acb4466b0
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999 John Hay. All rights reserved.
|
||||
* Copyright (c) 1995 - 2001 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -46,16 +46,24 @@
|
||||
*/
|
||||
|
||||
#include "opt_netgraph.h"
|
||||
#include "ar.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include "isa_if.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#ifdef NETGRAPH
|
||||
@ -70,13 +78,8 @@
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <i386/isa/if_arregs.h>
|
||||
#include <i386/isa/ic/hd64570.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
|
||||
#ifndef COMPAT_OLDISA
|
||||
#error "The ar device requires the old isa compatibility shims"
|
||||
#endif
|
||||
#include <i386/isa/if_arregs.h>
|
||||
|
||||
#ifndef NETGRAPH
|
||||
#include "sppp.h"
|
||||
@ -95,42 +98,6 @@
|
||||
|
||||
#define PPP_HEADER_LEN 4
|
||||
|
||||
#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK)
|
||||
|
||||
#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
ARC_GET_WIN(win))
|
||||
#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0))
|
||||
#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0)
|
||||
|
||||
struct ar_hardc {
|
||||
int cunit;
|
||||
struct ar_softc *sc;
|
||||
u_short iobase;
|
||||
int isa_irq;
|
||||
int numports;
|
||||
caddr_t mem_start;
|
||||
caddr_t mem_end;
|
||||
u_char *orbase;
|
||||
|
||||
u_int memsize; /* in bytes */
|
||||
u_int winsize; /* in bytes */
|
||||
u_int winmsk;
|
||||
u_char bustype; /* ISA, MCA, PCI.... */
|
||||
u_char interface[NPORT];/* X21, V.35, EIA-530.... */
|
||||
u_char revision;
|
||||
u_char handshake; /* handshake lines supported by card. */
|
||||
|
||||
u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */
|
||||
u_int txc_dtr_off[NPORT/NCHAN];
|
||||
|
||||
sca_regs *sca[NPORT/NCHAN];
|
||||
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
static struct ar_hardc ar_hardc[NAR];
|
||||
|
||||
struct ar_softc {
|
||||
#ifndef NETGRAPH
|
||||
struct sppp ifsppp;
|
||||
@ -188,15 +155,14 @@ struct ar_softc {
|
||||
#endif /* NETGRAPH */
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
|
||||
#ifdef NETGRAPH
|
||||
#define DOG_HOLDOFF 6 /* dog holds off for 6 secs */
|
||||
#define QUITE_A_WHILE 300 /* 5 MINUTES */
|
||||
#define LOTS_OF_PACKETS 100
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
static int arprobe(struct isa_device *id);
|
||||
static int arattach_isa(struct isa_device *id);
|
||||
|
||||
/*
|
||||
* This translate from irq numbers to
|
||||
* the value that the arnet card needs
|
||||
@ -222,19 +188,36 @@ static int irqtable[16] = {
|
||||
7 /* 15 */
|
||||
};
|
||||
|
||||
struct isa_driver ardriver = {
|
||||
INTR_TYPE_NET,
|
||||
arprobe,
|
||||
arattach_isa,
|
||||
"ar"
|
||||
static int ar_isa_probe (device_t);
|
||||
static int ar_isa_attach (device_t);
|
||||
|
||||
static struct isa_pnp_id ar_ids[] = {
|
||||
{0, NULL}
|
||||
};
|
||||
COMPAT_ISA_DRIVER(ar, ardriver);
|
||||
|
||||
struct ar_hardc *arattach_pci(int unit, vm_offset_t mem_addr);
|
||||
void arintr_hc(struct ar_hardc *hc);
|
||||
static device_method_t ar_methods[] = {
|
||||
DEVMETHOD(device_probe, ar_isa_probe),
|
||||
DEVMETHOD(device_attach, ar_isa_attach),
|
||||
DEVMETHOD(device_detach, ar_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static ointhand2_t arintr;
|
||||
static int arattach(struct ar_hardc *hc);
|
||||
static driver_t ar_isa_driver = {
|
||||
"ar",
|
||||
ar_methods,
|
||||
sizeof (struct ar_hardc)
|
||||
};
|
||||
|
||||
devclass_t ar_devclass;
|
||||
|
||||
DRIVER_MODULE(if_ar, isa, ar_isa_driver, ar_devclass, 0, 0);
|
||||
#ifndef NETGRAPH
|
||||
MODULE_DEPEND(if_ar, sppp, 1, 1, 1);
|
||||
#else
|
||||
MODULE_DEPEND(ng_sync_ar, netgraph, 1, 1, 1);
|
||||
#endif
|
||||
|
||||
static void arintr(void *arg);
|
||||
static void ar_xmit(struct ar_softc *sc);
|
||||
#ifndef NETGRAPH
|
||||
static void arstart(struct ifnet *ifp);
|
||||
@ -293,20 +276,22 @@ static int ngar_done_init = 0;
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
/*
|
||||
* Register the Adapter.
|
||||
* Probe to see if it is there.
|
||||
* Get its information and fill it in.
|
||||
*/
|
||||
static int
|
||||
arprobe(struct isa_device *id)
|
||||
ar_isa_probe(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
u_int tmp;
|
||||
u_short port;
|
||||
int error;
|
||||
u_long membase, memsize, port_start, port_count;
|
||||
|
||||
/*
|
||||
* Register the card.
|
||||
*/
|
||||
error = ISA_PNP_PROBE(device_get_parent(device), device, ar_ids);
|
||||
if(error == ENXIO || error == 0)
|
||||
return (error);
|
||||
|
||||
if((error = ar_allocate_ioport(device, 0, ARC_IO_SIZ))) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now see if the card is realy there.
|
||||
@ -314,65 +299,23 @@ arprobe(struct isa_device *id)
|
||||
* XXX For now I just check the undocumented ports
|
||||
* for "570". We will probably have to do more checking.
|
||||
*/
|
||||
port = id->id_iobase;
|
||||
error = bus_get_resource(device, SYS_RES_IOPORT, 0, &port_start,
|
||||
&port_count);
|
||||
|
||||
if((inb(port+AR_ID_5) != '5') || (inb(port+AR_ID_7) != '7') ||
|
||||
(inb(port+AR_ID_0) != '0'))
|
||||
return 0;
|
||||
/*
|
||||
* We have a card here, fill in what we can.
|
||||
*/
|
||||
tmp = inb(port + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(port + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = inb(port + AR_PNUM);
|
||||
hc->handshake = inb(port + AR_HNDSH);
|
||||
|
||||
id->id_msize = hc->winsize;
|
||||
|
||||
hc->iobase = id->id_iobase;
|
||||
hc->mem_start = id->id_maddr;
|
||||
hc->mem_end = id->id_maddr + id->id_msize;
|
||||
hc->cunit = id->id_unit;
|
||||
hc->isa_irq = id->id_irq;
|
||||
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
id->id_unit);
|
||||
return 0;
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
if((inb(port_start + AR_ID_5) != '5') ||
|
||||
(inb(port_start + AR_ID_7) != '7') ||
|
||||
(inb(port_start + AR_ID_0) != '0')) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
|
||||
memsize = inb(port_start + AR_REV);
|
||||
memsize = 1 << ((memsize & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
memsize *= ARC_WIN_SIZ;
|
||||
error = bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize);
|
||||
ar_deallocate_resources(device);
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024)))
|
||||
return 0;
|
||||
|
||||
return ARC_IO_SIZ; /* return the amount of IO addresses used. */
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -383,57 +326,93 @@ arprobe(struct isa_device *id)
|
||||
* Attach each port to sppp and bpf.
|
||||
*/
|
||||
static int
|
||||
arattach_isa(struct isa_device *id)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
id->id_ointr = arintr;
|
||||
return arattach(hc);
|
||||
}
|
||||
|
||||
struct ar_hardc *
|
||||
arattach_pci(int unit, vm_offset_t mem_addr)
|
||||
ar_isa_attach(device_t device)
|
||||
{
|
||||
u_int tmp;
|
||||
u_long irq, junk;
|
||||
struct ar_hardc *hc;
|
||||
u_int i, tmp;
|
||||
|
||||
hc = malloc(sizeof(struct ar_hardc), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
if(ar_allocate_ioport(device, 0, ARC_IO_SIZ))
|
||||
return (ENXIO);
|
||||
hc->bt = rman_get_bustag(hc->res_ioport);
|
||||
hc->bh = rman_get_bushandle(hc->res_ioport);
|
||||
|
||||
hc->cunit = unit;
|
||||
hc->mem_start = (caddr_t)mem_addr;
|
||||
hc->sca[0] = (sca_regs *)(mem_addr + AR_PCI_SCA_1_OFFSET);
|
||||
hc->sca[1] = (sca_regs *)(mem_addr + AR_PCI_SCA_2_OFFSET);
|
||||
hc->iobase = 0;
|
||||
hc->orbase = (u_char *)(mem_addr + AR_PCI_ORBASE_OFFSET);
|
||||
hc->iobase = rman_get_start(hc->res_ioport);
|
||||
|
||||
tmp = hc->orbase[AR_BMI * 4];
|
||||
tmp = inb(hc->iobase + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
tmp = hc->orbase[AR_REV * 4];
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(hc->iobase + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = (1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT)) * 16 * 1024;
|
||||
hc->mem_end = (caddr_t)(mem_addr + hc->winsize);
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = hc->orbase[AR_PNUM * 4];
|
||||
hc->handshake = hc->orbase[AR_HNDSH * 4];
|
||||
hc->numports = inb(hc->iobase + AR_PNUM);
|
||||
hc->handshake = inb(hc->iobase + AR_HNDSH);
|
||||
|
||||
for(i = 1; i < hc->numports; i++)
|
||||
hc->interface[i] = hc->interface[0];
|
||||
if(ar_allocate_memory(device, 0, hc->winsize))
|
||||
return (ENXIO);
|
||||
|
||||
TRC(printf("arp%d: bus %x, rev %d, memstart %p, winsize %d, "
|
||||
"winmsk %x, interface %x\n",
|
||||
unit, hc->bustype, hc->revision, hc->mem_start, hc->winsize,
|
||||
hc->winmsk, hc->interface[0]));
|
||||
hc->mem_start = rman_get_virtual(hc->res_memory);
|
||||
hc->mem_end = hc->mem_start + hc->winsize;
|
||||
hc->cunit = device_get_unit(device);
|
||||
|
||||
arattach(hc);
|
||||
return hc;
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
hc->cunit);
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024))) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if(ar_allocate_irq(device, 0, 1))
|
||||
return (ENXIO);
|
||||
|
||||
if(bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
hc->isa_irq = irq;
|
||||
|
||||
if(ar_attach(device)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
arattach(struct ar_hardc *hc)
|
||||
int
|
||||
ar_attach(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
struct ar_softc *sc;
|
||||
#ifndef NETGRAPH
|
||||
struct ifnet *ifp;
|
||||
@ -441,6 +420,8 @@ arattach(struct ar_hardc *hc)
|
||||
#endif /* NETGRAPH */
|
||||
int unit;
|
||||
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
|
||||
printf("arc%d: %uK RAM, %u ports, rev %u.\n",
|
||||
hc->cunit,
|
||||
hc->memsize/1024,
|
||||
@ -449,6 +430,10 @@ arattach(struct ar_hardc *hc)
|
||||
|
||||
arc_init(hc);
|
||||
|
||||
if(BUS_SETUP_INTR(device_get_parent(device), device, hc->res_irq,
|
||||
INTR_TYPE_NET, arintr, hc, &hc->intr_cookie) != 0)
|
||||
return (1);
|
||||
|
||||
sc = hc->sc;
|
||||
|
||||
for(unit=0;unit<hc->numports;unit+=NCHAN)
|
||||
@ -508,11 +493,11 @@ arattach(struct ar_hardc *hc)
|
||||
*/
|
||||
if (ngar_done_init == 0) ngar_init(NULL);
|
||||
if (ng_make_node_common(&typestruct, &sc->node) != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
|
||||
if (ng_name_node(sc->node, sc->nodename)) {
|
||||
NG_NODE_UNREF(sc->node); /* drop it again */
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
NG_NODE_SET_PRIVATE(sc->node, sc);
|
||||
callout_handle_init(&sc->handle);
|
||||
@ -527,7 +512,139 @@ arattach(struct ar_hardc *hc)
|
||||
if(hc->bustype == AR_BUS_ISA)
|
||||
ARC_SET_OFF(hc->iobase);
|
||||
|
||||
return 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ar_detach(device_t device)
|
||||
{
|
||||
device_t parent = device_get_parent(device);
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->intr_cookie != NULL) {
|
||||
if (BUS_TEARDOWN_INTR(parent, device,
|
||||
hc->res_irq, hc->intr_cookie) != 0) {
|
||||
printf("intr teardown failed.. continuing\n");
|
||||
}
|
||||
hc->intr_cookie = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* deallocate any system resources we may have
|
||||
* allocated on behalf of this driver.
|
||||
*/
|
||||
FREE(hc->sc, M_DEVBUF);
|
||||
hc->sc = NULL;
|
||||
hc->mem_start = NULL;
|
||||
return (ar_deallocate_resources(device));
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_ioport(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_ioport = rid;
|
||||
hc->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
|
||||
&hc->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_ioport == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_irq(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_irq = rid;
|
||||
hc->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
|
||||
&hc->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
|
||||
if (hc->res_irq == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_memory = rid;
|
||||
hc->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_plx_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_plx_memory = rid;
|
||||
hc->res_plx_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_plx_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_plx_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_deallocate_resources(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->res_irq != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
bus_release_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
hc->res_irq = 0;
|
||||
}
|
||||
if (hc->res_ioport != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
bus_release_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
hc->res_ioport = 0;
|
||||
}
|
||||
if (hc->res_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
hc->res_memory = 0;
|
||||
}
|
||||
if (hc->res_plx_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
hc->res_plx_memory = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -537,18 +654,9 @@ arattach(struct ar_hardc *hc)
|
||||
* Repeat until there is no more interrupts.
|
||||
*/
|
||||
static void
|
||||
arintr(int unit)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
|
||||
hc = &ar_hardc[unit];
|
||||
arintr_hc(hc);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
arintr_hc(struct ar_hardc *hc)
|
||||
arintr(void *arg)
|
||||
{
|
||||
struct ar_hardc *hc = (struct ar_hardc *)arg;
|
||||
sca_regs *sca;
|
||||
u_char isr0, isr1, isr2, arisr;
|
||||
int scano;
|
||||
@ -838,10 +946,10 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
TRC(printf("ar%d: ioctl: ifsppp.pp_flags = %x, if_flags %x.\n",
|
||||
ifp->if_unit, ((struct sppp *)ifp)->pp_flags, ifp->if_flags);)
|
||||
if(error)
|
||||
return error;
|
||||
return (error);
|
||||
|
||||
if((cmd != SIOCSIFFLAGS) && cmd != (SIOCSIFADDR))
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
TRC(printf("ar%d: arioctl %s.\n", ifp->if_unit,
|
||||
(cmd == SIOCSIFFLAGS) ? "SIOCSIFFLAGS" : "SIOCSIFADDR");)
|
||||
@ -862,7 +970,7 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
sppp_flush(ifp);
|
||||
}
|
||||
splx(s);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
@ -1051,7 +1159,7 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
TRC(printf("x = %x", x));
|
||||
if(x & AR_PIM_DATA) {
|
||||
printf("No PIM installed\n");
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
x = (x >> 1) & 0x01;
|
||||
@ -1105,20 +1213,20 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
*pimctrl = AR_PIM_MODEG;
|
||||
*pimctrl = AR_PIM_MODEG | AR_PIM_AUTO_LED;
|
||||
if(ctype > 255)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 239)
|
||||
return(AR_IFACE_V_35);
|
||||
return (AR_IFACE_V_35);
|
||||
if(ctype > 207)
|
||||
return(AR_IFACE_EIA_232);
|
||||
return (AR_IFACE_EIA_232);
|
||||
if(ctype > 178)
|
||||
return(AR_IFACE_X_21);
|
||||
return (AR_IFACE_X_21);
|
||||
if(ctype > 150)
|
||||
return(AR_IFACE_EIA_530);
|
||||
return (AR_IFACE_EIA_530);
|
||||
if(ctype > 25)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 7)
|
||||
return(AR_IFACE_LOOPBACK);
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_LOOPBACK);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1173,10 +1281,10 @@ arc_init(struct ar_hardc *hc)
|
||||
* Mem address, irq,
|
||||
*/
|
||||
mar = kvtop(hc->mem_start) >> 16;
|
||||
isr = irqtable[ffs(hc->isa_irq) - 1] << 1;
|
||||
isr = irqtable[hc->isa_irq] << 1;
|
||||
if(isr == 0)
|
||||
printf("ar%d: Warning illegal interrupt %d\n",
|
||||
hc->cunit, ffs(hc->isa_irq) - 1);
|
||||
hc->cunit, hc->isa_irq);
|
||||
isr = isr | ((kvtop(hc->mem_start) & 0xc000) >> 10);
|
||||
|
||||
hc->sca[0] = (sca_regs *)hc->mem_start;
|
||||
@ -1577,7 +1685,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
*rxstat = rxdesc->stat;
|
||||
TRC(printf("ar%d: PKT AVAIL len %d, %x.\n",
|
||||
sc->unit, *len, *rxstat));
|
||||
return 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
rxdesc++;
|
||||
@ -1588,7 +1696,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
|
||||
*len = 0;
|
||||
*rxstat = 0;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@ -2276,7 +2384,7 @@ ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
/*
|
||||
* get data from another node and transmit it to the correct channel
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
ngar_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
int s;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999 John Hay. All rights reserved.
|
||||
* Copyright (c) 1995 - 2001 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -46,16 +46,24 @@
|
||||
*/
|
||||
|
||||
#include "opt_netgraph.h"
|
||||
#include "ar.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include "isa_if.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#ifdef NETGRAPH
|
||||
@ -70,13 +78,8 @@
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <i386/isa/if_arregs.h>
|
||||
#include <i386/isa/ic/hd64570.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
|
||||
#ifndef COMPAT_OLDISA
|
||||
#error "The ar device requires the old isa compatibility shims"
|
||||
#endif
|
||||
#include <i386/isa/if_arregs.h>
|
||||
|
||||
#ifndef NETGRAPH
|
||||
#include "sppp.h"
|
||||
@ -95,42 +98,6 @@
|
||||
|
||||
#define PPP_HEADER_LEN 4
|
||||
|
||||
#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK)
|
||||
|
||||
#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
ARC_GET_WIN(win))
|
||||
#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0))
|
||||
#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0)
|
||||
|
||||
struct ar_hardc {
|
||||
int cunit;
|
||||
struct ar_softc *sc;
|
||||
u_short iobase;
|
||||
int isa_irq;
|
||||
int numports;
|
||||
caddr_t mem_start;
|
||||
caddr_t mem_end;
|
||||
u_char *orbase;
|
||||
|
||||
u_int memsize; /* in bytes */
|
||||
u_int winsize; /* in bytes */
|
||||
u_int winmsk;
|
||||
u_char bustype; /* ISA, MCA, PCI.... */
|
||||
u_char interface[NPORT];/* X21, V.35, EIA-530.... */
|
||||
u_char revision;
|
||||
u_char handshake; /* handshake lines supported by card. */
|
||||
|
||||
u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */
|
||||
u_int txc_dtr_off[NPORT/NCHAN];
|
||||
|
||||
sca_regs *sca[NPORT/NCHAN];
|
||||
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
static struct ar_hardc ar_hardc[NAR];
|
||||
|
||||
struct ar_softc {
|
||||
#ifndef NETGRAPH
|
||||
struct sppp ifsppp;
|
||||
@ -188,15 +155,14 @@ struct ar_softc {
|
||||
#endif /* NETGRAPH */
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
|
||||
#ifdef NETGRAPH
|
||||
#define DOG_HOLDOFF 6 /* dog holds off for 6 secs */
|
||||
#define QUITE_A_WHILE 300 /* 5 MINUTES */
|
||||
#define LOTS_OF_PACKETS 100
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
static int arprobe(struct isa_device *id);
|
||||
static int arattach_isa(struct isa_device *id);
|
||||
|
||||
/*
|
||||
* This translate from irq numbers to
|
||||
* the value that the arnet card needs
|
||||
@ -222,19 +188,36 @@ static int irqtable[16] = {
|
||||
7 /* 15 */
|
||||
};
|
||||
|
||||
struct isa_driver ardriver = {
|
||||
INTR_TYPE_NET,
|
||||
arprobe,
|
||||
arattach_isa,
|
||||
"ar"
|
||||
static int ar_isa_probe (device_t);
|
||||
static int ar_isa_attach (device_t);
|
||||
|
||||
static struct isa_pnp_id ar_ids[] = {
|
||||
{0, NULL}
|
||||
};
|
||||
COMPAT_ISA_DRIVER(ar, ardriver);
|
||||
|
||||
struct ar_hardc *arattach_pci(int unit, vm_offset_t mem_addr);
|
||||
void arintr_hc(struct ar_hardc *hc);
|
||||
static device_method_t ar_methods[] = {
|
||||
DEVMETHOD(device_probe, ar_isa_probe),
|
||||
DEVMETHOD(device_attach, ar_isa_attach),
|
||||
DEVMETHOD(device_detach, ar_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static ointhand2_t arintr;
|
||||
static int arattach(struct ar_hardc *hc);
|
||||
static driver_t ar_isa_driver = {
|
||||
"ar",
|
||||
ar_methods,
|
||||
sizeof (struct ar_hardc)
|
||||
};
|
||||
|
||||
devclass_t ar_devclass;
|
||||
|
||||
DRIVER_MODULE(if_ar, isa, ar_isa_driver, ar_devclass, 0, 0);
|
||||
#ifndef NETGRAPH
|
||||
MODULE_DEPEND(if_ar, sppp, 1, 1, 1);
|
||||
#else
|
||||
MODULE_DEPEND(ng_sync_ar, netgraph, 1, 1, 1);
|
||||
#endif
|
||||
|
||||
static void arintr(void *arg);
|
||||
static void ar_xmit(struct ar_softc *sc);
|
||||
#ifndef NETGRAPH
|
||||
static void arstart(struct ifnet *ifp);
|
||||
@ -293,20 +276,22 @@ static int ngar_done_init = 0;
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
/*
|
||||
* Register the Adapter.
|
||||
* Probe to see if it is there.
|
||||
* Get its information and fill it in.
|
||||
*/
|
||||
static int
|
||||
arprobe(struct isa_device *id)
|
||||
ar_isa_probe(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
u_int tmp;
|
||||
u_short port;
|
||||
int error;
|
||||
u_long membase, memsize, port_start, port_count;
|
||||
|
||||
/*
|
||||
* Register the card.
|
||||
*/
|
||||
error = ISA_PNP_PROBE(device_get_parent(device), device, ar_ids);
|
||||
if(error == ENXIO || error == 0)
|
||||
return (error);
|
||||
|
||||
if((error = ar_allocate_ioport(device, 0, ARC_IO_SIZ))) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now see if the card is realy there.
|
||||
@ -314,65 +299,23 @@ arprobe(struct isa_device *id)
|
||||
* XXX For now I just check the undocumented ports
|
||||
* for "570". We will probably have to do more checking.
|
||||
*/
|
||||
port = id->id_iobase;
|
||||
error = bus_get_resource(device, SYS_RES_IOPORT, 0, &port_start,
|
||||
&port_count);
|
||||
|
||||
if((inb(port+AR_ID_5) != '5') || (inb(port+AR_ID_7) != '7') ||
|
||||
(inb(port+AR_ID_0) != '0'))
|
||||
return 0;
|
||||
/*
|
||||
* We have a card here, fill in what we can.
|
||||
*/
|
||||
tmp = inb(port + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(port + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = inb(port + AR_PNUM);
|
||||
hc->handshake = inb(port + AR_HNDSH);
|
||||
|
||||
id->id_msize = hc->winsize;
|
||||
|
||||
hc->iobase = id->id_iobase;
|
||||
hc->mem_start = id->id_maddr;
|
||||
hc->mem_end = id->id_maddr + id->id_msize;
|
||||
hc->cunit = id->id_unit;
|
||||
hc->isa_irq = id->id_irq;
|
||||
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
id->id_unit);
|
||||
return 0;
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
if((inb(port_start + AR_ID_5) != '5') ||
|
||||
(inb(port_start + AR_ID_7) != '7') ||
|
||||
(inb(port_start + AR_ID_0) != '0')) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
|
||||
memsize = inb(port_start + AR_REV);
|
||||
memsize = 1 << ((memsize & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
memsize *= ARC_WIN_SIZ;
|
||||
error = bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize);
|
||||
ar_deallocate_resources(device);
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024)))
|
||||
return 0;
|
||||
|
||||
return ARC_IO_SIZ; /* return the amount of IO addresses used. */
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -383,57 +326,93 @@ arprobe(struct isa_device *id)
|
||||
* Attach each port to sppp and bpf.
|
||||
*/
|
||||
static int
|
||||
arattach_isa(struct isa_device *id)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
id->id_ointr = arintr;
|
||||
return arattach(hc);
|
||||
}
|
||||
|
||||
struct ar_hardc *
|
||||
arattach_pci(int unit, vm_offset_t mem_addr)
|
||||
ar_isa_attach(device_t device)
|
||||
{
|
||||
u_int tmp;
|
||||
u_long irq, junk;
|
||||
struct ar_hardc *hc;
|
||||
u_int i, tmp;
|
||||
|
||||
hc = malloc(sizeof(struct ar_hardc), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
if(ar_allocate_ioport(device, 0, ARC_IO_SIZ))
|
||||
return (ENXIO);
|
||||
hc->bt = rman_get_bustag(hc->res_ioport);
|
||||
hc->bh = rman_get_bushandle(hc->res_ioport);
|
||||
|
||||
hc->cunit = unit;
|
||||
hc->mem_start = (caddr_t)mem_addr;
|
||||
hc->sca[0] = (sca_regs *)(mem_addr + AR_PCI_SCA_1_OFFSET);
|
||||
hc->sca[1] = (sca_regs *)(mem_addr + AR_PCI_SCA_2_OFFSET);
|
||||
hc->iobase = 0;
|
||||
hc->orbase = (u_char *)(mem_addr + AR_PCI_ORBASE_OFFSET);
|
||||
hc->iobase = rman_get_start(hc->res_ioport);
|
||||
|
||||
tmp = hc->orbase[AR_BMI * 4];
|
||||
tmp = inb(hc->iobase + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
tmp = hc->orbase[AR_REV * 4];
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(hc->iobase + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = (1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT)) * 16 * 1024;
|
||||
hc->mem_end = (caddr_t)(mem_addr + hc->winsize);
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = hc->orbase[AR_PNUM * 4];
|
||||
hc->handshake = hc->orbase[AR_HNDSH * 4];
|
||||
hc->numports = inb(hc->iobase + AR_PNUM);
|
||||
hc->handshake = inb(hc->iobase + AR_HNDSH);
|
||||
|
||||
for(i = 1; i < hc->numports; i++)
|
||||
hc->interface[i] = hc->interface[0];
|
||||
if(ar_allocate_memory(device, 0, hc->winsize))
|
||||
return (ENXIO);
|
||||
|
||||
TRC(printf("arp%d: bus %x, rev %d, memstart %p, winsize %d, "
|
||||
"winmsk %x, interface %x\n",
|
||||
unit, hc->bustype, hc->revision, hc->mem_start, hc->winsize,
|
||||
hc->winmsk, hc->interface[0]));
|
||||
hc->mem_start = rman_get_virtual(hc->res_memory);
|
||||
hc->mem_end = hc->mem_start + hc->winsize;
|
||||
hc->cunit = device_get_unit(device);
|
||||
|
||||
arattach(hc);
|
||||
return hc;
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
hc->cunit);
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024))) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if(ar_allocate_irq(device, 0, 1))
|
||||
return (ENXIO);
|
||||
|
||||
if(bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
hc->isa_irq = irq;
|
||||
|
||||
if(ar_attach(device)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
arattach(struct ar_hardc *hc)
|
||||
int
|
||||
ar_attach(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
struct ar_softc *sc;
|
||||
#ifndef NETGRAPH
|
||||
struct ifnet *ifp;
|
||||
@ -441,6 +420,8 @@ arattach(struct ar_hardc *hc)
|
||||
#endif /* NETGRAPH */
|
||||
int unit;
|
||||
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
|
||||
printf("arc%d: %uK RAM, %u ports, rev %u.\n",
|
||||
hc->cunit,
|
||||
hc->memsize/1024,
|
||||
@ -449,6 +430,10 @@ arattach(struct ar_hardc *hc)
|
||||
|
||||
arc_init(hc);
|
||||
|
||||
if(BUS_SETUP_INTR(device_get_parent(device), device, hc->res_irq,
|
||||
INTR_TYPE_NET, arintr, hc, &hc->intr_cookie) != 0)
|
||||
return (1);
|
||||
|
||||
sc = hc->sc;
|
||||
|
||||
for(unit=0;unit<hc->numports;unit+=NCHAN)
|
||||
@ -508,11 +493,11 @@ arattach(struct ar_hardc *hc)
|
||||
*/
|
||||
if (ngar_done_init == 0) ngar_init(NULL);
|
||||
if (ng_make_node_common(&typestruct, &sc->node) != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
|
||||
if (ng_name_node(sc->node, sc->nodename)) {
|
||||
NG_NODE_UNREF(sc->node); /* drop it again */
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
NG_NODE_SET_PRIVATE(sc->node, sc);
|
||||
callout_handle_init(&sc->handle);
|
||||
@ -527,7 +512,139 @@ arattach(struct ar_hardc *hc)
|
||||
if(hc->bustype == AR_BUS_ISA)
|
||||
ARC_SET_OFF(hc->iobase);
|
||||
|
||||
return 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ar_detach(device_t device)
|
||||
{
|
||||
device_t parent = device_get_parent(device);
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->intr_cookie != NULL) {
|
||||
if (BUS_TEARDOWN_INTR(parent, device,
|
||||
hc->res_irq, hc->intr_cookie) != 0) {
|
||||
printf("intr teardown failed.. continuing\n");
|
||||
}
|
||||
hc->intr_cookie = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* deallocate any system resources we may have
|
||||
* allocated on behalf of this driver.
|
||||
*/
|
||||
FREE(hc->sc, M_DEVBUF);
|
||||
hc->sc = NULL;
|
||||
hc->mem_start = NULL;
|
||||
return (ar_deallocate_resources(device));
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_ioport(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_ioport = rid;
|
||||
hc->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
|
||||
&hc->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_ioport == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_irq(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_irq = rid;
|
||||
hc->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
|
||||
&hc->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
|
||||
if (hc->res_irq == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_memory = rid;
|
||||
hc->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_plx_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_plx_memory = rid;
|
||||
hc->res_plx_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_plx_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_plx_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_deallocate_resources(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->res_irq != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
bus_release_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
hc->res_irq = 0;
|
||||
}
|
||||
if (hc->res_ioport != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
bus_release_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
hc->res_ioport = 0;
|
||||
}
|
||||
if (hc->res_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
hc->res_memory = 0;
|
||||
}
|
||||
if (hc->res_plx_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
hc->res_plx_memory = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -537,18 +654,9 @@ arattach(struct ar_hardc *hc)
|
||||
* Repeat until there is no more interrupts.
|
||||
*/
|
||||
static void
|
||||
arintr(int unit)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
|
||||
hc = &ar_hardc[unit];
|
||||
arintr_hc(hc);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
arintr_hc(struct ar_hardc *hc)
|
||||
arintr(void *arg)
|
||||
{
|
||||
struct ar_hardc *hc = (struct ar_hardc *)arg;
|
||||
sca_regs *sca;
|
||||
u_char isr0, isr1, isr2, arisr;
|
||||
int scano;
|
||||
@ -838,10 +946,10 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
TRC(printf("ar%d: ioctl: ifsppp.pp_flags = %x, if_flags %x.\n",
|
||||
ifp->if_unit, ((struct sppp *)ifp)->pp_flags, ifp->if_flags);)
|
||||
if(error)
|
||||
return error;
|
||||
return (error);
|
||||
|
||||
if((cmd != SIOCSIFFLAGS) && cmd != (SIOCSIFADDR))
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
TRC(printf("ar%d: arioctl %s.\n", ifp->if_unit,
|
||||
(cmd == SIOCSIFFLAGS) ? "SIOCSIFFLAGS" : "SIOCSIFADDR");)
|
||||
@ -862,7 +970,7 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
sppp_flush(ifp);
|
||||
}
|
||||
splx(s);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
@ -1051,7 +1159,7 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
TRC(printf("x = %x", x));
|
||||
if(x & AR_PIM_DATA) {
|
||||
printf("No PIM installed\n");
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
x = (x >> 1) & 0x01;
|
||||
@ -1105,20 +1213,20 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
*pimctrl = AR_PIM_MODEG;
|
||||
*pimctrl = AR_PIM_MODEG | AR_PIM_AUTO_LED;
|
||||
if(ctype > 255)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 239)
|
||||
return(AR_IFACE_V_35);
|
||||
return (AR_IFACE_V_35);
|
||||
if(ctype > 207)
|
||||
return(AR_IFACE_EIA_232);
|
||||
return (AR_IFACE_EIA_232);
|
||||
if(ctype > 178)
|
||||
return(AR_IFACE_X_21);
|
||||
return (AR_IFACE_X_21);
|
||||
if(ctype > 150)
|
||||
return(AR_IFACE_EIA_530);
|
||||
return (AR_IFACE_EIA_530);
|
||||
if(ctype > 25)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 7)
|
||||
return(AR_IFACE_LOOPBACK);
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_LOOPBACK);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1173,10 +1281,10 @@ arc_init(struct ar_hardc *hc)
|
||||
* Mem address, irq,
|
||||
*/
|
||||
mar = kvtop(hc->mem_start) >> 16;
|
||||
isr = irqtable[ffs(hc->isa_irq) - 1] << 1;
|
||||
isr = irqtable[hc->isa_irq] << 1;
|
||||
if(isr == 0)
|
||||
printf("ar%d: Warning illegal interrupt %d\n",
|
||||
hc->cunit, ffs(hc->isa_irq) - 1);
|
||||
hc->cunit, hc->isa_irq);
|
||||
isr = isr | ((kvtop(hc->mem_start) & 0xc000) >> 10);
|
||||
|
||||
hc->sca[0] = (sca_regs *)hc->mem_start;
|
||||
@ -1577,7 +1685,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
*rxstat = rxdesc->stat;
|
||||
TRC(printf("ar%d: PKT AVAIL len %d, %x.\n",
|
||||
sc->unit, *len, *rxstat));
|
||||
return 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
rxdesc++;
|
||||
@ -1588,7 +1696,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
|
||||
*len = 0;
|
||||
*rxstat = 0;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@ -2276,7 +2384,7 @@ ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
/*
|
||||
* get data from another node and transmit it to the correct channel
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
ngar_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
int s;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 John Hay.
|
||||
* Copyright (c) 1999 - 2001 John Hay.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,58 +29,67 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef COMPILING_LINT
|
||||
#warning "The ar pci driver is broken and is not compiled with LINT"
|
||||
#else
|
||||
|
||||
#include "ar.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#ifndef COMPAT_OLDPCI
|
||||
#error "The ar device requires the old pci compatibility shims"
|
||||
#include <i386/isa/ic/hd64570.h>
|
||||
#include <i386/isa/if_arregs.h>
|
||||
|
||||
#ifdef TRACE
|
||||
#define TRC(x) x
|
||||
#else
|
||||
#define TRC(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The must match with the real functions in if_ar.c
|
||||
*/
|
||||
extern void *arattach_pci(int unit, vm_offset_t mem_vaddr);
|
||||
extern void arintr_hc(void *hc);
|
||||
#define TRCL(x) x
|
||||
|
||||
static const char *ar_pci_probe(pcici_t tag, pcidi_t type);
|
||||
static void ar_pci_attach(pcici_t config_id, int unit);
|
||||
static int ar_pci_probe(device_t);
|
||||
static int ar_pci_attach(device_t);
|
||||
|
||||
static u_long arc_count = NAR;
|
||||
|
||||
static struct pci_device ar_pci_driver =
|
||||
{
|
||||
"ar",
|
||||
ar_pci_probe,
|
||||
ar_pci_attach,
|
||||
&arc_count,
|
||||
NULL
|
||||
static device_method_t ar_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ar_pci_probe),
|
||||
DEVMETHOD(device_attach, ar_pci_attach),
|
||||
DEVMETHOD(device_detach, ar_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
COMPAT_PCI_DRIVER (ar_pci, ar_pci_driver);
|
||||
static driver_t ar_pci_driver = {
|
||||
"ar",
|
||||
ar_pci_methods,
|
||||
sizeof(struct ar_hardc),
|
||||
};
|
||||
|
||||
static const char *
|
||||
ar_pci_probe(pcici_t tag, pcidi_t type)
|
||||
DRIVER_MODULE(if_ar, pci, ar_pci_driver, ar_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
ar_pci_probe(device_t device)
|
||||
{
|
||||
u_int32_t type = pci_get_devid(device);
|
||||
|
||||
switch(type) {
|
||||
case 0x5012114f:
|
||||
return ("Digi SYNC/570i-PCI 2 port");
|
||||
device_set_desc(device, "Digi SYNC/570i-PCI 2 port");
|
||||
return (0);
|
||||
break;
|
||||
case 0x5010114f:
|
||||
printf("Digi SYNC/570i-PCI 2 port (mapped below 1M)\n");
|
||||
printf("Please change the jumper to select linear mode.\n");
|
||||
break;
|
||||
case 0x5013114f:
|
||||
return ("Digi SYNC/570i-PCI 4 port");
|
||||
device_set_desc(device, "Digi SYNC/570i-PCI 4 port");
|
||||
return (0);
|
||||
break;
|
||||
case 0x5011114f:
|
||||
printf("Digi SYNC/570i-PCI 4 port (mapped below 1M)\n");
|
||||
@ -89,38 +98,73 @@ ar_pci_probe(pcici_t tag, pcidi_t type)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_pci_attach(pcici_t config_id, int unit)
|
||||
static int
|
||||
ar_pci_attach(device_t device)
|
||||
{
|
||||
int error;
|
||||
u_int i, tmp;
|
||||
u_char *inten;
|
||||
void *hc;
|
||||
vm_offset_t mem_vaddr, mem_paddr;
|
||||
vm_offset_t plx_vaddr, plx_paddr;
|
||||
struct ar_hardc *hc;
|
||||
|
||||
if(!pci_map_mem(config_id, 0x10, &plx_vaddr, &plx_paddr)) {
|
||||
printf("arp: map failed.\n");
|
||||
return;
|
||||
}
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
bzero(hc, sizeof(struct ar_hardc));
|
||||
|
||||
if(!pci_map_mem(config_id, 0x18, &mem_vaddr, &mem_paddr)) {
|
||||
printf("arp: map failed.\n");
|
||||
return;
|
||||
}
|
||||
error = ar_allocate_plx_memory(device, 0x10, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
hc = arattach_pci(unit, mem_vaddr);
|
||||
if(!hc)
|
||||
return;
|
||||
error = ar_allocate_memory(device, 0x18, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
error = ar_allocate_irq(device, 0, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
hc->plx_mem = rman_get_virtual(hc->res_plx_memory);
|
||||
hc->mem_start = rman_get_virtual(hc->res_memory);
|
||||
|
||||
hc->cunit = device_get_unit(device);
|
||||
hc->sca[0] = (sca_regs *)(hc->mem_start + AR_PCI_SCA_1_OFFSET);
|
||||
hc->sca[1] = (sca_regs *)(hc->mem_start + AR_PCI_SCA_2_OFFSET);
|
||||
hc->iobase = 0;
|
||||
hc->orbase = (u_char *)(hc->mem_start + AR_PCI_ORBASE_OFFSET);
|
||||
|
||||
tmp = hc->orbase[AR_BMI * 4];
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
tmp = hc->orbase[AR_REV * 4];
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = (1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT)) * 16 * 1024;
|
||||
hc->mem_end = (caddr_t)(hc->mem_start + hc->winsize);
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = hc->orbase[AR_PNUM * 4];
|
||||
hc->handshake = hc->orbase[AR_HNDSH * 4];
|
||||
|
||||
for(i = 1; i < hc->numports; i++)
|
||||
hc->interface[i] = hc->interface[0];
|
||||
|
||||
TRC(printf("arp%d: bus %x, rev %d, memstart %p, winsize %d, "
|
||||
"winmsk %x, interface %x\n",
|
||||
unit, hc->bustype, hc->revision, hc->mem_start, hc->winsize,
|
||||
hc->winmsk, hc->interface[0]));
|
||||
|
||||
ar_attach(device);
|
||||
|
||||
/* Magic to enable the card to generate interrupts. */
|
||||
inten = (u_char *)plx_vaddr;
|
||||
inten = (u_char *)hc->plx_mem;
|
||||
inten[0x69] = 0x09;
|
||||
|
||||
if(!pci_map_int(config_id, arintr_hc, (void *)hc, &net_imask)) {
|
||||
free(hc, M_DEVBUF);
|
||||
return;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999 John Hay. All rights reserved.
|
||||
* Copyright (c) 1995 - 2001 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -167,4 +167,61 @@
|
||||
#define AR_PIM_READ AR_PIM_MODEG
|
||||
#define AR_PIM_WRITE AR_PIM_MODEY
|
||||
|
||||
#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK)
|
||||
|
||||
#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
ARC_GET_WIN(win))
|
||||
#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0))
|
||||
#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0)
|
||||
|
||||
struct ar_hardc {
|
||||
int cunit;
|
||||
struct ar_softc *sc;
|
||||
u_short iobase;
|
||||
int isa_irq;
|
||||
int numports;
|
||||
caddr_t mem_start;
|
||||
caddr_t mem_end;
|
||||
caddr_t plx_mem;
|
||||
u_char *orbase;
|
||||
|
||||
u_int memsize; /* in bytes */
|
||||
u_int winsize; /* in bytes */
|
||||
u_int winmsk;
|
||||
u_char bustype; /* ISA, MCA, PCI.... */
|
||||
u_char interface[NPORT];/* X21, V.35, EIA-530.... */
|
||||
u_char revision;
|
||||
u_char handshake; /* handshake lines supported by card. */
|
||||
|
||||
u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */
|
||||
u_int txc_dtr_off[NPORT/NCHAN];
|
||||
|
||||
sca_regs *sca[NPORT/NCHAN];
|
||||
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int rid_ioport;
|
||||
int rid_memory;
|
||||
int rid_plx_memory;
|
||||
int rid_irq;
|
||||
int rid_drq;
|
||||
struct resource* res_ioport; /* resource for port range */
|
||||
struct resource* res_memory; /* resource for mem range */
|
||||
struct resource* res_plx_memory;
|
||||
struct resource* res_irq; /* resource for irq range */
|
||||
struct resource* res_drq; /* resource for dma channel */
|
||||
void *intr_cookie;
|
||||
};
|
||||
|
||||
extern devclass_t ar_devclass;
|
||||
|
||||
int ar_allocate_ioport(device_t device, int rid, u_long size);
|
||||
int ar_allocate_irq(device_t device, int rid, u_long size);
|
||||
int ar_allocate_memory(device_t device, int rid, u_long size);
|
||||
int ar_allocate_plx_memory(device_t device, int rid, u_long size);
|
||||
int ar_deallocate_resources(device_t device);
|
||||
int ar_attach(device_t device);
|
||||
int ar_detach (device_t);
|
||||
|
||||
#endif /* _IF_ARREGS_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999 John Hay. All rights reserved.
|
||||
* Copyright (c) 1995 - 2001 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -46,16 +46,24 @@
|
||||
*/
|
||||
|
||||
#include "opt_netgraph.h"
|
||||
#include "ar.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include "isa_if.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#ifdef NETGRAPH
|
||||
@ -70,13 +78,8 @@
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <i386/isa/if_arregs.h>
|
||||
#include <i386/isa/ic/hd64570.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
|
||||
#ifndef COMPAT_OLDISA
|
||||
#error "The ar device requires the old isa compatibility shims"
|
||||
#endif
|
||||
#include <i386/isa/if_arregs.h>
|
||||
|
||||
#ifndef NETGRAPH
|
||||
#include "sppp.h"
|
||||
@ -95,42 +98,6 @@
|
||||
|
||||
#define PPP_HEADER_LEN 4
|
||||
|
||||
#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK)
|
||||
|
||||
#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
ARC_GET_WIN(win))
|
||||
#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0))
|
||||
#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0)
|
||||
|
||||
struct ar_hardc {
|
||||
int cunit;
|
||||
struct ar_softc *sc;
|
||||
u_short iobase;
|
||||
int isa_irq;
|
||||
int numports;
|
||||
caddr_t mem_start;
|
||||
caddr_t mem_end;
|
||||
u_char *orbase;
|
||||
|
||||
u_int memsize; /* in bytes */
|
||||
u_int winsize; /* in bytes */
|
||||
u_int winmsk;
|
||||
u_char bustype; /* ISA, MCA, PCI.... */
|
||||
u_char interface[NPORT];/* X21, V.35, EIA-530.... */
|
||||
u_char revision;
|
||||
u_char handshake; /* handshake lines supported by card. */
|
||||
|
||||
u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */
|
||||
u_int txc_dtr_off[NPORT/NCHAN];
|
||||
|
||||
sca_regs *sca[NPORT/NCHAN];
|
||||
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
static struct ar_hardc ar_hardc[NAR];
|
||||
|
||||
struct ar_softc {
|
||||
#ifndef NETGRAPH
|
||||
struct sppp ifsppp;
|
||||
@ -188,15 +155,14 @@ struct ar_softc {
|
||||
#endif /* NETGRAPH */
|
||||
};
|
||||
|
||||
static int next_ar_unit = 0;
|
||||
|
||||
#ifdef NETGRAPH
|
||||
#define DOG_HOLDOFF 6 /* dog holds off for 6 secs */
|
||||
#define QUITE_A_WHILE 300 /* 5 MINUTES */
|
||||
#define LOTS_OF_PACKETS 100
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
static int arprobe(struct isa_device *id);
|
||||
static int arattach_isa(struct isa_device *id);
|
||||
|
||||
/*
|
||||
* This translate from irq numbers to
|
||||
* the value that the arnet card needs
|
||||
@ -222,19 +188,36 @@ static int irqtable[16] = {
|
||||
7 /* 15 */
|
||||
};
|
||||
|
||||
struct isa_driver ardriver = {
|
||||
INTR_TYPE_NET,
|
||||
arprobe,
|
||||
arattach_isa,
|
||||
"ar"
|
||||
static int ar_isa_probe (device_t);
|
||||
static int ar_isa_attach (device_t);
|
||||
|
||||
static struct isa_pnp_id ar_ids[] = {
|
||||
{0, NULL}
|
||||
};
|
||||
COMPAT_ISA_DRIVER(ar, ardriver);
|
||||
|
||||
struct ar_hardc *arattach_pci(int unit, vm_offset_t mem_addr);
|
||||
void arintr_hc(struct ar_hardc *hc);
|
||||
static device_method_t ar_methods[] = {
|
||||
DEVMETHOD(device_probe, ar_isa_probe),
|
||||
DEVMETHOD(device_attach, ar_isa_attach),
|
||||
DEVMETHOD(device_detach, ar_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static ointhand2_t arintr;
|
||||
static int arattach(struct ar_hardc *hc);
|
||||
static driver_t ar_isa_driver = {
|
||||
"ar",
|
||||
ar_methods,
|
||||
sizeof (struct ar_hardc)
|
||||
};
|
||||
|
||||
devclass_t ar_devclass;
|
||||
|
||||
DRIVER_MODULE(if_ar, isa, ar_isa_driver, ar_devclass, 0, 0);
|
||||
#ifndef NETGRAPH
|
||||
MODULE_DEPEND(if_ar, sppp, 1, 1, 1);
|
||||
#else
|
||||
MODULE_DEPEND(ng_sync_ar, netgraph, 1, 1, 1);
|
||||
#endif
|
||||
|
||||
static void arintr(void *arg);
|
||||
static void ar_xmit(struct ar_softc *sc);
|
||||
#ifndef NETGRAPH
|
||||
static void arstart(struct ifnet *ifp);
|
||||
@ -293,20 +276,22 @@ static int ngar_done_init = 0;
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
/*
|
||||
* Register the Adapter.
|
||||
* Probe to see if it is there.
|
||||
* Get its information and fill it in.
|
||||
*/
|
||||
static int
|
||||
arprobe(struct isa_device *id)
|
||||
ar_isa_probe(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
u_int tmp;
|
||||
u_short port;
|
||||
int error;
|
||||
u_long membase, memsize, port_start, port_count;
|
||||
|
||||
/*
|
||||
* Register the card.
|
||||
*/
|
||||
error = ISA_PNP_PROBE(device_get_parent(device), device, ar_ids);
|
||||
if(error == ENXIO || error == 0)
|
||||
return (error);
|
||||
|
||||
if((error = ar_allocate_ioport(device, 0, ARC_IO_SIZ))) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now see if the card is realy there.
|
||||
@ -314,65 +299,23 @@ arprobe(struct isa_device *id)
|
||||
* XXX For now I just check the undocumented ports
|
||||
* for "570". We will probably have to do more checking.
|
||||
*/
|
||||
port = id->id_iobase;
|
||||
error = bus_get_resource(device, SYS_RES_IOPORT, 0, &port_start,
|
||||
&port_count);
|
||||
|
||||
if((inb(port+AR_ID_5) != '5') || (inb(port+AR_ID_7) != '7') ||
|
||||
(inb(port+AR_ID_0) != '0'))
|
||||
return 0;
|
||||
/*
|
||||
* We have a card here, fill in what we can.
|
||||
*/
|
||||
tmp = inb(port + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(port + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = inb(port + AR_PNUM);
|
||||
hc->handshake = inb(port + AR_HNDSH);
|
||||
|
||||
id->id_msize = hc->winsize;
|
||||
|
||||
hc->iobase = id->id_iobase;
|
||||
hc->mem_start = id->id_maddr;
|
||||
hc->mem_end = id->id_maddr + id->id_msize;
|
||||
hc->cunit = id->id_unit;
|
||||
hc->isa_irq = id->id_irq;
|
||||
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
id->id_unit);
|
||||
return 0;
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
id->id_unit);
|
||||
break;
|
||||
if((inb(port_start + AR_ID_5) != '5') ||
|
||||
(inb(port_start + AR_ID_7) != '7') ||
|
||||
(inb(port_start + AR_ID_0) != '0')) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
membase = bus_get_resource_start(device, SYS_RES_MEMORY, 0);
|
||||
memsize = inb(port_start + AR_REV);
|
||||
memsize = 1 << ((memsize & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
memsize *= ARC_WIN_SIZ;
|
||||
error = bus_set_resource(device, SYS_RES_MEMORY, 0, membase, memsize);
|
||||
ar_deallocate_resources(device);
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024)))
|
||||
return 0;
|
||||
|
||||
return ARC_IO_SIZ; /* return the amount of IO addresses used. */
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -383,57 +326,93 @@ arprobe(struct isa_device *id)
|
||||
* Attach each port to sppp and bpf.
|
||||
*/
|
||||
static int
|
||||
arattach_isa(struct isa_device *id)
|
||||
{
|
||||
struct ar_hardc *hc = &ar_hardc[id->id_unit];
|
||||
id->id_ointr = arintr;
|
||||
return arattach(hc);
|
||||
}
|
||||
|
||||
struct ar_hardc *
|
||||
arattach_pci(int unit, vm_offset_t mem_addr)
|
||||
ar_isa_attach(device_t device)
|
||||
{
|
||||
u_int tmp;
|
||||
u_long irq, junk;
|
||||
struct ar_hardc *hc;
|
||||
u_int i, tmp;
|
||||
|
||||
hc = malloc(sizeof(struct ar_hardc), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
if(ar_allocate_ioport(device, 0, ARC_IO_SIZ))
|
||||
return (ENXIO);
|
||||
hc->bt = rman_get_bustag(hc->res_ioport);
|
||||
hc->bh = rman_get_bushandle(hc->res_ioport);
|
||||
|
||||
hc->cunit = unit;
|
||||
hc->mem_start = (caddr_t)mem_addr;
|
||||
hc->sca[0] = (sca_regs *)(mem_addr + AR_PCI_SCA_1_OFFSET);
|
||||
hc->sca[1] = (sca_regs *)(mem_addr + AR_PCI_SCA_2_OFFSET);
|
||||
hc->iobase = 0;
|
||||
hc->orbase = (u_char *)(mem_addr + AR_PCI_ORBASE_OFFSET);
|
||||
hc->iobase = rman_get_start(hc->res_ioport);
|
||||
|
||||
tmp = hc->orbase[AR_BMI * 4];
|
||||
tmp = inb(hc->iobase + AR_BMI);
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
tmp = hc->orbase[AR_REV * 4];
|
||||
hc->interface[1] = hc->interface[0];
|
||||
hc->interface[2] = hc->interface[0];
|
||||
hc->interface[3] = hc->interface[0];
|
||||
tmp = inb(hc->iobase + AR_REV);
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = (1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT)) * 16 * 1024;
|
||||
hc->mem_end = (caddr_t)(mem_addr + hc->winsize);
|
||||
hc->winsize = 1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT);
|
||||
hc->winsize *= ARC_WIN_SIZ;
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = hc->orbase[AR_PNUM * 4];
|
||||
hc->handshake = hc->orbase[AR_HNDSH * 4];
|
||||
hc->numports = inb(hc->iobase + AR_PNUM);
|
||||
hc->handshake = inb(hc->iobase + AR_HNDSH);
|
||||
|
||||
for(i = 1; i < hc->numports; i++)
|
||||
hc->interface[i] = hc->interface[0];
|
||||
if(ar_allocate_memory(device, 0, hc->winsize))
|
||||
return (ENXIO);
|
||||
|
||||
TRC(printf("arp%d: bus %x, rev %d, memstart %p, winsize %d, "
|
||||
"winmsk %x, interface %x\n",
|
||||
unit, hc->bustype, hc->revision, hc->mem_start, hc->winsize,
|
||||
hc->winmsk, hc->interface[0]));
|
||||
hc->mem_start = rman_get_virtual(hc->res_memory);
|
||||
hc->mem_end = hc->mem_start + hc->winsize;
|
||||
hc->cunit = device_get_unit(device);
|
||||
|
||||
arattach(hc);
|
||||
return hc;
|
||||
switch(hc->interface[0]) {
|
||||
case AR_IFACE_EIA_232:
|
||||
printf("ar%d: The EIA 232 interface is not supported.\n",
|
||||
hc->cunit);
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
case AR_IFACE_V_35:
|
||||
break;
|
||||
case AR_IFACE_EIA_530:
|
||||
printf("ar%d: WARNING: The EIA 530 interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
case AR_IFACE_X_21:
|
||||
break;
|
||||
case AR_IFACE_COMBO:
|
||||
printf("ar%d: WARNING: The COMBO interface is untested.\n",
|
||||
hc->cunit);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a little sanity check.
|
||||
*/
|
||||
if((hc->numports > NPORT) || (hc->memsize > (512*1024))) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if(ar_allocate_irq(device, 0, 1))
|
||||
return (ENXIO);
|
||||
|
||||
if(bus_get_resource(device, SYS_RES_IRQ, 0, &irq, &junk)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
hc->isa_irq = irq;
|
||||
|
||||
if(ar_attach(device)) {
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
arattach(struct ar_hardc *hc)
|
||||
int
|
||||
ar_attach(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
struct ar_softc *sc;
|
||||
#ifndef NETGRAPH
|
||||
struct ifnet *ifp;
|
||||
@ -441,6 +420,8 @@ arattach(struct ar_hardc *hc)
|
||||
#endif /* NETGRAPH */
|
||||
int unit;
|
||||
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
|
||||
printf("arc%d: %uK RAM, %u ports, rev %u.\n",
|
||||
hc->cunit,
|
||||
hc->memsize/1024,
|
||||
@ -449,6 +430,10 @@ arattach(struct ar_hardc *hc)
|
||||
|
||||
arc_init(hc);
|
||||
|
||||
if(BUS_SETUP_INTR(device_get_parent(device), device, hc->res_irq,
|
||||
INTR_TYPE_NET, arintr, hc, &hc->intr_cookie) != 0)
|
||||
return (1);
|
||||
|
||||
sc = hc->sc;
|
||||
|
||||
for(unit=0;unit<hc->numports;unit+=NCHAN)
|
||||
@ -508,11 +493,11 @@ arattach(struct ar_hardc *hc)
|
||||
*/
|
||||
if (ngar_done_init == 0) ngar_init(NULL);
|
||||
if (ng_make_node_common(&typestruct, &sc->node) != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
sprintf(sc->nodename, "%s%d", NG_AR_NODE_TYPE, sc->unit);
|
||||
if (ng_name_node(sc->node, sc->nodename)) {
|
||||
NG_NODE_UNREF(sc->node); /* drop it again */
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
NG_NODE_SET_PRIVATE(sc->node, sc);
|
||||
callout_handle_init(&sc->handle);
|
||||
@ -527,7 +512,139 @@ arattach(struct ar_hardc *hc)
|
||||
if(hc->bustype == AR_BUS_ISA)
|
||||
ARC_SET_OFF(hc->iobase);
|
||||
|
||||
return 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ar_detach(device_t device)
|
||||
{
|
||||
device_t parent = device_get_parent(device);
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->intr_cookie != NULL) {
|
||||
if (BUS_TEARDOWN_INTR(parent, device,
|
||||
hc->res_irq, hc->intr_cookie) != 0) {
|
||||
printf("intr teardown failed.. continuing\n");
|
||||
}
|
||||
hc->intr_cookie = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* deallocate any system resources we may have
|
||||
* allocated on behalf of this driver.
|
||||
*/
|
||||
FREE(hc->sc, M_DEVBUF);
|
||||
hc->sc = NULL;
|
||||
hc->mem_start = NULL;
|
||||
return (ar_deallocate_resources(device));
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_ioport(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_ioport = rid;
|
||||
hc->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
|
||||
&hc->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_ioport == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_irq(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_irq = rid;
|
||||
hc->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
|
||||
&hc->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
|
||||
if (hc->res_irq == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_memory = rid;
|
||||
hc->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_allocate_plx_memory(device_t device, int rid, u_long size)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
hc->rid_plx_memory = rid;
|
||||
hc->res_plx_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
|
||||
&hc->rid_plx_memory, 0ul, ~0ul, size, RF_ACTIVE);
|
||||
if (hc->res_plx_memory == NULL) {
|
||||
goto errexit;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
ar_deallocate_resources(device_t device)
|
||||
{
|
||||
struct ar_hardc *hc = device_get_softc(device);
|
||||
|
||||
if (hc->res_irq != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
bus_release_resource(device, SYS_RES_IRQ,
|
||||
hc->rid_irq, hc->res_irq);
|
||||
hc->res_irq = 0;
|
||||
}
|
||||
if (hc->res_ioport != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
bus_release_resource(device, SYS_RES_IOPORT,
|
||||
hc->rid_ioport, hc->res_ioport);
|
||||
hc->res_ioport = 0;
|
||||
}
|
||||
if (hc->res_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_memory, hc->res_memory);
|
||||
hc->res_memory = 0;
|
||||
}
|
||||
if (hc->res_plx_memory != 0) {
|
||||
bus_deactivate_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
bus_release_resource(device, SYS_RES_MEMORY,
|
||||
hc->rid_plx_memory, hc->res_plx_memory);
|
||||
hc->res_plx_memory = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -537,18 +654,9 @@ arattach(struct ar_hardc *hc)
|
||||
* Repeat until there is no more interrupts.
|
||||
*/
|
||||
static void
|
||||
arintr(int unit)
|
||||
{
|
||||
struct ar_hardc *hc;
|
||||
|
||||
hc = &ar_hardc[unit];
|
||||
arintr_hc(hc);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
arintr_hc(struct ar_hardc *hc)
|
||||
arintr(void *arg)
|
||||
{
|
||||
struct ar_hardc *hc = (struct ar_hardc *)arg;
|
||||
sca_regs *sca;
|
||||
u_char isr0, isr1, isr2, arisr;
|
||||
int scano;
|
||||
@ -838,10 +946,10 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
TRC(printf("ar%d: ioctl: ifsppp.pp_flags = %x, if_flags %x.\n",
|
||||
ifp->if_unit, ((struct sppp *)ifp)->pp_flags, ifp->if_flags);)
|
||||
if(error)
|
||||
return error;
|
||||
return (error);
|
||||
|
||||
if((cmd != SIOCSIFFLAGS) && cmd != (SIOCSIFADDR))
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
TRC(printf("ar%d: arioctl %s.\n", ifp->if_unit,
|
||||
(cmd == SIOCSIFFLAGS) ? "SIOCSIFFLAGS" : "SIOCSIFADDR");)
|
||||
@ -862,7 +970,7 @@ arioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
sppp_flush(ifp);
|
||||
}
|
||||
splx(s);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
#endif /* NETGRAPH */
|
||||
|
||||
@ -1051,7 +1159,7 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
TRC(printf("x = %x", x));
|
||||
if(x & AR_PIM_DATA) {
|
||||
printf("No PIM installed\n");
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
x = (x >> 1) & 0x01;
|
||||
@ -1105,20 +1213,20 @@ ar_read_pim_iface(volatile struct ar_hardc *hc, int channel)
|
||||
*pimctrl = AR_PIM_MODEG;
|
||||
*pimctrl = AR_PIM_MODEG | AR_PIM_AUTO_LED;
|
||||
if(ctype > 255)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 239)
|
||||
return(AR_IFACE_V_35);
|
||||
return (AR_IFACE_V_35);
|
||||
if(ctype > 207)
|
||||
return(AR_IFACE_EIA_232);
|
||||
return (AR_IFACE_EIA_232);
|
||||
if(ctype > 178)
|
||||
return(AR_IFACE_X_21);
|
||||
return (AR_IFACE_X_21);
|
||||
if(ctype > 150)
|
||||
return(AR_IFACE_EIA_530);
|
||||
return (AR_IFACE_EIA_530);
|
||||
if(ctype > 25)
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
if(ctype > 7)
|
||||
return(AR_IFACE_LOOPBACK);
|
||||
return(AR_IFACE_UNKNOWN);
|
||||
return (AR_IFACE_LOOPBACK);
|
||||
return (AR_IFACE_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1173,10 +1281,10 @@ arc_init(struct ar_hardc *hc)
|
||||
* Mem address, irq,
|
||||
*/
|
||||
mar = kvtop(hc->mem_start) >> 16;
|
||||
isr = irqtable[ffs(hc->isa_irq) - 1] << 1;
|
||||
isr = irqtable[hc->isa_irq] << 1;
|
||||
if(isr == 0)
|
||||
printf("ar%d: Warning illegal interrupt %d\n",
|
||||
hc->cunit, ffs(hc->isa_irq) - 1);
|
||||
hc->cunit, hc->isa_irq);
|
||||
isr = isr | ((kvtop(hc->mem_start) & 0xc000) >> 10);
|
||||
|
||||
hc->sca[0] = (sca_regs *)hc->mem_start;
|
||||
@ -1577,7 +1685,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
*rxstat = rxdesc->stat;
|
||||
TRC(printf("ar%d: PKT AVAIL len %d, %x.\n",
|
||||
sc->unit, *len, *rxstat));
|
||||
return 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
rxdesc++;
|
||||
@ -1588,7 +1696,7 @@ ar_packet_avail(struct ar_softc *sc,
|
||||
|
||||
*len = 0;
|
||||
*rxstat = 0;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@ -2276,7 +2384,7 @@ ngar_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
/*
|
||||
* get data from another node and transmit it to the correct channel
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
ngar_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
int s;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999 John Hay. All rights reserved.
|
||||
* Copyright (c) 1995 - 2001 John Hay. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -167,4 +167,61 @@
|
||||
#define AR_PIM_READ AR_PIM_MODEG
|
||||
#define AR_PIM_WRITE AR_PIM_MODEY
|
||||
|
||||
#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK)
|
||||
|
||||
#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
ARC_GET_WIN(win))
|
||||
#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \
|
||||
AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0))
|
||||
#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0)
|
||||
|
||||
struct ar_hardc {
|
||||
int cunit;
|
||||
struct ar_softc *sc;
|
||||
u_short iobase;
|
||||
int isa_irq;
|
||||
int numports;
|
||||
caddr_t mem_start;
|
||||
caddr_t mem_end;
|
||||
caddr_t plx_mem;
|
||||
u_char *orbase;
|
||||
|
||||
u_int memsize; /* in bytes */
|
||||
u_int winsize; /* in bytes */
|
||||
u_int winmsk;
|
||||
u_char bustype; /* ISA, MCA, PCI.... */
|
||||
u_char interface[NPORT];/* X21, V.35, EIA-530.... */
|
||||
u_char revision;
|
||||
u_char handshake; /* handshake lines supported by card. */
|
||||
|
||||
u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */
|
||||
u_int txc_dtr_off[NPORT/NCHAN];
|
||||
|
||||
sca_regs *sca[NPORT/NCHAN];
|
||||
|
||||
bus_space_tag_t bt;
|
||||
bus_space_handle_t bh;
|
||||
int rid_ioport;
|
||||
int rid_memory;
|
||||
int rid_plx_memory;
|
||||
int rid_irq;
|
||||
int rid_drq;
|
||||
struct resource* res_ioport; /* resource for port range */
|
||||
struct resource* res_memory; /* resource for mem range */
|
||||
struct resource* res_plx_memory;
|
||||
struct resource* res_irq; /* resource for irq range */
|
||||
struct resource* res_drq; /* resource for dma channel */
|
||||
void *intr_cookie;
|
||||
};
|
||||
|
||||
extern devclass_t ar_devclass;
|
||||
|
||||
int ar_allocate_ioport(device_t device, int rid, u_long size);
|
||||
int ar_allocate_irq(device_t device, int rid, u_long size);
|
||||
int ar_allocate_memory(device_t device, int rid, u_long size);
|
||||
int ar_allocate_plx_memory(device_t device, int rid, u_long size);
|
||||
int ar_deallocate_resources(device_t device);
|
||||
int ar_attach(device_t device);
|
||||
int ar_detach (device_t);
|
||||
|
||||
#endif /* _IF_ARREGS_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 John Hay.
|
||||
* Copyright (c) 1999 - 2001 John Hay.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,58 +29,67 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef COMPILING_LINT
|
||||
#warning "The ar pci driver is broken and is not compiled with LINT"
|
||||
#else
|
||||
|
||||
#include "ar.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#ifndef COMPAT_OLDPCI
|
||||
#error "The ar device requires the old pci compatibility shims"
|
||||
#include <i386/isa/ic/hd64570.h>
|
||||
#include <i386/isa/if_arregs.h>
|
||||
|
||||
#ifdef TRACE
|
||||
#define TRC(x) x
|
||||
#else
|
||||
#define TRC(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The must match with the real functions in if_ar.c
|
||||
*/
|
||||
extern void *arattach_pci(int unit, vm_offset_t mem_vaddr);
|
||||
extern void arintr_hc(void *hc);
|
||||
#define TRCL(x) x
|
||||
|
||||
static const char *ar_pci_probe(pcici_t tag, pcidi_t type);
|
||||
static void ar_pci_attach(pcici_t config_id, int unit);
|
||||
static int ar_pci_probe(device_t);
|
||||
static int ar_pci_attach(device_t);
|
||||
|
||||
static u_long arc_count = NAR;
|
||||
|
||||
static struct pci_device ar_pci_driver =
|
||||
{
|
||||
"ar",
|
||||
ar_pci_probe,
|
||||
ar_pci_attach,
|
||||
&arc_count,
|
||||
NULL
|
||||
static device_method_t ar_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ar_pci_probe),
|
||||
DEVMETHOD(device_attach, ar_pci_attach),
|
||||
DEVMETHOD(device_detach, ar_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
COMPAT_PCI_DRIVER (ar_pci, ar_pci_driver);
|
||||
static driver_t ar_pci_driver = {
|
||||
"ar",
|
||||
ar_pci_methods,
|
||||
sizeof(struct ar_hardc),
|
||||
};
|
||||
|
||||
static const char *
|
||||
ar_pci_probe(pcici_t tag, pcidi_t type)
|
||||
DRIVER_MODULE(if_ar, pci, ar_pci_driver, ar_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
ar_pci_probe(device_t device)
|
||||
{
|
||||
u_int32_t type = pci_get_devid(device);
|
||||
|
||||
switch(type) {
|
||||
case 0x5012114f:
|
||||
return ("Digi SYNC/570i-PCI 2 port");
|
||||
device_set_desc(device, "Digi SYNC/570i-PCI 2 port");
|
||||
return (0);
|
||||
break;
|
||||
case 0x5010114f:
|
||||
printf("Digi SYNC/570i-PCI 2 port (mapped below 1M)\n");
|
||||
printf("Please change the jumper to select linear mode.\n");
|
||||
break;
|
||||
case 0x5013114f:
|
||||
return ("Digi SYNC/570i-PCI 4 port");
|
||||
device_set_desc(device, "Digi SYNC/570i-PCI 4 port");
|
||||
return (0);
|
||||
break;
|
||||
case 0x5011114f:
|
||||
printf("Digi SYNC/570i-PCI 4 port (mapped below 1M)\n");
|
||||
@ -89,38 +98,73 @@ ar_pci_probe(pcici_t tag, pcidi_t type)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static void
|
||||
ar_pci_attach(pcici_t config_id, int unit)
|
||||
static int
|
||||
ar_pci_attach(device_t device)
|
||||
{
|
||||
int error;
|
||||
u_int i, tmp;
|
||||
u_char *inten;
|
||||
void *hc;
|
||||
vm_offset_t mem_vaddr, mem_paddr;
|
||||
vm_offset_t plx_vaddr, plx_paddr;
|
||||
struct ar_hardc *hc;
|
||||
|
||||
if(!pci_map_mem(config_id, 0x10, &plx_vaddr, &plx_paddr)) {
|
||||
printf("arp: map failed.\n");
|
||||
return;
|
||||
}
|
||||
hc = (struct ar_hardc *)device_get_softc(device);
|
||||
bzero(hc, sizeof(struct ar_hardc));
|
||||
|
||||
if(!pci_map_mem(config_id, 0x18, &mem_vaddr, &mem_paddr)) {
|
||||
printf("arp: map failed.\n");
|
||||
return;
|
||||
}
|
||||
error = ar_allocate_plx_memory(device, 0x10, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
hc = arattach_pci(unit, mem_vaddr);
|
||||
if(!hc)
|
||||
return;
|
||||
error = ar_allocate_memory(device, 0x18, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
error = ar_allocate_irq(device, 0, 1);
|
||||
if(error)
|
||||
goto errexit;
|
||||
|
||||
hc->plx_mem = rman_get_virtual(hc->res_plx_memory);
|
||||
hc->mem_start = rman_get_virtual(hc->res_memory);
|
||||
|
||||
hc->cunit = device_get_unit(device);
|
||||
hc->sca[0] = (sca_regs *)(hc->mem_start + AR_PCI_SCA_1_OFFSET);
|
||||
hc->sca[1] = (sca_regs *)(hc->mem_start + AR_PCI_SCA_2_OFFSET);
|
||||
hc->iobase = 0;
|
||||
hc->orbase = (u_char *)(hc->mem_start + AR_PCI_ORBASE_OFFSET);
|
||||
|
||||
tmp = hc->orbase[AR_BMI * 4];
|
||||
hc->bustype = tmp & AR_BUS_MSK;
|
||||
hc->memsize = (tmp & AR_MEM_MSK) >> AR_MEM_SHFT;
|
||||
hc->memsize = 1 << hc->memsize;
|
||||
hc->memsize <<= 16;
|
||||
hc->interface[0] = (tmp & AR_IFACE_MSK);
|
||||
tmp = hc->orbase[AR_REV * 4];
|
||||
hc->revision = tmp & AR_REV_MSK;
|
||||
hc->winsize = (1 << ((tmp & AR_WSIZ_MSK) >> AR_WSIZ_SHFT)) * 16 * 1024;
|
||||
hc->mem_end = (caddr_t)(hc->mem_start + hc->winsize);
|
||||
hc->winmsk = hc->winsize - 1;
|
||||
hc->numports = hc->orbase[AR_PNUM * 4];
|
||||
hc->handshake = hc->orbase[AR_HNDSH * 4];
|
||||
|
||||
for(i = 1; i < hc->numports; i++)
|
||||
hc->interface[i] = hc->interface[0];
|
||||
|
||||
TRC(printf("arp%d: bus %x, rev %d, memstart %p, winsize %d, "
|
||||
"winmsk %x, interface %x\n",
|
||||
unit, hc->bustype, hc->revision, hc->mem_start, hc->winsize,
|
||||
hc->winmsk, hc->interface[0]));
|
||||
|
||||
ar_attach(device);
|
||||
|
||||
/* Magic to enable the card to generate interrupts. */
|
||||
inten = (u_char *)plx_vaddr;
|
||||
inten = (u_char *)hc->plx_mem;
|
||||
inten[0x69] = 0x09;
|
||||
|
||||
if(!pci_map_int(config_id, arintr_hc, (void *)hc, &net_imask)) {
|
||||
free(hc, M_DEVBUF);
|
||||
return;
|
||||
}
|
||||
return (0);
|
||||
|
||||
errexit:
|
||||
ar_deallocate_resources(device);
|
||||
return (ENXIO);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user