void ips_issue_copperhead_cmd(ips_command_t *command) { int i; intrmask_t mask = splbio(); /* hmmm, is there a cleaner way to do this? */ if(command->sc->state & IPS_OFFLINE){ splx(mask); command->status.value = IPS_ERROR_STATUS; command->callback(command); return; } command->timeout = 10; for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT; i++ ){ if( i == 20){ printf("sem bit still set, can't send a command\n"); splx(mask); return; } DELAY(500);/* need to do a delay here */ } ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr); ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START); splx(mask); }
/* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */ int ips_copperhead_reinit(ips_softc_t *sc, int force) { int i, j; u_int32_t postcode = 0, configstatus = 0; ips_write_1(sc, COPPER_REG_SCPR, 0x80); ips_write_1(sc, COPPER_REG_SCPR, 0); device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n"); for(j = 0; j < 2; j++){ postcode <<= 8; for(i = 0; i < 45; i++){ if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){ postcode |= ips_read_1(sc, COPPER_REG_ISPR); ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT); break; } else DELAY(1000000); } if(i == 45) return 1; } for(j = 0; j < 2; j++){ configstatus <<= 8; for(i = 0; i < 240; i++){ if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){ configstatus |= ips_read_1(sc, COPPER_REG_ISPR); ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT); break; } else DELAY(1000000); } if(i == 240) return 1; } for(i = 0; i < 240; i++){ if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){ break; } else DELAY(1000000); } if(i == 240) return 1; ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT); ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT); ips_copperhead_queue_init(sc); ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT); i = ips_read_1(sc, COPPER_REG_SCPR); ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT); if(!configstatus){ device_printf(sc->dev, "adapter initialization failed\n"); return 1; } if(force && ips_clear_adapter(sc)){ device_printf(sc->dev, "adapter clear failed\n"); return 1; } return 0; }