|
|
Sample Programs from NeXSTEP 3.3
/* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved.
*
* AMD_Regs.h - register defintions for AMD 53C974/79C974 SCSI/PCI chip.
*
* HISTORY
* 21 Oct 94 Doug Mitchell at NeXT
* Created.
*/
#import "ioPorts.h"
#define AMD_PCI_REGISTER_SPACE 0x60
#define AMD_PCI_REGISTER_OFFSET 0 /* FIXME */
/*
* SCSI registers. All are byte-wide.
*/
#define currXfrCntLow 0x00 // r/o
#define startXfrCntLow 0x00 // w/o
#define currXfrCntMid 0x04 // r/o
#define startXfrCntMid 0x04 // w/o
#define scsiFifo 0x08 // r/w
#define scsiCmd 0x0c // r/w
#define scsiStat 0x10 // r/o
#define scsiDestID 0x10 // w/o
#define intrStatus 0x14 // r/o
#define scsiTimeout 0x14 // w/o
#define internState 0x18 // r/o
#define syncPeriod 0x18 // w/o
#define currFifoState 0x1c // r/o
#define syncOffset 0x1c // w/o
#define control1 0x20 // r/w
#define clockFactor 0x24 // w/o
#define control2 0x2c // r/w
#define control3 0x30 // r/w
#define control4 0x34 // r/w
#define currXfrCntHi 0x38 // r/o
#define startXfrCntHi 0x38 // w/o
/*
* Macros for reading and writing SCSI registers.
* These assume the presence of a local or instance variable ioBase.
*/
#define REG_PORT(reg) (ioBase + reg)
#define READ_REG(reg) inb(REG_PORT(reg))
#define WRITE_REG(reg, data) outb(REG_PORT(reg), data)
/*
* Miscellaneous commands.
*/
#define SCMD_NOP 0x00
#define SCMD_CLEAR_FIFO 0x01
#define SCMD_RESET_DEVICE 0x02
#define SCMD_RESET_SCSI 0x03
/*
* idle state commands.
*/
#define SCMD_SELECT 0x41 // select w/o ATN, cdb
#define SCMD_SELECT_ATN 0x42 // select, ATN, 1 msg byte, cdb
#define SCMD_SELECT_ATN_STOP 0x43 // select, ATN, 1 msg byte, stop
#define SCMD_ENABLE_SELECT 0x44 // enable select/reselect
#define SCMD_DISABLE_SELECT 0x45 // disable select/reselect
#define SCMD_SELECT_ATN_3 0x46 // select, ATN, 3 msg bytes, cdb
/*
* initiator mode commands.
*/
#define SCMD_TRANSFER_INFO 0x10
#define SCMD_INIT_CMD_CMPLT 0x11
#define SCMD_MSG_ACCEPTED 0x12
#define SCMD_TRANSFER_PAD 0x18
#define SCMD_SET_ATN 0x1a
#define SCMD_CLR_ATN 0x1b
/*
* OR this with command to enable DMA.
*/
#define SCMD_ENABLEDMA 0x80
/*
* status register (scsiStat)
*/
#define SS_INTERRUPT 0x80 // interrupt pending
#define SS_ILLEGALOP 0x40 // illegal operation
#define SS_PARITYERROR 0x20 // SCSI bus parity error
#define SS_COUNTZERO 0x10 // transfer count == 0
#define SS_PHASEMASK 0x07 // SCSI bus phase mask
/*
* internal state register (internState)
*/
#define INS_SYNC_FULL 0x10 // sync offset buffer full
#define INS_STATE_MASK 0x07
/*
* interrupt status register (intrStatus)
*/
#define IS_SCSIRESET 0x80 // SCSI bus reset detected
#define IS_ILLEGALCMD 0x40 // illegal cmd issued
#define IS_DISCONNECT 0x20 // target disconnected
#define IS_SERVICE_REQ 0x10
#define IS_SUCCESSFUL_OP 0x08
#define IS_RESELECTED 0x04 // reselected as initiator
/*
* FIFO state register (currFifoState)
*/
#define FS_FIFO_LEVEL_MASK 0x1f
/*
* Sync offset register (syncOffset)
* We're not messing with these RAD/RAA bits just yet...
*/
#define SOR_RAD_MASK 0xc0 // req/ack deassertion
#define SOR_RAD_DEFAULT 0x00
#define SOR_RAA_MASK 0x30 // req/ack assertion
#define SOR_RAA_DEFAULT 0x00
/*
* Control register 1 (control1)
*/
#define CR1_EXTEND_TIMING 0x80 // extended timing mode
#define CR1_RESET_INTR_DIS 0x40 // disable SCSI reset interrupt
#define CR1_PERR_ENABLE 0x10 // enable parity error reporting
#define CR1_SCSI_ID 0x07 // SCSI ID bits
/*
* Control register 2 (control2)
*/
#define CR2_ENABLE_FEAT 0x40 // enable extended features
/*
* Control register 3 (control3)
*/
#define CR3_ADDL_ID_CHECK 0x80 // enable additional ID check
#define CR3_FAST_SCSI 0x10 // enable fast SCSI
#define CR3_FAST_CLOCK 0x08 // fast clock
/*
* Control register 4 (control4)
*/
#define CR4_GLITCH_MASK 0xc0 // glitch eater bits
#define CR4_GLITCH_12 0x00 // 12 ns
#define CR4_GLITCH_25 0x80 // 25 ns
#define CR4_GLITCH_35 0x40 // 35 ns
#define CR4_GLITCH_0 0xc0 // 0 ns
#define CR4_REDUCE_PWR 0x20 // reduced power mode
#define CR4_ACTIVE_NEG_MASK 0x0c // active negation control bits
#define CR4_ACTIVE_NEG_DISABLE 0x00 // active negation disabled
#define CR4_ACTIVE_NEG_RA 0x08 // active negation on REQ and ACK
#define CR4_ACTIVE_NEG_ALL 0x04 // active negation on REQ, ACK, data
/*
* DMA registers. All are 32 bits.
*/
#define dmaCommand 0x40 // r/w
#define dmaStartCount 0x44 // r/w
#define dmaStartAddrs 0x48 // r/w
#define dmaWorkByteCount 0x4c // r/o
#define dmaWorkAddrs 0x50 // r/o
#define dmaStatus 0x54 // r/o
#define dmaStartMdlAddrs 0x58 // r/w
#define dmaWorkMdlAddrs 0x5c // r/o
/*
* Macros for reading and writing DMA registers.
* These assume the presence of a local or instance variable ioBase.
*/
#define READ_REGL(reg) inl(REG_PORT(reg))
#define WRITE_REGL(reg, data) outl(REG_PORT(reg), data);
/*
* DMA command register (dmaCommand)
*/
#define DC_DIR 0x80 // direction
#define DC_DIR_READ 0x80 // scsi --> memory
#define DC_DIR_WRITE 0x00 // scsi <-- memory
#define DC_INTR_ENABLE 0x40 // enable DMA interrupts
#define DC_PAGE_INTR_ENABLE 0x20 // enable per-page interrupts
#define DC_MDL 0x10 // enable MDL
#define DC_DIAG 0x04 // diagnostic
#define DC_CMD_MASK 0x03 // command bits
#define DC_CMD_IDLE 0x00
#define DC_CMD_BLAST 0x01
#define DC_CMD_ABORT 0x02
#define DC_CMD_START 0x03
/*
* DMA status register (dmaStatus)
*/
#define DS_BLAST_COMPLETE 0x20 // DMA Blast command complete
#define DS_SCSI_INTR 0x10 // SCSI interrupt pending
#define DS_DMA_COMPLETE 0x08 // DMA transfer complete
#define DS_ABORT 0x04 // DMA transfer aborted
#define DS_DMA_ERROR 0x02 // DMA error occurred
#define DS_POWER_DOWN 0x01 // power down pin state
/*
* Misc. chip constants.
*/
#define AMD_DMA_PAGE_SIZE 0x1000
#define AMD_DMA_PAGE_MASK 0xfff
#define AMD_TRUNC_PAGE(x) ((vm_offset_t)(((vm_offset_t)(x)) & \
~AMD_DMA_PAGE_MASK))
#define AMD_ROUND_PAGE(x) ((vm_offset_t)((((vm_offset_t)(x)) + \
AMD_DMA_PAGE_MASK) & ~AMD_DMA_PAGE_MASK))
/*
* DMA alignment requirements.
*/
#define AMD_READ_START_ALIGN 4
#define AMD_WRITE_START_ALIGN 4
#define AMD_READ_LENGTH_ALIGN 0
#define AMD_WRITE_LENGTH_ALIGN 0
/*
* We are ID 7, by convention.
*/
#define AMD_SCSI_ID 7
/*
* Default clock rate, in MHz, in case it's not in the instance table.
*/
#define AMD_DEFAULT_CLOCK 40
/*
* Clock Conversion factor.
*/
#define AMD_CLOCK_FACTOR(clockRate) ((clockRate + 4) / 5)
/*
* Calculate select timeout register based on clock rate, select timeout,
* and clocking factor.
*
* The offical formula is:
* reg = ((select timeout in s) * (clock rate in hz)) /
* (8192 * clock factor)
*
* Change select timeout to ms and clock rate to MHz, amd multiply
* numerator by 1000...
*
* reg = ((select timeout in ms) * (clock rate in Mhz) * 1000) /
* (8192 * clock factor)
*/
static inline unsigned amdSelectTimeout(
unsigned selto, // ms
unsigned clockRate) // MHz
{
unsigned denom; // for roundup
unsigned factor;
factor = AMD_CLOCK_FACTOR(clockRate);
denom = 8192 * factor;
return (((selto * clockRate * 1000) + denom - 1) / denom);
}
/*
* 79C974 actually times out a bit faster than the official formula says it
* should. SCSI spec says timeout should be 250 ms; let's cut some slack...
*/
#define AMD_SELECT_TO 300
/*
* Sync negotiation constants and inlines.
*/
/*
* Max sync offset of 53C974.
*/
#define AMD_MAX_SYNC_OFFSET 15
/*
* Macros to convert the value in perTargetData.syncXferPeriod to and
* from the value specified in a SDTR message.
*/
#define NS_PERIOD_TO_SDTR(period) (period / 4)
#define SDTR_TO_NS_PERIOD(sdtr) (sdtr * 4)
/*
* Default (and desired) minimum clock periods in ns.
*/
#define MIN_PERIOD_FASTCLK_FASTSCSI 100
#define MIN_PERIOD_NORM 200
/*
* Routine to convert the value in perTargetData.syncXferPeriod to
* the value used in syncPeriod register. The value of syncPeriod
* rounds up to round down the frequency.
*/
static inline unsigned nsPeriodToSyncPeriodReg(
unsigned char nsPeriod, // desired period in ns
unsigned fastSCSI, // value of control3.CR3_FAST_SCSI
unsigned clockRate) // in MHz
{
BOOL fastClock;
unsigned clockPeriod; // in ns
fastClock = (clockRate > 25) ? YES : NO;
clockPeriod = 1000 / clockRate;
if(fastClock && !fastSCSI) {
/*
* reg = (clocks per period) - 1.
*/
return (((nsPeriod + clockPeriod - 1) / clockPeriod) - 1);
}
else {
/*
* reg = clocks per period.
*/
return ((nsPeriod + clockPeriod - 1) / clockPeriod);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.