1*433d6423SLionel Sambuc /* 2*433d6423SLionel Sambuc * fxp.c 3*433d6423SLionel Sambuc * 4*433d6423SLionel Sambuc * This file contains an ethernet device driver for Intel 82557, 82558, 5*433d6423SLionel Sambuc * 82559, 82550, and 82562 fast ethernet controllers. 6*433d6423SLionel Sambuc * 7*433d6423SLionel Sambuc * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com> 8*433d6423SLionel Sambuc */ 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc #include <minix/drivers.h> 11*433d6423SLionel Sambuc #include <minix/netdriver.h> 12*433d6423SLionel Sambuc 13*433d6423SLionel Sambuc #include <stdlib.h> 14*433d6423SLionel Sambuc #include <net/hton.h> 15*433d6423SLionel Sambuc #include <net/gen/ether.h> 16*433d6423SLionel Sambuc #include <net/gen/eth_io.h> 17*433d6423SLionel Sambuc #include <machine/pci.h> 18*433d6423SLionel Sambuc #include <minix/ds.h> 19*433d6423SLionel Sambuc #include <minix/endpoint.h> 20*433d6423SLionel Sambuc 21*433d6423SLionel Sambuc #include <minix/timers.h> 22*433d6423SLionel Sambuc 23*433d6423SLionel Sambuc #define debug 0 24*433d6423SLionel Sambuc #define RAND_UPDATE /**/ 25*433d6423SLionel Sambuc #define printW() ((void)0) 26*433d6423SLionel Sambuc 27*433d6423SLionel Sambuc #include "assert.h" 28*433d6423SLionel Sambuc #include "fxp.h" 29*433d6423SLionel Sambuc #include "mii.h" 30*433d6423SLionel Sambuc 31*433d6423SLionel Sambuc /* Number of receive buffers */ 32*433d6423SLionel Sambuc #define N_RX_BUF 40 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc /* Number of transmit buffers */ 35*433d6423SLionel Sambuc #define N_TX_BUF 4 36*433d6423SLionel Sambuc 37*433d6423SLionel Sambuc /* I/O vectors are handled IOVEC_NR entries at a time. */ 38*433d6423SLionel Sambuc #define IOVEC_NR 16 39*433d6423SLionel Sambuc 40*433d6423SLionel Sambuc /* Configuration */ 41*433d6423SLionel Sambuc #define FXP_ENVVAR "FXPETH" 42*433d6423SLionel Sambuc 43*433d6423SLionel Sambuc typedef int irq_hook_t; 44*433d6423SLionel Sambuc 45*433d6423SLionel Sambuc /* ignore interrupt for the moment */ 46*433d6423SLionel Sambuc #define interrupt(x) do { } while(0) 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc static union tmpbuf 49*433d6423SLionel Sambuc { 50*433d6423SLionel Sambuc char pad[4096]; 51*433d6423SLionel Sambuc struct cbl_conf cc; 52*433d6423SLionel Sambuc struct ias ias; 53*433d6423SLionel Sambuc } *tmpbufp; 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc typedef struct fxp 56*433d6423SLionel Sambuc { 57*433d6423SLionel Sambuc port_t fxp_base_port; 58*433d6423SLionel Sambuc int fxp_mode; 59*433d6423SLionel Sambuc int fxp_got_int; 60*433d6423SLionel Sambuc int fxp_send_int; 61*433d6423SLionel Sambuc int fxp_flags; 62*433d6423SLionel Sambuc int fxp_client; 63*433d6423SLionel Sambuc int fxp_features; /* Needed? */ 64*433d6423SLionel Sambuc int fxp_irq; 65*433d6423SLionel Sambuc int fxp_type; /* What kind of hardware */ 66*433d6423SLionel Sambuc int fxp_ms_regs; /* Master/slave registers */ 67*433d6423SLionel Sambuc int fxp_ee_addrlen; /* #EEPROM address bits */ 68*433d6423SLionel Sambuc int fxp_tx_alive; 69*433d6423SLionel Sambuc int fxp_need_reset; 70*433d6423SLionel Sambuc 71*433d6423SLionel Sambuc /* Rx */ 72*433d6423SLionel Sambuc vir_bytes fxp_read_s; 73*433d6423SLionel Sambuc int fxp_rx_nbuf; 74*433d6423SLionel Sambuc int fxp_rx_bufsize; 75*433d6423SLionel Sambuc struct rfd *fxp_rx_buf; 76*433d6423SLionel Sambuc phys_bytes fxp_rx_busaddr; 77*433d6423SLionel Sambuc int fxp_rx_head; 78*433d6423SLionel Sambuc int fxp_rx_need_restart; 79*433d6423SLionel Sambuc int fxp_need_conf; /* Re-configure after draining send 80*433d6423SLionel Sambuc * queue 81*433d6423SLionel Sambuc */ 82*433d6423SLionel Sambuc 83*433d6423SLionel Sambuc /* Tx */ 84*433d6423SLionel Sambuc int fxp_tx_nbuf; 85*433d6423SLionel Sambuc int fxp_tx_bufsize; 86*433d6423SLionel Sambuc struct tx *fxp_tx_buf; 87*433d6423SLionel Sambuc phys_bytes fxp_tx_busaddr; 88*433d6423SLionel Sambuc int fxp_tx_idle; 89*433d6423SLionel Sambuc int fxp_tx_head; 90*433d6423SLionel Sambuc int fxp_tx_tail; 91*433d6423SLionel Sambuc int fxp_tx_threshold; 92*433d6423SLionel Sambuc 93*433d6423SLionel Sambuc /* Link status */ 94*433d6423SLionel Sambuc int fxp_report_link; 95*433d6423SLionel Sambuc int fxp_link_up; 96*433d6423SLionel Sambuc int fxp_mii_busy; 97*433d6423SLionel Sambuc u16_t fxp_mii_scr; 98*433d6423SLionel Sambuc 99*433d6423SLionel Sambuc /* PCI related */ 100*433d6423SLionel Sambuc int fxp_seen; /* TRUE iff device available */ 101*433d6423SLionel Sambuc 102*433d6423SLionel Sambuc /* 'large' items */ 103*433d6423SLionel Sambuc irq_hook_t fxp_hook; 104*433d6423SLionel Sambuc ether_addr_t fxp_address; 105*433d6423SLionel Sambuc message fxp_rx_mess; 106*433d6423SLionel Sambuc message fxp_tx_mess; 107*433d6423SLionel Sambuc struct sc fxp_stat; 108*433d6423SLionel Sambuc u8_t fxp_conf_bytes[CC_BYTES_NR]; 109*433d6423SLionel Sambuc char fxp_name[sizeof("fxp#n")]; 110*433d6423SLionel Sambuc iovec_t fxp_iovec[IOVEC_NR]; 111*433d6423SLionel Sambuc iovec_s_t fxp_iovec_s[IOVEC_NR]; 112*433d6423SLionel Sambuc } 113*433d6423SLionel Sambuc fxp_t; 114*433d6423SLionel Sambuc 115*433d6423SLionel Sambuc /* fxp_mode */ 116*433d6423SLionel Sambuc #define FM_DISABLED 0x0 117*433d6423SLionel Sambuc #define FM_ENABLED 0x1 118*433d6423SLionel Sambuc 119*433d6423SLionel Sambuc /* fxp_flags */ 120*433d6423SLionel Sambuc #define FF_EMPTY 0x000 121*433d6423SLionel Sambuc #define FF_PACK_SENT 0x001 122*433d6423SLionel Sambuc #define FF_PACK_RECV 0x002 123*433d6423SLionel Sambuc #define FF_SEND_AVAIL 0x004 124*433d6423SLionel Sambuc #define FF_READING 0x010 125*433d6423SLionel Sambuc #define FF_PROMISC 0x040 126*433d6423SLionel Sambuc #define FF_MULTI 0x080 127*433d6423SLionel Sambuc #define FF_BROAD 0x100 128*433d6423SLionel Sambuc #define FF_ENABLED 0x200 129*433d6423SLionel Sambuc 130*433d6423SLionel Sambuc /* fxp_features */ 131*433d6423SLionel Sambuc #define FFE_NONE 0x0 132*433d6423SLionel Sambuc 133*433d6423SLionel Sambuc /* fxp_type */ 134*433d6423SLionel Sambuc #define FT_UNKNOWN 0x0 135*433d6423SLionel Sambuc #define FT_82557 0x1 136*433d6423SLionel Sambuc #define FT_82558A 0x2 137*433d6423SLionel Sambuc #define FT_82559 0x4 138*433d6423SLionel Sambuc #define FT_82801 0x8 139*433d6423SLionel Sambuc 140*433d6423SLionel Sambuc static int fxp_instance; 141*433d6423SLionel Sambuc 142*433d6423SLionel Sambuc static fxp_t *fxp_state; 143*433d6423SLionel Sambuc 144*433d6423SLionel Sambuc static minix_timer_t fxp_watchdog; 145*433d6423SLionel Sambuc 146*433d6423SLionel Sambuc static u32_t system_hz; 147*433d6423SLionel Sambuc 148*433d6423SLionel Sambuc #define fxp_inb(port, offset) (do_inb((port) + (offset))) 149*433d6423SLionel Sambuc #define fxp_inl(port, offset) (do_inl((port) + (offset))) 150*433d6423SLionel Sambuc #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value))) 151*433d6423SLionel Sambuc #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value))) 152*433d6423SLionel Sambuc 153*433d6423SLionel Sambuc static void fxp_init(message *mp); 154*433d6423SLionel Sambuc static void fxp_pci_conf(void); 155*433d6423SLionel Sambuc static int fxp_probe(fxp_t *fp, int skip); 156*433d6423SLionel Sambuc static void fxp_conf_hw(fxp_t *fp); 157*433d6423SLionel Sambuc static void fxp_init_hw(fxp_t *fp); 158*433d6423SLionel Sambuc static void fxp_init_buf(fxp_t *fp); 159*433d6423SLionel Sambuc static void fxp_reset_hw(fxp_t *fp); 160*433d6423SLionel Sambuc static void fxp_confaddr(fxp_t *fp); 161*433d6423SLionel Sambuc static void fxp_rec_mode(fxp_t *fp); 162*433d6423SLionel Sambuc static void fxp_writev_s(const message *mp, int from_int); 163*433d6423SLionel Sambuc static void fxp_readv_s(message *mp, int from_int); 164*433d6423SLionel Sambuc static void fxp_do_conf(fxp_t *fp); 165*433d6423SLionel Sambuc static void fxp_cu_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int 166*433d6423SLionel Sambuc check_idle); 167*433d6423SLionel Sambuc static void fxp_ru_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int 168*433d6423SLionel Sambuc check_idle); 169*433d6423SLionel Sambuc static void fxp_restart_ru(fxp_t *fp); 170*433d6423SLionel Sambuc static void fxp_getstat_s(message *mp); 171*433d6423SLionel Sambuc static void fxp_handler(fxp_t *fp); 172*433d6423SLionel Sambuc static void fxp_check_ints(fxp_t *fp); 173*433d6423SLionel Sambuc static void fxp_watchdog_f(minix_timer_t *tp); 174*433d6423SLionel Sambuc static int fxp_link_changed(fxp_t *fp); 175*433d6423SLionel Sambuc static void fxp_report_link(fxp_t *fp); 176*433d6423SLionel Sambuc static void reply(fxp_t *fp); 177*433d6423SLionel Sambuc static void mess_reply(message *req, message *reply); 178*433d6423SLionel Sambuc static u16_t eeprom_read(fxp_t *fp, int reg); 179*433d6423SLionel Sambuc static void eeprom_addrsize(fxp_t *fp); 180*433d6423SLionel Sambuc static u16_t mii_read(fxp_t *fp, int reg); 181*433d6423SLionel Sambuc static u8_t do_inb(port_t port); 182*433d6423SLionel Sambuc static u32_t do_inl(port_t port); 183*433d6423SLionel Sambuc static void do_outb(port_t port, u8_t v); 184*433d6423SLionel Sambuc static void do_outl(port_t port, u32_t v); 185*433d6423SLionel Sambuc static void tell_dev(vir_bytes start, size_t size, int pci_bus, int 186*433d6423SLionel Sambuc pci_dev, int pci_func); 187*433d6423SLionel Sambuc 188*433d6423SLionel Sambuc static void handle_hw_intr(void) 189*433d6423SLionel Sambuc { 190*433d6423SLionel Sambuc int r; 191*433d6423SLionel Sambuc fxp_t *fp; 192*433d6423SLionel Sambuc 193*433d6423SLionel Sambuc fp= fxp_state; 194*433d6423SLionel Sambuc 195*433d6423SLionel Sambuc if (fp->fxp_mode != FM_ENABLED) 196*433d6423SLionel Sambuc return; 197*433d6423SLionel Sambuc fxp_handler(fp); 198*433d6423SLionel Sambuc 199*433d6423SLionel Sambuc r= sys_irqenable(&fp->fxp_hook); 200*433d6423SLionel Sambuc if (r != OK) { 201*433d6423SLionel Sambuc panic("unable enable interrupts: %d", r); 202*433d6423SLionel Sambuc } 203*433d6423SLionel Sambuc 204*433d6423SLionel Sambuc if (!fp->fxp_got_int) 205*433d6423SLionel Sambuc return; 206*433d6423SLionel Sambuc fp->fxp_got_int= 0; 207*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_ENABLED); 208*433d6423SLionel Sambuc fxp_check_ints(fp); 209*433d6423SLionel Sambuc } 210*433d6423SLionel Sambuc 211*433d6423SLionel Sambuc /* SEF functions and variables. */ 212*433d6423SLionel Sambuc static void sef_local_startup(void); 213*433d6423SLionel Sambuc static int sef_cb_init_fresh(int type, sef_init_info_t *info); 214*433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo); 215*433d6423SLionel Sambuc 216*433d6423SLionel Sambuc /*===========================================================================* 217*433d6423SLionel Sambuc * main * 218*433d6423SLionel Sambuc *===========================================================================*/ 219*433d6423SLionel Sambuc int main(int argc, char *argv[]) 220*433d6423SLionel Sambuc { 221*433d6423SLionel Sambuc message m; 222*433d6423SLionel Sambuc int ipc_status; 223*433d6423SLionel Sambuc int r; 224*433d6423SLionel Sambuc 225*433d6423SLionel Sambuc /* SEF local startup. */ 226*433d6423SLionel Sambuc env_setargs(argc, argv); 227*433d6423SLionel Sambuc sef_local_startup(); 228*433d6423SLionel Sambuc 229*433d6423SLionel Sambuc while (TRUE) 230*433d6423SLionel Sambuc { 231*433d6423SLionel Sambuc if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK) 232*433d6423SLionel Sambuc panic("netdriver_receive failed: %d", r); 233*433d6423SLionel Sambuc 234*433d6423SLionel Sambuc if (is_ipc_notify(ipc_status)) { 235*433d6423SLionel Sambuc switch (_ENDPOINT_P(m.m_source)) { 236*433d6423SLionel Sambuc case HARDWARE: 237*433d6423SLionel Sambuc handle_hw_intr(); 238*433d6423SLionel Sambuc break; 239*433d6423SLionel Sambuc case CLOCK: 240*433d6423SLionel Sambuc expire_timers(m.m_notify.timestamp); 241*433d6423SLionel Sambuc break; 242*433d6423SLionel Sambuc default: 243*433d6423SLionel Sambuc panic(" illegal notify from: %d", m.m_source); 244*433d6423SLionel Sambuc } 245*433d6423SLionel Sambuc 246*433d6423SLionel Sambuc /* get new message */ 247*433d6423SLionel Sambuc continue; 248*433d6423SLionel Sambuc } 249*433d6423SLionel Sambuc 250*433d6423SLionel Sambuc switch (m.m_type) 251*433d6423SLionel Sambuc { 252*433d6423SLionel Sambuc case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break; 253*433d6423SLionel Sambuc case DL_READV_S: fxp_readv_s(&m, FALSE); break; 254*433d6423SLionel Sambuc case DL_CONF: fxp_init(&m); break; 255*433d6423SLionel Sambuc case DL_GETSTAT_S: fxp_getstat_s(&m); break; 256*433d6423SLionel Sambuc default: 257*433d6423SLionel Sambuc panic(" illegal message: %d", m.m_type); 258*433d6423SLionel Sambuc } 259*433d6423SLionel Sambuc } 260*433d6423SLionel Sambuc } 261*433d6423SLionel Sambuc 262*433d6423SLionel Sambuc /*===========================================================================* 263*433d6423SLionel Sambuc * sef_local_startup * 264*433d6423SLionel Sambuc *===========================================================================*/ 265*433d6423SLionel Sambuc static void sef_local_startup() 266*433d6423SLionel Sambuc { 267*433d6423SLionel Sambuc /* Register init callbacks. */ 268*433d6423SLionel Sambuc sef_setcb_init_fresh(sef_cb_init_fresh); 269*433d6423SLionel Sambuc sef_setcb_init_lu(sef_cb_init_fresh); 270*433d6423SLionel Sambuc sef_setcb_init_restart(sef_cb_init_fresh); 271*433d6423SLionel Sambuc 272*433d6423SLionel Sambuc /* Register live update callbacks. */ 273*433d6423SLionel Sambuc sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); 274*433d6423SLionel Sambuc sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree); 275*433d6423SLionel Sambuc 276*433d6423SLionel Sambuc /* Register signal callbacks. */ 277*433d6423SLionel Sambuc sef_setcb_signal_handler(sef_cb_signal_handler); 278*433d6423SLionel Sambuc 279*433d6423SLionel Sambuc /* Let SEF perform startup. */ 280*433d6423SLionel Sambuc sef_startup(); 281*433d6423SLionel Sambuc } 282*433d6423SLionel Sambuc 283*433d6423SLionel Sambuc /*===========================================================================* 284*433d6423SLionel Sambuc * sef_cb_init_fresh * 285*433d6423SLionel Sambuc *===========================================================================*/ 286*433d6423SLionel Sambuc static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 287*433d6423SLionel Sambuc { 288*433d6423SLionel Sambuc /* Initialize the fxp driver. */ 289*433d6423SLionel Sambuc long v; 290*433d6423SLionel Sambuc int r; 291*433d6423SLionel Sambuc vir_bytes ft; 292*433d6423SLionel Sambuc 293*433d6423SLionel Sambuc system_hz = sys_hz(); 294*433d6423SLionel Sambuc 295*433d6423SLionel Sambuc v = 0; 296*433d6423SLionel Sambuc (void) env_parse("instance", "d", 0, &v, 0, 255); 297*433d6423SLionel Sambuc fxp_instance = (int) v; 298*433d6423SLionel Sambuc 299*433d6423SLionel Sambuc ft = sizeof(*fxp_state); 300*433d6423SLionel Sambuc 301*433d6423SLionel Sambuc if(!(fxp_state = alloc_contig(ft, 0, NULL))) 302*433d6423SLionel Sambuc panic("couldn't allocate table: %d", ENOMEM); 303*433d6423SLionel Sambuc 304*433d6423SLionel Sambuc memset(fxp_state, 0, ft); 305*433d6423SLionel Sambuc 306*433d6423SLionel Sambuc if((r=tsc_calibrate()) != OK) 307*433d6423SLionel Sambuc panic("tsc_calibrate failed: %d", r); 308*433d6423SLionel Sambuc 309*433d6423SLionel Sambuc /* Announce we are up! */ 310*433d6423SLionel Sambuc netdriver_announce(); 311*433d6423SLionel Sambuc 312*433d6423SLionel Sambuc return(OK); 313*433d6423SLionel Sambuc } 314*433d6423SLionel Sambuc 315*433d6423SLionel Sambuc /*===========================================================================* 316*433d6423SLionel Sambuc * sef_cb_signal_handler * 317*433d6423SLionel Sambuc *===========================================================================*/ 318*433d6423SLionel Sambuc static void sef_cb_signal_handler(int signo) 319*433d6423SLionel Sambuc { 320*433d6423SLionel Sambuc port_t port; 321*433d6423SLionel Sambuc fxp_t *fp; 322*433d6423SLionel Sambuc 323*433d6423SLionel Sambuc /* Only check for termination signal, ignore anything else. */ 324*433d6423SLionel Sambuc if (signo != SIGTERM) return; 325*433d6423SLionel Sambuc 326*433d6423SLionel Sambuc fp= fxp_state; 327*433d6423SLionel Sambuc 328*433d6423SLionel Sambuc if (fp->fxp_mode == FM_ENABLED && (fp->fxp_flags & FF_ENABLED)) { 329*433d6423SLionel Sambuc port= fp->fxp_base_port; 330*433d6423SLionel Sambuc 331*433d6423SLionel Sambuc /* Reset device */ 332*433d6423SLionel Sambuc if (debug) 333*433d6423SLionel Sambuc printf("%s: resetting device\n", fp->fxp_name); 334*433d6423SLionel Sambuc fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET); 335*433d6423SLionel Sambuc } 336*433d6423SLionel Sambuc 337*433d6423SLionel Sambuc exit(0); 338*433d6423SLionel Sambuc } 339*433d6423SLionel Sambuc 340*433d6423SLionel Sambuc /*===========================================================================* 341*433d6423SLionel Sambuc * fxp_init * 342*433d6423SLionel Sambuc *===========================================================================*/ 343*433d6423SLionel Sambuc static void fxp_init(mp) 344*433d6423SLionel Sambuc message *mp; 345*433d6423SLionel Sambuc { 346*433d6423SLionel Sambuc static int first_time= 1; 347*433d6423SLionel Sambuc 348*433d6423SLionel Sambuc fxp_t *fp; 349*433d6423SLionel Sambuc message reply_mess; 350*433d6423SLionel Sambuc 351*433d6423SLionel Sambuc if (first_time) 352*433d6423SLionel Sambuc { 353*433d6423SLionel Sambuc first_time= 0; 354*433d6423SLionel Sambuc fxp_pci_conf(); /* Configure PCI devices. */ 355*433d6423SLionel Sambuc 356*433d6423SLionel Sambuc init_timer(&fxp_watchdog); 357*433d6423SLionel Sambuc set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f, 0); 358*433d6423SLionel Sambuc } 359*433d6423SLionel Sambuc 360*433d6423SLionel Sambuc fp= fxp_state; 361*433d6423SLionel Sambuc if (fp->fxp_mode == FM_DISABLED) 362*433d6423SLionel Sambuc { 363*433d6423SLionel Sambuc /* This is the default, try to (re)locate the device. */ 364*433d6423SLionel Sambuc fxp_conf_hw(fp); 365*433d6423SLionel Sambuc if (fp->fxp_mode == FM_DISABLED) 366*433d6423SLionel Sambuc { 367*433d6423SLionel Sambuc /* Probe failed, or the device is configured off. */ 368*433d6423SLionel Sambuc reply_mess.m_type= DL_CONF_REPLY; 369*433d6423SLionel Sambuc reply_mess.m_netdrv_net_dl_conf.stat= ENXIO; 370*433d6423SLionel Sambuc mess_reply(mp, &reply_mess); 371*433d6423SLionel Sambuc return; 372*433d6423SLionel Sambuc } 373*433d6423SLionel Sambuc if (fp->fxp_mode == FM_ENABLED) 374*433d6423SLionel Sambuc fxp_init_hw(fp); 375*433d6423SLionel Sambuc fxp_report_link(fp); 376*433d6423SLionel Sambuc } 377*433d6423SLionel Sambuc 378*433d6423SLionel Sambuc assert(fp->fxp_mode == FM_ENABLED); 379*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_ENABLED); 380*433d6423SLionel Sambuc 381*433d6423SLionel Sambuc fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD); 382*433d6423SLionel Sambuc 383*433d6423SLionel Sambuc if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ) 384*433d6423SLionel Sambuc fp->fxp_flags |= FF_PROMISC; 385*433d6423SLionel Sambuc if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ) 386*433d6423SLionel Sambuc fp->fxp_flags |= FF_MULTI; 387*433d6423SLionel Sambuc if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ) 388*433d6423SLionel Sambuc fp->fxp_flags |= FF_BROAD; 389*433d6423SLionel Sambuc 390*433d6423SLionel Sambuc fxp_rec_mode(fp); 391*433d6423SLionel Sambuc 392*433d6423SLionel Sambuc reply_mess.m_type = DL_CONF_REPLY; 393*433d6423SLionel Sambuc reply_mess.m_netdrv_net_dl_conf.stat = OK; 394*433d6423SLionel Sambuc memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr, 395*433d6423SLionel Sambuc fp->fxp_address.ea_addr, 396*433d6423SLionel Sambuc sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr)); 397*433d6423SLionel Sambuc 398*433d6423SLionel Sambuc mess_reply(mp, &reply_mess); 399*433d6423SLionel Sambuc } 400*433d6423SLionel Sambuc 401*433d6423SLionel Sambuc /*===========================================================================* 402*433d6423SLionel Sambuc * fxp_pci_conf * 403*433d6423SLionel Sambuc *===========================================================================*/ 404*433d6423SLionel Sambuc static void fxp_pci_conf() 405*433d6423SLionel Sambuc { 406*433d6423SLionel Sambuc fxp_t *fp; 407*433d6423SLionel Sambuc 408*433d6423SLionel Sambuc fp= fxp_state; 409*433d6423SLionel Sambuc 410*433d6423SLionel Sambuc strlcpy(fp->fxp_name, "fxp#0", sizeof(fp->fxp_name)); 411*433d6423SLionel Sambuc fp->fxp_name[4] += fxp_instance; 412*433d6423SLionel Sambuc fp->fxp_seen= FALSE; 413*433d6423SLionel Sambuc fp->fxp_features= FFE_NONE; 414*433d6423SLionel Sambuc 415*433d6423SLionel Sambuc pci_init(); 416*433d6423SLionel Sambuc 417*433d6423SLionel Sambuc if (fxp_probe(fp, fxp_instance)) 418*433d6423SLionel Sambuc fp->fxp_seen= TRUE; 419*433d6423SLionel Sambuc } 420*433d6423SLionel Sambuc 421*433d6423SLionel Sambuc /*===========================================================================* 422*433d6423SLionel Sambuc * fxp_probe * 423*433d6423SLionel Sambuc *===========================================================================*/ 424*433d6423SLionel Sambuc static int fxp_probe(fxp_t *fp, int skip) 425*433d6423SLionel Sambuc { 426*433d6423SLionel Sambuc int r, devind; 427*433d6423SLionel Sambuc u16_t vid, did; 428*433d6423SLionel Sambuc u32_t bar; 429*433d6423SLionel Sambuc u8_t ilr, rev; 430*433d6423SLionel Sambuc char *str; 431*433d6423SLionel Sambuc #if VERBOSE 432*433d6423SLionel Sambuc char *dname; 433*433d6423SLionel Sambuc #endif 434*433d6423SLionel Sambuc 435*433d6423SLionel Sambuc r= pci_first_dev(&devind, &vid, &did); 436*433d6423SLionel Sambuc if (r == 0) 437*433d6423SLionel Sambuc return FALSE; 438*433d6423SLionel Sambuc 439*433d6423SLionel Sambuc while (skip--) 440*433d6423SLionel Sambuc { 441*433d6423SLionel Sambuc r= pci_next_dev(&devind, &vid, &did); 442*433d6423SLionel Sambuc if (!r) 443*433d6423SLionel Sambuc return FALSE; 444*433d6423SLionel Sambuc } 445*433d6423SLionel Sambuc 446*433d6423SLionel Sambuc #if VERBOSE 447*433d6423SLionel Sambuc dname= pci_dev_name(vid, did); 448*433d6423SLionel Sambuc if (!dname) 449*433d6423SLionel Sambuc dname= "unknown device"; 450*433d6423SLionel Sambuc printf("%s: %s (%04x/%04x) at %s\n", 451*433d6423SLionel Sambuc fp->fxp_name, dname, vid, did, pci_slot_name(devind)); 452*433d6423SLionel Sambuc #endif 453*433d6423SLionel Sambuc pci_reserve(devind); 454*433d6423SLionel Sambuc 455*433d6423SLionel Sambuc bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0; 456*433d6423SLionel Sambuc if (bar < 0x400) { 457*433d6423SLionel Sambuc panic("fxp_probe: base address is not properly configured"); 458*433d6423SLionel Sambuc } 459*433d6423SLionel Sambuc fp->fxp_base_port= bar; 460*433d6423SLionel Sambuc 461*433d6423SLionel Sambuc ilr= pci_attr_r8(devind, PCI_ILR); 462*433d6423SLionel Sambuc fp->fxp_irq= ilr; 463*433d6423SLionel Sambuc if (debug) 464*433d6423SLionel Sambuc { 465*433d6423SLionel Sambuc printf("%s: using I/O address 0x%lx, IRQ %d\n", 466*433d6423SLionel Sambuc fp->fxp_name, (unsigned long)bar, ilr); 467*433d6423SLionel Sambuc } 468*433d6423SLionel Sambuc 469*433d6423SLionel Sambuc rev= pci_attr_r8(devind, PCI_REV); 470*433d6423SLionel Sambuc str= NULL; 471*433d6423SLionel Sambuc fp->fxp_type= FT_UNKNOWN; 472*433d6423SLionel Sambuc switch(rev) 473*433d6423SLionel Sambuc { 474*433d6423SLionel Sambuc case FXP_REV_82557A: str= "82557A"; /* 0x01 */ 475*433d6423SLionel Sambuc fp->fxp_type= FT_82557; 476*433d6423SLionel Sambuc break; 477*433d6423SLionel Sambuc case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */ 478*433d6423SLionel Sambuc case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */ 479*433d6423SLionel Sambuc case FXP_REV_82558A: str= "82558A"; /* 0x04 */ 480*433d6423SLionel Sambuc fp->fxp_type= FT_82558A; 481*433d6423SLionel Sambuc break; 482*433d6423SLionel Sambuc case FXP_REV_82558B: str= "82558B"; /* 0x05 */ 483*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 484*433d6423SLionel Sambuc break; 485*433d6423SLionel Sambuc case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */ 486*433d6423SLionel Sambuc case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */ 487*433d6423SLionel Sambuc case FXP_REV_82559C: str= "82559C"; /* 0x08 */ 488*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 489*433d6423SLionel Sambuc break; 490*433d6423SLionel Sambuc case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */ 491*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 492*433d6423SLionel Sambuc break; 493*433d6423SLionel Sambuc case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */ 494*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 495*433d6423SLionel Sambuc break; 496*433d6423SLionel Sambuc case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */ 497*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 498*433d6423SLionel Sambuc break; 499*433d6423SLionel Sambuc case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */ 500*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 501*433d6423SLionel Sambuc break; 502*433d6423SLionel Sambuc case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */ 503*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 504*433d6423SLionel Sambuc break; 505*433d6423SLionel Sambuc case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */ 506*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 507*433d6423SLionel Sambuc break; 508*433d6423SLionel Sambuc case FXP_REV_82801CAM: str= "82801CAM"; /* 0x42 */ 509*433d6423SLionel Sambuc fp->fxp_type= FT_82801; 510*433d6423SLionel Sambuc break; 511*433d6423SLionel Sambuc case FXP_REV_82801DB: str= "82801DB"; /* 0x81 */ 512*433d6423SLionel Sambuc fp->fxp_type= FT_82801; 513*433d6423SLionel Sambuc break; 514*433d6423SLionel Sambuc case FXP_REV_82550_4: str= "82550(4)"; /* 0x83 */ 515*433d6423SLionel Sambuc fp->fxp_type= FT_82559; 516*433d6423SLionel Sambuc break; 517*433d6423SLionel Sambuc } 518*433d6423SLionel Sambuc 519*433d6423SLionel Sambuc #if VERBOSE 520*433d6423SLionel Sambuc if (str) 521*433d6423SLionel Sambuc printf("%s: device revision: %s\n", fp->fxp_name, str); 522*433d6423SLionel Sambuc else 523*433d6423SLionel Sambuc printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev); 524*433d6423SLionel Sambuc #endif 525*433d6423SLionel Sambuc 526*433d6423SLionel Sambuc if (fp->fxp_type == FT_UNKNOWN) 527*433d6423SLionel Sambuc { 528*433d6423SLionel Sambuc printf("fxp_probe: device is not supported by this driver\n"); 529*433d6423SLionel Sambuc return FALSE; 530*433d6423SLionel Sambuc } 531*433d6423SLionel Sambuc 532*433d6423SLionel Sambuc return TRUE; 533*433d6423SLionel Sambuc } 534*433d6423SLionel Sambuc 535*433d6423SLionel Sambuc /*===========================================================================* 536*433d6423SLionel Sambuc * fxp_conf_hw * 537*433d6423SLionel Sambuc *===========================================================================*/ 538*433d6423SLionel Sambuc static void fxp_conf_hw(fxp_t *fp) 539*433d6423SLionel Sambuc { 540*433d6423SLionel Sambuc #if VERBOSE 541*433d6423SLionel Sambuc int i; 542*433d6423SLionel Sambuc #endif 543*433d6423SLionel Sambuc 544*433d6423SLionel Sambuc fp->fxp_mode= FM_DISABLED; /* Superfluous */ 545*433d6423SLionel Sambuc 546*433d6423SLionel Sambuc if (!fp->fxp_seen) 547*433d6423SLionel Sambuc return; 548*433d6423SLionel Sambuc 549*433d6423SLionel Sambuc /* PCI device is present */ 550*433d6423SLionel Sambuc fp->fxp_mode= FM_ENABLED; 551*433d6423SLionel Sambuc 552*433d6423SLionel Sambuc fp->fxp_flags= FF_EMPTY; 553*433d6423SLionel Sambuc fp->fxp_got_int= 0; 554*433d6423SLionel Sambuc fp->fxp_send_int= 0; 555*433d6423SLionel Sambuc fp->fxp_ee_addrlen= 0; /* Unknown */ 556*433d6423SLionel Sambuc fp->fxp_need_reset= 0; 557*433d6423SLionel Sambuc fp->fxp_report_link= 0; 558*433d6423SLionel Sambuc fp->fxp_link_up= -1; /* Unknown */ 559*433d6423SLionel Sambuc fp->fxp_mii_busy= 0; 560*433d6423SLionel Sambuc fp->fxp_read_s= 0; 561*433d6423SLionel Sambuc fp->fxp_rx_need_restart= 0; 562*433d6423SLionel Sambuc fp->fxp_need_conf= 0; 563*433d6423SLionel Sambuc fp->fxp_tx_head= 0; 564*433d6423SLionel Sambuc fp->fxp_tx_tail= 0; 565*433d6423SLionel Sambuc fp->fxp_tx_alive= 0; 566*433d6423SLionel Sambuc fp->fxp_tx_threshold= TXTT_MIN; 567*433d6423SLionel Sambuc 568*433d6423SLionel Sambuc /* Try to come up with a sensible configuration for the current 569*433d6423SLionel Sambuc * device. Unfortunately every device is different, defaults are 570*433d6423SLionel Sambuc * not always zero, and some fields are re-used with a completely 571*433d6423SLionel Sambuc * different interpretation. We start out with a sensible default 572*433d6423SLionel Sambuc * for all devices and then add device specific changes. 573*433d6423SLionel Sambuc */ 574*433d6423SLionel Sambuc fp->fxp_conf_bytes[0]= CC_BYTES_NR; 575*433d6423SLionel Sambuc fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT; 576*433d6423SLionel Sambuc fp->fxp_conf_bytes[2]= CAI_DEFAULT; 577*433d6423SLionel Sambuc fp->fxp_conf_bytes[3]= 0; 578*433d6423SLionel Sambuc fp->fxp_conf_bytes[4]= 0; 579*433d6423SLionel Sambuc fp->fxp_conf_bytes[5]= 0; 580*433d6423SLionel Sambuc fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES; 581*433d6423SLionel Sambuc fp->fxp_conf_bytes[7]= CUR_1; 582*433d6423SLionel Sambuc fp->fxp_conf_bytes[8]= CCB8_503_MII; 583*433d6423SLionel Sambuc fp->fxp_conf_bytes[9]= 0; 584*433d6423SLionel Sambuc fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI | 585*433d6423SLionel Sambuc CCB10_RES1; 586*433d6423SLionel Sambuc fp->fxp_conf_bytes[11]= 0; 587*433d6423SLionel Sambuc fp->fxp_conf_bytes[12]= CIS_DEFAULT; 588*433d6423SLionel Sambuc fp->fxp_conf_bytes[13]= CCB13_DEFAULT; 589*433d6423SLionel Sambuc fp->fxp_conf_bytes[14]= CCB14_DEFAULT; 590*433d6423SLionel Sambuc fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2; 591*433d6423SLionel Sambuc fp->fxp_conf_bytes[16]= CCB16_DEFAULT; 592*433d6423SLionel Sambuc fp->fxp_conf_bytes[17]= CCB17_DEFAULT; 593*433d6423SLionel Sambuc fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE; 594*433d6423SLionel Sambuc fp->fxp_conf_bytes[19]= CCB19_FDPE; 595*433d6423SLionel Sambuc fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1; 596*433d6423SLionel Sambuc fp->fxp_conf_bytes[21]= CCB21_RES21; 597*433d6423SLionel Sambuc 598*433d6423SLionel Sambuc #if VERBOSE 599*433d6423SLionel Sambuc for (i= 0; i<CC_BYTES_NR; i++) 600*433d6423SLionel Sambuc printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]); 601*433d6423SLionel Sambuc printf("\n"); 602*433d6423SLionel Sambuc #endif 603*433d6423SLionel Sambuc 604*433d6423SLionel Sambuc switch(fp->fxp_type) 605*433d6423SLionel Sambuc { 606*433d6423SLionel Sambuc case FT_82557: 607*433d6423SLionel Sambuc break; 608*433d6423SLionel Sambuc case FT_82558A: 609*433d6423SLionel Sambuc case FT_82559: 610*433d6423SLionel Sambuc case FT_82801: 611*433d6423SLionel Sambuc fp->fxp_conf_bytes[18] |= CCB18_LROK; 612*433d6423SLionel Sambuc 613*433d6423SLionel Sambuc if (fp->fxp_type == FT_82801) 614*433d6423SLionel Sambuc { 615*433d6423SLionel Sambuc fp->fxp_conf_bytes[6] = 0xba; /* ctrl 1 */ 616*433d6423SLionel Sambuc fp->fxp_conf_bytes[15] = 0x48; /* promiscuous */ 617*433d6423SLionel Sambuc fp->fxp_conf_bytes[21] = 0x05; /* mc_all */ 618*433d6423SLionel Sambuc } 619*433d6423SLionel Sambuc break; 620*433d6423SLionel Sambuc default: 621*433d6423SLionel Sambuc panic("fxp_conf_hw: bad device type: %d", fp->fxp_type); 622*433d6423SLionel Sambuc } 623*433d6423SLionel Sambuc 624*433d6423SLionel Sambuc /* Assume an 82555 (compatible) PHY. The should be changed for 625*433d6423SLionel Sambuc * 82557 NICs with different PHYs 626*433d6423SLionel Sambuc */ 627*433d6423SLionel Sambuc fp->fxp_ms_regs = 0; /* No master/slave registers. */ 628*433d6423SLionel Sambuc 629*433d6423SLionel Sambuc #if VERBOSE 630*433d6423SLionel Sambuc for (i= 0; i<CC_BYTES_NR; i++) 631*433d6423SLionel Sambuc printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]); 632*433d6423SLionel Sambuc printf("\n"); 633*433d6423SLionel Sambuc #endif 634*433d6423SLionel Sambuc } 635*433d6423SLionel Sambuc 636*433d6423SLionel Sambuc /*===========================================================================* 637*433d6423SLionel Sambuc * fxp_init_hw * 638*433d6423SLionel Sambuc *===========================================================================*/ 639*433d6423SLionel Sambuc static void fxp_init_hw(fp) 640*433d6423SLionel Sambuc fxp_t *fp; 641*433d6423SLionel Sambuc { 642*433d6423SLionel Sambuc int i, r, isr; 643*433d6423SLionel Sambuc port_t port; 644*433d6423SLionel Sambuc phys_bytes bus_addr; 645*433d6423SLionel Sambuc 646*433d6423SLionel Sambuc port= fp->fxp_base_port; 647*433d6423SLionel Sambuc 648*433d6423SLionel Sambuc fxp_init_buf(fp); 649*433d6423SLionel Sambuc 650*433d6423SLionel Sambuc fp->fxp_flags = FF_EMPTY; 651*433d6423SLionel Sambuc fp->fxp_flags |= FF_ENABLED; 652*433d6423SLionel Sambuc 653*433d6423SLionel Sambuc /* Set the interrupt handler and policy. Do not automatically 654*433d6423SLionel Sambuc * reenable interrupts. Return the IRQ line number on interrupts. 655*433d6423SLionel Sambuc */ 656*433d6423SLionel Sambuc fp->fxp_hook = fp->fxp_irq; 657*433d6423SLionel Sambuc r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook); 658*433d6423SLionel Sambuc if (r != OK) 659*433d6423SLionel Sambuc panic("sys_irqsetpolicy failed: %d", r); 660*433d6423SLionel Sambuc 661*433d6423SLionel Sambuc fxp_reset_hw(fp); 662*433d6423SLionel Sambuc 663*433d6423SLionel Sambuc r= sys_irqenable(&fp->fxp_hook); 664*433d6423SLionel Sambuc if (r != OK) 665*433d6423SLionel Sambuc panic("sys_irqenable failed: %d", r); 666*433d6423SLionel Sambuc 667*433d6423SLionel Sambuc /* Reset PHY? */ 668*433d6423SLionel Sambuc 669*433d6423SLionel Sambuc fxp_do_conf(fp); 670*433d6423SLionel Sambuc 671*433d6423SLionel Sambuc /* Set pointer to statistical counters */ 672*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat), 673*433d6423SLionel Sambuc &bus_addr); 674*433d6423SLionel Sambuc if (r != OK) 675*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 676*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */); 677*433d6423SLionel Sambuc 678*433d6423SLionel Sambuc /* Ack previous interrupts */ 679*433d6423SLionel Sambuc isr= fxp_inb(port, SCB_INT_STAT); 680*433d6423SLionel Sambuc fxp_outb(port, SCB_INT_STAT, isr); 681*433d6423SLionel Sambuc 682*433d6423SLionel Sambuc /* Enable interrupts */ 683*433d6423SLionel Sambuc fxp_outb(port, SCB_INT_MASK, 0); 684*433d6423SLionel Sambuc 685*433d6423SLionel Sambuc fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr, 686*433d6423SLionel Sambuc TRUE /* check idle */); 687*433d6423SLionel Sambuc 688*433d6423SLionel Sambuc fxp_confaddr(fp); 689*433d6423SLionel Sambuc if (debug) 690*433d6423SLionel Sambuc { 691*433d6423SLionel Sambuc printf("%s: Ethernet address ", fp->fxp_name); 692*433d6423SLionel Sambuc for (i= 0; i < 6; i++) 693*433d6423SLionel Sambuc { 694*433d6423SLionel Sambuc printf("%x%c", fp->fxp_address.ea_addr[i], 695*433d6423SLionel Sambuc i < 5 ? ':' : '\n'); 696*433d6423SLionel Sambuc } 697*433d6423SLionel Sambuc } 698*433d6423SLionel Sambuc } 699*433d6423SLionel Sambuc 700*433d6423SLionel Sambuc /*===========================================================================* 701*433d6423SLionel Sambuc * fxp_init_buf * 702*433d6423SLionel Sambuc *===========================================================================*/ 703*433d6423SLionel Sambuc static void fxp_init_buf(fp) 704*433d6423SLionel Sambuc fxp_t *fp; 705*433d6423SLionel Sambuc { 706*433d6423SLionel Sambuc size_t rx_totbufsize, tx_totbufsize, tot_bufsize, alloc_bufsize; 707*433d6423SLionel Sambuc char *alloc_buf; 708*433d6423SLionel Sambuc phys_bytes buf, bus_addr; 709*433d6423SLionel Sambuc int i, r; 710*433d6423SLionel Sambuc struct rfd *rfdp; 711*433d6423SLionel Sambuc struct tx *txp; 712*433d6423SLionel Sambuc phys_bytes ph; 713*433d6423SLionel Sambuc 714*433d6423SLionel Sambuc fp->fxp_rx_nbuf= N_RX_BUF; 715*433d6423SLionel Sambuc rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd); 716*433d6423SLionel Sambuc fp->fxp_rx_bufsize= rx_totbufsize; 717*433d6423SLionel Sambuc 718*433d6423SLionel Sambuc fp->fxp_tx_nbuf= N_TX_BUF; 719*433d6423SLionel Sambuc tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx); 720*433d6423SLionel Sambuc fp->fxp_tx_bufsize= tx_totbufsize; 721*433d6423SLionel Sambuc 722*433d6423SLionel Sambuc tot_bufsize= sizeof(*tmpbufp) + tx_totbufsize + rx_totbufsize; 723*433d6423SLionel Sambuc if (tot_bufsize % 4096) 724*433d6423SLionel Sambuc tot_bufsize += 4096 - (tot_bufsize % 4096); 725*433d6423SLionel Sambuc alloc_bufsize= tot_bufsize; 726*433d6423SLionel Sambuc alloc_buf= alloc_contig(alloc_bufsize, AC_ALIGN4K, &ph); 727*433d6423SLionel Sambuc if (alloc_buf == NULL) { 728*433d6423SLionel Sambuc panic("fxp_init_buf: unable to alloc_contig size: %d", alloc_bufsize); 729*433d6423SLionel Sambuc } 730*433d6423SLionel Sambuc 731*433d6423SLionel Sambuc buf= (phys_bytes)alloc_buf; 732*433d6423SLionel Sambuc 733*433d6423SLionel Sambuc tell_dev((vir_bytes)buf, tot_bufsize, 0, 0, 0); 734*433d6423SLionel Sambuc 735*433d6423SLionel Sambuc tmpbufp= (union tmpbuf *)buf; 736*433d6423SLionel Sambuc 737*433d6423SLionel Sambuc fp->fxp_rx_buf= (struct rfd *)&tmpbufp[1]; 738*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize, 739*433d6423SLionel Sambuc &bus_addr); 740*433d6423SLionel Sambuc if (r != OK) 741*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 742*433d6423SLionel Sambuc fp->fxp_rx_busaddr= bus_addr; 743*433d6423SLionel Sambuc 744*433d6423SLionel Sambuc #if 0 745*433d6423SLionel Sambuc printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n", 746*433d6423SLionel Sambuc fp->fxp_rx_busaddr, fp->fxp_rx_buf); 747*433d6423SLionel Sambuc #endif 748*433d6423SLionel Sambuc 749*433d6423SLionel Sambuc for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++) 750*433d6423SLionel Sambuc { 751*433d6423SLionel Sambuc rfdp->rfd_status= 0; 752*433d6423SLionel Sambuc rfdp->rfd_command= 0; 753*433d6423SLionel Sambuc if (i != fp->fxp_rx_nbuf-1) 754*433d6423SLionel Sambuc { 755*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)&rfdp[1], 756*433d6423SLionel Sambuc sizeof(rfdp[1]), &bus_addr); 757*433d6423SLionel Sambuc if (r != OK) 758*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 759*433d6423SLionel Sambuc rfdp->rfd_linkaddr= bus_addr; 760*433d6423SLionel Sambuc } 761*433d6423SLionel Sambuc else 762*433d6423SLionel Sambuc { 763*433d6423SLionel Sambuc rfdp->rfd_linkaddr= fp->fxp_rx_busaddr; 764*433d6423SLionel Sambuc rfdp->rfd_command |= RFDC_EL; 765*433d6423SLionel Sambuc } 766*433d6423SLionel Sambuc rfdp->rfd_reserved= 0; 767*433d6423SLionel Sambuc rfdp->rfd_res= 0; 768*433d6423SLionel Sambuc rfdp->rfd_size= sizeof(rfdp->rfd_buf); 769*433d6423SLionel Sambuc 770*433d6423SLionel Sambuc } 771*433d6423SLionel Sambuc fp->fxp_rx_head= 0; 772*433d6423SLionel Sambuc 773*433d6423SLionel Sambuc fp->fxp_tx_buf= (struct tx *)((char *)fp->fxp_rx_buf+rx_totbufsize); 774*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_tx_buf, 775*433d6423SLionel Sambuc (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr); 776*433d6423SLionel Sambuc if (r != OK) 777*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 778*433d6423SLionel Sambuc 779*433d6423SLionel Sambuc for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++) 780*433d6423SLionel Sambuc { 781*433d6423SLionel Sambuc txp->tx_status= 0; 782*433d6423SLionel Sambuc txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */ 783*433d6423SLionel Sambuc if (i != fp->fxp_tx_nbuf-1) 784*433d6423SLionel Sambuc { 785*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)&txp[1], 786*433d6423SLionel Sambuc (phys_bytes)sizeof(txp[1]), &bus_addr); 787*433d6423SLionel Sambuc if (r != OK) 788*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 789*433d6423SLionel Sambuc txp->tx_linkaddr= bus_addr; 790*433d6423SLionel Sambuc } 791*433d6423SLionel Sambuc else 792*433d6423SLionel Sambuc { 793*433d6423SLionel Sambuc txp->tx_linkaddr= fp->fxp_tx_busaddr; 794*433d6423SLionel Sambuc } 795*433d6423SLionel Sambuc txp->tx_tbda= TX_TBDA_NIL; 796*433d6423SLionel Sambuc txp->tx_size= 0; 797*433d6423SLionel Sambuc txp->tx_tthresh= fp->fxp_tx_threshold; 798*433d6423SLionel Sambuc txp->tx_ntbd= 0; 799*433d6423SLionel Sambuc } 800*433d6423SLionel Sambuc fp->fxp_tx_idle= 1; 801*433d6423SLionel Sambuc } 802*433d6423SLionel Sambuc 803*433d6423SLionel Sambuc /*===========================================================================* 804*433d6423SLionel Sambuc * fxp_reset_hw * 805*433d6423SLionel Sambuc *===========================================================================*/ 806*433d6423SLionel Sambuc static void fxp_reset_hw(fp) 807*433d6423SLionel Sambuc fxp_t *fp; 808*433d6423SLionel Sambuc { 809*433d6423SLionel Sambuc /* Inline the function in init? */ 810*433d6423SLionel Sambuc port_t port; 811*433d6423SLionel Sambuc 812*433d6423SLionel Sambuc port= fp->fxp_base_port; 813*433d6423SLionel Sambuc 814*433d6423SLionel Sambuc /* Reset device */ 815*433d6423SLionel Sambuc fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET); 816*433d6423SLionel Sambuc tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY)); 817*433d6423SLionel Sambuc 818*433d6423SLionel Sambuc /* Disable interrupts */ 819*433d6423SLionel Sambuc fxp_outb(port, SCB_INT_MASK, SIM_M); 820*433d6423SLionel Sambuc 821*433d6423SLionel Sambuc /* Set CU base to zero */ 822*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */); 823*433d6423SLionel Sambuc 824*433d6423SLionel Sambuc /* Set RU base to zero */ 825*433d6423SLionel Sambuc fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */); 826*433d6423SLionel Sambuc } 827*433d6423SLionel Sambuc 828*433d6423SLionel Sambuc /*===========================================================================* 829*433d6423SLionel Sambuc * fxp_confaddr * 830*433d6423SLionel Sambuc *===========================================================================*/ 831*433d6423SLionel Sambuc static void fxp_confaddr(fxp_t *fp) 832*433d6423SLionel Sambuc { 833*433d6423SLionel Sambuc static char eakey[]= FXP_ENVVAR "#_EA"; 834*433d6423SLionel Sambuc static char eafmt[]= "x:x:x:x:x:x"; 835*433d6423SLionel Sambuc int i, r; 836*433d6423SLionel Sambuc phys_bytes bus_addr; 837*433d6423SLionel Sambuc long v; 838*433d6423SLionel Sambuc 839*433d6423SLionel Sambuc /* User defined ethernet address? */ 840*433d6423SLionel Sambuc eakey[sizeof(FXP_ENVVAR)-1]= '0' + fxp_instance; 841*433d6423SLionel Sambuc 842*433d6423SLionel Sambuc for (i= 0; i < 6; i++) 843*433d6423SLionel Sambuc { 844*433d6423SLionel Sambuc if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) 845*433d6423SLionel Sambuc break; 846*433d6423SLionel Sambuc fp->fxp_address.ea_addr[i]= v; 847*433d6423SLionel Sambuc } 848*433d6423SLionel Sambuc 849*433d6423SLionel Sambuc if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */ 850*433d6423SLionel Sambuc 851*433d6423SLionel Sambuc if (i == 0) 852*433d6423SLionel Sambuc { 853*433d6423SLionel Sambuc /* Get ethernet address from EEPROM */ 854*433d6423SLionel Sambuc for (i= 0; i<3; i++) 855*433d6423SLionel Sambuc { 856*433d6423SLionel Sambuc v= eeprom_read(fp, i); 857*433d6423SLionel Sambuc fp->fxp_address.ea_addr[i*2]= (v & 0xff); 858*433d6423SLionel Sambuc fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff); 859*433d6423SLionel Sambuc } 860*433d6423SLionel Sambuc } 861*433d6423SLionel Sambuc 862*433d6423SLionel Sambuc /* Tell NIC about ethernet address */ 863*433d6423SLionel Sambuc tmpbufp->ias.ias_status= 0; 864*433d6423SLionel Sambuc tmpbufp->ias.ias_command= CBL_C_EL | CBL_AIS; 865*433d6423SLionel Sambuc tmpbufp->ias.ias_linkaddr= 0; 866*433d6423SLionel Sambuc memcpy(tmpbufp->ias.ias_ethaddr, fp->fxp_address.ea_addr, 867*433d6423SLionel Sambuc sizeof(tmpbufp->ias.ias_ethaddr)); 868*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias, 869*433d6423SLionel Sambuc (phys_bytes)sizeof(tmpbufp->ias), &bus_addr); 870*433d6423SLionel Sambuc if (r != OK) 871*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 872*433d6423SLionel Sambuc 873*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */); 874*433d6423SLionel Sambuc 875*433d6423SLionel Sambuc /* Wait for CU command to complete */ 876*433d6423SLionel Sambuc SPIN_UNTIL(tmpbufp->ias.ias_status & CBL_F_C, 1000); 877*433d6423SLionel Sambuc 878*433d6423SLionel Sambuc if (!(tmpbufp->ias.ias_status & CBL_F_C)) 879*433d6423SLionel Sambuc panic("fxp_confaddr: CU command failed to complete"); 880*433d6423SLionel Sambuc if (!(tmpbufp->ias.ias_status & CBL_F_OK)) 881*433d6423SLionel Sambuc panic("fxp_confaddr: CU command failed"); 882*433d6423SLionel Sambuc 883*433d6423SLionel Sambuc #if VERBOSE 884*433d6423SLionel Sambuc printf("%s: hardware ethernet address: ", fp->fxp_name); 885*433d6423SLionel Sambuc for (i= 0; i<6; i++) 886*433d6423SLionel Sambuc { 887*433d6423SLionel Sambuc printf("%02x%s", fp->fxp_address.ea_addr[i], 888*433d6423SLionel Sambuc i < 5 ? ":" : ""); 889*433d6423SLionel Sambuc } 890*433d6423SLionel Sambuc printf("\n"); 891*433d6423SLionel Sambuc #endif 892*433d6423SLionel Sambuc } 893*433d6423SLionel Sambuc 894*433d6423SLionel Sambuc /*===========================================================================* 895*433d6423SLionel Sambuc * fxp_rec_mode * 896*433d6423SLionel Sambuc *===========================================================================*/ 897*433d6423SLionel Sambuc static void fxp_rec_mode(fp) 898*433d6423SLionel Sambuc fxp_t *fp; 899*433d6423SLionel Sambuc { 900*433d6423SLionel Sambuc fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */ 901*433d6423SLionel Sambuc fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM); 902*433d6423SLionel Sambuc fp->fxp_conf_bytes[21] &= ~CCB21_MA; 903*433d6423SLionel Sambuc 904*433d6423SLionel Sambuc if (fp->fxp_flags & FF_PROMISC) 905*433d6423SLionel Sambuc fp->fxp_conf_bytes[15] |= CCB15_PM; 906*433d6423SLionel Sambuc if (fp->fxp_flags & FF_MULTI) 907*433d6423SLionel Sambuc fp->fxp_conf_bytes[21] |= CCB21_MA; 908*433d6423SLionel Sambuc 909*433d6423SLionel Sambuc if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC))) 910*433d6423SLionel Sambuc fp->fxp_conf_bytes[15] |= CCB15_BD; 911*433d6423SLionel Sambuc 912*433d6423SLionel Sambuc /* Queue request if not idle */ 913*433d6423SLionel Sambuc if (fp->fxp_tx_idle) 914*433d6423SLionel Sambuc { 915*433d6423SLionel Sambuc fxp_do_conf(fp); 916*433d6423SLionel Sambuc } 917*433d6423SLionel Sambuc else 918*433d6423SLionel Sambuc { 919*433d6423SLionel Sambuc printf("fxp_rec_mode: setting fxp_need_conf\n"); 920*433d6423SLionel Sambuc fp->fxp_need_conf= TRUE; 921*433d6423SLionel Sambuc } 922*433d6423SLionel Sambuc } 923*433d6423SLionel Sambuc 924*433d6423SLionel Sambuc /*===========================================================================* 925*433d6423SLionel Sambuc * fxp_writev_s * 926*433d6423SLionel Sambuc *===========================================================================*/ 927*433d6423SLionel Sambuc static void fxp_writev_s(const message *mp, int from_int) 928*433d6423SLionel Sambuc { 929*433d6423SLionel Sambuc endpoint_t iov_endpt; 930*433d6423SLionel Sambuc cp_grant_id_t iov_grant; 931*433d6423SLionel Sambuc vir_bytes iov_offset; 932*433d6423SLionel Sambuc int i, j, n, o, r, s, count, size, prev_head; 933*433d6423SLionel Sambuc int fxp_tx_nbuf, fxp_tx_head; 934*433d6423SLionel Sambuc u16_t tx_command; 935*433d6423SLionel Sambuc fxp_t *fp; 936*433d6423SLionel Sambuc iovec_s_t *iovp; 937*433d6423SLionel Sambuc struct tx *txp, *prev_txp; 938*433d6423SLionel Sambuc 939*433d6423SLionel Sambuc fp= fxp_state; 940*433d6423SLionel Sambuc 941*433d6423SLionel Sambuc count = mp->m_net_netdrv_dl_writev_s.count; 942*433d6423SLionel Sambuc fp->fxp_client= mp->m_source; 943*433d6423SLionel Sambuc 944*433d6423SLionel Sambuc assert(fp->fxp_mode == FM_ENABLED); 945*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_ENABLED); 946*433d6423SLionel Sambuc 947*433d6423SLionel Sambuc if (from_int) 948*433d6423SLionel Sambuc { 949*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_SEND_AVAIL); 950*433d6423SLionel Sambuc fp->fxp_flags &= ~FF_SEND_AVAIL; 951*433d6423SLionel Sambuc fp->fxp_tx_alive= TRUE; 952*433d6423SLionel Sambuc } 953*433d6423SLionel Sambuc 954*433d6423SLionel Sambuc if (fp->fxp_tx_idle) 955*433d6423SLionel Sambuc { 956*433d6423SLionel Sambuc txp= fp->fxp_tx_buf; 957*433d6423SLionel Sambuc fxp_tx_head= 0; /* lint */ 958*433d6423SLionel Sambuc prev_txp= NULL; /* lint */ 959*433d6423SLionel Sambuc } 960*433d6423SLionel Sambuc else 961*433d6423SLionel Sambuc { 962*433d6423SLionel Sambuc fxp_tx_nbuf= fp->fxp_tx_nbuf; 963*433d6423SLionel Sambuc prev_head= fp->fxp_tx_head; 964*433d6423SLionel Sambuc fxp_tx_head= prev_head+1; 965*433d6423SLionel Sambuc if (fxp_tx_head == fxp_tx_nbuf) 966*433d6423SLionel Sambuc fxp_tx_head= 0; 967*433d6423SLionel Sambuc assert(fxp_tx_head < fxp_tx_nbuf); 968*433d6423SLionel Sambuc 969*433d6423SLionel Sambuc if (fxp_tx_head == fp->fxp_tx_tail) 970*433d6423SLionel Sambuc { 971*433d6423SLionel Sambuc /* Send queue is full */ 972*433d6423SLionel Sambuc assert(!(fp->fxp_flags & FF_SEND_AVAIL)); 973*433d6423SLionel Sambuc fp->fxp_flags |= FF_SEND_AVAIL; 974*433d6423SLionel Sambuc goto suspend; 975*433d6423SLionel Sambuc } 976*433d6423SLionel Sambuc 977*433d6423SLionel Sambuc prev_txp= &fp->fxp_tx_buf[prev_head]; 978*433d6423SLionel Sambuc txp= &fp->fxp_tx_buf[fxp_tx_head]; 979*433d6423SLionel Sambuc } 980*433d6423SLionel Sambuc 981*433d6423SLionel Sambuc assert(!(fp->fxp_flags & FF_SEND_AVAIL)); 982*433d6423SLionel Sambuc assert(!(fp->fxp_flags & FF_PACK_SENT)); 983*433d6423SLionel Sambuc 984*433d6423SLionel Sambuc iov_endpt= mp->m_source; 985*433d6423SLionel Sambuc iov_grant= mp->m_net_netdrv_dl_writev_s.grant; 986*433d6423SLionel Sambuc 987*433d6423SLionel Sambuc size= 0; 988*433d6423SLionel Sambuc o= 0; 989*433d6423SLionel Sambuc iov_offset= 0; 990*433d6423SLionel Sambuc for (i= 0; i<count; i += IOVEC_NR, 991*433d6423SLionel Sambuc iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0])) 992*433d6423SLionel Sambuc { 993*433d6423SLionel Sambuc n= IOVEC_NR; 994*433d6423SLionel Sambuc if (i+n > count) 995*433d6423SLionel Sambuc n= count-i; 996*433d6423SLionel Sambuc r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset, 997*433d6423SLionel Sambuc (vir_bytes)fp->fxp_iovec_s, 998*433d6423SLionel Sambuc n * sizeof(fp->fxp_iovec_s[0])); 999*433d6423SLionel Sambuc if (r != OK) 1000*433d6423SLionel Sambuc panic("fxp_writev: sys_safecopyfrom failed: %d", r); 1001*433d6423SLionel Sambuc 1002*433d6423SLionel Sambuc for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++) 1003*433d6423SLionel Sambuc { 1004*433d6423SLionel Sambuc s= iovp->iov_size; 1005*433d6423SLionel Sambuc if (size + s > ETH_MAX_PACK_SIZE_TAGGED) { 1006*433d6423SLionel Sambuc panic("fxp_writev: invalid packet size: %d", size + s); 1007*433d6423SLionel Sambuc } 1008*433d6423SLionel Sambuc 1009*433d6423SLionel Sambuc r= sys_safecopyfrom(iov_endpt, iovp->iov_grant, 1010*433d6423SLionel Sambuc 0, (vir_bytes)(txp->tx_buf+o), s); 1011*433d6423SLionel Sambuc if (r != OK) { 1012*433d6423SLionel Sambuc panic("fxp_writev_s: sys_safecopyfrom failed: %d", r); 1013*433d6423SLionel Sambuc } 1014*433d6423SLionel Sambuc size += s; 1015*433d6423SLionel Sambuc o += s; 1016*433d6423SLionel Sambuc } 1017*433d6423SLionel Sambuc } 1018*433d6423SLionel Sambuc if (size < ETH_MIN_PACK_SIZE) 1019*433d6423SLionel Sambuc panic("fxp_writev: invalid packet size: %d", size); 1020*433d6423SLionel Sambuc 1021*433d6423SLionel Sambuc txp->tx_status= 0; 1022*433d6423SLionel Sambuc txp->tx_command= TXC_EL | CBL_XMIT; 1023*433d6423SLionel Sambuc txp->tx_tbda= TX_TBDA_NIL; 1024*433d6423SLionel Sambuc txp->tx_size= TXSZ_EOF | size; 1025*433d6423SLionel Sambuc txp->tx_tthresh= fp->fxp_tx_threshold; 1026*433d6423SLionel Sambuc txp->tx_ntbd= 0; 1027*433d6423SLionel Sambuc if (fp->fxp_tx_idle) 1028*433d6423SLionel Sambuc { 1029*433d6423SLionel Sambuc fp->fxp_tx_idle= 0; 1030*433d6423SLionel Sambuc fp->fxp_tx_head= fp->fxp_tx_tail= 0; 1031*433d6423SLionel Sambuc 1032*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr, 1033*433d6423SLionel Sambuc TRUE /* check idle */); 1034*433d6423SLionel Sambuc } 1035*433d6423SLionel Sambuc else 1036*433d6423SLionel Sambuc { 1037*433d6423SLionel Sambuc /* Link new request in transmit list */ 1038*433d6423SLionel Sambuc tx_command= prev_txp->tx_command; 1039*433d6423SLionel Sambuc assert(tx_command == (TXC_EL | CBL_XMIT)); 1040*433d6423SLionel Sambuc prev_txp->tx_command= CBL_XMIT; 1041*433d6423SLionel Sambuc fp->fxp_tx_head= fxp_tx_head; 1042*433d6423SLionel Sambuc } 1043*433d6423SLionel Sambuc 1044*433d6423SLionel Sambuc fp->fxp_flags |= FF_PACK_SENT; 1045*433d6423SLionel Sambuc 1046*433d6423SLionel Sambuc /* If the interrupt handler called, don't send a reply. The reply 1047*433d6423SLionel Sambuc * will be sent after all interrupts are handled. 1048*433d6423SLionel Sambuc */ 1049*433d6423SLionel Sambuc if (from_int) 1050*433d6423SLionel Sambuc return; 1051*433d6423SLionel Sambuc reply(fp); 1052*433d6423SLionel Sambuc return; 1053*433d6423SLionel Sambuc 1054*433d6423SLionel Sambuc suspend: 1055*433d6423SLionel Sambuc if (from_int) 1056*433d6423SLionel Sambuc panic("fxp: should not be sending"); 1057*433d6423SLionel Sambuc 1058*433d6423SLionel Sambuc fp->fxp_tx_mess= *mp; 1059*433d6423SLionel Sambuc reply(fp); 1060*433d6423SLionel Sambuc } 1061*433d6423SLionel Sambuc 1062*433d6423SLionel Sambuc /*===========================================================================* 1063*433d6423SLionel Sambuc * fxp_readv_s * 1064*433d6423SLionel Sambuc *===========================================================================*/ 1065*433d6423SLionel Sambuc static void fxp_readv_s(mp, from_int) 1066*433d6423SLionel Sambuc message *mp; 1067*433d6423SLionel Sambuc int from_int; 1068*433d6423SLionel Sambuc { 1069*433d6423SLionel Sambuc int i, j, n, o, r, s, count, size, fxp_rx_head, fxp_rx_nbuf; 1070*433d6423SLionel Sambuc endpoint_t iov_endpt; 1071*433d6423SLionel Sambuc cp_grant_id_t iov_grant; 1072*433d6423SLionel Sambuc port_t port; 1073*433d6423SLionel Sambuc unsigned packlen; 1074*433d6423SLionel Sambuc vir_bytes iov_offset; 1075*433d6423SLionel Sambuc u16_t rfd_status; 1076*433d6423SLionel Sambuc u16_t rfd_res; 1077*433d6423SLionel Sambuc u8_t scb_status; 1078*433d6423SLionel Sambuc fxp_t *fp; 1079*433d6423SLionel Sambuc iovec_s_t *iovp; 1080*433d6423SLionel Sambuc struct rfd *rfdp, *prev_rfdp; 1081*433d6423SLionel Sambuc 1082*433d6423SLionel Sambuc fp= fxp_state; 1083*433d6423SLionel Sambuc 1084*433d6423SLionel Sambuc count = mp->m_net_netdrv_dl_readv_s.count; 1085*433d6423SLionel Sambuc fp->fxp_client= mp->m_source; 1086*433d6423SLionel Sambuc 1087*433d6423SLionel Sambuc assert(fp->fxp_mode == FM_ENABLED); 1088*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_ENABLED); 1089*433d6423SLionel Sambuc 1090*433d6423SLionel Sambuc port= fp->fxp_base_port; 1091*433d6423SLionel Sambuc 1092*433d6423SLionel Sambuc fxp_rx_head= fp->fxp_rx_head; 1093*433d6423SLionel Sambuc rfdp= &fp->fxp_rx_buf[fxp_rx_head]; 1094*433d6423SLionel Sambuc 1095*433d6423SLionel Sambuc rfd_status= rfdp->rfd_status; 1096*433d6423SLionel Sambuc if (!(rfd_status & RFDS_C)) 1097*433d6423SLionel Sambuc { 1098*433d6423SLionel Sambuc /* Receive buffer is empty, suspend */ 1099*433d6423SLionel Sambuc goto suspend; 1100*433d6423SLionel Sambuc } 1101*433d6423SLionel Sambuc 1102*433d6423SLionel Sambuc if (!(rfd_status & RFDS_OK)) 1103*433d6423SLionel Sambuc { 1104*433d6423SLionel Sambuc /* Not OK? What happened? */ 1105*433d6423SLionel Sambuc assert(0); 1106*433d6423SLionel Sambuc } 1107*433d6423SLionel Sambuc else 1108*433d6423SLionel Sambuc { 1109*433d6423SLionel Sambuc assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR | 1110*433d6423SLionel Sambuc RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT | 1111*433d6423SLionel Sambuc RFDS_RXERR))); 1112*433d6423SLionel Sambuc } 1113*433d6423SLionel Sambuc rfd_res= rfdp->rfd_res; 1114*433d6423SLionel Sambuc assert(rfd_res & RFDR_EOF); 1115*433d6423SLionel Sambuc assert(rfd_res & RFDR_F); 1116*433d6423SLionel Sambuc 1117*433d6423SLionel Sambuc packlen= rfd_res & RFDSZ_SIZE; 1118*433d6423SLionel Sambuc 1119*433d6423SLionel Sambuc iov_endpt = mp->m_source; 1120*433d6423SLionel Sambuc iov_grant = mp->m_net_netdrv_dl_readv_s.grant; 1121*433d6423SLionel Sambuc 1122*433d6423SLionel Sambuc size= 0; 1123*433d6423SLionel Sambuc o= 0; 1124*433d6423SLionel Sambuc iov_offset= 0; 1125*433d6423SLionel Sambuc for (i= 0; i<count; i += IOVEC_NR, 1126*433d6423SLionel Sambuc iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0])) 1127*433d6423SLionel Sambuc { 1128*433d6423SLionel Sambuc n= IOVEC_NR; 1129*433d6423SLionel Sambuc if (i+n > count) 1130*433d6423SLionel Sambuc n= count-i; 1131*433d6423SLionel Sambuc r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset, 1132*433d6423SLionel Sambuc (vir_bytes)fp->fxp_iovec_s, 1133*433d6423SLionel Sambuc n * sizeof(fp->fxp_iovec_s[0])); 1134*433d6423SLionel Sambuc if (r != OK) 1135*433d6423SLionel Sambuc panic("fxp_readv_s: sys_safecopyfrom failed: %d", r); 1136*433d6423SLionel Sambuc 1137*433d6423SLionel Sambuc for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++) 1138*433d6423SLionel Sambuc { 1139*433d6423SLionel Sambuc s= iovp->iov_size; 1140*433d6423SLionel Sambuc if (size + s > packlen) 1141*433d6423SLionel Sambuc { 1142*433d6423SLionel Sambuc assert(packlen > size); 1143*433d6423SLionel Sambuc s= packlen-size; 1144*433d6423SLionel Sambuc } 1145*433d6423SLionel Sambuc 1146*433d6423SLionel Sambuc r= sys_safecopyto(iov_endpt, iovp->iov_grant, 1147*433d6423SLionel Sambuc 0, (vir_bytes)(rfdp->rfd_buf+o), s); 1148*433d6423SLionel Sambuc if (r != OK) 1149*433d6423SLionel Sambuc { 1150*433d6423SLionel Sambuc panic("fxp_readv: sys_safecopyto failed: %d", r); 1151*433d6423SLionel Sambuc } 1152*433d6423SLionel Sambuc 1153*433d6423SLionel Sambuc size += s; 1154*433d6423SLionel Sambuc if (size == packlen) 1155*433d6423SLionel Sambuc break; 1156*433d6423SLionel Sambuc o += s; 1157*433d6423SLionel Sambuc } 1158*433d6423SLionel Sambuc if (size == packlen) 1159*433d6423SLionel Sambuc break; 1160*433d6423SLionel Sambuc } 1161*433d6423SLionel Sambuc if (size < packlen) 1162*433d6423SLionel Sambuc { 1163*433d6423SLionel Sambuc assert(0); 1164*433d6423SLionel Sambuc } 1165*433d6423SLionel Sambuc 1166*433d6423SLionel Sambuc fp->fxp_read_s= packlen; 1167*433d6423SLionel Sambuc fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV; 1168*433d6423SLionel Sambuc 1169*433d6423SLionel Sambuc /* Re-init the current buffer */ 1170*433d6423SLionel Sambuc rfdp->rfd_status= 0; 1171*433d6423SLionel Sambuc rfdp->rfd_command= RFDC_EL; 1172*433d6423SLionel Sambuc rfdp->rfd_reserved= 0; 1173*433d6423SLionel Sambuc rfdp->rfd_res= 0; 1174*433d6423SLionel Sambuc rfdp->rfd_size= sizeof(rfdp->rfd_buf); 1175*433d6423SLionel Sambuc 1176*433d6423SLionel Sambuc fxp_rx_nbuf= fp->fxp_rx_nbuf; 1177*433d6423SLionel Sambuc if (fxp_rx_head == 0) 1178*433d6423SLionel Sambuc { 1179*433d6423SLionel Sambuc prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1]; 1180*433d6423SLionel Sambuc } 1181*433d6423SLionel Sambuc else 1182*433d6423SLionel Sambuc prev_rfdp= &rfdp[-1]; 1183*433d6423SLionel Sambuc 1184*433d6423SLionel Sambuc assert(prev_rfdp->rfd_command & RFDC_EL); 1185*433d6423SLionel Sambuc prev_rfdp->rfd_command &= ~RFDC_EL; 1186*433d6423SLionel Sambuc 1187*433d6423SLionel Sambuc fxp_rx_head++; 1188*433d6423SLionel Sambuc if (fxp_rx_head == fxp_rx_nbuf) 1189*433d6423SLionel Sambuc fxp_rx_head= 0; 1190*433d6423SLionel Sambuc assert(fxp_rx_head < fxp_rx_nbuf); 1191*433d6423SLionel Sambuc fp->fxp_rx_head= fxp_rx_head; 1192*433d6423SLionel Sambuc 1193*433d6423SLionel Sambuc if (!from_int) 1194*433d6423SLionel Sambuc reply(fp); 1195*433d6423SLionel Sambuc 1196*433d6423SLionel Sambuc return; 1197*433d6423SLionel Sambuc 1198*433d6423SLionel Sambuc suspend: 1199*433d6423SLionel Sambuc if (fp->fxp_rx_need_restart) 1200*433d6423SLionel Sambuc { 1201*433d6423SLionel Sambuc fp->fxp_rx_need_restart= 0; 1202*433d6423SLionel Sambuc 1203*433d6423SLionel Sambuc /* Check the status of the RU */ 1204*433d6423SLionel Sambuc scb_status= fxp_inb(port, SCB_STATUS); 1205*433d6423SLionel Sambuc if ((scb_status & SS_RUS_MASK) != SS_RU_NORES) 1206*433d6423SLionel Sambuc { 1207*433d6423SLionel Sambuc /* Race condition? */ 1208*433d6423SLionel Sambuc printf("fxp_readv: restart race: 0x%x\n", 1209*433d6423SLionel Sambuc scb_status); 1210*433d6423SLionel Sambuc assert((scb_status & SS_RUS_MASK) == SS_RU_READY); 1211*433d6423SLionel Sambuc } 1212*433d6423SLionel Sambuc else 1213*433d6423SLionel Sambuc { 1214*433d6423SLionel Sambuc fxp_restart_ru(fp); 1215*433d6423SLionel Sambuc } 1216*433d6423SLionel Sambuc } 1217*433d6423SLionel Sambuc if (from_int) 1218*433d6423SLionel Sambuc { 1219*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_READING); 1220*433d6423SLionel Sambuc 1221*433d6423SLionel Sambuc /* No need to store any state */ 1222*433d6423SLionel Sambuc return; 1223*433d6423SLionel Sambuc } 1224*433d6423SLionel Sambuc 1225*433d6423SLionel Sambuc fp->fxp_rx_mess= *mp; 1226*433d6423SLionel Sambuc assert(!(fp->fxp_flags & FF_READING)); 1227*433d6423SLionel Sambuc fp->fxp_flags |= FF_READING; 1228*433d6423SLionel Sambuc 1229*433d6423SLionel Sambuc reply(fp); 1230*433d6423SLionel Sambuc } 1231*433d6423SLionel Sambuc 1232*433d6423SLionel Sambuc /*===========================================================================* 1233*433d6423SLionel Sambuc * fxp_do_conf * 1234*433d6423SLionel Sambuc *===========================================================================*/ 1235*433d6423SLionel Sambuc static void fxp_do_conf(fp) 1236*433d6423SLionel Sambuc fxp_t *fp; 1237*433d6423SLionel Sambuc { 1238*433d6423SLionel Sambuc int r; 1239*433d6423SLionel Sambuc phys_bytes bus_addr; 1240*433d6423SLionel Sambuc 1241*433d6423SLionel Sambuc /* Configure device */ 1242*433d6423SLionel Sambuc tmpbufp->cc.cc_status= 0; 1243*433d6423SLionel Sambuc tmpbufp->cc.cc_command= CBL_C_EL | CBL_CONF; 1244*433d6423SLionel Sambuc tmpbufp->cc.cc_linkaddr= 0; 1245*433d6423SLionel Sambuc memcpy(tmpbufp->cc.cc_bytes, fp->fxp_conf_bytes, 1246*433d6423SLionel Sambuc sizeof(tmpbufp->cc.cc_bytes)); 1247*433d6423SLionel Sambuc 1248*433d6423SLionel Sambuc r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->cc, 1249*433d6423SLionel Sambuc (phys_bytes)sizeof(tmpbufp->cc), &bus_addr); 1250*433d6423SLionel Sambuc if (r != OK) 1251*433d6423SLionel Sambuc panic("sys_umap failed: %d", r); 1252*433d6423SLionel Sambuc 1253*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */); 1254*433d6423SLionel Sambuc 1255*433d6423SLionel Sambuc /* Wait for CU command to complete */ 1256*433d6423SLionel Sambuc SPIN_UNTIL(tmpbufp->cc.cc_status & CBL_F_C, 100000); 1257*433d6423SLionel Sambuc 1258*433d6423SLionel Sambuc if (!(tmpbufp->cc.cc_status & CBL_F_C)) 1259*433d6423SLionel Sambuc panic("fxp_do_conf: CU command failed to complete"); 1260*433d6423SLionel Sambuc if (!(tmpbufp->cc.cc_status & CBL_F_OK)) 1261*433d6423SLionel Sambuc panic("fxp_do_conf: CU command failed"); 1262*433d6423SLionel Sambuc 1263*433d6423SLionel Sambuc } 1264*433d6423SLionel Sambuc 1265*433d6423SLionel Sambuc /*===========================================================================* 1266*433d6423SLionel Sambuc * fxp_cu_ptr_cmd * 1267*433d6423SLionel Sambuc *===========================================================================*/ 1268*433d6423SLionel Sambuc static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle) 1269*433d6423SLionel Sambuc fxp_t *fp; 1270*433d6423SLionel Sambuc int cmd; 1271*433d6423SLionel Sambuc phys_bytes bus_addr; 1272*433d6423SLionel Sambuc int check_idle; 1273*433d6423SLionel Sambuc { 1274*433d6423SLionel Sambuc spin_t spin; 1275*433d6423SLionel Sambuc port_t port; 1276*433d6423SLionel Sambuc u8_t scb_cmd; 1277*433d6423SLionel Sambuc 1278*433d6423SLionel Sambuc port= fp->fxp_base_port; 1279*433d6423SLionel Sambuc 1280*433d6423SLionel Sambuc if (check_idle) 1281*433d6423SLionel Sambuc { 1282*433d6423SLionel Sambuc /* Consistency check. Make sure that CU is idle */ 1283*433d6423SLionel Sambuc if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE) 1284*433d6423SLionel Sambuc panic("fxp_cu_ptr_cmd: CU is not idle"); 1285*433d6423SLionel Sambuc } 1286*433d6423SLionel Sambuc 1287*433d6423SLionel Sambuc fxp_outl(port, SCB_POINTER, bus_addr); 1288*433d6423SLionel Sambuc fxp_outb(port, SCB_CMD, cmd); 1289*433d6423SLionel Sambuc 1290*433d6423SLionel Sambuc /* What is a reasonable time-out? There is nothing in the 1291*433d6423SLionel Sambuc * documentation. 1 ms should be enough. We use 100 ms. 1292*433d6423SLionel Sambuc */ 1293*433d6423SLionel Sambuc spin_init(&spin, 100000); 1294*433d6423SLionel Sambuc do { 1295*433d6423SLionel Sambuc /* Wait for CU command to be accepted */ 1296*433d6423SLionel Sambuc scb_cmd= fxp_inb(port, SCB_CMD); 1297*433d6423SLionel Sambuc if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP) 1298*433d6423SLionel Sambuc break; 1299*433d6423SLionel Sambuc } while (spin_check(&spin)); 1300*433d6423SLionel Sambuc 1301*433d6423SLionel Sambuc if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP) 1302*433d6423SLionel Sambuc panic("fxp_cu_ptr_cmd: CU does not accept command"); 1303*433d6423SLionel Sambuc } 1304*433d6423SLionel Sambuc 1305*433d6423SLionel Sambuc /*===========================================================================* 1306*433d6423SLionel Sambuc * fxp_ru_ptr_cmd * 1307*433d6423SLionel Sambuc *===========================================================================*/ 1308*433d6423SLionel Sambuc static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle) 1309*433d6423SLionel Sambuc fxp_t *fp; 1310*433d6423SLionel Sambuc int cmd; 1311*433d6423SLionel Sambuc phys_bytes bus_addr; 1312*433d6423SLionel Sambuc int check_idle; 1313*433d6423SLionel Sambuc { 1314*433d6423SLionel Sambuc spin_t spin; 1315*433d6423SLionel Sambuc port_t port; 1316*433d6423SLionel Sambuc u8_t scb_cmd; 1317*433d6423SLionel Sambuc 1318*433d6423SLionel Sambuc port= fp->fxp_base_port; 1319*433d6423SLionel Sambuc 1320*433d6423SLionel Sambuc if (check_idle) 1321*433d6423SLionel Sambuc { 1322*433d6423SLionel Sambuc /* Consistency check, make sure that RU is idle */ 1323*433d6423SLionel Sambuc if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE) 1324*433d6423SLionel Sambuc panic("fxp_ru_ptr_cmd: RU is not idle"); 1325*433d6423SLionel Sambuc } 1326*433d6423SLionel Sambuc 1327*433d6423SLionel Sambuc fxp_outl(port, SCB_POINTER, bus_addr); 1328*433d6423SLionel Sambuc fxp_outb(port, SCB_CMD, cmd); 1329*433d6423SLionel Sambuc 1330*433d6423SLionel Sambuc spin_init(&spin, 1000); 1331*433d6423SLionel Sambuc do { 1332*433d6423SLionel Sambuc /* Wait for RU command to be accepted */ 1333*433d6423SLionel Sambuc scb_cmd= fxp_inb(port, SCB_CMD); 1334*433d6423SLionel Sambuc if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP) 1335*433d6423SLionel Sambuc break; 1336*433d6423SLionel Sambuc } while (spin_check(&spin)); 1337*433d6423SLionel Sambuc 1338*433d6423SLionel Sambuc if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP) 1339*433d6423SLionel Sambuc panic("fxp_ru_ptr_cmd: RU does not accept command"); 1340*433d6423SLionel Sambuc } 1341*433d6423SLionel Sambuc 1342*433d6423SLionel Sambuc /*===========================================================================* 1343*433d6423SLionel Sambuc * fxp_restart_ru * 1344*433d6423SLionel Sambuc *===========================================================================*/ 1345*433d6423SLionel Sambuc static void fxp_restart_ru(fp) 1346*433d6423SLionel Sambuc fxp_t *fp; 1347*433d6423SLionel Sambuc { 1348*433d6423SLionel Sambuc int i, fxp_rx_nbuf; 1349*433d6423SLionel Sambuc port_t port; 1350*433d6423SLionel Sambuc struct rfd *rfdp; 1351*433d6423SLionel Sambuc 1352*433d6423SLionel Sambuc port= fp->fxp_base_port; 1353*433d6423SLionel Sambuc 1354*433d6423SLionel Sambuc fxp_rx_nbuf= fp->fxp_rx_nbuf; 1355*433d6423SLionel Sambuc for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++) 1356*433d6423SLionel Sambuc { 1357*433d6423SLionel Sambuc rfdp->rfd_status= 0; 1358*433d6423SLionel Sambuc rfdp->rfd_command= 0; 1359*433d6423SLionel Sambuc if (i == fp->fxp_rx_nbuf-1) 1360*433d6423SLionel Sambuc rfdp->rfd_command= RFDC_EL; 1361*433d6423SLionel Sambuc rfdp->rfd_reserved= 0; 1362*433d6423SLionel Sambuc rfdp->rfd_res= 0; 1363*433d6423SLionel Sambuc rfdp->rfd_size= sizeof(rfdp->rfd_buf); 1364*433d6423SLionel Sambuc } 1365*433d6423SLionel Sambuc fp->fxp_rx_head= 0; 1366*433d6423SLionel Sambuc 1367*433d6423SLionel Sambuc /* Make sure that RU is in the 'No resources' state */ 1368*433d6423SLionel Sambuc if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES) 1369*433d6423SLionel Sambuc panic("fxp_restart_ru: RU is in an unexpected state"); 1370*433d6423SLionel Sambuc 1371*433d6423SLionel Sambuc fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr, 1372*433d6423SLionel Sambuc FALSE /* do not check idle */); 1373*433d6423SLionel Sambuc } 1374*433d6423SLionel Sambuc 1375*433d6423SLionel Sambuc /*===========================================================================* 1376*433d6423SLionel Sambuc * fxp_getstat_s * 1377*433d6423SLionel Sambuc *===========================================================================*/ 1378*433d6423SLionel Sambuc static void fxp_getstat_s(message *mp) 1379*433d6423SLionel Sambuc { 1380*433d6423SLionel Sambuc int r; 1381*433d6423SLionel Sambuc fxp_t *fp; 1382*433d6423SLionel Sambuc u32_t *p; 1383*433d6423SLionel Sambuc eth_stat_t stats; 1384*433d6423SLionel Sambuc 1385*433d6423SLionel Sambuc fp= fxp_state; 1386*433d6423SLionel Sambuc 1387*433d6423SLionel Sambuc assert(fp->fxp_mode == FM_ENABLED); 1388*433d6423SLionel Sambuc assert(fp->fxp_flags & FF_ENABLED); 1389*433d6423SLionel Sambuc 1390*433d6423SLionel Sambuc p= &fp->fxp_stat.sc_tx_fcp; 1391*433d6423SLionel Sambuc *p= 0; 1392*433d6423SLionel Sambuc 1393*433d6423SLionel Sambuc /* The dump commmand doesn't take a pointer. Setting a pointer 1394*433d6423SLionel Sambuc * doesn't hurt though. 1395*433d6423SLionel Sambuc */ 1396*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */); 1397*433d6423SLionel Sambuc 1398*433d6423SLionel Sambuc /* Wait for CU command to complete */ 1399*433d6423SLionel Sambuc SPIN_UNTIL(*p != 0, 1000); 1400*433d6423SLionel Sambuc 1401*433d6423SLionel Sambuc if (*p == 0) 1402*433d6423SLionel Sambuc panic("fxp_getstat: CU command failed to complete"); 1403*433d6423SLionel Sambuc if (*p != SCM_DSC) 1404*433d6423SLionel Sambuc panic("fxp_getstat: bad magic"); 1405*433d6423SLionel Sambuc 1406*433d6423SLionel Sambuc stats.ets_recvErr= 1407*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_crc + 1408*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_align + 1409*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_resource + 1410*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_overrun + 1411*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_cd + 1412*433d6423SLionel Sambuc fp->fxp_stat.sc_rx_short; 1413*433d6423SLionel Sambuc stats.ets_sendErr= 1414*433d6423SLionel Sambuc fp->fxp_stat.sc_tx_maxcol + 1415*433d6423SLionel Sambuc fp->fxp_stat.sc_tx_latecol + 1416*433d6423SLionel Sambuc fp->fxp_stat.sc_tx_crs; 1417*433d6423SLionel Sambuc stats.ets_OVW= fp->fxp_stat.sc_rx_overrun; 1418*433d6423SLionel Sambuc stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc; 1419*433d6423SLionel Sambuc stats.ets_frameAll= fp->fxp_stat.sc_rx_align; 1420*433d6423SLionel Sambuc stats.ets_missedP= fp->fxp_stat.sc_rx_resource; 1421*433d6423SLionel Sambuc stats.ets_packetR= fp->fxp_stat.sc_rx_good; 1422*433d6423SLionel Sambuc stats.ets_packetT= fp->fxp_stat.sc_tx_good; 1423*433d6423SLionel Sambuc stats.ets_transDef= fp->fxp_stat.sc_tx_defered; 1424*433d6423SLionel Sambuc stats.ets_collision= fp->fxp_stat.sc_tx_totcol; 1425*433d6423SLionel Sambuc stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol; 1426*433d6423SLionel Sambuc stats.ets_carrSense= fp->fxp_stat.sc_tx_crs; 1427*433d6423SLionel Sambuc stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun; 1428*433d6423SLionel Sambuc stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun; 1429*433d6423SLionel Sambuc stats.ets_CDheartbeat= 0; 1430*433d6423SLionel Sambuc stats.ets_OWC= fp->fxp_stat.sc_tx_latecol; 1431*433d6423SLionel Sambuc 1432*433d6423SLionel Sambuc r= sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, 0, 1433*433d6423SLionel Sambuc (vir_bytes)&stats, sizeof(stats)); 1434*433d6423SLionel Sambuc if (r != OK) 1435*433d6423SLionel Sambuc panic("fxp_getstat_s: sys_safecopyto failed: %d", r); 1436*433d6423SLionel Sambuc 1437*433d6423SLionel Sambuc mp->m_type= DL_STAT_REPLY; 1438*433d6423SLionel Sambuc r= ipc_send(mp->m_source, mp); 1439*433d6423SLionel Sambuc if (r != OK) 1440*433d6423SLionel Sambuc panic("fxp_getstat_s: ipc_send failed: %d", r); 1441*433d6423SLionel Sambuc } 1442*433d6423SLionel Sambuc 1443*433d6423SLionel Sambuc /*===========================================================================* 1444*433d6423SLionel Sambuc * fxp_handler * 1445*433d6423SLionel Sambuc *===========================================================================*/ 1446*433d6423SLionel Sambuc static void fxp_handler(fxp_t *fp) 1447*433d6423SLionel Sambuc { 1448*433d6423SLionel Sambuc int port; 1449*433d6423SLionel Sambuc u16_t isr; 1450*433d6423SLionel Sambuc 1451*433d6423SLionel Sambuc RAND_UPDATE 1452*433d6423SLionel Sambuc 1453*433d6423SLionel Sambuc port= fp->fxp_base_port; 1454*433d6423SLionel Sambuc 1455*433d6423SLionel Sambuc /* Ack interrupt */ 1456*433d6423SLionel Sambuc isr= fxp_inb(port, SCB_INT_STAT); 1457*433d6423SLionel Sambuc fxp_outb(port, SCB_INT_STAT, isr); 1458*433d6423SLionel Sambuc 1459*433d6423SLionel Sambuc if (isr & SIS_FR) 1460*433d6423SLionel Sambuc { 1461*433d6423SLionel Sambuc isr &= ~SIS_FR; 1462*433d6423SLionel Sambuc 1463*433d6423SLionel Sambuc if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING)) 1464*433d6423SLionel Sambuc { 1465*433d6423SLionel Sambuc fp->fxp_got_int= TRUE; 1466*433d6423SLionel Sambuc interrupt(fxp_tasknr); 1467*433d6423SLionel Sambuc } 1468*433d6423SLionel Sambuc } 1469*433d6423SLionel Sambuc if (isr & SIS_CNA) 1470*433d6423SLionel Sambuc { 1471*433d6423SLionel Sambuc isr &= ~SIS_CNA; 1472*433d6423SLionel Sambuc if (!fp->fxp_tx_idle) 1473*433d6423SLionel Sambuc { 1474*433d6423SLionel Sambuc fp->fxp_send_int= TRUE; 1475*433d6423SLionel Sambuc if (!fp->fxp_got_int) 1476*433d6423SLionel Sambuc { 1477*433d6423SLionel Sambuc fp->fxp_got_int= TRUE; 1478*433d6423SLionel Sambuc interrupt(fxp_tasknr); 1479*433d6423SLionel Sambuc } 1480*433d6423SLionel Sambuc } 1481*433d6423SLionel Sambuc } 1482*433d6423SLionel Sambuc if (isr & SIS_RNR) 1483*433d6423SLionel Sambuc { 1484*433d6423SLionel Sambuc isr &= ~SIS_RNR; 1485*433d6423SLionel Sambuc 1486*433d6423SLionel Sambuc /* Assume that receive buffer is full of packets. fxp_readv 1487*433d6423SLionel Sambuc * will restart the RU. 1488*433d6423SLionel Sambuc */ 1489*433d6423SLionel Sambuc fp->fxp_rx_need_restart= 1; 1490*433d6423SLionel Sambuc } 1491*433d6423SLionel Sambuc if (isr) 1492*433d6423SLionel Sambuc { 1493*433d6423SLionel Sambuc printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n", 1494*433d6423SLionel Sambuc isr); 1495*433d6423SLionel Sambuc } 1496*433d6423SLionel Sambuc } 1497*433d6423SLionel Sambuc 1498*433d6423SLionel Sambuc /*===========================================================================* 1499*433d6423SLionel Sambuc * fxp_check_ints * 1500*433d6423SLionel Sambuc *===========================================================================*/ 1501*433d6423SLionel Sambuc static void fxp_check_ints(fxp_t *fp) 1502*433d6423SLionel Sambuc { 1503*433d6423SLionel Sambuc int n, fxp_flags, prev_tail; 1504*433d6423SLionel Sambuc int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold; 1505*433d6423SLionel Sambuc port_t port; 1506*433d6423SLionel Sambuc u32_t busaddr; 1507*433d6423SLionel Sambuc u16_t tx_status; 1508*433d6423SLionel Sambuc u8_t scb_status; 1509*433d6423SLionel Sambuc struct tx *txp; 1510*433d6423SLionel Sambuc 1511*433d6423SLionel Sambuc fxp_flags= fp->fxp_flags; 1512*433d6423SLionel Sambuc 1513*433d6423SLionel Sambuc if (fxp_flags & FF_READING) 1514*433d6423SLionel Sambuc { 1515*433d6423SLionel Sambuc if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C)) 1516*433d6423SLionel Sambuc ; /* Nothing */ 1517*433d6423SLionel Sambuc else 1518*433d6423SLionel Sambuc { 1519*433d6423SLionel Sambuc fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */); 1520*433d6423SLionel Sambuc } 1521*433d6423SLionel Sambuc } 1522*433d6423SLionel Sambuc if (fp->fxp_tx_idle) 1523*433d6423SLionel Sambuc ; /* Nothing to do */ 1524*433d6423SLionel Sambuc else if (fp->fxp_send_int) 1525*433d6423SLionel Sambuc { 1526*433d6423SLionel Sambuc fp->fxp_send_int= FALSE; 1527*433d6423SLionel Sambuc fxp_tx_tail= fp->fxp_tx_tail; 1528*433d6423SLionel Sambuc fxp_tx_nbuf= fp->fxp_tx_nbuf; 1529*433d6423SLionel Sambuc n= 0; 1530*433d6423SLionel Sambuc for (;;) 1531*433d6423SLionel Sambuc { 1532*433d6423SLionel Sambuc txp= &fp->fxp_tx_buf[fxp_tx_tail]; 1533*433d6423SLionel Sambuc tx_status= txp->tx_status; 1534*433d6423SLionel Sambuc if (!(tx_status & TXS_C)) 1535*433d6423SLionel Sambuc break; 1536*433d6423SLionel Sambuc 1537*433d6423SLionel Sambuc n++; 1538*433d6423SLionel Sambuc 1539*433d6423SLionel Sambuc assert(tx_status & TXS_OK); 1540*433d6423SLionel Sambuc if (tx_status & TXS_U) 1541*433d6423SLionel Sambuc { 1542*433d6423SLionel Sambuc fxp_tx_threshold= fp->fxp_tx_threshold; 1543*433d6423SLionel Sambuc if (fxp_tx_threshold < TXTT_MAX) 1544*433d6423SLionel Sambuc { 1545*433d6423SLionel Sambuc fxp_tx_threshold++; 1546*433d6423SLionel Sambuc fp->fxp_tx_threshold= fxp_tx_threshold; 1547*433d6423SLionel Sambuc } 1548*433d6423SLionel Sambuc printf( 1549*433d6423SLionel Sambuc "fxp_check_ints: fxp_tx_threshold = 0x%x\n", 1550*433d6423SLionel Sambuc fxp_tx_threshold); 1551*433d6423SLionel Sambuc } 1552*433d6423SLionel Sambuc 1553*433d6423SLionel Sambuc if (txp->tx_command & TXC_EL) 1554*433d6423SLionel Sambuc { 1555*433d6423SLionel Sambuc fp->fxp_tx_idle= 1; 1556*433d6423SLionel Sambuc break; 1557*433d6423SLionel Sambuc } 1558*433d6423SLionel Sambuc 1559*433d6423SLionel Sambuc fxp_tx_tail++; 1560*433d6423SLionel Sambuc if (fxp_tx_tail == fxp_tx_nbuf) 1561*433d6423SLionel Sambuc fxp_tx_tail= 0; 1562*433d6423SLionel Sambuc assert(fxp_tx_tail < fxp_tx_nbuf); 1563*433d6423SLionel Sambuc } 1564*433d6423SLionel Sambuc 1565*433d6423SLionel Sambuc if (fp->fxp_need_conf) 1566*433d6423SLionel Sambuc { 1567*433d6423SLionel Sambuc /* Check the status of the CU */ 1568*433d6423SLionel Sambuc port= fp->fxp_base_port; 1569*433d6423SLionel Sambuc scb_status= fxp_inb(port, SCB_STATUS); 1570*433d6423SLionel Sambuc if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE) 1571*433d6423SLionel Sambuc { 1572*433d6423SLionel Sambuc /* Nothing to do */ 1573*433d6423SLionel Sambuc printf("scb_status = 0x%x\n", scb_status); 1574*433d6423SLionel Sambuc } 1575*433d6423SLionel Sambuc else 1576*433d6423SLionel Sambuc { 1577*433d6423SLionel Sambuc printf("fxp_check_ints: fxp_need_conf\n"); 1578*433d6423SLionel Sambuc fp->fxp_need_conf= FALSE; 1579*433d6423SLionel Sambuc fxp_do_conf(fp); 1580*433d6423SLionel Sambuc } 1581*433d6423SLionel Sambuc } 1582*433d6423SLionel Sambuc 1583*433d6423SLionel Sambuc if (n) 1584*433d6423SLionel Sambuc { 1585*433d6423SLionel Sambuc if (!fp->fxp_tx_idle) 1586*433d6423SLionel Sambuc { 1587*433d6423SLionel Sambuc fp->fxp_tx_tail= fxp_tx_tail; 1588*433d6423SLionel Sambuc 1589*433d6423SLionel Sambuc /* Check the status of the CU */ 1590*433d6423SLionel Sambuc port= fp->fxp_base_port; 1591*433d6423SLionel Sambuc scb_status= fxp_inb(port, SCB_STATUS); 1592*433d6423SLionel Sambuc if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE) 1593*433d6423SLionel Sambuc { 1594*433d6423SLionel Sambuc /* Nothing to do */ 1595*433d6423SLionel Sambuc printf("scb_status = 0x%x\n", 1596*433d6423SLionel Sambuc scb_status); 1597*433d6423SLionel Sambuc 1598*433d6423SLionel Sambuc } 1599*433d6423SLionel Sambuc else 1600*433d6423SLionel Sambuc { 1601*433d6423SLionel Sambuc if (fxp_tx_tail == 0) 1602*433d6423SLionel Sambuc prev_tail= fxp_tx_nbuf-1; 1603*433d6423SLionel Sambuc else 1604*433d6423SLionel Sambuc prev_tail= fxp_tx_tail-1; 1605*433d6423SLionel Sambuc busaddr= fp->fxp_tx_buf[prev_tail]. 1606*433d6423SLionel Sambuc tx_linkaddr; 1607*433d6423SLionel Sambuc 1608*433d6423SLionel Sambuc fxp_cu_ptr_cmd(fp, SC_CU_START, 1609*433d6423SLionel Sambuc busaddr, 1 /* check idle */); 1610*433d6423SLionel Sambuc } 1611*433d6423SLionel Sambuc } 1612*433d6423SLionel Sambuc 1613*433d6423SLionel Sambuc if (fp->fxp_flags & FF_SEND_AVAIL) 1614*433d6423SLionel Sambuc { 1615*433d6423SLionel Sambuc fxp_writev_s(&fp->fxp_tx_mess, 1616*433d6423SLionel Sambuc TRUE /* from int */); 1617*433d6423SLionel Sambuc } 1618*433d6423SLionel Sambuc } 1619*433d6423SLionel Sambuc 1620*433d6423SLionel Sambuc } 1621*433d6423SLionel Sambuc if (fp->fxp_report_link) 1622*433d6423SLionel Sambuc fxp_report_link(fp); 1623*433d6423SLionel Sambuc 1624*433d6423SLionel Sambuc if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV)) 1625*433d6423SLionel Sambuc reply(fp); 1626*433d6423SLionel Sambuc } 1627*433d6423SLionel Sambuc 1628*433d6423SLionel Sambuc /*===========================================================================* 1629*433d6423SLionel Sambuc * fxp_watchdog_f * 1630*433d6423SLionel Sambuc *===========================================================================*/ 1631*433d6423SLionel Sambuc static void fxp_watchdog_f(tp) 1632*433d6423SLionel Sambuc minix_timer_t *tp; 1633*433d6423SLionel Sambuc { 1634*433d6423SLionel Sambuc fxp_t *fp; 1635*433d6423SLionel Sambuc 1636*433d6423SLionel Sambuc set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f, 0); 1637*433d6423SLionel Sambuc 1638*433d6423SLionel Sambuc fp= fxp_state; 1639*433d6423SLionel Sambuc if (fp->fxp_mode != FM_ENABLED) 1640*433d6423SLionel Sambuc return; 1641*433d6423SLionel Sambuc 1642*433d6423SLionel Sambuc /* Handle race condition, MII interface might be busy */ 1643*433d6423SLionel Sambuc if(!fp->fxp_mii_busy) 1644*433d6423SLionel Sambuc { 1645*433d6423SLionel Sambuc /* Check the link status. */ 1646*433d6423SLionel Sambuc if (fxp_link_changed(fp)) 1647*433d6423SLionel Sambuc { 1648*433d6423SLionel Sambuc #if VERBOSE 1649*433d6423SLionel Sambuc printf("fxp_watchdog_f: link changed\n"); 1650*433d6423SLionel Sambuc #endif 1651*433d6423SLionel Sambuc fp->fxp_report_link= TRUE; 1652*433d6423SLionel Sambuc fp->fxp_got_int= TRUE; 1653*433d6423SLionel Sambuc interrupt(fxp_tasknr); 1654*433d6423SLionel Sambuc } 1655*433d6423SLionel Sambuc } 1656*433d6423SLionel Sambuc 1657*433d6423SLionel Sambuc if (!(fp->fxp_flags & FF_SEND_AVAIL)) 1658*433d6423SLionel Sambuc { 1659*433d6423SLionel Sambuc /* Assume that an idle system is alive */ 1660*433d6423SLionel Sambuc fp->fxp_tx_alive= TRUE; 1661*433d6423SLionel Sambuc return; 1662*433d6423SLionel Sambuc } 1663*433d6423SLionel Sambuc if (fp->fxp_tx_alive) 1664*433d6423SLionel Sambuc { 1665*433d6423SLionel Sambuc fp->fxp_tx_alive= FALSE; 1666*433d6423SLionel Sambuc return; 1667*433d6423SLionel Sambuc } 1668*433d6423SLionel Sambuc 1669*433d6423SLionel Sambuc fp->fxp_need_reset= TRUE; 1670*433d6423SLionel Sambuc fp->fxp_got_int= TRUE; 1671*433d6423SLionel Sambuc interrupt(fxp_tasknr); 1672*433d6423SLionel Sambuc } 1673*433d6423SLionel Sambuc 1674*433d6423SLionel Sambuc /*===========================================================================* 1675*433d6423SLionel Sambuc * fxp_link_changed * 1676*433d6423SLionel Sambuc *===========================================================================*/ 1677*433d6423SLionel Sambuc static int fxp_link_changed(fp) 1678*433d6423SLionel Sambuc fxp_t *fp; 1679*433d6423SLionel Sambuc { 1680*433d6423SLionel Sambuc u16_t scr; 1681*433d6423SLionel Sambuc 1682*433d6423SLionel Sambuc scr= mii_read(fp, MII_SCR); 1683*433d6423SLionel Sambuc scr &= ~(MII_SCR_RES|MII_SCR_RES_1); 1684*433d6423SLionel Sambuc 1685*433d6423SLionel Sambuc return (fp->fxp_mii_scr != scr); 1686*433d6423SLionel Sambuc } 1687*433d6423SLionel Sambuc 1688*433d6423SLionel Sambuc /*===========================================================================* 1689*433d6423SLionel Sambuc * fxp_report_link * 1690*433d6423SLionel Sambuc *===========================================================================*/ 1691*433d6423SLionel Sambuc static void fxp_report_link(fxp_t *fp) 1692*433d6423SLionel Sambuc { 1693*433d6423SLionel Sambuc u16_t mii_ctrl, mii_status, mii_id1, mii_id2, 1694*433d6423SLionel Sambuc mii_ana, mii_anlpa, mii_ane, mii_extstat, 1695*433d6423SLionel Sambuc mii_ms_ctrl, mii_ms_status, scr; 1696*433d6423SLionel Sambuc u32_t oui; 1697*433d6423SLionel Sambuc int model, rev; 1698*433d6423SLionel Sambuc int f, link_up; 1699*433d6423SLionel Sambuc 1700*433d6423SLionel Sambuc fp->fxp_report_link= FALSE; 1701*433d6423SLionel Sambuc 1702*433d6423SLionel Sambuc scr= mii_read(fp, MII_SCR); 1703*433d6423SLionel Sambuc scr &= ~(MII_SCR_RES|MII_SCR_RES_1); 1704*433d6423SLionel Sambuc fp->fxp_mii_scr= scr; 1705*433d6423SLionel Sambuc 1706*433d6423SLionel Sambuc mii_ctrl= mii_read(fp, MII_CTRL); 1707*433d6423SLionel Sambuc mii_read(fp, MII_STATUS); /* The status reg is latched, read twice */ 1708*433d6423SLionel Sambuc mii_status= mii_read(fp, MII_STATUS); 1709*433d6423SLionel Sambuc mii_id1= mii_read(fp, MII_PHYID_H); 1710*433d6423SLionel Sambuc mii_id2= mii_read(fp, MII_PHYID_L); 1711*433d6423SLionel Sambuc mii_ana= mii_read(fp, MII_ANA); 1712*433d6423SLionel Sambuc mii_anlpa= mii_read(fp, MII_ANLPA); 1713*433d6423SLionel Sambuc mii_ane= mii_read(fp, MII_ANE); 1714*433d6423SLionel Sambuc if (mii_status & MII_STATUS_EXT_STAT) 1715*433d6423SLionel Sambuc mii_extstat= mii_read(fp, MII_EXT_STATUS); 1716*433d6423SLionel Sambuc else 1717*433d6423SLionel Sambuc mii_extstat= 0; 1718*433d6423SLionel Sambuc if (fp->fxp_ms_regs) 1719*433d6423SLionel Sambuc { 1720*433d6423SLionel Sambuc mii_ms_ctrl= mii_read(fp, MII_MS_CTRL); 1721*433d6423SLionel Sambuc mii_ms_status= mii_read(fp, MII_MS_STATUS); 1722*433d6423SLionel Sambuc } 1723*433d6423SLionel Sambuc else 1724*433d6423SLionel Sambuc { 1725*433d6423SLionel Sambuc mii_ms_ctrl= 0; 1726*433d6423SLionel Sambuc mii_ms_status= 0; 1727*433d6423SLionel Sambuc } 1728*433d6423SLionel Sambuc 1729*433d6423SLionel Sambuc /* How do we know about the link status? */ 1730*433d6423SLionel Sambuc link_up= !!(mii_status & MII_STATUS_LS); 1731*433d6423SLionel Sambuc 1732*433d6423SLionel Sambuc fp->fxp_link_up= link_up; 1733*433d6423SLionel Sambuc if (!link_up) 1734*433d6423SLionel Sambuc { 1735*433d6423SLionel Sambuc #if VERBOSE 1736*433d6423SLionel Sambuc printf("%s: link down\n", fp->fxp_name); 1737*433d6423SLionel Sambuc #endif 1738*433d6423SLionel Sambuc return; 1739*433d6423SLionel Sambuc } 1740*433d6423SLionel Sambuc 1741*433d6423SLionel Sambuc oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) | 1742*433d6423SLionel Sambuc ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT); 1743*433d6423SLionel Sambuc model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT); 1744*433d6423SLionel Sambuc rev= (mii_id2 & MII_PL_REV_MASK); 1745*433d6423SLionel Sambuc 1746*433d6423SLionel Sambuc #if VERBOSE 1747*433d6423SLionel Sambuc printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev); 1748*433d6423SLionel Sambuc #endif 1749*433d6423SLionel Sambuc 1750*433d6423SLionel Sambuc if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO)) 1751*433d6423SLionel Sambuc { 1752*433d6423SLionel Sambuc printf("%s: PHY: ", fp->fxp_name); 1753*433d6423SLionel Sambuc f= 1; 1754*433d6423SLionel Sambuc if (mii_ctrl & MII_CTRL_LB) 1755*433d6423SLionel Sambuc { 1756*433d6423SLionel Sambuc printf("loopback mode"); 1757*433d6423SLionel Sambuc f= 0; 1758*433d6423SLionel Sambuc } 1759*433d6423SLionel Sambuc if (mii_ctrl & MII_CTRL_PD) 1760*433d6423SLionel Sambuc { 1761*433d6423SLionel Sambuc if (!f) printf(", "); 1762*433d6423SLionel Sambuc f= 0; 1763*433d6423SLionel Sambuc printf("powered down"); 1764*433d6423SLionel Sambuc } 1765*433d6423SLionel Sambuc if (mii_ctrl & MII_CTRL_ISO) 1766*433d6423SLionel Sambuc { 1767*433d6423SLionel Sambuc if (!f) printf(", "); 1768*433d6423SLionel Sambuc f= 0; 1769*433d6423SLionel Sambuc printf("isolated"); 1770*433d6423SLionel Sambuc } 1771*433d6423SLionel Sambuc printf("\n"); 1772*433d6423SLionel Sambuc return; 1773*433d6423SLionel Sambuc } 1774*433d6423SLionel Sambuc if (!(mii_ctrl & MII_CTRL_ANE)) 1775*433d6423SLionel Sambuc { 1776*433d6423SLionel Sambuc printf("%s: manual config: ", fp->fxp_name); 1777*433d6423SLionel Sambuc switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB)) 1778*433d6423SLionel Sambuc { 1779*433d6423SLionel Sambuc case MII_CTRL_SP_10: printf("10 Mbps"); break; 1780*433d6423SLionel Sambuc case MII_CTRL_SP_100: printf("100 Mbps"); break; 1781*433d6423SLionel Sambuc case MII_CTRL_SP_1000: printf("1000 Mbps"); break; 1782*433d6423SLionel Sambuc case MII_CTRL_SP_RES: printf("reserved speed"); break; 1783*433d6423SLionel Sambuc } 1784*433d6423SLionel Sambuc if (mii_ctrl & MII_CTRL_DM) 1785*433d6423SLionel Sambuc printf(", full duplex"); 1786*433d6423SLionel Sambuc else 1787*433d6423SLionel Sambuc printf(", half duplex"); 1788*433d6423SLionel Sambuc printf("\n"); 1789*433d6423SLionel Sambuc return; 1790*433d6423SLionel Sambuc } 1791*433d6423SLionel Sambuc 1792*433d6423SLionel Sambuc if (!debug) goto resspeed; 1793*433d6423SLionel Sambuc 1794*433d6423SLionel Sambuc printf("%s: ", fp->fxp_name); 1795*433d6423SLionel Sambuc mii_print_stat_speed(mii_status, mii_extstat); 1796*433d6423SLionel Sambuc printf("\n"); 1797*433d6423SLionel Sambuc 1798*433d6423SLionel Sambuc if (!(mii_status & MII_STATUS_ANC)) 1799*433d6423SLionel Sambuc printf("%s: auto-negotiation not complete\n", fp->fxp_name); 1800*433d6423SLionel Sambuc if (mii_status & MII_STATUS_RF) 1801*433d6423SLionel Sambuc printf("%s: remote fault detected\n", fp->fxp_name); 1802*433d6423SLionel Sambuc if (!(mii_status & MII_STATUS_ANA)) 1803*433d6423SLionel Sambuc { 1804*433d6423SLionel Sambuc printf("%s: local PHY has no auto-negotiation ability\n", 1805*433d6423SLionel Sambuc fp->fxp_name); 1806*433d6423SLionel Sambuc } 1807*433d6423SLionel Sambuc if (!(mii_status & MII_STATUS_LS)) 1808*433d6423SLionel Sambuc printf("%s: link down\n", fp->fxp_name); 1809*433d6423SLionel Sambuc if (mii_status & MII_STATUS_JD) 1810*433d6423SLionel Sambuc printf("%s: jabber condition detected\n", fp->fxp_name); 1811*433d6423SLionel Sambuc if (!(mii_status & MII_STATUS_EC)) 1812*433d6423SLionel Sambuc { 1813*433d6423SLionel Sambuc printf("%s: no extended register set\n", fp->fxp_name); 1814*433d6423SLionel Sambuc goto resspeed; 1815*433d6423SLionel Sambuc } 1816*433d6423SLionel Sambuc if (!(mii_status & MII_STATUS_ANC)) 1817*433d6423SLionel Sambuc goto resspeed; 1818*433d6423SLionel Sambuc 1819*433d6423SLionel Sambuc printf("%s: local cap.: ", fp->fxp_name); 1820*433d6423SLionel Sambuc if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) 1821*433d6423SLionel Sambuc { 1822*433d6423SLionel Sambuc printf("1000 Mbps: T-"); 1823*433d6423SLionel Sambuc switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) 1824*433d6423SLionel Sambuc { 1825*433d6423SLionel Sambuc case MII_MSC_1000T_FD: printf("FD"); break; 1826*433d6423SLionel Sambuc case MII_MSC_1000T_HD: printf("HD"); break; 1827*433d6423SLionel Sambuc default: printf("FD/HD"); break; 1828*433d6423SLionel Sambuc } 1829*433d6423SLionel Sambuc if (mii_ana) 1830*433d6423SLionel Sambuc printf(", "); 1831*433d6423SLionel Sambuc } 1832*433d6423SLionel Sambuc mii_print_techab(mii_ana); 1833*433d6423SLionel Sambuc printf("\n"); 1834*433d6423SLionel Sambuc 1835*433d6423SLionel Sambuc if (mii_ane & MII_ANE_PDF) 1836*433d6423SLionel Sambuc printf("%s: parallel detection fault\n", fp->fxp_name); 1837*433d6423SLionel Sambuc if (!(mii_ane & MII_ANE_LPANA)) 1838*433d6423SLionel Sambuc { 1839*433d6423SLionel Sambuc printf("%s: link-partner does not support auto-negotiation\n", 1840*433d6423SLionel Sambuc fp->fxp_name); 1841*433d6423SLionel Sambuc goto resspeed; 1842*433d6423SLionel Sambuc } 1843*433d6423SLionel Sambuc 1844*433d6423SLionel Sambuc printf("%s: remote cap.: ", fp->fxp_name); 1845*433d6423SLionel Sambuc if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD)) 1846*433d6423SLionel Sambuc if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD)) 1847*433d6423SLionel Sambuc { 1848*433d6423SLionel Sambuc printf("1000 Mbps: T-"); 1849*433d6423SLionel Sambuc switch(mii_ms_status & 1850*433d6423SLionel Sambuc (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD)) 1851*433d6423SLionel Sambuc { 1852*433d6423SLionel Sambuc case MII_MSS_LP1000T_FD: printf("FD"); break; 1853*433d6423SLionel Sambuc case MII_MSS_LP1000T_HD: printf("HD"); break; 1854*433d6423SLionel Sambuc default: printf("FD/HD"); break; 1855*433d6423SLionel Sambuc } 1856*433d6423SLionel Sambuc if (mii_anlpa) 1857*433d6423SLionel Sambuc printf(", "); 1858*433d6423SLionel Sambuc } 1859*433d6423SLionel Sambuc mii_print_techab(mii_anlpa); 1860*433d6423SLionel Sambuc printf("\n"); 1861*433d6423SLionel Sambuc 1862*433d6423SLionel Sambuc if (fp->fxp_ms_regs) 1863*433d6423SLionel Sambuc { 1864*433d6423SLionel Sambuc printf("%s: ", fp->fxp_name); 1865*433d6423SLionel Sambuc if (mii_ms_ctrl & MII_MSC_MS_MANUAL) 1866*433d6423SLionel Sambuc { 1867*433d6423SLionel Sambuc printf("manual %s", 1868*433d6423SLionel Sambuc (mii_ms_ctrl & MII_MSC_MS_VAL) ? 1869*433d6423SLionel Sambuc "MASTER" : "SLAVE"); 1870*433d6423SLionel Sambuc } 1871*433d6423SLionel Sambuc else 1872*433d6423SLionel Sambuc { 1873*433d6423SLionel Sambuc printf("%s device", 1874*433d6423SLionel Sambuc (mii_ms_ctrl & MII_MSC_MULTIPORT) ? 1875*433d6423SLionel Sambuc "multiport" : "single-port"); 1876*433d6423SLionel Sambuc } 1877*433d6423SLionel Sambuc if (mii_ms_ctrl & MII_MSC_RES) 1878*433d6423SLionel Sambuc printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES); 1879*433d6423SLionel Sambuc printf(": "); 1880*433d6423SLionel Sambuc if (mii_ms_status & MII_MSS_FAULT) 1881*433d6423SLionel Sambuc printf("M/S config fault"); 1882*433d6423SLionel Sambuc else if (mii_ms_status & MII_MSS_MASTER) 1883*433d6423SLionel Sambuc printf("MASTER"); 1884*433d6423SLionel Sambuc else 1885*433d6423SLionel Sambuc printf("SLAVE"); 1886*433d6423SLionel Sambuc printf("\n"); 1887*433d6423SLionel Sambuc } 1888*433d6423SLionel Sambuc 1889*433d6423SLionel Sambuc if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD)) 1890*433d6423SLionel Sambuc { 1891*433d6423SLionel Sambuc if (!(mii_ms_status & MII_MSS_LOCREC)) 1892*433d6423SLionel Sambuc { 1893*433d6423SLionel Sambuc printf("%s: local receiver not OK\n", 1894*433d6423SLionel Sambuc fp->fxp_name); 1895*433d6423SLionel Sambuc } 1896*433d6423SLionel Sambuc if (!(mii_ms_status & MII_MSS_REMREC)) 1897*433d6423SLionel Sambuc { 1898*433d6423SLionel Sambuc printf("%s: remote receiver not OK\n", 1899*433d6423SLionel Sambuc fp->fxp_name); 1900*433d6423SLionel Sambuc } 1901*433d6423SLionel Sambuc } 1902*433d6423SLionel Sambuc if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR)) 1903*433d6423SLionel Sambuc { 1904*433d6423SLionel Sambuc printf("%s", fp->fxp_name); 1905*433d6423SLionel Sambuc if (mii_ms_status & MII_MSS_RES) 1906*433d6423SLionel Sambuc printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES); 1907*433d6423SLionel Sambuc if (mii_ms_status & MII_MSS_IDLE_ERR) 1908*433d6423SLionel Sambuc { 1909*433d6423SLionel Sambuc printf(" idle error %d", 1910*433d6423SLionel Sambuc mii_ms_status & MII_MSS_IDLE_ERR); 1911*433d6423SLionel Sambuc } 1912*433d6423SLionel Sambuc printf("\n"); 1913*433d6423SLionel Sambuc } 1914*433d6423SLionel Sambuc 1915*433d6423SLionel Sambuc resspeed: 1916*433d6423SLionel Sambuc #if VERBOSE 1917*433d6423SLionel Sambuc printf("%s: link up, %d Mbps, %s duplex\n", 1918*433d6423SLionel Sambuc fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10, 1919*433d6423SLionel Sambuc (scr & MII_SCR_FD) ? "full" : "half"); 1920*433d6423SLionel Sambuc #endif 1921*433d6423SLionel Sambuc ; 1922*433d6423SLionel Sambuc } 1923*433d6423SLionel Sambuc 1924*433d6423SLionel Sambuc /*===========================================================================* 1925*433d6423SLionel Sambuc * reply * 1926*433d6423SLionel Sambuc *===========================================================================*/ 1927*433d6423SLionel Sambuc static void reply(fp) 1928*433d6423SLionel Sambuc fxp_t *fp; 1929*433d6423SLionel Sambuc { 1930*433d6423SLionel Sambuc message reply; 1931*433d6423SLionel Sambuc int flags; 1932*433d6423SLionel Sambuc int r; 1933*433d6423SLionel Sambuc 1934*433d6423SLionel Sambuc flags = DL_NOFLAGS; 1935*433d6423SLionel Sambuc if (fp->fxp_flags & FF_PACK_SENT) 1936*433d6423SLionel Sambuc flags |= DL_PACK_SEND; 1937*433d6423SLionel Sambuc if (fp->fxp_flags & FF_PACK_RECV) 1938*433d6423SLionel Sambuc flags |= DL_PACK_RECV; 1939*433d6423SLionel Sambuc 1940*433d6423SLionel Sambuc reply.m_type = DL_TASK_REPLY; 1941*433d6423SLionel Sambuc reply.m_netdrv_net_dl_task.flags = flags; 1942*433d6423SLionel Sambuc reply.m_netdrv_net_dl_task.count = fp->fxp_read_s; 1943*433d6423SLionel Sambuc 1944*433d6423SLionel Sambuc r= ipc_send(fp->fxp_client, &reply); 1945*433d6423SLionel Sambuc 1946*433d6423SLionel Sambuc if (r < 0) 1947*433d6423SLionel Sambuc panic("fxp: ipc_send failed: %d", r); 1948*433d6423SLionel Sambuc 1949*433d6423SLionel Sambuc fp->fxp_read_s = 0; 1950*433d6423SLionel Sambuc fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV); 1951*433d6423SLionel Sambuc } 1952*433d6423SLionel Sambuc 1953*433d6423SLionel Sambuc /*===========================================================================* 1954*433d6423SLionel Sambuc * mess_reply * 1955*433d6423SLionel Sambuc *===========================================================================*/ 1956*433d6423SLionel Sambuc static void mess_reply(req, reply_mess) 1957*433d6423SLionel Sambuc message *req; 1958*433d6423SLionel Sambuc message *reply_mess; 1959*433d6423SLionel Sambuc { 1960*433d6423SLionel Sambuc if (ipc_send(req->m_source, reply_mess) != OK) 1961*433d6423SLionel Sambuc panic("fxp: unable to mess_reply"); 1962*433d6423SLionel Sambuc } 1963*433d6423SLionel Sambuc 1964*433d6423SLionel Sambuc /*===========================================================================* 1965*433d6423SLionel Sambuc * eeprom_read * 1966*433d6423SLionel Sambuc *===========================================================================*/ 1967*433d6423SLionel Sambuc static u16_t eeprom_read(fp, reg) 1968*433d6423SLionel Sambuc fxp_t *fp; 1969*433d6423SLionel Sambuc int reg; 1970*433d6423SLionel Sambuc { 1971*433d6423SLionel Sambuc port_t port; 1972*433d6423SLionel Sambuc u16_t v; 1973*433d6423SLionel Sambuc int b, i, alen; 1974*433d6423SLionel Sambuc 1975*433d6423SLionel Sambuc alen= fp->fxp_ee_addrlen; 1976*433d6423SLionel Sambuc if (!alen) 1977*433d6423SLionel Sambuc { 1978*433d6423SLionel Sambuc eeprom_addrsize(fp); 1979*433d6423SLionel Sambuc alen= fp->fxp_ee_addrlen; 1980*433d6423SLionel Sambuc assert(alen == 6 || alen == 8); 1981*433d6423SLionel Sambuc } 1982*433d6423SLionel Sambuc 1983*433d6423SLionel Sambuc port= fp->fxp_base_port; 1984*433d6423SLionel Sambuc 1985*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */ 1986*433d6423SLionel Sambuc v= EEPROM_READ_PREFIX; 1987*433d6423SLionel Sambuc for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--) 1988*433d6423SLionel Sambuc { 1989*433d6423SLionel Sambuc b= ((v & (1 << i)) ? CE_EEDI : 0); 1990*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ 1991*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ 1992*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 1993*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); 1994*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 1995*433d6423SLionel Sambuc } 1996*433d6423SLionel Sambuc 1997*433d6423SLionel Sambuc v= reg; 1998*433d6423SLionel Sambuc for (i= alen-1; i >= 0; i--) 1999*433d6423SLionel Sambuc { 2000*433d6423SLionel Sambuc b= ((v & (1 << i)) ? CE_EEDI : 0); 2001*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ 2002*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ 2003*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2004*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); 2005*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2006*433d6423SLionel Sambuc } 2007*433d6423SLionel Sambuc 2008*433d6423SLionel Sambuc v= 0; 2009*433d6423SLionel Sambuc for (i= 0; i<16; i++) 2010*433d6423SLionel Sambuc { 2011*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */ 2012*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2013*433d6423SLionel Sambuc b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO); 2014*433d6423SLionel Sambuc v= (v << 1) | b; 2015*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS ); 2016*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2017*433d6423SLionel Sambuc } 2018*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */ 2019*433d6423SLionel Sambuc micro_delay(EECS_DELAY); 2020*433d6423SLionel Sambuc 2021*433d6423SLionel Sambuc return v; 2022*433d6423SLionel Sambuc } 2023*433d6423SLionel Sambuc 2024*433d6423SLionel Sambuc /*===========================================================================* 2025*433d6423SLionel Sambuc * eeprom_addrsize * 2026*433d6423SLionel Sambuc *===========================================================================*/ 2027*433d6423SLionel Sambuc static void eeprom_addrsize(fp) 2028*433d6423SLionel Sambuc fxp_t *fp; 2029*433d6423SLionel Sambuc { 2030*433d6423SLionel Sambuc port_t port; 2031*433d6423SLionel Sambuc u16_t v; 2032*433d6423SLionel Sambuc int b, i; 2033*433d6423SLionel Sambuc 2034*433d6423SLionel Sambuc port= fp->fxp_base_port; 2035*433d6423SLionel Sambuc 2036*433d6423SLionel Sambuc /* Try to find out the size of the EEPROM */ 2037*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */ 2038*433d6423SLionel Sambuc v= EEPROM_READ_PREFIX; 2039*433d6423SLionel Sambuc for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--) 2040*433d6423SLionel Sambuc { 2041*433d6423SLionel Sambuc b= ((v & (1 << i)) ? CE_EEDI : 0); 2042*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ 2043*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ 2044*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2045*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); 2046*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2047*433d6423SLionel Sambuc } 2048*433d6423SLionel Sambuc 2049*433d6423SLionel Sambuc for (i= 0; i<32; i++) 2050*433d6423SLionel Sambuc { 2051*433d6423SLionel Sambuc b= 0; 2052*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */ 2053*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */ 2054*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2055*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | b); 2056*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2057*433d6423SLionel Sambuc v= fxp_inb(port, CSR_EEPROM); 2058*433d6423SLionel Sambuc if (!(v & CE_EEDO)) 2059*433d6423SLionel Sambuc break; 2060*433d6423SLionel Sambuc } 2061*433d6423SLionel Sambuc if (i >= 32) 2062*433d6423SLionel Sambuc panic("eeprom_addrsize: failed"); 2063*433d6423SLionel Sambuc fp->fxp_ee_addrlen= i+1; 2064*433d6423SLionel Sambuc 2065*433d6423SLionel Sambuc /* Discard 16 data bits */ 2066*433d6423SLionel Sambuc for (i= 0; i<16; i++) 2067*433d6423SLionel Sambuc { 2068*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */ 2069*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2070*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, CE_EECS ); 2071*433d6423SLionel Sambuc micro_delay(EESK_PERIOD/2+1); 2072*433d6423SLionel Sambuc } 2073*433d6423SLionel Sambuc fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */ 2074*433d6423SLionel Sambuc micro_delay(EECS_DELAY); 2075*433d6423SLionel Sambuc 2076*433d6423SLionel Sambuc #if VERBOSE 2077*433d6423SLionel Sambuc printf("%s EEPROM address length: %d\n", 2078*433d6423SLionel Sambuc fp->fxp_name, fp->fxp_ee_addrlen); 2079*433d6423SLionel Sambuc #endif 2080*433d6423SLionel Sambuc } 2081*433d6423SLionel Sambuc 2082*433d6423SLionel Sambuc /*===========================================================================* 2083*433d6423SLionel Sambuc * mii_read * 2084*433d6423SLionel Sambuc *===========================================================================*/ 2085*433d6423SLionel Sambuc static u16_t mii_read(fp, reg) 2086*433d6423SLionel Sambuc fxp_t *fp; 2087*433d6423SLionel Sambuc int reg; 2088*433d6423SLionel Sambuc { 2089*433d6423SLionel Sambuc spin_t spin; 2090*433d6423SLionel Sambuc port_t port; 2091*433d6423SLionel Sambuc u32_t v; 2092*433d6423SLionel Sambuc 2093*433d6423SLionel Sambuc port= fp->fxp_base_port; 2094*433d6423SLionel Sambuc 2095*433d6423SLionel Sambuc assert(!fp->fxp_mii_busy); 2096*433d6423SLionel Sambuc fp->fxp_mii_busy++; 2097*433d6423SLionel Sambuc 2098*433d6423SLionel Sambuc if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY)) 2099*433d6423SLionel Sambuc panic("mii_read: MDI not ready"); 2100*433d6423SLionel Sambuc fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) | 2101*433d6423SLionel Sambuc (reg << CM_REG_SHIFT)); 2102*433d6423SLionel Sambuc 2103*433d6423SLionel Sambuc spin_init(&spin, 100000); 2104*433d6423SLionel Sambuc do { 2105*433d6423SLionel Sambuc v= fxp_inl(port, CSR_MDI_CTL); 2106*433d6423SLionel Sambuc if (v & CM_READY) 2107*433d6423SLionel Sambuc break; 2108*433d6423SLionel Sambuc } while (spin_check(&spin)); 2109*433d6423SLionel Sambuc 2110*433d6423SLionel Sambuc if (!(v & CM_READY)) 2111*433d6423SLionel Sambuc panic("mii_read: MDI not ready after command"); 2112*433d6423SLionel Sambuc 2113*433d6423SLionel Sambuc fp->fxp_mii_busy--; 2114*433d6423SLionel Sambuc assert(!fp->fxp_mii_busy); 2115*433d6423SLionel Sambuc 2116*433d6423SLionel Sambuc return v & CM_DATA_MASK; 2117*433d6423SLionel Sambuc } 2118*433d6423SLionel Sambuc 2119*433d6423SLionel Sambuc static u8_t do_inb(port_t port) 2120*433d6423SLionel Sambuc { 2121*433d6423SLionel Sambuc int r; 2122*433d6423SLionel Sambuc u32_t value; 2123*433d6423SLionel Sambuc 2124*433d6423SLionel Sambuc r= sys_inb(port, &value); 2125*433d6423SLionel Sambuc if (r != OK) 2126*433d6423SLionel Sambuc panic("sys_inb failed: %d", r); 2127*433d6423SLionel Sambuc return value; 2128*433d6423SLionel Sambuc } 2129*433d6423SLionel Sambuc 2130*433d6423SLionel Sambuc static u32_t do_inl(port_t port) 2131*433d6423SLionel Sambuc { 2132*433d6423SLionel Sambuc int r; 2133*433d6423SLionel Sambuc u32_t value; 2134*433d6423SLionel Sambuc 2135*433d6423SLionel Sambuc r= sys_inl(port, &value); 2136*433d6423SLionel Sambuc if (r != OK) 2137*433d6423SLionel Sambuc panic("sys_inl failed: %d", r); 2138*433d6423SLionel Sambuc return value; 2139*433d6423SLionel Sambuc } 2140*433d6423SLionel Sambuc 2141*433d6423SLionel Sambuc static void do_outb(port_t port, u8_t value) 2142*433d6423SLionel Sambuc { 2143*433d6423SLionel Sambuc int r; 2144*433d6423SLionel Sambuc 2145*433d6423SLionel Sambuc r= sys_outb(port, value); 2146*433d6423SLionel Sambuc if (r != OK) 2147*433d6423SLionel Sambuc panic("sys_outb failed: %d", r); 2148*433d6423SLionel Sambuc } 2149*433d6423SLionel Sambuc 2150*433d6423SLionel Sambuc static void do_outl(port_t port, u32_t value) 2151*433d6423SLionel Sambuc { 2152*433d6423SLionel Sambuc int r; 2153*433d6423SLionel Sambuc 2154*433d6423SLionel Sambuc r= sys_outl(port, value); 2155*433d6423SLionel Sambuc if (r != OK) 2156*433d6423SLionel Sambuc panic("sys_outl failed: %d", r); 2157*433d6423SLionel Sambuc } 2158*433d6423SLionel Sambuc 2159*433d6423SLionel Sambuc static void tell_dev(buf, size, pci_bus, pci_dev, pci_func) 2160*433d6423SLionel Sambuc vir_bytes buf; 2161*433d6423SLionel Sambuc size_t size; 2162*433d6423SLionel Sambuc int pci_bus; 2163*433d6423SLionel Sambuc int pci_dev; 2164*433d6423SLionel Sambuc int pci_func; 2165*433d6423SLionel Sambuc { 2166*433d6423SLionel Sambuc int r; 2167*433d6423SLionel Sambuc endpoint_t dev_e; 2168*433d6423SLionel Sambuc message m; 2169*433d6423SLionel Sambuc 2170*433d6423SLionel Sambuc r= ds_retrieve_label_endpt("amddev", &dev_e); 2171*433d6423SLionel Sambuc if (r != OK) 2172*433d6423SLionel Sambuc { 2173*433d6423SLionel Sambuc #if 0 2174*433d6423SLionel Sambuc printf( 2175*433d6423SLionel Sambuc "fxp`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n", 2176*433d6423SLionel Sambuc r); 2177*433d6423SLionel Sambuc #endif 2178*433d6423SLionel Sambuc return; 2179*433d6423SLionel Sambuc } 2180*433d6423SLionel Sambuc 2181*433d6423SLionel Sambuc m.m_type= IOMMU_MAP; 2182*433d6423SLionel Sambuc m.m2_i1= pci_bus; 2183*433d6423SLionel Sambuc m.m2_i2= pci_dev; 2184*433d6423SLionel Sambuc m.m2_i3= pci_func; 2185*433d6423SLionel Sambuc m.m2_l1= buf; 2186*433d6423SLionel Sambuc m.m2_l2= size; 2187*433d6423SLionel Sambuc 2188*433d6423SLionel Sambuc r= ipc_sendrec(dev_e, &m); 2189*433d6423SLionel Sambuc if (r != OK) 2190*433d6423SLionel Sambuc { 2191*433d6423SLionel Sambuc printf("fxp`tell_dev: ipc_sendrec to %d failed: %d\n", 2192*433d6423SLionel Sambuc dev_e, r); 2193*433d6423SLionel Sambuc return; 2194*433d6423SLionel Sambuc } 2195*433d6423SLionel Sambuc if (m.m_type != OK) 2196*433d6423SLionel Sambuc { 2197*433d6423SLionel Sambuc printf("fxp`tell_dev: dma map request failed: %d\n", 2198*433d6423SLionel Sambuc m.m_type); 2199*433d6423SLionel Sambuc return; 2200*433d6423SLionel Sambuc } 2201*433d6423SLionel Sambuc } 2202*433d6423SLionel Sambuc 2203*433d6423SLionel Sambuc /* 2204*433d6423SLionel Sambuc * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $ 2205*433d6423SLionel Sambuc */ 2206*433d6423SLionel Sambuc 2207