1/*
2 * Copyright 2004-2006, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Lotz <mmlr@mlotz.ch>
7 *		Niels S. Reedijk
8 */
9
10#ifndef UHCI_HARDWARE_H
11#define UHCI_HARDWARE_H
12
13/************************************************************
14 * The Registers                                            *
15 ************************************************************/
16
17// R/W -- Read/Write
18// R/WC -- Read/Write Clear
19// ** -- Only writable with words!
20
21// PCI register
22#define PCI_LEGSUP				0xC0
23#define PCI_LEGSUP_USBPIRQDEN	0x2000
24#define PCI_LEGSUP_CLEAR_SMI	0x8f00
25
26// Registers
27#define UHCI_USBCMD				0x00 	// USB Command - word - R/W
28#define UHCI_USBSTS				0x02	// USB Status - word - R/WC
29#define UHCI_USBINTR			0x04	// USB Interrupt Enable - word - R/W
30#define UHCI_FRNUM				0x06	// Frame number - word - R/W**
31#define UHCI_FRBASEADD			0x08	// Frame List BAse Address - dword - R/W
32#define UHCI_SOFMOD				0x0c	// Start of Frame Modify - byte - R/W
33#define UHCI_PORTSC1			0x10	// Port 1 Status/Control - word - R/WC**
34#define UHCI_PORTSC2			0x12	// Port 2 Status/Control - word - R/WC**
35
36// USBCMD
37#define UHCI_USBCMD_RS			0x01	// Run/Stop
38#define UHCI_USBCMD_HCRESET		0x02 	// Host Controller Reset
39#define UHCI_USBCMD_GRESET		0x04 	// Global Reset
40#define UHCI_USBCMD_EGSM		0x08	// Enter Global Suspensd mode
41#define UHCI_USBCMD_FGR			0x10	// Force Global resume
42#define UHCI_USBCMD_SWDBG		0x20	// Software Debug
43#define UHCI_USBCMD_CF			0x40	// Configure Flag
44#define UHCI_USBCMD_MAXP		0x80	// Max packet
45
46//USBSTS
47#define UHCI_USBSTS_USBINT		0x01	// USB interrupt
48#define UHCI_USBSTS_ERRINT		0x02	// USB error interrupt
49#define UHCI_USBSTS_RESDET		0x04	// Resume Detect
50#define UHCI_USBSTS_HOSTERR		0x08	// Host System Error
51#define UHCI_USBSTS_HCPRERR		0x10	// Host Controller Process error
52#define UHCI_USBSTS_HCHALT		0x20	// HCHalted
53
54//USBINTR
55#define UHCI_USBINTR_CRC		0x01	// Timeout/ CRC interrupt enable
56#define UHCI_USBINTR_RESUME		0x02	// Resume interrupt enable
57#define UHCI_USBINTR_IOC		0x04	// Interrupt on complete enable
58#define UHCI_USBINTR_SHORT		0x08	// Short packet interrupt enable
59
60//PORTSC
61#define UHCI_PORTSC_CURSTAT		0x0001	// Current connect status
62#define UHCI_PORTSC_STATCHA		0x0002	// Current connect status change
63#define UHCI_PORTSC_ENABLED		0x0004	// Port enabled/disabled
64#define UHCI_PORTSC_ENABCHA		0x0008	// Change in enabled/disabled
65#define UHCI_PORTSC_LINE_0		0x0010	// The status of D+
66#define UHCI_PORTSC_LINE_1		0x0020	// The status of D-
67#define UHCI_PORTSC_RESUME		0x0040	// Something with the suspend state ???
68#define UHCI_PORTSC_LOWSPEED	0x0100	// Low speed device attached?
69#define UHCI_PORTSC_RESET		0x0200	// Port is in reset
70#define UHCI_PORTSC_SUSPEND		0x1000	// Set port in suspend state
71
72#define UHCI_PORTSC_DATAMASK	0x13f5	// Mask that excludes the change bits
73
74/************************************************************
75 * Hardware structs                                         *
76 ************************************************************/
77
78// Framelist flags
79#define FRAMELIST_TERMINATE    0x1
80#define FRAMELIST_NEXT_IS_QH   0x2
81
82// Number of frames
83#define NUMBER_OF_FRAMES		1024
84#define MAX_AVAILABLE_BANDWIDTH	900	// Microseconds
85
86// Represents a Transfer Descriptor (TD)
87typedef struct
88{
89	// Hardware part
90	uint32	link_phy;		// Link to the next TD/QH
91	uint32	status;			// Status field
92	uint32	token;			// Contains the packet header (where it needs to be sent)
93	uint32	buffer_phy;		// A pointer to the buffer with the actual packet
94	// Software part
95	uint32	this_phy;		// A physical pointer to this address
96	void	*link_log;		// Pointer to the next logical TD/QT
97	void	*buffer_log;	// Pointer to the logical buffer
98	size_t	buffer_size;	// Size of the buffer
99} uhci_td;
100
101#define	TD_NEXT_IS_QH				0x02
102
103// Control and Status
104#define TD_CONTROL_SPD				(1 << 29)
105#define TD_CONTROL_3_ERRORS			(3 << 27)
106#define TD_CONTROL_LOWSPEED			(1 << 26)
107#define TD_CONTROL_ISOCHRONOUS		(1 << 25)
108#define TD_CONTROL_IOC				(1 << 24)
109
110#define TD_STATUS_ACTIVE			(1 << 23)
111#define TD_STATUS_ERROR_STALLED		(1 << 22)
112#define TD_STATUS_ERROR_BUFFER		(1 << 21)
113#define TD_STATUS_ERROR_BABBLE		(1 << 20)
114#define TD_STATUS_ERROR_NAK			(1 << 19)
115#define TD_STATUS_ERROR_CRC			(1 << 18)
116#define TD_STATUS_ERROR_TIMEOUT		(1 << 18)
117#define TD_STATUS_ERROR_BITSTUFF	(1 << 17)
118
119#define TD_STATUS_ACTLEN_MASK		0x07ff
120#define TD_STATUS_ACTLEN_NULL		0x07ff
121
122// Token
123#define TD_TOKEN_MAXLEN_SHIFT		21
124#define TD_TOKEN_NULL_DATA			(0x07ff << TD_TOKEN_MAXLEN_SHIFT)
125#define TD_TOKEN_DATA_TOGGLE_SHIFT	19
126#define TD_TOKEN_DATA1				(1 << TD_TOKEN_DATA_TOGGLE_SHIFT)
127
128#define TD_TOKEN_SETUP				0x2d
129#define TD_TOKEN_IN					0x69
130#define TD_TOKEN_OUT				0xe1
131
132#define TD_TOKEN_ENDPTADDR_SHIFT	15
133#define TD_TOKEN_DEVADDR_SHIFT		8
134
135#define TD_DEPTH_FIRST				0x04
136#define TD_TERMINATE				0x01
137#define TD_ERROR_MASK				0x440000
138#define TD_ERROR_COUNT_SHIFT		27
139#define TD_ERROR_COUNT_MASK			0x03
140#define TD_LINK_MASK				0xfffffff0
141
142
143static inline size_t
144uhci_td_maximum_length(uhci_td *descriptor)
145{
146	size_t length = (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT) + 1;
147	if (length == TD_STATUS_ACTLEN_NULL + 1)
148		return 0;
149	return length;
150}
151
152
153static inline size_t
154uhci_td_actual_length(uhci_td *descriptor)
155{
156	size_t length = (descriptor->status & TD_STATUS_ACTLEN_MASK) + 1;
157	if (length == TD_STATUS_ACTLEN_NULL + 1)
158		return 0;
159	return length;
160}
161
162
163// Represents a Queue Head (QH)
164typedef struct
165{
166	// Hardware part
167	uint32	link_phy;		// Link to the next TD/QH
168	uint32	element_phy;	// Pointer to the first element in the queue
169	// Software part
170	uint32	this_phy;		// The physical pointer to this address
171	void	*link_log;		// Pointer to the next logical TD/QH
172} uhci_qh;
173
174#define QH_TERMINATE			0x01
175#define QH_NEXT_IS_QH  			0x02
176#define QH_LINK_MASK			0xfffffff0
177
178#endif
179