249 lines
		
	
	
	
		
			7.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			249 lines
		
	
	
	
		
			7.1 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Apple Peripheral System Controller (PSC) | ||
|  |  * | ||
|  |  * The PSC is used on the AV Macs to control IO functions not handled | ||
|  |  * by the VIAs (Ethernet, DSP, SCC, Sound). This includes nine DMA | ||
|  |  * channels. | ||
|  |  * | ||
|  |  * The first seven DMA channels appear to be "one-shot" and are actually | ||
|  |  * sets of two channels; one member is active while the other is being | ||
|  |  * configured, and then you flip the active member and start all over again. | ||
|  |  * The one-shot channels are grouped together and are: | ||
|  |  * | ||
|  |  * 1. SCSI | ||
|  |  * 2. Ethernet Read | ||
|  |  * 3. Ethernet Write | ||
|  |  * 4. Floppy Disk Controller | ||
|  |  * 5. SCC Channel A Receive | ||
|  |  * 6. SCC Channel B Receive | ||
|  |  * 7. SCC Channel A Transmit | ||
|  |  * | ||
|  |  * The remaining two channels are handled somewhat differently. They appear | ||
|  |  * to be closely tied and share one set of registers. They also seem to run | ||
|  |  * continuously, although how you keep the buffer filled in this scenario is | ||
|  |  * not understood as there seems to be only one input and one output buffer | ||
|  |  * pointer. | ||
|  |  * | ||
|  |  * Much of this was extrapolated from what was known about the Ethernet | ||
|  |  * registers and subsequently confirmed using MacsBug (ie by pinging the | ||
|  |  * machine with easy-to-find patterns and looking for them in the DMA | ||
|  |  * buffers, or by sending a file over the serial ports and finding the | ||
|  |  * file in the buffers.) | ||
|  |  * | ||
|  |  * 1999-05-25 (jmt) | ||
|  |  */ | ||
|  | 
 | ||
|  | #define PSC_BASE	(0x50F31000)
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * The IER/IFR registers work like the VIA, except that it has 4 | ||
|  |  * of them each on different interrupt levels, and each register | ||
|  |  * set only seems to handle four interrupts instead of seven. | ||
|  |  * | ||
|  |  * To access a particular set of registers, add 0xn0 to the base | ||
|  |  * where n = 3,4,5 or 6. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define pIFRbase	0x100
 | ||
|  | #define pIERbase	0x104
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * One-shot DMA control registers | ||
|  |  */ | ||
|  | 
 | ||
|  | #define PSC_MYSTERY	0x804
 | ||
|  | 
 | ||
|  | #define PSC_CTL_BASE	0xC00
 | ||
|  | 
 | ||
|  | #define PSC_SCSI_CTL	0xC00
 | ||
|  | #define PSC_ENETRD_CTL  0xC10
 | ||
|  | #define PSC_ENETWR_CTL  0xC20
 | ||
|  | #define PSC_FDC_CTL	0xC30
 | ||
|  | #define PSC_SCCA_CTL	0xC40
 | ||
|  | #define PSC_SCCB_CTL	0xC50
 | ||
|  | #define PSC_SCCATX_CTL	0xC60
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * DMA channels. Add +0x10 for the second channel in the set. | ||
|  |  * You're supposed to use one channel while the other runs and | ||
|  |  * then flip channels and do the whole thing again. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define PSC_ADDR_BASE	0x1000
 | ||
|  | #define PSC_LEN_BASE	0x1004
 | ||
|  | #define PSC_CMD_BASE	0x1008
 | ||
|  | 
 | ||
|  | #define PSC_SET0	0x00
 | ||
|  | #define PSC_SET1	0x10
 | ||
|  | 
 | ||
|  | #define PSC_SCSI_ADDR	0x1000	/* confirmed */
 | ||
|  | #define PSC_SCSI_LEN	0x1004	/* confirmed */
 | ||
|  | #define PSC_SCSI_CMD	0x1008	/* confirmed */
 | ||
|  | #define PSC_ENETRD_ADDR 0x1020	/* confirmed */
 | ||
