📄 nsp_cs.c
字号:
{ struct Scsi_Host *host; /* registered host structure */ nsp_hw_data *data; nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));#else host = scsi_register(sht, sizeof(nsp_hw_data));#endif if (host == NULL) { nsp_dbg(NSP_DEBUG_INIT, "host failed"); return NULL; } /* Copy global variable to driver specific area */ data = (nsp_hw_data *)host->hostdata; *data = nsp_data_base; data->ScsiInfo->host = host;#ifdef NSP_DEBUG data->CmdId = 0;#endif nsp_dbg(NSP_DEBUG_INIT, "irq base=0x%p,%d data=0x%p,%d", &nsp_data_base, (&nsp_data_base)->IrqNumber, data, data->IrqNumber); host->unique_id = data->BaseAddress; host->io_port = data->BaseAddress; host->n_io_port = data->NumAddress; host->irq = data->IrqNumber; host->base = data->MmioAddress; spin_lock_init(&(data->Lock)); snprintf(data->nspinfo, sizeof(data->nspinfo), "NinjaSCSI-3/32Bi Driver $Revision: 1.25 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d", host->io_port, host->io_port + host->n_io_port - 1, host->base, host->irq); sht->name = data->nspinfo; nsp_dbg(NSP_DEBUG_INIT, "end"); return host; /* detect done. */}#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))/*----------------------------------------*//* Compatibility functions for 2.4 kernel *//*----------------------------------------*/static int nsp_detect_old(Scsi_Host_Template *sht){ if (nsp_detect(sht) == NULL) { return 0; } else { return 1; /* detects 1 Ninja host card */ }}static int nsp_release_old(struct Scsi_Host *shpnt){ //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata; /* PCMCIA Card Service dose same things below. */ /* So we do nothing. */ //if (shpnt->irq) { // free_irq(shpnt->irq, data->ScsiInfo); //} //if (shpnt->io_port) { // release_region(shpnt->io_port, shpnt->n_io_port); //} return 0;}#endif/*----------------------------------------------------------------*//* return info string *//*----------------------------------------------------------------*/static const char *nsp_info(struct Scsi_Host *shpnt){ nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata; return data->nspinfo;}#undef SPRINTF#define SPRINTF(args...) \ do { \ if(length > (pos - buffer)) { \ pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \ nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\ } \ } while(0)/* Shows Ninja host card information for user. */static intnsp_proc_info(#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host,#endif char *buffer, char **start, off_t offset, int length,#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) int hostno,#endif int inout){ int id; char *pos = buffer; int thislength; int speed; unsigned long flags; nsp_hw_data *data;#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host;#else int hostno;#endif if (inout) { return -EINVAL; }#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) hostno = host->host_no;#else /* search this HBA host */ host = scsi_host_hn_get(hostno); if (host == NULL) { return -ESRCH; }#endif data = (nsp_hw_data *)host->hostdata; SPRINTF("NinjaSCSI status\n\n"); SPRINTF("Driver version: $Revision: 1.25 $\n"); SPRINTF("SCSI host No.: %d\n", hostno); SPRINTF("IRQ: %d\n", host->irq); SPRINTF("IO: 0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1); SPRINTF("MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1); SPRINTF("sg_tablesize: %d\n", host->sg_tablesize); SPRINTF("burst transfer mode: "); switch (nsp_burst_mode) { case BURST_IO8: SPRINTF("io8"); break; case BURST_IO32: SPRINTF("io32"); break; case BURST_MEM32: SPRINTF("mem32"); break; default: SPRINTF("???"); break; } SPRINTF("\n"); SPRINTF("Chip ID: %d\n", data->ChipRev >> 4); SPRINTF("Chip revision: %d\n", data->ChipRev & 0x0f); spin_lock_irqsave(&(data->Lock), flags); SPRINTF("CurrentSC: 0x%p\n\n", data->CurrentSC); spin_unlock_irqrestore(&(data->Lock), flags); SPRINTF("SDTR status\n"); for(id = 0; id < NUMBER(data->Sync); id++) { SPRINTF("id %d: ", id); if (id == host->this_id) { SPRINTF("----- NinjaSCSI-3 host adapter\n"); continue; } switch(data->Sync[id].SyncNegotiation) { case SYNC_OK: SPRINTF(" sync"); break; case SYNC_NG: SPRINTF("async"); break; case SYNC_NOT_YET: SPRINTF(" none"); break; default: SPRINTF("?????"); break; } if (data->Sync[id].SyncPeriod != 0) { speed = 1000000 / (data->Sync[id].SyncPeriod * 4); SPRINTF(" transfer %d.%dMB/s, offset %d", speed / 1000, speed % 1000, data->Sync[id].SyncOffset ); } SPRINTF("\n"); } thislength = pos - (buffer + offset); if(thislength < 0) { *start = 0; return 0; } thislength = MIN(thislength, length); *start = buffer + offset; return thislength;}#undef SPRINTF/*---------------------------------------------------------------*//* error handler *//*---------------------------------------------------------------*//*static int nsp_eh_strategy(struct Scsi_Host *Shost){ return FAILED;}*//*static int nsp_eh_abort(Scsi_Cmnd *SCpnt){ nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt); return nsp_eh_bus_reset(SCpnt);}*//*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt){ nsp_dbg(NSP_DEBUG_BUSRESET, "%s: SCpnt=0x%p", SCpnt); return FAILED;}*//* Do bus reset. This function uses in low-level initialize functions. */static int nsp_bus_reset(nsp_hw_data *data){ unsigned int base = data->BaseAddress; int i; nsp_msg(KERN_WARNING, "Bus reset"); nsp_write(base, IRQCONTROL, IRQCONTROL_ALL_CLEAR_AND_MASK); nsp_index_write(base, SCSIBUSCTRL, SCSI_RST); mdelay(100); /* 100ms */ nsp_index_write(base, SCSIBUSCTRL, 0); for(i = 0; i < 5; i++) { nsp_index_read(base, IRQPHASESENCE); /* dummy read */ } nsphw_init_sync(data); nsp_write(base, IRQCONTROL, IRQCONTROL_ALL_CLEAR); if (data->CurrentSC != NULL) { nsp_msg(KERN_WARNING, "clean up current scsi command."); data->CurrentSC->result = DID_ERROR << 16; nsp_scsi_done(data->CurrentSC); } return SUCCESS;}/* Do bus reset. This function uses in high-level SCSI driver. */static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt){ nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt); return nsp_bus_reset(data);}/* Initialise Ninja host adapter. */static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt){ nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; nsp_dbg(NSP_DEBUG_BUSRESET, "in"); nsp_msg(KERN_DEBUG, "host reset"); nsphw_init(data); return SUCCESS;}/********************************************************************** PCMCIA functions**********************************************************************//*====================================================================== nsp_cs_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. The dev_link structure is initialized, but we don't actually configure the card at this point -- we wait until we receive a card insertion event.======================================================================*/static dev_link_t *nsp_cs_attach(void){ scsi_info_t *info; client_reg_t client_reg; dev_link_t *link; int ret, i; nsp_hw_data *data = &nsp_data_base; nsp_dbg(NSP_DEBUG_INIT, "in"); /* Create new SCSI device */ info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { return NULL; } memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; data->ScsiInfo = info; nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); /* The io structure describes IO port mapping */ link->io.NumPorts1 = 0x10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 10; /* not used */ /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; if (irq_list[0] == -1) { link->irq.IRQInfo2 = irq_mask; } else { for (i = 0; i < 4; i++) { link->irq.IRQInfo2 |= BIT(irq_list[i]); } } /* Interrupt handler */ link->irq.Handler = &nspintr; link->irq.Instance = info; link->irq.Attributes |= (SA_SHIRQ | SA_SAMPLE_RANDOM); /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; /* Register with Card Services */ link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME ; client_reg.event_handler = &nsp_cs_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; ret = CardServices(RegisterClient, &link->handle, &client_reg); if (ret != CS_SUCCESS) { cs_error(link->handle, RegisterClient, ret); nsp_cs_detach(link); return NULL; } nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); return link;} /* nsp_cs_attach *//*====================================================================== This deletes a driver "instance". The device is de-registered with Card Services. If it has been released, all local data structures are freed. Otherwise, the structures will be freed when the device is released.======================================================================*/static void nsp_cs_detach(dev_link_t *link){ dev_link_t **linkp; nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); /* Locate device structure */ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { if (*linkp == link) { break; } } if (*linkp == NULL) { return; } if (link->state & DEV_CONFIG) { nsp_cs_release(link); } /* Break the link with Card Services */ if (link->handle) { CardServices(DeregisterClient, link->handle); } /* Unlink device structure, free bits */ *linkp = link->next; kfree(link->priv); link->priv = NULL;} /* nsp_cs_detach *//*====================================================================== nsp_cs_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the ethernet device available to the system.======================================================================*/#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed#define CFG_CHECK(fn, args...) \if (CardServices(fn, args) != 0) goto next_entry/*====================================================================*/static void nsp_cs_config(dev_link_t *link){ client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; int last_ret, last_fn; unsigned char tuple_data[64]; config_info_t conf; win_req_t req; memreq_t map; cistpl_cftable_entry_t dflt = { 0 }; struct Scsi_Host *host; nsp_hw_data *data = &nsp_data_base;#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) Scsi_Device *dev; dev_node_t **tail, *node;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -