📄 adwcam.c
字号:
s = splsoftvm(); error = bus_dmamap_load(adw->buffer_dmat, acb->dmamap, csio->data_ptr, csio->dxfer_len, adwexecuteacb, acb, /*flags*/0); if (error == EINPROGRESS) { /* * So as to maintain ordering, * freeze the controller queue * until our mapping is * returned. */ xpt_freeze_simq(sim, 1); acb->state |= CAM_RELEASE_SIMQ; } splx(s); } else { struct bus_dma_segment seg; /* Pointer to physical buffer */ seg.ds_addr = (bus_addr_t)csio->data_ptr; seg.ds_len = csio->dxfer_len; adwexecuteacb(acb, &seg, 1, 0); } } else { struct bus_dma_segment *segs; if ((ccbh->flags & CAM_DATA_PHYS) != 0) panic("adw_action - Physical " "segment pointers " "unsupported"); if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) panic("adw_action - Virtual " "segment addresses " "unsupported"); /* Just use the segments provided */ segs = (struct bus_dma_segment *)csio->data_ptr; adwexecuteacb(acb, segs, csio->sglist_cnt, (csio->sglist_cnt < ADW_SGSIZE) ? 0 : EFBIG); } } else { adwexecuteacb(acb, NULL, 0, 0); } break; } case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ { adw_idle_cmd_status_t status; adw_idle_cmd_send(adw, ADW_IDLE_CMD_DEVICE_RESET, ccb->ccb_h.target_id); status = adw_idle_cmd_wait(adw); if (status == ADW_IDLE_CMD_SUCCESS) { ccb->ccb_h.status = CAM_REQ_CMP; if (bootverbose) { xpt_print_path(ccb->ccb_h.path); printf("BDR Delivered\n"); } } else ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); break; } case XPT_ABORT: /* Abort the specified CCB */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; case XPT_SET_TRAN_SETTINGS: { struct ccb_trans_settings *cts; u_int target_mask; int s; cts = &ccb->cts; target_mask = 0x01 << ccb->ccb_h.target_id; s = splcam(); if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { u_int discenb; discenb = adw_lram_read_16(adw, ADW_MC_DISC_ENABLE); if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) discenb |= target_mask; else discenb &= ~target_mask; adw_lram_write_16(adw, ADW_MC_DISC_ENABLE, discenb); } if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) { if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) adw->tagenb |= target_mask; else adw->tagenb &= ~target_mask; } if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) { u_int wdtrenb_orig; u_int wdtrenb; u_int wdtrdone; wdtrenb_orig = adw_lram_read_16(adw, ADW_MC_WDTR_ABLE); wdtrenb = wdtrenb_orig; wdtrdone = adw_lram_read_16(adw, ADW_MC_WDTR_DONE); switch (cts->bus_width) { case MSG_EXT_WDTR_BUS_32_BIT: case MSG_EXT_WDTR_BUS_16_BIT: wdtrenb |= target_mask; break; case MSG_EXT_WDTR_BUS_8_BIT: default: wdtrenb &= ~target_mask; break; } if (wdtrenb != wdtrenb_orig) { adw_lram_write_16(adw, ADW_MC_WDTR_ABLE, wdtrenb); wdtrdone &= ~target_mask; adw_lram_write_16(adw, ADW_MC_WDTR_DONE, wdtrdone); } } if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) { u_int sdtrenb_orig; u_int sdtrenb; u_int ultraenb_orig; u_int ultraenb; u_int sdtrdone; sdtrenb_orig = adw_lram_read_16(adw, ADW_MC_SDTR_ABLE); sdtrenb = sdtrenb_orig; ultraenb_orig = adw_lram_read_16(adw, ADW_MC_ULTRA_ABLE); ultraenb = ultraenb_orig; sdtrdone = adw_lram_read_16(adw, ADW_MC_SDTR_DONE); if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) { if (cts->sync_period == 0) { sdtrenb &= ~target_mask; } else if (cts->sync_period > 12) { ultraenb &= ~target_mask; sdtrenb |= target_mask; } else { ultraenb |= target_mask; sdtrenb |= target_mask; } } if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) { if (cts->sync_offset == 0) sdtrenb &= ~target_mask; } if (sdtrenb != sdtrenb_orig || ultraenb != ultraenb_orig) { adw_lram_write_16(adw, ADW_MC_SDTR_ABLE, sdtrenb); adw_lram_write_16(adw, ADW_MC_ULTRA_ABLE, ultraenb); sdtrdone &= ~target_mask; adw_lram_write_16(adw, ADW_MC_SDTR_DONE, sdtrdone); } } } splx(s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_GET_TRAN_SETTINGS: /* Get default/user set transfer settings for the target */ { struct ccb_trans_settings *cts; u_int target_mask; cts = &ccb->cts; target_mask = 0x01 << ccb->ccb_h.target_id; if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { cts->flags = 0; if ((adw->user_discenb & target_mask) != 0) cts->flags |= CCB_TRANS_DISC_ENB; if ((adw->user_tagenb & target_mask) != 0) cts->flags |= CCB_TRANS_TAG_ENB; if ((adw->user_wdtr & target_mask) != 0) cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; else cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; if ((adw->user_sdtr & target_mask) != 0) { if ((adw->user_ultra & target_mask) != 0) cts->sync_period = 12; /* 20MHz */ else cts->sync_period = 25; /* 10MHz */ cts->sync_offset = 15; /* XXX ??? */ } cts->valid = CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; ccb->ccb_h.status = CAM_REQ_CMP; } else { u_int targ_tinfo; cts->flags = 0; if ((adw_lram_read_16(adw, ADW_MC_DISC_ENABLE) & target_mask) != 0) cts->flags |= CCB_TRANS_DISC_ENB; if ((adw->tagenb & target_mask) != 0) cts->flags |= CCB_TRANS_TAG_ENB; targ_tinfo = adw_lram_read_16(adw, ADW_MC_DEVICE_HSHK_CFG_TABLE + (2 * ccb->ccb_h.target_id)); if ((targ_tinfo & ADW_HSHK_CFG_WIDE_XFR) != 0) cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; else cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; cts->sync_period = ADW_HSHK_CFG_PERIOD_FACTOR(targ_tinfo); cts->sync_offset = targ_tinfo & ADW_HSHK_CFG_OFFSET; if (cts->sync_period == 0) cts->sync_offset = 0; if (cts->sync_offset == 0) cts->sync_period = 0; } cts->valid = CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_CALC_GEOMETRY: { struct ccb_calc_geometry *ccg; u_int32_t size_mb; u_int32_t secs_per_cylinder; int extended; /* * XXX Use Adaptec translation until I find out how to * get this information from the card. */ ccg = &ccb->ccg; size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); extended = 1; if (size_mb > 1024 && extended) { ccg->heads = 255; ccg->secs_per_track = 63; } else { ccg->heads = 64; ccg->secs_per_track = 32; } secs_per_cylinder = ccg->heads * ccg->secs_per_track; ccg->cylinders = ccg->volume_size / secs_per_cylinder; ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_RESET_BUS: /* Reset the specified SCSI bus */ { adw_idle_cmd_status_t status; adw_idle_cmd_send(adw, ADW_IDLE_CMD_SCSI_RESET, /*param*/0); status = adw_idle_cmd_wait(adw); if (status == ADW_IDLE_CMD_SUCCESS) { ccb->ccb_h.status = CAM_REQ_CMP; if (bootverbose) { xpt_print_path(adw->path); printf("Bus Reset Delivered\n"); } } else ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); break; } case XPT_TERM_IO: /* Terminate the I/O process */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; case XPT_PATH_INQ: /* Path routing inquiry */ { struct ccb_pathinq *cpi = &ccb->cpi; cpi->version_num = 1; cpi->hba_inquiry = PI_WIDE_16|PI_SDTR_ABLE|PI_TAG_ABLE; cpi->target_sprt = 0; cpi->hba_misc = 0; cpi->hba_eng_cnt = 0; cpi->max_target = ADW_MAX_TID; cpi->max_lun = ADW_MAX_LUN; cpi->initiator_id = adw->initiator_id; cpi->bus_id = cam_sim_bus(sim); cpi->base_transfer_speed = 3300; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "AdvanSys", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; } default: ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; }}static voidadw_poll(struct cam_sim *sim){ adw_intr(cam_sim_softc(sim));}static voidadw_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg){}struct adw_softc *adw_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh){ struct adw_softc *adw; int i; /* * Allocate a storage area for us */ adw = malloc(sizeof(struct adw_softc), M_DEVBUF, M_NOWAIT); if (adw == NULL) { printf("adw%d: cannot malloc!\n", unit); return NULL; } bzero(adw, sizeof(struct adw_softc)); LIST_INIT(&adw->pending_ccbs); SLIST_INIT(&adw->sg_maps); adw->unit = unit; adw->tag = tag; adw->bsh = bsh; i = adw->unit / 10; adw->name = malloc(sizeof("adw") + i + 1, M_DEVBUF, M_NOWAIT); if (adw->name == NULL) { printf("adw%d: cannot malloc name!\n", unit); free(adw, M_DEVBUF); return NULL; } sprintf(adw->name, "adw%d", adw->unit); return(adw);}voidadw_free(struct adw_softc *adw){ switch (adw->init_level) { case 6: { struct sg_map_node *sg_map; while ((sg_map = SLIST_FIRST(&adw->sg_maps)) != NULL) { SLIST_REMOVE_HEAD(&adw->sg_maps, links); bus_dmamap_unload(adw->sg_dmat, sg_map->sg_dmamap); bus_dmamem_free(adw->sg_dmat, sg_map->sg_vaddr, sg_map->sg_dmamap); free(sg_map, M_DEVBUF); } bus_dma_tag_destroy(adw->sg_dmat); } case 5: bus_dmamap_unload(adw->acb_dmat, adw->acb_dmamap); case 4: bus_dmamem_free(adw->acb_dmat, adw->acbs, adw->acb_dmamap); bus_dmamap_destroy(adw->acb_dmat, adw->acb_dmamap); case 3: bus_dma_tag_destroy(adw->acb_dmat); case 2: bus_dma_tag_destroy(adw->buffer_dmat); case 1: bus_dma_tag_destroy(adw->parent_dmat); case 0: break; } free(adw->name, M_DEVBUF); free(adw, M_DEVBUF);}intadw_init(struct adw_softc *adw){ struct adw_eeprom eep_config; u_int16_t checksum; u_int16_t scsicfg1; adw_reset_chip(adw); checksum = adw_eeprom_read(adw, &eep_config); bcopy(eep_config.serial_number, adw->serial_number, sizeof(adw->serial_number)); if (checksum != eep_config.checksum) { u_int16_t serial_number[3]; printf("%s: EEPROM checksum failed. Restoring Defaults\n", adw_name(adw)); /* * Restore the default EEPROM settings. * Assume the 6 byte board serial number that was read * from EEPROM is correct even if the EEPROM checksum * failed. */ bcopy(&adw_default_eeprom, &eep_config, sizeof(eep_config)); bcopy(adw->serial_number, eep_config.serial_number, sizeof(serial_number));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -