hptrr_os_bsd.c revision 176031
190075Sobrien/*
2132718Skan * Copyright (c) HighPoint Technologies, Inc.
390075Sobrien * All rights reserved.
490075Sobrien *
590075Sobrien * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
790075Sobrien * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
990075Sobrien *    notice, this list of conditions and the following disclaimer.
1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
11132718Skan *    notice, this list of conditions and the following disclaimer in the
12132718Skan *    documentation and/or other materials provided with the distribution.
13132718Skan *
14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17132718Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2090075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2190075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2490075Sobrien * SUCH DAMAGE.
2590075Sobrien *
2690075Sobrien * $FreeBSD: head/sys/dev/hptrr/hptrr_os_bsd.c 176031 2008-02-06 05:33:17Z scottl $
27169689Skan */
28169689Skan#include <dev/hptrr/hptrr_config.h>
2990075Sobrien/* $Id: os_bsd.c,v 1.11 2005/06/03 14:06:38 kdh Exp $
3090075Sobrien *
3190075Sobrien * HighPoint RAID Driver for FreeBSD
3290075Sobrien * Copyright (C) 2005 HighPoint Technologies, Inc. All Rights Reserved.
3390075Sobrien */
34132718Skan
35132718Skan#include <dev/hptrr/os_bsd.h>
36132718Skan
3790075Sobrien/* hardware access */
3890075SobrienHPT_U8   os_inb  (void *port) { return inb((unsigned)(HPT_UPTR)port); }
3990075SobrienHPT_U16  os_inw  (void *port) { return inw((unsigned)(HPT_UPTR)port); }
4090075SobrienHPT_U32  os_inl  (void *port) { return inl((unsigned)(HPT_UPTR)port); }
4190075Sobrien
4290075Sobrienvoid os_outb (void *port, HPT_U8 value) { outb((unsigned)(HPT_UPTR)port, (value)); }
4390075Sobrienvoid os_outw (void *port, HPT_U16 value) { outw((unsigned)(HPT_UPTR)port, (value)); }
4490075Sobrienvoid os_outl (void *port, HPT_U32 value) { outl((unsigned)(HPT_UPTR)port, (value)); }
4590075Sobrien
4690075Sobrienvoid os_insw (void *port, HPT_U16 *buffer, HPT_U32 count)
4790075Sobrien{ insw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
4890075Sobrien
4990075Sobrienvoid os_outsw(void *port, HPT_U16 *buffer, HPT_U32 count)
5090075Sobrien{ outsw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
5190075Sobrien
5290075SobrienHPT_U32 __dummy_reg = 0;
5390075Sobrien
5490075Sobrien/* PCI configuration space */
5590075SobrienHPT_U8  os_pci_readb (void *osext, HPT_U8 offset)
5690075Sobrien{
5790075Sobrien    return  pci_read_config(((PHBA)osext)->pcidev, offset, 1);
5890075Sobrien}
5990075Sobrien
6090075SobrienHPT_U16 os_pci_readw (void *osext, HPT_U8 offset)
6190075Sobrien{
6290075Sobrien    return  pci_read_config(((PHBA)osext)->pcidev, offset, 2);
6390075Sobrien}
6490075Sobrien
6590075SobrienHPT_U32 os_pci_readl (void *osext, HPT_U8 offset)
6690075Sobrien{
67132718Skan    return  pci_read_config(((PHBA)osext)->pcidev, offset, 4);
68132718Skan}
6990075Sobrien
7090075Sobrienvoid os_pci_writeb (void *osext, HPT_U8 offset, HPT_U8 value)
7190075Sobrien{
7290075Sobrien    pci_write_config(((PHBA)osext)->pcidev, offset, value, 1);
7390075Sobrien}
7490075Sobrien
7590075Sobrienvoid os_pci_writew (void *osext, HPT_U8 offset, HPT_U16 value)
7690075Sobrien{
7790075Sobrien    pci_write_config(((PHBA)osext)->pcidev, offset, value, 2);
7890075Sobrien}
7990075Sobrien
8090075Sobrienvoid os_pci_writel (void *osext, HPT_U8 offset, HPT_U32 value)
8190075Sobrien{
8290075Sobrien    pci_write_config(((PHBA)osext)->pcidev, offset, value, 4);
8390075Sobrien}
8490075Sobrien
8590075Sobrienvoid *os_map_pci_bar(
8690075Sobrien    void *osext,
8790075Sobrien    int index,
8890075Sobrien    HPT_U32 offset,
8990075Sobrien    HPT_U32 length
9090075Sobrien)
9190075Sobrien{
9290075Sobrien	PHBA hba = (PHBA)osext;
93132718Skan
94132718Skan    hba->pcibar[index].rid = 0x10 + index * 4;
9590075Sobrien
9690075Sobrien    if (pci_read_config(hba->pcidev, hba->pcibar[index].rid, 4) & 1)
9790075Sobrien    	hba->pcibar[index].type = SYS_RES_IOPORT;
9890075Sobrien    else
9990075Sobrien    	hba->pcibar[index].type = SYS_RES_MEMORY;
10090075Sobrien
10190075Sobrien    hba->pcibar[index].res = bus_alloc_resource(hba->pcidev,
10290075Sobrien		hba->pcibar[index].type, &hba->pcibar[index].rid, 0, ~0, length, RF_ACTIVE);
10390075Sobrien
10490075Sobrien	hba->pcibar[index].base = (char *)rman_get_virtual(hba->pcibar[index].res) + offset;
10590075Sobrien	return hba->pcibar[index].base;
10690075Sobrien}
10790075Sobrien
10890075Sobrienvoid os_unmap_pci_bar(void *osext, void *base)
10990075Sobrien{
11090075Sobrien	PHBA hba = (PHBA)osext;
11190075Sobrien	int index;
11290075Sobrien
11390075Sobrien	for (index=0; index<6; index++) {
11490075Sobrien		if (hba->pcibar[index].base==base) {
11590075Sobrien			bus_release_resource(hba->pcidev, hba->pcibar[index].type,
11690075Sobrien				hba->pcibar[index].rid, hba->pcibar[index].res);
11790075Sobrien			hba->pcibar[index].base = 0;
11890075Sobrien			return;
11990075Sobrien		}
12090075Sobrien	}
12190075Sobrien}
12290075Sobrien
12390075Sobrienvoid freelist_reserve(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT count)
12490075Sobrien{
12590075Sobrien    PVBUS_EXT vbus_ext = osext;
12690075Sobrien
12790075Sobrien    if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
12890075Sobrien        vbus_ext = ((PHBA)osext)->vbus_ext;
12990075Sobrien
13090075Sobrien    list->next = vbus_ext->freelist_head;
13190075Sobrien    vbus_ext->freelist_head = list;
13290075Sobrien    list->dma = 0;
13390075Sobrien    list->size = size;
13490075Sobrien    list->head = 0;
13590075Sobrien#ifdef DBG
13690075Sobrien    list->reserved_count =
13790075Sobrien#endif
13890075Sobrien    list->count = count;
13990075Sobrien}
14090075Sobrien
14190075Sobrienvoid *freelist_get(struct freelist *list)
14290075Sobrien{
143132718Skan    void * result;
14490075Sobrien    if (list->count) {
14590075Sobrien        HPT_ASSERT(list->head);
14690075Sobrien        result = list->head;
14790075Sobrien        list->head = *(void **)result;
14890075Sobrien        list->count--;
14990075Sobrien        return result;
15090075Sobrien    }
15190075Sobrien    return 0;
15290075Sobrien}
15390075Sobrien
15490075Sobrienvoid freelist_put(struct freelist * list, void *p)
15590075Sobrien{
15690075Sobrien    HPT_ASSERT(list->dma==0);
15790075Sobrien    list->count++;
15890075Sobrien    *(void **)p = list->head;
15990075Sobrien    list->head = p;
16090075Sobrien}
16190075Sobrien
16290075Sobrienvoid freelist_reserve_dma(struct freelist *list, void *osext, HPT_UINT size, HPT_UINT alignment, HPT_UINT count)
16390075Sobrien{
16490075Sobrien    PVBUS_EXT vbus_ext = osext;
165132718Skan
16690075Sobrien    if (vbus_ext->ext_type!=EXT_TYPE_VBUS)
16790075Sobrien        vbus_ext = ((PHBA)osext)->vbus_ext;
16890075Sobrien
16990075Sobrien    list->next = vbus_ext->freelist_dma_head;
17090075Sobrien    vbus_ext->freelist_dma_head = list;
17190075Sobrien    list->dma = 1;
172132718Skan    list->alignment = alignment;
17390075Sobrien    list->size = size;
17490075Sobrien    list->head = 0;
17590075Sobrien#ifdef DBG
17690075Sobrien    list->reserved_count =
17790075Sobrien#endif
17890075Sobrien    list->count = count;
17990075Sobrien}
18090075Sobrien
18190075Sobrienvoid *freelist_get_dma(struct freelist *list, BUS_ADDRESS *busaddr)
18290075Sobrien{
18390075Sobrien    void *result;
18490075Sobrien    HPT_ASSERT(list->dma);
18590075Sobrien    result = freelist_get(list);
18690075Sobrien    if (result)
18790075Sobrien        *busaddr = *(BUS_ADDRESS *)((void **)result+1);
18890075Sobrien    return result;
18990075Sobrien}
19090075Sobrien
19190075Sobrienvoid freelist_put_dma(struct freelist *list, void *p, BUS_ADDRESS busaddr)
19290075Sobrien{
19390075Sobrien    HPT_ASSERT(list->dma);
19490075Sobrien    list->count++;
19590075Sobrien    *(void **)p = list->head;
19690075Sobrien    *(BUS_ADDRESS *)((void **)p+1) = busaddr;
197132718Skan    list->head = p;
198117395Skan}
19990075Sobrien
20090075SobrienHPT_U32 os_get_stamp(void)
20190075Sobrien{
202117395Skan    HPT_U32 stamp;
20390075Sobrien    do { stamp = random(); } while (stamp==0);
204117395Skan    return stamp;
205132718Skan}
20690075Sobrien
20790075Sobrienvoid os_stallexec(HPT_U32 microseconds)
20890075Sobrien{
20990075Sobrien    DELAY(microseconds);
21090075Sobrien}
21190075Sobrien
212117395Skanstatic void os_timer_for_ldm(void *arg)
21390075Sobrien{
21490075Sobrien	PVBUS_EXT vbus_ext = (PVBUS_EXT)arg;
21590075Sobrien	ldm_on_timer((PVBUS)vbus_ext->vbus);
21690075Sobrien}
21790075Sobrien
21890075Sobrienvoid  os_request_timer(void * osext, HPT_U32 interval)
21990075Sobrien{
220117395Skan	PVBUS_EXT vbus_ext = osext;
22190075Sobrien
22290075Sobrien	HPT_ASSERT(vbus_ext->ext_type==EXT_TYPE_VBUS);
22390075Sobrien
22490075Sobrien	untimeout(os_timer_for_ldm, vbus_ext, vbus_ext->timer);
22590075Sobrien	vbus_ext->timer = timeout(os_timer_for_ldm, vbus_ext, interval * hz / 1000000);
22690075Sobrien}
22790075Sobrien
228117395SkanHPT_TIME os_query_time(void)
22990075Sobrien{
23090075Sobrien	return ticks * (1000000 / hz);
23190075Sobrien}
23290075Sobrien
23390075Sobrienvoid os_schedule_task(void *osext, OSM_TASK *task)
23490075Sobrien{
23590075Sobrien	PVBUS_EXT vbus_ext = osext;
23690075Sobrien
23790075Sobrien	HPT_ASSERT(task->next==0);
23890075Sobrien
23990075Sobrien	if (vbus_ext->tasks==0)
24090075Sobrien		vbus_ext->tasks = task;
24190075Sobrien	else {
24290075Sobrien		OSM_TASK *t = vbus_ext->tasks;
24390075Sobrien		while (t->next) t = t->next;
24490075Sobrien		t->next = task;
24590075Sobrien	}
24690075Sobrien
24790075Sobrien	if (vbus_ext->worker.ta_context)
24890075Sobrien		TASK_ENQUEUE(&vbus_ext->worker);
24990075Sobrien}
25090075Sobrien
25190075Sobrienint os_revalidate_device(void *osext, int id)
25290075Sobrien{
25390075Sobrien
25490075Sobrien    return 0;
25590075Sobrien}
25690075Sobrien
25790075Sobrienint os_query_remove_device(void *osext, int id)
25890075Sobrien{
25990075Sobrien	PVBUS_EXT				vbus_ext = (PVBUS_EXT)osext;
26090075Sobrien	struct cam_periph		*periph = NULL;
26190075Sobrien    struct cam_path			*path;
26290075Sobrien    int						status,retval = 0;
26390075Sobrien
26490075Sobrien    status = xpt_create_path(&path, NULL, vbus_ext->sim->path_id, id, 0);
265117395Skan    if (status == CAM_REQ_CMP) {
26690075Sobrien		if((periph = cam_periph_find(path, "da")) != NULL){
267117395Skan			if(periph->refcount >= 1)
26890075Sobrien				retval = -1;
26990075Sobrien		}
27090075Sobrien		xpt_free_path(path);
27190075Sobrien    }
27290075Sobrien
27390075Sobrien    return retval;
27490075Sobrien}
27590075Sobrien
27690075SobrienHPT_U8 os_get_vbus_seq(void *osext)
27790075Sobrien{
27890075Sobrien    return ((PVBUS_EXT)osext)->sim->path_id;
27990075Sobrien}
28090075Sobrien
28190075Sobrienint  os_printk(char *fmt, ...)
28290075Sobrien{
28390075Sobrien    va_list args;
28490075Sobrien    static char buf[512];
28590075Sobrien
28690075Sobrien    va_start(args, fmt);
28790075Sobrien    vsnprintf(buf, sizeof(buf), fmt, args);
28890075Sobrien    va_end(args);
28990075Sobrien    return printf("%s: %s\n", driver_name, buf);
290132718Skan}
291132718Skan
292#ifdef DBG
293void os_check_stack(const char *location, int size){}
294
295void __os_dbgbreak(const char *file, int line)
296{
297    printf("*** break at %s:%d ***", file, line);
298    while (1);
299}
300
301int hptrr_dbg_level = 1;
302#endif
303