|  | #define PSC_ENETRD_LEN  0x1024	/* confirmed */
 | ||
|  | #define PSC_ENETRD_CMD  0x1028	/* confirmed */
 | ||
|  | #define PSC_ENETWR_ADDR 0x1040	/* confirmed */
 | ||
|  | #define PSC_ENETWR_LEN  0x1044	/* confirmed */
 | ||
|  | #define PSC_ENETWR_CMD  0x1048	/* confirmed */
 | ||
|  | #define PSC_FDC_ADDR	0x1060	/* strongly suspected */
 | ||
|  | #define PSC_FDC_LEN	0x1064	/* strongly suspected */
 | ||
|  | #define PSC_FDC_CMD	0x1068	/* strongly suspected */
 | ||
|  | #define PSC_SCCA_ADDR	0x1080	/* confirmed */
 | ||
|  | #define PSC_SCCA_LEN	0x1084	/* confirmed */
 | ||
|  | #define PSC_SCCA_CMD	0x1088	/* confirmed */
 | ||
|  | #define PSC_SCCB_ADDR	0x10A0	/* confirmed */
 | ||
|  | #define PSC_SCCB_LEN	0x10A4	/* confirmed */
 | ||
|  | #define PSC_SCCB_CMD	0x10A8	/* confirmed */
 | ||
|  | #define PSC_SCCATX_ADDR	0x10C0	/* confirmed */
 | ||
|  | #define PSC_SCCATX_LEN	0x10C4	/* confirmed */
 | ||
|  | #define PSC_SCCATX_CMD	0x10C8	/* confirmed */
 | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Free-running DMA registers. The only part known for sure are the bits in | ||
|  |  * the control register, the buffer addresses and the buffer length. Everything | ||
|  |  * else is anybody's guess. | ||
|  |  * | ||
|  |  * These registers seem to be mirrored every thirty-two bytes up until offset | ||
|  |  * 0x300. It's safe to assume then that a new set of registers starts there. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define PSC_SND_CTL	0x200	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Sound (Singer?) control register. | ||
|  | 				 * | ||
|  | 				 * bit 0  : ???? | ||
|  | 				 * bit 1  : ???? | ||
|  | 				 * bit 2  : Set to one to enable sound | ||
|  | 				 *          output. Possibly a mute flag. | ||
|  | 				 * bit 3  : ???? | ||
|  | 				 * bit 4  : ???? | ||
|  | 				 * bit 5  : ???? | ||
|  | 				 * bit 6  : Set to one to enable pass-thru | ||
|  | 				 *          audio. In this mode the audio data | ||
|  | 				 *          seems to appear in both the input | ||
|  | 				 *          buffer and the output buffer. | ||
|  | 				 * bit 7  : Set to one to activate the | ||
|  | 				 *          sound input DMA or zero to | ||
|  | 				 *          disable it. | ||
|  | 				 * bit 8  : Set to one to activate the | ||
|  | 				 *          sound output DMA or zero to | ||
|  | 				 *          disable it. | ||
|  | 				 * bit 9  : \ | ||
|  | 				 * bit 11 :  | | ||
|  | 				 *          These two bits control the sample | ||
|  | 				 *          rate. Usually set to binary 10 and | ||
|  | 				 *	    MacOS 8.0 says I'm at 48 KHz. Using | ||
|  | 				 *	    a binary value of 01 makes things | ||
|  | 				 *	    sound about 1/2 speed (24 KHz?) and | ||
|  | 				 *          binary 00 is slower still (22 KHz?) | ||
|  | 				 * | ||
|  | 				 * Setting this to 0x0000 is a good way to | ||
|  | 				 * kill all DMA at boot time so that the | ||
|  | 				 * PSC won't overwrite the kernel image | ||
|  | 				 * with sound data. | ||
|  | 				 */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * 0x0202 - 0x0203 is unused. Writing there | ||
|  |  * seems to clobber the control register. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define PSC_SND_SOURCE	0x204	/*
 | ||
|  | 				 * [ 32-bit ] | ||
|  | 				 * Controls input source and volume: | ||
|  | 				 * | ||
|  | 				 * bits 12-15 : input source volume, 0 - F | ||
|  | 				 * bits 16-19 : unknown, always 0x5 | ||
|  | 				 * bits 20-23 : input source selection: | ||
|  | 				 *                  0x3 = CD Audio | ||
|  | 				 *                  0x4 = External Audio | ||
|  | 				 * | ||
|  | 				 * The volume is definitely not the general | ||
|  | 				 * output volume as it doesn't affect the | ||
|  | 				 * alert sound volume. | ||
|  | 				 */ | ||
|  | #define PSC_SND_STATUS1	0x208	/*
 | ||
