refactory code, rewrite dpr driver, mini fixes

This commit is contained in:
Angell Fear
2011-04-04 23:17:39 +06:00
parent affaea457e
commit 29ef78a086
55 changed files with 26232 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
#ifndef __LINUX_I2C_AK4183_H
#define __LINUX_I2C_AK4183_H
/* linux/i2c/ak4183.h */
struct ak4183_platform_data {
u16 model;
u16 x_plate_ohms;
u16 y_plate_ohms;
int (*get_pendown_state)(void);
void (*clear_penirq)(void); /* If needed, clear 2nd level
interrupt source */
int (*init_platform_hw)(void);
void (*exit_platform_hw)(void);
};
#endif

View File

@@ -0,0 +1,161 @@
/*
* Bluetooth G900 chip control
*
* Copyright (c) 2008 Angell Fear
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/rfkill.h>
#include <mach/g900-gpio.h>
/*
#define G900_BT_RESET 83
#define G900_BT_POWER 114
echo "1" > "/sys/class/gpio/gpio114/value"
echo "0" > "/sys/class/gpio/gpio83/value"
cat "/sys/class/gpio/gpio83/value"
#echo "1" > "/sys/class/gpio/gpio114/value"
*/
static void g900_bt_on(void)
{
gpio_set_value(G900_BT_RESET, 0);
gpio_set_value(G900_BT_POWER, 1);
gpio_set_value(G900_BT_RESET, 1);
mdelay(20);
gpio_set_value(G900_BT_RESET, 0);
}
static void g900_bt_off(void)
{
gpio_set_value(G900_BT_RESET, 1);
mdelay(10);
gpio_set_value(G900_BT_POWER, 0);
gpio_set_value(G900_BT_RESET, 0);
}
static int g900_bt_set_block(void *data, bool blocked)
{
pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
if (!blocked) {
pr_info("g900_BT: going ON\n");
g900_bt_on();
} else {
pr_info("g900_BT: going OFF\n");
g900_bt_off();
}
return 0;
}
static const struct rfkill_ops g900_bt_rfkill_ops = {
.set_block = g900_bt_set_block,
};
static int g900_bt_probe(struct platform_device *dev)
{
int rc;
struct rfkill *rfk;
rc = gpio_request(G900_BT_RESET, "Bluetooth reset");
if (rc)
goto err_reset;
rc = gpio_direction_output(G900_BT_RESET, 0);
if (rc)
goto err_reset_dir;
rc = gpio_request(G900_BT_POWER, "Bluetooth power");
if (rc)
goto err_pwr;
rc = gpio_direction_output(G900_BT_POWER, 0);
if (rc)
goto err_pwr_dir;
rfk = rfkill_alloc("g900-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
&g900_bt_rfkill_ops, NULL);
if (!rfk) {
rc = -ENOMEM;
goto err_rfk_alloc;
}
rfkill_set_led_trigger_name(rfk, "g900-bt");
rc = rfkill_register(rfk);
if (rc)
goto err_rfkill;
platform_set_drvdata(dev, rfk);
return 0;
err_rfkill:
rfkill_destroy(rfk);
err_rfk_alloc:
g900_bt_off();
err_pwr_dir:
gpio_free(G900_BT_POWER);
err_pwr:
err_reset_dir:
gpio_free(G900_BT_RESET);
err_reset:
return rc;
}
static int __devexit g900_bt_remove(struct platform_device *dev)
{
struct rfkill *rfk = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
if (rfk) {
rfkill_unregister(rfk);
rfkill_destroy(rfk);
}
rfk = NULL;
g900_bt_off();
gpio_free(G900_BT_POWER);
gpio_free(G900_BT_RESET);
return 0;
}
static struct platform_driver g900_bt_driver = {
.probe = g900_bt_probe,
.remove = __devexit_p(g900_bt_remove),
.driver = {
.name = "g900-bt",
.owner = THIS_MODULE,
},
};
static int __init g900_bt_init(void)
{
return platform_driver_register(&g900_bt_driver);
}
static void __exit g900_bt_exit(void)
{
platform_driver_unregister(&g900_bt_driver);
}
module_init(g900_bt_init);
module_exit(g900_bt_exit);

View File

@@ -0,0 +1,417 @@
/*linux/drivers/video/g900fb2.c --
*
* Copyright (C) 2010 Angell Fear
*
* Copyright (C) 2010 Kosyak
*
* Copyright (C) 2008 El Tuba
*
* Based on N311fb framebuffer
*
* Copyright (C) 2008 Vladimir Chernichkin
*
* Copyright (C) 2007, Google Inc.
*
* Copyright (C) 2002 James Simmons
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/fb.h>
#define FB_WIDTH 480
#define FB_HEIGHT 800
#define VIDEOMEMSTART 0x0a000000
#define FB_BYTES_PER_PIXEL 2
#define VIDEOMEMSIZE FB_WIDTH * FB_HEIGHT * FB_BYTES_PER_PIXEL * 2
static void *videomemory;
static u_long videomemorysize = VIDEOMEMSIZE ;
module_param(videomemorysize, ulong, 0);
static int g900fb_enable __initdata = 1; /* disabled by default */
module_param(g900fb_enable, bool, 0);
static unsigned int lowres;
module_param(lowres, uint, 0);
MODULE_PARM_DESC(lowres, "Set 0 = 800/480, 1 = 400x240)");
static unsigned int buffers;
module_param(buffers, uint, 0);
MODULE_PARM_DESC(buffers, "Set num buffers (min 1, max 2)");
struct g900_fb {
int rotation;
struct fb_info fb;
u32 cmap[16];
};
static struct fb_var_screeninfo g900fb_default __initdata = {
.bits_per_pixel = 16,
.red = { 11, 5, 0 },
.green = { 5, 6, 0 },
.blue = { 0, 5, 0 },
.accel_flags = FB_ACCEL_NONE,
};
static struct fb_fix_screeninfo g900fb_fix __initdata = {
.id = "g900 FB",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.accel = FB_ACCEL_NONE,
.xpanstep = 1, /* 1 */
.ypanstep = 1, /* 1 */
.ywrapstep = 0,
.smem_start = VIDEOMEMSTART,
.smem_len = VIDEOMEMSIZE,
.line_length = (FB_WIDTH * FB_BYTES_PER_PIXEL),
};
static int g900fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
//static int g900fb_set_par(struct fb_info *info);
static int g900fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info);
static int g900fb_pan_display(struct fb_var_screeninfo *var,struct fb_info *info);
//static int g900fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
static void g900fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
static void g900fb_copyarea(struct fb_info *info, const struct fb_copyarea *region);
static void g900fb_imageblit(struct fb_info *info, const struct fb_image *image);
static void g900fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
/* Метод ускорения для заполнения прямоугольника линиями пикселей */
/* похоже вообще не используеться */
cfb_fillrect(info,rect);
};
static void g900fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
/* Метод ускорения копирования одной прямоугольной области в другую */
/* похоже вообще не используеться */
cfb_copyarea(info,region);
};
static void g900fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
/* Метод ускорения рисования на экране картинки */
/* Без этого даже не отображаеться консоль !!! */
cfb_imageblit(info,image);
};
//static int g900fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
static struct fb_ops g900fb_ops = {
.fb_check_var = g900fb_check_var, /* Проверка параметров */
//.fb_set_par = g900fb_set_par, /* Программирование регистров контроллера */
.fb_setcolreg = g900fb_setcolreg, /* Установка карты цветов */
.fb_pan_display = g900fb_pan_display, /* переключение страниц буферов */
.fb_fillrect = g900fb_fillrect,
.fb_copyarea = g900fb_copyarea,
.fb_imageblit = g900fb_imageblit,
//.fb_ioctl = g900fb_ioctl, /* Зависимая от устройства ioctl */
//.fb_blank = g900fb_blank, /* Включение/выключение экрана */
//.fb_mmap = g900fb_mmap,
};
static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
{
unsigned int mask = (1 << bf->length) - 1;
return (val >> (16 - bf->length) & mask) << bf->offset;
}
static int g900fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
//return 0;
if((var->rotate & 1) != (info->var.rotate & 1)) {
if((var->xres != info->var.yres) ||
(var->yres != info->var.xres) ||
(var->xres_virtual != info->var.yres) ||
(var->yres_virtual >
info->var.xres * buffers) ||
(var->yres_virtual < info->var.xres )) {
return -EINVAL;
}
} else {
if((var->xres != info->var.xres) ||
(var->yres != info->var.yres) ||
(var->xres_virtual != info->var.xres) ||
(var->yres_virtual >
info->var.yres * buffers) ||
(var->yres_virtual < info->var.yres )) {
return -EINVAL;
}
}
if((var->xoffset != info->var.xoffset) ||
(var->bits_per_pixel != info->var.bits_per_pixel) ||
(var->grayscale != info->var.grayscale)) {
return -EINVAL;
}
return 0;
}
/* This routine actually sets the video mode. It's in here where we
* the hardware state info->par and fix which can be affected by the
* change in par. For this driver it doesn't do much.
*/
/*
static int g900fb_set_par(struct fb_info *info)
{
struct g900_fb *fb = container_of(info, struct g900_fb, fb);
if(fb->rotation != fb->fb.var.rotate) {
fb->rotation = fb->fb.var.rotate;
//TODO: Dynamic Rotation!!!
}
return 0;
}
*/
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
static int g900fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct g900_fb *fb = container_of(info, struct g900_fb, fb);
if (regno < 16) {
fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
convert_bitfield(blue, &fb->fb.var.blue) |
convert_bitfield(green, &fb->fb.var.green) |
convert_bitfield(red, &fb->fb.var.red);
return 0;
}
else {
return 1;
}
}
static int g900fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
/* TODO find hardware flip page or copyarea*/
u32 len;
if(buffers != 2 ) return 0;
if(info->var.yoffset < var->yres) return 0;
len = var->yoffset * info->fix.line_length;
memcpy(info->screen_base, (info->screen_base + len), len);
return 0;
#if 0
struct fb_copyarea fbca;
memset(&fbca, 0, sizeof(fbca));
fbca.sx = 0;
fbca.sy = info->var->yres;
fbca.dx = 0;
fbca.dy = 0;
fbca.width = info->var.yres*(lowres+1);
fbca.height = info->var.xres;
cfb_copyarea(info,&fbca);
return 0;
#endif
}
/*
* Initialisation
*/
static int __init g900fb_probe(struct platform_device *dev)
{
struct g900_fb *fb;
int retval = -ENOMEM;
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if(fb == NULL)
goto err;
if (!request_mem_region(VIDEOMEMSTART, videomemorysize, "g900fb")) {
printk(KERN_INFO"g900fb: cannot get framebuffer\n");
goto err1;
}
if(lowres != 1 ) lowres = 0;
if(buffers != 2 ) buffers = 1;
fb->fb.flags = FBINFO_FLAG_DEFAULT;
fb->fb.fbops = &g900fb_ops;
fb->fb.pseudo_palette = fb->cmap;
fb->fb.fix = g900fb_fix;
fb->fb.var = g900fb_default;
if(lowres == 1)
{
fb->fb.var.xres = FB_WIDTH / 2;
fb->fb.var.yres = FB_HEIGHT / 2;
}else{
fb->fb.var.xres = FB_WIDTH;
fb->fb.var.yres = FB_HEIGHT;
}
fb->fb.var.xres_virtual = fb->fb.var.xres;
fb->fb.var.yres_virtual = fb->fb.var.yres*buffers;
fb->fb.var.height = fb->fb.var.xres;
fb->fb.var.width = fb->fb.var.yres;
fb->fb.screen_base = ioremap(VIDEOMEMSTART, videomemorysize);
retval = fb_set_var(&fb->fb, &fb->fb.var);
if(retval)
goto err1;
retval = register_framebuffer(&fb->fb);
if (retval < 0)
goto err2;
platform_set_drvdata(dev, &fb->fb);
printk(KERN_INFO "fb%d: g900 frame buffer device, using %ldK of video memory\n",
fb->fb.node, videomemorysize >> 10);
return 0;
err2:
framebuffer_release(&fb->fb);
err1:
kfree(fb);
err:
iounmap(videomemory);
return retval;
}
static int g900fb_remove(struct platform_device *dev)
{
struct g900_fb *fb = platform_get_drvdata(dev);
if (fb) {
unregister_framebuffer(&fb->fb);
iounmap(videomemory);
framebuffer_release(&fb->fb);
kfree(fb);
}
return 0;
}
static struct platform_driver g900fb_driver = {
.probe = g900fb_probe,
.remove = g900fb_remove,
.driver = {
.name = "g900fb",
},
};
#ifndef MODULE
static int __init g900fb_setup(char *options)
{
char *this_opt;
g900fb_enable = 1;
if (!options || !*options)
return 1;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
if (!strncmp(this_opt, "disable", 7))
g900fb_enable = 0;
}
return 1;
}
#endif /* MODULE */
static struct platform_device *g900fb_device;
static int __init g900fb_init(void)
{
int ret = 0;
#ifndef MODULE
char *option = NULL;
if (fb_get_options("g900fb", &option))
return -ENODEV;
g900fb_setup(option);
#endif
if (!g900fb_enable)
return -ENXIO;
ret = platform_driver_register(&g900fb_driver);
if (!ret) {
g900fb_device = platform_device_alloc("g900fb", 0);
if (g900fb_device)
ret = platform_device_add(g900fb_device);
else
ret = -ENOMEM;
if (ret) {
platform_device_put(g900fb_device);
platform_driver_unregister(&g900fb_driver);
}
}
return ret;
}
module_init(g900fb_init);
#ifdef MODULE
static void __exit g900fb_exit(void)
{
platform_device_unregister(g900fb_device);
platform_driver_unregister(&g900fb_driver);
}
module_exit(g900fb_exit);
MODULE_AUTHOR("Angell <angell@angellfear.ru>");
MODULE_DESCRIPTION("Framebuffer driver for the Toshiba g900 ");
MODULE_LICENSE("GPL");
#endif

View File

@@ -0,0 +1,9 @@
#
# Makefile for the touchscreen drivers.
#
#obj-$(CONFIG_TOUCHSCREEN_MSM) += msm_ts.o
obj-y += g900_ts.o
obj-y += tssc_manager.o calibrate.o
#tp_cal.o

View File

@@ -0,0 +1,459 @@
/* calibrate.c
*
*/
#include <linux/module.h>
#include "tssc.h"
//#include <mach/board.h>
#define CALIBRATION_SCREEN_WIDTH 2048
#define CALIBRATION_SCREEN_HEIGHT 2048
#define CALIBRATION_POINTS 5
#define CALIBRATION_COORDINATES (CALIBRATION_POINTS * 2)
#define CALIBRATION_SAMPLE_SIZE 20
#define CALIBRATION_X_GAP 5
#define CALIBRATION_Y_GAP 5
// 5 points coordinates:
// Point 1 - (15, 20)
// Point 2 - (223, 20)
// Point 3 - (119, 159)
// Point 4 - (15, 298)
// Point 5 - (223, 298)
#define TP_CALIBRATION_POINT1_X 128
#define TP_CALIBRATION_POINT1_Y 128
#define TP_CALIBRATION_POINT2_X 1903
#define TP_CALIBRATION_POINT2_Y 128
#define TP_CALIBRATION_POINT3_X 128
#define TP_CALIBRATION_POINT3_Y 1907
#define TP_CALIBRATION_POINT4_X 1903
#define TP_CALIBRATION_POINT4_Y 1907
#define TP_CALIBRATION_POINT5_X 1024
#define TP_CALIBRATION_POINT5_Y 1024
#define CALIBRATION_X_RANGE 1560
#define CALIBRATION_Y_RANGE 1640
#define CALIBRATION_ERROR 30//15//10
// Flag to decide wheather current TP need to do adjustment or not.
// 0: No, not necessary to do adjustment.
// 1: Yes, should use calibration algorithm to do adjustment.
static int adjustment_flag = 0;
static int calibration_flag = 0;
static int calibration_count = 0;
static int calibration_index = 0;
// calibration_direction: Raw data vs. screen coordinate direction.
// 0: No swaped. X, Y same direction.
// 1: No swaped. X, same direction, Y reversed.
// 2: No swaped. X, reversed, Y same direction.
// 3: No swaped. X reversed, Y reversed.
// 4: X, Y swaped. X, Y same direction.
// 5: X, Y swaped. X, same direction, Y reversed.
// 6: X, Y swaped. X, reversed, Y same direction.
// 7: X, Y swaped. X, same direction, Y reversed.
static int calibration_x_direction = 0;
static int calibration_y_direction = 0;
static int calibration_swapped = 0;
static int calibration_x_min = TP_X_MIN;
static int calibration_x_max = TP_X_MAX;
static int calibration_y_min = TP_Y_MIN;
static int calibration_y_max = TP_Y_MAX;
static int saved_x_min = TP_X_MIN;
static int saved_x_max = TP_X_MAX;
static int saved_y_min = TP_Y_MIN;
static int saved_y_max = TP_Y_MAX;
static int calibration_x[CALIBRATION_POINTS];
static int calibration_y[CALIBRATION_POINTS];
static int saved_x[CALIBRATION_POINTS];
static int saved_y[CALIBRATION_POINTS];
static int screen_x[CALIBRATION_POINTS];
static int screen_y[CALIBRATION_POINTS];
/*
* Get the touch input raw data and store into the coordinates buffer.
*/
void calibration_get_points(int x, int y)
{
int dx;
int dy;
if (calibration_index >= CALIBRATION_POINTS)
return;
dx = abs(calibration_x[calibration_index] - x);
dy = abs(calibration_y[calibration_index] - y);
if ((dx < CALIBRATION_X_GAP) && (dy < CALIBRATION_Y_GAP))
calibration_count++;
calibration_x[calibration_index] = x;
calibration_y[calibration_index] = y;
}
/*
* Translate the touch input raw data to the calibrated data.
*/
void calibration_translate(int x, int y, int *rx, int *ry)
{
int cx, cy;
if (calibration_flag > 0 && calibration_flag <= CALIBRATION_POINTS) { /* Under calibration */
calibration_get_points(x, y);
*rx = x;
*ry = y;
} else { /* Normal touch input */
if (adjustment_flag) { /* After calibration */
int kx = 0;
int ky = 0;
if (calibration_swapped) { /* X, Y swapped */
// Ratio translation.
if ((calibration_x_max > calibration_x_min) && (calibration_y_max > calibration_y_min)) {
kx = TP_X_MIN + ((x - calibration_y_min) * (TP_X_MAX - TP_X_MIN) / (calibration_y_max - calibration_y_min));
ky = TP_Y_MIN + ((y - calibration_x_min) * (TP_Y_MAX - TP_Y_MIN) / (calibration_x_max - calibration_x_min));
}
// X, Y direction
cx = (calibration_x_direction) ? (ky) : (TP_X_MAX - ky);
cy = (calibration_y_direction) ? (kx) : (TP_Y_MAX - kx);
} else {
// Ratio translation.
if ((calibration_x_max > calibration_x_min) && (calibration_y_max > calibration_y_min)) {
kx = TP_X_MIN + ((x - calibration_x_min) * (TP_X_MAX - TP_X_MIN) / (calibration_x_max - calibration_x_min));
ky = TP_Y_MIN + ((y - calibration_y_min) * (TP_Y_MAX - TP_Y_MIN) / (calibration_y_max - calibration_y_min));
}
// X, Y direction
cx = (calibration_x_direction) ? (kx) : (TP_X_MAX - kx);
cy = (calibration_y_direction) ? (ky) : (TP_Y_MAX - ky);
}
if (cx < TP_X_MIN)
cx = TP_X_MIN;
else if (cx > TP_X_MAX)
cx = TP_X_MAX;
if (cy < TP_Y_MIN)
cy = TP_Y_MIN;
else if (cy > TP_Y_MAX)
cy = TP_Y_MAX;
*rx = cx;
*ry = cy;
} else { /* No need to do calibration */
*rx = y; /* Current device, x and y swapped */
*ry = x;
}
}
}
/*
* Show the calibration parameters.
*/
void calibration_show_parameters(int status)
{
int i;
for (i = 0; i < CALIBRATION_POINTS; i++)
printk(KERN_INFO "touch_calibration: Point %d %d, %d.\n",
i+1, calibration_x[i], calibration_y[i]);
printk(KERN_INFO "touch_calibration: do calibration %s.\n",
status ? "error" : "ok");
printk(KERN_INFO "touch_calibration: x max %d, x min %d.\n",
calibration_x_min, calibration_x_max);
printk(KERN_INFO "touch_calibration: y max %d, y min %d.\n",
calibration_y_min, calibration_y_max);
printk(KERN_INFO "touch_calibration: %s x %s, y %s.\n",
calibration_swapped ? "X Y swapped," : "",
calibration_x_direction ? "reversed" : "same direction",
calibration_y_direction ? "reversed" : "same direction");
}
/*
* Calculate calibration variables.
*/
void calibration_calculate_varialbes(void)
{
int xdir, xlen, ydir, ylen;
int x_length, y_length;
int x1, x2, y1, y2;
int i;
int result = 0;
saved_x_min = calibration_x_min;
saved_x_max = calibration_x_max;
saved_y_min = calibration_y_min;
saved_y_max = calibration_y_max;
if (calibration_index < CALIBRATION_POINTS - 1) {
result = 1; /* Calibration points not enough */
} else {
if (calibration_x[0] > calibration_x[1]) {
xdir = 0; /* Reversed */
xlen = calibration_x[0] - calibration_x[1];
} else {
xdir = 1; /* Same */
xlen = calibration_x[1] - calibration_x[0];
}
if (calibration_y[0] > calibration_y[1]) {
ydir = 0; /* Reversed */
ylen = calibration_y[0] - calibration_y[1];
} else {
ydir = 1; /* Same */
ylen = calibration_y[1] - calibration_y[0];
}
if (xlen > ylen) {
calibration_swapped = 0; /* No swapped */
calibration_x_direction = xdir;
x_length = xlen;
if (calibration_y[0] > calibration_y[3]) {
calibration_y_direction = 0; /* Reversed */
y_length = calibration_y[0] - calibration_y[3];
} else {
calibration_y_direction = 1; /* Same */
y_length = calibration_y[3] - calibration_y[0];
}
x1 = (calibration_x_direction) ? (calibration_x[0]) : (calibration_x[1]);
x2 = (calibration_x_direction) ? (calibration_x[1]) : (calibration_x[0]);
y1 = (calibration_y_direction) ? (calibration_y[0]) : (calibration_y[3]);
y2 = (calibration_y_direction) ? (calibration_y[3]) : (calibration_y[0]);
} else {
calibration_swapped = 1; /* X, Y swapped */
calibration_x_direction = ydir;
x_length = ylen;
if (calibration_x[0] > calibration_x[3]) {
calibration_y_direction = 0; /* Reversed */
y_length = calibration_x[0] - calibration_x[3];
} else {
calibration_y_direction = 1; /* Same */
y_length = calibration_x[3] - calibration_x[0];
}
x1 = (calibration_x_direction) ? (calibration_y[0]) : (calibration_y[1]);
x2 = (calibration_x_direction) ? (calibration_y[1]) : (calibration_y[0]);
y1 = (calibration_y_direction) ? (calibration_x[0]) : (calibration_x[3]);
y2 = (calibration_y_direction) ? (calibration_x[3]) : (calibration_x[0]);
}
xlen = (screen_x[1] - screen_x[0]);
if (xlen) {
calibration_x_min = x1 - ((x_length) * (screen_x[0]) / xlen);
calibration_x_max = x2 + ((x_length) * (CALIBRATION_SCREEN_WIDTH-screen_x[1]) / xlen);
} else {
result = 1;
}
ylen = (screen_y[2] - screen_y[0]);
if (ylen) {
calibration_y_min = y1 - ((y_length) * (screen_y[0]) / ylen);
calibration_y_max = y2 + ((y_length) * (CALIBRATION_SCREEN_HEIGHT-screen_y[2]) / ylen);
} else {
result = 1;
}
}
if(0)
{
printk("mfg_mode=factory2\n");
#if 0
printk("calibration_x_max-calibration_x_min=%d calibration_y_max-calibration_y_min=%d\n"
, calibration_x_max-calibration_x_min, calibration_y_max-calibration_y_min);
printk("abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min))=%d\n", abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min)));
printk("abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min))=%d\n", abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min)));
if(abs(CALIBRATION_X_RANGE-(calibration_x_max-calibration_x_min))>CALIBRATION_ERROR
|| abs(CALIBRATION_Y_RANGE-(calibration_y_max-calibration_y_min))>CALIBRATION_ERROR
) result=1;
#endif
}
// if (calibration_x_min > 250 || calibration_x_max < 700 || calibration_y_min > 250 || calibration_y_max < 700)
// result = 1; /* Not in the acceptable area */
calibration_show_parameters(result);
if (result == 1) {
for (i=0; i<CALIBRATION_POINTS; i++) {
calibration_x[i] = saved_x[i];
calibration_y[i] = saved_y[i];
}
calibration_x_min = saved_x_min;
calibration_x_max = saved_x_max;
calibration_y_min = saved_y_min;
calibration_y_max = saved_y_max;
calibration_flag = 9; /* Calibration error */
} else {
for (i=0; i<CALIBRATION_POINTS; i++) {
saved_x[i] = calibration_x[i];
saved_y[i] = calibration_y[i];
}
calibration_flag = 8; /* Calibration ok */
}
adjustment_flag = 1; /* Calibration finished */
}
/*
* Set the coordinates of calibration points from input data buffer.
*/
void calibration_set(int *inPtr)
{
int i;
int j = 0;
for (i = 0; i < CALIBRATION_POINTS; i++) {
calibration_x[i] = inPtr[j++];
calibration_y[i] = inPtr[j++];
}
}
/*
* Initialize calibration parameters at boot time.
*/
void calibration_init(void)
{
screen_x[0] = TP_CALIBRATION_POINT1_X;
screen_x[1] = TP_CALIBRATION_POINT2_X;
screen_x[2] = TP_CALIBRATION_POINT3_X;
screen_x[3] = TP_CALIBRATION_POINT4_X;
screen_x[4] = TP_CALIBRATION_POINT5_X;
screen_y[0] = TP_CALIBRATION_POINT1_Y;
screen_y[1] = TP_CALIBRATION_POINT2_Y;
screen_y[2] = TP_CALIBRATION_POINT3_Y;
screen_y[3] = TP_CALIBRATION_POINT4_Y;
screen_y[4] = TP_CALIBRATION_POINT5_Y;
}
/*
* Display the flag of the calibration algorithm.
* 0: exit calibration mode.
* 1: enter calibration mode.
* 2: calibration error.
* 3: calibration ok.
*/
ssize_t calibration_show(char *buf)
{
return sprintf(buf, "%d\n", calibration_flag);
}
/*
* Store the flag of the calibration algorithm.
*/
void calibration_store(const char *buf)
{
char *ptr_data = (char *)buf;
unsigned long val = simple_strtoul(ptr_data, NULL, 10);
if (val == 0) { /* exit calibration mode */
calibration_flag = 0;
calibration_count = 0;
calibration_calculate_varialbes();
calibration_index = 0;
printk(KERN_DEBUG "touch_calibration: exit.\n");
} else { /* calibration mode */
calibration_flag = val;
calibration_index = val - 1;
calibration_count = 0;
if (val <= CALIBRATION_POINTS)
printk(KERN_DEBUG "touch_calibration: point %d.\n",
calibration_index + 1);
else
printk(KERN_ERR "touch_calibration: point error.\n");
}
}
/*
* Display the coordinates of the calibration touch panel input points.
*/
ssize_t calibration_points_show(char *buf)
{
return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
saved_x[0], saved_y[0], saved_x[1], saved_y[1],
saved_x[2], saved_y[2], saved_x[3], saved_y[3],
saved_x[4], saved_y[4]);
}
/*
* Store the coordinates of the calibration touch panel input points.
*/
void calibration_points_store(const char *buf)
{
char *ptr_data = (char *)buf;
char *p;
int cnt = 0;
int tmp[CALIBRATION_COORDINATES];
unsigned long val;
while ((p = strsep(&ptr_data, ","))) {
if (!*p)
break;
if (cnt >= CALIBRATION_COORDINATES)
break;
val = simple_strtoul(p, NULL, 10);
tmp[cnt++] = val;
}
calibration_set(&tmp[0]);
calibration_index = CALIBRATION_POINTS;
calibration_calculate_varialbes();
calibration_index = 0;
}
/*
* Display the coordinates of the calibration screen points.
*/
ssize_t calibration_screen_show(char *buf)
{
return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
screen_x[0], screen_y[0],
screen_x[1], screen_y[1], screen_x[2], screen_y[2],
screen_x[3], screen_y[3], screen_x[4], screen_y[4]);
}
/*
* Store the coordinates of the calibration screen points.
*/
void calibration_screen_store(const char *buf)
{
char *ptr_data = (char *)buf;
char *p;
int cnt = 0;
int tmp[CALIBRATION_COORDINATES];
unsigned long val;
while ((p = strsep(&ptr_data, ","))) {
if (!*p)
break;
if (cnt >= CALIBRATION_COORDINATES)
break;
val = simple_strtoul(p, NULL, 10);
tmp[cnt++] = val;
}
if (cnt >= CALIBRATION_COORDINATES) {
int i;
int j = 0;
for (i = 0; i < CALIBRATION_POINTS; i++) {
screen_x[i] = tmp[j++];
screen_y[i] = tmp[j++];
}
}
}

View File

@@ -0,0 +1,491 @@
/*
* drivers/input/touchscreen/ak4183.c
*
* Copyright (c) 2010 SashaG <...>
* Copyright (c) 2010 Fear <angell@angellfear.ru>
*
* Using code from:
* tsc2007.c
*
* Copyright (c) 2008 MtekVision Co., Ltd.
* Copyright (c) 2005 David Brownell
* Copyright (c) 2006 Nokia Corporation
* - corgi_ts.c
* Copyright (C) 2004-2005 Richard Purdie
* - omap_ts.[hc], ads7846.h, ts_osk.c
* Copyright (C) 2002 MontaVista Software
* Copyright (C) 2004 Texas Instruments
* Copyright (C) 2005 Dirk Behme
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include "../ak4183.h"
#define TS_POLL_DELAY 1000 /* us delay between samples */
#define TS_POLL_PERIOD 100000 /* us delay between samples */
#define AK4183_12BIT 1 /*12 bit resolution*/
#define devdbg(x...) printk(x)
#define AK4183_BIT_S (0x1 << 7)
#define AK4183_BIT_A2 (0x1 << 6)
#define AK4183_BIT_A1 (0x1 << 5)
#define AK4183_BIT_A0 (0x1 << 4)
#define AK4183_BIT_PD0 (0x1 << 2)
#define AK4183_BIT_R8BIT (0x1 << 1)
#define MAX_12BIT ((1 << 12) - 1)
#if AK4183_12BIT
#define ADC_ON_12BIT 0
#else
#define ADC_ON_12BIT AK4183_BIT_R8BIT
#endif
/*
BIT Name Function
7 S Start Bit. “1” Accelerate and Axis Command, “0”: Sleep mode Command
6-4 A2-A0 Channel Selection Bits. Analog inputs to the A/D converter and the activated driver switches are
selected. Please see the following table for the detail.
3 X1 Dont care
2 PD0 Power down bit (refer to power-down control)
1 MODE Resolution of A/D converter. “0”: 12 bit output “1”: 8 bit output
0 X2 Dont care
*/
#define READ_X ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A2 )
#define READ_Y ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A0 | AK4183_BIT_A2 )
#define READ_Z1 ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A1 | AK4183_BIT_A2 )
#define READ_Z2 ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A0 | AK4183_BIT_A1 | AK4183_BIT_A2 )
#define READ_AX ( ADC_ON_12BIT | AK4183_BIT_S )
#define READ_AY ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A0 )
#define READ_AXY ( ADC_ON_12BIT | AK4183_BIT_S | AK4183_BIT_A1 )
#define PWRDOWN ( AK4183_BIT_S | AK4183_BIT_PD0 )
#define samples 200
////touch calib test data
#define tmc_ax -11
//-0,05705; *200
#define tmc_bx 566382
//2831,91107; *200
#define tmc_x0 450
//450;
#define tmc_x10 476382
//bx-x0
#define tmc_ax_m_x0 -5135
//ax*x0
#define tmc_ay -11
//-0,05579;
#define tmc_by 593736
//2968,68213 *200
#define tmc_y0 440
//440;
#define tmc_y10 505736
//bx-x0
#define tmc_ay_m_y0 -4910
//ay*y0
struct ts_event {
u16 x;
u16 y;
u16 z1, z2;
};
struct ak4183 {
struct input_dev *input;
char phys[32];
struct delayed_work work;
struct i2c_client *client;
u16 model;
u16 x_plate_ohms;
bool pendown;
int irq;
int (*get_pendown_state)(void);
void (*clear_penirq)(void);
};
/*
0 4000 left 32 право 419
верх лево X=0x0150 Y=0x0ee0 P=0x0106
верх право X=0x0e50 Y=0x0ee0 P=0x0104
низ лево X=0x0110 Y=0x0090 P=0x00ea
низ право X=0x0dc0 Y=0x0080 P=0x00ec
wince
CalibrationData 2174,1990 563,3553 700,465 3463,506 3440,3547
wince hex
CalibrationData 0x87E,0x7C6 0x233,0xDE1 0x2BC,0x1D1 0xD87,0x1FA 0xD70,0xDDB
середина, верх лево,низ лево,низ право, верх право
*/
static int abs_x[3] = {0x0110, 0x0dc0, 1};
module_param_array(abs_x, int, NULL, 0);
MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
//static int abs_y[3] = {0x0ee0, 0x0080, 20};
static int abs_y[3] = {0x0080, 0x0ee0, 1};
module_param_array(abs_y, int, NULL, 0);
MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
static int abs_p[3] = {0, 0xfff, 2};
module_param_array(abs_p, int, NULL, 0);
MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
static inline int ak4183_xfer(struct ak4183 *tsc, u8 cmd)
{
s32 data;
u16 val;
data = i2c_smbus_read_word_data(tsc->client, cmd);
if (data < 0) {
dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
return data;
}
/* The protocol and raw data format from i2c interface:
* S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
* Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
*/
val = swab16(data) >> 4;
//dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
return val;
}
static u32 ak4183_read_values(struct ak4183 *tsc, struct ts_event *tc)
{
u32 rt = 0;
s32 rtt = 0;
//s32 x,y;
tc->x = ak4183_xfer(tsc, READ_X);//x
tc->y = ak4183_xfer(tsc, READ_Y);//y
//devdbg(KERN_INFO "AK4183: %5i;%5i;",
// tc->x,tc->y);
tc->z1 = ak4183_xfer(tsc,READ_Z1);//z1
tc->z2 = ak4183_xfer(tsc,READ_Z2);//z2
if (likely(tc->x && tc->z1)) {
/* compute touch pressure resistance using equation #1 */
rt = tc->x*(tc->z2-tc->z1)/(tc->z1);
if (rt<6350){ // min toch
rtt=rt-5000;//for func ; 0-max touch
if (rt<5000){rt=5000;} // max
rt=(6350-rt)*3;//0xFFF max
if (rt>=0xFFF) {rt=0xFFE;}//max
// devdbg(KERN_INFO "AK4183: %5u;%5u;%5u;%5u;%5u;",
// tc->x,tc->y,tc->z1,tc->z2,rtt);
}else{
rt=0;//no touch
}
}
//todo : need pwrdown
if (rt){//*200
tc->x=(u32)(((s32)(tc->x)*tmc_x10+rtt*tmc_ax_m_x0)/(tmc_x10+tmc_ax*rtt));
tc->y=(u32)(((s32)(tc->y)*tmc_y10+rtt*tmc_ay_m_y0)/(tmc_y10+tmc_ay*rtt));
tc->y = MAX_12BIT - tc->y;
}
return rt;
}
static void ak4183_send_up_event(struct ak4183 *tsc)
{
struct input_dev *input = tsc->input;
dev_dbg(&tsc->client->dev, "UP\n");
input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0);
input_sync(input);
}
static void ak4183_work(struct work_struct *work)
{
struct ak4183 *ts =
container_of(to_delayed_work(work), struct ak4183, work);
struct ts_event tc;
u32 rt;
/*
* NOTE: We can't rely on the pressure to determine the pen down
* state, even though this controller has a pressure sensor.
* The pressure value can fluctuate for quite a while after
* lifting the pen and in some cases may not even settle at the
* expected value.
*
* The only safe way to check for the pen up condition is in the
* work function by reading he pen signal state (it's a GPIO
* and IRQ). Unfortunately such callback is not always available,
* in that case we have rely on the pressure anyway.
*/
if (ts->get_pendown_state) {
if (unlikely(!ts->get_pendown_state())) {
ak4183_send_up_event(ts);
ts->pendown = false;
goto out;
}
//dev_dbg(&ts->client->dev, "pen is still down\n");
}
rt = ak4183_read_values(ts, &tc);
if (rt > MAX_12BIT) {
/*
* Sample found inconsistent by debouncing or pressure is
* beyond the maximum. Don't report it to user space,
* repeat at least once more the measurement.
*/
dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
goto out;
}
if (rt) {
struct input_dev *input = ts->input;
if (!ts->pendown) {
dev_dbg(&ts->client->dev, "DOWN\n");
input_report_key(input, BTN_TOUCH, 1);
ts->pendown = true;
}
devdbg("ak4183 x = 0x%4x,y = 0x%4x,rt = 0x%4x", tc.x, tc.y, rt);
input_report_abs(input, ABS_X, tc.x);
input_report_abs(input, ABS_Y, tc.y);
input_report_abs(input, ABS_PRESSURE, 1);
input_sync(input);
} else if (!ts->get_pendown_state && ts->pendown) {
/*
* We don't have callback to check pendown state, so we
* have to assume that since pressure reported is 0 the
* pen was lifted up.
*/
ak4183_send_up_event(ts);
ts->pendown = false;
}
out:
if (ts->pendown)
schedule_delayed_work(&ts->work,
usecs_to_jiffies(TS_POLL_PERIOD));
else
enable_irq(ts->irq);
}
static irqreturn_t ak4183_irq(int irq, void *handle)
{
struct ak4183 *ts = handle;
if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
disable_irq_nosync(ts->irq);
devdbg("ak4183 disable_irq_nosync");
schedule_delayed_work(&ts->work,
usecs_to_jiffies(TS_POLL_DELAY));
}
if (ts->clear_penirq)
{
ts->clear_penirq();
}
schedule_delayed_work(&ts->work,
usecs_to_jiffies(TS_POLL_DELAY));
return IRQ_HANDLED;
}
static void ak4183_free_irq(struct ak4183 *ts)
{
free_irq(ts->irq, ts);
if (cancel_delayed_work_sync(&ts->work)) {
/*
* Work was pending, therefore we need to enable
* IRQ here to balance the disable_irq() done in the
* interrupt handler.
*/
enable_irq(ts->irq);
}
}
static int __devinit ak4183_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ak4183 *ts;
struct ak4183_platform_data *pdata = pdata = client->dev.platform_data;
struct input_dev *input_dev;
int err;
if (!pdata) {
dev_err(&client->dev, "platform data is required!\n");
return -EINVAL;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA))
{
dev_err(&client->dev, "err i2c_check_functionality!\n");
return -EIO;
}
ts = kzalloc(sizeof(struct ak4183), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
err = -ENOMEM;
dev_err(&client->dev, "err input_allocate_device!\n");
goto err_free_mem;
}
ts->client = client;
ts->irq = client->irq;
ts->input = input_dev;
INIT_DELAYED_WORK(&ts->work, ak4183_work);
ts->model = pdata->model;
ts->x_plate_ohms = pdata->x_plate_ohms;
ts->get_pendown_state = pdata->get_pendown_state;
ts->clear_penirq = pdata->clear_penirq;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
//input_dev->name = "AK4183 Touchscreen";
input_dev->name = "g900-ts";
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
/*
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
*/
input_set_abs_params(input_dev, ABS_X, abs_x[0], abs_x[1], abs_x[2], 0);
input_set_abs_params(input_dev, ABS_Y, abs_y[0], abs_y[1], abs_y[2], 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
if (pdata->init_platform_hw)
pdata->init_platform_hw();
//76 I 1 0 FE
err = request_irq(ts->irq, ak4183_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
client->dev.driver->name, ts);
if (err < 0) {
dev_err(&client->dev, "irq %d busy?\n", ts->irq);
goto err_free_mem;
}
/* Prepare for touch readings - power down ADC and enable PENIRQ */
/* err = ak4183_xfer(ts, PWRDOWN);
if (err < 0){
goto err_free_irq;
dev_err(&client->dev, "err ak4183_xfer\n");
}
*/
err = input_register_device(input_dev);
if (err){
goto err_free_irq;
dev_err(&client->dev, "err input_register_device\n");
}
i2c_set_clientdata(client, ts);
return 0;
err_free_irq:
ak4183_free_irq(ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
err_free_mem:
input_free_device(input_dev);
kfree(ts);
return err;
}
static int __devexit ak4183_remove(struct i2c_client *client)
{
struct ak4183 *ts = i2c_get_clientdata(client);
struct ak4183_platform_data *pdata = client->dev.platform_data;
ak4183_free_irq(ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
input_unregister_device(ts->input);
kfree(ts);
return 0;
}
static struct i2c_device_id ak4183_idtable[] = {
{ "ak4183", 0x48 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4183_idtable);
static struct i2c_driver ak4183_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "ak4183"
},
.id_table = ak4183_idtable,
.probe = ak4183_probe,
.remove = __devexit_p(ak4183_remove),
};
static int __init ak4183_init(void)
{
return i2c_add_driver(&ak4183_driver);
}
static void __exit ak4183_exit(void)
{
i2c_del_driver(&ak4183_driver);
}
module_init(ak4183_init);
module_exit(ak4183_exit);
MODULE_AUTHOR("angell <angell@angellfear.ru>");
MODULE_DESCRIPTION("AK4183 TouchScreen Driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,454 @@
/* drivers/input/touchscreen/msm_ts.c
*
* By Octavian Voicu <octavian@voicu.gmail.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/fb_helper.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/mach-types.h>
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
#define MSM_TS_DEBUG 0
#define MSM_TS_ABS_X_MIN 0
#define MSM_TS_ABS_X_MAX 479
#define MSM_TS_ABS_Y_MIN 0
#if defined(CONFIG_MACH_HTCBLACKSTONE) || defined(CONFIG_MACH_HTCKOVSKY)
#define MSM_TS_ABS_Y_MAX 799
#else
#define MSM_TS_ABS_Y_MAX 639
#endif
#define MSM_TS_ABS_PRESSURE_MIN 0
#define MSM_TS_ABS_PRESSURE_MAX 1
#define MSM_TS_ABS_SIZE_MIN 0
#define MSM_TS_ABS_SIZE_MAX 15
#define MSM_TS_LCD_WIDTH 480
#if defined(CONFIG_MACH_HTCBLACKSTONE) || defined(CONFIG_MACH_HTCKOVSKY)
#define MSM_TS_LCD_HEIGHT 800
#else
#define MSM_TS_LCD_HEIGHT 640
#endif
/* Touchscreen registers */
#define TSSC_CTL 0x100
#define TSSC_STATUS 0x10c
#define TSSC_DATA_LO_AVE 0x110
#define TSSC_DATA_UP_AVE 0x114
/* returns whether position was inside vkeyb, so as to eat event */
typedef int msm_ts_handler_t(int, int, int);
msm_ts_handler_t *msm_ts_handler; // virtual keyboard handler
extern msm_ts_handler_t *msm_ts_handler_pad; // blackstone handler
/* Work used by the polling mechanism after an interrupt has fired */
static void msm_ts_process_irq1(struct work_struct *work);
static void msm_ts_process_irq2(struct work_struct *work);
static void msm_ts_process_timeout(struct work_struct *work);
static DECLARE_WORK(msm_ts_work_irq1, msm_ts_process_irq1);
static DECLARE_WORK(msm_ts_work_irq2, msm_ts_process_irq2);
static DECLARE_DELAYED_WORK(msm_ts_work_timeout, msm_ts_process_timeout);
/* Function which processes the touchscreen data */
static void msm_ts_process_data(int irq);
static struct input_dev *msm_ts_dev;
static int calib_step, calib_xmin, calib_xmax, calib_ymin, calib_ymax, rawts=0;
/* lavender.t: (temporarily) add a kernel option to set calibration. */
static int __init msmts_calib_setup(char *str)
{
int xmin, ymin, xmax, ymax;
char* endp;
int ok = 0;
endp = NULL;
xmin = simple_strtol(str, &endp, 0);
if (endp > str && *endp == '.')
{
str = endp + 1;
endp = NULL;
ymin = simple_strtol(str, &endp, 0);
if (endp > str && *endp == '.')
{
str = endp + 1;
endp = NULL;
xmax = simple_strtol(str, &endp, 0);
if (endp > str && *endp == '.')
{
str = endp + 1;
endp = NULL;
ymax = simple_strtol(str, &endp, 0);
if (endp > str)
{
calib_step = 3;
calib_xmin = xmin;
calib_ymin = ymin;
calib_xmax = xmax;
calib_ymax = ymax;
ok = 1;
}
}
}
}
return ok;
}
__setup("msmts_calib=", msmts_calib_setup);
module_param_named(raw, rawts, int, S_IRUGO | S_IWUSR | S_IWGRP);
static void msm_ts_predma_callback(struct fb_info *fb, struct msmfb_update_area *area)
{
int x, y;
/* Draw two red dots during calibration (in upper-left and lower-right corners) */
if (calib_step > 0 && calib_step < 3) {
struct fb_info *fb = fb_helper_get_first_fb();
for (x = 0;x < 3;x++) {
for (y = 0;y < 3;y++) {
fb_helper_plot(fb, x,y,0xF800);
fb_helper_plot(fb, MSM_TS_LCD_WIDTH - 1 - x, MSM_TS_LCD_HEIGHT - 1 - y, 0xF800);
}
}
/* Make it a full screen update */
area->x = 0;
area->y = 0;
area->width = fb->var.xres;
area->height = fb->var.yres;
}
}
static void msm_ts_process_irq1(struct work_struct *tmp_work)
{
msm_ts_process_data(INT_TCHSCRN1);
}
static void msm_ts_process_irq2(struct work_struct *tmp_work)
{
msm_ts_process_data(INT_TCHSCRN2);
}
static void msm_ts_process_timeout(struct work_struct *tmp_work)
{
#if MSM_TS_DEBUG
printk(KERN_DEBUG "msm_ts: release interrupt didn't fire, sending pen up event manually\n");
#endif
msm_ts_process_data(0);
}
static void msm_ts_process_data(int irq)
{
unsigned long status, data;
int absx, absy, touched, x=0, y=0;
int vkey=0, bspad=0;
static int prev_absx = -1, prev_absy = -1, prev_touched = -1;
unsigned long data2;
int x2,y2,ax,bx,ay,by,cx,cy,size;
/* Read status and data */
status = readl(MSM_TS_BASE + TSSC_STATUS);
data = readl(MSM_TS_BASE + TSSC_DATA_LO_AVE);
/* Get stylus position and press state */
absx = data & 0xFFFF;
absy = data >> 16;
//touched = status & 0x100 ? 1 : 0;
touched = status & 0x200 ? 0 : 1; // The 0x200 flag seems to be more reliable
/* When pen released, we can disable our timeout */
if (!touched) {
cancel_delayed_work(&msm_ts_work_timeout);
}
/* When an interrupt timeout was reached, we assume pen released */
if (!irq) {
absx = absy = touched = 0;
}
/* Filter invalid/unreliable data. Based on:
* - When touched, the 0x800 flag must be present in CTL. We remove the 0x800 flag when we're done with it.
* - When touched, we verify that the 0x2000 flag is present in STATUS. When this is not the case, it has been seen there are some weird
* x/y values. Perhaps the hardware is updating while that flag is gone? The 0x800 flag is present in this case, which is why
* that check is not sufficient.
*/
if (touched && (readl(MSM_TS_BASE + TSSC_CTL) & 0x800) == 0) {
#if MSM_TS_DEBUG
printk(KERN_DEBUG "msm_ts: invalid data (no 0x800 flag in CTL)\n");
#endif
goto skip;
}
if (touched && (status & 0x2000) == 0) {
#if MSM_TS_DEBUG
printk(KERN_DEBUG "msm_ts: invalid data (no 0x2000 flag in STATUS)\n");
#endif
goto skip;
}
/* Only do something when the touch state or position have changed */
if (absx != prev_absx || absy != prev_absy || touched != prev_touched) {
/* First three tap are to calibrate upper-left and lower-right corners */
if (calib_step < 3 && !rawts) {
if (touched && !prev_touched) {
if (calib_step == 1) {
/* This is upper-left corner */
calib_xmax = absx;
calib_ymin = absy;
printk(KERN_WARNING "msm_ts: maxx=%04x miny=%04x\n", calib_xmax, calib_ymin);
printk(KERN_WARNING "Calibration step 2: tap red dot in lower-right corner\n");
} else if(calib_step == 2) {
/* This is lower-right corner */
calib_xmin = absx;
calib_ymax = absy;
printk(KERN_WARNING "msm_ts: minx=%04x maxy=%04x\n", calib_xmin, calib_ymax);
printk(KERN_WARNING "Calibration successful!\n\n# ");
} else {
printk(KERN_WARNING "Calibration step 1: tap red dot in upper-left corner\n");
}
calib_step++;
}
} else {
/* On stylus up, use same coordinates as last position we had (since they're 0 otherwise) */
if (touched) {
data2 = readl(MSM_TS_BASE + TSSC_DATA_UP_AVE);
x2 = data2 & 0xFFFF;
y2 = data2 >> 16;
if (!x2 || !y2)
goto skip;
ax = 300 - 100 * (absx + 6 * y2 / 11 - 200) / x2;
ay = -240 + 100 * (absy + 7 * x2 / 10 + 1100) / y2;
bx = -110 - 200 * (absx - 3 * x2 - 200) / y2;
by = 70 + 100 * (absy - 12 * y2 / 5 + 1100) / x2;
cx = 200 - absx + 3 * x2 - 6 * y2 / 11;
cy = 1100 + absy - 12 * y2 / 5 + 7 * x2 / 10;
size = (ax+bx+cx+ay+by+cy - 200) / 64;
if (size <= MSM_TS_ABS_SIZE_MIN)
size = MSM_TS_ABS_SIZE_MIN + 1;
else if (size > MSM_TS_ABS_SIZE_MAX)
size = MSM_TS_ABS_SIZE_MAX;
// printk(KERN_INFO "TS: %3d %3d %3d %3d %3d %3d %4d\n",
// ax,bx,cx,ay,by,cy,size);
} else {
absx = prev_absx;
absy = prev_absy;
size = MSM_TS_ABS_SIZE_MIN;
}
/* Calculate coordinates in pixels, clip to screen and make sure we don't to divisions by zero */
if(!rawts) {
x = MSM_TS_LCD_WIDTH - 1 - (absx - calib_xmin) * MSM_TS_LCD_WIDTH / (calib_xmax == calib_xmin ? MSM_TS_LCD_HEIGHT : calib_xmax - calib_xmin);
if (x < 0) x = 0;
if (x >= MSM_TS_LCD_WIDTH) x = MSM_TS_LCD_WIDTH - 1;
y = (absy - calib_ymin) * MSM_TS_LCD_HEIGHT / (calib_ymax == calib_ymin ? MSM_TS_LCD_HEIGHT : calib_ymax - calib_ymin);
if (y < 0) y = 0;
if (y >= MSM_TS_LCD_HEIGHT) y = MSM_TS_LCD_HEIGHT - 1;
/* Call our handler if it's registered -- the virtual keyboards gets data from this */
if (msm_ts_handler_pad && !rawts) {
bspad = (*msm_ts_handler_pad)(x, y, prev_touched);
} else {
bspad = 0;
}
if (msm_ts_handler && !rawts) {
vkey = (*msm_ts_handler)(x, y, touched);
} else {
vkey = 0;
}
#if MSM_TS_DEBUG
printk(KERN_DEBUG "msm_ts: x=%d,y=%d,t=%d,vkeyb=%d\n", x, y, touched, vkey);
#endif
} else {
#if MSM_TS_DEBUG
printk(KERN_DEBUG "msm_ts: absx=%d,absy=%d,t=%d\n", absx, absy, touched);
#endif
}
/* Send data to linux input system, if not eaten by vkeyb */
if(rawts) {
input_report_abs(msm_ts_dev, ABS_X, absx);
input_report_abs(msm_ts_dev, ABS_Y, absy);
input_report_abs(msm_ts_dev, ABS_PRESSURE, touched ? MSM_TS_ABS_PRESSURE_MAX : MSM_TS_ABS_PRESSURE_MIN);
input_report_abs(msm_ts_dev, ABS_TOOL_WIDTH, size);
input_report_key(msm_ts_dev, BTN_TOUCH, touched);
input_sync(msm_ts_dev);
} else if (!(vkey || bspad)) {
input_report_abs(msm_ts_dev, ABS_X, x);
input_report_abs(msm_ts_dev, ABS_Y, y);
input_report_abs(msm_ts_dev, ABS_PRESSURE, touched ? MSM_TS_ABS_PRESSURE_MAX : MSM_TS_ABS_PRESSURE_MIN);
input_report_abs(msm_ts_dev, ABS_TOOL_WIDTH, size);
input_report_key(msm_ts_dev, BTN_TOUCH, touched);
input_sync(msm_ts_dev);
}
}
/* Save the state so we won't report the same position and state twice */
prev_absx = touched ? absx : 0;
prev_absy = touched ? absy : 0;
prev_touched = touched;
}
skip:
/* Indicate to the hardware that we have handled the data and the touchscreen may update it again */
msleep(10);
if (irq) {
enable_irq(irq);
writel(readl(MSM_TS_BASE + TSSC_CTL) & ~0x800, MSM_TS_BASE + TSSC_CTL);
}
}
static irqreturn_t msm_ts_interrupt(int irq, void *dev)
{
// Disable the irq until we processed it.
disable_irq(irq);
// Schedule work based on which irq was triggered
switch (irq) {
case INT_TCHSCRN1:
schedule_work(&msm_ts_work_irq1);
break;
case INT_TCHSCRN2:
schedule_work(&msm_ts_work_irq2);
break;
}
// Reset the timeout. When we don't receive irq's for a little while, we assume the pen no longer touches the surface. As this
// is not always notified by an irq, we have a fallback in which we timeout.
cancel_delayed_work(&msm_ts_work_timeout);
schedule_delayed_work(&msm_ts_work_timeout, HZ / 5);
return IRQ_HANDLED;
}
static int __init msm_ts_init(void)
{
int err;
#if defined CONFIG_TOUCHSCREEN_TSSC_MANAGER
if(!machine_is_htckovsky()) {
printk("\"Old\" touchscreen driver called for a non-blackstone device\n");
printk("If you really want that, edit the msm_ts.c file and delete this check\n");
return 0;
}
#endif
printk(KERN_INFO "msm_ts: initing\n");
/* We depend on a framebuffer for painting calibration dots */
if (num_registered_fb == 0 && !rawts) {
printk(KERN_INFO "msm_ts: no framebuffer registered, cannot paint calibration dots\n");
}
/* Remove the 0x800 flag, in case they were still set, which would prevent us from getting interrupts */
writel(readl(MSM_TS_BASE + TSSC_CTL) & ~0x800, MSM_TS_BASE + TSSC_CTL);
/* Configure input device */
msm_ts_dev = input_allocate_device();
if (!msm_ts_dev)
return -ENOMEM;
msm_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
msm_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
if(!rawts) {
input_set_abs_params(msm_ts_dev, ABS_X, MSM_TS_ABS_X_MIN, MSM_TS_ABS_X_MAX, 0, 0);
input_set_abs_params(msm_ts_dev, ABS_Y, MSM_TS_ABS_Y_MIN, MSM_TS_ABS_Y_MAX, 0, 0);
} else {
input_set_abs_params(msm_ts_dev, ABS_X, 0, 0xffff, 0, 0);
input_set_abs_params(msm_ts_dev, ABS_Y, 0, 0xffff, 0, 0);
}
input_set_abs_params(msm_ts_dev, ABS_PRESSURE, MSM_TS_ABS_PRESSURE_MIN, MSM_TS_ABS_PRESSURE_MAX, 0, 0);
input_set_abs_params(msm_ts_dev, ABS_TOOL_WIDTH, MSM_TS_ABS_SIZE_MIN, MSM_TS_ABS_SIZE_MAX, 0, 0);
msm_ts_dev->name = "MSM touchscreen";
msm_ts_dev->phys = "msm_ts/input0";
/* Register the interrupt handler. This IRQ is fired when a touch is detected */
if (request_irq(INT_TCHSCRN1, msm_ts_interrupt, IRQF_TRIGGER_FALLING, "msm_ts", 0) < 0) {
printk(KERN_ERR "msm_ts: can't allocate irq %d\n", INT_TCHSCRN1);
err = -EBUSY;
goto fail1;
}
/* This IRQ is fired when a release is detected. It is not 100% reliable. */
if (request_irq(INT_TCHSCRN2, msm_ts_interrupt, IRQF_TRIGGER_FALLING, "msm_ts", 0) < 0) {
printk(KERN_ERR "msm_ts: can't allocate irq %d\n", INT_TCHSCRN2);
err = -EBUSY;
goto fail2;
}
/* Register the input device */
err = input_register_device(msm_ts_dev);
if (err)
goto fail3;
/* Register the msmfb pre-dma callback */
if(!rawts) {
if (msmfb_predma_register_callback(msm_ts_predma_callback) != 0) {
printk(KERN_WARNING "msm_ts: unable to register pre-dma callback, calibration dots cannot be drawn\n");
}
}
/* Done */
printk(KERN_WARNING "msm_ts: init successful\n");
return 0;
fail3:
free_irq(INT_TCHSCRN2, NULL);
fail2:
free_irq(INT_TCHSCRN1, NULL);
cancel_delayed_work(&msm_ts_work_timeout);
flush_scheduled_work();
fail1:
input_free_device(msm_ts_dev);
return err;
}
static void __exit msm_ts_exit(void)
{
msmfb_predma_unregister_callback(msm_ts_predma_callback);
free_irq(INT_TCHSCRN1, NULL);
cancel_delayed_work(&msm_ts_work_timeout);
flush_scheduled_work();
input_unregister_device(msm_ts_dev);
}
module_init(msm_ts_init);
module_exit(msm_ts_exit);
MODULE_AUTHOR("Octavian Voicu, octavian.voicu@gmail.com");
MODULE_DESCRIPTION("MSM touchscreen driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,268 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/mach-types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
//#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include "tssc.h"
#define MAGIC 0x81
#define TP_IOC_GETMFG _IOR(MAGIC, 1, unsigned long)
extern char *get_tp_cal_ram(void);
int tp_get_cal(unsigned char *data)
{
unsigned char *cal, i;
cal = get_tp_cal_ram();
for(i=0; i<32; i++)
printk("%2x ", *cal++);
printk("\n");
if (copy_to_user(data, cal, 32))
return -EFAULT;
return 0;
}
/* calibration read func */
static int tp_calibration_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
unsigned char *cal, i, data1='1';
int len;
printk("tp_calibration_read():\n");
cal = get_tp_cal_ram();
for(i=0; i<32; i++)
printk("%2x ", *cal++);
printk("\n");
if (cal) {
//memcpy((void *)page, (void *) cal, 32+0x40);
//len = sprintf(page, "%x\n", cal);
len = sprintf(page, "%c\n", data1);
}
else {
printk("%s - no calibration data\n", __FUNCTION__);
return -EIO;
}
return 0;
}
static int tp_calibration_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
printk("%s do nothing\n", __FUNCTION__);
return 0;
}
#if 0
/* most content happens here */
static int tp_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int error = 0;
int retval = 0;
switch(cmd) {
case TP_IOC_GETMFG:
retval = get_tp_cal_ram(req.buf);
break;
default:
printk("tp: unknown command\n");
return -ENOTTY;
};
return retval;
}
int tp_read(struct file *filp, char *buf, size_t count,loff_t *f_pos)
{
unsigned char *cal, i;
printk("tp_read():\n");
cal = get_tp_cal_ram();
for(i=0; i<32; i++)
printk("%2x ", *cal++);
printk("\n");
if(
copy_to_user(buf, cal ,count)
)
{
printk("tp_read():err\n");
}
else
{
printk("tp_read():ok\n");
}
return 0;
}
#endif
/*
* Display the coordinates of the calibration screen points.
*/
ssize_t calibration_mfg_show(char *buf)
{
unsigned char *cal, i;
typedef struct _TP_CAL_IN_FLASH
{
unsigned short x1;
unsigned short y1;
unsigned short x2;
unsigned short y2;
unsigned short x3;
unsigned short y3;
unsigned short x4;
unsigned short y4;
unsigned short x5;
unsigned short y5;
unsigned long crc;
}TP_CAL_IN_FLASH, *PTP_CAL_IN_FLASH;
PTP_CAL_IN_FLASH pTpCal;
pTpCal = (PTP_CAL_IN_FLASH) get_tp_cal_ram();
printk("calibration_mfg_show():\n");
cal = get_tp_cal_ram();
for(i=0; i<32; i++)
printk("%2x ", *cal++);
printk("\n");
printk("calibration_mfg_show(): %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%lx\n",
pTpCal->x1,
pTpCal->y1,
pTpCal->x2,
pTpCal->y2,
pTpCal->x3,
pTpCal->y3,
pTpCal->x4,
pTpCal->y4,
pTpCal->x5,
pTpCal->y5,
pTpCal->crc);
//return sprintf(buf, "%d,",*cal);
//return sprintf(buf, "%d,",pTpCal->x1);
#if 0
int n=sprintf(buf, "%d\n",i);
printk(buf, "%d\n",i);
return n;
#endif
#if 1
return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%lx\n",
pTpCal->x1,
pTpCal->y1,
pTpCal->x2,
pTpCal->y2,
pTpCal->x3,
pTpCal->y3,
pTpCal->x4,
pTpCal->y4,
pTpCal->x5,
pTpCal->y5,
pTpCal->crc);
#endif
}
/*
* Store the coordinates of the calibration screen points.
*/
void calibration_mfg_store(const char *buf)
{
printk("Writing to calibration_mfg is not supported\n");
}
static int tp_open(struct inode *inode, struct file *filp)
{
printk("tp_open():\n");
return nonseekable_open(inode, filp);
}
static int tp_release(struct inode *inode, struct file *filp)
{
printk("tp_release():\n");
return 0;
}
static struct file_operations tp_fops = {
.owner = THIS_MODULE,
// .ioctl = tp_ioctl,
.open = tp_open,
.release = tp_release,
};
static struct miscdevice tp_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "tp",
.fops = &tp_fops,
};
static int tp_init_module(void)
{
int rc;
struct proc_dir_entry *proc_tp;
printk("tp_init_module():\n");
printk("TP_IOC_GETMFG=%d\n\n", TP_IOC_GETMFG);
rc = misc_register(&tp_device);
if (rc) {
printk(KERN_ERR "misc_register(): fail\n");
return rc;
}
else
printk(KERN_ERR "misc_register(): OK\n");
proc_tp = create_proc_entry("tp_cal", 0644, NULL);
if (!proc_tp) {
printk(KERN_ERR "tp: alloc calibration error\n");
rc = PTR_ERR(proc_tp);
if (misc_deregister(&tp_device))
printk(KERN_ERR "tp: deregister fail\n");
return rc;
}
proc_tp->read_proc = &tp_calibration_read;
proc_tp->write_proc = &tp_calibration_write;
return 0;
}
static void tp_exit_module(void)
{
if (misc_deregister(&tp_device))
printk("tp: deregister fail\n");
else
printk("tp_exit_module: OK");
//remove_proc_entry("tp_calibration", NULL);
}
module_init(tp_init_module);
module_exit(tp_exit_module);
MODULE_AUTHOR("zion_huang@htc.com");
MODULE_LICENSE("HTC");

View File

@@ -0,0 +1,203 @@
/* tssc.h
*/
#ifndef __LINUX_TSSC_H
#define __LINUX_TSSC_H
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/sizes.h>
#define TP_X_MIN 0
#define TP_X_MAX 1023
#define TP_Y_MIN 0
#define TP_Y_MAX 1023
struct tssc_ts_platform_data {
int swapped;
int x_reversed;
int y_reversed;
int x_min;
int x_max;
int y_min;
int y_max;
};
struct tssc_ssbi_priorities {
unsigned long priority0 : 3;
unsigned long priority1 : 3;
unsigned long priority2 : 3;
unsigned long reserved : 23;
};
struct tssc_ssbi {
volatile unsigned long ctl;
volatile unsigned long reset;
volatile unsigned long cmd;
volatile unsigned long bypass;
volatile unsigned long rd;
volatile unsigned long status;
volatile struct tssc_ssbi_priorities priorities;
};
struct tssc_ctl {
unsigned long enable : 1;
unsigned long command_wr : 1;
unsigned long tssc_sw_reset : 1;
unsigned long mode : 2;
unsigned long en_average : 1;
unsigned long debounce_en : 1;
unsigned long debounce_time : 3;
unsigned long intr_flag1 : 1;
unsigned long data_flag : 1;
unsigned long intr_flag2 : 1;
unsigned long reserved31_13 : 19;
};
struct tssc_opn {
unsigned long resolution1 : 2;
unsigned long resolution2 : 2;
unsigned long resolution3 : 2;
unsigned long resolution4 : 2;
unsigned long num_sample1 : 2;
unsigned long num_sample2 : 2;
unsigned long num_sample3 : 2;
unsigned long num_sample4 : 2;
unsigned long operation1 : 4;
unsigned long operation2 : 4;
unsigned long operation3 : 4;
unsigned long operation4 : 4;
};
struct tssc_sampling_int {
unsigned long sampling_int : 5;
unsigned long reserved31_5 : 27;
};
struct tssc_status {
unsigned long error : 1;
unsigned long samples_collected : 5;
unsigned long operation : 3;
unsigned long penirq_status : 1;
unsigned long adc_eoc_status : 1;
unsigned long error_code : 2;
unsigned long busy : 1;
unsigned long tssc_fsm_state : 4;
unsigned long tssc_ssbi_fsm_state : 3;
unsigned long reserved31_21 : 11;
};
struct tssc_avg_12 {
unsigned long samples_avg_1 : 16;
unsigned long samples_avg_2 : 16;
};
struct tssc_avg_34 {
unsigned long samples_avg_3 : 16;
unsigned long samples_avg_4 : 16;
};
struct tssc_sample_1 {
unsigned long raw_sample_1 : 16;
unsigned long raw_sample_2 : 16;
};
struct tssc_sample_2 {
unsigned long raw_sample_3 : 16;
unsigned long raw_sample_4 : 16;
};
struct tssc_sample_3 {
unsigned long raw_sample_5 : 16;
unsigned long raw_sample_6 : 16;
};
struct tssc_sample_4 {
unsigned long raw_sample_7 : 16;
unsigned long raw_sample_8 : 16;
};
struct tssc_sample_5 {
unsigned long raw_sample_9 : 16;
unsigned long raw_sample_10 : 16;
};
struct tssc_sample_6 {
unsigned long raw_sample_11 : 16;
unsigned long raw_sample_12 : 16;
};
struct tssc_sample_7 {
unsigned long raw_sample_13 : 16;
unsigned long raw_sample_14 : 16;
};
struct tssc_sample_8 {
unsigned long raw_sample_15 : 16;
unsigned long raw_sample_16 : 16;
};
struct tssc_test_1 {
unsigned long test_penirq_n : 1;
unsigned long test_mode : 1;
unsigned long gate_debounce_en : 1;
unsigned long reserved_bits23_3 : 21;
unsigned long test_ssbi_rd_data : 8;
};
struct tssc_software_register {
volatile struct tssc_ctl tssc_ctl;
volatile struct tssc_opn tssc_opn;
volatile struct tssc_sampling_int tssc_sampling_int;
volatile struct tssc_status tssc_status;
volatile struct tssc_avg_12 tssc_avg_12;
volatile struct tssc_avg_34 tssc_avg_34;
volatile struct tssc_sample_1 tssc_sample_1_1;
volatile struct tssc_sample_2 tssc_sample_1_2;
volatile struct tssc_sample_3 tssc_sample_1_3;
volatile struct tssc_sample_4 tssc_sample_1_4;
volatile struct tssc_sample_5 tssc_sample_1_5;
volatile struct tssc_sample_6 tssc_sample_1_6;
volatile struct tssc_sample_7 tssc_sample_1_7;
volatile struct tssc_sample_8 tssc_sample_1_8;
volatile struct tssc_sample_1 tssc_sample_2_1;
volatile struct tssc_sample_2 tssc_sample_2_2;
volatile struct tssc_sample_3 tssc_sample_2_3;
volatile struct tssc_sample_4 tssc_sample_2_4;
volatile struct tssc_sample_5 tssc_sample_2_5;
volatile struct tssc_sample_6 tssc_sample_2_6;
volatile struct tssc_sample_7 tssc_sample_2_7;
volatile struct tssc_sample_8 tssc_sample_2_8;
volatile struct tssc_sample_1 tssc_sample_3_1;
volatile struct tssc_sample_2 tssc_sample_3_2;
volatile struct tssc_sample_3 tssc_sample_3_3;
volatile struct tssc_sample_4 tssc_sample_3_4;
volatile struct tssc_sample_5 tssc_sample_3_5;
volatile struct tssc_sample_6 tssc_sample_3_6;
volatile struct tssc_sample_7 tssc_sample_3_7;
volatile struct tssc_sample_8 tssc_sample_3_8;
volatile struct tssc_sample_1 tssc_sample_4_1;
volatile struct tssc_sample_2 tssc_sample_4_2;
volatile struct tssc_sample_3 tssc_sample_4_3;
volatile struct tssc_sample_4 tssc_sample_4_4;
volatile struct tssc_sample_5 tssc_sample_4_5;
volatile struct tssc_sample_6 tssc_sample_4_6;
volatile struct tssc_sample_7 tssc_sample_4_7;
volatile struct tssc_sample_8 tssc_sample_4_8;
volatile struct tssc_test_1 tssc_test_1;
volatile unsigned long tssc_test_2;
};
// Calibration algorithm functions
ssize_t calibration_show(char *buf);
void calibration_store(const char *buf);
ssize_t calibration_points_show(char *buf);
void calibration_points_store(const char *buf);
ssize_t calibration_screen_show(char *buf);
void calibration_screen_store(const char *buf);
void calibration_init(void);
void calibration_check_mode(void);
void calibration_translate(int x, int y, int *rx, int *ry);
ssize_t calibration_mfg_show(char *buf);
void calibration_mfg_store(const char *buf);
#endif

View File

@@ -0,0 +1,632 @@
/* drivers/input/touchscreen/tssc_manager.c * * Copyright (C) 2008 HTC, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
/*#include <mach/iomap.h>*/
#include <mach/g900-gpio.h>
#include "tssc.h"
#include <linux/earlysuspend.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
static void tssc_manager_early_suspend(struct early_suspend *h);
static void tssc_manager_late_resume(struct early_suspend *h);
#endif
typedef int ts_handler_t(int, int, int);
ts_handler_t *ts_handler_pad; // blackstone handler
/// For calibration, display the reference points.
static ssize_t tssc_calibration_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return calibration_show(buf);
}
/// For calibration, store the reference points.
static ssize_t tssc_calibration_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
calibration_store(buf);
return count;
}
static ssize_t tssc_calibration_points_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return calibration_points_show(buf);
}
static ssize_t tssc_calibration_points_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
calibration_points_store(buf);
return count;
}
static ssize_t tssc_calibration_screen_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return calibration_screen_show(buf);
}
static ssize_t tssc_calibration_screen_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
calibration_screen_store(buf);
return count;
}
/*
static ssize_t tssc_calibration_mfg_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return calibration_mfg_show(buf);
}
static ssize_t tssc_calibration_mfg_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
calibration_mfg_store(buf);
return count;
}
*/
/// sys/class/input/input1/calibration
static DEVICE_ATTR(calibration, 0666, tssc_calibration_show, tssc_calibration_store);
/// sys/class/input/input1/calibration_points
static DEVICE_ATTR(calibration_points, 0666, tssc_calibration_points_show, tssc_calibration_points_store);
/// sys/class/input/input1/calibration_screen
static DEVICE_ATTR(calibration_screen, 0666, tssc_calibration_screen_show, tssc_calibration_screen_store);
/// sys/class/input/input1/calibration_mfg
//static DEVICE_ATTR(calibration_mfg, 0666, tssc_calibration_mfg_show, tssc_calibration_mfg_store);
#define TSSC_MANAGER_NAME "tssc-manager"
static unsigned int ts_irq_down = -1;
struct tssc_manager_data {
struct input_dev *input_dev;
int use_irq;
struct hrtimer timer;
struct work_struct work;
struct work_struct polling_work;
int x;
int x16;
int y;
int y16;
int z1;
int z2;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
};
//----------------------------------------------
#define ENABLE_TSSC_AVERAGE
#define TOUCH_POLLING_NSEC 8400000//9000000//
#define TOUCH_QUEUE_NUMBER 2//3
static long touch_sample_count = 0;
static long touch_report_count = 0;
static int touch_queue_index = 0;
static bool first_touch = true;
int touch_queue_x[TOUCH_QUEUE_NUMBER];
int touch_queue_y[TOUCH_QUEUE_NUMBER];
int touch_queue_p[TOUCH_QUEUE_NUMBER];
int touch_deviation_x[TOUCH_QUEUE_NUMBER];
int touch_deviation_y[TOUCH_QUEUE_NUMBER];
int touch_average_x;
int touch_average_y;
int touch_average_p;
long total_x = 0;
long total_y = 0;
#define TOUCH_MOVE_VALUE 30
#define XY_temp 7//10//5//
int touch_noise_index = TOUCH_QUEUE_NUMBER;
enum {
DEBUG_TP_OFF = 0,
DEBUG_TP_ON = 1,
};
static int debug_tp;
module_param_named(debug, debug_tp, int, S_IRUGO | S_IWUSR | S_IWGRP);
//----------------------------------------------
static int touch_check_noise(int x, int x16, int y, int y16, int p)
{
struct timespec ts;
struct rtc_time tm;
int X_temp=abs(x-x16);
int Y_temp=abs(y-y16);
if (x16>0 && y16>0) {
if ((X_temp>=XY_temp)||(Y_temp>=XY_temp)) {
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "touch_check_noise(): This is a noise point.\t");
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "x=%d y=%d x16=%d y16=%d\t", x, y, x16, y16);
getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec, &tm);
if(debug_tp & DEBUG_TP_ON) pr_info("(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
/*
* Add touch point data into the queue.
*/
static int touch_add_queue(int x, int x16, int y, int y16,int p)
{
if(touch_check_noise(x, x16, y, y16, p))
{
return 0;
}
touch_queue_x[touch_queue_index] = x;
touch_queue_y[touch_queue_index] = y;
touch_queue_p[touch_queue_index] = p;
touch_queue_index++;
if (touch_queue_index >= TOUCH_QUEUE_NUMBER)
touch_queue_index = 0;
//touch_sample_count++;
return ++touch_sample_count;
}
/*
* Report touch up input event.
*/
static void touch_input_up(struct input_dev *dev)
{
if (ts_handler_pad)
(*ts_handler_pad)(0, 0, 0);
if (touch_report_count > 0) {
input_report_abs(dev, ABS_PRESSURE, 0);
input_report_abs(dev, ABS_TOOL_WIDTH, 0);
input_report_key(dev, BTN_TOUCH, 0);
input_report_key(dev, BTN_2, 0);
input_sync(dev);
touch_report_count = 0; /* reset report count */
}
}
static void touch_get_average(void)
{
int i;
long total_x = 0;
long total_y = 0;
long total_p = 0;
for (i = 0; i < TOUCH_QUEUE_NUMBER; i++) {
total_x += touch_queue_x[i];
total_y += touch_queue_y[i];
total_p += touch_queue_p[i];
}
touch_average_x = total_x / TOUCH_QUEUE_NUMBER;
touch_average_y = total_y / TOUCH_QUEUE_NUMBER;
touch_average_p = total_p / TOUCH_QUEUE_NUMBER;
}
/*
* Process the current touch point in the queue.
*/
static void touch_process_queue(struct input_dev *dev)
{
int x = 0;
int y = 0;
int bspad = 0;
struct timespec ts;
struct rtc_time tm;
if (touch_sample_count <= 1) {
if (touch_sample_count == 1) {
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "touch_process_queue(): This is point #%ld.\t", touch_sample_count);
getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec, &tm);
if(debug_tp & DEBUG_TP_ON) pr_info("(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
}
return;
}
if (touch_sample_count >= TOUCH_QUEUE_NUMBER)
touch_get_average();
calibration_translate(touch_average_x, touch_average_y, &x, &y);
if (ts_handler_pad)
bspad = (*ts_handler_pad)(x, y, 1);
if (!bspad && x >= 0 && y >= 0) {
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "touch_process_queue(): x=%d\t", x);
input_report_abs(dev, ABS_X, x);
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "y=%d\t", y);
input_report_abs(dev, ABS_Y, y);
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "p=%d\n", touch_average_p);
input_report_abs(dev, ABS_PRESSURE, touch_average_p);
input_report_abs(dev, ABS_TOOL_WIDTH, 1);
input_report_key(dev, BTN_TOUCH, 1);
input_report_key(dev, BTN_2, 0);
input_sync(dev);
touch_report_count++;
}
}
/*
* Process the final touch points in the queue.
*/
static void touch_finish_queue(struct input_dev *dev)
{
touch_sample_count = 0;
touch_queue_index = 0;
touch_input_up(dev);
}
static void tssc_manager_work_func(struct work_struct *work)
{
struct tssc_manager_data *ts;
ts = container_of(work, struct tssc_manager_data, work);
hrtimer_start(&ts->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
}
static int tssc_manager_polling_func(struct tssc_manager_data *ts)
{
//struct tssc_manager_data *ts;
int pressure;
//ts = container_of(polling_work, struct tssc_manager_data, polling_work);
/***************************************************************************/
if(debug_tp & DEBUG_TP_ON) printk(KERN_DEBUG "tssc_manager_polling_func(): ts->z1=%d ts->z2=%d\n", ts->z1, ts->z2);
if (ts->z1) {
pressure = (ts->x * ((ts->z2 * 100 / ts->z1) - 100)) / 900;
//pressure = 350 - pressure;
pressure = 270 - pressure;
if (pressure <= 5)
pressure = 5; /* Report all touch points */
else if (pressure > 255)
pressure = 255;
} else {
pressure = 0;
//printk(KERN_DEBUG "tssc_manager_polling_func(): ts->z1==0\n");
}
if (ts->x!=0 && ts->y!=0 && ts->z1!=0 && ts->z2!=0 && pressure) {
if (touch_add_queue(ts->x, ts->x16, ts->y, ts->y16, pressure)) {
touch_process_queue(ts->input_dev);
}
} else {
//printk(KERN_DEBUG "tssc_manager_polling_func(): !(ts->x!=0 && ts->y!=0 && ts->z1!=0 && ts->z2!=0)\n");
//printk(KERN_DEBUG "tssc_manager_polling_func(): pressure==0)\n");
}
//if ((tssc_reg->tssc_status.penirq_status == 1) && (tssc_reg->tssc_status.busy == 0)) {
touch_finish_queue(ts->input_dev);
//hrtimer_cancel(&ts->timer);
enable_irq(ts_irq_down);
first_touch=true;
return 1;
//}
return 0;
}
static enum hrtimer_restart tssc_polling_timer_func (struct hrtimer *timer)
{
struct tssc_manager_data *ts = container_of(timer, struct tssc_manager_data, timer);
//schedule_work(&ts->polling_work);
if(!tssc_manager_polling_func(ts))
{
hrtimer_start(&ts->timer, ktime_set(0, TOUCH_POLLING_NSEC), HRTIMER_MODE_REL);
}
return HRTIMER_NORESTART;
}
static irqreturn_t tssc_manager_irq_down_handler(int irq, void *dev_id)
{
struct tssc_manager_data *ts = dev_id;
disable_irq(ts_irq_down);
schedule_work(&ts->work);
return IRQ_HANDLED;
}
static void tssc_power_on(void)
{
touch_sample_count = 0;
touch_report_count = 0;
touch_queue_index = 0;
}
static void tssc_power_off(void)
{
}
static int tssc_manager_input_init(void)
{
struct tssc_manager_data *ts;
int ret = 0;
int ret_down = 0;
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (ts == NULL) {
ret = -ENOMEM;
goto err_alloc_data_failed;
}
INIT_WORK(&ts->work, tssc_manager_work_func);
//INIT_WORK(&ts->polling_work, tssc_manager_polling_work_func);
tssc_power_on();
// Allocate input device.
ts->input_dev = input_allocate_device();
if (ts->input_dev == NULL) {
ret = -ENOMEM;
printk(KERN_ERR "tssc_manager_input_init: Failed to allocate input device\n");
goto err_input_dev_alloc_failed;
}
ts->input_dev->name = TSSC_MANAGER_NAME;
set_bit(EV_SYN, ts->input_dev->evbit);
set_bit(EV_KEY, ts->input_dev->evbit);
set_bit(BTN_TOUCH, ts->input_dev->keybit);
set_bit(BTN_2, ts->input_dev->keybit);
set_bit(EV_ABS, ts->input_dev->evbit);
// Set input parameters boundary.
input_set_abs_params(ts->input_dev, ABS_X, TP_X_MIN, TP_X_MAX, 0, 0);
input_set_abs_params(ts->input_dev, ABS_Y, TP_Y_MIN, TP_Y_MAX, 0, 0);
input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
input_set_abs_params(ts->input_dev, ABS_HAT0X, TP_X_MIN, TP_X_MAX, 0, 0);
input_set_abs_params(ts->input_dev, ABS_HAT0Y, TP_Y_MIN, TP_Y_MAX, 0, 0);
ret = input_register_device(ts->input_dev);
if (ret) {
printk(KERN_ERR "tssc_manager_input_init: Unable to register %s input device\n", ts->input_dev->name);
goto err_input_register_device_failed;
}
// Create device files.
ret = device_create_file(&ts->input_dev->dev, &dev_attr_calibration);
if (ret) {
printk(KERN_ERR "tssc_manager_input_init: Error to create calibration attribute\n");
goto err_input_register_device_failed;
}
ret = device_create_file(&ts->input_dev->dev, &dev_attr_calibration_points);
if (ret) {
printk(KERN_ERR "tssc_manager_input_init: Error to create calibration_points attribute\n");
goto err_input_register_device_failed;
}
ret = device_create_file(&ts->input_dev->dev, &dev_attr_calibration_screen);
if (ret) {
printk(KERN_ERR "tssc_manager_input_init: Error to create calibration_screen attribute\n");
goto err_input_register_device_failed;
}
/* ret = device_create_file(&ts->input_dev->dev, &dev_attr_calibration_mfg);
if (ret) {
printk(KERN_ERR "tssc_manager_input_init: Error to create calibration_mfg attribute\n");
goto err_input_register_device_failed;
}*/
if (ts_irq_down) {
ret_down = request_irq(ts_irq_down, tssc_manager_irq_down_handler,
IRQF_TRIGGER_RISING, TSSC_MANAGER_NAME, ts);
}
if (ret_down == 0) {
ts->use_irq = 1;
} else {
ts->use_irq = 0;
}
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts->timer.function = tssc_polling_timer_func ;
//hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
#ifdef CONFIG_HAS_EARLYSUSPEND
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ts->early_suspend.suspend = tssc_manager_early_suspend;
ts->early_suspend.resume = tssc_manager_late_resume;
register_early_suspend(&ts->early_suspend);
#endif
printk(KERN_INFO "tssc_manager_input_init: Start touchscreen %s in %s mode\n",
ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
calibration_init();
return 0;
err_input_register_device_failed:
input_free_device(ts->input_dev);
err_input_dev_alloc_failed:
kfree(ts);
err_alloc_data_failed:
return ret;
}
static int tssc_manager_probe(struct platform_device *platform_dev)
{
printk(KERN_INFO "tssc_manager_probe\n");
return tssc_manager_input_init();
}
static int tssc_manager_remove(struct platform_device *platform_dev)
{
struct tssc_manager_data *ts = dev_get_drvdata(&platform_dev->dev);
printk(KERN_INFO "tssc_manager_remove\n");
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&ts->early_suspend);
#endif
if (ts->use_irq) {
free_irq(ts_irq_down, ts);
}
hrtimer_cancel(&ts->timer);
input_unregister_device(ts->input_dev);
// Remove device files.
device_remove_file(&ts->input_dev->dev, &dev_attr_calibration);
device_remove_file(&ts->input_dev->dev, &dev_attr_calibration_points);
device_remove_file(&ts->input_dev->dev, &dev_attr_calibration_screen);
//device_remove_file(&ts->input_dev->dev, &dev_attr_calibration_mfg);
kfree(ts);
return 0;
}
static int tssc_manager_suspend(struct tssc_manager_data *ts, pm_message_t mesg)
{
if (ts->use_irq) {
disable_irq(ts_irq_down);
}
//hrtimer_cancel(&ts->timer);
//cancel_work_sync(&ts->work);
//cancel_work_sync(&ts->polling_work);
tssc_power_off();
return 0;
}
static int tssc_manager_resume(struct tssc_manager_data *ts)
{
printk(KERN_DEBUG "tssc_manager_resume(): ts->use_irq=%d\n", ts->use_irq);
tssc_power_on();
if (ts->use_irq) {
enable_irq(ts_irq_down);
}
//hrtimer_start(&ts->timer, ktime_set(0, TOUCH_POLLING_NSEC), HRTIMER_MODE_REL);
return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void tssc_manager_early_suspend(struct early_suspend *h)
{
struct tssc_manager_data *ts;
ts = container_of(h, struct tssc_manager_data, early_suspend);
tssc_manager_suspend(ts, PMSG_SUSPEND);
}
static void tssc_manager_late_resume(struct early_suspend *h)
{
struct tssc_manager_data *ts;
ts = container_of(h, struct tssc_manager_data, early_suspend);
tssc_manager_resume(ts);
}
#endif
static struct platform_driver tssc_manager_driver = {
.probe = tssc_manager_probe,
.remove = tssc_manager_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = tssc_manager_suspend,
.resume = tssc_manager_resume,
#endif
.driver = {
.name = TSSC_MANAGER_NAME,
},
};
static int __devinit tssc_manager_init(void)
{
int result = 0;
debug_tp = 1;
printk(KERN_INFO "tssc_manager_init\n");
result = platform_driver_register(&tssc_manager_driver);
if (result < 0)
printk(KERN_ERR "tssc_manager_init: platform_driver_register failed\n");
return result;
}
static void __exit tssc_manager_exit(void)
{
printk(KERN_ERR "tssc_manager_exit\n");
}
module_init(tssc_manager_init);
module_exit(tssc_manager_exit);
MODULE_DESCRIPTION("TSSC Manager Driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,13 @@
wlan-y += cfg.o
wlan-y += cmd.o
wlan-y += cmdresp.o
wlan-y += debugfs.o
wlan-y += ethtool.o
wlan-y += main.o
wlan-y += rx.o
wlan-y += tx.o
wlan-y += if_spi.o
wlan-$(CONFIG_G900_WIFI_MESH) += mesh.o
obj-$(CONFIG_G900_WIFI) += wlan.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
#ifndef __LBS_CFG80211_H__
#define __LBS_CFG80211_H__
struct device;
struct lbs_private;
struct regulatory_request;
struct wiphy;
struct wireless_dev *lbs_cfg_alloc(struct device *dev);
int lbs_cfg_register(struct lbs_private *priv);
void lbs_cfg_free(struct lbs_private *priv);
int lbs_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request);
void lbs_send_disconnect_notification(struct lbs_private *priv);
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
void lbs_scan_deinit(struct lbs_private *priv);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
/* Copyright (C) 2007, Red Hat, Inc. */
#ifndef _LBS_CMD_H_
#define _LBS_CMD_H_
#include <net/cfg80211.h>
#include "host.h"
#include "dev.h"
/* Command & response transfer between host and card */
struct cmd_ctrl_node {
struct list_head list;
int result;
/* command response */
int (*callback)(struct lbs_private *,
unsigned long,
struct cmd_header *);
unsigned long callback_arg;
/* command data */
struct cmd_header *cmdbuf;
/* wait queue */
u16 cmdwaitqwoken;
wait_queue_head_t cmdwait_q;
};
/* lbs_cmd() infers the size of the buffer to copy data back into, from
the size of the target of the pointer. Since the command to be sent
may often be smaller, that size is set in cmd->size by the caller.*/
#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
(cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
__lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
})
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size);
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg);
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg);
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *resp);
int lbs_allocate_cmd_buffer(struct lbs_private *priv);
int lbs_free_cmd_buffer(struct lbs_private *priv);
int lbs_execute_next_command(struct lbs_private *priv);
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
int result);
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
/* From cmdresp.c */
void lbs_mac_event_disconnected(struct lbs_private *priv);
/* Events */
int lbs_process_event(struct lbs_private *priv, u32 event);
/* Actual commands */
int lbs_update_hw_spec(struct lbs_private *priv);
int lbs_set_channel(struct lbs_private *priv, u8 channel);
int lbs_update_channel(struct lbs_private *priv);
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
struct wol_config *p_wol_config);
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
struct sleep_params *sp);
void lbs_ps_confirm_sleep(struct lbs_private *priv);
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
void lbs_set_mac_control(struct lbs_private *priv);
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
s16 *maxlevel);
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
/* Commands only used in wext.c, assoc. and scan.c */
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
int8_t p1, int8_t p2);
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
int8_t p2, int usesnr);
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
uint16_t cmd_action);
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep);
int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
int lbs_set_11d_domain_info(struct lbs_private *priv,
struct regulatory_request *request,
struct ieee80211_supported_band **bands);
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);
int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);
int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);
#endif /* _LBS_CMD_H */

View File

@@ -0,0 +1,343 @@
/**
* This file contains the handling of command
* responses as well as events generated by firmware.
*/
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <asm/unaligned.h>
#include <net/cfg80211.h>
#include "cfg.h"
#include "cmd.h"
/**
* @brief This function handles disconnect event. it
* reports disconnect to upper layer, clean tx/rx packets,
* reset link state etc.
*
* @param priv A pointer to struct lbs_private structure
* @return n/a
*/
void lbs_mac_event_disconnected(struct lbs_private *priv)
{
if (priv->connect_status != LBS_CONNECTED)
return;
lbs_deb_enter(LBS_DEB_ASSOC);
/*
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
* It causes problem in the Supplicant
*/
msleep_interruptible(1000);
if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
lbs_send_disconnect_notification(priv);
/* report disconnect to upper layer */
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
/* Free Tx and Rx packets */
kfree_skb(priv->currenttxskb);
priv->currenttxskb = NULL;
priv->tx_pending_len = 0;
priv->connect_status = LBS_DISCONNECTED;
if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
lbs_deb_leave(LBS_DEB_ASSOC);
}
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
{
uint16_t respcmd, curcmd;
struct cmd_header *resp;
int ret = 0;
unsigned long flags;
uint16_t result;
lbs_deb_enter(LBS_DEB_HOST);
mutex_lock(&priv->lock);
spin_lock_irqsave(&priv->driver_lock, flags);
if (!priv->cur_cmd) {
lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
ret = -1;
spin_unlock_irqrestore(&priv->driver_lock, flags);
goto done;
}
resp = (void *)data;
curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
respcmd, le16_to_cpu(resp->seqnum), len);
lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
if (respcmd != CMD_RET(curcmd) &&
respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
if (resp->result == cpu_to_le16(0x0004)) {
/* 0x0004 means -EAGAIN. Drop the response, let it time out
and be resubmitted */
lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
le16_to_cpu(resp->command));
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
/* Now we got response from FW, cancel the command timer */
del_timer(&priv->command_timer);
priv->cmd_timed_out = 0;
if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
u16 action = le16_to_cpu(psmode->action);
lbs_deb_host(
"CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
result, action);
if (result) {
lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n",
result);
/*
* We should not re-try enter-ps command in
* ad-hoc mode. It takes place in
* lbs_execute_next_command().
*/
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
action == PS_MODE_ACTION_ENTER_PS)
priv->psmode = LBS802_11POWERMODECAM;
} else if (action == PS_MODE_ACTION_ENTER_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_AWAKE;
lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
if (priv->connect_status != LBS_CONNECTED) {
/*
* When Deauth Event received before Enter_PS command
* response, We need to wake up the firmware.
*/
lbs_deb_host(
"disconnected, invoking lbs_ps_wakeup\n");
spin_unlock_irqrestore(&priv->driver_lock, flags);
mutex_unlock(&priv->lock);
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
false);
mutex_lock(&priv->lock);
spin_lock_irqsave(&priv->driver_lock, flags);
}
} else if (action == PS_MODE_ACTION_EXIT_PS) {
priv->needtowakeup = 0;
priv->psstate = PS_STATE_FULL_POWER;
lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
} else {
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
}
lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
goto done;
}
/* If the command is not successful, cleanup and return failure */
if ((result != 0 || !(respcmd & 0x8000))) {
lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
result, respcmd);
/*
* Handling errors here
*/
switch (respcmd) {
case CMD_RET(CMD_GET_HW_SPEC):
case CMD_RET(CMD_802_11_RESET):
lbs_deb_host("CMD_RESP: reset failed\n");
break;
}
lbs_complete_command(priv, priv->cur_cmd, result);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (priv->cur_cmd && priv->cur_cmd->callback) {
ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
resp);
}
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->cur_cmd) {
/* Clean up and Put current command back to cmdfreeq */
lbs_complete_command(priv, priv->cur_cmd, result);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
done:
mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
int lbs_process_event(struct lbs_private *priv, u32 event)
{
int ret = 0;
struct cmd_header cmd;
lbs_deb_enter(LBS_DEB_CMD);
switch (event) {
case MACREG_INT_CODE_LINK_SENSED:
lbs_deb_cmd("EVENT: link sensed\n");
break;
case MACREG_INT_CODE_DEAUTHENTICATED:
lbs_deb_cmd("EVENT: deauthenticated\n");
lbs_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_DISASSOCIATED:
lbs_deb_cmd("EVENT: disassociated\n");
lbs_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
lbs_deb_cmd("EVENT: link lost\n");
lbs_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_PS_SLEEP:
lbs_deb_cmd("EVENT: ps sleep\n");
/* handle unexpected PS SLEEP event */
if (priv->psstate == PS_STATE_FULL_POWER) {
lbs_deb_cmd(
"EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
break;
}
priv->psstate = PS_STATE_PRE_SLEEP;
lbs_ps_confirm_sleep(priv);
break;
case MACREG_INT_CODE_HOST_AWAKE:
lbs_deb_cmd("EVENT: host awake\n");
if (priv->reset_deep_sleep_wakeup)
priv->reset_deep_sleep_wakeup(priv);
priv->is_deep_sleep = 0;
lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
sizeof(cmd));
priv->is_host_sleep_activated = 0;
wake_up_interruptible(&priv->host_sleep_q);
break;
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
if (priv->reset_deep_sleep_wakeup)
priv->reset_deep_sleep_wakeup(priv);
lbs_deb_cmd("EVENT: ds awake\n");
priv->is_deep_sleep = 0;
priv->wakeup_dev_required = 0;
wake_up_interruptible(&priv->ds_awake_q);
break;
case MACREG_INT_CODE_PS_AWAKE:
lbs_deb_cmd("EVENT: ps awake\n");
/* handle unexpected PS AWAKE event */
if (priv->psstate == PS_STATE_FULL_POWER) {
lbs_deb_cmd(
"EVENT: In FULL POWER mode - ignore PS AWAKE\n");
break;
}
priv->psstate = PS_STATE_AWAKE;
if (priv->needtowakeup) {
/*
* wait for the command processing to finish
* before resuming sending
* priv->needtowakeup will be set to FALSE
* in lbs_ps_wakeup()
*/
lbs_deb_cmd("waking up ...\n");
lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
}
break;
case MACREG_INT_CODE_MIC_ERR_UNICAST:
lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
lbs_send_mic_failureevent(priv, event);
break;
case MACREG_INT_CODE_MIC_ERR_MULTICAST:
lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
lbs_send_mic_failureevent(priv, event);
break;
case MACREG_INT_CODE_MIB_CHANGED:
lbs_deb_cmd("EVENT: MIB CHANGED\n");
break;
case MACREG_INT_CODE_INIT_DONE:
lbs_deb_cmd("EVENT: INIT DONE\n");
break;
case MACREG_INT_CODE_ADHOC_BCN_LOST:
lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
break;
case MACREG_INT_CODE_RSSI_LOW:
lbs_pr_alert("EVENT: rssi low\n");
break;
case MACREG_INT_CODE_SNR_LOW:
lbs_pr_alert("EVENT: snr low\n");
break;
case MACREG_INT_CODE_MAX_FAIL:
lbs_pr_alert("EVENT: max fail\n");
break;
case MACREG_INT_CODE_RSSI_HIGH:
lbs_pr_alert("EVENT: rssi high\n");
break;
case MACREG_INT_CODE_SNR_HIGH:
lbs_pr_alert("EVENT: snr high\n");
break;
case MACREG_INT_CODE_MESH_AUTO_STARTED:
/* Ignore spurious autostart events */
lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n");
break;
default:
lbs_pr_alert("EVENT: unknown event id %d\n", event);
break;
}
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}

View File

@@ -0,0 +1,987 @@
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "decl.h"
#include "cmd.h"
#include "debugfs.h"
static struct dentry *lbs_dir;
static char *szStates[] = {
"Connected",
"Disconnected"
};
#ifdef PROC_DEBUG
static void lbs_debug_init(struct lbs_private *priv);
#endif
static int open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t write_file_dummy(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return -EINVAL;
}
static const size_t len = PAGE_SIZE;
static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
size_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
ssize_t res;
if (!buf)
return -ENOMEM;
pos += snprintf(buf+pos, len-pos, "state = %s\n",
szStates[priv->connect_status]);
pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
(u32) priv->regioncode);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return res;
}
static ssize_t lbs_sleepparams_write(struct file *file,
const char __user *user_buf, size_t count,
loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t buf_size, ret;
struct sleep_params sp;
int p1, p2, p3, p4, p5, p6;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, user_buf, buf_size)) {
ret = -EFAULT;
goto out_unlock;
}
ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
if (ret != 6) {
ret = -EINVAL;
goto out_unlock;
}
sp.sp_error = p1;
sp.sp_offset = p2;
sp.sp_stabletime = p3;
sp.sp_calcontrol = p4;
sp.sp_extsleepclk = p5;
sp.sp_reserved = p6;
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
if (!ret)
ret = count;
else if (ret > 0)
ret = -EINVAL;
out_unlock:
free_page(addr);
return ret;
}
static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t ret;
size_t pos = 0;
struct sleep_params sp;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
if (ret)
goto out_unlock;
pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
sp.sp_offset, sp.sp_stabletime,
sp.sp_calcontrol, sp.sp_extsleepclk,
sp.sp_reserved);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
out_unlock:
free_page(addr);
return ret;
}
static ssize_t lbs_host_sleep_write(struct file *file,
const char __user *user_buf, size_t count,
loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t buf_size, ret;
int host_sleep;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, user_buf, buf_size)) {
ret = -EFAULT;
goto out_unlock;
}
ret = sscanf(buf, "%d", &host_sleep);
if (ret != 1) {
ret = -EINVAL;
goto out_unlock;
}
if (host_sleep == 0)
ret = lbs_set_host_sleep(priv, 0);
else if (host_sleep == 1) {
if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
lbs_pr_info("wake parameters not configured");
ret = -EINVAL;
goto out_unlock;
}
ret = lbs_set_host_sleep(priv, 1);
} else {
lbs_pr_err("invalid option\n");
ret = -EINVAL;
}
if (!ret)
ret = count;
out_unlock:
free_page(addr);
return ret;
}
static ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t ret;
size_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return ret;
}
/*
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
* get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
* firmware. Here's an example:
* 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
* 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
* The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
* 00 00 are the data bytes of this TLV. For this TLV, their meaning is
* defined in mrvlietypes_thresholds
*
* This function searches in this TLV data chunk for a given TLV type
* and returns a pointer to the first data byte of the TLV, or to NULL
* if the TLV hasn't been found.
*/
static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
{
struct mrvl_ie_header *tlv_h;
uint16_t length;
ssize_t pos = 0;
while (pos < size) {
tlv_h = (struct mrvl_ie_header *) tlv;
if (!tlv_h->len)
return NULL;
if (tlv_h->type == cpu_to_le16(tlv_type))
return tlv_h;
length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
pos += length;
tlv += length;
}
return NULL;
}
static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct cmd_ds_802_11_subscribe_event *subscribed;
struct mrvl_ie_thresholds *got;
struct lbs_private *priv = file->private_data;
ssize_t ret = 0;
size_t pos = 0;
char *buf;
u8 value;
u8 freq;
int events = 0;
buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
if (!subscribed) {
ret = -ENOMEM;
goto out_page;
}
subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
subscribed->action = cpu_to_le16(CMD_ACT_GET);
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
if (ret)
goto out_cmd;
got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
if (got) {
value = got->value;
freq = got->freq;
events = le16_to_cpu(subscribed->events);
pos += snprintf(buf, len, "%d %d %d\n", value, freq,
!!(events & event_mask));
}
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
out_cmd:
kfree(subscribed);
out_page:
free_page((unsigned long)buf);
return ret;
}
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
struct file *file,
const char __user *userbuf, size_t count,
loff_t *ppos)
{
struct cmd_ds_802_11_subscribe_event *events;
struct mrvl_ie_thresholds *tlv;
struct lbs_private *priv = file->private_data;
ssize_t buf_size;
int value, freq, new_mask;
uint16_t curr_mask;
char *buf;
int ret;
buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
ret = -EFAULT;
goto out_page;
}
ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
if (ret != 3) {
ret = -EINVAL;
goto out_page;
}
events = kzalloc(sizeof(*events), GFP_KERNEL);
if (!events) {
ret = -ENOMEM;
goto out_page;
}
events->hdr.size = cpu_to_le16(sizeof(*events));
events->action = cpu_to_le16(CMD_ACT_GET);
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
if (ret)
goto out_events;
curr_mask = le16_to_cpu(events->events);
if (new_mask)
new_mask = curr_mask | event_mask;
else
new_mask = curr_mask & ~event_mask;
/* Now everything is set and we can send stuff down to the firmware */
tlv = (void *)events->tlv;
events->action = cpu_to_le16(CMD_ACT_SET);
events->events = cpu_to_le16(new_mask);
tlv->header.type = cpu_to_le16(tlv_type);
tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
tlv->value = value;
if (tlv_type != TLV_TYPE_BCNMISS)
tlv->freq = freq;
/* The command header, the action, the event mask, and one TLV */
events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
if (!ret)
ret = count;
out_events:
kfree(events);
out_page:
free_page((unsigned long)buf);
return ret;
}
static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
file, userbuf, count, ppos);
}
static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
file, userbuf, count, ppos);
}
static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
file, userbuf, count, ppos);
}
static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
file, userbuf, count, ppos);
}
static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
file, userbuf, count, ppos);
}
static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
file, userbuf, count, ppos);
}
static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
file, userbuf, count, ppos);
}
static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
file, userbuf, count, ppos);
}
static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
file, userbuf, count, ppos);
}
static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
file, userbuf, count, ppos);
}
static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
file, userbuf, count, ppos);
}
static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
file, userbuf, count, ppos);
}
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
u32 val = 0;
if (!buf)
return -ENOMEM;
ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
mdelay(10);
if (!ret) {
pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
priv->mac_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
return ret;
}
static ssize_t lbs_rdmac_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_wrmac_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%x %x", &offset, &value);
if (res != 2) {
res = -EFAULT;
goto out_unlock;
}
res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
u32 val;
if (!buf)
return -ENOMEM;
ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
mdelay(10);
if (!ret) {
pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
priv->bbp_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
return ret;
}
static ssize_t lbs_rdbbp_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_wrbbp_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%x %x", &offset, &value);
if (res != 2) {
res = -EFAULT;
goto out_unlock;
}
res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
u32 val;
if (!buf)
return -ENOMEM;
ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
mdelay(10);
if (!ret) {
pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
priv->rf_offset, val);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
}
free_page(addr);
return ret;
}
static ssize_t lbs_rdrf_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
priv->rf_offset = simple_strtoul(buf, NULL, 16);
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_wrrf_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%x %x", &offset, &value);
if (res != 2) {
res = -EFAULT;
goto out_unlock;
}
res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
mdelay(10);
if (!res)
res = count;
out_unlock:
free_page(addr);
return res;
}
#define FOPS(fread, fwrite) { \
.owner = THIS_MODULE, \
.open = open_file_generic, \
.read = (fread), \
.write = (fwrite), \
}
struct lbs_debugfs_files {
const char *name;
int perm;
struct file_operations fops;
};
static const struct lbs_debugfs_files debugfs_files[] = {
{ "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
{ "hostsleep", 0644, FOPS(lbs_host_sleep_read,
lbs_host_sleep_write), },
};
static const struct lbs_debugfs_files debugfs_events_files[] = {
{"low_rssi", 0644, FOPS(lbs_lowrssi_read,
lbs_lowrssi_write), },
{"low_snr", 0644, FOPS(lbs_lowsnr_read,
lbs_lowsnr_write), },
{"failure_count", 0644, FOPS(lbs_failcount_read,
lbs_failcount_write), },
{"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
lbs_bcnmiss_write), },
{"high_rssi", 0644, FOPS(lbs_highrssi_read,
lbs_highrssi_write), },
{"high_snr", 0644, FOPS(lbs_highsnr_read,
lbs_highsnr_write), },
};
static const struct lbs_debugfs_files debugfs_regs_files[] = {
{"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
{"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
{"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
{"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
{"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
{"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
};
void lbs_debugfs_init(void)
{
if (!lbs_dir)
lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
}
void lbs_debugfs_remove(void)
{
if (lbs_dir)
debugfs_remove(lbs_dir);
}
void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
{
int i;
const struct lbs_debugfs_files *files;
if (!lbs_dir)
goto exit;
priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
if (!priv->debugfs_dir)
goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
files = &debugfs_files[i];
priv->debugfs_files[i] = debugfs_create_file(files->name,
files->perm,
priv->debugfs_dir,
priv,
&files->fops);
}
priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
if (!priv->events_dir)
goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
files = &debugfs_events_files[i];
priv->debugfs_events_files[i] = debugfs_create_file(files->name,
files->perm,
priv->events_dir,
priv,
&files->fops);
}
priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
if (!priv->regs_dir)
goto exit;
for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
files = &debugfs_regs_files[i];
priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
files->perm,
priv->regs_dir,
priv,
&files->fops);
}
#ifdef PROC_DEBUG
lbs_debug_init(priv);
#endif
exit:
return;
}
void lbs_debugfs_remove_one(struct lbs_private *priv)
{
int i;
for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
debugfs_remove(priv->debugfs_regs_files[i]);
debugfs_remove(priv->regs_dir);
for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
debugfs_remove(priv->debugfs_events_files[i]);
debugfs_remove(priv->events_dir);
#ifdef PROC_DEBUG
debugfs_remove(priv->debugfs_debug);
#endif
for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
debugfs_remove(priv->debugfs_files[i]);
debugfs_remove(priv->debugfs_dir);
}
/* debug entry */
#ifdef PROC_DEBUG
#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
#define item_addr(n) (offsetof(struct lbs_private, n))
struct debug_data {
char name[32];
u32 size;
size_t addr;
};
/* To debug any member of struct lbs_private, simply add one line here.
*/
static struct debug_data items[] = {
{"psmode", item_size(psmode), item_addr(psmode)},
{"psstate", item_size(psstate), item_addr(psstate)},
};
static int num_of_items = ARRAY_SIZE(items);
/**
* @brief proc read function
*
* @param page pointer to buffer
* @param s read data starting position
* @param off offset
* @param cnt counter
* @param eof end of file flag
* @param data data to output
* @return number of output data
*/
static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
int val = 0;
size_t pos = 0;
ssize_t res;
char *p;
int i;
struct debug_data *d;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
if (!buf)
return -ENOMEM;
p = buf;
d = file->private_data;
for (i = 0; i < num_of_items; i++) {
if (d[i].size == 1)
val = *((u8 *) d[i].addr);
else if (d[i].size == 2)
val = *((u16 *) d[i].addr);
else if (d[i].size == 4)
val = *((u32 *) d[i].addr);
else if (d[i].size == 8)
val = *((u64 *) d[i].addr);
pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
}
res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
free_page(addr);
return res;
}
/**
* @brief proc write function
*
* @param f file pointer
* @param buf pointer to data buffer
* @param cnt data number to write
* @param data data to write
* @return number of data
*/
static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
size_t cnt, loff_t *ppos)
{
int r, i;
char *pdata;
char *p;
char *p0;
char *p1;
char *p2;
struct debug_data *d = f->private_data;
pdata = kmalloc(cnt, GFP_KERNEL);
if (pdata == NULL)
return 0;
if (copy_from_user(pdata, buf, cnt)) {
lbs_deb_debugfs("Copy from user failed\n");
kfree(pdata);
return 0;
}
p0 = pdata;
for (i = 0; i < num_of_items; i++) {
do {
p = strstr(p0, d[i].name);
if (p == NULL)
break;
p1 = strchr(p, '\n');
if (p1 == NULL)
break;
p0 = p1++;
p2 = strchr(p, '=');
if (!p2)
break;
p2++;
r = simple_strtoul(p2, NULL, 0);
if (d[i].size == 1)
*((u8 *) d[i].addr) = (u8) r;
else if (d[i].size == 2)
*((u16 *) d[i].addr) = (u16) r;
else if (d[i].size == 4)
*((u32 *) d[i].addr) = (u32) r;
else if (d[i].size == 8)
*((u64 *) d[i].addr) = (u64) r;
break;
} while (1);
}
kfree(pdata);
return (ssize_t)cnt;
}
static const struct file_operations lbs_debug_fops = {
.owner = THIS_MODULE,
.open = open_file_generic,
.write = lbs_debugfs_write,
.read = lbs_debugfs_read,
};
/**
* @brief create debug proc file
*
* @param priv pointer struct lbs_private
* @param dev pointer net_device
* @return N/A
*/
static void lbs_debug_init(struct lbs_private *priv)
{
int i;
if (!priv->debugfs_dir)
return;
for (i = 0; i < num_of_items; i++)
items[i].addr += (size_t) priv;
priv->debugfs_debug = debugfs_create_file("debug", 0644,
priv->debugfs_dir, &items[0],
&lbs_debug_fops);
}
#endif

View File

@@ -0,0 +1,10 @@
#ifndef _LBS_DEBUGFS_H_
#define _LBS_DEBUGFS_H_
void lbs_debugfs_init(void);
void lbs_debugfs_remove(void);
void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev);
void lbs_debugfs_remove_one(struct lbs_private *priv);
#endif

View File

@@ -0,0 +1,56 @@
/**
* This file contains declaration referring to
* functions defined in other source files
*/
#ifndef _LBS_DECL_H_
#define _LBS_DECL_H_
#include <linux/netdevice.h>
struct lbs_private;
struct sk_buff;
struct net_device;
struct cmd_ds_command;
/* ethtool.c */
extern const struct ethtool_ops lbs_ethtool_ops;
/* tx.c */
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev);
/* rx.c */
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
/* main.c */
struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
void lbs_remove_card(struct lbs_private *priv);
int lbs_start_card(struct lbs_private *priv);
void lbs_stop_card(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
int lbs_rtap_supported(struct lbs_private *priv);
int lbs_set_mac_address(struct net_device *dev, void *addr);
void lbs_set_multicast_list(struct net_device *dev);
int lbs_suspend(struct lbs_private *priv);
int lbs_resume(struct lbs_private *priv);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
#endif

View File

@@ -0,0 +1,395 @@
/**
* This header file contains global constant/enum definitions,
* global variable declaration.
*/
#ifndef _LBS_DEFS_H_
#define _LBS_DEFS_H_
#include <linux/spinlock.h>
#ifdef CONFIG_LIBERTAS_DEBUG
#define DEBUG
#define PROC_DEBUG
#endif
#ifndef DRV_NAME
#define DRV_NAME "libertas"
#endif
#define LBS_DEB_ENTER 0x00000001
#define LBS_DEB_LEAVE 0x00000002
#define LBS_DEB_MAIN 0x00000004
#define LBS_DEB_NET 0x00000008
#define LBS_DEB_MESH 0x00000010
#define LBS_DEB_WEXT 0x00000020
#define LBS_DEB_IOCTL 0x00000040
#define LBS_DEB_SCAN 0x00000080
#define LBS_DEB_ASSOC 0x00000100
#define LBS_DEB_JOIN 0x00000200
#define LBS_DEB_11D 0x00000400
#define LBS_DEB_DEBUGFS 0x00000800
#define LBS_DEB_ETHTOOL 0x00001000
#define LBS_DEB_HOST 0x00002000
#define LBS_DEB_CMD 0x00004000
#define LBS_DEB_RX 0x00008000
#define LBS_DEB_TX 0x00010000
#define LBS_DEB_USB 0x00020000
#define LBS_DEB_CS 0x00040000
#define LBS_DEB_FW 0x00080000
#define LBS_DEB_THREAD 0x00100000
#define LBS_DEB_HEX 0x00200000
#define LBS_DEB_SDIO 0x00400000
#define LBS_DEB_SYSFS 0x00800000
#define LBS_DEB_SPI 0x01000000
#define LBS_DEB_CFG80211 0x02000000
extern unsigned int lbs_debug;
#ifdef DEBUG
#define LBS_DEB_LL(grp, grpnam, fmt, args...) \
do { if ((lbs_debug & (grp)) == (grp)) \
printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
in_interrupt() ? " (INT)" : "", ## args); } while (0)
#else
#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
#endif
#define lbs_deb_enter(grp) \
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
#define lbs_deb_enter_args(grp, fmt, args...) \
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
#define lbs_deb_leave(grp) \
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
#define lbs_deb_leave_args(grp, fmt, args...) \
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
__func__, ##args);
#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, " wext", fmt, ##args)
#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, " ioctl", fmt, ##args)
#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, " scan", fmt, ##args)
#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, " assoc", fmt, ##args)
#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, " join", fmt, ##args)
#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, " 11d", fmt, ##args)
#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, " debugfs", fmt, ##args)
#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, " ethtool", fmt, ##args)
#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, " host", fmt, ##args)
#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, " cmd", fmt, ##args)
#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, " rx", fmt, ##args)
#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args)
#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args)
#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args)
#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
#define lbs_pr_info(format, args...) \
printk(KERN_INFO DRV_NAME": " format, ## args)
#define lbs_pr_err(format, args...) \
printk(KERN_ERR DRV_NAME": " format, ## args)
#define lbs_pr_alert(format, args...) \
printk(KERN_ALERT DRV_NAME": " format, ## args)
#ifdef DEBUG
static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
{
int i = 0;
if (len &&
(lbs_debug & LBS_DEB_HEX) &&
(lbs_debug & grp))
{
for (i = 1; i <= len; i++) {
if ((i & 0xf) == 1) {
if (i != 1)
printk("\n");
printk(DRV_NAME " %s: ", prompt);
}
printk("%02x ", (u8) * buf);
buf++;
}
printk("\n");
}
}
#else
#define lbs_deb_hex(grp,prompt,buf,len) do {} while (0)
#endif
/** Buffer Constants */
/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
* driver has more local TxPDs. Each TxPD on the host memory is associated
* with a Tx control node. The driver maintains 8 RxPD descriptors for
* station firmware to store Rx packet information.
*
* Current version of MAC has a 32x6 multicast address buffer.
*
* 802.11b can have up to 14 channels, the driver keeps the
* BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
*/
#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
#define LBS_NUM_CMD_BUFFERS 10
#define LBS_CMD_BUFFER_SIZE (2 * 1024)
#define MRVDRV_MAX_CHANNEL_SIZE 14
#define MRVDRV_ASSOCIATION_TIME_OUT 255
#define MRVDRV_SNAP_HEADER_LEN 8
#define LBS_UPLD_SIZE 2312
#define DEV_NAME_LEN 32
/* Wake criteria for HOST_SLEEP_CFG command */
#define EHS_WAKE_ON_BROADCAST_DATA 0x0001
#define EHS_WAKE_ON_UNICAST_DATA 0x0002
#define EHS_WAKE_ON_MAC_EVENT 0x0004
#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
/* Wake rules for Host_Sleep_CFG command */
#define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00
#define WOL_RULE_NET_TYPE_MESH 0x10
#define WOL_RULE_ADDR_TYPE_BCAST 0x01
#define WOL_RULE_ADDR_TYPE_MCAST 0x08
#define WOL_RULE_ADDR_TYPE_UCAST 0x02
#define WOL_RULE_OP_AND 0x01
#define WOL_RULE_OP_OR 0x02
#define WOL_RULE_OP_INVALID 0xFF
#define WOL_RESULT_VALID_CMD 0
#define WOL_RESULT_NOSPC_ERR 1
#define WOL_RESULT_EEXIST_ERR 2
/** Misc constants */
/* This section defines 802.11 specific contants */
#define MRVDRV_MAX_BSS_DESCRIPTS 16
#define MRVDRV_MAX_REGION_CODE 6
#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
#define MRVDRV_CHANNELS_PER_SCAN 4
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
#define MRVDRV_MIN_BEACON_INTERVAL 20
#define MRVDRV_MAX_BEACON_INTERVAL 1000
#define MRVDRV_BEACON_INTERVAL 100
#define MARVELL_MESH_IE_LENGTH 9
/* Values used to populate the struct mrvl_mesh_ie. The only time you need this
* is when enabling the mesh using CMD_MESH_CONFIG.
*/
#define MARVELL_MESH_IE_TYPE 4
#define MARVELL_MESH_IE_SUBTYPE 0
#define MARVELL_MESH_IE_VERSION 0
#define MARVELL_MESH_PROTO_ID_HWMP 0
#define MARVELL_MESH_METRIC_ID 0
#define MARVELL_MESH_CAPABILITY 0
/** INT status Bit Definition*/
#define MRVDRV_TX_DNLD_RDY 0x0001
#define MRVDRV_RX_UPLD_RDY 0x0002
#define MRVDRV_CMD_DNLD_RDY 0x0004
#define MRVDRV_CMD_UPLD_RDY 0x0008
#define MRVDRV_CARDEVENT 0x0010
/* Automatic TX control default levels */
#define POW_ADAPT_DEFAULT_P0 13
#define POW_ADAPT_DEFAULT_P1 15
#define POW_ADAPT_DEFAULT_P2 18
#define TPC_DEFAULT_P0 5
#define TPC_DEFAULT_P1 10
#define TPC_DEFAULT_P2 13
/** TxPD status */
/* Station firmware use TxPD status field to report final Tx transmit
* result, Bit masks are used to present combined situations.
*/
#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
/** Tx mesh flag */
/* Currently we are using normal WDS flag as mesh flag.
* TODO: change to proper mesh flag when MAC understands it.
*/
#define TxPD_CONTROL_WDS_FRAME (1<<17)
#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME
/** Mesh interface ID */
#define MESH_IFACE_ID 0x0001
/** Mesh id should be in bits 14-13-12 */
#define MESH_IFACE_BIT_OFFSET 0x000c
/** Mesh enable bit in FW capability */
#define MESH_CAPINFO_ENABLE_MASK (1<<16)
/** FW definition from Marvell v4 */
#define MRVL_FW_V4 (0x04)
/** FW definition from Marvell v5 */
#define MRVL_FW_V5 (0x05)
/** FW definition from Marvell v10 */
#define MRVL_FW_V10 (0x0a)
/** FW major revision definition */
#define MRVL_FW_MAJOR_REV(x) ((x)>>24)
/** RxPD status */
#define MRVDRV_RXPD_STATUS_OK 0x0001
/** RxPD status - Received packet types */
/** Rx mesh flag */
/* Currently we are using normal WDS flag as mesh flag.
* TODO: change to proper mesh flag when MAC understands it.
*/
#define RxPD_CONTROL_WDS_FRAME (0x40)
#define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME
/** RSSI-related defines */
/* RSSI constants are used to implement 802.11 RSSI threshold
* indication. if the Rx packet signal got too weak for 5 consecutive
* times, miniport driver (driver) will report this event to wrapper
*/
#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96)
/** RTS/FRAG related defines */
#define MRVDRV_RTS_MIN_VALUE 0
#define MRVDRV_RTS_MAX_VALUE 2347
#define MRVDRV_FRAG_MIN_VALUE 256
#define MRVDRV_FRAG_MAX_VALUE 2346
/* This is for firmware specific length */
#define EXTRA_LEN 36
#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
(ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN)
#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
(ETH_FRAME_LEN + sizeof(struct rxpd) \
+ MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
#define CMD_F_HOSTCMD (1 << 0)
#define FW_CAPINFO_WPA (1 << 0)
#define FW_CAPINFO_PS (1 << 1)
#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13)
#define FW_CAPINFO_BOOT2_UPGRADE (1<<14)
#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15)
#define KEY_LEN_WPA_AES 16
#define KEY_LEN_WPA_TKIP 32
#define KEY_LEN_WEP_104 13
#define KEY_LEN_WEP_40 5
#define RF_ANTENNA_1 0x1
#define RF_ANTENNA_2 0x2
#define RF_ANTENNA_AUTO 0xFFFF
#define BAND_B (0x01)
#define BAND_G (0x02)
#define ALL_802_11_BANDS (BAND_B | BAND_G)
#define MAX_RATES 14
#define MAX_LEDS 8
/** Global Variable Declaration */
extern const char lbs_driver_version[];
extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
/** ENUM definition*/
/** SNRNF_TYPE */
enum SNRNF_TYPE {
TYPE_BEACON = 0,
TYPE_RXPD,
MAX_TYPE_B
};
/** SNRNF_DATA*/
enum SNRNF_DATA {
TYPE_NOAVG = 0,
TYPE_AVG,
MAX_TYPE_AVG
};
/** LBS_802_11_POWER_MODE */
enum LBS_802_11_POWER_MODE {
LBS802_11POWERMODECAM,
LBS802_11POWERMODEMAX_PSP,
LBS802_11POWERMODEFAST_PSP,
/*not a real mode, defined as an upper bound */
LBS802_11POWEMODEMAX
};
/** PS_STATE */
enum PS_STATE {
PS_STATE_FULL_POWER,
PS_STATE_AWAKE,
PS_STATE_PRE_SLEEP,
PS_STATE_SLEEP
};
/** DNLD_STATE */
enum DNLD_STATE {
DNLD_RES_RECEIVED,
DNLD_DATA_SENT,
DNLD_CMD_SENT,
DNLD_BOOTCMD_SENT,
};
/** LBS_MEDIA_STATE */
enum LBS_MEDIA_STATE {
LBS_CONNECTED,
LBS_DISCONNECTED
};
/** LBS_802_11_PRIVACY_FILTER */
enum LBS_802_11_PRIVACY_FILTER {
LBS802_11PRIVFILTERACCEPTALL,
LBS802_11PRIVFILTER8021XWEP
};
/** mv_ms_type */
enum mv_ms_type {
MVMS_DAT = 0,
MVMS_CMD = 1,
MVMS_TXDONE = 2,
MVMS_EVENT
};
/** KEY_TYPE_ID */
enum KEY_TYPE_ID {
KEY_TYPE_ID_WEP = 0,
KEY_TYPE_ID_TKIP,
KEY_TYPE_ID_AES
};
/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */
enum KEY_INFO_WPA {
KEY_INFO_WPA_MCAST = 0x01,
KEY_INFO_WPA_UNICAST = 0x02,
KEY_INFO_WPA_ENABLED = 0x04
};
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
/* Default Rate, 11Mbps */
#define FWT_DEFAULT_RATE 3
#define FWT_DEFAULT_SSN 0xffffffff
#define FWT_DEFAULT_DSN 0
#define FWT_DEFAULT_HOPCOUNT 0
#define FWT_DEFAULT_TTL 0
#define FWT_DEFAULT_EXPIRATION 0
#define FWT_DEFAULT_SLEEPMODE 0
#define FWT_DEFAULT_SNR 0
#endif

View File

@@ -0,0 +1,173 @@
/**
* This file contains definitions and data structures specific
* to Marvell 802.11 NIC. It contains the Device Information
* structure struct lbs_private..
*/
#ifndef _LBS_DEV_H_
#define _LBS_DEV_H_
#include "mesh.h"
#include "defs.h"
#include "host.h"
#include <linux/kfifo.h>
/** sleep_params */
struct sleep_params {
uint16_t sp_error;
uint16_t sp_offset;
uint16_t sp_stabletime;
uint8_t sp_calcontrol;
uint8_t sp_extsleepclk;
uint16_t sp_reserved;
};
/** Private structure for the MV device */
struct lbs_private {
/* Basic networking */
struct net_device *dev;
u32 connect_status;
struct work_struct mcast_work;
u32 nr_of_multicastmacaddr;
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
/* CFG80211 */
struct wireless_dev *wdev;
bool wiphy_registered;
struct cfg80211_scan_request *scan_req;
u8 assoc_bss[ETH_ALEN];
u8 disassoc_reason;
/* Mesh */
struct net_device *mesh_dev; /* Virtual device */
#ifdef CONFIG_G900_WIFI_MESH
u32 mesh_connect_status;
struct lbs_mesh_stats mstats;
int mesh_open;
uint16_t mesh_tlv;
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
u8 mesh_ssid_len;
#endif
/* Debugfs */
struct dentry *debugfs_dir;
struct dentry *debugfs_debug;
struct dentry *debugfs_files[6];
struct dentry *events_dir;
struct dentry *debugfs_events_files[6];
struct dentry *regs_dir;
struct dentry *debugfs_regs_files[6];
/* Hardware debugging */
u32 mac_offset;
u32 bbp_offset;
u32 rf_offset;
/* Power management */
u16 psmode;
u32 psstate;
u8 needtowakeup;
/* Deep sleep */
int is_deep_sleep;
int deep_sleep_required;
int is_auto_deep_sleep_enabled;
int wakeup_dev_required;
int is_activity_detected;
int auto_deep_sleep_timeout; /* in ms */
wait_queue_head_t ds_awake_q;
struct timer_list auto_deepsleep_timer;
/* Host sleep*/
int is_host_sleep_configured;
int is_host_sleep_activated;
wait_queue_head_t host_sleep_q;
/* Hardware access */
void *card;
u8 fw_ready;
u8 surpriseremoved;
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
void (*reset_card) (struct lbs_private *priv);
int (*enter_deep_sleep) (struct lbs_private *priv);
int (*exit_deep_sleep) (struct lbs_private *priv);
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
/* Adapter info (from EEPROM) */
u32 fwrelease;
u32 fwcapinfo;
u16 regioncode;
u8 current_addr[ETH_ALEN];
/* Command download */
u8 dnld_sent;
/* bit0 1/0=data_sent/data_tx_done,
bit1 1/0=cmd_sent/cmd_tx_done,
all other bits reserved 0 */
u16 seqnum;
struct cmd_ctrl_node *cmd_array;
struct cmd_ctrl_node *cur_cmd;
struct list_head cmdfreeq; /* free command buffers */
struct list_head cmdpendingq; /* pending command buffers */
struct timer_list command_timer;
int cmd_timed_out;
/* Command responses sent from the hardware to the driver */
u8 resp_idx;
u8 resp_buf[2][LBS_UPLD_SIZE];
u32 resp_len[2];
/* Events sent from hardware to driver */
struct kfifo event_fifo;
/** thread to service interrupts */
struct task_struct *main_thread;
wait_queue_head_t waitq;
struct workqueue_struct *work_thread;
/** Encryption stuff */
u8 authtype_auto;
u8 wep_tx_key;
u8 wep_key[4][WLAN_KEY_LEN_WEP104];
u8 wep_key_len[4];
/* Wake On LAN */
uint32_t wol_criteria;
uint8_t wol_gpio;
uint8_t wol_gap;
/* Transmitting */
int tx_pending_len; /* -1 while building packet */
u8 tx_pending_buf[LBS_UPLD_SIZE];
/* protected by hard_start_xmit serialization */
u8 txretrycount;
struct sk_buff *currenttxskb;
/* Locks */
struct mutex lock;
spinlock_t driver_lock;
/* NIC/link operation characteristics */
u16 mac_control;
u8 radio_on;
u8 cur_rate;
u8 channel;
s16 txpower_cur;
s16 txpower_min;
s16 txpower_max;
/** Scanning */
struct delayed_work scan_work;
int scan_channel;
/* Queue of things waiting for scan completion */
wait_queue_head_t scan_q;
/* Whether the scan was initiated internally and not by cfg80211 */
bool internal_scan;
unsigned long last_scan;
};
extern struct cmd_confirm_sleep confirm_sleep;
#endif

View File

@@ -0,0 +1,116 @@
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include "decl.h"
#include "cmd.h"
static void lbs_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct lbs_private *priv = dev->ml_priv;
snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
priv->fwrelease >> 24 & 0xff,
priv->fwrelease >> 16 & 0xff,
priv->fwrelease >> 8 & 0xff,
priv->fwrelease & 0xff);
strcpy(info->driver, "libertas");
strcpy(info->version, lbs_driver_version);
}
/* All 8388 parts have 16KiB EEPROM size at the time of writing.
* In case that changes this needs fixing.
*/
#define LBS_EEPROM_LEN 16384
static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
{
return LBS_EEPROM_LEN;
}
static int lbs_ethtool_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * bytes)
{
struct lbs_private *priv = dev->ml_priv;
struct cmd_ds_802_11_eeprom_access cmd;
int ret;
lbs_deb_enter(LBS_DEB_ETHTOOL);
if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
eeprom->len > LBS_EEPROM_READ_LEN) {
ret = -EINVAL;
goto out;
}
cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
LBS_EEPROM_READ_LEN + eeprom->len);
cmd.action = cpu_to_le16(CMD_ACT_GET);
cmd.offset = cpu_to_le16(eeprom->offset);
cmd.len = cpu_to_le16(eeprom->len);
ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
if (!ret)
memcpy(bytes, cmd.value, eeprom->len);
out:
lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
return ret;
}
static void lbs_ethtool_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct lbs_private *priv = dev->ml_priv;
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
return;
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
wol->wolopts |= WAKE_UCAST;
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
wol->wolopts |= WAKE_MCAST;
if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
wol->wolopts |= WAKE_BCAST;
if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
wol->wolopts |= WAKE_PHY;
}
static int lbs_ethtool_set_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
struct lbs_private *priv = dev->ml_priv;
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
return -EOPNOTSUPP;
priv->wol_criteria = 0;
if (wol->wolopts & WAKE_UCAST)
priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
if (wol->wolopts & WAKE_MCAST)
priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
if (wol->wolopts & WAKE_BCAST)
priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
if (wol->wolopts & WAKE_PHY)
priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
if (wol->wolopts == 0)
priv->wol_criteria |= EHS_REMOVE_WAKEUP;
return 0;
}
const struct ethtool_ops lbs_ethtool_ops = {
.get_drvinfo = lbs_ethtool_get_drvinfo,
.get_eeprom = lbs_ethtool_get_eeprom,
.get_eeprom_len = lbs_ethtool_get_eeprom_len,
#ifdef CONFIG_G900_WIFI_MESH
.get_sset_count = lbs_mesh_ethtool_get_sset_count,
.get_ethtool_stats = lbs_mesh_ethtool_get_stats,
.get_strings = lbs_mesh_ethtool_get_strings,
#endif
.get_wol = lbs_ethtool_get_wol,
.set_wol = lbs_ethtool_set_wol,
};

View File

@@ -0,0 +1,972 @@
/**
* This file function prototypes, data structure
* and definitions for all the host/station commands
*/
#ifndef _LBS_HOST_H_
#define _LBS_HOST_H_
#include "types.h"
#include "defs.h"
#define DEFAULT_AD_HOC_CHANNEL 6
#define CMD_OPTION_WAITFORRSP 0x0002
/** Host command IDs */
/* Return command are almost always the same as the host command, but with
* bit 15 set high. There are a few exceptions, though...
*/
#define CMD_RET(cmd) (0x8000 | cmd)
/* Return command convention exceptions: */
#define CMD_RET_802_11_ASSOCIATE 0x8012
/* Command codes */
#define CMD_GET_HW_SPEC 0x0003
#define CMD_EEPROM_UPDATE 0x0004
#define CMD_802_11_RESET 0x0005
#define CMD_802_11_SCAN 0x0006
#define CMD_802_11_GET_LOG 0x000b
#define CMD_MAC_MULTICAST_ADR 0x0010
#define CMD_802_11_AUTHENTICATE 0x0011
#define CMD_802_11_EEPROM_ACCESS 0x0059
#define CMD_802_11_ASSOCIATE 0x0050
#define CMD_802_11_SET_WEP 0x0013
#define CMD_802_11_GET_STAT 0x0014
#define CMD_802_3_GET_STAT 0x0015
#define CMD_802_11_SNMP_MIB 0x0016
#define CMD_MAC_REG_MAP 0x0017
#define CMD_BBP_REG_MAP 0x0018
#define CMD_MAC_REG_ACCESS 0x0019
#define CMD_BBP_REG_ACCESS 0x001a
#define CMD_RF_REG_ACCESS 0x001b
#define CMD_802_11_RADIO_CONTROL 0x001c
#define CMD_802_11_RF_CHANNEL 0x001d
#define CMD_802_11_RF_TX_POWER 0x001e
#define CMD_802_11_RSSI 0x001f
#define CMD_802_11_RF_ANTENNA 0x0020
#define CMD_802_11_PS_MODE 0x0021
#define CMD_802_11_DATA_RATE 0x0022
#define CMD_RF_REG_MAP 0x0023
#define CMD_802_11_DEAUTHENTICATE 0x0024
#define CMD_802_11_REASSOCIATE 0x0025
#define CMD_MAC_CONTROL 0x0028
#define CMD_802_11_AD_HOC_START 0x002b
#define CMD_802_11_AD_HOC_JOIN 0x002c
#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
#define CMD_802_11_ENABLE_RSN 0x002f
#define CMD_802_11_SET_AFC 0x003c
#define CMD_802_11_GET_AFC 0x003d
#define CMD_802_11_DEEP_SLEEP 0x003e
#define CMD_802_11_AD_HOC_STOP 0x0040
#define CMD_802_11_HOST_SLEEP_CFG 0x0043
#define CMD_802_11_WAKEUP_CONFIRM 0x0044
#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045
#define CMD_802_11_BEACON_STOP 0x0049
#define CMD_802_11_MAC_ADDRESS 0x004d
#define CMD_802_11_LED_GPIO_CTRL 0x004e
#define CMD_802_11_EEPROM_ACCESS 0x0059
#define CMD_802_11_BAND_CONFIG 0x0058
#define CMD_GSPI_BUS_CONFIG 0x005a
#define CMD_802_11D_DOMAIN_INFO 0x005b
#define CMD_802_11_KEY_MATERIAL 0x005e
#define CMD_802_11_SLEEP_PARAMS 0x0066
#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
#define CMD_802_11_SLEEP_PERIOD 0x0068
#define CMD_802_11_TPC_CFG 0x0072
#define CMD_802_11_PA_CFG 0x0073
#define CMD_802_11_FW_WAKE_METHOD 0x0074
#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
#define CMD_802_11_TX_RATE_QUERY 0x007f
#define CMD_GET_TSF 0x0080
#define CMD_BT_ACCESS 0x0087
#define CMD_FWT_ACCESS 0x0095
#define CMD_802_11_MONITOR_MODE 0x0098
#define CMD_MESH_ACCESS 0x009b
#define CMD_MESH_CONFIG_OLD 0x00a3
#define CMD_MESH_CONFIG 0x00ac
#define CMD_SET_BOOT2_VER 0x00a5
#define CMD_FUNC_INIT 0x00a9
#define CMD_FUNC_SHUTDOWN 0x00aa
#define CMD_802_11_BEACON_CTRL 0x00b0
/* For the IEEE Power Save */
#define PS_MODE_ACTION_ENTER_PS 0x0030
#define PS_MODE_ACTION_EXIT_PS 0x0031
#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034
#define CMD_ENABLE_RSN 0x0001
#define CMD_DISABLE_RSN 0x0000
#define CMD_ACT_GET 0x0000
#define CMD_ACT_SET 0x0001
/* Define action or option for CMD_802_11_SET_WEP */
#define CMD_ACT_ADD 0x0002
#define CMD_ACT_REMOVE 0x0004
#define CMD_TYPE_WEP_40_BIT 0x01
#define CMD_TYPE_WEP_104_BIT 0x02
#define CMD_NUM_OF_WEP_KEYS 4
#define CMD_WEP_KEY_INDEX_MASK 0x3fff
/* Define action or option for CMD_802_11_SCAN */
#define CMD_BSS_TYPE_BSS 0x0001
#define CMD_BSS_TYPE_IBSS 0x0002
#define CMD_BSS_TYPE_ANY 0x0003
/* Define action or option for CMD_802_11_SCAN */
#define CMD_SCAN_TYPE_ACTIVE 0x0000
#define CMD_SCAN_TYPE_PASSIVE 0x0001
#define CMD_SCAN_RADIO_TYPE_BG 0
#define CMD_SCAN_PROBE_DELAY_TIME 0
/* Define action or option for CMD_MAC_CONTROL */
#define CMD_ACT_MAC_RX_ON 0x0001
#define CMD_ACT_MAC_TX_ON 0x0002
#define CMD_ACT_MAC_LOOPBACK_ON 0x0004
#define CMD_ACT_MAC_WEP_ENABLE 0x0008
#define CMD_ACT_MAC_INT_ENABLE 0x0010
#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
#define CMD_SUBSCRIBE_SNR_LOW 0x0002
#define CMD_SUBSCRIBE_FAILCOUNT 0x0004
#define CMD_SUBSCRIBE_BCNMISS 0x0008
#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
#define RADIO_PREAMBLE_LONG 0x00
#define RADIO_PREAMBLE_SHORT 0x02
#define RADIO_PREAMBLE_AUTO 0x04
/* Define action or option for CMD_802_11_RF_CHANNEL */
#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
/* Define action or option for CMD_802_11_DATA_RATE */
#define CMD_ACT_SET_TX_AUTO 0x0000
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
#define CMD_ACT_GET_TX_RATE 0x0002
/* Options for CMD_802_11_FW_WAKE_METHOD */
#define CMD_WAKE_METHOD_UNCHANGED 0x0000
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
#define CMD_WAKE_METHOD_GPIO 0x0002
/* Object IDs for CMD_802_11_SNMP_MIB */
#define SNMP_MIB_OID_BSS_TYPE 0x0000
#define SNMP_MIB_OID_OP_RATE_SET 0x0001
#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */
#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */
#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */
#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005
#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006
#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007
#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008
#define SNMP_MIB_OID_11D_ENABLE 0x0009
#define SNMP_MIB_OID_11H_ENABLE 0x000A
/* Define action or option for CMD_BT_ACCESS */
enum cmd_bt_access_opts {
/* The bt commands start at 5 instead of 1 because the old dft commands
* are mapped to 1-4. These old commands are no longer maintained and
* should not be called.
*/
CMD_ACT_BT_ACCESS_ADD = 5,
CMD_ACT_BT_ACCESS_DEL,
CMD_ACT_BT_ACCESS_LIST,
CMD_ACT_BT_ACCESS_RESET,
CMD_ACT_BT_ACCESS_SET_INVERT,
CMD_ACT_BT_ACCESS_GET_INVERT
};
/* Define action or option for CMD_FWT_ACCESS */
enum cmd_fwt_access_opts {
CMD_ACT_FWT_ACCESS_ADD = 1,
CMD_ACT_FWT_ACCESS_DEL,
CMD_ACT_FWT_ACCESS_LOOKUP,
CMD_ACT_FWT_ACCESS_LIST,
CMD_ACT_FWT_ACCESS_LIST_ROUTE,
CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR,
CMD_ACT_FWT_ACCESS_RESET,
CMD_ACT_FWT_ACCESS_CLEANUP,
CMD_ACT_FWT_ACCESS_TIME,
};
/* Define action or option for CMD_802_11_HOST_SLEEP_CFG */
enum cmd_wol_cfg_opts {
CMD_ACT_ACTION_NONE = 0,
CMD_ACT_SET_WOL_RULE,
CMD_ACT_GET_WOL_RULE,
CMD_ACT_RESET_WOL_RULE,
};
/* Define action or option for CMD_MESH_ACCESS */
enum cmd_mesh_access_opts {
CMD_ACT_MESH_GET_TTL = 1,
CMD_ACT_MESH_SET_TTL,
CMD_ACT_MESH_GET_STATS,
CMD_ACT_MESH_GET_ANYCAST,
CMD_ACT_MESH_SET_ANYCAST,
CMD_ACT_MESH_SET_LINK_COSTS,
CMD_ACT_MESH_GET_LINK_COSTS,
CMD_ACT_MESH_SET_BCAST_RATE,
CMD_ACT_MESH_GET_BCAST_RATE,
CMD_ACT_MESH_SET_RREQ_DELAY,
CMD_ACT_MESH_GET_RREQ_DELAY,
CMD_ACT_MESH_SET_ROUTE_EXP,
CMD_ACT_MESH_GET_ROUTE_EXP,
CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT = 17,
};
/* Define actions and types for CMD_MESH_CONFIG */
enum cmd_mesh_config_actions {
CMD_ACT_MESH_CONFIG_STOP = 0,
CMD_ACT_MESH_CONFIG_START,
CMD_ACT_MESH_CONFIG_SET,
CMD_ACT_MESH_CONFIG_GET,
};
enum cmd_mesh_config_types {
CMD_TYPE_MESH_SET_BOOTFLAG = 1,
CMD_TYPE_MESH_SET_BOOTTIME,
CMD_TYPE_MESH_SET_DEF_CHANNEL,
CMD_TYPE_MESH_SET_MESH_IE,
CMD_TYPE_MESH_GET_DEFAULTS,
CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */
};
/** Card Event definition */
#define MACREG_INT_CODE_TX_PPA_FREE 0
#define MACREG_INT_CODE_TX_DMA_DONE 1
#define MACREG_INT_CODE_LINK_LOST_W_SCAN 2
#define MACREG_INT_CODE_LINK_LOST_NO_SCAN 3
#define MACREG_INT_CODE_LINK_SENSED 4
#define MACREG_INT_CODE_CMD_FINISHED 5
#define MACREG_INT_CODE_MIB_CHANGED 6
#define MACREG_INT_CODE_INIT_DONE 7
#define MACREG_INT_CODE_DEAUTHENTICATED 8
#define MACREG_INT_CODE_DISASSOCIATED 9
#define MACREG_INT_CODE_PS_AWAKE 10
#define MACREG_INT_CODE_PS_SLEEP 11
#define MACREG_INT_CODE_MIC_ERR_MULTICAST 13
#define MACREG_INT_CODE_MIC_ERR_UNICAST 14
#define MACREG_INT_CODE_WM_AWAKE 15
#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 16
#define MACREG_INT_CODE_ADHOC_BCN_LOST 17
#define MACREG_INT_CODE_HOST_AWAKE 18
#define MACREG_INT_CODE_STOP_TX 19
#define MACREG_INT_CODE_START_TX 20
#define MACREG_INT_CODE_CHANNEL_SWITCH 21
#define MACREG_INT_CODE_MEASUREMENT_RDY 22
#define MACREG_INT_CODE_WMM_CHANGE 23
#define MACREG_INT_CODE_BG_SCAN_REPORT 24
#define MACREG_INT_CODE_RSSI_LOW 25
#define MACREG_INT_CODE_SNR_LOW 26
#define MACREG_INT_CODE_MAX_FAIL 27
#define MACREG_INT_CODE_RSSI_HIGH 28
#define MACREG_INT_CODE_SNR_HIGH 29
#define MACREG_INT_CODE_MESH_AUTO_STARTED 35
#define MACREG_INT_CODE_FIRMWARE_READY 48
/* 802.11-related definitions */
/* TxPD descriptor */
struct txpd {
/* union to cope up with later FW revisions */
union {
/* Current Tx packet status */
__le32 tx_status;
struct {
/* BSS type: client, AP, etc. */
u8 bss_type;
/* BSS number */
u8 bss_num;
/* Reserved */
__le16 reserved;
} bss;
} u;
/* Tx control */
__le32 tx_control;
__le32 tx_packet_location;
/* Tx packet length */
__le16 tx_packet_length;
/* First 2 byte of destination MAC address */
u8 tx_dest_addr_high[2];
/* Last 4 byte of destination MAC address */
u8 tx_dest_addr_low[4];
/* Pkt Priority */
u8 priority;
/* Pkt Trasnit Power control */
u8 powermgmt;
/* Amount of time the packet has been queued (units = 2ms) */
u8 pktdelay_2ms;
/* reserved */
u8 reserved1;
} __packed;
/* RxPD Descriptor */
struct rxpd {
/* union to cope up with later FW revisions */
union {
/* Current Rx packet status */
__le16 status;
struct {
/* BSS type: client, AP, etc. */
u8 bss_type;
/* BSS number */
u8 bss_num;
} __packed bss;
} __packed u;
/* SNR */
u8 snr;
/* Tx control */
u8 rx_control;
/* Pkt length */
__le16 pkt_len;
/* Noise Floor */
u8 nf;
/* Rx Packet Rate */
u8 rx_rate;
/* Pkt addr */
__le32 pkt_ptr;
/* Next Rx RxPD addr */
__le32 next_rxpd_ptr;
/* Pkt Priority */
u8 priority;
u8 reserved[3];
} __packed;
struct cmd_header {
__le16 command;
__le16 size;
__le16 seqnum;
__le16 result;
} __packed;
/* Generic structure to hold all key types. */
struct enc_key {
u16 len;
u16 flags; /* KEY_INFO_* from defs.h */
u16 type; /* KEY_TYPE_* from defs.h */
u8 key[32];
};
/* lbs_offset_value */
struct lbs_offset_value {
u32 offset;
u32 value;
} __packed;
#define MAX_11D_TRIPLETS 83
struct mrvl_ie_domain_param_set {
struct mrvl_ie_header header;
u8 country_code[3];
struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
} __packed;
struct cmd_ds_802_11d_domain_info {
struct cmd_header hdr;
__le16 action;
struct mrvl_ie_domain_param_set domain;
} __packed;
/*
* Define data structure for CMD_GET_HW_SPEC
* This structure defines the response for the GET_HW_SPEC command
*/
struct cmd_ds_get_hw_spec {
struct cmd_header hdr;
/* HW Interface version number */
__le16 hwifversion;
/* HW version number */
__le16 version;
/* Max number of TxPD FW can handle */
__le16 nr_txpd;
/* Max no of Multicast address */
__le16 nr_mcast_adr;
/* MAC address */
u8 permanentaddr[6];
/* region Code */
__le16 regioncode;
/* Number of antenna used */
__le16 nr_antenna;
/* FW release number, example 0x01030304 = 2.3.4p1 */
__le32 fwrelease;
/* Base Address of TxPD queue */
__le32 wcb_base;
/* Read Pointer of RxPd queue */
__le32 rxpd_rdptr;
/* Write Pointer of RxPd queue */
__le32 rxpd_wrptr;
/*FW/HW capability */
__le32 fwcapinfo;
} __packed;
struct cmd_ds_802_11_subscribe_event {
struct cmd_header hdr;
__le16 action;
__le16 events;
/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
* number of TLVs. From the v5.1 manual, those TLVs would add up to
* 40 bytes. However, future firmware might add additional TLVs, so I
* bump this up a bit.
*/
uint8_t tlv[128];
} __packed;
/*
* This scan handle Country Information IE(802.11d compliant)
* Define data structure for CMD_802_11_SCAN
*/
struct cmd_ds_802_11_scan {
struct cmd_header hdr;
uint8_t bsstype;
uint8_t bssid[ETH_ALEN];
uint8_t tlvbuffer[0];
} __packed;
struct cmd_ds_802_11_scan_rsp {
struct cmd_header hdr;
__le16 bssdescriptsize;
uint8_t nr_sets;
uint8_t bssdesc_and_tlvbuffer[0];
} __packed;
struct cmd_ds_802_11_get_log {
struct cmd_header hdr;
__le32 mcasttxframe;
__le32 failed;
__le32 retry;
__le32 multiretry;
__le32 framedup;
__le32 rtssuccess;
__le32 rtsfailure;
__le32 ackfailure;
__le32 rxfrag;
__le32 mcastrxframe;
__le32 fcserror;
__le32 txframe;
__le32 wepundecryptable;
} __packed;
struct cmd_ds_mac_control {
struct cmd_header hdr;
__le16 action;
u16 reserved;
} __packed;
struct cmd_ds_mac_multicast_adr {
struct cmd_header hdr;
__le16 action;
__le16 nr_of_adrs;
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
} __packed;
struct cmd_ds_802_11_authenticate {
struct cmd_header hdr;
u8 bssid[ETH_ALEN];
u8 authtype;
u8 reserved[10];
} __packed;
struct cmd_ds_802_11_deauthenticate {
struct cmd_header hdr;
u8 macaddr[ETH_ALEN];
__le16 reasoncode;
} __packed;
struct cmd_ds_802_11_associate {
struct cmd_header hdr;
u8 bssid[6];
__le16 capability;
__le16 listeninterval;
__le16 bcnperiod;
u8 dtimperiod;
u8 iebuf[512]; /* Enough for required and most optional IEs */
} __packed;
struct cmd_ds_802_11_associate_response {
struct cmd_header hdr;
__le16 capability;
__le16 statuscode;
__le16 aid;
u8 iebuf[512];
} __packed;
struct cmd_ds_802_11_set_wep {
struct cmd_header hdr;
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
__le16 action;
/* key Index selected for Tx */
__le16 keyindex;
/* 40, 128bit or TXWEP */
uint8_t keytype[4];
uint8_t keymaterial[4][16];
} __packed;
struct cmd_ds_802_11_snmp_mib {
struct cmd_header hdr;
__le16 action;
__le16 oid;
__le16 bufsize;
u8 value[128];
} __packed;
struct cmd_ds_reg_access {
struct cmd_header hdr;
__le16 action;
__le16 offset;
union {
u8 bbp_rf; /* for BBP and RF registers */
__le32 mac; /* for MAC registers */
} value;
} __packed;
struct cmd_ds_802_11_radio_control {
struct cmd_header hdr;
__le16 action;
__le16 control;
} __packed;
struct cmd_ds_802_11_beacon_control {
struct cmd_header hdr;
__le16 action;
__le16 beacon_enable;
__le16 beacon_period;
} __packed;
struct cmd_ds_802_11_sleep_params {
struct cmd_header hdr;
/* ACT_GET/ACT_SET */
__le16 action;
/* Sleep clock error in ppm */
__le16 error;
/* Wakeup offset in usec */
__le16 offset;
/* Clock stabilization time in usec */
__le16 stabletime;
/* control periodic calibration */
uint8_t calcontrol;
/* control the use of external sleep clock */
uint8_t externalsleepclk;
/* reserved field, should be set to zero */
__le16 reserved;
} __packed;
struct cmd_ds_802_11_rf_channel {
struct cmd_header hdr;
__le16 action;
__le16 channel;
__le16 rftype; /* unused */
__le16 reserved; /* unused */
u8 channellist[32]; /* unused */
} __packed;
struct cmd_ds_802_11_rssi {
struct cmd_header hdr;
/* request: number of beacons (N) to average the SNR and NF over
* response: SNR of most recent beacon
*/
__le16 n_or_snr;
/* The following fields are only set in the response.
* In the request these are reserved and should be set to 0.
*/
__le16 nf; /* most recent beacon noise floor */
__le16 avg_snr; /* average SNR weighted by N from request */
__le16 avg_nf; /* average noise floor weighted by N from request */
} __packed;
struct cmd_ds_802_11_mac_address {
struct cmd_header hdr;
__le16 action;
u8 macadd[ETH_ALEN];
} __packed;
struct cmd_ds_802_11_rf_tx_power {
struct cmd_header hdr;
__le16 action;
__le16 curlevel;
s8 maxlevel;
s8 minlevel;
} __packed;
/* MONITOR_MODE only exists in OLPC v5 firmware */
struct cmd_ds_802_11_monitor_mode {
struct cmd_header hdr;
__le16 action;
__le16 mode;
} __packed;
struct cmd_ds_set_boot2_ver {
struct cmd_header hdr;
__le16 action;
__le16 version;
} __packed;
struct cmd_ds_802_11_fw_wake_method {
struct cmd_header hdr;
__le16 action;
__le16 method;
} __packed;
struct cmd_ds_802_11_ps_mode {
struct cmd_header hdr;
__le16 action;
/* Interval for keepalive in PS mode:
* 0x0000 = don't change
* 0x001E = firmware default
* 0xFFFF = disable
*/
__le16 nullpktinterval;
/* Number of DTIM intervals to wake up for:
* 0 = don't change
* 1 = firmware default
* 5 = max
*/
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
/* AdHoc awake period (FW v9+ only):
* 0 = don't change
* 1 = always awake (IEEE standard behavior)
* 2 - 31 = sleep for (n - 1) periods and awake for 1 period
* 32 - 254 = invalid
* 255 = sleep at each ATIM
*/
__le16 adhoc_awake_period;
} __packed;
struct cmd_confirm_sleep {
struct cmd_header hdr;
__le16 action;
__le16 nullpktinterval;
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
} __packed;
struct cmd_ds_802_11_data_rate {
struct cmd_header hdr;
__le16 action;
__le16 reserved;
u8 rates[MAX_RATES];
} __packed;
struct cmd_ds_802_11_rate_adapt_rateset {
struct cmd_header hdr;
__le16 action;
__le16 enablehwauto;
__le16 bitmap;
} __packed;
struct cmd_ds_802_11_ad_hoc_start {
struct cmd_header hdr;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 bsstype;
__le16 beaconperiod;
u8 dtimperiod; /* Reserved on v9 and later */
struct ieee_ie_ibss_param_set ibss;
u8 reserved1[4];
struct ieee_ie_ds_param_set ds;
u8 reserved2[4];
__le16 probedelay; /* Reserved on v9 and later */
__le16 capability;
u8 rates[MAX_RATES];
u8 tlv_memory_size_pad[100];
} __packed;
struct cmd_ds_802_11_ad_hoc_result {
struct cmd_header hdr;
u8 pad[3];
u8 bssid[ETH_ALEN];
} __packed;
struct adhoc_bssdesc {
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 type;
__le16 beaconperiod;
u8 dtimperiod;
__le64 timestamp;
__le64 localtime;
struct ieee_ie_ds_param_set ds;
u8 reserved1[4];
struct ieee_ie_ibss_param_set ibss;
u8 reserved2[4];
__le16 capability;
u8 rates[MAX_RATES];
/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
* Adhoc join command and will cause a binary layout mismatch with
* the firmware
*/
} __packed;
struct cmd_ds_802_11_ad_hoc_join {
struct cmd_header hdr;
struct adhoc_bssdesc bss;
__le16 failtimeout; /* Reserved on v9 and later */
__le16 probedelay; /* Reserved on v9 and later */
} __packed;
struct cmd_ds_802_11_ad_hoc_stop {
struct cmd_header hdr;
} __packed;
struct cmd_ds_802_11_enable_rsn {
struct cmd_header hdr;
__le16 action;
__le16 enable;
} __packed;
struct MrvlIEtype_keyParamSet {
/* type ID */
__le16 type;
/* length of Payload */
__le16 length;
/* type of key: WEP=0, TKIP=1, AES=2 */
__le16 keytypeid;
/* key control Info specific to a keytypeid */
__le16 keyinfo;
/* length of key */
__le16 keylen;
/* key material of size keylen */
u8 key[32];
} __packed;
#define MAX_WOL_RULES 16
struct host_wol_rule {
uint8_t rule_no;
uint8_t rule_ops;
__le16 sig_offset;
__le16 sig_length;
__le16 reserve;
__be32 sig_mask;
__be32 signature;
} __packed;
struct wol_config {
uint8_t action;
uint8_t pattern;
uint8_t no_rules_in_cmd;
uint8_t result;
struct host_wol_rule rule[MAX_WOL_RULES];
} __packed;
struct cmd_ds_host_sleep {
struct cmd_header hdr;
__le32 criteria;
uint8_t gpio;
uint16_t gap;
struct wol_config wol_conf;
} __packed;
struct cmd_ds_802_11_key_material {
struct cmd_header hdr;
__le16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
} __packed;
struct cmd_ds_802_11_eeprom_access {
struct cmd_header hdr;
__le16 action;
__le16 offset;
__le16 len;
/* firmware says it returns a maximum of 20 bytes */
#define LBS_EEPROM_READ_LEN 20
u8 value[LBS_EEPROM_READ_LEN];
} __packed;
struct cmd_ds_802_11_tpc_cfg {
struct cmd_header hdr;
__le16 action;
uint8_t enable;
int8_t P0;
int8_t P1;
int8_t P2;
uint8_t usesnr;
} __packed;
struct cmd_ds_802_11_pa_cfg {
struct cmd_header hdr;
__le16 action;
uint8_t enable;
int8_t P0;
int8_t P1;
int8_t P2;
} __packed;
struct cmd_ds_802_11_led_ctrl {
struct cmd_header hdr;
__le16 action;
__le16 numled;
u8 data[256];
} __packed;
/* Automatic Frequency Control */
struct cmd_ds_802_11_afc {
struct cmd_header hdr;
__le16 afc_auto;
union {
struct {
__le16 threshold;
__le16 period;
};
struct {
__le16 timing_offset; /* signed */
__le16 carrier_offset; /* signed */
};
};
} __packed;
struct cmd_tx_rate_query {
__le16 txrate;
} __packed;
struct cmd_ds_get_tsf {
__le64 tsfvalue;
} __packed;
struct cmd_ds_bt_access {
struct cmd_header hdr;
__le16 action;
__le32 id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
} __packed;
struct cmd_ds_fwt_access {
struct cmd_header hdr;
__le16 action;
__le32 id;
u8 valid;
u8 da[ETH_ALEN];
u8 dir;
u8 ra[ETH_ALEN];
__le32 ssn;
__le32 dsn;
__le32 metric;
u8 rate;
u8 hopcount;
u8 ttl;
__le32 expiration;
u8 sleepmode;
__le32 snr;
__le32 references;
u8 prec[ETH_ALEN];
} __packed;
struct cmd_ds_mesh_config {
struct cmd_header hdr;
__le16 action;
__le16 channel;
__le16 type;
__le16 length;
u8 data[128]; /* last position reserved */
} __packed;
struct cmd_ds_mesh_access {
struct cmd_header hdr;
__le16 action;
__le32 data[32]; /* last position reserved */
} __packed;
/* Number of stats counters returned by the firmware */
#define MESH_STATS_NUM 8
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
/*
* linux/drivers/net/wireless/libertas/if_spi.c
*
* Driver for Marvell SPI WLAN cards.
*
* Copyright 2008 Analog Devices Inc.
*
* Authors:
* Andrey Yurovsky <andrey@cozybit.com>
* Colin McCabe <colin@cozybit.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#ifndef _LBS_IF_SPI_H_
#define _LBS_IF_SPI_H_
void if_spi_init(void);
void if_spi_exit(void);
#define IPFIELD_ALIGN_OFFSET 2
#define IF_SPI_CMD_BUF_SIZE 2400
/***************** Firmware *****************/
#define IF_SPI_FW_NAME_MAX 30
struct chip_ident {
u16 chip_id;
u16 name;
};
#define MAX_MAIN_FW_LOAD_CRC_ERR 10
/* Chunk size when loading the helper firmware */
#define HELPER_FW_LOAD_CHUNK_SZ 64
/* Value to write to indicate end of helper firmware dnld */
#define FIRMWARE_DNLD_OK 0x0000
/* Value to check once the main firmware is downloaded */
#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
/***************** SPI Interface Unit *****************/
/* Masks used in SPI register read/write operations */
#define IF_SPI_READ_OPERATION_MASK 0x0
#define IF_SPI_WRITE_OPERATION_MASK 0x8000
/* SPI register offsets. 4-byte aligned. */
#define IF_SPI_DEVICEID_CTRL_REG 0x00 /* DeviceID controller reg */
#define IF_SPI_IO_READBASE_REG 0x04 /* Read I/O base reg */
#define IF_SPI_IO_WRITEBASE_REG 0x08 /* Write I/O base reg */
#define IF_SPI_IO_RDWRPORT_REG 0x0C /* Read/Write I/O port reg */
#define IF_SPI_CMD_READBASE_REG 0x10 /* Read command base reg */
#define IF_SPI_CMD_WRITEBASE_REG 0x14 /* Write command base reg */
#define IF_SPI_CMD_RDWRPORT_REG 0x18 /* Read/Write command port reg */
#define IF_SPI_DATA_READBASE_REG 0x1C /* Read data base reg */
#define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */
#define IF_SPI_DATA_RDWRPORT_REG 0x24 /* Read/Write data port reg */
#define IF_SPI_SCRATCH_1_REG 0x28 /* Scratch reg 1 */
#define IF_SPI_SCRATCH_2_REG 0x2C /* Scratch reg 2 */
#define IF_SPI_SCRATCH_3_REG 0x30 /* Scratch reg 3 */
#define IF_SPI_SCRATCH_4_REG 0x34 /* Scratch reg 4 */
#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
#define IF_SPI_TX_FRAME_STATUS_REG 0x3C /* Tx frame status reg */
#define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */
#define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */
#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
#define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */
#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
#define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */
#define IF_SPI_HOST_INT_STATUS_REG 0x5C /* Host interrupt status reg */
#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
#define IF_SPI_HOST_INT_STATUS_MASK_REG 0x64 /* Host interrupt status mask */
#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
#define IF_SPI_DELAY_READ_REG 0x6C /* Delay read reg */
#define IF_SPI_SPU_BUS_MODE_REG 0x70 /* SPU BUS mode reg */
/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
/** Host Interrupt Control bit : Wake up */
#define IF_SPI_HICT_WAKE_UP (1<<0)
/** Host Interrupt Control bit : WLAN ready */
#define IF_SPI_HICT_WLAN_READY (1<<1)
/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */
/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */
/*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */
/** Host Interrupt Control bit : Tx auto download */
#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5)
/** Host Interrupt Control bit : Rx auto upload */
#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6)
/** Host Interrupt Control bit : Command auto download */
#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7)
/** Host Interrupt Control bit : Command auto upload */
#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8)
/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
/** Card Interrupt Case bit : Tx download over */
#define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0)
/** Card Interrupt Case bit : Rx upload over */
#define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1)
/** Card Interrupt Case bit : Command download over */
#define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2)
/** Card Interrupt Case bit : Host event */
#define IF_SPI_CIC_HOST_EVENT (1<<3)
/** Card Interrupt Case bit : Command upload over */
#define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4)
/** Card Interrupt Case bit : Power down */
#define IF_SPI_CIC_POWER_DOWN (1<<5)
/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
#define IF_SPI_CIS_TX_DOWNLOAD_OVER (1<<0)
#define IF_SPI_CIS_RX_UPLOAD_OVER (1<<1)
#define IF_SPI_CIS_CMD_DOWNLOAD_OVER (1<<2)
#define IF_SPI_CIS_HOST_EVENT (1<<3)
#define IF_SPI_CIS_CMD_UPLOAD_OVER (1<<4)
#define IF_SPI_CIS_POWER_DOWN (1<<5)
/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
#define IF_SPI_HICU_TX_DOWNLOAD_RDY (1<<0)
#define IF_SPI_HICU_RX_UPLOAD_RDY (1<<1)
#define IF_SPI_HICU_CMD_DOWNLOAD_RDY (1<<2)
#define IF_SPI_HICU_CARD_EVENT (1<<3)
#define IF_SPI_HICU_CMD_UPLOAD_RDY (1<<4)
#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW (1<<5)
#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW (1<<6)
#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW (1<<7)
#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW (1<<8)
#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW (1<<9)
#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10)
/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
/** Host Interrupt Status bit : Tx download ready */
#define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0)
/** Host Interrupt Status bit : Rx upload ready */
#define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1)
/** Host Interrupt Status bit : Command download ready */
#define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2)
/** Host Interrupt Status bit : Card event */
#define IF_SPI_HIST_CARD_EVENT (1<<3)
/** Host Interrupt Status bit : Command upload ready */
#define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4)
/** Host Interrupt Status bit : I/O write FIFO overflow */
#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5)
/** Host Interrupt Status bit : I/O read FIFO underflow */
#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6)
/** Host Interrupt Status bit : Data write FIFO overflow */
#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7)
/** Host Interrupt Status bit : Data read FIFO underflow */
#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8)
/** Host Interrupt Status bit : Command write FIFO overflow */
#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9)
/** Host Interrupt Status bit : Command read FIFO underflow */
#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10)
/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
/** Host Interrupt Status Mask bit : Tx download ready */
#define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0)
/** Host Interrupt Status Mask bit : Rx upload ready */
#define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1)
/** Host Interrupt Status Mask bit : Command download ready */
#define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2)
/** Host Interrupt Status Mask bit : Card event */
#define IF_SPI_HISM_CARDEVENT (1<<3)
/** Host Interrupt Status Mask bit : Command upload ready */
#define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4)
/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5)
/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6)
/** Host Interrupt Status Mask bit : Data write FIFO overflow */
#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7)
/** Host Interrupt Status Mask bit : Data write FIFO underflow */
#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8)
/** Host Interrupt Status Mask bit : Command write FIFO overflow */
#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9)
/** Host Interrupt Status Mask bit : Command write FIFO underflow */
#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10)
/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
/* SCK edge on which the WLAN module outputs data on MISO */
#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
/* In a SPU read operation, there is a delay between writing the SPU
* register name and getting back data from the WLAN module.
* This can be specified in terms of nanoseconds or in terms of dummy
* clock cycles which the master must output before receiving a response. */
#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
/* Some different modes of SPI operation */
#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,111 @@
/**
* Contains all definitions needed for the Libertas' MESH implementation.
*/
#ifndef _LBS_MESH_H_
#define _LBS_MESH_H_
#include <net/iw_handler.h>
#include <net/lib80211.h>
#include "host.h"
#ifdef CONFIG_G900_WIFI_MESH
/* Mesh statistics */
struct lbs_mesh_stats {
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
u32 fwd_drop_ttl; /* Fwd: TTL zero */
u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
u32 fwd_drop_noroute; /* Fwd: No route to Destination */
u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
u32 drop_blind; /* Rx: Dropped by blinding table */
u32 tx_failed_cnt; /* Tx: Failed transmissions */
};
struct net_device;
struct lbs_private;
int lbs_init_mesh(struct lbs_private *priv);
int lbs_deinit_mesh(struct lbs_private *priv);
int lbs_add_mesh(struct lbs_private *priv);
void lbs_remove_mesh(struct lbs_private *priv);
/* Sending / Receiving */
struct rxpd;
struct txpd;
struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
struct net_device *dev, struct rxpd *rxpd);
void lbs_mesh_set_txpd(struct lbs_private *priv,
struct net_device *dev, struct txpd *txpd);
/* Command handling */
struct cmd_ds_command;
struct cmd_ds_mesh_access;
struct cmd_ds_mesh_config;
int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
int lbs_mesh_bt_reset(struct lbs_private *priv);
int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
struct cmd_ds_fwt_access *cmd);
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
struct cmd_ds_mesh_access *cmd);
int lbs_mesh_config_send(struct lbs_private *priv,
struct cmd_ds_mesh_config *cmd,
uint16_t action, uint16_t type);
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
/* Persistent configuration */
void lbs_persist_config_init(struct net_device *net);
void lbs_persist_config_remove(struct net_device *net);
/* Ethtool statistics */
struct ethtool_stats;
void lbs_mesh_ethtool_get_stats(struct net_device *dev,
struct ethtool_stats *stats, uint64_t *data);
int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
void lbs_mesh_ethtool_get_strings(struct net_device *dev,
uint32_t stringset, uint8_t *s);
/* Accessors */
#define lbs_mesh_open(priv) (priv->mesh_open)
#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED)
#else
#define lbs_init_mesh(priv)
#define lbs_deinit_mesh(priv)
#define lbs_add_mesh(priv)
#define lbs_remove_mesh(priv)
#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
#define lbs_mesh_set_txpd(priv, dev, txpd)
#define lbs_mesh_config(priv, enable, chan)
#define lbs_mesh_open(priv) (0)
#define lbs_mesh_connected(priv) (0)
#endif
#endif

View File

@@ -0,0 +1,44 @@
#include <net/ieee80211_radiotap.h>
struct tx_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
u8 txpower;
u8 rts_retries;
u8 data_retries;
} __packed;
#define TX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \
(1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \
(1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \
0)
#define IEEE80211_FC_VERSION_MASK 0x0003
#define IEEE80211_FC_TYPE_MASK 0x000c
#define IEEE80211_FC_TYPE_MGT 0x0000
#define IEEE80211_FC_TYPE_CTL 0x0004
#define IEEE80211_FC_TYPE_DATA 0x0008
#define IEEE80211_FC_SUBTYPE_MASK 0x00f0
#define IEEE80211_FC_TOFROMDS_MASK 0x0300
#define IEEE80211_FC_TODS_MASK 0x0100
#define IEEE80211_FC_FROMDS_MASK 0x0200
#define IEEE80211_FC_NODS 0x0000
#define IEEE80211_FC_TODS 0x0100
#define IEEE80211_FC_FROMDS 0x0200
#define IEEE80211_FC_DSTODS 0x0300
struct rx_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 flags;
u8 rate;
u8 antsignal;
} __packed;
#define RX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\
0)

View File

@@ -0,0 +1,276 @@
/**
* This file contains the handling of RX in wlan driver.
*/
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <net/cfg80211.h>
#include "defs.h"
#include "host.h"
#include "radiotap.h"
#include "decl.h"
#include "dev.h"
struct eth803hdr {
u8 dest_addr[6];
u8 src_addr[6];
u16 h803_len;
} __packed;
struct rfc1042hdr {
u8 llc_dsap;
u8 llc_ssap;
u8 llc_ctrl;
u8 snap_oui[3];
u16 snap_type;
} __packed;
struct rxpackethdr {
struct eth803hdr eth803_hdr;
struct rfc1042hdr rfc1042_hdr;
} __packed;
struct rx80211packethdr {
struct rxpd rx_pd;
void *eth80211_hdr;
} __packed;
static int process_rxed_802_11_packet(struct lbs_private *priv,
struct sk_buff *skb);
/**
* @brief This function processes received packet and forwards it
* to kernel/upper layer
*
* @param priv A pointer to struct lbs_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
{
int ret = 0;
struct net_device *dev = priv->dev;
struct rxpackethdr *p_rx_pkt;
struct rxpd *p_rx_pd;
int hdrchop;
struct ethhdr *p_ethhdr;
const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
lbs_deb_enter(LBS_DEB_RX);
BUG_ON(!skb);
skb->ip_summed = CHECKSUM_NONE;
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
return process_rxed_802_11_packet(priv, skb);
p_rx_pd = (struct rxpd *) skb->data;
p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
le32_to_cpu(p_rx_pd->pkt_ptr));
dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
min_t(unsigned int, skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
lbs_deb_rx("rx err: frame received with bad length\n");
dev->stats.rx_length_errors++;
ret = 0;
dev_kfree_skb(skb);
goto done;
}
lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n",
skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr),
skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr));
lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
sizeof(p_rx_pkt->eth803_hdr.dest_addr));
lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr,
sizeof(p_rx_pkt->eth803_hdr.src_addr));
if (memcmp(&p_rx_pkt->rfc1042_hdr,
rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
/*
* Replace the 803 header and rfc1042 header (llc/snap) with an
* EthernetII header, keep the src/dst and snap_type (ethertype)
*
* The firmware only passes up SNAP frames converting
* all RX Data from 802.11 to 802.2/LLC/SNAP frames.
*
* To create the Ethernet II, just move the src, dst address right
* before the snap_type.
*/
p_ethhdr = (struct ethhdr *)
((u8 *) &p_rx_pkt->eth803_hdr
+ sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr)
- sizeof(p_rx_pkt->eth803_hdr.dest_addr)
- sizeof(p_rx_pkt->eth803_hdr.src_addr)
- sizeof(p_rx_pkt->rfc1042_hdr.snap_type));
memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr,
sizeof(p_ethhdr->h_source));
memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr,
sizeof(p_ethhdr->h_dest));
/* Chop off the rxpd + the excess memory from the 802.2/llc/snap header
* that was removed
*/
hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd;
} else {
lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP",
(u8 *) &p_rx_pkt->rfc1042_hdr,
sizeof(p_rx_pkt->rfc1042_hdr));
/* Chop off the rxpd */
hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd;
}
/* Chop off the leading header bytes so the skb points to the start of
* either the reconstructed EthII frame or the 802.2/llc/snap frame
*/
skb_pull(skb, hdrchop);
priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
skb->protocol = eth_type_trans(skb, dev);
if (in_interrupt())
netif_rx(skb);
else
netif_rx_ni(skb);
ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
/**
* @brief This function converts Tx/Rx rates from the Marvell WLAN format
* (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
*
* @param rate Input rate
* @return Output Rate (0 if invalid)
*/
static u8 convert_mv_rate_to_radiotap(u8 rate)
{
switch (rate) {
case 0: /* 1 Mbps */
return 2;
case 1: /* 2 Mbps */
return 4;
case 2: /* 5.5 Mbps */
return 11;
case 3: /* 11 Mbps */
return 22;
/* case 4: reserved */
case 5: /* 6 Mbps */
return 12;
case 6: /* 9 Mbps */
return 18;
case 7: /* 12 Mbps */
return 24;
case 8: /* 18 Mbps */
return 36;
case 9: /* 24 Mbps */
return 48;
case 10: /* 36 Mbps */
return 72;
case 11: /* 48 Mbps */
return 96;
case 12: /* 54 Mbps */
return 108;
}
lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
return 0;
}
/**
* @brief This function processes a received 802.11 packet and forwards it
* to kernel/upper layer
*
* @param priv A pointer to struct lbs_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
static int process_rxed_802_11_packet(struct lbs_private *priv,
struct sk_buff *skb)
{
int ret = 0;
struct net_device *dev = priv->dev;
struct rx80211packethdr *p_rx_pkt;
struct rxpd *prxpd;
struct rx_radiotap_hdr radiotap_hdr;
struct rx_radiotap_hdr *pradiotap_hdr;
lbs_deb_enter(LBS_DEB_RX);
p_rx_pkt = (struct rx80211packethdr *) skb->data;
prxpd = &p_rx_pkt->rx_pd;
/* lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); */
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
lbs_deb_rx("rx err: frame received with bad length\n");
dev->stats.rx_length_errors++;
ret = -EINVAL;
kfree_skb(skb);
goto done;
}
lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
/* create the exported radio header */
/* radiotap header */
memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
/* XXX must check radiotap_hdr.hdr.it_pad for pad */
radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
/* XXX must check no carryout */
radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
/* chop the rxpd */
skb_pull(skb, sizeof(struct rxpd));
/* add space for the new radio header */
if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__);
ret = -ENOMEM;
kfree_skb(skb);
goto done;
}
pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
skb->protocol = eth_type_trans(skb, priv->dev);
if (in_interrupt())
netif_rx(skb);
else
netif_rx_ni(skb);
ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}

View File

@@ -0,0 +1,204 @@
/**
* This file contains the handling of TX in wlan driver.
*/
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/sched.h>
#include <net/cfg80211.h>
#include "host.h"
#include "radiotap.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
/**
* @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
* units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
*
* @param rate Input rate
* @return Output Rate (0 if invalid)
*/
static u32 convert_radiotap_rate_to_mv(u8 rate)
{
switch (rate) {
case 2: /* 1 Mbps */
return 0 | (1 << 4);
case 4: /* 2 Mbps */
return 1 | (1 << 4);
case 11: /* 5.5 Mbps */
return 2 | (1 << 4);
case 22: /* 11 Mbps */
return 3 | (1 << 4);
case 12: /* 6 Mbps */
return 4 | (1 << 4);
case 18: /* 9 Mbps */
return 5 | (1 << 4);
case 24: /* 12 Mbps */
return 6 | (1 << 4);
case 36: /* 18 Mbps */
return 7 | (1 << 4);
case 48: /* 24 Mbps */
return 8 | (1 << 4);
case 72: /* 36 Mbps */
return 9 | (1 << 4);
case 96: /* 48 Mbps */
return 10 | (1 << 4);
case 108: /* 54 Mbps */
return 11 | (1 << 4);
}
return 0;
}
/**
* @brief This function checks the conditions and sends packet to IF
* layer if everything is ok.
*
* @param priv A pointer to struct lbs_private structure
* @param skb A pointer to skb which includes TX packet
* @return 0 or -1
*/
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
struct lbs_private *priv = dev->ml_priv;
struct txpd *txpd;
char *p802x_hdr;
uint16_t pkt_len;
netdev_tx_t ret = NETDEV_TX_OK;
lbs_deb_enter(LBS_DEB_TX);
/* We need to protect against the queues being restarted before
we get round to stopping them */
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->surpriseremoved)
goto free;
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
/* We'll never manage to send this one; drop it and return 'OK' */
dev->stats.tx_dropped++;
dev->stats.tx_errors++;
goto free;
}
netif_stop_queue(priv->dev);
if (priv->mesh_dev)
netif_stop_queue(priv->mesh_dev);
if (priv->tx_pending_len) {
/* This can happen if packets come in on the mesh and eth
device simultaneously -- there's no mutual exclusion on
hard_start_xmit() calls between devices. */
lbs_deb_tx("Packet on %s while busy\n", dev->name);
ret = NETDEV_TX_BUSY;
goto unlock;
}
priv->tx_pending_len = -1;
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
txpd = (void *)priv->tx_pending_buf;
memset(txpd, 0, sizeof(struct txpd));
p802x_hdr = skb->data;
pkt_len = skb->len;
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
/* set txpd fields from the radiotap header */
txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate));
/* skip the radiotap header */
p802x_hdr += sizeof(*rtap_hdr);
pkt_len -= sizeof(*rtap_hdr);
/* copy destination address from 802.11 header */
memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
} else {
/* copy destination address from 802.3 header */
memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
}
txpd->tx_packet_length = cpu_to_le16(pkt_len);
txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
lbs_mesh_set_txpd(priv, dev, txpd);
lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
spin_lock_irqsave(&priv->driver_lock, flags);
priv->tx_pending_len = pkt_len + sizeof(struct txpd);
lbs_deb_tx("%s lined up packet\n", __func__);
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
/* Keep the skb to echo it back once Tx feedback is
received from FW */
skb_orphan(skb);
/* Keep the skb around for when we get feedback */
priv->currenttxskb = skb;
} else {
free:
dev_kfree_skb_any(skb);
}
unlock:
spin_unlock_irqrestore(&priv->driver_lock, flags);
wake_up(&priv->waitq);
lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
return ret;
}
/**
* @brief This function sends to the host the last transmitted packet,
* filling the radiotap headers with transmission information.
*
* @param priv A pointer to struct lbs_private structure
* @param status A 32 bit value containing transmission status.
*
* @returns void
*/
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
{
struct tx_radiotap_hdr *radiotap_hdr;
if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR ||
priv->currenttxskb == NULL)
return;
radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
radiotap_hdr->data_retries = try_count ?
(1 + priv->txretrycount - try_count) : 0;
priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
priv->dev);
netif_rx(priv->currenttxskb);
priv->currenttxskb = NULL;
if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
if (priv->mesh_dev && lbs_mesh_connected(priv))
netif_wake_queue(priv->mesh_dev);
}
EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);

View File

@@ -0,0 +1,266 @@
/**
* This header file contains definition for global types
*/
#ifndef _LBS_TYPES_H_
#define _LBS_TYPES_H_
#include <linux/if_ether.h>
#include <linux/ieee80211.h>
#include <asm/byteorder.h>
struct ieee_ie_header {
u8 id;
u8 len;
} __packed;
struct ieee_ie_cf_param_set {
struct ieee_ie_header header;
u8 cfpcnt;
u8 cfpperiod;
__le16 cfpmaxduration;
__le16 cfpdurationremaining;
} __packed;
struct ieee_ie_ibss_param_set {
struct ieee_ie_header header;
__le16 atimwindow;
} __packed;
union ieee_ss_param_set {
struct ieee_ie_cf_param_set cf;
struct ieee_ie_ibss_param_set ibss;
} __packed;
struct ieee_ie_fh_param_set {
struct ieee_ie_header header;
__le16 dwelltime;
u8 hopset;
u8 hoppattern;
u8 hopindex;
} __packed;
struct ieee_ie_ds_param_set {
struct ieee_ie_header header;
u8 channel;
} __packed;
union ieee_phy_param_set {
struct ieee_ie_fh_param_set fh;
struct ieee_ie_ds_param_set ds;
} __packed;
/** TLV type ID definition */
#define PROPRIETARY_TLV_BASE_ID 0x0100
/* Terminating TLV type */
#define MRVL_TERMINATE_TLV_ID 0xffff
#define TLV_TYPE_SSID 0x0000
#define TLV_TYPE_RATES 0x0001
#define TLV_TYPE_PHY_FH 0x0002
#define TLV_TYPE_PHY_DS 0x0003
#define TLV_TYPE_CF 0x0004
#define TLV_TYPE_IBSS 0x0006
#define TLV_TYPE_DOMAIN 0x0007
#define TLV_TYPE_POWER_CAPABILITY 0x0021
#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0)
#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1)
#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2)
#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4)
#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5)
#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6)
#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7)
#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8)
#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9)
#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10)
#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11)
#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12)
#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13)
#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14)
#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15)
#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16)
#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17)
#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18)
#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19)
#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23)
#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31)
#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37)
#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291)
/** TLV related data structures*/
struct mrvl_ie_header {
__le16 type;
__le16 len;
} __packed;
struct mrvl_ie_data {
struct mrvl_ie_header header;
u8 Data[1];
} __packed;
struct mrvl_ie_rates_param_set {
struct mrvl_ie_header header;
u8 rates[1];
} __packed;
struct mrvl_ie_ssid_param_set {
struct mrvl_ie_header header;
u8 ssid[1];
} __packed;
struct mrvl_ie_wildcard_ssid_param_set {
struct mrvl_ie_header header;
u8 MaxSsidlength;
u8 ssid[1];
} __packed;
struct chanscanmode {
#ifdef __BIG_ENDIAN_BITFIELD
u8 reserved_2_7:6;
u8 disablechanfilt:1;
u8 passivescan:1;
#else
u8 passivescan:1;
u8 disablechanfilt:1;
u8 reserved_2_7:6;
#endif
} __packed;
struct chanscanparamset {
u8 radiotype;
u8 channumber;
struct chanscanmode chanscanmode;
__le16 minscantime;
__le16 maxscantime;
} __packed;
struct mrvl_ie_chanlist_param_set {
struct mrvl_ie_header header;
struct chanscanparamset chanscanparam[1];
} __packed;
struct mrvl_ie_cf_param_set {
struct mrvl_ie_header header;
u8 cfpcnt;
u8 cfpperiod;
__le16 cfpmaxduration;
__le16 cfpdurationremaining;
} __packed;
struct mrvl_ie_ds_param_set {
struct mrvl_ie_header header;
u8 channel;
} __packed;
struct mrvl_ie_rsn_param_set {
struct mrvl_ie_header header;
u8 rsnie[1];
} __packed;
struct mrvl_ie_tsf_timestamp {
struct mrvl_ie_header header;
__le64 tsftable[1];
} __packed;
/* v9 and later firmware only */
struct mrvl_ie_auth_type {
struct mrvl_ie_header header;
__le16 auth;
} __packed;
/** Local Power capability */
struct mrvl_ie_power_capability {
struct mrvl_ie_header header;
s8 minpower;
s8 maxpower;
} __packed;
/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
struct mrvl_ie_thresholds {
struct mrvl_ie_header header;
u8 value;
u8 freq;
} __packed;
struct mrvl_ie_beacons_missed {
struct mrvl_ie_header header;
u8 beaconmissed;
u8 reserved;
} __packed;
struct mrvl_ie_num_probes {
struct mrvl_ie_header header;
__le16 numprobes;
} __packed;
struct mrvl_ie_bcast_probe {
struct mrvl_ie_header header;
__le16 bcastprobe;
} __packed;
struct mrvl_ie_num_ssid_probe {
struct mrvl_ie_header header;
__le16 numssidprobe;
} __packed;
struct led_pin {
u8 led;
u8 pin;
} __packed;
struct mrvl_ie_ledgpio {
struct mrvl_ie_header header;
struct led_pin ledpin[1];
} __packed;
struct led_bhv {
uint8_t firmwarestate;
uint8_t led;
uint8_t ledstate;
uint8_t ledarg;
} __packed;
struct mrvl_ie_ledbhv {
struct mrvl_ie_header header;
struct led_bhv ledbhv[1];
} __packed;
/* Meant to be packed as the value member of a struct ieee80211_info_element.
* Note that the len member of the ieee80211_info_element varies depending on
* the mesh_id_len */
struct mrvl_meshie_val {
uint8_t oui[3];
uint8_t type;
uint8_t subtype;
uint8_t version;
uint8_t active_protocol_id;
uint8_t active_metric_id;
uint8_t mesh_capability;
uint8_t mesh_id_len;
uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
} __packed;
struct mrvl_meshie {
u8 id, len;
struct mrvl_meshie_val val;
} __packed;
struct mrvl_mesh_defaults {
__le32 bootflag;
uint8_t boottime;
uint8_t reserved;
__le16 channel;
struct mrvl_meshie meshie;
} __packed;
#endif

View File

@@ -0,0 +1,195 @@
/*
* Buttons support for Toshiba G900. GPIO buttons
* based on:
* Xiao Huang g900_button.c
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/gpio_keys.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <mach/g900-gpio.h>
#include <mach/gpio.h>
#ifdef CONFIG_SWITCH_GPIO
#include <linux/switch.h>
#include "../generic.h"
/*
static struct gpio_switch_platform_data headset_switch_data = {
.name = "h2w",
.gpio = GPIO51_BTN_nJackInsert,
};
static struct platform_device headset_switch_device = {
.name = "switch-gpio",
.dev = {
.platform_data = &headset_switch_data,
}
};
*/
static struct gpio_switch_platform_data kbr_switch_data = {
.name = "kbr",
.gpio = GPIO9_BTN_nKBOpen,
};
static struct platform_device kbr_switch_device = {
.name = "switch-gpio",
.dev = {
.platform_data = &kbr_switch_data,
}
};
static struct platform_device *switch_device[] __initdata = {
//&headset_switch_device,
&kbr_switch_device,
};
#endif
static struct gpio_keys_button gpio_buttons[] = {
#ifndef CONFIG_G900_POWER_BUTTON
{KEY_POWER, GPIO3_BTN_nPower, 0, "Power button"},
#endif
#ifndef CONFIG_SWITCH_GPIO
{99 , GPIO9_BTN_nKBOpen, 0, "Keyboard open"},
{SW_HEADPHONE_INSERT, GPIO51_BTN_nJackInsert, 0, "HeadPhone insert"},
#endif
{KEY_PLAY, GPIO10_BTN_nHeadSet, 0, "HeadSet button"},
};
static struct input_dev *input_dev = NULL;
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
int i, state;
int gpiovalue;
for (i = 0; i < ARRAY_SIZE(gpio_buttons); i++)
{
if (IRQ_GPIO(gpio_buttons[i].gpio) == irq)
{
gpiovalue = GET_GPIO(gpio_buttons[i].gpio);
//printk("gpio=%d, active_low=%d\n", gpiovalue, gpio_buttons[i].active_low );
state = (gpiovalue ? 1 : 0) ^ (gpio_buttons[i].active_low);
/*state = (gpio_buttons[i].active_low ? !state : state);*/
input_report_key(input_dev, gpio_buttons[i].code, state);
input_sync(input_dev);
//printk("code=%d, state=%d\n", gpio_buttons[i].code, state);
}
}
return IRQ_HANDLED;
}
static int buttons_probe(struct platform_device *pdev)
{
int i, err;
int irqflag = IRQF_SAMPLE_RANDOM;
#ifdef CONFIG_PREEMPT_RT
irqflag |= IRQF_NODELAY;
#endif
if (!machine_is_g900())
return -ENODEV;
#ifdef CONFIG_SWITCH_GPIO
err=platform_add_devices(ARRAY_AND_SIZE(switch_device));
#endif
if (!(input_dev = input_allocate_device())) return -ENOMEM;
input_dev->name = "g900_buttons";
set_bit(EV_KEY, input_dev->evbit);
for (i = 0; i < ARRAY_SIZE(gpio_buttons); i++)
{
set_bit(gpio_buttons[i].code, input_dev->keybit);
}
err=input_register_device(input_dev);
if (err) {
printk(KERN_ERR "Could not input_register_device \n");
return err;
}
for (i = 0; i < ARRAY_SIZE(gpio_buttons); i++)
{
//assign irq and keybit
set_irq_type(IRQ_GPIO(gpio_buttons[i].gpio), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING);
err = request_irq(IRQ_GPIO(gpio_buttons[i].gpio), gpio_irq_handler, irqflag, "g900-gpio-buttons", NULL);
if (err)
{
printk(KERN_ERR "%s: Cannot assign GPIO(%d) IRQ\n", __FUNCTION__, gpio_buttons[i].gpio);
return err;
}
//printk("*****IRQ %d OK****", IRQ_GPIO(gpio_buttons[i].gpio));
}
return 0;
}
static int buttons_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(gpio_buttons); i++)
{
free_irq(IRQ_GPIO(gpio_buttons[i].gpio), NULL);
}
input_unregister_device(input_dev);
input_free_device(input_dev);
return 0;
}
static int buttons_suspend(struct platform_device *pdev, pm_message_t state)
{
return 0;
}
static int buttons_resume(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver buttons_driver = {
.driver = {
.name = "g900-button",
},
.probe = buttons_probe,
.remove = buttons_remove,
#ifdef CONFIG_PM
.suspend = buttons_suspend,
.resume = buttons_resume,
#endif
};
static int __init buttons_init(void)
{
return platform_driver_register(&buttons_driver);
}
static void __exit buttons_exit(void)
{
platform_driver_unregister(&buttons_driver);
}
module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("El Tuba<tuba.linux@gmail.com>");
MODULE_DESCRIPTION("Buttons driver for Toshiba G900");

View File

@@ -0,0 +1,239 @@
/*
* Keypad driver for Toshiba G900.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
*
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <mach/pxa27x_keypad.h>
#include <mach/mfp-pxa27x.h>
#include "../generic.h"
/****************************************************************
* Keyboard
****************************************************************/
static unsigned long g900_keypad_pins[] __initdata = {
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
GPIO95_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH,
GPIO13_KP_MKIN_7 | WAKEUP_ON_LEVEL_HIGH,
GPIO103_KP_MKOUT_0,
GPIO104_KP_MKOUT_1,
GPIO105_KP_MKOUT_2,
GPIO106_KP_MKOUT_3,
GPIO107_KP_MKOUT_4,
GPIO108_KP_MKOUT_5,
GPIO35_KP_MKOUT_6,
GPIO22_KP_MKOUT_7,
};
static unsigned int g900_matrix_keys[] = {
KEY(0, 0, KEY_C),
KEY(0, 1, KEY_Z),
KEY(0, 2, KEY_B),
KEY(0, 3, KEY_X),
KEY(0, 4, KEY_V),
KEY(0, 5, KEY_LEFTSHIFT), /* Shift on keyboard */
KEY(0, 6, KEY_F1), /* Left Softkey on keyboard */
KEY(0, 7, KEY_N),
// KEY(1, 0, KEY_LANGUAGE), /* RU button */
KEY(1, 0, KEY_X), /* RU button */
KEY(1, 1, KEY_MENU), /* WIN key on keyboard */
KEY(1, 2, KEY_SPACE),
KEY(1, 3, KEY_LEFTALT), /*KEY_OK*/
KEY(1, 4, KEY_2),
KEY(1, 5, KEY_FN), /* GREEN COMMA */
// KEY(1, 5, KEY_8),
KEY(1, 6, KEY_F2), /* Right Softkey on keyboard */
KEY(1, 7, KEY_COMMA),
KEY(2, 0, KEY_R),
KEY(2, 1, KEY_W),
KEY(2, 2, KEY_Y),
KEY(2, 3, KEY_E),
KEY(2, 4, KEY_T),
KEY(2, 5, KEY_Q),
KEY(2, 6, KEY_U),
KEY(2, 7, KEY_J),
KEY(3, 0, KEY_F),
KEY(3, 1, KEY_S),
KEY(3, 2, KEY_G),
KEY(3, 3, KEY_D),
KEY(3, 4, KEY_H),
KEY(3, 5, KEY_A),
KEY(3, 6, KEY_WWW), /* IE button upper the screen */
KEY(3, 7, KEY_ENTER),
KEY(4, 0, KEY_BACKSPACE),
KEY(4, 1, KEY_P),
KEY(4, 2, KEY_O),
KEY(4, 3, KEY_I),
KEY(4, 4, KEY_1),
KEY(4, 5, KEY_VOLUMEDOWN), /* VOLUME DOWN */
KEY(4, 6, KEY_VOLUMEUP), /* VOLUME UP */
KEY(4, 7, KEY_CAMERA),
KEY(5, 0, KEY_KPENTER), /* Middle button below the screen */
KEY(5, 1, KEY_UP),
KEY(5, 2, KEY_APOSTROPHE),
KEY(5, 3, KEY_M),
KEY(5, 4, KEY_F3), /* GREEN PHONE */
KEY(5, 5, KEY_UP), /* UP dpad*/
KEY(5, 6, KEY_BACK), /* KEY_OK */
KEY(5, 7, KEY_F4), /* RED PHONE */
KEY(6, 0, KEY_LEFTCTRL),
KEY(6, 1, KEY_BACKSLASH), /* + shift = | */
KEY(6, 2, KEY_L),
KEY(6, 3, KEY_K),
KEY(6, 4, KEY_F2), /* Right Softkey below the screen */
KEY(6, 5, KEY_LEFT), /* LEFT dpad*/
KEY(6, 6, KEY_F1), /* Left Softkey below the screen */
KEY(6, 7, KEY_DOWN), /* DOWN dpad*/
KEY(7, 0, KEY_RIGHT),
KEY(7, 1, KEY_DOWN),
KEY(7, 2, KEY_LEFT),
KEY(7, 3, KEY_DOT),
KEY(7, 4, KEY_MAIL), /* Key mail below the screen */
KEY(7, 5, KEY_RIGHT), /* RIGHT dpad*/
KEY(7, 6, KEY_MENU), /* Windows key below the screen KEY_RIGHTMETA*/
KEY(7, 7, KEY_HOME), /* Key Contact below the screen */
/* keys alternate function */
KEY(8, 0, KEY_SEMICOLON), /* + shift = : */
KEY(8, 1, KEY_MINUS), /* + shift = _ */
KEY(8, 2, KEY_EQUAL),
KEY(8, 3, KEY_APOSTROPHE), /* + shift = ' */
KEY(8, 4, KEY_SEMICOLON),
KEY(8, 5, KEY_LEFTSHIFT),
KEY(8, 6, KEY_F1),
KEY(8, 7, KEY_7),
KEY(9, 0, KEY_TAB),
KEY(9, 1, KEY_LEFTMETA),
KEY(9, 2, KEY_SPACE),
KEY(9, 3, KEY_LEFTALT),
KEY(9, 4, KEY_2),
// KEY(9, 5, KEY_FN), /* KEY_FN */
KEY(9, 6, KEY_F2),
KEY(9, 7, KEY_8), /* + shift = * */
KEY(10, 0, KEY_7), /* + shift = & */
KEY(10, 1, KEY_4), /* + shift = $ */
KEY(10, 2, KEY_0), /* + shift = ) */
KEY(10, 3, KEY_5), /* + shift = % */
KEY(10, 4, KEY_9), /* + shift = ( */
KEY(10, 5, KEY_2), /* + shift = @ */
KEY(10, 6, KEY_1),
KEY(10, 7, KEY_4),
KEY(11, 0, KEY_SLASH), /* + shift = ? */
KEY(11, 1, KEY_6), /* + shift = ^ */
KEY(11, 2, KEY_1), /* + shift = ! */
KEY(11, 3, KEY_BACKSLASH),
KEY(11, 4, KEY_MINUS),
KEY(11, 5, KEY_GRAVE), /* + shift = ~ */
KEY(11, 6, KEY_WWW),
KEY(11, 7, KEY_ENTER),
KEY(12, 0, KEY_DELETE),
KEY(12, 1, KEY_SLASH),
KEY(12, 2, KEY_3),
KEY(12, 3, KEY_2),
KEY(12, 4, KEY_1),
KEY(12, 5, KEY_VOLUMEDOWN),
KEY(12, 6, KEY_VOLUMEUP),
KEY(12, 7, KEY_CAMERA),
KEY(13, 0, KEY_KPENTER),
KEY(13, 1, KEY_PAGEUP), /* PG UP*/
KEY(13, 2, KEY_9),
KEY(13, 3, KEY_8),
KEY(13, 4, KEY_PHONE), /* GREEN PHONE */
KEY(13, 5, KEY_UP),
KEY(13, 6, KEY_OK),
KEY(13, 7, KEY_F4), /* RED PHONE */
KEY(14, 0, KEY_ESC),
KEY(14, 1, KEY_KPPLUS),
KEY(14, 2, KEY_6),
KEY(14, 3, KEY_5),
KEY(14, 4, KEY_F2),
KEY(14, 5, KEY_LEFT),
KEY(14, 6, KEY_F1),
KEY(14, 7, KEY_DOWN),
KEY(15, 0, KEY_X), /* FOLDER */
KEY(15, 1, KEY_PAGEDOWN), /* PG DWN */
KEY(15, 2, KEY_3), /* shift + 3 = # */
KEY(15, 3, KEY_0),
KEY(15, 4, KEY_MAIL),
KEY(15, 5, KEY_RIGHT),
KEY(15, 6, KEY_RIGHTMETA),
KEY(15, 7, KEY_HOME)
};
static struct pxa27x_keypad_platform_data g900_keypad_platform_data = {
.matrix_key_rows = 8,
.matrix_key_cols = 8,
.matrix_key_map = g900_matrix_keys,
.matrix_key_map_size = ARRAY_SIZE(g900_matrix_keys),
// .direct_key_map = { KEY_CONNECT },
// .direct_key_num = 1,
// .debounce_interval = 30,
};
static int __devinit g900_keypad_probe(struct platform_device *dev)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(g900_keypad_pins));
pxa_set_keypad_info(&g900_keypad_platform_data);
return 0;
}
static struct platform_driver g900_keypad_driver = {
.driver = {
.name = "g900-keyboard",
},
.probe = g900_keypad_probe,
};
static int __init g900_keypad_init(void)
{
if (!machine_is_g900())
return -ENODEV;
return platform_driver_register(&g900_keypad_driver);
}
static void __exit g900_keypad_exit(void)
{
platform_driver_unregister(&g900_keypad_driver);
}
module_init(g900_keypad_init);
module_exit(g900_keypad_exit);
MODULE_AUTHOR ("Angell Fear <angell@angellfear.ru>");
MODULE_DESCRIPTION ("Keypad support for Toshiba G900");
MODULE_LICENSE ("GPL");

View File

@@ -0,0 +1,129 @@
/*
* Buttons support for Toshiba G900. GPIO buttons
* based on:
* Xiao Huang g900_button.c
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/gpio_keys.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <mach/g900-gpio.h>
#include <mach/gpio.h>
#include <mach/regs-ost.h>
#include <mach/reset.h>
#define BTN_POWER GPIO3_BTN_nPower
static unsigned int noreset;
module_param(noreset, uint, 0);
MODULE_PARM_DESC(noreset, "Set 0 = reset, any = no action)"); /* TODO add pm suspend action */
static void cpu_hw_reset(void)
{
/* Initialize the watchdog and let it fire */
OWER = OWER_WME;
OSSR = OSSR_M3;
OSMR3 = OSCR + 368640; /* ... in 100 ms */
}
static irqreturn_t pwr_btn_irq(int irq, void *dev_id)
{
int state;
state = GET_GPIO(BTN_POWER);
if(state){
printk("g900-power-button: unpress");
}else{
if(noreset == 0 )
{
cpu_hw_reset();
}
}
printk("g900-power-button: state=%d\n", state);
return IRQ_HANDLED;
}
static int buttons_probe(struct platform_device *pdev)
{
int err;
int irqflag = IRQF_SAMPLE_RANDOM;
#ifdef CONFIG_PREEMPT_RT
irqflag |= IRQF_NODELAY;
#endif
if (!machine_is_g900())
return -ENODEV;
//assign irq and keybit
set_irq_type(IRQ_GPIO(BTN_POWER), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING);
err = request_irq(IRQ_GPIO(BTN_POWER), pwr_btn_irq, irqflag, "g900-gpio-buttons", NULL);
if (err)
{
printk(KERN_ERR "g900-power-button: Cannot assign GPIO(%d) IRQ\n", BTN_POWER);
return err;
}
printk("g900-power-button: *****IRQ %d OK****", IRQ_GPIO(BTN_POWER));
return 0;
}
static int buttons_remove(struct platform_device *pdev)
{
free_irq(IRQ_GPIO(BTN_POWER), NULL);
return 0;
}
static int buttons_suspend(struct platform_device *pdev, pm_message_t state)
{
return 0;
}
static int buttons_resume(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver buttons_driver = {
.driver = {
.name = "g900-power-button",
},
.probe = buttons_probe,
.remove = buttons_remove,
#ifdef CONFIG_PM
.suspend = buttons_suspend,
.resume = buttons_resume,
#endif
};
static int __init buttons_init(void)
{
return platform_driver_register(&buttons_driver);
}
static void __exit buttons_exit(void)
{
platform_driver_unregister(&buttons_driver);
}
module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Angell FEar<angell@angellfear.ru>");
MODULE_DESCRIPTION("Power Button driver for Toshiba G900");

View File

@@ -0,0 +1,2 @@
obj-$(CONFIG_G900_PHONE) += msm6280.o msm6280_batt.o msm6280_atchanel.o

Binary file not shown.

View File

@@ -0,0 +1,860 @@
/*
*
* Copyright (C) 2011 Angell Fear <angell@angellfear.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* Example platform data:
static struct plat_msm6280 msm6280_plat_data = {
.poll_time = 100,
.irq = 0,
};
static struct platform_device msm_tty = {
.name = "msm6280",
.id = -1,
.dev = {
.platform_data = &msm6280_plat_data,
},
};
* The initial minor number is 209 in the low-density serial port:
* mknod /dev/ttyMSM0 c 204 209
*/
#define MSM6280_MAJOR 204
#define MSM6280_MINOR 209
#define MAX_MSM6280 3
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/freezer.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <mach/pxa2xx-regs.h>
#include <mach/g900-gpio.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/irq.h>
#include <linux/ctype.h>
#define IRQ_RX gpio_to_irq(0)
#include "msm6280.h"
#define UART_TO_MSM6280(uart_port) ((struct msm6280_port *) uart_port)
#define MSM6280_TO_UART(msm_port) ((struct uart_port *) msm_port)
struct plat_msm6280 {
int irq;
int poll_time;
};
struct msm6280_port {
struct uart_port uart;
void *virt;
u16 rx_start;
u16 rx_len;
u16 tx_start;
u16 tx_len;
};
static struct msm6280_port msm6280_uart_ports[] = {
{
.uart = {
.line = 0,
},
.rx_start = 0x0000,
.rx_len = 0x03FC,
.tx_start = 0x0400,
.tx_len = 0x03FC,
},
{
.uart = {
.line = 1,
},
.rx_start = 0x0800,
.rx_len = 0x07FC,
.tx_start = 0x1000,
.tx_len = 0x07FC,
},
{
.uart = {
.line = 2,
},
.rx_start = 0x1800,
.rx_len = 0x5E84,
.tx_start = 0x7688,
.tx_len = 0x0970,
},
};
#define UART6280_NR ARRAY_SIZE(msm6280_uart_ports)
struct msm6280_ports {
struct msm6280_port *ports[UART6280_NR]; /* the chanels */
unsigned long phys;
void *virt;
int inwork;
int irq;
/* for handling irqs: need workqueue since we do spi_sync */
struct workqueue_struct *workqueue;
struct work_struct work;
/* set to 1 to make the workhandler exit as soon as possible */
int force_end_work;
/* poll time (in ms) for ctrl lines */
int poll_time;
/* and its timer */
struct timer_list timer;
};
struct msm6280_ports *msm6280ports; /* the chip */
static DEFINE_MUTEX(msm6280s_lock); /* race on probe */
static const char *msm6280_type(struct uart_port *port) { return "MSM6280";}
static void msm6280_release_port(struct uart_port *port){}
static void msm6280_config_port(struct uart_port *port, int flags){}
static int msm6280_verify_port(struct uart_port *port, struct serial_struct *ser){ return -EINVAL;}
static void msm6280_stop_tx(struct uart_port *port){}
static int msm6280_request_port(struct uart_port *port){return 0;}
static void msm6280_break_ctl(struct uart_port *port, int break_state) {}
static void msm6280_enable_ms(struct uart_port *port) {}
static void msm6280_stop_rx(struct uart_port *port) {}
static unsigned int msm6280_tx_empty(struct uart_port *port) { return TIOCSER_TEMT; }
static unsigned int msm6280_get_mctrl(struct uart_port *port) { return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; }
static void msm6280_set_mctrl(struct uart_port *port, unsigned int mctrl) {}
static void msm6280_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old){}
static void msm6280_shutdown(struct uart_port *port){}
static int msm6280_startup(struct uart_port *port){return 0;}
static void msm6280_work(struct work_struct *w)
{
struct msm6280_ports *s = container_of(w, struct msm6280_ports, work);
int i,y,atcnt=0;
char chr;
u8 MQBOX0,MQBOX1,MQBOX2,MQBOX3;
u8 mask = 0;
struct uart_port *up;
u16 head, tail;
char atbuf[256];
//int rxchars;
//int conf, cconf, rts, crts;
//struct circ_buf *xmit = &s->port.state->xmit;
dvp("%s\n", __func__);
//mutex_lock(&msm6280s_lock);
if(s->inwork)
{
dvp("s->inwork != 0\n");
return;
}
s->inwork = 1;
MQBOX0 = *((u8*) s->virt + 0x7FFC);
MQBOX1 = *((u8*) s->virt + 0x7FFD);
MQBOX2 = *((u8*) s->virt + 0x7FFE);
MQBOX3 = *((u8*) s->virt + 0x7FFF);
#if 0
dvp("MQBOX %02x,%02x,%02x,%02x\n",MQBOX0,MQBOX1,MQBOX2,MQBOX3);
dvp("PORT | RX head | RX tail | TX head | TX tail\n");
for(i=0;i<UART6280_NR;i++) {
if(s->ports[i]){
dvp("%d | 0x%04x | 0x%04x | 0x%04x | 0x%04x \n",i,
*((u16*)s->virt + (s->ports[i]->rx_start / 2)),
*((u16*)s->virt + (s->ports[i]->rx_start / 2) + 1),
*((u16*)s->virt + (s->ports[i]->tx_start / 2)),
*((u16*)s->virt + (s->ports[i]->tx_start / 2) + 1));
}else{
//dvp("%d | disabled \n",i);
}
}
#endif
for(i=0;i<UART6280_NR;i++) {
if(likely(!s->ports[i])) break;
mask = (1<<i);
if(MQBOX3 & mask)
{
//dvp("Clear MQBOX3 chanel to port %d\n",i);
//*((u8*) s->virt + 0x7FFF) |= mask;
}
head = *((u16*)s->virt + (s->ports[i]->rx_start / 2));
tail = *((u16*)s->virt + (s->ports[i]->rx_start / 2) + 1);
if(unlikely((MQBOX2 & mask) || (tail != head)))
{
dvp("receive_chars to port %d\n",i);
up = MSM6280_TO_UART(s->ports[i]);
if(tail != head ) {
if(unlikely(i==0)){
atcnt=0;
atbuf[0] = 0;
}
dvp("R<-: ");
y = 0;
while((head != tail))
{
if(tail >= s->ports[i]->rx_len ){
tail = 0;
}
if(y >= s->ports[i]->rx_len ) break;
chr =*((u8*)s->virt +( tail + 4 + s->ports[i]->rx_start));
tail++;
y++;
up->icount.rx++;
if (!uart_handle_sysrq_char(up, c))
{
tty_insert_flip_char(up->state->port.tty, chr, TTY_NORMAL);
dcp(chr);
}
/* at resporens other devices */
if(unlikely(i==0 && y < 256)){
atbuf[atcnt] = chr;
atcnt++;
}
}
tty_flip_buffer_push(up->state->port.tty);
*((u16*)s->virt + (s->ports[i]->rx_start / 2) + 1) = tail;
dcc("\n");
if(unlikely(i==0)){
atbuf[atcnt] = 0;
msm6280_atresp(atbuf);
}
}
*((u8*) s->virt + 0x7FFE) |= mask;
}
}
*((u8*) s->virt + 0x7FFE) = 0; // clear MQBOX2
*((u8*) s->virt + 0x7FFF) = 0; // clear MQBOX3
s->inwork = 0;
//mutex_unlock(&msm6280s_lock);
}
static void msm6280_dowork(struct msm6280_ports *s)
{
if (!s->force_end_work && !work_pending(&s->work) &&
!freezing(current))
queue_work(s->workqueue, &s->work);
}
static void msm6280_timeout(unsigned long data)
{
struct msm6280_ports *s = (struct msm6280_ports *)data;
int i;
for(i=0;i<UART6280_NR;i++) {
if (s->ports[i]->uart.state) {
msm6280_dowork(s);
mod_timer(&s->timer, jiffies + s->poll_time);
return;
}
}
}
static irqreturn_t msm6280_irq(int irqno, void *dev_id)
{
struct msm6280_ports *s = dev_id;
dvp("%s\n", __func__);
msm6280_dowork(s);
return IRQ_HANDLED;
}
static unsigned char
transmit_char(struct uart_port *up, struct circ_buf *xmit)
{
unsigned char ret;
ret=xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->icount.tx++;
return ret;
}
static void msm6280_start_tx(struct uart_port *up)
{
struct circ_buf *xmit = &up->state->xmit;
u16 count;
u16 head,tail;
char ch;
struct msm6280_port *s = UART_TO_MSM6280(up);
dvp("%s\n", __func__);
mutex_lock(&msm6280s_lock);
if (up->x_char) {
dvp("send x_char 0x%02x(%c)\n",up->x_char,up->x_char);
up->icount.tx++;
up->x_char = 0;
mutex_unlock(&msm6280s_lock);
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
msm6280_stop_tx(up);
mutex_unlock(&msm6280s_lock);
return;
}
/*************************/
head = *((u16*)s->virt + (s->tx_start / 2));
tail = *((u16*)s->virt + (s->tx_start / 2) + 1);
count= (s->tx_len-1);
dvp("\nS-> :");
while(count--)
{
//if(tail==(head+1)) {
// printk("FULL BUF0x%04x, tail = 0x%04x: \n",head,tail);
// break; // <20><><EFBFBD><EFBFBD><EFBFBD>, DPram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
//}
if(head >= s->tx_len ){
head = 0x00;
}
ch=transmit_char(up, xmit);
*((u8*)s->virt + head + + 4 + s->tx_start) = ch;
dcp(ch);
head++;
if (uart_circ_empty(xmit)) // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> uarte <20><><EFBFBD><EFBFBD><EFBFBD>
break;
}
*((u16*)s->virt + (s->tx_start / 2)) = head;
*((u8*) s->virt + 0x7FFC) = *((u8*) s->virt + 0x7FFC) | (1 << up->line ); //interput
dvp("\n");
/*************************/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(up);
if (uart_circ_empty(xmit))
msm6280_stop_tx(up);
mutex_unlock(&msm6280s_lock);
}
static struct uart_ops msm6280_ops = {
.tx_empty = msm6280_tx_empty,
.set_mctrl = msm6280_set_mctrl,
.get_mctrl = msm6280_get_mctrl,
.stop_tx = msm6280_stop_tx,
.start_tx = msm6280_start_tx,
.stop_rx = msm6280_stop_rx,
.enable_ms = msm6280_enable_ms,
.break_ctl = msm6280_break_ctl,
.startup = msm6280_startup,
.shutdown = msm6280_shutdown,
.set_termios = msm6280_set_termios,
.type = msm6280_type,
.release_port = msm6280_release_port,
.request_port = msm6280_request_port,
.config_port = msm6280_config_port,
.verify_port = msm6280_verify_port,
};
static struct uart_driver msm6280_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "ttyMSM",
.dev_name = "ttyMSM",
.major = TTY_MAJOR,
.minor = 72,
.nr = MAX_MSM6280,
};
static inline struct uart_port *get_port_from_line(unsigned int line)
{
return &msm6280_uart_ports[line].uart;
}
static int __devinit msm6280_probe(struct platform_device *pdev )
{
struct msm6280_port *msm6280_port;
struct uart_port *port;
int retval=0;
dp("%s\n", __func__);
if (unlikely(pdev->id < 0 || pdev->id >= UART6280_NR))
return -ENXIO;
dp("detected port #%d\n", pdev->id);
//mutex_lock(&msm6280s_lock);
port = get_port_from_line(pdev->id);
port->ops = &msm6280_ops;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
port->fifosize = 64;
port->irq = msm6280ports->irq;
port->uartclk = 115000 * 16;
port->type = 69;
port->line = pdev->id;
port->dev = &pdev->dev;
msm6280_port = UART_TO_MSM6280(port);
msm6280_port->virt = msm6280ports->virt;
platform_set_drvdata(pdev, port);
msm6280ports->ports[pdev->id] = UART_TO_MSM6280(port);
retval = uart_add_one_port(&msm6280_uart_driver, port);
dp("%s: adding port %d\n", __func__, pdev->id);
if (unlikely(retval))
dp("uart_add_one_port failed for line %d with error %d\n", pdev->id, retval);
if (unlikely(pdev->id == 0)){
msm6280_batt_probe();
// *((u8*) msm6280ports->virt + 0x7FFE) = 1; // fake port 0 interput
}
msm6280_dowork(msm6280ports);
//mutex_unlock(&msm6280s_lock);
return retval;
}
static int __devexit msm6280_remove( struct platform_device *pdev)
{
dp("%s\n", __func__);
//struct msm6280_port *msm6280_port = platform_get_drvdata(pdev);
if (unlikely(pdev->id == 0)){
msm6280_batt_remove();
}
return 0;
}
static struct platform_driver msm6280_driver = {
.driver = {
.name = "msm6280",
.owner = THIS_MODULE,
},
.probe = msm6280_probe,
.remove = __devexit_p(msm6280_remove),
.suspend = NULL,
.resume = NULL,
};
static int __init
msm6280_init( void )
{
int ret;
dp("%s\n", __func__);
if (!machine_is_g900())
return -ENODEV;
msm6280ports = kzalloc(sizeof(struct msm6280_ports), GFP_KERNEL);
/** maping **/
msm6280ports->phys=PXA_CS5_PHYS;
msm6280ports->virt=ioremap(msm6280ports->phys, 0x8000);
if (! msm6280ports->virt) {
P_ERR("cannot allocate ioremap\n");
ret=-ENOMEM;
goto err1;
}
msm6280ports->poll_time = 100;
msm6280ports->irq = gpio_to_irq(0);
init_timer(&msm6280ports->timer);
msm6280ports->timer.function = msm6280_timeout;
msm6280ports->timer.data = (unsigned long) msm6280ports;
msm6280ports->inwork = 0;
/**/
msm6280ports->workqueue = create_freezeable_workqueue("msm6280-work");
if (!msm6280ports->workqueue) {
P_ERR("cannot create workqueue\n");
ret=-EBUSY;
goto err2;
}
INIT_WORK(&msm6280ports->work, msm6280_work);
ret = request_irq(msm6280ports->irq, msm6280_irq, 0, "MSM6280_IRQ", msm6280ports);
if (ret)
{
P_ERR("cannot allocate irq %d\n", msm6280ports->irq);
ret=-EBUSY;
goto err3;
}
set_irq_type(msm6280ports->irq, IRQ_TYPE_EDGE_FALLING);
ret = uart_register_driver(&msm6280_uart_driver);
if (unlikely(ret))
return ret;
/*
ret = platform_driver_probe(&msm6280_driver, msm6280_probe);
if (unlikely(ret))
uart_unregister_driver(&msm6280_uart_driver);
*/
dp("driver initialized\n");
return platform_driver_register( &msm6280_driver );
err3:
msm6280ports->irq = 0;
destroy_workqueue(msm6280ports->workqueue);
msm6280ports->workqueue = NULL;
err2:
iounmap(msm6280ports->virt);
err1:
return ret;
}
static void __exit
msm6280_exit( void )
{
dp("%s\n", __func__);
platform_driver_unregister( &msm6280_driver );
msm6280ports->irq = 0;
destroy_workqueue(msm6280ports->workqueue);
msm6280ports->workqueue = NULL;
free_irq(msm6280ports->irq, &msm6280ports);
iounmap(msm6280ports->virt);
}
module_init( msm6280_init );
module_exit( msm6280_exit );
MODULE_AUTHOR("Angell Fear");
MODULE_DESCRIPTION("Toshiba G900 Core Hardware Driver");
MODULE_LICENSE("GPL");
//MODULE_ALIAS("dpram:msm6280");
#if 0
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/pxa2xx-regs.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/pda_power.h>
//#define MSM6280_DEBUG
#include "msm6280.h"
static struct msm6280struct *msm6280_data; /* the chip */
static DEFINE_MUTEX(msm6280_lock); /* race on probe */
#include "msm6280_tty_data.c"
#include "msm6280_tty_com.c"
static void msm6280_work(struct work_struct *w)
{
struct msm6280struct *s = container_of(w, struct msm6280struct, work);
//struct circ_buf *xmit = &s->port.state->xmit;
/// <20><><EFBFBD> <20><><EFBFBD><EFBFBD> tty
ddvprintk("\nmsm6280_work!!!!!!!!!!!\n");
if( MQBOX3(s) == 0b001 || // port 0
MQBOX3(s) == 0b010 || // port 1
MQBOX3(s) == 0b100 ) // port 2
{
ddvprintk("Clear intr chanel 0x%04x \n",MQBOX3(s));
}else if(MQBOX3(s) != 0){
ddvprintk("ERROR 3 !!! Unknow chanel 0x%04x\n",MQBOX3(s));
}
if(MQBOX2(s) == 0b001) // port 0
{
receive_chars(s.port_at);
}else
if(MQBOX2(s) == 0b010){ // port 1
//receive_chars_hz(s.port_data);
}else
if(MQBOX2(s) == 0b100){ // port 2
receive_chars_data(s.port_data);
}else
if(MQBOX2(s) != 0){
ddvprintk("ERROR 2 !!! Unknow chanel 0x%04x\n",MQBOX2(s));
}
MQBOX(s) = 0;
}
static void msm6280_dowork(struct msm6280struct *s) //
{
if (!s->force_end_work && !work_pending(&s->work) &&
!freezing(current))
queue_work(s->workqueue, &s->work);
}
static irqreturn_t msm6280_irq(int irq, void *dev_id) //
{
struct msm6280struct *s = dev_id;
ddbprintk("\nmsm6280_irq!!!!!!!!!!!\n");
//ddvprintk("MQBOX %02x,%02x,%02x,%02x\n",MQBOX0,MQBOX1,MQBOX2,MQBOX3);
ddvprintk("PORT | RX head | RX tail | TX head | TX tail\n");
ddvprintk("AT | 0x%04x | 0x%04x | 0x%04x | 0x%04x \n",*((u16*)s->virt + RX_AT_START),*((u16*)s->virt + RX_AT_START + 1),*((u16*)s->virt + TX_AT_START),*((u16*)s->virt + TX_AT_START + 1));
ddvprintk("DATA | 0x%04x | 0x%04x | 0x%04x | 0x%04x \n",*((u16*)s->virt + RX_DT_START),*((u16*)s->virt + RX_DT_START + 1),*((u16*)s->virt + TX_DT_START),*((u16*)s->virt + TX_DT_START + 1));
ddvprintk("HZ | 0x%04x | 0x%04x | 0x%04x | 0x%04x \n",*((u16*)s->virt + RX_HZ_START),*((u16*)s->virt + RX_HZ_START + 1),*((u16*)s->virt + TX_HZ_START),*((u16*)s->virt + TX_HZ_START + 1));
msm6280_dowork(s);
return IRQ_HANDLED;
}
int __init msm6280_init(void)
{
int ret;
/*
clear TRACES
clear IRQS
addlist TRACES p2v(0x14000000)
addlist TRACES p2v(0x14000400)
addlist TRACES p2v(0x14000800)
addlist TRACES p2v(0x14001000)
addlist TRACES p2v(0x14001800)
addlist TRACES p2v(0x14007688)
addlist TRACES p2v(0x14007FFC)
wirq 10
*/
if (!machine_is_g900())
return -ENODEV;
msm6280_data[i] = kzalloc(sizeof(struct msm6280struct), GFP_KERNEL);
/** maping **/
msm6280_data.data_phys=PXA_CS5_PHYS;
msm6280_data.data_virt=ioremap(msm6280_data.data_phys, 0x8000);
if (! msm6280_data.data_virt) {
ret=-ENOMEM;
goto err1;
}
msm6280_data.en_at=false;
msm6280_data.en_data=false;
msm6280_data.workqueue = create_workqueue("msm6280");
if (!msm6280_data.workqueue) {
printk(KERN_ERR "MSM6280: %s: cannot create workqueue\n", __FUNCTION__);
ret=-EBUSY;
goto err2;
}
INIT_WORK(&msm6280_data.work, msm6280_work);
ret = request_irq(IRQ_RX, msm6280_irq, 0, "MSM6280_IRQ", &msm6280_data);
if (ret)
{
printk(KERN_ERR "%s: Cannot assign GPIO_0 for MSM6280 IRQ\n", __FUNCTION__);
goto err3;
}
set_irq_type(IRQ_RX, IRQ_TYPE_EDGE_FALLING);
ret = msm6280_tty_com_probe();
if(ret != 0)
goto err3;
ret = msm6280_tty_data_probe();
msm6280_batt_probe();
return 0;
err3:
destroy_workqueue(msm6280_data.workqueue);
msm6280_data.workqueue = NULL;
err2:
iounmap(msm6280_data.data_virt);
err1:
return ret;
}
static void msm6280_shutdown(struct uart_port *port)
{
struct msm6280struct *s = container_of(port,
struct msm6280struct,
port);
if (s->irq)
free_irq(s->irq, s);
}
void __exit msm6280_exit(void)
{
msm6280_data->force_end_work = 1;
if (msm6280_data->poll_time > 0)
del_timer_sync(&msm6280_data->timer);
if (msm6280_data->workqueue) {
flush_workqueue(msm6280_data->workqueue);
destroy_workqueue(msm6280_data->workqueue);
msm6280_data->workqueue = NULL;
}
msm6280_batt_remove();
msm6280_tty_data_probe();
msm6280_tty_com_remove();
free_irq(IRQ_RX, &msm6280_data);
iounmap(msm6280_data.data_virt);
}
module_init(msm6280_init);
module_exit(msm6280_exit);
MODULE_AUTHOR("Angell Fear <angell@angellfear.ru>");
MODULE_DESCRIPTION("Dual Port RAM communication for Toshiba G900, PXA270<->MSM6280");
MODULE_LICENSE("GPL");
#endif

View File

@@ -0,0 +1,90 @@
#ifndef __MSM6280_H__
#define __MSM6280_H__
#define LOGTAG "MSM6280: "
#define MSM6280_DEBUG
#define P_ERR(x...) printk(KERN_ERR LOGTAG x)
#ifdef MSM6280_DEBUG
#define dp(x...) printk(LOGTAG x)
#define dvp(x...) printk(LOGTAG x)
#define dip(x...) printk(LOGTAG x)
#define dcp(s) if( isascii(s) && isprint(s) ){ printk("%c",s); }else{ printk("<0x%02x>",s); }
#define dvcp(s...) dcp(s)
#define dcc(s...) printk(s)
#else
#define dp(x...) printk(LOGTAG x)
#define dvp(x...)
#define dip(x...)
#define dcp(s) if( isascii(s) && isprint(s) ){ printk("%c",s); }else{ printk("<0x%02x>",s); }
#define dvcp(s)
#endif
/* MMAP DPR on MSM6280 for G900 */
/*
start size desc
--------------------------------------------
0x0 0x4 RX POINTER AT chanel
0x4 0x3FC RX BUFFER
0x400 0x4 TX POINTER
0x404 0x3FC TX BUFFER
--------------------------------------------
0x800 0x4 RX POINTER not use???
0x804 0x7FC RX BUFFER
0x1000 0x4 TX POINTER
0x1004 0x7FC TX BUFFER
--------------------------------------------
0x1800 0x4 RX POINTER DATA chanel
0x1804 0x5E84 RX BUFFER
0x7688 0x4 TX POINTER
0x768C 0x970 TX BUFFER
--------------------------------------------
0x7FFC 0x4 QcMailBox
--<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
0 <20><>
1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2 <20><><EFBFBD><EFBFBD>
--<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
0 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
3 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
--<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
QMAILBOX = 1<<(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*8+<2B><><EFBFBD><EFBFBD><EFBFBD>)
*/
//#define MBOX(index) mbtmp = MBOX2; mbtmp = MBOX3; mbtmp = MBOX4;mbtmp = MBOX1; mbtmp |=(1 << index ); MBOX1 = mbtmp;
//#define MBOXR mbtmp = MBOX2; mbtmp = MBOX3; mbtmp = MBOX4;mbtmp = MBOX1;
int msm6280_atresp(char *);
void msm6280_batt_probe(void );
void msm6280_batt_remove(void );
void msm6280_battery(char *,int );
#endif

Binary file not shown.

View File

@@ -0,0 +1,146 @@
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/pxa2xx-regs.h>
#include <asm/gpio.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <mach/g900-gpio.h>
#include <linux/pda_power.h>
#include "msm6280.h"
/** SPLITER **/
int msm6280_atresp(char *atbuf)
{
char *p;
int end=0,j=0,i=0,len,x,y,z;
char buf[256],values[256];
char tmp[5][16];
//printk("MSM6280: atresp = %s\n",atbuf);
for (p = atbuf,j=0; *p != '\0' ;p++,j++) {
if (*p == ':'){
while(*(atbuf + end) == 0x0d || *(atbuf + end) == 0x0a) end++;
len=j-end;
strncpy(buf, atbuf+end, len);
buf[len] = 0;
p++;
for(i=0;((*p != 0) && (*p != 0x0d)) ;p++,i++)
{
values[i]=*p;
}
end = j;
values[i]=0;
//printk("MSM6280: AT ANSWER end=%d,len=%d, %s - %s\n",end,len,buf,values);
#ifdef CONFIG_POWER_SUPPLY
/**
BATTERY
plug charger
$CBN: 1,49,1
unplug charger
$CBN: 1,49,4
$CBN - 1,61,14 ??
$CBN: 1,49,8
$CBN: 1,77,0
call AT+CBN
+CBN: 1,49
call AT+CBC
+CBC: 0,49 ?? power capacity??
*/
if(
(buf[0] == '$' || buf[0] == '+')&&
buf[1] == 'C' &&
buf[2] == 'B' &&
(buf[3] == 'N' /*|| buf[3] == 'C'*/)
)
{
dvp("AT BATERY ANSWER %s - %s\n",buf,values);
for (x=0,y=0,z=0; values[z] != '\0' ;z++,y++) {
if(values[z] == ','){
tmp[x][y] = 0;
x++;
z++;
y=0;
}
tmp[x][y] = values[z];
}
tmp[x][y] = 0;
for (x=0; x<4 ;x++) {
dvp("tmp[%i] = \"%s\"\n",x,tmp[x]);
}
z = -1;
if(tmp[2][0] == '1' && (tmp[2][1] == 0 || (tmp[2][1] == '4' && tmp[2][2] == 0) )){
z = 1;
}
if(tmp[2][0] == '4' && tmp[2][1] == 0){
z = 0;
}
dvp("AT !! call battery( %s , %d)\n",tmp[1],z);
msm6280_battery(tmp[1],z);
}
#endif
}
}
/**
======================
LED
AT+LED=3,10,0
======================
*/
return 0;
}

View File

@@ -0,0 +1,274 @@
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/serial_reg.h>
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/pxa2xx-regs.h>
#include <asm/gpio.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <mach/g900-gpio.h>
#include <linux/pda_power.h>
#include "msm6280.h"
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
int p_BATT_CAPACITY=50;
int p_AC_POWER=0;
#ifdef CONFIG_POWER_SUPPLY
#include <linux/power_supply.h>
static int g900_power_get_property(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *val)
{
int ret = 0;
switch (prop) {
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = p_BATT_CAPACITY;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY: /* All our batteries are Li-ions (right?)*/
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
case POWER_SUPPLY_PROP_STATUS:
if (p_AC_POWER > 0 && p_BATT_CAPACITY <= 99)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (p_AC_POWER == 1 && p_BATT_CAPACITY > 99)
val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case POWER_SUPPLY_PROP_ONLINE: /* either USB or AC */
if (psy->type == POWER_SUPPLY_TYPE_MAINS){ /* AC on/offline*/
if(p_AC_POWER==1){
val->intval = 1;
}else{
val->intval = 0;
}
}else if(psy->type == POWER_SUPPLY_TYPE_USB) { /* USB on/offline */
/*
40 USB detect IRQ
41 USB_P2_7(Client = 1, host =0(up 75,93) )
*/
val->intval =0 ;// (GPIO41_USB_MODE ? 1 : 0); /* TODO!!! */
}else
dvp("POWER_SUPPLY_PROP_ONLINE type = %d = %d \n",psy->type,val->intval);
break;
#define VOLTAGE_MIN 3635000 /* todo */
#define VOLTAGE_MAX 4158000 /* todo */
#define VOLTAGE_STEP ((VOLTAGE_MAX - VOLTAGE_MIN)/100)
/* case POWER_SUPPLY_PROP_BATT_VOL:
val->intval = (p_BATT_CAPACITY * VOLTAGE_STEP ) + VOLTAGE_MIN; //fake !!! percent math
break;
case POWER_SUPPLY_PROP_BATT_TEMP:
val->intval = 27; /// fake !!!
break;
*/
case POWER_SUPPLY_PROP_PRESENT:
val->intval = 0;
break;
case POWER_SUPPLY_PROP_HEALTH:
val->intval = 1;
break;
#if 0
case POWER_SUPPLY_PROP_VOLTAGE_MIN: /* lowest measured value in uV */
val->intval = VOLTAGE_MIN;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX: /* highest measured value in uV */
val->intval = VOLTAGE_MAX;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
val->intval = (p_BATT_CAPACITY * VOLTAGE_STEP ) + VOLTAGE_MIN; /*mV*/ //fake !!! percent math
break;
#endif
default:
ret = -EINVAL;
}
return ret;
}
/* property for AC and USB */
static enum power_supply_property g900_power_line_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
/* main battery properties */
static enum power_supply_property g900_power_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_HEALTH,
/* POWER_SUPPLY_PROP_BATT_VOL,
POWER_SUPPLY_PROP_BATT_TEMP,
*/
#if 0
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
#endif
};
static char *g900_power_supplied_to[] = {
"main-battery",
/* backup-battery could be added if we knew how to access info about it */
};
static struct power_supply g900_psy_ac = {
.name = "ac",
.type = POWER_SUPPLY_TYPE_MAINS,
.supplied_to = g900_power_supplied_to,
.num_supplicants = ARRAY_SIZE(g900_power_supplied_to),
.properties = g900_power_line_props,
.num_properties = ARRAY_SIZE(g900_power_line_props),
.get_property = g900_power_get_property,
};
static struct power_supply g900_psy_usb = {
.name = "usb",
.type = POWER_SUPPLY_TYPE_USB,
.supplied_to = g900_power_supplied_to,
.num_supplicants = ARRAY_SIZE(g900_power_supplied_to),
.properties = g900_power_line_props,
.num_properties = ARRAY_SIZE(g900_power_line_props),
.get_property = g900_power_get_property,
};
static struct power_supply g900_psy_battery = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = g900_power_battery_props,
.num_properties = ARRAY_SIZE(g900_power_battery_props),
.get_property = g900_power_get_property,
.use_for_apm = 1,
};
#endif
static struct platform_device *pdev;
void msm6280_batt_probe(void){
#ifdef CONFIG_POWER_SUPPLY
int ret;
dvp("batt_probe \n");
pdev = platform_device_register_simple("MSM6280_batt",
0, NULL, 0);
if (IS_ERR(pdev)) {
ret = PTR_ERR(pdev);
dvp("failed to register pdev ret=%d\n",ret);
return;
}
if (power_supply_register(&pdev->dev, &g900_psy_ac) != 0)
dev_err(&pdev->dev, "failed to register %s power supply\n",g900_psy_ac.name);
if (power_supply_register(&pdev->dev, &g900_psy_usb) != 0)
dev_err(&pdev->dev, "failed to register %s power supply\n",g900_psy_usb.name);
if (power_supply_register(&pdev->dev, &g900_psy_battery) != 0)
dev_err(&pdev->dev, "failed to register %s power supply\n",g900_psy_battery.name);
#endif
}
void msm6280_batt_remove(void){
#ifdef CONFIG_POWER_SUPPLY
power_supply_unregister(&g900_psy_ac);
power_supply_unregister(&g900_psy_usb);
power_supply_unregister(&g900_psy_battery);
#endif
}
#ifdef CONFIG_POWER_SUPPLY
void msm6280_battery(char *percent,int acpower)
{
int capacity = 0;
dvp("BATERY %s%% - POWER %d\n",percent,acpower);
capacity = percent[0]-'0';
if((percent[1]-'0') >=0 && (percent[1]-'0') <=9)
{
capacity=(capacity*10)+(percent[1]-'0');
if((percent[2]-'0') >=0 && (percent[2]-'0') <=9)
{
capacity=(capacity*10)+(percent[2]-'0');
}
}
if(p_BATT_CAPACITY != capacity)
{
p_BATT_CAPACITY = capacity;
}
if((acpower >= 0) && (p_AC_POWER != acpower))
{
p_AC_POWER = acpower;
power_supply_changed(&g900_psy_ac);
}
power_supply_changed(&g900_psy_battery);
dvp("BATERY %d%% - POWER %d\n",p_BATT_CAPACITY,p_AC_POWER);
}
#endif

Binary file not shown.

View File

@@ -0,0 +1,249 @@
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
static void dpram_enable_ms(struct uart_port *port) {}
static void dpram_stop_tx(struct uart_port *port) {}
static void dpram_stop_rx(struct uart_port *port) {}
static unsigned int dpram_tx_empty(struct uart_port *port) { return TIOCSER_TEMT; }
static unsigned int dpram_get_mctrl(struct uart_port *port) { return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; }
static void dpram_set_mctrl(struct uart_port *port, unsigned int mctrl) {}
static void dpram_break_ctl(struct uart_port *port, int break_state) {}
static void dpram_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old){}
static void dpram_pm(struct uart_port *port, unsigned int state, unsigned int oldstate){}
static void dpram_release_port(struct uart_port *port){}
static int dpram_request_port(struct uart_port *port){ return 0; }
static void dpram_config_port(struct uart_port *port, int flags) { port->type = PORT_DPRAM;}
static int dpram_verify_port(struct uart_port *port, struct serial_struct *ser) { return -EINVAL;}
static const char * dpram_type(struct uart_port *port) { return "DPRAM"; }
/**/
static void
receive_chars(struct uart_port *up)
{
unsigned int ch,atcnt,i=0;
u16 head,tail;
char atbuf[256];
struct tty_struct *tty;
if( msm6280_data.en_at ) dvprintk("en_at = true\n"); else dvprintk("en_at = false\n");
if( msm6280_data.en_at ) tty = up->state->port.tty;
ddbprintk("receive_chars_com\n");
head = *((u16*)msm6280_data.data_virt + RX_AT_START);
tail = *((u16*)msm6280_data.data_virt + RX_AT_START + 1);
if(tail == head ) return ; // mb fast IRQ
dprintk("R<-: ");
atcnt=0;
atbuf[0] = 0;
while((head != tail))
{
if(tail >= RX_AT_BUF){
tail = 0x00;
}
if(i >= RX_AT_BUF) break;
ch =*((u8*)msm6280_data.data_virt+tail+(RX_AT_BUF_START));
tail++;
i++;
if (msm6280_data.en_at)
{
up->icount.rx++;
if (!uart_handle_sysrq_char(up, c))
{
tty_insert_flip_char(tty, ch, TTY_NORMAL);
dcharprint(ch);
}
}
/* at resporens other devices */
atbuf[atcnt] = ch;
atcnt++;
}
atbuf[atcnt] = 0;
msm6280_atresp(atbuf);
if (msm6280_data.en_at) tty_flip_buffer_push(tty);
*((u16*)msm6280_data.data_virt+(RX_AT_START+0x01))=tail;
drprintk("\n");
return;
}
static unsigned char
transmit_char(struct uart_port *up, struct circ_buf *xmit)
{
unsigned char ret;
ret=xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->icount.tx++;
return ret;
}
static void transmit_chars(struct uart_port *up)
{
struct circ_buf *xmit = &up->state->xmit;
u16 count;
u16 head,tail;
char s;
if (up->x_char) {
dprintk("send x_char 0x%02x(%c)\n",up->x_char,up->x_char);
up->icount.tx++;
up->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
dpram_stop_tx(up);
return;
}
ddbprintk("transmit_chars_com\n");
/*************************/
head = *((u16*)msm6280_data.data_virt + TX_AT_START);
tail = *((u16*)msm6280_data.data_virt + TX_AT_START + 1);
count=TX_AT_BUF-1;
dprintk("\nS-> :");
while(count--)
{
//if(tail==(head+1)) {
// printk("FULL BUF0x%04x, tail = 0x%04x: \n",head,tail);
// break; // <20><><EFBFBD><EFBFBD><EFBFBD>, DPram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
//}
if(head >= TX_AT_BUF){
head = 0x00;
}
s=transmit_char(up, xmit);
*((u8*)msm6280_data.data_virt+head+TX_AT_BUF_START)=s;
dcharprint(s);
head++;
if (uart_circ_empty(xmit)) // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> uarte <20><><EFBFBD><EFBFBD><EFBFBD>
break;
}
*((u16*)msm6280_data.data_virt + TX_AT_START) = head;
MQBOX0 |= 0b001; // chanel 0
drprintk("\n");
/*************************/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(up);
if (uart_circ_empty(xmit))
dpram_stop_tx(up);
}
static void dpram_start_tx(struct uart_port *port)
{
transmit_chars(port);
}
static int dpram_startup(struct uart_port *port)
{
if(!msm6280_data.en_at) msm6280_data.port_at = port;
msm6280_data.en_at = true;
receive_chars(msm6280_data.port_at);
return 0;
}
static void dpram_shutdown(struct uart_port *port)
{
msm6280_data.en_at = false;
}
struct uart_ops dpram_pops = {
.tx_empty = dpram_tx_empty,
.set_mctrl = dpram_set_mctrl,
.get_mctrl = dpram_get_mctrl,
.stop_tx = dpram_stop_tx,
.start_tx = dpram_start_tx,
.stop_rx = dpram_stop_rx,
.enable_ms = dpram_enable_ms,
.break_ctl = dpram_break_ctl,
.startup = dpram_startup,
.shutdown = dpram_shutdown,
.set_termios = dpram_set_termios,
.pm = dpram_pm,
.type = dpram_type,
.release_port = dpram_release_port,
.request_port = dpram_request_port,
.config_port = dpram_config_port,
.verify_port = dpram_verify_port,
};
static struct uart_port dpram_port = {
.type = PORT_DPRAM,
.iotype = UPIO_MEM,
.irq = IRQ_RX,
.uartclk = 115000 * 16,
.fifosize = 64,
.ops = &dpram_pops,
.line = 0,
};
static struct uart_driver dpram_reg = {
.owner = THIS_MODULE,
.driver_name = "msm6280_at_uart",
.dev_name = "ttyMSM",
//.dev_name = "ttyS",
//.dev_name = "smd",
.major = TTY_MAJOR,
.minor = 72,
.nr = 1,
};
int msm6280_tty_com_probe()
{
int ret;
ret = uart_register_driver(&dpram_reg);
if (ret != 0)
goto err1;
dpram_port.mapbase=msm6280_data.data_phys;
ret = uart_add_one_port(&dpram_reg, &dpram_port);
if (ret != 0)
goto err2;
return 0;
err2:
uart_remove_one_port(&dpram_reg, &dpram_port);
err1:
uart_unregister_driver(&dpram_reg);
return ret;
}
void msm6280_tty_com_remove(void)
{
uart_remove_one_port(&dpram_reg, &dpram_port);
uart_unregister_driver(&dpram_reg);
}

View File

@@ -0,0 +1,239 @@
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
static void dpram_data_enable_ms(struct uart_port *port) {}
static void dpram_data_stop_tx(struct uart_port *port) {}
static void dpram_data_stop_rx(struct uart_port *port) {}
static unsigned int dpram_data_tx_empty(struct uart_port *port) { return TIOCSER_TEMT; }
static unsigned int dpram_data_get_mctrl(struct uart_port *port) { return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; }
static void dpram_data_set_mctrl(struct uart_port *port, unsigned int mctrl) {}
static void dpram_data_break_ctl(struct uart_port *port, int break_state) {}
static void dpram_data_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old){}
static void dpram_data_pm(struct uart_port *port, unsigned int state, unsigned int oldstate){}
static void dpram_data_release_port(struct uart_port *port){}
static int dpram_data_request_port(struct uart_port *port){ return 0; }
static void dpram_data_config_port(struct uart_port *port, int flags) { port->type = PORT_DPRAM;}
static int dpram_data_verify_port(struct uart_port *port, struct serial_struct *ser) { return -EINVAL;}
static const char * dpram_data_type(struct uart_port *port) { return "DPRAM"; }
/**/
static void
receive_chars_data(struct uart_port *up)
{
unsigned int ch,i=0;
u16 head,tail;
struct tty_struct *tty;
//if( msm6280_data.en_data ) ddvprintk("en_data = true\n"); else ddvprintk("en_data = false\n");
if( msm6280_data.en_data ) tty = up->state->port.tty;
ddbprintk("receive_chars_data\n");
head = *((u16*)msm6280_data.data_virt + RX_DT_START);
tail = *((u16*)msm6280_data.data_virt + RX_DT_START + 1);
ddvprintk("transmit_chars_data head = 0x%04x, tail = 0x%04x: \n",head,tail);
if(tail == head ) return ; // mb fast IRQ
ddprintk("DR<-: ");
while((head != tail))
{
if(tail >= RX_DT_BUF){
tail = 0x00;
}
if(i >= RX_DT_BUF) break;
ch =*((u8*)msm6280_data.data_virt+tail+(RX_DT_BUF_START));
tail++;
i++;
if (msm6280_data.en_data)
{
up->icount.rx++;
if (!uart_handle_sysrq_char(up, c))
{
tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
}
dcharprint(ch);
}
if (msm6280_data.en_data) tty_flip_buffer_push(tty);
*((u16*)msm6280_data.data_virt+RX_DT_START + 1 ) = tail;
drprintk("\n");
return;
}
static unsigned char
transmit_char_data(struct uart_port *up, struct circ_buf *xmit)
{
unsigned char ret;
ret=xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->icount.tx++;
return ret;
}
static void transmit_chars_data(struct uart_port *up)
{
struct circ_buf *xmit = &up->state->xmit;
u16 count;
u16 head,tail;
char s;
if (up->x_char) {
ddprintk("send x_char 0x%02x(%c)\n",up->x_char,up->x_char);
up->icount.tx++;
up->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
dpram_data_stop_tx(up);
return;
}
ddbprintk("ransmit_chars_data\n");
/*************************/
head = *((u16*)msm6280_data.data_virt + TX_DT_START);
tail = *((u16*)msm6280_data.data_virt + TX_DT_START + 1);
count=TX_DT_BUF-1;
ddprintk("\nDS-> :");
while(count--)
{
//if(tail==(head+1)) {
// printk("FULL BUF0x%04x, tail = 0x%04x: \n",head,tail);
// break; // <20><><EFBFBD><EFBFBD><EFBFBD>, DPram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
//}
if(head >= TX_DT_BUF){
head = 0x00;
}
s=transmit_char_data(up, xmit);
*((u8*)msm6280_data.data_virt+head+(TX_DT_BUF_START)) = s;
ddcharprint(s);
head++;
if (uart_circ_empty(xmit)) // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> uarte <20><><EFBFBD><EFBFBD><EFBFBD>
break;
}
*((u16*)msm6280_data.data_virt + TX_DT_START) = head;
MQBOX0 |= 0b100; // chanel 2
drprintk("\n");
/*************************/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(up);
if (uart_circ_empty(xmit))
dpram_data_stop_tx(up);
}
static void dpram_data_start_tx(struct uart_port *port)
{
transmit_chars_data(port);
}
static int dpram_data_startup(struct uart_port *port)
{
if(!msm6280_data.en_data) msm6280_data.port_data = port;
msm6280_data.en_data = true;
receive_chars_data(msm6280_data.port_data);
return 0;
}
static void dpram_data_shutdown(struct uart_port *port)
{
msm6280_data.en_data = false;
}
struct uart_ops dpram_data_pops = {
.tx_empty = dpram_data_tx_empty,
.set_mctrl = dpram_data_set_mctrl,
.get_mctrl = dpram_data_get_mctrl,
.stop_tx = dpram_data_stop_tx,
.start_tx = dpram_data_start_tx,
.stop_rx = dpram_data_stop_rx,
.enable_ms = dpram_data_enable_ms,
.break_ctl = dpram_data_break_ctl,
.startup = dpram_data_startup,
.shutdown = dpram_data_shutdown,
.set_termios = dpram_data_set_termios,
.pm = dpram_data_pm,
.type = dpram_data_type,
.release_port = dpram_data_release_port,
.request_port = dpram_data_request_port,
.config_port = dpram_data_config_port,
.verify_port = dpram_data_verify_port,
};
static struct uart_port dpram_data_port = {
.type = PORT_DPRAM,
.iotype = UPIO_MEM,
.irq = -1/*IRQ_RX*/,
.uartclk = 115000 * 16,
.fifosize = 64,
.ops = &dpram_data_pops,
.line = 1,
};
static struct uart_driver dpram_data_reg_data = {
.owner = THIS_MODULE,
.driver_name = "msm6280_data_uart",
.dev_name = "ttyMSM",
//.dev_name = "smd",
.major = TTY_MAJOR,
.minor = 73,
.nr = 3,
};
int msm6280_tty_data_probe()
{
int ret;
ret = uart_register_driver(&dpram_data_reg_data);
if (ret != 0)
goto err1;
dpram_data_port.mapbase=msm6280_data.data_phys+RX_DT_START;
ret = uart_add_one_port(&dpram_data_reg_data, &dpram_data_port);
if (ret != 0)
goto err2;
return 0;
err2:
uart_remove_one_port(&dpram_data_reg_data, &dpram_data_port);
err1:
uart_unregister_driver(&dpram_data_reg_data);
return ret;
}
void msm6280_tty_data_remove(void)
{
uart_remove_one_port(&dpram_data_reg_data, &dpram_data_port);
uart_unregister_driver(&dpram_data_reg_data);
}

View File

@@ -0,0 +1,338 @@
/*
*
* Based on arch/arm/mach-pxa/htcblueangel/blueangel_dpram.c
* Autor: Angell Fear <angell@angellfear.ru>
* MSM6280 to PXA270 communication on Dual Port RAM for Toshiba G900
*
*/
/**/
static void dpram_hz_enable_ms(struct uart_port *port)
{
ddprintk("dpram_hz_enable_ms\n");
}
static void dpram_hz_stop_tx(struct uart_port *port)
{
//ddprintk("dpram_hz_stop_tx\n");
}
static void dpram_hz_stop_rx(struct uart_port *port)
{
ddprintk("dpram_hz_stop_rx\n");
}
static void
receive_chars_hz(struct uart_port *up)
{
unsigned int ch,i=0;
u16 head,tail;
struct tty_struct *tty;
if( msm6280_data.en_hz ) ddvprintk("en_hz = true\n"); else ddvprintk("en_hz = false\n");
if( msm6280_data.en_hz ) tty = up->state->port.tty;
head = *((u16*)msm6280_data.data_virt + RX_HZ_START);
tail = *((u16*)msm6280_data.data_virt + RX_HZ_START + 1);
ddvprintk("receive_chars_hz head = 0x%04x, tail = 0x%04x: \n",head,tail);
if(tail == head ) return ; // mb fast IRQ
ddprintk("HR<-: ");
while((head != tail))
{
if(tail >= RX_HZ_BUF){
tail = 0x00;
}
if(i >= RX_HZ_BUF) break;
ch =*((u8*)msm6280_data.data_virt+tail+(RX_HZ_BUF_START));
tail++;
i++;
if (msm6280_data.en_hz)
{
up->icount.rx++;
if (!uart_handle_sysrq_char(up, c))
{
tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
}
dcharprint(ch);
}
if (msm6280_data.en_hz) tty_flip_buffer_push(tty);
*((u16*)msm6280_data.data_virt+RX_HZ_START + 1 ) = tail;
/*
MBOX1 = 0x0;
MBOX2 = 0x0;
MBOX3 = 0x0;
MBOX4 = 0x0;
*/
ddprintk("\n");
return;
}
static unsigned char
transmit_char_hz(struct uart_port *up, struct circ_buf *xmit)
{
unsigned char ret;
ret=xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->icount.tx++;
return ret;
}
static void transmit_chars_hz(struct uart_port *up)
{
struct circ_buf *xmit = &up->state->xmit;
u16 count;
u16 head,tail;
char s;
if (up->x_char) {
//ddprintk("send x_char 0x%02x(%c)\n",up->x_char,up->x_char);
up->icount.tx++;
up->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(up)) {
dpram_hz_stop_tx(up);
return;
}
/*************************/
/*
<EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>
{
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>. <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> msm <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
}
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> len+tail
*/
head = *((u16*)msm6280_data.data_virt + TX_HZ_START);
tail = *((u16*)msm6280_data.data_virt + TX_HZ_START + 1);
count=TX_HZ_BUF-1;
//ddvprintk("transmit_chars head = 0x%04x, tail = 0x%04x: \n",head,tail);
ddmprintk("transmit_chars_hz MBOX=%02x,%02x,%02x,%02x\n",MBOX1,MBOX2,MBOX3,MBOX4);
ddprintk("\nHS-> :");
while(count--)
{
//if(tail==(head+1)) {
// printk("FULL BUF0x%04x, tail = 0x%04x: \n",head,tail);
// break; // <20><><EFBFBD><EFBFBD><EFBFBD>, DPram <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
//}
if(head >= TX_HZ_BUF){
head = 0x00;
}
s=transmit_char_hz(up, xmit);
*((u8*)msm6280_data.data_virt+head+(TX_HZ_BUF_START)) = s;
dcharprint(s);
head++;
if (uart_circ_empty(xmit)) // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> uarte <20><><EFBFBD><EFBFBD><EFBFBD>
break;
}
*((u16*)msm6280_data.data_virt + TX_HZ_START) = head;
ddprintk("dpram_hz_end_Tx head = 0x%04x, tail = 0x%04x: \n",head,tail);
MBOX1 = (0x1<<2); /*MAILBOX set ch1 INTERPUT*/
MBOX2 = 0x0;
//MBOX3 = 0x0;
//MBOX4 = 0x0;
ddprintk("\n");
/*************************/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(up);
if (uart_circ_empty(xmit))
dpram_hz_stop_tx(up);
}
static void dpram_hz_start_tx(struct uart_port *port)
{
//ddprintk("dpram_hz_start_tx\n");
transmit_chars_hz(port);
}
static unsigned int dpram_hz_tx_empty(struct uart_port *port)
{
//ddprintk("dpram_hz_tx_empty\n");
return TIOCSER_TEMT;
}
static unsigned int dpram_hz_get_mctrl(struct uart_port *port)
{
//ddprintk("dpram_hz_get_mctrl\n");
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}
static void dpram_hz_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
//ddprintk("dpram_hz_set_mctrl\n");
}
static void dpram_hz_break_ctl(struct uart_port *port, int break_state)
{
//ddprintk("dpram_hz_break_ctl\n");
}
static int dpram_hz_startup(struct uart_port *port)
{
msm6280_data.port_hz = port;
msm6280_data.en_hz = true;
ddprintk("\n!!!dpram_hz_startup!!!!\n");
return 0;
}
static void dpram_hz_shutdown(struct uart_port *port)
{
msm6280_data.en_hz = false;
ddprintk("dpram_hz_shutdown\n");
}
static void
dpram_hz_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
//ddprintk("dpram_hz_set_termios\n");
}
static void
dpram_hz_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
//ddprintk("dpram_hz_pm %d %d\n", state, oldstate);
}
static void dpram_hz_release_port(struct uart_port *port)
{
//ddprintk("dpram_hz_release_port\n");
}
static int dpram_hz_request_port(struct uart_port *port)
{
//ddprintk("dpram_hz_request_port\n");
return 0;
}
static void dpram_hz_config_port(struct uart_port *port, int flags)
{
//ddprintk("dpram_hz_config_port\n");
port->type = PORT_DPRAM;
}
static int
dpram_hz_verify_port(struct uart_port *port, struct serial_struct *ser)
{
/* we don't want the core code to modify any port params */
return -EINVAL;
}
static const char *
dpram_hz_type(struct uart_port *port)
{
return "DPRAM";
}
struct uart_ops dpram_hz_pops = {
.tx_empty = dpram_hz_tx_empty,
.set_mctrl = dpram_hz_set_mctrl,
.get_mctrl = dpram_hz_get_mctrl,
.stop_tx = dpram_hz_stop_tx,
.start_tx = dpram_hz_start_tx,
.stop_rx = dpram_hz_stop_rx,
.enable_ms = dpram_hz_enable_ms,
.break_ctl = dpram_hz_break_ctl,
.startup = dpram_hz_startup,
.shutdown = dpram_hz_shutdown,
.set_termios = dpram_hz_set_termios,
.pm = dpram_hz_pm,
.type = dpram_hz_type,
.release_port = dpram_hz_release_port,
.request_port = dpram_hz_request_port,
.config_port = dpram_hz_config_port,
.verify_port = dpram_hz_verify_port,
};
static struct uart_port dpram_hz_port = {
.type = PORT_DPRAM,
.iotype = UPIO_MEM,
.irq = IRQ_RX,
.uartclk = 115000 * 16,
.fifosize = 64,
.ops = &dpram_hz_pops,
.line = 1,
};
static struct uart_driver dpram_hz_reg_data = {
.owner = THIS_MODULE,
.driver_name = "msm6280_hz_uart",
.dev_name = "ttyMSM",
//.dev_name = "smd",
.major = TTY_MAJOR,
.minor = 73,
.nr = 2,
};
int msm6280_tty_hz_probe()
{
int ret;
ret = uart_register_driver(&dpram_hz_reg_data);
if (ret != 0)
goto err1;
dpram_hz_port.mapbase=msm6280_data.data_phys+RX_HZ_START;
ret = uart_add_one_port(&dpram_hz_reg_data, &dpram_hz_port);
if (ret != 0)
goto err2;
return 0;
err2:
uart_remove_one_port(&dpram_hz_reg_data, &dpram_hz_port);
err1:
uart_unregister_driver(&dpram_hz_reg_data);
return ret;
}
void msm6280_tty_hz_remove(void)
{
uart_remove_one_port(&dpram_hz_reg_data, &dpram_hz_port);
uart_unregister_driver(&dpram_hz_reg_data);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,361 @@
clear TRACES
clear IRQS
addlist TRACES p2v(0x40e00000) 0xFFFFFFFE
addlist TRACES p2v(0x14000000)
addlist TRACES p2v(0x14000400)
addlist TRACES p2v(0x14000800)
addlist TRACES p2v(0x14001000)
addlist TRACES p2v(0x14001800)
addlist TRACES p2v(0x14007688)
addlist TRACES p2v(0x14007FFC)
wirq 10
0x0000 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <
0x0400 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> >
0x1800 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
0x7688 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Output("%s %s %s(%d) %08x=%08x (%08x)"
, header, atype, name, pos
, mc->addr, newval, changed);
001879: 00455770: 0x7ffc=00000000 (00000004)
001879: 00455ad7: >0x7688=06cd06cd (00610000)
001879: 00455ad7: 0x7ffc=04000000 (04000000)
001879: 00455f5d: 0x7ffc=00000000 (04000000)
001879: 00458a85: <0x1800=00a400b1 (00000015)
001879: 00458abc: 0x7ffc=00040000 (00040000)
001879: 00458def: <0x1800=00b100b1 (00150000)
001879: 00458def: 0x7ffc=00000400 (00040400)
001879: 0045939d: 0x7ffc=00000000 (00000400)
001879: 0045b44d: >0x7688=06cd06f8 (00000035)
001879: 0045b616: >0x7688=06cd070f (000001f7)
001879: 0045b616: 0x7ffc=00000004 (00000004)
001879: 0045b769: 0x7ffc=00000000 (00000004)
001879: 0045c011: >0x7688=070f070f (01c20000)
001879: 0045c011: 0x7ffc=04000000 (04000000)
001879: 0045c2e0: 0x7ffc=00000000 (04000000)
001879: 00488c45: <0x0000=02cf02d1 (0000001e)
001879: 00488c45: 0x7ffc=00010000 (00010000)
001879: 0048907f: 0x7ffc=00000000 (00010000)
001879: 00489850: <0x0000=02d102d1 (001e0000)
001879: 00490b1b: <0x1800=00b100dd (0000006c)
001879: 00490b1b: 0x7ffc=00040000 (00040000)
001879: 0049104e: <0x1800=00dd00dd (006c0000)
001879: 0049104e: 0x7ffc=00000400 (00040400)
001879: 004912d4: 0x7ffc=00000000 (00000400)
002773: 0069a728: <0x0000=02d102f9 (00000028)
002773: 0069a728: 0x7ffc=00010000 (00010000)
002773: 0069a9b8: 0x7ffc=00000000 (00010000)
002773: 0069afed: <0x0000=02f902f9 (00280000)
002773: 006a0b16: <0x1800=00dd00ea (00000037)
002773: 006a0b16: 0x7ffc=00040000 (00040000)
002773: 006a0e33: <0x1800=00ea00ea (00370000)
002773: 006a0e33: 0x7ffc=00000400 (00040400)
002773: 006a229a: >0x7688=070f071c (00000013)
002773: 006a229a: 0x7ffc=00000404 (00000004)
002773: 006a365d: 0x7ffc=00000000 (00000404)
002773: 006a48bd: >0x7688=071c071c (00130000)
002773: 006a48bd: 0x7ffc=04000000 (04000000)
002773: 006a4af3: 0x7ffc=00000000 (04000000)
002773: 006a78ec: <0x1800=00ea0103 (000001e9)
002773: 006a78ec: 0x7ffc=00040000 (00040000)
002773: 006a7c96: <0x1800=01030103 (01e90000)
002773: 006a7c96: 0x7ffc=00000400 (00040400)
002773: 006a827e: 0x7ffc=00000000 (00000400)
002773: 006a9141: >0x7688=071c073b (00000027)
002773: 006a9936: >0x7688=073b073b (00270000)
002773: 006a9936: 0x7ffc=04000000 (04000000)
002773: 006a9c31: 0x7ffc=00000000 (04000000)
002773: 006aefee: <0x1800=01030122 (00000021)
002773: 006aefee: 0x7ffc=00040000 (00040000)
002773: 006af2e2: <0x1800=01220122 (00210000)
002773: 006af2e2: 0x7ffc=00000400 (00040400)
002773: 006af38d: 0x7ffc=00000000 (00000400)
002773: 006b071c: >0x7688=073b075a (00000061)
002773: 006b0f5b: >0x7688=075a075a (00610000)
002773: 006b0f5b: 0x7ffc=04000000 (04000000)
002773: 006b11bc: 0x7ffc=00000000 (04000000)
002773: 006b5e50: <0x1800=01220141 (00000063)
002773: 006b5e50: 0x7ffc=00040000 (00040000)
002773: 006b60a8: <0x1800=01410141 (00630000)
002773: 006b60a8: 0x7ffc=00000400 (00040400)
002773: 006b618f: 0x7ffc=00000000 (00000400)
002773: 006b9e4f: >0x7688=075a0875 (00000f2f)
002773: 006ba877: >0x7688=08750875 (0f2f0000)
002773: 006ba877: 0x7ffc=04000000 (04000000)
002773: 006bab3a: 0x7ffc=00000000 (04000000)
003783: 00825209: >0x7688=08750020 (00000855)
003783: 00825ed9: >0x7688=00200020 (08550000)
003783: 00825ed9: 0x7ffc=04000000 (04000000)
003783: 008262cd: 0x7ffc=00000000 (04000000)
004784: 009ecdae: >0x7688=0020013b (0000011b)
004784: 009eda27: >0x7688=013b013b (011b0000)
004784: 009eda27: 0x7ffc=04000000 (04000000)
004784: 009ede54: 0x7ffc=00000000 (04000000)
005983: 00c44ea4: >0x7688=013b01a3 (00000098)
005983: 00c44ea4: 0x7ffc=00000004 (00000004)
005983: 00c46f0c: 0x7ffc=00000000 (00000004)
005983: 00c47c69: >0x7688=01a301a3 (00980000)
005983: 00c47c69: 0x7ffc=04000000 (04000000)
005983: 00c48011: 0x7ffc=00000000 (04000000)
006715: 0108ca20: >0x7688=01a3020b (000003a8)
006715: 0108d587: >0x7688=020b020b (03a80000)
006715: 0108d587: 0x7ffc=04000000 (04000000)
006715: 0108d927: 0x7ffc=00000000 (04000000)
006836: 0136a44a: >0x7688=020b0273 (00000078)
006836: 0136b000: >0x7688=02730273 (00780000)
006836: 0136b000: 0x7ffc=04000000 (04000000)
006836: 0136b30b: 0x7ffc=00000000 (04000000)
007229: 016345e8: >0x7688=027302db (000000a8)
007229: 016345e8: 0x7ffc=00000004 (00000004)
007229: 0163466e: 0x7ffc=00000000 (00000004)
007229: 01635147: >0x7688=02db02db (00a80000)
007229: 01635147: 0x7ffc=04000000 (04000000)
007229: 01635391: 0x7ffc=00000000 (04000000)
022157: 034efeb0: >0x7688=02db02ea (00000031)
022157: 034efeb0: 0x7ffc=00000004 (00000004)
022157: 034fbbe7: 0x7ffc=00000000 (00000004)
022157: 034fce52: >0x7688=02ea02ea (00310000)
022157: 034fce52: 0x7ffc=04000000 (04000000)
022157: 034fd287: 0x7ffc=00000000 (04000000)
022157: 0350074f: <0x1800=01410155 (00000014)
022157: 0350074f: 0x7ffc=00040000 (00040000)
022157: 03500be2: <0x1800=01550155 (00140000)
022157: 03500be2: 0x7ffc=00000400 (00040400)
022157: 0350106e: 0x7ffc=00000000 (00000400)
022218: 035650ce: >0x0400=00040011 (00000015)
022218: 035650ce: 0x7ffc=00000001 (00000001)
022218: 0356fe67: 0x7ffc=00000000 (00000001)
022218: 03570f61: >0x0400=00110011 (00150000)
022218: 03570f61: 0x7ffc=01000000 (01000000)
022218: 035713d7: 0x7ffc=00000000 (01000000)
023030: 0382185f: <0x0000=02f902fb (00000002)
023030: 0382185f: 0x7ffc=00010000 (00010000)
023030: 03821aec: 0x7ffc=00000000 (00010000)
023030: 03822110: <0x0000=02fb02fb (00020000)
023041: 0382b981: >0x0400=00110018 (00000009)
023041: 0382c01a: <0x0000=02fb0323 (000001d8)
023041: 0382c01a: 0x7ffc=00010000 (00010000)
023041: 0382c3f3: 0x7ffc=00000000 (00010000)
023041: 0382c7ba: >0x0400=0x180018 (00090000)
023041: 0382c7ba: 0x7ffc=01000000 (01000000)
023041: 0382c8be: 0x7ffc=00000000 (01000000)
023041: 0382cbd2: <0x0000=03230323 (01d80000)
023041: 0382cbd2: 0x7ffc=00000100 (00000100)
023041: 0382ceb5: 0x7ffc=00000000 (00000100)
023041: 03832e7f: <0x0000=03230332 (00000011)
023041: 03832e7f: 0x7ffc=00010000 (00010000)
023041: 038330de: 0x7ffc=00000000 (00010000)
023041: 03835b26: <0x0000=03320332 (00110000)
023159: 03868ccf: <0x1800=00000000 (01550155)
023160: 03869f9f: <0x0000=03320334 (00000006)
023160: 03869f9f: 0x7ffc=00010000 (00010000)
023160: 0386a2c7: 0x7ffc=00000000 (00010000)
023160: 0386a9fd: <0x0000=03340334 (00060000)
023160: 0386c726: <0x0000=0334034f (0000007b)
023160: 0386c726: 0x7ffc=00010000 (00010000)
023160: 0386ca42: 0x7ffc=00000000 (00010000)
023160: 0386d133: <0x0000=034f034f (007b0000)
025551: 03cc0d2d: <0x0000=034f035c (00000013)
025551: 03cc0d2d: 0x7ffc=00010000 (00010000)
025551: 03cc0fb0: 0x7ffc=00000000 (00010000)
025551: 03cc16c4: <0x0000=035c035c (00130000)
025551: 03cc16c4: 0x7ffc=00000100 (00000100)
025551: 03cc19f7: 0x7ffc=00000000 (00000100)
027907: 03eceaf2: <0x0000=035c0369 (00000035)
027907: 03eceaf2: 0x7ffc=00010000 (00010000)
027907: 03eced79: 0x7ffc=00000000 (00010000)
027907: 03ecf3c2: <0x0000=03690369 (00350000)
040130: 047a6688: >0x0400=0x180036 (0000002e)
040130: 047a6688: 0x7ffc=00000001 (00000001)
040130: 047b2e9c: 0x7ffc=00000000 (00000001)
040130: 047b333d: >0x0400=00360036 (002e0000)
040130: 047b333d: 0x7ffc=01000000 (01000000)
040130: 047b3626: 0x7ffc=00000000 (01000000)
040130: 047b7dc2: <0x0000=0369036b (00000002)
040130: 047b7dc2: 0x7ffc=00010000 (00010000)
040130: 047b7eef: 0x7ffc=00000000 (00010000)
040130: 047b8499: <0x0000=036b036b (00020000)
040130: 047b8499: 0x7ffc=00000100 (00000100)
040130: 047b87cb: 0x7ffc=00000000 (00000100)
076201: 0705911a: >0x0400=00360061 (00000057)
076201: 0705911a: 0x7ffc=00000001 (00000001)
076201: 07064d93: 0x7ffc=00000000 (00000001)
076201: 07065b8f: >0x0400=00610061 (00570000)
076201: 07065b8f: 0x7ffc=01000000 (01000000)
076201: 07065f5f: 0x7ffc=00000000 (01000000)
076219: 0707a937: <0x0000=036b036d (00000006)
076219: 0707a937: 0x7ffc=00010000 (00010000)
076219: 0707abe9: 0x7ffc=00000000 (00010000)
076219: 0707b2d4: <0x0000=036d036d (00060000)
076225: 070875db: >0x0400=0061006d (0000000c)
076225: 070875db: 0x7ffc=00000001 (00000001)
076231: 0708993b: 0x7ffc=00000000 (00000001)
076232: 0708a39c: >0x0400=006d006d (000c0000)
076232: 0708a39c: 0x7ffc=01000000 (01000000)
076232: 0708a645: 0x7ffc=00000000 (01000000)
076238: 0708e864: <0x0000=036d036f (00000002)
076238: 0708e864: 0x7ffc=00010000 (00010000)
076238: 0708ec13: 0x7ffc=00000000 (00010000)
076238: 0708f275: <0x0000=036f036f (00020000)
076243: 0709b07b: >0x0400=006d0079 (00000014)
076243: 0709b07b: 0x7ffc=00000001 (00000001)
076250: 0709d451: >0x0400=00790079 (00140000)
076250: 0709d451: 0x7ffc=01000000 (01000001)
076250: 0709d6f4: 0x7ffc=00000000 (01000000)
076256: 070a5dea: <0x0000=036f0371 (0000001e)
076256: 070a5dea: 0x7ffc=00010000 (00010000)
076256: 070a6003: 0x7ffc=00000000 (00010000)
076256: 070a662c: <0x0000=03710371 (001e0000)
076271: 070c4efa: >0x0400=0079008b (000000f2)
076271: 070c4efa: 0x7ffc=00000001 (00000001)
076277: 070c7e8a: 0x7ffc=00000000 (00000001)
076281: 070c8c7f: >0x0400=008b008b (00f20000)
076281: 070c8c7f: 0x7ffc=01000000 (01000000)
076281: 070c8fab: 0x7ffc=00000000 (01000000)
076288: 070ccbd3: <0x0000=03710373 (00000002)
076288: 070ccbd3: 0x7ffc=00010000 (00010000)
076288: 070ccdef: 0x7ffc=00000000 (00010000)
076288: 070cd417: <0x0000=03730373 (00020000)
076359: 0715bf14: >0x7688=02ea0312 (000001f8)
076359: 0715bf14: 0x7ffc=00000004 (00000004)
076362: 07167c3e: 0x7ffc=00000000 (00000004)
076364: 07169002: >0x7688=03120312 (01f80000)
076364: 07169002: 0x7ffc=04000000 (04000000)
076364: 07169372: 0x7ffc=00000000 (04000000)
076364: 0716c80a: <0x1800=00000039 (00000039)
076364: 0716c80a: 0x7ffc=00040000 (00040000)
076364: 0716cc08: <0x1800=00390039 (00390000)
076364: 0716cc08: 0x7ffc=00000400 (00040400)
076364: 0716d009: 0x7ffc=00000000 (00000400)
076364: 0716e15a: >0x7688=0312034b (00000059)
076364: 0716ea0f: >0x7688=034b034b (00590000)
076364: 0716ea0f: 0x7ffc=04000000 (04000000)
076364: 0716ed21: 0x7ffc=00000000 (04000000)
076364: 07170736: <0x1800=00390061 (00000058)
076364: 07170736: 0x7ffc=00040000 (00040000)
076364: 07170ad6: <0x1800=00610061 (00580000)
076364: 07170ad6: 0x7ffc=00000400 (00040400)
076364: 07170e52: 0x7ffc=00000000 (00000400)
076364: 07174628: <0x1800=0061007a (0000001b)
076364: 07174628: 0x7ffc=00040000 (00040000)
076364: 071749f7: <0x1800=007a007a (001b0000)
076364: 071749f7: 0x7ffc=00000400 (00040400)
076364: 07174e03: 0x7ffc=00000000 (00000400)
076364: 0717725e: <0x1800=007a00a6 (000000dc)
076364: 0717725e: 0x7ffc=00040000 (00040000)
076364: 0717761a: <0x1800=00a600a6 (00dc0000)
076364: 0717761a: 0x7ffc=00000400 (00040400)
076364: 07177cc0: 0x7ffc=00000000 (00000400)
076364: 0717cf70: >0x7688=034b036c (00000027)
076364: 0717cf70: 0x7ffc=00000004 (00000004)
076364: 0718fa4e: >0x7688=036c036c (00270000)
076364: 0718fa4e: 0x7ffc=04000000 (04000004)
076364: 0718fcc9: 0x7ffc=00000000 (04000000)
076364: 07192d7c: <0x1800=00a600b3 (00000015)
076364: 07192d7c: 0x7ffc=00040000 (00040000)
076364: 07192fa7: <0x1800=00b300b3 (00150000)
076364: 07192fa7: 0x7ffc=00000400 (00040400)
076364: 07193041: 0x7ffc=00000000 (00000400)
076364: 071957df: >0x7688=036c0397 (000000fb)
076364: 071957df: 0x7ffc=00000004 (00000004)
076364: 071959c5: >0x7688=036c03ae (00000039)
076450: 071a7443: 0x7ffc=00000000 (00000004)
076450: 071a7fcd: >0x7688=03ae03ae (00c20000)
076450: 071a7fcd: 0x7ffc=04000000 (04000000)
076450: 071a82c7: 0x7ffc=00000000 (04000000)
076450: 071d63ec: <0x0000=03730375 (00000006)
076450: 071d63ec: 0x7ffc=00010000 (00010000)
076450: 071d6870: 0x7ffc=00000000 (00010000)
076450: 071d6fdc: <0x0000=03750375 (00060000)
076450: 071de1cc: <0x1800=00b300df (0000006c)
076450: 071de1cc: 0x7ffc=00040000 (00040000)
076450: 071de6c9: <0x1800=00df00df (006c0000)
076450: 071de6c9: 0x7ffc=00000400 (00040400)
076450: 071de9a8: 0x7ffc=00000000 (00000400)
077370: 073a06bb: <0x0000=0375039d (000000e8)
077370: 073a06bb: 0x7ffc=00010000 (00010000)
077370: 073a093d: 0x7ffc=00000000 (00010000)
077370: 073a0f8c: <0x0000=039d039d (00e80000)
077370: 073a8a8c: <0x1800=00df00ec (00000033)
077370: 073a8ad0: 0x7ffc=00040000 (00040000)
077370: 073a8dfd: <0x1800=00ec00ec (00330000)
077370: 073a8dfd: 0x7ffc=00000400 (00040400)
077370: 073a8ebb: 0x7ffc=00000000 (00000400)
077370: 073aa2b8: >0x7688=03ae03bb (00000015)
077370: 073aab72: >0x7688=03bb03bb (00150000)
077370: 073aab72: 0x7ffc=04000000 (04000000)
077370: 073aad8d: 0x7ffc=00000000 (04000000)
077370: 073acfdc: <0x1800=00ec0105 (000001e9)
077370: 073acfdc: 0x7ffc=00040000 (00040000)
077370: 073ad385: <0x1800=01050105 (01e90000)
077370: 073ad385: 0x7ffc=00000400 (00040400)
077370: 073ad749: 0x7ffc=00000000 (00000400)
077370: 073ae976: >0x7688=03bb03da (00000061)
077370: 073b1a5b: >0x7688=03da03da (00610000)
077370: 073b1a5b: 0x7ffc=04000000 (04000000)
077370: 073b1e69: 0x7ffc=00000000 (04000000)
077370: 073b5bee: <0x1800=01050124 (00000021)
077370: 073b5bee: 0x7ffc=00040000 (00040000)
077370: 073b6018: <0x1800=01240124 (00210000)
077370: 073b6018: 0x7ffc=00000400 (00040400)
077370: 073b640f: 0x7ffc=00000000 (00000400)
077370: 073b74ee: >0x7688=03da03f9 (00000023)
077370: 073b7d0d: >0x7688=03f903f9 (00230000)
077370: 073b7d0d: 0x7ffc=04000000 (04000000)
077370: 073b8022: 0x7ffc=00000000 (04000000)
077370: 073bcdb7: <0x1800=01240143 (00000067)
077370: 073bcdb7: 0x7ffc=00040000 (00040000)
077370: 073bd15e: <0x1800=01430143 (00670000)
077370: 073bd15e: 0x7ffc=00000400 (00040400)
077370: 073bd6df: 0x7ffc=00000000 (00000400)
077370: 073be9bd: >0x7688=03f90514 (000006ed)
077370: 073bf335: >0x7688=05140514 (06ed0000)
077370: 073bf335: 0x7ffc=04000000 (04000000)
077370: 073bf619: 0x7ffc=00000000 (04000000)
078380: 075a2c93: >0x7688=0514062f (0000033b)
078380: 075a3910: >0x7688=062f062f (033b0000)
078380: 075a3910: 0x7ffc=04000000 (04000000)
078380: 075a3cf3: 0x7ffc=00000000 (04000000)
079381: 07707e05: >0x7688=062f074a (00000165)
079381: 07708ac1: >0x7688=074a074a (01650000)
079381: 07708ac1: 0x7ffc=04000000 (04000000)
079381: 07708e89: 0x7ffc=00000000 (04000000)
080473: 07946b19: >0x7688=074a07b2 (000000f8)
080473: 07949dcd: >0x7688=07b207b2 (00f80000)
080473: 07949dcd: 0x7ffc=04000000 (04000000)
080473: 0794a17e: 0x7ffc=00000000 (04000000)
080964: 07d0875a: >0x7688=07b2081a (00000fa8)
080964: 07d0875a: 0x7ffc=00000004 (00000004)
080964: 07d0a57c: 0x7ffc=00000000 (00000004)
080964: 07d0b57d: >0x7688=081a081a (0fa80000)
080964: 07d0b5c3: 0x7ffc=04000000 (04000000)
080964: 07d0ba0d: 0x7ffc=00000000 (04000000)
081181: 07f12b2c: >0x7688=081a0882 (00000098)
081181: 07f12b2c: 0x7ffc=00000004 (00000004)
081181: 07f13634: 0x7ffc=00000000 (00000004)
081181: 07f148eb: >0x7688=08820882 (00980000)
081181: 07f148eb: 0x7ffc=04000000 (04000000)
081181: 07f14c35: 0x7ffc=00000000 (04000000)
081444: 080adc7f: >0x7688=088208ea (00000068)
081444: 080adc7f: 0x7ffc=00000004 (00000004)
081444: 080add0a: 0x7ffc=00000000 (00000004)
081444: 080ae81a: >0x7688=08ea08ea (00680000)
081444: 080ae81a: 0x7ffc=04000000 (04000000)
081444: 080aea44: 0x7ffc=00000000 (04000000)
083056: 082c034e: >0x0400=008b0092 (00000019)
083056: 082c034e: 0x7ffc=00000001 (00000001)
083056: 082c04ce: 0x7ffc=00000000 (00000001)
083056: 082c0d8c: >0x0400=00920092 (00190000)
083056: 082c0d8c: 0x7ffc=01000000 (01000000)
083056: 082c1075: 0x7ffc=00000000 (01000000)
083056: 082c5898: <0x0000=039d03ac (00000031)
083056: 082c5898: 0x7ffc=00010000 (00010000)
083056: 082c59f1: 0x7ffc=00000000 (00010000)
083056: 082c71c6: <0x0000=03ac03ac (00310000)

View File

@@ -0,0 +1,821 @@
irq:80405cd0@A06FC3F8=810540ec abort:8043fc4c@A06FC3F0=81054110 prefetch:80405840@A06FC3EC=8105413c data=8101b000 sizes=c:00001328,t:0003d328
Beginning memory tracing.
Watching TRACES(00): Addr a9300000(@40e00000)
Watching TRACES(01): Addr ba600000(@14000000)
Watching TRACES(02): Addr ba600400(@14000400)
Watching TRACES(03): Addr ba600800(@14000800)
Watching TRACES(04): Addr ba601000(@14001000)
Watching TRACES(05): Addr ba601800(@14001800)
Watching TRACES(06): Addr ba607688(@14007688)
Watching TRACES(07): Addr ba607ffc(@14007ffc)
Replacing windows exception handlers...
Finished installing exception handlers.
000000: 000008ec: mem TRACES(0) a9300000=17fec9ff (00000000)
000000: 000008ec: mem TRACES(1) ba600000=025f025f (00000000)
000000: 000008ec: mem TRACES(2) ba600400=02c602c6 (00000000)
000000: 000008ec: mem TRACES(3) ba600800=00000000 (00000000)
000000: 000008ec: mem TRACES(4) ba601000=00000000 (00000000)
000000: 000008ec: mem TRACES(5) ba601800=00000000 (00000000)
000000: 000008ec: mem TRACES(6) ba607688=03ca03ca (00000000)
000000: 000008ec: mem TRACES(7) ba607ffc=00000000 (00000000)
025177: 0498710e: mem TRACES(2) ba600400=02c602f1 (00000037)
025177: 0498710e: mem TRACES(7) ba607ffc=00000001 (00000001)
025177: 04993298: mem TRACES(7) ba607ffc=00000000 (00000001)
025177: 0499a3c0: mem TRACES(0) a9300000=07fec9fe (00000001)
025177: 0499a3c0: mem TRACES(2) ba600400=02f102f1 (00370000)
025177: 0499a3c0: mem TRACES(7) ba607ffc=01000000 (01000000)
025177: 0499a695: mem TRACES(0) a9300000=07fec9ff (00000001)
025177: 0499a878: mem TRACES(7) ba607ffc=00000000 (01000000)
025177: 049b071e: mem TRACES(0) a9300000=17fec9fe (00000001)
025177: 049b071e: mem TRACES(1) ba600000=025f0261 (0000003e)
025177: 049b071e: mem TRACES(7) ba607ffc=00010000 (00010000)
025177: 049b098e: mem TRACES(0) a9300000=07fec9ff (00000001)
025177: 049b0b57: mem TRACES(7) ba607ffc=00000000 (00010000)
025177: 049b13a5: mem TRACES(1) ba600000=02610261 (003e0000)
025177: 049b13a5: mem TRACES(7) ba607ffc=00000100 (00000100)
025177: 049b1b22: mem TRACES(7) ba607ffc=00000000 (00000100)
025251: 04a1b4db: mem TRACES(2) ba600400=02f102fd (0000000c)
025251: 04a1b4db: mem TRACES(7) ba607ffc=00000001 (00000001)
025259: 04a1d97c: mem TRACES(0) a9300000=17fec9fe (00000001)
025259: 04a1d97c: mem TRACES(2) ba600400=02fd02fd (000c0000)
025259: 04a1d97c: mem TRACES(7) ba607ffc=01000000 (01000001)
025259: 04a1daa7: mem TRACES(0) a9300000=17fec9ff (00000001)
025259: 04a1dc25: mem TRACES(7) ba607ffc=00000000 (01000000)
025266: 04a2178c: mem TRACES(0) a9300000=07fec9fe (00000001)
025266: 04a2178c: mem TRACES(1) ba600000=02610263 (00000002)
025266: 04a2178c: mem TRACES(7) ba607ffc=00010000 (00010000)
025266: 04a21865: mem TRACES(0) a9300000=57fec9ff (00000001)
025266: 04a219a7: mem TRACES(7) ba607ffc=00000000 (00010000)
025266: 04a21fc9: mem TRACES(1) ba600000=02630263 (00020000)
025314: 04a833cb: mem TRACES(2) ba600400=02fd0309 (000001f4)
025314: 04a833cb: mem TRACES(7) ba607ffc=00000001 (00000001)
025321: 04a8da9d: mem TRACES(0) a9300000=07fec9fe (00000001)
025321: 04a8da9d: mem TRACES(2) ba600400=03090309 (01f40000)
025321: 04a8da9d: mem TRACES(7) ba607ffc=01000000 (01000001)
025321: 04a8dc60: mem TRACES(0) a9300000=07fec9ff (00000001)
025321: 04a8dde5: mem TRACES(7) ba607ffc=00000000 (01000000)
025326: 04a915e9: mem TRACES(0) a9300000=47fec9fe (00000001)
025326: 04a915e9: mem TRACES(1) ba600000=02630265 (00000006)
025326: 04a915e9: mem TRACES(7) ba607ffc=00010000 (00010000)
025326: 04a9175b: mem TRACES(0) a9300000=17fec9ff (00000001)
025326: 04a91802: mem TRACES(7) ba607ffc=00000000 (00010000)
025326: 04a91f46: mem TRACES(1) ba600000=02650265 (00060000)
025348: 04abf9fe: mem TRACES(2) ba600400=0309031b (00000012)
025348: 04abf9fe: mem TRACES(7) ba607ffc=00000001 (00000001)
025372: 04acb4a4: mem TRACES(7) ba607ffc=00000000 (00000001)
025372: 04acc11d: mem TRACES(2) ba600400=031b031b (00120000)
025372: 04acc11d: mem TRACES(7) ba607ffc=01000000 (01000000)
025372: 04acc165: mem TRACES(0) a9300000=f7fec9fe (00000001)
025372: 04acc390: mem TRACES(0) a9300000=47fec9ff (00000001)
025372: 04acc522: mem TRACES(7) ba607ffc=00000000 (01000000)
025372: 04ad3393: mem TRACES(0) a9300000=17fac9fe (00000001)
025372: 04ad3393: mem TRACES(1) ba600000=02650267 (00000002)
025372: 04ad3393: mem TRACES(7) ba607ffc=00010000 (00010000)
025372: 04ad3647: mem TRACES(0) a9300000=17fac9ff (00000001)
025372: 04ad3805: mem TRACES(7) ba607ffc=00000000 (00010000)
025372: 04ad3f79: mem TRACES(1) ba600000=02670267 (00020000)
025372: 04ad3f79: mem TRACES(7) ba607ffc=00000100 (00000100)
025372: 04ad3fe7: mem TRACES(7) ba607ffc=00000000 (00000100)
025856: 04eaa8f2: mem TRACES(6) ba607688=03ca03f2 (00000038)
025856: 04eaa8f2: mem TRACES(7) ba607ffc=00000004 (00000004)
025882: 04eb6885: mem TRACES(7) ba607ffc=00000000 (00000004)
025882: 04eb78fe: mem TRACES(0) a9300000=07fec9fe (00000001)
025882: 04eb78fe: mem TRACES(6) ba607688=03f203f2 (00380000)
025882: 04eb78fe: mem TRACES(7) ba607ffc=04000000 (04000000)
025882: 04eb7ad6: mem TRACES(0) a9300000=17fec9ff (00000001)
025882: 04eb7ca9: mem TRACES(7) ba607ffc=00000000 (04000000)
025882: 04ebba87: mem TRACES(0) a9300000=07fec9fe (00000001)
025882: 04ebba87: mem TRACES(5) ba601800=0000003a (0000003a)
025882: 04ebba87: mem TRACES(7) ba607ffc=00040000 (00040000)
025882: 04ebbd6c: mem TRACES(0) a9300000=07fec9ff (00000001)
025882: 04ebc01a: mem TRACES(5) ba601800=003a003a (003a0000)
025882: 04ebc01a: mem TRACES(7) ba607ffc=00000400 (00040400)
025882: 04ebc30a: mem TRACES(7) ba607ffc=00000000 (00000400)
025882: 04ebe7c4: mem TRACES(0) a9300000=17fec9fe (00000001)
025882: 04ebe7c4: mem TRACES(5) ba601800=003a0062 (00000058)
025882: 04ebe7c4: mem TRACES(7) ba607ffc=00040000 (00040000)
025882: 04ebeb3e: mem TRACES(0) a9300000=17fec9ff (00000001)
025882: 04ebed77: mem TRACES(5) ba601800=00620062 (00580000)
025882: 04ebed77: mem TRACES(7) ba607ffc=00000400 (00040400)
025882: 04ebeecf: mem TRACES(7) ba607ffc=00000000 (00000400)
025882: 04ed0c12: mem TRACES(6) ba607688=03f2042a (000007d8)
025882: 04ed0c12: mem TRACES(7) ba607ffc=00000004 (00000004)
025882: 04edd495: mem TRACES(0) a9300000=17fec9fe (00000001)
025882: 04edd495: mem TRACES(6) ba607688=042a042a (07d80000)
025882: 04edd495: mem TRACES(7) ba607ffc=04000000 (04000004)
025882: 04edd74b: mem TRACES(0) a9300000=37fec9ff (00000001)
025882: 04edd943: mem TRACES(7) ba607ffc=00000000 (04000000)
025882: 04ee1401: mem TRACES(0) a9300000=07fec9fe (00000001)
025882: 04ee1401: mem TRACES(5) ba601800=0062007c (0000001e)
025882: 04ee1401: mem TRACES(7) ba607ffc=00040000 (00040000)
025882: 04ee16d2: mem TRACES(0) a9300000=07fec9ff (00000001)
025882: 04ee19f4: mem TRACES(5) ba601800=007c007c (001e0000)
025882: 04ee19f4: mem TRACES(7) ba607ffc=00000400 (00040400)
025882: 04ee1bb8: mem TRACES(7) ba607ffc=00000000 (00000400)
025882: 04ee4261: mem TRACES(5) ba601800=007c00a8 (000000d4)
025882: 04ee4261: mem TRACES(7) ba607ffc=00040000 (00040000)
025882: 04ee42ba: mem TRACES(0) a9300000=17fec9fe (00000001)
025882: 04ee449f: mem TRACES(0) a9300000=07fec9ff (00000001)
025882: 04ee4636: mem TRACES(7) ba607ffc=00000000 (00040000)
025882: 04ee4e84: mem TRACES(5) ba601800=00a800a8 (00d40000)
025882: 04ee4e84: mem TRACES(7) ba607ffc=00000400 (00000400)
025882: 04ee4f68: mem TRACES(7) ba607ffc=00000000 (00000400)
025882: 04ef6b62: mem TRACES(6) ba607688=042a044b (00000061)
025882: 04ef6b62: mem TRACES(7) ba607ffc=00000004 (00000004)
025882: 04f028d3: mem TRACES(7) ba607ffc=00000000 (00000004)
025882: 04f032fb: mem TRACES(6) ba607688=044b044b (00610000)
025882: 04f032fb: mem TRACES(7) ba607ffc=04000000 (04000000)
025882: 04f03342: mem TRACES(0) a9300000=57fec9fe (00000001)
025882: 04f0354b: mem TRACES(0) a9300000=07fec9ff (00000001)
025882: 04f0368c: mem TRACES(7) ba607ffc=00000000 (04000000)
025882: 04f06301: mem TRACES(0) a9300000=57fec9fe (00000001)
025882: 04f06301: mem TRACES(5) ba601800=00a800b5 (0000001d)
025882: 04f06301: mem TRACES(7) ba607ffc=00040000 (00040000)
025882: 04f064a4: mem TRACES(0) a9300000=17fec9ff (00000001)
025882: 04f06732: mem TRACES(5) ba601800=00b500b5 (001d0000)
025882: 04f06732: mem TRACES(7) ba607ffc=00000400 (00040400)
025882: 04f06b71: mem TRACES(7) ba607ffc=00000000 (00000400)
025882: 04f0b984: mem TRACES(6) ba607688=044b0476 (0000003d)
025882: 04f0b984: mem TRACES(7) ba607ffc=00000004 (00000004)
025882: 04f0bb58: mem TRACES(6) ba607688=044b048d (000000fb)
025882: 04f1addc: mem TRACES(7) ba607ffc=00000000 (00000004)
025882: 04f1b89c: mem TRACES(0) a9300000=07fec9fe (00000001)
025882: 04f1b89c: mem TRACES(6) ba607688=048d048d (00c60000)
025882: 04f1b89c: mem TRACES(7) ba607ffc=04000000 (04000000)
025882: 04f1badf: mem TRACES(0) a9300000=07fec9ff (00000001)
025882: 04f1bc93: mem TRACES(7) ba607ffc=00000000 (04000000)
025950: 04f44291: mem TRACES(0) a9300000=07fec9fe (00000001)
025950: 04f44291: mem TRACES(1) ba600000=02670269 (0000000e)
025950: 04f44291: mem TRACES(7) ba607ffc=00010000 (00010000)
025950: 04f4454d: mem TRACES(0) a9300000=17fec9ff (00000001)
025950: 04f4454d: mem TRACES(7) ba607ffc=00000000 (00010000)
025950: 04f482c4: mem TRACES(1) ba600000=02690269 (000e0000)
025950: 04f482c4: mem TRACES(7) ba607ffc=00000100 (00000100)
025950: 04f4c62d: mem TRACES(7) ba607ffc=00000000 (00000100)
025950: 04f4ef6f: mem TRACES(0) a9300000=07fac9fe (00000001)
025950: 04f4ef6f: mem TRACES(5) ba601800=00b500e1 (00000054)
025950: 04f4ef6f: mem TRACES(7) ba607ffc=00040000 (00040000)
025950: 04f4f204: mem TRACES(0) a9300000=07fac9ff (00000001)
025950: 04f4f4b4: mem TRACES(5) ba601800=00e100e1 (00540000)
025950: 04f4f4b4: mem TRACES(7) ba607ffc=00000400 (00040400)
025950: 04f4f755: mem TRACES(7) ba607ffc=00000000 (00000400)
026915: 050de61c: mem TRACES(0) a9300000=17fec9fe (00000001)
026915: 050de61c: mem TRACES(5) ba601800=00e10106 (000001e7)
026915: 050de61c: mem TRACES(7) ba607ffc=00040000 (00040000)
026915: 050de73e: mem TRACES(0) a9300000=67fec9ff (00000001)
026915: 050de9d3: mem TRACES(5) ba601800=01060106 (01e70000)
026915: 050de9d3: mem TRACES(7) ba607ffc=00000400 (00040400)
026915: 050dee55: mem TRACES(7) ba607ffc=00000000 (00000400)
026915: 050e00eb: mem TRACES(6) ba607688=048d04b8 (00000035)
026915: 050e0ac5: mem TRACES(0) a9300000=07fec9fe (00000001)
026915: 050e0ac5: mem TRACES(6) ba607688=04b804b8 (00350000)
026915: 050e0ac5: mem TRACES(7) ba607ffc=04000000 (04000000)
026915: 050e0c28: mem TRACES(0) a9300000=07fec9ff (00000001)
026915: 050e0da3: mem TRACES(7) ba607ffc=00000000 (04000000)
027316: 05222f3c: mem TRACES(0) a9300000=17fec9fe (00000001)
027316: 05222f3c: mem TRACES(1) ba600000=02690291 (000000f8)
027316: 05222f3c: mem TRACES(7) ba607ffc=00010000 (00010000)
027316: 05223093: mem TRACES(0) a9300000=17fec9ff (00000001)
027316: 05223214: mem TRACES(7) ba607ffc=00000000 (00010000)
027316: 0522389a: mem TRACES(1) ba600000=02910291 (00f80000)
027316: 0522cea3: mem TRACES(0) a9300000=37fec9fe (00000001)
027316: 0522cea3: mem TRACES(5) ba601800=01060113 (00000015)
027316: 0522cea3: mem TRACES(7) ba607ffc=00040000 (00040000)
027316: 0522d1a8: mem TRACES(0) a9300000=07fec9ff (00000001)
027316: 0522d1a8: mem TRACES(5) ba601800=01130113 (00150000)
027316: 0522d1a8: mem TRACES(7) ba607ffc=00000400 (00040400)
027316: 0522d283: mem TRACES(7) ba607ffc=00000000 (00000400)
027316: 0522e571: mem TRACES(6) ba607688=04b804c5 (0000007d)
027316: 0522f044: mem TRACES(0) a9300000=07fec9fe (00000001)
027316: 0522f044: mem TRACES(6) ba607688=04c504c5 (007d0000)
027316: 0522f044: mem TRACES(7) ba607ffc=04000000 (04000000)
027316: 0522f151: mem TRACES(0) a9300000=07fec9ff (00000001)
027316: 0522f299: mem TRACES(7) ba607ffc=00000000 (04000000)
027316: 05231b8b: mem TRACES(0) a9300000=17fec9fe (00000001)
027316: 05231b8b: mem TRACES(5) ba601800=0113012c (0000003f)
027316: 05231b8b: mem TRACES(7) ba607ffc=00040000 (00040000)
027316: 05231d7c: mem TRACES(0) a9300000=07fec9ff (00000001)
027316: 05231fc3: mem TRACES(5) ba601800=012c012c (003f0000)
027316: 05231fc3: mem TRACES(7) ba607ffc=00000400 (00040400)
027316: 052331be: mem TRACES(7) ba607ffc=00000000 (00000400)
027316: 052335dc: mem TRACES(6) ba607688=04c504e4 (00000021)
027316: 052335dc: mem TRACES(7) ba607ffc=00000004 (00000004)
027316: 0523364f: mem TRACES(7) ba607ffc=00000000 (00000004)
027316: 05234192: mem TRACES(0) a9300000=07fec9fe (00000001)
027316: 05234192: mem TRACES(6) ba607688=04e404e4 (00210000)
027316: 05234192: mem TRACES(7) ba607ffc=04000000 (04000000)
027316: 05234359: mem TRACES(0) a9300000=17fec9ff (00000001)
027316: 052344e7: mem TRACES(7) ba607ffc=00000000 (04000000)
027316: 05238fb3: mem TRACES(5) ba601800=012c014b (00000067)
027316: 05239011: mem TRACES(0) a9300000=57fec9fe (00000001)
027316: 05239011: mem TRACES(7) ba607ffc=00040000 (00040000)
027316: 052391a5: mem TRACES(0) a9300000=17fec9ff (00000001)
027316: 052393ff: mem TRACES(5) ba601800=014b014b (00670000)
027316: 052393ff: mem TRACES(7) ba607ffc=00000400 (00040400)
027316: 052397c3: mem TRACES(7) ba607ffc=00000000 (00000400)
027316: 0523a91a: mem TRACES(6) ba607688=04e40504 (000001e0)
027316: 0523cd0b: mem TRACES(0) a9300000=07fec9fe (00000001)
027316: 0523cd0b: mem TRACES(6) ba607688=05040504 (01e00000)
027316: 0523cd0b: mem TRACES(7) ba607ffc=04000000 (04000000)
027316: 0523d0b2: mem TRACES(0) a9300000=07fec9ff (00000001)
027316: 0523d0b2: mem TRACES(7) ba607ffc=00000000 (04000000)
027316: 05242c57: mem TRACES(0) a9300000=07fec9fe (00000001)
027316: 05242c57: mem TRACES(5) ba601800=014b016a (00000021)
027316: 05242c57: mem TRACES(7) ba607ffc=00040000 (00040000)
027316: 05242e83: mem TRACES(0) a9300000=07fec9ff (00000001)
027316: 05242e83: mem TRACES(5) ba601800=016a016a (00210000)
027316: 05242e83: mem TRACES(7) ba607ffc=00000400 (00040400)
027316: 05242f13: mem TRACES(7) ba607ffc=00000000 (00000400)
027316: 0524547b: mem TRACES(6) ba607688=0504061f (0000031b)
027316: 0524547b: mem TRACES(7) ba607ffc=00000004 (00000004)
027316: 052496bb: mem TRACES(7) ba607ffc=00000000 (00000004)
027316: 0524a2e3: mem TRACES(0) a9300000=17fec9fe (00000001)
027316: 0524a2e3: mem TRACES(6) ba607688=061f061f (031b0000)
027316: 0524a2e3: mem TRACES(7) ba607ffc=04000000 (04000000)
027316: 0524a69b: mem TRACES(0) a9300000=07fe89ff (00000001)
027316: 0524a69b: mem TRACES(7) ba607ffc=00000000 (04000000)
028327: 053ceb4b: mem TRACES(6) ba607688=061f073a (00000125)
028327: 053cf801: mem TRACES(0) a9300000=87fec9fe (00000001)
028327: 053cf801: mem TRACES(6) ba607688=073a073a (01250000)
028327: 053cf801: mem TRACES(7) ba607ffc=04000000 (04000000)
028327: 053cf9a8: mem TRACES(0) a9300000=07fec9ff (00000001)
028327: 053cfc0e: mem TRACES(7) ba607ffc=00000000 (04000000)
029328: 055bed8d: mem TRACES(6) ba607688=073a0855 (00000f6f)
029328: 055bfa93: mem TRACES(0) a9300000=17fec9fe (00000001)
029328: 055bfa93: mem TRACES(6) ba607688=08550855 (0f6f0000)
029328: 055bfa93: mem TRACES(7) ba607ffc=04000000 (04000000)
029328: 055bfd35: mem TRACES(0) a9300000=07fec9ff (00000001)
029328: 055bfeae: mem TRACES(7) ba607ffc=00000000 (04000000)
038384: 071cbb0a: mem TRACES(2) ba600400=031b0339 (00000022)
038384: 071cbb0a: mem TRACES(7) ba607ffc=00000001 (00000001)
038384: 071d85f9: mem TRACES(7) ba607ffc=00000000 (00000001)
038384: 071d868d: mem TRACES(0) a9300000=07fec9fe (00000001)
038384: 071d868d: mem TRACES(2) ba600400=03390339 (00220000)
038384: 071d868d: mem TRACES(7) ba607ffc=01000000 (01000000)
038384: 071d88ab: mem TRACES(0) a9300000=07fec9ff (00000001)
038384: 071d8996: mem TRACES(7) ba607ffc=00000000 (01000000)
038384: 071dcede: mem TRACES(0) a9300000=07fec9fe (00000001)
038384: 071dcede: mem TRACES(1) ba600000=02910293 (00000002)
038384: 071dcede: mem TRACES(7) ba607ffc=00010000 (00010000)
038384: 071dd019: mem TRACES(0) a9300000=77fec9ff (00000001)
038384: 071dd019: mem TRACES(7) ba607ffc=00000000 (00010000)
038384: 071dd5fe: mem TRACES(1) ba600000=02930293 (00020000)
038384: 071dd5fe: mem TRACES(7) ba607ffc=00000100 (00000100)
038384: 071dd93d: mem TRACES(7) ba607ffc=00000000 (00000100)
041542: 079a43ab: mem TRACES(2) ba600400=03390340 (00000079)
041542: 079a43ab: mem TRACES(7) ba607ffc=00000001 (00000001)
041542: 079afbfa: mem TRACES(7) ba607ffc=00000000 (00000001)
041542: 079b96a5: mem TRACES(0) a9300000=07fec9fe (00000001)
041542: 079b96a5: mem TRACES(2) ba600400=03400340 (00790000)
041542: 079b96a5: mem TRACES(7) ba607ffc=01000000 (01000000)
041542: 079b9859: mem TRACES(0) a9300000=07fec9ff (00000001)
041542: 079b99ea: mem TRACES(7) ba607ffc=00000000 (01000000)
041542: 079c00f5: mem TRACES(0) a9300000=17fec9fe (00000001)
041542: 079c00f5: mem TRACES(1) ba600000=029302a2 (00000031)
041542: 079c00f5: mem TRACES(7) ba607ffc=00010000 (00010000)
041542: 079c03f1: mem TRACES(0) a9300000=47fec9ff (00000001)
041542: 079c03f1: mem TRACES(7) ba607ffc=00000000 (00010000)
041542: 079c0e1f: mem TRACES(1) ba600000=02a202a2 (00310000)
044150: 0817684e: mem TRACES(6) ba607688=08550864 (00000031)
044150: 0817684e: mem TRACES(7) ba607ffc=00000004 (00000004)
044150: 08182a22: mem TRACES(7) ba607ffc=00000000 (00000004)
044150: 0818b309: mem TRACES(0) a9300000=17fec9fe (00000001)
044150: 0818b309: mem TRACES(6) ba607688=08640864 (00310000)
044150: 0818b309: mem TRACES(7) ba607ffc=04000000 (04000000)
044150: 0818b5a3: mem TRACES(0) a9300000=17fec9ff (00000001)
044150: 0818b7b0: mem TRACES(7) ba607ffc=00000000 (04000000)
044150: 08192b32: mem TRACES(0) a9300000=17fec9fe (00000001)
044150: 08192b32: mem TRACES(5) ba601800=016a017e (00000014)
044150: 08192b32: mem TRACES(7) ba607ffc=00040000 (00040000)
044150: 08192ffc: mem TRACES(0) a9300000=07fec9ff (00000001)
044150: 08192ffc: mem TRACES(5) ba601800=017e017e (00140000)
044150: 08192ffc: mem TRACES(7) ba607ffc=00000400 (00040400)
044150: 08193443: mem TRACES(7) ba607ffc=00000000 (00000400)
044223: 082d9707: mem TRACES(2) ba600400=0340034d (0000000d)
044223: 082d9707: mem TRACES(7) ba607ffc=00000001 (00000001)
044223: 082e5b4d: mem TRACES(7) ba607ffc=00000000 (00000001)
044223: 082e6521: mem TRACES(0) a9300000=17fec9fe (00000001)
044223: 082e6521: mem TRACES(2) ba600400=034d034d (000d0000)
044223: 082e6521: mem TRACES(7) ba607ffc=01000000 (01000000)
044223: 082e67be: mem TRACES(0) a9300000=07fec9ff (00000001)
044223: 082e69c3: mem TRACES(7) ba607ffc=00000000 (01000000)
045022: 08710d8c: mem TRACES(0) a9300000=17fec9fe (00000001)
045022: 08710d8c: mem TRACES(1) ba600000=02a202a4 (00000006)
045022: 08710d8c: mem TRACES(7) ba607ffc=00010000 (00010000)
045022: 08710ebc: mem TRACES(0) a9300000=17fec9ff (00000001)
045022: 0871104f: mem TRACES(7) ba607ffc=00000000 (00010000)
045022: 08711782: mem TRACES(1) ba600000=02a402a4 (00060000)
045058: 08717515: mem TRACES(1) ba600000=02a402cc (00000068)
045058: 0871caaa: mem TRACES(0) a9300000=17fec9fe (00000001)
045058: 0871caaa: mem TRACES(7) ba607ffc=00010000 (00010000)
045058: 0871ce33: mem TRACES(0) a9300000=17fec9ff (00000001)
045058: 0871ce33: mem TRACES(7) ba607ffc=00000000 (00010000)
045058: 0871d91e: mem TRACES(1) ba600000=02cc02cc (00680000)
045058: 08723b42: mem TRACES(5) ba601800=00000000 (017e017e)
045058: 0872522a: mem TRACES(0) a9300000=17fec9fe (00000001)
045058: 0872522a: mem TRACES(1) ba600000=02cc02ce (00000002)
045058: 0872522a: mem TRACES(7) ba607ffc=00010000 (00010000)
045058: 08725472: mem TRACES(0) a9300000=17fec9ff (00000001)
045058: 08725472: mem TRACES(7) ba607ffc=00000000 (00010000)
045058: 08725c1b: mem TRACES(1) ba600000=02ce02ce (00020000)
045058: 08727a1f: mem TRACES(0) a9300000=07fec9fe (00000001)
045058: 08727a1f: mem TRACES(1) ba600000=02ce02e9 (00000027)
045058: 08727a1f: mem TRACES(7) ba607ffc=00010000 (00010000)
045058: 08727c9f: mem TRACES(0) a9300000=17fec9ff (00000001)
045058: 08727c9f: mem TRACES(7) ba607ffc=00000000 (00010000)
045058: 087284c2: mem TRACES(1) ba600000=02e902e9 (00270000)
061085: 0ada0bd9: mem TRACES(2) ba600400=034d0378 (00000035)
061085: 0ada0bd9: mem TRACES(7) ba607ffc=00000001 (00000001)
061100: 0adaca2c: mem TRACES(7) ba607ffc=00000000 (00000001)
061100: 0adb3a8f: mem TRACES(0) a9300000=57fec9fe (00000001)
061100: 0adb3a8f: mem TRACES(2) ba600400=03780378 (00350000)
061100: 0adb3a8f: mem TRACES(7) ba607ffc=01000000 (01000000)
061100: 0adb3d4b: mem TRACES(0) a9300000=17fec9ff (00000001)
061100: 0adb3f0d: mem TRACES(7) ba607ffc=00000000 (01000000)
061107: 0adc9b85: mem TRACES(0) a9300000=17fec9fe (00000001)
061107: 0adc9b85: mem TRACES(1) ba600000=02e902eb (00000002)
061107: 0adc9b85: mem TRACES(7) ba607ffc=00010000 (00010000)
061107: 0adc9d33: mem TRACES(0) a9300000=47fec9ff (00000001)
061107: 0adca01e: mem TRACES(7) ba607ffc=00000000 (00010000)
061107: 0adca76d: mem TRACES(1) ba600000=02eb02eb (00020000)
061177: 0ae53ce5: mem TRACES(2) ba600400=03780384 (000000fc)
061177: 0ae53ce5: mem TRACES(7) ba607ffc=00000001 (00000001)
061182: 0ae5f6b5: mem TRACES(7) ba607ffc=00000000 (00000001)
061182: 0ae6042c: mem TRACES(0) a9300000=07fac9fe (00000001)
061182: 0ae6042c: mem TRACES(2) ba600400=03840384 (00fc0000)
061182: 0ae6042c: mem TRACES(7) ba607ffc=01000000 (01000000)
061182: 0ae60629: mem TRACES(0) a9300000=17fac9ff (00000001)
061182: 0ae607bc: mem TRACES(7) ba607ffc=00000000 (01000000)
061182: 0ae6895a: mem TRACES(0) a9300000=07fec9fe (00000001)
061182: 0ae6895a: mem TRACES(1) ba600000=02eb02ed (00000006)
061182: 0ae6895a: mem TRACES(7) ba607ffc=00010000 (00010000)
061182: 0ae68bdf: mem TRACES(0) a9300000=57fec9ff (00000001)
061182: 0ae68bdf: mem TRACES(7) ba607ffc=00000000 (00010000)
061182: 0ae6a391: mem TRACES(1) ba600000=02ed02ed (00060000)
061221: 0aeafee9: mem TRACES(2) ba600400=03840390 (00000014)
061221: 0aeafee9: mem TRACES(7) ba607ffc=00000001 (00000001)
061226: 0aebb131: mem TRACES(7) ba607ffc=00000000 (00000001)
061226: 0aebbf60: mem TRACES(0) a9300000=07fec9fe (00000001)
061226: 0aebbf60: mem TRACES(2) ba600400=03900390 (00140000)
061226: 0aebbf60: mem TRACES(7) ba607ffc=01000000 (01000000)
061226: 0aebc0ee: mem TRACES(0) a9300000=17fec9ff (00000001)
061226: 0aebc2a4: mem TRACES(7) ba607ffc=00000000 (01000000)
061284: 0aec824a: mem TRACES(1) ba600000=02ed02ef (00000002)
061284: 0aec824a: mem TRACES(7) ba607ffc=00010000 (00010000)
061284: 0aec8295: mem TRACES(0) a9300000=57fec9fe (00000001)
061284: 0aec84f2: mem TRACES(0) a9300000=17fec9ff (00000001)
061284: 0aec869a: mem TRACES(7) ba607ffc=00000000 (00010000)
061284: 0aec8deb: mem TRACES(1) ba600000=02ef02ef (00020000)
061333: 0af8ddf8: mem TRACES(2) ba600400=039003a2 (00000032)
061333: 0af8ddf8: mem TRACES(7) ba607ffc=00000001 (00000001)
061339: 0af933bd: mem TRACES(0) a9300000=07fac9fe (00000001)
061339: 0af933bd: mem TRACES(2) ba600400=03a203a2 (00320000)
061339: 0af933bd: mem TRACES(7) ba607ffc=01000000 (01000001)
061339: 0af934e9: mem TRACES(0) a9300000=17fac9ff (00000001)
061339: 0af93655: mem TRACES(7) ba607ffc=00000000 (01000000)
061346: 0af974a4: mem TRACES(0) a9300000=17fec9fe (00000001)
061346: 0af974a4: mem TRACES(1) ba600000=02ef02f1 (0000001e)
061346: 0af974a4: mem TRACES(7) ba607ffc=00010000 (00010000)
061346: 0af97578: mem TRACES(0) a9300000=07fec9ff (00000001)
061346: 0af976c7: mem TRACES(7) ba607ffc=00000000 (00010000)
061346: 0af97d77: mem TRACES(1) ba600000=02f102f1 (001e0000)
061407: 0b012e8b: mem TRACES(6) ba607688=0864088c (000000e8)
061407: 0b012e8b: mem TRACES(7) ba607ffc=00000004 (00000004)
061411: 0b01eb3e: mem TRACES(7) ba607ffc=00000000 (00000004)
061411: 0b01f9d8: mem TRACES(0) a9300000=07fec9fe (00000001)
061411: 0b01f9d8: mem TRACES(6) ba607688=088c088c (00e80000)
061411: 0b01f9d8: mem TRACES(7) ba607ffc=04000000 (04000000)
061411: 0b01fca7: mem TRACES(0) a9300000=07fec9ff (00000001)
061411: 0b01fecb: mem TRACES(7) ba607ffc=00000000 (04000000)
061411: 0b02347a: mem TRACES(0) a9300000=17fec9fe (00000001)
061411: 0b02347a: mem TRACES(5) ba601800=00000039 (00000039)
061411: 0b02347a: mem TRACES(7) ba607ffc=00040000 (00040000)
061411: 0b02368d: mem TRACES(0) a9300000=07fec9ff (00000001)
061411: 0b02391c: mem TRACES(5) ba601800=00390039 (00390000)
061411: 0b02391c: mem TRACES(7) ba607ffc=00000400 (00040400)
061411: 0b023d6e: mem TRACES(7) ba607ffc=00000000 (00000400)
061411: 0b024e0e: mem TRACES(6) ba607688=088c08c5 (00000049)
061411: 0b0256b0: mem TRACES(6) ba607688=08c508c5 (00490000)
061411: 0b0256b0: mem TRACES(7) ba607ffc=04000000 (04000000)
061411: 0b025704: mem TRACES(0) a9300000=17fec9fe (00000001)
061411: 0b0258e2: mem TRACES(0) a9300000=17fec9ff (00000001)
061411: 0b025a8c: mem TRACES(7) ba607ffc=00000000 (04000000)
061411: 0b02750f: mem TRACES(0) a9300000=b7fec9fe (00000001)
061411: 0b02750f: mem TRACES(5) ba601800=00390061 (00000058)
061411: 0b02750f: mem TRACES(7) ba607ffc=00040000 (00040000)
061411: 0b027802: mem TRACES(0) a9300000=17fec9ff (00000001)
061411: 0b027802: mem TRACES(5) ba601800=00610061 (00580000)
061411: 0b027802: mem TRACES(7) ba607ffc=00000400 (00040400)
061411: 0b0278a9: mem TRACES(7) ba607ffc=00000000 (00000400)
061411: 0b02b271: mem TRACES(0) a9300000=07fec9fe (00000001)
061411: 0b02b271: mem TRACES(5) ba601800=0061007a (0000001b)
061411: 0b02b271: mem TRACES(7) ba607ffc=00040000 (00040000)
061411: 0b02b63e: mem TRACES(0) a9300000=47fec9ff (00000001)
061411: 0b02b63e: mem TRACES(5) ba601800=007a007a (001b0000)
061411: 0b02b63e: mem TRACES(7) ba607ffc=00000400 (00040400)
061411: 0b02baf6: mem TRACES(7) ba607ffc=00000000 (00000400)
061411: 0b02dea7: mem TRACES(0) a9300000=17fec9fe (00000001)
061411: 0b02dea7: mem TRACES(5) ba601800=007a00a6 (000000dc)
061411: 0b02dea7: mem TRACES(7) ba607ffc=00040000 (00040000)
061411: 0b02e08e: mem TRACES(0) a9300000=07fec9ff (00000001)
061411: 0b02e2dd: mem TRACES(5) ba601800=00a600a6 (00dc0000)
061411: 0b02e2dd: mem TRACES(7) ba607ffc=00000400 (00040400)
061411: 0b02e75d: mem TRACES(7) ba607ffc=00000000 (00000400)
061411: 0b034009: mem TRACES(6) ba607688=08c508e6 (00000023)
061411: 0b034009: mem TRACES(7) ba607ffc=00000004 (00000004)
061411: 0b04380d: mem TRACES(7) ba607ffc=00000000 (00000004)
061411: 0b0441ce: mem TRACES(0) a9300000=17fec9fe (00000001)
061411: 0b0441ce: mem TRACES(6) ba607688=08e608e6 (00230000)
061411: 0b0441ce: mem TRACES(7) ba607ffc=04000000 (04000000)
061411: 0b0443ea: mem TRACES(0) a9300000=97fec9ff (00000001)
061411: 0b044595: mem TRACES(7) ba607ffc=00000000 (04000000)
061411: 0b0475ad: mem TRACES(0) a9300000=17fec9fe (00000001)
061411: 0b0475ad: mem TRACES(5) ba601800=00a600b3 (00000015)
061411: 0b0475ad: mem TRACES(7) ba607ffc=00040000 (00040000)
061411: 0b047712: mem TRACES(0) a9300000=07fec9ff (00000001)
061411: 0b047930: mem TRACES(5) ba601800=00b300b3 (00150000)
061411: 0b047930: mem TRACES(7) ba607ffc=00000400 (00040400)
061411: 0b047ce8: mem TRACES(7) ba607ffc=00000000 (00000400)
061411: 0b04e584: mem TRACES(6) ba607688=08e60911 (000001f7)
061411: 0b04e584: mem TRACES(7) ba607ffc=00000004 (00000004)
061411: 0b04e73a: mem TRACES(6) ba607688=08e60928 (00000039)
061411: 0b05c14c: mem TRACES(7) ba607ffc=00000000 (00000004)
061411: 0b05c9e4: mem TRACES(0) a9300000=47fec9fe (00000001)
061411: 0b05c9e4: mem TRACES(6) ba607688=09280928 (01ce0000)
061411: 0b05c9e4: mem TRACES(7) ba607ffc=04000000 (04000000)
061411: 0b05cbe5: mem TRACES(0) a9300000=67fec9ff (00000001)
061411: 0b05cd4a: mem TRACES(7) ba607ffc=00000000 (04000000)
061466: 0b07ad04: mem TRACES(0) a9300000=17fec9fe (00000001)
061466: 0b07ad04: mem TRACES(1) ba600000=02f102f3 (00000002)
061466: 0b07ad04: mem TRACES(7) ba607ffc=00010000 (00010000)
061466: 0b07aea8: mem TRACES(0) a9300000=07fec9ff (00000001)
061466: 0b07b034: mem TRACES(7) ba607ffc=00000000 (00010000)
061466: 0b07b6cd: mem TRACES(1) ba600000=02f302f3 (00020000)
061469: 0b081d08: mem TRACES(0) a9300000=17fec9fe (00000001)
061469: 0b081d08: mem TRACES(5) ba601800=00b300df (0000006c)
061469: 0b081d08: mem TRACES(7) ba607ffc=00040000 (00040000)
061469: 0b081e96: mem TRACES(0) a9300000=17fec9ff (00000001)
061469: 0b082116: mem TRACES(5) ba601800=00df00df (006c0000)
061469: 0b082116: mem TRACES(7) ba607ffc=00000400 (00040400)
061469: 0b08253b: mem TRACES(7) ba607ffc=00000000 (00000400)
062447: 0b1d01bd: mem TRACES(0) a9300000=17fec9fe (00000001)
062447: 0b1d01bd: mem TRACES(5) ba601800=00df0104 (000001db)
062447: 0b1d01bd: mem TRACES(7) ba607ffc=00040000 (00040000)
062447: 0b1d02dd: mem TRACES(0) a9300000=47fec9ff (00000001)
062447: 0b1d0551: mem TRACES(5) ba601800=01040104 (01db0000)
062447: 0b1d0551: mem TRACES(7) ba607ffc=00000400 (00040400)
062447: 0b1d0a45: mem TRACES(7) ba607ffc=00000000 (00000400)
062447: 0b1d1d2c: mem TRACES(6) ba607688=09280953 (0000007b)
062447: 0b1d6fcc: mem TRACES(6) ba607688=09530953 (007b0000)
062447: 0b1d6fcc: mem TRACES(7) ba607ffc=04000000 (04000000)
062447: 0b1d700e: mem TRACES(0) a9300000=17fec9fe (00000001)
062447: 0b1d7170: mem TRACES(0) a9300000=07fec9ff (00000001)
062447: 0b1d7170: mem TRACES(7) ba607ffc=00000000 (04000000)
062516: 0b1e5f4c: mem TRACES(0) a9300000=37fec9fe (00000001)
062516: 0b1e5f4c: mem TRACES(1) ba600000=02f3031b (000001e8)
062516: 0b1e5f4c: mem TRACES(7) ba607ffc=00010000 (00010000)
062516: 0b1e6067: mem TRACES(0) a9300000=17fec9ff (00000001)
062516: 0b1e61d0: mem TRACES(7) ba607ffc=00000000 (00010000)
062516: 0b1e685a: mem TRACES(1) ba600000=031b031b (01e80000)
062516: 0b1e685a: mem TRACES(7) ba607ffc=00000100 (00000100)
062516: 0b1e8898: mem TRACES(7) ba607ffc=00000000 (00000100)
062524: 0b1f511f: mem TRACES(5) ba601800=01040111 (00000015)
062524: 0b1f511f: mem TRACES(7) ba607ffc=00040000 (00040000)
062524: 0b1f516a: mem TRACES(0) a9300000=77fec9fe (00000001)
062524: 0b1f5439: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b1f5439: mem TRACES(5) ba601800=01110111 (00150000)
062524: 0b1f5439: mem TRACES(7) ba607ffc=00000400 (00040400)
062524: 0b1f551f: mem TRACES(7) ba607ffc=00000000 (00000400)
062524: 0b1f6817: mem TRACES(6) ba607688=09530960 (00000033)
062524: 0b1f7041: mem TRACES(0) a9300000=07fec9fe (00000001)
062524: 0b1f7041: mem TRACES(6) ba607688=09600960 (00330000)
062524: 0b1f7041: mem TRACES(7) ba607ffc=04000000 (04000000)
062524: 0b1f71c9: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b1f7345: mem TRACES(7) ba607ffc=00000000 (04000000)
062524: 0b1fea8d: mem TRACES(0) a9300000=17fec9fe (00000001)
062524: 0b1fea8d: mem TRACES(5) ba601800=0111012a (0000003b)
062524: 0b1fea8d: mem TRACES(7) ba607ffc=00040000 (00040000)
062524: 0b1fecf2: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b1fecf2: mem TRACES(5) ba601800=012a012a (003b0000)
062524: 0b1fecf2: mem TRACES(7) ba607ffc=00000400 (00040400)
062524: 0b1fedf4: mem TRACES(7) ba607ffc=00000000 (00000400)
062524: 0b202449: mem TRACES(6) ba607688=0960000f (0000096f)
062524: 0b202449: mem TRACES(7) ba607ffc=00000004 (00000004)
062524: 0b2024af: mem TRACES(7) ba607ffc=00000000 (00000004)
062524: 0b202eaa: mem TRACES(0) a9300000=17fec9fe (00000001)
062524: 0b202eaa: mem TRACES(6) ba607688=000f000f (096f0000)
062524: 0b202eaa: mem TRACES(7) ba607ffc=04000000 (04000000)
062524: 0b202ff9: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b203151: mem TRACES(7) ba607ffc=00000000 (04000000)
062524: 0b20b96f: mem TRACES(5) ba601800=012a0149 (00000063)
062524: 0b20b96f: mem TRACES(7) ba607ffc=00040000 (00040000)
062524: 0b20b9b4: mem TRACES(0) a9300000=17fec9fe (00000001)
062524: 0b20bc3b: mem TRACES(0) a9300000=17fec9ff (00000001)
062524: 0b20bc3b: mem TRACES(5) ba601800=01490149 (00630000)
062524: 0b20bc3b: mem TRACES(7) ba607ffc=00000400 (00040400)
062524: 0b20bcfc: mem TRACES(7) ba607ffc=00000000 (00000400)
062524: 0b20d4b0: mem TRACES(6) ba607688=000f002e (00000021)
062524: 0b20d4b0: mem TRACES(7) ba607ffc=00000004 (00000004)
062524: 0b211904: mem TRACES(7) ba607ffc=00000000 (00000004)
062524: 0b21238c: mem TRACES(6) ba607688=002e002e (00210000)
062524: 0b21238c: mem TRACES(7) ba607ffc=04000000 (04000000)
062524: 0b2123cd: mem TRACES(0) a9300000=17fec9fe (00000001)
062524: 0b2124d9: mem TRACES(0) a9300000=47fec9ff (00000001)
062524: 0b212680: mem TRACES(7) ba607ffc=00000000 (04000000)
062524: 0b215bf0: mem TRACES(0) a9300000=17fec9fe (00000001)
062524: 0b215bf0: mem TRACES(5) ba601800=01490168 (00000021)
062524: 0b215bf0: mem TRACES(7) ba607ffc=00040000 (00040000)
062524: 0b215d6b: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b215f8c: mem TRACES(5) ba601800=01680168 (00210000)
062524: 0b215f8c: mem TRACES(7) ba607ffc=00000400 (00040400)
062524: 0b21782d: mem TRACES(6) ba607688=002e0149 (00000167)
062524: 0b21782d: mem TRACES(7) ba607ffc=00000404 (00000004)
062524: 0b21a7de: mem TRACES(7) ba607ffc=00000000 (00000404)
062524: 0b21b4b8: mem TRACES(0) a9300000=07fec9fe (00000001)
062524: 0b21b4b8: mem TRACES(6) ba607688=01490149 (01670000)
062524: 0b21b4b8: mem TRACES(7) ba607ffc=04000000 (04000000)
062524: 0b21b6ac: mem TRACES(0) a9300000=07fec9ff (00000001)
062524: 0b21b818: mem TRACES(7) ba607ffc=00000000 (04000000)
063672: 0b3ede26: mem TRACES(6) ba607688=01490264 (0000032d)
063672: 0b3ede26: mem TRACES(7) ba607ffc=00000004 (00000004)
063672: 0b3f07a7: mem TRACES(7) ba607ffc=00000000 (00000004)
063672: 0b3f097c: mem TRACES(0) a9300000=17fac9fe (00000001)
063672: 0b3f097c: mem TRACES(6) ba607688=02640264 (032d0000)
063672: 0b3f097c: mem TRACES(7) ba607ffc=04000000 (04000000)
063672: 0b3f0c1f: mem TRACES(0) a9300000=47fac9ff (00000001)
063672: 0b3f0e42: mem TRACES(7) ba607ffc=00000000 (04000000)
064580: 0bbaf853: mem TRACES(6) ba607688=0264037f (0000011b)
064580: 0bbb04ae: mem TRACES(0) a9300000=07fac9fe (00000001)
064580: 0bbb04ae: mem TRACES(6) ba607688=037f037f (011b0000)
064580: 0bbb04ae: mem TRACES(7) ba607ffc=04000000 (04000000)
064580: 0bbb06b6: mem TRACES(0) a9300000=17fac9ff (00000001)
064580: 0bbb0862: mem TRACES(7) ba607ffc=00000000 (04000000)
066314: 0c957634: mem TRACES(0) a9300000=07fec9fe (00000001)
066314: 0c957634: mem TRACES(1) ba600000=031b0329 (00000032)
066314: 0c957634: mem TRACES(7) ba607ffc=00010000 (00010000)
066314: 0c95787d: mem TRACES(0) a9300000=17fec9ff (00000001)
066314: 0c957a27: mem TRACES(7) ba607ffc=00000000 (00010000)
066314: 0c958147: mem TRACES(1) ba600000=03290329 (00320000)
066332: 0c98d11e: mem TRACES(2) ba600400=03a203ac (0000000e)
066332: 0c98d11e: mem TRACES(7) ba607ffc=00000001 (00000001)
066332: 0c98d8bf: mem TRACES(7) ba607ffc=00000000 (00000001)
066332: 0c98e7ad: mem TRACES(0) a9300000=17fec9fe (00000001)
066332: 0c98e7ad: mem TRACES(2) ba600400=03ac03ac (000e0000)
066332: 0c98e7ad: mem TRACES(7) ba607ffc=01000000 (01000000)
066332: 0c98e968: mem TRACES(0) a9300000=07fec9ff (00000001)
066332: 0c98ead2: mem TRACES(7) ba607ffc=00000000 (01000000)
066332: 0c9919c0: mem TRACES(0) a9300000=07fec9fe (00000001)
066332: 0c9919c0: mem TRACES(1) ba600000=03290338 (00000011)
066332: 0c9919c0: mem TRACES(7) ba607ffc=00010000 (00010000)
066332: 0c991b5e: mem TRACES(0) a9300000=47fec9ff (00000001)
066332: 0c991cc4: mem TRACES(7) ba607ffc=00000000 (00010000)
066332: 0c9923bd: mem TRACES(1) ba600000=03380338 (00110000)
067416: 0d0c91c6: mem TRACES(0) a9300000=17fec9fe (00000001)
067416: 0d0c91c6: mem TRACES(1) ba600000=03380345 (0000007d)
067416: 0d0c91c6: mem TRACES(7) ba607ffc=00010000 (00010000)
067416: 0d0c944b: mem TRACES(0) a9300000=17fec9ff (00000001)
067416: 0d0c9625: mem TRACES(7) ba607ffc=00000000 (00010000)
067416: 0d0c9e17: mem TRACES(1) ba600000=03450345 (007d0000)
067416: 0d0c9e17: mem TRACES(7) ba607ffc=00000100 (00000100)
067416: 0d0ca169: mem TRACES(7) ba607ffc=00000000 (00000100)
075387: 10126480: mem TRACES(6) ba607688=037f03c0 (000000bf)
075387: 10126480: mem TRACES(7) ba607ffc=00000004 (00000004)
075387: 101331b1: mem TRACES(0) a9300000=47fec9fe (00000001)
075387: 101331b1: mem TRACES(6) ba607688=03c003c0 (00bf0000)
075387: 101331b1: mem TRACES(7) ba607ffc=04000000 (04000004)
075387: 10133459: mem TRACES(0) a9300000=17fec9ff (00000001)
075387: 101336cf: mem TRACES(7) ba607ffc=00000000 (04000000)
076342: 103345fc: mem TRACES(0) a9300000=07fec9fe (00000001)
076342: 103345fc: mem TRACES(5) ba601800=016801e4 (0000008c)
076342: 103345fc: mem TRACES(7) ba607ffc=00040000 (00040000)
076342: 10334723: mem TRACES(0) a9300000=17fec9ff (00000001)
076342: 103349ee: mem TRACES(5) ba601800=01e401e4 (008c0000)
076342: 103349ee: mem TRACES(7) ba607ffc=00000400 (00040400)
076342: 10334e1e: mem TRACES(7) ba607ffc=00000000 (00000400)
077753: 10734be0: mem TRACES(6) ba607688=03c00403 (000007c3)
077753: 107357c1: mem TRACES(0) a9300000=07fec9fe (00000001)
077753: 107357c1: mem TRACES(6) ba607688=04030403 (07c30000)
077753: 107357c1: mem TRACES(7) ba607ffc=04000000 (04000000)
077753: 10735b34: mem TRACES(0) a9300000=17fec9ff (00000001)
077753: 10735b34: mem TRACES(7) ba607ffc=00000000 (04000000)
078268: 10885447: mem TRACES(6) ba607688=04030448 (0000004b)
078268: 10885447: mem TRACES(7) ba607ffc=00000004 (00000004)
078268: 10886114: mem TRACES(7) ba607ffc=00000000 (00000004)
078268: 10886e75: mem TRACES(0) a9300000=17fec9fe (00000001)
078268: 10886e75: mem TRACES(6) ba607688=04480448 (004b0000)
078268: 10886e75: mem TRACES(7) ba607ffc=04000000 (04000000)
078268: 1088707b: mem TRACES(0) a9300000=17fec9ff (00000001)
078268: 1088707b: mem TRACES(7) ba607ffc=00000000 (04000000)
078678: 109997f4: mem TRACES(0) a9300000=17fec9fe (00000001)
078678: 109997f4: mem TRACES(5) ba601800=01e40263 (00000387)
078678: 109997f4: mem TRACES(7) ba607ffc=00040000 (00040000)
078678: 10999a84: mem TRACES(0) a9300000=17fec9ff (00000001)
078678: 10999d7e: mem TRACES(5) ba601800=02630263 (03870000)
078678: 10999d7e: mem TRACES(7) ba607ffc=00000400 (00040400)
078678: 1099a08d: mem TRACES(7) ba607ffc=00000000 (00000400)
079097: 10b0b4bc: mem TRACES(6) ba607688=0448048d (000000c5)
079097: 10b0b4bc: mem TRACES(7) ba607ffc=00000004 (00000004)
079097: 10b0b647: mem TRACES(7) ba607ffc=00000000 (00000004)
079097: 10b0c544: mem TRACES(0) a9300000=17fec9fe (00000001)
079097: 10b0c544: mem TRACES(6) ba607688=048d048d (00c50000)
079097: 10b0c544: mem TRACES(7) ba607ffc=04000000 (04000000)
079097: 10b0c647: mem TRACES(0) a9300000=17fec9ff (00000001)
079097: 10b0c9d7: mem TRACES(7) ba607ffc=00000000 (04000000)
079515: 10c3dd04: mem TRACES(0) a9300000=47fec9fe (00000001)
079515: 10c3dd04: mem TRACES(5) ba601800=026302fb (00000098)
079515: 10c3dd04: mem TRACES(7) ba607ffc=00040000 (00040000)
079515: 10c3de27: mem TRACES(0) a9300000=07fec9ff (00000001)
079515: 10c3e16c: mem TRACES(5) ba601800=02fb02fb (00980000)
079515: 10c3e16c: mem TRACES(7) ba607ffc=00000400 (00040400)
079515: 10c3f96b: mem TRACES(7) ba607ffc=00000000 (00000400)
079839: 10cbd288: mem TRACES(0) a9300000=17fec9fe (00000001)
079839: 10cbd288: mem TRACES(5) ba601800=02fb037b (00000180)
079839: 10cbd288: mem TRACES(7) ba607ffc=00040000 (00040000)
079839: 10cbd3ae: mem TRACES(0) a9300000=17fec9ff (00000001)
079839: 10cbd697: mem TRACES(5) ba601800=037b037b (01800000)
079839: 10cbd697: mem TRACES(7) ba607ffc=00000400 (00040400)
079839: 10cbd77a: mem TRACES(7) ba607ffc=00000000 (00000400)
081407: 117dc42f: mem TRACES(6) ba607688=048d04ce (00000043)
081407: 117dd022: mem TRACES(0) a9300000=17fec9fe (00000001)
081407: 117dd022: mem TRACES(6) ba607688=04ce04ce (00430000)
081407: 117dd022: mem TRACES(7) ba607ffc=04000000 (04000000)
081407: 117dd37a: mem TRACES(0) a9300000=17fec9ff (00000001)
081407: 117dd37a: mem TRACES(7) ba607ffc=00000000 (04000000)
081820: 11bbebc4: mem TRACES(6) ba607688=04ce0514 (000001da)
081820: 11bbebc4: mem TRACES(7) ba607ffc=00000004 (00000004)
081820: 11bc016c: mem TRACES(7) ba607ffc=00000000 (00000004)
081820: 11bc0499: mem TRACES(6) ba607688=05140514 (01da0000)
081820: 11bc0499: mem TRACES(7) ba607ffc=04000000 (04000000)
081820: 11bc04fc: mem TRACES(0) a9300000=07fec9fe (00000001)
081820: 11bc06d5: mem TRACES(0) a9300000=07fec9ff (00000001)
081820: 11bc06d5: mem TRACES(7) ba607ffc=00000000 (04000000)
082150: 11e246a9: mem TRACES(6) ba607688=05140557 (00000043)
082150: 11e2529d: mem TRACES(0) a9300000=07fec9fe (00000001)
082150: 11e2529d: mem TRACES(6) ba607688=05570557 (00430000)
082150: 11e2529d: mem TRACES(7) ba607ffc=04000000 (04000000)
082150: 11e25620: mem TRACES(0) a9300000=07fec9ff (00000001)
082150: 11e25620: mem TRACES(7) ba607ffc=00000000 (04000000)
082293: 11f0b0a6: mem TRACES(6) ba607688=055705a5 (000000f2)
082293: 11f0b0a6: mem TRACES(7) ba607ffc=00000004 (00000004)
082293: 11f0c9ab: mem TRACES(7) ba607ffc=00000000 (00000004)
082293: 11f0d1e0: mem TRACES(0) a9300000=07fec9fe (00000001)
082293: 11f0d1e0: mem TRACES(6) ba607688=05a505a5 (00f20000)
082293: 11f0d1e0: mem TRACES(7) ba607ffc=04000000 (04000000)
082293: 11f0d440: mem TRACES(0) a9300000=87fec9ff (00000001)
082293: 11f0d440: mem TRACES(7) ba607ffc=00000000 (04000000)
082467: 11fb8e15: mem TRACES(6) ba607688=05a505e9 (0000004c)
082467: 11fb9a16: mem TRACES(0) a9300000=17fec9fe (00000001)
082467: 11fb9a16: mem TRACES(6) ba607688=05e905e9 (004c0000)
082467: 11fb9a16: mem TRACES(7) ba607ffc=04000000 (04000000)
082467: 11fb9d8a: mem TRACES(0) a9300000=07fec9ff (00000001)
082467: 11fb9d8a: mem TRACES(7) ba607ffc=00000000 (04000000)
083009: 122002eb: mem TRACES(0) a9300000=17fec9fe (00000001)
083009: 122002eb: mem TRACES(5) ba601800=037b0450 (0000072b)
083009: 122002eb: mem TRACES(7) ba607ffc=00040000 (00040000)
083009: 122005bf: mem TRACES(0) a9300000=17fec9ff (00000001)
083009: 12200967: mem TRACES(5) ba601800=04500450 (072b0000)
083009: 12200967: mem TRACES(7) ba607ffc=00000400 (00040400)
083009: 12200b95: mem TRACES(7) ba607ffc=00000000 (00000400)
083009: 12204530: mem TRACES(0) a9300000=17fec9fe (00000001)
083009: 12204530: mem TRACES(5) ba601800=0450055d (0000010d)
083009: 12204530: mem TRACES(7) ba607ffc=00040000 (00040000)
083009: 12204742: mem TRACES(0) a9300000=17fec9ff (00000001)
083009: 12204acb: mem TRACES(5) ba601800=055d055d (010d0000)
083009: 12204acb: mem TRACES(7) ba607ffc=00000400 (00040400)
083009: 12204cae: mem TRACES(7) ba607ffc=00000000 (00000400)
083072: 122b2552: mem TRACES(6) ba607688=05e90628 (000003c1)
083072: 122b2552: mem TRACES(7) ba607ffc=00000004 (00000004)
083072: 122b3e36: mem TRACES(7) ba607ffc=00000000 (00000004)
083072: 122b607e: mem TRACES(0) a9300000=57fec9fe (00000001)
083072: 122b607e: mem TRACES(6) ba607688=06280628 (03c10000)
083072: 122b607e: mem TRACES(7) ba607ffc=04000000 (04000000)
083072: 122b6340: mem TRACES(0) a9300000=07fec9ff (00000001)
083072: 122b6527: mem TRACES(7) ba607ffc=00000000 (04000000)
083205: 12360249: mem TRACES(6) ba607688=0628066a (00000042)
083205: 12360249: mem TRACES(7) ba607ffc=00000004 (00000004)
083205: 12362927: mem TRACES(7) ba607ffc=00000000 (00000004)
083205: 1236389b: mem TRACES(0) a9300000=07fec9fe (00000001)
083205: 1236389b: mem TRACES(6) ba607688=066a066a (00420000)
083205: 1236389b: mem TRACES(7) ba607ffc=04000000 (04000000)
083205: 12363b16: mem TRACES(0) a9300000=47fec9ff (00000001)
083205: 12363dab: mem TRACES(7) ba607ffc=00000000 (04000000)
083964: 1283e1cc: mem TRACES(0) a9300000=07fec9fe (00000001)
083964: 1283e1cc: mem TRACES(5) ba601800=055d06a4 (000003f9)
083964: 1283e1cc: mem TRACES(7) ba607ffc=00040000 (00040000)
083964: 1283e487: mem TRACES(0) a9300000=07fec9ff (00000001)
083964: 1283e8e2: mem TRACES(5) ba601800=06a406a4 (03f90000)
083964: 1283e8e2: mem TRACES(7) ba607ffc=00000400 (00040400)
083964: 1283eb81: mem TRACES(7) ba607ffc=00000000 (00000400)
084080: 128d40c7: mem TRACES(0) a9300000=07fec9fe (00000001)
084080: 128d40c7: mem TRACES(5) ba601800=06a4076d (000001c9)
084080: 128d40c7: mem TRACES(7) ba607ffc=00040000 (00040000)
084080: 128d43a2: mem TRACES(0) a9300000=07fec9ff (00000001)
084080: 128d47bb: mem TRACES(5) ba601800=076d076d (01c90000)
084080: 128d47bb: mem TRACES(7) ba607ffc=00000400 (00040400)
084080: 128d48f7: mem TRACES(7) ba607ffc=00000000 (00000400)
084529: 12c10d51: mem TRACES(5) ba601800=076d08b0 (00000fdd)
084529: 12c10d51: mem TRACES(7) ba607ffc=00040000 (00040000)
084529: 12c10da5: mem TRACES(0) a9300000=17fec9fe (00000001)
084529: 12c10fe4: mem TRACES(0) a9300000=07fec9ff (00000001)
084529: 12c113b2: mem TRACES(5) ba601800=08b008b0 (0fdd0000)
084529: 12c113b2: mem TRACES(7) ba607ffc=00000400 (00040400)
084529: 12c1169b: mem TRACES(7) ba607ffc=00000000 (00000400)
084529: 12c88624: mem TRACES(0) a9300000=17fec9fe (00000001)
084529: 12c88624: mem TRACES(5) ba601800=08b0097a (000001ca)
084529: 12c88624: mem TRACES(7) ba607ffc=00040000 (00040000)
084529: 12c888b5: mem TRACES(0) a9300000=07fec9ff (00000001)
084529: 12c88c41: mem TRACES(5) ba601800=097a097a (01ca0000)
084529: 12c88c41: mem TRACES(7) ba607ffc=00000400 (00040400)
084529: 12c88f32: mem TRACES(7) ba607ffc=00000000 (00000400)
085284: 1328ec5d: mem TRACES(6) ba607688=066a06ad (000000c7)
085284: 1328f87a: mem TRACES(0) a9300000=17fec9fe (00000001)
085284: 1328f87a: mem TRACES(6) ba607688=06ad06ad (00c70000)
085284: 1328f87a: mem TRACES(7) ba607ffc=04000000 (04000000)
085284: 1328fbde: mem TRACES(0) a9300000=07fec9ff (00000001)
085284: 1328fbde: mem TRACES(7) ba607ffc=00000000 (04000000)
087431: 14213ac2: mem TRACES(0) a9300000=07fec9fe (00000001)
087431: 14213ac2: mem TRACES(5) ba601800=097a0ae0 (0000039a)
087431: 14213ac2: mem TRACES(7) ba607ffc=00040000 (00040000)
087431: 14213dda: mem TRACES(0) a9300000=57fec9ff (00000001)
087431: 142142a4: mem TRACES(5) ba601800=0ae00ae0 (039a0000)
087431: 142142a4: mem TRACES(7) ba607ffc=00000400 (00040400)
087431: 142143ed: mem TRACES(7) ba607ffc=00000000 (00000400)
088588: 14b091b5: mem TRACES(0) a9300000=07fec9fe (00000001)
088588: 14b091b5: mem TRACES(5) ba601800=0ae00c7b (0000069b)
088588: 14b091b5: mem TRACES(7) ba607ffc=00040000 (00040000)
088588: 14b09448: mem TRACES(0) a9300000=07fec9ff (00000001)
088588: 14b098d4: mem TRACES(5) ba601800=0c7b0c7b (069b0000)
088588: 14b098d4: mem TRACES(7) ba607ffc=00000400 (00040400)
088588: 14b099d0: mem TRACES(7) ba607ffc=00000000 (00000400)
089916: 15286a69: mem TRACES(6) ba607688=06ad0715 (000001b8)
089916: 1528768b: mem TRACES(0) a9300000=17fec9fe (00000001)
089916: 1528768b: mem TRACES(6) ba607688=07150715 (01b80000)
089916: 1528768b: mem TRACES(7) ba607ffc=04000000 (04000000)
089916: 15287890: mem TRACES(0) a9300000=17fec9ff (00000001)
089916: 15287a02: mem TRACES(7) ba607ffc=00000000 (04000000)
090168: 152aab58: mem TRACES(6) ba607688=0715077d (00000068)
090168: 152ab700: mem TRACES(0) a9300000=37fec9fe (00000001)
090168: 152ab700: mem TRACES(6) ba607688=077d077d (00680000)
090168: 152ab700: mem TRACES(7) ba607ffc=04000000 (04000000)
090168: 152ab8ad: mem TRACES(0) a9300000=07fec9ff (00000001)
090168: 152aba41: mem TRACES(7) ba607ffc=00000000 (04000000)
090420: 152cb3ab: mem TRACES(6) ba607688=077d07e5 (00000098)
090420: 152cb3ab: mem TRACES(7) ba607ffc=00000004 (00000004)
090420: 152cc5ec: mem TRACES(7) ba607ffc=00000000 (00000004)
090420: 152cd176: mem TRACES(0) a9300000=07fec9fe (00000001)
090420: 152cd176: mem TRACES(6) ba607688=07e507e5 (00980000)
090420: 152cd176: mem TRACES(7) ba607ffc=04000000 (04000000)
090420: 152cd3b2: mem TRACES(0) a9300000=07fec9ff (00000001)
090420: 152cd553: mem TRACES(7) ba607ffc=00000000 (04000000)
090672: 152f5609: mem TRACES(6) ba607688=07e5084d (00000fa8)
090672: 152f5609: mem TRACES(7) ba607ffc=00000004 (00000004)
090672: 152f5c25: mem TRACES(7) ba607ffc=00000000 (00000004)
090672: 152f6fc8: mem TRACES(0) a9300000=07fec9fe (00000001)
090672: 152f6fc8: mem TRACES(6) ba607688=084d084d (0fa80000)
090672: 152f6fc8: mem TRACES(7) ba607ffc=04000000 (04000000)
090672: 152f72c2: mem TRACES(0) a9300000=17fec9ff (00000001)
090672: 152f72c2: mem TRACES(7) ba607ffc=00000000 (04000000)
093346: 155a882b: mem TRACES(0) a9300000=17fec9fe (00000001)
093346: 155a882b: mem TRACES(1) ba600000=03450353 (00000016)
093346: 155a882b: mem TRACES(7) ba607ffc=00010000 (00010000)
093346: 155a894b: mem TRACES(0) a9300000=57fec9ff (00000001)
093346: 155a8ac1: mem TRACES(7) ba607ffc=00000000 (00010000)
093346: 155a924f: mem TRACES(1) ba600000=03530353 (00160000)
093350: 155b641b: mem TRACES(2) ba600400=03ac03b6 (0000001a)
093350: 155b641b: mem TRACES(7) ba607ffc=00000001 (00000001)
093357: 155b9102: mem TRACES(0) a9300000=f7fec9fe (00000001)
093357: 155b9102: mem TRACES(2) ba600400=03b603b6 (001a0000)
093357: 155b9102: mem TRACES(7) ba607ffc=01000000 (01000001)
093357: 155b921c: mem TRACES(0) a9300000=17fec9ff (00000001)
093357: 155b9435: mem TRACES(7) ba607ffc=00000000 (01000000)
093357: 155bc048: mem TRACES(0) a9300000=17fec9fe (00000001)
093357: 155bc048: mem TRACES(1) ba600000=03530362 (00000031)
093357: 155bc048: mem TRACES(7) ba607ffc=00010000 (00010000)
093357: 155bc26e: mem TRACES(0) a9300000=07fec9ff (00000001)
093357: 155bc26e: mem TRACES(7) ba607ffc=00000000 (00010000)
093357: 155bcbb2: mem TRACES(1) ba600000=03620362 (00310000)
095856: 1581b13a: mem TRACES(0) a9300000=27fec9fe (00000001)
095856: 1581b13a: mem TRACES(1) ba600000=0362036f (0000000d)
095856: 1581b13a: mem TRACES(7) ba607ffc=00010000 (00010000)
095856: 1581b25d: mem TRACES(0) a9300000=c7fec9ff (00000001)
095856: 1581b3e6: mem TRACES(7) ba607ffc=00000000 (00010000)
095856: 1581bab4: mem TRACES(1) ba600000=036f036f (000d0000)
095856: 1581bab4: mem TRACES(7) ba607ffc=00000100 (00000100)
095856: 1581be90: mem TRACES(7) ba607ffc=00000000 (00000100)
099262: 15c31918: mem TRACES(2) ba600400=03b603d4 (00000062)
099262: 15c31918: mem TRACES(7) ba607ffc=00000001 (00000001)
099262: 15c3d770: mem TRACES(7) ba607ffc=00000000 (00000001)
099262: 15c44f8b: mem TRACES(0) a9300000=07fec9fe (00000001)
099262: 15c44f8b: mem TRACES(2) ba600400=03d403d4 (00620000)
099262: 15c44f8b: mem TRACES(7) ba607ffc=01000000 (01000000)
099262: 15c451cd: mem TRACES(0) a9300000=57fec9ff (00000001)
099262: 15c451cd: mem TRACES(7) ba607ffc=00000000 (01000000)
099262: 15c4a7d9: mem TRACES(0) a9300000=17fec9fe (00000001)
099262: 15c4a7d9: mem TRACES(1) ba600000=036f0371 (0000001e)
099262: 15c4a7d9: mem TRACES(7) ba607ffc=00010000 (00010000)
099262: 15c4a91f: mem TRACES(0) a9300000=07fec9ff (00000001)
099262: 15c4a91f: mem TRACES(7) ba607ffc=00000000 (00010000)
099262: 15c4aec5: mem TRACES(1) ba600000=03710371 (001e0000)
099262: 15c4aec5: mem TRACES(7) ba607ffc=00000100 (00000100)
099262: 15c4b1d8: mem TRACES(7) ba607ffc=00000000 (00000100)

View File

@@ -0,0 +1,6 @@
vdump p2v(0x14000800) 4
vdump p2v(0x14001000) 4
vdump p2v(0x14001800) 4
vdump p2v(0x14007688) 4