File: [local] / sys / arch / hppa / gsc / if_ie_gsc.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:05:54 2008 UTC (16 years, 6 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: if_ie_gsc.c,v 1.25 2004/10/28 19:13:30 mickey Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* References:
* 1. 82596DX and 82596SX High-Performance 32-bit Local Area Network Coprocessor
* Intel Corporation, November 1996, Order Number: 290219-006
*
* 2. 712 I/O Subsystem ERS Rev 1.0
* Hewlett-Packard, June 17 1992, Dwg No. A-A2263-66510-31
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <hppa/dev/cpudevs.h>
#include <hppa/gsc/gscbusvar.h>
#include <dev/ic/i82596reg.h>
#include <dev/ic/i82596var.h>
#define IEGSC_GECKO IEMD_FLAG0
struct ie_gsc_regs {
u_int32_t ie_reset;
u_int32_t ie_port;
u_int32_t ie_attn;
};
#define IE_SIZE 0x8000
int ie_gsc_probe(struct device *, void *, void *);
void ie_gsc_attach(struct device *, struct device *, void *);
struct cfattach ie_gsc_ca = {
sizeof(struct ie_softc), ie_gsc_probe, ie_gsc_attach
};
static int ie_gsc_media[] = {
IFM_ETHER | IFM_10_2,
};
#define IE_NMEDIA (sizeof(ie_gsc_media) / sizeof(ie_gsc_media[0]))
char *ie_mem;
void ie_gsc_reset(struct ie_softc *sc, int what);
void ie_gsc_attend(struct ie_softc *sc);
void ie_gsc_run(struct ie_softc *sc);
void ie_gsc_port(struct ie_softc *sc, u_int);
#ifdef USELEDS
int ie_gsc_intrhook(struct ie_softc *sc, int what);
#endif
u_int16_t ie_gsc_read16(struct ie_softc *sc, int offset);
void ie_gsc_write16(struct ie_softc *sc, int offset, u_int16_t v);
void ie_gsc_write24(struct ie_softc *sc, int offset, int addr);
void ie_gsc_memcopyin(struct ie_softc *sc, void *p, int offset, size_t);
void ie_gsc_memcopyout(struct ie_softc *sc, const void *p, int, size_t);
void
ie_gsc_reset(sc, what)
struct ie_softc *sc;
int what;
{
volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
int i;
r->ie_reset = 0;
/*
* per [2] 4.6.2.1
* delay for 10 system clocks + 5 transmit clocks,
* NB: works for system clocks over 10MHz
*/
DELAY(1000);
switch (what) {
case IE_CHIP_PROBE:
break;
case IE_CARD_RESET:
/*
* after the hardware reset:
* inform i825[89]6 about new SCP address,
* maddr must be at least 16-byte aligned
*/
ie_gsc_port(sc, IE_PORT_SCP);
ie_gsc_attend(sc);
for (i = 9000; i-- && ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp));
DELAY(100))
pdcache(0, sc->sc_maddr + sc->iscp, IE_ISCP_SZ);
#ifdef I82596_DEBUG
if (i < 0) {
printf("timeout for PORT command (%x)%s\n",
ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)),
(sc->sc_flags & IEGSC_GECKO)? " on gecko":"");
return;
}
#endif
break;
}
}
void
ie_gsc_attend(sc)
struct ie_softc *sc;
{
volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
DELAY(1);
r->ie_attn = 0;
DELAY(1);
}
void
ie_gsc_run(sc)
struct ie_softc *sc;
{
}
void
ie_gsc_port(sc, cmd)
struct ie_softc *sc;
u_int cmd;
{
switch (cmd) {
case IE_PORT_RESET:
cmd = 0;
break;
case IE_PORT_TEST:
cmd = ((u_int)sc->sc_maddr + sc->scp) | 1;
break;
case IE_PORT_SCP:
cmd = ((u_int)sc->sc_maddr + sc->scp) | 2;
break;
case IE_PORT_DUMP:
cmd = 3;
break;
}
if (sc->sc_flags & IEGSC_GECKO) {
volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
r->ie_port = cmd & 0xffff;
DELAY(1000);
r->ie_port = cmd >> 16;
DELAY(1000);
} else {
volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
r->ie_port = cmd >> 16;
DELAY(1000);
r->ie_port = cmd & 0xffff;
DELAY(1000);
}
}
#ifdef USELEDS
int
ie_gsc_intrhook(sc, where)
struct ie_softc *sc;
int where;
{
switch (where) {
case IE_INTR_ENRCV:
ledctl(PALED_NETRCV, 0, 0);
break;
case IE_INTR_ENSND:
ledctl(PALED_NETSND, 0, 0);
break;
case IE_INTR_EXIT:
case IE_INTR_LOOP:
fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
break;
}
return 0;
}
#endif
u_int16_t
ie_gsc_read16(sc, offset)
struct ie_softc *sc;
int offset;
{
volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr));
return *addr;
}
void
ie_gsc_write16(sc, offset, v)
struct ie_softc *sc;
int offset;
u_int16_t v;
{
volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
*addr = v;
asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr));
}
void
ie_gsc_write24(sc, offset, v)
struct ie_softc *sc;
int offset;
int v;
{
volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
addr[0] = (v ) & 0xffff;
addr[1] = (v >> 16) & 0xffff;
asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+0));
asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+1));
}
void
ie_gsc_memcopyin(sc, p, offset, size)
struct ie_softc *sc;
void *p;
int offset;
size_t size;
{
pdcache(0, sc->bh + offset, size);
bcopy ((void *)((u_long)sc->bh + offset), p, size);
}
void
ie_gsc_memcopyout(sc, p, offset, size)
struct ie_softc *sc;
const void *p;
int offset;
size_t size;
{
bcopy (p, (void *)((u_long)sc->bh + offset), size);
fdcache(0, sc->bh + offset, size);
}
int
ie_gsc_probe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct gsc_attach_args *ga = aux;
if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
(ga->ga_type.iodc_sv_model != HPPA_FIO_LAN &&
ga->ga_type.iodc_sv_model != HPPA_FIO_GLAN))
return 0;
return 1;
}
void
ie_gsc_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct pdc_lan_station_id pdc_mac PDC_ALIGNMENT;
struct ie_softc *sc = (struct ie_softc *)self;
struct gsc_attach_args *ga = aux;
/*bus_dma_segment_t seg;
int rseg;*/
int rv;
#ifdef PMAPDEBUG
extern int pmapdebug;
int opmapdebug = pmapdebug;
pmapdebug = 0;
#endif
sc->iot = sc->bt = ga->ga_iot;
if (bus_space_map(sc->iot, ga->ga_hpa, IOMOD_HPASIZE, 0, &sc->ioh)) {
printf(": can't map IO space\n");
return;
}
if (ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN)
sc->sc_flags |= IEGSC_GECKO;
sc->sc_msize = IE_SIZE;
/* XXX memory must be under 16M until the mi part is fixed */
#if 0
if (bus_dmamem_alloc(ga->ga_dmatag, sc->sc_msize, NBPG, 0,
&seg, 1, &rseg, BUS_DMA_NOWAIT)) {
printf (": cannot allocate %d bytes of DMA memory\n",
sc->sc_msize);
return;
}
if (bus_dmamem_map(ga->ga_dmatag, &seg, rseg, sc->sc_msize,
(caddr_t *)&sc->bh, BUS_DMA_NOWAIT)) {
printf (": cannot map DMA memory\n");
bus_dmamem_free(ga->ga_dmatag, &seg, rseg);
return;
}
bzero((void *)sc->bh, sc->sc_msize);
sc->sc_maddr = kvtop((caddr_t)sc->bh);
#else
sc->bh = (u_int)ie_mem;
sc->sc_maddr = sc->bh;
#endif
sc->sysbus = 0x40 | IE_SYSBUS_82586 | IE_SYSBUS_INTLOW | IE_SYSBUS_TRG | IE_SYSBUS_BE;
sc->do_xmitnopchain = 0;
sc->hwreset = ie_gsc_reset;
sc->chan_attn = ie_gsc_attend;
sc->port = ie_gsc_port;
sc->hwinit = ie_gsc_run;
sc->memcopyout = ie_gsc_memcopyout;
sc->memcopyin = ie_gsc_memcopyin;
sc->ie_bus_read16 = ie_gsc_read16;
sc->ie_bus_write16 = ie_gsc_write16;
sc->ie_bus_write24 = ie_gsc_write24;
#ifdef USELEDS
sc->intrhook = ie_gsc_intrhook;
#else
sc->intrhook = NULL;
#endif
#ifdef I82596_DEBUG
printf(" mem %x[%p]/%x", sc->bh, sc->sc_maddr, sc->sc_msize);
sc->sc_debug = IED_ALL;
#endif
rv = i82596_probe(sc);
if (!rv) {
/*bus_dmamem_free(ga->ga_dmatag, &seg, sc->sc_msize);*/
}
#ifdef PMAPDEBUG
pmapdebug = opmapdebug;
#endif
if (!rv) {
printf("\n");
return;
}
if (pdc_call((iodcio_t)pdc, 0, PDC_LAN_STATION_ID,
PDC_LAN_STATION_ID_READ, &pdc_mac, ga->ga_hpa) < 0)
bcopy((void *)ASP_PROM, sc->sc_arpcom.ac_enaddr,
ETHER_ADDR_LEN);
else
bcopy(pdc_mac.addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
printf(":");
sc->iscp = 0;
sc->scp = 32;
sc->scb = 94;
sc->buf_area = 256;
sc->buf_area_sz = sc->sc_msize - sc->buf_area;
sc->sc_type = sc->sc_flags & IEGSC_GECKO? "LASI/i82596CA" : "i82596DX";
sc->sc_vers = ga->ga_type.iodc_model * 10 + ga->ga_type.iodc_sv_rev;
i82596_attach(sc, sc->sc_type, (char *)sc->sc_arpcom.ac_enaddr,
ie_gsc_media, IE_NMEDIA, ie_gsc_media[0]);
sc->sc_ih = gsc_intr_establish((struct gsc_softc *)parent,
ga->ga_irq, IPL_NET, i82596_intr, sc, sc->sc_dev.dv_xname);
}