Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

692 lines
24 KiB
C

static char sccsid[] = "@(#)20 1.5 src/bos/kernext/mpa/mpa_ioctl.c, sysxmpa, bos411, 9428A410j 3/28/94 16:22:50";
/*
* COMPONENT_NAME: (SYSXMPA) MP/A SDLC DEVICE DRIVER
*
* FUNCTIONS: change_parms
* cio_halt
* cio_start
* mpa_ioctl
* sdlc_init
*
*
* ORIGINS: 27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1993
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*******************************************************************
* Include Files *
*******************************************************************/
#include <sys/adspace.h>
#include <sys/errids.h>
#include <sys/devinfo.h>
#include <sys/dma.h>
#include <sys/device.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/ioacc.h>
#include <sys/iocc.h>
#include <sys/malloc.h>
#include <sys/mpadd.h>
#include <sys/param.h>
#include <sys/pin.h>
#include <sys/sleep.h>
#include <sys/sysdma.h>
#include <sys/sysmacros.h>
#include <sys/syspest.h>
#include <sys/xmem.h>
#include <sys/trchkid.h>
#include <sys/ddtrace.h>
extern void recv_timer();
/*
* NAME: mpa_ioctl
*
* FUNCTION: Performs a variety of control functions to the MPA device
*
* EXECUTION ENVIRONMENT:
*
* Preemptable : Yes
* VMM Critical Region: No
* Runs on Fixed Stack: Yes
* May Page Fault : Yes
* May Backtrack : Yes
*
* NOTES: More detailed description of the function, down to
* what bits / data structures, etc it manipulates.
*
* DATA STRUCTURES:
*
* RETURN VALUE DESCRIPTION:
*/
int mpa_ioctl ( dev_t dev,
int cmd,
caddr_t arg,
int devflag,
int chan,
int ext )
{
int error; /* return value */
struct acb *acb; /* pointer to acb struct */
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ log a trace hook ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
DDHKWD5(HKWD_DD_MPADD, DD_ENTRY_IOCTL, 0, dev, cmd,
devflag, chan, ext);
MPATRACE4("IocE",dev,cmd,chan);
if ( ((acb = get_acb(minor(dev))) == NULL) ||
!(OPENP.op_flags&OP_OPENED) )
{
MPATRACE2("Ioe1",dev);
return ENXIO;
}
if (lockl(&acb->adap_lock, LOCK_SIGRET) != LOCK_SUCC)
{
MPATRACE2("Ioe2",dev);
return EINTR;
}
error = 0;
switch ( cmd )
{
case CIO_START: /* Start Device Command */
error = cio_start(acb, arg, devflag, chan);
break;
case CIO_HALT: /* Halt Device Command */
error = cio_halt(acb, arg, devflag, chan);
break;
case MP_CHG_PARMS: /* Change Parameters Command */
error = change_parms(acb, arg, devflag, chan);
break;
default:
error = 0;
break;
}
MPATRACE3("IocX",dev,error);
unlockl(&acb->adap_lock);
if (error == -1)
{
return EIO;
}
DDHKWD5(HKWD_DD_MPADD, DD_EXIT_IOCTL, error, dev, 0, 0, 0, 0 );
return (error);
} /* mpa_ioctl() */
/*--------------------- SDLC_INIT -------------------------------*/
/* */
/* NAME: sdlc_init */
/* */
/* FUNCTION: */
/* Sets up pos */
/* based on current info in dds, then initializes ports based */
/* on current info in dds, gets card ready for xfers. */
/* */
/* EXECUTION ENVIRONMENT: */
/* Can be called from process or offlevel environment. */
/* */
/* DATA STRUCTURES: */
/* */
/* RETURNS: */
/* 0 If the init succeeded. */
/* */
/* EXTERNAL PROCEDURES CALLED: */
/* */
/* */
/* */
/* */
/*----------------------------------------------------------------------*/
int sdlc_init (struct acb *acb)
{
uchar value;
int count,rc,cntr=0;
ulong pos;
MPATRACE2("SdlE",acb->dev);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ I set this flag here so that if an irpt line is hung ³
³ The irpt handler can disable the card and set MPADEAD ³
³ Then this start code can check for MPADEAD and know ³
³ There is a problem and return a bad rc to application ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
acb->flags &= ~MPADEAD;
acb->stats.ds.irpt_fail = 0;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Set up 8255 Port B for operation. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ 8255 PORT C bit Assignment ³
³ | d7 | d6 | d5 | d4 | d3 | d2 | d1 | d0 | ³
³ | | | | | | | | ³
³ | | | | | | | 0=Turn on Speed Select ³
³ | | | | | | 0=Turn on Select Standby ³
³ | | | | | 0=Turn on Test ³
³ | | | | 0=Reset Modem Status Changed Logic ³
³ | | | 1=Reset 8273 ³
³ | | 1=Gate Timer 2 ³
³ | 1=Gate Timer 1 ³
³ 1=Enable Level 4 Interrupt ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Drop the 8273 reset bit. ³
³ The 8273 was put in a reset ³
³ state by the config code or the close or halt code.³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
value = 0x00;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Set up default values ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
value = SEL_STANBY_OFF|TEST_OFF|FREE_STAT_CHG;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ If DRS (Data Rate Select) is not indicated, it ³
³ can be turned off here using SPEED_SEL_OFF ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( !(acb->strt_blk.modem_flags & MF_DRS_ON) )
{
value |= SPEED_SEL_OFF; /* DRS Off */
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ We should enable level 4 interrupts so we can detect ³
³ changes in modem status (DSR and CTS changes) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
value |= ENABLE_IRPT4;
while ( ++cntr < 2)
{
if(PIO_PUTC(acb, PORT_B_8255, value )==-1)
{
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ if this fails then pos2 enable may be off try ³
³ setting it back on and try again ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
pos = MPA_IOCC_ATT;
BUS_PUTC( pos + POS2, acb->pos2 );
BUS_PUTC( pos + POS3, acb->pos3 );
IOCC_DET(pos);
}
else
{
acb->state.port_b_8255 = value;
MPATRACE3("Sdl1",acb->dev,acb->state.port_b_8255);
break;
}
}
if(cntr==2)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
if(acb->flags&MPADEAD)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ 8255 PORT C bit Assignment ³
³ | d7 | d6 | d5 | d4 | d3 | d2 | d1 | d0 | ³
³ | | | | | | | | ³
³ | | | | | | | 1= Gate Internal clk ³
³ | | | | | | 1= Gate External clk ³
³ | | | | | 1 = Set Electronic Wrap ³
³ | | | | 0=Enable irpts and DMA req ³
³ | | | Oscillating= Recving data ³
³ | | Oscillating= Timer 0 output ³
³ | 0=Test active in Electronic Wrap Mode ³
³ 1=SDLC, 0 = BSC ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Only the lower nibble of port C is writable. ³
³ Disable irpts and DMA and set 8273 in electronic wrap ³
³ and degate both internal and external clocks. This ³
³ Isolates the 8273 from both modem(DCE) and microchannel ³
³ interfaces for the setup procedures that follow: ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if(PIO_PUTC( acb, PORT_C_8255, 0x0C )==-1)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
if(acb->flags&MPADEAD)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ set up the Operating mode reg of 8273..reset all valid bits ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=RESET_OPER_MODE_CMD;
acb->cmd_parms.parm[0]=0xC0;
acb->cmd_parms.parm_count=1;
acb->state.oper_mode_8273=acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ turn on early interrupts on transmit to provide ³
³ faster turnaround on the receive ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
value = SET_EARLY_TX_ON;
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=SET_OPER_MODE_CMD;
acb->cmd_parms.parm[0]=value;
acb->cmd_parms.parm_count=1;
acb->state.oper_mode_8273 |= acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Reset all bits in the Serial I/O mode reg of 8273 ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=RESET_IO_MODE_CMD;
acb->cmd_parms.parm[0]=0xF8;
acb->cmd_parms.parm_count=1;
acb->state.serial_io_8273 = acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Set the bits in Serial I/O mode reg ³
³ for NRZI if indicated by caller ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( acb->strt_blk.data_flags & DATA_FLG_NRZI )
{
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=SET_IO_MODE_CMD;
acb->cmd_parms.parm[0]=SET_NRZI_DATA;
acb->cmd_parms.parm_count=1;
acb->state.serial_io_8273 |= acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Reset the data transfer reg bit (makes default DMA) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=RESET_DATA_XFER_CMD;
acb->cmd_parms.parm[0]=0xFE;
acb->cmd_parms.parm_count=1;
acb->state.data_xfer_8273=acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Reset the One bit delay reg of 8273 ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=RESET_1_BIT_DELAY_CMD;
acb->cmd_parms.parm[0]=0x7F;
acb->cmd_parms.parm_count=1;
acb->state.one_bit_8273=acb->cmd_parms.parm[0];
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ 8273 PORT B bit Assignment ³
³ | d7 | d6 | d5 | d4 | d3 | d2 | d1 | d0 | ³
³ | | | | | | | | ³
³ | | | | | | | RTS-Request to Send ³
³ | | | | | | Reserved ³
³ | | | | | DTR-Data Terminal Ready ³
³ | | | | Reserved ³
³ | | | V.25 bis ENABLE ³
³ | | Flag Detect ³
³ | NOT USED ³
³ NOT USED ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ set up the Port B reg of 8273, Reset all valid bits. ³
³ However, don't set DTR at this time... ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=RESET_8273_PORT_B_CMD;
acb->cmd_parms.parm[0]=0xCA;
acb->state.port_b_8273=acb->cmd_parms.parm[0];
acb->cmd_parms.parm_count=1;
if((rc=que_command(acb)) ) return(rc);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ If being set up as Continuous Carrier, ³
³ turn RTS on now so it will always be on³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( acb->strt_blk.data_flags & DATA_FLG_C_CARR_ON )
{
bzero(&acb->cmd_parms,sizeof(cmd_phase_t));
acb->cmd_parms.cmd=SET_8273_PORT_B_CMD;
acb->cmd_parms.parm[0]=SET_8273_PORT_B_RTS;
acb->state.port_b_8273 |=SET_RTS;
acb->cmd_parms.parm_count=1;
if( (rc=que_command(acb)) ) return (rc);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ set the station type in adapter control block. ³
³ if no poll_addr is specified, set up in GENERAL³
³ receive mode (passes all frames to memory). ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if(acb->strt_blk.poll_addr)
{
acb->station_type = SELECTIVE; /* setup as selective receiver */
}
else
{
acb->station_type = GENERAL; /* setup as general receiver */
}
MPATRACE4("Sdl2",acb->dev,acb->station_type,acb->strt_blk.poll_addr);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Set up 8255 Port C for operation. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Enable external clock, DMA, and interrupts ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
value = 0x00;
value |= GATE_EXT_CLK;
if(PIO_PUTC( acb, PORT_C_8255, value)==-1)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
acb->state.port_c_8255 = value;
if(acb->flags&MPADEAD)
{
mpalog(acb,ERRID_MPA_ADPERR , __LINE__,__FILE__,0,0);
return EIO;
}
MPATRACE3("SdlX",acb->dev,acb->flags);
return(0);
} /* sdlc_init */
int cio_start (struct acb *acb,
t_start_dev *arg,
int devflag,
int chan)
{
int rc=0;
MPATRACE4("CstE",acb->dev,devflag,chan);
if ( acb->flags & STARTED_CIO )
{
MPATRACE4("Cse1",acb->dev,devflag,chan);
return EBUSY;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ get parameter block ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->strt_blk,sizeof(t_start_dev));
if (rc = COPYIN (devflag, (caddr_t)arg, &acb->strt_blk,
sizeof(t_start_dev)))
{
MPATRACE4("Cse2",acb->dev,chan,rc);
rc= EFAULT;
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Check to see if baud_rate is set, or if ³
³ the physical link is not RS232, or data ³
³ protocol is not SDLC Half Duplex ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( (acb->strt_blk.baud_rate != 0) ||
(!(acb->strt_blk.phys_link & PHYS_232)) ||
(acb->strt_blk.data_proto != DATA_PROTO_SDLC_HDX) )
{
MPATRACE4("Cse3",acb->strt_blk.baud_rate,acb->strt_blk.phys_link,acb->strt_blk.data_proto);
return (EINVAL);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Clear the status structure ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
bzero(&acb->stats,sizeof(mpa_query_t));
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Get the poll address from the start block ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
acb->station_addr = acb->strt_blk.poll_addr;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ make sure adapter is reset. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( (rc = shutdown_adapter(acb)) )
{
MPATRACE4("Cse4",acb->dev,chan,rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ set the adapter up for SDLC transfers ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( (rc = sdlc_init(acb)) )
{
MPATRACE4("Cse5",acb->dev,chan,rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ handle modem logic for the connection ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( (rc=ctrl_modem(acb)) )
{
MPATRACE4("Cse5",acb->dev,chan,rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Kick off the first recv.. There will always be a recive ³
³ outstanding with this driver design. When xmits are ³
³ required the recv is aborted until after the xmit completes ³
³ then restarted. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if( (rc = startrecv(acb)) )
{
MPATRACE4("Cse6",acb->dev,chan,rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Start receive timer now, but it won't start reporting timeouts ³
³ until the line is active. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( (acb->strt_blk.rcv_timeout != 0) &&
(!(acb->flags & RCV_TIMER_ON)) )
{
acb->flags |= RCV_TIMER_ON;
timeout(recv_timer, (caddr_t)acb, (HZ/10) * (int)acb->strt_blk.rcv_timeout );
}
MPATRACE3("CstX",acb->dev,rc);
return rc;
} /* cio_start */
int cio_halt (struct acb *acb,
cio_sess_blk_t *arg,
int devflag,
int chan)
{
int rc=0,cnt=0;
cio_sess_blk_t sess_blk;
MPATRACE2("ChlE",acb->dev);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ get parameter block ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (COPYIN (devflag, (caddr_t)arg, &sess_blk, sizeof(sess_blk)))
{
MPATRACE2("Che1",acb->dev);
return EFAULT;
}
if ( !(acb->flags & STARTED_CIO) )
{
sess_blk.status = CIO_OK;
async_status(acb,CIO_HALT_DONE, CIO_OK,0,0, 0);
MPATRACE3("Chlx",acb->dev,acb->flags);
return 0; /* Device already halted */
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ do not shutdown if xmit pending ³
³ NOTE: irpts not disabled so xmits ³
³ can complete ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
while( (acb->act_xmit_head != NULL) && ++cnt < 49 )
{
delay(1);
}
if( (rc=shutdown_adapter(acb)) )
{
MPATRACE2("Che2",acb->dev);
return rc;
}
free_active_q(acb);
sess_blk.status = CIO_OK;
async_status(acb,CIO_HALT_DONE, CIO_OK,0,0, 0);
MPATRACE3("ChlX",acb->dev,rc);
return 0;
} /* cio_halt */
int change_parms ( struct acb *acb,
t_chg_parms *arg,
int devflag,
int chan)
{ /*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ start of change parameters ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
int chg_mask; /* mask for parameters */
int parm1, parm2; /* parameters */
int rc = 0; /* return code */
int lvl; /* saved irpt level */
t_chg_parms new_parm; /* chg parms struct */
MPATRACE2("CpmE",acb->dev);
bzero(&new_parm,sizeof(t_chg_parms));
if (rc = COPYIN (devflag, (caddr_t)arg, &new_parm, sizeof(t_chg_parms)))
{
return EFAULT;
}
parm1 = (int) new_parm.rcv_timer;
parm2 = (int) new_parm.poll_addr;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Set the change mask value to determine which parameter ³
³ needs to be changed (rcv_timer, poll_addr, or both). ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
chg_mask = new_parm.chg_mask;
MPATRACE4("Cpm1",acb->dev,parm1,parm2);
if (chg_mask & FS_RCV_TMR) /* receive timer needs to be changed */
{
MPATRACE2("Cpm2",acb->dev);
acb->strt_blk.rcv_timeout = new_parm.rcv_timer;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ If timer is on and new rcv_timeout is zero, stop timer ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( acb->strt_blk.rcv_timeout == 0 )
{
untimeout(recv_timer,(caddr_t)acb);
acb->flags &= ~RCV_TIMER_ON;
}
}
if (chg_mask & FS_POLL_ADDR) /* poll address needs to be changed */
{
MPATRACE2("Cpm3",acb->dev);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Disable the receiver before ³
³ changing the poll address. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( acb->strt_blk.rcv_timeout != 0 )
{
untimeout(recv_timer,(caddr_t)acb);
acb->flags &= ~RCV_TIMER_ON;
}
if ( (rc = stoprecv(acb)) )
{
MPATRACE2("Cpe1",rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Setup the adapter to perform selective ³
³ receives on the poll address passed in.³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
acb->station_addr = new_parm.poll_addr;
acb->station_type = SELECTIVE;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Enable the receiver again once ³
³ the poll address is changed. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( (rc = startrecv(acb)) )
{
MPATRACE2("Cpe2",rc);
return rc;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ start the receive timer if indicated ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ( (acb->strt_blk.rcv_timeout != 0 ) &&
(!(acb->flags & RCV_TIMER_ON)) )
{
acb->flags |= RCV_TIMER_ON;
timeout(recv_timer, (caddr_t)acb, (HZ/10) * (int)acb->strt_blk.rcv_timeout );
}
}
MPATRACE2("CpmX",rc);
return rc;
} /* change_parms */