* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)if_css.c 7.7 (Berkeley) %G%
* DEC/CSS IMP11-A ARPAnet IMP interface driver.
* Since "imp11a" is such a mouthful, it is called
* "css" after the LH/DH being called "acc".
* As delivered from DEC/CSS, it
* is addressed and vectored as two DR11-B's. This makes
* Autoconfig almost IMPOSSIBLE. To make it work, the
* interrupt vectors must be restrapped to make the vectors
* consecutive. The 020 hole between the CSR addresses is
* tolerated, althought that could be cleaned-up also.
* Additionally, the TRANSMIT side of the IMP11-A has the
* lower address of the two subunits, so the vector ordering
* in the CONFIG file is reversed from most other devices.
* device css0 .... cssxint cssrint
* If you get it wrong, it will still autoconfig, but will just
* sit there with RECEIVE IDLE indicated on the front panel.
#include "../netimp/if_imp.h"
#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"
int cssprobe(), cssattach(), cssrint(), cssxint();
struct uba_device
*cssinfo
[NCSS
];
u_short cssstd
[] = { 0 };
struct uba_driver cssdriver
=
{ cssprobe
, 0, cssattach
, 0, cssstd
, "css", cssinfo
};
int cssinit(), cssoutput(), cssdown(), cssreset();
* "Lower half" of IMP interface driver.
* Each IMP interface is handled by a common module which handles
* the IMP-host protocol and a hardware driver which manages the
* hardware specific details of talking with the IMP.
* The hardware portion of the IMP driver handles DMA and related
* management of UNIBUS resources. The IMP protocol module interprets
* contents of these messages and "controls" the actions of the
* hardware module during IMP resets, but not, for instance, during
* The two modules are coupled at "attach time", and ever after,
* through the imp interface structure. Higher level protocols,
* e.g. IP, interact with the IMP driver, rather than the CSS.
struct imp_softc
*css_imp
; /* pointer to IMP's imp_softc struct */
struct ifuba css_ifuba
; /* UNIBUS resources */
struct mbuf
*css_iq
; /* input reassembly queue */
short css_olen
; /* size of last message sent */
char css_flush
; /* flush remainder of message */
* Reset the IMP and cause a transmitter interrupt by
register int br
, cvec
; /* r11, r10 value-result */
register struct cssdevice
*addr
= (struct cssdevice
*)reg
;
br
= 0; cvec
= br
; br
= cvec
;
addr
->css_icsr
= CSS_CLR
;
addr
->css_ocsr
= CSS_CLR
;
addr
->css_ocsr
= CSS_IE
| CSS_GO
; /* enable interrupts */
* Call the IMP module to allow it to set up its internal
* state, then tie the two modules together by setting up
* the back pointers to common data structures.
register struct uba_device
*ui
;
register struct css_softc
*sc
= &css_softc
[ui
->ui_unit
];
register struct impcb
*ip
;
if ((sc
->css_imp
= impattach(ui
->ui_driver
->ud_dname
, ui
->ui_unit
,
ip
= &sc
->css_imp
->imp_cb
;
ip
->ic_output
= cssoutput
;
sc
->css_ifuba
.ifu_flags
= UBA_CANTWAIT
| UBA_NEED16
;
sc
->css_ifuba
.ifu_flags
|= UBA_NEEDBDP
;
* Reset interface after UNIBUS reset.
* If interface is on specified uba, reset its state.
register struct uba_device
*ui
;
register struct css_softc
*sc
;
if (unit
>= NCSS
|| (ui
= cssinfo
[unit
]) == 0 || ui
->ui_alive
== 0 ||
sc
->css_imp
->imp_if
.if_flags
&= ~IFF_RUNNING
;
/* must go through IMP to allow it to set state */
(*sc
->css_imp
->imp_if
.if_init
)(sc
->css_imp
->imp_if
.if_unit
);
* Initialize interface: clear recorded pending operations,
* and retrieve, and reinitialize UNIBUS resources.
register struct css_softc
*sc
;
register struct uba_device
*ui
;
register struct cssdevice
*addr
;
if (unit
>= NCSS
|| (ui
= cssinfo
[unit
]) == 0 || ui
->ui_alive
== 0) {
printf("css%d: not alive\n", unit
);
* Header length is 0 to if_ubainit since we have to pass
* the IMP leader up to the protocol interpretaion
* routines. If we had the deader length as
* sizeof(struct imp_leader), then the if_ routines
* would assume we handle it on input and output.
if ((sc
->css_imp
->imp_if
.if_flags
& IFF_RUNNING
) == 0 &&
if_ubainit(&sc
->css_ifuba
, ui
->ui_ubanum
, 0,
(int)btoc(IMP_RCVBUF
)) == 0) {
printf("css%d: can't initialize\n", unit
);
sc
->css_imp
->imp_if
.if_flags
&= ~(IFF_UP
| IFF_RUNNING
);
sc
->css_imp
->imp_if
.if_flags
|= IFF_RUNNING
;
addr
= (struct cssdevice
*)ui
->ui_addr
;
/* reset the imp interface. */
addr
->css_icsr
= CSS_CLR
;
addr
->css_ocsr
= CSS_CLR
;
addr
->css_icsr
= IN_HRDY
; /* close the relay */
* This may hang if the imp isn't really there.
* Will test and verify safe operation.
if ((addr
->css_icsr
& (IN_HRDY
|IN_IMPNR
)) == IN_HRDY
)
addr
->css_icsr
= IN_HRDY
; /* close the relay */
printf("css%d: imp doesn't respond, icsr=%b\n", unit
,
CSS_INBITS
, addr
->css_icsr
);
* Put up a read. We can't restart any outstanding writes
* until we're back in synch with the IMP (i.e. we've flushed
* the NOOPs it throws at us).
* Note: IMP_RCVBUF includes the leader.
info
= sc
->css_ifuba
.ifu_r
.ifrw_info
;
addr
->css_iba
= (u_short
)info
;
addr
->css_iwc
= -(IMP_RCVBUF
>> 1);
IN_HRDY
| CSS_IE
| IN_WEN
| ((info
& 0x30000) >> 12) | CSS_GO
;
* Drop the host ready line to mark host down.
register struct cssdevice
*addr
;
addr
= (struct cssdevice
*)(cssinfo
[unit
]->ui_addr
);
/* reset the imp interface. */
addr
->css_icsr
= CSS_CLR
;
addr
->css_ocsr
= CSS_CLR
;
register struct css_softc
*sc
= &css_softc
[unit
];
sc
->css_imp
->imp_cb
.ic_oactive
= 0;
if (sc
->css_ifuba
.ifu_xtofree
) {
m_freem(sc
->css_ifuba
.ifu_xtofree
);
sc
->css_ifuba
.ifu_xtofree
= 0;
* Start output on an interface.
struct uba_device
*ui
= cssinfo
[unit
];
register struct css_softc
*sc
= &css_softc
[unit
];
register struct cssdevice
*addr
;
sc
->css_olen
= if_wubaput(&sc
->css_ifuba
, m
);
* Have request mapped to UNIBUS for transmission.
* Purge any stale data from the BDP, and start the output.
if (sc
->css_ifuba
.ifu_flags
& UBA_NEEDBDP
)
UBAPURGE(sc
->css_ifuba
.ifu_uba
, sc
->css_ifuba
.ifu_w
.ifrw_bdp
);
addr
= (struct cssdevice
*)ui
->ui_addr
;
info
= sc
->css_ifuba
.ifu_w
.ifrw_info
;
addr
->css_oba
= (u_short
)info
;
addr
->css_owc
= -((sc
->css_olen
+ 1) >> 1);
(u_short
)(CSS_IE
| OUT_ENLB
| ((info
& 0x30000) >> 12) | CSS_GO
);
sc
->css_imp
->imp_cb
.ic_oactive
= 1;
* Output interrupt handler.
register struct uba_device
*ui
= cssinfo
[unit
];
register struct css_softc
*sc
= &css_softc
[unit
];
register struct cssdevice
*addr
;
addr
= (struct cssdevice
*)ui
->ui_addr
;
if (sc
->css_imp
->imp_cb
.ic_oactive
== 0) {
printf("css%d: stray output interrupt csr=%b\n",
unit
, addr
->css_ocsr
, CSS_OUTBITS
);
sc
->css_imp
->imp_if
.if_opackets
++;
sc
->css_imp
->imp_cb
.ic_oactive
= 0;
if (addr
->css_ocsr
& CSS_ERR
){
sc
->css_imp
->imp_if
.if_oerrors
++;
printf("css%d: output error, ocsr=%b icsr=%b\n", unit
,
addr
->css_ocsr
, CSS_OUTBITS
,
addr
->css_icsr
, CSS_INBITS
);
if (sc
->css_ifuba
.ifu_xtofree
) {
m_freem(sc
->css_ifuba
.ifu_xtofree
);
sc
->css_ifuba
.ifu_xtofree
= 0;
* Input interrupt handler
register struct css_softc
*sc
= &css_softc
[unit
];
register struct cssdevice
*addr
;
sc
->css_imp
->imp_if
.if_ipackets
++;
* Purge BDP; flush message if error indicated.
addr
= (struct cssdevice
*)cssinfo
[unit
]->ui_addr
;
if (sc
->css_ifuba
.ifu_flags
& UBA_NEEDBDP
)
UBAPURGE(sc
->css_ifuba
.ifu_uba
, sc
->css_ifuba
.ifu_r
.ifrw_bdp
);
if (addr
->css_icsr
& CSS_ERR
) {
printf("css%d: recv error, csr=%b\n", unit
,
addr
->css_icsr
, CSS_INBITS
);
sc
->css_imp
->imp_if
.if_ierrors
++;
if (addr
->css_icsr
& IN_EOM
)
len
= IMP_RCVBUF
+ (addr
->css_iwc
<< 1);
if (len
< 0 || len
> IMP_RCVBUF
) {
printf("css%d: bad length=%d\n", len
);
sc
->css_imp
->imp_if
.if_ierrors
++;
* The offset parameter is always 0 since using
* trailers on the ARPAnet is insane.
m
= if_rubaget(&sc
->css_ifuba
, len
, 0, &sc
->css_imp
->imp_if
);
if ((addr
->css_icsr
& IN_EOM
) == 0) {
* Setup for next message.
info
= sc
->css_ifuba
.ifu_r
.ifrw_info
;
addr
->css_iba
= (u_short
)info
;
addr
->css_iwc
= - (IMP_RCVBUF
>> 1);
IN_HRDY
| CSS_IE
| IN_WEN
| ((info
& 0x30000) >> 12) | CSS_GO
;