drivers/scsi/pcmcia/nsp_cs.c

Source file repositories/reference/linux-study-clean/drivers/scsi/pcmcia/nsp_cs.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/pcmcia/nsp_cs.c
Extension
.c
Size
46625 bytes
Lines
1759
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nsp_sync_table {
	unsigned int min_period;
	unsigned int max_period;
	unsigned int chip_period;
	unsigned int ack_width;
};

static struct nsp_sync_table nsp_sync_table_40M[] = {
	{0x0c, 0x0c, 0x1, 0},	/* 20MB	  50ns*/
	{0x19, 0x19, 0x3, 1},	/* 10MB	 100ns*/ 
	{0x1a, 0x25, 0x5, 2},	/* 7.5MB 150ns*/ 
	{0x26, 0x32, 0x7, 3},	/* 5MB	 200ns*/
	{   0,    0,   0, 0},
};

static struct nsp_sync_table nsp_sync_table_20M[] = {
	{0x19, 0x19, 0x1, 0},	/* 10MB	 100ns*/ 
	{0x1a, 0x25, 0x2, 0},	/* 7.5MB 150ns*/ 
	{0x26, 0x32, 0x3, 1},	/* 5MB	 200ns*/
	{   0,    0,   0, 0},
};

/*
 * setup synchronous data transfer mode
 */
static int nsp_analyze_sdtr(struct scsi_cmnd *SCpnt)
{
	unsigned char	       target = scmd_id(SCpnt);
//	unsigned char	       lun    = SCpnt->device->lun;
	nsp_hw_data           *data   = (nsp_hw_data *)SCpnt->device->host->hostdata;
	sync_data	      *sync   = &(data->Sync[target]);
	struct nsp_sync_table *sync_table;
	unsigned int	       period, offset;

	nsp_dbg(NSP_DEBUG_SYNC, "in");

	period = sync->SyncPeriod;
	offset = sync->SyncOffset;

	nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset);

	if ((data->ScsiClockDiv & (BIT(0)|BIT(1))) == CLOCK_20M) {
		sync_table = nsp_sync_table_20M;
	} else {
		sync_table = nsp_sync_table_40M;
	}

	for (; sync_table->max_period != 0; sync_table++) {
		if ( period >= sync_table->min_period &&
		     period <= sync_table->max_period	 ) {
			break;
		}
	}

	if (period != 0 && sync_table->max_period == 0) {
		/*
		 * No proper period/offset found
		 */
		nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset");

		sync->SyncPeriod      = 0;
		sync->SyncOffset      = 0;
		sync->SyncRegister    = 0;
		sync->AckWidth	      = 0;

		return false;
	}

	sync->SyncRegister    = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) |
		                (offset & SYNCREG_OFFSET_MASK);
	sync->AckWidth	      = sync_table->ack_width;

	nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth);

	return true;
}


/*
 * start ninja hardware timer
 */
static void nsp_start_timer(struct scsi_cmnd *SCpnt, int time)
{
	unsigned int base = SCpnt->device->host->io_port;
	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;

	//nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time);
	data->TimerCount = time;
	nsp_index_write(base, TIMERCOUNT, time);
}

Annotation

Implementation Notes