// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: serial_mod.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
* Copyright 2004 by Sun Microsystems, Inc.
extern int term_init(FILE *fp
,void (*)(void *, char *, int), void *cbData
,char **tty_name
);
extern int term_console (char *pty_dev
, char *display
);
extern serialInterface
*systemConsole
;
extern char * console_display
;
Module::get_help_string()
return "PCI Serial Device";
Module::create(const char *_modname
, const char *_instance_name
)
return new Serial(_modname
, _instance_name
);
pciXactnStatus
Serial::pciTarget_mem32access(uint64_t offset
, bool wr
,uint64_t * buf
, uint8_t size
){
debug_info("%s: %s MEM32: offset %llx size %x\n", HERE
, wr
?"WRITE":"READ ", offset
, size
);
int retval
= reg_access((char*)buf
, offset
- pciMem32_base
,wr
);
return Module::get_help_string();
Serial::Serial(const char *_modname
, const char *_instance_name
)
: Module(_modname
, _instance_name
)
cfg->pci_device_id = 0x0; //XXX look up from spec
cfg->class_code = 0x10000; //XXX verify
display
= strdup(console_display
);
debug_info("%s: destructor\n", HERE
);
SYSTEM_ss_unregister((void*)this);
DR_unregister((void*)this);
Serial::parse_arg(const char *arg
)
if(argval("mem32_base",arg
,&pciMem32_base
)){
debug_more("%s:mem32_base = %llx\n",getName(),pciMem32_base
);
}else if(argval("mem32_size",arg
,&pciMem32_size
)){
debug_more("%s:mem32_size = %llx\n",getName(),pciMem32_size
);
if(!strcmp("sam-console",arg
)){
}else if(argval("redirectA",arg
,&termAredirect
)){
debug_more("%s: term A redirected to file %s\n",termAredirect
);
}else if (argval("redirectB",arg
,&termBredirect
)){
debug_more("%s: term B redirected to file %s\n",termBredirect
);
return dev_parse_arg(arg
);
bool ret
= dev_check_args();
// all the args are provided correctly. init the console now.
// can't do this from init_done because console-send in rc file
// can be called before init_done.
systemConsole
= (serialInterface
*)this; // blaze system has a callback that
// uses this to allow prints from
// fakeprom. using access_serial_cb()
// could be removed if there was a
// way to set the name of serial device
// as being done by conf. In any case its
// better than hard coding the sysconf
// supplied name in blaze code.
// Hence future cleanup item XXX
termAfp
= fopen(termAredirect
,"w");
termBfp
= fopen(termBredirect
,"w");
portHandle
[0] = term_init(termAfp
, handleSerialIp
, (void *) this, &ttyAname
);
printf("TIP connection for %s port A is %s\n",getName(),ttyAname
);
portHandle
[1] = term_init(termBfp
, handleSerialIp
, (void *) this, &ttyBname
);
printf("TIP connection for %s port B is %s\n",getName(),ttyBname
);
systemConsole
->portH
= portHandle
[0];
if(display
[0] != 0 && termAredirect
== 0){
if(term_console(ttyAname
, display
) < 0){
debug_err("%s:Unable to popup XTERM for simulated Os\n",getName());
debug_err("%s: DISPLAY variable not set or using console redirection\n",getName());
// called once after blaze has initialized devices and cpu data structs
dev_init_done(debug_level
);
// map in the device. these functions would normally be
// performed by the boot prom
// 1. get the lowest available base address on the bus
pciMem32_base
= getBase(PCI_MEM32
,pciMem32_size
);
// Map in the address if this is a v4 restore or a new v5 run
if(restore_v4_dump() || !restore_v5_dump()){
// 2. set the base address 0 register
confSpace
->confAccessSize(PCI_CONF_BASE0
,true,&pciMem32_base
,4);
// 3. enable the pci mem32 access by setting the command reg.
confSpace
->confAccessSize(PCI_CONF_COMM
,true,&command
,2);
plist
->writeToFakeProm();
if(Module::debug_level
>= 2)
// called each time a new module instance has been created
Serial::module_added(mmi_instance_t target
, const char *target_name
)
dev_module_added(target_name
);
// called each time a new module instance has been unloaded
Serial::module_deleted(mmi_instance_t target
, const char *target_name
)
dev_module_deleted(target_name
);
// print interesting info about this module
printf("%s: This is a Serial PCI device\n",
printf("TIP for port A is %s\n",ttyAname
);
printf("TIP for port B is %s\n",ttyBname
);
// return pointer to interface
Serial::get_interface(const char *name
)
if (!strcmp(name
, PCI_GENERIC_DEV_INTERFACE
))
return (genericPciDevIf
*)this;
if (!strcmp(name
, "Serial"))
debug_more("enter serial_mod.cc ::get_dev_props\n");
pcisimc_props
[0].value
= new char[strlen(devif_getBusName())+1];
strcpy(pcisimc_props
[0].value
,devif_getBusName());
pcisimc_props
[0].size
= strlen(devif_getBusName()) + 1;
sprintf(pcisimc_device
,"%d",devif_getDevice());
pcisimc_props
[1].value
= pcisimc_device
;
pcisimc_props
[1].size
= strlen(pcisimc_device
)+1;
sprintf(pcisimc_membase
,"%d",pciMem32_base
);
pcisimc_props
[2].value
= pcisimc_membase
;
pcisimc_props
[2].size
= strlen(pcisimc_membase
)+1;
sprintf(pcisimc_memsize
,"%d",pciMem32_size
);
pcisimc_props
[3].value
= pcisimc_memsize
;
pcisimc_props
[3].size
= strlen(pcisimc_memsize
)+1;
strcpy(pcisimc_isconsole
,"1");
strcpy(pcisimc_isconsole
,"0");
pcisimc_props
[4].value
= pcisimc_isconsole
;
pcisimc_props
[4].size
= 2;
pcisimc_reg
[0].pci_phys_hi
= 0x00000000 | devif_getDevice() << 11 | devif_getFunction() << 8;
pcisimc_reg
[0].pci_phys_mid
= 0;
pcisimc_reg
[0].pci_phys_low
= 0;
pcisimc_reg
[0].pci_size_hi
= 0;
pcisimc_reg
[0].pci_size_low
= 0;
// pcisimc_reg[1].pci_phys_hi = 0x82000000 | devif_getDevice() << 11;
pcisimc_reg
[1].pci_phys_hi
= 0x02000000 | devif_getDevice() << 11 | devif_getFunction() << 8 | PCI_CONF_BASE0
;
pcisimc_reg
[1].pci_phys_mid
= 0;
pcisimc_reg
[1].pci_phys_low
= 0;
pcisimc_reg
[1].pci_size_hi
= 0;
pcisimc_reg
[1].pci_size_low
= pciMem32_size
;
pcisimc_assigned_addr
[0].pci_phys_hi
= 0x82000000 | devif_getDevice() << 11 | devif_getFunction() << 8 | PCI_CONF_BASE0
;
pcisimc_assigned_addr
[0].pci_phys_mid
= 0;
pcisimc_assigned_addr
[0].pci_phys_low
= pciMem32_base
;
pcisimc_assigned_addr
[0].pci_size_hi
= 0;
pcisimc_assigned_addr
[0].pci_size_low
= pciMem32_size
;
pcisimc_intr
= slot_irl
[0];
plist
->add_bunch(pcisimc_props
);
debug_more("leave serial_mod.cc ::get_dev_props plist->count %x\n",plist
->count
);
void handleSerialIp(void * sptr
, char * data
, int port
){
Serial
* S
= (Serial
*)sptr
;
S
->chars_send(data
,port
);
snprintf(reg_descr
,100,"%s Vendor ID", getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,0x108e,0x0,0x0),PCI_CONF_VENID
);//0x108e, ro
snprintf(reg_descr
,100,"%s Device ID", getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
, 2,0x0,0x0,0x0),PCI_CONF_DEVID
); //0x0, ro
snprintf(reg_descr
,100,"%s command reg", getName());
confSpace
->addConfReg(new pciCommandReg(reg_descr
,(genericPciDev
*)this,0x2),PCI_CONF_COMM
);// write mask = 0x2, only allows mem32 access
snprintf(reg_descr
,100,"%s status reg", getName());
confSpace
->addConfReg(new pciStatusReg(reg_descr
,(genericPciDev
*)this,0x0,0x0),PCI_CONF_STAT
);//write mask = 0x0, init val 0x0
snprintf(reg_descr
,100,"%s revision id",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0,0x0),PCI_CONF_REVID
);// rev id = 0x0, ro
snprintf(reg_descr
,100,"%s prog class",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),PCI_CONF_PROGCLASS
);//0x00, ro
snprintf(reg_descr
,100,"%s sub class",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0x0),PCI_CONF_SUBCLASS
);//0x00, ro
snprintf(reg_descr
,100,"%s base class",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x01,0x0),PCI_CONF_BASCLASS
);//0x01, ro
snprintf(reg_descr
,100,"%s Header type",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x00,0x00,0x0),PCI_CONF_HEADER
); //0x00,ro
snprintf(reg_descr
,100,"%s BAR0",getName());
confSpace
->addConfReg(new baseAddrReg(reg_descr
,(genericPciDev
*)this,pciMem32_size
,PCI_MEM32
),PCI_CONF_BASE0
);//0x2000 non prefetchable, pci mem32 mapped
snprintf(reg_descr
,100,"%s interrupt line",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x0,0xff),PCI_CONF_ILINE
);//0x0
snprintf(reg_descr
,100,"%s interrupt pin",getName());
confSpace
->addConfReg(new pciConfReg(reg_descr
,1,0x1,0x00),PCI_CONF_IPIN
);//0x1,ro
mmi_instance_t
Serial::pciDev_getInstance(){ return Module::getInstance();}
const char * Serial::pciDev_getName(){ return Module::getName();}
void Serial::pciDev_confAccessCb(bool_t wr
, uint64_t offset
, uint8_t size
){
if(offset
== PCI_CONF_BASE0
){
pciMem32_base
= confSpace
->readConf(offset
) & 0xfffffff0;