| From: [email protected] (Bruce)
Message-Id: <[email protected]>
To: [email protected]
Subject: Re: configure_driver returns EINVAL (errno 22)
Hi John,
Thanks for the quick response, here are the vitals:
Target systems are all alpha pci machines. In house we are
currently using an AlphaStation 200 4/166.
OS is Digital UNIX 4.0B
Phone number is (619) 457-0750
This is the sysconfigtab snippet:
ma:
Subsystem_Description = Magma PCI Serial card driver
Module_Type = Dynamic
Module_Path = /subsys/ma.mod
Module_Config_Name = ma
Device_Char_Major = ANY
PCI_Option = PCI_SE_Rev - 0x210, Vendor_Id - 0x11c9, Device_Id - 0x10, Driver_
Name - ma, Type - C, Adpt_Config - N
The following is the driver code for the autoconfiguration. The stuff
inside the "#ifdef OLDWAY" works. The problem is at the point
where configure_driver() is called, it returns with errno == 22.
Btw: This is a pci serial port mux.
Thanks for the help,
Bruce Schoenleber
-------------- maconfig.c--------------------------------
#ifndef lint
static char sid2[] = "%W% Magma PCI DU common driver %G%";
#endif
extern int nodev(), nulldev();
/* auto configuration routines */
static int maprobe (struct pci_config_hdr *, struct controller *);
static int maattach (struct controller *);
static int madettach (struct bus*, struct controller *);
int ma_configure (cfg_op_t, cfg_attr_t *, size_t, cfg_attr_t *, size_t);
struct controller *mainfo[MAXBOARDS];
ihandler_id_t *ma_id_t[MAXBOARDS];
/* driver/device attributes */
static int cmajnum = -1;
static int begunit = 0;
static int numunit = 0;
static int maversion = 19;
static int ma_is_dynamic = 0;
static int ma_config = FALSE; /* State flags indicating driver configured */
dev_t ma_devno = NODEV; /* No major number assigned yet. */
static unsigned char mcfgname[CFG_ATTR_NAME_SZ] = "";
static unsigned char modtype[300] = "";
static unsigned char devcmajor[300] = "";
static unsigned char subsysdscr[300] = "";
static unsigned char modpath[300] = "";
static unsigned char modconf[MAXBOARDS][300] = {"","","","","",""};
static unsigned char pci_optiondata[300] = "";
cfg_subsys_attr_t ma_attributes[] = {
{"Module_Config_Name",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)mcfgname,2,CFG_ATTR_NAME_SZ,0
},
{"PCI_Option",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)pci_optiondata,0,300,0
},
{"Module_Type",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modtype,2,300,0
},
{"Device_Char_Major",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)devcmajor,0,300,0
},
{"Subsystem_Description",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)subsysdscr,0,300,0
},
{"Module_Path",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modpath,0,300,0
},
{"Module_Config1",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[0],0,300,0
},
{"Module_Config2",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[1],0,300,0
},
{"Module_Config3",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[2],0,300,0
},
{"Module_Config4",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[3],0,300,0
},
{"Module_Config5",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[4],0,300,0
},
{"Module_Config6",
CFG_ATTR_STRTYPE, CFG_OP_CONFIGURE | CFG_OP_QUERY,
(caddr_t)modconf[5],0,300,0
},
{"majnum",
CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&cmajnum,0,99,0
},
{"begunit",
CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&begunit,0,8,0
},
{"numunit",
CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&numunit,0,8,0
},
{"version",
CFG_ATTR_INTTYPE, CFG_OP_QUERY,
(caddr_t)&maversion,0,9999999,0
},
{"",0,0,0,0,0,0}
};
#define MABUSNAME "pci" /* This is a PCI driver */
#define MAJOR_INSTANCE 1
#ifdef OLDWAY
struct pci_option ma_option_snippet [] = {
{0x210, MA_VENDOR_ID, MA_PCI16DMA, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, "ma", 'C', 0},
{0x210, MA_VENDOR_ID, MA_PCI4DMA, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, "ma", 'C', 0},
{0x210, MA_VENDOR_ID, MA_PCI16, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, "ma", 'C', 0},
{0x210, PCI_VID_INVALID, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0,0,0,0, "", '', 0} /* Null terminator in the table */
};
#endif
struct driver madriver = {
maprobe, /* probe */
0, /* slave */
maattach, /* cattach */
0, /* dattach */
0, /* go */
0, /* addr_list */
0, /* dev_name */
0, /* dev_list */
"ma", /* ctlr_name */
mainfo, /* ctlr_list */
0, /* xclu */
0, /* addr1_size */
0, /* addr1_atype */
0, /* addr2_size */
0, /* addr2_atype */
madettach, /* ctlr_unattach */
0 /* dev_unattach */
};
struct dsent ma_cdevsw= {
maopen, /* d_open */
maclose, /* d_close */
nodev, /* d_stratagy */
maread, /* d_read */
mawrite, /* d_write */
maioctl, /* d_ioctl */
nodev, /* d_dump */
nodev, /* d_psize */
nodev, /* d_stop */
nodev, /* d_reset */
maselect, /* d_select */
nodev, /* d_mmap */
nodev, /* d_segmap */
NULL, /* d_ttys */
DEV_FUNNEL_NULL, /* d_funnel */
0, /* d_bflags */
0 /* d_cflags */
};
#ifdef MADEBUG
cfg_attr_t cfg_buf[64];
#endif
int
ma_configure (cfg_op_t op, cfg_attr_t *indata, size_t indata_size,
cfg_attr_t *outdata, size_t outdata_size)
{
dev_t devno = NODEV;
int i, status;
switch (op)
{
default:
maprintf("ma_configure: Unkown operation\n",0);
return ENOTSUP;
case CFG_OP_RECONFIGURE:
maprintf("ma_configure: reconfigure operation\n",0);
return ESUCCESS;
case CFG_OP_QUERY:
maprintf("ma_configure: query, operation\n",0);
return ESUCCESS;
case CFG_OP_UNCONFIGURE:
maprintf("ma_configure: unconfig\n",0);
if (madaemonflag) return(EBUSY);
i = devsw_del (mcfgname, 1);
if (i) return(ESRCH);
if (unconfigure_driver(MABUSNAME, LDBL_WILDNUM,
&madriver, MABUSNAME, LDBL_WILDNUM) != 0)
return(ESRCH);
return (ESUCCESS);
case CFG_OP_CONFIGURE:
#ifdef MADEBUG
printf("\nma_configure: Config request\n");
bcopy(indata, cfg_buf[0].name,
indata_size*(sizeof(cfg_attr_t)));
for( i=0; i < indata_size; i++)
{
printf("%s: ",cfg_buf[i].name);
switch(cfg_buf[i].type)
{
case CFG_ATTR_STRTYPE:
printf("%s\n",cfg_buf[i].attr.str.val);
break;
default:
switch(cfg_buf[i].status)
{
case CFG_ATTR_EEXISTS:
printf("**Attribute does not exist\n");
break;
case CFG_ATTR_EOP:
printf("**Attribute does not support operation\n");
break;
case CFG_ATTR_ESUBSYS:
printf("**Subsystem Failure\n");
break;
case CFG_ATTR_ESMALL:
printf("**Attribute size/value too small\n");
break;
case CFG_ATTR_ELARGE:
printf("**Attribute size/value too large\n");
break;
case CFG_ATTR_ETYPE:
printf("**Attribute invalid type\n");
break;
case CFG_ATTR_EINDEX:
printf("**Attribute invalid index\n");
break;
case CFG_ATTR_EMEM:
printf("**Attribute memory allocation error\n");
break;
default:
printf("**Unknown attribute: ");
printf("%x\n", cfg_buf[i].status);
break;
}
break;
}
}
#endif MADEBUG
if (ma_config) return (EINVAL); /* already configured */
maprintf("ma: config name is %s\n",mcfgname);
if(strcmp(mcfgname,"")==0)
strcpy(mcfgname, "ma");
if (cfgmgr_get_state(mcfgname,&ma_is_dynamic) !=
ESUCCESS)
return(EINVAL);
if (ma_is_dynamic == SUBSYSTEM_DYNAMICALLY_CONFIGURED) {
maprintf("ma: Dynamic configuration\n",0);
if ((status = register_config()) != ESUCCESS)
return(status);
if ((status = configure_driver(mcfgname,
DRIVER_WILDNUM,
DRIVER_WILDNAME,
&madriver)) != ESUCCESS) {
maprintf("ma_configure, config driver failed, status %d",
status);
return(status);
}
if ((status = register_majornum()) != ESUCCESS)
return(status);
return(status);
} else { /* static configuration */
maprintf("ma: Static configuration\n",0);
return(EINVAL);
}
#ifdef OLDWAY
if (ma_is_dynamic == SUBSYSTEM_DYNAMICALLY_CONFIGURED)
{
if(strcmp(mcfgname,"")==0)
{
maprintf("ma_configure, null config name.",0);
return(ENODEV);
}
if (ldbl_stanza_resolver(mcfgname, MABUSNAME, &madriver,
(caddr_t *)ma_option_snippet) != 0)
return(EINVAL);
if (ldbl_ctlr_configure(MABUSNAME, LDBL_WILDNUM,
mcfgname, &madriver, 0))
return(EINVAL);
/*
** The above call should have called
** the driver's probe interface for
** each instance of the controller.
** If there were no controllers found
** then fail the driver configure
** operation.
*/
if (nboards == 0)
{
maprintf("ma_configure: no controllers found.",0);
return(ENODEV);
}
}
if(strcmp(devcmajor,"")!=0)
{
if((strcmp(devcmajor,"-1")==0) ||
(strcmp(devcmajor,"?")==0) ||
(strcmp(devcmajor,"any")==0) ||
(strcmp(devcmajor,"ANY")==0))
devno = NODEV;
else
{
devno = atoi(devcmajor);
devno = makedev(devno,0);
}
}
else
return EINVAL;
if ((devno = cdevsw_add(devno, &ma_cdevsw)) == NODEV) {
printf("ma_configure: cdevsw add failed --Nodev--\n");
return ENODEV;
}
ma_devno = devno;
cmajnum = major(devno);
begunit = 0;
numunit = nboards;
ma_config = TRUE;
#endif OLD
break;
} /* switch (op) */
#ifdef MADEBUG
printf("ma_configure: succeeded, major num %d\n", cmajnum);
#endif
return ESUCCESS;
}
static int
register_config()
{
struct controller_config ctlr, *ctlrp;
struct device_config dev, *devp;
int status;
ctlrp = &ctlr;
devp = &dev;
ctlrp->revision = CTLR_CONFIG_REVISION;
ctlrp->devdriver = &madriver;
strcpy(ctlrp->subsystem_name, mcfgname);
strcpy(ctlrp->bus_name, MABUSNAME);
if ((status = create_controller_struct(ctlrp)) != ESUCCESS) {
maprintf("ma: create controller struct failed status
%d\n",status);
return(status);
}
devp->revision = DEVICE_CONFIG_REVISION;
devp->controller_num = 0 /*LDBL_WILDNUM*/; /* ldbl_wildnum gets einval */
strcpy(devp->device_type, "tty");
strcpy(devp->device_name, "ma");
strcpy(devp->controller_name, "ma");
if ((status = create_device_struct(devp)) != ESUCCESS) {
maprintf("ma: create device struct failed status %d\n",status);
}
return(status);
}
static int
register_majornum()
{
if (nboards == 0)
return(ENODEV);
if ((cmajnum = devsw_add(mcfgname, MAJOR_INSTANCE, cmajnum, &ma_cdevsw))
==
ENODEV) {
maprintf("ma: Failed to get major number.\n",0);
return (ENODEV);
}
maprintf("ma: Major number is %d\n",cmajnum);
ma_devno = cmajnum;
begunit = 0;
numunit = nboards;
ma_config = TRUE;
return(ESUCCESS);
}
static int
maprobe (struct pci_config_hdr *pci, struct controller *ctlr)
{
u_int boardno;
register u_short btype, clock;
register ma_board_t *maboard;
#ifdef MADEBUG
printf("maprobe: round %d\n",nboards);
#endif
if (!(pci->command & CMD_MEM_SPACE) || !(pci->command & CMD_BUS_MASTER)) {
printf("maprobe%d at pci%d not configured by PCI POST code.\n",
ctlr->ctlr_num, ctlr->bus_num);
return(0);
}
if (nboards++ > MAXBOARDS)
{
printf("maprobe: failed\n");
return(0);
}
boardno = ctlr->ctlr_num;
if (nboards && (boardno < nboards))
{
if (ma_board[boardno] == NULL)
ma_board[boardno] = (ma_board_t *)
MALLOC(maboard, ma_board_t *, sizeof(ma_board_t),
M_DEVBUF, M_NOWAIT);
else
{
printf("maprobe: board %d already attached", boardno);
nboards--;
return(-1);
}
if (ma_board[boardno] == NULL)
{
printf("maprobe: board %d failed, enomem\n", boardno);
nboards--;
return(-1);
}
}
else
{
printf("maprobe: board %d failed, enodev\n", boardno);
nboards--;
return(-1);
}
#ifdef MADEBUG
printf("maprobe: board struct @ 0x%lx\n",maboard);
#endif
bzero((char *)maboard, sizeof(ma_board_t));
maboard->b_attach_flags |= SOFT_STATE_ALLOCATED;
maboard->b_boardno = boardno;
maboard->b_ctlr = ctlr;
/*
** get the board info. Bus dependent!
*/
btype = -1;
maboard->b_pci_cfg_hdr = pci;
#ifdef OLDBOARDS
maboard->b_baseaddr = pci->bar0;
#else
maboard->b_plx = pci->bar0;
maboard->b_baseaddr = pci->bar2;
#ifdef MADEBUG
printf("maprobe: PLX @ 0x%lx, CD2400 starts @ 0x%lx\n",
maboard->b_plx, maboard->b_baseaddr);
#endif
#endif
/*
** first grab the vendor id and veryify that is is ours.
** then grab the device type.
** Note that the PCI_VID and PCI_DID are from the pci.h system
** header file.
*/
btype = (u_short) read_io_port(pci->config_base + PCI_VID, 2, 0);
mb();
if (btype != MA_VENDOR_ID) {
printf("maprobe: non-Magma vendor Id. 0x%x\n", btype);
goto probe_fail;
}
btype = (u_short) read_io_port(pci->config_base + PCI_DID, 2, 0);
mb();
/*
** Board specific setup. This could be done in the attach
** routine, but the intent is to keep all PCI configuration
** stuff here.
*/
switch (btype) {
default:
printf("maprobe: unrecognized board type %d\n", btype);
goto probe_fail;
case MA_PCI16DMA:
case MA_PCI4DMA:
/* these two are the old style boards and all have 30Mhz clocks */
maboard->b_clock = 30000000;
break;
case MA_PCI16:
/* On the new boards, we use the PCI revid field for the clock */
clock = (u_short) read_io_port(pci->config_base + PCI_REVID, 2, 0);
maboard->b_clock = (u_int) clock * 1000000;
maprintf("maprobe: clock speed is %d\n",clock);
break;
}
maboard->b_type = (u_int) btype;
maboard->b_slot = ctlr->slot;
maboard->b_bus = ctlr->bus_num;
maboard->b_bname = ctlr->bus_name;
return (1);
probe_fail:
bzero((char *)maboard, sizeof(ma_board_t)); /* paranoia */
FREE (maboard, M_DEVBUF);
ma_board[boardno] = NULL;
nboards--;
return (0);
}
STATIC int
maattach (struct controller *ctlr)
{
ma_board_t *maboard;
u_int boardno, port, i;
ihandler_t handler;
struct handler_intr_info info;
u_char reg;
maline_t *mal;
permset_t *set;
boardno = ctlr->ctlr_num;
if ((maboard = ma_board[boardno]) == NULL)
{
printf("maattach: bad board number\n");
goto attach_fail;
}
if (maboard->b_ctlr != ctlr)
{
printf("maattach: bad board pointer\n");
goto attach_fail;
}
if ( ! mabaudset )
mainitbaud();
/* set up interrupt handler */
handler.ih_bus = ctlr->bus_hd;
info.configuration_st = (caddr_t)ctlr;
info.config_type = CONTROLLER_CONFIG_TYPE;
info.intr = maintr;
info.param = (caddr_t)boardno;
handler.ih_bus_info = (char *)&info;
ma_id_t[boardno] = handler_add(&handler);
if (ma_id_t[boardno] == NULL)
{
printf("maattach: handler_add failed\n");
goto attach_fail;
}
if (handler_enable(ma_id_t[boardno]) != 0)
{
printf("maattach: handler_enable failed\n");
handler_del(ma_id_t[boardno]);
goto attach_fail;
}
maboard->b_ihandl = ma_id_t[boardno];
maboard->b_attach_flags |= INTERRUPT_ADDED;
/* Initialize MUTEX; we will use this MUTEX later on
** to lock our instance structure
**/
simple_lock_init(&maboard->b_lock);
maboard->b_attach_flags |= MUTEX_ADDED;
reg = (u_char)maboard->b_type;
/*
** Multiple board support.
*/
switch (reg)
{
default:
printf("ma%d: board type %d not recognized\n",ctlr->ctlr_num, reg);
goto attach_fail;
case MA_PCI16:
case MA_PCI16DMA:
maboard->b_intr = cd2400_intr;
maboard->b_nsports = 16;
maboard->b_npports = 0;
maboard->b_2400s = 4;
maboard->b_1400s = 0;
maboard->b_iackr = (NULL);
maboard->b_iackt = (NULL);
maboard->b_iackm = (NULL);
if (reg == MA_PCI16DMA) {
maboard->b_iack24 =
(u_long)(maboard->b_baseaddr + INTR_ACK_16PCIDMA);
maboard->b_chips[0] =
(u_long)maboard->b_baseaddr + BASE_16PCI1DMA;
maboard->b_chips[1] =
(u_long)maboard->b_baseaddr + BASE_16PCI2DMA;
maboard->b_chips[2] =
(u_long)maboard->b_baseaddr + BASE_16PCI3DMA;
maboard->b_chips[3] =
(u_long)maboard->b_baseaddr + BASE_16PCI4DMA;
} else { /* MAPCI16 */
maboard->b_iack24 =
(u_long)(maboard->b_baseaddr + (INTR_ACK_16PCIDMA<<2));
maboard->b_chips[0] =
(u_long)maboard->b_baseaddr + (BASE_16PCI1DMA<<2);
maboard->b_chips[1] =
(u_long)maboard->b_baseaddr + (BASE_16PCI2DMA<<2);
maboard->b_chips[2] =
(u_long)maboard->b_baseaddr + (BASE_16PCI3DMA<<2);
maboard->b_chips[3] =
(u_long)maboard->b_baseaddr + (BASE_16PCI4DMA<<2);
}
break;
case MA_PCI4DMA:
maboard->b_nsports = 4;
maboard->b_npports = 0;
maboard->b_2400s = 1;
maboard->b_1400s = 0;
maboard->b_iackr = (NULL);
maboard->b_iackt = (NULL);
maboard->b_iackm = (NULL);
maboard->b_iack24 = (u_long)(maboard->b_baseaddr + INTR_ACK_16PCIDMA);
maboard->b_intr = cd2400_intr;
maboard->b_chips[0] =
(u_long)maboard->b_baseaddr + BASE_16PCI1DMA;
maboard->b_chips[1] = 0;
maboard->b_chips[2] = 0;
maboard->b_chips[3] = 0;
break;
case MA_PCI8:
#ifdef NOTDONE
maboard->b_nsports = 8;
maboard->b_npports = 0;
maboard->b_2400s = 0;
maboard->b_1400s = 2;
maboard->b_iackr = (u_long)(maboard->b_baseaddr + INTR_ACKR_8PCI);
maboard->b_iackt = (u_long)(maboard->b_baseaddr + INTR_ACKT_8PCI);
maboard->b_iackm = (u_long)(maboard->b_baseaddr + INTR_ACKM_8PCI);
maboard->b_iack24 = (NULL);
maboard->b_intr = cd1400_intr;
maboard->b_chips[0] =
(u_long)maboard->b_baseaddr + BASE_8PCI1;
maboard->b_chips[1] =
(u_long)maboard->b_baseaddr + BASE_8PCI2;
maboard->b_chips[2] = 0;
maboard->b_chips[3] = 0;
#endif
break;
}
if (maboard->b_nsports)
{
if ((MALLOC(maboard->b_malinebase, maline_t *,
sizeof(maline_t) * maboard->b_nsports,
M_DEVBUF, M_NOWAIT)) == NULL)
{
printf("ma%d: could not allocate line structures\n",boardno);
goto attach_fail;
}
maboard->b_attach_flags |= MHLINE_ADDED;
if ((MALLOC(maboard->b_psetbase, permset_t *,
sizeof(permset_t) * maboard->b_nsports,
M_DEVBUF, M_NOWAIT)) == NULL)
{
printf("ma%d: could not allocate permset structures\n",boardno);
goto attach_fail;
}
maboard->b_attach_flags |= PERMSET_ADDED;
(void) bzero((caddr_t)maboard->b_malinebase,
sizeof(maline_t) * maboard->b_nsports);
(void) bzero((caddr_t)maboard->b_psetbase,
sizeof(permset_t) * maboard->b_nsports);
}
/*
** now do chip specific setup
*/
if (maboard->b_type == MA_PCI16) {
i = (u_int) read_io_port(maboard->b_plx+0x68L, 4, 0);
#ifdef MADEBUG
printf("ma: plx ICR is 0x%x\n",i);
#endif
i |= 0x0800;
write_io_port(maboard->b_plx+0x68L, 4, 0, i);
}
#ifdef MADEBUG
printf("ma: attaching %d ports\n",maboard->b_nsports);
#endif
/* set up line structures */
mal = maboard->b_malinebase;
set = maboard->b_psetbase;
for (port = 0; port < maboard->b_nsports; port++, mal++, set++)
{
trace(0x3bad000000000000, (u_long) port);
trace(0x3bad000000000001, (u_long) mal);
mal->board = boardno;
mal->unit = port;
mal->permset = set;
mal->clock = maboard->b_clock;
mal->l_lock = &maboard->b_lock;
switch (maboard->b_type)
{
default: /* this should not be possible if we got this far! */
maprintf("ma%d: Fatal err, the sky has fallen twice!", boardno);
goto attach_fail;
case MA_PCI16:
case MA_PCI16DMA:
case MA_PCI4DMA:
{
register u_long cd24;
trace(0x3bad000000000002, (u_long) mal);
mal->l_open = cd2400_open;
mal->l_close = cd2400_close;
mal->l_param = cd2400_param;
mal->l_start = cd2400_start;
mal->l_endbreak = cd2400_endbreak;
mal->l_mctl = cd2400_mctl;
mal->chip = CD_2400;
if ( port < 4 )
mal->cd2400 = maboard->b_chips[0];
else if ( port < 8 )
mal->cd2400 = maboard->b_chips[1];
else if ( port < 12 )
mal->cd2400 = maboard->b_chips[2];
else if ( port < 16 )
mal->cd2400 = maboard->b_chips[3];
/* allocate the dma buffers */
mal->l_rab = (u_int *) kalloc(MADMASIZE);
mal->l_rbb = (u_int *) kalloc(MADMASIZE);
mal->l_tab = (u_int *) kalloc(MADMASIZE);
mal->l_tbb = (u_int *) kalloc(MADMASIZE);
if ( (mal->l_rab == (u_int *)NULL ) ||
( mal->l_rbb == (u_int *)NULL ) ||
( mal->l_tab == (u_int *)NULL ) ||
( mal->l_tbb == (u_int *)NULL ) )
{
maprintf("ma%d: could not allocate dma buffers\n",boardno);
goto attach_fail;
}
if (dma_map_alloc(MADMASIZE,
maboard->b_ctlr, &mal->l_dma_hndl_ra, 0) == 0) {
maprintf("ma%d: could not allocate dma map\n",boardno);
goto attach_fail;
}
if (dma_map_alloc(MADMASIZE,
maboard->b_ctlr, &mal->l_dma_hndl_rb, 0) == 0) {
maprintf("ma%d: could not allocate dma map\n",boardno);
goto attach_fail;
}
if (dma_map_alloc(MADMASIZE,
maboard->b_ctlr, &mal->l_dma_hndl_ta, 0) == 0) {
maprintf("ma%d: could not allocate dma map\n",boardno);
goto attach_fail;
}
if (dma_map_alloc(MADMASIZE,
maboard->b_ctlr, &mal->l_dma_hndl_tb, 0) == 0) {
maprintf("ma%d: could not allocate dma map\n",boardno);
goto attach_fail;
}
cd24 = mal->cd2400;
trace(0x3bad000000000003, (u_long) cd24);
trace(0x3bad0000000000f3, (u_long) (gfrcr));
/* Initialize the cd2400 if 1st port of chip */
if ((port % 4) == 0)
{
#ifdef MADEBUGXXXX
reg = (u_char) read_io_port(cd24+gfrcr, 1, 0);
mb();
trace(0x3bad000000000004, (u_long) reg);
#endif
/* clear gfcr */
write_io_port(cd24+gfrcr, 1, 0, 0);
mb();
/* reset chip */
write_io_port(cd24+ccr, 1, 0, CCR_RSTALL);
mb();
trace(0x3bad000000000005, (u_long) port);
/* it takes ~500 mics to reset, give it 2X that */
DELAY ( 1000 ); /* wait for gfrcr to be non-zero */
for ( i = 0; i < 10; i++ )
{
reg = (u_char) read_io_port(cd24+gfrcr, 1, 0);
mb();
if (reg) break;
maprintf ( ".",mal);
DELAY (1000); /* wait for gfrcr to be non-0 */
}
reg = (u_char) read_io_port(cd24+gfrcr, 1, 0);
mb();
trace(0x3bad000000000006, (u_long) reg);
if (reg == 0)
{
printf ("ma: failed to reset\n");
trace(0x3bad000000000007, (u_long) reg);
goto attach_fail;
}
}
mal->revision = reg;
trace(0x3bad000000000008, (u_long) port);
cd2400_config(mal);
break;
} /* cases ma_pci4dma and ma_pci16dma */
#ifdef NOTDONE
case MA_PCI8:
{
register u_long cd14;
trace(0x3bad000000000009, (u_long) mal);
mal->l_open = cd1400_open;
mal->l_close = cd1400_close;
mal->l_param = cd1400_param;
mal->l_start = cd1400_start;
mal->l_endbreak = cd1400_endbreak;
mal->l_mctl = cd1400_mctl;
mal->chip = CD_1400;
if ( port < 4 )
mal->cd1400 = maboard->b_chips[0];
else if ( port < 8 )
mal->cd1400 = maboard->b_chips[1];
else if ( port < 12 )
mal->cd1400 = maboard->b_chips[2];
else if ( port < 16 )
mal->cd1400 = maboard->b_chips[3];
cd14 = mal->cd1400;
/* Initialize the cd1400 if 1st port of chip */
if ((port % 4) == 0)
{
write_io_port(cd14+GFRCR, 1, 0, 0); /* clear GFRCR */
mb();
/* reset chip */
write_io_port(cd14+CCR, 1, 0, CCR_FULL_RESET);
mb();
/* it takes ~500 mics to reset, give it 2X that */
DELAY ( 1000 ); /* wait for gfrcr to be non-zero */
for ( i = 0; i < 10; i++ )
{
reg = (u_char) read_io_port(cd14+GFRCR, 1, 0);
mb();
if (reg) break;
maprintf ( ".",mal);
DELAY (1000); /* wait for gfrcr to be non-0 */
}
reg = (u_char) read_io_port(cd14+GFRCR, 1, 0);
mb();
if (reg == 0)
{
maprintf ("ma%d: failed to reset\n", boardno);
return(-1);
}
/* set chip id in [R,T,M]ICR global registers */
switch (port) {
case 0:
write_io_port(cd14+RICR, 1, 0, 0x01);
mb();
write_io_port(cd14+TICR, 1, 0, 0x02);
mb();
write_io_port(cd14+MICR, 1, 0, 0x03);
break;
case 4:
write_io_port(cd14+RICR, 1, 0, 0x11);
mb();
write_io_port(cd14+TICR, 1, 0, 0x12);
mb();
write_io_port(cd14+MICR, 1, 0, 0x13);
break;
case 8:
write_io_port(cd14+RICR, 1, 0, 0x21);
mb();
write_io_port(cd14+TICR, 1, 0, 0x22);
mb();
write_io_port(cd14+MICR, 1, 0, 0x23);
break;
case 12:
write_io_port(cd14+RICR, 1, 0, 0x31);
mb();
write_io_port(cd14+TICR, 1, 0, 0x32);
mb();
write_io_port(cd14+MICR, 1, 0, 0x33);
break;
}
mb();
}
reg = (u_char) read_io_port(cd14+GFRCR, 1, 0);
mb();
mal->revision = reg;
cd1400_config (mal); /* configure the port */
} /* case ma_pci8 */
#endif NOTDONE
}
trace(0x3bad00000000000a, (u_long) port);
} /* for port */
#ifdef MADEBUG
printf("\nma: %s revision 0x%x\n",
maboard->b_malinebase->chip == CD_1400 ? "CD1400" : "CD2400",
maboard->b_malinebase->revision);
#endif
return (0);
attach_fail:
printf("MAGMA: could not attach board %d",boardno);
(void)madettach(NULL, ctlr);
return (-1);
}
static int
madettach (struct bus *bus, struct controller *ctlr)
{
u_int instance, port;
register ma_board_t *maboard;
register maline_t *mal;
instance = ctlr->ctlr_num;
if (instance < 0 || instance > nboards)
return (ENODEV);
maprintf("ma%d: is being detached.", instance);
nboards--;
maboard = (ma_board_t *) ma_board[instance];
if (maboard == NULL) {
maprintf("ma%d: detach: could not get state", instance);
return (ENODEV);
}
if (maboard->b_attach_flags & SERIAL_PORT_MUTEXES) {
/* reset the chips to quiesce interrupts */
switch (maboard->b_type) {
default:
maprintf("ma: madetach, bad board type %d\n", maboard->b_type);
break;
case MA_PCI16:
/* Clear plx interrupt enable */
port = (u_int) read_io_port(maboard->b_plx+0x68L, 4, 0);
port &= ~0x0800;
write_io_port(maboard->b_plx+0x68L, 4, 0, port);
/* No break */
case MA_PCI16DMA:
case MA_PCI4DMA:
for (port = 0; port < maboard->b_2400s; port++) {
write_io_port(maboard->b_chips[port]+ccr, 1, 0, CCR_RSTALL);
mb();
}
break;
}
maboard->b_attach_flags &= ~SERIAL_PORT_MUTEXES;
}
#if 0
if (maboard->b_attach_flags & HANDLE_ADDED) {
ddi_dma_free (maboard->dvma.dvma_handle);
maboard->dvma.dvma_handle = NULL;
maboard->b_attach_flags &= ~HANDLE_ADDED;
}
if (maboard->b_attach_flags & SYNC_ADDED)
delete_sync(maboard);
if (maboard->b_attach_flags & DVMA_ADDED) {
FREE (maboard->ma_dvma.dvma_address, M_DEVBUF);
maboard->ma_dvma.dvma_address = NULL;
maboard->b_attach_flags &= ~DVMA_ADDED;
}
#endif
if (maboard->b_attach_flags & PERMSET_ADDED) {
FREE (maboard->b_psetbase, M_DEVBUF);
maboard->b_psetbase = NULL;
maboard->b_attach_flags &= ~PERMSET_ADDED;
}
if (maboard->b_attach_flags & MHLINE_ADDED) {
FREE (maboard->b_malinebase, M_DEVBUF);
maboard->b_malinebase = NULL;
maboard->b_attach_flags &= ~MHLINE_ADDED;
}
if (maboard->b_attach_flags & MUTEX_ADDED) {
simple_lock_terminate(&maboard->b_lock);
maboard->b_attach_flags &= ~MUTEX_ADDED;
}
if (maboard->b_attach_flags & INTERRUPT_ADDED) {
if (handler_disable(maboard->b_ihandl) != 0)
return(ENXIO);
(void)handler_del(maboard->b_ihandl);
ma_id_t[instance] = maboard->b_ihandl = NULL;
maboard->b_attach_flags &= ~INTERRUPT_ADDED;
}
if (maboard->b_attach_flags & SOFT_STATE_ALLOCATED) {
/* remove this board from our polling board array */
for( port = 0; port < nboards; port++ ) {
if( ma_board[port] == maboard ) {
ma_board[port] = NULL;
break;
}
}
bzero((char *)maboard, sizeof(ma_board_t));
FREE (maboard, M_DEVBUF);
}
return ( 0 );
}
|