1
0
Files
irix-657m-src/stand/arcs/lib/libsk/io/ioc3uart.c
2022-09-29 17:59:04 +03:00

345 lines
9.4 KiB
C

#include <sys/SN/addrs.h>
#include <sys/SN/agent.h> /* hub - network interface */
#include <sys/SN/klconfig.h> /* config stuff */
#include <libsc.h>
#include <arcs/errno.h>
#include <sys/graph.h>
#include <sys/hwgraph.h>
#include <sys/SN/promcfg.h>
#include <arcs/cfgdata.h>
#include <sys/SN/SN0/klhwinit.h>
#include <promgraph.h>
#include <sys/PCI/ioc3.h>
#include <sys/PCI/bridge.h>
extern graph_hdl_t prom_graph_hdl ;
extern int ns16550_install(COMPONENT *) ;
extern int ef_install(COMPONENT *) ;
extern int pckbd_install(COMPONENT *) ;
extern int _ns16550_strat(COMPONENT *self, IOBLOCK *iob);
extern int _if_strat(COMPONENT *self, IOBLOCK *iob);
extern int _kbd_strat(COMPONENT *self, IOBLOCK *iob);
extern int _ioc3_strat(COMPONENT *self, IOBLOCK *iob) ;
extern vertex_hdl_t hw_vertex_hdl ;
int _ioc3_strat() ;
static int kl_ioc3_AddChild(COMPONENT *, int , int(*)());
int num_ioc3 ;
int ioc3_installed ;
/*
* This file contains routines to install and init the IOC3
* controller in the IO6prom.
*
* When the IOC3 is discovered, a klioc3_t structure is
* created and is attached to the lboard_t of the board of
* which it is a part of.
*
* An IOC3 has the following components which have different
* device drivers to handle them:
*
* . UART - _ns16550_strat
* . Ethernet - _if_strat
* . keyboard - _kbd_strat
* . mouse - _ms_strat
*
*/
/*
* These are the old style ARCS templates for the various
* IOC3 components. The reason for having these here is that
* the prom driver still understand and need these structures.
* All this will go away when we have in the PROM the IO
* infrastructure and drivers that understand IO infrastructure.
*/
static COMPONENT ttyptmpl = {
PeripheralClass, /* Class */
LinePeripheral, /* Controller */
(IDENTIFIERFLAG)(ConsoleIn|ConsoleOut|Input|Output), /* Flags */
SGI_ARCS_VERS, /* Version */
SGI_ARCS_REV, /* Revision */
0, /* Key */
0x01, /* Affinity */
0, /* ConfigurationDataSize */
0, /* IdentifierLength */
NULL /* Identifier */
};
static COMPONENT netdev = {
PeripheralClass, /* Class */
NetworkPeripheral, /* Controller */
(IDENTIFIERFLAG)(Input|Output), /* Flags */
SGI_ARCS_VERS, /* Version */
SGI_ARCS_REV, /* Revision */
0, /* Key */
0x01, /* Affinity */
0, /* ConfigurationDataSize */
0, /* IdentifierLength */
NULL /* Identifier */
};
static COMPONENT kbdtempl = {
PeripheralClass, /* Class */
KeyboardPeripheral, /* Type */
ReadOnly|ConsoleIn|Input, /* Flags */
SGI_ARCS_VERS, /* Version */
SGI_ARCS_REV, /* Revision */
0, /* Key */
0x01, /* Affinity */
0, /* ConfigurationDataSize */
0, /* IdentifierLength */
NULL /* Identifier */
};
/*
* Called By: vvisit_install in promgraph.c. It is called when
* drivers for each device is being 'installed'.
* Installing a driver is putting the address of
* the driver _strat routine in a known place in
* the promgraph, which can be later easily
* retrieved. Also, any devices attached to the
* controller are discovered and the KLCONFIG is
* updated. hinv uses this info and the graph info.
*/
/*
* Procedure: The procedure is not well defined for all kinds
* of devices. Each device may need their own
* special processing. The general flow is given below:
* XXX
*/
int
kl_ioc3_install(vertex_hdl_t hw_vhdl, vertex_hdl_t devctlr_vhdl)
{
int i = 0, ctlr_num ;
COMPONENT *uart_compt, *net_compt, *kbd_compt ;
COMPONENT tmp_compt ;
graph_error_t graph_err ;
klinfo_t *ctrkli_ptr ;
__psunsigned_t hub_base ;
unsigned char hubwid ;
__psunsigned_t ioc3_register_base,
ioc3_uart_base, ioc3_enet_base ;
ULONG Key ;
prom_dev_info_t *dev_info ;
if (!ioc3_installed)
ioc3_installed = 1 ;
else {
return 1 ;
}
/* Get the dev_info struct of the device controller. */
graph_err = graph_info_get_LBL(prom_graph_hdl, devctlr_vhdl,
INFO_LBL_DEV_INFO,NULL,
(arbitrary_info_t *)&dev_info) ;
if (graph_err != GRAPH_SUCCESS) {
printf("ioc3 install: cannot get dev_info\n");
return 0;
}
/* register strategy routine for controller */
kl_reg_drv_strat(dev_info, _ioc3_strat) ;
/* Update klinfo_t of the controller with its adapter number = virt id */
ctrkli_ptr = dev_info->kl_comp ;
ctrkli_ptr->virtid = Key = num_ioc3++ ; /* number of ioc3's found */
/* Build the rest of the Key for this controller. */
Key |= MK_SN0_KEY(ctrkli_ptr->nasid,
ctrkli_ptr->widid, ctrkli_ptr->physid) ;
hub_base = (__psunsigned_t) REMOTE_HUB(ctrkli_ptr->nasid, 0) ;
#if 0
if (ctrkli_ptr->nasid)
else
hub_base = (__psunsigned_t) LOCAL_HUB(0) ;
#endif
hubwid = GET_FIELD64((hub_base + IIO_WIDGET_CTRL), WIDGET_ID_MASK, 0) ;
ADD_HUBWID_KEY(Key, hubwid) ;
ADD_HSTNASID_KEY(Key, get_nasid()) ;
/* Fill up ARCS info and put it in klinfo_t of the device */
uart_compt = (COMPONENT *)malloc(sizeof(COMPONENT)) ;
if (uart_compt == NULL) {
printf("ioc3 uart inst : malloc failed \n") ;
return 0 ;
}
bcopy(&ttyptmpl, uart_compt, sizeof(COMPONENT)) ;
uart_compt->AffinityMask = (ULONG)devctlr_vhdl ;
uart_compt->Key = Key ;
tmp_compt.Key = ((__psunsigned_t) GET_PCIBASE_FROM_KEY(uart_compt->Key)) +
IOC3_SIO_UA_BASE ;
ns16550_install(&tmp_compt) ;
kl_ioc3_AddChild(uart_compt, KLSTRUCT_IOC3UART, _ns16550_strat) ;
/*
* Install Ethernet device
*/
net_compt = (COMPONENT *)malloc(sizeof(COMPONENT)) ;
if (net_compt == NULL) {
printf("ethernet install : malloc failed \n") ;
return 0 ;
}
bcopy(&netdev, net_compt, sizeof(COMPONENT));
net_compt->Type = NetworkPeripheral ;
net_compt->AffinityMask = (ULONG)devctlr_vhdl;
net_compt->IdentifierLength = 0 ;
net_compt->Key = Key;
ef_install(net_compt) ;
kl_ioc3_AddChild(net_compt, KLSTRUCT_IOC3ENET, _if_strat) ;
/*
* Install Keyboard device
*/
kbd_compt = (COMPONENT *)malloc(sizeof(COMPONENT)) ;
if (kbd_compt == NULL) {
printf("keyboard install : malloc failed \n") ;
return 0 ;
}
bcopy(&kbdtempl, kbd_compt, sizeof(COMPONENT));
kbd_compt->AffinityMask = (ULONG)devctlr_vhdl;
kbd_compt->Key = Key;
PUT_INSTALL_STATUS(kbd_compt, 0) ;
pckbd_install(kbd_compt) ;
/* Install only if devices are found XXX check for mouse and/or kbd */
if (GET_INSTALL_STATUS(kbd_compt))
kl_ioc3_AddChild(kbd_compt, KLSTRUCT_IOC3PCKM, _kbd_strat) ;
#if 0
else {
printf("***Warning: IOC3 PC Keyboard not found.\n") ;
printf(" Reverting back to tty keyboard\n") ;
}
#endif
return 1;
}
#ifndef SN_PDI
static int
kl_ioc3_AddChild(COMPONENT *arcs_compt, int type, int(*dev_strat)())
{
klinfo_t *klinf_ptr ;
vertex_hdl_t devctlr_vhdl = arcs_compt->AffinityMask ; /* Kludge */
char *ctmp ;
klinf_ptr = (klinfo_t *)init_device_graph(devctlr_vhdl, type) ;
if (arcs_compt->IdentifierLength) {
ctmp = malloc(arcs_compt->IdentifierLength + 1) ;
strncpy(ctmp, arcs_compt->Identifier, arcs_compt->IdentifierLength) ;
arcs_compt->Identifier = ctmp ;
}
klinf_ptr->physid = (arcs_compt->Key & 0xf) ; /* target */
klinf_ptr->arcs_compt = arcs_compt ;
link_device_to_graph(hw_vertex_hdl, devctlr_vhdl,
(klinfo_t *)klinf_ptr, dev_strat) ;
return 1 ;
}
#endif
int
_ioc3_strat(COMPONENT *self, IOBLOCK *iob)
{
switch (iob->FunctionCode) {
case FC_INITIALIZE:
_ns16550_strat(self, iob) ;
_if_strat(self, iob) ;
_kbd_strat(self, iob) ;
return iob->ErrorNumber ;
default:
return iob->ErrorNumber = EINVAL;
}
}
int
ioc3_compt_install(type, devctlr_vhdl, Key)
{
COMPONENT *compt ;
COMPONENT tmp_compt, *inst_compt ;
graph_error_t graph_err ;
int (*_install)(), (*_strat)() ;
void *tmpl ;
/* Fill up ARCS info and put it in klinfo_t of the device */
compt = (COMPONENT *)malloc(sizeof(COMPONENT)) ;
if (compt == NULL) {
printf("ioc3 inst : malloc failed \n") ;
return 0 ;
}
bcopy(&tmpl, compt, sizeof(COMPONENT)) ;
compt->AffinityMask = (ULONG)devctlr_vhdl ;
compt->Key = Key ;
switch(type) {
case KLSTRUCT_IOC3UART :
_install = ns16550_install ;
_strat = _ns16550_strat ;
tmpl = (void *)&ttyptmpl ;
tmp_compt.Key = ((__psunsigned_t)
GET_PCIBASE_FROM_KEY(compt->Key)) +
IOC3_SIO_UA_BASE ;
inst_compt = &tmp_compt ;
break ;
case KLSTRUCT_IOC3ENET :
_install = ef_install ;
_strat = _if_strat ;
tmpl = (void *)&netdev ;
inst_compt = compt ;
break ;
case KLSTRUCT_IOC3PCKM :
_install = pckbd_install ;
_strat = _kbd_strat ;
tmpl = (void *)&kbdtempl ;
inst_compt = compt ;
break ;
#if 0
case KLSTRUCT_IOC3MS :
break ;
#endif
}
(*_install)(inst_compt) ;
kl_ioc3_AddChild(compt, type, _strat) ;
return 1 ;
}