|  | 				 * [ 32-bit ] | ||
|  | 				 * Appears to be a read-only status register. | ||
|  | 				 * The usual value is 0x00400002. | ||
|  | 				 */ | ||
|  | #define PSC_SND_HUH3	0x20C	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Unknown 16-bit value, always 0x0000. | ||
|  | 				 */ | ||
|  | #define PSC_SND_BITS2GO	0x20E	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Counts down to zero from some constant | ||
|  | 				 * value. The value appears to be the | ||
|  | 				 * number of _bits_ remaining before the | ||
|  | 				 * buffer is full, which would make sense | ||
|  | 				 * since Apple's docs say the sound DMA | ||
|  | 				 * channels are 1 bit wide. | ||
|  | 				 */ | ||
|  | #define PSC_SND_INADDR	0x210	/*
 | ||
|  | 				 * [ 32-bit ] | ||
|  | 				 * Address of the sound input DMA buffer | ||
|  | 				 */ | ||
|  | #define PSC_SND_OUTADDR	0x214	/*
 | ||
|  | 				 * [ 32-bit ] | ||
|  | 				 * Address of the sound output DMA buffer | ||
|  | 				 */ | ||
|  | #define PSC_SND_LEN	0x218	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Length of both buffers in eight-byte units. | ||
|  | 				 */ | ||
|  | #define PSC_SND_HUH4	0x21A	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Unknown, always 0x0000. | ||
|  | 				 */ | ||
|  | #define PSC_SND_STATUS2	0x21C	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Appears to e a read-only status register. | ||
|  | 				 * The usual value is 0x0200. | ||
|  | 				 */ | ||
|  | #define PSC_SND_HUH5	0x21E	/*
 | ||
|  | 				 * [ 16-bit ] | ||
|  | 				 * Unknown, always 0x0000. | ||
|  | 				 */ | ||
|  | 
 | ||
|  | #ifndef __ASSEMBLY__
 | ||
|  | 
 | ||
|  | extern volatile __u8 *psc; | ||
|  | extern int psc_present; | ||
|  | 
 | ||
|  | /*
 | ||
|  |  *	Access functions | ||
|  |  */ | ||
|  | 
 | ||
|  | static inline void psc_write_byte(int offset, __u8 data) | ||
|  | { | ||
|  | 	*((volatile __u8 *)(psc + offset)) = data; | ||
|  | } | ||
|  | 
 | ||
|  | static inline void psc_write_word(int offset, __u16 data) | ||
|  | { | ||
|  | 	*((volatile __u16 *)(psc + offset)) = data; | ||
|  | } | ||
|  | 
 | ||
|  | static inline void psc_write_long(int offset, __u32 data) | ||
|  | { | ||
|  | 	*((volatile __u32 *)(psc + offset)) = data; | ||
|  | } | ||
|  | 
 | ||
|  | static inline u8 psc_read_byte(int offset) | ||
|  | { | ||
|  | 	return *((volatile __u8 *)(psc + offset)); | ||
|  | } | ||
|  | 
 | ||
|  | static inline u16 psc_read_word(int offset) | ||
|  | { | ||
|  | 	return *((volatile __u16 *)(psc + offset)); | ||
|  | } | ||
|  | 
 | ||
|  | static inline u32 psc_read_long(int offset) | ||
|  | { | ||
|  | 	return *((volatile __u32 *)(psc + offset)); | ||
|  | } | ||
|  | 
 | ||
|  | #endif /* __ASSEMBLY__ */
 |