2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
16 #include <sys/types.h>
17 #include <sys/select.h>
19 #include <aros/debug.h>
28 #include <proto/exec.h>
29 #include <proto/oop.h>
33 #include "ahci_intern.h"
37 #define kprintf(fmt, args...) device_printf(NULL, fmt ,##args)
40 #define __packed __attribute__((__packed__))
42 #error Define __packed appropriately for your compiler!
45 typedef uint8_t u_int8_t
;
46 typedef uint16_t u_int16_t
;
47 typedef uint32_t u_int32_t
;
48 typedef uint64_t u_int64_t
;
49 typedef unsigned int u_int
;
51 #define le16toh(x) AROS_LE2WORD(x)
52 #define le32toh(x) AROS_LE2LONG(x)
53 #define htole32(x) AROS_LONG2LE(x)
54 #define htole16(x) AROS_WORD2LE(x)
56 #define PAGE_SIZE 4096
59 struct MinNode dev_Node
;
60 OOP_Object
*dev_Object
;
61 struct AHCIBase
*dev_AHCIBase
;
62 struct ahci_softc
*dev_softc
;
68 #define KKASSERT(expr) ASSERT(expr)
70 int kvsnrprintf(char *str
, size_t size
, int radix
, const char *format
, va_list ap
);
71 int kvsnprintf(char *str
, size_t size
, const char *format
, va_list ap
);
72 int ksnprintf(char *buff
, size_t len
, const char *fmt
, ...);
73 int kvcprintf(char const *fmt
, void (*func
)(int, void*), void *arg
, int radix
, va_list ap
);
75 static inline void bug_c(int c
, void *info
)
80 static inline int device_printf(device_t dev
, const char *fmt
, ...)
85 err
= kvcprintf(fmt
, bug_c
, NULL
, 10, args
);
91 #define panic(fmt, args...) do { Forbid(); device_printf(NULL, fmt ,##args); Disable(); for (;;); } while (0);
93 static inline void *kmalloc(size_t size
, unsigned where
, unsigned flags
)
95 return AllocVec(size
, flags
);
98 static inline void kfree(void *ptr
, unsigned where
)
103 static inline void crit_enter(void)
108 static inline void crit_exit(void)
113 typedef struct Task
*thread_t
;
115 static inline int kthread_create(void (*func
)(void *), void *arg
, thread_t
*tdp
, const char *fmt
, ...)
121 kvsnprintf(name
, sizeof(name
), fmt
, args
);
124 name
[sizeof(name
)-1] = 0;
126 *tdp
= NewCreateTask(TASKTAG_NAME
, name
,
132 return (*tdp
== NULL
) ? ENOMEM
: 0;
136 typedef u_int16_t pci_vendor_id_t
;
137 typedef u_int16_t pci_product_id_t
;
138 typedef u_int32_t pcireg_t
;
140 static inline u_int32_t
pci_read_config(device_t dev
, int reg
, int width
)
143 struct AHCIBase
*AHCIBase
= dev
->dev_AHCIBase
;
144 OOP_MethodID HiddPCIDeviceMethodBase
= AHCIBase
->ahci_HiddPCIDeviceMethodBase
;
145 struct pHidd_PCIDevice_ReadConfigByte cb
;
146 struct pHidd_PCIDevice_ReadConfigWord cw
;
147 struct pHidd_PCIDevice_ReadConfigLong cl
;
148 OOP_Object
*Device
= dev
->dev_Object
;
152 cb
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigByte
;
154 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cb
);
158 cw
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigWord
;
160 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cw
);
164 cl
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_ReadConfigLong
;
166 val
= (u_int32_t
)OOP_DoMethod(Device
, (OOP_Msg
)&cl
);
173 static inline void pci_write_config(device_t dev
, int reg
, u_int32_t val
, int width
)
175 struct AHCIBase
*AHCIBase
= dev
->dev_AHCIBase
;
176 OOP_MethodID HiddPCIDeviceMethodBase
= AHCIBase
->ahci_HiddPCIDeviceMethodBase
;
177 struct pHidd_PCIDevice_WriteConfigByte cb
;
178 struct pHidd_PCIDevice_WriteConfigWord cw
;
179 struct pHidd_PCIDevice_WriteConfigLong cl
;
180 OOP_Object
*Device
= dev
->dev_Object
;
184 cb
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigByte
;
187 OOP_DoMethod(Device
, (OOP_Msg
)&cb
);
191 cw
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigWord
;
193 cw
.val
= val
& 0xffff;
194 OOP_DoMethod(Device
, (OOP_Msg
)&cw
);
198 cl
.mID
= HiddPCIDeviceMethodBase
+ moHidd_PCIDevice_WriteConfigLong
;
201 OOP_DoMethod(Device
, (OOP_Msg
)&cl
);
207 static inline u_int16_t
pci_get_vendor(device_t dev
)
209 return (u_int16_t
)pci_read_config(dev
, PCIR_VENDOR
, 2);
212 static inline u_int16_t
pci_get_device(device_t dev
)
214 return (u_int16_t
)pci_read_config(dev
, PCIR_DEVICE
, 2);
217 static inline u_int8_t
pci_get_class(device_t dev
)
219 return (u_int8_t
)pci_read_config(dev
, PCIR_CLASS
, 1);
222 static inline u_int8_t
pci_get_subclass(device_t dev
)
224 return (u_int8_t
)pci_read_config(dev
, PCIR_SUBCLASS
, 1);
228 typedef IPTR bus_size_t
;
229 typedef IPTR bus_addr_t
;
236 typedef struct bus_dma_tag
*bus_dma_tag_t
;
238 #define BUS_DMA_MAX_SLABS 16
239 #define BUS_DMA_MAX_SEGMENTS 1024
241 typedef IPTR bus_space_tag_t
;
242 typedef APTR bus_dmamap_t
;
243 typedef IPTR bus_space_handle_t
;
244 typedef int bus_dma_filter_t(void *arg
, bus_addr_t paddr
);
246 #define BUS_SPACE_MAXADDR ~0
247 #define BUS_SPACE_MAXADDR_32BIT ((ULONG)~0)
249 int bus_dma_tag_create(bus_dma_tag_t parent
, bus_size_t alignment
, bus_size_t boundary
, bus_addr_t lowaddr
, bus_addr_t highaddr
, bus_dma_filter_t
*filter
, void *filterarg
, bus_size_t maxsize
, int nsegments
, bus_size_t maxsegsz
, int flags
, bus_dma_tag_t
*dmat
);
251 int bus_dma_tag_destroy(bus_dma_tag_t tag
);
253 #define BUS_DMA_ALLOCNOW 0
254 #define BUS_DMA_ZERO MEMF_CLEAR
256 int bus_dmamem_alloc(bus_dma_tag_t tag
, void **vaddr
, unsigned flags
, bus_dmamap_t
*map
);
258 bus_size_t
bus_dma_tag_getmaxsize(bus_dma_tag_t tag
);
260 void bus_dmamem_free(bus_dma_tag_t tag
, void *vaddr
, bus_dmamap_t map
);
262 int bus_dmamap_create(bus_dma_tag_t tag
, unsigned flags
, bus_dmamap_t
*map
);
264 void bus_dmamap_destroy(bus_dma_tag_t tag
, bus_dmamap_t map
);
266 typedef void bus_dmamap_callback_t(void *info
, bus_dma_segment_t
*segs
, int nsegs
, int error
);
268 #define BUS_DMA_NOWAIT 0
269 #define BUS_DMA_WAITOK 0
271 int bus_dmamap_load(bus_dma_tag_t tag
, bus_dmamap_t map
, void *data
, size_t len
, bus_dmamap_callback_t
*callback
, void *info
, unsigned flags
);
273 #define BUS_DMASYNC_PREREAD 0
274 #define BUS_DMASYNC_PREWRITE DMA_ReadFromRAM
275 #define BUS_DMASYNC_POSTREAD (1 << 31)
276 #define BUS_DMASYNC_POSTWRITE (1 << 31) | DMA_ReadFromRAM
278 void bus_dmamap_sync(bus_dma_tag_t tag
, bus_dmamap_t map
, unsigned flags
);
280 void bus_dmamap_unload(bus_dma_tag_t tag
, bus_dmamap_t map
);
282 /* Generic bus operations */
283 enum bus_resource_t
{
288 #define AHCI_IRQ_RID 0
291 bus_space_tag_t res_tag
;
292 bus_space_handle_t res_handle
;
296 #define RF_SHAREABLE (1 << 0)
297 #define RF_ACTIVE (1 << 1)
299 struct resource
*bus_alloc_resource_any(device_t dev
, enum bus_resource_t type
, int *rid
, u_int flags
);
301 int bus_release_resource(device_t dev
, enum bus_resource_t type
, int rid
, struct resource
*res
);
303 static inline bus_space_tag_t
rman_get_bustag(struct resource
*r
)
308 static inline bus_space_handle_t
rman_get_bushandle(struct resource
*r
)
310 return r
->res_handle
;
314 typedef void driver_intr_t(void *arg
);
316 #define INTR_MPSAFE 0
318 int bus_setup_intr(device_t dev
, struct resource
*r
, int flags
, driver_intr_t handler
, void *arg
, void **cookiep
, void *serializer
);
320 int bus_teardown_intr(device_t dev
, struct resource
*r
, void *cookie
);
324 static inline int bus_space_subregion(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, size_t size
, bus_space_handle_t
*result
)
326 *result
= ioh
+ offset
;
330 #define BUS_SPACE_BARRIER_READ 0
331 #define BUS_SPACE_BARRIER_WRITE 0
333 static inline void bus_space_barrier(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, size_t size
, unsigned flags
)
335 /* FIXME: Sync bus area */
338 static inline u_int32_t
bus_space_read_4(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
)
340 return *(u_int32_t
*)(ioh
+ offset
);
343 static inline void bus_space_write_4(bus_space_tag_t iot
, bus_space_handle_t ioh
, unsigned offset
, u_int32_t val
)
345 *(u_int32_t
*)(ioh
+ offset
) = val
;
349 /* Generic device info */
350 static inline void *device_get_softc(device_t dev
)
352 return dev
->dev_softc
;
355 /* Lock management */
358 struct SignalSemaphore sem
;
362 static inline void lockinit(struct lock
*lock
, const char *name
, unsigned flags
, unsigned count
)
365 InitSemaphore(&lock
->sem
);
368 static inline void lockuninit(struct lock
*lock
)
373 #define LK_RELEASE (1 << 0)
374 #define LK_EXCLUSIVE (1 << 1)
375 #define LK_CANRECURSE (1 << 2)
376 #define LK_NOWAIT (1 << 3)
378 static inline int lockmgr(struct lock
*lock
, int flags
)
382 flags
&= (LK_EXCLUSIVE
| LK_NOWAIT
| LK_RELEASE
);
385 ObtainSemaphoreShared(&lock
->sem
);
387 case LK_EXCLUSIVE
| LK_NOWAIT
:
388 err
= (AttemptSemaphore(&lock
->sem
) == FALSE
) ? 1 : 0;
391 ObtainSemaphore(&lock
->sem
);
394 ReleaseSemaphore(&lock
->sem
);
402 #define atomic_clear_int(ptr, val) AROS_ATOMIC_AND(*(ptr), ~(val))
403 #define atomic_set_int(ptr, val) AROS_ATOMIC_OR(*(ptr), (val))
407 static const int hz
= (1000000 / 2); /* UNIT_MICROHZ frequency */
409 typedef void timeout_t (void *);
412 struct Task
*co_Task
;
415 void callout_init_mp(struct callout
*c
);
417 void callout_init(struct callout
*c
);
419 void callout_stop(struct callout
*c
);
421 void callout_stop_sync(struct callout
*c
);
423 int callout_reset(struct callout
*c
, unsigned int ticks
, void (*func
)(void *), void *arg
);
425 struct sysctl_ctx_list
{};
427 /* BSD style TailQs */
428 #define TAILQ_HEAD(sname,type) struct sname { struct type *tqh_first; struct type **tqh_last; }
429 #define TAILQ_ENTRY(type) struct { struct type *tqe_next; struct type **tqe_prev; }
430 #define TAILQ_FIRST(head) ((head)->tqh_first)
431 #define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == NULL)
432 #define TAILQ_INIT(head) do { \
433 (head)->tqh_first = NULL; \
434 (head)->tqh_last = &(head)->tqh_first; \
436 #define TAILQ_NEXT(elm,field) ((elm)->field.tqe_next)
437 #define TAILQ_REMOVE(head,elm,field) do { \
438 if ((elm)->field.tqe_next) \
439 (elm)->field.tqe_next->field.tqe_prev = (elm)->field.tqe_prev; \
441 (head)->tqh_last = (elm)->field.tqe_prev; \
442 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
444 #define TAILQ_INSERT_TAIL(head,elm,field) do { \
445 (elm)->field.tqe_next = NULL; \
446 (elm)->field.tqe_prev = (head)->tqh_last; \
447 *(head)->tqh_last = (elm); \
448 (head)->tqh_last = &(elm)->field.tqe_next; \
450 #define TAILQ_FOREACH(elm,head,field) \
451 for ((elm) = ((head)->tqh_first); \
452 (elm) != NULL; (elm)=(elm)->field.tqe_next)
454 #define device_get_name(dev) "ahci.device "
455 #define device_get_unit(dev) ((dev)->dev_HostID)
461 #define M_ZERO MEMF_CLEAR
463 static const int bootverbose
= 0;
466 static inline int ffs(unsigned int bits
)
470 for (i
= 0; i
< 32; i
++, bits
>>= 1)
478 void ahci_ata_io_complete(struct ata_xfer
*xa
);
480 #endif /* AHCI_AROS_H */